use of com.android.resources.ResourceType in project bazel by bazelbuild.
the class ResourceUsageAnalyzer method recordMapping.
private void recordMapping(@Nullable Path mapping) throws IOException {
if (mapping == null || !mapping.toFile().exists()) {
return;
}
final String arrowIndicator = " -> ";
final String resourceIndicator = ".R$";
Map<String, String> nameMap = null;
for (String line : Files.readLines(mapping.toFile(), UTF_8)) {
if (line.startsWith(" ") || line.startsWith("\t")) {
if (nameMap != null) {
// We're processing the members of a resource class: record names into the map
int n = line.length();
int i = 0;
for (; i < n; i++) {
if (!Character.isWhitespace(line.charAt(i))) {
break;
}
}
if (i < n && line.startsWith("int", i)) {
// int or int[]
int start = line.indexOf(' ', i + 3) + 1;
int arrow = line.indexOf(arrowIndicator);
if (start > 0 && arrow != -1) {
int end = line.indexOf(' ', start + 1);
if (end != -1) {
String oldName = line.substring(start, end);
String newName = line.substring(arrow + arrowIndicator.length()).trim();
if (!newName.equals(oldName)) {
nameMap.put(newName, oldName);
}
}
}
}
}
continue;
} else {
nameMap = null;
}
int index = line.indexOf(resourceIndicator);
if (index == -1) {
// resource name reflection
if (line.startsWith("android.support.v7.widget.SuggestionsAdapter ")) {
suggestionsAdapter = line.substring(line.indexOf(arrowIndicator) + arrowIndicator.length(), line.indexOf(':') != -1 ? line.indexOf(':') : line.length()).trim().replace('.', '/') + DOT_CLASS;
} else if (line.startsWith("android.support.v7.internal.widget.ResourcesWrapper ") || line.startsWith("android.support.v7.widget.ResourcesWrapper ") || (// Recently wrapper moved
resourcesWrapper == null && line.startsWith("android.support.v7.widget.TintContextWrapper$TintResources "))) {
resourcesWrapper = line.substring(line.indexOf(arrowIndicator) + arrowIndicator.length(), line.indexOf(':') != -1 ? line.indexOf(':') : line.length()).trim().replace('.', '/') + DOT_CLASS;
}
continue;
}
int arrow = line.indexOf(arrowIndicator, index + 3);
if (arrow == -1) {
continue;
}
String typeName = line.substring(index + resourceIndicator.length(), arrow);
ResourceType type = ResourceType.getEnum(typeName);
if (type == null) {
continue;
}
int end = line.indexOf(':', arrow + arrowIndicator.length());
if (end == -1) {
end = line.length();
}
String target = line.substring(arrow + arrowIndicator.length(), end).trim();
String ownerName = AsmUtils.toInternalName(target);
nameMap = Maps.newHashMap();
Pair<ResourceType, Map<String, String>> pair = Pair.of(type, nameMap);
resourceObfuscation.put(ownerName, pair);
// For fast lookup in isResourceClass
resourceObfuscation.put(ownerName + DOT_CLASS, pair);
}
}
use of com.android.resources.ResourceType in project bazel by bazelbuild.
the class ResourceUsageAnalyzer method stripUnused.
private void stripUnused(Element element, List<Resource> removed) {
ResourceType type = ResourceUsageModel.getResourceType(element);
if (type == ResourceType.ATTR) {
// Not yet properly handled
return;
}
Resource resource = model.getResource(element);
if (resource != null) {
if (resource.type == ResourceType.DECLARE_STYLEABLE || resource.type == ResourceType.ATTR) {
// tracking field references of the R_styleable_attr fields yet
return;
}
if (!resource.isReachable() && (resource.type == ResourceType.STYLE || resource.type == ResourceType.PLURALS || resource.type == ResourceType.ARRAY)) {
NodeList children = element.getChildNodes();
for (int i = children.getLength() - 1; i >= 0; i--) {
Node child = children.item(i);
element.removeChild(child);
}
}
}
NodeList children = element.getChildNodes();
for (int i = children.getLength() - 1; i >= 0; i--) {
Node child = children.item(i);
if (child.getNodeType() == Node.ELEMENT_NODE) {
stripUnused((Element) child, removed);
}
}
if (resource != null && !resource.isReachable() && resource.type != ResourceType.ID) {
removed.add(resource);
Node parent = element.getParentNode();
parent.removeChild(element);
}
}
use of com.android.resources.ResourceType in project bazel by bazelbuild.
the class DataResourceXml method parse.
/**
* Parses xml resources from a Path to the provided overwritable and combining collections.
*
* <p>This method is a bit tricky in the service of performance -- creating several collections
* and merging them was more expensive than writing to mutable collections directly.
*
* @param xmlInputFactory Used to create an XMLEventReader from the supplied resource path.
* @param path The path to the xml resource to be parsed.
* @param fqnFactory Used to create {@link FullyQualifiedName}s from the resource names.
* @param overwritingConsumer A consumer for overwritable {@link DataResourceXml}s.
* @param combiningConsumer A consumer for combining {@link DataResourceXml}s.
* @throws XMLStreamException Thrown with the resource format is invalid.
* @throws FactoryConfigurationError Thrown with the {@link XMLInputFactory} is misconfigured.
* @throws IOException Thrown when there is an error reading a file.
*/
public static void parse(XMLInputFactory xmlInputFactory, Path path, Factory fqnFactory, KeyValueConsumer<DataKey, DataResource> overwritingConsumer, KeyValueConsumer<DataKey, DataResource> combiningConsumer) throws XMLStreamException, FactoryConfigurationError, IOException {
XMLEventReader eventReader = xmlInputFactory.createXMLEventReader(new BufferedInputStream(Files.newInputStream(path)), StandardCharsets.UTF_8.toString());
try {
// TODO(corysmith): Make the xml parsing more readable.
for (StartElement resources = XmlResourceValues.moveToResources(eventReader); resources != null; resources = XmlResourceValues.moveToResources(eventReader)) {
// Record attributes on the <resources> tag.
Iterator<Attribute> attributes = XmlResourceValues.iterateAttributesFrom(resources);
while (attributes.hasNext()) {
Attribute attribute = attributes.next();
Namespaces namespaces = Namespaces.from(attribute.getName());
String attributeName = attribute.getName().getNamespaceURI().isEmpty() ? attribute.getName().getLocalPart() : attribute.getName().getPrefix() + ":" + attribute.getName().getLocalPart();
overwritingConsumer.consume(fqnFactory.create(VirtualType.RESOURCES_ATTRIBUTE, attributeName), DataResourceXml.createWithNamespaces(path, ResourcesAttribute.of(attributeName, attribute.getValue()), namespaces));
}
// Process resource declarations.
for (StartElement start = XmlResourceValues.findNextStart(eventReader); start != null; start = XmlResourceValues.findNextStart(eventReader)) {
Namespaces.Collector namespacesCollector = Namespaces.collector();
if (XmlResourceValues.isEatComment(start) || XmlResourceValues.isSkip(start)) {
continue;
}
ResourceType resourceType = getResourceType(start);
if (resourceType == null) {
throw new XMLStreamException(path + " contains an unrecognized resource type: " + start, start.getLocation());
}
if (resourceType == DECLARE_STYLEABLE) {
// Styleables are special, as they produce multiple overwrite and combining values,
// so we let the value handle the assignments.
XmlResourceValues.parseDeclareStyleable(fqnFactory, path, overwritingConsumer, combiningConsumer, eventReader, start);
} else {
// Of simple resources, only IDs and Public are combining.
KeyValueConsumer<DataKey, DataResource> consumer = (resourceType == ID || resourceType == PUBLIC) ? combiningConsumer : overwritingConsumer;
String elementName = XmlResourceValues.getElementName(start);
if (elementName == null) {
throw new XMLStreamException(String.format("resource name is required for %s", resourceType), start.getLocation());
}
FullyQualifiedName key = fqnFactory.create(resourceType, elementName);
XmlResourceValue xmlResourceValue = parseXmlElements(resourceType, eventReader, start, namespacesCollector);
consumer.consume(key, DataResourceXml.createWithNamespaces(path, xmlResourceValue, namespacesCollector.toNamespaces()));
}
}
}
} catch (XMLStreamException e) {
throw new XMLStreamException(path + ": " + e.getMessage(), e.getLocation(), e);
} catch (RuntimeException e) {
throw new RuntimeException("Error parsing " + path, e);
}
}
use of com.android.resources.ResourceType in project bazel by bazelbuild.
the class RClassGenerator method getInitializers.
/** Convert the {@link SymbolLoader} data, to a map of {@link FieldInitializer}. */
private static Map<ResourceType, List<FieldInitializer>> getInitializers(Table<String, String, SymbolEntry> symbols, Table<String, String, SymbolEntry> values) {
Map<ResourceType, List<FieldInitializer>> initializers = new EnumMap<>(ResourceType.class);
for (String typeName : symbols.rowKeySet()) {
ResourceType resourceType = ResourceType.getEnum(typeName);
Preconditions.checkNotNull(resourceType);
initializers.put(resourceType, getInitializers(typeName, symbols, values));
}
return initializers;
}
use of com.android.resources.ResourceType in project bazel by bazelbuild.
the class AndroidResourceClassWriter method fillInitializers.
private void fillInitializers(Map<ResourceType, List<FieldInitializer>> initializers) throws AttrLookupException {
Map<ResourceType, Integer> typeIdMap = chooseTypeIds();
Map<String, Integer> attrAssignments = assignAttrIds(typeIdMap.get(ResourceType.ATTR));
for (Map.Entry<ResourceType, Set<String>> fieldEntries : innerClasses.entrySet()) {
ResourceType type = fieldEntries.getKey();
ImmutableList<String> sortedFields = Ordering.natural().immutableSortedCopy(fieldEntries.getValue());
List<FieldInitializer> fields;
if (type == ResourceType.STYLEABLE) {
fields = getStyleableInitializers(attrAssignments, sortedFields);
} else if (type == ResourceType.ATTR) {
fields = getAttrInitializers(attrAssignments, sortedFields);
} else {
int typeId = typeIdMap.get(type);
fields = getResourceInitializers(type, typeId, sortedFields);
}
// The maximum number of Java fields is 2^16.
// See the JVM reference "4.11. Limitations of the Java Virtual Machine."
Preconditions.checkArgument(fields.size() < (1 << 16));
initializers.put(type, fields);
}
}
Aggregations