diff --git a/scripts/generate_rules/generate_package_files.py b/scripts/generate_rules/generate_package_files.py index 862ccfdc1..174d3365a 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 a387f4156..6b2bc0a90 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 93dc50351..c39f9f70b 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 000000000..06c592b1e --- /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}}