def whetherHasSourceBetweenTwoLine(lines, startLineNo, startIndex, endLineNo, endIndex): '''检查指定的两个位置之间是否有代码{对应的}的行号和其所在行的位置 Args: lines:所有行 startLineNo:开始的行号 startIndex:开始行中开始查找的位置 endLineNo:结束的行号 endIndex:结束行中开始查找的位置 Returns: True:指定的两个位置之间有代码;False:指定的两个位置之间没有代码 ''' # 开始行,startIndex之后有代码 if not common.IsBlankLine(lines[startLineNo][startIndex + 1:]): return True # 结束行,endIndex之前有代码 if not common.IsBlankLine(lines[endLineNo][:endIndex]): return True i = startLineNo + 1 while i < endLineNo: #null line skip if common.IsBlankLine(lines[i]): i += 1 continue #define line skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue # line start with # skip if strcmp.Search(r'^\s*#', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue # 有代码行 return True return False
def checkNewLine(filename, indentation, lines, startLineNo, endLineNo, ruleCheckKey, Error): errMessageHeader = 'Code Style Rule: If an expression is too long,' errorMessageIndentation = ' it should be wrapped, and the new line should indent 4 spaces.' errorMessageStartWord = ' it should be wrapped before a Logical AND (&&) or a Logical OR (||).' errorMessageBoth = ' it should be wrapped before a Logical AND (&&) or a Logical OR (||), and the new line should indent 4 spaces.' checkStartLineNo = startLineNo + 1 maxLimit = endLineNo+ 1 skipEndLno = -1 previousLine = lines[startLineNo].strip() for i in xrange(checkStartLineNo, maxLimit): errorMessage = '' hasIndentationError = False hasStartWordError = False #if ( a > 1 # ) --如果最后一个右括号所在的行,右括号前没有代码,则不check if i == endLineNo and lines[i].strip().startswith(')') and lines[i].count(')') == 1: continue #空白行--skip if common.IsBlankLine(lines[i]): continue if i <= skipEndLno: continue #宏定义--skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): skipEndLno = common.getDefineMacroEndLineNo(lines, i) continue #预定义--skip if strcmp.Search(r'^\s*#', lines[i]): skipEndLno = common.getDefineMacroEndLineNo(lines, i) continue #新行相对缩进4个空格check tempIndentation = 0 m = strcmp.Search(r'^(\s*)\S', lines[i]) if m: tempIndentation = len(m.group(1).replace('\t', ' ')) # 缩进错误,编辑errormessage if indentation + 4 != tempIndentation: hasIndentationError = True #换行以二元操作符为起点check # 不是以二元操作符为起点,编辑errormessage if not checkIfStartWithDyadicOperator(lines[i], previousLine): hasStartWordError = True #如果有错误信息,报错 if hasIndentationError and hasStartWordError: errorMessage = errMessageHeader + errorMessageBoth elif hasIndentationError: errorMessage = errMessageHeader + errorMessageIndentation elif hasStartWordError: errorMessage = errMessageHeader + errorMessageStartWord if errorMessage: Error(filename, lines, i, ruleCheckKey, 3, errorMessage) #保存当前行,目的是下一行是以&开头时,判断&是一元操作符,还是二元操作符 previousLine = lines[i].strip()
def CheckCSC020006(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error): '''如果出现较长的表达式,也要进行换行。换行以二元逻辑操作符为起点,新行相对缩进4个空格。 Args: filename:文件名 file_extension:文件扩展名 clean_lines:Holds 3 copies of all lines with different preprocessing applied to them 1) elided member contains lines without strings and comments, 2) lines member contains lines without comments, and 3) raw_lines member contains all the lines without processing.(行首以/*开头的多行注释被替换成空白) rawlines:all the lines without processing nesting_state: Holds states related to parsing braces.(cpplint中的对象,暂时未使用) startLineNo:for,while,if,switch所在的行 ruleCheckKey:ruleid Error: error output method ''' lines = clean_lines.elided i = 0 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 m = strcmp.Search(r'(\bif\b|\bwhile\b)', lines[i]) if m: indentation, startLineNo,endLineNo = getStatementStartEnd(lines, i, m.group(1)) if endLineNo == -1 or endLineNo == clean_lines.NumLines() - 1: break if startLineNo == endLineNo: i = endLineNo + 1 continue checkNewLine(filename,indentation, lines, startLineNo, endLineNo, ruleCheckKey, Error) i = endLineNo i += 1
def CheckCSC110006(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error, cpplines, fileErrorCount): lines = clean_lines.elided errMessage = "Code Style Rule: Usage of functions strcpy, sprintf, strcat is forbidden. Please use strncpy, snprintf, strncat instead." 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 += 1 continue if (strcmp.Search(r'(\b^\.*strcpy\b\s*\()|(\b^\.*sprintf\b\s*\()|(\b^\.*strcat\b\s*\()', lines[i])): Error(filename, lines, i, ruleCheckKey, 3, errMessage) i += 1 continue i += 1
def getFunctionCloseCurlyBraceInfo(lines, openCurlyBraceLno, openCurlyBraceIdx): '''返回{对应的}的行号和其所在行的位置 Args: lines:所有行 openParenthesisLno:{所在行的行号 openParenthesisIdx:{在其所在行的位置 Returns: 返回{对应的}所在的line number和其所在行的位置;如果查不到},则返回-1, -1 ''' lengthOfLines =len(lines) i = openCurlyBraceLno openCurlyBraceQty = 0 closeCurlyBraceQty = 0 while i < lengthOfLines: #null line skip if common.IsBlankLine(lines[i]): i += 1 continue #define line skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue # line start with # skip if strcmp.Search(r'^\s*#', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue if i == openCurlyBraceLno: checkStartIndex = openCurlyBraceIdx else: checkStartIndex = 0 # #逐个字符累计左右大括号 for j in xrange(checkStartIndex, len(lines[i])): if lines[i][j] == '{': openCurlyBraceQty += 1 elif lines[i][j] == '}': closeCurlyBraceQty += 1 else: continue # 左右大括号的个数相同时,返回右大括号的行号和位置 if openCurlyBraceQty == closeCurlyBraceQty and openCurlyBraceQty > 0: return i, j i += 1 # 如果查不到*/,则返回-1,说明文件有问题,不要再check该文件了 return -1, -1
def getEndInfoOfCondition(lines, startLineNo, keyWordIndex): '''函数功能:查找for,while,if,switch后面的()中)所在的行,及其在所在行的位置 Args: lines:文件中各个行的内容组成的数组(已去完注释,字符串已被清空) startLineNo:for,while,if,switch所在的行 keyWordIndex:for,while,if,switch在行中的index Returns: 右圆括号的lineNo,其位于所在行的位置,如果找不到,则返回-1,-1 ''' linesLength = len(lines) i = startLineNo openParenthesisQty = 0 closeParenthesisQty = 0 while i < linesLength: #空白行--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 checkStartIndex = 0 if i == startLineNo: checkStartIndex = keyWordIndex #逐个字符累计左右圆括号 for j in xrange(checkStartIndex, len(lines[i])): if lines[i][j] == '(': openParenthesisQty += 1 elif lines[i][j] == ')': closeParenthesisQty += 1 #左右圆括号个数相同,则返回最后一个右圆括号的lineNo,其位于所在行的位置 if openParenthesisQty == closeParenthesisQty and openParenthesisQty > 0: return i, j i += 1 return -1, -1
def checkNewLine(filename, lines, startLineNo, endLineNo, ruleCheckKey, Error): errMessage = 'Code Style Rule: When a function declaration/definition is too long, it should be wrapped before the type of a parameter. For example, funcA(int a, int b) should wrap before "int b".' checkStartLineNo = startLineNo + 1 maxLimit = endLineNo + 1 skipEndLno = -1 previousLine = lines[startLineNo].strip() for i in xrange(checkStartLineNo, maxLimit): errorMessage = '' #空白行--skip if common.IsBlankLine(lines[i]): continue if i <= skipEndLno: continue #宏定义--skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): skipEndLno = common.getDefineMacroEndLineNo(lines, i) continue #预定义--skip if strcmp.Search(r'^\s*#', lines[i]): skipEndLno = common.getDefineMacroEndLineNo(lines, i) continue line = lines[i].strip() # int func(int a \n\t )不报错; if line.startswith(')'): previousLine = lines[i].strip() continue # int func(\n \tint a)不报错; if previousLine.endswith('('): previousLine = lines[i].strip() continue # int func(int \n\t&a)报错;int func(int \n\t*a)报错; if line.startswith('&') or line.startswith('*'): Error(filename, lines, i, ruleCheckKey, 3, errMessage) #int func(int \n\ta,int b )报错 elif not previousLine.endswith(','): Error(filename, lines, i, ruleCheckKey, 3, errMessage) #保存当前行,目的是下一行是以&开头时,判断&是一元操作符,还是二元操作符 previousLine = lines[i].strip()
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 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 CheckCSC080005(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error): lines = clean_lines.elided errMessage = "Code Style Rule: Please put the opening curly brace of a for loop on the same line with the for keyword." i = 0 while i < clean_lines.NumLines(): #define line skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue if strcmp.Search(r'^\s*for\s*\(', lines[i]): lineNo = getParenthesisEndLineNo(lines, i) if lineNo != -1: i = lineNo if not lines[i].strip().endswith('{'): Error(filename, lines, i, ruleCheckKey, 3, errMessage) i = i + 1 continue i += 1
def getNextNotNullLineNo(lines, startLno): '''从startLno向下查找第一个非空的行 Args: lines:a copy of all lines without strings and comments startLno:目标行 Returns: 第一个非空的行的行号 ''' lengthOfLines = len(lines) i = startLno + 1 while i < lengthOfLines: if common.IsBlankLine(lines[i]): i += 1 continue elif strcmp.Search(r'^\s*#', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue else: break if i < lengthOfLines: return i else: return lengthOfLines - 1
def CheckCSC030027(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error): '''左大括号{之后如果有内容,请保留一个空格。[必须] Args: filename:文件名 file_extension:文件扩展名 clean_lines:Holds 3 copies of all lines with different preprocessing applied to them 1) elided member contains lines without strings and comments, 2) lines member contains lines without comments, and 3) raw_lines member contains all the lines without processing.(行首以/*开头的多行注释被替换成空白) rawlines:all the lines without processing nesting_state: Holds states related to parsing braces.(cpplint中的对象,暂时未使用) startLineNo:for,while,if,switch所在的行 ruleCheckKey:ruleid Error: error output method ''' lines = clean_lines.elided errMessage = 'Code Style Rule: If there is contents after a left curly brace "{", please leave a space between them.' i = 0 while i < clean_lines.NumLines(): # null line skip if common.IsBlankLine(lines[i]): i += 1 continue #define line skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue # line start with # skip if strcmp.Search(r'^\s*#', lines[i]): i += 1 continue m = strcmp.Search(r'\{[^\s\}\\]', lines[i]) # 当 { 后面的字符不是空格,也不是},也不是换行符时,报错 if m: Error(filename, lines, i, ruleCheckKey, 3, errMessage) i += 1
def CheckCSC030017(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error, cpplines, fileErrorCount): # 赋值判断 #因为 * & 即是指针也是运算符,无法判断,所有不判断这两个 arraySign1 = ["+","-","*","/","%","&", "|", "~", "^"] # 运算符 # eg. if (a && b), if (a || b) arraySign2 = ["&&", "||"] # 必须在等号后判断的,否则容易产生误判 # error 数据有赋值为负数的情况,'-'删除 arraySign3 = ["+","/","%", "|", "<<", ">>"] lines = clean_lines.elided errMessage = "Code Style Rule: There should a space both before and after a binary operator \"%s\". For example: A = B." i = 0 FoldinglineFlag = False line = '' while i < clean_lines.NumLines(): findFlg = True index = 0 signTag = '' if lines[i].endswith("\\"): # 换行的第一行,清空缓存的line if not FoldinglineFlag: line = '' FoldinglineFlag = True line = line + lines[i][0:len(lines[i])] i += 1 continue else : # 换行的最后一行 if FoldinglineFlag: line = line + lines[i] line = _RE_PATTERN_CLEANSE_LINE_ESCAPES.sub('', line) line = _RE_PATTERN_CLEANSE_LINE_SINGLE_QUOTES.sub("''", line) line = _RE_PATTERN_CLEANSE_LINE_DOUBLE_QUOTES.sub('""', line) else : line = lines[i] FoldinglineFlag = False line = lines[i].replace("->", ".") if common.IsBlankLine(line): i += 1 continue #define line skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue if strcmp.Search(r'^\s*#', line): i += 1 continue # 查找"operator",忽略操作符重载的函数名的判断 if strcmp.Search(r'\boperator\b', line): i += 1 continue # 查找"===",忽略 if strcmp.Search(r'===', line): i += 1 continue #只判断结束语句 endPos = line.rfind(";") if endPos == -1: endPos = len(line) # 查找"=" index2 = line.rfind("=", 0, endPos) if -1 != index2 and -1 == line.find('virtual ', 0, index2): # 忽略字符串中的 = 的判断 # static std::string myTestData = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \ #strFlgIndex = line.find("\"", 0, endPos) #if strFlgIndex >= index2: # i += 1 # continue arraySign1FLg = False index3 = cpplines[i].rfind("=", 0, endPos) # 判断前一位是否为运算符 if line[index2 - 1:index2] in arraySign1: findFlg = checkSignLeftRightBlank(line, index2 - 2, index2 + 1) signTag = line[index2 - 1:index2] + '=' arraySign1FLg = True if not findFlg: replaceCorrectString(cpplines, i, index3 - 2, index3 + 1, signTag) fileErrorCount[0] = fileErrorCount[0] + 1 if not arraySign1FLg: if line[index2 - 1:index2] == "<" or line[index2 - 1:index2] == ">": # "<<=",">>=" 情况 if line[index2 - 2:index2 - 1] == "<" or line[index2 - 2:index2 - 1] == ">": findFlg = checkSignLeftRightBlank(line, index2 - 3, index2 + 1) signTag = line[index2 - 2:index2] + '=' if not findFlg: replaceCorrectString(cpplines, i, index3 - 3, index3 + 1, signTag) fileErrorCount[0] = fileErrorCount[0] + 1 else: # "<=",">=" 情况 findFlg = checkSignLeftRightBlank(line, index2 - 2, index2 + 1) signTag = line[index2 - 2:index2] + '=' if not findFlg: replaceCorrectString(cpplines, i, index3 - 2, index3 + 1, signTag) fileErrorCount[0] = fileErrorCount[0] + 1 # "!=" 情况 elif line[index2 - 1:index2] == "!" : findFlg = checkSignLeftRightBlank(line, index2 - 2, index2 + 1) signTag = '!=' if not findFlg: replaceCorrectString(cpplines, i, index3 - 2, index3 + 1, signTag) fileErrorCount[0] = fileErrorCount[0] + 1 # "==" 情况 elif line[index2 - 1:index2] == "=" : findFlg = checkSignLeftRightBlank(line, index2 - 2, index2 + 1) signTag = '==' if not findFlg: replaceCorrectString(cpplines, i, index3 - 2, index3 + 1, signTag) fileErrorCount[0] = fileErrorCount[0] + 1 else: # "=" 情况 findFlg = checkSignLeftRightBlank(line, index2 - 1, index2 + 1) signTag = '=' if not findFlg: replaceCorrectString(cpplines, i, index3 - 1, index3 + 1, signTag) fileErrorCount[0] = fileErrorCount[0] + 1 for k in xrange(len(arraySign3)): index = line.find(arraySign3[k], index2, endPos) # "||" 在 '|'判断时产生误判 if -1 != index and line[index: index +2 ] != '||': # next = *s++ 误判 indexPlusPlus = line.find('++') if indexPlusPlus == index: continue findFlg = checkSignLeftRightBlank(line, index - 1, index + len(arraySign3[k])) signTag = arraySign3[k] if not findFlg: index = cpplines[i].find(arraySign3[k], index2, endPos) replaceCorrectString(cpplines, i, index - 1, index + len(arraySign3[k]), signTag) fileErrorCount[0] = fileErrorCount[0] + 1 break # 赋值判断 for j in xrange(len(arraySign2)): index = line.find(arraySign2[j], 0, endPos) if -1 != index: findFlg = checkSignLeftRightBlank(line, index - 1, index + len(arraySign2[j])) signTag = arraySign2[j] if not findFlg: index = cpplines[i].find(arraySign2[j], 0, endPos) replaceCorrectString(cpplines, i, index - 1, index + len(arraySign2[j]), signTag) fileErrorCount[0] = fileErrorCount[0] + 1 #如果是类似 (XXX)*(XXX) 的形式,也需要报错。因为这种情况说明写法有问题,导致无法判断是乘号还是指针 if strcmp.Search(r'\(\w+\)\*\(\w+\)', line): signTag = '*' findFlg = False if not findFlg: cpplines[i] = cpplines[i].replace(")*(", ") * (") fileErrorCount[0] = fileErrorCount[0] + 1 if not findFlg: Error(filename, lines, i, ruleCheckKey, 3, errMessage % signTag) i += 1 # end of CheckCSC030017
def CheckCSC140009(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error): '''函数声明的注释要求:函数的概要说明与详细说明之间必须空一行。[必须] (其他规则要求概要说明只能写在一行) Args: filename:文件名 file_extension:文件扩展名 clean_lines:Holds 3 copies of all lines with different preprocessing applied to them 1) elided member contains lines without strings and comments, 2) lines member contains lines without comments, and 3) raw_lines member contains all the lines without processing.(行首以/*开头的多行注释被替换成空白) rawlines:all the lines without processing nesting_state: Holds states related to parsing braces.(cpplint中的对象,暂时未使用) ruleCheckKey:ruleid Error: error output method ''' particularTypeList = [] lines = clean_lines.elided isStrutsEnumUnionDeclare = False strutsEnumUnionOpenLno = 0 regExp = '' skipEndLno = -1 i = 0 templateStartLno = -1 while i < clean_lines.NumLines(): #null line skip if common.IsBlankLine(lines[i]): i += 1 continue #define line skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue # line start with # skip if strcmp.Search(r'^\s*#', lines[i]): i += 1 continue # template declare ,goto next line m = strcmp.Search(r'^\s*template\s*<', lines[i]) if m: if i == -1: break templateStartLno = i i = getTemplateEndLno(lines, i) + 1 else: templateStartLno = -1 # check typedef,将定于的类型别名存放到particularTypeList中 # typedef特殊类型(结构体,联合,枚举)check m = strcmp.Search(r'(\btypedef\b\s+(\bstruct\b|\bunion\b|\benum\b))\s*(\w+)\s*{*', lines[i].replace('*',' ').replace('&',' ')) if m: typeList,skipEndLno = getNickNameFromTypedefParticularType(m.group(1), lines, i) for typeListItem in typeList: if not (typeListItem in particularTypeList): if not regExp: regExp += r'\b' + typeListItem + r'\b' else: regExp += r'|\b' + typeListItem + r'\b' particularTypeList.append(typeListItem) i = skipEndLno + 1 continue # typedef单独在某一行 或者 typedef基本类型 时 elif strcmp.Search(r'\btypedef\b', lines[i]): # check typedef的目标是特殊类型还是基本类型 isTypedefParticularType,skipEndLno,typeList =getNicknameIfTypedefAndPaticulartypeInTwoLine(lines, i) if isTypedefParticularType: # 特殊类型 for typeListItem in typeList: if not (typeListItem in particularTypeList): if not regExp: regExp += r'\b' + typeListItem + r'\b' else: regExp += r'|\b' + typeListItem + r'\b' particularTypeList.append(typeListItem) i = skipEndLno + 1 continue else: # 基本类型 typeList,skipEndLno=getNicknameFromTypedefBaseType(lines, i) for typeListItem in typeList: if not (typeListItem in particularTypeList): if not regExp: regExp += r'\b' + typeListItem + r'\b' else: regExp += r'|\b' + typeListItem + r'\b' particularTypeList.append(typeListItem) i = skipEndLno + 1 continue # 特殊类型 struct AA::aa; 或者 struct A;这种声明,直接把声明的类型存放到particularTypeList中 m = strcmp.Search(r'(\bstruct\b|\bunion\b|\benum\b)\s+(\w+|\w+::\w+);', lines[i]) if m: if not (m.group(2) in particularTypeList): if not regExp: regExp += r'\b' + m.group(2) + r'\b' else: regExp += r'|\b' + m.group(2) + r'\b' particularTypeList.append(m.group(2)) i += 1 continue # 特殊类型(结构体,联合,枚举)定义时,将其类型保存到particularTypeList中 m = strcmp.Search(r'(\bstruct\b|\bunion\b|\benum\b)', lines[i]) if m: isStrutsEnumUnionDeclare,declareType,skipEndLno,hasError = checkStructEnumUnionDeclare(m.group(1), lines, i) #特殊类型(结构体,联合,枚举)定义时 if isStrutsEnumUnionDeclare: if hasError: break else: if not (declareType in particularTypeList): if not regExp: regExp += r'\b' + declareType + r'\b' else: regExp += r'|\b' + declareType + r'\b' particularTypeList.append(declareType) if declareType.find('::') > -1: declareTypeTemp = declareType[declareType.find('::'):].replace('::','').strip() if not (declareTypeTemp in particularTypeList): if not regExp: regExp += r'\b' + declareTypeTemp + r'\b' else: regExp += r'|\b' + declareTypeTemp + r'\b' particularTypeList.append(declareTypeTemp) #跳到特殊类型定义的下一行去 i = skipEndLno + 1 continue # check 是否含有基本类型的关键字 checkFunctionStartIndex = -1 checkTypeword = '' m = strcmp.Search(r'(\bvoid\b|\bbool\b|\bchar\b|\bwchar_t\b|\bshort\b|\bint\b|\blong\b|\bfloat\b|\bdouble\b)\s*\w*\s*', lines[i].replace('*',' ')) if m: checkTypeword = m.group(1) checkFunctionStartIndex = m.start() if len(particularTypeList) > 0: # check 是否含有特殊类型的关键字 m = strcmp.Search(r'(' + regExp + r')\s*\w*\s*', lines[i].replace('*',' ')) #同时找到基本类型和特殊类型关键字时,哪个在前面,以哪个为基准check函数 if m: particularIndex = m.start() if m.start() < checkFunctionStartIndex: checkFunctionStartIndex = m.start() checkTypeword = m.group(1) #没有找到基本类型 else: if len(particularTypeList) == 0: i += 1 continue # check 是否含有特殊类型 m = strcmp.Search(r'(' + regExp + r')\s*\w*\s*', lines[i].replace('*',' ')) if m: checkTypeword = m.group(1) checkFunctionStartIndex = m.start() # 如果找到下面的格式的代码,判断其是否是函数声明 # int function(...) # struct AAA function (...) if checkFunctionStartIndex > -1: #判断是否是函数声明或定义,左右圆括号所在的行号,是否发生错误 isFunctionDeclareOrDefinition,checkStartLineNo,checkEndLineNo,hasError = isFunction( checkTypeword, lines, i, checkFunctionStartIndex) if hasError: break # 是函数声明或定义 if isFunctionDeclareOrDefinition: isFunctionDeclare, blockEndLineNo = isFunctionDeclaration( lines, checkEndLineNo) # 文件不正常, return if blockEndLineNo == -1: return # 函数定义 if not isFunctionDeclare: i = blockEndLineNo + 1 continue # 函数声明 #check fuction declare前的注释 if templateStartLno == -1: checkStartLineNo = i - 1 else: checkStartLineNo = templateStartLno - 1 checkComment(filename, lines, rawlines, checkStartLineNo, ruleCheckKey, Error) i = checkEndLineNo + 1 continue i += 1
def isFunctionDeclaration(lines, startLno): '''在已知是函数的情况下,判断是否是函数声明还是函数定义 Args: lines:a copy of all lines without strings and comments startLno: function() )所在的行的行号 Returns: boolean: True--函数声明; False--函数定义 int: 函数声明时,function() )所在的行的行号;函数定义时,返回}所在行的行号 当文件格式不正常,无法正常判断时,返回 False,-1 ''' closeParenthesisIndex = lines[startLno].find(')') # 找不到)的位置,文件不正常 if closeParenthesisIndex == -1: return False, -1 # )所在行,)之后不为空白,且)后不是;,说明这是函数声明 if lines[startLno].endswith('\\'): tempLine = lines[startLno][lines[startLno].find(')') + 1:len(lines[startLno]) - 1].strip() else: tempLine = lines[startLno][lines[startLno].find(')') + 1:].strip() if tempLine and tempLine.startswith(';'): return True, startLno # )之后不为空白,但是不是;也不是{,文件不正常 if tempLine and (not tempLine.startswith('{')): return False, -1 i = startLno lengthOfLines = len(lines) openCurlyBraceLineNo = -1 while i < lengthOfLines: #null line skip if common.IsBlankLine(lines[i]): i += 1 continue #define line skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue # line start with # skip if strcmp.Search(r'^\s*#', lines[i]): i += 1 continue if i == startLno: pass # 如果有换行符,去掉换行符 elif lines[i].endswith("\\"): tempLine = lines[i][:len(lines[i]) -1].strip() else: tempLine = lines[i].strip() # 如果改行只有换行符和空格而没有代码时 if common.IsBlankLine(tempLine): i += 1 continue # )之后不为空白,是{,说明是函数定义 if tempLine.startswith('{'): openCurlyBraceLineNo = i break # )之后不为空白,是;,说明是函数声明 elif tempLine.startswith(';'): return True, startLno # )之后不为空白,但是不是;也不是{,文件不正常 else: return False, -1 if openCurlyBraceLineNo == -1: return False, -1 # 查找{对应的}所在行的行号 i = openCurlyBraceLineNo openCurlyBraceQty = 0 closeCurlyBraceQty = 0 closeCurlyBracelineNo = -1 while i < lengthOfLines: #null line skip if common.IsBlankLine(lines[i]): i += 1 continue #define line skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue # line start with # skip if strcmp.Search(r'^\s*#', lines[i]): i += 1 continue openCurlyBraceQty = openCurlyBraceQty + lines[i].count('{') closeCurlyBraceQty = closeCurlyBraceQty + lines[i].count('}') if openCurlyBraceQty == closeCurlyBraceQty and openCurlyBraceQty > 0: closeCurlyBracelineNo = i break i += 1 # 找不到)的位置,文件不正常 if openCurlyBraceQty != closeCurlyBraceQty or openCurlyBraceQty == 0 or closeCurlyBraceQty == 0: return False, -1 # 返回:函数定义,}所在行的行号 return False, closeCurlyBracelineNo
def CheckCSC020003(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error): errorMessage = 'Code Style Rule: When a function declaration/definition is too long, it should be wrapped before the type of a parameter. For example, funcA(int a, int b) should wrap before "int b".' particularTypeList = [] lines = clean_lines.elided isStrutsEnumUnionDeclare = False strutsEnumUnionOpenLno = 0 regExp = '' skipEndLno = -1 i = 0 while i < clean_lines.NumLines(): #null line skip if common.IsBlankLine(lines[i]): i += 1 continue #define line skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue # line start with # skip if strcmp.Search(r'^\s*#', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue # template declare line skip m = strcmp.Search(r'^\s*template\s*<', lines[i]) if m: if i == -1: break i = getTemplateEndLno(lines, i) + 1 continue # check typedef,将定于的类型别名存放到particularTypeList中 # typedef特殊类型(结构体,联合,枚举)check m = strcmp.Search(r'(\btypedef\b\s+(\bstruct\b|\bunion\b|\benum\b))\s*(\w+)\s*{*', lines[i].replace('*',' ').replace('&',' ')) if m: typeList,skipEndLno = getNickNameFromTypedefParticularType(m.group(1), lines, i) for typeListItem in typeList: if not (typeListItem in particularTypeList): if not regExp: regExp += r'\b' + typeListItem + r'\b' else: regExp += r'|\b' + typeListItem + r'\b' particularTypeList.append(typeListItem) i = skipEndLno + 1 continue # typedef单独在某一行 或者 typedef基本类型 时 elif strcmp.Search(r'\btypedef\b', lines[i]): # check typedef的目标是特殊类型还是基本类型 isTypedefParticularType,skipEndLno,typeList =getNicknameIfTypedefAndPaticulartypeInTwoLine(lines, i) if isTypedefParticularType: # 特殊类型 for typeListItem in typeList: if not (typeListItem in particularTypeList): if not regExp: regExp += r'\b' + typeListItem + r'\b' else: regExp += r'|\b' + typeListItem + r'\b' particularTypeList.append(typeListItem) i = skipEndLno + 1 continue else: # 基本类型 typeList,skipEndLno=getNicknameFromTypedefBaseType(lines, i) for typeListItem in typeList: if not (typeListItem in particularTypeList): if not regExp: regExp += r'\b' + typeListItem + r'\b' else: regExp += r'|\b' + typeListItem + r'\b' particularTypeList.append(typeListItem) i = skipEndLno + 1 continue # 特殊类型 struct AA::aa; 或者 struct A;这种声明,直接把声明的类型存放到particularTypeList中 m = strcmp.Search(r'(\bstruct\b|\bunion\b|\benum\b)\s+(\w+|\w+::\w+);', lines[i]) if m: if not (m.group(2) in particularTypeList): if not regExp: regExp += r'\b' + m.group(2) + r'\b' else: regExp += r'|\b' + m.group(2) + r'\b' particularTypeList.append(m.group(2)) i += 1 continue # 特殊类型(结构体,联合,枚举)定义时,将其类型保存到particularTypeList中 m = strcmp.Search(r'(\bstruct\b|\bunion\b|\benum\b)', lines[i]) if m: isStrutsEnumUnionDeclare,declareType,skipEndLno,hasError = checkStructEnumUnionDeclare(m.group(1), lines, i) #特殊类型(结构体,联合,枚举)定义时 if isStrutsEnumUnionDeclare: if hasError: break else: if not (declareType in particularTypeList): if not regExp: regExp += r'\b' + declareType + r'\b' else: regExp += r'|\b' + declareType + r'\b' particularTypeList.append(declareType) if declareType.find('::') > -1: declareTypeTemp = declareType[declareType.find('::'):].replace('::','').strip() if not (declareTypeTemp in particularTypeList): if not regExp: regExp += r'\b' + declareTypeTemp + r'\b' else: regExp += r'|\b' + declareTypeTemp + r'\b' particularTypeList.append(declareTypeTemp) #跳到特殊类型定义的下一行去 i = skipEndLno + 1 continue # check 是否含有基本类型的关键字 baseIndex = -1 particularIndex = -1 checkTypeword = '' m = strcmp.Search(r'(\bvoid\b|\bbool\b|\bchar\b|\bwchar_t\b|\bshort\b|\bint\b|\blong\b|\bfloat\b|\bdouble\b)\s*\w*\s*', lines[i].replace('*',' ')) if m: checkTypeword = m.group(1) baseIndex = lines[i].replace('*',' ').find(checkTypeword) if len(particularTypeList) > 0: # check 是否含有特殊类型的关键字 m = strcmp.Search(r'(' + regExp + r')\s*\w*\s*', lines[i].replace('*',' ')) #同时找到基本类型和特殊类型关键字时,哪个在前面,以哪个为基准check函数 if m: particularIndex = lines[i].replace('*',' ').find(m.group(1)) if particularIndex < baseIndex and particularIndex > -1: checkTypeword = m.group(1) #没有找到基本类型 else: if len(particularTypeList) == 0: i += 1 continue # check 是否含有特殊类型 m = strcmp.Search(r'(' + regExp + r')\s*\w*\s*', lines[i].replace('*',' ')) if m: checkTypeword = m.group(1) particularIndex = lines[i].replace('*',' ').find(checkTypeword) if baseIndex > -1 or particularIndex > -1: #判断是否是函数声明定义,左右圆括号所在的行号,是否发生错误 isFunction,checkStartLineNo,checkEndLineNo,hasError = isFunctionDeclare(checkTypeword, lines, i) if hasError: break if isFunction: #func()左右圆括号所在的行号相同,说明该函数()中间没有换行 if checkStartLineNo == checkEndLineNo: i = checkEndLineNo + 1 continue #check换行 checkNewLine(filename, lines, checkStartLineNo, checkEndLineNo, ruleCheckKey, Error) i = checkEndLineNo + 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
def CheckCSC020010(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error): '''函数功能:一行中最多有一条语句。 特殊:for循环除外 Args: filename:文件名 file_extension:文件扩展名 clean_lines:Holds 3 copies of all lines with different preprocessing applied to them 1) elided member contains lines without strings and comments, 2) lines member contains lines without comments, and 3) raw_lines member contains all the lines without processing.(行首以/*开头的多行注释被替换成空白) rawlines:all the lines without processing nesting_state: Holds states related to parsing braces.(cpplint中的对象,暂时未使用) startLineNo:for,while,if,switch所在的行 ruleCheckKey:ruleid Error: error output method ''' errorMessage = 'Code Style Rule: There should be only one statement per line.' lines = clean_lines.elided i = 0 closeParenthesisLineNo = -1 closeParenthesisIndex = -1 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 findIndex = 0 preCloseParenthesisIndex = -1 preCloseParenthesisLineNo = -1 if closeParenthesisLineNo == i: preCloseParenthesisLineNo = closeParenthesisLineNo preCloseParenthesisIndex = closeParenthesisIndex findIndex = closeParenthesisIndex #查找for mFor = strcmp.Search(r'\bfor\b', lines[i][findIndex:]) if mFor: #当前行有之前for的)时 # for (af;adsf; # ) { for ( if preCloseParenthesisLineNo == i: Error(filename, lines, i, ruleCheckKey, 3, errorMessage) hasSystemError,hasLastFor,closeParenthesisLineNo,closeParenthesisIndex=getEndInfoOfLastForConditionInALine(lines, i) if hasSystemError: return if closeParenthesisLineNo == -1: return if closeParenthesisLineNo == i: i += 1 continue if closeParenthesisLineNo > i: i = closeParenthesisLineNo continue # 当前行没有之前for的)时 # AAA(); for(i=0;i<1;i++) { if strcmp.Search(r';\s*[^\s\}\)\\/]', lines[i][0:mFor.end()]): Error(filename, lines, i, ruleCheckKey, 3, errorMessage) #查找本行最后最后一个for的)所在的位置 hasSystemError,hasLastFor,closeParenthesisLineNo,closeParenthesisIndex=getEndInfoOfLastForConditionInALine(lines, i) if hasSystemError: return if closeParenthesisLineNo == -1: return if closeParenthesisLineNo == i: i += 1 continue if closeParenthesisLineNo > i: i = closeParenthesisLineNo continue # 当前行没有之前for的)时 # for(i=0;i<1;i++) { ...... closeParenthesisLineNo, closeParenthesisIndex = getEndInfoOfCondition(lines, i, findIndex + mFor.start()) #找不到for的()中)所在的行号 if closeParenthesisLineNo == -1: return # for的)在不在本行在后面时,不再check本行了,check)在的行 #for(i=0;i<1; #i++) { ...... if closeParenthesisLineNo > i: i = closeParenthesisLineNo continue #for的)在本行时 elif closeParenthesisLineNo == i: secondFor = strcmp.Search(r'\bfor\b', lines[i][closeParenthesisIndex:]) # 本行有两个以上的for时 # for(i=0;i<1;){ for(i=0 if secondFor: Error(filename, lines, i, ruleCheckKey, 3, errorMessage) #查找本行最后最后一个for的)所在的位置 hasSystemError,hasLastFor,closeParenthesisLineNo,closeParenthesisIndex=getEndInfoOfLastForConditionInALine(lines, i) if hasSystemError: return if closeParenthesisLineNo == -1: return if closeParenthesisLineNo == i: i += 1 continue if closeParenthesisLineNo > i: i = closeParenthesisLineNo continue # 本行有1个for时 else: #查看该行中是否出现这种情况: ;后面有语句 #1.for () {aaa();bbb() #2.for () {aaa(); mSemicolon = strcmp.Search(r';\s*[^\s\}\)\\/]|[^\s\{\}]\s*;', lines[i][closeParenthesisIndex:]) if mSemicolon: if mSemicolon.start(): Error(filename, lines, i, ruleCheckKey, 3, errorMessage) i += 1 continue #在for的condition表达式之外时 else: # 当前行时下列情形的第二行时 # for(int i=0;i<10 # i++){ function(); # } if preCloseParenthesisLineNo == i: m = strcmp.Search(r'[^\s\{\}]\s*;', lines[i][preCloseParenthesisIndex + 1:]) if m: #避免下面情形误判.因为既存处理,行末/**/换行时可能无法lines中可能残留注释 # for(int i=0;i<10 # i++){ /*function(); # } if lines[i][preCloseParenthesisIndex + 1:m.start()].find('/*') == -1: Error(filename, lines, i, ruleCheckKey, 3, errorMessage) i += 1 continue #当前行中没有for的表达式 #查看该行中是否出现这种情况: ;后面有语句 mSemicolon = strcmp.Search(r';\s*[^\s\}\)\\/]', lines[i]) if mSemicolon: #当前行没有之前for的)时 #funtion(); AAA(); if preCloseParenthesisLineNo < i: Error(filename, lines, i, ruleCheckKey, 3, errorMessage) #当前行有之前for的)时 # for (asdf;asdf; # ){ funtion();funtion2(); if preCloseParenthesisLineNo == i and mSemicolon.start() > preCloseParenthesisIndex: Error(filename, lines, i, ruleCheckKey, 3, errorMessage) #当前行有之前for的)时 # for (asdf; # asdf;){ funtion();funtion2(); elif preCloseParenthesisLineNo == i and mSemicolon.start() < preCloseParenthesisIndex: if strcmp.Search(r';\s*[^\s\}\)\\/]', lines[i][preCloseParenthesisIndex:]): Error(filename, lines, i, ruleCheckKey, 3, errorMessage) i += 1 continue
def getStatementStartEnd(lines, startLineNo, typeword): #函数功能:查找if,while的左右括号所在的行号,以及if,while行的缩进情况 #if,while所在行,凡是含有if,while字符串的单词,都相应的字符串都被替换 substring = '' if typeword == 'if': substring = '12' elif typeword == 'while': substring = '12345' startLine = strcmp.Sub(r'\w' + typeword, '0' + substring, lines[startLineNo]) startLine = strcmp.Sub(r'' + typeword + r'\w', substring + '0', startLine) #int a; /* if (*/ or int a; /* if( or int a; /* adfa \n if */这三种情况skip,当成if的左右括号在一行,不check的情况 typewordIndex = startLine.find(typeword) multiCommentStartIndex = startLine.find('/*') multiCommentEndIndex = startLine.find('*/') if multiCommentStartIndex > -1 and multiCommentEndIndex > -1 and \ typewordIndex > multiCommentStartIndex and typewordIndex < multiCommentEndIndex: return 0,startLineNo,startLineNo elif multiCommentStartIndex == -1 and multiCommentEndIndex > -1 and typewordIndex < multiCommentEndIndex: return 0,startLineNo,startLineNo elif multiCommentEndIndex == -1 and multiCommentStartIndex > -1 and typewordIndex > multiCommentStartIndex: return 0,startLineNo,startLineNo #查找if,while所在行的缩进的空格数量,tab键作为4个空格 indentation = 0 m = strcmp.Search(r'^(\s*)\S', startLine) if m: indentation = len(m.group(1).replace('\t', ' ')) #查找if(),while()中左右括号所在的行 lengthOfLines = len(lines) openParenthesisQty = 0 closeParenthesisQty = 0 checkStartLineNo = -1 checkEndLineNo = -1 skipEndLno = -1 line = '' for i in xrange(startLineNo, lengthOfLines): checkEndLineNo = i line = lines[i] if i == startLineNo: line = lines[i][startLine.find(typeword):] #空白行--skip if common.IsBlankLine(line): continue if i <= skipEndLno: continue #宏定义--skip if strcmp.Search(r'^\s*#\s*define\s+', line): skipEndLno = common.getDefineMacroEndLineNo(lines, i) continue #预定义--skip if strcmp.Search(r'^\s*#', lines[i]): skipEndLno = common.getDefineMacroEndLineNo(lines, i) continue openParenthesisQty = openParenthesisQty + line.count('(') closeParenthesisQty = closeParenthesisQty + line.count(')') if openParenthesisQty > 0 and checkStartLineNo == -1: checkStartLineNo = i if openParenthesisQty == closeParenthesisQty and openParenthesisQty > 0: break if openParenthesisQty != openParenthesisQty: return indentation, checkStartLineNo, -1 return indentation, checkStartLineNo, checkEndLineNo
def CheckCSC020009(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error, cpplines, fileErrorCount): '''函数体定义需要遵循下面的规范: {和}分别单独占一行。 [例外]如果是定义在class定义中的空实现,{和}分别单独在一行,或者需将{和}写在一起,并放置在函数后面。 {和}分别单独占一行也是可以的。[必须] cpp文件中的空实现,{和}分别单独占一行。 Args: filename:文件名 file_extension:文件扩展名 clean_lines:Holds 3 copies of all lines with different preprocessing applied to them 1) elided member contains lines without strings and comments, 2) lines member contains lines without comments, and 3) raw_lines member contains all the lines without processing.(行首以/*开头的多行注释被替换成空白) rawlines:all the lines without processing nesting_state: Holds states related to parsing braces.(cpplint中的对象,暂时未使用) ruleCheckKey:ruleid Error: error output method ''' errorMessageHeader = 'Code Style Rule:' #{和}分别单独占一行。 errorMessage = ' The left curly brace "{" and right curly brace "}" in a function definition should be both in a separate line.' # 右大括号右边不能带分号 semicolonErrorMessage = ' There should be no semicolon after the right curly brace "}".' # function() { } ---error hasSpaceInBraceErrorMessage = ' Please leave no space between the left and right curly braces. For example: void func() {}.' # class定义(struct定义)中,空实现,{和}写在一起,{和)放置在函数后面 or {和}分别单独占一行。 exceptionClassDefinition = ' For an empty function in the class(or struct) definition block, it can be written in the following two formats: 1.Put the "{" and "}" in the same line with the function name 2.Put the "{" and "}" both in a separate line.' lines = clean_lines.elided i = 0 currentLineHasError = False nextLineHasError = False openCurlyBraceIndex = -1 closeCurlyBraceLineNo = -1 closeCurlyBraceIndex = -1 classStartLineNo = -1 classStartIndex = -1 classEndLineNo = -1 classEndIndex = -1 templateCloseAngleBraceLineNo = -1 templateCloseAngleBraceIndex = -1 while i < clean_lines.NumLines(): #null line skip if common.IsBlankLine(lines[i]): i += 1 continue #define line skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue # line start with # skip if strcmp.Search(r'^\s*#', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue # template<class t, class t1>---- skkip m = strcmp.Search(r'\btemplate\b', lines[i]) if m: templateCloseAngleBraceLineNo,templateCloseAngleBraceIndex = getTemplateEndLno(lines, i, m.start()) #找不到template >所在的位置,则说明代码有问题,不再check if templateCloseAngleBraceLineNo == -1 or templateCloseAngleBraceIndex == -1: return i = templateCloseAngleBraceLineNo # 当前行是class的}所在的行,或者}后面的行时,重新找class定义 if classEndLineNo <= i: # 当前行是template 的>所在的行,从class定义和templae的>后开始查找 class定义 if templateCloseAngleBraceLineNo == i: classFindBeginIndex = templateCloseAngleBraceIndex # 当前行是class的};所在的行 if classEndLineNo == i: if templateCloseAngleBraceIndex < classEndIndex: classFindBeginIndex = classEndIndex # 当前行不是template 的>所在的行 and 当前行是class的};所在的行,从class定义后开始查找 class定义 elif classEndLineNo == i: classFindBeginIndex = classEndIndex # 当前行不是template 的>所在的行 and 当前行不是class的}所在的行 else: classFindBeginIndex = 0 # check是不是class定义 m = strcmp.Search(r'\b(class|struct)\b', lines[i][classFindBeginIndex:]) if m: isClassDefinition,classEndLineNo,classEndIndex = findClassStructDefinitionEndInfo(lines, i, m.start(), m.group(1)) if isClassDefinition and (classEndLineNo == -1 or classEndIndex == -1): return # 是class定义 if isClassDefinition: classStartLineNo = i classStartIndex = classFindBeginIndex + m.start() # 假如几个函数定义都写到一行了而且都不符合要求,这一行只报一个错误,不会重复报多个错误 currentLineHasError = False if i == closeCurlyBraceLineNo and nextLineHasError: currentLineHasError = True nextLineHasError = False currentLine = lines[i] lengthCurrentLine = len(lines[i]) # 查找{ openCurlyBraceIndex = currentLine.find('{') if openCurlyBraceIndex == -1: i += 1 continue # 如果{左侧满足operator += (...) 或者aaa(...)这种格式,说明这个是函数定义 # operator +=(int a, int b) {} # AA::BB() {} # BB() {} while openCurlyBraceIndex > -1 and openCurlyBraceIndex < lengthCurrentLine: # 判断{是否是函数定义的第一个{ isFunction, tempCloseParenthesislineNo, tempcloseParenthesisIndex, hasInitializationList = isFunctionDefinition(lines, i, openCurlyBraceIndex) # 是函数定义 if isFunction: # 查找{对应的}的行号和其所在行的位置 closeCurlyBraceLineNo, closeCurlyBraceIndex = getFunctionCloseCurlyBraceInfo(lines, i, openCurlyBraceIndex) # 查不到{对应的}的行号和其所在行的位置,说明文件不正常,不再check了 if closeCurlyBraceLineNo == -1: return # check 函数是否在class 的{}内 isInClassDefinition = isInBlock(closeCurlyBraceLineNo, closeCurlyBraceIndex, classStartLineNo, classStartIndex, classEndLineNo, classEndIndex) # }后面是逗号-- 不是函数定义 if whetherCommarIsCloseAfterCloseCurlyBrace(lines, closeCurlyBraceLineNo, closeCurlyBraceIndex): # {}不在同一行 if i < closeCurlyBraceLineNo: i = closeCurlyBraceLineNo break # {}在同一行 # check 本行下一个{ tempOpenCurlyBraceIndex = currentLine[closeCurlyBraceIndex + 1:].find('{') if tempOpenCurlyBraceIndex == -1: i += 1 break openCurlyBraceIndex = closeCurlyBraceIndex + 1 + tempOpenCurlyBraceIndex continue # {}在同一行 if closeCurlyBraceLineNo == i: if (not currentLineHasError) and strcmp.Search(r'^\s*;', lines[closeCurlyBraceLineNo][closeCurlyBraceIndex + 1:]): Error(filename, lines, i, ruleCheckKey, 3, errorMessageHeader + semicolonErrorMessage) # {}之间没有内容 and 无初始化列表时 if common.IsBlankLine(lines[i][openCurlyBraceIndex + 1:closeCurlyBraceIndex]) and (not hasInitializationList): # ) 与 {不在同一行 if tempCloseParenthesislineNo != i and (not currentLineHasError): # class定义中 if isInClassDefinition: # {和}写在一起,{和)放置在函数后面 or {和}分别单独占一行。 Error(filename, lines, i, ruleCheckKey, 3, errorMessageHeader + exceptionClassDefinition) else: # {和}分别单独占一行 Error(filename, lines, i, ruleCheckKey, 3, errorMessageHeader + errorMessage) currentLineHasError = True elif tempCloseParenthesislineNo == i and (not currentLineHasError): # class定义中时, if isInClassDefinition: # function() {} other code(for example: get();)---error if strcmp.Search(r'^\s*[^\s\;]', lines[closeCurlyBraceLineNo][closeCurlyBraceIndex + 1:]): Error(filename, lines, i, ruleCheckKey, 3, errorMessageHeader + errorMessage) currentLineHasError = True # function() { } ---error if openCurlyBraceIndex + 1 < closeCurlyBraceIndex: Error(filename, lines, i, ruleCheckKey, 3, errorMessageHeader + hasSpaceInBraceErrorMessage) currentLineHasError = True # class定义外 else: Error(filename, lines, i, ruleCheckKey, 3, errorMessageHeader + errorMessage) currentLineHasError = True # {}之间有内容 or have初始化列表时 # 要求:{和}分别单独占一行 else: if not currentLineHasError: currentLineHasError = True Error(filename, lines, i, ruleCheckKey, 3, errorMessageHeader + errorMessage) tempOpenCurlyBraceIndex = currentLine[openCurlyBraceIndex + 1:].find('{') if tempOpenCurlyBraceIndex == -1: i += 1 break openCurlyBraceIndex = openCurlyBraceIndex + 1 + tempOpenCurlyBraceIndex # {}不在同一行 else: hasCode = whetherHasSourceBetweenTwoLine(lines, i, openCurlyBraceIndex, closeCurlyBraceLineNo, closeCurlyBraceIndex) # check { --------------------> if not currentLineHasError: # 空实现(无代码 and 没有初始化列表) if (not hasCode) and (not hasInitializationList): # class定义中时 if isInClassDefinition: # )与{在同一行 if tempCloseParenthesislineNo == i: # {和}写在一起,{和)放置在函数后面 or {和}分别单独占一行。 Error(filename, lines, i, ruleCheckKey, 3, errorMessageHeader + exceptionClassDefinition) currentLineHasError = True # class定义外时 else: # )与{在同一行 if tempCloseParenthesislineNo == i: #{和}分别单独占一行。 Error(filename, lines, i, ruleCheckKey, 3, errorMessageHeader + errorMessage) currentLineHasError = True # 非空实现 else: # {独占一行 if common.IsBlankLine(lines[i][:openCurlyBraceIndex]) and common.IsBlankLine(lines[i][openCurlyBraceIndex + 1:]): pass # {非独占一行 else: currentLineHasError = True Error(filename, lines, i, ruleCheckKey, 3, errorMessageHeader + errorMessage) # check { <-------------------- # check } --------------------> # 非空实现(有代码 or 有初始化列表) if hasCode or hasInitializationList: # }独占一行 # chcek }前是否有代码 hasCodeBeforeCloseCurlyBrace = False if not common.IsBlankLine(lines[closeCurlyBraceLineNo][:closeCurlyBraceIndex]): hasCodeBeforeCloseCurlyBrace = True # chcek }后是否有分号 hasSemicolonAfterCloseCurlyBrace = False mForSemicolon = strcmp.Search(r'^\s*;', lines[closeCurlyBraceLineNo][closeCurlyBraceIndex + 1:]) if mForSemicolon: hasSemicolonAfterCloseCurlyBrace = True # chcek }后是否有代码 # }后有分号时 if hasSemicolonAfterCloseCurlyBrace: # chcek 分号后是否有代码 if common.IsBlankLine(lines[closeCurlyBraceLineNo][closeCurlyBraceIndex + 1 + mForSemicolon.end():]): hasCodeAfterCloseCurlyBrace = False else: hasCodeAfterCloseCurlyBrace = True # }后没有分号时 else: # chcek }后是否有代码 if common.IsBlankLine(lines[closeCurlyBraceLineNo][closeCurlyBraceIndex + 1:]): hasCodeAfterCloseCurlyBrace = False else: hasCodeAfterCloseCurlyBrace = True # }后有分号 and }所在的行有代码 if (hasCodeBeforeCloseCurlyBrace or hasCodeAfterCloseCurlyBrace) and hasSemicolonAfterCloseCurlyBrace: nextLineHasError = True currentLineHasError = True Error(filename, lines, closeCurlyBraceLineNo, ruleCheckKey, 3, errorMessageHeader + errorMessage) Error(filename, lines, closeCurlyBraceLineNo, ruleCheckKey, 3, errorMessageHeader + semicolonErrorMessage) # }后有分号 elif hasSemicolonAfterCloseCurlyBrace: nextLineHasError = True currentLineHasError = True Error(filename, lines, closeCurlyBraceLineNo, ruleCheckKey, 3, errorMessageHeader + semicolonErrorMessage) # }所在的行有代码 elif hasCodeBeforeCloseCurlyBrace or hasCodeAfterCloseCurlyBrace: nextLineHasError = True currentLineHasError = True Error(filename, lines, closeCurlyBraceLineNo, ruleCheckKey, 3, errorMessageHeader + errorMessage) # 空实现 else: # check }后是否有分号 if strcmp.Search(r'^\s*;', lines[closeCurlyBraceLineNo][closeCurlyBraceIndex + 1:]): nextLineHasError = True currentLineHasError = True Error(filename, lines, closeCurlyBraceLineNo, ruleCheckKey, 3, errorMessageHeader + semicolonErrorMessage) # )与{不在同一行 and }后有代码 elif strcmp.Search(r'^\s*\S', lines[closeCurlyBraceLineNo][closeCurlyBraceIndex + 1:]): if not isInClassDefinition: nextLineHasError = True currentLineHasError = True Error(filename, lines, closeCurlyBraceLineNo, ruleCheckKey, 3, errorMessageHeader + errorMessage) elif tempCloseParenthesislineNo != i: nextLineHasError = True currentLineHasError = True Error(filename, lines, closeCurlyBraceLineNo, ruleCheckKey, 3, errorMessageHeader + errorMessage) # check } <-------------------- i = closeCurlyBraceLineNo break # 不是函数定义 else: tempOpenCurlyBraceIndex = currentLine[openCurlyBraceIndex + 1:].find('{') if tempOpenCurlyBraceIndex == -1: i += 1 break openCurlyBraceIndex = openCurlyBraceIndex + 1 + tempOpenCurlyBraceIndex
def findClassStructDefinitionEndInfo(lines, startLineNo, startIndex, keyWord): '''从startLno向下查找class的}所在的行号 Args: lines:a copy of all lines without strings and comments startLno:leyword[class]所在的行号 startIndex: leyword[class] index keyWord: 关键字 Returns: 是否是class/struct定义,class的};(or struct 的})所在的行号,index (systemError: return True, -1, -1) ''' openCurlyBraceQty = 0 closeCurlyBraceQty = 0 lengthOfLines = len(lines) i = startLineNo semicolonIndex = -1 otherCharIndex = -1 closeCurlyBraceIndex = -1 colonIndex = -1 commaIndex = -1 while i < lengthOfLines: endLine = i #null line skip if common.IsBlankLine(lines[i]): i += 1 continue #define line skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue # line start with # skip if strcmp.Search(r'^\s*#', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue if i == startLineNo: line = lines[i][startIndex:] else: line = lines[i] if openCurlyBraceQty == closeCurlyBraceQty and openCurlyBraceQty > 0: # struct if keyWord == 'struct': return True, i, closeCurlyBraceIndex # class # class A {};--是函数定义 if line.strip().startswith(';'): endIndex = line.find(';') if i == startLineNo: endIndex = endIndex + startIndex return True, i, endIndex # class {} AA-- }后没有;,说明文件有问题 else: return True, -1, -1 # 逐个字符对比,累计{,}的数量 for j in xrange(0, len(line)): if line[j] == '{': openCurlyBraceQty += 1 elif line[j] == '}': closeCurlyBraceIndex = j closeCurlyBraceQty += 1 elif line[j] == ':': colonIndex = j elif line[j] == ',': commaIndex = j elif line[j] == ';': semicolonIndex = j elif line[j] in ['(',')', '=']: otherCharIndex = j #{,}个数相同 if openCurlyBraceQty == closeCurlyBraceQty: # class A; --不是class定义 # struct A a; --不是struct定义 if openCurlyBraceQty == 0 and semicolonIndex != -1: return False, -1, -1 #class a: public b, public c {-- 避免这种情况当成非类定义 # function(class A a,struct A c);--不是class定义 elif openCurlyBraceQty == 0 and colonIndex == -1 and commaIndex != -1: return False, -1, -1 # stuct a a ={};--不是struct定义 # function(struct A b,struct A c);--不是struct定义 elif openCurlyBraceQty == 0 and otherCharIndex != -1: return False, -1, -1 elif openCurlyBraceQty > 0: # struct if keyWord == 'struct': return True, i, closeCurlyBraceIndex # class # class A {};--是函数定义 if line[j + 1 :].strip().startswith(';'): semicolonIndex = line[j:].find(';') if i == startLineNo: endIndex = startIndex + j + semicolonIndex else: endIndex = j + semicolonIndex return True, i, endIndex # class A {} \\ or class A {} -- check next line elif line[j + 1 :].strip() == '\\' or (not line[j + 1 :].strip()): break # class {} AA-- }后没有;,说明文件有问题 else: return True, -1, -1 break i += 1 return False, -1, -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 CheckCSC030006(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error, cpplines, fileErrorCount): errMessage = "Code Style Rule: There should be a blank line after every function definition." lines = clean_lines.elided #函数定义的例子 #void A (){ #Test1& operator = (const Test1& t1){ // 赋值运算符 #void VRS_210010::CheckGlobalInitInConstructor(){ #void VRS_210010::foo(string s, int i):name(s), id(i){} ; #int bb<t,t1>::aa(){ #AA::A VRS_210010::CheckGlobalInitInConstructor(){ #1 operator关键字 #2 ::找 #3 普通 i = 0 while i < clean_lines.NumLines(): line = lines[i] #null line skip if common.IsBlankLine(line): i += 1 continue #define line skip if strcmp.Search(r'^\s*#\s*define\s+', line): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue # line start with # skip if strcmp.Search(r'^\s*#', line): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue # 查找{ openCurlyBraceIndex = line.find('{') if openCurlyBraceIndex == -1: i += 1 continue # 如果{左侧满足operator += (...) 或者aaa(...)这种格式,说明这个是函数定义 # operator +=(int a, int b) {} # AA::BB() {} # BB() {} # 判断{是否是函数定义的第一个{ isFunction, tempCloseParenthesislineNo, tempcloseParenthesisIndex = isFunctionDefinition(lines, i, openCurlyBraceIndex) # 是函数定义 if isFunction: # 查找{对应的}的行号和其所在行的位置 closeCurlyBraceLineNo, closeCurlyBraceIndex = getFunctionCloseCurlyBraceInfo(lines, i, openCurlyBraceIndex) # 查不到{对应的}的行号和其所在行的位置,说明文件不正常,不再check了 if closeCurlyBraceLineNo == -1: return # {}在同一行 if closeCurlyBraceLineNo == i: i += 1 continue else : # 文件结束 if -1 == lines[closeCurlyBraceLineNo + 1].find('EOF') and \ closeCurlyBraceLineNo + 1 < clean_lines.NumLines() - 1 and \ lines[closeCurlyBraceLineNo + 1].strip() != '};' and \ lines[closeCurlyBraceLineNo + 1].strip() != '}' : # 函数定义后必须有空行 if not common.IsBlankLine(lines[closeCurlyBraceLineNo + 1]) : Error(filename, lines, closeCurlyBraceLineNo, ruleCheckKey, 3, errMessage) i = closeCurlyBraceLineNo + 2 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 CheckCSC030017(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error): # 赋值判断 #因为 * & 即是指针也是运算符,无法判断,所有不判断这两个 arraySign1 = ["+","-","*","/","%","&", "|", "~", "^"] # 运算符 # eg. if (a && b), if (a || b) arraySign2 = ["&&", "||"] # 必须在等号后判断的,否则容易产生误判 # error 数据有赋值为负数的情况,'-'删除 arraySign3 = ["+","/","%", "|", "<<", ">>"] lines = clean_lines.elided errMessage = "Code Style Rule: There should a space both before and after a binary operator \"%s\". For example: A = B." i = 0 while i < clean_lines.NumLines(): findFlg = True index = 0 signTag = '' line = lines[i].replace("->", ".") if common.IsBlankLine(line): i += 1 continue #define line skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue if strcmp.Search(r'^\s*#', line): i += 1 continue # 查找"operator",忽略操作符重载的函数名的判断 if strcmp.Search(r'\boperator\b', line): i += 1 continue # 查找"===",忽略 if strcmp.Search(r'===', line): i += 1 continue #只判断结束语句 endPos = line.rfind(";") if endPos == -1: endPos = len(line) # 查找"=" index2 = line.rfind("=", 0, endPos) if -1 != index2 and -1 == line.find('virtual ', 0, index2): arraySign1FLg = False # 判断前一位是否为运算符 if line[index2 - 1:index2] in arraySign1: findFlg = checkSignLeftRightBlank(line, index2 - 2, index2 + 1) signTag = line[index2 - 1:index2] + '=' arraySign1FLg = True if not arraySign1FLg: if line[index2 - 1:index2] == "<" or line[index2 - 1:index2] == ">": # "<<=",">>=" 情况 if line[index2 - 2:index2 - 1] == "<" or line[index2 - 2:index2 - 1] == ">": findFlg = checkSignLeftRightBlank(line, index2 - 3, index2 + 1) else: # "<=",">=" 情况 findFlg = checkSignLeftRightBlank(line, index2 - 2, index2 + 1) signTag = line[index2 - 2:index2] + '=' # "!=" 情况 elif line[index2 - 1:index2] == "!" : findFlg = checkSignLeftRightBlank(line, index2 - 2, index2 + 1) signTag = '!=' # "==" 情况 elif line[index2 - 1:index2] == "=" : findFlg = checkSignLeftRightBlank(line, index2 - 2, index2 + 1) signTag = '==' else: # "=" 情况 findFlg = checkSignLeftRightBlank(line, index2 - 1, index2 + 1) signTag = '=' for k in xrange(len(arraySign3)): index = line.find(arraySign3[k], index2, endPos) if -1 != index: # next = *s++ 误判 indexPlusPlus = line.find('++') if indexPlusPlus == index: continue findFlg = checkSignLeftRightBlank(line, index - 1, index + len(arraySign3[k])) signTag = arraySign3[k] break # 赋值判断 for j in xrange(len(arraySign2)): index = line.find(arraySign2[j], 0, endPos) if -1 != index: findFlg = checkSignLeftRightBlank(line, index - 1, index + len(arraySign2[j])) signTag = arraySign2[j] #如果是类似 (XXX)*(XXX) 的形式,也需要报错。因为这种情况说明写法有问题,导致无法判断是乘号还是指针 if strcmp.Search(r'\(\w+\)\*\(\w+\)', line): signTag = '*' findFlg = False if not findFlg: Error(filename, lines, i, ruleCheckKey, 3, errMessage % signTag) i += 1 # end of CheckCSC030017
def CheckCSC030029(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error, cpplines, fileErrorCount): '''如果做大括号{和右大括号}出现在一行,并且之间没有内容,请写在一起,不要留空格。[必须] Args: filename:文件名 file_extension:文件扩展名 clean_lines:Holds 3 copies of all lines with different preprocessing applied to them 1) elided member contains lines without strings and comments, 2) lines member contains lines without comments, and 3) raw_lines member contains all the lines without processing.(行首以/*开头的多行注释被替换成空白) rawlines:all the lines without processing nesting_state: Holds states related to parsing braces.(cpplint中的对象,暂时未使用) startLineNo:for,while,if,switch所在的行 ruleCheckKey:ruleid Error: error output method ''' lines = clean_lines.elided errMessage = 'Code Style Rule: If a left curly brace "{" is closely followed by a right curly brace "}", there should be no space between them.' i = 0 while i < clean_lines.NumLines(): # null line skip if common.IsBlankLine(lines[i]): i += 1 continue #define line skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue # line start with # skip if strcmp.Search(r'^\s*#', lines[i]): i += 1 continue # if no {, skip if lines[i].find('{') == -1: i += 1 continue # 查看是否存在{}中全是空格的情况 m = strcmp.Search(r'\{\s+\}', lines[i]) # 不存在{}中全是空格的情况,进入下次循环 if not m: i += 1 continue # 存在{}中全是空格的情况,需要检查rawlines[i],避免if(...) { /*1111111*/ }被误判 # 检查rawlines[i] --Start # 该行如果没有注释标识符/* 且 {...}中...全是空格,则报错 if rawlines[i].find('/*') == -1: Error(filename, lines, i, ruleCheckKey, 3, errMessage) j = cpplines[i].find("{") + 1 strTemp = "{" while j < len(cpplines[i]): if cpplines[i][j] == " ": strTemp += " " j += 1 elif cpplines[i][j] == "}": fileErrorCount[0] += 1 cpplines[i] = cpplines[i].replace(strTemp, "{") break else: break i += 1 continue # 因为lines中已经去掉多行注释了,为了避免if(...) { /*1111111*/ }被误判,需要检查rawlines m = strcmp.Search(r'\{\s+\}', rawlines[i]) # 不存在{}中全是空格的情况,进入下次循环 if not m: i += 1 continue startIndex = m.start() endIndex = m.end() inSingleQuotesblock = False inDoubleQuotesblock = False while startIndex != -1: # 判断{ }是否在两个单引号中间 singleQuotesQty = rawlines[i][0:startIndex].count("'") if singleQuotesQty % 2 == 1 and rawlines[i][startIndex:].count("'") > 0: inSingleQuotesblock = True if not inSingleQuotesblock: # 判断{ }是否在两个双引号中间 doubleQuotesQty = rawlines[i][0:startIndex].count('"') if doubleQuotesQty % 2 == 1 and rawlines[i][startIndex:].count('"') > 0: inDoubleQuotesblock = True # { }在两个单引号中间或者在两个双引号中间,需要查找下一个{ } if inSingleQuotesblock or inDoubleQuotesblock: pass # { }不是字符串中的字符 else: # 为了避免注释中的{ }情况被误判 # if(...) {} else { /*111 { }1111*/ } # if(...) {} else { /*1111111*/ } // { } # if(...) {} else { /*1111111*/ } /*1111111*/ /* { } singleCommentIndex = rawlines[i][0:startIndex].rfind('//') multiCommentOpenIndex = rawlines[i][0:startIndex].rfind('/*') multiCommentCloseIndex = rawlines[i][0:startIndex].rfind('*/') isComment = False if singleCommentIndex == -1 and multiCommentOpenIndex == -1: pass # if(...) {} else { /*1111111*/ } /*1111111*/ /* { } elif multiCommentOpenIndex > -1 and multiCommentOpenIndex > multiCommentCloseIndex: isComment =True # if(...) {} else { /*1111111*/ } /*1111111*/ // { } # if(...) {} else { /*1111111*/ } // /*1111111*/ { } # if(...) {} else { /*1111111*/ } // 2345345*/ { } elif singleCommentIndex > -1: if (multiCommentCloseIndex > -1 and singleCommentIndex > multiCommentCloseIndex) or \ (multiCommentOpenIndex > -1 and singleCommentIndex < multiCommentOpenIndex) or \ multiCommentOpenIndex == -1: isComment =True # if(...) {} else { /*1111111 # if(...) { } */ multiCommentOpenIndex = rawlines[i][startIndex:].find('/*') multiCommentCloseIndex = rawlines[i][startIndex:].find('*/') if not isComment and multiCommentCloseIndex > -1 and multiCommentCloseIndex < multiCommentOpenIndex: isComment = True # {}中全是空格且不是注释的情况,报错,不再check本行了,check下一行 if not isComment: Error(filename, lines, i, ruleCheckKey, 3, errMessage) j = cpplines[i].find("{") + 1 strTemp = "{" while j < len(cpplines[i]): if cpplines[i][j] == " ": strTemp += " " j += 1 elif cpplines[i][j] == "}": fileErrorCount[0] += 1 cpplines[i] = cpplines[i].replace(strTemp, "{") break else: break i += 1 startIndex = -1 continue # 查找下一个{ } m = strcmp.Search(r'\{\s+\}', rawlines[i][endIndex:]) if m: inSingleQuotesblock = False inDoubleQuotesblock = False startIndex = endIndex + m.start() endIndex = endIndex + m.end() continue # 查找不到下一个{ },不再检查本行了,去检查下一行 else: i += 1 startIndex = -1
def CheckCSC030028(filename, file_extension, clean_lines, rawlines, nesting_state, ruleCheckKey, Error, cpplines, fileErrorCount): '''右大括号}之前如果有内容,请保留一个空格。[必须] Args: filename:文件名 file_extension:文件扩展名 clean_lines:Holds 3 copies of all lines with different preprocessing applied to them 1) elided member contains lines without strings and comments, 2) lines member contains lines without comments, and 3) raw_lines member contains all the lines without processing.(行首以/*开头的多行注释被替换成空白) rawlines:all the lines without processing nesting_state: Holds states related to parsing braces.(cpplint中的对象,暂时未使用) startLineNo:for,while,if,switch所在的行 ruleCheckKey:ruleid Error: error output method ''' lines = clean_lines.elided errMessage = 'Code Style Rule: If there is contents before a right curly brace "}", please leave a space between them.' i = 0 while i < clean_lines.NumLines(): # null line skip if common.IsBlankLine(lines[i]): i += 1 continue #define line skip if strcmp.Search(r'^\s*#\s*define\s+', lines[i]): i = common.getDefineMacroEndLineNo(lines, i) + 1 continue # line start with # skip if strcmp.Search(r'^\s*#', lines[i]): i += 1 continue m = strcmp.Search(r'[^\s\{]\}', lines[i]) # 当 } 前面的字符不是空格,也不是{,则报错 if m: Error(filename, lines, i, ruleCheckKey, 3, errMessage) fileErrorCount[0] += 1 cpplines[i] = cpplines[i].replace("}", " }") i += 1 continue # 查看}前是否紧跟着多行注释标识符的*/ m = strcmp.Search(r'\*/\}', rawlines[i]) # 找不到这种情况,进入下次循环 if not m: i += 1 continue startIndex = m.start() endIndex = m.end() # */} 是//后面的注释内容则check下一行,不再check本行了 if rawlines[i][startIndex:].rfind('//') > -1: i += 1 continue inSingleQuotesblock = False inDoubleQuotesblock = False while startIndex != -1: # 判断*/}是否在两个单引号中间 singleQuotesQty = rawlines[i][0:startIndex].count("'") if singleQuotesQty % 2 == 1 and rawlines[i][startIndex:].count("'") > 0: inSingleQuotesblock = True if not inSingleQuotesblock: # 判断*/}是否在两个双引号中间 doubleQuotesQty = rawlines[i][0:startIndex].count('"') if doubleQuotesQty % 2 == 1 and rawlines[i][startIndex:].count('"') > 0: inDoubleQuotesblock = True # */}在两个单引号中间或者在两个双引号中间,需要查找下一个{ } if inSingleQuotesblock or inDoubleQuotesblock: # 查找下一个*/} m = strcmp.Search(r'\*/\}', rawlines[i][endIndex:]) if m: inSingleQuotesblock = False inDoubleQuotesblock = False startIndex = endIndex + m.start() endIndex = endIndex + m.end() # 查找不到下一个*/},不再检查本行了,去检查下一行 else: i += 1 startIndex = -1 # */}不是字符串中的字符 else: # */} 不是//后面的注释内容,则报错;如果是//后面的注释内容,则check下一行,不再check本行了 if rawlines[i][startIndex:].rfind('//') == -1: Error(filename, lines, i, ruleCheckKey, 3, errMessage) fileErrorCount[0] += 1 cpplines[i] = cpplines[i].replace("}", " }") i += 1 startIndex = -1