================
@@ -124,133 +96,260 @@ def create_comment_text(warning: str, cpp_files:
List[str]) -> str:
<details>
<summary>
-View the output from clang-tidy here.
+View the output from {self.name} here.
</summary>
```
-{warning}
+{linter_output}
```
</details>
"""
+ # TODO: Refactor this
+ def find_comment(self, pr: any) -> any:
+ all_linter_names = list(map(attrgetter("name"), ALL_LINTERS))
+ other_linter_names = [name for name in all_linter_names if name !=
self.name]
+
+ other_tags = [
+ self.COMMENT_TAG.format(linter=name) for name in other_linter_names
+ ]
+
+ for comment in pr.as_issue().get_comments():
+ body = comment.body
+ if self.comment_tag in body and not any(
+ other_tag in body for other_tag in other_tags
+ ):
+ return comment
+ return None
-def find_comment(pr: any) -> any:
- for comment in pr.as_issue().get_comments():
- if COMMENT_TAG in comment.body:
- return comment
- return None
+ def update_pr(self, comment_text: str, args: LintArgs, create_new: bool)
-> None:
+ import github
+ from github import IssueComment, PullRequest
+ repo = github.Github(args.token).get_repo(args.repo)
+ pr = repo.get_issue(args.issue_number).as_pull_request()
-def create_comment(
- comment_text: str, args: LintArgs, create_new: bool
-) -> Optional[dict]:
- import github
+ comment_text = self.comment_tag + "\n\n" + comment_text
- repo = github.Github(args.token).get_repo(args.repo)
- pr = repo.get_issue(args.issue_number).as_pull_request()
+ existing_comment = self.find_comment(pr)
- comment_text = COMMENT_TAG + "\n\n" + comment_text
+ if create_new or existing_comment:
+ self.comment = {"body": comment_text}
+ if existing_comment:
+ self.comment["id"] = existing_comment.id
- existing_comment = find_comment(pr)
- comment = None
- if create_new or existing_comment:
- comment = {"body": comment_text}
- if existing_comment:
- comment["id"] = existing_comment.id
- return comment
+ def run(self, args: LintArgs) -> bool:
+ if args.verbose:
+ print(f"got changed files: {args.changed_files}")
+ files_to_lint = self.filter_changed_files(args.changed_files)
-def run_clang_tidy(changed_files: List[str], args: LintArgs) -> Optional[str]:
- if not changed_files:
- print("no c/c++ files found")
- return None
+ if not files_to_lint and args.verbose:
+ print("no modified files found")
- git_diff_cmd = [
- "git",
- "diff",
- "-U0",
- f"{args.start_rev}...{args.end_rev}",
- "--",
- ] + changed_files
-
- diff_proc = subprocess.run(
- git_diff_cmd,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- text=True,
- check=False,
- )
+ is_success = True
+ linter_output = None
- if diff_proc.returncode != 0:
- print(f"Git diff failed: {diff_proc.stderr}")
- return None
+ if files_to_lint:
+ linter_output = self.run_linter_tool(files_to_lint, args)
+ if linter_output:
+ is_success = False
+
+ should_update_gh = args.token is not None and args.repo is not None
+
+ if is_success:
+ if should_update_gh:
+ comment_text = (
+ ":white_check_mark: With the latest revision "
+ f"this PR passed the {self.friendly_name}."
+ )
+ self.update_pr(comment_text, args, create_new=False)
+ return True
+ else:
+ if should_update_gh:
+ if linter_output:
+ comment_text = self.pr_comment_text_for_diff(
+ linter_output, files_to_lint, args
+ )
+ self.update_pr(comment_text, args, create_new=True)
+ else:
+ comment_text = (
+ f":warning: The {self.friendly_name} failed without
printing "
+ "an output. Check the logs for output. :warning:"
+ )
+ self.update_pr(comment_text, args, create_new=False)
+ else:
+ if linter_output:
+ print(
+ f"Warning: {self.friendly_name}, {self.name} detected "
+ "some issues with your code..."
+ )
+ print(linter_output)
+ else:
+ print(f"Warning: {self.friendly_name}, {self.name} failed
to run.")
+ return False
+
+
+class ClangTidyLintHelper(LintHelper):
+ name = "clang-tidy"
+ friendly_name = "C/C++ code linter"
+
+ def instructions(self, cpp_files: List[str], args: LintArgs) -> str:
+ files_str = " ".join(cpp_files)
+ return f"""
+git diff -U0 origin/main...HEAD -- {files_str} |
+python3 clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py \\
+ -path {args.build_path} -p1 -quiet"""
+
+ def filter_changed_files(self, changed_files: List[str]) -> List[str]:
+ clang_tidy_changed_files = [
+ arg for arg in changed_files if "third-party" not in arg
+ ]
+
+ filtered_files = []
+ for filepath in clang_tidy_changed_files:
+ _, ext = os.path.splitext(filepath)
+ if ext not in (".cpp", ".c", ".h", ".hpp", ".hxx", ".cxx"):
+ continue
+ if not self._should_lint_file(filepath):
+ continue
+ if os.path.exists(filepath):
+ filtered_files.append(filepath)
+ return filtered_files
+
+ def _should_lint_file(self, filepath: str) -> bool:
+ # TODO: Add more rules when enabling other projects to use clang-tidy
in CI.
+ return filepath.startswith("clang-tools-extra/clang-tidy/")
+
+ def run_linter_tool(self, cpp_files: List[str], args: LintArgs) ->
Optional[str]:
+ if not cpp_files:
+ return None
+
+ git_diff_cmd = [
+ "git",
+ "diff",
+ "-U0",
+ f"{args.start_rev}...{args.end_rev}",
+ "--",
+ ] + cpp_files
+
+ diff_proc = subprocess.run(
+ git_diff_cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ text=True,
+ check=False,
+ )
+
+ if diff_proc.returncode != 0:
+ print(f"Git diff failed: {diff_proc.stderr}")
+ return None
+
+ diff_content = diff_proc.stdout
+ if not diff_content.strip():
+ if args.verbose:
+ print("No diff content found")
+ return None
+
+ tidy_diff_cmd = [
+ "clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py",
+ "-path",
+ args.build_path,
+ "-p1",
+ "-quiet",
+ ]
- diff_content = diff_proc.stdout
- if not diff_content.strip():
- print("No diff content found")
+ if args.verbose:
+ print(f"Running clang-tidy-diff: {' '.join(tidy_diff_cmd)}")
+
+ proc = subprocess.run(
+ tidy_diff_cmd,
+ input=diff_content,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ text=True,
+ check=False,
+ )
+
+ clean_output = self._clean_clang_tidy_output(proc.stdout.strip())
+ return clean_output
+
+ def _clean_clang_tidy_output(self, output: str) -> Optional[str]:
+ if not output or output == "No relevant changes found.":
+ return None
+
+ lines = output.split("\n")
+ cleaned_lines = []
+
+ for line in lines:
+ if line.startswith("Running clang-tidy in") or
line.endswith("generated."):
+ continue
+
+ idx = line.rfind("llvm-project/")
+ if idx != -1:
+ line = line[idx + len("llvm-project/") :]
+
+ cleaned_lines.append(line)
+
+ if cleaned_lines:
+ return "\n".join(cleaned_lines)
return None
- tidy_diff_cmd = [
- "clang-tools-extra/clang-tidy/tool/clang-tidy-diff.py",
- "-path",
- args.build_path,
- "-p1",
- "-quiet",
- ]
-
- if args.verbose:
- print(f"Running clang-tidy-diff: {' '.join(tidy_diff_cmd)}")
-
- proc = subprocess.run(
- tidy_diff_cmd,
- input=diff_content,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- text=True,
- check=False,
- )
- return clean_clang_tidy_output(proc.stdout.strip())
+class Doc8LintHelper(LintHelper):
+ name = "doc8"
+ friendly_name = "documentation linter"
----------------
EugeneZelenko wrote:
`Final`.
https://github.com/llvm/llvm-project/pull/168827
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits