Last active
August 29, 2015 14:05
-
-
Save JohnWong/d75adad722dce2bdf34b to your computer and use it in GitHub Desktop.
Objective-C Block Checker
This file contains hidden or 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
#coding=utf-8 | |
import argparse | |
import re | |
import sys | |
import os | |
reload(sys) | |
sys.setdefaultencoding('utf8') | |
class BlockChecker: | |
selfregex = re.compile('.*[([ \t]self[ .]') | |
def readfile(self, filepath): | |
with open(filepath, "r") as fp: | |
content = fp.read() | |
return content | |
def filtercomment(self, content): | |
coderesult = '' | |
status = 0 | |
for ch in content: | |
if status == 0: | |
if ch == '/': | |
status = 1 | |
else: | |
coderesult += ch | |
elif status == 1: | |
if ch == '*': | |
status = 2 | |
elif ch == '/': | |
status = 5 | |
else: | |
coderesult += '/' + ch | |
status = 0 | |
elif status == 2: | |
if ch == '*': | |
status = 4 | |
else: | |
status = 3 | |
if ch == '\n': | |
coderesult += '\n' | |
elif status == 3: | |
if ch == '*': | |
status = 4 | |
elif ch == '\n': | |
coderesult += '\n' | |
elif status == 4: | |
if ch == '/': | |
status = 0 | |
elif ch != '*': | |
status = 3; | |
if ch == '\n': | |
coderesult += '\n' | |
elif status == 5: | |
if ch == '\n': | |
status = 0 | |
coderesult += ch | |
return coderesult | |
pass | |
pass | |
def filterblock(self, content): | |
status = 0 | |
blocks = [] | |
code = '' | |
linenum = 1 | |
for ch in content: | |
if ch == '\n': | |
linenum += 1 | |
if status == 0: | |
if ch == '@': | |
status = 1 | |
elif ch == '(': | |
status = 3 | |
elif ch == '^': | |
blockstart = linenum | |
status = 4 | |
elif status == 1: | |
if ch == '"': | |
status = 2 | |
else: | |
status = 0 | |
elif status == 2: | |
if ch == '"': | |
status = 0 | |
elif status == 3: | |
if ch == ')': | |
status = 0 | |
elif status == 4: | |
if ch == '{': | |
status = 5 | |
elif status == 5: | |
if ch == '}': | |
blockend = linenum | |
blocks.append([code, blockstart, blockend]) | |
status = 0 | |
else: | |
code += ch | |
return blocks | |
def iscontainself(self, blockcode): | |
iterator = self.selfregex.search(blockcode) | |
return iterator != None | |
def checkfile(self, filepath): | |
content = self.readfile(filepath) | |
code = self.filtercomment(content) | |
blocks = self.filterblock(code) | |
result = [] | |
for block in blocks: | |
if self.iscontainself(block[0]): | |
result.append(block[1:]) | |
return result | |
def printitemtoxcode(self, filePath, lineNum): | |
print("%s:%d: %s: %s" % (filePath, lineNum, "warning", "self in block may cause memory leak.")) | |
def printtoxcode(self, result): | |
for (key, value) in result.items(): | |
for block in value: | |
self.printitemtoxcode(key, block[0]) | |
pass | |
def getsourcefiles(self, rootpath, suffix): | |
file_list = [] | |
if rootpath is None: | |
raise Exception('rootpath is None') | |
for dirpath, dirnames, filenames in os.walk(rootpath): | |
for name in filenames: | |
if name.endswith(suffix + '.m'): | |
filepath = dirpath + os.sep + name | |
file_list.append(filepath) | |
return file_list | |
def printresult(self, result): | |
print('Find ' + str(len(result)) + 'instances') | |
multiprint('=') | |
for (key, value) in result.items(): | |
print(key) | |
lines = '' | |
for block in value: | |
lines += str(block[0]) + '-' + str(block[1]) + ' ' | |
print(lines) | |
multiprint('-') | |
def check(self, rootpath, suffix): | |
filelist = self.getsourcefiles(rootpath, suffix) | |
result = {} | |
for filepath in filelist: | |
fileresult = self.checkfile(filepath) | |
if len(fileresult) > 0: | |
result[filepath] = fileresult | |
self.printtoxcode(result) | |
return result | |
if __name__ == '__main__': | |
parser = argparse.ArgumentParser(description='Check ViewController Xcode project to find self in block code ') | |
parser.add_argument('path', help='Objective-c source root.') | |
parser.add_argument('-suffix', help='Objective-c class file suffix. Default is "Controller".', default='Controller') | |
args = parser.parse_args() | |
rootpath = args.path | |
suffix = args.suffix | |
blockChecker = BlockChecker() | |
result = blockChecker.check(rootpath, suffix) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Check whether self appeared in blocks of a UIViewController. This may cause memory leak.