blob: a15c97b1ce8c74102832b488e4e0fe51565d2379 [file] [log] [blame]
#!/usr/bin/python
# Copyright 2019, The Android Open Source Project
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use, copy,
# modify, merge, publish, distribute, sublicense, and/or sell copies
# of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
import os
class ResourceLocation:
def __init__(self, file, line=None):
self.file = file
self.line = line
def __str__(self):
if self.line is not None:
return self.file + ':' + str(self.line)
else:
return self.file
class Resource:
def __init__(self, name, type, location=None):
self.name = name
self.type = type
self.locations = []
if location is not None:
self.locations.append(location)
def __eq__(self, other):
if isinstance(other, _Grab):
return other == self
return self.name == other.name and self.type == other.type
def __ne__(self, other):
if isinstance(other, _Grab):
return other != self
return self.name != other.name or self.type != other.type
def __hash__(self):
return hash((self.name, self.type))
def __str__(self):
result = ''
for location in self.locations:
result += str(location) + ': '
result += '<'+self.type+' name="'+self.name+'"'
return result + '>'
def __repr__(self):
return str(self)
def get_all_resources(resDir):
allResDirs = [f for f in os.listdir(resDir) if os.path.isdir(os.path.join(resDir, f))]
valuesDirs = [f for f in allResDirs if f.startswith('values')]
fileDirs = [f for f in allResDirs if not f.startswith('values')]
resources = set()
# Get the filenames of the all the files in all the fileDirs
for dir in fileDirs:
type = dir.split('-')[0]
for file in os.listdir(os.path.join(resDir, dir)):
if file.endswith('.xml'):
add_resource_to_set(resources,
Resource(file[:-4], type,
ResourceLocation(os.path.join(resDir, dir, file))))
for dir in valuesDirs:
for file in os.listdir(os.path.join(resDir, dir)):
if file.endswith('.xml'):
for resource in get_resources_from_single_file(os.path.join(resDir, dir, file)):
add_resource_to_set(resources, resource)
return resources
def get_resources_from_single_file(filename):
# defer importing lxml to here so that people who aren't editing chassis don't have to have
# lxml installed
import lxml.etree as etree
doc = etree.parse(filename)
resourceTag = doc.getroot()
result = set()
for resource in resourceTag:
if resource.tag == 'declare-styleable' or resource.tag is etree.Comment:
continue
if resource.tag == 'item' or resource.tag == 'public':
add_resource_to_set(result, Resource(resource.get('name'), resource.get('type'),
ResourceLocation(filename, resource.sourceline)))
else:
add_resource_to_set(result, Resource(resource.get('name'), resource.tag,
ResourceLocation(filename, resource.sourceline)))
return result
def remove_layout_resources(resourceSet):
result = set()
for resource in resourceSet:
if resource.type != 'layout':
result.add(resource)
return result
# Used to get objects out of sets
class _Grab:
def __init__(self, value):
self.search_value = value
def __hash__(self):
return hash(self.search_value)
def __eq__(self, other):
if self.search_value == other:
self.actual_value = other
return True
return False
def add_resource_to_set(resourceset, resource):
grabber = _Grab(resource)
if grabber in resourceset:
grabber.actual_value.locations.extend(resource.locations)
else:
resourceset.update([resource])
def merge_resources(set1, set2):
for resource in set2:
add_resource_to_set(set1, resource)