Skip to content

Commit

Permalink
Merge pull request Ericsson#4056 from Szelethus/analyzers_remove_flags
Browse files Browse the repository at this point in the history
[analyzers] Deprecate --all and --details for analyzers
  • Loading branch information
bruntib authored Oct 25, 2023
2 parents fa41e4e + 3f90f00 commit 3999910
Show file tree
Hide file tree
Showing 8 changed files with 92 additions and 112 deletions.
2 changes: 1 addition & 1 deletion analyzer/codechecker_analyzer/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ def perform_analysis(args, skip_handlers, actions, metadata_tool,

# TODO: cppcheck may require a different environment than clang.
version = analyzer_types.supported_analyzers[analyzer] \
.get_version(context.analyzer_env)
.get_binary_version(context.analyzer_env)
metadata_info['analyzer_statistics']['version'] = version

metadata_tool['analyzers'][analyzer] = metadata_info
Expand Down
13 changes: 11 additions & 2 deletions analyzer/codechecker_analyzer/analyzers/analyzer_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,18 @@ def resolve_missing_binary(cls, configured_binary, environ):
"""
raise NotImplementedError("Subclasses should implement this!")

@abstractmethod
def get_binary_version(self, environ, details=False) -> str:
"""
Return the version number of the binary that CodeChecker found, even
if its incompatible. If details is true, additional version information
is provided. If details is false, the return value should be
convertible to a distutils.version.StrictVersion type.
"""
raise NotImplementedError("Subclasses should implement this!")

@classmethod
def is_binary_version_incompatible(cls, configured_binary, environ) \
-> Optional[str]:
def is_binary_version_incompatible(cls, environ) -> Optional[str]:
"""
CodeChecker can only execute certain versions of analyzers.
Returns a error object (an optional string). If the return value is
Expand Down
6 changes: 2 additions & 4 deletions analyzer/codechecker_analyzer/analyzers/analyzer_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,7 @@ def check_supported_analyzers(analyzers):
# Check version compatibility of the analyzer binary.
if analyzer_bin:
analyzer = supported_analyzers[analyzer_name]
error = analyzer.is_binary_version_incompatible(analyzer_bin,
check_env)
error = analyzer.is_binary_version_incompatible(check_env)
if error:
failed_analyzers.add((analyzer_name,
f"Incompatible version: {error}"))
Expand Down Expand Up @@ -221,8 +220,7 @@ def construct_analyzer(buildaction,
LOG.error('Unsupported analyzer type: %s', analyzer_type)
return analyzer

except Exception as ex:
LOG.debug_analyzer(ex)
except Exception:
# We should've detected well before this point that something is off
# with the analyzer. We can't recover here.
raise
Expand Down
14 changes: 8 additions & 6 deletions analyzer/codechecker_analyzer/analyzers/clangsa/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,16 +171,18 @@ def __add_plugin_load_flags(cls, analyzer_cmd: List[str]):
analyzer_cmd.extend(["-load", plugin])

@classmethod
def get_version(cls, env=None):
""" Get analyzer version information. """
version = [cls.analyzer_binary(), '--version']
def get_binary_version(self, environ, details=False) -> str:
if details:
version = [self.analyzer_binary(), '--version']
else:
version = [self.analyzer_binary(), '-dumpversion']
try:
output = subprocess.check_output(version,
env=env,
env=environ,
universal_newlines=True,
encoding="utf-8",
errors="ignore")
return output
return output.strip()
except (subprocess.CalledProcessError, OSError) as oerr:
LOG.warning("Failed to get analyzer version: %s",
' '.join(version))
Expand Down Expand Up @@ -578,7 +580,7 @@ def resolve_missing_binary(cls, configured_binary, environ):
return clang

@classmethod
def is_binary_version_incompatible(cls, configured_binary, environ):
def is_binary_version_incompatible(cls, environ):
"""
We support pretty much every ClangSA version.
"""
Expand Down
23 changes: 17 additions & 6 deletions analyzer/codechecker_analyzer/analyzers/clangtidy/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,16 @@ def need_asterisk(checker: str) -> bool:
return result


def parse_version(tidy_output):
"""
Parse clang-tidy version output and return the version number.
"""
version_re = re.compile(r'.*version (?P<version>[\d\.]+)', re.S)
match = version_re.match(tidy_output)
if match:
return match.group('version')


class ClangTidy(analyzer_base.SourceAnalyzer):
"""
Constructs the clang tidy analyzer commands.
Expand All @@ -220,16 +230,17 @@ def analyzer_binary(cls):
.analyzer_binaries[cls.ANALYZER_NAME]

@classmethod
def get_version(cls, env=None):
""" Get analyzer version information. """
version = [cls.analyzer_binary(), '--version']
def get_binary_version(self, environ, details=False) -> str:
version = [self.analyzer_binary(), '--version']
try:
output = subprocess.check_output(version,
env=env,
env=environ,
universal_newlines=True,
encoding="utf-8",
errors="ignore")
return output
if details:
return output.strip()
return parse_version(output)
except (subprocess.CalledProcessError, OSError) as oerr:
LOG.warning("Failed to get analyzer version: %s",
' '.join(version))
Expand Down Expand Up @@ -533,7 +544,7 @@ def resolve_missing_binary(cls, configured_binary, environ):
return clangtidy

@classmethod
def is_binary_version_incompatible(cls, configured_binary, environ):
def is_binary_version_incompatible(cls, environ):
"""
We support pretty much every Clang-Tidy version.
"""
Expand Down
36 changes: 10 additions & 26 deletions analyzer/codechecker_analyzer/analyzers/cppcheck/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ def parse_version(cppcheck_output):
version_re = re.compile(r'^Cppcheck (?P<version>[\d\.]+)')
match = version_re.match(cppcheck_output)
if match:
return StrictVersion(match.group('version'))
return match.group('version')


class Cppcheck(analyzer_base.SourceAnalyzer):
Expand All @@ -83,16 +83,18 @@ def analyzer_binary(cls):
.analyzer_binaries[cls.ANALYZER_NAME]

@classmethod
def get_version(cls, env=None):
def get_binary_version(self, environ, details=False) -> str:
""" Get analyzer version information. """
version = [cls.analyzer_binary(), '--version']
version = [self.analyzer_binary(), '--version']
try:
output = subprocess.check_output(version,
env=env,
env=environ,
universal_newlines=True,
encoding="utf-8",
errors="ignore")
return output
if details:
return output.strip()
return parse_version(output)
except (subprocess.CalledProcessError, OSError) as oerr:
LOG.warning("Failed to get analyzer version: %s",
' '.join(version))
Expand Down Expand Up @@ -334,33 +336,15 @@ def resolve_missing_binary(cls, configured_binary, env):
return cppcheck

@classmethod
def __get_analyzer_version(cls, analyzer_binary, env):
"""
Return the analyzer version.
"""
command = [analyzer_binary, "--version"]

try:
result = subprocess.check_output(
command,
env=env,
encoding="utf-8",
errors="ignore")
return parse_version(result)
except (subprocess.CalledProcessError, OSError):
return []

@classmethod
def is_binary_version_incompatible(cls, configured_binary, environ):
def is_binary_version_incompatible(cls, environ):
"""
Check the version compatibility of the given analyzer binary.
"""
analyzer_version = \
cls.__get_analyzer_version(configured_binary, environ)
analyzer_version = cls.get_binary_version(environ)

# The analyzer version should be above 1.80 because '--plist-output'
# argument was introduced in this release.
if analyzer_version >= StrictVersion("1.80"):
if StrictVersion(analyzer_version) >= StrictVersion("1.80"):
return None

return "CppCheck binary found is too old at " \
Expand Down
23 changes: 9 additions & 14 deletions analyzer/codechecker_analyzer/analyzers/gcc/analyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,11 +42,6 @@ def analyzer_binary(cls):
return analyzer_context.get_context() \
.analyzer_binaries[cls.ANALYZER_NAME]

@classmethod
def get_version(cls, env=None):
""" Get analyzer version information. """
return cls.__get_analyzer_version(cls.analyzer_binary(), env)

def add_checker_config(self, checker_cfg):
# TODO
pass
Expand Down Expand Up @@ -174,19 +169,20 @@ def resolve_missing_binary(cls, configured_binary, env):
pass

@classmethod
def __get_analyzer_version(cls, analyzer_binary, env):
def get_binary_version(self, environ, details=False) -> str:
"""
Return the analyzer version.
"""
# --version outputs a lot of garbage as well (like copyright info),
# this only contains the version info.
version = [analyzer_binary, '-dumpfullversion']
if details:
version = [self.analyzer_binary(), '--version']
else:
version = [self.analyzer_binary(), '-dumpfullversion']
try:
output = subprocess.check_output(version,
env=env,
env=environ,
encoding="utf-8",
errors="ignore")
return output
return output.strip()
except (subprocess.CalledProcessError, OSError) as oerr:
LOG.warning("Failed to get analyzer version: %s",
' '.join(version))
Expand All @@ -195,12 +191,11 @@ def __get_analyzer_version(cls, analyzer_binary, env):
return None

@classmethod
def is_binary_version_incompatible(cls, configured_binary, environ):
def is_binary_version_incompatible(cls, environ):
"""
Check the version compatibility of the given analyzer binary.
"""
analyzer_version = \
cls.__get_analyzer_version(configured_binary, environ)
analyzer_version = cls.get_binary_version(environ)

# The analyzer version should be above 13.0.0 because the
# '-fdiagnostics-format=sarif-file' argument was introduced in this
Expand Down
Loading

0 comments on commit 3999910

Please sign in to comment.