aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/android
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2018-05-03 15:29:49 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-05-03 15:31:47 -0700
commitbfbb11bcc55017ed22e99e1f2221b62e0beff609 (patch)
treeae0082ba50086864e4edde53f6b7ee564ecad412 /src/tools/android
parent36bc96e2e645dec2eca9a8f4174f9ed6b351df51 (diff)
Internal change
PiperOrigin-RevId: 195321054
Diffstat (limited to 'src/tools/android')
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/FullyQualifiedName.java180
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/ParsedAndroidData.java16
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/aapt2/ResourceCompiler.java4
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 =