Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion analyzer/codechecker_analyzer/analyzers/analyzer_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,28 @@
import sys
import shlex

from typing import Optional
from typing import List, Optional

from codechecker_analyzer import analyzer_context
from codechecker_common.logger import get_logger

LOG = get_logger('analyzer')


class AnalyzerConfig:
def __init__(self, option: str, documentation: str, value_type: type):
self.option = option
self.documentation = documentation
self.value_type = value_type


class CheckerConfig:
def __init__(self, checker: str, option: str, documentation: str):
self.checker = checker
self.option = option
self.documentation = documentation


class SourceAnalyzer(metaclass=ABCMeta):
"""
Base class for different source analyzers.
Expand Down Expand Up @@ -138,6 +152,14 @@ def get_analyzer_checkers(cls):
"""
raise NotImplementedError("Subclasses should implement this!")

@classmethod
def get_analyzer_config(cls) -> List[AnalyzerConfig]:
return []

@classmethod
def get_checker_config(cls) -> List[CheckerConfig]:
return []

def post_analyze(self, result_handler):
"""
Run immediately after the analyze function.
Expand Down
25 changes: 17 additions & 8 deletions analyzer/codechecker_analyzer/analyzers/clangsa/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,13 @@ class ClangSA(analyzer_base.SourceAnalyzer):

__ctu_autodetection = None

__additional_analyzer_config = {
'cc-verbatim-args-file':
__additional_analyzer_config = [
analyzer_base.AnalyzerConfig(
'cc-verbatim-args-file',
'A file path containing flags that are forwarded verbatim to the '
'analyzer tool. E.g.: cc-verbatim-args-file=<filepath>'
}
'analyzer tool. E.g.: cc-verbatim-args-file=<filepath>',
util.ExistingPath)
]

def __init__(self, cfg_handler, buildaction):
super().__init__(cfg_handler, buildaction)
Expand Down Expand Up @@ -290,7 +292,7 @@ def get_analyzer_checkers(
return parse_clang_help_page(command, 'CHECKERS:')

@classmethod
def get_checker_config(cls) -> List[str]:
def get_checker_config(cls) -> List[analyzer_base.CheckerConfig]:
"""
Return the list of checker config options.

Expand All @@ -311,10 +313,14 @@ def get_checker_config(cls) -> List[str]:
if version_info.major_version >= 9:
command.append("-analyzer-checker-option-help-developer")

return parse_clang_help_page(command, 'OPTIONS:')
result = []
for cfg, doc in parse_clang_help_page(command, 'OPTIONS:'):
result.append(analyzer_base.CheckerConfig(*cfg.split(':', 1), doc))

return result

@classmethod
def get_analyzer_config(cls) -> List[Tuple[str, str]]:
def get_analyzer_config(cls) -> List[analyzer_base.AnalyzerConfig]:
"""Return the list of analyzer config options."""
command = [cls.analyzer_binary(), "-cc1"]

Expand All @@ -323,8 +329,11 @@ def get_analyzer_config(cls) -> List[Tuple[str, str]]:
command.append("-analyzer-config-help")

native_config = parse_clang_help_page(command, 'OPTIONS:')
native_config = map(
lambda cfg: analyzer_base.AnalyzerConfig(cfg[0], cfg[1], str),
native_config)

return native_config + list(cls.__additional_analyzer_config.items())
return list(native_config) + list(cls.__additional_analyzer_config)

def post_analyze(self, result_handler):
"""
Expand Down
35 changes: 26 additions & 9 deletions analyzer/codechecker_analyzer/analyzers/clangtidy/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -256,11 +256,19 @@ class ClangTidy(analyzer_base.SourceAnalyzer):
# Cache object for get_analyzer_checkers().
__analyzer_checkers = None

__additional_analyzer_config = {
'cc-verbatim-args-file':
__additional_analyzer_config = [
analyzer_base.AnalyzerConfig(
'cc-verbatim-args-file',
'A file path containing flags that are forwarded verbatim to the '
'analyzer tool. E.g.: cc-verbatim-args-file=<filepath>'
}
'analyzer tool. E.g.: cc-verbatim-args-file=<filepath>',
util.ExistingPath),
analyzer_base.AnalyzerConfig(
'take-config-from-directory',
'The .clang-tidy config file should be taken into account when '
'analysis is executed through CodeChecker. Possible values: true, '
'false. Default: false',
str)
]

@classmethod
def analyzer_binary(cls):
Expand Down Expand Up @@ -334,24 +342,29 @@ def get_analyzer_checkers(cls):
return []

@classmethod
def get_checker_config(cls):
def get_checker_config(cls) -> List[analyzer_base.CheckerConfig]:
"""
Return the checker configuration of the all of the supported checkers.
"""
try:
result = subprocess.check_output(
help_page = subprocess.check_output(
[cls.analyzer_binary(), "-dump-config", "-checks=*"],
env=analyzer_context.get_context()
.get_env_for_bin(cls.analyzer_binary()),
universal_newlines=True,
encoding="utf-8",
errors="ignore")
return parse_checker_config(result)
except (subprocess.CalledProcessError, OSError):
return []

result = []
for cfg, doc in parse_checker_config(help_page):
result.append(analyzer_base.CheckerConfig(*cfg.split(':', 1), doc))

return result

@classmethod
def get_analyzer_config(cls):
def get_analyzer_config(cls) -> List[analyzer_base.AnalyzerConfig]:
"""
Return the analyzer configuration with all checkers enabled.
"""
Expand All @@ -370,7 +383,11 @@ def get_analyzer_config(cls):
except (subprocess.CalledProcessError, OSError):
native_config = []

return native_config + list(cls.__additional_analyzer_config.items())
native_config = map(
lambda cfg: analyzer_base.AnalyzerConfig(cfg[0], cfg[1], str),
native_config)

return list(native_config) + list(cls.__additional_analyzer_config)

def get_checker_list(self, config) -> Tuple[List[str], List[str]]:
"""
Expand Down
38 changes: 23 additions & 15 deletions analyzer/codechecker_analyzer/analyzers/cppcheck/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from collections import defaultdict
import sys
from typing import List
from packaging.version import Version
from pathlib import Path
import os
Expand Down Expand Up @@ -299,27 +300,34 @@ def get_analyzer_checkers(cls):
return []

@classmethod
def get_analyzer_config(cls):
def get_analyzer_config(cls) -> List[analyzer_base.AnalyzerConfig]:
"""
Config options for cppcheck.
"""
return [
("addons", "A list of cppcheck addon files."),
("libraries", "A list of cppcheck library definiton files."),
("platform", "The platform configuration .xml file."),
("inconclusive", "Enable inconclusive reports."),
("cc-verbatim-args-file",
"A file path containing flags that are forwarded verbatim to the "
"analyzer tool. E.g.: cc-verbatim-args-file=<filepath>")
analyzer_base.AnalyzerConfig(
"addons",
"A list of cppcheck addon files.",
str),
analyzer_base.AnalyzerConfig(
"libraries",
"A list of cppcheck library definiton files.",
str),
analyzer_base.AnalyzerConfig(
"platform",
"The platform configuration .xml file.",
str),
analyzer_base.AnalyzerConfig(
"inconclusive",
"Enable inconclusive reports.",
str),
analyzer_base.AnalyzerConfig(
"cc-verbatim-args-file",
"A file path containing flags that are forwarded verbatim to "
"the analyzer tool. E.g.: cc-verbatim-args-file=<filepath>",
util.ExistingPath)
]

@classmethod
def get_checker_config(cls):
"""
TODO add config options for cppcheck checkers.
"""
return []

def post_analyze(self, result_handler):
"""
Post process the reuslts after the analysis.
Expand Down
19 changes: 7 additions & 12 deletions analyzer/codechecker_analyzer/analyzers/gcc/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#
# -------------------------------------------------------------------------
from typing import List
from packaging.version import Version
import shlex
import subprocess
Expand Down Expand Up @@ -124,25 +125,19 @@ def get_analyzer_checkers(cls):
return []

@classmethod
def get_analyzer_config(cls):
def get_analyzer_config(cls) -> List[analyzer_base.AnalyzerConfig]:
"""
Config options for gcc.
"""
# TODO
return [
('cc-verbatim-args-file',
'A file path containing flags that are forwarded verbatim to the '
'analyzer tool. E.g.: cc-verbatim-args-file=<filepath>')
analyzer_base.AnalyzerConfig(
'cc-verbatim-args-file',
'A file path containing flags that are forwarded verbatim to '
'the analyzer tool. E.g.: cc-verbatim-args-file=<filepath>',
util.ExistingPath)
]

@classmethod
def get_checker_config(cls):
"""
TODO add config options for gcc checkers.
"""
# TODO
return []

def post_analyze(self, result_handler: GccResultHandler):
"""
Post process the reuslts after the analysis.
Expand Down
18 changes: 7 additions & 11 deletions analyzer/codechecker_analyzer/analyzers/infer/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import json
from pathlib import Path
import sys
from typing import List

from codechecker_common import util
from codechecker_common.logger import get_logger
Expand Down Expand Up @@ -138,23 +139,18 @@ def get_analyzer_checkers(cls):
return []

@classmethod
def get_analyzer_config(cls):
def get_analyzer_config(cls) -> List[analyzer_base.AnalyzerConfig]:
"""
Config options for infer.
"""
return [
('cc-verbatim-args-file',
'A file path containing flags that are forwarded verbatim to the '
'analyzer tool. E.g.: cc-verbatim-args-file=<filepath>')
analyzer_base.AnalyzerConfig(
'cc-verbatim-args-file',
'A file path containing flags that are forwarded verbatim to '
'the analyzer tool. E.g.: cc-verbatim-args-file=<filepath>',
util.ExistingPath)
]

@classmethod
def get_checker_config(cls):
"""
Config options for infer checkers.
"""
return []

def analyze(self, analyzer_cmd, res_handler, proc_callback=None, env=None):

env = analyzer_context.get_context().get_env_for_bin(
Expand Down
16 changes: 8 additions & 8 deletions analyzer/codechecker_analyzer/arg.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
import re


AnalyzerConfig = collections.namedtuple(
'AnalyzerConfig', ["analyzer", "option", "value"])
CheckerConfig = collections.namedtuple(
"CheckerConfig", ["analyzer", "checker", "option", "value"])
AnalyzerConfigArg = collections.namedtuple(
"AnalyzerConfigArg", ["analyzer", "option", "value"])
CheckerConfigArg = collections.namedtuple(
"CheckerConfigArg", ["analyzer", "checker", "option", "value"])
AnalyzerBinary = collections.namedtuple(
"AnalyzerBinary", ["analyzer", "path"])

Expand Down Expand Up @@ -106,7 +106,7 @@ def existing_abspath(path: str) -> str:
return path


def analyzer_config(arg: str) -> AnalyzerConfig:
def analyzer_config(arg: str) -> AnalyzerConfigArg:
"""
This function can be used at "type" argument of argparse.add_argument().
It checks the format of --analyzer-config flag:
Expand All @@ -120,11 +120,11 @@ def analyzer_config(arg: str) -> AnalyzerConfig:
f"Analyzer option in wrong format: {arg}, should be "
"<analyzer>:<option>=<value>")

return AnalyzerConfig(
return AnalyzerConfigArg(
m.group("analyzer"), m.group("option"), m.group("value"))


def checker_config(arg: str) -> CheckerConfig:
def checker_config(arg: str) -> CheckerConfigArg:
"""
This function can be used at "type" argument of argparse.add_argument().
It checks the format of --checker-config flag:
Expand All @@ -139,7 +139,7 @@ def checker_config(arg: str) -> CheckerConfig:
f"Checker option in wrong format: {arg}, should be "
"<analyzer>:<checker>:<option>=<value>")

return CheckerConfig(
return CheckerConfigArg(
m.group("analyzer"), m.group("checker"),
m.group("option"), m.group("value"))

Expand Down
Loading