@@ -36,6 +36,7 @@ class LintArgs:
3636 issue_number : int = 0
3737 build_path : str = "build"
3838 clang_tidy_binary : str = "clang-tidy"
39+ doc8_binary : str = "doc8"
3940
4041 def __init__ (self , args : argparse .Namespace ) -> None :
4142 if args is not None :
@@ -50,6 +51,7 @@ def __init__(self, args: argparse.Namespace) -> None:
5051 self .verbose = args .verbose
5152 self .build_path = args .build_path
5253 self .clang_tidy_binary = args .clang_tidy_binary
54+ self .doc8_binary = args .doc8_binary
5355
5456
5557class LintHelper :
@@ -289,8 +291,59 @@ def _clean_clang_tidy_output(self, output: str) -> str:
289291 return ""
290292
291293
294+ class Doc8LintHelper (LintHelper ):
295+ name : Final = "doc8"
296+ friendly_name : Final = "documentation linter"
292297
293- ALL_LINTERS = (ClangTidyLintHelper (),)
298+ def instructions (self , files_to_lint : Sequence [str ], args : LintArgs ) -> str :
299+ files_str = " " .join (files_to_lint )
300+ return f"doc8 -q { files_str } "
301+
302+ def filter_changed_files (self , changed_files : Sequence [str ]) -> Sequence [str ]:
303+ filtered_files = []
304+ for filepath in changed_files :
305+ _ , ext = os .path .splitext (filepath )
306+ if ext != ".rst" :
307+ continue
308+ if not filepath .startswith ("clang-tools-extra/docs/clang-tidy/" ):
309+ continue
310+ if os .path .exists (filepath ):
311+ filtered_files .append (filepath )
312+ return filtered_files
313+
314+ def run_linter_tool (self , files_to_lint : Sequence [str ], args : LintArgs ) -> str :
315+ if not files_to_lint :
316+ return ""
317+
318+ doc8_cmd = [args .doc8_binary , "-q" ]
319+ doc8_cmd .extend (files_to_lint )
320+
321+ if args .verbose :
322+ print (f"Running doc8: { ' ' .join (doc8_cmd )} " )
323+
324+ proc = subprocess .run (
325+ doc8_cmd ,
326+ stdout = subprocess .PIPE ,
327+ stderr = subprocess .PIPE ,
328+ text = True ,
329+ check = False ,
330+ )
331+
332+ if proc .returncode == 0 :
333+ return ""
334+
335+ output = proc .stdout .strip ()
336+ if output :
337+ return output
338+
339+ error_output = proc .stderr .strip ()
340+ if error_output :
341+ return error_output
342+
343+ return f"doc8 exited with return code { proc .returncode } but no output."
344+
345+
346+ ALL_LINTERS = (ClangTidyLintHelper (), Doc8LintHelper ())
294347
295348
296349if __name__ == "__main__" :
@@ -331,6 +384,12 @@ def _clean_clang_tidy_output(self, output: str) -> str:
331384 default = "clang-tidy" ,
332385 help = "Path to clang-tidy binary" ,
333386 )
387+ parser .add_argument (
388+ "--doc8-binary" ,
389+ type = str ,
390+ default = "doc8" ,
391+ help = "Path to doc8 binary" ,
392+ )
334393 parser .add_argument (
335394 "--verbose" , action = "store_true" , default = True , help = "Verbose output"
336395 )
0 commit comments