Beispiel #1
0
    def make_include_guard(self, config_file, name):
        """Returns properly formatted include guard based on repository root and
        file name.

        Keyword arguments:
        config_file -- Config object
        name -- file name string
        """
        repo_root_name_override = config_file.group("repoRootNameOverride")

        repo_root = Task.get_repo_root()
        guard_root = os.path.relpath(name, repo_root)
        if not repo_root_name_override:
            guard_path = os.path.basename(repo_root) + os.sep
        else:
            guard_path = repo_root_name_override[0] + os.sep
        include_roots = config_file.group("includeGuardRoots")

        if include_roots:
            prefix = ""
            for include_root in include_roots:
                if guard_root.startswith(
                        include_root) and len(include_root) > len(prefix):
                    prefix = include_root
            guard_path += guard_root[len(prefix):]
            return (regex.sub("[^a-zA-Z0-9]", "_", guard_path).upper() +
                    "_").lstrip("_")

        # No include guard roots matched, so append full name
        guard_path += guard_root
        return regex.sub("[^a-zA-Z0-9]", "_", guard_path).upper() + "_"
Beispiel #2
0
    def make_include_guard(self, config_file, name):
        """Returns properly formatted include guard based on repository root and
        file name.

        Keyword arguments:
        config_file -- Config object
        name -- file name string
        """
        repo_root = Task.get_repo_root()

        name = os.path.relpath(name, repo_root)
        guard_path = os.path.basename(repo_root) + "/"
        include_roots = config_file.group("includeGuardRoots")

        if include_roots:
            for include_root in include_roots:
                if name.startswith(include_root):
                    guard_path += name[len(include_root):]
                    return re.sub("[^a-zA-Z0-9]", "_",
                                  guard_path).upper() + "_"

        # No include guard roots matched, so append full name
        guard_path += name
        return re.sub("[^a-zA-Z0-9]", "_", guard_path).upper() + "_"
Beispiel #3
0
def main():
    # Parse command-line arguments
    parser = argparse.ArgumentParser(
        description=
        "Runs all formatting tasks on the code base. This should be invoked from a directory within the project."
    )
    parser.add_argument(
        "-v",
        dest="verbose1",
        action="store_true",
        help="verbosity level 1 (prints names of processed files)")
    parser.add_argument(
        "-vv",
        dest="verbose2",
        action="store_true",
        help=
        "verbosity level 2 (prints names of processed files and tasks run on them)"
    )
    parser.add_argument(
        "-j",
        dest="jobs",
        type=int,
        default=mp.cpu_count(),
        help="number of jobs to run (default is number of cores)")
    parser.add_argument(
        "-y",
        dest="year",
        type=int,
        default=date.today().year,
        help=
        "year to use when updating license headers (default is current year)")
    parser.add_argument(
        "-clang",
        dest="clang_version",
        type=str,
        default="",
        help=
        "version suffix for clang-format (invokes \"clang-format-CLANG_VERSION\" or \"clang-format\" if no suffix provided)"
    )
    parser.add_argument(
        "-f",
        dest="file",
        type=str,
        default="",
        nargs="+",
        help=
        "file or directory names (can be path relative to python invocation directory or absolute path)"
    )
    args = parser.parse_args()

    # All discovered files are relative to Git repo root directory, so find the
    # root.
    root_path = Task.get_repo_root()
    if root_path == "":
        print("Error: not invoked within a Git repository", file=sys.stderr)
        sys.exit(1)

    # If no files explicitly specified
    if not args.file:
        # Delete temporary files from previous incomplete run
        files = [
            os.path.join(dp, f)
            for dp, dn, fn in os.walk(root_path)
            for f in fn
            if f.endswith(".tmp")
        ]
        for f in files:
            os.remove(f)

        # Recursively create list of files in given directory
        files = [
            os.path.join(dp, f) for dp, dn, fn in os.walk(root_path) for f in fn
        ]

        if not files:
            print("Error: no files found to format", file=sys.stderr)
            sys.exit(1)
    else:
        files = []
        for name in args.file:
            # If a directory was specified, recursively expand it
            if os.path.isdir(name):
                files.extend([
                    os.path.join(dp, f)
                    for dp, dn, fn in os.walk(name)
                    for f in fn
                ])
            else:
                files.append(name)

    # Convert relative paths of files to absolute paths
    files = [os.path.abspath(name) for name in files]

    # Don't run tasks on Git metadata
    files = [name for name in files if os.sep + ".git" + os.sep not in name]

    # Don't check for changes in or run tasks on ignored files
    files = filter_ignored_files(files)

    # Create list of all changed files
    changed_file_list = []

    output_list = subprocess.run(
        ["git", "diff", "--name-only", "master"],
        stdout=subprocess.PIPE).stdout.split()
    for line in output_list:
        changed_file_list.append(root_path + os.sep +
                                 line.strip().decode("ascii"))

    # Don't run tasks on modifiable or generated files
    work = []
    for name in files:
        config_file = Config(os.path.dirname(name), ".styleguide")

        if config_file.is_modifiable_file(name):
            continue
        if config_file.is_generated_file(name):
            # Emit warning if a generated file was editted
            if name in changed_file_list:
                print("Warning: generated file '" + name + "' modified")
            continue

        work.append(name)
    files = work

    # If there are no files left, do nothing
    if len(files) == 0:
        sys.exit(0)

    # Prepare file batches for batch tasks
    chunksize = math.ceil(len(files) / args.jobs)
    file_batches = [
        files[i:i + chunksize] for i in range(0, len(files), chunksize)
    ]

    # IncludeOrder is run after Stdlib so any C std headers changed to C++ or
    # vice versa are sorted properly. ClangFormat is run after the other tasks
    # so it can clean up their formatting.
    task_pipeline = [
        BraceComment(),
        CIdentList(),
        IncludeGuard(),
        LicenseUpdate(str(args.year)),
        JavaClass(),
        Newline(),
        Stdlib(),
        IncludeOrder(),
        UsingDeclaration(),
        UsingNamespaceStd(),
        Whitespace()
    ]
    run_pipeline(task_pipeline, args, files)

    task_pipeline = [ClangFormat(args.clang_version)]
    run_batch(task_pipeline, args, file_batches)

    # These tasks fix clang-format formatting
    task_pipeline = [Jni()]
    run_pipeline(task_pipeline, args, files)

    # Lint is run last since previous tasks can affect its output.
    task_pipeline = [PyFormat(), Lint()]
    run_batch(task_pipeline, args, file_batches)
Beispiel #4
0
def test_includeguard():
    test = TaskTest(IncludeGuard())

    repo_root = os.path.basename(Task.get_repo_root()).upper()

    # Fix incorrect include guard
    test.add_input("./Test.h",
        "#ifndef WRONG_H" + os.linesep + \
        "#define WRONG_C" + os.linesep + \
        os.linesep + \
        "#endif" + os.linesep)
    test.add_output(
        "#ifndef " + repo_root + "_TEST_H_" + os.linesep + \
        "#define " + repo_root + "_TEST_H_" + os.linesep + \
        os.linesep + \
        "#endif  // " + repo_root + "_TEST_H_" + os.linesep, True, True)

    # Ensure nested preprocessor statements are handled properly for incorrect
    # include guard
    test.add_input("./Test.h",
        "#ifndef WRONG_H" + os.linesep + \
        "#define WRONG_C" + os.linesep + \
        os.linesep + \
        "#if SOMETHING" + os.linesep + \
        "// do something" + os.linesep + \
        "#endif" + os.linesep + \
        "#endif" + os.linesep)
    test.add_output(
        "#ifndef " + repo_root + "_TEST_H_" + os.linesep + \
        "#define " + repo_root + "_TEST_H_" + os.linesep + \
        os.linesep + \
        "#if SOMETHING" + os.linesep + \
        "// do something" + os.linesep + \
        "#endif" + os.linesep + \
        "#endif  // " + repo_root + "_TEST_H_" + os.linesep, True, True)

    # Don't touch correct include guard
    test.add_input("./Test.h",
        "#ifndef " + repo_root + "_TEST_H_" + os.linesep + \
        "#define " + repo_root + "_TEST_H_" + os.linesep + \
        os.linesep + \
        "#endif  // " + repo_root + "_TEST_H_" + os.linesep)
    test.add_latest_input_as_output(True)

    # Fail on missing include guard
    test.add_input("./Test.h", "// Empty file" + os.linesep)
    test.add_latest_input_as_output(False)

    # Verify pragma once counts as include guard
    test.add_input("./Test.h", "#pragma once" + os.linesep)
    test.add_latest_input_as_output(True)

    # Ensure include guard roots are processed correctly
    test.add_input("./Test.h",
        "#ifndef " + repo_root + "_WPIFORMAT_TEST_H_" + os.linesep + \
        "#define " + repo_root + "_WPIFORMAT_TEST_H_" + os.linesep + \
        os.linesep + \
        "#endif  // " + repo_root + "_WPIFORMAT_TEST_H_" + os.linesep)
    test.add_output(
        "#ifndef " + repo_root + "_TEST_H_" + os.linesep + \
        "#define " + repo_root + "_TEST_H_" + os.linesep + \
        os.linesep + \
        "#endif  // " + repo_root + "_TEST_H_" + os.linesep, True, True)

    # Ensure leading underscores are removed (this occurs if the user doesn't
    # include a trailing "/" in the include guard root)
    test.add_input("./Test/Test.h",
        "#ifndef " + repo_root + "_WPIFORMAT_TEST_TEST_H_" + os.linesep + \
        "#define " + repo_root + "_WPIFORMAT_TEST_TEST_H_" + os.linesep + \
        os.linesep + \
        "#endif  // " + repo_root + "_WPIFORMAT_TEST_TEST_H_" + os.linesep)
    test.add_output(
        "#ifndef " + repo_root + "_TEST_H_" + os.linesep + \
        "#define " + repo_root + "_TEST_H_" + os.linesep + \
        os.linesep + \
        "#endif  // " + repo_root + "_TEST_H_" + os.linesep, True, True)

    test.run(OutputType.FILE)