scripts: Tidy linting tries to reduce filepaths
This CL makes tricium_clang_tidy attempt to find better file paths than
those reported by tidy that correspond to the same file.
BUG=b:241155489
TEST=lint_package --fetch-only
Change-Id: Ic94a3a9badfa8f2a2713dc8a4db78555175d5fea
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/4819573
Commit-Queue: Ryan Beltran <ryanbeltran@chromium.org>
Reviewed-by: George Burgess <gbiv@chromium.org>
Tested-by: Ryan Beltran <ryanbeltran@chromium.org>
diff --git a/scripts/tricium_clang_tidy.py b/scripts/tricium_clang_tidy.py
index c394e9b..fd9f182 100644
--- a/scripts/tricium_clang_tidy.py
+++ b/scripts/tricium_clang_tidy.py
@@ -54,6 +54,7 @@
from chromite.lib import build_target_lib
from chromite.lib import commandline
+from chromite.lib import constants
from chromite.lib import cros_build_lib
from chromite.lib import osutils
from chromite.lib import portage_util
@@ -63,6 +64,9 @@
# The directory under which the compiler wrapper stores clang-tidy reports.
LINT_BASE = Path("/tmp/linting_output/clang-tidy")
+PLATFORM_PATH = constants.CHROOT_SOURCE_ROOT / "src/platform"
+PLATFORM2_PATH = constants.CHROOT_SOURCE_ROOT / "src/platform2"
+
class TidyReplacement(NamedTuple):
"""Represents a replacement emitted by clang-tidy.
@@ -195,6 +199,63 @@
return LineOffsetMap(m.start() for m in re.finditer(r"\n", data))
+def transform_filepaths(
+ file_path: str, tidy_invocation_dir: Path
+) -> Optional[Path]:
+ """Try to transform a weird path into the true path via educated guessing.
+
+ Args:
+ file_path: The file path as reported by clang tidy.
+ tidy_invocation_dir: The working directory when tidy was invoked.
+
+ Returns:
+ Path which corresponds to input and exists or None.
+ """
+
+ if not file_path:
+ return None
+ path = Path(file_path)
+
+ def replace_path(pattern: str, replacement: str) -> Optional[Path]:
+ if pattern in file_path:
+ new_path = Path(re.sub(f"(^|.*/){pattern}", replacement, file_path))
+ if new_path.exists():
+ return new_path
+ return None
+
+ possible_replacements = (
+ # .../platform2 almost always refers to platform2 regardless of prefix.
+ ("platform2", PLATFORM2_PATH),
+ # .../usr/include/ sometimes refers to things in platform or platform2.
+ ("usr/include", PLATFORM2_PATH),
+ ("usr/include", PLATFORM_PATH),
+ # .../gen/include/ sometimes refers to things in platform or platform2.
+ ("gen/include", PLATFORM2_PATH),
+ ("gen/include", PLATFORM_PATH),
+ )
+
+ for pattern, replacement in possible_replacements:
+ path_guess = replace_path(pattern, str(replacement))
+ if path_guess:
+ return path_guess.resolve()
+
+ # Rarely (e.g., in the case of missing |#include|s, clang will emit relative
+ # file paths for diagnostics.
+ if path.is_absolute():
+ if path.exists():
+ return path.resolve()
+ else:
+ from_invocation_dir = tidy_invocation_dir / path
+ if from_invocation_dir.exists():
+ return from_invocation_dir.resolve()
+
+ logging.warning(
+ "Tidy referenced a file that cannot be located: %r",
+ file_path,
+ )
+ return path
+
+
def parse_tidy_fixes_file(
tidy_invocation_dir: Path, yaml_data: Any
) -> Iterable[TidyDiagnostic]:
@@ -240,28 +301,21 @@
cached_line_offsets[file_path] = offsets
return offsets
- # Rarely (e.g., in the case of missing |#include|s, clang will emit relative
- # file paths for diagnostics. This fixes those.
- def makeabs(file_path: str) -> Path:
- """Resolves a |file_path| emitted by clang-tidy to an absolute path."""
- if not file_path:
- return None
- path = Path(file_path)
- if not path.is_absolute():
- path = tidy_invocation_dir / path
- return path.resolve()
-
try:
for diag in yaml_data["Diagnostics"]:
message = diag["DiagnosticMessage"]
file_path = message["FilePath"]
- absolute_file_path = makeabs(file_path)
+ absolute_file_path = transform_filepaths(
+ file_path, tidy_invocation_dir
+ )
line_offsets = get_line_offsets(absolute_file_path)
replacements = []
for replacement in message.get("Replacements", ()):
- replacement_file_path = makeabs(replacement["FilePath"])
+ replacement_file_path = transform_filepaths(
+ replacement["FilePath"], tidy_invocation_dir
+ )
# FIXME(gbiv): This happens in practice with things like
# hicpp-member-init. Supporting it should be simple, but I'd
@@ -292,7 +346,9 @@
if not note["Message"].startswith("expanded from macro "):
continue
- absolute_note_path = makeabs(note["FilePath"])
+ absolute_note_path = transform_filepaths(
+ note["FilePath"], tidy_invocation_dir
+ )
note_offsets = get_line_offsets(absolute_note_path)
expansion_locs.append(
TidyExpandedFrom(