improve misra analysis perf for misra_5_4, misra_5_5, misra_20_1 (#2329)
fix bad indent
This commit is contained in:
parent
d75d9c1866
commit
a288ea3c1f
151
addons/misra.py
151
addons/misra.py
|
@ -32,7 +32,7 @@ except ImportError:
|
||||||
|
|
||||||
def grouped(iterable, n):
|
def grouped(iterable, n):
|
||||||
"""s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), (s2n,s2n+1,s2n+2,...s3n-1), ..."""
|
"""s -> (s0,s1,s2,...sn-1), (sn,sn+1,sn+2,...s2n-1), (s2n,s2n+1,s2n+2,...s3n-1), ..."""
|
||||||
return zip(*[iter(iterable)]*n)
|
return zip(*[iter(iterable)] * n)
|
||||||
|
|
||||||
|
|
||||||
typeBits = {
|
typeBits = {
|
||||||
|
@ -119,7 +119,7 @@ def getEssentialTypeCategory(expr):
|
||||||
# TODO this is incomplete
|
# TODO this is incomplete
|
||||||
e1 = getEssentialTypeCategory(expr.astOperand1)
|
e1 = getEssentialTypeCategory(expr.astOperand1)
|
||||||
e2 = getEssentialTypeCategory(expr.astOperand2)
|
e2 = getEssentialTypeCategory(expr.astOperand2)
|
||||||
#print('{0}: {1} {2}'.format(expr.str, e1, e2))
|
# print('{0}: {1} {2}'.format(expr.str, e1, e2))
|
||||||
if e1 and e2 and e1 == e2:
|
if e1 and e2 and e1 == e2:
|
||||||
return e1
|
return e1
|
||||||
if expr.valueType:
|
if expr.valueType:
|
||||||
|
@ -166,7 +166,8 @@ def getEssentialType(expr):
|
||||||
return typeToken.str
|
return typeToken.str
|
||||||
typeToken = typeToken.next
|
typeToken = typeToken.next
|
||||||
|
|
||||||
elif expr.astOperand1 and expr.astOperand2 and expr.str in ('+', '-', '*', '/', '%', '&', '|', '^', '>>', "<<", "?", ":"):
|
elif expr.astOperand1 and expr.astOperand2 and expr.str in (
|
||||||
|
'+', '-', '*', '/', '%', '&', '|', '^', '>>', "<<", "?", ":"):
|
||||||
if expr.astOperand1.valueType and expr.astOperand1.valueType.pointer > 0:
|
if expr.astOperand1.valueType and expr.astOperand1.valueType.pointer > 0:
|
||||||
return None
|
return None
|
||||||
if expr.astOperand2.valueType and expr.astOperand2.valueType.pointer > 0:
|
if expr.astOperand2.valueType and expr.astOperand2.valueType.pointer > 0:
|
||||||
|
@ -600,7 +601,6 @@ class Define:
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def getAddonRules():
|
def getAddonRules():
|
||||||
"""Returns dict of MISRA rules handled by this addon."""
|
"""Returns dict of MISRA rules handled by this addon."""
|
||||||
addon_rules = []
|
addon_rules = []
|
||||||
|
@ -762,17 +762,17 @@ class MisraChecker:
|
||||||
self.settings = settings
|
self.settings = settings
|
||||||
|
|
||||||
# Test validation rules lists
|
# Test validation rules lists
|
||||||
self.verify_expected = list()
|
self.verify_expected = list()
|
||||||
self.verify_actual = list()
|
self.verify_actual = list()
|
||||||
|
|
||||||
# List of formatted violation messages
|
# List of formatted violation messages
|
||||||
self.violations = dict()
|
self.violations = dict()
|
||||||
|
|
||||||
# if --rule-texts is specified this dictionary
|
# if --rule-texts is specified this dictionary
|
||||||
# is loaded with descriptions of each rule
|
# is loaded with descriptions of each rule
|
||||||
# by rule number (in hundreds).
|
# by rule number (in hundreds).
|
||||||
# ie rule 1.2 becomes 102
|
# ie rule 1.2 becomes 102
|
||||||
self.ruleTexts = dict()
|
self.ruleTexts = dict()
|
||||||
|
|
||||||
# Dictionary of dictionaries for rules to suppress
|
# Dictionary of dictionaries for rules to suppress
|
||||||
# Dict1 is keyed by rule number in the hundreds format of
|
# Dict1 is keyed by rule number in the hundreds format of
|
||||||
|
@ -782,7 +782,7 @@ class MisraChecker:
|
||||||
# or an item of None which indicates suppress rule for the entire file.
|
# or an item of None which indicates suppress rule for the entire file.
|
||||||
# The line and symbol name tuple may have None as either of its elements but
|
# The line and symbol name tuple may have None as either of its elements but
|
||||||
# should not be None for both.
|
# should not be None for both.
|
||||||
self.suppressedRules = dict()
|
self.suppressedRules = dict()
|
||||||
|
|
||||||
# List of suppression extracted from the dumpfile
|
# List of suppression extracted from the dumpfile
|
||||||
self.dumpfileSuppressions = None
|
self.dumpfileSuppressions = None
|
||||||
|
@ -791,7 +791,7 @@ class MisraChecker:
|
||||||
self.filePrefix = None
|
self.filePrefix = None
|
||||||
|
|
||||||
# Number of all violations suppressed per rule
|
# Number of all violations suppressed per rule
|
||||||
self.suppressionStats = dict()
|
self.suppressionStats = dict()
|
||||||
|
|
||||||
self.stdversion = stdversion
|
self.stdversion = stdversion
|
||||||
|
|
||||||
|
@ -964,57 +964,56 @@ class MisraChecker:
|
||||||
macro = {}
|
macro = {}
|
||||||
compile_name = re.compile(r'#define ([a-zA-Z0-9_]+)')
|
compile_name = re.compile(r'#define ([a-zA-Z0-9_]+)')
|
||||||
compile_param = re.compile(r'#define ([a-zA-Z0-9_]+)[(]([a-zA-Z0-9_, ]+)[)]')
|
compile_param = re.compile(r'#define ([a-zA-Z0-9_]+)[(]([a-zA-Z0-9_, ]+)[)]')
|
||||||
|
short_names = {}
|
||||||
|
macro_w_arg = []
|
||||||
for dir in data.directives:
|
for dir in data.directives:
|
||||||
res1 = compile_name.match(dir.str)
|
res1 = compile_name.match(dir.str)
|
||||||
if res1:
|
if res1:
|
||||||
if dir not in macro:
|
if dir not in macro:
|
||||||
macro.setdefault(dir, {})["name"] = []
|
macro.setdefault(dir, {})["name"] = []
|
||||||
macro.setdefault(dir, {})["params"] = []
|
macro.setdefault(dir, {})["params"] = []
|
||||||
macro[dir]["name"] = res1.group(1)
|
full_name = res1.group(1)
|
||||||
|
macro[dir]["name"] = full_name
|
||||||
|
short_name = full_name[:num_sign_chars]
|
||||||
|
if short_name in short_names:
|
||||||
|
_dir = short_names[short_name]
|
||||||
|
if full_name != macro[_dir]["name"]:
|
||||||
|
self.reportError(dir, 5, 4)
|
||||||
|
else:
|
||||||
|
short_names[short_name] = dir
|
||||||
res2 = compile_param.match(dir.str)
|
res2 = compile_param.match(dir.str)
|
||||||
if res2:
|
if res2:
|
||||||
res_gp2 = res2.group(2).split(",")
|
res_gp2 = res2.group(2).split(",")
|
||||||
res_gp2 = [macroname.replace(" ", "") for macroname in res_gp2]
|
res_gp2 = [macroname.replace(" ", "") for macroname in res_gp2]
|
||||||
macro[dir]["params"].extend(res_gp2)
|
macro[dir]["params"].extend(res_gp2)
|
||||||
for mvar in macro:
|
macro_w_arg.append(dir)
|
||||||
if len(macro[mvar]["params"]) > 0:
|
for mvar in macro_w_arg:
|
||||||
for i, macroparam1 in enumerate(macro[mvar]["params"]):
|
for i, macroparam1 in enumerate(macro[mvar]["params"]):
|
||||||
for j, macroparam2 in enumerate(macro[mvar]["params"]):
|
for j, macroparam2 in enumerate(macro[mvar]["params"]):
|
||||||
if j > i and macroparam1[:num_sign_chars] == macroparam2[:num_sign_chars]:
|
if j > i and macroparam1[:num_sign_chars] == macroparam2[:num_sign_chars]:
|
||||||
self.reportError(mvar, 5, 4)
|
self.reportError(mvar, 5, 4)
|
||||||
|
param = macroparam1
|
||||||
for x, m_var1 in enumerate(macro):
|
if param[:num_sign_chars] in short_names:
|
||||||
for y, m_var2 in enumerate(macro):
|
m_var1 = short_names[param[:num_sign_chars]]
|
||||||
if x < y and macro[m_var1]["name"] != macro[m_var2]["name"] and \
|
if m_var1.linenr > mvar.linenr:
|
||||||
macro[m_var1]["name"][:num_sign_chars] == macro[m_var2]["name"][:num_sign_chars]:
|
|
||||||
if m_var1.linenr > m_var2.linenr:
|
|
||||||
self.reportError(m_var1, 5, 4)
|
self.reportError(m_var1, 5, 4)
|
||||||
else:
|
else:
|
||||||
self.reportError(m_var2, 5, 4)
|
self.reportError(mvar, 5, 4)
|
||||||
for param in macro[m_var2]["params"]:
|
|
||||||
if macro[m_var1]["name"][:num_sign_chars] == param[:num_sign_chars]:
|
|
||||||
if m_var1.linenr > m_var2.linenr:
|
|
||||||
self.reportError(m_var1, 5, 4)
|
|
||||||
else:
|
|
||||||
self.reportError(m_var2, 5, 4)
|
|
||||||
|
|
||||||
def misra_5_5(self, data):
|
def misra_5_5(self, data):
|
||||||
num_sign_chars = self.get_num_significant_naming_chars(data)
|
num_sign_chars = self.get_num_significant_naming_chars(data)
|
||||||
macroNames = []
|
macroNames = {}
|
||||||
compiled = re.compile(r'#define ([A-Za-z0-9_]+)')
|
compiled = re.compile(r'#define ([A-Za-z0-9_]+)')
|
||||||
for dir in data.directives:
|
for dir in data.directives:
|
||||||
res = compiled.match(dir.str)
|
res = compiled.match(dir.str)
|
||||||
if res:
|
if res:
|
||||||
macroNames.append(res.group(1))
|
macroNames[res.group(1)[:num_sign_chars]] = dir
|
||||||
for var in data.variables:
|
for var in data.variables:
|
||||||
for macro in macroNames:
|
if var.nameToken and var.nameToken.str[:num_sign_chars] in macroNames:
|
||||||
if var.nameToken is not None:
|
self.reportError(var.nameToken, 5, 5)
|
||||||
if var.nameToken.str[:num_sign_chars] == macro[:num_sign_chars]:
|
|
||||||
self.reportError(var.nameToken, 5, 5)
|
|
||||||
for scope in data.scopes:
|
for scope in data.scopes:
|
||||||
for macro in macroNames:
|
if scope.className and scope.className[:num_sign_chars] in macroNames:
|
||||||
if scope.className and scope.className[:num_sign_chars] == macro[:num_sign_chars]:
|
self.reportError(scope.bodyStart, 5, 5)
|
||||||
self.reportError(scope.bodyStart, 5, 5)
|
|
||||||
|
|
||||||
def misra_7_1(self, rawTokens):
|
def misra_7_1(self, rawTokens):
|
||||||
compiled = re.compile(r'^0[0-7]+$')
|
compiled = re.compile(r'^0[0-7]+$')
|
||||||
|
@ -1073,8 +1072,8 @@ class MisraChecker:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
for t1, t2 in itertools.product(
|
for t1, t2 in itertools.product(
|
||||||
list(getTernaryOperandsRecursive(token.astOperand1) or [token.astOperand1]),
|
list(getTernaryOperandsRecursive(token.astOperand1) or [token.astOperand1]),
|
||||||
list(getTernaryOperandsRecursive(token.astOperand2) or [token.astOperand2]),
|
list(getTernaryOperandsRecursive(token.astOperand2) or [token.astOperand2]),
|
||||||
):
|
):
|
||||||
e1 = getEssentialTypeCategory(t1)
|
e1 = getEssentialTypeCategory(t1)
|
||||||
e2 = getEssentialTypeCategory(t2)
|
e2 = getEssentialTypeCategory(t2)
|
||||||
|
@ -1199,11 +1198,11 @@ class MisraChecker:
|
||||||
if vt1.type == 'void' or vt2.type == 'void':
|
if vt1.type == 'void' or vt2.type == 'void':
|
||||||
continue
|
continue
|
||||||
if (vt1.pointer > 0 and vt1.type == 'record' and
|
if (vt1.pointer > 0 and vt1.type == 'record' and
|
||||||
vt2.pointer > 0 and vt2.type == 'record' and
|
vt2.pointer > 0 and vt2.type == 'record' and
|
||||||
vt1.typeScopeId != vt2.typeScopeId):
|
vt1.typeScopeId != vt2.typeScopeId):
|
||||||
self.reportError(token, 11, 3)
|
self.reportError(token, 11, 3)
|
||||||
elif (vt1.pointer == vt2.pointer and vt1.pointer > 0 and
|
elif (vt1.pointer == vt2.pointer and vt1.pointer > 0 and
|
||||||
vt1.type != vt2.type and vt1.type != 'char'):
|
vt1.type != vt2.type and vt1.type != 'char'):
|
||||||
self.reportError(token, 11, 3)
|
self.reportError(token, 11, 3)
|
||||||
|
|
||||||
def misra_11_4(self, data):
|
def misra_11_4(self, data):
|
||||||
|
@ -1216,7 +1215,7 @@ class MisraChecker:
|
||||||
continue
|
continue
|
||||||
if vt2.pointer > 0 and vt1.pointer == 0 and (vt1.isIntegral() or vt1.isEnum()) and vt2.type != 'void':
|
if vt2.pointer > 0 and vt1.pointer == 0 and (vt1.isIntegral() or vt1.isEnum()) and vt2.type != 'void':
|
||||||
self.reportError(token, 11, 4)
|
self.reportError(token, 11, 4)
|
||||||
elif vt1.pointer > 0 and vt2.pointer == 0 and (vt2.isIntegral() or vt2.isEnum())and vt1.type != 'void':
|
elif vt1.pointer > 0 and vt2.pointer == 0 and (vt2.isIntegral() or vt2.isEnum()) and vt1.type != 'void':
|
||||||
self.reportError(token, 11, 4)
|
self.reportError(token, 11, 4)
|
||||||
|
|
||||||
def misra_11_5(self, data):
|
def misra_11_5(self, data):
|
||||||
|
@ -1230,7 +1229,8 @@ class MisraChecker:
|
||||||
if vt1.pointer > 0 and vt1.type != 'void' and vt2.pointer == vt1.pointer and vt2.type == 'void':
|
if vt1.pointer > 0 and vt1.type != 'void' and vt2.pointer == vt1.pointer and vt2.type == 'void':
|
||||||
self.reportError(token, 11, 5)
|
self.reportError(token, 11, 5)
|
||||||
continue
|
continue
|
||||||
if token.astOperand1.astOperand1 and token.astOperand1.astOperand1.str in ('malloc', 'calloc', 'realloc', 'free'):
|
if token.astOperand1.astOperand1 and token.astOperand1.astOperand1.str in (
|
||||||
|
'malloc', 'calloc', 'realloc', 'free'):
|
||||||
continue
|
continue
|
||||||
vt1 = token.valueType
|
vt1 = token.valueType
|
||||||
vt2 = token.astOperand1.valueType
|
vt2 = token.astOperand1.valueType
|
||||||
|
@ -1269,8 +1269,8 @@ class MisraChecker:
|
||||||
vt1.type != 'void'):
|
vt1.type != 'void'):
|
||||||
self.reportError(token, 11, 7)
|
self.reportError(token, 11, 7)
|
||||||
elif (vt1.pointer > 0 and vt2.pointer == 0 and
|
elif (vt1.pointer > 0 and vt2.pointer == 0 and
|
||||||
not vt2.isIntegral() and not vt2.isEnum() and
|
not vt2.isIntegral() and not vt2.isEnum() and
|
||||||
vt1.type != 'void'):
|
vt1.type != 'void'):
|
||||||
self.reportError(token, 11, 7)
|
self.reportError(token, 11, 7)
|
||||||
|
|
||||||
def misra_11_8(self, data):
|
def misra_11_8(self, data):
|
||||||
|
@ -1462,7 +1462,6 @@ class MisraChecker:
|
||||||
if state == STATE_CHECK and tok.str == ',':
|
if state == STATE_CHECK and tok.str == ',':
|
||||||
self.reportError(tok, 12, 3)
|
self.reportError(tok, 12, 3)
|
||||||
|
|
||||||
|
|
||||||
def misra_12_4(self, data):
|
def misra_12_4(self, data):
|
||||||
if typeBits['INT'] == 16:
|
if typeBits['INT'] == 16:
|
||||||
max_uint = 0xffff
|
max_uint = 0xffff
|
||||||
|
@ -1583,7 +1582,6 @@ class MisraChecker:
|
||||||
self.reportError(tn, 14, 2)
|
self.reportError(tn, 14, 2)
|
||||||
tn = tn.next
|
tn = tn.next
|
||||||
|
|
||||||
|
|
||||||
def misra_14_4(self, data):
|
def misra_14_4(self, data):
|
||||||
for token in data.tokenlist:
|
for token in data.tokenlist:
|
||||||
if token.str != '(':
|
if token.str != '(':
|
||||||
|
@ -1697,10 +1695,10 @@ class MisraChecker:
|
||||||
self.reportError(token, 16, 2)
|
self.reportError(token, 16, 2)
|
||||||
|
|
||||||
def misra_16_3(self, rawTokens):
|
def misra_16_3(self, rawTokens):
|
||||||
STATE_NONE = 0 # default state, not in switch case/default block
|
STATE_NONE = 0 # default state, not in switch case/default block
|
||||||
STATE_BREAK = 1 # break/comment is seen but not its ';'
|
STATE_BREAK = 1 # break/comment is seen but not its ';'
|
||||||
STATE_OK = 2 # a case/default is allowed (we have seen 'break;'/'comment'/'{'/attribute)
|
STATE_OK = 2 # a case/default is allowed (we have seen 'break;'/'comment'/'{'/attribute)
|
||||||
STATE_SWITCH = 3 # walking through switch statement scope
|
STATE_SWITCH = 3 # walking through switch statement scope
|
||||||
|
|
||||||
state = STATE_NONE
|
state = STATE_NONE
|
||||||
end_swtich_token = None # end '}' for the switch scope
|
end_swtich_token = None # end '}' for the switch scope
|
||||||
|
@ -1805,7 +1803,8 @@ class MisraChecker:
|
||||||
|
|
||||||
def misra_17_1(self, data):
|
def misra_17_1(self, data):
|
||||||
for token in data.tokenlist:
|
for token in data.tokenlist:
|
||||||
if isFunctionCall(token) and token.astOperand1.str in ('va_list', 'va_arg', 'va_start', 'va_end', 'va_copy'):
|
if isFunctionCall(token) and token.astOperand1.str in (
|
||||||
|
'va_list', 'va_arg', 'va_start', 'va_end', 'va_copy'):
|
||||||
self.reportError(token, 17, 1)
|
self.reportError(token, 17, 1)
|
||||||
elif token.str == 'va_list':
|
elif token.str == 'va_list':
|
||||||
self.reportError(token, 17, 1)
|
self.reportError(token, 17, 1)
|
||||||
|
@ -1953,15 +1952,20 @@ class MisraChecker:
|
||||||
self.reportError(token, 19, 2)
|
self.reportError(token, 19, 2)
|
||||||
|
|
||||||
def misra_20_1(self, data):
|
def misra_20_1(self, data):
|
||||||
|
token_in_file = {}
|
||||||
|
for token in data.tokenlist:
|
||||||
|
if token.file not in token_in_file:
|
||||||
|
token_in_file[token.file] = int(token.linenr)
|
||||||
|
else:
|
||||||
|
token_in_file[token.file] = min(token_in_file[token.file], int(token.linenr))
|
||||||
|
|
||||||
for directive in data.directives:
|
for directive in data.directives:
|
||||||
if not directive.str.startswith('#include'):
|
if not directive.str.startswith('#include'):
|
||||||
continue
|
continue
|
||||||
for token in data.tokenlist:
|
if directive.file not in token_in_file:
|
||||||
if token.file != directive.file:
|
continue
|
||||||
continue
|
if token_in_file[directive.file] < int(directive.linenr):
|
||||||
if int(token.linenr) < int(directive.linenr):
|
self.reportError(directive, 20, 1)
|
||||||
self.reportError(directive, 20, 1)
|
|
||||||
break
|
|
||||||
|
|
||||||
def misra_20_2(self, data):
|
def misra_20_2(self, data):
|
||||||
for directive in data.directives:
|
for directive in data.directives:
|
||||||
|
@ -2044,7 +2048,7 @@ class MisraChecker:
|
||||||
if mo:
|
if mo:
|
||||||
dir = mo.group(1)
|
dir = mo.group(1)
|
||||||
if dir not in ['define', 'elif', 'else', 'endif', 'error', 'if', 'ifdef', 'ifndef', 'include',
|
if dir not in ['define', 'elif', 'else', 'endif', 'error', 'if', 'ifdef', 'ifndef', 'include',
|
||||||
'pragma', 'undef', 'warning']:
|
'pragma', 'undef', 'warning']:
|
||||||
self.reportError(directive, 20, 13)
|
self.reportError(directive, 20, 13)
|
||||||
|
|
||||||
def misra_20_14(self, data):
|
def misra_20_14(self, data):
|
||||||
|
@ -2052,7 +2056,8 @@ class MisraChecker:
|
||||||
# the size increases when there are inner #if directives.
|
# the size increases when there are inner #if directives.
|
||||||
ifStack = []
|
ifStack = []
|
||||||
for directive in data.directives:
|
for directive in data.directives:
|
||||||
if directive.str.startswith('#if ') or directive.str.startswith('#ifdef ') or directive.str.startswith('#ifndef '):
|
if directive.str.startswith('#if ') or directive.str.startswith('#ifdef ') or directive.str.startswith(
|
||||||
|
'#ifndef '):
|
||||||
ifStack.append(directive)
|
ifStack.append(directive)
|
||||||
elif directive.str == '#else' or directive.str.startswith('#elif '):
|
elif directive.str == '#else' or directive.str.startswith('#elif '):
|
||||||
if len(ifStack) == 0:
|
if len(ifStack) == 0:
|
||||||
|
@ -2191,9 +2196,9 @@ class MisraChecker:
|
||||||
return self.violations.keys()
|
return self.violations.keys()
|
||||||
|
|
||||||
def addSuppressedRule(self, ruleNum,
|
def addSuppressedRule(self, ruleNum,
|
||||||
fileName = None,
|
fileName=None,
|
||||||
lineNumber = None,
|
lineNumber=None,
|
||||||
symbolName = None):
|
symbolName=None):
|
||||||
"""
|
"""
|
||||||
Add a suppression to the suppressions data structure
|
Add a suppression to the suppressions data structure
|
||||||
|
|
||||||
|
@ -2384,7 +2389,8 @@ class MisraChecker:
|
||||||
else:
|
else:
|
||||||
item_str = str(item[0])
|
item_str = str(item[0])
|
||||||
|
|
||||||
outlist.append("%s: %s: %s (%d locations suppressed)" % (float(ruleNum)/100, fname, item_str, self.suppressionStats.get(ruleNum, 0)))
|
outlist.append("%s: %s: %s (%d locations suppressed)" % (
|
||||||
|
float(ruleNum) / 100, fname, item_str, self.suppressionStats.get(ruleNum, 0)))
|
||||||
|
|
||||||
for line in sorted(outlist, reverse=True):
|
for line in sorted(outlist, reverse=True):
|
||||||
print(" %s" % line)
|
print(" %s" % line)
|
||||||
|
@ -2408,7 +2414,7 @@ class MisraChecker:
|
||||||
if res:
|
if res:
|
||||||
num1 = int(res.group(1))
|
num1 = int(res.group(1))
|
||||||
num2 = int(res.group(2))
|
num2 = int(res.group(2))
|
||||||
ruleNum = (num1*100)+num2
|
ruleNum = (num1 * 100) + num2
|
||||||
|
|
||||||
self.addSuppressedRule(ruleNum)
|
self.addSuppressedRule(ruleNum)
|
||||||
|
|
||||||
|
@ -2476,7 +2482,7 @@ class MisraChecker:
|
||||||
|
|
||||||
rule = None
|
rule = None
|
||||||
have_severity = False
|
have_severity = False
|
||||||
severity_loc = 0
|
severity_loc = 0
|
||||||
|
|
||||||
for line in file_stream:
|
for line in file_stream:
|
||||||
|
|
||||||
|
@ -2730,7 +2736,9 @@ def get_args():
|
||||||
"""Generates list of command-line arguments acceptable by misra.py script."""
|
"""Generates list of command-line arguments acceptable by misra.py script."""
|
||||||
parser = cppcheckdata.ArgumentParser()
|
parser = cppcheckdata.ArgumentParser()
|
||||||
parser.add_argument("--rule-texts", type=str, help=RULE_TEXTS_HELP)
|
parser.add_argument("--rule-texts", type=str, help=RULE_TEXTS_HELP)
|
||||||
parser.add_argument("--verify-rule-texts", help="Verify that all supported rules texts are present in given file and exit.", action="store_true")
|
parser.add_argument("--verify-rule-texts",
|
||||||
|
help="Verify that all supported rules texts are present in given file and exit.",
|
||||||
|
action="store_true")
|
||||||
parser.add_argument("--suppress-rules", type=str, help=SUPPRESS_RULES_HELP)
|
parser.add_argument("--suppress-rules", type=str, help=SUPPRESS_RULES_HELP)
|
||||||
parser.add_argument("--no-summary", help="Hide summary of violations", action="store_true")
|
parser.add_argument("--no-summary", help="Hide summary of violations", action="store_true")
|
||||||
parser.add_argument("--show-suppressed-rules", help="Print rule suppression list", action="store_true")
|
parser.add_argument("--show-suppressed-rules", help="Print rule suppression list", action="store_true")
|
||||||
|
@ -2781,7 +2789,7 @@ def main():
|
||||||
|
|
||||||
if settings.verify:
|
if settings.verify:
|
||||||
verify_expected = checker.get_verify_expected()
|
verify_expected = checker.get_verify_expected()
|
||||||
verify_actual = checker.get_verify_actual()
|
verify_actual = checker.get_verify_actual()
|
||||||
|
|
||||||
for expected in verify_expected:
|
for expected in verify_expected:
|
||||||
if expected not in verify_actual:
|
if expected not in verify_actual:
|
||||||
|
@ -2808,7 +2816,8 @@ def main():
|
||||||
|
|
||||||
if settings.show_summary:
|
if settings.show_summary:
|
||||||
print("\nMISRA rules violations found:\n\t%s\n" % (
|
print("\nMISRA rules violations found:\n\t%s\n" % (
|
||||||
"\n\t".join(["%s: %d" % (viol, len(checker.get_violations(viol))) for viol in checker.get_violation_types()])))
|
"\n\t".join(["%s: %d" % (viol, len(checker.get_violations(viol))) for viol in
|
||||||
|
checker.get_violation_types()])))
|
||||||
|
|
||||||
rules_violated = {}
|
rules_violated = {}
|
||||||
for severity, ids in checker.get_violations():
|
for severity, ids in checker.get_violations():
|
||||||
|
@ -2816,7 +2825,7 @@ def main():
|
||||||
rules_violated[misra_id] = rules_violated.get(misra_id, 0) + 1
|
rules_violated[misra_id] = rules_violated.get(misra_id, 0) + 1
|
||||||
print("MISRA rules violated:")
|
print("MISRA rules violated:")
|
||||||
convert = lambda text: int(text) if text.isdigit() else text
|
convert = lambda text: int(text) if text.isdigit() else text
|
||||||
misra_sort = lambda key: [ convert(c) for c in re.split(r'[\.-]([0-9]*)', key) ]
|
misra_sort = lambda key: [convert(c) for c in re.split(r'[\.-]([0-9]*)', key)]
|
||||||
for misra_id in sorted(rules_violated.keys(), key=misra_sort):
|
for misra_id in sorted(rules_violated.keys(), key=misra_sort):
|
||||||
res = re.match(r'misra-c2012-([0-9]+)\\.([0-9]+)', misra_id)
|
res = re.match(r'misra-c2012-([0-9]+)\\.([0-9]+)', misra_id)
|
||||||
if res is None:
|
if res is None:
|
||||||
|
|
Loading…
Reference in New Issue