def __print_checker_config(args: argparse.Namespace): """ Print checker config options according to the command line arguments to the standard output. The set of config options comes from the analyzers. """ if args.output_format == 'custom': args.output_format = 'rows' context = analyzer_context.get_context() working_analyzers, errored = analyzer_types.check_supported_analyzers( args.analyzers, context) analyzer_types.check_available_analyzers(working_analyzers, errored) analyzer_environment = env.extend(context.path_env_extra, context.ld_lib_path_extra) analyzer_config_map = analyzer_types.build_config_handlers( args, context, working_analyzers) if 'details' in args: header = ['Option', 'Description'] else: header = ['Option'] if args.output_format in ['csv', 'json']: header = list(map(__uglify, header)) rows = [] analyzer_failures = [] for analyzer in working_analyzers: config_handler = analyzer_config_map.get(analyzer) analyzer_class = analyzer_types.supported_analyzers[analyzer] configs = analyzer_class.get_checker_config(config_handler, analyzer_environment) if not configs: analyzer_failures.append(analyzer) continue rows.extend( (':'.join((analyzer, c[0])), c[1]) if 'details' in args else (':'.join((analyzer, c[0])), ) for c in configs) if rows: print(twodim.to_str(args.output_format, header, rows)) analyzer_types.print_unsupported_analyzers(errored) if analyzer_failures: LOG.error( "Failed to get checker configuration options for '%s' " "analyzer(s)! Please try to upgrade your analyzer " "version to use this feature.", ', '.join(analyzer_failures)) sys.exit(1)
def main(args): """ List the analyzers' basic information supported by CodeChecker. """ # If the given output format is not 'table', redirect logger's output to # the stderr. stream = None if 'output_format' in args and args.output_format != 'table': stream = 'stderr' logger.setup_logger(args.verbose if 'verbose' in args else None, stream) context = analyzer_context.get_context() working_analyzers, errored = \ analyzer_types.check_supported_analyzers( analyzer_types.supported_analyzers, context) if args.dump_config: binary = context.analyzer_binaries.get(args.dump_config) if args.dump_config == 'clang-tidy': subprocess.call([binary, '-dump-config', '-checks=*'], encoding="utf-8", errors="ignore") elif args.dump_config == 'clangsa': ret = subprocess.call([binary, '-cc1', '-analyzer-checker-option-help', '-analyzer-checker-option-help-alpha'], stderr=subprocess.PIPE, encoding="utf-8", errors="ignore") if ret: # This flag is supported from Clang 9. LOG.warning("'--dump-config clangsa' is not supported yet. " "Please make sure that you are using Clang 9 or " "newer.") return analyzer_environment = env.extend(context.path_env_extra, context.ld_lib_path_extra) analyzer_config_map = analyzer_types.build_config_handlers( args, context, working_analyzers) def uglify(text): """ csv and json format output contain this non human readable header string: no CamelCase and no space. """ return text.lower().replace(' ', '_') if 'analyzer_config' in args: if 'details' in args: header = ['Option', 'Description'] else: header = ['Option'] if args.output_format in ['csv', 'json']: header = list(map(uglify, header)) analyzer = args.analyzer_config config_handler = analyzer_config_map.get(analyzer) analyzer_class = analyzer_types.supported_analyzers[analyzer] configs = analyzer_class.get_analyzer_config(config_handler, analyzer_environment) rows = [(':'.join((analyzer, c[0])), c[1]) if 'details' in args else (':'.join((analyzer, c[0])),) for c in configs] print(output_formatters.twodim_to_str(args.output_format, header, rows)) return if 'details' in args: header = ['Name', 'Path', 'Version'] else: header = ['Name'] if args.output_format in ['csv', 'json']: header = list(map(uglify, header)) rows = [] for analyzer in working_analyzers: if 'details' not in args: rows.append([analyzer]) else: binary = context.analyzer_binaries.get(analyzer) try: version = subprocess.check_output( [binary, '--version'], encoding="utf-8", errors="ignore") except (subprocess.CalledProcessError, OSError): version = 'ERROR' rows.append([analyzer, binary, version]) if 'all' in args: for analyzer, err_reason in errored: if 'details' not in args: rows.append([analyzer]) else: rows.append([analyzer, context.analyzer_binaries.get(analyzer), err_reason]) if rows: print(output_formatters.twodim_to_str(args.output_format, header, rows))
def main(args): """ List the checkers available in the specified (or all supported) analyzers alongside with their description or enabled status in various formats. """ # If the given output format is not 'table', redirect logger's output to # the stderr. logger.setup_logger(args.verbose if 'verbose' in args else None, None if args.output_format == 'table' else 'stderr') context = analyzer_context.get_context() working_analyzers, errored = analyzer_types.check_supported_analyzers( args.analyzers, context) analyzer_environment = env.extend(context.path_env_extra, context.ld_lib_path_extra) analyzer_config_map = analyzer_types.build_config_handlers( args, context, working_analyzers) def uglify(text): """ csv and json format output contain this non human readable header string: no CamelCase and no space. """ return text.lower().replace(' ', '_') def match_guideline(checker_name, selected_guidelines): """ Returns True if checker_name gives reports related to any of the selected guideline rule. checker_name -- A full checker name. selected_guidelines -- A list of guideline names or guideline rule IDs. """ guideline = context.guideline_map.get(checker_name, {}) guideline_set = set(guideline) for value in guideline.values(): guideline_set |= set(value) return any(g in guideline_set for g in selected_guidelines) def format_guideline(guideline): """ Convert guideline rules to human-readable format. guideline -- Dictionary in the following format: {"guideline_1": ["rule_1", "rule_2"]} """ return ' '.join('Related {} rules: {}'.format(g, ', '.join(r)) for g, r in guideline.items()) # List available checker profiles. if 'profile' in args and args.profile == 'list': if 'details' in args: header = ['Profile name', 'Description'] rows = context.available_profiles.items() else: header = ['Profile name'] rows = [(key, "") for key in context.available_profiles.keys()] if args.output_format in ['csv', 'json']: header = list(map(uglify, header)) print(output_formatters.twodim_to_str(args.output_format, header, rows)) return # List checker config options. if 'checker_config' in args: if 'details' in args: header = ['Option', 'Description'] else: header = ['Option'] if args.output_format in ['csv', 'json']: header = list(map(uglify, header)) rows = [] for analyzer in working_analyzers: config_handler = analyzer_config_map.get(analyzer) analyzer_class = analyzer_types.supported_analyzers[analyzer] configs = analyzer_class.get_checker_config( config_handler, analyzer_environment) rows.extend( (':'.join((analyzer, c[0])), c[1]) if 'details' in args else (':'.join((analyzer, c[0])), ) for c in configs) print(output_formatters.twodim_to_str(args.output_format, header, rows)) return if args.guideline is not None and len(args.guideline) == 0: result = defaultdict(set) for _, guidelines in context.guideline_map.items(): for guideline, rules in guidelines.items(): result[guideline] |= set(rules) header = ['Guideline', 'Rules'] if args.output_format in ['csv', 'json']: header = list(map(uglify, header)) if args.output_format == 'json': rows = [(g, sorted(list(r))) for g, r in result.items()] else: rows = [(g, ', '.join(sorted(r))) for g, r in result.items()] if args.output_format == 'rows': for row in rows: print('Guideline: {}'.format(row[0])) print('Rules: {}'.format(row[1])) else: print( output_formatters.twodim_to_str(args.output_format, header, rows)) return # List available checkers. if 'details' in args: header = [ 'Enabled', 'Name', 'Analyzer', 'Severity', 'Guideline', 'Description' ] else: header = ['Name'] if args.output_format in ['csv', 'json']: header = list(map(uglify, header)) rows = [] for analyzer in working_analyzers: config_handler = analyzer_config_map.get(analyzer) analyzer_class = analyzer_types.supported_analyzers[analyzer] checkers = analyzer_class.get_analyzer_checkers( config_handler, analyzer_environment) default_checker_cfg = context.checker_config.get(analyzer + '_checkers') profile_checkers = None if 'profile' in args: if args.profile not in context.available_profiles: LOG.error("Checker profile '%s' does not exist!", args.profile) LOG.error("To list available profiles, use '--profile list'.") sys.exit(1) profile_checkers = [(args.profile, True)] config_handler.initialize_checkers(context.available_profiles, context.package_root, checkers, default_checker_cfg, profile_checkers) for checker_name, value in config_handler.checks().items(): state, description = value if state != CheckerState.enabled and 'profile' in args: continue if state == CheckerState.enabled and 'only_disabled' in args: continue elif state != CheckerState.enabled and 'only_enabled' in args: continue if args.output_format == 'json': state = state == CheckerState.enabled else: state = '+' if state == CheckerState.enabled else '-' if args.guideline is not None: if not match_guideline(checker_name, args.guideline): continue if 'details' in args: severity = context.severity_map.get(checker_name) guideline = context.guideline_map.get(checker_name, {}) if args.output_format != 'json': guideline = format_guideline(guideline) rows.append([ state, checker_name, analyzer, severity, guideline, description ]) else: rows.append([checker_name]) if 'show_warnings' in args: severity = context.severity_map.get('clang-diagnostic-') for warning in get_warnings(analyzer_environment): warning = 'clang-diagnostic-' + warning[2:] if 'guideline' in args: if not match_guideline(warning, args.guideline): continue guideline = context.guideline_map.get(warning, {}) if args.output_format != 'json': guideline = format_guideline(guideline) if 'details' in args: rows.append(['', warning, '-', severity, guideline, '-']) else: rows.append([warning]) if rows: print(output_formatters.twodim_to_str(args.output_format, header, rows)) for analyzer_binary, reason in errored: LOG.error( "Failed to get checkers for '%s'!" "The error reason was: '%s'", analyzer_binary, reason) LOG.error("Please check your installation and the " "'config/package_layout.json' file!")
def __get_detailed_checker_info(args: argparse.Namespace, cl: CheckerLabels) -> Dict[str, list]: """ Returns a dictionary which maps analyzer names to the collection of their supported checkers. Checker information is described with tuples of this information: (status, checker name, analyzer name, description, labels). """ context = analyzer_context.get_context() working_analyzers, _ = analyzer_types.check_supported_analyzers( analyzer_types.supported_analyzers, context) analyzer_config_map = analyzer_types.build_config_handlers( args, context, working_analyzers) analyzer_environment = env.extend(context.path_env_extra, context.ld_lib_path_extra) checker_info = defaultdict(list) for analyzer in working_analyzers: config_handler = analyzer_config_map.get(analyzer) analyzer_class = analyzer_types.supported_analyzers[analyzer] checkers = analyzer_class.get_analyzer_checkers( config_handler, analyzer_environment) profile_checkers = [] if 'profile' in args: available_profiles = cl.get_description('profile') if args.profile not in available_profiles: LOG.error("Checker profile '%s' does not exist!", args.profile) LOG.error("To list available profiles, use '--profile list'.") sys.exit(1) profile_checkers.append((f'profile:{args.profile}', True)) if 'label' in args: profile_checkers.extend((label, True) for label in args.label) if 'severity' in args: profile_checkers.append((f'severity:{args.severity}', True)) if 'guideline' in args: profile_checkers.append((__guideline_to_label(args, cl), True)) config_handler.initialize_checkers(context, checkers, profile_checkers) for checker, (state, description) in config_handler.checks().items(): # severity = cl.severity(checker) # guideline = guideline_rules_for_checker(checker, context) # checker_info[analyzer].append( # (state, checker, analyzer, severity, guideline, description)) checker_info[analyzer].append( (state, checker, analyzer, description, sorted(cl.labels_of_checker(checker, analyzer)))) if 'show_warnings' in args: for warning in get_warnings(analyzer_environment): warning = 'clang-diagnostic-' + warning # guideline = guideline_rules_for_checker(warning, context) # checker_info[ClangTidy.ANALYZER_NAME].append( # (CheckerState.default, warning, ClangTidy.ANALYZER_NAME, # 'MEDIUM', guideline, '')) checker_info[ClangTidy.ANALYZER_NAME].append( (CheckerState.default, warning, ClangTidy.ANALYZER_NAME, '', sorted(cl.labels_of_checker(warning, ClangTidy.ANALYZER_NAME)))) return checker_info
def main(args): """ List the checkers available in the specified (or all supported) analyzers alongside with their description or enabled status in various formats. """ logger.setup_logger(args.verbose if 'verbose' in args else None) # If nothing is set, list checkers for all supported analyzers. analyzers = args.analyzers \ if 'analyzers' in args \ else analyzer_types.supported_analyzers context = analyzer_context.get_context() working, errored = analyzer_types.check_supported_analyzers(analyzers, context) analyzer_environment = get_check_env(context.path_env_extra, context.ld_lib_path_extra) analyzer_config_map = analyzer_types.build_config_handlers(args, context, working) # List available checker profiles. if 'profile' in args and args.profile == 'list': if 'details' not in args: if args.output_format not in ['csv', 'json']: header = ['Profile name'] else: header = ['profile_name'] else: if args.output_format not in ['csv', 'json']: header = ['Profile name', 'Description'] else: header = ['profile_name', 'description'] rows = [] for (profile, description) in context.available_profiles.items(): if 'details' not in args: rows.append([profile]) else: rows.append([profile, description]) print(output_formatters.twodim_to_str(args.output_format, header, rows)) return # Use good looking different headers based on format. if 'details' not in args: if args.output_format not in ['csv', 'json']: header = ['Name'] else: header = ['name'] else: if args.output_format not in ['csv', 'json']: header = ['', 'Name', 'Analyzer', 'Severity', 'Description'] else: header = ['enabled', 'name', 'analyzer', 'severity', 'description'] rows = [] for analyzer in working: config_handler = analyzer_config_map.get(analyzer) analyzer_class = \ analyzer_types.supported_analyzers[analyzer] checkers = analyzer_class.get_analyzer_checkers(config_handler, analyzer_environment) default_checker_cfg = context.checker_config.get( analyzer + '_checkers') profile_checkers = None if 'profile' in args: if args.profile not in context.available_profiles: LOG.error("Checker profile '%s' does not exist!", args.profile) LOG.error("To list available profiles, use '--profile list'.") return profile_checkers = [(args.profile, True)] config_handler.initialize_checkers(context.available_profiles, context.package_root, checkers, default_checker_cfg, profile_checkers) for checker_name, value in config_handler.checks().items(): enabled, description = value if not enabled and 'profile' in args: continue if enabled and 'only_disabled' in args: continue elif not enabled and 'only_enabled' in args: continue if args.output_format != 'json': enabled = '+' if enabled else '-' if 'details' not in args: rows.append([checker_name]) else: severity = context.severity_map.get(checker_name) rows.append([enabled, checker_name, analyzer, severity, description]) if len(rows) > 0: print(output_formatters.twodim_to_str(args.output_format, header, rows)) for analyzer_binary, reason in errored: LOG.error("Failed to get checkers for '%s'!" "The error reason was: '%s'", analyzer_binary, reason) LOG.error("Please check your installation and the " "'config/package_layout.json' file!")
def main(args): """ List the checkers available in the specified (or all supported) analyzers alongside with their description or enabled status in various formats. """ logger.setup_logger(args.verbose if 'verbose' in args else None) # If nothing is set, list checkers for all supported analyzers. analyzers = args.analyzers \ if 'analyzers' in args \ else analyzer_types.supported_analyzers context = analyzer_context.get_context() working, errored = analyzer_types.check_supported_analyzers(analyzers, context) analyzer_environment = get_check_env(context.path_env_extra, context.ld_lib_path_extra) analyzer_config_map = analyzer_types.build_config_handlers(args, context, working) # List available checker profiles. if 'profile' in args and args.profile == 'list': if 'details' not in args: if args.output_format not in ['csv', 'json']: header = ['Profile name'] else: header = ['profile_name'] else: if args.output_format not in ['csv', 'json']: header = ['Profile name', 'Description'] else: header = ['profile_name', 'description'] rows = [] for (profile, description) in context.available_profiles.items(): if 'details' not in args: rows.append([profile]) else: rows.append([profile, description]) print(output_formatters.twodim_to_str(args.output_format, header, rows)) return # Use good looking different headers based on format. if 'details' not in args: if args.output_format not in ['csv', 'json']: header = ['Name'] else: header = ['name'] else: if args.output_format not in ['csv', 'json']: header = ['', 'Name', 'Analyzer', 'Severity', 'Description'] else: header = ['enabled', 'name', 'analyzer', 'severity', 'description'] rows = [] for analyzer in working: config_handler = analyzer_config_map.get(analyzer) analyzer_class = \ analyzer_types.supported_analyzers[analyzer] checkers = analyzer_class.get_analyzer_checkers(config_handler, analyzer_environment) default_checker_cfg = context.checker_config.get( analyzer + '_checkers') profile_checkers = None if 'profile' in args: if args.profile not in context.available_profiles: LOG.error("Checker profile '%s' does not exist!", args.profile) LOG.error("To list available profiles, use '--profile list'.") sys.exit(1) profile_checkers = [(args.profile, True)] config_handler.initialize_checkers(context.available_profiles, context.package_root, checkers, default_checker_cfg, profile_checkers) for checker_name, value in config_handler.checks().items(): enabled, description = value if not enabled and 'profile' in args: continue if enabled and 'only_disabled' in args: continue elif not enabled and 'only_enabled' in args: continue if args.output_format != 'json': enabled = '+' if enabled else '-' if 'details' not in args: rows.append([checker_name]) else: severity = context.severity_map.get(checker_name) rows.append([enabled, checker_name, analyzer, severity, description]) if len(rows) > 0: print(output_formatters.twodim_to_str(args.output_format, header, rows)) for analyzer_binary, reason in errored: LOG.error("Failed to get checkers for '%s'!" "The error reason was: '%s'", analyzer_binary, reason) LOG.error("Please check your installation and the " "'config/package_layout.json' file!")
def main(args): """ List the checkers available in the specified (or all supported) analyzers alongside with their description or enabled status in various formats. """ # If the given output format is not 'table', redirect logger's output to # the stderr. logger.setup_logger(args.verbose if 'verbose' in args else None, None if args.output_format == 'table' else 'stderr') context = analyzer_context.get_context() working_analyzers, errored = analyzer_types.check_supported_analyzers( args.analyzers, context) analyzer_environment = env.extend(context.path_env_extra, context.ld_lib_path_extra) analyzer_config_map = analyzer_types.build_config_handlers( args, context, working_analyzers) def uglify(text): """ csv and json format output contain this non human readable header string: no CamelCase and no space. """ return text.lower().replace(' ', '_') # List available checker profiles. if 'profile' in args and args.profile == 'list': if 'details' in args: header = ['Profile name', 'Description'] rows = context.available_profiles.items() else: header = ['Profile name'] rows = [(key, "") for key in context.available_profiles.keys()] if args.output_format in ['csv', 'json']: header = list(map(uglify, header)) print(output_formatters.twodim_to_str(args.output_format, header, rows)) return # List checker config options. if 'checker_config' in args: if 'details' in args: header = ['Option', 'Description'] else: header = ['Option'] if args.output_format in ['csv', 'json']: header = list(map(uglify, header)) rows = [] for analyzer in working_analyzers: config_handler = analyzer_config_map.get(analyzer) analyzer_class = analyzer_types.supported_analyzers[analyzer] configs = analyzer_class.get_checker_config( config_handler, analyzer_environment) rows.extend( (':'.join((analyzer, c[0])), c[1]) if 'details' in args else (':'.join((analyzer, c[0])), ) for c in configs) print(output_formatters.twodim_to_str(args.output_format, header, rows)) return # List available checkers. if 'details' in args: header = ['Enabled', 'Name', 'Analyzer', 'Severity', 'Description'] else: header = ['Name'] if args.output_format in ['csv', 'json']: header = list(map(uglify, header)) rows = [] for analyzer in working_analyzers: config_handler = analyzer_config_map.get(analyzer) analyzer_class = analyzer_types.supported_analyzers[analyzer] checkers = analyzer_class.get_analyzer_checkers( config_handler, analyzer_environment) default_checker_cfg = context.checker_config.get(analyzer + '_checkers') profile_checkers = None if 'profile' in args: if args.profile not in context.available_profiles: LOG.error("Checker profile '%s' does not exist!", args.profile) LOG.error("To list available profiles, use '--profile list'.") sys.exit(1) profile_checkers = [(args.profile, True)] config_handler.initialize_checkers(context.available_profiles, context.package_root, checkers, default_checker_cfg, profile_checkers) for checker_name, value in config_handler.checks().items(): state, description = value if state != CheckerState.enabled and 'profile' in args: continue if state == CheckerState.enabled and 'only_disabled' in args: continue elif state != CheckerState.enabled and 'only_enabled' in args: continue if args.output_format == 'json': state = state == CheckerState.enabled else: state = '+' if state == CheckerState.enabled else '-' if 'details' in args: severity = context.severity_map.get(checker_name) rows.append( [state, checker_name, analyzer, severity, description]) else: rows.append([checker_name]) if 'show_warnings' in args: severity = context.severity_map.get('clang-diagnostic-') for warning in get_warnings(analyzer_environment): if 'details' in args: rows.append(['', warning, '-', severity, '-']) else: rows.append([warning]) if rows: print(output_formatters.twodim_to_str(args.output_format, header, rows)) for analyzer_binary, reason in errored: LOG.error( "Failed to get checkers for '%s'!" "The error reason was: '%s'", analyzer_binary, reason) LOG.error("Please check your installation and the " "'config/package_layout.json' file!")