MISRA - support for per file/line error suppression (#1275)

* cppcheckdata.py: fixed Suppression.isMatch method

* cppcheckdata.py: fixed parsing <suppressions> tag

* misra.py: now uses cppcheckdata.reportError and supports suppressions
This commit is contained in:
Konrad Grochowski 2018-06-04 21:50:21 +02:00 committed by Daniel Marjamäki
parent 74b18d7fd9
commit 0c6d60d202
2 changed files with 24 additions and 13 deletions

View File

@ -483,14 +483,14 @@ class Suppression:
self.lineNumber = element.get('lineNumber') self.lineNumber = element.get('lineNumber')
self.symbolName = element.get('symbolName') self.symbolName = element.get('symbolName')
def isMatch(file, line, message, errorId): def isMatch(self, file, line, message, errorId):
if (fnmatch(file, self.fileName) if (fnmatch(file, self.fileName)
and (self.lineNumber is None or line == self.lineNumber) and (self.lineNumber is None or line == self.lineNumber)
and fnmatch(message, '*'+self.symbolName+'*') and (self.symbolName is None or fnmatch(message, '*'+self.symbolName+'*'))
and fnmatch(errorId, self.errorId)): and fnmatch(errorId, self.errorId)):
return true return True
else: else:
return false return False
class Configuration: class Configuration:
""" """
@ -506,7 +506,6 @@ class Configuration:
functions List of Function items functions List of Function items
variables List of Variable items variables List of Variable items
valueflow List of ValueFlow values valueflow List of ValueFlow values
suppressions List of warning suppressions
""" """
name = '' name = ''
@ -516,7 +515,6 @@ class Configuration:
functions = [] functions = []
variables = [] variables = []
valueflow = [] valueflow = []
suppressions = []
def __init__(self, confignode): def __init__(self, confignode):
self.name = confignode.get('cfg') self.name = confignode.get('cfg')
@ -526,7 +524,6 @@ class Configuration:
self.functions = [] self.functions = []
self.variables = [] self.variables = []
self.valueflow = [] self.valueflow = []
self.suppressions = []
arguments = [] arguments = []
for element in confignode: for element in confignode:
@ -562,9 +559,6 @@ class Configuration:
if element.tag == 'valueflow': if element.tag == 'valueflow':
for values in element: for values in element:
self.valueflow.append(ValueFlow(values)) self.valueflow.append(ValueFlow(values))
if element.tag == "suppressions":
for suppression in element:
self.suppressions.append(Suppression(suppression))
IdMap = {None: None, '0': None, '00000000': None, '0000000000000000': None} IdMap = {None: None, '0': None, '00000000': None, '0000000000000000': None}
for token in self.tokenlist: for token in self.tokenlist:
@ -664,6 +658,7 @@ class CppcheckData:
rawTokens = [] rawTokens = []
platform = None platform = None
configurations = [] configurations = []
suppressions = []
def __init__(self, filename): def __init__(self, filename):
self.configurations = [] self.configurations = []
@ -689,6 +684,13 @@ class CppcheckData:
self.rawTokens[i + 1].previous = self.rawTokens[i] self.rawTokens[i + 1].previous = self.rawTokens[i]
self.rawTokens[i].next = self.rawTokens[i + 1] self.rawTokens[i].next = self.rawTokens[i + 1]
for suppressionsNode in data.getroot():
if suppressionsNode.tag == "suppressions":
for suppression in suppressionsNode:
self.suppressions.append(Suppression(suppression))
# root is 'dumps' node, each config has its own 'dump' subnode. # root is 'dumps' node, each config has its own 'dump' subnode.
for cfgnode in data.getroot(): for cfgnode in data.getroot():
if cfgnode.tag == 'dump': if cfgnode.tag == 'dump':

View File

@ -23,6 +23,7 @@ import argparse
ruleTexts = {} ruleTexts = {}
suppressRules = {} suppressRules = {}
suppressions = None
typeBits = { typeBits = {
'CHAR': None, 'CHAR': None,
'SHORT': None, 'SHORT': None,
@ -60,9 +61,14 @@ def reportError(location, num1, num2):
errmsg = 'misra violation (use --rule-texts=<file> to get proper output) [' + id + ']' errmsg = 'misra violation (use --rule-texts=<file> to get proper output) [' + id + ']'
else: else:
return return
sys.stderr.write('[' + location.file + ':' + str(location.linenr) + '] (style): ' + errmsg + '\n') if not cppcheckdata.reportError('[{file}:{line}] {severity}: {message}',
callstack=[(location.file, location.linenr)],
VIOLATIONS.append(errmsg) severity='style',
message = errmsg,
errorId = id,
suppressions = suppressions,
outputFunc = sys.stderr.write) is None:
VIOLATIONS.append(errmsg)
def simpleMatch(token, pattern): def simpleMatch(token, pattern):
@ -1700,6 +1706,9 @@ def parseDump(dumpfile):
data = cppcheckdata.parsedump(dumpfile) data = cppcheckdata.parsedump(dumpfile)
global suppressions
suppressions = data.suppressions
typeBits['CHAR'] = data.platform.char_bit typeBits['CHAR'] = data.platform.char_bit
typeBits['SHORT'] = data.platform.short_bit typeBits['SHORT'] = data.platform.short_bit
typeBits['INT'] = data.platform.int_bit typeBits['INT'] = data.platform.int_bit