Code Completion
Include paths
Triggered by <, ", / characters. Handled before AST (preamble-level, no compilation needed). Quoted completion searches the includer's own directory first, then the configured include directories. Only files that look like headers are candidates: header extensions everywhere, extensionless files in system directories and other places such headers live.
Quoted include paths
Completion lists headers and directories from the configured search path and marks directories with a trailing slash
Angled include paths
Angled includes offer the same search-path candidates
Closing delimiter
Accepting a header closes the directive, replacing a delimiter already typed after the cursor instead of doubling it
Trigger contexts
#include_next— must detect that the directive is#include_next, not#include, and adjust search to start from the directory after the one that provided the current filecpp// in <bits/stl_vector.h>, provided by /usr/include/c++/14/ #include_next <^> // search starts AFTER /usr/include/c++/14/, skipping it__has_include()/__has_embed()— trigger include path completion inside these constructscpp#if __has_include(<^>) // suggest headers, same as #include <#embeddirective completioncpp#embed <^> // suggest embeddable resource files
Candidates and ranking
Traverse compiler search paths from compilation database
Both files and directories are candidates; directories are distinguished by a trailing
/in the labelFilter out already-included headers
cpp#include <vector> #include <^> // should not suggest "vector" againDeprioritize private/internal headers — paths that normal users should not include directly:
- Single
_prefix: lower priority (e.g._ctype.h) - Double
__prefix: even lower priority (compiler built-in internals like__config,__bit_reference) - Keywords like
detail,internal,impl,bitsin the path (third-party library private headers likeboost/detail/,bits/stdc++.h)
cpp#include <^> // __config, _ctype.h, bits/stdc++.h rank near bottom #include <boost/^> // boost/detail/ ranks lower than boost/asio/- Single
Path-distance-based ranking: headers closer to the current file in the project tree rank higher
Insertion behavior
Directory completion should NOT insert the trailing
/— let the user type it to re-trigger completion for the next level (currently the/is baked into the inserted text, which prevents the editor from auto-triggering the next completion round) (clangd#395)cpp#include <sys^> // accept "sys" → inserts "sys", user types "/" → next completion fires
Module import
Detected via text context analysis. Handled before AST (preamble-level, no compilation needed).
Triggered when cursor is after import or export import.
Import statements
Known module names complete after import, with the closing semicolon inserted
A statement that already contains its closing semicolon is complete and offers no module names.
Trigger on space character (#460)
Two-layer gating avoids firing on every space keystroke: the server registers
(space) as a trigger character, and space-triggered requests only proceed in import contexts (import,export import); all other spaces return empty immediately. This follows the same pattern used by TypeScript/Haxe language extensions (vscode#67714).Exclude self-module from results (self-import is invalid) — FIXME
Partition import within the same module
cpp// inside module foo import :^ // suggest :core, :io (only foo's own partitions)Note:
import M:part;is not valid C++ — partitions can only be imported via the short formimport :part;from within the same module.Hierarchical dot-completion
cppimport std.^ // suggest io, compat, etc.Note: dots in module names are a naming convention, not language-level hierarchy, but dot-triggered completion is still valuable UX.
Filter out non-exported (internal) partitions of other modules
Header unit import
cppimport <^> // suggest importable headers (same candidates as #include) import "^" // same, quoted formAuto-insert
importstatement on symbol completion (like auto-include for headers)cppstd::vector^ // on accept, also insert "import std;" at the top
Module declarations
Completion within module declaration contexts (module / export module).
import/modulekeyword completioncppimp^ // suggest "import" keyword mod^ // suggest "module" keywordModule name completion after
module/export modulecppmodule my^ // suggest existing module names (useful when writing implementation units)Partition name completion after
:cppexport module mylib:^ // suggest existing partition names of mylib module mylib:^ // same, for partition implementation unitmodule :private;completion (private module fragment)cppmodule :^ // suggest "private"export import :partitionre-export completion in primary interface unitcpp// in primary interface unit of mylib export import :^ // suggest mylib's interface partitions that need re-exporting
Member access
Triggered by ., ->, ::, or quickSuggestions. Forwarded to Clang CodeCompleteConsumer via stateless worker.
Members of a class
Fields, methods, the destructor and operators complete with plain names
The destructor completes as ~Account (never ~struct Account), operator= keeps no space before =, and a conversion operator spells its target type.
Instantiated class template members
The destructor label keeps the written template arguments
Pointer member access
-> on a pointer completes the pointee's members
Scope-qualified members
After :: static data, nested types, methods and the injected class name all list
Qualified completion is not filtered to the statically-reachable subset: instance fields and the destructor show up alongside the static members and nested types.
Inherited members
A derived object completes its own members and those of its base
Dependent member type
A variable whose type is a member alias of a dependent specialization completes the members of the class the alias stands for
The alias is resolved with the written template arguments substituted, so Vec<Vec<T>>::value_type lists the members of Vec<T> rather than nothing at all. An alias naming a reference (Vec<Vec<T>>::reference) lists the members of the class referred to.
Partial specialization members
A dependent specialization that matches a partial specialization completes through that specialization, not the primary template
Dependent alias chain
An alias that itself names a dependent member type resolves through every link of the chain
Dependent pointee members
-> on a pointer to a dependent member type completes the pointee's members
Concrete alias target
A dependent alias that names a concrete specialization completes the members that specialization instantiates to
The specialization is instantiated for the completion when the file never did, so its members carry the concrete argument types, and a partial specialization matching the arguments supplies them.
Designated initializer fields
{ . lists the fields of the aggregate being initialized, those of a matching partial specialization for a dependent one
Inaccessible members
Private and protected members are not offered where they cannot be used
Destructor labels
A destructor completes as ~ and the bare class name, whatever namespace the class lives in
Dependent expression results
A member access on what a subscript or a member call returns inside a template completes the members of the class it evaluates to
rows[0]. on a Vec<Vec<T>> lists the members of Vec<T>, followed through the container's reference alias the way the standard containers declare it. Where a member has a const overload, the constness of the object picks the one called, a data member reached through a const object counting as const, and -> on a returned iterator reaches the element.
Overloads sharing a return type
A dependent call whose candidate overloads all return the same type completes the members of that type
table[key]. on a map whose operator[] takes either a const K& or a K&& lists the members of the mapped type. The overloads may be defined outside the class, and the class template redeclared after its definition, as the standard maps are.
Deduced variable members
A variable declared auto from a dependent initializer completes the members of the class it deduces to
auto& row = rows[0]; row. lists the members of Vec<T>. The declarator applies as in a real deduction: const auto& makes the object const, a by-value auto drops the initializer's const, auto&& and decltype(auto) keep it, and auto* takes the pointee. From a data member, decltype(auto) takes the type the member is declared with, or with parentheses the const reference the expression is.
->— pointer member access (with Clang fixup)::— namespace/class scope membersDot-to-arrow: typing
.on a pointer triggers->member completion with automatic replacement (clangd#1349)cppstd::unique_ptr<Foo> ptr; ptr.^ // suggest Foo's members, insert as ptr->bar()Show free functions whose first parameter matches the object type alongside member results
cppstd::vector<int> v; v.^ // also suggest std::sort(v, ...), std::find(v, ...) etc.operator[],operator->,operator()in member suggestionsPrioritize direct members for the operator typed (
.members for.,->members for->)
Designated initializers
Sort completions in declaration order (required by C++20 designated initializers) (clangd#965)
cppstruct Cfg { int width; int height; bool fullscreen; }; Cfg c = { .^ // suggest: .width, .height, .fullscreen (in this order)Filter out already-used designators
cppCfg c = { .width = 800, .^ // only suggest .height, .fullscreenCompound literal designated initializers (
(struct T){ .field = })Anonymous struct/union member designators
cppstruct S { union { int i; float f; }; }; S s = { .^ // suggest .i, .f"Fill all members" snippet
cppCfg c = { ^ // first item: .width = ${1}, .height = ${2}, .fullscreen = ${3}
Override and out-of-line definitions
Override declarations
Inside a derived class, a base class's virtual function completes as a whole override declaration, return type and override included; inside the override, the name completes as itself, not as a call of the base version
Full inheritance hierarchy traversal for override candidates (clangd#226, clangd#2374)
cppstruct A { virtual void f(); }; struct B : A { }; struct C : B { ^ // suggest: void f() override (from A, through B) };Out-of-line definition completion
cpp// in .cpp file void MyClass::^ // suggest all member functions with full signature + body snippetShow all members (including private/protected) in definition contexts
cppclass Foo { private: void secret(); }; void Foo::^ // must include "secret" — this is a definition, not a callConstructors after
::in definition contextsSuppress redundant template parameters for constructors/destructors in class templates
cpptemplate<typename T> struct Vec { Vec(); ~Vec(); }; template<typename T> Vec<T>::^ // suggest "Vec()" and "~Vec()", not "Vec<T>()" or "~Vec<T>()"
Symbols
Fuzzy unqualified lookup
Strong prefix matches survive, weak subsequence matches and unqualified namespace members do not
Class template deduplication
A name that is also constructors and a deduction guide stays a single class entry
Constructor labels stay plain
Class template constructors and deduction guides complete as the bare class name, never a templated spelling
Keyword patterns
Keywords complete like any candidate, with plain insert text
Macros
Object-like macros complete as constants, function-like ones as functions with a parameter signature; argument snippets follow the function setting
Macro shadowing a declaration
A name redefined as a macro completes as the macro, not the shadowed declaration
Completion inside macro arguments
Member access written as a macro argument completes as it would outside the macro
Namespace-qualified lookup
ns:: lists the namespace's own members
Enum members
A scoped enum lists through Type::, an unscoped enumerator completes by bare name
Local shadowing a global
The shadowed global does not appear as a duplicate entry
Using-declaration
A name pulled in with using completes unqualified
Dependent scope qualifier
:: after a dependent member type lists that type's members, after a dependent specialization the members of its matching partial specialization, and after a dependent member enumeration its enumerators
Required qualifier
An enumerator the bare name does not reach completes with the qualifier it needs, matched against the bare name
Local hiding a function
A local that hides a same-named function is the candidate offered, not the function it hides
Constructor templates
A constructor template completes as the bare class name, like any other constructor
Overloads across namespaces
Same-named functions from different namespaces in scope bundle into one entry that counts all of them
Qualified name lookup (
std::)Argument-dependent lookup (ADL) candidates
Macro completion — object-like and function-like macros in the candidate set
C++ attribute completion
cpp[[^]] // suggest: nodiscard, deprecated, maybe_unused, likely, ...Cross-scope completion including class/struct-scoped symbols (inner types, static methods)
cppstruct Outer { struct Inner {}; static int count; }; Inn^ // suggest Outer::Inner from a different scopeRespect namespace aliases in inserted qualifiers (prefer shortest valid qualifier)
cppnamespace fs = std::filesystem; fs::ex^ // insert "fs::exists", not "std::filesystem::exists"Language-aware filtering (no C++ symbols in C files in mixed projects)
Function-argument comment completion (
/*param=*/style parameter hints)Identifier-based fallback completion when semantic analysis is unavailable
Functions and snippets
All options below live in the [code_completion] configuration section.
Signature and return type details
The parameter list and return type ride along as label details
Overload bundling
An overload set collapses into one entry with an overload count
Unbundled overloads
With bundling off, every overload is its own entry with its own signature
Parameter placeholder snippets
Calls insert tab-stop placeholders per argument; a no-argument function stays plain text
Snippets defer to bundling
While overloads are bundled, argument snippets stay off even when enabled
Default-argument parameters
A parameter with a default value drops out of the signature detail
The signature detail keeps only the required parameters; the trailing int retries = 3 is elided.
Variadic signature
A trailing ... shows in the parameter detail
Call parentheses
A completed call gets its parentheses with the cursor between them, unless arguments already follow the name or it is not being called
Template argument placeholders
A class template inserts a placeholder per template parameter without a default, and empty brackets when every parameter has one
Statement keywords
Statement keywords complete as keywords; the option inserts the whole statement with a placeholder for each part
Context-sensitive snippet: insert name only (no call syntax) in function pointer contexts
cppvoid (*fp)(int) = my_fun^; // insert "my_func", not "my_func(${1:int x})"Strip C++23 explicit object parameter from signatures and snippets
cppstruct S { void f(this S& self, int x); }; S s; s.f(^ // show signature "(int x)", not "(this S& self, int x)"Show default parameter values in signatures (clangd#100)
cppvoid open(std::string path, int mode = 0644); open(^ // detail shows "(string path, int mode = 0644)"Resolve lambda types to actual signatures
cppauto cmp = [](int a, int b) -> bool { return a < b; }; cmp^ // show "(int a, int b) -> bool", not "<lambda>"Resolve forwarding function parameters (clangd#447)
cppstruct Widget { Widget(int w, int h); }; auto p = std::make_unique<Widget>(^ // show "(int w, int h)"Set
InsertTextFormat::PlainTextwhen no placeholders are present
Templates and concepts
Concept-aware completion: infer available members from concept constraints on template parameters (clangd#1103)
cpptemplate<typename T> concept Drawable = requires(T t) { t.draw(); t.resize(int{}, int{}); }; template<Drawable T> void render(T& widget) { widget.^ // suggest draw(), resize() from Drawable concept }Use single-instantiation information for generic lambda completion — when a generic lambda is only called from one site, use that site's argument types to provide completion inside the lambda body
cppstd::vector<std::string> names; std::ranges::sort(names, [](const auto& a, const auto& b) { return a.^ // a is deducible as std::string from the single call site });cppauto results = names | std::views::transform([](const auto& s) { return s.^ // s is deducible as std::string });Suppress template parameter snippet for injected class name inside class template body
cpptemplate<typename T> struct Vec { Vec^ // suggest "Vec", not "Vec<${1:T}>" — injected class name };
Filtering and ranking
Underscore filtering
Underscore-prefixed internal symbols hide unless the typed prefix itself starts with one
Deprecated tagging
A [[deprecated]] candidate carries the Deprecated tag, its plain sibling does not
Word-boundary fuzzy match
Prefix fb matches the word starts of foo_bar_baz
frobnicate is only a weak scattered subsequence of fb and is dropped; foo_bar_baz matches on the foo/bar word boundaries and survives.
Case-insensitive prefix
A lowercase prefix matches a mixed-case identifier
Prefix outranks subsequence
An exact-prefix candidate sorts above a scattered subsequence match
For prefix fo, format_output is a true prefix and outscores fast_math_operation, which only matches as a subsequence.
Completion inside a word
Completing in the middle of a word offers both ranges: the editor either inserts before the rest of the word or replaces the whole word
Non-ASCII prefix
A prefix made of non-ASCII identifier characters is replaced, not inserted before
Fuzzy matching with word-boundary-aware scoring (camelCase, snake_case)
Filter out recovery context results (
CCC_Recovery)Result limit (
CodeCompletionOptions.limit)Frecency/recently-used boosting
Treat digit-letter boundaries as word breaks (clangd#1236)
cppi32^ // should match int32_t (digit-letter boundary: "32" → "t")Scope-aware relevance tiers: locals > members > namespace-scope > cross-scope
Context-based type boosting (suggest matching enum members when expected type is an enum) (clangd#462)
cppenum Color { Red, Green, Blue }; void paint(Color c); paint(^ // boost Red, Green, Blue to topFilter already-used enum values in switch statements
cppswitch (color) { case Red: break; case ^ // suggest Green, Blue only — Red already usedRank
nullptraboveNULLin C++ modeNaming signal boosting
cppauto foo = get^; // boost getFoo() over getBar()Reference-count and file-proximity ranking signals
Machine-learned ranking model
Auto-include insertion
Not yet implemented. Completing a symbol does not insert #include directives.
Insert
#includefor unresolved symbols on completion acceptcppstd::vec^ // on accept "vector", also insert #include <vector> at top of fileCheck transitive include graph to avoid duplicate includes
cpp// <algorithm> already includes <iterator> transitively std::back_inserter^ // do NOT insert #include <iterator> againContext-aware: no include insertion for forward declarations or pointer/reference-only usage (clangd#639)
cppclass Foo; Foo*^ // no include needed — forward declaration suffices for pointerInsert C headers in C files, C++ headers in C++ files
c// in a .c file size_^ // insert #include <stddef.h>, not #include <cstddef>Configurable behavior:
always/iwyu-only/neverPrefer project-relative paths over absolute paths
Respect IWYU pragmas and header mappings
Auto-insert
importfor C++20 module symbols
Documentation
Not yet implemented. Completion items do not include documentation.
Extract doc comments from declarations and definitions
cpp/// @brief Opens a file at the given path. /// @param path The file system path. void open(std::string path); op^ // completion popup shows the @brief docAvailable regardless of where the definition lives (header, source, index)
Propagate template pattern documentation to instantiations
Standard library documentation integration
Macro definitions as documentation (clangd#1485)
Trigger characters
Registered: . < > : " / and space.
| Character | Context | Behavior |
|---|---|---|
. | Member access | Semantic completion |
> | Via -> | Pointer member completion; any other > is ignored |
: | Via :: | Scope completion |
< | #include < | Include path completion |
" | #include " | Include path completion |
/ | Path separator | Include path continuation |
| After import | Module name completion (extension-gated) |
Protocol
-
completionItem/resolvefor lazy-loading documentation and details -
CompletionList.isIncompleteflag for incremental filtering -
commitCharactersfor auto-accepting completions on specific keystrokes -
filterText/sortTextfor client-side re-filtering
