# Buggy code
def check_supported_analyzers(analyzers, context):
    """
    Checks the given analyzers in the current context for their executability
    and support in CodeChecker.

    This method also updates the given context.analyzer_binaries if the
    context's configuration is bogus but had been resolved.

    :return: (enabled, failed) where enabled is a list of analyzer names
     and failed is a list of (analyzer, reason) tuple.
    """

    check_env = env.extend(context.path_env_extra, context.ld_lib_path_extra)

    analyzer_binaries = context.analyzer_binaries

    enabled_analyzers = set()
    failed_analyzers = set()

    for analyzer_name in analyzers:
        if analyzer_name not in supported_analyzers:
            failed_analyzers.add(
                (analyzer_name, "Analyzer unsupported by CodeChecker.")
            )
            continue

        # Get the compiler binary to check if it can run.
        available_analyzer = True
        analyzer_bin = analyzer_binaries.get(analyzer_name)
        if not analyzer_bin:
            failed_analyzers.add((analyzer_name, "Failed to detect analyzer binary."))
            available_analyzer = False
        elif not os.path.isabs(analyzer_bin):
            # If the analyzer is not in an absolute path, try to find it...
            found_bin = supported_analyzers[analyzer_name].resolve_missing_binary(
                analyzer_bin, check_env
            )

            # found_bin is an absolute path, an executable in one of the
            # PATH folders.
            # If found_bin is the same as the original binary, ie., normally
            # calling the binary without any search would have resulted in
            # the same binary being called, it's NOT a "not found".
            if found_bin and os.path.basename(found_bin) != analyzer_bin:
                LOG.debug(
                    "Configured binary '%s' for analyzer '%s' was "
                    "not found, but environment PATH contains '%s'.",
                    analyzer_bin,
                    analyzer_name,
                    found_bin,
                )
                context.analyzer_binaries[analyzer_name] = os.path.realpath(found_bin)

            analyzer_bin = found_bin

        if not analyzer_bin or not host_check.check_clang(analyzer_bin, check_env):
            # Analyzers unavailable under absolute paths are deliberately a
            # configuration problem.
            failed_analyzers.add((analyzer_name, "Cannot execute analyzer binary."))
            available_analyzer = False

        if available_analyzer:
            enabled_analyzers.add(analyzer_name)

    return enabled_analyzers, failed_analyzers


# Traceback (TypeError)
╰─ which clang
clang not found

╰─ which clang-tidy
~/LLVM/Build/bin/clang-tidy

╰─ ~/CodeChecker/build/CodeChecker/bin/CodeChecker check -l compile_commands.json --analyzers clang-tidy
'clang' binary can not be found in your PATH!
'clang' binary can not be found in your PATH!
[WARNING 2021-01-13 17:56] - 'clang' binary can not be found in your PATH!
[ERROR 2021-01-13 17:56] - Running check failed.
Traceback (most recent call last):
File "~/CodeChecker/build/CodeChecker/cc_bin/../lib/python3/codechecker_analyzer/cmd/check.py", line 819, in main
analysis_exit_status = analyze_module.main(analyze_args)
File "~/CodeChecker/build/CodeChecker/lib/python3/codechecker_analyzer/cmd/analyze.py", line 937, in main
analyzer_env)
File "~/CodeChecker/build/CodeChecker/lib/python3/codechecker_analyzer/analyzers/clangsa/version.py", line 73, in get
errors="ignore")
File "/usr/lib/python3.6/subprocess.py", line 356, in check_output
**kwargs).stdout
File "/usr/lib/python3.6/subprocess.py", line 423, in run
with Popen(*popenargs, **kwargs) as process:
File "/usr/lib/python3.6/subprocess.py", line 729, in __init__
restore_signals, start_new_session)
File "/usr/lib/python3.6/subprocess.py", line 1278, in _execute_child
executable = os.fsencode(executable)
File "/usr/lib/python3.6/os.py", line 800, in fsencode
filename = fspath(filename)  # Does type-checking of `filename`.
TypeError: expected str, bytes or os.PathLike object, not NoneType
Traceback (most recent call last):
File "~/CodeChecker/build/CodeChecker/cc_bin/../lib/python3/codechecker_analyzer/cmd/check.py", line 819, in main
analysis_exit_status = analyze_module.main(analyze_args)
File "~/CodeChecker/build/CodeChecker/lib/python3/codechecker_analyzer/cmd/analyze.py", line 937, in main
analyzer_env)
File "~/CodeChecker/build/CodeChecker/lib/python3/codechecker_analyzer/analyzers/clangsa/version.py", line 73, in get
errors="ignore")
File "/usr/lib/python3.6/subprocess.py", line 356, in check_output
**kwargs).stdout
File "/usr/lib/python3.6/subprocess.py", line 423, in run
with Popen(*popenargs, **kwargs) as process:
File "/usr/lib/python3.6/subprocess.py", line 729, in __init__
restore_signals, start_new_session)
File "/usr/lib/python3.6/subprocess.py", line 1278, in _execute_child
executable = os.fsencode(executable)
File "/usr/lib/python3.6/os.py", line 800, in fsencode
filename = fspath(filename)  # Does type-checking of `filename`.
TypeError: expected str, bytes or os.PathLike object, not NoneType
Traceback (most recent call last):
File "~/CodeChecker/build/CodeChecker/cc_bin/CodeChecker.py", line 141, in main
sys.exit(args.func(args))
File "~/CodeChecker/build/CodeChecker/cc_bin/../lib/python3/codechecker_analyzer/cmd/check.py", line 850, in main
return analysis_exit_status
UnboundLocalError: local variable 'analysis_exit_status' referenced before assignment

# Fixed code
def check_supported_analyzers(analyzers, context):
    """
    Checks the given analyzers in the current context for their executability
    and support in CodeChecker.

    This method also updates the given context.analyzer_binaries if the
    context's configuration is bogus but had been resolved.

    :return: (enabled, failed) where enabled is a list of analyzer names
     and failed is a list of (analyzer, reason) tuple.
    """

    check_env = env.extend(context.path_env_extra, context.ld_lib_path_extra)

    analyzer_binaries = context.analyzer_binaries

    enabled_analyzers = set()
    failed_analyzers = set()

    for analyzer_name in analyzers:
        if analyzer_name not in supported_analyzers:
            failed_analyzers.add(
                (analyzer_name, "Analyzer unsupported by CodeChecker!")
            )
            continue

        # Get the compiler binary to check if it can run.
        available_analyzer = True
        analyzer_bin = analyzer_binaries.get(analyzer_name)
        if not analyzer_bin:
            failed_analyzers.add((analyzer_name, "Failed to detect analyzer binary!"))
            continue
        elif not os.path.isabs(analyzer_bin):
            # If the analyzer is not in an absolute path, try to find it...
            found_bin = supported_analyzers[analyzer_name].resolve_missing_binary(
                analyzer_bin, check_env
            )

            # found_bin is an absolute path, an executable in one of the
            # PATH folders.
            # If found_bin is the same as the original binary, ie., normally
            # calling the binary without any search would have resulted in
            # the same binary being called, it's NOT a "not found".
            if found_bin and os.path.basename(found_bin) != analyzer_bin:
                LOG.debug(
                    "Configured binary '%s' for analyzer '%s' was "
                    "not found, but environment PATH contains '%s'.",
                    analyzer_bin,
                    analyzer_name,
                    found_bin,
                )
                context.analyzer_binaries[analyzer_name] = os.path.realpath(found_bin)

            analyzer_bin = found_bin

        if not analyzer_bin or not host_check.check_clang(analyzer_bin, check_env):
            # Analyzers unavailable under absolute paths are deliberately a
            # configuration problem.
            failed_analyzers.add((analyzer_name, "Cannot execute analyzer binary!"))
            available_analyzer = False

        if available_analyzer:
            enabled_analyzers.add(analyzer_name)

    return enabled_analyzers, failed_analyzers