예제 #1
0
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
예제 #2
0
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
예제 #3
0
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
예제 #4
0
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
예제 #5
0
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
예제 #6
0
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
  
      
예제 #7
0
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
  
      
예제 #8
0
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
예제 #9
0
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
예제 #10
0
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
예제 #11
0
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