Created
May 9, 2011 15:02
-
-
Save casidiablo/962681 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
Feel free to modify and/or enhance this tool. Also feel free to fix bugs you found. | |
I would be happy if you could share your modified version on the blog, where this tool | |
was posted. | |
Blog-URL: http://www.droidnova.com/android-resource-tracker,723.html | |
Project Page: http://code.google.com/p/androidresourcetracker | |
This tool is from a developer for developers, so be like a good colleague and share your | |
improvements to this tool with the others. | |
EXPLIZIT: No license... I trust your good will... if you get rich, share with me :) | |
Created on 24.09.2010 | |
@version: 1.0.1 | |
@author: Martin Breuer (aka WarrenFaith) | |
''' | |
import sys | |
import os | |
import re | |
import glob | |
helpInformation = '''This is a tool that help you to find out, if a resource is used. | |
Parameter: | |
-h : shows this help | |
-i : root directory of your android project | |
-v : show all matches | |
--unused-only : shows only unused elements - does not work with --used-only | |
--used-only : shows on used elements - does not work with --unused-only | |
--types string:id:drawable : show only the specified types''' | |
rootProjectDir = None | |
elementPath = "" | |
verbose = False | |
usedOnly = False | |
unusedOnly = False | |
resourceArray = {} | |
sourceArray = {} | |
xmlFiles = [] | |
resultArray = {} | |
inXml = 'inXml' | |
inSrc = 'inSrc' | |
unsure = 'unsure' | |
fetchOnly = [] | |
## recursive walk through all directories ## | |
def findR(path): | |
for dirs in os.listdir(path): | |
if os.path.isdir(os.path.join(path, dirs)): | |
if dirs == '.svn': | |
break | |
return findR(os.path.join(path, dirs)) | |
return path | |
def findXmlFiles(path): | |
for dirs in os.listdir(path): | |
if os.path.isdir(os.path.join(path, dirs)): | |
if dirs != '.svn': | |
findXmlFiles(os.path.join(path, dirs)) | |
else: | |
if dirs.endswith(".xml"): | |
newPath = os.path.basename(path) | |
xmlFiles.append(os.path.join(newPath, dirs)) | |
return None | |
def collectSources(path): | |
for dirs in os.listdir(path): | |
if os.path.isdir(os.path.join(path, dirs)): | |
if dirs == '.svn': | |
break | |
if not dirs.endswith('.java'): | |
sourceArray[os.path.join(path, dirs)] = [] | |
collectSources(os.path.join(path, dirs)) | |
return None | |
def parseR(pathToR): | |
patternResource = re.compile("\W(.+)\W(.+)=0x") | |
patternClass = re.compile("class\W(.+)\W{") | |
file = open(pathToR, "r") | |
currentClass = "ERROR"; | |
for line in file: | |
resourceHit = patternResource.search(line) | |
classHit = patternClass.search(line) | |
if classHit != None and classHit.group(1) != "R": | |
currentClass = classHit.group(1) | |
resourceArray[currentClass] = [] | |
if resourceHit != None: | |
resourceArray[currentClass] += [resourceHit.group(2)] | |
return None | |
def findPossibleMatchInSrc(type, item, searchString): | |
pattern = re.compile(searchString + item) | |
for dir in sourceArray: | |
for files in os.listdir(dir): | |
if files != ".svn" and files.endswith(".java"): | |
file = open(os.path.join(dir, files), "r") | |
lineNumber = 1 | |
for line in file: | |
if pattern.search(line) != None: | |
if verbose: | |
print(files + " - Line: " + str(lineNumber) + " :: " + line.strip()) | |
resultArray[type][item][unsure] = True | |
lineNumber += 1 | |
return None | |
def findOccurenceInSrc(type, item, searchString): | |
pattern = re.compile(searchString + item) | |
for dir in sourceArray: | |
for files in os.listdir(dir): | |
if files != ".svn" and files.endswith(".java"): | |
file = open(os.path.join(dir, files), "r") | |
lineNumber = 1 | |
for line in file: | |
if pattern.search(line) != None: | |
if verbose: | |
print(files + " - Line: " + str(lineNumber) + " :: " + line.strip()) | |
resultArray[type][item][inSrc] = True | |
lineNumber += 1 | |
return None | |
def findOccurenceInXml(type, item, plainTag, searchString): | |
if searchString == "@style/": | |
pattern = re.compile(searchString+"("+item+"|"+item.replace("_",".")+")") | |
else: | |
pattern = re.compile(searchString + item) | |
for files in xmlFiles: | |
file = open(os.path.join(elementPath, files), "r") | |
lineNumber = 1 | |
for line in file: | |
if pattern.search(line) != None: | |
if verbose: | |
print(files + " - Line: " + str(lineNumber) + " :: " + line.strip()) | |
resultArray[type][item][inXml] = True | |
lineNumber += 1 | |
return None | |
### Main programm ### | |
if len(sys.argv) == 1: | |
print(helpInformation) | |
sys.exit() | |
for index,arg in enumerate(sys.argv): | |
if arg == "-h": | |
print(helpInformation) | |
sys.exit() | |
if arg == "-i": | |
if len(sys.argv) <= index + 1: | |
print('''Given path is missing...''') | |
sys.exit() | |
rootProjectDir = sys.argv[index + 1] | |
elementPath = os.path.join(rootProjectDir, "res") | |
if arg == "-v": | |
verbose = True | |
if arg == "--used-only": | |
usedOnly = True | |
if arg == "--unused-only": | |
unusedOnly = True; | |
if arg == "--types": | |
if len(sys.argv) <= index + 1: | |
print("Given element typ or types missing...") | |
sys.exit() | |
fetchOnly = sys.argv[index + 1].split(":") | |
if unusedOnly and usedOnly: | |
print('''--used-only and --unused-only can't be used together. | |
Remove one parameter...''') | |
sys.exit() | |
print("Processing, fetching, working...") | |
# collect all src files | |
collectSources(os.path.join(rootProjectDir, "src")) | |
# find all xml files | |
findXmlFiles(os.path.join(rootProjectDir, "res")) | |
#add manifest | |
xmlFiles.append(os.path.join(rootProjectDir, "AndroidManifest.xml")) | |
# read the R class | |
os.chdir(rootProjectDir) | |
for srcDirs in glob.glob('gen'): | |
rclass = os.path.join(findR(os.path.join(rootProjectDir, srcDirs)), "R.java") | |
parseR(rclass) | |
for entry in resourceArray: | |
resultArray[entry] = {} | |
for item in resourceArray[entry]: | |
resultArray[entry][item] = {} | |
resultArray[entry][item][inSrc] = False | |
resultArray[entry][item][inXml] = False | |
resultArray[entry][item][unsure] = False | |
findOccurenceInSrc(entry, item, entry + ".") | |
findOccurenceInXml(entry, item, entry + "." + item, "@" + entry + "/") | |
findPossibleMatchInSrc(entry, item, 'getIdentifier\(\s*?\"') | |
for type in resultArray: | |
if type in fetchOnly or len(fetchOnly) is 0: | |
for element,matches in resultArray[type].items(): | |
if matches[inSrc] is False and matches[inXml] is False and matches[unsure] is False: | |
if usedOnly == False: | |
print("Unused: " + type + "." + element) | |
elif matches[inSrc] is True and matches[inXml] is True and matches[unsure] is True: | |
if unusedOnly == False: | |
print("Used in src and xml: " + type + "." + element) | |
elif matches[inSrc] is True or matches[unsure] is True and matches[inXml] is False: | |
if unusedOnly == False: | |
print("Used in src: " + type + "." + element) | |
elif matches[inSrc] is False and matches[unsure] is False and matches[inXml] is True: | |
if unusedOnly == False: | |
print("Used in xml: " + type + "." + element) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment