def CheckCSC100001(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error, cpplines, fileErrorCount): lines = clean_lines.elided errMessage = "Code Style Rule: Please don't rely on the default access level for class members(which is private)." for i in xrange(clean_lines.NumLines()): if common.IsBlankLine(lines[i]): continue if strcmp.Search(r'^\s*#', lines[i]): continue # template类型例子, # template <class T, ASN1::natural explicit_tag, # ASN1::tag_class_enum explicit_tag_class = ASN1::class_context_specific> if strcmp.Search(r'^\s*template\s*<', lines[i]): iRet = getTemplateEndLno(lines, i) if iRet != -1: i = iRet continue # eg. class A { # 查找到class类名后,检查类作用域内是否有public / protected / private关键字 # 排除namespace中的class声明 class NCWifiEvent; template <class T> if strcmp.Search(r'^\s*class\s+\w+', lines[i]) and not strcmp.Search(r'^\s*class\s+\w+\s*;', lines[i]) and not strcmp.Search(r'^\s*class\s+\w+\s*>', lines[i]) and lines[i].count('(') == 0: isClass, startBlockLineNo, endBlockLineNo =common.isClassDeclareCheck(lines, i) if isClass and startBlockLineNo < endBlockLineNo: bRet = checkmMemberFunctionAccessInClass(lines, startBlockLineNo , endBlockLineNo) if not bRet: Error(filename, lines, i, ruleCheckKey, 3, errMessage) continue
def checkmMemberFunctionAccessInClass(lines, startLineNo, endLineNo): accessFlg = False startLine = lines[startLineNo][lines[startLineNo].find('{') + len('{'):] i = 0 for i in range(startLineNo, endLineNo): line = lines[i] if i == startLineNo: line = startLine if common.IsBlankLine(line): continue if strcmp.Search(r'^\s*#', line): continue #找到成员的声明或者定义 if strcmp.Search(r'{|;|}', line): break # 空的class类,不判断public / protected / private关键字 if i == endLineNo - 1: return True startLine = lines[startLineNo][lines[startLineNo].find('class') + len('class'):] for i in range(startLineNo, endLineNo): line = lines[i] if i == startLineNo: line = startLine if common.IsBlankLine(line): continue if strcmp.Search(r'^\s*#', line): continue if strcmp.Search(r'^\s*template\s*<', line): iRet = getTemplateEndLno(lines, i) if iRet != -1: # skip template的声明 i = iRet continue if strcmp.Search(r'^\s*class\s+\w+', line) and not strcmp.Search(r'^\s*class\s+\w+\s*;', line) and not strcmp.Search(r'^\s*class\s+\w+\s*>', line) and line.count('(') == 0: isClass, startBlockLineNo, endBlockLineNo =common.isClassDeclareCheck(lines, i) if isClass: checkmMemberFunctionAccessInClass(lines, startBlockLineNo , endBlockLineNo) else: if (strcmp.Search(r'(\bpublic\b|\bprotected\b|\bprivate\b)\s*:', line)): accessFlg = True break #找到成员的声明或者定义 if strcmp.Search(r';|}', lines[i]) and not accessFlg: break return accessFlg
def CheckCSC030008(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error, cpplines, fileErrorCount): lines = clean_lines.elided isClassDeclare = False i = 1 while i < len(lines) : if common.IsBlankLine(lines[i]): i += 1 continue #宏定义--skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue if strcmp.Search(r'^\s*#', lines[i]): i += 1 continue # template类型例子, # template <class T, ASN1::natural explicit_tag, # ASN1::tag_class_enum explicit_tag_class = ASN1::class_context_specific> if strcmp.Search(r'^\s*template\s*<', lines[i]): iRet = getTemplateEndLno(lines, i) if iRet != -1: i = iRet + 1 continue # eg. class A { # 查找到class类名后,检查类作用域内是否有public / protected / private关键字 # 排除namespace中的class声明 class NCWifiEvent; template <class T> if strcmp.Search(r'^\s*class\s+\w+', lines[i]) and not strcmp.Search(r'^\s*class\s+\w+\s*;', lines[i]) and not strcmp.Search(r'^\s*class\s+\w+\s*>', lines[i]) and lines[i].count('(') == 0: #判断是否是类定义 isClassDeclare,startLineNo,endLineNo = common.isClassDeclareCheck(lines, i) #当class的类定义中,所有的代码都是在同一行时,没必要check if startLineNo == endLineNo: i = endLineNo + 1 continue #check 类定义 if isClassDeclare: checkClassBlock(filename, lines, startLineNo, endLineNo, ruleCheckKey, Error, cpplines, fileErrorCount) i = endLineNo + 1 continue i += 1
def CheckCSC020011(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error): """像struct,enum,union,class等含有成员的定义,需要遵循下面的规范: {单独占一行 }和;写在一起,并单独占一行 每个成员单独占一行 """ lines = clean_lines.elided i = 0 while i < clean_lines.NumLines(): if common.IsBlankLine(lines[i]): i += 1 continue if strcmp.Search(r"^\s*#\s*define\s+", lines[i]): i = getDefineMacroEndLineNo(lines, i) + 1 continue if strcmp.Search(r"^\s*#", lines[i]): i += 1 continue if strcmp.Search(r"^(\s*)\bstruct[\s*{;]", lines[i]) and lines[i].count("(") > 0: isBlock, startBlockLineNo, endBlockLineNo = isBlockDeclareCheck(lines, i, "struct") if isBlock and startBlockLineNo != endBlockLineNo: checkStructBlock(filename, lines, rawlines, startBlockLineNo, endBlockLineNo, ruleCheckKey, Error) i = endBlockLineNo elif strcmp.Search(r"^(\s*)\benum[\s*{;]", lines[i]): isBlock, startBlockLineNo, endBlockLineNo = isBlockDeclareCheck(lines, i, "enum") if isBlock and startBlockLineNo != endBlockLineNo: checkEnumBlock(filename, lines, rawlines, startBlockLineNo, endBlockLineNo, ruleCheckKey, Error) i = endBlockLineNo elif strcmp.Search(r"^(\s*)\bunion[\s*{;]", lines[i]): isBlock, startBlockLineNo, endBlockLineNo = isBlockDeclareCheck(lines, i, "union") if isBlock and startBlockLineNo != endBlockLineNo: checkUnionBlock(filename, lines, rawlines, startBlockLineNo, endBlockLineNo, ruleCheckKey, Error) i = endBlockLineNo elif strcmp.Search(r"^(\s*)\bclass[\s*:{;]", lines[i]): isClass, startBlockLineNo, endBlockLineNo = common.isClassDeclareCheck(lines, i) if isClass: checkClassBlock(filename, lines, rawlines, startBlockLineNo, endBlockLineNo, ruleCheckKey, Error) i = endBlockLineNo i += 1
def CheckCSC140003(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error): '''class声明必须有下面的注释说明。 概要说明 无 必须写在一行之内 详细说明 无 描述详细说明。 如有必要,可以列一些条目形式的内容,或一些SampleCode Args: filename:文件名 file_extension:文件的扩展名 clean_lines:文件的内容(不包含注释) rawlines:原始的文件内容 nesting_state:一个NestingState实例,维护有关嵌套块的当前堆栈信息进行解析。 ruleCheckKey:rule的id Error:error的句柄 ''' noteStartLineNo = 0 noteEndLineNo = 0 i = 0 while i < len(rawlines): if common.IsBlankLine(rawlines[i]): i += 1 continue if strcmp.Search(r'^\s*#\s*define\s+', rawlines[i]): i = getDefineMacroEndLineNo(rawlines, i) + 1 continue if strcmp.Search(r'^\s*#', rawlines[i]): i += 1 continue if rawlines[i].strip() == '/**': noteStartLineNo = i noteEndLineNo = 0 #结束 elif rawlines[i].strip() == '*/': if noteEndLineNo == 0: noteEndLineNo = i elif strcmp.Search(r'^(\s*)\bclass[\s*:{;]', rawlines[i]) : isClass, startBlockLineNo, endBlockLineNo = common.isClassDeclareCheck(rawlines, i) if isClass: checkClassDiscription(filename, file_extension, rawlines, rawlines, noteStartLineNo, noteEndLineNo, i, ruleCheckKey, Error) i += 1
def CheckCSC100005(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error, cpplines, fileErrorCount): lines = clean_lines.elided i = 0 isClassDeclare = False while i < clean_lines.NumLines(): #空白行--skip if common.IsBlankLine(lines[i]): i += 1 continue #宏定义--skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue #预定义--skip if strcmp.Search(r'^\s*#', lines[i]): i += 1 continue #template<...> -- skip if strcmp.Search(r'^\s*template\s*<', lines[i]): i = getTemplateEndLno(lines, i) if i == -1: break else: i += 1 continue #行是以"几个空格+class"或者"class"开头时,check class if strcmp.Search(r'^(\s*)\bclass\b', lines[i]): #判断该段代码是否以class为返回值的函数 if isFunctionDeclare('class', lines, i): i += 1 continue #判断是否是类定义 isClassDeclare,startLineNo,endLineNo = common.isClassDeclareCheck(lines, i) #当class的类定义中,所有的代码都是在同一行时,没必要check if startLineNo == endLineNo: i = endLineNo + 1 continue #check 类定义 if isClassDeclare: checkClassBlock(filename, lines, startLineNo, lines[startLineNo], endLineNo, ruleCheckKey, Error, cpplines, fileErrorCount) i = endLineNo i += 1
def CheckCSC030033(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error): '''类的构造函数的初始化列表中的空格遵循下面的规范: ':'和表达式之间必须有空格 ''' lines = clean_lines.elided i = 0 while i < clean_lines.NumLines(): if common.IsBlankLine(lines[i]): i += 1 continue if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): i = getDefineMacroEndLineNo(lines, i) + 1 continue if strcmp.Search(r'^\s*#', lines[i]): i += 1 continue if strcmp.Search(r'^(\s*)\bstruct[\s*{;]', lines[i]) and lines[i].count('(') > 0 : isBlock, startBlockLineNo, endBlockLineNo = isBlockDeclareCheck(lines, i, 'struct') if isBlock and startBlockLineNo != endBlockLineNo: checkBlock('struct', filename, lines, rawlines, i, endBlockLineNo, ruleCheckKey, Error) i = endBlockLineNo elif strcmp.Search(r'^(\s*)\bclass[\s*:{;]', lines[i]): isClass, startBlockLineNo, endBlockLineNo =common.isClassDeclareCheck(lines, i) if isClass: checkBlock('class', filename, lines, rawlines, i, endBlockLineNo, ruleCheckKey, Error) i = endBlockLineNo else: #函数的声明或者定义,不检查 m = strcmp.Search(r'\b(\w+)::(\w+)\s*\(', lines[i]) if m : flg, leftParenthesesLno, rightParenthesesLno, checkStartLineNo, endBlockLineNo = isFunctionDeclare(m.group(2), lines, i) if flg > 0 and m.group(1) == m.group(2): checkInitializerList(i, leftParenthesesLno, filename, lines, ruleCheckKey, Error) i = endBlockLineNo + 1 continue i += 1
def checkClassBlock(filename, lines, startLineNo, endLineNo, ruleCheckKey, Error, cpplines, fileErrorCount): errMessage = "Code Style Rule: There should be a blank line after every public/protected/private area." # public/protected/private区域表示 bDeclareFlg = False bBlankFlg = False i = startLineNo + 1 while i <= endLineNo: line = lines[i] if common.IsBlankLine(lines[i]): i += 1 #有区间标志,记录空行 if bDeclareFlg: bBlankFlg = True continue #宏定义--skip if strcmp.Search(r'^\s*#\s*define\s+', line): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue #预定义--skip if strcmp.Search(r'^\s*#', line): i += 1 continue # template类型例子, # template <class T, ASN1::natural explicit_tag, # ASN1::tag_class_enum explicit_tag_class = ASN1::class_context_specific> if strcmp.Search(r'^\s*template\s*<', lines[i]): iRet = getTemplateEndLno(lines, i) if iRet != -1: i = iRet + 1 continue m = strcmp.Search(r'^\s*(\bpublic\b|\bprivate\b|\bprotected\b)\s*:', line) if m: # 找到后修改标志 if not bDeclareFlg: bDeclareFlg = True else : if not bBlankFlg: Error(filename, lines, i, ruleCheckKey, 3, errMessage) # 有空行,变量修改为false,继续查找 else : bBlankFlg = False # 内嵌类 # eg. class A { # 查找到class类名后,检查类作用域内是否有public / protected / private关键字 # 排除namespace中的class声明 class NCWifiEvent; template <class T> if strcmp.Search(r'^\s*class\s+\w+', lines[i]) and not strcmp.Search(r'^\s*class\s+\w+\s*;', lines[i]) and not strcmp.Search(r'^\s*class\s+\w+\s*>', lines[i]) and lines[i].count('(') == 0: #判断是否是类定义 isClassDeclare,nestStartLineNo,nestEndLineNo = common.isClassDeclareCheck(lines, i) #当class的类定义中,所有的代码都是在同一行时,没必要check if nestStartLineNo == nestEndLineNo: i = nestEndLineNo + 1 continue # check 内部类 if isClassDeclare: checkClassBlock(filename, lines, nestStartLineNo, nestEndLineNo, ruleCheckKey, Error, cpplines, fileErrorCount) i = nestEndLineNo + 1 continue i += 1
def checkClassBlock(filename, lines, startLineNo, startLine, endLineNo, ruleCheckKey, Error, cpplines, fileErrorCount): #check 类定义 currentAccess = 'default' acessList = [] i = startLineNo errorMessage = 'Code Style Rule: In Class definitions, please put the access specifiers in the following order: first "public", second "protected", and finally "private".' skipEndLno = -1 line = '' openCurlyBraceQty = 0 closeCurlyBraceQty = 0 tempOpenCurlyBraceQty = 0 tempCloseCurlyBraceQty = 0 while i <= endLineNo: line = lines[i] #空白行--skip if common.IsBlankLine(line): i += 1 continue #宏定义--skip if strcmp.Search(r'^\s*#\s*define\s+', line): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue #预定义--skip if strcmp.Search(r'^\s*#', line): i += 1 continue #template<...> -- skip if strcmp.Search(r'^\s*template\s*<', lines[i]): i = getTemplateEndLno(lines, i) if i == -1: break else: i += 1 continue tempOpenCurlyBraceQty = openCurlyBraceQty tempCloseCurlyBraceQty = closeCurlyBraceQty openCurlyBraceQty = openCurlyBraceQty + line.count('{') closeCurlyBraceQty = closeCurlyBraceQty + line.count('}') if i == startLineNo: #startLineNo是class第一个左大括号所在的行 line = startLine[startLine.find('{') + 1:] m = strcmp.Search(r'^\s*(\bpublic\b|\bprivate\b|\bprotected\b)\s*:', line) if m: line = line[line.find(':') + 1:] currentAccess = m.group(1) # check是否满足public,protected,private这样的顺序 if currentAccess == 'public': if 'protected' in acessList or 'private' in acessList: Error(filename, lines, i, ruleCheckKey, 3, errorMessage) break elif currentAccess == 'protected': if 'private' in acessList: Error(filename, lines, i, ruleCheckKey, 3, errorMessage) break acessList.append(currentAccess) # check当前行是否是内部类 if strcmp.Search(r'^\s*\bclass\b', line.replace('{', '')): if isFunctionDeclare('class', lines, i): # class a function(); # 当前行是返回值为class的函数--skip i += 1 continue #判断是否是类定义 isClassDeclare,nestStartLineNo,nestEndLineNo = common.isClassDeclareCheck(lines, i) #当class的类定义中,所有的代码都是在同一行时,没必要check if nestStartLineNo == nestEndLineNo: i = nestEndLineNo + 1 continue # check 内部类 if isClassDeclare: if i == nestStartLineNo: nestStartLine = line[line.find('class'):] else: nestStartLine = lines[nestStartLineNo] checkClassBlock(filename, lines, nestStartLineNo, nestStartLine, nestEndLineNo, ruleCheckKey, Error, cpplines, fileErrorCount) i = nestEndLineNo + 1 continue i += 1
def checkBlock(blockKey, filename, lines, rawlines, startLineNo, EndLineNo, ruleCheckKey, Error): ''' 检查区域的代码 Args: blockKey:关键字 filename:文件名 lines:文件的内容 rawlines:原始的文件内容 startLineNo:开始的行数 EndLineNo:结束的行数 ruleCheckKey:rule的id Error:error的句柄 ''' keyName = '' #查找class/struct的名称 m = strcmp.Search(r'(struct|class)\s+(\w+)\b', lines[startLineNo]) if m: if m.group(2) != ' ' and m.group(2) != '{': keyName = m.group(2) # 匿名的struc不判断 if keyName == '': return startLine = lines[startLineNo][lines[startLineNo].find(blockKey) + len(blockKey):] i = startLineNo while i <= EndLineNo: line = lines[i] if i == startLineNo: line = startLine if common.IsBlankLine(line): i += 1 continue if strcmp.Search(r'^\s*#\s*define\s+', line): i = getDefineMacroEndLineNo(lines, i) + 1 continue if strcmp.Search(r'^\s*#', line): i += 1 continue if strcmp.Search(r'^(\s*)\bstruct[\s*{;]', line) and lines.count('(') > 0 : isBlock, startBlockLineNo, endBlockLineNo = isBlockDeclareCheck(lines, i, 'struct') if isBlock and startBlockLineNo != endBlockLineNo: checkBlock('struct', filename, lines, rawlines, i, endBlockLineNo, ruleCheckKey, Error) i = endBlockLineNo elif strcmp.Search(r'^(\s*)\bclass[\s*:{;]', line): isClass, startBlockLineNo, endBlockLineNo =common.isClassDeclareCheck(lines, i) if isClass: checkBlock('class', filename, lines, rawlines, i, endBlockLineNo, ruleCheckKey, Error) i = endBlockLineNo else: #构造函数的声明或者定义 pattern = r'\b(' + keyName + ')\s*\(' m = strcmp.Search(pattern, line) if m : flg, leftParenthesesLno, rightParenthesesLno, checkStartLineNo, endBlockLineNo = isFunctionDeclare(m.group(1), lines, i) if flg > 0 : checkInitializerList(i, leftParenthesesLno, filename, lines, ruleCheckKey, Error) i = endBlockLineNo + 1 continue i += 1
def CheckCSC030005(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error, cpplines, fileErrorCount): #列表clean_lines.elided的内容为['comment',codeLine1,codeLine2,...codeLineN,'comment'] #codeLineN在clean_lines.elided的index为clean_lines.NumLines()-1 lines = clean_lines.elided errorMessage = 'Code Style Rule: There should be a blank line after the definition of a struct/union/enum/class.' i = 0 endLineNo = clean_lines.NumLines() while i < clean_lines.NumLines(): #空白行--skip if common.IsBlankLine(lines[i]): i += 1 continue #宏定义--skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue #预定义--skip if strcmp.Search(r'^\s*#', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue #template<...> -- skip if strcmp.Search(r'^\s*template\s*<', lines[i]): i = getTemplateEndLno(lines, i) if i == -1: break else: i += 1 continue #check class if strcmp.Search(r'\bclass\b', lines[i]): #判断该段代码是否以class为返回值的函数 if isFunctionDeclare('class', lines, i): i += 1 continue #判断是否是类定义 isClassDeclare,startLineNo,endLineNo = common.isClassDeclareCheck(lines, i) if isClassDeclare: #如果class定义的最后一行同时是文件的最后一行(请参看lines = clean_lines.elided的注释)时,退出循环,不check了 if endLineNo >= clean_lines.NumLines() - 2: break # 下一行只有} or };,skip if not common.IsBlankLine(lines[endLineNo + 1]) and lines[endLineNo + 1].strip().replace(' ','') in ['}', '};']: i = startLineNo + 1 continue #如果class定义的最后一行的下一行不是空白行 ,报错 if not common.IsBlankLine(rawlines[endLineNo + 1]): Error(filename, lines, endLineNo, ruleCheckKey, 3, errorMessage) i = startLineNo + 1 continue #check struct,union,enum m = strcmp.Search(r'(\bstruct\b|\bunion\b|\benum\b)', lines[i]) if m: #判断该段代码是否以struct/union/enum为返回值的函数 if isFunctionDeclare(m.group(1), lines, i): i += 1 continue #判断是否是结构体/联合/枚举定义 isStructUnionEnumDeclare,endLineNo,canFindEndLine = checkStructEnumUnionDeclare(m.group(1), lines, i) if isStructUnionEnumDeclare: #如果代码不规范而导致无法找到结构体/联合/枚举定义的最后一行,退出循环 if not canFindEndLine: break #如果结构体/联合/枚举定义的最后一行同时是文件的最后一行(请参看lines = clean_lines.elided的注释)时,退出循环,不check了 if endLineNo >= clean_lines.NumLines() - 2: break # 下一行只有} or };,skip if not common.IsBlankLine(lines[endLineNo + 1]) and lines[endLineNo + 1].strip().replace(' ','') in ['}', '};']: i = endLineNo + 1 continue #如果结构体/联合/枚举定义的最后一行的下一行不是空白行 且 下一行不是只有},报错 if not common.IsBlankLine(rawlines[endLineNo + 1]) and rawlines[endLineNo + 1].strip().replace(' ','') not in ['}', '};']: Error(filename, lines, endLineNo, ruleCheckKey, 3, errorMessage) i = endLineNo + 1 continue i += 1