Skip to content

Commit fbf611e

Browse files
committed
[clang-tidy] Extend spelling for CheckOptions
The current way to specify CheckOptions is pretty verbose and unintuitive. Given that the options are a dictionary it makes much more sense to treat them as such in the config files. Example: ``` CheckOptions: {SomeCheck.Option: true, SomeCheck.OtherOption: 'ignore'} # Or CheckOptions: SomeCheck.Option: true SomeCheck.OtherOption: 'ignore' ``` This change will still handle the old syntax with no issue, ensuring we don't screw up users current config files. The only observable differences are support for the new syntax and `-dump=config` will emit using the new syntax. Reviewed By: aaron.ballman Differential Revision: https://reviews.llvm.org/D128337
1 parent 148071f commit fbf611e

File tree

10 files changed

+80
-36
lines changed

10 files changed

+80
-36
lines changed

clang-tools-extra/clang-tidy/ClangTidyOptions.cpp

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,18 +81,52 @@ struct NOptionMap {
8181
std::vector<ClangTidyOptions::StringPair> Options;
8282
};
8383

84+
template <>
85+
void yamlize(IO &IO, ClangTidyOptions::OptionMap &Options, bool,
86+
EmptyContext &Ctx) {
87+
if (IO.outputting()) {
88+
IO.beginMapping();
89+
// Only output as a map
90+
for (auto &Key : Options) {
91+
bool UseDefault;
92+
void *SaveInfo;
93+
IO.preflightKey(Key.getKey().data(), true, false, UseDefault, SaveInfo);
94+
StringRef S = Key.getValue().Value;
95+
IO.scalarString(S, needsQuotes(S));
96+
IO.postflightKey(SaveInfo);
97+
}
98+
IO.endMapping();
99+
} else {
100+
// We need custom logic here to support the old method of specifying check
101+
// options using a list of maps containing key and value keys.
102+
Input &I = reinterpret_cast<Input &>(IO);
103+
if (isa<SequenceNode>(I.getCurrentNode())) {
104+
MappingNormalization<NOptionMap, ClangTidyOptions::OptionMap> NOpts(
105+
IO, Options);
106+
EmptyContext Ctx;
107+
yamlize(IO, NOpts->Options, true, Ctx);
108+
} else if (isa<MappingNode>(I.getCurrentNode())) {
109+
IO.beginMapping();
110+
for (StringRef Key : IO.keys()) {
111+
IO.mapRequired(Key.data(), Options[Key].Value);
112+
}
113+
IO.endMapping();
114+
} else {
115+
IO.setError("expected a sequence or map");
116+
}
117+
}
118+
}
119+
84120
template <> struct MappingTraits<ClangTidyOptions> {
85121
static void mapping(IO &IO, ClangTidyOptions &Options) {
86-
MappingNormalization<NOptionMap, ClangTidyOptions::OptionMap> NOpts(
87-
IO, Options.CheckOptions);
88122
bool Ignored = false;
89123
IO.mapOptional("Checks", Options.Checks);
90124
IO.mapOptional("WarningsAsErrors", Options.WarningsAsErrors);
91125
IO.mapOptional("HeaderFilterRegex", Options.HeaderFilterRegex);
92126
IO.mapOptional("AnalyzeTemporaryDtors", Ignored); // legacy compatibility
93127
IO.mapOptional("FormatStyle", Options.FormatStyle);
94128
IO.mapOptional("User", Options.User);
95-
IO.mapOptional("CheckOptions", NOpts->Options);
129+
IO.mapOptional("CheckOptions", Options.CheckOptions);
96130
IO.mapOptional("ExtraArgs", Options.ExtraArgs);
97131
IO.mapOptional("ExtraArgsBefore", Options.ExtraArgsBefore);
98132
IO.mapOptional("InheritParentConfig", Options.InheritParentConfig);

clang-tools-extra/clang-tidy/tool/ClangTidyMain.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@ Configuration files:
5252
InheritParentConfig: true
5353
User: user
5454
CheckOptions:
55-
- key: some-check.SomeOption
56-
value: 'some value'
55+
some-check.SomeOption: 'some value'
5756
...
5857
5958
)");
@@ -171,8 +170,7 @@ line or a specific configuration file.
171170
static cl::opt<std::string> Config("config", cl::desc(R"(
172171
Specifies a configuration in YAML/JSON format:
173172
-config="{Checks: '*',
174-
CheckOptions: [{key: x,
175-
value: y}]}"
173+
CheckOptions: {x: y}}"
176174
When the value is empty, clang-tidy will
177175
attempt to find a file named .clang-tidy for
178176
each source file in its parent directories.

clang-tools-extra/clang-tidy/tool/run-clang-tidy.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,8 +236,7 @@ def main():
236236
config_group.add_argument('-config', default=None,
237237
help='Specifies a configuration in YAML/JSON format: '
238238
' -config="{Checks: \'*\', '
239-
' CheckOptions: [{key: x, '
240-
' value: y}]}" '
239+
' CheckOptions: {x: y}}" '
241240
'When the value is empty, clang-tidy will '
242241
'attempt to find a file named .clang-tidy for '
243242
'each source file in its parent directories.')

clang-tools-extra/clangd/unittests/TidyProviderTests.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,20 +20,17 @@ TEST(TidyProvider, NestedDirectories) {
2020
FS.Files[testPath(".clang-tidy")] = R"yaml(
2121
Checks: 'llvm-*'
2222
CheckOptions:
23-
- key: TestKey
24-
value: 1
23+
TestKey: 1
2524
)yaml";
2625
FS.Files[testPath("sub1/.clang-tidy")] = R"yaml(
2726
Checks: 'misc-*'
2827
CheckOptions:
29-
- key: TestKey
30-
value: 2
28+
TestKey: 2
3129
)yaml";
3230
FS.Files[testPath("sub1/sub2/.clang-tidy")] = R"yaml(
3331
Checks: 'bugprone-*'
3432
CheckOptions:
35-
- key: TestKey
36-
value: 3
33+
TestKey: 3
3734
InheritParentConfig: true
3835
)yaml";
3936

clang-tools-extra/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ Improvements to clang-tidy
113113
- Added an option -verify-config which will check the config file to ensure each
114114
`Checks` and `CheckOptions` entries are recognised.
115115

116+
- .clang-tidy files can now use the more natural dictionary syntax for specifying `CheckOptions`.
117+
116118
New checks
117119
^^^^^^^^^^
118120

clang-tools-extra/docs/clang-tidy/Contributing.rst

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -519,17 +519,15 @@ be set in a ``.clang-tidy`` file in the following way:
519519
.. code-block:: yaml
520520
521521
CheckOptions:
522-
- key: my-check.SomeOption1
523-
value: 123
524-
- key: my-check.SomeOption2
525-
value: 'some other value'
522+
my-check.SomeOption1: 123
523+
my-check.SomeOption2: 'some other value'
526524
527525
If you need to specify check options on a command line, you can use the inline
528526
YAML format:
529527

530528
.. code-block:: console
531529
532-
$ clang-tidy -config="{CheckOptions: [{key: a, value: b}, {key: x, value: y}]}" ...
530+
$ clang-tidy -config="{CheckOptions: {a: b, x: y}}" ...
533531
534532
535533
Testing Checks

clang-tools-extra/docs/clang-tidy/index.rst

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,7 @@ An overview of all the command-line options:
135135
--config=<string> -
136136
Specifies a configuration in YAML/JSON format:
137137
-config="{Checks: '*',
138-
CheckOptions: [{key: x,
139-
value: y}]}"
138+
CheckOptions: {x, y}}"
140139
When the value is empty, clang-tidy will
141140
attempt to find a file named .clang-tidy for
142141
each source file in its parent directories.
@@ -295,8 +294,7 @@ An overview of all the command-line options:
295294
InheritParentConfig: true
296295
User: user
297296
CheckOptions:
298-
- key: some-check.SomeOption
299-
value: 'some value'
297+
some-check.SomeOption: 'some value'
300298
...
301299
302300
.. _clang-tidy-nolint:
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// RUN: clang-tidy -checks='-*,google*' -config='{}' -dump-config - -- | FileCheck %s
22
// CHECK: CheckOptions:
3-
// CHECK-DAG: {{- key: *google-readability-braces-around-statements.ShortStatementLines *[[:space:]] *value: *'1'}}
4-
// CHECK-DAG: {{- key: *google-readability-function-size.StatementThreshold *[[:space:]] *value: *'800'}}
5-
// CHECK-DAG: {{- key: *google-readability-namespace-comments.ShortNamespaceLines *[[:space:]] *value: *'10'}}
6-
// CHECK-DAG: {{- key: *google-readability-namespace-comments.SpacesBeforeComments *[[:space:]] *value: *'2'}}
3+
// CHECK-DAG: {{google-readability-braces-around-statements.ShortStatementLines: '1'}}
4+
// CHECK-DAG: {{google-readability-function-size.StatementThreshold: '800'}}
5+
// CHECK-DAG: {{google-readability-namespace-comments.ShortNamespaceLines: '10'}}
6+
// CHECK-DAG: {{google-readability-namespace-comments.SpacesBeforeComments: '2'}}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
InheritParentConfig: true
2+
Checks: 'llvm-qualified-auto'
3+
CheckOptions:
4+
modernize-loop-convert.MaxCopySize: '20'
5+
llvm-qualified-auto.AddConstToQualified: 'true'
6+
IgnoreMacros: 'false'
7+

clang-tools-extra/test/clang-tidy/infrastructure/config-files.cpp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,16 @@
1515
// CHECK-COMMAND-LINE: HeaderFilterRegex: from command line
1616

1717
// For this test we have to use names of the real checks because otherwise values are ignored.
18+
// Running with the old key: <Key>, value: <value> CheckOptions
1819
// RUN: clang-tidy -dump-config %S/Inputs/config-files/4/44/- -- | FileCheck %s -check-prefix=CHECK-CHILD4
20+
// Running with the new <key>: <value> syntax
21+
// RUN: clang-tidy -dump-config %S/Inputs/config-files/4/key-dict/- -- | FileCheck %s -check-prefix=CHECK-CHILD4
22+
1923
// CHECK-CHILD4: Checks: {{.*}}modernize-loop-convert,modernize-use-using,llvm-qualified-auto
20-
// CHECK-CHILD4-DAG: - key: llvm-qualified-auto.AddConstToQualified{{ *[[:space:]] *}}value: 'true'
21-
// CHECK-CHILD4-DAG: - key: modernize-loop-convert.MaxCopySize{{ *[[:space:]] *}}value: '20'
22-
// CHECK-CHILD4-DAG: - key: modernize-loop-convert.MinConfidence{{ *[[:space:]] *}}value: reasonable
23-
// CHECK-CHILD4-DAG: - key: modernize-use-using.IgnoreMacros{{ *[[:space:]] *}}value: 'false'
24+
// CHECK-CHILD4-DAG: llvm-qualified-auto.AddConstToQualified: 'true'
25+
// CHECK-CHILD4-DAG: modernize-loop-convert.MaxCopySize: '20'
26+
// CHECK-CHILD4-DAG: modernize-loop-convert.MinConfidence: reasonable
27+
// CHECK-CHILD4-DAG: modernize-use-using.IgnoreMacros: 'false'
2428

2529
// RUN: clang-tidy --explain-config %S/Inputs/config-files/4/44/- -- | FileCheck %s -check-prefix=CHECK-EXPLAIN
2630
// CHECK-EXPLAIN: 'llvm-qualified-auto' is enabled in the {{.*}}{{[/\\]}}Inputs{{[/\\]}}config-files{{[/\\]}}4{{[/\\]}}44{{[/\\]}}.clang-tidy.
@@ -32,14 +36,21 @@
3236
// RUN: Checks: -llvm-qualified-auto, \
3337
// RUN: CheckOptions: [{key: modernize-loop-convert.MaxCopySize, value: 21}]}' \
3438
// RUN: %S/Inputs/config-files/4/44/- -- | FileCheck %s -check-prefix=CHECK-CHILD5
39+
// Also test with the {Key: Value} Syntax specified on command line
40+
// RUN: clang-tidy -dump-config \
41+
// RUN: --config='{InheritParentConfig: true, \
42+
// RUN: Checks: -llvm-qualified-auto, \
43+
// RUN: CheckOptions: {modernize-loop-convert.MaxCopySize: 21}}' \
44+
// RUN: %S/Inputs/config-files/4/44/- -- | FileCheck %s -check-prefix=CHECK-CHILD5
45+
3546
// CHECK-CHILD5: Checks: {{.*}}modernize-loop-convert,modernize-use-using,llvm-qualified-auto,-llvm-qualified-auto
36-
// CHECK-CHILD5-DAG: - key: modernize-loop-convert.MaxCopySize{{ *[[:space:]] *}}value: '21'
37-
// CHECK-CHILD5-DAG: - key: modernize-loop-convert.MinConfidence{{ *[[:space:]] *}}value: reasonable
38-
// CHECK-CHILD5-DAG: - key: modernize-use-using.IgnoreMacros{{ *[[:space:]] *}}value: 'false'
47+
// CHECK-CHILD5-DAG: modernize-loop-convert.MaxCopySize: '21'
48+
// CHECK-CHILD5-DAG: modernize-loop-convert.MinConfidence: reasonable
49+
// CHECK-CHILD5-DAG: modernize-use-using.IgnoreMacros: 'false'
3950

4051
// RUN: clang-tidy -dump-config \
4152
// RUN: --config='{InheritParentConfig: false, \
4253
// RUN: Checks: -llvm-qualified-auto}' \
4354
// RUN: %S/Inputs/config-files/4/44/- -- | FileCheck %s -check-prefix=CHECK-CHILD6
4455
// CHECK-CHILD6: Checks: {{.*-llvm-qualified-auto'? *$}}
45-
// CHECK-CHILD6-NOT: - key: modernize-use-using.IgnoreMacros
56+
// CHECK-CHILD6-NOT: modernize-use-using.IgnoreMacros

0 commit comments

Comments
 (0)