[clang-tools-extra] 5568f28 - [clang-tidy][NFC] Update gen-static-analyzer-docs.py
Piotr Zegar via cfe-commits
cfe-commits at lists.llvm.org
Fri Aug 11 03:37:54 PDT 2023
Author: Piotr Zegar
Date: 2023-08-11T10:36:45Z
New Revision: 5568f28c868eb13033d64189560ee0e62d745285
URL: https://github.com/llvm/llvm-project/commit/5568f28c868eb13033d64189560ee0e62d745285
DIFF: https://github.com/llvm/llvm-project/commit/5568f28c868eb13033d64189560ee0e62d745285.diff
LOG: [clang-tidy][NFC] Update gen-static-analyzer-docs.py
Update gen-static-analyzer-docs.py to generate more proper documentation
for Clang Static Analyzer checkers.
Fixes: #43715
Added:
Modified:
clang-tools-extra/docs/clang-tidy/checks/gen-static-analyzer-docs.py
Removed:
################################################################################
diff --git a/clang-tools-extra/docs/clang-tidy/checks/gen-static-analyzer-docs.py b/clang-tools-extra/docs/clang-tidy/checks/gen-static-analyzer-docs.py
index 1e54cd53bc455c..92b89c1c173985 100644
--- a/clang-tools-extra/docs/clang-tidy/checks/gen-static-analyzer-docs.py
+++ b/clang-tools-extra/docs/clang-tidy/checks/gen-static-analyzer-docs.py
@@ -3,7 +3,6 @@
References Checkers.td to determine what checks exist
"""
-import argparse
import subprocess
import json
import os
@@ -12,28 +11,31 @@
"""Get path of script so files are always in correct directory"""
__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
+default_checkers_td_location = "../../../../clang/include/clang/StaticAnalyzer/Checkers/Checkers.td"
+default_checkers_rst_location = "../../../../clang/docs/analyzer/checkers.rst"
+
"""Get dict of checker related info and parse for full check names
Returns:
checkers: dict of checker info
"""
-
-
-def get_checkers(checkers_td_directory):
+def get_checkers(checkers_td, checkers_rst):
p = subprocess.Popen(
[
"llvm-tblgen",
"--dump-json",
"-I",
- checkers_td_directory,
- checkers_td_directory + "Checkers.td",
+ os.path.dirname(checkers_td),
+ checkers_td,
],
stdout=subprocess.PIPE,
)
table_entries = json.loads(p.communicate()[0])
documentable_checkers = []
checkers = table_entries["!instanceof"]["Checker"]
- packages = table_entries["!instanceof"]["Package"]
+
+ with open(checkers_rst, "r") as f:
+ checker_rst_text = f.read()
for checker_ in checkers:
checker = table_entries[checker_]
@@ -62,7 +64,9 @@ def get_checkers(checkers_td_directory):
if not hidden and "alpha" not in full_package_name.lower():
checker["FullPackageName"] = full_package_name
+ checker["ShortName"] = checker_package_prefix + "." + checker_name
checker["AnchorUrl"] = anchor_url
+ checker["Documentation"] = ".. _%s:" % (checker["ShortName"].replace(".","-")) in checker_rst_text
documentable_checkers.append(checker)
documentable_checkers.sort(key=lambda x: x["FullPackageName"])
@@ -73,17 +77,15 @@ def get_checkers(checkers_td_directory):
Args:
checker: Checker for which to generate documentation.
- only_help_text: Generate documentation based off the checker description.
- Used when there is no other documentation to link to.
+ has_documentation: Specify that there is other documentation to link to.
"""
+def generate_documentation(checker, has_documentation):
-
-def generate_documentation(checker, only_help_text=False):
with open(
- os.path.join(__location__, checker["FullPackageName"] + ".rst"), "w"
+ os.path.join(__location__, "clang-analyzer", checker["ShortName"] + ".rst"), "w"
) as f:
f.write(".. title:: clang-tidy - %s\n" % checker["FullPackageName"])
- if not only_help_text:
+ if has_documentation:
f.write(".. meta::\n")
f.write(
" :http-equiv=refresh: 5;URL=https://clang.llvm.org/docs/analyzer/checkers.html#%s\n"
@@ -92,18 +94,31 @@ def generate_documentation(checker, only_help_text=False):
f.write("\n")
f.write("%s\n" % checker["FullPackageName"])
f.write("=" * len(checker["FullPackageName"]) + "\n")
- f.write("\n")
- if only_help_text:
- f.write("%s\n" % checker["HelpText"])
- else:
+ help_text = checker["HelpText"].strip()
+ if not help_text.endswith("."):
+ help_text += "."
+ characters = 80
+ for word in help_text.split(" "):
+ if characters+len(word)+1 > 80:
+ characters = len(word)
+ f.write("\n")
+ f.write(word)
+ else:
+ f.write(" ")
+ f.write(word)
+ characters += len(word) + 1
+ f.write("\n\n")
+ if has_documentation:
f.write(
"The %s check is an alias, please see\n" % checker["FullPackageName"]
)
f.write(
- "`Clang Static Analyzer Available Checkers <https://clang.llvm.org/docs/analyzer/checkers.html#%s>`_\n"
+ "`Clang Static Analyzer Available Checkers\n<https://clang.llvm.org/docs/analyzer/checkers.html#%s>`_\n"
% checker["AnchorUrl"]
)
f.write("for more information.\n")
+ else:
+ f.write("The %s check is an alias of\nClang Static Analyzer %s.\n" % (checker["FullPackageName"], checker["ShortName"]));
f.close()
@@ -112,70 +127,44 @@ def generate_documentation(checker, only_help_text=False):
Args:
checkers: dict acquired from get_checkers()
"""
-
-
def update_documentation_list(checkers):
with open(os.path.join(__location__, "list.rst"), "r+") as f:
f_text = f.read()
- header, check_text = f_text.split(".. toctree::\n")
- checks = check_text.split("\n")
+ check_text = f_text.split(".. csv-table:: Aliases..\n")[1]
+ checks = [x for x in check_text.split("\n") if ":header:" not in x and x]
+ old_check_text = "\n".join(checks)
+ checks = [x for x in checks if "clang-analyzer-" not in x]
for checker in checkers:
- if (" %s" % checker["FullPackageName"]) not in checks:
- checks.append(" %s" % checker["FullPackageName"])
+ if checker["Documentation"]:
+ checks.append(" `%s <clang-analyzer/%s.html>`_, `Clang Static Analyzer %s <https://clang.llvm.org/docs/analyzer/checkers.html#%s>`_," % (checker["FullPackageName"],
+ checker["ShortName"], checker["ShortName"], checker["AnchorUrl"]))
+ else:
+ checks.append(" `%s <clang-analyzer/%s.html>`_, Clang Static Analyzer %s," % (checker["FullPackageName"], checker["ShortName"], checker["ShortName"]))
+
checks.sort()
# Overwrite file with new data
f.seek(0)
- f.write(header)
- f.write(".. toctree::")
- for check in checks:
- f.write("%s\n" % check)
+ f_text = f_text.replace(old_check_text, "\n".join(checks))
+ f.write(f_text)
f.close()
-default_path_monorepo = "../../../../clang/include/clang/StaticAnalyzer/Checkers/"
-default_path_in_tree = "../../../../../include/clang/StaticAnalyzer/Checkers/"
-
-
-def parse_arguments():
- """Set up and parse command-line arguments
- Returns:
- file_path: Path to Checkers.td"""
- usage = """Parse Checkers.td to generate documentation for static analyzer checks"""
- parse = argparse.ArgumentParser(description=usage)
-
- file_path_help = """Path to Checkers directory
- defaults to ../../../../clang/include/clang/StaticAnalyzer/Checkers/ if it exists
- then to ../../../../../include/clang/StaticAnalyzer/Checkers/"""
-
- default_path = None
- if os.path.exists(default_path_monorepo):
- default_path = default_path_monorepo
- elif os.path.exists(default_path_in_tree):
- default_path = default_path_in_tree
-
- parse.add_argument(
- "file", type=str, help=file_path_help, nargs="?", default=default_path
- )
- args = parse.parse_args()
-
- if args.file is None:
- print("Could not find Checkers directory. Please see -h")
+def main():
+ CheckersPath = os.path.join(__location__, default_checkers_td_location)
+ if not os.path.exists(CheckersPath):
+ print("Could not find Checkers.td under %s." % (os.path.abspath(CheckersPath)))
exit(1)
- return args.file
-
+ CheckersDoc = os.path.join(__location__, default_checkers_rst_location)
+ if not os.path.exists(CheckersDoc):
+ print("Could not find checkers.rst under %s." % (os.path.abspath(CheckersDoc)))
+ exit(1)
-def main():
- file_path = parse_arguments()
- checkers = get_checkers(file_path)
+ checkers = get_checkers(CheckersPath, CheckersDoc)
for checker in checkers:
- # No documentation nor alpha documentation
- if checker["Documentation"][1] == 0 and checker["Documentation"][0] == 0:
- generate_documentation(checker, True)
- else:
- generate_documentation(checker)
- print("Generated documentation for: %s" % checker["FullPackageName"])
+ generate_documentation(checker, checker["Documentation"])
+ print("Generated documentation for: %s" % (checker["FullPackageName"]))
update_documentation_list(checkers)
More information about the cfe-commits
mailing list