From ddbb0d04e054f2ea1a062e2f2d7d5286b560c906 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 10 Feb 2026 21:23:09 -0800 Subject: [PATCH 1/2] Update shared query template to use QL modules instead of abstract classes. --- .../generate_rules/generate_package_files.py | 37 ++++++------------- .../templates/query.ql.template | 8 ++-- .../templates/shared_library.ql.template | 15 +++++--- .../templates/shared_library_test.ql.template | 8 ++++ 4 files changed, 33 insertions(+), 35 deletions(-) create mode 100644 scripts/generate_rules/templates/shared_library_test.ql.template diff --git a/scripts/generate_rules/generate_package_files.py b/scripts/generate_rules/generate_package_files.py index 862ccfdc1e..174d3365a5 100644 --- a/scripts/generate_rules/generate_package_files.py +++ b/scripts/generate_rules/generate_package_files.py @@ -120,7 +120,7 @@ repo_root = Path(__file__).parent.parent.parent rule_packages_file_path = repo_root.joinpath("rule_packages") env = Environment(loader=FileSystemLoader(Path(__file__).parent.joinpath( - "templates")), trim_blocks=True, lstrip_blocks=True) + "templates")), trim_blocks=True, lstrip_blocks=True, keep_trailing_newline=True) def write_shared_implementation(package_name, rule_id, query, language_name, ql_language_name, common_src_pack_dir, common_test_pack_dir, test_src_dir, skip_tests=False): @@ -164,6 +164,7 @@ def write_shared_implementation(package_name, rule_id, query, language_name, ql_ # Write out the test. Test are always stored under the `language_name` # directory. if not skip_tests: + shared_impl_test_dir = common_test_pack_dir.joinpath( "rules", shared_impl_dir_name @@ -176,31 +177,17 @@ def write_shared_implementation(package_name, rule_id, query, language_name, ql_ f"{query['shared_implementation_short_name']}.ql" ) - with open(shared_impl_test_query_path, "w", newline="\n") as f: - f.write("// GENERATED FILE - DO NOT MODIFY\n") - f.write( - "import " - + str(shared_impl_query_library_path.relative_to(common_src_pack_dir).with_suffix('')) - .replace("\\", "/") - .replace("/", ".") - + "\n" + shared_library_test_template = env.get_template( + "shared_library_test.ql.template" + ) + + if not shared_impl_test_query_path.exists(): + write_template( + shared_library_test_template, + query, + package_name, + shared_impl_test_query_path ) - f.write("\n") - class_name = str(query["shared_implementation_short_name"]) + "SharedQuery" - f.write("class TestFileQuery extends " + class_name + ",") - # ql formatting of this line depends on the line length - if len(class_name) > 61: - # Line break required after comma - f.write("\n TestQuery\n{ }\n") - elif len(class_name) == 61: - # Line break required before `{` - f.write(" TestQuery\n{ }\n") - elif len(class_name) > 57: - # Line break required after `{` - f.write(" TestQuery {\n}\n") - else: - # Under 100 characters, can be formatted on the same line - f.write(" TestQuery { }\n") # Create an empty test file, if one doesn't already exist shared_impl_test_dir.joinpath( diff --git a/scripts/generate_rules/templates/query.ql.template b/scripts/generate_rules/templates/query.ql.template index a387f41569..6b2bc0a90f 100644 --- a/scripts/generate_rules/templates/query.ql.template +++ b/scripts/generate_rules/templates/query.ql.template @@ -6,11 +6,11 @@ import codingstandards.{{ language_name }}.{{ standard_short_name }} {% if shared_implementation_short_name is defined %} import codingstandards.{{ ql_language_name }}.rules.{{ shared_implementation_short_name.lower() }}.{{ shared_implementation_short_name }} -class {{short_name}}Query extends {{shared_implementation_short_name}}SharedQuery { - {{short_name}}Query() { - this = {{package_name}}Package::{{shortname_camelcase}}Query() - } +module {{short_name}}Config implements {{shared_implementation_short_name}}ConfigSig { + Query getQuery() { result = {{package_name}}Package::{{shortname_camelcase}}Query() } } + +import {{shared_implementation_short_name}}<{{short_name}}Config> {% else %} from diff --git a/scripts/generate_rules/templates/shared_library.ql.template b/scripts/generate_rules/templates/shared_library.ql.template index 93dc503510..0ac54d7d0b 100644 --- a/scripts/generate_rules/templates/shared_library.ql.template +++ b/scripts/generate_rules/templates/shared_library.ql.template @@ -3,7 +3,8 @@ the first matching query in `rule_packages`. #} /** - * Provides a library with a `problems` predicate for the following issue: + * Provides a configurable module {{shared_implementation_short_name}} with a `problems` predicate + * for the following issue: * {{ description|join('\n * ') }} */ @@ -11,10 +12,12 @@ import cpp import codingstandards.{{ ql_language_name }}.Customizations import codingstandards.{{ ql_language_name }}.Exclusions -abstract class {{shared_implementation_short_name}}SharedQuery extends Query { } - -Query getQuery() { result instanceof {{shared_implementation_short_name}}SharedQuery } +signature module {{shared_implementation_short_name}}ConfigSig { + Query getQuery(); +} -query predicate problems(Element e, string message) { -not isExcluded(e, getQuery()) and message = "" +module {{shared_implementation_short_name}}<{{shared_implementation_short_name}}ConfigSig Config> { + query predicate problems(Element e, string message) { + not isExcluded(e, Config::getQuery()) and message = "" + } } diff --git a/scripts/generate_rules/templates/shared_library_test.ql.template b/scripts/generate_rules/templates/shared_library_test.ql.template new file mode 100644 index 0000000000..06c592b1ed --- /dev/null +++ b/scripts/generate_rules/templates/shared_library_test.ql.template @@ -0,0 +1,8 @@ +// GENERATED FILE - DO NOT MODIFY +import codingstandards.{{ ql_language_name }}.rules.{{ shared_implementation_short_name.lower() }}.{{ shared_implementation_short_name }} + +module TestFileConfig implements {{shared_implementation_short_name}}ConfigSig { + Query getQuery() { result instanceof TestQuery } +} + +import {{shared_implementation_short_name}} From f9c75154d734f4ea316f96dc0bc2e2c4996878d9 Mon Sep 17 00:00:00 2001 From: Mike Fairhurst Date: Tue, 10 Feb 2026 21:59:54 -0800 Subject: [PATCH 2/2] Fix indent in shared_library.ql.template --- .../generate_rules/templates/shared_library.ql.template | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scripts/generate_rules/templates/shared_library.ql.template b/scripts/generate_rules/templates/shared_library.ql.template index 0ac54d7d0b..c39f9f70bc 100644 --- a/scripts/generate_rules/templates/shared_library.ql.template +++ b/scripts/generate_rules/templates/shared_library.ql.template @@ -13,11 +13,11 @@ import codingstandards.{{ ql_language_name }}.Customizations import codingstandards.{{ ql_language_name }}.Exclusions signature module {{shared_implementation_short_name}}ConfigSig { - Query getQuery(); + Query getQuery(); } module {{shared_implementation_short_name}}<{{shared_implementation_short_name}}ConfigSig Config> { - query predicate problems(Element e, string message) { - not isExcluded(e, Config::getQuery()) and message = "" - } + query predicate problems(Element e, string message) { + not isExcluded(e, Config::getQuery()) and message = "" + } }