File: run_fixit.py

package info (click to toggle)
clazy 1.17-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 5,248 kB
  • sloc: cpp: 23,552; python: 1,450; xml: 450; sh: 237; makefile: 46
file content (120 lines) | stat: -rw-r--r-- 5,240 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# This is run sequentially, due to races. As clang-apply-replacements just applies all .yaml files it can find.
# We run a single clang-apply-replacements invocation, which changes all files in the tests/ directory.
import os
import shutil

from . import Args
from .checks import Check
from .os_utils import run_command, compare_files


def run_fixit_tests(requested_checks: list[Check], config: Args):

    success = patch_yaml_files(requested_checks, is_standalone=False, no_standalone=config.no_standalone, only_standalone=config.only_standalone)
    success = patch_yaml_files(requested_checks, is_standalone=True, no_standalone=config.no_standalone, only_standalone=config.only_standalone) and success

    for check in requested_checks:

        if not any(map(lambda test: test.should_run_fixits_test, check.tests)):
            continue

        # Call clazy-apply-replacements[.exe]
        if not run_clang_apply_replacements(check):
            return False

        # Now compare all the *.fixed files with the *.fixed.expected counterparts
        for test in check.tests:
            if test.should_run_fixits_test:
                # Check that the rewritten file is identical to the expected one
                if not compare_fixit_results(test, is_standalone=False, no_standalone=config.no_standalone, only_standalone=config.only_standalone, verbose=config.verbose):
                    success = False
                    continue

                if not compare_fixit_results(test, is_standalone=True, no_standalone=config.no_standalone, only_standalone=config.only_standalone, verbose=config.verbose):
                    success = False
                    continue

    return success

def compare_fixit_results(test, is_standalone: bool, no_standalone: bool, only_standalone: bool, verbose: bool):

    if (is_standalone and no_standalone) or (not is_standalone and only_standalone):
        # Nothing to do
        return True

    # Check that the rewritten file is identical to the expected one
    if not compare_files(False, test.expectedFixedFilename(), test.fixedFilename(is_standalone), test.printableName("", 0, is_standalone, False, True), verbose=verbose):
        return False

    # Some fixed cpp files have an header that was also fixed. Compare it here too.
    possible_headerfile_expected = test.expectedFixedFilename().replace('.cpp', '.h')
    if os.path.exists(possible_headerfile_expected):
        possible_headerfile = test.fixedFilename(is_standalone).replace('.cpp', '.h')
        if not compare_files(False, possible_headerfile_expected, possible_headerfile, test.printableName("", 0, is_standalone, False, True).replace('.cpp', '.h'), verbose=verbose):
            return False

    return True


# The yaml file references the test file in our git repo, but we don't want
# to rewrite that one, as we would need to discard git changes afterwards,
# so patch the yaml file and add a ".fixed" suffix to those files
def patch_fixit_yaml_file(test, is_standalone):
    yamlfilename = test.yamlFilename(is_standalone)
    fixedfilename = test.fixedFilename(is_standalone)

    f = open(yamlfilename, 'r')
    lines = f.readlines()
    f.close()
    f = open(yamlfilename, 'w')

    possible_headerfile = test.relativeFilename().replace(".cpp", ".h")

    for line in lines:
        stripped = line.strip()
        if stripped.startswith('MainSourceFile') or stripped.startswith("FilePath") or stripped.startswith("- FilePath"):
            line = line.replace(test.relativeFilename(), fixedfilename)

            # For Windows:
            line = line.replace(test.relativeFilename().replace(
                '/', '\\'), fixedfilename.replace('/', '\\'))

            # Some tests also apply fix their to their headers:
            if not test.relativeFilename().endswith(".hh"):
                line = line.replace(possible_headerfile,
                                    fixedfilename.replace(".cpp", ".h"))
        f.write(line)
    f.close()

    shutil.copyfile(test.relativeFilename(), fixedfilename)

    if os.path.exists(possible_headerfile):
        shutil.copyfile(possible_headerfile,
                        fixedfilename.replace(".cpp", ".h"))

    return True


def patch_yaml_files(requested_checks, is_standalone: bool, no_standalone: bool, only_standalone: bool):
    if (is_standalone and no_standalone) or (not is_standalone and only_standalone):
        # Nothing to do
        return True

    success = True
    for check in requested_checks:
        for test in check.tests:
            if test.should_run_fixits_test:
                yamlfilename = test.yamlFilename(is_standalone)
                if not os.path.exists(yamlfilename):
                    print("[FAIL] " + yamlfilename + " is missing!!")
                    success = False
                    continue
                if not patch_fixit_yaml_file(test, is_standalone):
                    print("[FAIL] Could not patch " + yamlfilename)
                    success = False
                    continue
    return success

def run_clang_apply_replacements(check):
    command = os.getenv('CLAZY_CLANG_APPLY_REPLACEMENTS', 'clang-apply-replacements')
    return run_command(command + ' ' + check.name)