xref: /aosp_15_r20/build/bazel/rules/cc/clang_tidy.bzl (revision 7594170e27e0732bc44b93d1440d87a54b6ffe7c)
1*7594170eSAndroid Build Coastguard Worker# Copyright (C) 2022 The Android Open Source Project
2*7594170eSAndroid Build Coastguard Worker#
3*7594170eSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
4*7594170eSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
5*7594170eSAndroid Build Coastguard Worker# You may obtain a copy of the License at
6*7594170eSAndroid Build Coastguard Worker#
7*7594170eSAndroid Build Coastguard Worker#     http://www.apache.org/licenses/LICENSE-2.0
8*7594170eSAndroid Build Coastguard Worker#
9*7594170eSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
10*7594170eSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
11*7594170eSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*7594170eSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
13*7594170eSAndroid Build Coastguard Worker# limitations under the License.
14*7594170eSAndroid Build Coastguard Worker
15*7594170eSAndroid Build Coastguard Workerload("@bazel_skylib//lib:paths.bzl", "paths")
16*7594170eSAndroid Build Coastguard Workerload("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
17*7594170eSAndroid Build Coastguard Workerload(
18*7594170eSAndroid Build Coastguard Worker    "@bazel_tools//tools/build_defs/cc:action_names.bzl",
19*7594170eSAndroid Build Coastguard Worker    "CPP_COMPILE_ACTION_NAME",
20*7594170eSAndroid Build Coastguard Worker    "C_COMPILE_ACTION_NAME",
21*7594170eSAndroid Build Coastguard Worker)
22*7594170eSAndroid Build Coastguard Workerload("@bazel_tools//tools/cpp:toolchain_utils.bzl", "find_cpp_toolchain")
23*7594170eSAndroid Build Coastguard Workerload("@soong_injection//cc_toolchain:config_constants.bzl", "constants")
24*7594170eSAndroid Build Coastguard Workerload("//build/bazel/rules:common.bzl", "get_dep_targets")
25*7594170eSAndroid Build Coastguard Workerload(":cc_library_common.bzl", "get_compilation_args")
26*7594170eSAndroid Build Coastguard Worker
27*7594170eSAndroid Build Coastguard WorkerClangTidyInfo = provider(
28*7594170eSAndroid Build Coastguard Worker    "Info provided from clang-tidy actions",
29*7594170eSAndroid Build Coastguard Worker    fields = {
30*7594170eSAndroid Build Coastguard Worker        "tidy_files": "Outputs from the clang-tidy tool",
31*7594170eSAndroid Build Coastguard Worker        # TODO(b/282188514) stop propagating transitive tidy files after Bazel migration
32*7594170eSAndroid Build Coastguard Worker        "transitive_tidy_files": "Outputs from the clang-tidy tool for all transitive dependencies." +
33*7594170eSAndroid Build Coastguard Worker                                 " Currently, these are needed so that mixed-build targets can also run clang-tidy for their dependencies.",
34*7594170eSAndroid Build Coastguard Worker    },
35*7594170eSAndroid Build Coastguard Worker)
36*7594170eSAndroid Build Coastguard Worker
37*7594170eSAndroid Build Coastguard Worker_TIDY_GLOBAL_NO_CHECKS = constants.TidyGlobalNoChecks.split(",")
38*7594170eSAndroid Build Coastguard Worker_TIDY_GLOBAL_NO_ERROR_CHECKS = constants.TidyGlobalNoErrorChecks.split(",")
39*7594170eSAndroid Build Coastguard Worker_TIDY_DEFAULT_GLOBAL_CHECKS = constants.TidyDefaultGlobalChecks.split(",")
40*7594170eSAndroid Build Coastguard Worker_TIDY_EXTERNAL_VENDOR_CHECKS = constants.TidyExternalVendorChecks.split(",")
41*7594170eSAndroid Build Coastguard Worker_TIDY_DEFAULT_GLOBAL_CHECKS_NO_ANALYZER = constants.TidyDefaultGlobalChecks.split(",") + ["-clang-analyzer-*"]
42*7594170eSAndroid Build Coastguard Worker_TIDY_EXTRA_ARG_FLAGS = constants.TidyExtraArgFlags
43*7594170eSAndroid Build Coastguard Worker
44*7594170eSAndroid Build Coastguard Workerdef _check_bad_tidy_flags(tidy_flags):
45*7594170eSAndroid Build Coastguard Worker    """should be kept up to date with
46*7594170eSAndroid Build Coastguard Worker    https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/check.go;l=128;drc=b45a2ea782074944f79fc388df20b06e01f265f7
47*7594170eSAndroid Build Coastguard Worker    """
48*7594170eSAndroid Build Coastguard Worker    for flag in tidy_flags:
49*7594170eSAndroid Build Coastguard Worker        flag = flag.strip()
50*7594170eSAndroid Build Coastguard Worker        if not flag.startswith("-"):
51*7594170eSAndroid Build Coastguard Worker            fail("Flag `%s` must start with `-`" % flag)
52*7594170eSAndroid Build Coastguard Worker        if flag.startswith("-fix"):
53*7594170eSAndroid Build Coastguard Worker            fail("Flag `%s` is not allowed, since it could cause multiple writes to the same source file" % flag)
54*7594170eSAndroid Build Coastguard Worker        if flag.startswith("-checks="):
55*7594170eSAndroid Build Coastguard Worker            fail("Flag `%s` is not allowed, use `tidy_checks` property instead" % flag)
56*7594170eSAndroid Build Coastguard Worker        if "-warnings-as-errors=" in flag:
57*7594170eSAndroid Build Coastguard Worker            fail("Flag `%s` is not allowed, use `tidy_checks_as_errors` property instead" % flag)
58*7594170eSAndroid Build Coastguard Worker        if " " in flag:
59*7594170eSAndroid Build Coastguard Worker            fail("Bad flag: `%s` is not an allowed multi-word flag. Should it be split into multiple flags?" % flag)
60*7594170eSAndroid Build Coastguard Worker
61*7594170eSAndroid Build Coastguard Workerdef _check_bad_tidy_checks(tidy_checks):
62*7594170eSAndroid Build Coastguard Worker    """should be kept up to date with
63*7594170eSAndroid Build Coastguard Worker    https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/check.go;l=145;drc=b45a2ea782074944f79fc388df20b06e01f265f7
64*7594170eSAndroid Build Coastguard Worker    """
65*7594170eSAndroid Build Coastguard Worker    for check in tidy_checks:
66*7594170eSAndroid Build Coastguard Worker        if " " in check:
67*7594170eSAndroid Build Coastguard Worker            fail("Check `%s` invalid, cannot contain spaces" % check)
68*7594170eSAndroid Build Coastguard Worker        if "," in check:
69*7594170eSAndroid Build Coastguard Worker            fail("Check `%s` invalid, cannot contain commas. Split each entry into its own string instead" % check)
70*7594170eSAndroid Build Coastguard Worker
71*7594170eSAndroid Build Coastguard Workerdef _add_with_tidy_flags(ctx, tidy_flags):
72*7594170eSAndroid Build Coastguard Worker    with_tidy_flags = ctx.attr._with_tidy_flags[BuildSettingInfo].value
73*7594170eSAndroid Build Coastguard Worker    if with_tidy_flags:
74*7594170eSAndroid Build Coastguard Worker        return tidy_flags + with_tidy_flags
75*7594170eSAndroid Build Coastguard Worker    return tidy_flags
76*7594170eSAndroid Build Coastguard Worker
77*7594170eSAndroid Build Coastguard Workerdef _add_header_filter(ctx, tidy_flags):
78*7594170eSAndroid Build Coastguard Worker    """If TidyFlags does not contain -header-filter, add default header filter.
79*7594170eSAndroid Build Coastguard Worker    """
80*7594170eSAndroid Build Coastguard Worker    for flag in tidy_flags:
81*7594170eSAndroid Build Coastguard Worker        # Find the substring because the flag could also appear as --header-filter=...
82*7594170eSAndroid Build Coastguard Worker        # and with or without single or double quotes.
83*7594170eSAndroid Build Coastguard Worker        if "-header-filter=" in flag:
84*7594170eSAndroid Build Coastguard Worker            return tidy_flags
85*7594170eSAndroid Build Coastguard Worker
86*7594170eSAndroid Build Coastguard Worker    # Default header filter should include only the module directory,
87*7594170eSAndroid Build Coastguard Worker    # not the out/soong/.../ModuleDir/...
88*7594170eSAndroid Build Coastguard Worker    # Otherwise, there will be too many warnings from generated files in out/...
89*7594170eSAndroid Build Coastguard Worker    # If a module wants to see warnings in the generated source files,
90*7594170eSAndroid Build Coastguard Worker    # it should specify its own -header-filter flag.
91*7594170eSAndroid Build Coastguard Worker    default_dirs = ctx.attr._default_tidy_header_dirs[BuildSettingInfo].value
92*7594170eSAndroid Build Coastguard Worker    if default_dirs == "":
93*7594170eSAndroid Build Coastguard Worker        header_filter = "-header-filter=^" + ctx.label.package + "/"
94*7594170eSAndroid Build Coastguard Worker    else:
95*7594170eSAndroid Build Coastguard Worker        header_filter = "-header-filter=\"(^%s/|%s)\"" % (ctx.label.package, default_dirs)
96*7594170eSAndroid Build Coastguard Worker    return tidy_flags + [header_filter]
97*7594170eSAndroid Build Coastguard Worker
98*7594170eSAndroid Build Coastguard Workerdef _add_extra_arg_flags(tidy_flags):
99*7594170eSAndroid Build Coastguard Worker    return tidy_flags + ["-extra-arg-before=" + f for f in _TIDY_EXTRA_ARG_FLAGS]
100*7594170eSAndroid Build Coastguard Worker
101*7594170eSAndroid Build Coastguard Workerdef _add_quiet_if_not_global_tidy(ctx, tidy_flags):
102*7594170eSAndroid Build Coastguard Worker    tidy_checks = ctx.attr._tidy_checks[BuildSettingInfo].value
103*7594170eSAndroid Build Coastguard Worker    if not tidy_checks:
104*7594170eSAndroid Build Coastguard Worker        return tidy_flags + [
105*7594170eSAndroid Build Coastguard Worker            "-quiet",
106*7594170eSAndroid Build Coastguard Worker            "-extra-arg-before=-fno-caret-diagnostics",
107*7594170eSAndroid Build Coastguard Worker        ]
108*7594170eSAndroid Build Coastguard Worker    return tidy_flags
109*7594170eSAndroid Build Coastguard Worker
110*7594170eSAndroid Build Coastguard Workerdef _clang_rewrite_tidy_checks(tidy_checks):
111*7594170eSAndroid Build Coastguard Worker    # List of tidy checks that should be disabled globally. When the compiler is
112*7594170eSAndroid Build Coastguard Worker    # updated, some checks enabled by this module may be disabled if they have
113*7594170eSAndroid Build Coastguard Worker    # become more strict, or if they are a new match for a wildcard group like
114*7594170eSAndroid Build Coastguard Worker    # `modernize-*`.
115*7594170eSAndroid Build Coastguard Worker    clang_tidy_disable_checks = [
116*7594170eSAndroid Build Coastguard Worker        "misc-no-recursion",
117*7594170eSAndroid Build Coastguard Worker        "readability-function-cognitive-complexity",  # http://b/175055536
118*7594170eSAndroid Build Coastguard Worker    ]
119*7594170eSAndroid Build Coastguard Worker
120*7594170eSAndroid Build Coastguard Worker    tidy_checks = tidy_checks + ["-" + c for c in clang_tidy_disable_checks]
121*7594170eSAndroid Build Coastguard Worker
122*7594170eSAndroid Build Coastguard Worker    # clang-tidy does not allow later arguments to override earlier arguments,
123*7594170eSAndroid Build Coastguard Worker    # so if we just disabled an argument that was explicitly enabled we must
124*7594170eSAndroid Build Coastguard Worker    # remove the enabling argument from the list.
125*7594170eSAndroid Build Coastguard Worker    return [t for t in tidy_checks if t not in clang_tidy_disable_checks]
126*7594170eSAndroid Build Coastguard Worker
127*7594170eSAndroid Build Coastguard Workerdef _add_checks_for_dir(directory):
128*7594170eSAndroid Build Coastguard Worker    """should be kept up to date with
129*7594170eSAndroid Build Coastguard Worker    https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/config/tidy.go;l=170;drc=b45a2ea782074944f79fc388df20b06e01f265f7
130*7594170eSAndroid Build Coastguard Worker    """
131*7594170eSAndroid Build Coastguard Worker
132*7594170eSAndroid Build Coastguard Worker    # This is a map of local path prefixes to the set of default clang-tidy checks
133*7594170eSAndroid Build Coastguard Worker    # to be used.  This is like android.IsThirdPartyPath, but with more patterns.
134*7594170eSAndroid Build Coastguard Worker    # The last matched local_path_prefix should be the most specific to be used.
135*7594170eSAndroid Build Coastguard Worker    directory_checks = [
136*7594170eSAndroid Build Coastguard Worker        ("external/", _TIDY_EXTERNAL_VENDOR_CHECKS),
137*7594170eSAndroid Build Coastguard Worker        ("frameworks/compile/mclinker/", _TIDY_EXTERNAL_VENDOR_CHECKS),
138*7594170eSAndroid Build Coastguard Worker        ("hardware/", _TIDY_EXTERNAL_VENDOR_CHECKS),
139*7594170eSAndroid Build Coastguard Worker        ("hardware/google/", _TIDY_DEFAULT_GLOBAL_CHECKS),
140*7594170eSAndroid Build Coastguard Worker        ("hardware/interfaces/", _TIDY_DEFAULT_GLOBAL_CHECKS),
141*7594170eSAndroid Build Coastguard Worker        ("hardware/ril/", _TIDY_DEFAULT_GLOBAL_CHECKS),
142*7594170eSAndroid Build Coastguard Worker        ("hardware/libhardware", _TIDY_DEFAULT_GLOBAL_CHECKS),  # all 'hardware/libhardware*'
143*7594170eSAndroid Build Coastguard Worker        ("vendor/", _TIDY_EXTERNAL_VENDOR_CHECKS),
144*7594170eSAndroid Build Coastguard Worker        ("vendor/google", _TIDY_DEFAULT_GLOBAL_CHECKS),  # all 'vendor/google*'
145*7594170eSAndroid Build Coastguard Worker        ("vendor/google/external/", _TIDY_EXTERNAL_VENDOR_CHECKS),
146*7594170eSAndroid Build Coastguard Worker        ("vendor/google_arc/libs/org.chromium.arc.mojom", _TIDY_EXTERNAL_VENDOR_CHECKS),
147*7594170eSAndroid Build Coastguard Worker        ("vendor/google_devices/", _TIDY_EXTERNAL_VENDOR_CHECKS),  # many have vendor code
148*7594170eSAndroid Build Coastguard Worker    ]
149*7594170eSAndroid Build Coastguard Worker
150*7594170eSAndroid Build Coastguard Worker    for d, checks in reversed(directory_checks):
151*7594170eSAndroid Build Coastguard Worker        if directory.startswith(d):
152*7594170eSAndroid Build Coastguard Worker            return checks
153*7594170eSAndroid Build Coastguard Worker
154*7594170eSAndroid Build Coastguard Worker    return _TIDY_DEFAULT_GLOBAL_CHECKS
155*7594170eSAndroid Build Coastguard Worker
156*7594170eSAndroid Build Coastguard Workerdef _add_global_tidy_checks(ctx, local_checks, input_file):
157*7594170eSAndroid Build Coastguard Worker    tidy_checks = ctx.attr._tidy_checks[BuildSettingInfo].value
158*7594170eSAndroid Build Coastguard Worker    global_tidy_checks = []
159*7594170eSAndroid Build Coastguard Worker    if tidy_checks:
160*7594170eSAndroid Build Coastguard Worker        global_tidy_checks = tidy_checks
161*7594170eSAndroid Build Coastguard Worker    elif not input_file.is_source:
162*7594170eSAndroid Build Coastguard Worker        # don't run clang-tidy for generated files
163*7594170eSAndroid Build Coastguard Worker        global_tidy_checks = _TIDY_DEFAULT_GLOBAL_CHECKS_NO_ANALYZER
164*7594170eSAndroid Build Coastguard Worker    else:
165*7594170eSAndroid Build Coastguard Worker        global_tidy_checks = _add_checks_for_dir(ctx.label.package)
166*7594170eSAndroid Build Coastguard Worker
167*7594170eSAndroid Build Coastguard Worker    # If Tidy_checks contains "-*", ignore all checks before "-*".
168*7594170eSAndroid Build Coastguard Worker    for i, check in enumerate(local_checks):
169*7594170eSAndroid Build Coastguard Worker        if check == "-*":
170*7594170eSAndroid Build Coastguard Worker            global_tidy_checks = []
171*7594170eSAndroid Build Coastguard Worker            local_checks = local_checks[i:]
172*7594170eSAndroid Build Coastguard Worker
173*7594170eSAndroid Build Coastguard Worker    tidy_checks = global_tidy_checks + _clang_rewrite_tidy_checks(local_checks)
174*7594170eSAndroid Build Coastguard Worker    tidy_checks.extend(_TIDY_GLOBAL_NO_CHECKS)
175*7594170eSAndroid Build Coastguard Worker
176*7594170eSAndroid Build Coastguard Worker    #TODO(b/255747672) disable cert check on windows only
177*7594170eSAndroid Build Coastguard Worker    return tidy_checks
178*7594170eSAndroid Build Coastguard Worker
179*7594170eSAndroid Build Coastguard Workerdef _add_global_tidy_checks_as_errors(tidy_checks_as_errors):
180*7594170eSAndroid Build Coastguard Worker    return tidy_checks_as_errors + _TIDY_GLOBAL_NO_ERROR_CHECKS
181*7594170eSAndroid Build Coastguard Worker
182*7594170eSAndroid Build Coastguard Workerdef _create_clang_tidy_action(
183*7594170eSAndroid Build Coastguard Worker        ctx,
184*7594170eSAndroid Build Coastguard Worker        clang_tool,
185*7594170eSAndroid Build Coastguard Worker        input_file,
186*7594170eSAndroid Build Coastguard Worker        tidy_checks,
187*7594170eSAndroid Build Coastguard Worker        tidy_checks_as_errors,
188*7594170eSAndroid Build Coastguard Worker        tidy_flags,
189*7594170eSAndroid Build Coastguard Worker        clang_flags,
190*7594170eSAndroid Build Coastguard Worker        headers,
191*7594170eSAndroid Build Coastguard Worker        tidy_timeout):
192*7594170eSAndroid Build Coastguard Worker    tidy_flags = _add_with_tidy_flags(ctx, tidy_flags)
193*7594170eSAndroid Build Coastguard Worker    tidy_flags = _add_header_filter(ctx, tidy_flags)
194*7594170eSAndroid Build Coastguard Worker    tidy_flags = _add_extra_arg_flags(tidy_flags)
195*7594170eSAndroid Build Coastguard Worker    tidy_flags = _add_quiet_if_not_global_tidy(ctx, tidy_flags)
196*7594170eSAndroid Build Coastguard Worker    tidy_checks = _add_global_tidy_checks(ctx, tidy_checks, input_file)
197*7594170eSAndroid Build Coastguard Worker    tidy_checks_as_errors = _add_global_tidy_checks_as_errors(tidy_checks_as_errors)
198*7594170eSAndroid Build Coastguard Worker
199*7594170eSAndroid Build Coastguard Worker    _check_bad_tidy_checks(tidy_checks)
200*7594170eSAndroid Build Coastguard Worker    _check_bad_tidy_flags(tidy_flags)
201*7594170eSAndroid Build Coastguard Worker
202*7594170eSAndroid Build Coastguard Worker    args = ctx.actions.args()
203*7594170eSAndroid Build Coastguard Worker    args.add(input_file)
204*7594170eSAndroid Build Coastguard Worker    if tidy_checks:
205*7594170eSAndroid Build Coastguard Worker        args.add("-checks=" + ",".join(tidy_checks))
206*7594170eSAndroid Build Coastguard Worker    if tidy_checks_as_errors:
207*7594170eSAndroid Build Coastguard Worker        args.add("-warnings-as-errors=" + ",".join(tidy_checks_as_errors))
208*7594170eSAndroid Build Coastguard Worker    if tidy_flags:
209*7594170eSAndroid Build Coastguard Worker        args.add_all(tidy_flags)
210*7594170eSAndroid Build Coastguard Worker    args.add("--")
211*7594170eSAndroid Build Coastguard Worker    args.add_all(clang_flags)
212*7594170eSAndroid Build Coastguard Worker
213*7594170eSAndroid Build Coastguard Worker    tidy_file = ctx.actions.declare_file(paths.join(ctx.label.name, input_file.short_path + ".tidy"))
214*7594170eSAndroid Build Coastguard Worker    env = {
215*7594170eSAndroid Build Coastguard Worker        "CLANG_CMD": clang_tool,
216*7594170eSAndroid Build Coastguard Worker        "TIDY_FILE": tidy_file.path,
217*7594170eSAndroid Build Coastguard Worker    }
218*7594170eSAndroid Build Coastguard Worker    if tidy_timeout:
219*7594170eSAndroid Build Coastguard Worker        env["TIDY_TIMEOUT"] = tidy_timeout
220*7594170eSAndroid Build Coastguard Worker
221*7594170eSAndroid Build Coastguard Worker    ctx.actions.run(
222*7594170eSAndroid Build Coastguard Worker        inputs = [input_file] + headers,
223*7594170eSAndroid Build Coastguard Worker        outputs = [tidy_file],
224*7594170eSAndroid Build Coastguard Worker        arguments = [args],
225*7594170eSAndroid Build Coastguard Worker        env = env,
226*7594170eSAndroid Build Coastguard Worker        progress_message = "Running clang-tidy on {}".format(input_file.short_path),
227*7594170eSAndroid Build Coastguard Worker        tools = [
228*7594170eSAndroid Build Coastguard Worker            ctx.executable._clang_tidy,
229*7594170eSAndroid Build Coastguard Worker            ctx.executable._clang_tidy_real,
230*7594170eSAndroid Build Coastguard Worker        ],
231*7594170eSAndroid Build Coastguard Worker        executable = ctx.executable._clang_tidy_sh,
232*7594170eSAndroid Build Coastguard Worker        execution_requirements = {
233*7594170eSAndroid Build Coastguard Worker            "no-sandbox": "1",
234*7594170eSAndroid Build Coastguard Worker        },
235*7594170eSAndroid Build Coastguard Worker        mnemonic = "ClangTidy",
236*7594170eSAndroid Build Coastguard Worker    )
237*7594170eSAndroid Build Coastguard Worker
238*7594170eSAndroid Build Coastguard Worker    return tidy_file
239*7594170eSAndroid Build Coastguard Worker
240*7594170eSAndroid Build Coastguard Workerdef generate_clang_tidy_actions(
241*7594170eSAndroid Build Coastguard Worker        ctx,
242*7594170eSAndroid Build Coastguard Worker        flags,
243*7594170eSAndroid Build Coastguard Worker        deps,
244*7594170eSAndroid Build Coastguard Worker        srcs,
245*7594170eSAndroid Build Coastguard Worker        hdrs,
246*7594170eSAndroid Build Coastguard Worker        language,
247*7594170eSAndroid Build Coastguard Worker        tidy_flags,
248*7594170eSAndroid Build Coastguard Worker        tidy_checks,
249*7594170eSAndroid Build Coastguard Worker        tidy_checks_as_errors,
250*7594170eSAndroid Build Coastguard Worker        tidy_timeout):
251*7594170eSAndroid Build Coastguard Worker    """Generates actions for clang tidy
252*7594170eSAndroid Build Coastguard Worker
253*7594170eSAndroid Build Coastguard Worker    Args:
254*7594170eSAndroid Build Coastguard Worker        ctx (Context): rule context that is expected to contain
255*7594170eSAndroid Build Coastguard Worker            - ctx.executable._clang_tidy
256*7594170eSAndroid Build Coastguard Worker            - ctx.executable._clang_tidy_sh
257*7594170eSAndroid Build Coastguard Worker            - ctx.executable._clang_tidy_real
258*7594170eSAndroid Build Coastguard Worker            - ctx.label._with_tidy_flags
259*7594170eSAndroid Build Coastguard Worker        flags (list[str]): list of target-specific (non-toolchain) flags passed
260*7594170eSAndroid Build Coastguard Worker            to clang compile action
261*7594170eSAndroid Build Coastguard Worker        deps (list[Target]): list of Targets which provide headers to
262*7594170eSAndroid Build Coastguard Worker            compilation context
263*7594170eSAndroid Build Coastguard Worker        srcs (list[File]): list of srcs to which clang-tidy will be applied
264*7594170eSAndroid Build Coastguard Worker        hdrs (list[File]): list of headers used by srcs. This is used to provide
265*7594170eSAndroid Build Coastguard Worker            explicit inputs to the action
266*7594170eSAndroid Build Coastguard Worker        language (str): must be one of ["c++", "c"]. This is used to decide what
267*7594170eSAndroid Build Coastguard Worker            toolchain arguments are passed to the clang compile action
268*7594170eSAndroid Build Coastguard Worker        tidy_flags (list[str]): additional flags to pass to the clang-tidy tool
269*7594170eSAndroid Build Coastguard Worker        tidy_checks (list[str]): list of checks for clang-tidy to perform
270*7594170eSAndroid Build Coastguard Worker        tidy_checks_as_errors (list[str]): list of checks to pass as
271*7594170eSAndroid Build Coastguard Worker            "-warnings-as-errors" to clang-tidy
272*7594170eSAndroid Build Coastguard Worker        tidy_checks_as_errors (str): timeout to pass to clang-tidy tool
273*7594170eSAndroid Build Coastguard Worker        tidy_timeout (str): timeout in seconds after which to stop a clang-tidy
274*7594170eSAndroid Build Coastguard Worker            invocation
275*7594170eSAndroid Build Coastguard Worker    Returns:
276*7594170eSAndroid Build Coastguard Worker        tidy_file_outputs: (list[File]): list of .tidy files output by the
277*7594170eSAndroid Build Coastguard Worker            clang-tidy.sh tool
278*7594170eSAndroid Build Coastguard Worker    """
279*7594170eSAndroid Build Coastguard Worker    toolchain = find_cpp_toolchain(ctx)
280*7594170eSAndroid Build Coastguard Worker    feature_config = cc_common.configure_features(
281*7594170eSAndroid Build Coastguard Worker        ctx = ctx,
282*7594170eSAndroid Build Coastguard Worker        cc_toolchain = toolchain,
283*7594170eSAndroid Build Coastguard Worker        language = "c++",
284*7594170eSAndroid Build Coastguard Worker        requested_features = ctx.features,
285*7594170eSAndroid Build Coastguard Worker        unsupported_features = ctx.disabled_features,
286*7594170eSAndroid Build Coastguard Worker    )
287*7594170eSAndroid Build Coastguard Worker
288*7594170eSAndroid Build Coastguard Worker    language = language
289*7594170eSAndroid Build Coastguard Worker    action_name = ""
290*7594170eSAndroid Build Coastguard Worker    if language == "c++":
291*7594170eSAndroid Build Coastguard Worker        action_name = CPP_COMPILE_ACTION_NAME
292*7594170eSAndroid Build Coastguard Worker    elif language == "c":
293*7594170eSAndroid Build Coastguard Worker        action_name = C_COMPILE_ACTION_NAME
294*7594170eSAndroid Build Coastguard Worker    else:
295*7594170eSAndroid Build Coastguard Worker        fail("invalid language:", language)
296*7594170eSAndroid Build Coastguard Worker
297*7594170eSAndroid Build Coastguard Worker    dep_info = cc_common.merge_cc_infos(direct_cc_infos = [d[CcInfo] for d in deps])
298*7594170eSAndroid Build Coastguard Worker    compilation_ctx = dep_info.compilation_context
299*7594170eSAndroid Build Coastguard Worker    args = get_compilation_args(
300*7594170eSAndroid Build Coastguard Worker        toolchain = toolchain,
301*7594170eSAndroid Build Coastguard Worker        feature_config = feature_config,
302*7594170eSAndroid Build Coastguard Worker        flags = flags,
303*7594170eSAndroid Build Coastguard Worker        compilation_ctx = compilation_ctx,
304*7594170eSAndroid Build Coastguard Worker        action_name = action_name,
305*7594170eSAndroid Build Coastguard Worker    )
306*7594170eSAndroid Build Coastguard Worker
307*7594170eSAndroid Build Coastguard Worker    clang_tool = cc_common.get_tool_for_action(
308*7594170eSAndroid Build Coastguard Worker        feature_configuration = feature_config,
309*7594170eSAndroid Build Coastguard Worker        action_name = action_name,
310*7594170eSAndroid Build Coastguard Worker    )
311*7594170eSAndroid Build Coastguard Worker
312*7594170eSAndroid Build Coastguard Worker    header_inputs = (
313*7594170eSAndroid Build Coastguard Worker        hdrs +
314*7594170eSAndroid Build Coastguard Worker        compilation_ctx.headers.to_list() +
315*7594170eSAndroid Build Coastguard Worker        compilation_ctx.direct_headers +
316*7594170eSAndroid Build Coastguard Worker        compilation_ctx.direct_private_headers +
317*7594170eSAndroid Build Coastguard Worker        compilation_ctx.direct_public_headers +
318*7594170eSAndroid Build Coastguard Worker        compilation_ctx.direct_textual_headers
319*7594170eSAndroid Build Coastguard Worker    )
320*7594170eSAndroid Build Coastguard Worker
321*7594170eSAndroid Build Coastguard Worker    tidy_file_outputs = []
322*7594170eSAndroid Build Coastguard Worker    for src in srcs:
323*7594170eSAndroid Build Coastguard Worker        tidy_file = _create_clang_tidy_action(
324*7594170eSAndroid Build Coastguard Worker            ctx = ctx,
325*7594170eSAndroid Build Coastguard Worker            input_file = src,
326*7594170eSAndroid Build Coastguard Worker            headers = header_inputs,
327*7594170eSAndroid Build Coastguard Worker            clang_tool = paths.basename(clang_tool),
328*7594170eSAndroid Build Coastguard Worker            tidy_checks = tidy_checks,
329*7594170eSAndroid Build Coastguard Worker            tidy_checks_as_errors = tidy_checks_as_errors,
330*7594170eSAndroid Build Coastguard Worker            tidy_flags = tidy_flags,
331*7594170eSAndroid Build Coastguard Worker            clang_flags = args,
332*7594170eSAndroid Build Coastguard Worker            tidy_timeout = tidy_timeout,
333*7594170eSAndroid Build Coastguard Worker        )
334*7594170eSAndroid Build Coastguard Worker        tidy_file_outputs.append(tidy_file)
335*7594170eSAndroid Build Coastguard Worker
336*7594170eSAndroid Build Coastguard Worker    return tidy_file_outputs
337*7594170eSAndroid Build Coastguard Worker
338*7594170eSAndroid Build Coastguard Workerdef collect_deps_clang_tidy_info(ctx):
339*7594170eSAndroid Build Coastguard Worker    transitive_clang_tidy_files = []
340*7594170eSAndroid Build Coastguard Worker    for attr_deps in get_dep_targets(ctx.attr, predicate = lambda target: ClangTidyInfo in target).values():
341*7594170eSAndroid Build Coastguard Worker        for dep in attr_deps:
342*7594170eSAndroid Build Coastguard Worker            transitive_clang_tidy_files.append(dep[ClangTidyInfo].transitive_tidy_files)
343*7594170eSAndroid Build Coastguard Worker    return ClangTidyInfo(
344*7594170eSAndroid Build Coastguard Worker        tidy_files = depset(),
345*7594170eSAndroid Build Coastguard Worker        transitive_tidy_files = depset(transitive = transitive_clang_tidy_files),
346*7594170eSAndroid Build Coastguard Worker    )
347*7594170eSAndroid Build Coastguard Worker
348*7594170eSAndroid Build Coastguard Workerdef _never_tidy_for_dir(directory):
349*7594170eSAndroid Build Coastguard Worker    # should stay up to date with https://cs.android.com/android/platform/superproject/+/master:build/soong/cc/config/tidy.go;l=227;drc=f5864ba3633fdbadfb434483848887438fc11f59
350*7594170eSAndroid Build Coastguard Worker    return directory.startswith("external/grpc-grpc")
351*7594170eSAndroid Build Coastguard Worker
352*7594170eSAndroid Build Coastguard Workerdef clang_tidy_for_dir(allow_external_vendor, directory):
353*7594170eSAndroid Build Coastguard Worker    return not _never_tidy_for_dir(directory) and (
354*7594170eSAndroid Build Coastguard Worker        allow_external_vendor or _add_checks_for_dir(directory) != _TIDY_EXTERNAL_VENDOR_CHECKS
355*7594170eSAndroid Build Coastguard Worker    )
356