cppcheckdata.py: reformat documentation

This commit is contained in:
Daniel Marjamäki 2016-07-25 13:47:26 +02:00
parent 07b43c6929
commit 8c8ad96fe5
1 changed files with 204 additions and 225 deletions

View File

@ -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
'''
"""
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}'