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

Commit 09f4d706 authored by Adam Lesinski's avatar Adam Lesinski
Browse files

AAPT2: Forward @TestApi in resource comments to JavaDoc

Bug: 37894597
Test: make aapt2_tests
Change-Id: I357fb84941bfbb3892a8c46feb47f55b865b6649
parent b76b3056
Loading
Loading
Loading
Loading
+47 −18
Original line number Original line Diff line number Diff line
@@ -17,6 +17,7 @@
#include "java/AnnotationProcessor.h"
#include "java/AnnotationProcessor.h"


#include <algorithm>
#include <algorithm>
#include <array>


#include "text/Unicode.h"
#include "text/Unicode.h"
#include "text/Utf8Iterator.h"
#include "text/Utf8Iterator.h"
@@ -41,30 +42,54 @@ StringPiece AnnotationProcessor::ExtractFirstSentence(const StringPiece& comment
  return comment;
  return comment;
}
}


void AnnotationProcessor::AppendCommentLine(std::string& comment) {
struct AnnotationRule {
  enum : uint32_t {
    kDeprecated = 0x01,
    kSystemApi = 0x02,
    kTestApi = 0x04,
  };

  StringPiece doc_str;
  uint32_t bit_mask;
  StringPiece annotation;
};

static std::array<AnnotationRule, 2> sAnnotationRules = {{
    {"@SystemApi", AnnotationRule::kSystemApi, "@android.annotation.SystemApi"},
    {"@TestApi", AnnotationRule::kTestApi, "@android.annotation.TestApi"},
}};

void AnnotationProcessor::AppendCommentLine(std::string comment) {
  static const std::string sDeprecated = "@deprecated";
  static const std::string sDeprecated = "@deprecated";
  static const std::string sSystemApi = "@SystemApi";


  // Treat deprecated specially, since we don't remove it from the source comment.
  if (comment.find(sDeprecated) != std::string::npos) {
  if (comment.find(sDeprecated) != std::string::npos) {
    annotation_bit_mask_ |= kDeprecated;
    annotation_bit_mask_ |= AnnotationRule::kDeprecated;
  }
  }


  std::string::size_type idx = comment.find(sSystemApi);
  for (const AnnotationRule& rule : sAnnotationRules) {
    std::string::size_type idx = comment.find(rule.doc_str.data());
    if (idx != std::string::npos) {
    if (idx != std::string::npos) {
    annotation_bit_mask_ |= kSystemApi;
      annotation_bit_mask_ |= rule.bit_mask;
    comment.erase(comment.begin() + idx,
      comment.erase(comment.begin() + idx, comment.begin() + idx + rule.doc_str.size());
                  comment.begin() + idx + sSystemApi.size());
    }
  }
  }


  if (util::TrimWhitespace(comment).empty()) {
  // Check if after removal of annotations the line is empty.
  const StringPiece trimmed = util::TrimWhitespace(comment);
  if (trimmed.empty()) {
    return;
    return;
  }
  }


  // If there was trimming to do, copy the string.
  if (trimmed.size() != comment.size()) {
    comment = trimmed.to_string();
  }

  if (!has_comments_) {
  if (!has_comments_) {
    has_comments_ = true;
    has_comments_ = true;
    comment_ << "/**";
    comment_ << "/**";
  }
  }

  comment_ << "\n * " << std::move(comment);
  comment_ << "\n * " << std::move(comment);
}
}


@@ -73,16 +98,18 @@ void AnnotationProcessor::AppendComment(const StringPiece& comment) {
  for (StringPiece line : util::Tokenize(comment, '\n')) {
  for (StringPiece line : util::Tokenize(comment, '\n')) {
    line = util::TrimWhitespace(line);
    line = util::TrimWhitespace(line);
    if (!line.empty()) {
    if (!line.empty()) {
      std::string lineCopy = line.to_string();
      AppendCommentLine(line.to_string());
      AppendCommentLine(lineCopy);
    }
    }
  }
  }
}
}


void AnnotationProcessor::AppendNewLine() { comment_ << "\n *"; }
void AnnotationProcessor::AppendNewLine() {
  if (has_comments_) {
    comment_ << "\n *";
  }
}


void AnnotationProcessor::WriteToStream(std::ostream* out,
void AnnotationProcessor::WriteToStream(const StringPiece& prefix, std::ostream* out) const {
                                        const StringPiece& prefix) const {
  if (has_comments_) {
  if (has_comments_) {
    std::string result = comment_.str();
    std::string result = comment_.str();
    for (StringPiece line : util::Tokenize(result, '\n')) {
    for (StringPiece line : util::Tokenize(result, '\n')) {
@@ -92,12 +119,14 @@ void AnnotationProcessor::WriteToStream(std::ostream* out,
         << "\n";
         << "\n";
  }
  }


  if (annotation_bit_mask_ & kDeprecated) {
  if (annotation_bit_mask_ & AnnotationRule::kDeprecated) {
    *out << prefix << "@Deprecated\n";
    *out << prefix << "@Deprecated\n";
  }
  }


  if (annotation_bit_mask_ & kSystemApi) {
  for (const AnnotationRule& rule : sAnnotationRules) {
    *out << prefix << "@android.annotation.SystemApi\n";
    if (annotation_bit_mask_ & rule.bit_mask) {
      *out << prefix << rule.annotation << "\n";
    }
  }
  }
}
}


+32 −43
Original line number Original line Diff line number Diff line
@@ -24,64 +24,53 @@


namespace aapt {
namespace aapt {


/**
// Builds a JavaDoc comment from a set of XML comments.
 * Builds a JavaDoc comment from a set of XML comments.
// This will also look for instances of @SystemApi and convert them to
 * This will also look for instances of @SystemApi and convert them to
// actual Java annotations.
 * actual Java annotations.
//
 *
// Example:
 * Example:
//
 *
// Input XML:
 * Input XML:
//
 *
// <!-- This is meant to be hidden because
 * <!-- This is meant to be hidden because
//      It is system api. Also it is @deprecated
 *      It is system api. Also it is @deprecated
//      @SystemApi
 *      @SystemApi
//      -->
 *      -->
//
 *
// Output JavaDoc:
 * Output JavaDoc:
//
 *
//  /**
 *  /\*
//   * This is meant to be hidden because
 *   * This is meant to be hidden because
//   * It is system api. Also it is @deprecated
 *   * It is system api. Also it is @deprecated
//   */
 *   *\/
//
 *
// Output Annotations:
 * Output Annotations:
//
 *
// @Deprecated
 * @Deprecated
// @android.annotation.SystemApi
 * @android.annotation.SystemApi
 *
 */
class AnnotationProcessor {
class AnnotationProcessor {
 public:
 public:
  // Extracts the first sentence of a comment. The algorithm selects the substring starting from
  // the beginning of the string, and ending at the first '.' character that is followed by a
  // whitespace character. If these requirements are not met, the whole string is returned.
  static android::StringPiece ExtractFirstSentence(const android::StringPiece& comment);
  static android::StringPiece ExtractFirstSentence(const android::StringPiece& comment);


  /**
  // Adds more comments. Resources can have value definitions for various configurations, and
   * Adds more comments. Since resources can have various values with different
  // each of the definitions may have comments that need to be processed.
   * configurations,
   * we need to collect all the comments.
   */
  void AppendComment(const android::StringPiece& comment);
  void AppendComment(const android::StringPiece& comment);


  void AppendNewLine();
  void AppendNewLine();


  /**
  // Writes the comments and annotations to the stream, with the given prefix before each line.
   * Writes the comments and annotations to the stream, with the given prefix
  void WriteToStream(const android::StringPiece& prefix, std::ostream* out) const;
   * before each line.
   */
  void WriteToStream(std::ostream* out, const android::StringPiece& prefix) const;


 private:
 private:
  enum : uint32_t {
    kDeprecated = 0x01,
    kSystemApi = 0x02,
  };

  std::stringstream comment_;
  std::stringstream comment_;
  std::stringstream mAnnotations;
  std::stringstream mAnnotations;
  bool has_comments_ = false;
  bool has_comments_ = false;
  uint32_t annotation_bit_mask_ = 0;
  uint32_t annotation_bit_mask_ = 0;


  void AppendCommentLine(std::string& line);
  void AppendCommentLine(std::string line);
};
};


}  // namespace aapt
}  // namespace aapt
+15 −2
Original line number Original line Diff line number Diff line
@@ -34,7 +34,7 @@ TEST(AnnotationProcessorTest, EmitsDeprecated) {
  processor.AppendComment(comment);
  processor.AppendComment(comment);


  std::stringstream result;
  std::stringstream result;
  processor.WriteToStream(&result, "");
  processor.WriteToStream("", &result);
  std::string annotations = result.str();
  std::string annotations = result.str();


  EXPECT_THAT(annotations, HasSubstr("@Deprecated"));
  EXPECT_THAT(annotations, HasSubstr("@Deprecated"));
@@ -45,7 +45,7 @@ TEST(AnnotationProcessorTest, EmitsSystemApiAnnotationAndRemovesFromComment) {
  processor.AppendComment("@SystemApi This is a system API");
  processor.AppendComment("@SystemApi This is a system API");


  std::stringstream result;
  std::stringstream result;
  processor.WriteToStream(&result, "");
  processor.WriteToStream("", &result);
  std::string annotations = result.str();
  std::string annotations = result.str();


  EXPECT_THAT(annotations, HasSubstr("@android.annotation.SystemApi"));
  EXPECT_THAT(annotations, HasSubstr("@android.annotation.SystemApi"));
@@ -53,6 +53,19 @@ TEST(AnnotationProcessorTest, EmitsSystemApiAnnotationAndRemovesFromComment) {
  EXPECT_THAT(annotations, HasSubstr("This is a system API"));
  EXPECT_THAT(annotations, HasSubstr("This is a system API"));
}
}


TEST(AnnotationProcessorTest, EmitsTestApiAnnotationAndRemovesFromComment) {
  AnnotationProcessor processor;
  processor.AppendComment("@TestApi This is a test API");

  std::stringstream result;
  processor.WriteToStream("", &result);
  std::string annotations = result.str();

  EXPECT_THAT(annotations, HasSubstr("@android.annotation.TestApi"));
  EXPECT_THAT(annotations, Not(HasSubstr("@TestApi")));
  EXPECT_THAT(annotations, HasSubstr("This is a test API"));
}

TEST(AnnotationProcessor, ExtractsFirstSentence) {
TEST(AnnotationProcessor, ExtractsFirstSentence) {
  EXPECT_THAT(AnnotationProcessor::ExtractFirstSentence("This is the only sentence"),
  EXPECT_THAT(AnnotationProcessor::ExtractFirstSentence("This is the only sentence"),
              Eq("This is the only sentence"));
              Eq("This is the only sentence"));
+4 −5
Original line number Original line Diff line number Diff line
@@ -18,12 +18,12 @@


#include "androidfw/StringPiece.h"
#include "androidfw/StringPiece.h"


using android::StringPiece;
using ::android::StringPiece;


namespace aapt {
namespace aapt {


void ClassMember::WriteToStream(const StringPiece& prefix, bool final, std::ostream* out) const {
void ClassMember::WriteToStream(const StringPiece& prefix, bool final, std::ostream* out) const {
  processor_.WriteToStream(out, prefix);
  processor_.WriteToStream(prefix, out);
}
}


void MethodDefinition::AppendStatement(const StringPiece& statement) {
void MethodDefinition::AppendStatement(const StringPiece& statement) {
@@ -81,9 +81,8 @@ constexpr static const char* sWarningHeader =
    " * should not be modified by hand.\n"
    " * should not be modified by hand.\n"
    " */\n\n";
    " */\n\n";


bool ClassDefinition::WriteJavaFile(const ClassDefinition* def,
bool ClassDefinition::WriteJavaFile(const ClassDefinition* def, const StringPiece& package,
                                    const StringPiece& package, bool final,
                                    bool final, std::ostream* out) {
                                    std::ostream* out) {
  *out << sWarningHeader << "package " << package << ";\n\n";
  *out << sWarningHeader << "package " << package << ";\n\n";
  def->WriteToStream("", final, out);
  def->WriteToStream("", final, out);
  return bool(*out);
  return bool(*out);
+59 −85
Original line number Original line Diff line number Diff line
@@ -22,7 +22,9 @@
#include "test/Test.h"
#include "test/Test.h"
#include "util/Util.h"
#include "util/Util.h"


using android::StringPiece;
using ::android::StringPiece;
using ::testing::HasSubstr;
using ::testing::Not;


namespace aapt {
namespace aapt {


@@ -52,8 +54,7 @@ TEST(JavaClassGeneratorTest, TransformInvalidJavaIdentifierCharacter) {
          .AddSimple("android:id/hey-man", ResourceId(0x01020000))
          .AddSimple("android:id/hey-man", ResourceId(0x01020000))
          .AddValue("android:attr/cool.attr", ResourceId(0x01010000),
          .AddValue("android:attr/cool.attr", ResourceId(0x01010000),
                    test::AttributeBuilder(false).Build())
                    test::AttributeBuilder(false).Build())
          .AddValue(
          .AddValue("android:styleable/hey.dude", ResourceId(0x01030000),
              "android:styleable/hey.dude", ResourceId(0x01030000),
                    test::StyleableBuilder()
                    test::StyleableBuilder()
                        .AddItem("android:attr/cool.attr", ResourceId(0x01010000))
                        .AddItem("android:attr/cool.attr", ResourceId(0x01010000))
                        .Build())
                        .Build())
@@ -61,8 +62,7 @@ TEST(JavaClassGeneratorTest, TransformInvalidJavaIdentifierCharacter) {


  std::unique_ptr<IAaptContext> context =
  std::unique_ptr<IAaptContext> context =
      test::ContextBuilder()
      test::ContextBuilder()
          .AddSymbolSource(
          .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
              util::make_unique<ResourceTableSymbolSource>(table.get()))
          .SetNameManglerPolicy(NameManglerPolicy{"android"})
          .SetNameManglerPolicy(NameManglerPolicy{"android"})
          .Build();
          .Build();
  JavaClassGenerator generator(context.get(), table.get(), {});
  JavaClassGenerator generator(context.get(), table.get(), {});
@@ -72,14 +72,9 @@ TEST(JavaClassGeneratorTest, TransformInvalidJavaIdentifierCharacter) {


  std::string output = out.str();
  std::string output = out.str();


  EXPECT_NE(std::string::npos,
  EXPECT_THAT(output, HasSubstr("public static final int hey_man=0x01020000;"));
            output.find("public static final int hey_man=0x01020000;"));
  EXPECT_THAT(output, HasSubstr("public static final int[] hey_dude={"));

  EXPECT_THAT(output, HasSubstr("public static final int hey_dude_cool_attr=0;"));
  EXPECT_NE(std::string::npos,
            output.find("public static final int[] hey_dude={"));

  EXPECT_NE(std::string::npos,
            output.find("public static final int hey_dude_cool_attr=0;"));
}
}


TEST(JavaClassGeneratorTest, CorrectPackageNameIsUsed) {
TEST(JavaClassGeneratorTest, CorrectPackageNameIsUsed) {
@@ -92,8 +87,7 @@ TEST(JavaClassGeneratorTest, CorrectPackageNameIsUsed) {


  std::unique_ptr<IAaptContext> context =
  std::unique_ptr<IAaptContext> context =
      test::ContextBuilder()
      test::ContextBuilder()
          .AddSymbolSource(
          .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
              util::make_unique<ResourceTableSymbolSource>(table.get()))
          .SetNameManglerPolicy(NameManglerPolicy{"android"})
          .SetNameManglerPolicy(NameManglerPolicy{"android"})
          .Build();
          .Build();
  JavaClassGenerator generator(context.get(), table.get(), {});
  JavaClassGenerator generator(context.get(), table.get(), {});
@@ -101,11 +95,10 @@ TEST(JavaClassGeneratorTest, CorrectPackageNameIsUsed) {
  ASSERT_TRUE(generator.Generate("android", "com.android.internal", &out));
  ASSERT_TRUE(generator.Generate("android", "com.android.internal", &out));


  std::string output = out.str();
  std::string output = out.str();
  EXPECT_NE(std::string::npos, output.find("package com.android.internal;"));
  EXPECT_THAT(output, HasSubstr("package com.android.internal;"));
  EXPECT_NE(std::string::npos,
  EXPECT_THAT(output, HasSubstr("public static final int one=0x01020000;"));
            output.find("public static final int one=0x01020000;"));
  EXPECT_THAT(output, Not(HasSubstr("two")));
  EXPECT_EQ(std::string::npos, output.find("two"));
  EXPECT_THAT(output, Not(HasSubstr("com_foo$two")));
  EXPECT_EQ(std::string::npos, output.find("com_foo$two"));
}
}


TEST(JavaClassGeneratorTest, AttrPrivateIsWrittenAsAttr) {
TEST(JavaClassGeneratorTest, AttrPrivateIsWrittenAsAttr) {
@@ -118,8 +111,7 @@ TEST(JavaClassGeneratorTest, AttrPrivateIsWrittenAsAttr) {


  std::unique_ptr<IAaptContext> context =
  std::unique_ptr<IAaptContext> context =
      test::ContextBuilder()
      test::ContextBuilder()
          .AddSymbolSource(
          .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
              util::make_unique<ResourceTableSymbolSource>(table.get()))
          .SetNameManglerPolicy(NameManglerPolicy{"android"})
          .SetNameManglerPolicy(NameManglerPolicy{"android"})
          .Build();
          .Build();
  JavaClassGenerator generator(context.get(), table.get(), {});
  JavaClassGenerator generator(context.get(), table.get(), {});
@@ -127,9 +119,8 @@ TEST(JavaClassGeneratorTest, AttrPrivateIsWrittenAsAttr) {
  ASSERT_TRUE(generator.Generate("android", &out));
  ASSERT_TRUE(generator.Generate("android", &out));


  std::string output = out.str();
  std::string output = out.str();
  EXPECT_NE(std::string::npos, output.find("public static final class attr"));
  EXPECT_THAT(output, HasSubstr("public static final class attr"));
  EXPECT_EQ(std::string::npos,
  EXPECT_THAT(output, Not(HasSubstr("public static final class ^attr-private")));
            output.find("public static final class ^attr-private"));
}
}


TEST(JavaClassGeneratorTest, OnlyWritePublicResources) {
TEST(JavaClassGeneratorTest, OnlyWritePublicResources) {
@@ -140,16 +131,13 @@ TEST(JavaClassGeneratorTest, OnlyWritePublicResources) {
          .AddSimple("android:id/one", ResourceId(0x01020000))
          .AddSimple("android:id/one", ResourceId(0x01020000))
          .AddSimple("android:id/two", ResourceId(0x01020001))
          .AddSimple("android:id/two", ResourceId(0x01020001))
          .AddSimple("android:id/three", ResourceId(0x01020002))
          .AddSimple("android:id/three", ResourceId(0x01020002))
          .SetSymbolState("android:id/one", ResourceId(0x01020000),
          .SetSymbolState("android:id/one", ResourceId(0x01020000), SymbolState::kPublic)
                          SymbolState::kPublic)
          .SetSymbolState("android:id/two", ResourceId(0x01020001), SymbolState::kPrivate)
          .SetSymbolState("android:id/two", ResourceId(0x01020001),
                          SymbolState::kPrivate)
          .Build();
          .Build();


  std::unique_ptr<IAaptContext> context =
  std::unique_ptr<IAaptContext> context =
      test::ContextBuilder()
      test::ContextBuilder()
          .AddSymbolSource(
          .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
              util::make_unique<ResourceTableSymbolSource>(table.get()))
          .SetNameManglerPolicy(NameManglerPolicy{"android"})
          .SetNameManglerPolicy(NameManglerPolicy{"android"})
          .Build();
          .Build();


@@ -160,10 +148,9 @@ TEST(JavaClassGeneratorTest, OnlyWritePublicResources) {
    std::stringstream out;
    std::stringstream out;
    ASSERT_TRUE(generator.Generate("android", &out));
    ASSERT_TRUE(generator.Generate("android", &out));
    std::string output = out.str();
    std::string output = out.str();
    EXPECT_NE(std::string::npos,
    EXPECT_THAT(output, HasSubstr("public static final int one=0x01020000;"));
              output.find("public static final int one=0x01020000;"));
    EXPECT_THAT(output, Not(HasSubstr("two")));
    EXPECT_EQ(std::string::npos, output.find("two"));
    EXPECT_THAT(output, Not(HasSubstr("three")));
    EXPECT_EQ(std::string::npos, output.find("three"));
  }
  }


  options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
  options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
@@ -172,11 +159,9 @@ TEST(JavaClassGeneratorTest, OnlyWritePublicResources) {
    std::stringstream out;
    std::stringstream out;
    ASSERT_TRUE(generator.Generate("android", &out));
    ASSERT_TRUE(generator.Generate("android", &out));
    std::string output = out.str();
    std::string output = out.str();
    EXPECT_NE(std::string::npos,
    EXPECT_THAT(output, HasSubstr("public static final int one=0x01020000;"));
              output.find("public static final int one=0x01020000;"));
    EXPECT_THAT(output, HasSubstr("public static final int two=0x01020001;"));
    EXPECT_NE(std::string::npos,
    EXPECT_THAT(output, Not(HasSubstr("three")));
              output.find("public static final int two=0x01020001;"));
    EXPECT_EQ(std::string::npos, output.find("three"));
  }
  }


  options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
  options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
@@ -185,12 +170,9 @@ TEST(JavaClassGeneratorTest, OnlyWritePublicResources) {
    std::stringstream out;
    std::stringstream out;
    ASSERT_TRUE(generator.Generate("android", &out));
    ASSERT_TRUE(generator.Generate("android", &out));
    std::string output = out.str();
    std::string output = out.str();
    EXPECT_NE(std::string::npos,
    EXPECT_THAT(output, HasSubstr("public static final int one=0x01020000;"));
              output.find("public static final int one=0x01020000;"));
    EXPECT_THAT(output, HasSubstr("public static final int two=0x01020001;"));
    EXPECT_NE(std::string::npos,
    EXPECT_THAT(output, HasSubstr("public static final int three=0x01020002;"));
              output.find("public static final int two=0x01020001;"));
    EXPECT_NE(std::string::npos,
              output.find("public static final int three=0x01020002;"));
  }
  }
}
}


@@ -246,8 +228,7 @@ TEST(JavaClassGeneratorTest, EmitOtherPackagesAttributesInStyleable) {


  std::unique_ptr<IAaptContext> context =
  std::unique_ptr<IAaptContext> context =
      test::ContextBuilder()
      test::ContextBuilder()
          .AddSymbolSource(
          .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
              util::make_unique<ResourceTableSymbolSource>(table.get()))
          .SetNameManglerPolicy(NameManglerPolicy{"android"})
          .SetNameManglerPolicy(NameManglerPolicy{"android"})
          .Build();
          .Build();
  JavaClassGenerator generator(context.get(), table.get(), {});
  JavaClassGenerator generator(context.get(), table.get(), {});
@@ -256,8 +237,8 @@ TEST(JavaClassGeneratorTest, EmitOtherPackagesAttributesInStyleable) {
  EXPECT_TRUE(generator.Generate("android", &out));
  EXPECT_TRUE(generator.Generate("android", &out));


  std::string output = out.str();
  std::string output = out.str();
  EXPECT_NE(std::string::npos, output.find("int foo_bar="));
  EXPECT_THAT(output, HasSubstr("int foo_bar="));
  EXPECT_NE(std::string::npos, output.find("int foo_com_lib_bar="));
  EXPECT_THAT(output, HasSubstr("int foo_com_lib_bar="));
}
}


TEST(JavaClassGeneratorTest, CommentsForSimpleResourcesArePresent) {
TEST(JavaClassGeneratorTest, CommentsForSimpleResourcesArePresent) {
@@ -271,24 +252,22 @@ TEST(JavaClassGeneratorTest, CommentsForSimpleResourcesArePresent) {


  std::unique_ptr<IAaptContext> context =
  std::unique_ptr<IAaptContext> context =
      test::ContextBuilder()
      test::ContextBuilder()
          .AddSymbolSource(
          .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
              util::make_unique<ResourceTableSymbolSource>(table.get()))
          .SetNameManglerPolicy(NameManglerPolicy{"android"})
          .SetNameManglerPolicy(NameManglerPolicy{"android"})
          .Build();
          .Build();
  JavaClassGenerator generator(context.get(), table.get(), {});
  JavaClassGenerator generator(context.get(), table.get(), {});
  std::stringstream out;
  std::stringstream out;
  ASSERT_TRUE(generator.Generate("android", &out));
  ASSERT_TRUE(generator.Generate("android", &out));
  std::string actual = out.str();
  std::string output = out.str();


  const char* expectedText =
  const char* expected_text =
      R"EOF(/**
      R"EOF(/**
     * This is a comment
     * This is a comment
     * @deprecated
     * @deprecated
     */
     */
    @Deprecated
    @Deprecated
    public static final int foo=0x01010000;)EOF";
    public static final int foo=0x01010000;)EOF";

  EXPECT_THAT(output, HasSubstr(expected_text));
  EXPECT_NE(std::string::npos, actual.find(expectedText));
}
}


TEST(JavaClassGeneratorTest, CommentsForEnumAndFlagAttributesArePresent) {}
TEST(JavaClassGeneratorTest, CommentsForEnumAndFlagAttributesArePresent) {}
@@ -298,8 +277,7 @@ TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent)
  attr.SetComment(StringPiece("This is an attribute"));
  attr.SetComment(StringPiece("This is an attribute"));


  Styleable styleable;
  Styleable styleable;
  styleable.entries.push_back(
  styleable.entries.push_back(Reference(test::ParseNameOrDie("android:attr/one")));
      Reference(test::ParseNameOrDie("android:attr/one")));
  styleable.SetComment(StringPiece("This is a styleable"));
  styleable.SetComment(StringPiece("This is a styleable"));


  std::unique_ptr<ResourceTable> table =
  std::unique_ptr<ResourceTable> table =
@@ -312,8 +290,7 @@ TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent)


  std::unique_ptr<IAaptContext> context =
  std::unique_ptr<IAaptContext> context =
      test::ContextBuilder()
      test::ContextBuilder()
          .AddSymbolSource(
          .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
              util::make_unique<ResourceTableSymbolSource>(table.get()))
          .SetNameManglerPolicy(NameManglerPolicy{"android"})
          .SetNameManglerPolicy(NameManglerPolicy{"android"})
          .Build();
          .Build();
  JavaClassGeneratorOptions options;
  JavaClassGeneratorOptions options;
@@ -321,12 +298,12 @@ TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent)
  JavaClassGenerator generator(context.get(), table.get(), options);
  JavaClassGenerator generator(context.get(), table.get(), options);
  std::stringstream out;
  std::stringstream out;
  ASSERT_TRUE(generator.Generate("android", &out));
  ASSERT_TRUE(generator.Generate("android", &out));
  std::string actual = out.str();
  std::string output = out.str();


  EXPECT_NE(std::string::npos, actual.find("attr name android:one"));
  EXPECT_THAT(output, HasSubstr("attr name android:one"));
  EXPECT_NE(std::string::npos, actual.find("attr description"));
  EXPECT_THAT(output, HasSubstr("attr description"));
  EXPECT_NE(std::string::npos, actual.find(attr.GetComment().data()));
  EXPECT_THAT(output, HasSubstr(attr.GetComment()));
  EXPECT_NE(std::string::npos, actual.find(styleable.GetComment().data()));
  EXPECT_THAT(output, HasSubstr(styleable.GetComment()));
}
}


TEST(JavaClassGeneratorTest, CommentsForRemovedAttributesAreNotPresentInClass) {
TEST(JavaClassGeneratorTest, CommentsForRemovedAttributesAreNotPresentInClass) {
@@ -341,8 +318,7 @@ TEST(JavaClassGeneratorTest, CommentsForRemovedAttributesAreNotPresentInClass) {


  std::unique_ptr<IAaptContext> context =
  std::unique_ptr<IAaptContext> context =
      test::ContextBuilder()
      test::ContextBuilder()
          .AddSymbolSource(
          .AddSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
              util::make_unique<ResourceTableSymbolSource>(table.get()))
          .SetNameManglerPolicy(NameManglerPolicy{"android"})
          .SetNameManglerPolicy(NameManglerPolicy{"android"})
          .Build();
          .Build();
  JavaClassGeneratorOptions options;
  JavaClassGeneratorOptions options;
@@ -350,17 +326,17 @@ TEST(JavaClassGeneratorTest, CommentsForRemovedAttributesAreNotPresentInClass) {
  JavaClassGenerator generator(context.get(), table.get(), options);
  JavaClassGenerator generator(context.get(), table.get(), options);
  std::stringstream out;
  std::stringstream out;
  ASSERT_TRUE(generator.Generate("android", &out));
  ASSERT_TRUE(generator.Generate("android", &out));
  std::string actual = out.str();
  std::string output = out.str();


  EXPECT_EQ(std::string::npos, actual.find("@attr name android:one"));
  EXPECT_THAT(output, Not(HasSubstr("@attr name android:one")));
  EXPECT_EQ(std::string::npos, actual.find("@attr description"));
  EXPECT_THAT(output, Not(HasSubstr("@attr description")));


  // We should find @removed only in the attribute javadoc and not anywhere else
  // We should find @removed only in the attribute javadoc and not anywhere else
  // (i.e. the class
  // (i.e. the class javadoc).
  // javadoc).
  const std::string kRemoved("removed");
  const size_t pos = actual.find("removed");
  ASSERT_THAT(output, HasSubstr(kRemoved));
  EXPECT_NE(std::string::npos, pos);
  std::string after_first_match = output.substr(output.find(kRemoved) + kRemoved.size());
  EXPECT_EQ(std::string::npos, actual.find("removed", pos + 1));
  EXPECT_THAT(after_first_match, Not(HasSubstr(kRemoved)));
}
}


TEST(JavaClassGeneratorTest, GenerateOnResourcesLoadedCallbackForSharedLibrary) {
TEST(JavaClassGeneratorTest, GenerateOnResourcesLoadedCallbackForSharedLibrary) {
@@ -381,19 +357,17 @@ TEST(JavaClassGeneratorTest, GenerateOnResourcesLoadedCallbackForSharedLibrary)


  JavaClassGeneratorOptions options;
  JavaClassGeneratorOptions options;
  options.use_final = false;
  options.use_final = false;
  options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{
  options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{{"com.foo", "com.boo"}};
      {"com.foo", "com.boo"},
  };
  JavaClassGenerator generator(context.get(), table.get(), options);
  JavaClassGenerator generator(context.get(), table.get(), options);


  std::stringstream out;
  std::stringstream out;
  ASSERT_TRUE(generator.Generate("android", &out));
  ASSERT_TRUE(generator.Generate("android", &out));


  std::string actual = out.str();
  std::string output = out.str();


  EXPECT_NE(std::string::npos, actual.find("void onResourcesLoaded"));
  EXPECT_THAT(output, HasSubstr("void onResourcesLoaded"));
  EXPECT_NE(std::string::npos, actual.find("com.foo.R.onResourcesLoaded"));
  EXPECT_THAT(output, HasSubstr("com.foo.R.onResourcesLoaded"));
  EXPECT_NE(std::string::npos, actual.find("com.boo.R.onResourcesLoaded"));
  EXPECT_THAT(output, HasSubstr("com.boo.R.onResourcesLoaded"));
}
}


}  // namespace aapt
}  // namespace aapt
Loading