Commit 782b865c authored by jaceksur's avatar jaceksur Committed by Wouter van Oortmerssen

Annotate getters with @Pure when --java-checkerframework is specified. (#5510)

Together with @Nullable, this allows users to use static analysis tools
like CheckerFramework to catch NPEs caused by unset fields.
parent 3bfc86ea
...@@ -514,6 +514,7 @@ struct IDLOptions { ...@@ -514,6 +514,7 @@ struct IDLOptions {
std::string cpp_object_api_string_type; std::string cpp_object_api_string_type;
bool cpp_object_api_string_flexible_constructor; bool cpp_object_api_string_flexible_constructor;
bool gen_nullable; bool gen_nullable;
bool java_checkerframework;
bool gen_generated; bool gen_generated;
std::string object_prefix; std::string object_prefix;
std::string object_suffix; std::string object_suffix;
...@@ -594,6 +595,7 @@ struct IDLOptions { ...@@ -594,6 +595,7 @@ struct IDLOptions {
cpp_object_api_pointer_type("std::unique_ptr"), cpp_object_api_pointer_type("std::unique_ptr"),
cpp_object_api_string_flexible_constructor(false), cpp_object_api_string_flexible_constructor(false),
gen_nullable(false), gen_nullable(false),
java_checkerframework(false),
gen_generated(false), gen_generated(false),
object_suffix("T"), object_suffix("T"),
union_value_namespacing(true), union_value_namespacing(true),
......
...@@ -101,6 +101,7 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const { ...@@ -101,6 +101,7 @@ std::string FlatCompiler::GetUsageString(const char *program_name) const {
" --gen-object-api Generate an additional object-based API.\n" " --gen-object-api Generate an additional object-based API.\n"
" --gen-compare Generate operator== for object-based API types.\n" " --gen-compare Generate operator== for object-based API types.\n"
" --gen-nullable Add Clang _Nullable for C++ pointer. or @Nullable for Java\n" " --gen-nullable Add Clang _Nullable for C++ pointer. or @Nullable for Java\n"
" --java-checkerframework Add @Pure for Java.\n"
" --gen-generated Add @Generated annotation for Java\n" " --gen-generated Add @Generated annotation for Java\n"
" --gen-all Generate not just code for the current schema files,\n" " --gen-all Generate not just code for the current schema files,\n"
" but for all files it includes as well.\n" " but for all files it includes as well.\n"
...@@ -261,6 +262,8 @@ int FlatCompiler::Compile(int argc, const char **argv) { ...@@ -261,6 +262,8 @@ int FlatCompiler::Compile(int argc, const char **argv) {
opts.cpp_object_api_string_flexible_constructor = true; opts.cpp_object_api_string_flexible_constructor = true;
} else if (arg == "--gen-nullable") { } else if (arg == "--gen-nullable") {
opts.gen_nullable = true; opts.gen_nullable = true;
} else if (arg == "--java-checkerframework") {
opts.java_checkerframework = true;
} else if (arg == "--gen-generated") { } else if (arg == "--gen-generated") {
opts.gen_generated = true; opts.gen_generated = true;
} else if (arg == "--object-prefix") { } else if (arg == "--object-prefix") {
......
...@@ -228,6 +228,9 @@ class GeneralGenerator : public BaseGenerator { ...@@ -228,6 +228,9 @@ class GeneralGenerator : public BaseGenerator {
if (parser_.opts.gen_nullable) { if (parser_.opts.gen_nullable) {
code += "\nimport javax.annotation.Nullable;\n"; code += "\nimport javax.annotation.Nullable;\n";
} }
if (parser_.opts.java_checkerframework) {
code += "\nimport org.checkerframework.dataflow.qual.Pure;\n";
}
code += lang_.class_annotation; code += lang_.class_annotation;
} }
if (parser_.opts.gen_generated) { if (parser_.opts.gen_generated) {
...@@ -254,6 +257,14 @@ class GeneralGenerator : public BaseGenerator { ...@@ -254,6 +257,14 @@ class GeneralGenerator : public BaseGenerator {
: ""; : "";
} }
std::string GenPureAnnotation(const Type &t) const {
return lang_.language == IDLOptions::kJava &&
parser_.opts.java_checkerframework &&
!IsScalar(DestinationType(t, true).base_type)
? " @Pure "
: "";
}
std::string GenTypeBasic(const Type &type, bool enableLangOverrides) const { std::string GenTypeBasic(const Type &type, bool enableLangOverrides) const {
// clang-format off // clang-format off
static const char * const java_typename[] = { static const char * const java_typename[] = {
...@@ -969,10 +980,11 @@ class GeneralGenerator : public BaseGenerator { ...@@ -969,10 +980,11 @@ class GeneralGenerator : public BaseGenerator {
std::string dest_mask = DestinationMask(field.value.type, true); std::string dest_mask = DestinationMask(field.value.type, true);
std::string dest_cast = DestinationCast(field.value.type); std::string dest_cast = DestinationCast(field.value.type);
std::string src_cast = SourceCast(field.value.type); std::string src_cast = SourceCast(field.value.type);
std::string method_start = " public " + std::string method_start =
" public " +
(field.required ? "" : GenNullableAnnotation(field.value.type)) + (field.required ? "" : GenNullableAnnotation(field.value.type)) +
type_name_dest + optional + " " + GenPureAnnotation(field.value.type) + type_name_dest + optional +
MakeCamel(field.name, lang_.first_camel_upper); " " + MakeCamel(field.name, lang_.first_camel_upper);
std::string obj = lang_.language == IDLOptions::kCSharp std::string obj = lang_.language == IDLOptions::kCSharp
? "(new " + type_name + "())" ? "(new " + type_name + "())"
: "obj"; : "obj";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment