Annotation: expose annotation type with enum class
This is in preparation for 'checkapi' allowing/disallowing certain
annotations being added/deleted. Before, it's impossible to see what
type of annotation a specific AidlAnnotation. APIs like 'IsHide' etc..
only work on AidlAnnotable, but can not be used on individual
annotations.
This ensures that when we talk about an annotation, that annotation
is guaranteed to exist (e.g. can't typo "nillable" for instance).
Future considerations:
- We could remove 'GetName' of AidlAnnotation
- IsHide/etc.. can be replaced with generic API
Bug: 146215188
Test: atest --test-mapping .
Change-Id: If45942385cb92c32d5ae9ba8e2a3bd9f044ecbb6
diff --git a/aidl_language.cpp b/aidl_language.cpp
index 68ed32b..e08142a 100644
--- a/aidl_language.cpp
+++ b/aidl_language.cpp
@@ -128,64 +128,66 @@
bool AidlErrorLog::sHadError = false;
-static const string kNullable("nullable");
-static const string kUtf8InCpp("utf8InCpp");
-static const string kVintfStability("VintfStability");
-static const string kUnsupportedAppUsage("UnsupportedAppUsage");
-static const string kJavaStableParcelable("JavaOnlyStableParcelable");
-static const string kHide("Hide");
-static const string kBacking("Backing");
+const std::vector<AidlAnnotation::Schema>& AidlAnnotation::AllSchemas() {
+ static const std::vector<Schema> kSchemas{
+ {AidlAnnotation::Type::NULLABLE, "nullable", {}},
+ {AidlAnnotation::Type::UTF8_IN_CPP, "utf8InCpp", {}},
+ {AidlAnnotation::Type::VINTF_STABILITY, "VintfStability", {}},
+ {AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
+ "UnsupportedAppUsage",
+ {{"expectedSignature", "String"},
+ {"implicitMember", "String"},
+ {"maxTargetSdk", "int"},
+ {"publicAlternatives", "String"},
+ {"trackingBug", "long"}}},
+ {AidlAnnotation::Type::JAVA_STABLE_PARCELABLE, "JavaOnlyStableParcelable", {}},
+ {AidlAnnotation::Type::HIDE, "Hide", {}},
+ {AidlAnnotation::Type::BACKING, "Backing", {{"type", "String"}}}};
+ return kSchemas;
+}
-static const std::map<string, std::map<std::string, std::string>> kAnnotationParameters{
- {kNullable, {}},
- {kUtf8InCpp, {}},
- {kVintfStability, {}},
- {kUnsupportedAppUsage,
- {{"expectedSignature", "String"},
- {"implicitMember", "String"},
- {"maxTargetSdk", "int"},
- {"publicAlternatives", "String"},
- {"trackingBug", "long"}}},
- {kJavaStableParcelable, {}},
- {kHide, {}},
- {kBacking, {{"type", "String"}}}};
+std::string AidlAnnotation::TypeToString(Type type) {
+ for (const Schema& schema : AllSchemas()) {
+ if (type == schema.type) return schema.name;
+ }
+ AIDL_FATAL(AIDL_LOCATION_HERE) << "Unrecognized type: " << static_cast<size_t>(type);
+ __builtin_unreachable();
+}
AidlAnnotation* AidlAnnotation::Parse(
const AidlLocation& location, const string& name,
std::map<std::string, std::shared_ptr<AidlConstantValue>>* parameter_list) {
- if (kAnnotationParameters.find(name) == kAnnotationParameters.end()) {
+ const Schema* schema = nullptr;
+ for (const Schema& a_schema : AllSchemas()) {
+ if (a_schema.name == name) {
+ schema = &a_schema;
+ }
+ }
+
+ if (schema == nullptr) {
std::ostringstream stream;
stream << "'" << name << "' is not a recognized annotation. ";
stream << "It must be one of:";
- for (const auto& kv : kAnnotationParameters) {
- stream << " " << kv.first;
+ for (const Schema& s : AllSchemas()) {
+ stream << " " << s.name;
}
stream << ".";
AIDL_ERROR(location) << stream.str();
return nullptr;
}
if (parameter_list == nullptr) {
- return new AidlAnnotation(location, name);
+ return new AidlAnnotation(location, *schema, {});
}
- return new AidlAnnotation(location, name, std::move(*parameter_list));
+ return new AidlAnnotation(location, *schema, std::move(*parameter_list));
}
-AidlAnnotation::AidlAnnotation(const AidlLocation& location, const string& name)
- : AidlAnnotation(location, name, {}) {}
-
AidlAnnotation::AidlAnnotation(
- const AidlLocation& location, const string& name,
+ const AidlLocation& location, const Schema& schema,
std::map<std::string, std::shared_ptr<AidlConstantValue>>&& parameters)
- : AidlNode(location), name_(name), parameters_(std::move(parameters)) {}
+ : AidlNode(location), schema_(schema), parameters_(std::move(parameters)) {}
bool AidlAnnotation::CheckValid() const {
- auto supported_params_iterator = kAnnotationParameters.find(GetName());
- if (supported_params_iterator == kAnnotationParameters.end()) {
- AIDL_ERROR(this) << GetName() << " annotation does not have any supported parameters.";
- return false;
- }
- const auto& supported_params = supported_params_iterator->second;
for (const auto& name_and_param : parameters_) {
const std::string& param_name = name_and_param.first;
const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
@@ -194,13 +196,13 @@
<< GetName() << ".";
return false;
}
- auto parameter_mapping_it = supported_params.find(param_name);
- if (parameter_mapping_it == supported_params.end()) {
+ auto parameter_mapping_it = schema_.supported_parameters.find(param_name);
+ if (parameter_mapping_it == schema_.supported_parameters.end()) {
std::ostringstream stream;
stream << "Parameter " << param_name << " not supported ";
stream << "for annotation " << GetName() << ".";
stream << "It must be one of:";
- for (const auto& kv : supported_params) {
+ for (const auto& kv : schema_.supported_parameters) {
stream << " " << kv.first;
}
AIDL_ERROR(this) << stream.str();
@@ -221,11 +223,11 @@
std::map<std::string, std::string> AidlAnnotation::AnnotationParams(
const ConstantValueDecorator& decorator) const {
std::map<std::string, std::string> raw_params;
- const auto& supported_params = kAnnotationParameters.at(GetName());
for (const auto& name_and_param : parameters_) {
const std::string& param_name = name_and_param.first;
const std::shared_ptr<AidlConstantValue>& param = name_and_param.second;
- AidlTypeSpecifier type{AIDL_LOCATION_HERE, supported_params.at(param_name), false, nullptr, ""};
+ AidlTypeSpecifier type{AIDL_LOCATION_HERE, schema_.supported_parameters.at(param_name), false,
+ nullptr, ""};
if (!param->CheckValid()) {
AIDL_ERROR(this) << "Invalid value for parameter " << param_name << " on annotation "
<< GetName() << ".";
@@ -251,9 +253,9 @@
}
static const AidlAnnotation* GetAnnotation(const vector<AidlAnnotation>& annotations,
- const string& name) {
+ AidlAnnotation::Type type) {
for (const auto& a : annotations) {
- if (a.GetName() == name) {
+ if (a.GetType() == type) {
return &a;
}
}
@@ -263,23 +265,23 @@
AidlAnnotatable::AidlAnnotatable(const AidlLocation& location) : AidlNode(location) {}
bool AidlAnnotatable::IsNullable() const {
- return GetAnnotation(annotations_, kNullable);
+ return GetAnnotation(annotations_, AidlAnnotation::Type::NULLABLE);
}
bool AidlAnnotatable::IsUtf8InCpp() const {
- return GetAnnotation(annotations_, kUtf8InCpp);
+ return GetAnnotation(annotations_, AidlAnnotation::Type::UTF8_IN_CPP);
}
bool AidlAnnotatable::IsVintfStability() const {
- return GetAnnotation(annotations_, kVintfStability);
+ return GetAnnotation(annotations_, AidlAnnotation::Type::VINTF_STABILITY);
}
const AidlAnnotation* AidlAnnotatable::UnsupportedAppUsage() const {
- return GetAnnotation(annotations_, kUnsupportedAppUsage);
+ return GetAnnotation(annotations_, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE);
}
const AidlTypeSpecifier* AidlAnnotatable::BackingType(const AidlTypenames& typenames) const {
- auto annotation = GetAnnotation(annotations_, kBacking);
+ auto annotation = GetAnnotation(annotations_, AidlAnnotation::Type::BACKING);
if (annotation != nullptr) {
auto annotation_params = annotation->AnnotationParams(AidlConstantValueDecorator);
if (auto it = annotation_params.find("type"); it != annotation_params.end()) {
@@ -296,11 +298,12 @@
}
bool AidlAnnotatable::IsStableApiParcelable(Options::Language lang) const {
- return GetAnnotation(annotations_, kJavaStableParcelable) && lang == Options::Language::JAVA;
+ return lang == Options::Language::JAVA &&
+ GetAnnotation(annotations_, AidlAnnotation::Type::JAVA_STABLE_PARCELABLE);
}
bool AidlAnnotatable::IsHide() const {
- return GetAnnotation(annotations_, kHide);
+ return GetAnnotation(annotations_, AidlAnnotation::Type::HIDE);
}
void AidlAnnotatable::DumpAnnotations(CodeWriter* writer) const {
@@ -310,15 +313,22 @@
}
bool AidlAnnotatable::CheckValid(const AidlTypenames&) const {
- std::set<string> supported_annotations = GetSupportedAnnotations();
+ std::set<AidlAnnotation::Type> supported_annotations = GetSupportedAnnotations();
for (const auto& annotation : GetAnnotations()) {
if (!annotation.CheckValid()) {
return false;
}
- if (supported_annotations.find(annotation.GetName()) == supported_annotations.end()) {
+
+ std::vector<std::string> supported_annot_strings;
+ for (AidlAnnotation::Type type : supported_annotations) {
+ supported_annot_strings.push_back(AidlAnnotation::TypeToString(type));
+ }
+
+ if (supported_annotations.find(annotation.GetType()) == supported_annotations.end()) {
AIDL_ERROR(this) << "'" << annotation.GetName()
<< "' is not a supported annotation for this node. "
- << "It must be one of: " << android::base::Join(supported_annotations, ", ");
+ << "It must be one of: "
+ << android::base::Join(supported_annot_strings, ", ");
return false;
}
}
@@ -394,10 +404,11 @@
return result.second;
}
-std::set<string> AidlTypeSpecifier::GetSupportedAnnotations() const {
+std::set<AidlAnnotation::Type> AidlTypeSpecifier::GetSupportedAnnotations() const {
// kHide and kUnsupportedAppUsage are both method return annotations
// which we don't distinguish from other type specifiers.
- return {kNullable, kUtf8InCpp, kUnsupportedAppUsage, kHide};
+ return {AidlAnnotation::Type::NULLABLE, AidlAnnotation::Type::UTF8_IN_CPP,
+ AidlAnnotation::Type::UNSUPPORTED_APP_USAGE, AidlAnnotation::Type::HIDE};
}
bool AidlTypeSpecifier::CheckValid(const AidlTypenames& typenames) const {
@@ -752,8 +763,9 @@
return true;
}
-std::set<string> AidlParcelable::GetSupportedAnnotations() const {
- return {kVintfStability, kUnsupportedAppUsage, kJavaStableParcelable, kHide};
+std::set<AidlAnnotation::Type> AidlParcelable::GetSupportedAnnotations() const {
+ return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
+ AidlAnnotation::Type::JAVA_STABLE_PARCELABLE, AidlAnnotation::Type::HIDE};
}
bool AidlParcelable::CheckValid(const AidlTypenames& typenames) const {
@@ -792,8 +804,9 @@
writer->Write("}\n");
}
-std::set<string> AidlStructuredParcelable::GetSupportedAnnotations() const {
- return {kVintfStability, kUnsupportedAppUsage, kHide};
+std::set<AidlAnnotation::Type> AidlStructuredParcelable::GetSupportedAnnotations() const {
+ return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
+ AidlAnnotation::Type::HIDE};
}
bool AidlStructuredParcelable::CheckValid(const AidlTypenames& typenames) const {
@@ -951,8 +964,9 @@
return true;
}
-std::set<string> AidlEnumDeclaration::GetSupportedAnnotations() const {
- return {kVintfStability, kBacking, kHide};
+std::set<AidlAnnotation::Type> AidlEnumDeclaration::GetSupportedAnnotations() const {
+ return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::BACKING,
+ AidlAnnotation::Type::HIDE};
}
bool AidlEnumDeclaration::CheckValid(const AidlTypenames& typenames) const {
@@ -1042,8 +1056,9 @@
writer->Write("}\n");
}
-std::set<string> AidlInterface::GetSupportedAnnotations() const {
- return {kVintfStability, kUnsupportedAppUsage, kHide};
+std::set<AidlAnnotation::Type> AidlInterface::GetSupportedAnnotations() const {
+ return {AidlAnnotation::Type::VINTF_STABILITY, AidlAnnotation::Type::UNSUPPORTED_APP_USAGE,
+ AidlAnnotation::Type::HIDE};
}
bool AidlInterface::CheckValid(const AidlTypenames& typenames) const {
diff --git a/aidl_language.h b/aidl_language.h
index 3780e4a..44c8078 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -213,6 +213,17 @@
class AidlAnnotation : public AidlNode {
public:
+ enum class Type {
+ BACKING = 1,
+ HIDE,
+ JAVA_STABLE_PARCELABLE,
+ UNSUPPORTED_APP_USAGE,
+ VINTF_STABILITY,
+ NULLABLE,
+ UTF8_IN_CPP,
+ };
+ static std::string TypeToString(Type type);
+
static AidlAnnotation* Parse(
const AidlLocation& location, const string& name,
std::map<std::string, std::shared_ptr<AidlConstantValue>>* parameter_list);
@@ -222,7 +233,8 @@
virtual ~AidlAnnotation() = default;
bool CheckValid() const;
- const string& GetName() const { return name_; }
+ const string& GetName() const { return schema_.name; };
+ const Type& GetType() const { return schema_.type; }
string ToString(const ConstantValueDecorator& decorator) const;
std::map<std::string, std::string> AnnotationParams(
const ConstantValueDecorator& decorator) const;
@@ -230,10 +242,21 @@
void SetComments(const string& comments) { comments_ = comments; }
private:
- AidlAnnotation(const AidlLocation& location, const string& name);
- AidlAnnotation(const AidlLocation& location, const string& name,
+ struct Schema {
+ AidlAnnotation::Type type;
+
+ // text name in .aidl file, e.g. "nullable"
+ std::string name;
+
+ // map from param name -> value type
+ std::map<std::string, std::string> supported_parameters;
+ };
+ static const std::vector<Schema>& AllSchemas();
+
+ AidlAnnotation(const AidlLocation& location, const Schema& schema,
std::map<std::string, std::shared_ptr<AidlConstantValue>>&& parameters);
- const string name_;
+
+ const Schema& schema_;
string comments_;
std::map<std::string, std::shared_ptr<AidlConstantValue>> parameters_;
};
@@ -274,7 +297,7 @@
virtual bool CheckValid(const AidlTypenames&) const;
protected:
- virtual std::set<string> GetSupportedAnnotations() const = 0;
+ virtual std::set<AidlAnnotation::Type> GetSupportedAnnotations() const = 0;
private:
vector<AidlAnnotation> annotations_;
@@ -331,7 +354,7 @@
// resolution fails.
bool Resolve(const AidlTypenames& typenames);
- std::set<string> GetSupportedAnnotations() const override;
+ std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
bool CheckValid(const AidlTypenames& typenames) const override;
bool LanguageSpecificCheckValid(Options::Language lang) const;
const AidlNode& AsAidlNode() const override { return *this; }
@@ -736,7 +759,7 @@
std::string GetCppName() const { return name_->GetColonName(); }
std::string GetCppHeader() const { return cpp_header_; }
- std::set<string> GetSupportedAnnotations() const override;
+ std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
bool CheckValid(const AidlTypenames& typenames) const override;
bool LanguageSpecificCheckValid(Options::Language lang) const override;
const AidlParcelable* AsParcelable() const override { return this; }
@@ -768,7 +791,7 @@
void Dump(CodeWriter* writer) const override;
- std::set<string> GetSupportedAnnotations() const override;
+ std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
bool CheckValid(const AidlTypenames& typenames) const override;
bool LanguageSpecificCheckValid(Options::Language lang) const override;
@@ -815,7 +838,7 @@
return enumerators_;
}
bool Autofill();
- std::set<string> GetSupportedAnnotations() const override;
+ std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
bool CheckValid(const AidlTypenames& typenames) const override;
bool LanguageSpecificCheckValid(Options::Language) const override { return true; }
std::string GetPreprocessDeclarationName() const override { return "enum"; }
@@ -850,7 +873,7 @@
void Dump(CodeWriter* writer) const override;
- std::set<string> GetSupportedAnnotations() const override;
+ std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
bool CheckValid(const AidlTypenames& typenames) const override;
bool LanguageSpecificCheckValid(Options::Language lang) const override;