From 61743471d93051008eeaa1231e92c58322cfeea3 Mon Sep 17 00:00:00 2001 From: Ben Boeckel Date: Thu, 15 May 2025 15:21:27 +0200 Subject: [PATCH] ast-grep: add a rule to find adjacent string literals in cmStrCat calls --- .../cmstrcat-adjacent-literals-snapshot.yml | 312 ++++++++++++++++++ .../cmstrcat-adjacent-literals-test.yml | 39 +++ .../rules/cmstrcat-adjacent-literals.yml | 19 ++ Utilities/ast-grep/utils/cmstrcat-arg.yml | 23 ++ Utilities/ast-grep/utils/cmstrcat-call.yml | 5 + Utilities/ast-grep/utils/string-literal.yml | 13 + sgconfig.yml | 6 + 7 files changed, 417 insertions(+) create mode 100644 Utilities/ast-grep/rule-tests/__snapshots__/cmstrcat-adjacent-literals-snapshot.yml create mode 100644 Utilities/ast-grep/rule-tests/cmstrcat-adjacent-literals-test.yml create mode 100644 Utilities/ast-grep/rules/cmstrcat-adjacent-literals.yml create mode 100644 Utilities/ast-grep/utils/cmstrcat-arg.yml create mode 100644 Utilities/ast-grep/utils/cmstrcat-call.yml create mode 100644 Utilities/ast-grep/utils/string-literal.yml create mode 100644 sgconfig.yml diff --git a/Utilities/ast-grep/rule-tests/__snapshots__/cmstrcat-adjacent-literals-snapshot.yml b/Utilities/ast-grep/rule-tests/__snapshots__/cmstrcat-adjacent-literals-snapshot.yml new file mode 100644 index 0000000000..961e51079a --- /dev/null +++ b/Utilities/ast-grep/rule-tests/__snapshots__/cmstrcat-adjacent-literals-snapshot.yml @@ -0,0 +1,312 @@ +id: cmstrcat-adjacent-literals +snapshots: + cmStrCat("literal", "literal"): + labels: + - source: '"literal"' + style: primary + start: 9 + end: 18 + - source: cmStrCat("literal", "literal") + style: secondary + start: 0 + end: 30 + - source: ',' + style: secondary + start: 18 + end: 19 + - source: '"literal"' + style: secondary + start: 20 + end: 29 + cmStrCat("literal", "literal", "literal"): + labels: + - source: '"literal"' + style: primary + start: 9 + end: 18 + - source: cmStrCat("literal", "literal", "literal") + style: secondary + start: 0 + end: 41 + - source: ',' + style: secondary + start: 18 + end: 19 + - source: '"literal"' + style: secondary + start: 20 + end: 29 + cmStrCat("literal", "literal", "literal", variable): + labels: + - source: '"literal"' + style: primary + start: 9 + end: 18 + - source: cmStrCat("literal", "literal", "literal", variable) + style: secondary + start: 0 + end: 51 + - source: '"literal"' + style: secondary + start: 20 + end: 29 + cmStrCat("literal", "literal", variable): + labels: + - source: '"literal"' + style: primary + start: 9 + end: 18 + - source: cmStrCat("literal", "literal", variable) + style: secondary + start: 0 + end: 40 + - source: ',' + style: secondary + start: 18 + end: 19 + - source: '"literal"' + style: secondary + start: 20 + end: 29 + cmStrCat(variable, "literal", "literal" "literal"): + labels: + - source: '"literal"' + style: primary + start: 19 + end: 28 + - source: cmStrCat(variable, "literal", "literal" "literal") + style: secondary + start: 0 + end: 50 + - source: ',' + style: secondary + start: 28 + end: 29 + - source: '"literal" "literal"' + style: secondary + start: 30 + end: 49 + cmStrCat(variable, "literal", "literal"): + labels: + - source: '"literal"' + style: primary + start: 19 + end: 28 + - source: cmStrCat(variable, "literal", "literal") + style: secondary + start: 0 + end: 40 + - source: ',' + style: secondary + start: 28 + end: 29 + - source: '"literal"' + style: secondary + start: 30 + end: 39 + cmStrCat(variable, "literal", "literal", "literal"): + labels: + - source: '"literal"' + style: primary + start: 19 + end: 28 + - source: cmStrCat(variable, "literal", "literal", "literal") + style: secondary + start: 0 + end: 51 + - source: ',' + style: secondary + start: 28 + end: 29 + - source: '"literal"' + style: secondary + start: 30 + end: 39 + cmStrCat(variable, "literal", "literal", "literal", variable, "literal"): + labels: + - source: '"literal"' + style: primary + start: 19 + end: 28 + - source: cmStrCat(variable, "literal", "literal", "literal", variable, "literal") + style: secondary + start: 0 + end: 72 + - source: ',' + style: secondary + start: 28 + end: 29 + - source: '"literal"' + style: secondary + start: 30 + end: 39 + cmStrCat(variable, "literal", "literal", variable): + labels: + - source: '"literal"' + style: primary + start: 19 + end: 28 + - source: cmStrCat(variable, "literal", "literal", variable) + style: secondary + start: 0 + end: 50 + - source: ',' + style: secondary + start: 28 + end: 29 + - source: '"literal"' + style: secondary + start: 30 + end: 39 + cmStrCat(variable, "literal", "string_view"_s, variable): + labels: + - source: '"literal"' + style: primary + start: 19 + end: 28 + - source: cmStrCat(variable, "literal", "string_view"_s, variable) + style: secondary + start: 0 + end: 56 + - source: _s + style: secondary + start: 43 + end: 45 + - source: ',' + style: secondary + start: 28 + end: 29 + - source: '"string_view"_s' + style: secondary + start: 30 + end: 45 + cmStrCat(variable, "literal", 'l', variable): + labels: + - source: '"literal"' + style: primary + start: 19 + end: 28 + - source: cmStrCat(variable, "literal", 'l', variable) + style: secondary + start: 0 + end: 44 + - source: ',' + style: secondary + start: 28 + end: 29 + - source: '''l''' + style: secondary + start: 30 + end: 33 + cmStrCat(variable, "literal", R"(raw_literal)", variable): + labels: + - source: '"literal"' + style: primary + start: 19 + end: 28 + - source: cmStrCat(variable, "literal", R"(raw_literal)", variable) + style: secondary + start: 0 + end: 57 + - source: ',' + style: secondary + start: 28 + end: 29 + - source: R"(raw_literal)" + style: secondary + start: 30 + end: 46 + cmStrCat(variable, "string_view"_s, "literal", variable): + labels: + - source: '"string_view"_s' + style: primary + start: 19 + end: 34 + - source: _s + style: secondary + start: 32 + end: 34 + - source: cmStrCat(variable, "string_view"_s, "literal", variable) + style: secondary + start: 0 + end: 56 + - source: ',' + style: secondary + start: 34 + end: 35 + - source: '"literal"' + style: secondary + start: 36 + end: 45 + cmStrCat(variable, 'c', "literal" "literal"): + labels: + - source: '''c''' + style: primary + start: 19 + end: 22 + - source: cmStrCat(variable, 'c', "literal" "literal") + style: secondary + start: 0 + end: 44 + - source: ',' + style: secondary + start: 22 + end: 23 + - source: '"literal" "literal"' + style: secondary + start: 24 + end: 43 + cmStrCat(variable, 'c', "literal", variable): + labels: + - source: '''c''' + style: primary + start: 19 + end: 22 + - source: cmStrCat(variable, 'c', "literal", variable) + style: secondary + start: 0 + end: 44 + - source: ',' + style: secondary + start: 22 + end: 23 + - source: '"literal"' + style: secondary + start: 24 + end: 33 + cmStrCat(variable, 'c', 'l', variable): + labels: + - source: '''c''' + style: primary + start: 19 + end: 22 + - source: cmStrCat(variable, 'c', 'l', variable) + style: secondary + start: 0 + end: 38 + - source: ',' + style: secondary + start: 22 + end: 23 + - source: '''l''' + style: secondary + start: 24 + end: 27 + cmStrCat(variable, R"(raw_literal)", "literal", variable): + labels: + - source: R"(raw_literal)" + style: primary + start: 19 + end: 35 + - source: cmStrCat(variable, R"(raw_literal)", "literal", variable) + style: secondary + start: 0 + end: 57 + - source: ',' + style: secondary + start: 35 + end: 36 + - source: '"literal"' + style: secondary + start: 37 + end: 46 diff --git a/Utilities/ast-grep/rule-tests/cmstrcat-adjacent-literals-test.yml b/Utilities/ast-grep/rule-tests/cmstrcat-adjacent-literals-test.yml new file mode 100644 index 0000000000..a20a04dd5f --- /dev/null +++ b/Utilities/ast-grep/rule-tests/cmstrcat-adjacent-literals-test.yml @@ -0,0 +1,39 @@ +--- +id: cmstrcat-adjacent-literals +valid: + - 'cmStrCat("literal", variable)' + - 'cmStrCat(variable, "literal")' + - 'cmStrCat(variable, "literal", variable)' + - 'cmStrCat(variable, variable, "literal")' + - 'cmStrCat("literal", variable, variable)' + - 'cmStrCat(variable, "literal", variable)' + - 'cmStrCat("literal", binary + expr, "literal")' + - 'cmStrCat("literal", cond ? t : f, "literal")' + - 'cmStrCat("literal", field.expr, "literal")' + - 'cmStrCat("literal", identifier, "literal")' + - 'cmStrCat("literal", [lambda](){}, "literal")' + - 'cmStrCat("literal", 4, "literal")' + - 'cmStrCat("literal", (parens), "literal")' + - 'cmStrCat("literal", *ptr_expr, "literal")' + - 'cmStrCat("literal", qualified::ident, "literal")' + - 'cmStrCat("literal", subscript[expr], "literal")' + - 'cmStrCat("literal", +unary_expr, "literal")' + - 'cmStrCat("literal", ++update, "literal")' + - 'cmStrCat("literal", "udl"_unit, "literal")' +invalid: + - 'cmStrCat("literal", "literal")' + - 'cmStrCat("literal", "literal", "literal")' + - 'cmStrCat("literal", "literal", variable)' + - 'cmStrCat(variable, "literal", "literal")' + - 'cmStrCat(variable, "literal", "literal", "literal")' + - 'cmStrCat(variable, "literal", "literal", "literal", variable, "literal")' + - 'cmStrCat(variable, "literal", "literal", variable)' + - "cmStrCat(variable, \"literal\", 'l', variable)" + - "cmStrCat(variable, 'c', 'l', variable)" + - "cmStrCat(variable, 'c', \"literal\", variable)" + - "cmStrCat(variable, 'c', \"literal\" \"literal\")" + - 'cmStrCat(variable, "literal", "literal" "literal")' + - 'cmStrCat(variable, "literal", R"(raw_literal)", variable)' + - 'cmStrCat(variable, R"(raw_literal)", "literal", variable)' + - 'cmStrCat(variable, "literal", "string_view"_s, variable)' + - 'cmStrCat(variable, "string_view"_s, "literal", variable)' diff --git a/Utilities/ast-grep/rules/cmstrcat-adjacent-literals.yml b/Utilities/ast-grep/rules/cmstrcat-adjacent-literals.yml new file mode 100644 index 0000000000..bc001a36a7 --- /dev/null +++ b/Utilities/ast-grep/rules/cmstrcat-adjacent-literals.yml @@ -0,0 +1,19 @@ +--- +id: cmstrcat-adjacent-literals +language: Cpp +severity: warning +message: Adjacent `cmStrCat` arguments which are string literals should be combined +ignores: + - Utilities/ClangTidyModule/Tests/** +rule: + matches: string-literal + inside: + matches: cmstrcat-call + stopBy: + kind: call_expression + precedes: + matches: string-literal + follows: + pattern: ',' + stopBy: + matches: cmstrcat-arg diff --git a/Utilities/ast-grep/utils/cmstrcat-arg.yml b/Utilities/ast-grep/utils/cmstrcat-arg.yml new file mode 100644 index 0000000000..84160216eb --- /dev/null +++ b/Utilities/ast-grep/utils/cmstrcat-arg.yml @@ -0,0 +1,23 @@ +--- +id: cmstrcat-arg +language: Cpp +rule: + any: + - kind: binary_expression + - kind: call_expression + - kind: char_literal + - kind: concatenated_string + - kind: conditional_expression + - kind: field_expression + - kind: identifier + - kind: lambda_expression + - kind: number_literal + - kind: parenthesized_expression + - kind: pointer_expression + - kind: qualified_identifier + - kind: raw_string_literal + - kind: string_literal + - kind: subscript_expression + - kind: unary_expression + - kind: update_expression + - kind: user_defined_literal diff --git a/Utilities/ast-grep/utils/cmstrcat-call.yml b/Utilities/ast-grep/utils/cmstrcat-call.yml new file mode 100644 index 0000000000..34e68f9db7 --- /dev/null +++ b/Utilities/ast-grep/utils/cmstrcat-call.yml @@ -0,0 +1,5 @@ +--- +id: cmstrcat-call +language: Cpp +rule: + pattern: cmStrCat($$$) diff --git a/Utilities/ast-grep/utils/string-literal.yml b/Utilities/ast-grep/utils/string-literal.yml new file mode 100644 index 0000000000..1f6b557296 --- /dev/null +++ b/Utilities/ast-grep/utils/string-literal.yml @@ -0,0 +1,13 @@ +--- +id: string-literal +language: Cpp +rule: + any: + - kind: char_literal + - kind: concatenated_string + - kind: raw_string_literal + - kind: string_literal + - kind: user_defined_literal + has: + kind: literal_suffix + regex: '^_s$' diff --git a/sgconfig.yml b/sgconfig.yml new file mode 100644 index 0000000000..f340411733 --- /dev/null +++ b/sgconfig.yml @@ -0,0 +1,6 @@ +ruleDirs: +- Utilities/ast-grep/rules +testConfigs: +- testDir: Utilities/ast-grep/rule-tests +utilDirs: +- Utilities/ast-grep/utils