diff options
author | Googler <noreply@google.com> | 2018-05-03 15:29:49 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-05-03 15:31:47 -0700 |
commit | bfbb11bcc55017ed22e99e1f2221b62e0beff609 (patch) | |
tree | ae0082ba50086864e4edde53f6b7ee564ecad412 /src/tools/android/java/com/google | |
parent | 36bc96e2e645dec2eca9a8f4174f9ed6b351df51 (diff) |
Internal change
PiperOrigin-RevId: 195321054
Diffstat (limited to 'src/tools/android/java/com/google')
3 files changed, 73 insertions, 127 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java b/src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java index f23a21faef..e8f6ee3ada 100644 --- a/src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java +++ b/src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java @@ -16,16 +16,13 @@ package com.google.devtools.build.android; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Strings.emptyToNull; -import com.android.SdkConstants; import com.android.annotations.VisibleForTesting; import com.android.ide.common.resources.configuration.FolderConfiguration; import com.android.ide.common.resources.configuration.ResourceQualifier; -import com.android.resources.ResourceFolderType; import com.android.resources.ResourceType; import com.google.common.base.Joiner; import com.google.common.base.MoreObjects; import com.google.common.base.Preconditions; -import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterators; import com.google.common.collect.PeekingIterator; @@ -36,7 +33,6 @@ import java.io.OutputStream; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.Optional; @@ -62,7 +58,6 @@ public class FullyQualifiedName implements DataKey { // Using a HashMap to deduplicate the instances -- the key retrieves a single instance. private static final ConcurrentMap<FullyQualifiedName, FullyQualifiedName> instanceCache = new ConcurrentHashMap<>(); - private static final AtomicInteger cacheHit = new AtomicInteger(0); private final String pkg; private final ImmutableList<String> qualifiers; @@ -190,7 +185,7 @@ public class FullyQualifiedName implements DataKey { // TODO(corysmith): Add package when we start tracking it. return String.format( "%s%s/%s", - DEFAULT_PACKAGE.equals(pkg) ? "" : pkg + ':', + pkg != DEFAULT_PACKAGE ? pkg + ':' : "", DASH_JOINER.join( ImmutableList.<String>builder().add(type.getName()).addAll(qualifiers).build()), name); @@ -403,29 +398,29 @@ public class FullyQualifiedName implements DataKey { /** Represents the type of a {@link FullyQualifiedName}. */ public interface Type { - String getName(); + public String getName(); - ConcreteType getType(); + public ConcreteType getType(); - boolean isOverwritable(FullyQualifiedName fqn); + public boolean isOverwritable(FullyQualifiedName fqn); - int compareTo(Type other); + public int compareTo(Type other); @Override - boolean equals(Object obj); + public boolean equals(Object obj); @Override - int hashCode(); + public int hashCode(); @Override - String toString(); + public String toString(); /** * The category of type that a {@link Type} can be. * * <p><em>Note:</em> used for strict ordering of {@link FullyQualifiedName}s. */ - enum ConcreteType { + public enum ConcreteType { RESOURCE_TYPE, VIRTUAL_TYPE; } @@ -483,36 +478,53 @@ public class FullyQualifiedName implements DataKey { } } - /** Represents the configuration qualifiers in a resource directory. */ - public static class Qualifiers { - - // Qualifiers are reasonably expensive to create, so cache them on directory names. - private static final ConcurrentMap<String, Qualifiers> qualifierCache = - new ConcurrentHashMap<>(); + /** A factory for parsing an generating FullyQualified names with qualifiers and package. */ + public static class Factory { + public static final String INVALID_QUALIFIED_NAME_MESSAGE_NO_MATCH = + String.format( + "%%s is not a valid qualified name. " + + "It should be in the pattern [package:]{%s}/name", + Joiner.on(",") + .join( + ImmutableList.<String>builder() + .add(ResourceType.getNames()) + .add(VirtualType.getNames()) + .build())); + public static final String INVALID_QUALIFIED_NAME_MESSAGE_NO_TYPE_OR_NAME = + String.format( + "Could not find either resource type (%%s) or name (%%s) in %%s. " + + "It should be in the pattern [package:]{%s}/name", + Joiner.on(",") + .join( + ImmutableList.<String>builder() + .add(ResourceType.getNames()) + .add(VirtualType.getNames()) + .build())); public static final String INVALID_QUALIFIERS = "%s contains invalid qualifiers."; - private final ResourceFolderType folderType; + private static final Pattern PARSING_REGEX = + Pattern.compile( + "(?:(?<package>[^:]+):){0,1}(?<type>[^-/]+)(?:[^/]*)/(?:(?:(?<namespace>\\{[^}]+\\}))" + + "|(?:(?<misplacedPackage>[^:]+):)){0,1}(?<name>.+)"); private final ImmutableList<String> qualifiers; + private final String pkg; - private Qualifiers(ResourceFolderType folderType, ImmutableList<String> qualifiers) { - this.folderType = folderType; + private Factory(ImmutableList<String> qualifiers, String pkg) { this.qualifiers = qualifiers; + this.pkg = pkg; } - public static Qualifiers parseFrom(String directoryName) { - return qualifierCache.computeIfAbsent( - directoryName, d -> getQualifiers(Splitter.on(SdkConstants.RES_QUALIFIER_SEP).split(d))); - } - - private static Qualifiers getQualifiers(String... dirNameAndQualifiers) { - return getQualifiers(Arrays.asList(dirNameAndQualifiers)); + /** Creates a factory with default package from a directory name split on '-'. */ + public static Factory fromDirectoryName(String[] dirNameAndQualifiers) { + return from(getQualifiers(dirNameAndQualifiers)); } - private static Qualifiers getQualifiers(Iterable<String> dirNameAndQualifiers) { + private static List<String> getQualifiers(String[] dirNameAndQualifiers) { PeekingIterator<String> rawQualifiers = - Iterators.peekingIterator(dirNameAndQualifiers.iterator()); + Iterators.peekingIterator(Iterators.forArray(dirNameAndQualifiers)); // Remove directory name - final ResourceFolderType folderType = ResourceFolderType.getTypeByName(rawQualifiers.next()); + rawQualifiers.next(); + List<String> transformedLocaleQualifiers = new ArrayList<>(); List<String> handledQualifiers = new ArrayList<>(); // Do some substitution of language/region qualifiers. while (rawQualifiers.hasNext()) { @@ -521,14 +533,14 @@ public class FullyQualifiedName implements DataKey { && rawQualifiers.hasNext() && "419".equalsIgnoreCase(rawQualifiers.peek())) { // Replace the es-419. - handledQualifiers.add("b+es+419"); + transformedLocaleQualifiers.add("b+es+419"); // Consume the next value, as it's been replaced. rawQualifiers.next(); } else if ("sr".equalsIgnoreCase(qualifier) && rawQualifiers.hasNext() && "rlatn".equalsIgnoreCase(rawQualifiers.peek())) { // Replace the sr-rLatn. - handledQualifiers.add("b+sr+Latn"); + transformedLocaleQualifiers.add("b+sr+Latn"); // Consume the next value, as it's been replaced. rawQualifiers.next(); } else { @@ -546,12 +558,21 @@ public class FullyQualifiedName implements DataKey { } config.normalize(); + // This is fragile but better than the Gradle scheme of just dropping + // entire subtrees. ImmutableList.Builder<String> builder = ImmutableList.<String>builder(); + addIfNotNull(config.getCountryCodeQualifier(), builder); + addIfNotNull(config.getNetworkCodeQualifier(), builder); + if (transformedLocaleQualifiers.isEmpty()) { + addIfNotNull(config.getLocaleQualifier(), builder); + } else { + builder.addAll(transformedLocaleQualifiers); + } // index 3 is past the country code, network code, and locale indices. - for (int i = 0; i < FolderConfiguration.getQualifierCount(); ++i) { + for (int i = 3; i < FolderConfiguration.getQualifierCount(); ++i) { addIfNotNull(config.getQualifier(i), builder); } - return new Qualifiers(folderType, builder.build()); + return builder.build(); } private static void addIfNotNull( @@ -561,89 +582,12 @@ public class FullyQualifiedName implements DataKey { } } - /** Returns the qualifiers as a list of strings. */ - public List<String> asList() { - return qualifiers; - } - - public ResourceFolderType asFolderType() { - return folderType; - } - - @VisibleForTesting - public static Qualifiers fromList(List<String> qualifiers) { - return new Qualifiers(null, ImmutableList.copyOf(qualifiers)); - } - } - - /** A factory for parsing an generating FullyQualified names with qualifiers and package. */ - public static class Factory { - - public static final String INVALID_QUALIFIED_NAME_MESSAGE_NO_MATCH = - String.format( - "%%s is not a valid qualified name. " - + "It should be in the pattern [package:]{%s}/name", - Joiner.on(",") - .join( - ImmutableList.<String>builder() - .add(ResourceType.getNames()) - .add(VirtualType.getNames()) - .build())); - public static final String INVALID_QUALIFIED_NAME_MESSAGE_NO_TYPE_OR_NAME = - String.format( - "Could not find either resource type (%%s) or name (%%s) in %%s. " - + "It should be in the pattern [package:]{%s}/name", - Joiner.on(",") - .join( - ImmutableList.<String>builder() - .add(ResourceType.getNames()) - .add(VirtualType.getNames()) - .build())); - private static final Pattern PARSING_REGEX = - Pattern.compile( - "(?:(?<package>[^:]+):){0,1}(?<type>[^-/]+)(?:[^/]*)/(?:(?:(?<namespace>\\{[^}]+\\}))" - + "|(?:(?<misplacedPackage>[^:]+):)){0,1}(?<name>.+)"); - // private final ImmutableList<String> qualifiers; - - private final String pkg; - - private final Qualifiers qs; - - private Factory(Qualifiers qualifiers, String pkg) { - // this.qualifiers = qualifiers; - this.pkg = pkg; - this.qs = qualifiers; - } - - /** Creates a factory with default package from a directory name split on '-'. */ - @VisibleForTesting - public static Factory fromDirectoryName(String... dirNameAndQualifiers) { - return using(Qualifiers.getQualifiers(dirNameAndQualifiers), DEFAULT_PACKAGE); - } - - /** Creates a factory with default package from a directory with '-' separating qualifiers. */ - public static Factory fromDirectoryName(String dirNameAndQualifiers) { - return using(Qualifiers.parseFrom(dirNameAndQualifiers), DEFAULT_PACKAGE); - } - - @VisibleForTesting public static Factory from(List<String> qualifiers, String pkg) { - return using(Qualifiers.fromList(qualifiers), pkg); + return new Factory(ImmutableList.copyOf(qualifiers), pkg.isEmpty() ? DEFAULT_PACKAGE : pkg); } - @VisibleForTesting public static Factory from(List<String> qualifiers) { - return from(qualifiers, DEFAULT_PACKAGE); - } - - /** Creates a factory with the qualifiers and package. */ - public static Factory using(Qualifiers qualifiers) { - return using(qualifiers, DEFAULT_PACKAGE); - } - - /** Creates a factory with the qualifiers and package. */ - public static Factory using(Qualifiers qualifiers, String pkg) { - return new Factory(qualifiers, pkg.isEmpty() ? DEFAULT_PACKAGE : pkg); + return from(ImmutableList.copyOf(qualifiers), DEFAULT_PACKAGE); } private static String deriveRawFullyQualifiedName(Path source) { @@ -676,7 +620,7 @@ public class FullyQualifiedName implements DataKey { } public FullyQualifiedName create(Type type, String name, String pkg) { - return FullyQualifiedName.of(pkg, qs.asList(), type, name); + return FullyQualifiedName.of(pkg, qualifiers, type, name); } public FullyQualifiedName create(ResourceType type, String name) { @@ -718,7 +662,7 @@ public class FullyQualifiedName implements DataKey { String.format(INVALID_QUALIFIED_NAME_MESSAGE_NO_TYPE_OR_NAME, type, name, raw)); } - return FullyQualifiedName.of(parsedPackage, qs.asList(), type, name); + return FullyQualifiedName.of(parsedPackage, qualifiers, type, name); } private String firstNonNull(String... values) { diff --git a/src/tools/android/java/com/google/devtools/build/android/ParsedAndroidData.java b/src/tools/android/java/com/google/devtools/build/android/ParsedAndroidData.java index 9d7380e1d4..83020c433e 100644 --- a/src/tools/android/java/com/google/devtools/build/android/ParsedAndroidData.java +++ b/src/tools/android/java/com/google/devtools/build/android/ParsedAndroidData.java @@ -27,7 +27,6 @@ import com.google.common.collect.Sets.SetView; import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.devtools.build.android.AndroidResourceMerger.MergingException; -import com.google.devtools.build.android.FullyQualifiedName.Qualifiers; import com.google.devtools.build.android.xml.StyleableXmlResourceValue; import java.io.IOException; import java.nio.file.FileVisitOption; @@ -299,16 +298,17 @@ public class ParsedAndroidData { @Override public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + final String[] dirNameAndQualifiers = + dir.getFileName().toString().split(SdkConstants.RES_QUALIFIER_SEP); + folderType = ResourceFolderType.getTypeByName(dirNameAndQualifiers[0]); + if (folderType == null) { + return FileVisitResult.CONTINUE; + } try { - final Qualifiers qualifiers = Qualifiers.parseFrom(dir.getFileName().toString()); - folderType = qualifiers.asFolderType(); - if (folderType == null) { - return FileVisitResult.CONTINUE; - } - fqnFactory = FullyQualifiedName.Factory.using(qualifiers); + fqnFactory = FullyQualifiedName.Factory.fromDirectoryName(dirNameAndQualifiers); return FileVisitResult.CONTINUE; } catch (IllegalArgumentException e) { - logger.severe( + logger.warning( String.format("%s is an invalid resource directory due to %s", dir, e.getMessage())); return FileVisitResult.SKIP_SUBTREE; } diff --git a/src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceCompiler.java b/src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceCompiler.java index 355fcbf4d0..b734eaa36a 100644 --- a/src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceCompiler.java +++ b/src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceCompiler.java @@ -14,6 +14,7 @@ package com.google.devtools.build.android.aapt2; +import com.android.SdkConstants; import com.android.builder.core.VariantType; import com.android.repository.Revision; import com.google.common.base.Preconditions; @@ -194,7 +195,8 @@ public class ResourceCompiler { Namespaces namespaces = Namespaces.from(qName); String attributeName = namespaceUri.isEmpty() ? localPart : prefix + ":" + localPart; - Factory fqnFactory = Factory.fromDirectoryName(type); + final String[] dirNameAndQualifiers = type.split(SdkConstants.RES_QUALIFIER_SEP); + Factory fqnFactory = Factory.fromDirectoryName(dirNameAndQualifiers); FullyQualifiedName fqn = fqnFactory.create(VirtualType.RESOURCES_ATTRIBUTE, qName.toString()); ResourcesAttribute resourceAttribute = |