diff options
Diffstat (limited to 'tools/aapt2/java/JavaClassGenerator.cpp')
| -rw-r--r-- | tools/aapt2/java/JavaClassGenerator.cpp | 169 | 
1 files changed, 88 insertions, 81 deletions
| diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp index dfd2ef6f5372..7280f3a968a0 100644 --- a/tools/aapt2/java/JavaClassGenerator.cpp +++ b/tools/aapt2/java/JavaClassGenerator.cpp @@ -21,7 +21,9 @@  #include "ValueVisitor.h"  #include "java/AnnotationProcessor.h" +#include "java/ClassDefinitionWriter.h"  #include "java/JavaClassGenerator.h" +#include "util/Comparators.h"  #include "util/StringPiece.h"  #include <algorithm> @@ -32,9 +34,6 @@  namespace aapt { -// The number of attributes to emit per line in a Styleable array. -constexpr size_t kAttribsPerLine = 4; -  JavaClassGenerator::JavaClassGenerator(ResourceTable* table, JavaClassGeneratorOptions options) :          mTable(table), mOptions(options) {  } @@ -92,12 +91,11 @@ bool JavaClassGenerator::skipSymbol(SymbolState state) {      return true;  } -void JavaClassGenerator::generateStyleable(const StringPiece16& packageNameToGenerate, -                                           const std::u16string& entryName, -                                           const Styleable* styleable, -                                           std::ostream* out) { -    const StringPiece finalModifier = mOptions.useFinal ? " final" : ""; - +void JavaClassGenerator::writeStyleableEntryForClass(ClassDefinitionWriter* outClassDef, +                                                     AnnotationProcessor* processor, +                                                     const StringPiece16& packageNameToGenerate, +                                                     const std::u16string& entryName, +                                                     const Styleable* styleable) {      // This must be sorted by resource ID.      std::vector<std::pair<ResourceId, ResourceNameRef>> sortedAttributes;      sortedAttributes.reserve(styleable->entries.size()); @@ -110,36 +108,31 @@ void JavaClassGenerator::generateStyleable(const StringPiece16& packageNameToGen      }      std::sort(sortedAttributes.begin(), sortedAttributes.end()); -    // First we emit the array containing the IDs of each attribute. -    *out << "    " -         << "public static final int[] " << transform(entryName) << " = {"; - -    const size_t attrCount = sortedAttributes.size(); -    for (size_t i = 0; i < attrCount; i++) { -        if (i % kAttribsPerLine == 0) { -            *out << "\n      "; -        } +    auto accessorFunc = [](const std::pair<ResourceId, ResourceNameRef>& a) -> ResourceId { +        return a.first; +    }; -        *out << sortedAttributes[i].first; -        if (i != attrCount - 1) { -            *out << ", "; -        } -    } -    *out << "\n    };\n"; +    // First we emit the array containing the IDs of each attribute. +    outClassDef->addArrayMember(transform(entryName), processor, +                                sortedAttributes.begin(), +                                sortedAttributes.end(), +                                accessorFunc);      // Now we emit the indices into the array. +    size_t attrCount = sortedAttributes.size();      for (size_t i = 0; i < attrCount; i++) { -        *out << "    " -             << "public static" << finalModifier -             << " int " << transform(entryName); +        std::stringstream name; +        name << transform(entryName);          // We may reference IDs from other packages, so prefix the entry name with          // the package.          const ResourceNameRef& itemName = sortedAttributes[i].second;          if (!itemName.package.empty() && packageNameToGenerate != itemName.package) { -            *out << "_" << transform(itemName.package); +            name << "_" << transform(itemName.package);          } -        *out << "_" << transform(itemName.entry) << " = " << i << ";\n"; +        name << "_" << transform(itemName.entry); + +        outClassDef->addIntMember(name.str(), nullptr, i);      }  } @@ -155,8 +148,8 @@ static void addAttributeFormatDoc(AnnotationProcessor* processor, Attribute* att      if (typeMask & android::ResTable_map::TYPE_STRING) {          processor->appendComment( -                "<p>May be a string value, using '\\;' to escape characters such as\n" -                "'\\n' or '\\uxxxx' for a unicode character;"); +                "<p>May be a string value, using '\\\\;' to escape characters such as\n" +                "'\\\\n' or '\\\\uxxxx' for a unicode character;");      }      if (typeMask & android::ResTable_map::TYPE_INTEGER) { @@ -222,14 +215,10 @@ static void addAttributeFormatDoc(AnnotationProcessor* processor, Attribute* att      }  } -bool JavaClassGenerator::generateType(const StringPiece16& packageNameToGenerate, -                                      const ResourceTablePackage* package, -                                      const ResourceTableType* type, -                                      std::ostream* out) { -    const StringPiece finalModifier = mOptions.useFinal ? " final" : ""; - -    std::u16string unmangledPackage; -    std::u16string unmangledName; +bool JavaClassGenerator::writeEntriesForClass(ClassDefinitionWriter* outClassDef, +                                              const StringPiece16& packageNameToGenerate, +                                              const ResourceTablePackage* package, +                                              const ResourceTableType* type) {      for (const auto& entry : type->entries) {          if (skipSymbol(entry->symbolStatus.state)) {              continue; @@ -238,7 +227,8 @@ bool JavaClassGenerator::generateType(const StringPiece16& packageNameToGenerate          ResourceId id(package->id.value(), type->id.value(), entry->id.value());          assert(id.isValid()); -        unmangledName = entry->name; +        std::u16string unmangledPackage; +        std::u16string unmangledName = entry->name;          if (NameMangler::unmangle(&unmangledName, &unmangledPackage)) {              // The entry name was mangled, and we successfully unmangled it.              // Check that we want to emit this symbol. @@ -246,12 +236,10 @@ bool JavaClassGenerator::generateType(const StringPiece16& packageNameToGenerate                  // Skip the entry if it doesn't belong to the package we're writing.                  continue;              } -        } else { -            if (packageNameToGenerate != package->name) { -                // We are processing a mangled package name, -                // but this is a non-mangled resource. -                continue; -            } +        } else if (packageNameToGenerate != package->name) { +            // We are processing a mangled package name, +            // but this is a non-mangled resource. +            continue;          }          if (!isValidSymbol(unmangledName)) { @@ -262,39 +250,33 @@ bool JavaClassGenerator::generateType(const StringPiece16& packageNameToGenerate              return false;          } -        if (type->type == ResourceType::kStyleable) { -            assert(!entry->values.empty()); -            generateStyleable(packageNameToGenerate, unmangledName, static_cast<const Styleable*>( -                    entry->values.front().value.get()), out); -        } else { -            AnnotationProcessor processor("    "); -            if (entry->symbolStatus.state != SymbolState::kUndefined) { -                processor.appendComment(entry->symbolStatus.comment); -            } +        // Build the comments and annotations for this entry. -            for (const auto& configValue : entry->values) { -                processor.appendComment(configValue.value->getComment()); -            } - -            if (!entry->values.empty()) { -                if (Attribute* attr = valueCast<Attribute>(entry->values.front().value.get())) { -                    // We list out the available values for the given attribute. -                    addAttributeFormatDoc(&processor, attr); -                } -            } +        AnnotationProcessor processor; +        if (entry->symbolStatus.state != SymbolState::kUndefined) { +            processor.appendComment(entry->symbolStatus.comment); +        } -            std::string comment = processor.buildComment(); -            if (!comment.empty()) { -                *out << comment << "\n"; -            } +        for (const auto& configValue : entry->values) { +            processor.appendComment(configValue.value->getComment()); +        } -            std::string annotations = processor.buildAnnotations(); -            if (!annotations.empty()) { -                *out << annotations << "\n"; +        // If this is an Attribute, append the format Javadoc. +        if (!entry->values.empty()) { +            if (Attribute* attr = valueCast<Attribute>(entry->values.front().value.get())) { +                // We list out the available values for the given attribute. +                addAttributeFormatDoc(&processor, attr);              } +        } -            *out << "    " << "public static" << finalModifier -                 << " int " << transform(unmangledName) << " = " << id << ";\n"; +        if (type->type == ResourceType::kStyleable) { +            assert(!entry->values.empty()); +            const Styleable* styleable = static_cast<const Styleable*>( +                    entry->values.front().value.get()); +            writeStyleableEntryForClass(outClassDef, &processor, packageNameToGenerate, +                                        unmangledName, styleable); +        } else { +            outClassDef->addResourceMember(transform(unmangledName), &processor, id);          }      }      return true; @@ -312,17 +294,42 @@ bool JavaClassGenerator::generate(const StringPiece16& packageNameToGenerate,      for (const auto& package : mTable->packages) {          for (const auto& type : package->types) { -            StringPiece16 typeStr;              if (type->type == ResourceType::kAttrPrivate) { -                typeStr = toString(ResourceType::kAttr); -            } else { -                typeStr = toString(type->type); +                continue;              } -            *out << "  public static final class " << typeStr << " {\n"; -            if (!generateType(packageNameToGenerate, package.get(), type.get(), out)) { + +            ClassDefinitionWriterOptions classOptions; +            classOptions.useFinalQualifier = mOptions.useFinal; +            classOptions.forceCreationIfEmpty = +                    (mOptions.types == JavaClassGeneratorOptions::SymbolTypes::kPublic); +            ClassDefinitionWriter classDef(toString(type->type), classOptions); +            bool result = writeEntriesForClass(&classDef, packageNameToGenerate, +                                               package.get(), type.get()); +            if (!result) {                  return false;              } -            *out << "  }\n"; + +            if (type->type == ResourceType::kAttr) { +                // Also include private attributes in this same class. +                auto iter = std::lower_bound(package->types.begin(), package->types.end(), +                                             ResourceType::kAttrPrivate, cmp::lessThanType); +                if (iter != package->types.end() && (*iter)->type == ResourceType::kAttrPrivate) { +                    result = writeEntriesForClass(&classDef, packageNameToGenerate, +                                                  package.get(), iter->get()); +                    if (!result) { +                        return false; +                    } +                } +            } + +            AnnotationProcessor processor; +            if (type->type == ResourceType::kStyleable && +                    mOptions.types == JavaClassGeneratorOptions::SymbolTypes::kPublic) { +                // When generating a public R class, we don't want Styleable to be part of the API. +                // It is only emitted for documentation purposes. +                processor.appendComment("@doconly"); +            } +            classDef.writeToStream(out, "  ", &processor);          }      } | 
