Skip to content

Commit

Permalink
Add command for listing and querying data about analyzers
Browse files Browse the repository at this point in the history
  • Loading branch information
whisperity committed Apr 11, 2017
1 parent e1e7321 commit 85b0087
Show file tree
Hide file tree
Showing 3 changed files with 151 additions and 5 deletions.
21 changes: 21 additions & 0 deletions bin/codechecker-analyzers
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/usr/bin/env python
# -------------------------------------------------------------------------
# The CodeChecker Infrastructure
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
# -------------------------------------------------------------------------
"""
Entry point for the analyzers command.
"""

import imp
import os

THIS_PATH = os.path.dirname(os.path.abspath(__file__))
CC = os.path.join(THIS_PATH, "CodeChecker")

# Load CodeChecker from the current folder (the wrapper script (without .py))
CodeChecker = imp.load_source('CodeChecker', CC)

# Execute CC's main script with the current subcommand.
CodeChecker.main("analyzers")
11 changes: 6 additions & 5 deletions libcodechecker/analyze/analyzers/analyzer_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,10 @@ def check_supported_analyzers(analyzers, context):
elif not os.path.isabs(analyzer_bin):
# If the analyzer is not in an absolute path, try to find it...
if analyzer_name == CLANG_SA:
found_bin = analyzer_clangsa.ClangSA.\
found_bin = analyzer_clangsa.ClangSA. \
resolve_missing_binary(analyzer_bin, check_env)
elif analyzer_name == CLANG_TIDY:
found_bin = analyzer_clang_tidy.ClangTidy.\
found_bin = analyzer_clang_tidy.ClangTidy. \
resolve_missing_binary(analyzer_bin, check_env)

# found_bin is an absolute path, an executable in one of the
Expand All @@ -118,13 +118,14 @@ def check_supported_analyzers(analyzers, context):
if not found_bin or \
not host_check.check_clang(found_bin, check_env):
# If analyzer_bin is not False here, the resolver found one.
failed_analyzers.add((analyzer_name,
"Couldn't run analyzer binary."))
failed_analyzers.add((analyzer_name,
"Couldn't run analyzer binary."))
available_analyzer = False
elif host_check.check_clang(analyzer_bin, check_env):
# Analyzers unavailable under absolute paths are deliberately a
# configuration problem.
LOG.warning('Failed to run analyzer ' + analyzer_name + ' !')
failed_analyzers.add((analyzer_name,
"Cannot execute analyzer binary."))
available_analyzer = False

if available_analyzer:
Expand Down
124 changes: 124 additions & 0 deletions libcodechecker/analyzers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
# -------------------------------------------------------------------------
# The CodeChecker Infrastructure
# This file is distributed under the University of Illinois Open Source
# License. See LICENSE.TXT for details.
# -------------------------------------------------------------------------
"""
Subcommand module for the 'CodeChecker analyzers' command which lists the
analyzers available in CodeChecker.
"""

import argparse
import subprocess

from libcodechecker import generic_package_context
from libcodechecker import output_formatters
from libcodechecker.analyze.analyzers import analyzer_types
from libcodechecker.logger import add_verbose_arguments
from libcodechecker.logger import LoggerFactory

LOG = LoggerFactory.get_new_logger('ANALYZERS')


def get_argparser_ctor_args():
"""
This method returns a dict containing the kwargs for constructing an
argparse.ArgumentParser (either directly or as a subparser).
"""

return {
'prog': 'CodeChecker analyzers',
'formatter_class': argparse.ArgumentDefaultsHelpFormatter,

# Description is shown when the command's help is queried directly
'description': "Get the list of available and supported analyzers, "
"querying their version and actual binary executed.",

# Help is shown when the "parent" CodeChecker command lists the
# individual subcommands.
'help': "List supported and available analyzers."
}


def add_arguments_to_parser(parser):
"""
Add the subcommand's arguments to the given argparse.ArgumentParser.
"""

parser.add_argument('--all',
dest="all",
action='store_true',
default=False,
required=False,
help="Show all supported analyzers, not just the "
"available ones.")

parser.add_argument('--details',
dest="details",
action='store_true',
default=False,
required=False,
help="Show details about the analyzers, not just "
"their names.")

parser.add_argument('-o', '--output',
dest='output_format',
required=False,
default='rows',
choices=output_formatters.USER_FORMATS,
help="Specify the format of the output list.")

add_verbose_arguments(parser)
parser.set_defaults(func=main)


def main(args):
"""
List the analyzers' basic information supported by CodeChecker.
"""

context = generic_package_context.get_context()
working, errored = \
analyzer_types.check_supported_analyzers(
analyzer_types.supported_analyzers,
context)

if args.output_format not in ['csv', 'json']:
if not args.details:
header = ['Name']
else:
header = ['Name', 'Path', 'Version']
else:
if not args.details:
header = ['name']
else:
header = ['name', 'path', 'version_string']

rows = []
for analyzer in working:
if not args.details:
rows.append([analyzer])
else:
binary = context.analyzer_binaries.get(analyzer)
try:
version = subprocess.check_output([binary,
'--version'])
except (subprocess.CalledProcessError, OSError):
version = 'ERROR'

rows.append([analyzer,
binary,
version])

if args.all:
for analyzer, err_reason in errored:
if not args.details:
rows.append([analyzer])
else:
rows.append([analyzer,
context.analyzer_binaries.get(analyzer),
err_reason])

if len(rows) > 0:
print(output_formatters.twodim_to_str(args.output_format,
header, rows))

0 comments on commit 85b0087

Please sign in to comment.