cppcheckdata.py: reformat documentation
This commit is contained in:
parent
07b43c6929
commit
8c8ad96fe5
|
@ -1,33 +1,35 @@
|
|||
## @mainpage cppcheckdata
|
||||
#
|
||||
# @brief This is a Python module that helps you access Cppcheck dump data.<br><br>
|
||||
#
|
||||
# License: No restrictions, use this as you need.<br><br>
|
||||
#
|
||||
"""
|
||||
cppcheckdata
|
||||
|
||||
This is a Python module that helps you access Cppcheck dump data.
|
||||
|
||||
License: No restrictions, use this as you need.
|
||||
"""
|
||||
|
||||
import xml.etree.ElementTree as ET
|
||||
import argparse
|
||||
|
||||
## Directive class. Contains information about each preprocessor directive in the source code.
|
||||
#
|
||||
# file and linenr denote the location where the directive is defined.
|
||||
#
|
||||
# To iterate through all directives use such code:
|
||||
# @code
|
||||
# data = cppcheckdata.parsedump(...)
|
||||
# for cfg in data.configurations:
|
||||
# for directive in cfg.directives:
|
||||
# print(directive.str)
|
||||
# @endcode
|
||||
#
|
||||
|
||||
|
||||
class Directive:
|
||||
## The directive line, with all C or C++ comments removed
|
||||
"""
|
||||
Directive class. Contains information about each preprocessor directive in the source code.
|
||||
|
||||
Attributes:
|
||||
str The directive line, with all C or C++ comments removed
|
||||
file Name of (possibly included) file where directive is defined
|
||||
linenr Line number in (possibly included) file where directive is defined
|
||||
|
||||
To iterate through all directives use such code:
|
||||
@code
|
||||
data = cppcheckdata.parsedump(...)
|
||||
for cfg in data.configurations:
|
||||
for directive in cfg.directives:
|
||||
print(directive.str)
|
||||
@endcode
|
||||
"""
|
||||
|
||||
str = None
|
||||
## name of (possibly included) file where directive is defined
|
||||
file = None
|
||||
## line number in (possibly included) file where directive is defined
|
||||
linenr = None
|
||||
|
||||
def __init__(self, element):
|
||||
|
@ -36,152 +38,97 @@ class Directive:
|
|||
self.linenr = element.get('linenr')
|
||||
|
||||
|
||||
## Token class. Contains information about each token in the source code.
|
||||
#
|
||||
# The CppcheckData.tokenlist is a list of Token items
|
||||
#
|
||||
# C++ class: http://cppcheck.net/devinfo/doxyoutput/classToken.html
|
||||
#
|
||||
# To iterate through all tokens use such code:
|
||||
# @code
|
||||
# data = cppcheckdata.parsedump(...)
|
||||
# for cfg in data.configurations:
|
||||
# code = ''
|
||||
# for token in cfg.tokenlist:
|
||||
# code = code + token.str + ' '
|
||||
# print(code)
|
||||
# @endcode
|
||||
#
|
||||
|
||||
|
||||
class Token:
|
||||
"""
|
||||
Token class. Contains information about each token in the source code.
|
||||
|
||||
The CppcheckData.tokenlist is a list of Token items
|
||||
|
||||
C++ class: http://cppcheck.net/devinfo/doxyoutput/classToken.html
|
||||
|
||||
Attributes:
|
||||
str Token string
|
||||
next Next token in tokenlist. For last token, next is None.
|
||||
previous Previous token in tokenlist. For first token, previous is None.
|
||||
link Linked token in tokenlist. Each '(', '[' and '{' are linked to the
|
||||
corresponding '}', ']' and ')'. For templates, the '<' is linked to
|
||||
the corresponding '>'.
|
||||
scope Scope information for this token. See the Scope class.
|
||||
isName Is this token a symbol name
|
||||
isNumber Is this token a number, for example 123, 12.34
|
||||
isInt Is this token a int value such as 1234
|
||||
isFloat Is this token a int value such as 12.34
|
||||
isString Is this token a string literal such as "hello"
|
||||
strlen string length for string literal
|
||||
isChar Is this token a char literal such as 'x'
|
||||
isOp Is this token a operator
|
||||
isArithmeticalOp Is this token a arithmetic operator
|
||||
isAssignmentOp Is this token a assignment operator
|
||||
isComparisonOp Is this token a comparison operator
|
||||
isLogicalOp Is this token a logical operator: && ||
|
||||
varId varId for token, each variable has a unique non-zero id
|
||||
variable Variable information for this token. See the Variable class.
|
||||
function If this token points at a function call, this attribute has the Function
|
||||
information. See the Function class.
|
||||
values Possible values of token
|
||||
typeScope type scope (token->type()->classScope)
|
||||
astParent ast parent
|
||||
astOperand1 ast operand1
|
||||
astOperand2 ast operand2
|
||||
file file name
|
||||
linenr line number
|
||||
|
||||
To iterate through all tokens use such code:
|
||||
@code
|
||||
data = cppcheckdata.parsedump(...)
|
||||
for cfg in data.configurations:
|
||||
code = ''
|
||||
for token in cfg.tokenlist:
|
||||
code = code + token.str + ' '
|
||||
print(code)
|
||||
@endcode
|
||||
"""
|
||||
|
||||
|
||||
Id = None
|
||||
## Token string
|
||||
str = None
|
||||
## Next token in tokenlist. For last token, next is None.
|
||||
next = None
|
||||
## Previous token in tokenlist. For first token, previous is None,
|
||||
previous = None
|
||||
linkId = None
|
||||
## Linked token in tokenlist. Each '(', '[' and '{' are linked to the
|
||||
# corresponding '}', ']' and ')'. For templates, the '<' is linked to
|
||||
# the corresponding '>'.
|
||||
link = None
|
||||
scopeId = None
|
||||
## Scope information for this token. See the Scope class.
|
||||
scope = None
|
||||
## Is this token a symbol name
|
||||
isName = False
|
||||
## Is this token a number, for example 123, 12.34
|
||||
isNumber = False
|
||||
## Is this token a int value such as 1234
|
||||
isInt = False
|
||||
## Is this token a int value such as 12.34
|
||||
isFloat = False
|
||||
## Is this token a string literal such as "hello"
|
||||
isString = False
|
||||
## string length for string literal
|
||||
strlen = None
|
||||
## Is this token a char literal such as 'x'
|
||||
isChar = False
|
||||
## Is this token a operator
|
||||
isOp = False
|
||||
## Is this token a arithmetic operator
|
||||
isArithmeticalOp = False
|
||||
## Is this token a assignment operator
|
||||
isAssignmentOp = False
|
||||
## Is this token a comparison operator
|
||||
isComparisonOp = False
|
||||
## Is this token a logical operator: && ||
|
||||
isLogicalOp = False
|
||||
## varId for token, each variable has a unique non-zero id
|
||||
varId = None
|
||||
variableId = None
|
||||
## Variable information for this token. See the Variable class.
|
||||
#
|
||||
# Example code:
|
||||
# @code
|
||||
# data = cppcheckdata.parsedump(...)
|
||||
# code = ''
|
||||
# for token in data.tokenlist:
|
||||
# code = code + token.str
|
||||
# if token.variable:
|
||||
# if token.variable.isLocal:
|
||||
# code = code + ':localvar'
|
||||
# if token.variable.isArgument:
|
||||
# code = code + ':arg'
|
||||
# code = code + ' '
|
||||
# print(code)
|
||||
# @endcode
|
||||
variable = None
|
||||
functionId = None
|
||||
## If this token points at a function call, this attribute has the Function
|
||||
# information. See the Function class.
|
||||
function = None
|
||||
valuesId = None
|
||||
## Possible values of token
|
||||
#
|
||||
# Example code:
|
||||
# @code
|
||||
# data = cppcheckdata.parsedump(...)
|
||||
# code = ''
|
||||
# for token in data.tokenlist:
|
||||
# code = code + token.str
|
||||
# if token.values:
|
||||
# # print values..
|
||||
# code = code + '{'
|
||||
# for value in token.values:
|
||||
# if value.intvalue:
|
||||
# code = code + str(value.intvalue) + ' '
|
||||
# code = code + '}'
|
||||
# code = code + ' '
|
||||
# print(code)
|
||||
# @endcode
|
||||
values = None
|
||||
|
||||
typeScopeId = None
|
||||
## type scope (token->type()->classScope)
|
||||
typeScope = None
|
||||
|
||||
astParentId = None
|
||||
## syntax tree parent
|
||||
astParent = None
|
||||
astOperand1Id = None
|
||||
## syntax tree operand1
|
||||
#
|
||||
# Example code:
|
||||
# @code
|
||||
# data = cppcheckdata.parsedump(...)
|
||||
# for token in data.tokenlist:
|
||||
#
|
||||
# # is this a addition?
|
||||
# if token.str == '+':
|
||||
#
|
||||
# # print LHS operand
|
||||
# print(token.astOperand1.str)
|
||||
#
|
||||
# @endcode
|
||||
astOperand1 = None
|
||||
astOperand2Id = None
|
||||
## syntax tree operand2
|
||||
#
|
||||
# Example code:
|
||||
# @code
|
||||
# data = cppcheckdata.parsedump(...)
|
||||
# for token in data.tokenlist:
|
||||
#
|
||||
# # is this a division?
|
||||
# if token.str == '/':
|
||||
#
|
||||
# # print RHS operand
|
||||
# print(token.astOperand2.str)
|
||||
#
|
||||
# @endcode
|
||||
astOperand2 = None
|
||||
|
||||
## file name
|
||||
file = None
|
||||
## line number
|
||||
linenr = None
|
||||
|
||||
def __init__(self, element):
|
||||
|
@ -246,9 +193,12 @@ class Token:
|
|||
self.astOperand1 = IdMap[self.astOperand1Id]
|
||||
self.astOperand2 = IdMap[self.astOperand2Id]
|
||||
|
||||
## Get value if it exists
|
||||
# Returns None if it doesn't exist
|
||||
def getValue(self, v):
|
||||
"""
|
||||
Get value if it exists
|
||||
Returns None if it doesn't exist
|
||||
"""
|
||||
|
||||
if not self.values:
|
||||
return None
|
||||
for value in self.values:
|
||||
|
@ -256,24 +206,28 @@ class Token:
|
|||
return value
|
||||
return None
|
||||
|
||||
## Scope. Information about global scope, function scopes, class scopes, inner scopes, etc.
|
||||
# C++ class: http://cppcheck.net/devinfo/doxyoutput/classScope.html
|
||||
|
||||
|
||||
class Scope:
|
||||
"""
|
||||
Scope. Information about global scope, function scopes, class scopes, inner scopes, etc.
|
||||
C++ class: http://cppcheck.net/devinfo/doxyoutput/classScope.html
|
||||
|
||||
Attributes
|
||||
classStart The { Token for this scope
|
||||
classEnd The } Token for this scope
|
||||
className Name of this scope.
|
||||
For a function scope, this is the function name;
|
||||
For a class scope, this is the class name.
|
||||
type Type of scope: Global, Function, Class, If, While
|
||||
"""
|
||||
|
||||
Id = None
|
||||
classStartId = None
|
||||
|
||||
## The { Token for this scope
|
||||
classStart = None
|
||||
classEndId = None
|
||||
## The } Token for this scope
|
||||
classEnd = None
|
||||
## Name of this scope.
|
||||
# For a function scope, this is the function name;
|
||||
# for a class scope, this is the class name.
|
||||
className = None
|
||||
## Type of scope: Global, Function, Class, If, While
|
||||
type = None
|
||||
|
||||
def __init__(self, element):
|
||||
|
@ -292,12 +246,15 @@ class Scope:
|
|||
self.classEnd = IdMap[self.classEndId]
|
||||
self.nestedIn = IdMap[self.nestedInId]
|
||||
|
||||
## Information about a function
|
||||
# C++ class:
|
||||
# http://cppcheck.net/devinfo/doxyoutput/classFunction.html
|
||||
|
||||
|
||||
class Function:
|
||||
"""
|
||||
Information about a function
|
||||
C++ class:
|
||||
http://cppcheck.net/devinfo/doxyoutput/classFunction.html
|
||||
"""
|
||||
|
||||
Id = None
|
||||
argument = None
|
||||
argumentId = None
|
||||
|
@ -319,35 +276,39 @@ class Function:
|
|||
self.argument[argnr] = IdMap[argid]
|
||||
self.tokenDef = IdMap[self.tokenDefId]
|
||||
|
||||
## Information about a variable
|
||||
# C++ class:
|
||||
# http://cppcheck.net/devinfo/doxyoutput/classVariable.html
|
||||
|
||||
|
||||
class Variable:
|
||||
"""
|
||||
Information about a variable
|
||||
C++ class:
|
||||
http://cppcheck.net/devinfo/doxyoutput/classVariable.html
|
||||
|
||||
Attributes:
|
||||
nameToken name token in variable declaration
|
||||
typeStartToken start token of variable declaration
|
||||
typeEndToken end token of variable declaration
|
||||
isArgument Is this variable a function argument?
|
||||
isArray Is this variable an array?
|
||||
isClass Is this variable a class or struct?
|
||||
isLocal Is this variable a local variable?
|
||||
isPointer Is this variable a pointer
|
||||
isReference Is this variable a reference
|
||||
isStatic Is this variable static?
|
||||
"""
|
||||
|
||||
Id = None
|
||||
nameTokenId = None
|
||||
## name token in variable declaration
|
||||
nameToken = None
|
||||
typeStartTokenId = None
|
||||
## start token of variable declaration
|
||||
typeStartToken = None
|
||||
typeEndTokenId = None
|
||||
## end token of variable declaration
|
||||
typeEndToken = None
|
||||
## Is this variable a function argument?
|
||||
isArgument = False
|
||||
## Is this variable an array?
|
||||
isArray = False
|
||||
## Is this variable a class or struct?
|
||||
isClass = False
|
||||
## Is this variable a local variable?
|
||||
isLocal = False
|
||||
## Is this variable a pointer
|
||||
isPointer = False
|
||||
## Is this variable a reference
|
||||
isReference = False
|
||||
## Is this variable static?
|
||||
isStatic = False
|
||||
|
||||
def __init__(self, element):
|
||||
|
@ -371,22 +332,36 @@ class Variable:
|
|||
self.typeStartToken = IdMap[self.typeStartTokenId]
|
||||
self.typeEndToken = IdMap[self.typeEndTokenId]
|
||||
|
||||
## ValueFlow class
|
||||
|
||||
|
||||
class ValueFlow:
|
||||
## ValueFlow::Value class
|
||||
# Each possible value has a ValueFlow::Value item.
|
||||
# Each ValueFlow::Value either has a intvalue or tokvalue
|
||||
# C++ class:
|
||||
# http://cppcheck.net/devinfo/doxyoutput/classValueFlow_1_1Value.html
|
||||
"""
|
||||
ValueFlow::Value class
|
||||
Each possible value has a ValueFlow::Value item.
|
||||
Each ValueFlow::Value either has a intvalue or tokvalue
|
||||
C++ class:
|
||||
http://cppcheck.net/devinfo/doxyoutput/classValueFlow_1_1Value.html
|
||||
|
||||
Attributes:
|
||||
values Possible values
|
||||
"""
|
||||
|
||||
|
||||
Id = None
|
||||
values = None
|
||||
|
||||
class Value:
|
||||
## integer value
|
||||
"""
|
||||
Value class
|
||||
|
||||
Attributes:
|
||||
intvalue integer value
|
||||
tokvalue token value
|
||||
condition condition where this Value comes from
|
||||
"""
|
||||
|
||||
intvalue = None
|
||||
## token value
|
||||
tokvalue = None
|
||||
## condition where this Value comes from
|
||||
condition = None
|
||||
|
||||
def __init__(self, element):
|
||||
|
@ -398,36 +373,36 @@ class ValueFlow:
|
|||
if self.condition:
|
||||
self.condition = int(self.condition)
|
||||
|
||||
Id = None
|
||||
|
||||
## Possible values
|
||||
values = None
|
||||
|
||||
def __init__(self, element):
|
||||
self.Id = element.get('id')
|
||||
self.values = []
|
||||
for value in element:
|
||||
self.values.append(ValueFlow.Value(value))
|
||||
|
||||
## Configuration class
|
||||
# This class contains the directives, tokens, scopes, functions,
|
||||
# variables and value flows for one configuration.
|
||||
|
||||
|
||||
class Configuration:
|
||||
## Name of the configuration, "" for default
|
||||
"""
|
||||
Configuration class
|
||||
This class contains the directives, tokens, scopes, functions,
|
||||
variables and value flows for one configuration.
|
||||
|
||||
Attributes:
|
||||
name Name of the configuration, "" for default
|
||||
directives List of Directive items
|
||||
tokenlist List of Token items
|
||||
scopes List of Scope items
|
||||
functions List of Function items
|
||||
variables List of Variable items
|
||||
valueflow List of ValueFlow values
|
||||
"""
|
||||
|
||||
name = ''
|
||||
## List of Directive items
|
||||
directives = []
|
||||
## List of Token items
|
||||
tokenlist = []
|
||||
## List of Scope items
|
||||
scopes = []
|
||||
## List of Function items
|
||||
functions = []
|
||||
## List of Variable items
|
||||
variables = []
|
||||
## List of ValueFlow values
|
||||
valueflow = []
|
||||
|
||||
def __init__(self, confignode):
|
||||
|
@ -492,41 +467,44 @@ class Configuration:
|
|||
for variable in self.variables:
|
||||
variable.setId(IdMap)
|
||||
|
||||
## Class that makes cppcheck dump data available
|
||||
# Contains a list of Configuration instances
|
||||
#
|
||||
# To iterate through all configurations use such code:
|
||||
# @code
|
||||
# data = cppcheckdata.parsedump(...)
|
||||
# for cfg in data.configurations:
|
||||
# print('cfg: ' + cfg.name)
|
||||
# @endcode
|
||||
#
|
||||
# To iterate through all tokens in each configuration use such code:
|
||||
# @code
|
||||
# data = cppcheckdata.parsedump(...)
|
||||
# for cfg in data.configurations:
|
||||
# print('cfg: ' + cfg.name)
|
||||
# code = ''
|
||||
# for token in cfg.tokenlist:
|
||||
# code = code + token.str + ' '
|
||||
# print(' ' + code)
|
||||
# @endcode
|
||||
#
|
||||
# To iterate through all scopes (functions, types, etc) use such code:
|
||||
# @code
|
||||
# data = cppcheckdata.parsedump(...)
|
||||
# for cfg in data.configurations:
|
||||
# print('cfg: ' + cfg.name)
|
||||
# for scope in cfg.scopes:
|
||||
# print(' type:' + scope.type + ' name:' + scope.className)
|
||||
# @endcode
|
||||
#
|
||||
#
|
||||
|
||||
|
||||
class CppcheckData:
|
||||
## List of Configurations
|
||||
"""
|
||||
Class that makes cppcheck dump data available
|
||||
Contains a list of Configuration instances
|
||||
|
||||
Attributes:
|
||||
configurations List of Configurations
|
||||
|
||||
To iterate through all configurations use such code:
|
||||
@code
|
||||
data = cppcheckdata.parsedump(...)
|
||||
for cfg in data.configurations:
|
||||
print('cfg: ' + cfg.name)
|
||||
@endcode
|
||||
|
||||
To iterate through all tokens in each configuration use such code:
|
||||
@code
|
||||
data = cppcheckdata.parsedump(...)
|
||||
for cfg in data.configurations:
|
||||
print('cfg: ' + cfg.name)
|
||||
code = ''
|
||||
for token in cfg.tokenlist:
|
||||
code = code + token.str + ' '
|
||||
print(' ' + code)
|
||||
@endcode
|
||||
|
||||
To iterate through all scopes (functions, types, etc) use such code:
|
||||
@code
|
||||
data = cppcheckdata.parsedump(...)
|
||||
for cfg in data.configurations:
|
||||
print('cfg: ' + cfg.name)
|
||||
for scope in cfg.scopes:
|
||||
print(' type:' + scope.type + ' name:' + scope.className)
|
||||
@endcode
|
||||
"""
|
||||
|
||||
configurations = []
|
||||
|
||||
def __init__(self, filename):
|
||||
|
@ -537,16 +515,21 @@ class CppcheckData:
|
|||
for cfgnode in data.getroot():
|
||||
self.configurations.append(Configuration(cfgnode))
|
||||
|
||||
## parse a cppcheck dump file
|
||||
|
||||
|
||||
def parsedump(filename):
|
||||
"""
|
||||
parse a cppcheck dump file
|
||||
"""
|
||||
return CppcheckData(filename)
|
||||
|
||||
## Check if type of ast node is float/double
|
||||
|
||||
|
||||
def astIsFloat(token):
|
||||
"""
|
||||
Check if type of ast node is float/double
|
||||
"""
|
||||
|
||||
if not token:
|
||||
return False
|
||||
if token.str == '.':
|
||||
|
@ -572,13 +555,11 @@ def astIsFloat(token):
|
|||
return True
|
||||
return False
|
||||
|
||||
# Create a cppcheck parser
|
||||
|
||||
class CppCheckFormatter(argparse.HelpFormatter):
|
||||
'''
|
||||
Properly formats multiline argument helps
|
||||
'''
|
||||
|
||||
"""
|
||||
Properly formats multiline argument helps
|
||||
"""
|
||||
def _split_lines(self, text, width):
|
||||
# this is the RawTextHelpFormatter._split_lines
|
||||
if text.startswith('R|'):
|
||||
|
@ -586,10 +567,10 @@ class CppCheckFormatter(argparse.HelpFormatter):
|
|||
return argparse.HelpFormatter._split_lines(self, text, width)
|
||||
|
||||
def ArgumentParser():
|
||||
'''
|
||||
"""
|
||||
Returns an argparse argument parser with an already-added
|
||||
argument definition for -t/--template
|
||||
'''
|
||||
"""
|
||||
parser = argparse.ArgumentParser(formatter_class=CppCheckFormatter)
|
||||
parser.add_argument('-t', '--template', metavar='<text>',
|
||||
default='{callstack}: ({severity}) {message}',
|
||||
|
@ -600,10 +581,8 @@ def ArgumentParser():
|
|||
"Pre-defined templates: gcc, vs, edit")
|
||||
return parser
|
||||
|
||||
# Format an error message.
|
||||
|
||||
def reportError(template, callstack=[], severity='', message='', id=''):
|
||||
'''
|
||||
"""
|
||||
Format an error message according to the template.
|
||||
|
||||
:param template: format string, or 'gcc', 'vs' or 'edit'.
|
||||
|
@ -611,7 +590,7 @@ def reportError(template, callstack=[], severity='', message='', id=''):
|
|||
:param severity: e.g. 'error', 'warning' ...
|
||||
:param id: message ID.
|
||||
:param message: message text.
|
||||
'''
|
||||
"""
|
||||
# expand predefined templates
|
||||
if template == 'gcc':
|
||||
template = '{file}:{line}: {severity}: {message}'
|
||||
|
|
Loading…
Reference in New Issue