Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5596a61b authored by Mark Punzalan's avatar Mark Punzalan
Browse files

[aapt2] Ignore annotations in flag/enum attribute values

Bug: 258855262
Test: atest aapt2_tests
Change-Id: If67a73b02da719b049c19cee561a2f9b8945956b
parent 27aeef3c
Loading
Loading
Loading
Loading
+24 −22
Original line number Diff line number Diff line
@@ -64,9 +64,10 @@ static std::array<AnnotationRule, 3> sAnnotationRules = {{
    {"@FlaggedApi", AnnotationRule::kFlaggedApi, "@android.annotation.FlaggedApi", true},
}};

void AnnotationProcessor::AppendCommentLine(std::string comment) {
void AnnotationProcessor::AppendCommentLine(std::string comment, bool add_api_annotations) {
  static constexpr std::string_view sDeprecated = "@deprecated";

  if (add_api_annotations) {
    // Treat deprecated specially, since we don't remove it from the source comment.
    if (comment.find(sDeprecated) != std::string::npos) {
      annotation_parameter_map_[AnnotationRule::kDeprecated] = "";
@@ -90,6 +91,7 @@ void AnnotationProcessor::AppendCommentLine(std::string comment) {
        }
      }
    }
  }

  // Check if after removal of annotations the line is empty.
  const StringPiece trimmed = util::TrimWhitespace(comment);
@@ -109,12 +111,12 @@ void AnnotationProcessor::AppendCommentLine(std::string comment) {
  comment_ << "\n * " << std::move(comment);
}

void AnnotationProcessor::AppendComment(StringPiece comment) {
void AnnotationProcessor::AppendComment(StringPiece comment, bool add_api_annotations) {
  // We need to process line by line to clean-up whitespace and append prefixes.
  for (StringPiece line : util::Tokenize(comment, '\n')) {
    line = util::TrimWhitespace(line);
    if (!line.empty()) {
      AppendCommentLine(std::string(line));
      AppendCommentLine(std::string(line), add_api_annotations);
    }
  }
}
+5 −2
Original line number Diff line number Diff line
@@ -60,7 +60,10 @@ class AnnotationProcessor {

  // Adds more comments. Resources can have value definitions for various configurations, and
  // each of the definitions may have comments that need to be processed.
  void AppendComment(android::StringPiece comment);
  //
  // If add_api_annotations is false, annotations found in the comment (e.g., "@SystemApi")
  // will NOT be converted to Java annotations.
  void AppendComment(android::StringPiece comment, bool add_api_annotations = true);

  void AppendNewLine();

@@ -73,7 +76,7 @@ class AnnotationProcessor {
  bool has_comments_ = false;
  std::unordered_map<uint32_t, std::string> annotation_parameter_map_;

  void AppendCommentLine(std::string line);
  void AppendCommentLine(std::string line, bool add_api_annotations);
};

}  // namespace aapt
+22 −1
Original line number Diff line number Diff line
@@ -136,7 +136,28 @@ TEST(AnnotationProcessorTest, NotEmitSystemApiAnnotation) {
  EXPECT_THAT(annotations, HasSubstr("This is a system API"));
}

TEST(AnnotationProcessor, ExtractsFirstSentence) {
TEST(AnnotationProcessorTest, DoNotAddApiAnnotations) {
  AnnotationProcessor processor;
  processor.AppendComment(
      "@SystemApi This is a system API\n"
      "@FlaggedApi This is a flagged API\n"
      "@TestApi This is a test API\n"
      "@deprecated Deprecate me\n", /*add_api_annotations=*/
      false);

  std::string annotations;
  StringOutputStream out(&annotations);
  Printer printer(&out);
  processor.Print(&printer);
  out.Flush();

  EXPECT_THAT(annotations, Not(HasSubstr("@android.annotation.SystemApi")));
  EXPECT_THAT(annotations, Not(HasSubstr("@android.annotation.FlaggedApi")));
  EXPECT_THAT(annotations, Not(HasSubstr("@android.annotation.TestApi")));
  EXPECT_THAT(annotations, Not(HasSubstr("@Deprecated")));
}

TEST(AnnotationProcessorTest, ExtractsFirstSentence) {
  EXPECT_THAT(AnnotationProcessor::ExtractFirstSentence("This is the only sentence"),
              Eq("This is the only sentence"));
  EXPECT_THAT(AnnotationProcessor::ExtractFirstSentence(
+4 −1
Original line number Diff line number Diff line
@@ -180,7 +180,10 @@ static void AddAttributeFormatDoc(AnnotationProcessor* processor, Attribute* att
           << "<td>" << std::hex << symbol.value << std::dec << "</td>"
           << "<td>" << util::TrimWhitespace(symbol.symbol.GetComment())
           << "</td></tr>";
      processor->AppendComment(line.str());
      // add_api_annotations is false since we don't want any annotations
      // (e.g., "@deprecated")/ found in the enum/flag values to be propagated
      // up to the attribute.
      processor->AppendComment(line.str(), /*add_api_annotations=*/false);
    }
    processor->AppendComment("</table>");
  }
+52 −1
Original line number Diff line number Diff line
@@ -324,7 +324,58 @@ TEST(JavaClassGeneratorTest, CommentsForSimpleResourcesArePresent) {
  EXPECT_THAT(output, HasSubstr(expected_text));
}

TEST(JavaClassGeneratorTest, CommentsForEnumAndFlagAttributesArePresent) {}
TEST(JavaClassGeneratorTest, CommentsForEnumAndFlagAttributesArePresent) {
  std::unique_ptr<Attribute> flagAttr =
      test::AttributeBuilder()
          .SetTypeMask(android::ResTable_map::TYPE_FLAGS)
          .SetComment("Flag attribute")
          .AddItemWithComment("flagOne", 0x01, "Flag comment 1")
          .AddItemWithComment("flagTwo", 0x02, "@deprecated Flag comment 2")
          .Build();
  std::unique_ptr<Attribute> enumAttr =
      test::AttributeBuilder()
          .SetTypeMask(android::ResTable_map::TYPE_ENUM)
          .SetComment("Enum attribute")
          .AddItemWithComment("enumOne", 0x01, "@TestApi Enum comment 1")
          .AddItemWithComment("enumTwo", 0x02, "Enum comment 2")
          .Build();

  std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
                                             .AddValue("android:attr/one", std::move(flagAttr))
                                             .AddValue("android:attr/two", std::move(enumAttr))
                                             .Build();

  std::unique_ptr<IAaptContext> context =
      test::ContextBuilder()
          .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
          .SetNameManglerPolicy(NameManglerPolicy{"android"})
          .Build();
  JavaClassGeneratorOptions options;
  options.use_final = false;
  JavaClassGenerator generator(context.get(), table.get(), options);

  std::string output;
  StringOutputStream out(&output);
  ASSERT_TRUE(generator.Generate("android", &out));
  out.Flush();

  // Special annotations from the enum/flag values should NOT generate
  // annotations for the attribute value.
  EXPECT_THAT(output, Not(HasSubstr("@Deprecated")));
  EXPECT_THAT(output, Not(HasSubstr("@android.annotation.TestApi")));

  EXPECT_THAT(output, HasSubstr("Flag attribute"));
  EXPECT_THAT(output, HasSubstr("flagOne"));
  EXPECT_THAT(output, HasSubstr("Flag comment 1"));
  EXPECT_THAT(output, HasSubstr("flagTwo"));
  EXPECT_THAT(output, HasSubstr("@deprecated Flag comment 2"));

  EXPECT_THAT(output, HasSubstr("Enum attribute"));
  EXPECT_THAT(output, HasSubstr("enumOne"));
  EXPECT_THAT(output, HasSubstr("@TestApi Enum comment 1"));
  EXPECT_THAT(output, HasSubstr("enumTwo"));
  EXPECT_THAT(output, HasSubstr("Enum comment 2"));
}

TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent) {
  Attribute attr;
Loading