Skip to content

Commit 57cee19

Browse files
committed
[clangd] Add CodePatterns config option under Completion
Allows enabling/disabling code patterns & snippets suggestion from completion. This can be done either with YAML config or CLI with --code-patterns
1 parent d0cd6f3 commit 57cee19

10 files changed

+87
-1
lines changed

clang-tools-extra/clangd/ClangdServer.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -457,6 +457,7 @@ void ClangdServer::codeComplete(PathRef File, Position Pos,
457457
CodeCompleteOpts.ArgumentLists = Config::current().Completion.ArgumentLists;
458458
CodeCompleteOpts.InsertIncludes =
459459
Config::current().Completion.HeaderInsertion;
460+
CodeCompleteOpts.CodePatterns = Config::current().Completion.CodePatterns;
460461
// FIXME(ibiryukov): even if Preamble is non-null, we may want to check
461462
// both the old and the new version in case only one of them matches.
462463
CodeCompleteResult Result = clangd::codeComplete(

clang-tools-extra/clangd/CodeComplete.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,10 @@ struct CompletionRecorder : public CodeCompleteConsumer {
950950
// Retain the results we might want.
951951
for (unsigned I = 0; I < NumResults; ++I) {
952952
auto &Result = InResults[I];
953+
if (Config::current().Completion.CodePatterns ==
954+
Config::CodePatternsPolicy::None &&
955+
Result.Kind == CodeCompletionResult::RK_Pattern)
956+
continue;
953957
// Class members that are shadowed by subclasses are usually noise.
954958
if (Result.Hidden && Result.Declaration &&
955959
Result.Declaration->isCXXClassMember())
@@ -2153,7 +2157,8 @@ class CodeCompleteFlow {
21532157

21542158
clang::CodeCompleteOptions CodeCompleteOptions::getClangCompleteOpts() const {
21552159
clang::CodeCompleteOptions Result;
2156-
Result.IncludeCodePatterns = EnableSnippets;
2160+
Result.IncludeCodePatterns =
2161+
EnableSnippets && (CodePatterns != Config::CodePatternsPolicy::None);
21572162
Result.IncludeMacros = true;
21582163
Result.IncludeGlobals = true;
21592164
// We choose to include full comments and not do doxygen parsing in

clang-tools-extra/clangd/CodeComplete.h

+3
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ struct CodeCompleteOptions {
111111
Config::ArgumentListsPolicy ArgumentLists =
112112
Config::ArgumentListsPolicy::FullPlaceholders;
113113

114+
/// Whether to suggest code patterns & snippets or not in completion
115+
Config::CodePatternsPolicy CodePatterns = Config::CodePatternsPolicy::All;
116+
114117
/// Whether to use the clang parser, or fallback to text-based completion
115118
/// (using identifiers in the current file and symbol indexes).
116119
enum CodeCompletionParse {

clang-tools-extra/clangd/Config.h

+7
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,11 @@ struct Config {
152152
NeverInsert // Never insert headers as part of code completion
153153
};
154154

155+
enum class CodePatternsPolicy {
156+
All, // Suggest all code patterns and snippets
157+
None // Suggest none of the code patterns and snippets
158+
};
159+
155160
/// Configures code completion feature.
156161
struct {
157162
/// Whether code completion includes results that are not visible in current
@@ -161,6 +166,8 @@ struct Config {
161166
ArgumentListsPolicy ArgumentLists = ArgumentListsPolicy::FullPlaceholders;
162167
/// Controls if headers should be inserted when completions are accepted
163168
HeaderInsertionPolicy HeaderInsertion = HeaderInsertionPolicy::IWYU;
169+
/// Enables code patterns & snippets suggestions
170+
CodePatternsPolicy CodePatterns = CodePatternsPolicy::All;
164171
} Completion;
165172

166173
/// Configures hover feature.

clang-tools-extra/clangd/ConfigCompile.cpp

+11
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,17 @@ struct FragmentCompiler {
707707
C.Completion.HeaderInsertion = *Val;
708708
});
709709
}
710+
711+
if (F.CodePatterns) {
712+
if (auto Val = compileEnum<Config::CodePatternsPolicy>("CodePatterns",
713+
*F.CodePatterns)
714+
.map("All", Config::CodePatternsPolicy::All)
715+
.map("None", Config::CodePatternsPolicy::None)
716+
.value())
717+
Out.Apply.push_back([Val](const Params &, Config &C) {
718+
C.Completion.CodePatterns = *Val;
719+
});
720+
}
710721
}
711722

712723
void compile(Fragment::HoverBlock &&F) {

clang-tools-extra/clangd/ConfigFragment.h

+6
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,12 @@ struct Fragment {
349349
/// symbol is forward-declared
350350
/// "Never": Never insert headers
351351
std::optional<Located<std::string>> HeaderInsertion;
352+
/// Will suggest code patterns & snippets.
353+
/// CLI option available '--code-patterns':
354+
/// Values are Config::CodePatternsPolicy:
355+
/// all => enable all code patterns and snippets suggestion
356+
/// none => disable all code patterns and snippets suggestion
357+
std::optional<Located<std::string>> CodePatterns;
352358
};
353359
CompletionBlock Completion;
354360

clang-tools-extra/clangd/ConfigYAML.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,10 @@ class Parser {
249249
if (auto HeaderInsertion = scalarValue(N, "HeaderInsertion"))
250250
F.HeaderInsertion = *HeaderInsertion;
251251
});
252+
Dict.handle("CodePatterns", [&](Node &N) {
253+
if (auto CodePatterns = scalarValue(N, "CodePatterns"))
254+
F.CodePatterns = *CodePatterns;
255+
});
252256
Dict.parse(N);
253257
}
254258

clang-tools-extra/clangd/tool/ClangdMain.cpp

+19
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,17 @@ opt<Config::HeaderInsertionPolicy> HeaderInsertion{
267267
"Never insert #include directives as part of code completion")),
268268
};
269269

270+
opt<Config::CodePatternsPolicy> CodePatterns{
271+
"code-patterns",
272+
cat(Features),
273+
desc("Code completion menu will suggest code patterns and snippets."),
274+
init(CodeCompleteOptions().CodePatterns),
275+
values(clEnumValN(Config::CodePatternsPolicy::All, "all",
276+
"Enable all code patterns and snippets."),
277+
clEnumValN(Config::CodePatternsPolicy::None, "none",
278+
"Disable all code patterns and snippets.")),
279+
};
280+
270281
opt<bool> ImportInsertions{
271282
"import-insertions",
272283
cat(Features),
@@ -669,6 +680,7 @@ class FlagsConfigProvider : public config::Provider {
669680
std::optional<Config::BackgroundPolicy> BGPolicy;
670681
std::optional<Config::ArgumentListsPolicy> ArgumentLists;
671682
std::optional<Config::HeaderInsertionPolicy> HeaderInsertionPolicy;
683+
std::optional<Config::CodePatternsPolicy> CodePatternsPolicy;
672684

673685
// If --compile-commands-dir arg was invoked, check value and override
674686
// default path.
@@ -723,6 +735,10 @@ class FlagsConfigProvider : public config::Provider {
723735
: Config::ArgumentListsPolicy::Delimiters;
724736
}
725737

738+
if (CodePatterns == Config::CodePatternsPolicy::None) {
739+
CodePatternsPolicy = Config::CodePatternsPolicy::None;
740+
}
741+
726742
Frag = [=](const config::Params &, Config &C) {
727743
if (CDBSearch)
728744
C.CompileFlags.CDBSearch = *CDBSearch;
@@ -736,6 +752,8 @@ class FlagsConfigProvider : public config::Provider {
736752
C.Completion.HeaderInsertion = *HeaderInsertionPolicy;
737753
if (AllScopesCompletion.getNumOccurrences())
738754
C.Completion.AllScopes = AllScopesCompletion;
755+
if (CodePatternsPolicy)
756+
C.Completion.CodePatterns = *CodePatternsPolicy;
739757

740758
if (Test)
741759
C.Index.StandardLibrary = false;
@@ -949,6 +967,7 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var
949967
Opts.CodeComplete.BundleOverloads = CompletionStyle != Detailed;
950968
Opts.CodeComplete.ShowOrigins = ShowOrigins;
951969
Opts.CodeComplete.InsertIncludes = HeaderInsertion;
970+
Opts.CodeComplete.CodePatterns = CodePatterns;
952971
Opts.CodeComplete.ImportInsertions = ImportInsertions;
953972
if (!HeaderInsertionDecorators) {
954973
Opts.CodeComplete.IncludeIndicator.Insert.clear();

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

+17
Original file line numberDiff line numberDiff line change
@@ -3326,6 +3326,23 @@ TEST(CompletionTest, AllScopesCompletion) {
33263326
kind(CompletionItemKind::EnumMember))));
33273327
}
33283328

3329+
TEST(CompletionTest, NoCodePatternsIfDisabled) {
3330+
clangd::CodeCompleteOptions Opts = {};
3331+
Opts.EnableSnippets = true;
3332+
Opts.CodePatterns = Config::CodePatternsPolicy::None;
3333+
3334+
auto Results = completions(R"cpp(
3335+
void function() {
3336+
/// Trying to trigger "for (init-statement; condition; inc-expression)
3337+
/// {statements}~" code pattern
3338+
for^
3339+
}
3340+
)cpp", {}, Opts);
3341+
3342+
EXPECT_THAT(Results.Completions,
3343+
Not(Contains(kind(CompletionItemKind::Snippet))));
3344+
}
3345+
33293346
TEST(CompletionTest, NoQualifierIfShadowed) {
33303347
clangd::CodeCompleteOptions Opts = {};
33313348
Opts.AllScopes = true;

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

+13
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,19 @@ TEST(ParseYAML, AllScopesWarn) {
217217
EXPECT_THAT(Results[0].Completion.AllScopes, testing::Eq(std::nullopt));
218218
}
219219

220+
TEST(ParseYAML, CodePatterns) {
221+
CapturedDiags Diags;
222+
Annotations YAML(R"yaml(
223+
Completion:
224+
CodePatterns: None
225+
)yaml");
226+
auto Results =
227+
Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
228+
ASSERT_THAT(Diags.Diagnostics, IsEmpty());
229+
ASSERT_EQ(Results.size(), 1u);
230+
EXPECT_THAT(Results[0].Completion.CodePatterns, llvm::ValueIs(val("None")));
231+
}
232+
220233
TEST(ParseYAML, ShowAKA) {
221234
CapturedDiags Diags;
222235
Annotations YAML(R"yaml(

0 commit comments

Comments
 (0)