aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/tools/android/java/com/google/devtools/build/android
diff options
context:
space:
mode:
authorGravatar corysmith <corysmith@google.com>2017-04-20 00:19:47 +0200
committerGravatar Klaus Aehlig <aehlig@google.com>2017-04-20 11:08:18 +0200
commit3c0bb56a74478cff675b636d5bf605a652451739 (patch)
treebb45dfb397ca59c1c20fabfc0971abc77455e106 /src/tools/android/java/com/google/devtools/build/android
parent652db6f23dce7351dcaf9755857e4827555d42c9 (diff)
Automated g4 rollback of commit 3217832d638f9a8fdf22e88e32d75bda32ff7235.
*** Reason for rollback *** Causes issues with library R generation. *** Original change description *** Refactor the RClassGenerator to be reusable for different packages. RELNOTES: None PiperOrigin-RevId: 153641485
Diffstat (limited to 'src/tools/android/java/com/google/devtools/build/android')
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidResourceClassWriter.java4
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java16
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/resources/FieldInitializer.java4
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/resources/IntArrayFieldInitializer.java7
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/resources/IntFieldInitializer.java6
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/resources/RClassGenerator.java114
-rw-r--r--src/tools/android/java/com/google/devtools/build/android/resources/ResourceSymbols.java19
7 files changed, 70 insertions, 100 deletions
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceClassWriter.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceClassWriter.java
index 1f0360c85b..37fb7a81a2 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceClassWriter.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceClassWriter.java
@@ -474,8 +474,8 @@ public class AndroidResourceClassWriter implements Flushable {
private void writeAsClass(Map<ResourceType, List<FieldInitializer>> initializers)
throws IOException {
RClassGenerator rClassGenerator =
- new RClassGenerator(outputBasePath, initializers, false /* finalFields */);
- rClassGenerator.write(packageName);
+ new RClassGenerator(outputBasePath, packageName, initializers, false /* finalFields */);
+ rClassGenerator.write();
}
private static String normalizeName(String resourceName) {
diff --git a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
index 45187f2d14..a9243d2584 100644
--- a/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
+++ b/src/tools/android/java/com/google/devtools/build/android/AndroidResourceProcessor.java
@@ -544,15 +544,23 @@ public class AndroidResourceProcessor {
Path classesOut,
boolean finalFields)
throws IOException {
- RClassGenerator classWriter =
- RClassGenerator.fromSymbols(classesOut, fullSymbolValues, finalFields);
for (String packageName : libMap.keySet()) {
- classWriter.write(packageName, ResourceSymbols.merge(libMap.get(packageName)).asFilterMap());
+ Collection<ResourceSymbols> symbols = libMap.get(packageName);
+ RClassGenerator classWriter = RClassGenerator.fromSymbols(
+ classesOut, packageName, fullSymbolValues, symbols, finalFields);
+ classWriter.write();
}
if (appPackageName != null) {
// Unlike the R.java generation, we also write the app's R.class file so that the class
// jar file can be complete (aapt doesn't generate it for us).
- classWriter.write(appPackageName);
+ RClassGenerator classWriter =
+ RClassGenerator.fromSymbols(
+ classesOut,
+ appPackageName,
+ fullSymbolValues,
+ ImmutableList.of(fullSymbolValues),
+ finalFields);
+ classWriter.write();
}
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/resources/FieldInitializer.java b/src/tools/android/java/com/google/devtools/build/android/resources/FieldInitializer.java
index a0b4dd59bb..a1e322fef6 100644
--- a/src/tools/android/java/com/google/devtools/build/android/resources/FieldInitializer.java
+++ b/src/tools/android/java/com/google/devtools/build/android/resources/FieldInitializer.java
@@ -15,7 +15,6 @@ package com.google.devtools.build.android.resources;
import java.io.IOException;
import java.io.Writer;
-import java.util.Set;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.commons.InstructionAdapter;
@@ -44,7 +43,4 @@ public interface FieldInitializer {
* for final fields yet.
*/
void writeInitSource(Writer writer) throws IOException;
-
- /** Tests if the field's name is in the provided set. */
- boolean nameIsIn(Set<String> fieldNames);
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/resources/IntArrayFieldInitializer.java b/src/tools/android/java/com/google/devtools/build/android/resources/IntArrayFieldInitializer.java
index eb78d53ade..48e6496d89 100644
--- a/src/tools/android/java/com/google/devtools/build/android/resources/IntArrayFieldInitializer.java
+++ b/src/tools/android/java/com/google/devtools/build/android/resources/IntArrayFieldInitializer.java
@@ -19,7 +19,6 @@ import com.google.common.collect.ImmutableCollection;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.io.Writer;
-import java.util.Set;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.Type;
import org.objectweb.asm.commons.InstructionAdapter;
@@ -93,13 +92,7 @@ public final class IntArrayFieldInitializer implements FieldInitializer {
builder.append(String.format(", 0x%x", attrId));
}
}
-
writer.write(String.format(" public static int[] %s = { %s };\n",
fieldName, builder.toString()));
}
-
- @Override
- public boolean nameIsIn(Set<String> fieldNames) {
- return fieldNames.contains(fieldName);
- }
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/resources/IntFieldInitializer.java b/src/tools/android/java/com/google/devtools/build/android/resources/IntFieldInitializer.java
index 2223a1a05f..400c26789e 100644
--- a/src/tools/android/java/com/google/devtools/build/android/resources/IntFieldInitializer.java
+++ b/src/tools/android/java/com/google/devtools/build/android/resources/IntFieldInitializer.java
@@ -15,7 +15,6 @@ package com.google.devtools.build.android.resources;
import java.io.IOException;
import java.io.Writer;
-import java.util.Set;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.commons.InstructionAdapter;
@@ -57,9 +56,4 @@ public final class IntFieldInitializer implements FieldInitializer {
writer.write(String.format(" public static int %s = 0x%x;\n",
fieldName, value));
}
-
- @Override
- public boolean nameIsIn(Set<String> fieldNames) {
- return fieldNames.contains(fieldName);
- }
}
diff --git a/src/tools/android/java/com/google/devtools/build/android/resources/RClassGenerator.java b/src/tools/android/java/com/google/devtools/build/android/resources/RClassGenerator.java
index e1149281ee..2d92e783cc 100644
--- a/src/tools/android/java/com/google/devtools/build/android/resources/RClassGenerator.java
+++ b/src/tools/android/java/com/google/devtools/build/android/resources/RClassGenerator.java
@@ -18,18 +18,19 @@ import com.android.builder.internal.SymbolLoader.SymbolEntry;
import com.android.resources.ResourceType;
import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
-import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
-import java.util.Map.Entry;
import java.util.Set;
+import java.util.logging.Logger;
import org.objectweb.asm.ClassWriter;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
@@ -43,83 +44,112 @@ import org.objectweb.asm.commons.InstructionAdapter;
* information. Also, the order of the constant pool tends to be different.
*/
public class RClassGenerator {
+
+ private static final Logger logger = Logger.getLogger(RClassGenerator.class.getName());
private static final int JAVA_VERSION = Opcodes.V1_7;
private static final String SUPER_CLASS = "java/lang/Object";
private final Path outFolder;
+ private final String packageName;
private final Map<ResourceType, List<FieldInitializer>> initializers;
private final boolean finalFields;
private static final Splitter PACKAGE_SPLITTER = Splitter.on('.');
/**
- * Create an RClassGenerator initialized with the ResourceSymbols values.
+ * Create an RClassGenerator given the final binary's symbol values, and a collection of symbols
+ * for the given package.
*
* @param outFolder base folder to place the output R class files.
- * @param values the final symbol values
+ * @param packageName the java package to use for the R class
+ * @param values the final symbol values (may include more symbols than needed for this package)
+ * @param packageSymbols the symbols in this package
* @param finalFields true if the fields should be marked final
*/
public static RClassGenerator fromSymbols(
Path outFolder,
+ String packageName,
ResourceSymbols values,
+ Collection<ResourceSymbols> packageSymbols,
boolean finalFields)
throws IOException {
+ Table<String, String, SymbolEntry> symbolsTable = getAllSymbols(packageSymbols);
Table<String, String, SymbolEntry> valuesTable = values.asTable();
Map<ResourceType, List<FieldInitializer>> initializers =
- getInitializers(valuesTable);
- return new RClassGenerator(outFolder, initializers, finalFields);
+ getInitializers(symbolsTable, valuesTable);
+ return new RClassGenerator(outFolder, packageName, initializers, finalFields);
}
/**
* Create an RClassGenerator given a collection of initializers.
*
* @param outFolder base folder to place the output R class files.
+ * @param packageName the java package to use for the R class
* @param initializers the list of initializers to use for each inner class
* @param finalFields true if the fields should be marked final
*/
public RClassGenerator(
Path outFolder,
+ String packageName,
Map<ResourceType, List<FieldInitializer>> initializers,
boolean finalFields) {
this.outFolder = outFolder;
+ this.packageName = packageName;
this.finalFields = finalFields;
this.initializers = initializers;
}
- /** Convert the {@link ResourceSymbols} data, to a map of {@link FieldInitializer}. */
+
+ private static Table<String, String, SymbolEntry> getAllSymbols(
+ Collection<ResourceSymbols> symbols) throws IOException {
+ Table<String, String, SymbolEntry> mergedSymbols = HashBasedTable.create();
+ for (ResourceSymbols tableProvider : symbols) {
+ mergedSymbols.putAll(tableProvider.asTable());
+ }
+ return mergedSymbols;
+ }
+
+ /** Convert the {@link SymbolTableProvider} data, to a map of {@link FieldInitializer}. */
private static Map<ResourceType, List<FieldInitializer>> getInitializers(
- Table<String, String, SymbolEntry> values) {
+ Table<String, String, SymbolEntry> symbols, Table<String, String, SymbolEntry> values) {
Map<ResourceType, List<FieldInitializer>> initializers = new EnumMap<>(ResourceType.class);
- for (String typeName : values.rowKeySet()) {
+ for (String typeName : symbols.rowKeySet()) {
ResourceType resourceType = ResourceType.getEnum(typeName);
Preconditions.checkNotNull(resourceType);
- initializers.put(resourceType, getInitializers(typeName, values));
+ initializers.put(resourceType, getInitializers(typeName, symbols, values));
}
return initializers;
}
private static List<FieldInitializer> getInitializers(
String typeName,
- Table<String, String, SymbolEntry> symbols) {
+ Table<String, String, SymbolEntry> symbols,
+ Table<String, String, SymbolEntry> values) {
Map<String, SymbolEntry> rowMap = symbols.row(typeName);
- List<String> symbolList = new ArrayList<>(rowMap.keySet());
+ Set<String> symbolSet = rowMap.keySet();
+ List<String> symbolList = new ArrayList<>(symbolSet);
Collections.sort(symbolList);
List<FieldInitializer> initializers = new ArrayList<>();
for (String symbolName : symbolList) {
- SymbolEntry value = symbols.get(typeName, symbolName);
- if (value.getType().equals("int")) {
- initializers.add(IntFieldInitializer.of(value.getName(), value.getValue()));
+ // get the matching SymbolEntry from the values Table.
+ SymbolEntry value = values.get(typeName, symbolName);
+ if (value != null) {
+ if (value.getType().equals("int")) {
+ initializers.add(IntFieldInitializer.of(value.getName(), value.getValue()));
+ } else {
+ Preconditions.checkArgument(value.getType().equals("int[]"));
+ initializers.add(IntArrayFieldInitializer.of(value.getName(), value.getValue()));
+ }
} else {
- Preconditions.checkArgument(value.getType().equals("int[]"));
- initializers.add(IntArrayFieldInitializer.of(value.getName(), value.getValue()));
+ // Value may be missing if resource overriding eliminates resources at the binary
+ // level, which were originally present at the library level.
+ logger.fine(
+ String.format(
+ "Skipping R.%s.%s -- value not known in binary's R.txt", typeName, symbolName));
}
}
return initializers;
}
- /**
- * Builds bytecode and writes out R.class file, and R$inner.class files for provided package and
- * symbols
- */
- public void write(String packageName, Map<ResourceType, Set<String>> symbolsToWrite)
- throws IOException {
+ /** Builds the bytecode and writes out the R.class file, and R$inner.class files. */
+ public void write() throws IOException {
Iterable<String> folders = PACKAGE_SPLITTER.split(packageName);
Path packageDir = outFolder;
for (String folder : folders) {
@@ -128,9 +158,7 @@ public class RClassGenerator {
// At least create the outFolder that was requested. However, if there are no symbols, don't
// create the R.class and inner class files (no need to have an empty class).
Files.createDirectories(packageDir);
- Map<ResourceType, List<FieldInitializer>> initializersToWrite =
- filterInitializers(symbolsToWrite);
- if (initializersToWrite.isEmpty()) {
+ if (initializers.isEmpty()) {
return;
}
Path rClassFile = packageDir.resolve(SdkConstants.FN_COMPILED_RESOURCE_CLASS);
@@ -149,7 +177,7 @@ public class RClassGenerator {
writeConstructor(classWriter);
// Build the R.class w/ the inner classes, then later build the individual R$inner.class.
- for (ResourceType resourceType : initializersToWrite.keySet()) {
+ for (ResourceType resourceType : initializers.keySet()) {
String innerClassName = rClassName + "$" + resourceType;
classWriter.visitInnerClass(
innerClassName,
@@ -161,41 +189,11 @@ public class RClassGenerator {
Files.write(rClassFile, classWriter.toByteArray());
// Now generate the R$inner.class files.
- for (Map.Entry<ResourceType, List<FieldInitializer>> entry : initializersToWrite.entrySet()) {
+ for (Map.Entry<ResourceType, List<FieldInitializer>> entry : initializers.entrySet()) {
writeInnerClass(entry.getValue(), packageDir, rClassName, entry.getKey().toString());
}
}
- /** Builds bytecode and writes out R.class file, and R$inner.class files for provided package. */
- public void write(String packageName) throws IOException {
- write(packageName, ImmutableMap.<ResourceType, Set<String>>of());
- }
-
- private Map<ResourceType, List<FieldInitializer>> filterInitializers(
- Map<ResourceType, Set<String>> symbolsToWrite) {
- Map<ResourceType, List<FieldInitializer>> initializersToWrite =
- new EnumMap<>(ResourceType.class);
- if (symbolsToWrite.isEmpty()) {
- return initializers;
- }
- for (Entry<ResourceType, Set<String>> entry : symbolsToWrite.entrySet()) {
- List<FieldInitializer> fieldsToWrite = new ArrayList<>();
- // Resource type may be missing if resource overriding eliminates resources at the binary
- // level, which were originally present at the library level.
- if (initializers.containsKey(entry.getKey())) {
- for (FieldInitializer field : initializers.get(entry.getKey())) {
- if (field.nameIsIn(entry.getValue())) {
- fieldsToWrite.add(field);
- }
- }
- }
- if (!fieldsToWrite.isEmpty()) {
- initializersToWrite.put(entry.getKey(), fieldsToWrite);
- }
- }
- return initializersToWrite;
- }
-
private void writeInnerClass(
List<FieldInitializer> initializers,
Path packageDir,
diff --git a/src/tools/android/java/com/google/devtools/build/android/resources/ResourceSymbols.java b/src/tools/android/java/com/google/devtools/build/android/resources/ResourceSymbols.java
index 051bd58de3..1860e228a3 100644
--- a/src/tools/android/java/com/google/devtools/build/android/resources/ResourceSymbols.java
+++ b/src/tools/android/java/com/google/devtools/build/android/resources/ResourceSymbols.java
@@ -18,7 +18,6 @@ import com.android.builder.dependency.SymbolFileProvider;
import com.android.builder.internal.SymbolLoader;
import com.android.builder.internal.SymbolLoader.SymbolEntry;
import com.android.builder.internal.SymbolWriter;
-import com.android.resources.ResourceType;
import com.android.utils.ILogger;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.HashMultimap;
@@ -32,13 +31,10 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.file.Path;
import java.util.Collection;
-import java.util.EnumMap;
import java.util.HashMap;
-import java.util.HashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
-import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import javax.annotation.Nullable;
@@ -189,19 +185,4 @@ public class ResourceSymbols {
}
writer.write();
}
-
- public Map<ResourceType, Set<String>> asFilterMap() throws IOException {
- Map<ResourceType, Set<String>> filter = new EnumMap<>(ResourceType.class);
- Table<String, String, SymbolEntry> symbolTable = asTable();
- for (String typeName : symbolTable.rowKeySet()) {
- Set<String> fields = new HashSet<>();
- for (SymbolEntry symbolEntry : symbolTable.row(typeName).values()) {
- fields.add(symbolEntry.getName());
- }
- if (!fields.isEmpty()) {
- filter.put(ResourceType.getEnum(typeName), fields);
- }
- }
- return filter;
- }
}