diff --git a/en/clice/dev/test-and-debug.md b/en/clice/dev/test-and-debug.md index beed7618..7d337732 100644 --- a/en/clice/dev/test-and-debug.md +++ b/en/clice/dev/test-and-debug.md @@ -75,7 +75,7 @@ cd tests CLICE_EXECUTABLE=../build/RelWithDebInfo/bin/clice npm run snap ``` -A fixture is a single `.cpp` at the corpus root, or a subdirectory entered through its `main.cpp` — one multi-file unit whose sibling sources (module interfaces, headers, extra sources) belong to the fixture. Corpus-wide compile flags live in the corpus's `corpus.json` manifest; a fixture appends its own with `- flags: [...]`. Each server-path run materializes the fixture into a throwaway workspace (sources arrive on disk with `§`-annotations already stripped), so fixtures never share state and background indexing — off by default, enabled per fixture with `- indexing: true` — sees the same bytes the compiler does. A fixture that deliberately does not compile cleanly declares `- diagnostics: expected`; unexpected diagnostics fail the fixture, and so does a clean compile under that declaration. +A fixture is a single `.cpp`, or a subdirectory entered through its `main.cpp` — one multi-file unit whose sibling sources (module interfaces, headers, extra sources) belong to the fixture. A fixture that documents a capability lives in a section directory of the corpus as `
/NN_name.cpp` (or `
/NN_unit/main.cpp`) and opens with a `/// # Capability name — details` doc header followed by its metadata list, where `status` (`supported`, `partial` or `unsupported`) is required: the directory keys the feature page's generated region, the two-digit number orders the item within it, and the header feeds the page (see `tools/docs/feature.ts`). Edge-case fixtures without a doc header stay at the corpus root. Corpus-wide compile flags live in the corpus's `corpus.json` manifest; a fixture appends its own with `- flags: [...]`. Each server-path run materializes the fixture into a throwaway workspace (sources arrive on disk with `§`-annotations already stripped), so fixtures never share state and background indexing — off by default, enabled per fixture with `- indexing: true` — sees the same bytes the compiler does. A fixture that deliberately does not compile cleanly declares `- diagnostics: expected`; unexpected diagnostics fail the fixture, and so does a clean compile under that declaration. By default a fixture is `verify: both` with `snap: shared`: the inspect and server results must render byte-identically and are pinned by one `.snap.yml`. A fixture whose two paths legitimately differ declares `- snap: separate` in its `///` doc header (with a `// snap:` comment explaining why) and each path pins its own `.inspect.snap.yml` / `.server.snap.yml`. A known-wrong divergence is declared as `- snap: skip`: the fixture runs nowhere and keeps no snapshot until the two paths agree. A feature that exists on only one path (include and import completion answered by the server; index dumps with no LSP request shape) declares `- verify: server` or `- verify: inspect` and that side owns the plain `.snap.yml`. diff --git a/en/clice/features/completion.md b/en/clice/features/completion.md index b27c6d7d..9db4d453 100644 --- a/en/clice/features/completion.md +++ b/en/clice/features/completion.md @@ -4,32 +4,31 @@ Triggered by `<`, `"`, `/` characters. Handled before AST (preamble-level, no compilation needed). Quoted completion searches the configured include directories, not the includer's own directory (unless it is on the include path). - + -- [x] Quoted include paths — headers and directories from the configured search path, directories marked by a trailing slash +| Capability | Status | Issues | +| -------------------- | --------- | ------ | +| Quoted include paths | Supported | | +| Angled include paths | Supported | | - Answered by the server before any compilation, so only the server path - exists for this fixture. +### Quoted include paths -
- Example +Headers and directories from the configured search path, directories marked by a trailing slash - ```cpp - #include "snap" - ``` +Answered by the server before any compilation, so only the server path +exists for this fixture. -
+```cpp +#include "snap" +``` -- [x] Angled include paths — the same search-path candidates in the angled form +### Angled include paths -
- Example - - ```cpp - #include - ``` +The same search-path candidates in the angled form -
+```cpp +#include +``` @@ -93,35 +92,36 @@ Detected via text context analysis. Handled before AST (preamble-level, no compi Triggered when cursor is after `import` or `export import`. - + -- [x] Import statements — known module names complete after `import`, with the closing semicolon inserted +| Capability | Status | Issues | +| ----------------- | --------- | ------ | +| Import statements | Supported | | - Answered by the server from its module map, so only the server path - exists for this fixture; the sibling module interface is opened first - so the module is known. The statement stays unterminated — a `;` on - the line means the import is already complete and nothing is offered. +### Import statements -
- Example +Known module names complete after `import`, with the closing semicolon inserted - `main.cpp`: +Answered by the server from its module map, so only the server path +exists for this fixture; the sibling module interface is opened first +so the module is known. The statement stays unterminated — a `;` on +the line means the import is already complete and nothing is offered. - ```cpp - import ma - ``` +`main.cpp`: - `mod_math.cppm`: +```cpp +import ma +``` - ```cpp - export module math; +`mod_math.cppm`: - export int add(int a, int b) { - return a + b; - } - ``` +```cpp +export module math; -
+export int add(int a, int b) { + return a + b; +} +``` @@ -208,130 +208,123 @@ Triggered by `.`, `->`, `::`, or quickSuggestions. Forwarded to Clang `CodeCompl ### Member Access - - -- [x] 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. - -
- Example - - ```cpp - // The member access expression is left dangling at the point. - struct Wallet { - int cents; - }; - - struct Account { - int balance; - int bazzzz(int a, int b); - operator Wallet(); - }; + - void bar() { - Account acc; - acc. - } - ``` +| Capability | Status | Issues | +| ----------------------------------------- | --------- | ------ | +| Members of a class | Supported | | +| Members of an instantiated class template | Supported | | +| Pointer member access | Supported | | +| Scope-qualified members | Supported | | +| Inherited members | Supported | | -
+### Members of a class -- [x] Members of an instantiated class template — the destructor label keeps the written template arguments +fields, methods, the destructor and operators complete with plain names -
- Example +The destructor completes as `~Account` (never `~struct Account`), +`operator=` keeps no space before `=`, and a conversion operator +spells its target type. - ```cpp - // The member access expression is left dangling at the point. - template - struct Box { - T value; - }; +```cpp +// The member access expression is left dangling at the point. +struct Wallet { + int cents; +}; - void bar() { - Box b; - b. - } - ``` +struct Account { + int balance; + int bazzzz(int a, int b); + operator Wallet(); +}; -
+void bar() { + Account acc; + acc. +} +``` -- [x] Pointer member access — `->` on a pointer completes the pointee's members +### Members of an instantiated class template -
- Example +The destructor label keeps the written template arguments - ```cpp - // The member access expression is left dangling at the point. - struct Node { - int value; - Node* next; - int compute(int a); - }; +```cpp +// The member access expression is left dangling at the point. +template +struct Box { + T value; +}; - void bar() { - Node* p; - p-> - } - ``` +void bar() { + Box b; + b. +} +``` -
+### Pointer member access -- [x] Scope-qualified members — after `::` static data, nested types, methods and the injected class name all list +`->` on a pointer completes the pointee's members - Qualified completion is not filtered to the statically-reachable subset: - instance fields and the destructor show up alongside the static members - and nested types. +```cpp +// The member access expression is left dangling at the point. +struct Node { + int value; + Node* next; + int compute(int a); +}; -
- Example +void bar() { + Node* p; + p-> +} +``` - ```cpp - // The qualified-id is left dangling at the point. - struct Config { - static int shared_count; - static int make(int seed); +### Scope-qualified members - struct Nested { - int a; - }; +After `::` static data, nested types, methods and the injected class name all list - int instance_field; - }; +Qualified completion is not filtered to the statically-reachable subset: +instance fields and the destructor show up alongside the static members +and nested types. - void bar() { - int v = Config::; - } - ``` +```cpp +// The qualified-id is left dangling at the point. +struct Config { + static int shared_count; + static int make(int seed); -
+ struct Nested { + int a; + }; -- [x] Inherited members — a derived object completes its own members and those of its base + int instance_field; +}; -
- Example +void bar() { + int v = Config::; +} +``` - ```cpp - // The member access expression is left dangling at the point. - struct Base { - int base_field; - int base_method(); - }; +### Inherited members - struct Derived : Base { - int derived_field; - }; +A derived object completes its own members and those of its base + +```cpp +// The member access expression is left dangling at the point. +struct Base { + int base_field; + int base_method(); +}; - void bar() { - Derived d; - d. - } - ``` +struct Derived : Base { + int derived_field; +}; -
+void bar() { + Derived d; + d. +} +``` @@ -431,217 +424,219 @@ Triggered by `.`, `->`, `::`, or quickSuggestions. Forwarded to Clang `CodeCompl ### Symbols - - -- [x] Unqualified lookup with fuzzy prefix matching — strong prefix matches survive, weak subsequence matches and unqualified namespace members do not - -
- Example + - ```cpp - // The completion expression dangles as an unfinished statement. - namespace A { - - void fooooo(); - - } +| Capability | Status | Issues | +| --------------------------------------------- | --------- | ------ | +| Unqualified lookup with fuzzy prefix matching | Supported | | +| Class template deduplication | Supported | | +| Constructor labels stay plain | Supported | | +| Keyword patterns | Supported | | +| Macros | Supported | | +| Macro shadowing a declaration | Supported | | +| Completion inside macro arguments | Supported | | +| Namespace-qualified lookup | Supported | | +| Enum members | Supported | | +| Local shadowing a global | Supported | | +| Using-declaration | Supported | | - struct X { - void operator()() {} - }; +### Unqualified lookup with fuzzy prefix matching - void bar() { - X functor; - auto folded = [](int x) { - }; - fo; - } - ``` +Strong prefix matches survive, weak subsequence matches and unqualified namespace members do not -
+```cpp +// The completion expression dangles as an unfinished statement. +namespace A { -- [x] Class template deduplication — a name that is also constructors and a deduction guide stays a single class entry +void fooooo(); -
- Example +} - ```cpp - // The completion prefix dangles as an unfinished statement. - template - struct Foo { - Foo() {} +struct X { + void operator()() {} +}; - Foo(T x) {} +void bar() { + X functor; + auto folded = [](int x) { + }; + fo; +} +``` - Foo(T x, T y) {} - }; +### Class template deduplication - template - Foo(T) -> Foo; +A name that is also constructors and a deduction guide stays a single class entry - void bar() { - Fo - } - ``` +```cpp +// The completion prefix dangles as an unfinished statement. +template +struct Foo { + Foo() {} -
+ Foo(T x) {} -- [x] Constructor labels stay plain — class template constructors and deduction guides complete as the bare class name, never a templated spelling + Foo(T x, T y) {} +}; -
- Example +template +Foo(T) -> Foo; - ```cpp - // The completion prefix dangles as an unfinished statement. - template - struct Bazzz { - Bazzz() {} +void bar() { + Fo +} +``` - Bazzz(T x) {} +### Constructor labels stay plain - Bazzz(T x, U y) {} - }; +Class template constructors and deduction guides complete as the bare class name, never a templated spelling - template - Bazzz(T) -> Bazzz; +```cpp +// The completion prefix dangles as an unfinished statement. +template +struct Bazzz { + Bazzz() {} - void bar() { - Ba - } - ``` + Bazzz(T x) {} -
+ Bazzz(T x, U y) {} +}; -- [x] Keyword patterns — keywords complete like any candidate, with plain insert text +template +Bazzz(T) -> Bazzz; -
- Example +void bar() { + Ba +} +``` - ```cpp - // The completion prefix cuts the initializer mid-expression. - int x = tru - ``` +### Keyword patterns -
+Keywords complete like any candidate, with plain insert text -- [x] Macros — object-like macros complete as constants, function-like ones as functions with a parameter signature; argument snippets follow the function setting +```cpp +// The completion prefix cuts the initializer mid-expression. +int x = tru +``` -
- Example +### Macros - ```cpp - #define RETRY_LIMIT 3 +object-like macros complete as constants, function-like ones as functions with a parameter signature; argument snippets follow the function setting - #define CLAMP(value, limit) ((value) < (limit) ? (value) : (limit)) +```cpp +#define RETRY_LIMIT 3 - int a = RETRY; - int b = CLA; - ``` +#define CLAMP(value, limit) ((value) < (limit) ? (value) : (limit)) -
+int a = RETRY; +int b = CLA; +``` -- [x] Macro shadowing a declaration — a name redefined as a macro completes as the macro, not the shadowed declaration +### Macro shadowing a declaration -
- Example +A name redefined as a macro completes as the macro, not the shadowed declaration - ```cpp - void GUARD(int); - #define GUARD 1 +```cpp +void GUARD(int); +#define GUARD 1 - int BOUND(int lo, int hi); - #define BOUND(lo, hi) ((lo) < (hi) ? (lo) : (hi)) +int BOUND(int lo, int hi); +#define BOUND(lo, hi) ((lo) < (hi) ? (lo) : (hi)) - int a = GUAR; - int b = BOUN; - ``` +int a = GUAR; +int b = BOUN; +``` -
+### Completion inside macro arguments -- [x] Namespace-qualified lookup — `ns::` lists the namespace's own members +Member access written as a macro argument completes as it would outside the macro -
- Example +```cpp +#define WRAP(...) __VA_ARGS__ - ```cpp - // The qualified-id is left dangling at the point. - namespace geometry { +struct Config { + int retries; + int timeout; +}; - int area_of(int r); +void run() { + Config config; + WRAP(config.); +} +``` - struct Point { - int x; - }; +### Namespace-qualified lookup - int origin; +`ns::` lists the namespace's own members - } // namespace geometry +```cpp +// The qualified-id is left dangling at the point. +namespace geometry { - void bar() { - int v = geometry::; - } - ``` +int area_of(int r); -
+struct Point { + int x; +}; -- [x] Enum members — a scoped enum lists through `Type::`, an unscoped enumerator completes by bare name +int origin; -
- Example +} // namespace geometry - ```cpp - // Both completion prefixes dangle; the statements stay - // semicolon-terminated so the second marker is not dragged into recovery. - enum class Color { Red, Green, Blue }; +void bar() { + int v = geometry::; +} +``` - enum Fruit { Apple, Banana }; +### Enum members - void bar() { - Color c = Color::; - int f = App; - } - ``` +A scoped enum lists through `Type::`, an unscoped enumerator completes by bare name -
+```cpp +// Both completion prefixes dangle; the statements stay +// semicolon-terminated so the second marker is not dragged into recovery. +enum class Color { Red, Green, Blue }; -- [x] Local shadowing a global — the shadowed global does not appear as a duplicate entry +enum Fruit { Apple, Banana }; -
- Example +void bar() { + Color c = Color::; + int f = App; +} +``` - ```cpp - // The completion prefix dangles as an unfinished statement. - int counter = 0; +### Local shadowing a global - void bar() { - int counter = 1; - int v = coun; - } - ``` +The shadowed global does not appear as a duplicate entry -
+```cpp +// The completion prefix dangles as an unfinished statement. +int counter = 0; -- [x] Using-declaration — a name pulled in with `using` completes unqualified +void bar() { + int counter = 1; + int v = coun; +} +``` -
- Example +### Using-declaration - ```cpp - // The completion prefix dangles as an unfinished statement. - namespace lib { +A name pulled in with `using` completes unqualified - int helper_fn(int x); +```cpp +// The completion prefix dangles as an unfinished statement. +namespace lib { - } +int helper_fn(int x); - using lib::helper_fn; +} - void bar() { - int v = help; - } - ``` +using lib::helper_fn; -
+void bar() { + int v = help; +} +``` @@ -677,123 +672,112 @@ Triggered by `.`, `->`, `::`, or quickSuggestions. Forwarded to Clang `CodeCompl All options below live in the `[code_completion]` configuration section. - - -- [x] Signature and return type details — the parameter list and return type ride along as label details - -
- Example - - ```cpp - // The completion prefix cuts the initializer mid-expression. - double foooo(int x, float y); - - int x = fo - ``` - -
- -- [x] Overload bundling — an overload set collapses into one entry with an overload count + -
- Example +| Capability | Status | Issues | +| --------------------------------- | --------- | ------ | +| Signature and return type details | Supported | | +| Overload bundling | Supported | | +| Unbundled overloads | Supported | | +| Parameter placeholder snippets | Supported | | +| Snippets defer to bundling | Supported | | +| Default-argument parameters | Supported | | +| Variadic signature | Supported | | - ```cpp - // The completion prefix cuts the initializer mid-expression. - int foooo(int x); - int foooo(int x, int y); - double foooo(double d); +### Signature and return type details - int x = fooo - ``` +The parameter list and return type ride along as label details -
+```cpp +// The completion prefix cuts the initializer mid-expression. +double foooo(int x, float y); -- [x] Unbundled overloads — with bundling off, every overload is its own entry with its own signature +int x = fo +``` -
- Example +### Overload bundling - ```cpp - // The completion prefix cuts the initializer mid-expression. - int foooo(int x); - int foooo(int x, int y); - double foooo(double d); +An overload set collapses into one entry with an overload count - int x = fooo - ``` +```cpp +// The completion prefix cuts the initializer mid-expression. +int foooo(int x); +int foooo(int x, int y); +double foooo(double d); -
+int x = fooo +``` -- [x] Parameter placeholder snippets — calls insert tab-stop placeholders per argument; a no-argument function stays plain text +### Unbundled overloads -
- Example +With bundling off, every overload is its own entry with its own signature - ```cpp - // The completion prefixes dangle as unfinished statements. - int foooo(int x, float y); - void nothing_to_fill(); +```cpp +// The completion prefix cuts the initializer mid-expression. +int foooo(int x); +int foooo(int x, int y); +double foooo(double d); - struct Foo { - int bazzzz(int a, int b); - }; +int x = fooo +``` - void bar() { - Foo f; - fo; - no; - f.ba; - } - ``` +### Parameter placeholder snippets -
+Calls insert tab-stop placeholders per argument; a no-argument function stays plain text -- [x] Snippets defer to bundling — while overloads are bundled, argument snippets stay off even when enabled +```cpp +// The completion prefixes dangle as unfinished statements. +int foooo(int x, float y); +void nothing_to_fill(); -
- Example +struct Foo { + int bazzzz(int a, int b); +}; - ```cpp - // The completion prefix cuts the initializer mid-expression. - int foooo(int x); - int foooo(int x, int y); +void bar() { + Foo f; + fo; + no; + f.ba; +} +``` - int z = fo - ``` +### Snippets defer to bundling -
+While overloads are bundled, argument snippets stay off even when enabled -- [x] Default-argument parameters — a parameter with a default value drops out of the signature detail +```cpp +// The completion prefix cuts the initializer mid-expression. +int foooo(int x); +int foooo(int x, int y); - The signature detail keeps only the required parameters; the trailing - `int retries = 3` is elided. +int z = fo +``` -
- Example +### Default-argument parameters - ```cpp - // The completion prefix cuts the initializer mid-expression. - int configure(int timeout, int retries = 3); +A parameter with a default value drops out of the signature detail - int x = confi - ``` +The signature detail keeps only the required parameters; the trailing +`int retries = 3` is elided. -
+```cpp +// The completion prefix cuts the initializer mid-expression. +int configure(int timeout, int retries = 3); -- [x] Variadic signature — a trailing `...` shows in the parameter detail +int x = confi +``` -
- Example +### Variadic signature - ```cpp - // The completion prefix cuts the initializer mid-expression. - int printf_like(const char* fmt, ...); +A trailing `...` shows in the parameter detail - int x = printf - ``` +```cpp +// The completion prefix cuts the initializer mid-expression. +int printf_like(const char* fmt, ...); -
+int x = printf +``` @@ -895,125 +879,91 @@ All options below live in the `[code_completion]` configuration section. }; ``` -### Macros - -- [x] Macro name completion, including macros deserialized from the preamble -- [x] Fuzzy matching for macros (same matcher as other symbols) -- [x] Correct `CompletionItemKind`: `Function` for function-like, `Constant` for object-like ([clangd#2002](https://github.com/clangd/clangd/issues/2002)) -- [x] Parameter list as the label detail for function-like macros -- [ ] Show macro definition/expansion as documentation ([clangd#1485](https://github.com/clangd/clangd/issues/1485)) - - ```cpp - #define MAX_BUF 4096 - MAX^ // completion detail shows: #define MAX_BUF 4096 - ``` - -- [x] Parameter placeholders for function-like macros (respect snippet settings) - - ```cpp - #define CHECK(cond, msg) ... - CHECK^ // insert: CHECK(${1:cond}, ${2:msg}) - ``` - -- [ ] Completion inside macro arguments with fallback to enclosing context - - ```cpp - #define WRAP(...) __VA_ARGS__ - WRAP(some_obj.^) // should still offer some_obj's members - ``` - ### Filtering & Ranking - + -- [x] Underscore filtering — underscore-prefixed internal symbols hide unless the typed prefix itself starts with one +| Capability | Status | Issues | +| --------------------------- | --------- | ------ | +| Underscore filtering | Supported | | +| Deprecated tagging | Supported | | +| Word-boundary fuzzy match | Supported | | +| Case-insensitive prefix | Supported | | +| Prefix outranks subsequence | Supported | | -
- Example +### Underscore filtering - ```cpp - // The completion prefixes are undeclared identifiers. The - // statements stay semicolon-terminated: an unterminated one puts the - // NEXT marker into a recovery context, which completion drops entirely. - int _private_thing; - int public_thing; - - int x = pu; - int y = _p; - ``` - -
- -- [x] Deprecated tagging — a [[deprecated]] candidate carries the Deprecated tag, its plain sibling does not +underscore-prefixed internal symbols hide unless the typed prefix itself starts with one -
- Example +```cpp +// The completion prefixes are undeclared identifiers. The +// statements stay semicolon-terminated: an unterminated one puts the +// NEXT marker into a recovery context, which completion drops entirely. +int _private_thing; +int public_thing; - ```cpp - // The completion prefix cuts the initializer mid-expression. - [[deprecated]] int old_thing(int x); - int new_thing(int x); - - int z = thing - ``` +int x = pu; +int y = _p; +``` -
+### Deprecated tagging -- [x] Word-boundary fuzzy match — prefix `fb` matches the word starts of `foo_bar_baz` +A [[deprecated]] candidate carries the Deprecated tag, its plain sibling does not - `frobnicate` is only a weak scattered subsequence of `fb` and is dropped; - `foo_bar_baz` matches on the `foo`/`bar` word boundaries and survives. +```cpp +// The completion prefix cuts the initializer mid-expression. +[[deprecated]] int old_thing(int x); +int new_thing(int x); -
- Example +int z = thing +``` - ```cpp - // The completion prefix dangles as an unfinished statement. - int foo_bar_baz; - int frobnicate; +### Word-boundary fuzzy match - void bar() { - int v = fb; - } - ``` +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. -- [x] Case-insensitive prefix — a lowercase prefix matches a mixed-case identifier +```cpp +// The completion prefix dangles as an unfinished statement. +int foo_bar_baz; +int frobnicate; -
- Example +void bar() { + int v = fb; +} +``` - ```cpp - // The completion prefix dangles as an unfinished statement. - int MyLongName; +### Case-insensitive prefix - void bar() { - int v = mylong; - } - ``` +A lowercase prefix matches a mixed-case identifier -
+```cpp +// The completion prefix dangles as an unfinished statement. +int MyLongName; -- [x] Prefix outranks subsequence — an exact-prefix candidate sorts above a scattered subsequence match +void bar() { + int v = mylong; +} +``` - For prefix `fo`, `format_output` is a true prefix and outscores - `fast_math_operation`, which only matches as a subsequence. +### Prefix outranks subsequence -
- Example +An exact-prefix candidate sorts above a scattered subsequence match - ```cpp - // The completion prefix dangles as an unfinished statement. - int format_output; - int fast_math_operation; +For prefix `fo`, `format_output` is a true prefix and outscores +`fast_math_operation`, which only matches as a subsequence. - void bar() { - int v = fo; - } - ``` +```cpp +// The completion prefix dangles as an unfinished statement. +int format_output; +int fast_math_operation; -
+void bar() { + int v = fo; +} +``` @@ -1107,6 +1057,7 @@ Not yet implemented. Completion items do not include documentation. - [ ] Available 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](https://github.com/clangd/clangd/issues/1485)) ## Trigger Characters diff --git a/en/clice/features/document-links.md b/en/clice/features/document-links.md index e65e6cb4..e5e71e41 100644 --- a/en/clice/features/document-links.md +++ b/en/clice/features/document-links.md @@ -2,186 +2,180 @@ Clickable links from source directives to their resolved target files. - ## Include Directives - + -- [x] Quoted includes — `#include "..."` links to the resolved header file +| Capability | Status | Issues | +| ---------------------------------------- | --------- | ----------------------------------------------------------- | +| Quoted includes | Supported | | +| Angle-bracket includes | Supported | | +| Macro-expanded paths | Supported | [clangd#2375](https://github.com/clangd/clangd/issues/2375) | +| `#include_next` and `__has_include_next` | Partial | | +| `__has_include` | Supported | | - Every include in the file is linked, not just the preamble run at - the top. +### Quoted includes -
- Example +`#include "..."` links to the resolved header file - ```cpp - #include "header_a.h" - #include "header_b.h" - int x = 1; - #include "header_c.h" - ``` +Every include in the file is linked, not just the preamble run at +the top. -
+```cpp +#include "header_a.h" +#include "header_b.h" +int x = 1; +#include "header_c.h" +``` -- [x] Angle-bracket includes — `#include <...>` links to the header found on the search path +### Angle-bracket includes -
- Example +`#include <...>` links to the header found on the search path - ```cpp - #include - ``` +```cpp +#include +``` -
+### Macro-expanded paths -- [x] Macro-expanded paths — `#include MACRO` links the directive argument to the expanded target ([clangd#2375](https://github.com/clangd/clangd/issues/2375)) +`#include MACRO` links the directive argument to the expanded target -
- Example +```cpp +#define HEADER "header_b.h" +#include HEADER +``` - ```cpp - #define HEADER "header_b.h" - #include HEADER - ``` +### `#include_next` and `__has_include_next` -
+Links continue down the search path -- [ ] `#include_next` and `__has_include_next` — links continue down the search path _(partial)_ +`first/wrap.h` shadows `second/wrap.h` on the search path; its +`#include_next` (guarded by `__has_include_next`) includes the second +copy. Next-in-path resolution only exists when the header is compiled +in an including TU's context — opened standalone it is compiled as its +own TU, where clang deliberately treats `#include_next` as a plain +include, so today both links land back on the first copy (as the +snapshot pins). - `first/wrap.h` shadows `second/wrap.h` on the search path; its - `#include_next` (guarded by `__has_include_next`) includes the second - copy. Next-in-path resolution only exists when the header is compiled - in an including TU's context — opened standalone it is compiled as its - own TU, where clang deliberately treats `#include_next` as a plain - include, so today both links land back on the first copy (as the - snapshot pins). +`main.cpp`: -
- Example +```cpp +#include - `main.cpp`: +int use_wrap = WRAP_FIRST + WRAP_SECOND; +``` - ```cpp - #include +`first/wrap.h`: - int use_wrap = WRAP_FIRST + WRAP_SECOND; - ``` +```cpp +#pragma once - `first/wrap.h`: +#define WRAP_FIRST 1 - ```cpp - #pragma once +#if __has_include_next() +#include_next +#endif +``` - #define WRAP_FIRST 1 +`second/wrap.h`: - #if __has_include_next() - #include_next - #endif - ``` +```cpp +#pragma once - `second/wrap.h`: +#define WRAP_SECOND 2 +``` - ```cpp - #pragma once +### `__has_include` - #define WRAP_SECOND 2 - ``` +The checked path links to the file it probes -
- -- [x] `__has_include` — the checked path links to the file it probes - -
- Example - - ```cpp - #if __has_include("header_c.h") - #include "header_c.h" - #endif - ``` - -
+```cpp +#if __has_include("header_c.h") +#include "header_c.h" +#endif +``` ## Embed Directives - - -- [x] `#embed` — the resource path links to the embedded file + -
- Example +| Capability | Status | Issues | +| ------------- | --------- | ------ | +| `#embed` | Supported | | +| `__has_embed` | Supported | | - ```cpp - const char data[] = { - #embed "data.bin" - }; - ``` +### `#embed` -
+The resource path links to the embedded file -- [x] `__has_embed` — the checked path links to the probed resource +```cpp +const char data[] = { +#embed "data.bin" +}; +``` -
- Example +### `__has_embed` - ```cpp - #if __has_embed("data.bin") - const char first_byte[] = { - #embed "data.bin" limit(1) - }; - #endif - ``` +The checked path links to the probed resource -
+```cpp +#if __has_embed("data.bin") +const char first_byte[] = { +#embed "data.bin" limit(1) +}; +#endif +``` ## Presentation - + -- [x] Resolved-path tooltips — every link carries its target's absolute path as the hover tooltip +| Capability | Status | Issues | +| ---------------------- | --------- | ------ | +| Resolved-path tooltips | Supported | | - Editors render the tooltip next to the follow-link hint, e.g. - `/usr/include/c++/14/vector (ctrl + click)`. Snapshots pin only the - link targets; the suite instead validates the tooltip against the - target on the server reply of every fixture in this corpus. +### Resolved-path tooltips -
- Example +Every link carries its target's absolute path as the hover tooltip - ```cpp - #include "header_a.h" - ``` +Editors render the tooltip next to the follow-link hint, e.g. +`/usr/include/c++/14/vector (ctrl + click)`. Snapshots pin only the +link targets; the suite instead validates the tooltip against the +target on the server reply of every fixture in this corpus. -
+```cpp +#include "header_a.h" +``` ## Module Declarations - + -- [ ] Module targets — `import` and `module` declarations link to their interface files +| Capability | Status | Issues | +| -------------- | ----------- | ------ | +| Module targets | Unsupported | | -
- Example +### Module targets - ```cpp - export module app; +`import` and `module` declarations link to their interface files - import lib; - import :part; - export import lib.extra; - ``` +```cpp +export module app; -
+import lib; +import :part; +export import lib.extra; +``` diff --git a/en/clice/features/document-symbols.md b/en/clice/features/document-symbols.md index 52c159d7..e0860275 100644 --- a/en/clice/features/document-symbols.md +++ b/en/clice/features/document-symbols.md @@ -1,6 +1,6 @@ # Document Symbols - @@ -9,710 +9,674 @@ Provides the file outline and breadcrumb navigation via `textDocument/documentSy ## Symbol Hierarchy - + -- [x] Nested symbol tree — symbols nest by their written scope; out-of-line definitions appear at their lexical position with qualified names +| Capability | Status | Issues | +| ---------------------------------- | ----------- | --------------------------------------------------------- | +| Nested symbol tree | Supported | | +| Symbol ranges and selection ranges | Supported | | +| Access specifier grouping | Unsupported | [clangd#499](https://github.com/clangd/clangd/issues/499) | +| Anonymous and inline scopes | Supported | | +| UTF-16 position encoding | Supported | | -
- Example +### Nested symbol tree - ```cpp - namespace demo { +Symbols nest by their written scope; out-of-line definitions appear at their lexical position with qualified names - struct Point { - int x; - int y; +```cpp +namespace demo { - int manhattan() const; - }; +struct Point { + int x; + int y; - int Point::manhattan() const { - return x + y; - } + int manhattan() const; +}; - enum class Axis { X, Y }; +int Point::manhattan() const { + return x + y; +} - int origin_distance(const Point& p); +enum class Axis { X, Y }; - namespace inner { - constexpr int level = 2; - } +int origin_distance(const Point& p); - } // namespace demo +namespace inner { +constexpr int level = 2; +} - // A reopened namespace gets its own outline node per written scope. - namespace demo { - int reopened(); - } +} // namespace demo - namespace demo::nested { - int compact(); - } - ``` +// A reopened namespace gets its own outline node per written scope. +namespace demo { +int reopened(); +} -
+namespace demo::nested { +int compact(); +} +``` -- [x] Symbol ranges and selection ranges — the range spans the whole declaration; the selection range covers the full written name, including multi-token names like `~Widget`, `operator==` and `operator bool` +### Symbol ranges and selection ranges -
- Example +The range spans the whole declaration; the selection range covers the full written name, including multi-token names like `~Widget`, `operator==` and `operator bool` - ```cpp - namespace members { +```cpp +namespace members { - struct Widget { - Widget(); - explicit Widget(int size); - ~Widget(); +struct Widget { + Widget(); + explicit Widget(int size); + ~Widget(); - Widget& operator=(const Widget& other); - bool operator==(const Widget& other) const; - operator bool() const; + Widget& operator=(const Widget& other); + bool operator==(const Widget& other) const; + operator bool() const; - static int instances(); + static int instances(); - int size; - unsigned bits : 3; - const char* name = "widget"; - }; + int size; + unsigned bits : 3; + const char* name = "widget"; +}; - Widget::Widget(int size) : size(size), bits(0) {} +Widget::Widget(int size) : size(size), bits(0) {} - int Widget::instances() { - return 0; - } +int Widget::instances() { + return 0; +} - } // namespace members - ``` +} // namespace members +``` -
+### Access specifier grouping -- [ ] Access specifier grouping — `public:` / `private:` / `protected:` as grouping nodes for breadcrumb navigation ([clangd#499](https://github.com/clangd/clangd/issues/499)) +`public:` / `private:` / `protected:` as grouping nodes for breadcrumb navigation -
- Example +```cpp +class Widget { +public: + void draw(); + void resize(); - ```cpp - class Widget { - public: - void draw(); - void resize(); +private: + int width; + int height; +}; +``` - private: - int width; - int height; - }; - ``` +### Anonymous and inline scopes -
+Anonymous namespaces, unnamed structs and unions group their members under a placeholder name; inline namespace members stay under the inline namespace node -- [x] Anonymous and inline scopes — anonymous namespaces, unnamed structs and unions group their members under a placeholder name; inline namespace members stay under the inline namespace node +```cpp +namespace { -
- Example +int hidden_counter = 0; - ```cpp - namespace { +} // namespace - int hidden_counter = 0; +namespace misc { - } // namespace +inline namespace v1 { - namespace misc { +int versioned(); - inline namespace v1 { +} // namespace v1 - int versioned(); +struct Outer { + struct { + int anonymous_member; + }; - } // namespace v1 + union { + int as_int; + float as_float; + }; +}; - struct Outer { - struct { - int anonymous_member; - }; +} // namespace misc +``` - union { - int as_int; - float as_float; - }; - }; +### UTF-16 position encoding - } // namespace misc - ``` +Columns after non-ASCII text count UTF-16 code units -
- -- [x] UTF-16 position encoding — columns after non-ASCII text count UTF-16 code units - -
- Example - - ```cpp - // π ≈ 3.14159, 中文注释 - constexpr double 半径 = 2.0; - constexpr double π值 = 3.14159; double area(); - ``` - -
+```cpp +// π ≈ 3.14159, 中文注释 +constexpr double 半径 = 2.0; +constexpr double π值 = 3.14159; double area(); +``` ## Symbol Kinds - - -- [x] Core symbol kinds — namespaces, classes, structs, unions, enums and their members, functions, variables, fields, structured bindings and lambdas all appear in the outline with a mapped LSP symbol kind - -
- Example + - ```cpp - namespace kinds { +| Capability | Status | Issues | +| --------------------------------------------- | --------- | ----------------------------------------------------------------- | +| Core symbol kinds | Supported | | +| Template declarations | Supported | | +| Template specializations and deduction guides | Supported | | +| Type aliases | Supported | | +| Explicit instantiation directives | Partial | [llvm#191658](https://github.com/llvm/llvm-project/issues/191658) | +| Macro definitions | Supported | [clangd#1744](https://github.com/clangd/clangd/issues/1744) | +| Macros in the preamble region | Partial | | - union Value { - int i; - float f; - }; +### Core symbol kinds - enum Flags { FlagA, FlagB }; +namespaces, classes, structs, unions, enums and their members, functions, variables, fields, structured bindings and lambdas all appear in the outline with a mapped LSP symbol kind - enum class Mode : unsigned char { Fast, Safe }; +```cpp +namespace kinds { - struct Pair { - struct Meta { - int tag; - }; +union Value { + int i; + float f; +}; - int first; - int second; - static int instances; - }; +enum Flags { FlagA, FlagB }; - Pair make_pair(); +enum class Mode : unsigned char { Fast, Safe }; - auto [bound_first, bound_second] = make_pair(); +struct Pair { + struct Meta { + int tag; + }; - auto lambda = [](int x) { - return x * 2; - }; + int first; + int second; + static int instances; +}; - } // namespace kinds - ``` +Pair make_pair(); -
+auto [bound_first, bound_second] = make_pair(); -- [x] Template declarations — class, function and variable templates carry a `template ` detail prefix; concepts and abbreviated function templates (`concept auto` parameters) appear as well +auto lambda = [](int x) { + return x * 2; +}; -
- Example +} // namespace kinds +``` - ```cpp - namespace templates { +### Template declarations - template - struct Box { - T value; +class, function and variable templates carry a `template ` detail prefix; concepts and abbreviated function templates (`concept auto` parameters) appear as well - void reset(); - }; +```cpp +namespace templates { - template - void Box::reset() {} +template +struct Box { + T value; - template - T zero() { - return T(); - } + void reset(); +}; - template - constexpr T pi = T(3.14159); +template +void Box::reset() {} - template - concept Small = sizeof(T) <= 4; +template +T zero() { + return T(); +} - void takes_concept(Small auto x); +template +constexpr T pi = T(3.14159); - } // namespace templates - ``` +template +concept Small = sizeof(T) <= 4; -
+void takes_concept(Small auto x); -- [x] Template specializations and deduction guides — explicit and partial specializations of class and variable templates appear with their template arguments in the name; members nest under their specialization; deduction guides render their deduced signature +} // namespace templates +``` -
- Example +### Template specializations and deduction guides - ```cpp - namespace spec { +Explicit and partial specializations of class and variable templates appear with their template arguments in the name; members nest under their specialization; deduction guides render their deduced signature - template - struct Box { - T value; - }; +```cpp +namespace spec { - template <> - struct Box {}; +template +struct Box { + T value; +}; - template - struct Box { - T* pointee; - }; +template <> +struct Box {}; - template - T zero() { - return T(); - } +template +struct Box { + T* pointee; +}; - template <> - int zero(); +template +T zero() { + return T(); +} - template - constexpr T pi = T(3); +template <> +int zero(); - template <> - constexpr int pi = 3; +template +constexpr T pi = T(3); - template - constexpr T* pi = nullptr; +template <> +constexpr int pi = 3; - template - struct Deduced { - Deduced(T raw); - }; +template +constexpr T* pi = nullptr; - template - Deduced(T*) -> Deduced; +template +struct Deduced { + Deduced(T raw); +}; - // Forces the implicit instantiation Box, which must not appear. - Box instantiated; +template +Deduced(T*) -> Deduced; - // An explicit class instantiation gets a childless node; the instantiated - // members and the function instantiation (whose location clang records at - // the primary) produce no symbols. - template struct Box; - template long zero(); +// Forces the implicit instantiation Box, which must not appear. +Box instantiated; - } // namespace spec - ``` +// An explicit class instantiation gets a childless node; the instantiated +// members and the function instantiation (whose location clang records at +// the primary) produce no symbols. +template struct Box; +template long zero(); -
+} // namespace spec +``` -- [x] Type aliases — `typedef`, `using` aliases and alias templates appear in the outline with a `type alias` detail +### Type aliases -
- Example +`typedef`, `using` aliases and alias templates appear in the outline with a `type alias` detail - ```cpp - namespace aliases { +```cpp +namespace aliases { - struct Widget {}; +struct Widget {}; - typedef Widget LegacyWidget; +typedef Widget LegacyWidget; - using ModernWidget = Widget; +using ModernWidget = Widget; - template - struct Box {}; +template +struct Box {}; - template - using BoxOf = Box; +template +using BoxOf = Box; - struct Holder { - using Inner = Widget; - }; +struct Holder { + using Inner = Widget; +}; - } // namespace aliases - ``` +} // namespace aliases +``` -
+### Explicit instantiation directives -- [ ] Explicit instantiation directives — the class forms appear as childless symbols; clang mislocates the function and variable forms at the pattern, so they are missing from the outline _(partial)_ ([llvm#191658](https://github.com/llvm/llvm-project/issues/191658)) +The class forms appear as childless symbols; clang mislocates the function and variable forms at the pattern, so they are missing from the outline -
- Example +```cpp +template +struct Box { + T value; +}; - ```cpp - template - struct Box { - T value; - }; +template struct Box; +extern template struct Box; - template struct Box; - extern template struct Box; +template +void convert(T value) {} - template - void convert(T value) {} +template void convert(int); - template void convert(int); +template +T zero = T(); - template - T zero = T(); +template int zero; +``` - template int zero; - ``` +### Macro definitions -
+object-like and function-like macro definitions in the outline, a parameter list as the function-like detail -- [x] Macro definitions — object-like and function-like macro definitions in the outline, a parameter list as the function-like detail ([clangd#1744](https://github.com/clangd/clangd/issues/1744)) +```cpp +// The assertion holds the directives out of the preamble region, whose +// live record the server path does not yet see. +static_assert(true); -
- Example +#define MAX_BUFFER_SIZE 4096 +#define CHECK(cond, msg) ((cond) ? 0 : (msg)) +#define TRACE(...) log(__VA_ARGS__) +#define SPLIT_\ +LIMIT 7 - ```cpp - // The assertion holds the directives out of the preamble region, whose - // live record the server path does not yet see. - static_assert(true); +struct Config { +#define CONFIG_VERSION 3 + int version = CONFIG_VERSION; +}; +``` - #define MAX_BUFFER_SIZE 4096 - #define CHECK(cond, msg) ((cond) ? 0 : (msg)) - #define TRACE(...) log(__VA_ARGS__) - #define SPLIT_\ - LIMIT 7 +### Macros in the preamble region - struct Config { - #define CONFIG_VERSION 3 - int version = CONFIG_VERSION; - }; - ``` +Definitions in the leading directive run outline on the inspect path, while the server's preamble record does not surface them yet -
+```cpp +#define PREAMBLE_LIMIT 8 +#define PREAMBLE_CHECK(cond) (!!(cond)) -- [ ] Macros in the preamble region — definitions in the leading directive run outline on the inspect path, while the server's preamble record does not surface them yet _(partial)_ - -
- Example - - ```cpp - #define PREAMBLE_LIMIT 8 - #define PREAMBLE_CHECK(cond) (!!(cond)) - - int after = PREAMBLE_LIMIT; - ``` - -
+int after = PREAMBLE_LIMIT; +``` ## Symbol Detail - - -- [x] Function signatures — parameter and return types in the `detail` field disambiguate overloads; constructors drop the `void` return type ([clangd#520](https://github.com/clangd/clangd/issues/520), [clangd#601](https://github.com/clangd/clangd/issues/601), [clangd#1232](https://github.com/clangd/clangd/issues/1232)) + -
- Example +| Capability | Status | Issues | +| -------------------------- | ----------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Function signatures | Supported | [clangd#520](https://github.com/clangd/clangd/issues/520), [clangd#601](https://github.com/clangd/clangd/issues/601), [clangd#1232](https://github.com/clangd/clangd/issues/1232) | +| Variable and field types | Supported | | +| Default argument stripping | Supported | [clangd#221](https://github.com/clangd/clangd/issues/221) | +| Base classes in detail | Unsupported | | +| Multiline signature ranges | Supported | [clangd#2221](https://github.com/clangd/clangd/issues/2221) | +| Scoped types | Supported | | - ```cpp - namespace detail { +### Function signatures - void process(int x); - void process(const char* s); +Parameter and return types in the `detail` field disambiguate overloads; constructors drop the `void` return type - struct Task { - Task(); - Task(int priority); +```cpp +namespace detail { - int run(bool async) const; - }; +void process(int x); +void process(const char* s); - } // namespace detail - ``` +struct Task { + Task(); + Task(int priority); -
+ int run(bool async) const; +}; -- [x] Variable and field types — the declared type in the `detail` field; lambdas render as `(lambda)` +} // namespace detail +``` -
- Example +### Variable and field types - ```cpp - namespace detail { +The declared type in the `detail` field; lambdas render as `(lambda)` - int timeout = 30; - const char* logger_name = "core"; +```cpp +namespace detail { - struct Config { - unsigned retries; - double backoff; - }; +int timeout = 30; +const char* logger_name = "core"; - auto on_error = [](int code) { - return code != 0; - }; +struct Config { + unsigned retries; + double backoff; +}; - } // namespace detail - ``` +auto on_error = [](int code) { + return code != 0; +}; -
+} // namespace detail +``` -- [x] Default argument stripping — the signature is derived from the function type, so default parameter values never leak into the outline ([clangd#221](https://github.com/clangd/clangd/issues/221)) +### Default argument stripping -
- Example +The signature is derived from the function type, so default parameter values never leak into the outline - ```cpp - namespace detail { +```cpp +namespace detail { - void open_file(const char* path, int mode = 0644); +void open_file(const char* path, int mode = 0644); - struct Server { - void listen(int port = 8080, int backlog = 128); - }; +struct Server { + void listen(int port = 8080, int backlog = 128); +}; - } // namespace detail - ``` +} // namespace detail +``` -
+### Base classes in detail -- [ ] Base classes in detail — show `: Shape` on derived class declarations +Show `: Shape` on derived class declarations -
- Example +```cpp +struct Shape {}; - ```cpp - struct Shape {}; +struct Circle : Shape { + double radius; +}; +``` - struct Circle : Shape { - double radius; - }; - ``` +### Multiline signature ranges -
+The symbol range starts at the beginning of the declaration and spans the full signature, so editor sticky scroll anchors correctly -- [x] Multiline signature ranges — the symbol range starts at the beginning of the declaration and spans the full signature, so editor sticky scroll anchors correctly ([clangd#2221](https://github.com/clangd/clangd/issues/2221)) +```cpp +struct Config {}; -
- Example +void process_data( + const Config& cfg, + int flags +) {} +``` - ```cpp - struct Config {}; +### Scoped types - void process_data( - const Config& cfg, - int flags - ) {} - ``` +A written class scope appears in the detail exactly once, for nested classes, template-ids, aliases and dependent names alike -
+```cpp +namespace scoped { -- [x] Scoped types — a written class scope appears in the detail exactly once, for nested classes, template-ids, aliases and dependent names alike +struct Outer { + struct Inner {}; + template struct Box {}; + using Alias = int; +}; -
- Example +struct User { + Outer::Inner plain; + Outer::Box boxed; + Outer::Alias aliased; + const Outer::Inner frozen; +}; - ```cpp - namespace scoped { +template +struct Holder { + typename T::type value; + typename T::inner::type deep; + typename T::template rebind bound; +}; - struct Outer { - struct Inner {}; - template struct Box {}; - using Alias = int; - }; - - struct User { - Outer::Inner plain; - Outer::Box boxed; - Outer::Alias aliased; - const Outer::Inner frozen; - }; - - template - struct Holder { - typename T::type value; - typename T::inner::type deep; - typename T::template rebind bound; - }; - - } // namespace scoped - ``` - -
+} // namespace scoped +``` ## Missing Symbols - - -- [ ] Include directives — `#include` entries in the outline ([clangd#2226](https://github.com/clangd/clangd/issues/2226)) + -
- Example +| Capability | Status | Issues | +| --------------------------------- | ----------- | ----------------------------------------------------------- | +| Include directives | Unsupported | [clangd#2226](https://github.com/clangd/clangd/issues/2226) | +| Local symbols | Supported | [clangd#616](https://github.com/clangd/clangd/issues/616) | +| Module declarations | Unsupported | | +| `#pragma mark` navigation markers | Unsupported | | +| Friend function definitions | Supported | | - ```cpp - #include "config.h" +### Include directives - int uses_config(); - ``` +`#include` entries in the outline -
+```cpp +#include "config.h" -- [x] Local symbols — variables and types declared inside function bodies nest under their function ([clangd#616](https://github.com/clangd/clangd/issues/616)) +int uses_config(); +``` -
- Example +### Local symbols - ```cpp - int compute() { - int local_sum = 0; +Variables and types declared inside function bodies nest under their function - struct Accumulator { - int total; - }; +```cpp +int compute() { + int local_sum = 0; - auto twice = [](int x) { - return 2 * x; - }; + struct Accumulator { + int total; + }; - struct Pair { - int a; - int b; - }; + auto twice = [](int x) { + return 2 * x; + }; - auto [first, second] = Pair{1, 2}; + struct Pair { + int a; + int b; + }; - return local_sum + twice(first) + second; - } - ``` + auto [first, second] = Pair{1, 2}; -
+ return local_sum + twice(first) + second; +} +``` -- [ ] Module declarations — `export module`, `module` and `import` declarations in the outline +### Module declarations -
- Example +`export module`, `module` and `import` declarations in the outline - ```cpp - export module app.core; +```cpp +export module app.core; - import std; +import std; - export int core_entry(); - ``` +export int core_entry(); +``` -
+### `#pragma mark` navigation markers -- [ ] `#pragma mark` navigation markers — editor section markers as outline entries +Editor section markers as outline entries -
- Example +```cpp +#pragma mark - Lifecycle - ```cpp - #pragma mark - Lifecycle +void setup(); - void setup(); +#pragma mark - Rendering - #pragma mark - Rendering +void draw(); +``` - void draw(); - ``` +### Friend function definitions -
+A friend function defined inline in a class appears under that class -- [x] Friend function definitions — a friend function defined inline in a class appears under that class +```cpp +struct Owner { + friend void inline_friend(Owner& o) {} -
- Example - - ```cpp - struct Owner { - friend void inline_friend(Owner& o) {} - - friend bool operator==(const Owner& lhs, const Owner& rhs) { - return &lhs == &rhs; - } - }; - ``` - -
+ friend bool operator==(const Owner& lhs, const Owner& rhs) { + return &lhs == &rhs; + } +}; +``` ## Symbol Tags - + -- [ ] Deprecated tag — mark `[[deprecated]]` symbols with the LSP `deprecated` symbol tag +| Capability | Status | Issues | +| ----------------------------- | ----------- | ----------------------------------------------------------- | +| Deprecated tag | Unsupported | | +| Access and storage indicators | Unsupported | [clangd#2123](https://github.com/clangd/clangd/issues/2123) | -
- Example +### Deprecated tag - ```cpp - [[deprecated("use open_v2")]] void open_v1(); +Mark `[[deprecated]]` symbols with the LSP `deprecated` symbol tag - void open_v2(); - ``` +```cpp +[[deprecated("use open_v2")]] void open_v1(); -
+void open_v2(); +``` -- [ ] Access and storage indicators — public / private / protected, static, virtual and abstract markers on outline entries ([clangd#2123](https://github.com/clangd/clangd/issues/2123)) +### Access and storage indicators -
- Example +Public / private / protected, static, virtual and abstract markers on outline entries - ```cpp - class Base { - public: - virtual void render() = 0; +```cpp +class Base { +public: + virtual void render() = 0; - protected: - static int instances(); +protected: + static int instances(); - private: - int id; - }; - ``` - -
+private: + int id; +}; +``` ## Location Correctness - - -- [x] Symbols from macro expansions — a symbol produced by a macro invocation is located at the invocation, not at the macro definition ([clangd#475](https://github.com/clangd/clangd/issues/475)) + -
- Example +| Capability | Status | Issues | +| -------------------------------- | --------- | ----------------------------------------------------------- | +| Symbols from macro expansions | Supported | [clangd#475](https://github.com/clangd/clangd/issues/475) | +| Names spelled in macro arguments | Supported | [clangd#1941](https://github.com/clangd/clangd/issues/1941) | - ```cpp - // The assertion holds the directives out of the preamble region, whose - // live record the server path does not yet see. - static_assert(true); +### Symbols from macro expansions - #define DEFINE_HANDLER(name) void name() +A symbol produced by a macro invocation is located at the invocation, not at the macro definition - DEFINE_HANDLER(on_ready); - DEFINE_HANDLER(on_close); +```cpp +// The assertion holds the directives out of the preamble region, whose +// live record the server path does not yet see. +static_assert(true); - #define DECLARE_CLASS(X) class X - DECLARE_CLASS(Generated) { - int member; - }; - ``` +#define DEFINE_HANDLER(name) void name() -
+DEFINE_HANDLER(on_ready); +DEFINE_HANDLER(on_close); -- [x] Names spelled in macro arguments — the selection range points at the name written in the macro argument; names spelled in the macro body fall back to the invocation site ([clangd#1941](https://github.com/clangd/clangd/issues/1941)) +#define DECLARE_CLASS(X) class X +DECLARE_CLASS(Generated) { + int member; +}; +``` -
- Example +### Names spelled in macro arguments - ```cpp - // The assertion holds the directives out of the preamble region, whose - // live record the server path does not yet see. - static_assert(true); +The selection range points at the name written in the macro argument; names spelled in the macro body fall back to the invocation site - #define VAR(X) int X = 1; +```cpp +// The assertion holds the directives out of the preamble region, whose +// live record the server path does not yet see. +static_assert(true); - VAR(from_argument) +#define VAR(X) int X = 1; - #define COUNTER() int counter_from_body = 0; +VAR(from_argument) - COUNTER() - ``` +#define COUNTER() int counter_from_body = 0; -
+COUNTER() +``` diff --git a/en/clice/features/folding-ranges.md b/en/clice/features/folding-ranges.md index 8509ba0f..04a7b121 100644 --- a/en/clice/features/folding-ranges.md +++ b/en/clice/features/folding-ranges.md @@ -1,624 +1,580 @@ # Folding Ranges - ## Fold Kinds - + + +| Capability | Status | Issues | +| ---------------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------ | +| Block folding | Supported | | +| Nested compound-statement folding | Supported | | +| Multi-line list folding | Supported | | +| Access-specifier section folding | Supported | [clangd#1455](https://github.com/clangd/clangd/issues/1455) | +| Preprocessor conditional folding (`#if` / `#ifdef` / `#ifndef` ... `#endif`) | Partial | [clangd#1661](https://github.com/clangd/clangd/issues/1661), [clangd#2059](https://github.com/clangd/clangd/issues/2059) | +| Custom region folding (`#pragma region` / `#pragma endregion`) | Supported | [clangd#1623](https://github.com/clangd/clangd/issues/1623) | +| Pragma classification | Supported | | +| Comment folding | Unsupported | | +| Include region folding | Unsupported | | +| Raw string literal folding | Unsupported | | +| `using` declaration blocks | Unsupported | | +| Template parameter list folding | Unsupported | | +| Template specializations and instantiations | Supported | | +| Abbreviated function templates | Supported | | +| Macro-generated folding | Supported | | +| Coroutine bodies | Supported | | +| Initializer-list constructions | Supported | | + +### Block folding + +functions, classes, structs, unions, enums, namespaces, lambdas + +```cpp +namespace geometry { + +enum class Shape { + Circle, + Square, + Triangle +}; + +struct Point { + int x; + int y; +}; + +union Value { + int as_int; + float as_float; +}; + +class Canvas { + Point origin; + + int area() { + auto scale = [](int factor) { + return factor * 2; + }; + return scale(4); + } +}; + +} // namespace geometry + +namespace spaced +{ + +struct Placeholder { + int filler; +}; + +} // namespace spaced +``` + +### Nested compound-statement folding + +`if`/`for`/`while` bodies inside functions + +```cpp +void process(int count) { + if (count > 0) { + for (int i = 0; i < count; i += 1) { + count -= 1; + } + } + + while (count > 0) { + count -= 1; + } + + // A bare scope block folds too. + { + int scratch = count; + count = scratch + 1; + } +} +``` + +### Multi-line list folding + +Function parameters, call arguments, initializer lists, lambda captures + +```cpp +void configure( + int width, // ┐ + int height, // │ foldable parameter list + bool fullscreen // ┘ +); + +int compute(int a, int b, int c); + +void demo() { + int values[] = { + 1, // ┐ + 2, // │ foldable initializer list + 3 // ┘ + }; + + int result = compute( + values[0], // ┐ + values[1], // │ foldable argument list + values[2] // ┘ + ); + + auto sum = [ + first = values[0], // ┐ + second = values[1] // ┘ foldable lambda capture + ] { + return first + second; + }; + + auto scale = []( + int base, // ┐ foldable lambda + int factor // ┘ parameter list + ) { + return base * factor; + }; + + result += sum() + scale(result, 2); +} + +int accumulate( + int start, // ┐ + int step, // │ foldable parameter list + int count // ┘ on a definition +) { + return start + step * count; +} + +void log_all( + const char* format, // ┐ variadic parameter + ... // ┘ list still folds +); + +struct Rect { + Rect(int w, int h); +}; + +Rect area( + 10, // ┐ foldable constructor + 20 // ┘ arguments +); + +Rect brace_area{ + 30, + 40 +}; +``` + +### Access-specifier section folding + +`public:` / `protected:` / `private:` regions within a class + +```cpp +class Widget { +public: // ┐ + void draw(); // │ foldable + void resize(); // ┘ +private: // ┐ + int width; // │ foldable + int height; // ┘ +}; +``` + +### Preprocessor conditional folding (`#if` / `#ifdef` / `#ifndef` ... `#endif`) + +Branch regions delimited by `#else` fold today; a bare `#if ... #endif` +block without an `#else` does not fold yet. clangd#2059 is a duplicate +of clangd#1661. + +```cpp +#ifdef ENABLE_LOGGING // ┐ +void log_message(); // │ no fold yet: bare conditional without #else +#endif // ┘ + +#ifdef USE_THREADS // ┐ +void spawn_workers(); // │ folds: branches delimited by #else +#else // │ +void run_inline(); // │ +#endif // ┘ + +#ifdef USE_EPOLL // ┐ +void poll_epoll(); // │ no fold yet: the branch before #elifdef +#elifdef USE_KQUEUE // │ ┐ +void poll_kqueue(); // │ │ folds: the #elifdef branch, delimited by #else +#else // │ ┘ +void poll_select(); // │ +#endif // ┘ +``` + +### Custom region folding (`#pragma region` / `#pragma endregion`) + +```cpp +#pragma region Configuration + +int retry_count = 3; +int timeout_ms = 5000; + +#pragma endregion +``` + +### Pragma classification + +Only the first argument token decides region/endregion + +```cpp +// The leading declaration ends the preamble so the pragmas below reach the +// main-file parse on both the inspect and the server path. +int before = 0; + +// Neither a region name nor another pragma's argument mentioning +// "endregion" may close the fold early. +#pragma region endregion_pair +int retries = 3; +#pragma mark see endregion notes +int limit = 10; +#pragma endregion + +// The tail of a multiline comment before the introducer must not hide +// the region either. +/* spans +a line */ #pragma region after_comment +int after = 1; +#pragma endregion +``` + +### Comment folding + +multi-line `/* */` and consecutive `//` line comments + +```cpp +// This is a long +// multi-line comment +// that should fold as one region + +/* + * Block comment + * should also fold + */ +``` + +### Include region folding + +Consecutive `#include` directives + +```cpp +#include // ┐ +#include // │ foldable region +#include // ┘ + +#include "app.h" // ┐ separate region +#include "config.h" // ┘ (blank line separates) +``` + +### Raw string literal folding + +```cpp +auto sql = R"( + SELECT * + FROM users + WHERE active = true +)"; // foldable multi-line raw string +``` -- [x] Block folding — functions, classes, structs, unions, enums, namespaces, lambdas +### `using` declaration blocks -
- Example +Consecutive using declarations/directives + +```cpp +using std::vector; // ┐ +using std::string; // │ foldable +using std::map; // ┘ +``` - ```cpp - namespace geometry { +### Template parameter list folding + +```cpp +template +struct Less; - enum class Shape { - Circle, - Square, - Triangle - }; - - struct Point { - int x; - int y; - }; - - union Value { - int as_int; - float as_float; - }; - - class Canvas { - Point origin; - - int area() { - auto scale = [](int factor) { - return factor * 2; - }; - return scale(4); - } - }; - - } // namespace geometry - - namespace spaced - { - - struct Placeholder { - int filler; - }; - - } // namespace spaced - ``` - -
- -- [x] Nested compound-statement folding — `if`/`for`/`while` bodies inside functions - -
- Example - - ```cpp - void process(int count) { - if (count > 0) { - for (int i = 0; i < count; i += 1) { - count -= 1; - } - } - - while (count > 0) { - count -= 1; - } - - // A bare scope block folds too. - { - int scratch = count; - count = scratch + 1; - } - } - ``` - -
- -- [x] Multi-line list folding — function parameters, call arguments, initializer lists, lambda captures - -
- Example - - ```cpp - void configure( - int width, // ┐ - int height, // │ foldable parameter list - bool fullscreen // ┘ - ); - - int compute(int a, int b, int c); - - void demo() { - int values[] = { - 1, // ┐ - 2, // │ foldable initializer list - 3 // ┘ - }; - - int result = compute( - values[0], // ┐ - values[1], // │ foldable argument list - values[2] // ┘ - ); - - auto sum = [ - first = values[0], // ┐ - second = values[1] // ┘ foldable lambda capture - ] { - return first + second; - }; - - auto scale = []( - int base, // ┐ foldable lambda - int factor // ┘ parameter list - ) { - return base * factor; - }; - - result += sum() + scale(result, 2); - } - - int accumulate( - int start, // ┐ - int step, // │ foldable parameter list - int count // ┘ on a definition - ) { - return start + step * count; - } - - void log_all( - const char* format, // ┐ variadic parameter - ... // ┘ list still folds - ); - - struct Rect { - Rect(int w, int h); - }; - - Rect area( - 10, // ┐ foldable constructor - 20 // ┘ arguments - ); - - Rect brace_area{ - 30, - 40 - }; - ``` - -
- -- [x] Access-specifier section folding — `public:` / `protected:` / `private:` regions within a class ([clangd#1455](https://github.com/clangd/clangd/issues/1455)) - -
- Example - - ```cpp - class Widget { - public: // ┐ - void draw(); // │ foldable - void resize(); // ┘ - private: // ┐ - int width; // │ foldable - int height; // ┘ - }; - ``` - -
- -- [ ] Preprocessor conditional folding (`#if` / `#ifdef` / `#ifndef` ... `#endif`) _(partial)_ ([clangd#1661](https://github.com/clangd/clangd/issues/1661), [clangd#2059](https://github.com/clangd/clangd/issues/2059)) - - Branch regions delimited by `#else` fold today; a bare `#if ... #endif` - block without an `#else` does not fold yet. clangd#2059 is a duplicate - of clangd#1661. - -
- Example - - ```cpp - #ifdef ENABLE_LOGGING // ┐ - void log_message(); // │ no fold yet: bare conditional without #else - #endif // ┘ - - #ifdef USE_THREADS // ┐ - void spawn_workers(); // │ folds: branches delimited by #else - #else // │ - void run_inline(); // │ - #endif // ┘ - - #ifdef USE_EPOLL // ┐ - void poll_epoll(); // │ no fold yet: the branch before #elifdef - #elifdef USE_KQUEUE // │ ┐ - void poll_kqueue(); // │ │ folds: the #elifdef branch, delimited by #else - #else // │ ┘ - void poll_select(); // │ - #endif // ┘ - ``` +template< + typename Key, // ┐ + typename Value, // │ foldable + typename Compare = Less // ┘ +> +class SortedMap { }; +``` -
- -- [x] Custom region folding (`#pragma region` / `#pragma endregion`) ([clangd#1623](https://github.com/clangd/clangd/issues/1623)) - -
- Example - - ```cpp - #pragma region Configuration +### Template specializations and instantiations - int retry_count = 3; - int timeout_ms = 5000; +Written specializations and their members fold; instantiated declarations reuse the pattern's source locations and must not fold it again - #pragma endregion - ``` +```cpp +template +struct Box { + T value; -
+ void reset() { + value = T(); + } +}; + +template <> +struct Box { + void reset() { + // nothing stored + } +}; + +template +struct Box { + T* pointee; +}; + +// Neither the implicit instantiation Box nor the explicit instantiation +// Box re-folds the primary's braces or the reset() body. +Box implicit_use; +template struct Box; +``` + +### Abbreviated function templates + +Bodies of functions with `auto` or constrained `auto` parameters fold like any other function + +```cpp +template +concept Small = sizeof(T) <= 8; + +void consume(Small auto x) { + auto copy = x; + copy += 1; +} + +void forward(auto value) { + consume(value); +} +``` + +### Macro-generated folding + +Braces and access specifiers spelled through macros fold at the invocation site + +```cpp +#define NS_BEGIN namespace ns { +#define NS_END } +#define PUBLIC public: +#define PRIVATE private: + +NS_BEGIN + +class Widget { +PUBLIC + void draw(); + void resize(); +PRIVATE + int width; + int height; +}; + +NS_END +``` + +### Coroutine bodies + +The written block folds exactly once and the coroutine transformation wrapper adds no duplicate fold; a coroutine lambda keeps its body fold + +```cpp +namespace std { + +template +struct coroutine_traits { + using promise_type = typename Ret::promise_type; +}; + +template +struct coroutine_handle { + coroutine_handle() = default; + + template + coroutine_handle(coroutine_handle) noexcept; + + static coroutine_handle from_address(void*) noexcept; +}; + +struct suspend_never { + bool await_ready() const noexcept; + void await_suspend(coroutine_handle<>) const noexcept; + void await_resume() const noexcept; +}; + +} // namespace std + +struct Task { + struct promise_type { + Task get_return_object(); + std::suspend_never initial_suspend(); + std::suspend_never final_suspend() noexcept; + void return_void(); + void unhandled_exception(); + }; +}; + +Task work() { + int steps = 0; + if (steps == 0) { + steps += 1; + } + co_return; +} + +void host() { + auto nested = []() -> Task { + int steps = 0; + steps += 1; + co_return; + }; +} +``` -- [x] Pragma classification — only the first argument token decides region/endregion - -
- Example - - ```cpp - // The leading declaration ends the preamble so the pragmas below reach the - // main-file parse on both the inspect and the server path. - int before = 0; - - // Neither a region name nor another pragma's argument mentioning - // "endregion" may close the fold early. - #pragma region endregion_pair - int retries = 3; - #pragma mark see endregion notes - int limit = 10; - #pragma endregion - - // The tail of a multiline comment before the introducer must not hide - // the region either. - /* spans - a line */ #pragma region after_comment - int after = 1; - #pragma endregion - ``` - -
- -- [ ] Comment folding — multi-line `/* */` and consecutive `//` line comments - -
- Example - - ```cpp - // This is a long - // multi-line comment - // that should fold as one region - - /* - * Block comment - * should also fold - */ - ``` - -
- -- [ ] Include region folding — consecutive `#include` directives - -
- Example - - ```cpp - #include // ┐ - #include // │ foldable region - #include // ┘ - - #include "app.h" // ┐ separate region - #include "config.h" // ┘ (blank line separates) - ``` - -
- -- [ ] Raw string literal folding - -
- Example - - ```cpp - auto sql = R"( - SELECT * - FROM users - WHERE active = true - )"; // foldable multi-line raw string - ``` - -
- -- [ ] `using` declaration blocks — consecutive using declarations/directives - -
- Example - - ```cpp - using std::vector; // ┐ - using std::string; // │ foldable - using std::map; // ┘ - ``` - -
- -- [ ] Template parameter list folding - -
- Example - - ```cpp - template - struct Less; - - template< - typename Key, // ┐ - typename Value, // │ foldable - typename Compare = Less // ┘ - > - class SortedMap { }; - ``` - -
- -- [x] Template specializations and instantiations — written specializations and their members fold; instantiated declarations reuse the pattern's source locations and must not fold it again - -
- Example - - ```cpp - template - struct Box { - T value; - - void reset() { - value = T(); - } - }; - - template <> - struct Box { - void reset() { - // nothing stored - } - }; - - template - struct Box { - T* pointee; - }; - - // Neither the implicit instantiation Box nor the explicit instantiation - // Box re-folds the primary's braces or the reset() body. - Box implicit_use; - template struct Box; - ``` - -
- -- [x] Abbreviated function templates — bodies of functions with `auto` or constrained `auto` parameters fold like any other function - -
- Example - - ```cpp - template - concept Small = sizeof(T) <= 8; - - void consume(Small auto x) { - auto copy = x; - copy += 1; - } - - void forward(auto value) { - consume(value); - } - ``` - -
- -- [x] Macro-generated folding — braces and access specifiers spelled through macros fold at the invocation site - -
- Example - - ```cpp - #define NS_BEGIN namespace ns { - #define NS_END } - #define PUBLIC public: - #define PRIVATE private: - - NS_BEGIN - - class Widget { - PUBLIC - void draw(); - void resize(); - PRIVATE - int width; - int height; - }; - - NS_END - ``` - -
- -- [x] Coroutine bodies — the written block folds exactly once and the coroutine transformation wrapper adds no duplicate fold; a coroutine lambda keeps its body fold - -
- Example - - ```cpp - namespace std { - - template - struct coroutine_traits { - using promise_type = typename Ret::promise_type; - }; - - template - struct coroutine_handle { - coroutine_handle() = default; - - template - coroutine_handle(coroutine_handle) noexcept; - - static coroutine_handle from_address(void*) noexcept; - }; - - struct suspend_never { - bool await_ready() const noexcept; - void await_suspend(coroutine_handle<>) const noexcept; - void await_resume() const noexcept; - }; - - } // namespace std - - struct Task { - struct promise_type { - Task get_return_object(); - std::suspend_never initial_suspend(); - std::suspend_never final_suspend() noexcept; - void return_void(); - void unhandled_exception(); - }; - }; - - Task work() { - int steps = 0; - if (steps == 0) { - steps += 1; - } - co_return; - } - - void host() { - auto nested = []() -> Task { - int steps = 0; - steps += 1; - co_return; - }; - } - ``` - -
- -- [x] Initializer-list constructions — the constructor's braces and the nested initializer list share delimiters and fold once; a parenthesized list argument keeps both folds - -
- Example - - ```cpp - namespace std { - - template - class initializer_list { - public: - using size_type = decltype(sizeof(0)); - - const T* ptr = nullptr; - size_type len = 0; - }; - - } // namespace std - - struct Bag { - Bag(std::initializer_list values); - }; - - Bag braces{ - 1, - 2 - }; - - Bag nested({ - 3, - 4 - }); - ``` - -
+### Initializer-list constructions + +The constructor's braces and the nested initializer list share delimiters and fold once; a parenthesized list argument keeps both folds + +```cpp +namespace std { + +template +class initializer_list { +public: + using size_type = decltype(sizeof(0)); + + const T* ptr = nullptr; + size_type len = 0; +}; + +} // namespace std + +struct Bag { + Bag(std::initializer_list values); +}; + +Bag braces{ + 1, + 2 +}; + +Bag nested({ + 3, + 4 +}); +``` ## Refinements - - -- [x] `collapsedText` placeholder (LSP 3.17) — show a summary when folded ([clangd#2667](https://github.com/clangd/clangd/issues/2667)) - - > **Client support**: VS Code does **not** support `collapsedText` yet - > ([vscode#70794](https://github.com/microsoft/vscode/issues/70794) — still - > open); Neovim with nvim-lsp supports it natively. Clients that do not - > implement this field will silently ignore it — the folding still works, - > only the placeholder text is missing. - -
- Example + - ```cpp - struct Config { - int width; - int height; - }; +| Capability | Status | Issues | +| -------------------------------------------------------- | ----------- | ----------------------------------------------------------- | +| `collapsedText` placeholder (LSP 3.17) | Supported | [clangd#2667](https://github.com/clangd/clangd/issues/2667) | +| Fold from the declaration line for function/class bodies | Unsupported | [clangd#2666](https://github.com/clangd/clangd/issues/2666) | +| Inactive preprocessor branch indication | Partial | | +| Single-line constructs stay unfolded | Supported | | - // When folded, the body collapses to a `{...}` placeholder while the - // signature stays visible: int process_data(const Config& cfg) {...} - int process_data(const Config& cfg) { - return cfg.width * cfg.height; - } - ``` +### `collapsedText` placeholder (LSP 3.17) -
+Show a summary when folded -- [ ] Fold from the declaration line for function/class bodies — keep the signature visible when folded ([clangd#2666](https://github.com/clangd/clangd/issues/2666)) +> **Client support**: VS Code does **not** support `collapsedText` yet +> ([vscode#70794](https://github.com/microsoft/vscode/issues/70794) — still +> open); Neovim with nvim-lsp supports it natively. Clients that do not +> implement this field will silently ignore it — the folding still works, +> only the placeholder text is missing. - > **Client support**: this depends on the client interpreting - > `FoldingRange.startLine` correctly. VS Code uses the line _after_ - > `startLine` as the first hidden line, so setting `startLine` to the - > declaration line achieves the desired effect. However, VS Code still - > leaves the closing `}` on a separate line rather than collapsing it onto - > the signature line ([vscode#3352](https://github.com/microsoft/vscode/issues/3352) - > — still open). Other clients may differ. +```cpp +struct Config { + int width; + int height; +}; -
- Example +// When folded, the body collapses to a `{...}` placeholder while the +// signature stays visible: int process_data(const Config& cfg) {...} +int process_data(const Config& cfg) { + return cfg.width * cfg.height; +} +``` - ```cpp - struct Config { - int width; - int height; - }; +### Fold from the declaration line for function/class bodies - // desired when folded: int process_data(const Config& cfg) {...} - // not: {... (signature hidden above fold)} - int process_data(const Config& cfg) { - int area = cfg.width * cfg.height; - return area; - } - ``` +Keep the signature visible when folded -
+> **Client support**: this depends on the client interpreting +> `FoldingRange.startLine` correctly. VS Code uses the line _after_ +> `startLine` as the first hidden line, so setting `startLine` to the +> declaration line achieves the desired effect. However, VS Code still +> leaves the closing `}` on a separate line rather than collapsing it onto +> the signature line ([vscode#3352](https://github.com/microsoft/vscode/issues/3352) +> — still open). Other clients may differ. -- [ ] Inactive preprocessor branch indication — visually distinguish or auto-fold inactive `#if`/`#else` branches _(partial)_ +```cpp +struct Config { + int width; + int height; +}; - The server emits a fold range for the region between the condition and - `#else`, so the first branch can be folded manually; the post-`#else` - branch gets no range yet. Knowing which branch is _inactive_ — to dim or - auto-fold it — is not implemented here; that information belongs to the - inactive-regions feature. +// desired when folded: int process_data(const Config& cfg) {...} +// not: {... (signature hidden above fold)} +int process_data(const Config& cfg) { + int area = cfg.width * cfg.height; + return area; +} +``` - > **Note**: this overlaps with semantic tokens (inactive code dimming) and - > is partly a client UX concern. The server can mark these ranges with - > `FoldingRangeKind.Region` and clients can choose to auto-fold them. +### Inactive preprocessor branch indication -
- Example +Visually distinguish or auto-fold inactive `#if`/`#else` branches - ```cpp - #ifdef _WIN32 - // ... Windows code (active) ... - #else - // ... POSIX code (inactive, could auto-fold) ... - #endif - ``` +The server emits a fold range for the region between the condition and +`#else`, so the first branch can be folded manually; the post-`#else` +branch gets no range yet. Knowing which branch is _inactive_ — to dim or +auto-fold it — is not implemented here; that information belongs to the +inactive-regions feature. -
+> **Note**: this overlaps with semantic tokens (inactive code dimming) and +> is partly a client UX concern. The server can mark these ranges with +> `FoldingRangeKind.Region` and clients can choose to auto-fold them. -- [x] Single-line constructs stay unfolded — a fold that hides nothing is noise +```cpp +#ifdef _WIN32 + // ... Windows code (active) ... +#else + // ... POSIX code (inactive, could auto-fold) ... +#endif +``` -
- Example +### Single-line constructs stay unfolded - ```cpp - namespace tiny { } +A fold that hides nothing is noise - struct Empty {}; +```cpp +namespace tiny { } - enum Flags { A, B }; +struct Empty {}; - void noop() {} +enum Flags { A, B }; - int values[] = {1, 2, 3}; +void noop() {} - auto lambda = [](int x) { return x; }; +int values[] = {1, 2, 3}; - int result = lambda(42); - ``` +auto lambda = [](int x) { return x; }; -
+int result = lambda(42); +``` diff --git a/en/clice/features/hover.md b/en/clice/features/hover.md index 11362a90..61d17e27 100644 --- a/en/clice/features/hover.md +++ b/en/clice/features/hover.md @@ -2,1434 +2,1339 @@ Rich information cards for the symbol under the cursor. - ## Symbol Information - + -- [x] Qualified name — the hover card shows the enclosing namespace and class scope +| Capability | Status | Issues | +| ------------------------- | --------- | ----------------------------------------------------------- | +| Qualified name | Supported | | +| Symbol kind | Supported | | +| Access specifier | Supported | | +| Definition rendering | Supported | | +| Initializer truncation | Partial | [clangd#710](https://github.com/clangd/clangd/issues/710) | +| Virtual modifiers | Partial | [clangd#2474](https://github.com/clangd/clangd/issues/2474) | +| Anonymous namespace scope | Partial | [clangd#436](https://github.com/clangd/clangd/issues/436) | -
- Example +### Qualified name - ```cpp - namespace app::detail { +The hover card shows the enclosing namespace and class scope - struct Engine { - void tick() { - int count = 0; - } - }; +```cpp +namespace app::detail { - int workers = 4; +struct Engine { + void tick() { + int count = 0; + } +}; - } +int workers = 4; - int global = 1; - ``` +} -
+int global = 1; +``` -- [x] Symbol kind — the card names what the symbol is: struct, enum, function, field, … +### Symbol kind -
- Example +The card names what the symbol is: struct, enum, function, field, … - ```cpp - namespace kinds { +```cpp +namespace kinds { - struct Point { - int x; - }; +struct Point { + int x; +}; - union Packet { - int raw; - }; +union Packet { + int raw; +}; - enum class Color { - Red, - }; +enum class Color { + Red, +}; - using Alias = Point; +using Alias = Point; - int length(Point p) { - return p.x; - } +int length(Point p) { + return p.x; +} - } - ``` +} +``` -
+### Access specifier -- [x] Access specifier — members show their public / protected / private access +Members show their public / protected / private access -
- Example +```cpp +class Account { +public: + int balance; - ```cpp - class Account { - public: - int balance; +protected: + int limit; - protected: - int limit; +private: + int pin; +}; +``` - private: - int pin; - }; - ``` +### Definition rendering -
+The card includes the symbol's source definition -- [x] Definition rendering — the card includes the symbol's source definition +```cpp +namespace retry { -
- Example +constexpr int max_retries = 3; - ```cpp - namespace retry { +int backoff(int attempt = 1) { + return attempt * max_retries; +} - constexpr int max_retries = 3; +} +``` - int backoff(int attempt = 1) { - return attempt * max_retries; - } +### Initializer truncation - } - ``` +Huge initializers render truncated, not in full -
+The rendered definition omits the initializer, but the evaluated +`Value` field still spells out all 256 elements. -- [ ] Initializer truncation — huge initializers render truncated, not in full _(partial)_ ([clangd#710](https://github.com/clangd/clangd/issues/710)) +```cpp +#define A(x) x, x, x, x +#define B(x) A(A(A(A(x)))) +int arr[] = {B(0)}; +``` - The rendered definition omits the initializer, but the evaluated - `Value` field still spells out all 256 elements. +### Virtual modifiers -
- Example +`virtual` / `override` / `final` show on method hover - ```cpp - #define A(x) x, x, x, x - #define B(x) A(A(A(A(x)))) - int arr[] = {B(0)}; - ``` +Modifiers written in the source render (`virtual … = 0`, `override`, +`final`), but an overriding method that omits the redundant `virtual` +keyword gives no sign of its virtuality — the card lacks the +`virtual void draw() override` form the issue asks for. -
+```cpp +struct Base { + virtual void draw() = 0; +}; -- [ ] Virtual modifiers — `virtual` / `override` / `final` show on method hover _(partial)_ ([clangd#2474](https://github.com/clangd/clangd/issues/2474)) +struct Circle : Base { + void draw() override; +}; - Modifiers written in the source render (`virtual … = 0`, `override`, - `final`), but an overriding method that omits the redundant `virtual` - keyword gives no sign of its virtuality — the card lacks the - `virtual void draw() override` form the issue asks for. +struct Dot final : Circle { + void draw() final; +}; +``` -
- Example +### Anonymous namespace scope - ```cpp - struct Base { - virtual void draw() = 0; - }; +`(anonymous namespace)` shows in the scope display - struct Circle : Base { - void draw() override; - }; +The cards render, but the anonymous segment is dropped from the +scope display: a top-level anonymous member shows no scope line at +all, and `outer::(anonymous)` shows just `outer`. - struct Dot final : Circle { - void draw() final; - }; - ``` +```cpp +namespace { +int hidden = 1; +} -
+namespace outer { +namespace { +int nested = 2; +} +} -- [ ] Anonymous namespace scope — `(anonymous namespace)` shows in the scope display _(partial)_ ([clangd#436](https://github.com/clangd/clangd/issues/436)) - - The cards render, but the anonymous segment is dropped from the - scope display: a top-level anonymous member shows no scope line at - all, and `outer::(anonymous)` shows just `outer`. - -
- Example - - ```cpp - namespace { - int hidden = 1; - } - - namespace outer { - namespace { - int nested = 2; - } - } - - int sum = hidden + outer::nested; - ``` - -
+int sum = hidden + outer::nested; +``` ## Type Information - - -- [x] Variable types — pointers, references, arrays - - A variable's card pretty-prints its declared type, spelling the pointer, - reference and array declarators the way they read in source. - -
- Example - - ```cpp - namespace variable_type { + - int target; +| Capability | Status | Issues | +| ------------------------ | ----------- | ----------------------------------------------------------- | +| Variable types | Supported | | +| Type aliases | Supported | | +| Function signatures | Supported | | +| Template parameters | Supported | | +| `auto` deduction | Supported | | +| `decltype` deduction | Supported | | +| CTAD | Partial | [clangd#435](https://github.com/clangd/clangd/issues/435) | +| Instantiation arguments | Partial | [clangd#230](https://github.com/clangd/clangd/issues/230) | +| Lambda `auto` parameters | Unsupported | [clangd#493](https://github.com/clangd/clangd/issues/493) | +| Sugared `auto` | Supported | | +| Type formatting | Unsupported | [clangd#2156](https://github.com/clangd/clangd/issues/2156) | +| Anonymous struct typedef | Supported | [clangd#2219](https://github.com/clangd/clangd/issues/2219) | +| Concept constraints | Partial | | - int *ptr = ⌖ +### Variable types - int &ref = target; +pointers, references, arrays - int numbers[4]{}; +A variable's card pretty-prints its declared type, spelling the pointer, +reference and array declarators the way they read in source. - } - ``` +```cpp +namespace variable_type { -
+int target; -- [x] Type aliases — the desugared `aka` form +int *ptr = ⌖ - A sugared type shows its underlying type as `Alias (aka int)`. The - `show_aka` option turns the `aka` suffix off. +int &ref = target; -
- Example +int numbers[4]{}; - ```cpp - namespace aka_desugar { +} +``` - using Handle = int; - using Alias = Handle; +### Type aliases - Handle direct = 0; +The desugared `aka` form - Alias chained = 0; +A sugared type shows its underlying type as `Alias (aka int)`. The +`show_aka` option turns the `aka` suffix off. - } - ``` +```cpp +namespace aka_desugar { -
+using Handle = int; +using Alias = Handle; -- [x] Function signatures — return type, parameter names, defaults +Handle direct = 0; - A function's card lists its return type, each parameter with its name, - and any default argument. +Alias chained = 0; -
- Example +} +``` - ```cpp - namespace function_signature { +### Function signatures - int add(int lhs, int rhs); +Return type, parameter names, defaults - void configure(int width, bool visible = true); +A function's card lists its return type, each parameter with its name, +and any default argument. - } - ``` +```cpp +namespace function_signature { -
+int add(int lhs, int rhs); -- [x] Template parameters — type, template-template, non-type +void configure(int width, bool visible = true); - Each template parameter kind reports its form: a type parameter, a - template-template parameter, and a non-type parameter with its default. +} +``` -
- Example +### Template parameters - ```cpp - // Template type parameter. - namespace type_param { - template void foo(); - } +type, template-template, non-type - // Template template parameter. - namespace template_template_param { - template class T> void foo(); - } +Each template parameter kind reports its form: a type parameter, a +template-template parameter, and a non-type parameter with its default. - // Non-type template parameter. - namespace non_type_param { - template void foo(); - } - ``` +```cpp +// Template type parameter. +namespace type_param { +template void foo(); +} -
+// Template template parameter. +namespace template_template_param { +template class T> void foo(); +} -- [x] `auto` deduction — the type the placeholder resolves to +// Non-type template parameter. +namespace non_type_param { +template void foo(); +} +``` - Hovering an `auto` placeholder shows the type substituted for it — - builtins, pointers, lambdas, template instantiations, and the - `/* not deduced */` marker inside an uninstantiated template. +### `auto` deduction -
- Example +The type the placeholder resolves to - ```cpp - namespace auto_deduction { +Hovering an `auto` placeholder shows the type substituted for it — +builtins, pointers, lambdas, template instantiations, and the +`/* not deduced */` marker inside an uninstantiated template. - struct Bar {}; - struct Pair { int first; int second; }; - template struct Box {}; +```cpp +namespace auto_deduction { - void locals() { - int n = 0; - auto a = 1; - const auto b = 1; - auto& c = n; - auto* d = &n; - auto e = &n; - auto f = []{}; - auto g = Box(); - auto [x, y] = Pair{}; - } +struct Bar {}; +struct Pair { int first; int second; }; +template struct Box {}; - auto with_trailing() -> int { return 0; } +void locals() { + int n = 0; + auto a = 1; + const auto b = 1; + auto& c = n; + auto* d = &n; + auto e = &n; + auto f = []{}; + auto g = Box(); + auto [x, y] = Pair{}; +} - auto deduced_return() { return Bar(); } +auto with_trailing() -> int { return 0; } - template void undeduced() { - auto u = T(); - } +auto deduced_return() { return Bar(); } - } - ``` +template void undeduced() { + auto u = T(); +} -
+} +``` -- [x] `decltype` deduction — value, reference and dependent forms +### `decltype` deduction - Hovering a `decltype` or `decltype(auto)` placeholder shows the resolved - type, including the reference the parenthesized-expression rule adds. +value, reference and dependent forms -
- Example +Hovering a `decltype` or `decltype(auto)` placeholder shows the resolved +type, including the reference the parenthesized-expression rule adds. - ```cpp - namespace decltype_deduction { +```cpp +namespace decltype_deduction { - int base = 0; +int base = 0; - void locals() { - int n = 0; - const int cn = 0; - int& r = n; - decltype(auto) a = 1; - decltype(auto) b = cn; - decltype(auto) c = r; - decltype(n) d = n; - decltype((n)) e = n; - decltype(static_cast(n)) f = static_cast(n); - } +void locals() { + int n = 0; + const int cn = 0; + int& r = n; + decltype(auto) a = 1; + decltype(auto) b = cn; + decltype(auto) c = r; + decltype(n) d = n; + decltype((n)) e = n; + decltype(static_cast(n)) f = static_cast(n); +} - decltype(base) mirror = base; +decltype(base) mirror = base; - template decltype(auto) undeduced() { return T(); } +template decltype(auto) undeduced() { return T(); } - template struct Dependent { - using kind = decltype(T::member); - }; +template struct Dependent { + using kind = decltype(T::member); +}; - } - ``` +} +``` -
+### CTAD -- [ ] CTAD — deduced template arguments of a class placeholder _(partial)_ ([clangd#435](https://github.com/clangd/clangd/issues/435)) +Deduced template arguments of a class placeholder - With class template argument deduction the variable's card shows the - deduced `Box`, but hovering the class-name spelling still reports - the primary template without its arguments. +With class template argument deduction the variable's card shows the +deduced `Box`, but hovering the class-name spelling still reports +the primary template without its arguments. -
- Example +```cpp +namespace ctad_arguments { - ```cpp - namespace ctad_arguments { +template struct Box { + Box(T); +}; - template struct Box { - Box(T); - }; +Box picked(42); - Box picked(42); +} +``` - } - ``` +### Instantiation arguments -
+Template parameters bound at a use site -- [ ] Instantiation arguments — template parameters bound at a use site _(partial)_ ([clangd#230](https://github.com/clangd/clangd/issues/230)) +A use of a template shows the substituted types (`Wrapper`, +`identity`, `int x`), but not an explicit `T = int` mapping of each +parameter to the argument it was bound to. - A use of a template shows the substituted types (`Wrapper`, - `identity`, `int x`), but not an explicit `T = int` mapping of each - parameter to the argument it was bound to. +```cpp +namespace instantiation_args { -
- Example +template struct Wrapper { + T value; +}; - ```cpp - namespace instantiation_args { +template T identity(T x) { + return x; +} - template struct Wrapper { - T value; - }; +void demo() { + Wrapper holder; + int r = identity(42); +} - template T identity(T x) { - return x; - } +} +``` - void demo() { - Wrapper holder; - int r = identity(42); - } +### Lambda `auto` parameters - } - ``` +Deduced parameter type -
+Hovering the `auto` parameter of a generic lambda yields no card; the +deduced parameter type is not shown. -- [ ] Lambda `auto` parameters — deduced parameter type ([clangd#493](https://github.com/clangd/clangd/issues/493)) +```cpp +namespace lambda_auto_params { - Hovering the `auto` parameter of a generic lambda yields no card; the - deduced parameter type is not shown. +auto printer = [](auto value) { return value; }; -
- Example +} +``` - ```cpp - namespace lambda_auto_params { +### Sugared `auto` - auto printer = [](auto value) { return value; }; +Alias sugar preserved through deduction - } - ``` +clangd tracks lost alias sugar through `auto` as clangd#709; clice +already keeps the alias spelling and appends its desugared form, so +`auto` deduced from an aliased return type reads as `Outer // aka: int`. -
+```cpp +namespace sugared_auto { -- [x] Sugared `auto` — alias sugar preserved through deduction +using Inner = int; +using Outer = Inner; - clangd tracks lost alias sugar through `auto` as clangd#709; clice - already keeps the alias spelling and appends its desugared form, so - `auto` deduced from an aliased return type reads as `Outer // aka: int`. +Outer make(); -
- Example +void demo() { + auto value = make(); +} - ```cpp - namespace sugared_auto { +} +``` - using Inner = int; - using Outer = Inner; +### Type formatting - Outer make(); +clang-format applied to rendered types - void demo() { - auto value = make(); - } +Long or nested types are printed by the compiler's default type printer; +they are not re-wrapped or aligned through clang-format. - } - ``` +```cpp +namespace clang_format_types { -
+template +struct Tuple {}; -- [ ] Type formatting — clang-format applied to rendered types ([clangd#2156](https://github.com/clangd/clangd/issues/2156)) +Tuple wide; - Long or nested types are printed by the compiler's default type printer; - they are not re-wrapped or aligned through clang-format. +} +``` -
- Example +### Anonymous struct typedef - ```cpp - namespace clang_format_types { +The classic C `typedef struct {…} Name` - template - struct Tuple {}; +Compiled as C11: clangd renders a misleading `struct Point` for the +alias of an anonymous struct; clice names the struct after its typedef, +so both the alias and a variable of it report a clean `Point` card. - Tuple wide; +```cpp +/// A 2-D point. +typedef struct { + int x, y; +} Point; - } - ``` +Point origin = {.y = 2, .x = 1}; +``` -
+### Concept constraints -- [x] Anonymous struct typedef — the classic C `typedef struct {…} Name` ([clangd#2219](https://github.com/clangd/clangd/issues/2219)) +The constraint behind a parameter or `auto` placeholder - Compiled as C11: clangd renders a misleading `struct Point` for the - alias of an anonymous struct; clice names the struct after its typedef, - so both the alias and a variable of it report a clean `Point` card. +The constrained-parameter and concept-reference cards carry the +constraint, but hovering the placeholder of a constrained `Addable auto` +variable shows only the deduced type — the constraint is dropped. -
- Example +```cpp +namespace concept_constraints { - ```cpp - /// A 2-D point. - typedef struct { - int x, y; - } Point; +template +concept Addable = requires(T a) { a + a; }; - Point origin = {.y = 2, .x = 1}; - ``` +template +void sum(U a, U b); -
+auto flag = Addable; -- [ ] Concept constraints — the constraint behind a parameter or `auto` placeholder _(partial)_ +Addable auto total = 1; - The constrained-parameter and concept-reference cards carry the - constraint, but hovering the placeholder of a constrained `Addable auto` - variable shows only the deduced type — the constraint is dropped. - -
- Example - - ```cpp - namespace concept_constraints { - - template - concept Addable = requires(T a) { a + a; }; - - template - void sum(U a, U b); - - auto flag = Addable; - - Addable auto total = 1; - - } - ``` - -
+} +``` ## Layout Information - - -- [x] Field layout — size, offset, alignment and padding show on field hover - - The corpus pins an x86-64 target, so the bit numbers are stable. + -
- Example +| Capability | Status | Issues | +| ----------------- | --------- | ----------------------------------------------------------- | +| Field layout | Supported | | +| Type-level layout | Partial | [clangd#1763](https://github.com/clangd/clangd/issues/1763) | +| Vtable offset | Partial | [clangd#1771](https://github.com/clangd/clangd/issues/1771) | - ```cpp - struct Header { - char tag; - int length; - }; +### Field layout - struct Flags { - int ready : 1; - int end : 1; - }; - ``` +size, offset, alignment and padding show on field hover -
+The corpus pins an x86-64 target, so the bit numbers are stable. -- [ ] Type-level layout — hovering the type itself shows its size, alignment and padding _(partial)_ ([clangd#1763](https://github.com/clangd/clangd/issues/1763)) +```cpp +struct Header { + char tag; + int length; +}; - Size and alignment show on the type card today; the total padding - does not yet. +struct Flags { + int ready : 1; + int end : 1; +}; +``` -
- Example +### Type-level layout - ```cpp - namespace layout { +Hovering the type itself shows its size, alignment and padding - struct Widget { - int id; - double value; - }; +Size and alignment show on the type card today; the total padding +does not yet. - } - ``` +```cpp +namespace layout { -
+struct Widget { + int id; + double value; +}; -- [ ] Vtable offset — virtual methods show their table slot _(partial)_ ([clangd#1771](https://github.com/clangd/clangd/issues/1771)) +} +``` - The method card renders without any vtable fact today. +### Vtable offset -
- Example +Virtual methods show their table slot - ```cpp - struct Shape { - virtual void draw(); - virtual void move(); - }; - ``` +The method card renders without any vtable fact today. -
+```cpp +struct Shape { + virtual void draw(); + virtual void move(); +}; +``` ## Expression Context - + -- [x] Constant evaluation — constexpr, enumerators, sizeof +| Capability | Status | Issues | +| -------------------- | ----------- | ----------------------------------------------------------- | +| Constant evaluation | Supported | | +| Call arguments | Supported | | +| Pass semantics | Supported | | +| Implicit conversions | Supported | | +| String literals | Partial | [clangd#1016](https://github.com/clangd/clangd/issues/1016) | +| Numeric literals | Unsupported | [clangd#1669](https://github.com/clangd/clangd/issues/1669) | +| Record variables | Partial | [clangd#1622](https://github.com/clangd/clangd/issues/1622) | - When an initializer is a constant expression, the card evaluates it and - shows the resulting value. +### Constant evaluation -
- Example +constexpr, enumerators, sizeof - ```cpp - namespace constant_value { +When an initializer is a constant expression, the card evaluates it and +shows the resulting value. - constexpr int square(int n) { return n * n; } - int from_call = square(5); +```cpp +namespace constant_value { - int from_sizeof = sizeof(int); +constexpr int square(int n) { return n * n; } +int from_call = square(5); - enum Color { Red = -1, Green = 5 }; - Color picked = Green; +int from_sizeof = sizeof(int); - template struct Sum { static constexpr int value = A + B; }; - int from_member = Sum<3, 4>::value; +enum Color { Red = -1, Green = 5 }; +Color picked = Green; - } - ``` +template struct Sum { static constexpr int value = A + B; }; +int from_member = Sum<3, 4>::value; -
+} +``` -- [x] Call arguments — which parameter each argument binds to +### Call arguments - Hovering an argument at a call site shows the parameter it is passed to, - naming the parameter it binds. +Which parameter each argument binds to -
- Example +Hovering an argument at a call site shows the parameter it is passed to, +naming the parameter it binds. - ```cpp - namespace callee_arguments { +```cpp +namespace callee_arguments { - void configure(int width, int& out, int flags = 0); +void configure(int width, int& out, int flags = 0); - void demo() { - int w = 1024; - int result = 0; - configure(w, result, 3); - } +void demo() { + int w = 1024; + int result = 0; + configure(w, result, 3); +} - } - ``` +} +``` -
+### Pass semantics -- [x] Pass semantics — by value, by reference, by const reference +By value, by reference, by const reference - The argument card states how the value reaches the callee: copied by - value, or bound to a mutable or const reference parameter. +The argument card states how the value reaches the callee: copied by +value, or bound to a mutable or const reference parameter. -
- Example +```cpp +namespace pass_semantics { - ```cpp - namespace pass_semantics { +void by_value(int x); +void by_ref(int& x); +void by_const_ref(const int& x); - void by_value(int x); - void by_ref(int& x); - void by_const_ref(const int& x); +void demo() { + int n = 0; + by_value(n); + by_ref(n); + by_const_ref(n); +} - void demo() { - int n = 0; - by_value(n); - by_ref(n); - by_const_ref(n); - } +} +``` - } - ``` +### Implicit conversions -
+Argument converted to the parameter type -- [x] Implicit conversions — argument converted to the parameter type +When an argument reaches a parameter through an implicit conversion, the +card notes the target type, for both built-in and user-defined +conversions. - When an argument reaches a parameter through an implicit conversion, the - card notes the target type, for both built-in and user-defined - conversions. +```cpp +namespace implicit_conversion { -
- Example +struct Wrapper { + Wrapper(int value); +}; - ```cpp - namespace implicit_conversion { +void take_float(float x); +void take_wrapper(Wrapper w); - struct Wrapper { - Wrapper(int value); - }; +void demo() { + int n = 0; + take_float(n); + take_wrapper(n); +} - void take_float(float x); - void take_wrapper(Wrapper w); +} +``` - void demo() { - int n = 0; - take_float(n); - take_wrapper(n); - } +### String literals - } - ``` +The length reported on hover -
+A string-literal card reports the array type and its size in bytes +(`const char[6]`, `Size: 6 bytes` — the length plus the null +terminator), not an explicit character count. -- [ ] String literals — the length reported on hover _(partial)_ ([clangd#1016](https://github.com/clangd/clangd/issues/1016)) +```cpp +namespace string_length { - A string-literal card reports the array type and its size in bytes - (`const char[6]`, `Size: 6 bytes` — the length plus the null - terminator), not an explicit character count. +const char *greeting = "hello"; -
- Example +} +``` - ```cpp - namespace string_length { +### Numeric literals - const char *greeting = "hello"; +Type and value of an integer or float literal - } - ``` +Hovering a numeric literal yields no card, unlike character and string +literals, whose type and value are shown. -
+```cpp +namespace numeric_literal_type { -- [ ] Numeric literals — type and value of an integer or float literal ([clangd#1669](https://github.com/clangd/clangd/issues/1669)) +auto count = 42; +auto ratio = 3.14; - Hovering a numeric literal yields no card, unlike character and string - literals, whose type and value are shown. +} +``` -
- Example +### Record variables - ```cpp - namespace numeric_literal_type { +Enclosing constant value leaks in - auto count = 42; - auto ratio = 3.14; +Hovering a record-typed argument of a constant-evaluable call currently +reports that call's value (`Value = 7`) on the variable — a value that +is not the record's own. - } - ``` +```cpp +namespace record_value_misleading { -
+struct Tag {}; -- [ ] Record variables — enclosing constant value leaks in _(partial)_ ([clangd#1622](https://github.com/clangd/clangd/issues/1622)) +constexpr int rank(Tag) { + return 7; +} - Hovering a record-typed argument of a constant-evaluable call currently - reports that call's value (`Value = 7`) on the variable — a value that - is not the record's own. +void demo() { + Tag t; + int r = rank(t); +} -
- Example - - ```cpp - namespace record_value_misleading { - - struct Tag {}; - - constexpr int rank(Tag) { - return 7; - } - - void demo() { - Tag t; - int r = rank(t); - } - - } - ``` - -
+} +``` ## Documentation - - -- [x] Doxygen `///` comments — extracted from the declaration and rendered on hover - - Applies to plain functions, primary templates and their specializations; - a reference resolves to the most specialized declaration's comment. - -
- Example - - ```cpp - namespace docs { - /// Adds two integers. - int add(int a, int b); - - /// A box holding a value. - template struct Box {}; - - /// A box of pointers. - template struct Box {}; - - void use() { - Box b; - Box p; - } - } - ``` - -
- -- [x] Synthesized accessor docs — trivial getters/setters get a generated one-line description - - A trivial getter or setter with no comment of its own gets a synthesized - "Trivial accessor/setter for `field`." line in its hover card. - -
- Example - - ```cpp - namespace accessors { - struct Widget { - int width; - int getWidth() { return width; } - void setWidth(int w) { width = w; } - }; - } - ``` - -
+ -- [ ] `@copydoc` tags — copy another symbol's documentation onto this one _(partial)_ ([clangd#1320](https://github.com/clangd/clangd/issues/1320)) +| Capability | Status | Issues | +| ---------------------------------- | ----------- | ----------------------------------------------------------- | +| Doxygen `///` comments | Supported | | +| Synthesized accessor docs | Supported | | +| `@copydoc` tags | Partial | [clangd#1320](https://github.com/clangd/clangd/issues/1320) | +| Inherited override docs | Partial | [clangd#2504](https://github.com/clangd/clangd/issues/2504) | +| Overload doc sharing | Partial | [clangd#2506](https://github.com/clangd/clangd/issues/2506) | +| Inherited constructor docs | Unsupported | [clangd#1936](https://github.com/clangd/clangd/issues/1936) | +| Banner comments | Partial | [clangd#974](https://github.com/clangd/clangd/issues/974) | +| Declaration vs definition comments | Supported | | +| Whitespace and newlines | Partial | [clangd#2057](https://github.com/clangd/clangd/issues/2057) | +| Comment indentation | Partial | [clangd#1040](https://github.com/clangd/clangd/issues/1040) | +| Template keyword from a macro | Partial | [clangd#1226](https://github.com/clangd/clangd/issues/1226) | +| Comment suppression option | Unsupported | [clangd#2148](https://github.com/clangd/clangd/issues/2148) | - A `@copydoc target` tag should copy `target`'s documentation into this - symbol's hover card. clice does not resolve the tag yet — the card shows - the literal `@copydoc base_func()` text. +### Doxygen `///` comments + +Extracted from the declaration and rendered on hover + +Applies to plain functions, primary templates and their specializations; +a reference resolves to the most specialized declaration's comment. + +```cpp +namespace docs { +/// Adds two integers. +int add(int a, int b); + +/// A box holding a value. +template struct Box {}; + +/// A box of pointers. +template struct Box {}; + +void use() { + Box b; + Box p; +} +} +``` + +### Synthesized accessor docs + +Trivial getters/setters get a generated one-line description + +A trivial getter or setter with no comment of its own gets a synthesized +"Trivial accessor/setter for `field`." line in its hover card. + +```cpp +namespace accessors { +struct Widget { + int width; + int getWidth() { return width; } + void setWidth(int w) { width = w; } +}; +} +``` + +### `@copydoc` tags + +Copy another symbol's documentation onto this one + +A `@copydoc target` tag should copy `target`'s documentation into this +symbol's hover card. clice does not resolve the tag yet — the card shows +the literal `@copydoc base_func()` text. + +```cpp +namespace copydoc { +/// Detailed documentation. +void base_func(); -
- Example +/// @copydoc base_func() +void wrapper(); +} +``` - ```cpp - namespace copydoc { - /// Detailed documentation. - void base_func(); +### Inherited override docs + +An override with no comment shows the base method's documentation + +Hovering an overriding method that carries no comment of its own should +surface the documentation from the method it overrides. clice does not +inherit it yet — the override's card carries no description. + +```cpp +namespace inherit_docs { +struct Base { + /// Renders the widget. + virtual void draw(); +}; +struct Circle : Base { + void draw() override; +}; +} +``` + +### Overload doc sharing + +A later overload with no comment reuses the first overload's documentation + +Consecutive overloads often document only the first; a later undocumented +overload should reuse that shared description. clice does not share it +yet — the later overload's card carries no description. + +```cpp +namespace overloads { +/// Opens a file. +void open(const char* path); +void open(const char* path, int flags); +} +``` - /// @copydoc base_func() - void wrapper(); - } - ``` +### Inherited constructor docs -
+`using Base::Base;` surfaces the base constructor's documentation -- [ ] Inherited override docs — an override with no comment shows the base method's documentation _(partial)_ ([clangd#2504](https://github.com/clangd/clangd/issues/2504)) +A constructor pulled in with `using Base::Base;` should carry the base +constructor's documentation on hover. There is no hover surface for it: +the name in the using-declaration resolves to the class, not the +inherited constructor. - Hovering an overriding method that carries no comment of its own should - surface the documentation from the method it overrides. clice does not - inherit it yet — the override's card carries no description. +```cpp +namespace inherited_ctor { +struct Base { + /// Constructs from a value. + Base(int value); +}; +struct Derived : Base { + using Base::Base; +}; +} +``` -
- Example +### Banner comments - ```cpp - namespace inherit_docs { - struct Base { - /// Renders the widget. - virtual void draw(); - }; - struct Circle : Base { - void draw() override; - }; - } - ``` +A section banner separated by a blank line must not attach to the next declaration -
+A `// ==== Section ====` banner followed by a blank line should not be +misattributed as documentation for the declaration below it. clice +currently attaches it anyway — the banner text appears in the card. -- [ ] Overload doc sharing — a later overload with no comment reuses the first overload's documentation _(partial)_ ([clangd#2506](https://github.com/clangd/clangd/issues/2506)) +```cpp +namespace banners { +// ==== Section Banner ==== - Consecutive overloads often document only the first; a later undocumented - overload should reuse that shared description. clice does not share it - yet — the later overload's card carries no description. +void foo(); +} +``` -
- Example +### Declaration vs definition comments - ```cpp - namespace overloads { - /// Opens a file. - void open(const char* path); - void open(const char* path, int flags); - } - ``` +The declaration's doc wins over a definition-site comment -
+clangd tracks this as clangd#829; clice already prefers the +declaration's `///` documentation over the definition's plain `//` note, +showing it at both the declaration and the definition site. -- [ ] Inherited constructor docs — `using Base::Base;` surfaces the base constructor's documentation ([clangd#1936](https://github.com/clangd/clangd/issues/1936)) +```cpp +namespace decldef { +/// Public API documentation. +void process(int x); - A constructor pulled in with `using Base::Base;` should carry the base - constructor's documentation on hover. There is no hover surface for it: - the name in the using-declaration resolves to the class, not the - inherited constructor. +// Internal implementation note. +void process(int x) { (void)x; } +} +``` -
- Example +### Whitespace and newlines - ```cpp - namespace inherited_ctor { - struct Base { - /// Constructs from a value. - Base(int value); - }; - struct Derived : Base { - using Base::Base; - }; - } - ``` +A markdown table in a comment keeps its line breaks -
+A markdown table written across several `///` lines should render as a +table with its line breaks preserved. clice currently flattens the lines +onto one line, so the table does not render. -- [ ] Banner comments — a section banner separated by a blank line must not attach to the next declaration _(partial)_ ([clangd#974](https://github.com/clangd/clangd/issues/974)) +```cpp +namespace tables { +/// | Column A | Column B | +/// |----------|----------| +/// | 1 | 2 | +void table_fn(); +} +``` - A `// ==== Section ====` banner followed by a blank line should not be - misattributed as documentation for the declaration below it. clice - currently attaches it anyway — the banner text appears in the card. +### Comment indentation -
- Example +Indented lines in a comment render without spurious extra indentation - ```cpp - namespace banners { - // ==== Section Banner ==== +A doc comment whose body contains an indented block should render with +correct indentation. clice currently strips the leading indentation, so +an indented code block loses its offset and the blank line collapses. - void foo(); - } - ``` +```cpp +namespace indented { +/// Summary line. +/// +/// step_one(); +/// step_two(); +void run(); +} +``` -
+### Template keyword from a macro -- [x] Declaration vs definition comments — the declaration's doc wins over a definition-site comment +The docstring should survive the expansion - clangd tracks this as clangd#829; clice already prefers the - declaration's `///` documentation over the definition's plain `//` note, - showing it at both the declaration and the definition site. +When the `template` keyword is produced by a macro expansion, the +declaration's doc comment should still appear on hover. clice currently +drops it — the card carries no description. -
- Example +```cpp +int anchor = 0; - ```cpp - namespace decldef { - /// Public API documentation. - void process(int x); +#define TEMPLATE template - // Internal implementation note. - void process(int x) { (void)x; } - } - ``` +/// A documented template function. +TEMPLATE void run(T value); +``` -
+### Comment suppression option -- [ ] Whitespace and newlines — a markdown table in a comment keeps its line breaks _(partial)_ ([clangd#2057](https://github.com/clangd/clangd/issues/2057)) +A config switch to hide misattributed doc comments - A markdown table written across several `///` lines should render as a - table with its line breaks preserved. clice currently flattens the lines - onto one line, so the table does not render. +A stray comment picked up by the association heuristic — a section +banner separated from the code by a blank line, for example — always +reaches the hover card: clice has no config option to suppress doc +comments whose attachment is a guess. -
- Example +```cpp +namespace suppression { +// TODO: tidy this file up. - ```cpp - namespace tables { - /// | Column A | Column B | - /// |----------|----------| - /// | 1 | 2 | - void table_fn(); - } - ``` - -
- -- [ ] Comment indentation — indented lines in a comment render without spurious extra indentation _(partial)_ ([clangd#1040](https://github.com/clangd/clangd/issues/1040)) - - A doc comment whose body contains an indented block should render with - correct indentation. clice currently strips the leading indentation, so - an indented code block loses its offset and the blank line collapses. - -
- Example - - ```cpp - namespace indented { - /// Summary line. - /// - /// step_one(); - /// step_two(); - void run(); - } - ``` - -
- -- [ ] Template keyword from a macro — the docstring should survive the expansion _(partial)_ ([clangd#1226](https://github.com/clangd/clangd/issues/1226)) - - When the `template` keyword is produced by a macro expansion, the - declaration's doc comment should still appear on hover. clice currently - drops it — the card carries no description. - -
- Example - - ```cpp - int anchor = 0; - - #define TEMPLATE template - - /// A documented template function. - TEMPLATE void run(T value); - ``` - -
- -- [ ] Comment suppression option — a config switch to hide misattributed doc comments ([clangd#2148](https://github.com/clangd/clangd/issues/2148)) - - A stray comment picked up by the association heuristic — a section - banner separated from the code by a blank line, for example — always - reaches the hover card: clice has no config option to suppress doc - comments whose attachment is a guess. - -
- Example - - ```cpp - namespace suppression { - // TODO: tidy this file up. - - int counter; - } - ``` - -
+int counter; +} +``` ## Macro Hover - + -- [x] Definition text at every site — `#define`, use, `#ifdef` and `#undef` all show the macro's definition +| Capability | Status | Issues | +| ----------------------------- | ----------- | ----------------------------------------------------------- | +| Definition text at every site | Supported | | +| Fully-expanded preview | Supported | | +| Command-line macros | Supported | | +| Nested macro in arguments | Partial | | +| Use before definition | Partial | [clangd#2642](https://github.com/clangd/clangd/issues/2642) | +| `#define` inside the preamble | Unsupported | | - A macro's hover card carries its `#define` text wherever the name - appears: the definition itself, a use, an `#ifdef` guard and an `#undef`. +### Definition text at every site -
- Example +`#define`, use, `#ifdef` and `#undef` all show the macro's definition - ```cpp - int anchor = 0; +A macro's hover card carries its `#define` text wherever the name +appears: the definition itself, a use, an `#ifdef` guard and an `#undef`. - #define LIMIT 64 +```cpp +int anchor = 0; - int use = LIMIT; +#define LIMIT 64 - #ifdef LIMIT - int guarded = 1; - #endif +int use = LIMIT; - #undef LIMIT - ``` +#ifdef LIMIT +int guarded = 1; +#endif -
+#undef LIMIT +``` -- [x] Fully-expanded preview — a function-like macro use shows its arguments substituted through the body +### Fully-expanded preview - Hovering a function-like macro invocation shows the `#define` text and a - preview of the fully-expanded result with the call's arguments spliced in. +A function-like macro use shows its arguments substituted through the body -
- Example +Hovering a function-like macro invocation shows the `#define` text and a +preview of the fully-expanded result with the call's arguments spliced in. - ```cpp - int x = 1, y = 2; +```cpp +int x = 1, y = 2; - #define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MAX(a, b) ((a) > (b) ? (a) : (b)) - int z = MAX(x, y); - ``` +int z = MAX(x, y); +``` -
+### Command-line macros -- [x] Command-line macros — `-D` definitions hover with a synthesized `#define` +`-D` definitions hover with a synthesized `#define` - A macro defined on the command line (`-DFROM_CLI=7`) shows a synthesized - `#define FROM_CLI 7` in its hover card, then its expansion. +A macro defined on the command line (`-DFROM_CLI=7`) shows a synthesized +`#define FROM_CLI 7` in its hover card, then its expansion. -
- Example +```cpp +int cli = FROM_CLI; +``` - ```cpp - int cli = FROM_CLI; - ``` +### Nested macro in arguments -
+A macro named inside another invocation's arguments -- [ ] Nested macro in arguments — a macro named inside another invocation's arguments _(partial)_ +The recorded expansion starts at the outer invocation, so hovering an +inner macro named inside the arguments shows only its definition, not an +expansion preview. - The recorded expansion starts at the outer invocation, so hovering an - inner macro named inside the arguments shows only its definition, not an - expansion preview. +```cpp +int anchor = 0; -
- Example +#define ECHO(x) x +#define INNER_VAL 99 - ```cpp - int anchor = 0; +int nested = ECHO(INNER_VAL); +``` - #define ECHO(x) x - #define INNER_VAL 99 +### Use before definition - int nested = ECHO(INNER_VAL); - ``` +Hovering a macro name that appears before its `#define` -
+A macro name used in an `#if` above its own `#define` should still hover +with the macro's definition. clice currently returns no hover at the +pre-definition use; a use after the `#define` works normally. -- [ ] Use before definition — hovering a macro name that appears before its `#define` _(partial)_ ([clangd#2642](https://github.com/clangd/clangd/issues/2642)) +```cpp +int anchor = 0; - A macro name used in an `#if` above its own `#define` should still hover - with the macro's definition. clice currently returns no hover at the - pre-definition use; a use after the `#define` works normally. +#if COUNT > 0 +int positive = 1; +#endif -
- Example +#define COUNT 3 - ```cpp - int anchor = 0; +int use = COUNT; +``` - #if COUNT > 0 - int positive = 1; - #endif +### `#define` inside the preamble - #define COUNT 3 +Hover on a leading directive - int use = COUNT; - ``` +A `#define` in the file's preamble region (the leading run of directives +before the first declaration) is not part of the live parse's +preprocessor record, so hovering its name yields nothing. Every other +macro fixture opens with a declaration precisely to push its directives +past the preamble boundary. -
+```cpp +#define EARLY 1 -- [ ] `#define` inside the preamble — hover on a leading directive - - A `#define` in the file's preamble region (the leading run of directives - before the first declaration) is not part of the live parse's - preprocessor record, so hovering its name yields nothing. Every other - macro fixture opens with a declaration precisely to push its directives - past the preamble boundary. - -
- Example - - ```cpp - #define EARLY 1 - - int use = EARLY; - ``` - -
+int use = EARLY; +``` ## Special Hover Targets - - -- [ ] Members on type hover — hovering an enum or struct type lists its members _(partial)_ ([clangd#959](https://github.com/clangd/clangd/issues/959)) - - The card names the type (and a struct's layout), but the member list is - not expanded — the body renders as `{}`. - -
- Example - - ```cpp - namespace members { - - enum Color { - Red, - Green, - Blue, - }; + - struct Point { - int x; - int y; - }; +| Capability | Status | Issues | +| ------------------------------ | ----------- | ----------------------------------------------------------- | +| Members on type hover | Partial | [clangd#959](https://github.com/clangd/clangd/issues/959) | +| Typedef underlying struct | Partial | [clangd#2020](https://github.com/clangd/clangd/issues/2020) | +| Keyword documentation | Unsupported | [clangd#1862](https://github.com/clangd/clangd/issues/1862) | +| Attribute documentation | Supported | [clangd#1862](https://github.com/clangd/clangd/issues/1862) | +| Include directive hover | Supported | | +| `this` expression | Supported | | +| Predefined identifiers | Supported | | +| No hover on meaningless tokens | Supported | | +| GTK-Doc and kernel-doc | Unsupported | [clangd#2662](https://github.com/clangd/clangd/issues/2662) | +| LaTeX math in Doxygen | Unsupported | [clangd#2669](https://github.com/clangd/clangd/issues/2669) | - } - ``` +### Members on type hover -
+Hovering an enum or struct type lists its members -- [ ] Typedef underlying struct — hovering an alias expands the aliased definition _(partial)_ ([clangd#2020](https://github.com/clangd/clangd/issues/2020)) +The card names the type (and a struct's layout), but the member list is +not expanded — the body renders as `{}`. - The card resolves the alias to its underlying type name, but does not - expand that struct's definition or member list. +```cpp +namespace members { -
- Example +enum Color { + Red, + Green, + Blue, +}; - ```cpp - namespace aliases { +struct Point { + int x; + int y; +}; - struct Widget { - int id; - double value; - }; +} +``` - using Handle = Widget; +### Typedef underlying struct - typedef Widget Widget_t; +Hovering an alias expands the aliased definition - } - ``` +The card resolves the alias to its underlying type name, but does not +expand that struct's definition or member list. -
+```cpp +namespace aliases { -- [ ] Keyword documentation — hovering a language keyword shows its description ([clangd#1862](https://github.com/clangd/clangd/issues/1862)) +struct Widget { + int id; + double value; +}; - Hovering a keyword such as `const` or `virtual` produces no card. +using Handle = Widget; -
- Example +typedef Widget Widget_t; - ```cpp - namespace keywords { +} +``` - const int limit = 42; +### Keyword documentation - struct Widget { - virtual void draw(); - }; +Hovering a language keyword shows its description - } - ``` +Hovering a keyword such as `const` or `virtual` produces no card. -
+```cpp +namespace keywords { -- [x] Attribute documentation — hovering an attribute shows its description ([clangd#1862](https://github.com/clangd/clangd/issues/1862)) +const int limit = 42; - The attribute's own documentation renders in the card, for both GNU - `__attribute__` spellings and C++ `[[...]]` attributes. +struct Widget { + virtual void draw(); +}; -
- Example +} +``` - ```cpp - namespace attr_docs { - void foo(int * __attribute__((nonnull, noescape)) ); +### Attribute documentation - [[nodiscard]] int compute(); - } - ``` +Hovering an attribute shows its description -
+The attribute's own documentation renders in the card, for both GNU +`__attribute__` spellings and C++ `[[...]]` attributes. -- [x] Include directive hover — hovering an `#include` shows the resolved header path +```cpp +namespace attr_docs { +void foo(int * __attribute__((nonnull, noescape)) ); - The card resolves the quoted header to its file on disk. +[[nodiscard]] int compute(); +} +``` -
- Example +### Include directive hover - ```cpp - #include "own_header.h" +Hovering an `#include` shows the resolved header path - int use = own_header_value; - ``` +The card resolves the quoted header to its file on disk. -
+```cpp +#include "own_header.h" -- [x] `this` expression — hovering `this` shows the pointed-to class type +int use = own_header_value; +``` - Works in a plain class and inside a class template. +### `this` expression -
- Example +Hovering `this` shows the pointed-to class type - ```cpp - namespace this_hover { +Works in a plain class and inside a class template. - struct Widget { - Widget* self() { - return this; - } - }; +```cpp +namespace this_hover { - template - struct Box { - const Box* self() const { - return this; - } - }; +struct Widget { + Widget* self() { + return this; + } +}; - } - ``` +template +struct Box { + const Box* self() const { + return this; + } +}; -
+} +``` -- [x] Predefined identifiers — `__func__` hover shows the current function name +### Predefined identifiers - The value resolves in a concrete function; inside a template only the - approximate type is known. +`__func__` hover shows the current function name -
- Example +The value resolves in a concrete function; inside a template only the +approximate type is known. - ```cpp - namespace predefined { +```cpp +namespace predefined { - void current() { - const char* name = __func__; - } +void current() { + const char* name = __func__; +} - template - void generic() { - const char* name = __func__; - } +template +void generic() { + const char* name = __func__; +} - } - ``` +} +``` -
+### No hover on meaningless tokens -- [x] No hover on meaningless tokens — builtin keywords and empty bodies yield no card +Builtin keywords and empty bodies yield no card - Hovering a builtin type keyword or the inside of an empty body - produces no card at all, so editors show nothing rather than noise. - (Numeric and bool literals also have no card today, but that is a - tracked gap — see the numeric-literal item — not a promise.) +Hovering a builtin type keyword or the inside of an empty body +produces no card at all, so editors show nothing rather than noise. +(Numeric and bool literals also have no card today, but that is a +tracked gap — see the numeric-literal item — not a promise.) -
- Example +```cpp +namespace negatives { - ```cpp - namespace negatives { +int counter = 0; - int counter = 0; +void noop() {} - void noop() {} +} +``` - } - ``` +### GTK-Doc and kernel-doc -
+Recognize GObject Introspection annotations -- [ ] GTK-Doc and kernel-doc — recognize GObject Introspection annotations ([clangd#2662](https://github.com/clangd/clangd/issues/2662)) +GTK-Doc / kernel-doc comment syntax and GObject Introspection +annotations are not parsed into the hover card. - GTK-Doc / kernel-doc comment syntax and GObject Introspection - annotations are not parsed into the hover card. +```cpp +/** + * gtk_widget_show: + * @widget: (transfer none): a #GtkWidget + * + * Flags a widget to be displayed. + */ +void gtk_widget_show(GtkWidget *widget); +``` -
- Example +### LaTeX math in Doxygen - ```cpp - /** - * gtk_widget_show: - * @widget: (transfer none): a #GtkWidget - * - * Flags a widget to be displayed. - */ - void gtk_widget_show(GtkWidget *widget); - ``` +Render `@f$ ... @f$` formulas -
+Doxygen LaTeX math formulas are shown verbatim, not rendered as math. -- [ ] LaTeX math in Doxygen — render `@f$ ... @f$` formulas ([clangd#2669](https://github.com/clangd/clangd/issues/2669)) - - Doxygen LaTeX math formulas are shown verbatim, not rendered as math. - -
- Example - - ```cpp - /// The area of a circle is @f$ A = \pi r^2 @f$. - double circle_area(double r); - ``` - -
+```cpp +/// The area of a circle is @f$ A = \pi r^2 @f$. +double circle_area(double r); +``` ## Presentation - + -- [x] Markdown rendering — cards render as markdown, or plain text via `parse_comment_as_markdown = false` +| Capability | Status | Issues | +| ------------------ | --------- | ------ | +| Markdown rendering | Supported | | -
- Example +### Markdown rendering - ```cpp - /// Computes the answer. Tests primality of `p`. - constexpr int answer(int p) { - return p + 41; - } +Cards render as markdown, or plain text via `parse_comment_as_markdown = false` - int value = answer(1); +```cpp +/// Computes the answer. Tests primality of `p`. +constexpr int answer(int p) { + return p + 41; +} - struct Layout { - char first; - int second; - }; - ``` +int value = answer(1); -
+struct Layout { + char first; + int second; +}; +``` ## Module-Related - - -- [ ] Import statement hover — hovering `import` shows the module's info + - Hovering an `import` declaration does not yet describe the imported - module. +| Capability | Status | Issues | +| ---------------------- | ----------- | ------ | +| Import statement hover | Unsupported | | +| Module name hover | Unsupported | | -
- Example +### Import statement hover - ```cpp - export module app; +Hovering `import` shows the module's info - import utils; - ``` +Hovering an `import` declaration does not yet describe the imported +module. -
+```cpp +export module app; -- [ ] Module name hover — hovering a module name lists its owning files +import utils; +``` - Hovering a module name does not yet list the files or partitions that - declare it. +### Module name hover -
- Example +Hovering a module name lists its owning files - ```cpp - export module math; +Hovering a module name does not yet list the files or partitions that +declare it. - export module math:algebra; - ``` +```cpp +export module math; -
+export module math:algebra; +``` @@ -1437,122 +1342,115 @@ Rich information cards for the symbol under the cursor. Robustness on inputs that have broken other tooling. - - -- [x] MSVC inheritance model — `MSInheritanceAttr` does not corrupt record hover - - clangd tracks this as clangd#1643 and clangd#2212; under an MSVC target - the implicit inheritance attribute does not leak into the record or - method card. - -
- Example - - ```cpp - namespace ms { + - struct Widget { - int value; - void update(); - }; +| Capability | Status | Issues | +| ---------------------------- | --------- | ------ | +| MSVC inheritance model | Supported | | +| Most-vexing-parse | Supported | | +| Large unsigned enum constant | Supported | | +| Call with default arguments | Supported | | +| Macro-shadowed symbol | Supported | | - int Widget::* member = &Widget::value; +### MSVC inheritance model - } - ``` +`MSInheritanceAttr` does not corrupt record hover -
+clangd tracks this as clangd#1643 and clangd#2212; under an MSVC target +the implicit inheritance attribute does not leak into the record or +method card. -- [x] Most-vexing-parse — object init and function declaration hover distinctly +```cpp +namespace ms { - clangd tracks this as clangd#2225; clice reads the direct-init as a - variable and the vexing form as a function declaration. +struct Widget { + int value; + void update(); +}; -
- Example +int Widget::* member = &Widget::value; - ```cpp - namespace mvp { +} +``` - struct Timer { - Timer(); - Timer(int); - }; +### Most-vexing-parse - int seconds = 5; +Object init and function declaration hover distinctly - void demo() { - Timer active(seconds); - Timer empty(); - } +clangd tracks this as clangd#2225; clice reads the direct-init as a +variable and the vexing form as a function declaration. - } - ``` +```cpp +namespace mvp { -
+struct Timer { + Timer(); + Timer(int); +}; -- [x] Large unsigned enum constant — hovering a `0xFFFF...ULL` enumerator does not crash +int seconds = 5; - clangd crashes on this (clangd#2381); clice renders the full unsigned - value without overflow. +void demo() { + Timer active(seconds); + Timer empty(); +} -
- Example +} +``` - ```cpp - namespace big_enum { +### Large unsigned enum constant - enum class Flags : unsigned long long { - Max = 0xFFFFFFFFFFFFFFFFULL, - }; +Hovering a `0xFFFF...ULL` enumerator does not crash - } - ``` +clangd crashes on this (clangd#2381); clice renders the full unsigned +value without overflow. -
+```cpp +namespace big_enum { -- [x] Call with default arguments — hovering a call that omits defaults does not crash +enum class Flags : unsigned long long { + Max = 0xFFFFFFFFFFFFFFFFULL, +}; - clangd crashes on this (clangd#551); clice renders the callee signature - with its default arguments. +} +``` -
- Example +### Call with default arguments - ```cpp - namespace defaults { +Hovering a call that omits defaults does not crash - int compute(int a, int b = 10, int c = 20); +clangd crashes on this (clangd#551); clice renders the callee signature +with its default arguments. - int result = compute(1); +```cpp +namespace defaults { - } - ``` +int compute(int a, int b = 10, int c = 20); -
+int result = compute(1); -- [x] Macro-shadowed symbol — a function-like macro over a same-named function +} +``` - clangd tracks this as clangd#2490; at the call site the function-like - macro is active, and clice's card shows that macro and its expansion. +### Macro-shadowed symbol -
- Example +A function-like macro over a same-named function - ```cpp - namespace shadow { +clangd tracks this as clangd#2490; at the call site the function-like +macro is active, and clice's card shows that macro and its expansion. - int lookup(int key) { - return key; - } +```cpp +namespace shadow { - } +int lookup(int key) { + return key; +} - #define lookup(key) ((key) + 100) +} - int value = lookup(5); - ``` +#define lookup(key) ((key) + 100) -
+int value = lookup(5); +``` diff --git a/en/clice/features/inlay-hints.md b/en/clice/features/inlay-hints.md index 995f51a1..aee628b9 100644 --- a/en/clice/features/inlay-hints.md +++ b/en/clice/features/inlay-hints.md @@ -1,6 +1,6 @@ # Inlay Hints - @@ -9,1151 +9,1081 @@ clice renders inline annotations for the information the code leaves implicit: p ## Parameter Hints - + + +| Capability | Status | Issues | +| ------------------------------------ | --------- | ------------------------------------------------------------------------------------------------------------------------ | +| Parameter name hints | Supported | | +| Hint suppression | Supported | [clangd#1877](https://github.com/clangd/clangd/issues/1877) | +| Setter and builtin suppression | Supported | | +| Mutable reference markers | Supported | [clangd#1123](https://github.com/clangd/clangd/issues/1123) | +| Forwarding resolution | Supported | [clangd#2324](https://github.com/clangd/clangd/issues/2324) | +| Names from definitions | Supported | | +| Function pointers and call operators | Supported | [clangd#1734](https://github.com/clangd/clangd/issues/1734), [clangd#1742](https://github.com/clangd/clangd/issues/1742) | +| Deducing `this` | Supported | [clangd#1777](https://github.com/clangd/clangd/issues/1777) | +| Dependent calls | Supported | | +| Unexpanded packs | Supported | | +| Macros at call sites | Supported | [clangd#2620](https://github.com/clangd/clangd/issues/2620) | +| Implicit constructor calls | Supported | | +| Pseudo-object expressions | Supported | | +| Explicit instantiation | Supported | [clangd#1034](https://github.com/clangd/clangd/issues/1034) | +| Sloppy name matching | Partial | [clangd#2248](https://github.com/clangd/clangd/issues/2248) | +| Inherited constructors | Partial | [clangd#1364](https://github.com/clangd/clangd/issues/1364) | +| Anonymous parameters | Supported | | +| Operators and literals | Supported | | +| Packs in constructor arguments | Partial | | + +### Parameter name hints + +Argument names at call sites and constructor calls -- [x] Parameter name hints — argument names at call sites and constructor calls - -
- Example - - ```cpp - void draw(int width, int height); - - struct Point { - Point(int x, int y); - Point(const Point& other); - Point(Point&& other); - }; - - void use() { - draw(10, 20); - Point p(1, 2); - Point q{3, 4}; - // Copy and move constructors stay quiet; a temporary's own braces - // still hint (the outer prvalue construction is elided anyway). - Point r(p); - Point m(Point{5, 6}); - Point s(static_cast(r)); - } - ``` - -
- -- [x] Hint suppression — arguments that already spell the parameter name, and `/*name=*/` comments ([clangd#1877](https://github.com/clangd/clangd/issues/1877)) - -
- Example - - ```cpp - void draw(int width, int height); - - void use() { - int width = 5; - int h = 2; - // `width` matches the parameter spelling: only `height:` hints. - draw(width, h); - // An inline comment naming the parameter serves the same purpose; - // a comment naming something else does not. - draw(/*width=*/1, /*height=*/2); - draw(/*margin=*/6, 7); - } - - struct Sizes { - static int width; - int height; - - void member() { - // A bare member access spells the parameter name: suppressed. - draw(5, height); - } - }; - - void qualified(Sizes s) { - // A qualified name is not a plain spelling match. - draw(Sizes::width, 3); - // Neither is an access through a written base object. - draw(4, s.height); - } - ``` - -
- -- [x] Setter and builtin suppression — `setX(x)` and `std::move`/`std::forward` arguments stay bare - -
- Example - - ```cpp - namespace std { - - template - struct remove_reference { - using type = T; - }; - - template - struct remove_reference { - using type = T; - }; - - template - struct remove_reference { - using type = T; - }; - - template - constexpr T&& forward(typename remove_reference::type& t) noexcept; - - template - constexpr typename remove_reference::type&& move(T&& t) noexcept; - - } // namespace std - - struct Config { - void setWidth(int width); - void set_height(int height); - // The parameter carries extra information beyond the setter name, so - // it still hints. - void setTimeout(int timeout_millis); - }; - - void consume(int&& sink); - - // The three-argument algorithm form of std::move is a real call whose - // parameters deserve hints; only the single-argument cast stays bare. - namespace std { - - template - T* move(T* first, T* last, T* result); - - } // namespace std - - void use(Config& config) { - config.setWidth(3); - config.set_height(4); - config.setTimeout(5); - int value = 1; - consume(std::move(value)); - int buffer[4]; - std::move(buffer, buffer + 2, buffer + 2); - } - ``` - -
- -- [x] Mutable reference markers — `&` flags arguments passed by non-const lvalue reference ([clangd#1123](https://github.com/clangd/clangd/issues/1123)) - -
- Example - - ```cpp - void mutate(int& value); - void observe(const int& value); - void take(int&& value); - - void use() { - int v = 0; - mutate(v); - observe(v); - take(static_cast(v)); - } - ``` - -
- -- [x] Forwarding resolution — packs forwarded through wrappers resolve to the target's parameter names ([clangd#2324](https://github.com/clangd/clangd/issues/2324)) - -
- Example - - ```cpp - namespace std { - - template - struct remove_reference { - using type = T; - }; - - template - constexpr T&& forward(typename remove_reference::type& t) noexcept; - - } // namespace std - - void target(int first, int second); - - template - void wrap(Args&&... args) { - target(std::forward(args)...); - } - - // A plain pass-through works without std::forward as well. - void sink(int a, int b, int c); - - template - void call_with(Ts... ts) { - sink(ts...); - } - - // Forwarding also resolves through packs sandwiched between fixed - // head and tail arguments. - int accumulate(int, int b, double); - - template - int head_tail(int a, Args&&... args) { - return accumulate(1, std::forward(args)..., 1.0); - } - - template - int chain(Args&&... args) { - return head_tail(std::forward(args)...); - } - - void use() { - wrap(1, 2); - call_with(1, 2, 3); - chain(32, 42); - } - ``` - -
- -- [x] Names from definitions — unnamed declaration parameters take the definition's names; leading underscores strip - -
- Example - - ```cpp - void resize(int, int); - - void fill(int _value, int __count); +```cpp +void draw(int width, int height); + +struct Point { + Point(int x, int y); + Point(const Point& other); + Point(Point&& other); +}; + +void use() { + draw(10, 20); + Point p(1, 2); + Point q{3, 4}; + // Copy and move constructors stay quiet; a temporary's own braces + // still hint (the outer prvalue construction is elided anyway). + Point r(p); + Point m(Point{5, 6}); + Point s(static_cast(r)); +} +``` - int scale(int good); +### Hint suppression - void use() { - resize(800, 600); - fill(1, 2); - // When both name their parameter, the declaration wins. - scale(7); - } +Arguments that already spell the parameter name, and `/*name=*/` comments - void resize(int width, int height) {} +```cpp +void draw(int width, int height); + +void use() { + int width = 5; + int h = 2; + // `width` matches the parameter spelling: only `height:` hints. + draw(width, h); + // An inline comment naming the parameter serves the same purpose; + // a comment naming something else does not. + draw(/*width=*/1, /*height=*/2); + draw(/*margin=*/6, 7); +} + +struct Sizes { + static int width; + int height; + + void member() { + // A bare member access spells the parameter name: suppressed. + draw(5, height); + } +}; + +void qualified(Sizes s) { + // A qualified name is not a plain spelling match. + draw(Sizes::width, 3); + // Neither is an access through a written base object. + draw(4, s.height); +} +``` - int scale(int bad) { - return bad; - } - ``` +### Setter and builtin suppression -
+`setX(x)` and `std::move`/`std::forward` arguments stay bare -- [x] Function pointers and call operators — indirect calls still name their parameters ([clangd#1734](https://github.com/clangd/clangd/issues/1734), [clangd#1742](https://github.com/clangd/clangd/issues/1742)) +```cpp +namespace std { + +template +struct remove_reference { + using type = T; +}; + +template +struct remove_reference { + using type = T; +}; + +template +struct remove_reference { + using type = T; +}; + +template +constexpr T&& forward(typename remove_reference::type& t) noexcept; + +template +constexpr typename remove_reference::type&& move(T&& t) noexcept; + +} // namespace std + +struct Config { + void setWidth(int width); + void set_height(int height); + // The parameter carries extra information beyond the setter name, so + // it still hints. + void setTimeout(int timeout_millis); +}; + +void consume(int&& sink); + +// The three-argument algorithm form of std::move is a real call whose +// parameters deserve hints; only the single-argument cast stays bare. +namespace std { + +template +T* move(T* first, T* last, T* result); + +} // namespace std + +void use(Config& config) { + config.setWidth(3); + config.set_height(4); + config.setTimeout(5); + int value = 1; + consume(std::move(value)); + int buffer[4]; + std::move(buffer, buffer + 2, buffer + 2); +} +``` -
- Example +### Mutable reference markers - ```cpp - struct Callback { - void operator()(int status, int detail) const; - }; +`&` flags arguments passed by non-const lvalue reference - void (*handler)(int status, const char* message); +```cpp +void mutate(int& value); +void observe(const int& value); +void take(int&& value); + +void use() { + int v = 0; + mutate(v); + observe(v); + take(static_cast(v)); +} +``` - void use() { - Callback cb; - cb(1, 2); - cb.operator()(3, 4); - handler(0, "ok"); - auto cmp = [](int lhs, int rhs) { return lhs < rhs; }; - cmp(1, 2); - } - ``` +### Forwarding resolution -
+Packs forwarded through wrappers resolve to the target's parameter names -- [x] Deducing `this` — the explicit object parameter never hints (C++23) ([clangd#1777](https://github.com/clangd/clangd/issues/1777)) +```cpp +namespace std { -
- Example +template +struct remove_reference { + using type = T; +}; - ```cpp - struct Widget { - void resize(this Widget& self, int width, int height); - }; +template +constexpr T&& forward(typename remove_reference::type& t) noexcept; - void use() { - Widget w; - w.resize(800, 600); - } - ``` +} // namespace std -
+void target(int first, int second); -- [x] Dependent calls — parameter names appear even when the callee is only known inside a template +template +void wrap(Args&&... args) { + target(std::forward(args)...); +} - Candidates are matched by argument count; only a unique surviving - candidate names the parameters, so a call that could still hit several - overloads stays bare rather than guessing. +// A plain pass-through works without std::forward as well. +void sink(int a, int b, int c); -
- Example - - ```cpp - template - void apply(T scale); +template +void call_with(Ts... ts) { + sink(ts...); +} - template - struct Holder { - void member(T item); - static void static_member(T slot); - }; +// Forwarding also resolves through packs sandwiched between fixed +// head and tail arguments. +int accumulate(int, int b, double); - void overload(int value); - void overload(double value); +template +int head_tail(int a, Args&&... args) { + return accumulate(1, std::forward(args)..., 1.0); +} - template - struct Runner { - void run(Holder holder, T value) { - apply(value); - holder.member(value); - Holder::static_member(value); - // Several overloads remain viable: no hint. - overload(T{}); - } - }; - ``` +template +int chain(Args&&... args) { + return head_tail(std::forward(args)...); +} -
- -- [x] Unexpanded packs — a written pack expansion breaks the 1:1 argument mapping and stops hinting - -
- Example - - ```cpp - void plot(int x, int y, int z); - - template - void relay(Ts... ts) { - // `ts...` may instantiate to any number of arguments. - plot(0, ts...); - } - - void use() { - // The outer call still resolves through pack forwarding: 1 and 2 land - // in plot's y and z. - relay(1, 2); - } - ``` - -
- -- [x] Macros at call sites — arguments spelled as macros hint; calls generated inside macro bodies do not ([clangd#2620](https://github.com/clangd/clangd/issues/2620)) - -
- Example - - ```cpp - void report(double value); - void plot(double x, double y); - int check(int status); - - #define PI 3.14 - #define CALL_REPORT() report(2.71) - #define PAIR 1.0, 2.0 - #define ASSERT(expr) if(!(expr)) {} +void use() { + wrap(1, 2); + call_with(1, 2, 3); + chain(32, 42); +} +``` - void use() { - // An object-like macro is still one written argument. - report(PI); - // The call only exists inside the macro body. - CALL_REPORT(); - // One macro covering several arguments has no place to anchor. - plot(PAIR); - // Code written as a macro argument keeps its hints. - ASSERT(check(42) == 0); - } - ``` +### Names from definitions -
+Unnamed declaration parameters take the definition's names; leading underscores strip -- [x] Implicit constructor calls — conversions the code never wrote produce no hints of their own +```cpp +void resize(int, int); -
- Example +void fill(int _value, int __count); - ```cpp - struct Seconds { - Seconds(int raw); - }; +int scale(int good); - void wait(Seconds); - void hold(Seconds duration); +void use() { + resize(800, 600); + fill(1, 2); + // When both name their parameter, the declaration wins. + scale(7); +} - Seconds use() { - // The implicit Seconds(5) must not surface `raw:`. - wait(5); - // The written call still hints its own parameter. - hold(6); - // Nor does the conversion in a return statement. - return 7; - } - ``` +void resize(int width, int height) {} -
+int scale(int bad) { + return bad; +} +``` -- [x] Pseudo-object expressions — MS property accesses stay quiet; written subscripts keep the accessor's names +### Function pointers and call operators -
- Example +Indirect calls still name their parameters - ```cpp - int printf(const char* Format, ...); +```cpp +struct Callback { + void operator()(int status, int detail) const; +}; + +void (*handler)(int status, const char* message); + +void use() { + Callback cb; + cb(1, 2); + cb.operator()(3, 4); + handler(0, "ok"); + auto cmp = [](int lhs, int rhs) { return lhs < rhs; }; + cmp(1, 2); +} +``` - struct State { - __declspec(property(get = GetX, put = PutX)) int x[]; - int GetX(int row, int column); - void PutX(int value); +### Deducing `this` - // The syntactic form is a binary operator: no `value:` hint on `y`. - void Work(int y) { - x = y; - } - }; +The explicit object parameter never hints (C++23) - int use() { - State s; - // The semantic form of __builtin_dump_struct calls printf; none of it - // is written here. - __builtin_dump_struct(&s, printf); - printf("%d", 42); - // Property subscripts read best with the accessor's parameter names. - return s.x[1][2]; - } - ``` +```cpp +struct Widget { + void resize(this Widget& self, int width, int height); +}; + +void use() { + Widget w; + w.resize(800, 600); +} +``` -
+### Dependent calls -- [x] Explicit instantiation — an explicit instantiation definition adds no duplicate hints, while its written template arguments hint normally ([clangd#1034](https://github.com/clangd/clangd/issues/1034)) +Parameter names appear even when the callee is only known inside a template -
- Example +Candidates are matched by argument count; only a unique surviving +candidate names the parameters, so a call that could still hit several +overloads stays bare rather than guessing. - ```cpp - template - void apply(T value) {} +```cpp +template +void apply(T scale); + +template +struct Holder { + void member(T item); + static void static_member(T slot); +}; + +void overload(int value); +void overload(double value); + +template +struct Runner { + void run(Holder holder, T value) { + apply(value); + holder.member(value); + Holder::static_member(value); + // Several overloads remain viable: no hint. + overload(T{}); + } +}; +``` - template void apply(int value); +### Unexpanded packs - void use() { - apply(42); - } +A written pack expansion breaks the 1:1 argument mapping and stops hinting - int measure(int amount); +```cpp +void plot(int x, int y, int z); + +template +void relay(Ts... ts) { + // `ts...` may instantiate to any number of arguments. + plot(0, ts...); +} + +void use() { + // The outer call still resolves through pack forwarding: 1 and 2 land + // in plot's y and z. + relay(1, 2); +} +``` - template - struct Box {}; +### Macros at call sites - template struct Box; - ``` +Arguments spelled as macros hint; calls generated inside macro bodies do not -
+```cpp +void report(double value); +void plot(double x, double y); +int check(int status); + +#define PI 3.14 +#define CALL_REPORT() report(2.71) +#define PAIR 1.0, 2.0 +#define ASSERT(expr) if(!(expr)) {} + +void use() { + // An object-like macro is still one written argument. + report(PI); + // The call only exists inside the macro body. + CALL_REPORT(); + // One macro covering several arguments has no place to anchor. + plot(PAIR); + // Code written as a macro argument keeps its hints. + ASSERT(check(42) == 0); +} +``` -- [ ] Sloppy name matching — `aParam` does not yet suppress an argument spelled `param` _(partial)_ ([clangd#2248](https://github.com/clangd/clangd/issues/2248)) +### Implicit constructor calls -
- Example +Conversions the code never wrote produce no hints of their own - ```cpp - void draw(int aParam); +```cpp +struct Seconds { + Seconds(int raw); +}; + +void wait(Seconds); +void hold(Seconds duration); + +Seconds use() { + // The implicit Seconds(5) must not surface `raw:`. + wait(5); + // The written call still hints its own parameter. + hold(6); + // Nor does the conversion in a return statement. + return 7; +} +``` - void use() { - int param = 3; - // Ideally the near-match would suppress the hint; today it still shows. - draw(param); - } - ``` +### Pseudo-object expressions -
+MS property accesses stay quiet; written subscripts keep the accessor's names -- [ ] Inherited constructors — `using Base::Base` calls lose their parameter names _(partial)_ ([clangd#1364](https://github.com/clangd/clangd/issues/1364)) +```cpp +int printf(const char* Format, ...); + +struct State { + __declspec(property(get = GetX, put = PutX)) int x[]; + int GetX(int row, int column); + void PutX(int value); + + // The syntactic form is a binary operator: no `value:` hint on `y`. + void Work(int y) { + x = y; + } +}; + +int use() { + State s; + // The semantic form of __builtin_dump_struct calls printf; none of it + // is written here. + __builtin_dump_struct(&s, printf); + printf("%d", 42); + // Property subscripts read best with the accessor's parameter names. + return s.x[1][2]; +} +``` -
- Example +### Explicit instantiation - ```cpp - struct Base { - Base(int width); - }; +An explicit instantiation definition adds no duplicate hints, while its written template arguments hint normally - struct Derived : Base { - using Base::Base; - }; +```cpp +template +void apply(T value) {} - // No `width:` hint yet. - Derived d(7); - ``` +template void apply(int value); -
+void use() { + apply(42); +} -- [x] Anonymous parameters — nothing to name, though a mutable reference still flags `&` +int measure(int amount); -
- Example +template +struct Box {}; - ```cpp - void value_sink(int); - void ref_sink(int&); - void const_ref_sink(const int&); - void rvalue_sink(int&&); +template struct Box; +``` - void use() { - int v = 0; - value_sink(1); - // Only the `&` marker survives without a name. - ref_sink(v); - const_ref_sink(v); - rvalue_sink(2); - } - ``` +### Sloppy name matching -
+`aParam` does not yet suppress an argument spelled `param` -- [x] Operators and literals — operator syntax and user-defined literals stay bare; member and default member initializers hint +```cpp +void draw(int aParam); -
- Example +void use() { + int param = 3; + // Ideally the near-match would suppress the hint; today it still shows. + draw(param); +} +``` - ```cpp - struct S { - S(int param); - }; +### Inherited constructors - void operator+(S lhs, S rhs); +`using Base::Base` calls lose their parameter names - long double operator""_w(long double param); +```cpp +struct Base { + Base(int width); +}; - struct Holder { - S member; - S defaulted{3}; - Holder() : member(42) {} - }; +struct Derived : Base { + using Base::Base; +}; - void use() { - S a(1); - S b(2); - a + b; - 1.2_w; - } - ``` +// No `width:` hint yet. +Derived d(7); +``` -
+### Anonymous parameters -- [ ] Packs in constructor arguments — outer calls resolve; hints inside the expansion are still missing _(partial)_ +Nothing to name, though a mutable reference still flags `&` -
- Example +```cpp +void value_sink(int); +void ref_sink(int&); +void const_ref_sink(const int&); +void rvalue_sink(int&&); + +void use() { + int v = 0; + value_sink(1); + // Only the `&` marker survives without a name. + ref_sink(v); + const_ref_sink(v); + rvalue_sink(2); +} +``` - ```cpp - struct Foo { - Foo(); - Foo(int x); - }; +### Operators and literals - void consume(Foo a, int b); +Operator syntax and user-defined literals stay bare; member and default member initializers hint - template - void relay(Args... args) { - consume(args...); - } +```cpp +struct S { + S(int param); +}; + +void operator+(S lhs, S rhs); + +long double operator""_w(long double param); + +struct Holder { + S member; + S defaulted{3}; + Holder() : member(42) {} +}; + +void use() { + S a(1); + S b(2); + a + b; + 1.2_w; +} +``` - template - void construct(Args... args) { - // The written Foo{args...} and the literal after it get no hints yet. - consume(Foo{args...}, 1); - } +### Packs in constructor arguments - void use() { - relay(Foo{}, 42); - relay(42, 42); - construct(42); - } - ``` +Outer calls resolve; hints inside the expansion are still missing -
+```cpp +struct Foo { + Foo(); + Foo(int x); +}; + +void consume(Foo a, int b); + +template +void relay(Args... args) { + consume(args...); +} + +template +void construct(Args... args) { + // The written Foo{args...} and the literal after it get no hints yet. + consume(Foo{args...}, 1); +} + +void use() { + relay(Foo{}, 42); + relay(42, 42); + construct(42); +} +``` ## Type Hints - - -- [x] Deduced `auto` variables — the hint shows the full variable type, qualifiers included + -
- Example +| Capability | Status | Issues | +| ------------------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------ | +| Deduced `auto` variables | Supported | | +| Type sugar and the length limit | Supported | [clangd#1298](https://github.com/clangd/clangd/issues/1298), [clangd#1357](https://github.com/clangd/clangd/issues/1357) | +| Structured bindings | Supported | | +| Lambdas | Supported | [clangd#1163](https://github.com/clangd/clangd/issues/1163) | +| Deduced return types | Supported | | +| `decltype` spellings | Supported | | +| `auto` parameters | Supported | | +| Explicitly spelled initializers | Partial | [clangd#1749](https://github.com/clangd/clangd/issues/1749) | +| Dependent `auto` | Partial | [clangd#2275](https://github.com/clangd/clangd/issues/2275) | +| Scope suppression | Supported | | +| Tuple-protocol bindings | Supported | | +| Instantiated templates | Partial | [clangd#2275](https://github.com/clangd/clangd/issues/2275) | - ```cpp - int make(); +### Deduced `auto` variables - void use() { - auto value = make(); - const auto& ref = value; - auto* ptr = &value; - } - ``` +The hint shows the full variable type, qualifiers included -
- -- [x] Type sugar and the length limit — aliases keep their spelling; over-long types fall back to the sugared name ([clangd#1298](https://github.com/clangd/clangd/issues/1298), [clangd#1357](https://github.com/clangd/clangd/issues/1357)) - -
- Example - - ```cpp - using Integer = int; - - Integer make_alias(); - - template - struct extremely_long_template_name {}; - - using Compact = extremely_long_template_name; - - Compact make_compact(); - - extremely_long_template_name make_long(); - - template - struct Defaulted {}; - - Defaulted make_defaulted(); - - void use() { - auto aliased = make_alias(); - auto shortened = make_compact(); - // No sugar short enough to fall back to: the hint is dropped. - auto dropped = make_long(); - // Default template arguments never print. - auto defaulted = make_defaulted(); - } - ``` - -
- -- [x] Structured bindings — each binding hints its canonical type; the aggregate itself stays bare - -
- Example - - ```cpp - struct Pair { - int first; - float second; - }; - - Pair make(); - - int array[2]; - - void use() { - auto [a, b] = make(); - auto [x, y] = array; - } - ``` - -
- -- [x] Lambdas — variables, deduced return types, and init-captures all hint ([clangd#1163](https://github.com/clangd/clangd/issues/1163)) - -
- Example +```cpp +int make(); - ```cpp - int compute(); +void use() { + auto value = make(); + const auto& ref = value; + auto* ptr = &value; +} +``` - void use() { - auto callback = [captured = compute()](int x) { - return x + captured; - }; - auto bare = [] { - return 1.5; - }; - } - ``` +### Type sugar and the length limit -
+Aliases keep their spelling; over-long types fall back to the sugared name -- [x] Deduced return types — `-> T` after the parameter list, declarations included +```cpp +using Integer = int; -
- Example +Integer make_alias(); - ```cpp - auto answer() { - return 42; - } +template +struct extremely_long_template_name {}; - auto& ref_answer() { - static int storage = 0; - return storage; - } +using Compact = extremely_long_template_name; - // A declaration hints once a later definition supplies the deduction; a - // definition-less one stays silent. - auto declared(int x); - auto deducible(int x); +Compact make_compact(); - auto deducible(int x) { - return x + 1; - } +extremely_long_template_name make_long(); - // Written trailing return types need no hint. - auto spelled() -> int; - auto pointer() -> auto* { - return "text"; - } +template +struct Defaulted {}; - struct Convertible { - operator auto() { - return 42; - } - }; - ``` +Defaulted make_defaulted(); -
+void use() { + auto aliased = make_alias(); + auto shortened = make_compact(); + // No sugar short enough to fall back to: the hint is dropped. + auto dropped = make_long(); + // Default template arguments never print. + auto defaulted = make_defaulted(); +} +``` -- [x] `decltype` spellings — the underlying type shows next to the written `decltype` +### Structured bindings -
- Example +Each binding hints its canonical type; the aggregate itself stays bare - ```cpp - int source(); +```cpp +struct Pair { + int first; + float second; +}; - decltype(source()) value = 1; +Pair make(); - int& ref = value; - // decltype(auto) preserves the reference. - decltype(auto) forwarded = ref; +int array[2]; - // Every written decltype spelling hints: declarators, alias targets, - // return types and functional casts. - const decltype(0)& bound = value; +void use() { + auto [a, b] = make(); + auto [x, y] = array; +} +``` - decltype(0) declared(); +### Lambdas - auto trailing() -> decltype(0); +variables, deduced return types, and init-captures all hint - template - struct Wrap; +```cpp +int compute(); + +void use() { + auto callback = [captured = compute()](int x) { + return x + captured; + }; + auto bare = [] { + return 1.5; + }; +} +``` - using Alias = Wrap; +### Deduced return types - auto constructed = decltype(0){}; - ``` +`-> T` after the parameter list, declarations included -
+```cpp +auto answer() { + return 42; +} + +auto& ref_answer() { + static int storage = 0; + return storage; +} + +// A declaration hints once a later definition supplies the deduction; a +// definition-less one stays silent. +auto declared(int x); +auto deducible(int x); + +auto deducible(int x) { + return x + 1; +} + +// Written trailing return types need no hint. +auto spelled() -> int; +auto pointer() -> auto* { + return "text"; +} + +struct Convertible { + operator auto() { + return 42; + } +}; +``` -- [x] `auto` parameters — a template with exactly one instantiation reveals the deduced type +### `decltype` spellings -
- Example +The underlying type shows next to the written `decltype` - ```cpp - int twice(auto x) { - return x + x; - } +```cpp +int source(); - int result = twice(21); +decltype(source()) value = 1; - // A second instantiation makes the deduction ambiguous: no hint. - int measure(auto x) { - return 1; - } +int& ref = value; +// decltype(auto) preserves the reference. +decltype(auto) forwarded = ref; - int a = measure(1); - int b = measure(2.0); +// Every written decltype spelling hints: declarators, alias targets, +// return types and functional casts. +const decltype(0)& bound = value; - // Packs and parameters after them never hint. - int spread(auto first, auto... rest, auto last) { - return 0; - } +decltype(0) declared(); - int c = spread(nullptr, 'x', 2.0f, 3); +auto trailing() -> decltype(0); - // Deduplication: a template body hints once across instantiations of the - // same deduced type. - template - void body() { - auto var = 42; - } +template +struct Wrap; - template void body(); - template void body(); - ``` +using Alias = Wrap; -
+auto constructed = decltype(0){}; +``` -- [ ] Explicitly spelled initializers — casts and functional casts still hint redundantly _(partial)_ ([clangd#1749](https://github.com/clangd/clangd/issues/1749)) +### `auto` parameters -
- Example +A template with exactly one instantiation reveals the deduced type - ```cpp - int compute(); +```cpp +int twice(auto x) { + return x + x; +} - void use() { - // The type is already written on the right-hand side; ideally these - // two hints would be suppressed. - auto widened = static_cast(compute()); - auto braced = int{42}; - } - ``` +int result = twice(21); -
+// A second instantiation makes the deduction ambiguous: no hint. +int measure(auto x) { + return 1; +} -- [ ] Dependent `auto` — deduction inside an uninstantiated template body stays silent _(partial)_ ([clangd#2275](https://github.com/clangd/clangd/issues/2275)) +int a = measure(1); +int b = measure(2.0); -
- Example +// Packs and parameters after them never hint. +int spread(auto first, auto... rest, auto last) { + return 0; +} - ```cpp - template - void body(T input) { - // No hint: the deduced type depends on T. - auto derived = input + 1; - // A dependence-free initializer still hints normally. - auto counter = 0; - } - ``` +int c = spread(nullptr, 'x', 2.0f, 3); -
+// Deduplication: a template body hints once across instantiations of the +// same deduced type. +template +void body() { + auto var = 42; +} -- [x] Scope suppression — namespace qualifiers drop from hints; class scopes stay +template void body(); +template void body(); +``` -
- Example +### Explicitly spelled initializers - ```cpp - namespace outer { - namespace inner { +Casts and functional casts still hint redundantly - struct S1 {}; - S1 make_s1(); - auto x = make_s1(); +```cpp +int compute(); + +void use() { + // The type is already written on the right-hand side; ideally these + // two hints would be suppressed. + auto widened = static_cast(compute()); + auto braced = int{42}; +} +``` - struct S2 { - template - struct Nested {}; - }; +### Dependent `auto` - S2::Nested make_nested(); - auto y = make_nested(); +Deduction inside an uninstantiated template body stays silent - } // namespace inner - } // namespace outer - ``` +```cpp +template +void body(T input) { + // No hint: the deduced type depends on T. + auto derived = input + 1; + // A dependence-free initializer still hints normally. + auto counter = 0; +} +``` -
+### Scope suppression -- [x] Tuple-protocol bindings — hints print the canonical type, not `tuple_element::type` +Namespace qualifiers drop from hints; class scopes stay -
- Example +```cpp +namespace outer { +namespace inner { - ```cpp - struct IntPair { - int a; - int b; - }; +struct S1 {}; +S1 make_s1(); +auto x = make_s1(); - namespace std { +struct S2 { + template + struct Nested {}; +}; - template - struct tuple_size {}; +S2::Nested make_nested(); +auto y = make_nested(); - template <> - struct tuple_size { - constexpr static unsigned value = 2; - }; +} // namespace inner +} // namespace outer +``` - template - struct tuple_element {}; +### Tuple-protocol bindings - template - struct tuple_element { - using type = int; - }; +Hints print the canonical type, not `tuple_element::type` - } // namespace std +```cpp +struct IntPair { + int a; + int b; +}; - template - int get(const IntPair& p) { - if constexpr(I == 0) { - return p.a; - } else { - return p.b; - } - } +namespace std { - IntPair make(); +template +struct tuple_size {}; - auto [x, y] = make(); - ``` +template <> +struct tuple_size { + constexpr static unsigned value = 2; +}; -
+template +struct tuple_element {}; -- [ ] Instantiated templates — instantiated bodies repeat no hints at the pattern; dependent `auto` could reveal the deduced type while exactly one instantiation exists _(partial)_ ([clangd#2275](https://github.com/clangd/clangd/issues/2275)) +template +struct tuple_element { + using type = int; +}; -
- Example +} // namespace std - ```cpp - void take(int first, int second); +template +int get(const IntPair& p) { + if constexpr(I == 0) { + return p.a; + } else { + return p.b; + } +} - template - struct Single { - void reset() { - take(1, 2); - // Deducible from the only instantiation, but not yet deduced. - auto copy = T(); - } - }; +IntPair make(); - template struct Single; +auto [x, y] = make(); +``` - template - struct Twice { - void reset() { - // No hint: two instantiations deduce contradicting types. - auto copy = T(); - } - }; +### Instantiated templates - template struct Twice; - template struct Twice; - ``` +Instantiated bodies repeat no hints at the pattern; dependent `auto` could reveal the deduced type while exactly one instantiation exists -
+```cpp +void take(int first, int second); + +template +struct Single { + void reset() { + take(1, 2); + // Deducible from the only instantiation, but not yet deduced. + auto copy = T(); + } +}; + +template struct Single; + +template +struct Twice { + void reset() { + // No hint: two instantiations deduce contradicting types. + auto copy = T(); + } +}; + +template struct Twice; +template struct Twice; +``` ## Designator Hints - - -- [x] Field and index designators — positional aggregate initialization shows `.field=` and `[index]=` ([clangd#2303](https://github.com/clangd/clangd/issues/2303)) - -
- Example - - ```cpp - struct Point { - int x; - int y; - int z; - }; + - Point p{1, 2 + 2}; +| Capability | Status | Issues | +| -------------------------------------- | ----------- | ----------------------------------------------------------- | +| Field and index designators | Supported | [clangd#2303](https://github.com/clangd/clangd/issues/2303) | +| Nested aggregates | Supported | | +| Anonymous members | Supported | | +| Designator suppression | Supported | | +| Aggregates only | Supported | | +| Broken initializers | Supported | | +| Parenthesized aggregate initialization | Unsupported | [clangd#2540](https://github.com/clangd/clangd/issues/2540) | - int coordinates[2] = {7, 8}; +### Field and index designators - // Array designators survive dependent-sized members; reserved names are - // skipped rather than printed. - template - struct Array { - T __elements[N]; - }; +Positional aggregate initialization shows `.field=` and `[index]=` - Array pair = {0, 1}; - ``` - -
- -- [x] Nested aggregates — written braces recurse; omitted braces flatten into `.outer.inner=` - -
- Example - - ```cpp - struct Inner { - int x; - int y; - }; - - struct Outer { - Inner a; - Inner b; - }; +```cpp +struct Point { + int x; + int y; + int z; +}; - Outer o{{1, 2}, 3}; - ``` +Point p{1, 2 + 2}; -
+int coordinates[2] = {7, 8}; -- [x] Anonymous members — unnamed unions and structs vanish from the designator path +// Array designators survive dependent-sized members; reserved names are +// skipped rather than printed. +template +struct Array { + T __elements[N]; +}; -
- Example +Array pair = {0, 1}; +``` - ```cpp - struct State { - union { - struct { - struct { - int y; - }; - } x; - }; - }; +### Nested aggregates - State s{42}; - ``` +Written braces recurse; omitted braces flatten into `.outer.inner=` -
+```cpp +struct Inner { + int x; + int y; +}; -- [x] Designator suppression — written designators and `/*name=*/` comments keep their inits bare +struct Outer { + Inner a; + Inner b; +}; -
- Example +Outer o{{1, 2}, 3}; +``` - ```cpp - struct Point { - int a; - int b; - int c; - int d; - int e; - }; +### Anonymous members - // Mixing written designators with positional inits is a C99 extension - // clang accepts with a warning; only the bare `4` needs help. - Point p{/*a=*/1, .c = 2, /* .d = */ 3, 4}; - ``` +Unnamed unions and structs vanish from the designator path -
+```cpp +struct State { + union { + struct { + struct { + int y; + }; + } x; + }; +}; + +State s{42}; +``` -- [x] Aggregates only — constructor calls, copies and idiomatic zero-init produce no designators +### Designator suppression -
- Example +Written designators and `/*name=*/` comments keep their inits bare - ```cpp - struct Constructible { - Constructible(int amount); - }; +```cpp +struct Point { + int a; + int b; + int c; + int d; + int e; +}; + +// Mixing written designators with positional inits is a C99 extension +// clang accepts with a warning; only the bare `4` needs help. +Point p{/*a=*/1, .c = 2, /* .d = */ 3, 4}; +``` - // A braced constructor call names parameters, not fields. - Constructible built{5}; +### Aggregates only - struct Copyable { - int x; - }; +Constructor calls, copies and idiomatic zero-init produce no designators - Copyable original{1}; - Copyable duplicate{original}; +```cpp +struct Constructible { + Constructible(int amount); +}; - // The idiomatic `{}` zero-initializer stays quiet. - struct Wide { - int fields[8]; - }; +// A braced constructor call names parameters, not fields. +Constructible built{5}; - Wide zeroed{}; - ``` +struct Copyable { + int x; +}; -
+Copyable original{1}; +Copyable duplicate{original}; -- [x] Broken initializers — designators survive next to initializers that fail to compile +// The idiomatic `{}` zero-initializer stays quiet. +struct Wide { + int fields[8]; +}; -
- Example +Wide zeroed{}; +``` - ```cpp - // The first initializer deliberately fails to convert. - struct Empty {}; +### Broken initializers - struct Mixed { - int a; - int b; - }; +Designators survive next to initializers that fail to compile - void use() { - Mixed m{Empty(), 1}; - } - ``` +```cpp +// The first initializer deliberately fails to convert. +struct Empty {}; -
+struct Mixed { + int a; + int b; +}; -- [ ] Parenthesized aggregate initialization — C++20 `Point(1, 2)` gets no hints yet ([clangd#2540](https://github.com/clangd/clangd/issues/2540)) +void use() { + Mixed m{Empty(), 1}; +} +``` -
- Example +### Parenthesized aggregate initialization - ```cpp - struct Point { - int x; - int y; - }; +C++20 `Point(1, 2)` gets no hints yet - Point p(1, 2); - ``` +```cpp +struct Point { + int x; + int y; +}; -
+Point p(1, 2); +``` ## Other Hint Kinds - + -- [ ] Template parameter hints — deduced and explicit template arguments at call sites ([clangd#2583](https://github.com/clangd/clangd/issues/2583)) +| Capability | Status | Issues | +| ------------------------- | ----------- | ----------------------------------------------------------- | +| Template parameter hints | Unsupported | [clangd#2583](https://github.com/clangd/clangd/issues/2583) | +| CTAD arguments | Unsupported | [clangd#2331](https://github.com/clangd/clangd/issues/2331) | +| Implicit conversion hints | Unsupported | [clangd#2254](https://github.com/clangd/clangd/issues/2254) | -
- Example +### Template parameter hints - ```cpp - template - T convert(U val); +Deduced and explicit template arguments at call sites - // Could hint `T: float` next to the explicit argument list. - float converted = convert(42); - ``` - -
- -- [ ] CTAD arguments — deduced class template arguments after the template name ([clangd#2331](https://github.com/clangd/clangd/issues/2331)) - -
- Example +```cpp +template +T convert(U val); - ```cpp - template - struct Pair { - A first; - B second; - Pair(A a, B b); - }; +// Could hint `T: float` next to the explicit argument list. +float converted = convert(42); +``` - // Could hint `` after `pair`. - Pair pair(1, 2.5); - ``` +### CTAD arguments -
+Deduced class template arguments after the template name -- [ ] Implicit conversion hints — surface the conversions a call site performs ([clangd#2254](https://github.com/clangd/clangd/issues/2254)) +```cpp +template +struct Pair { + A first; + B second; + Pair(A a, B b); +}; + +// Could hint `` after `pair`. +Pair pair(1, 2.5); +``` -
- Example +### Implicit conversion hints - ```cpp - void process(double val); +Surface the conversions a call site performs - // Could hint `(double)` before the argument. - void use() { - process(42); - } - ``` +```cpp +void process(double val); -
+// Could hint `(double)` before the argument. +void use() { + process(42); +} +``` diff --git a/en/clice/features/navigation.md b/en/clice/features/navigation.md index 58836092..cd731011 100644 --- a/en/clice/features/navigation.md +++ b/en/clice/features/navigation.md @@ -2,305 +2,262 @@ ## Go to Definition - + -- [x] Cross-TU go-to-definition +| Capability | Status | Issues | +| ---------------------------------------------------------------------- | ----------- | ----------------------------------------------------------- | +| Cross-TU go-to-definition | Supported | | +| Definition and declaration alternate at the cursor site | Supported | | +| Declaration-only symbols navigate to their declaration | Supported | | +| Go-to-definition on `#include` directives | Supported | | +| Local variables and parameters navigate to their declaration | Supported | | +| Navigate through macro wrappers to the underlying declaration | Supported | | +| Names conjured by a macro body or token paste anchor at the invocation | Supported | | +| Tokens inside a `#define` body carry no navigation of their own | Supported | | +| Error recovery | Unsupported | | +| Dependent member navigation in uninstantiated templates | Supported | | +| Template specialization navigates to the primary template | Unsupported | [clangd#212](https://github.com/clangd/clangd/issues/212) | +| `auto` keyword navigates to the deduced type | Unsupported | [clangd#2055](https://github.com/clangd/clangd/issues/2055) | - A use in one translation unit resolves to the definition supplied by - a sibling source — the answer spans the project, not the current - file alone. +### Cross-TU go-to-definition -
- Example +A use in one translation unit resolves to the definition supplied by +a sibling source — the answer spans the project, not the current +file alone. - `main.cpp`: +`main.cpp`: - ```cpp - #include "shared.h" +```cpp +#include "shared.h" - int run(int value) { - return transform(value); - } - ``` +int run(int value) { + return transform(value); +} +``` - `lib.cpp`: +`lib.cpp`: - ```cpp - #include "shared.h" +```cpp +#include "shared.h" - int transform(int value) { - return value * 2; - } - ``` +int transform(int value) { + return value * 2; +} +``` - `shared.h`: +`shared.h`: - ```cpp - #pragma once +```cpp +#pragma once - int transform(int value); - ``` +int transform(int value); +``` -
+### Definition and declaration alternate at the cursor site -- [x] Definition and declaration alternate at the cursor site +On a use, go-to-definition reaches the definition. Invoked on the +definition it steps to the declaration, and on the declaration it +steps to the definition — the two sites alternate. A symbol defined +inline, with no separate declaration, keeps its definition as the +answer. - On a use, go-to-definition reaches the definition. Invoked on the - definition it steps to the declaration, and on the declaration it - steps to the definition — the two sites alternate. A symbol defined - inline, with no separate declaration, keeps its definition as the - answer. +```cpp +int scale(int value); -
- Example +int scale(int value) { + return value * 2; +} - ```cpp - int scale(int value); +int apply(int value) { + return scale(value); +} +``` - int scale(int value) { - return value * 2; - } +### Declaration-only symbols navigate to their declaration - int apply(int value) { - return scale(value); - } - ``` +Symbols that carry only a declaration — pure virtuals, `extern` +variables, in-class static constants — resolve to that declaration +instead of returning nothing. -
+```cpp +extern int threshold; -- [x] Declaration-only symbols navigate to their declaration +int probe(int value); - Symbols that carry only a declaration — pure virtuals, `extern` - variables, in-class static constants — resolve to that declaration - instead of returning nothing. +struct Screen { + static const int margin = 4; + virtual void refresh() = 0; +}; -
- Example +int watch(Screen& screen, int value) { + screen.refresh(); + return probe(value) + threshold + Screen::margin; +} +``` - ```cpp - extern int threshold; +### Go-to-definition on `#include` directives - int probe(int value); +Invoked on an `#include` line, go-to-definition opens the included +file. This works for the leading includes compiled into the preamble +(the PCH) as well as ordinary ones later in the file. - struct Screen { - static const int margin = 4; - virtual void refresh() = 0; - }; +`main.cpp`: - int watch(Screen& screen, int value) { - screen.refresh(); - return probe(value) + threshold + Screen::margin; - } - ``` +```cpp +#include "panel.h" -
+int build() { + return dimension(); +} -- [x] Go-to-definition on `#include` directives +#include "extra.h" - Invoked on an `#include` line, go-to-definition opens the included - file. This works for the leading includes compiled into the preamble - (the PCH) as well as ordinary ones later in the file. +int total() { + return build() + spacing(); +} +``` -
- Example +`extra.h`: - `main.cpp`: +```cpp +inline int spacing() { + return 2; +} +``` - ```cpp - #include "panel.h" +`panel.h`: - int build() { - return dimension(); - } +```cpp +#pragma once - #include "extra.h" +int dimension(); +``` - int total() { - return build() + spacing(); - } - ``` +### Local variables and parameters navigate to their declaration - `extra.h`: +Go-to-definition on a local variable or parameter jumps to its +declaration inside the function body. - ```cpp - inline int spacing() { - return 2; - } - ``` +```cpp +int accumulate(int base) { + int total = base; + total = total + base; + return total; +} +``` - `panel.h`: +### Navigate through macro wrappers to the underlying declaration - ```cpp - #pragma once +A name spelled in a macro argument anchors at its spelling, so +definition and declaration alternate there exactly as at a plain +site, and a later use resolves through the wrapper to the function it +declares. - int dimension(); - ``` +```cpp +#define DECLARE_HOOK(name) int name(int value) -
+DECLARE_HOOK(notify); -- [x] Local variables and parameters navigate to their declaration +DECLARE_HOOK(notify) { + return value + 1; +} - Go-to-definition on a local variable or parameter jumps to its - declaration inside the function body. +int trigger(int value) { + return notify(value); +} +``` -
- Example +### Names conjured by a macro body or token paste anchor at the invocation - ```cpp - int accumulate(int base) { - int total = base; - total = total + base; - return total; - } - ``` +A name assembled by token paste has no spelling of its own in the +source, so it anchors at the macro invocation that creates it: the +invocation is its definition site, and a plain use of the name jumps +back to that invocation. -
+```cpp +#define MAKE_FLAG(name) bool flag_##name = false -- [x] Navigate through macro wrappers to the underlying declaration +MAKE_FLAG(verbose); - A name spelled in a macro argument anchors at its spelling, so - definition and declaration alternate there exactly as at a plain - site, and a later use resolves through the wrapper to the function it - declares. +bool read_flag() { + return flag_verbose; +} +``` -
- Example +### Tokens inside a `#define` body carry no navigation of their own - ```cpp - #define DECLARE_HOOK(name) int name(int value) +A token written inside a macro body has no meaning until an expansion +assigns one, so navigation on it yields nothing, while the invocation +token always resolves to the macro being expanded. - DECLARE_HOOK(notify); +```cpp +#define DEFINE_COUNTER int counter = 0 - DECLARE_HOOK(notify) { - return value + 1; - } +DEFINE_COUNTER; +``` - int trigger(int value) { - return notify(value); - } - ``` +### Error recovery -
+Navigate to a variable whose type is unresolved -- [x] Names conjured by a macro body or token paste anchor at the invocation +When a variable's type name fails to resolve, go-to-definition on a +later use of the variable currently returns nothing, even though the +variable's own declaration is still recorded. - A name assembled by token paste has no spelling of its own in the - source, so it anchors at the macro invocation that creates it: the - invocation is its definition site, and a plain use of the name jumps - back to that invocation. +```cpp +Unresolved handle; // 'Unresolved' does not name a type -
- Example +void read() { + (void) handle; // go-to-def on handle → the declaration above +} +``` - ```cpp - #define MAKE_FLAG(name) bool flag_##name = false +### Dependent member navigation in uninstantiated templates - MAKE_FLAG(verbose); +Inside a template that is never instantiated, a member accessed on an +object of a dependent type resolves to the member declared on the +corresponding class template. - bool read_flag() { - return flag_verbose; - } - ``` +```cpp +template +struct Sink { + void push(T value); +}; -
+template +void drain(Sink& sink, T value) { + sink.push(value); +} +``` -- [x] Tokens inside a `#define` body carry no navigation of their own +### Template specialization navigates to the primary template - A token written inside a macro body has no meaning until an expansion - assigns one, so navigation on it yields nothing, while the invocation - token always resolves to the macro being expanded. +Go-to-definition on the name of an explicit specialization resolves to +the specialization itself; stepping from it to the primary template it +specializes is not offered. -
- Example +```cpp +template +struct Formatter {}; // primary template - ```cpp - #define DEFINE_COUNTER int counter = 0 +template <> +struct Formatter {}; // go-to-def on Formatter → primary template +``` - DEFINE_COUNTER; - ``` +### `auto` keyword navigates to the deduced type -
+Go-to-definition on the `auto` keyword should reach the type it was +deduced to; today it returns nothing. -- [ ] Error recovery — navigate to a variable whose type is unresolved +```cpp +struct Widget {}; - When a variable's type name fails to resolve, go-to-definition on a - later use of the variable currently returns nothing, even though the - variable's own declaration is still recorded. +Widget make_widget(); -
- Example - - ```cpp - Unresolved handle; // 'Unresolved' does not name a type - - void read() { - (void) handle; // go-to-def on handle → the declaration above - } - ``` - -
- -- [x] Dependent member navigation in uninstantiated templates - - Inside a template that is never instantiated, a member accessed on an - object of a dependent type resolves to the member declared on the - corresponding class template. - -
- Example - - ```cpp - template - struct Sink { - void push(T value); - }; - - template - void drain(Sink& sink, T value) { - sink.push(value); - } - ``` - -
- -- [ ] Template specialization navigates to the primary template ([clangd#212](https://github.com/clangd/clangd/issues/212)) - - Go-to-definition on the name of an explicit specialization resolves to - the specialization itself; stepping from it to the primary template it - specializes is not offered. - -
- Example - - ```cpp - template - struct Formatter {}; // primary template - - template <> - struct Formatter {}; // go-to-def on Formatter → primary template - ``` - -
- -- [ ] `auto` keyword navigates to the deduced type ([clangd#2055](https://github.com/clangd/clangd/issues/2055)) - - Go-to-definition on the `auto` keyword should reach the type it was - deduced to; today it returns nothing. - -
- Example - - ```cpp - struct Widget {}; - - Widget make_widget(); - - void use() { - auto widget = make_widget(); // go-to-def on auto → Widget - } - ``` - -
+void use() { + auto widget = make_widget(); // go-to-def on auto → Widget +} +``` @@ -310,536 +267,495 @@ Navigate to definitions of implicitly invoked code. In C++ many constructs gener Implicit navigation requires an unambiguous source token — patterns where the token already has a well-defined go-to-def target (e.g., a variable name always goes to its declaration) cannot be repurposed for implicit call navigation. - - -- [ ] `override` / `final` — navigate to the overridden base method - - Go-to-definition on the `override` or `final` specifier should reach the - base class virtual method it overrides; today it returns nothing. - -
- Example - - ```cpp - struct Base { - virtual void draw(); - virtual void paint(); - }; - - struct Derived : Base { - void draw() override; // go-to-def on override → Base::draw - void paint() final; // go-to-def on final → Base::paint - }; - ``` - -
- -- [ ] `break` / `continue` — navigate to the enclosing loop or switch head ([clangd#1921](https://github.com/clangd/clangd/issues/1921)) - - Go-to-definition on `break` or `continue` should reach the head of the - loop or switch it controls; today it returns nothing. - -
- Example - - ```cpp - void loop() { - for (int i = 0; i < 10; i += 1) { - if (i == 5) break; // go-to-def on break → the for loop - continue; // go-to-def on continue → the for loop - } - } - ``` - -
- -- [x] Constructor calls — from parentheses or braces to the selected constructor - - Go-to-definition on the opening parenthesis or brace of a constructor - call reaches the constructor overload resolution selected, for both the - `T(args)` and `T{args}` forms. - -
- Example - - ```cpp - struct Widget { - Widget(int w, int h); - }; - - void build() { - Widget a(800, 600); - Widget b{800, 600}; - } - ``` - -
- -- [ ] Copy/move construction and assignment — to the constructor or assignment operator _(partial)_ - - Go-to-definition on the `=` of an assignment reaches the assignment - operator. The `=` that introduces a copy- or move-initialization - (`T b = a;`) is initialization syntax rather than an operator call and is - not yet resolved. - -
- Example - - ```cpp - struct Widget { - Widget(int v); - Widget(const Widget& other); - Widget(Widget&& other); - Widget& operator=(const Widget& other); - }; - - void copies(Widget a) { - Widget b = a; - Widget c = static_cast(a); - b = c; - } - ``` - -
- -- [x] CTAD — navigate to the selected constructor + + +| Capability | Status | Issues | +| --------------------------------------------------- | ----------- | ----------------------------------------------------------- | +| `override` / `final` | Unsupported | | +| `break` / `continue` | Unsupported | [clangd#1921](https://github.com/clangd/clangd/issues/1921) | +| Constructor calls | Supported | | +| Copy/move construction and assignment | Partial | | +| CTAD | Supported | | +| Aggregate initialization | Supported | | +| `delete` expression | Unsupported | | +| `new` expression | Partial | | +| Member initializer list | Partial | | +| Delegating constructors | Partial | | +| Inherited constructors | Partial | | +| Return value implicit construction | Supported | | +| Lambda init-capture | Unsupported | | +| Overloaded operators | Supported | | +| C++20 rewritten operators | Supported | | +| User-defined literals | Unsupported | | +| Implicit conversion operators | Unsupported | [clangd#1931](https://github.com/clangd/clangd/issues/1931) | +| Casts invoking a constructor or conversion operator | Partial | | +| Range-based for | Unsupported | | +| Structured bindings | Unsupported | | +| `co_await` / `co_yield` / `co_return` | Partial | | + +### `override` / `final` + +Navigate to the overridden base method + +Go-to-definition on the `override` or `final` specifier should reach the +base class virtual method it overrides; today it returns nothing. + +```cpp +struct Base { + virtual void draw(); + virtual void paint(); +}; + +struct Derived : Base { + void draw() override; // go-to-def on override → Base::draw + void paint() final; // go-to-def on final → Base::paint +}; +``` + +### `break` / `continue` + +Navigate to the enclosing loop or switch head + +Go-to-definition on `break` or `continue` should reach the head of the +loop or switch it controls; today it returns nothing. + +```cpp +void loop() { + for (int i = 0; i < 10; i += 1) { + if (i == 5) break; // go-to-def on break → the for loop + continue; // go-to-def on continue → the for loop + } +} +``` + +### Constructor calls + +From parentheses or braces to the selected constructor + +Go-to-definition on the opening parenthesis or brace of a constructor +call reaches the constructor overload resolution selected, for both the +`T(args)` and `T{args}` forms. + +```cpp +struct Widget { + Widget(int w, int h); +}; + +void build() { + Widget a(800, 600); + Widget b{800, 600}; +} +``` + +### Copy/move construction and assignment + +To the constructor or assignment operator + +Go-to-definition on the `=` of an assignment reaches the assignment +operator. The `=` that introduces a copy- or move-initialization +(`T b = a;`) is initialization syntax rather than an operator call and is +not yet resolved. + +```cpp +struct Widget { + Widget(int v); + Widget(const Widget& other); + Widget(Widget&& other); + Widget& operator=(const Widget& other); +}; + +void copies(Widget a) { + Widget b = a; + Widget c = static_cast(a); + b = c; +} +``` + +### CTAD + +Navigate to the selected constructor + +When class template argument deduction picks a specialization, go-to- +definition on the constructor call reaches the constructor that was +selected, not merely the class template. + +```cpp +template +struct Box { + Box(T input) : value(input) {} + T value; +}; - When class template argument deduction picks a specialization, go-to- - definition on the constructor call reaches the constructor that was - selected, not merely the class template. +template +Box(T) -> Box; -
- Example +void use() { + Box b(7); +} +``` - ```cpp - template - struct Box { - Box(T input) : value(input) {} - T value; - }; +### Aggregate initialization - template - Box(T) -> Box; +Navigate to the struct definition - void use() { - Box b(7); - } - ``` +An aggregate has no constructor, so go-to-definition on its initializer +brace reaches the aggregate's definition. -
+```cpp +struct Point { + int x; + int y; +}; -- [x] Aggregate initialization — navigate to the struct definition +void use() { + auto p = Point{1, 2}; +} +``` - An aggregate has no constructor, so go-to-definition on its initializer - brace reaches the aggregate's definition. +### `delete` expression -
- Example +Navigate to the destructor - ```cpp - struct Point { - int x; - int y; - }; +Go-to-definition on `delete` should reach the destructor it runs; today +it returns nothing. - void use() { - auto p = Point{1, 2}; - } - ``` +```cpp +struct Widget { + ~Widget(); +}; -
+void dispose(Widget* widget) { + delete widget; // go-to-def on delete → Widget::~Widget +} +``` -- [ ] `delete` expression — navigate to the destructor +### `new` expression - Go-to-definition on `delete` should reach the destructor it runs; today - it returns nothing. +Navigate to the constructor and overloaded `operator new` -
- Example +Go-to-definition on `new` reaches the class's overloaded `operator new`. +The constructor invoked by the same expression is not part of the reply. - ```cpp - struct Widget { - ~Widget(); - }; +```cpp +struct Pool { + Pool(); + static void* operator new(decltype(sizeof(0)) size); +}; - void dispose(Widget* widget) { - delete widget; // go-to-def on delete → Widget::~Widget - } - ``` +void make() { + Pool* p = new Pool(); +} +``` -
+### Member initializer list -- [ ] `new` expression — navigate to the constructor and overloaded `operator new` _(partial)_ +Navigate to base and member constructors - Go-to-definition on `new` reaches the class's overloaded `operator new`. - The constructor invoked by the same expression is not part of the reply. +The base and member constructors run by an initializer list are reached +from the opening parenthesis of each initializer. The initializer name +itself resolves to the base type or the member, so navigation to the +constructor goes through the parenthesis. -
- Example +```cpp +struct Base { + Base(int x); +}; - ```cpp - struct Pool { - Pool(); - static void* operator new(decltype(sizeof(0)) size); - }; +struct Logger { + Logger(int level); +}; - void make() { - Pool* p = new Pool(); - } - ``` +struct App : Base { + Logger logger; + App() : Base(42), logger(1) {} +}; +``` -
+### Delegating constructors -- [ ] Member initializer list — navigate to base and member constructors _(partial)_ +Navigate to the target constructor - The base and member constructors run by an initializer list are reached - from the opening parenthesis of each initializer. The initializer name - itself resolves to the base type or the member, so navigation to the - constructor goes through the parenthesis. +A delegating constructor's target is reached from the opening parenthesis +of the delegated call. The constructor name itself resolves to the class +type, so navigation to the target constructor goes through the +parenthesis. -
- Example +```cpp +struct Widget { + Widget(int w, int h); + Widget() : Widget(0, 0) {} +}; +``` - ```cpp - struct Base { - Base(int x); - }; +### Inherited constructors - struct Logger { - Logger(int level); - }; +Navigate to the base constructors brought in by `using` - struct App : Base { - Logger logger; - App() : Base(42), logger(1) {} - }; - ``` +Go-to-definition on an inherited-constructor declaration +(`using Base::Base;`) reaches a base constructor. When the base declares +several constructors the reply resolves to one of them rather than +listing the whole set. -
+```cpp +struct Base { + Base(int x); + Base(int x, int y); +}; + +struct Derived : Base { + using Base::Base; +}; +``` -- [ ] Delegating constructors — navigate to the target constructor _(partial)_ +### Return value implicit construction - A delegating constructor's target is reached from the opening parenthesis - of the delegated call. The constructor name itself resolves to the class - type, so navigation to the target constructor goes through the - parenthesis. +Navigate to the constructor -
- Example +A braced `return {args}` implicitly constructs the function's return +type; go-to-definition on the brace reaches the selected constructor. - ```cpp - struct Widget { - Widget(int w, int h); - Widget() : Widget(0, 0) {} - }; - ``` +```cpp +struct Widget { + Widget(int w, int h); +}; -
+Widget create() { + return {800, 600}; +} +``` -- [ ] Inherited constructors — navigate to the base constructors brought in by `using` _(partial)_ +### Lambda init-capture - Go-to-definition on an inherited-constructor declaration - (`using Base::Base;`) reaches a base constructor. When the base declares - several constructors the reply resolves to one of them rather than - listing the whole set. +Navigate to the constructor -
- Example +Go-to-definition on the `=` of a lambda init-capture should reach the +constructor that builds the captured value; today it returns nothing. - ```cpp - struct Base { - Base(int x); - Base(int x, int y); - }; +```cpp +struct Widget { + Widget(int v); + Widget(Widget&& other); +}; + +void use(Widget w) { + // go-to-def on = → Widget(Widget&&) + auto f = [x = static_cast(w)] {}; +} +``` - struct Derived : Base { - using Base::Base; - }; - ``` +### Overloaded operators -
+From the operator token to its definition -- [x] Return value implicit construction — navigate to the constructor +Go-to-definition on an overloaded operator token reaches the operator's +definition. The binary, subscript, call and arrow operators (`+`, `[]`, +`()`, `->`) are all resolved. + +```cpp +struct Iterator { + int value; +}; - A braced `return {args}` implicitly constructs the function's return - type; go-to-definition on the brace reaches the selected constructor. +struct Vec { + Vec operator+(const Vec& other) const; + int operator[](int index) const; + int operator()(int a, int b) const; + Iterator* operator->(); +}; + +void use(Vec a, Vec b) { + Vec c = a + b; + int e = a[0]; + int f = a(1, 2); + a->value; +} +``` -
- Example +### C++20 rewritten operators - ```cpp - struct Widget { - Widget(int w, int h); - }; +Navigate to the operator the rewrite uses + +For a comparison synthesized by the C++20 rewrite rules, go-to-definition +on the written operator reaches the operator that actually implements it: +`!=` reaches `operator==`, and `>` reaches `operator<=>`. + +```cpp +namespace std { +struct strong_ordering { + int n; + constexpr operator int() const { return n; } + static const strong_ordering equal, greater, less; +}; +constexpr strong_ordering strong_ordering::equal = {0}; +constexpr strong_ordering strong_ordering::greater = {1}; +constexpr strong_ordering strong_ordering::less = {-1}; +} - Widget create() { - return {800, 600}; - } - ``` +struct S { + int value; + bool operator==(const S& other) const; + auto operator<=>(const S& other) const = default; +}; + +void use(S a, S b) { + bool ne = a != b; + bool gt = a > b; +} +``` + +### User-defined literals -
+Navigate to the literal operator -- [ ] Lambda init-capture — navigate to the constructor +Go-to-definition on a user-defined-literal suffix should reach its +`operator""`; today it returns nothing. - Go-to-definition on the `=` of a lambda init-capture should reach the - constructor that builds the captured value; today it returns nothing. - -
- Example - - ```cpp - struct Widget { - Widget(int v); - Widget(Widget&& other); - }; - - void use(Widget w) { - // go-to-def on = → Widget(Widget&&) - auto f = [x = static_cast(w)] {}; - } - ``` - -
- -- [x] Overloaded operators — from the operator token to its definition - - Go-to-definition on an overloaded operator token reaches the operator's - definition. The binary, subscript, call and arrow operators (`+`, `[]`, - `()`, `->`) are all resolved. - -
- Example - - ```cpp - struct Iterator { - int value; - }; - - struct Vec { - Vec operator+(const Vec& other) const; - int operator[](int index) const; - int operator()(int a, int b) const; - Iterator* operator->(); - }; - - void use(Vec a, Vec b) { - Vec c = a + b; - int e = a[0]; - int f = a(1, 2); - a->value; - } - ``` - -
- -- [x] C++20 rewritten operators — navigate to the operator the rewrite uses - - For a comparison synthesized by the C++20 rewrite rules, go-to-definition - on the written operator reaches the operator that actually implements it: - `!=` reaches `operator==`, and `>` reaches `operator<=>`. - -
- Example - - ```cpp - namespace std { - struct strong_ordering { - int n; - constexpr operator int() const { return n; } - static const strong_ordering equal, greater, less; - }; - constexpr strong_ordering strong_ordering::equal = {0}; - constexpr strong_ordering strong_ordering::greater = {1}; - constexpr strong_ordering strong_ordering::less = {-1}; - } - - struct S { - int value; - bool operator==(const S& other) const; - auto operator<=>(const S& other) const = default; - }; - - void use(S a, S b) { - bool ne = a != b; - bool gt = a > b; - } - ``` - -
- -- [ ] User-defined literals — navigate to the literal operator - - Go-to-definition on a user-defined-literal suffix should reach its - `operator""`; today it returns nothing. - -
- Example - - ```cpp - struct Duration { - unsigned long long ticks; - }; - - Duration operator""_ms(unsigned long long value); - - void use() { - Duration d = 500_ms; // go-to-def on _ms → operator""_ms - } - ``` - -
- -- [ ] Implicit conversion operators — from a conversion context to the operator ([clangd#1931](https://github.com/clangd/clangd/issues/1931)) - - Go-to-definition from a context that runs a user-defined conversion (a - condition, `!`, an explicit `bool(...)`) should reach the conversion - operator; today it returns nothing. - -
- Example - - ```cpp - struct Guard { - explicit operator bool() const; - }; - - void use(Guard g) { - if (g) {} // go-to-def on ( → Guard::operator bool - bool ok = !g; // go-to-def on ! → Guard::operator bool - } - ``` - -
- -- [ ] Casts invoking a constructor or conversion operator _(partial)_ - - A `static_cast` that constructs its target reaches the selected - constructor. A `static_cast` that runs a user-defined conversion operator - does not yet reach the operator. - -
- Example - - ```cpp - struct Meters { - explicit operator double() const; - }; - - struct Foo { - explicit Foo(int value); - }; - - void use(Meters m) { - double d = static_cast(m); - Foo f = static_cast(42); - } - ``` - -
- -- [ ] Range-based for — navigate to `begin()` / `end()` - - Go-to-definition on the `:` of a range-based for should reach the - `begin()` / `end()` chosen for the range; today it returns nothing. - -
- Example - - ```cpp - struct Iterator { - int operator*() const; - Iterator& operator++(); - bool operator!=(const Iterator& other) const; - }; - - struct Range { - Iterator begin(); - Iterator end(); - }; - - void use(Range r) { - for (int x : r) {} // go-to-def on : → Range::begin / Range::end - } - ``` - -
- -- [ ] Structured bindings — navigate to the underlying accessors or fields - - Go-to-definition on a structured binding name resolves to the binding - itself rather than the underlying field or accessor it names. - -
- Example - - ```cpp - struct Pair { - int first; - int second; - }; - - void use(Pair p) { - // go-to-def on a → Pair::first, on b → Pair::second - auto [a, b] = p; - } - ``` - -
- -- [ ] `co_await` / `co_yield` / `co_return` — navigate to the awaiter or promise method _(partial)_ - - Go-to-definition on `co_yield` reaches the promise's `yield_value`. The - `co_await` and `co_return` keywords do not yet reach the awaiter's or - promise's methods. - -
- Example - - ```cpp - namespace std { - template - struct coroutine_traits { - using promise_type = typename Ret::promise_type; - }; - template - struct coroutine_handle { - coroutine_handle() = default; - template - coroutine_handle(coroutine_handle) noexcept; - static coroutine_handle from_address(void*) noexcept; - }; - struct suspend_never { - bool await_ready() const noexcept; - void await_suspend(coroutine_handle<>) const noexcept; - void await_resume() const noexcept; - }; - } - - struct Awaiter { - bool await_ready() const noexcept; - void await_suspend(std::coroutine_handle<>) const noexcept; - int await_resume() const noexcept; - }; - - struct Task { - struct promise_type { - Task get_return_object(); - std::suspend_never initial_suspend(); - std::suspend_never final_suspend() noexcept; - Awaiter yield_value(int value); - void return_value(int value); - void unhandled_exception(); - }; - }; - - Task example() { - co_await Awaiter{}; - co_yield 1; - co_return 2; - } - ``` - -
+```cpp +struct Duration { + unsigned long long ticks; +}; + +Duration operator""_ms(unsigned long long value); + +void use() { + Duration d = 500_ms; // go-to-def on _ms → operator""_ms +} +``` + +### Implicit conversion operators + +From a conversion context to the operator + +Go-to-definition from a context that runs a user-defined conversion (a +condition, `!`, an explicit `bool(...)`) should reach the conversion +operator; today it returns nothing. + +```cpp +struct Guard { + explicit operator bool() const; +}; + +void use(Guard g) { + if (g) {} // go-to-def on ( → Guard::operator bool + bool ok = !g; // go-to-def on ! → Guard::operator bool +} +``` + +### Casts invoking a constructor or conversion operator + +A `static_cast` that constructs its target reaches the selected +constructor. A `static_cast` that runs a user-defined conversion operator +does not yet reach the operator. + +```cpp +struct Meters { + explicit operator double() const; +}; + +struct Foo { + explicit Foo(int value); +}; + +void use(Meters m) { + double d = static_cast(m); + Foo f = static_cast(42); +} +``` + +### Range-based for + +Navigate to `begin()` / `end()` + +Go-to-definition on the `:` of a range-based for should reach the +`begin()` / `end()` chosen for the range; today it returns nothing. + +```cpp +struct Iterator { + int operator*() const; + Iterator& operator++(); + bool operator!=(const Iterator& other) const; +}; + +struct Range { + Iterator begin(); + Iterator end(); +}; + +void use(Range r) { + for (int x : r) {} // go-to-def on : → Range::begin / Range::end +} +``` + +### Structured bindings + +Navigate to the underlying accessors or fields + +Go-to-definition on a structured binding name resolves to the binding +itself rather than the underlying field or accessor it names. + +```cpp +struct Pair { + int first; + int second; +}; + +void use(Pair p) { + // go-to-def on a → Pair::first, on b → Pair::second + auto [a, b] = p; +} +``` + +### `co_await` / `co_yield` / `co_return` + +Navigate to the awaiter or promise method + +Go-to-definition on `co_yield` reaches the promise's `yield_value`. The +`co_await` and `co_return` keywords do not yet reach the awaiter's or +promise's methods. + +```cpp +namespace std { +template +struct coroutine_traits { + using promise_type = typename Ret::promise_type; +}; +template +struct coroutine_handle { + coroutine_handle() = default; + template + coroutine_handle(coroutine_handle) noexcept; + static coroutine_handle from_address(void*) noexcept; +}; +struct suspend_never { + bool await_ready() const noexcept; + void await_suspend(coroutine_handle<>) const noexcept; + void await_resume() const noexcept; +}; +} + +struct Awaiter { + bool await_ready() const noexcept; + void await_suspend(std::coroutine_handle<>) const noexcept; + int await_resume() const noexcept; +}; + +struct Task { + struct promise_type { + Task get_return_object(); + std::suspend_never initial_suspend(); + std::suspend_never final_suspend() noexcept; + Awaiter yield_value(int value); + void return_value(int value); + void unhandled_exception(); + }; +}; + +Task example() { + co_await Awaiter{}; + co_yield 1; + co_return 2; +} +``` @@ -849,314 +765,288 @@ Navigate from a symbol usage or definition to its declaration. In C++, many enti clice returns the declaration locations plus the definition — symbols defined inline have no separate declaration — minus the site the cursor already stands on, so declaration and definition sites alternate just like go-to-definition. - - -- [x] Cross-TU go-to-declaration - - Go-to-declaration on a use resolves sites in other files: the - prototype lives in a shared header and the out-of-line definition in a - sibling source, and both are offered from a use in another file. - -
- Example - - `main.cpp`: - - ```cpp - #include "shared.h" + - int run(int value) { - return scale(value); - } - ``` +| Capability | Status | Issues | +| ----------------------------------------------------------------- | --------- | ------ | +| Cross-TU go-to-declaration | Supported | | +| Functions | Supported | | +| Forward declarations of classes and structs | Supported | | +| Static data member | Supported | | +| `extern` variable | Supported | | +| Multiple declarations | Supported | | +| Declaration and definition with cosmetically different signatures | Supported | | - `lib.cpp`: +### Cross-TU go-to-declaration - ```cpp - #include "shared.h" +Go-to-declaration on a use resolves sites in other files: the +prototype lives in a shared header and the out-of-line definition in a +sibling source, and both are offered from a use in another file. - int scale(int value) { - return value * 2; - } - ``` +`main.cpp`: - `shared.h`: +```cpp +#include "shared.h" - ```cpp - #pragma once +int run(int value) { + return scale(value); +} +``` - int scale(int value); - ``` +`lib.cpp`: -
+```cpp +#include "shared.h" -- [x] Functions — from a use or out-of-line definition to the prototype +int scale(int value) { + return value * 2; +} +``` - Go-to-declaration reaches a function's prototype both from a call site - and from the out-of-line definition — the two non-cursor sites the - prototype alternates with. +`shared.h`: -
- Example +```cpp +#pragma once - ```cpp - struct Widget { - void draw(); - }; +int scale(int value); +``` - void Widget::draw() {} +### Functions - void render(Widget& widget) { - widget.draw(); - } - ``` +From a use or out-of-line definition to the prototype -
+Go-to-declaration reaches a function's prototype both from a call site +and from the out-of-line definition — the two non-cursor sites the +prototype alternates with. -- [x] Forward declarations of classes and structs +```cpp +struct Widget { + void draw(); +}; - A class with a forward declaration and a later definition offers both - from a use — the forward declaration stays part of the declaration set - rather than being dropped in favour of the definition. +void Widget::draw() {} -
- Example +void render(Widget& widget) { + widget.draw(); +} +``` - ```cpp - struct Widget; +### Forward declarations of classes and structs - struct Widget { - int value; - }; +A class with a forward declaration and a later definition offers both +from a use — the forward declaration stays part of the declaration set +rather than being dropped in favour of the definition. - class Panel; +```cpp +struct Widget; - class Panel { - int width; - }; +struct Widget { + int value; +}; - int probe(Widget& widget, Panel& panel) { - return widget.value; - } - ``` +class Panel; -
+class Panel { + int width; +}; -- [x] Static data member — to the in-class declaration +int probe(Widget& widget, Panel& panel) { + return widget.value; +} +``` - A static data member is declared inside the class and defined out of - line; go-to-declaration on a use offers the in-class declaration - alongside the definition. +### Static data member -
- Example +To the in-class declaration - ```cpp - struct Config { - static int timeout; - }; +A static data member is declared inside the class and defined out of +line; go-to-declaration on a use offers the in-class declaration +alongside the definition. - int Config::timeout = 30; +```cpp +struct Config { + static int timeout; +}; - int read_config() { - return Config::timeout; - } - ``` +int Config::timeout = 30; -
+int read_config() { + return Config::timeout; +} +``` -- [x] `extern` variable — to the declaration +### `extern` variable - A use of an `extern` variable offers the `extern` declaration and - the defining declaration together, so the header-side declaration is - always reachable from a use. +To the declaration -
- Example +A use of an `extern` variable offers the `extern` declaration and +the defining declaration together, so the header-side declaration is +always reachable from a use. - ```cpp - extern int log_level; +```cpp +extern int log_level; - int log_level = 0; +int log_level = 0; - int read_level() { - return log_level; - } - ``` +int read_level() { + return log_level; +} +``` -
+### Multiple declarations -- [x] Multiple declarations — every declaration site +Every declaration site - When an entity is declared in several places, go-to-declaration on a - use lists every declaration site, not only the nearest one. +When an entity is declared in several places, go-to-declaration on a +use lists every declaration site, not only the nearest one. -
- Example +```cpp +int clamp(int value); +int clamp(int value); - ```cpp - int clamp(int value); - int clamp(int value); +int clamp(int value) { + return value < 0 ? 0 : value; +} - int clamp(int value) { - return value < 0 ? 0 : value; - } +int hold(int value) { + return clamp(value); +} +``` - int hold(int value) { - return clamp(value); - } - ``` +### Declaration and definition with cosmetically different signatures -
+Parameter names, and a top-level `const` on a parameter, are not part +of a function's type: the declaration and the definition below spell the +same function differently, yet go-to-declaration still connects a use to +the prototype. -- [x] Declaration and definition with cosmetically different signatures +```cpp +int render(int width, const int height); - Parameter names, and a top-level `const` on a parameter, are not part - of a function's type: the declaration and the definition below spell the - same function differently, yet go-to-declaration still connects a use to - the prototype. +int render(int w, int h) { + return w * h; +} -
- Example - - ```cpp - int render(int width, const int height); - - int render(int w, int h) { - return w * h; - } - - int use_render() { - return render(800, 600); - } - ``` - -
+int use_render() { + return render(800, 600); +} +``` ## Go to Implementation - - -- [x] Virtual methods — each level of a chain to its own overriders - - Along a three-level override chain, go-to-implementation from each method - reaches the override one level down — base to middle, middle to leaf. + -
- Example +| Capability | Status | Issues | +| ----------------------------- | ----------- | --------------------------------------------------------- | +| Override chain | Supported | | +| Sibling overrides | Supported | | +| Non-virtual function | Unsupported | [clangd#854](https://github.com/clangd/clangd/issues/854) | +| Base class | Supported | | +| Template duck-type navigation | Unsupported | | - ```cpp - struct Base { - virtual void run() = 0; - }; +### Override chain - struct Middle : Base { - void run() override {} - }; +Each level of a chain to its own overriders - struct Leaf : Middle { - void run() override {} - }; - ``` +Along a three-level override chain, go-to-implementation from each method +reaches the override one level down — base to middle, middle to leaf. -
+```cpp +struct Base { + virtual void run() = 0; +}; -- [x] Virtual method — every sibling override +struct Middle : Base { + void run() override {} +}; - Go-to-implementation on a virtual method lists every override across - the sibling derived classes. +struct Leaf : Middle { + void run() override {} +}; +``` -
- Example +### Sibling overrides - ```cpp - struct Shape { - virtual int area() = 0; - }; +Every sibling override - struct Circle : Shape { - int area() override { return 1; } - }; +Go-to-implementation on a virtual method lists every override across +the sibling derived classes. - struct Square : Shape { - int area() override { return 2; } - }; +```cpp +struct Shape { + virtual int area() = 0; +}; - struct Triangle : Shape { - int area() override { return 3; } - }; - ``` +struct Circle : Shape { + int area() override { return 1; } +}; -
+struct Square : Shape { + int area() override { return 2; } +}; -- [ ] Non-virtual function — declaration to out-of-line definition ([clangd#854](https://github.com/clangd/clangd/issues/854)) +struct Triangle : Shape { + int area() override { return 3; } +}; +``` - Go-to-implementation on a non-virtual function declaration should reach - its out-of-line definition, behaving as a superset of go-to-definition; - today it returns nothing. +### Non-virtual function -
- Example +Declaration to out-of-line definition - ```cpp - struct Widget { - void draw(); // go-to-impl on draw → out-of-line definition below - }; +Go-to-implementation on a non-virtual function declaration should reach +its out-of-line definition, behaving as a superset of go-to-definition; +today it returns nothing. - void Widget::draw() {} - ``` +```cpp +struct Widget { + void draw(); // go-to-impl on draw → out-of-line definition below +}; -
+void Widget::draw() {} +``` -- [x] Base class — every derived class +### Base class - Go-to-implementation on a base class name lists the classes that derive - from it. +Every derived class -
- Example +Go-to-implementation on a base class name lists the classes that derive +from it. - ```cpp - struct Base {}; +```cpp +struct Base {}; - struct Circle : Base {}; +struct Circle : Base {}; - struct Square : Base {}; - ``` +struct Square : Base {}; +``` -
+### Template duck-type navigation -- [ ] Template duck-type navigation +From a dependent member call, go-to-implementation should list the +concrete methods of every known instantiation; the same applies to a +generic lambda's dependent calls. Today it returns nothing. - From a dependent member call, go-to-implementation should list the - concrete methods of every known instantiation; the same applies to a - generic lambda's dependent calls. Today it returns nothing. +```cpp +template +void process(T& obj) { + obj.foo(); // go-to-impl on foo → A::foo (from the process(a) instantiation) +} -
- Example +struct A { + void foo() {} +}; - ```cpp - template - void process(T& obj) { - obj.foo(); // go-to-impl on foo → A::foo (from the process(a) instantiation) - } +void run(A a) { + process(a); +} - struct A { - void foo() {} - }; - - void run(A a) { - process(a); - } - - void generic() { - auto call = [](auto& x) { x.bar(); }; // go-to-impl on bar → the concrete bar - } - ``` - -
+void generic() { + auto call = [](auto& x) { x.bar(); }; // go-to-impl on bar → the concrete bar +} +``` @@ -1164,758 +1054,648 @@ clice returns the declaration locations plus the definition — symbols defined Navigate to the type definition of a symbol. Applicable to variables, parameters, fields, and any other named entity that has a type. When the type is a type alias or a pointer-like wrapper, navigation should unwrap to the underlying/pointee type. - - -- [x] Variables and parameters - - Go-to-type-definition on a local variable or a parameter reaches the - definition of its type. + -
- Example +| Capability | Status | Issues | +| --------------------------------- | ----------- | ----------------------------------------------------------- | +| Variables and parameters | Supported | | +| Class and struct fields | Supported | | +| `auto`-deduced variables | Unsupported | | +| Smart pointer to the pointee type | Partial | [clangd#1026](https://github.com/clangd/clangd/issues/1026) | +| Type aliases | Partial | | +| Structured binding variables | Supported | | - ```cpp - struct Widget {}; +### Variables and parameters - Widget make_widget(); +Go-to-type-definition on a local variable or a parameter reaches the +definition of its type. - int probe(Widget param) { - Widget local = make_widget(); - return 0; - } - ``` +```cpp +struct Widget {}; -
+Widget make_widget(); -- [x] Class and struct fields +int probe(Widget param) { + Widget local = make_widget(); + return 0; +} +``` - Go-to-type-definition on a field access reaches the definition of the - field's type. +### Class and struct fields -
- Example +Go-to-type-definition on a field access reaches the definition of the +field's type. - ```cpp - struct Logger {}; +```cpp +struct Logger {}; - class Store {}; +class Store {}; - struct App { - Logger logger; - Store store; - }; +struct App { + Logger logger; + Store store; +}; - int use(App& app) { - app.logger; - app.store; - return 0; - } - ``` +int use(App& app) { + app.logger; + app.store; + return 0; +} +``` -
+### `auto`-deduced variables -- [ ] `auto`-deduced variables +Go-to-type-definition on an `auto`-deduced variable should reach the +deduced type's definition; today the variable carries no type relation, +so it returns nothing. - Go-to-type-definition on an `auto`-deduced variable should reach the - deduced type's definition; today the variable carries no type relation, - so it returns nothing. +```cpp +struct Widget {}; -
- Example +Widget make_widget(); - ```cpp - struct Widget {}; +void probe() { + auto widget = make_widget(); // go-to-type-def on widget → Widget +} +``` - Widget make_widget(); +### Smart pointer to the pointee type - void probe() { - auto widget = make_widget(); // go-to-type-def on widget → Widget - } - ``` +Go-to-type-definition on a smart-pointer variable reaches the wrapper +type itself; unwrapping to the pointee type is not offered. -
+```cpp +template +struct Ptr { + T* operator->(); + T& operator*(); + T* raw; +}; -- [ ] Smart pointer to the pointee type _(partial)_ ([clangd#1026](https://github.com/clangd/clangd/issues/1026)) +struct Widget {}; - Go-to-type-definition on a smart-pointer variable reaches the wrapper - type itself; unwrapping to the pointee type is not offered. +int use(Ptr ptr) { + return 0; +} +``` -
- Example +### Type aliases - ```cpp - template - struct Ptr { - T* operator->(); - T& operator*(); - T* raw; - }; +Go-to-type-definition on a variable of an aliased type reaches the +`using` or `typedef` declaration; it does not yet unwrap the alias to +the underlying type's definition. - struct Widget {}; +```cpp +struct Impl {}; - int use(Ptr ptr) { - return 0; - } - ``` +using Handle = Impl; -
+typedef Impl LegacyHandle; -- [ ] Type aliases _(partial)_ +int use(Handle handle, LegacyHandle legacy) { + return 0; +} +``` - Go-to-type-definition on a variable of an aliased type reaches the - `using` or `typedef` declaration; it does not yet unwrap the alias to - the underlying type's definition. +### Structured binding variables -
- Example +Go-to-type-definition on a structured binding reaches the definition of +the bound member's type. - ```cpp - struct Impl {}; +```cpp +struct Widget {}; - using Handle = Impl; +struct Pair { + Widget first; + int second; +}; - typedef Impl LegacyHandle; +Pair make_pair(); - int use(Handle handle, LegacyHandle legacy) { - return 0; - } - ``` - -
- -- [x] Structured binding variables - - Go-to-type-definition on a structured binding reaches the definition of - the bound member's type. - -
- Example - - ```cpp - struct Widget {}; - - struct Pair { - Widget first; - int second; - }; - - Pair make_pair(); - - int use() { - auto [widget, count] = make_pair(); - return 0; - } - ``` - -
+int use() { + auto [widget, count] = make_pair(); + return 0; +} +``` ## Find References - - -- [x] Cross-TU find references - - Find references gathers uses from other files too: a function - defined in one source and called from a sibling reports both call - sites together with the declaration in the shared header, not only the - uses in the current file. - -
- Example - - `main.cpp`: - - ```cpp - #include "shared.h" - - int run(int value) { - return compute(value); - } - ``` - - `lib.cpp`: - - ```cpp - #include "shared.h" - - int compute(int value) { - return value * 2; - } - - int again(int value) { - return compute(value) + 1; - } - ``` - - `shared.h`: - - ```cpp - #pragma once - - int compute(int value); - ``` - -
+ -- [x] Declaration and definition sites appear among references +| Capability | Status | Issues | +| ------------------------------------------------------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------- | +| Cross-TU find references | Supported | | +| Declaration and definition sites appear among references | Supported | | +| Implicit references from range-based for loops | Unsupported | [clangd#1081](https://github.com/clangd/clangd/issues/1081) | +| Implicit constructor and destructor calls | Unsupported | | +| References through forwarding functions | Unsupported | [clangd#716](https://github.com/clangd/clangd/issues/716), [clangd#1872](https://github.com/clangd/clangd/issues/1872) | +| References in dependent and template contexts | Unsupported | [clangd#258](https://github.com/clangd/clangd/issues/258), [clangd#675](https://github.com/clangd/clangd/issues/675) | +| Read/write classification of references | Unsupported | [clangd#2139](https://github.com/clangd/clangd/issues/2139) | +| Enclosing function shown with each reference | Unsupported | [clangd#177](https://github.com/clangd/clangd/issues/177) | +| Macro references across expansions, `#ifdef`/`#ifndef` and `#undef` | Supported | | +| Macro references spelled inside other macro definitions | Unsupported | [clangd#346](https://github.com/clangd/clangd/issues/346) | +| Label and goto references | Supported | | - A reference query returns the declaration and the out-of-line - definition together with every use, so the whole surface of a symbol - is reachable from any one of its sites. +### Cross-TU find references -
- Example +Find references gathers uses from other files too: a function +defined in one source and called from a sibling reports both call +sites together with the declaration in the shared header, not only the +uses in the current file. - ```cpp - int scale(int value); +`main.cpp`: - int scale(int value) { - return value * 2; - } +```cpp +#include "shared.h" - int use() { - return scale(3); - } - ``` +int run(int value) { + return compute(value); +} +``` -
+`lib.cpp`: -- [ ] Implicit references from range-based for loops ([clangd#1081](https://github.com/clangd/clangd/issues/1081)) +```cpp +#include "shared.h" - Find references on `begin` reports only its own declaration; the - range-based for loop that implicitly calls it is not included among the - references. +int compute(int value) { + return value * 2; +} -
- Example +int again(int value) { + return compute(value) + 1; +} +``` - ```cpp - struct Iterator { - int operator*() const; - Iterator& operator++(); - bool operator!=(const Iterator& other) const; - }; +`shared.h`: - struct Range { - Iterator begin(); // find-refs here omits the range-for below - Iterator end(); - }; +```cpp +#pragma once - void use(Range r) { - for (int x : r) { - } - } - ``` +int compute(int value); +``` -
+### Declaration and definition sites appear among references -- [ ] Implicit constructor and destructor calls +A reference query returns the declaration and the out-of-line +definition together with every use, so the whole surface of a symbol +is reachable from any one of its sites. - Find references on a constructor reports only its explicit sites; an - object definition that implicitly invokes the constructor or its - destructor is not included. +```cpp +int scale(int value); -
- Example +int scale(int value) { + return value * 2; +} + +int use() { + return scale(3); +} +``` - ```cpp - struct Blob { - Blob(); // find-refs here omits the `Blob b;` definition below - ~Blob(); - }; +### Implicit references from range-based for loops + +Find references on `begin` reports only its own declaration; the +range-based for loop that implicitly calls it is not included among the +references. - void use() { - Blob b; - } - ``` +```cpp +struct Iterator { + int operator*() const; + Iterator& operator++(); + bool operator!=(const Iterator& other) const; +}; -
+struct Range { + Iterator begin(); // find-refs here omits the range-for below + Iterator end(); +}; -- [ ] References through forwarding functions ([clangd#716](https://github.com/clangd/clangd/issues/716), [clangd#1872](https://github.com/clangd/clangd/issues/1872)) +void use(Range r) { + for (int x : r) { + } +} +``` - Find references on a constructor does not include call sites that reach - it indirectly through a perfect-forwarding factory. +### Implicit constructor and destructor calls -
- Example +Find references on a constructor reports only its explicit sites; an +object definition that implicitly invokes the constructor or its +destructor is not included. + +```cpp +struct Blob { + Blob(); // find-refs here omits the `Blob b;` definition below + ~Blob(); +}; - ```cpp - template - T make(Args&&... args) { - return T(static_cast(args)...); - } +void use() { + Blob b; +} +``` - struct Widget { - Widget(int w, int h); // find-refs here omits the make call - }; +### References through forwarding functions - Widget build() { - return make(800, 600); - } - ``` +Find references on a constructor does not include call sites that reach +it indirectly through a perfect-forwarding factory. -
+```cpp +template +T make(Args&&... args) { + return T(static_cast(args)...); +} -- [ ] References in dependent and template contexts ([clangd#258](https://github.com/clangd/clangd/issues/258), [clangd#675](https://github.com/clangd/clangd/issues/675)) +struct Widget { + Widget(int w, int h); // find-refs here omits the make call +}; - Find references on a member does not include dependent call sites in a - template, even when the template is instantiated with the member's - class. +Widget build() { + return make(800, 600); +} +``` -
- Example +### References in dependent and template contexts - ```cpp - struct A { - void foo(); // find-refs here omits the dependent obj.foo() below - }; +Find references on a member does not include dependent call sites in a +template, even when the template is instantiated with the member's +class. - template - void process(T& obj) { - obj.foo(); - } +```cpp +struct A { + void foo(); // find-refs here omits the dependent obj.foo() below +}; - void run(A a) { - process(a); - } - ``` +template +void process(T& obj) { + obj.foo(); +} -
+void run(A a) { + process(a); +} +``` -- [ ] Read/write classification of references ([clangd#2139](https://github.com/clangd/clangd/issues/2139)) +### Read/write classification of references - The reference reply carries only locations, so a reader cannot tell a - write from a read; annotating each result with its access kind is not - offered. +The reference reply carries only locations, so a reader cannot tell a +write from a read; annotating each result with its access kind is not +offered. -
- Example +```cpp +int use() { + int x = 0; // write + int y = x + 1; // read + x = y; // write + return x; +} +``` - ```cpp - int use() { - int x = 0; // write - int y = x + 1; // read - x = y; // write - return x; - } - ``` +### Enclosing function shown with each reference -
+Each reference is reported as a bare location; the name of the function +that encloses it is not attached, so results carry no context beyond +the file and line. -- [ ] Enclosing function shown with each reference ([clangd#177](https://github.com/clangd/clangd/issues/177)) +```cpp +int shared_value = 0; - Each reference is reported as a bare location; the name of the function - that encloses it is not attached, so results carry no context beyond - the file and line. +int reader() { + return shared_value; +} -
- Example +int writer() { + shared_value = 1; + return shared_value; +} +``` - ```cpp - int shared_value = 0; +### Macro references across expansions, `#ifdef`/`#ifndef` and `#undef` - int reader() { - return shared_value; - } +A macro's references span its expansions, the `#ifdef` / `#ifndef` +conditionals that test it and the `#undef` that cancels it. Each +`#define` of a name is its own symbol, so a redefinition after `#undef` +collects only its own uses. - int writer() { - shared_value = 1; - return shared_value; - } - ``` +```cpp +#define FEATURE 1 -
+int on = FEATURE; -- [x] Macro references across expansions, `#ifdef`/`#ifndef` and `#undef` +#ifdef FEATURE +int guarded = 1; +#endif - A macro's references span its expansions, the `#ifdef` / `#ifndef` - conditionals that test it and the `#undef` that cancels it. Each - `#define` of a name is its own symbol, so a redefinition after `#undef` - collects only its own uses. +#ifndef FEATURE +int missing = 0; +#endif -
- Example +#undef FEATURE - ```cpp - #define FEATURE 1 +#define FEATURE 2 - int on = FEATURE; +int again = FEATURE; +``` - #ifdef FEATURE - int guarded = 1; - #endif +### Macro references spelled inside other macro definitions - #ifndef FEATURE - int missing = 0; - #endif +Find references on a macro does not include the mentions of it written +inside the bodies of other macro definitions. - #undef FEATURE +```cpp +#define WIDTH 100 // find-refs here omits the WIDTH tokens in AREA below - #define FEATURE 2 +#define AREA (WIDTH * WIDTH) - int again = FEATURE; - ``` +int total = AREA; +``` -
+### Label and goto references -- [ ] Macro references spelled inside other macro definitions ([clangd#346](https://github.com/clangd/clangd/issues/346)) +Find references on a label lists the label itself together with every +`goto` that jumps to it. - Find references on a macro does not include the mentions of it written - inside the bodies of other macro definitions. - -
- Example - - ```cpp - #define WIDTH 100 // find-refs here omits the WIDTH tokens in AREA below - - #define AREA (WIDTH * WIDTH) - - int total = AREA; - ``` - -
- -- [x] Label and goto references - - Find references on a label lists the label itself together with every - `goto` that jumps to it. - -
- Example - - ```cpp - int loop(int failed) { - retry: - if (failed) { - goto retry; - } - return 0; - } - ``` - -
+```cpp +int loop(int failed) { + retry: + if (failed) { + goto retry; + } + return 0; +} +``` ## Call Hierarchy - - -- [x] Prepare call hierarchy on functions and methods - - Preparing a call hierarchy works on a free function and on a member - method alike, anchoring an item at the entity under the cursor. - -
- Example - - ```cpp - struct Service { - void start(); - }; - - void Service::start() {} - - void launch(Service& s) { - s.start(); - } - ``` - -
- -- [x] Incoming calls - - Incoming calls list every caller of a function, and a caller that - invokes it more than once contributes each call site. - -
- Example - - ```cpp - int helper(int v) { - return v; - } - - int alpha() { - return helper(1); - } - - int beta() { - return helper(2) + helper(3); - } - ``` + -
+| Capability | Status | Issues | +| ----------------------------------------------- | ----------- | ----------------------------------------------------------- | +| Prepare call hierarchy on functions and methods | Supported | | +| Incoming calls | Supported | | +| Outgoing calls | Supported | | +| Function signature in the item detail | Unsupported | | +| Qualified name for member functions | Partial | | +| Follow virtual dispatch | Unsupported | | +| Non-function targets | Unsupported | [clangd#1308](https://github.com/clangd/clangd/issues/1308) | +| Calls inside lambdas | Supported | | +| Constructor calls through forwarding functions | Unsupported | [clangd#2242](https://github.com/clangd/clangd/issues/2242) | -- [x] Outgoing calls +### Prepare call hierarchy on functions and methods - Outgoing calls list every function a body invokes, one entry per - callee. +Preparing a call hierarchy works on a free function and on a member +method alike, anchoring an item at the entity under the cursor. -
- Example +```cpp +struct Service { + void start(); +}; - ```cpp - int one() { - return 1; - } +void Service::start() {} - int two() { - return 2; - } +void launch(Service& s) { + s.start(); +} +``` - int three() { - return 3; - } +### Incoming calls - int dispatch() { - return one() + two() + three(); - } - ``` +Incoming calls list every caller of a function, and a caller that +invokes it more than once contributes each call site. -
+```cpp +int helper(int v) { + return v; +} -- [ ] Function signature in the item detail +int alpha() { + return helper(1); +} - A call hierarchy item carries only its name; the function signature is - not attached in a detail field, so overloads are indistinguishable in - the hierarchy. +int beta() { + return helper(2) + helper(3); +} +``` -
- Example +### Outgoing calls - ```cpp - int compute(int a, int b) { // no signature attached to this item - return a + b; - } +Outgoing calls list every function a body invokes, one entry per +callee. - int caller() { - return compute(1, 2); - } - ``` +```cpp +int one() { + return 1; +} -
+int two() { + return 2; +} -- [ ] Qualified name for member functions _(partial)_ +int three() { + return 3; +} - A member function's call hierarchy item is produced, but its name field - carries only the bare method name (`draw`), not the qualified - `Circle::draw` that would tell it apart from a free function. +int dispatch() { + return one() + two() + three(); +} +``` -
- Example +### Function signature in the item detail - ```cpp - struct Circle { - void draw(); - }; +A call hierarchy item carries only its name; the function signature is +not attached in a detail field, so overloads are indistinguishable in +the hierarchy. - void Circle::draw() {} - ``` +```cpp +int compute(int a, int b) { // no signature attached to this item + return a + b; +} -
+int caller() { + return compute(1, 2); +} +``` -- [ ] Follow virtual dispatch +### Qualified name for member functions - Incoming calls of a base virtual method do not include calls made - through derived overrides; a call to an override is attributed only to - that override, never to the base it overrides. +A member function's call hierarchy item is produced, but its name field +carries only the bare method name (`draw`), not the qualified +`Circle::draw` that would tell it apart from a free function. -
- Example +```cpp +struct Circle { + void draw(); +}; - ```cpp - struct Base { - virtual void draw(); - }; +void Circle::draw() {} +``` - struct Derived : Base { - void draw() override; - }; +### Follow virtual dispatch - void call_derived(Derived& d) { - d.draw(); // absent from the incoming calls of Base::draw - } - ``` +Incoming calls of a base virtual method do not include calls made +through derived overrides; a call to an override is attributed only to +that override, never to the base it overrides. -
+```cpp +struct Base { + virtual void draw(); +}; -- [ ] Non-function targets — variables and enum constants ([clangd#1308](https://github.com/clangd/clangd/issues/1308)) +struct Derived : Base { + void draw() override; +}; - Preparing a call hierarchy on a variable or an enum constant returns - nothing; the request is offered only for functions and methods. +void call_derived(Derived& d) { + d.draw(); // absent from the incoming calls of Base::draw +} +``` -
- Example +### Non-function targets - ```cpp - int counter = 0; // prepare call hierarchy here → nothing +Variables and enum constants - enum Mode { - Fast, // prepare call hierarchy here → nothing - Slow, - }; - ``` +Preparing a call hierarchy on a variable or an enum constant returns +nothing; the request is offered only for functions and methods. -
+```cpp +int counter = 0; // prepare call hierarchy here → nothing -- [x] Calls inside lambdas +enum Mode { + Fast, // prepare call hierarchy here → nothing + Slow, +}; +``` - A call written in a lambda body appears in the incoming calls of the - function it invokes, attributed to the function that encloses the - lambda. +### Calls inside lambdas -
- Example +A call written in a lambda body appears in the incoming calls of the +function it invokes, attributed to the function that encloses the +lambda. - ```cpp - void foo() {} +```cpp +void foo() {} - void use() { - auto task = [] { - foo(); - }; - task(); - } - ``` +void use() { + auto task = [] { + foo(); + }; + task(); +} +``` -
+### Constructor calls through forwarding functions -- [ ] Constructor calls through forwarding functions ([clangd#2242](https://github.com/clangd/clangd/issues/2242)) +Incoming calls of a constructor do not include the call sites that +reach it through a perfect-forwarding factory. - Incoming calls of a constructor do not include the call sites that - reach it through a perfect-forwarding factory. +```cpp +template +T make(Args&&... args) { + return T(static_cast(args)...); +} -
- Example +struct Widget { + Widget(int w, int h); // make below is absent from incoming calls +}; - ```cpp - template - T make(Args&&... args) { - return T(static_cast(args)...); - } - - struct Widget { - Widget(int w, int h); // make below is absent from incoming calls - }; - - Widget build() { - return make(800, 600); - } - ``` - -
+Widget build() { + return make(800, 600); +} +``` ## Type Hierarchy - - -- [x] Prepare type hierarchy on class, struct, enum and union - - Preparing a type hierarchy anchors an item on any user-defined type - tag — class, struct, enum and union alike. - -
- Example - - ```cpp - class Handle {}; - - struct Point {}; - - enum class Mode {}; - - union Storage { - int i; - float f; - }; - ``` - -
- -- [x] Supertypes + - Supertypes list every direct base of a class, including each base of a - multiple-inheritance derived type. +| Capability | Status | Issues | +| ------------------------------------------------------- | --------- | ------------------------------------------------------- | +| Prepare type hierarchy on class, struct, enum and union | Supported | | +| Supertypes | Supported | | +| Subtypes | Supported | | +| Template inheritance | Supported | | +| Template arguments in type hierarchy items | Partial | [clangd#31](https://github.com/clangd/clangd/issues/31) | -
- Example +### Prepare type hierarchy on class, struct, enum and union - ```cpp - struct Alpha {}; +Preparing a type hierarchy anchors an item on any user-defined type +tag — class, struct, enum and union alike. - struct Beta {}; +```cpp +class Handle {}; - struct Gamma : Alpha, Beta {}; - ``` +struct Point {}; -
+enum class Mode {}; -- [x] Subtypes +union Storage { + int i; + float f; +}; +``` - Subtypes list every class that derives from a base, across sibling - derived types. +### Supertypes -
- Example +Supertypes list every direct base of a class, including each base of a +multiple-inheritance derived type. - ```cpp - struct Shape {}; +```cpp +struct Alpha {}; - struct Circle : Shape {}; +struct Beta {}; - struct Square : Shape {}; +struct Gamma : Alpha, Beta {}; +``` - struct Triangle : Shape {}; - ``` +### Subtypes -
+Subtypes list every class that derives from a base, across sibling +derived types. -- [x] Template inheritance +```cpp +struct Shape {}; - Subtypes of a base include classes that derive from it through a class - template, such as a CRTP wrapper. +struct Circle : Shape {}; -
- Example +struct Square : Shape {}; - ```cpp - struct Base {}; +struct Triangle : Shape {}; +``` - template - struct CRTP : Base {}; +### Template inheritance - struct Widget : CRTP {}; - ``` +Subtypes of a base include classes that derive from it through a class +template, such as a CRTP wrapper. -
+```cpp +struct Base {}; -- [ ] Template arguments in type hierarchy items _(partial)_ ([clangd#31](https://github.com/clangd/clangd/issues/31)) +template +struct CRTP : Base {}; - A subtype produced by a class template specialization is listed, but - its item name carries only the bare template name (`Derived`), without - the template arguments that would distinguish `Derived`. +struct Widget : CRTP {}; +``` -
- Example +### Template arguments in type hierarchy items - ```cpp - struct Foo {}; +A subtype produced by a class template specialization is listed, but +its item name carries only the bare template name (`Derived`), without +the template arguments that would distinguish `Derived`. - struct Base {}; +```cpp +struct Foo {}; - template - struct Derived : Base {}; +struct Base {}; - Derived instance; - ``` +template +struct Derived : Base {}; -
+Derived instance; +``` @@ -1923,323 +1703,291 @@ Navigate to the type definition of a symbol. Applicable to variables, parameters Search the whole project for a symbol by name (`workspace/symbol`). - - -- [x] Basic workspace-wide symbol search — case-insensitive substring matching - - A query matches any symbol whose name contains it, ignoring case: - functions, types, enumerators and macros all participate, and a query - with no match returns an empty list rather than an error. - -
- Example - - ```cpp - // query: widget - // query: parse_config - // query: MODE - // query: fast - // query: no_such_symbol - - struct Widget { - int width; - }; - - enum class Mode { Fast, Safe }; - - #define MODE_DEFAULT 1 - - void parse_config() {} - ``` - -
- -- [x] Search spans the whole project — hits from files other than the queried one - - The query returns symbols from project files that are not even open - in the editor: `other.h` stays closed here, so its hit is served by - the background index. + -
- Example +| Capability | Status | Issues | +| ------------------------------------------------- | ----------- | ----------------------------------------------------------- | +| Basic workspace-wide symbol search | Supported | | +| Search spans the whole project | Supported | | +| Overload disambiguation | Partial | [clangd#1344](https://github.com/clangd/clangd/issues/1344) | +| Fuzzy matching | Unsupported | [clangd#914](https://github.com/clangd/clangd/issues/914) | +| Partially qualified name search | Unsupported | [clangd#550](https://github.com/clangd/clangd/issues/550) | +| Enumerator lookup under the enum's scope | Unsupported | [clangd#931](https://github.com/clangd/clangd/issues/931) | +| Underlying declarations ranked above type aliases | Unsupported | [clangd#2253](https://github.com/clangd/clangd/issues/2253) | +| Search by mangled (linker) name | Unsupported | | - `main.cpp`: +### Basic workspace-wide symbol search - ```cpp - // query: helper_elsewhere +case-insensitive substring matching - int local_anchor = 0; - ``` +A query matches any symbol whose name contains it, ignoring case: +functions, types, enumerators and macros all participate, and a query +with no match returns an empty list rather than an error. - `other.h`: +```cpp +// query: widget +// query: parse_config +// query: MODE +// query: fast +// query: no_such_symbol - ```cpp - void helper_elsewhere() {} - ``` +struct Widget { + int width; +}; -
+enum class Mode { Fast, Safe }; -- [ ] Overload disambiguation — parameter types shown in results _(partial)_ ([clangd#1344](https://github.com/clangd/clangd/issues/1344)) +#define MODE_DEFAULT 1 - Querying an overloaded name finds every overload, but each entry - carries only the bare name — nothing tells the two `process` results - apart short of opening both locations. +void parse_config() {} +``` -
- Example +### Search spans the whole project - ```cpp - // query: process +Hits from files other than the queried one - void process(int value) {} +The query returns symbols from project files that are not even open +in the editor: `other.h` stays closed here, so its hit is served by +the background index. - void process(bool flag, int level) {} - ``` +`main.cpp`: -
+```cpp +// query: helper_elsewhere -- [ ] Fuzzy matching — word-boundary-aware scoring for camelCase and snake_case ([clangd#914](https://github.com/clangd/clangd/issues/914)) +int local_anchor = 0; +``` - Matching is a case-insensitive substring test: `LinLis` does not find - `LinkedList`, and `pcfg` does not find `parse_config`. Word-boundary - initials should match and score for every symbol kind, macros - included. +`other.h`: -
- Example +```cpp +void helper_elsewhere() {} +``` - ```cpp - // query: LinLis - // query: pcfg +### Overload disambiguation - struct LinkedList {}; +Parameter types shown in results - void parse_config(); - ``` +Querying an overloaded name finds every overload, but each entry +carries only the bare name — nothing tells the two `process` results +apart short of opening both locations. -
+```cpp +// query: process -- [ ] Partially qualified name search ([clangd#550](https://github.com/clangd/clangd/issues/550)) +void process(int value) {} - Symbols match by bare name only: `net::Socket` finds nothing even - though `deep::net::Socket` exists, and neither does any other - qualifier-prefixed form. +void process(bool flag, int level) {} +``` -
- Example +### Fuzzy matching - ```cpp - // query: net::Socket +word-boundary-aware scoring for camelCase and snake_case - namespace deep { - namespace net { +Matching is a case-insensitive substring test: `LinLis` does not find +`LinkedList`, and `pcfg` does not find `parse_config`. Word-boundary +initials should match and score for every symbol kind, macros +included. - struct Socket {}; +```cpp +// query: LinLis +// query: pcfg - } // namespace net - } // namespace deep - ``` +struct LinkedList {}; -
+void parse_config(); +``` -- [ ] Enumerator lookup under the enum's scope ([clangd#931](https://github.com/clangd/clangd/issues/931)) +### Partially qualified name search - `Color::Red` should find the enumerator — for scoped and unscoped - enums alike — but qualified queries match nothing; only the bare - `Red` does. +Symbols match by bare name only: `net::Socket` finds nothing even +though `deep::net::Socket` exists, and neither does any other +qualifier-prefixed form. -
- Example +```cpp +// query: net::Socket - ```cpp - // query: Color::Red +namespace deep { +namespace net { - enum Color { Red, Green }; - ``` +struct Socket {}; -
+} // namespace net +} // namespace deep +``` -- [ ] Underlying declarations ranked above type aliases ([clangd#2253](https://github.com/clangd/clangd/issues/2253)) +### Enumerator lookup under the enum's scope - When both `ConnectionImpl` and its alias `Connection` match a query, - the underlying declaration should rank first. Results carry no - ranking today. +`Color::Red` should find the enumerator — for scoped and unscoped +enums alike — but qualified queries match nothing; only the bare +`Red` does. -
- Example +```cpp +// query: Color::Red - ```cpp - // query: Connection +enum Color { Red, Green }; +``` - struct ConnectionImpl {}; +### Underlying declarations ranked above type aliases - using Connection = ConnectionImpl; - ``` +When both `ConnectionImpl` and its alias `Connection` match a query, +the underlying declaration should rank first. Results carry no +ranking today. -
+```cpp +// query: Connection -- [ ] Search by mangled (linker) name +struct ConnectionImpl {}; - Pasting a linker symbol such as `_Z7processi` should resolve to the - function it mangles — useful when chasing linker errors and stack - traces. +using Connection = ConnectionImpl; +``` -
- Example +### Search by mangled (linker) name - ```cpp - // query: _Z7processi +Pasting a linker symbol such as `_Z7processi` should resolve to the +function it mangles — useful when chasing linker errors and stack +traces. - void process(int value); - ``` +```cpp +// query: _Z7processi -
+void process(int value); +``` ## Module Navigation - + -- [x] `import module_name` navigates to the module interface unit ([clangd#2310](https://github.com/clangd/clangd/issues/2310)) +| Capability | Status | Issues | +| ----------------------------------------------------------------- | --------- | ----------------------------------------------------------- | +| `import module_name` navigates to the module interface unit | Supported | [clangd#2310](https://github.com/clangd/clangd/issues/2310) | +| `import :partition` navigates to the partition unit | Supported | | +| Navigate between interface and implementation units of one module | Partial | | +| Dot-separated module name | Partial | | - Go-to-definition on the name in an `import` declaration opens the - module interface unit that exports it, and uses of an imported symbol - reach its definition in that unit. +### `import module_name` navigates to the module interface unit -
- Example +Go-to-definition on the name in an `import` declaration opens the +module interface unit that exports it, and uses of an imported symbol +reach its definition in that unit. - `main.cpp`: +`main.cpp`: - ```cpp - import widget; +```cpp +import widget; - int build() { - return area(2, 3); - } - ``` +int build() { + return area(2, 3); +} +``` - `widget.cppm`: +`widget.cppm`: - ```cpp - export module widget; +```cpp +export module widget; - export int area(int width, int height) { - return width * height; - } - ``` +export int area(int width, int height) { + return width * height; +} +``` -
+### `import :partition` navigates to the partition unit -- [x] `import :partition` navigates to the partition unit +Go-to-definition on the partition name after the colon in a partition +import opens the partition unit that declares it. - Go-to-definition on the partition name after the colon in a partition - import opens the partition unit that declares it. +`main.cpp`: -
- Example +```cpp +import pack; - `main.cpp`: +int run() { + return count(); +} +``` - ```cpp - import pack; +`pack.cppm`: - int run() { - return count(); - } - ``` +```cpp +export module pack; - `pack.cppm`: +export import :items; +``` - ```cpp - export module pack; +`pack_items.cppm`: - export import :items; - ``` +```cpp +export module pack:items; - `pack_items.cppm`: +export int count() { + return 3; +} +``` - ```cpp - export module pack:items; +### Navigate between interface and implementation units of one module - export int count() { - return 3; - } - ``` +Go-to-definition on the module name in an implementation unit +(`module m;`) jumps to the interface unit that declares the module; +the reverse direction, from the interface name to the implementation, +is not offered. -
+`main.cpp`: -- [ ] Navigate between interface and implementation units of one module _(partial)_ +```cpp +import store; - Go-to-definition on the module name in an implementation unit - (`module m;`) jumps to the interface unit that declares the module; - the reverse direction, from the interface name to the implementation, - is not offered. +int lookup(int key) { + return fetch(key); +} +``` -
- Example +`iface.cppm`: - `main.cpp`: +```cpp +export module store; - ```cpp - import store; +export int fetch(int key); +``` - int lookup(int key) { - return fetch(key); - } - ``` +`impl.cpp`: - `iface.cppm`: +```cpp +module store; - ```cpp - export module store; +int fetch(int key) { + return key * 2; +} +``` - export int fetch(int key); - ``` +### Dot-separated module name - `impl.cpp`: +Navigate each segment - ```cpp - module store; +Go-to-definition on the leading segment of a dot-separated module name +reaches the module's interface unit; the segments after a dot do not +resolve on their own yet. - int fetch(int key) { - return key * 2; - } - ``` +`main.cpp`: -
+```cpp +import app.core; -- [ ] Dot-separated module name — navigate each segment _(partial)_ +int run() { + return value(); +} +``` - Go-to-definition on the leading segment of a dot-separated module name - reaches the module's interface unit; the segments after a dot do not - resolve on their own yet. +`app_core.cppm`: -
- Example +```cpp +export module app.core; - `main.cpp`: - - ```cpp - import app.core; - - int run() { - return value(); - } - ``` - - `app_core.cppm`: - - ```cpp - export module app.core; - - export int value() { - return 1; - } - ``` - -
+export int value() { + return 1; +} +``` @@ -2247,95 +1995,85 @@ Search the whole project for a symbol by name (`workspace/symbol`). Highlight all references to the symbol under cursor within the current file (`textDocument/documentHighlight`). - - -- [ ] Highlight every reference to the symbol under the cursor in the current file - - Placing the cursor on `total` should light up its declaration and - every use in the file; the request is not implemented. - -
- Example - - ```cpp - int total = 0; - - void accumulate(int amount) { - total = total + amount; - } - ``` - -
- -- [ ] Read/write classification for symbol highlights - - Each highlight should carry its access kind, so editors can tint - writes differently from reads. - -
- Example - - ```cpp - void tally() { - int count = 0; // write - int next = count; // read - count = next; // write - } - ``` - -
- -- [ ] Control flow token highlighting ([clangd#1921](https://github.com/clangd/clangd/issues/1921)) - - Highlighting `break` or `continue` should also light up the loop or - `switch` it belongs to — and `return` / `throw` the function exits - they mark. - -
- Example - - ```cpp - void drain(int outer, int inner) { - for (int i = 0; i < outer; i += 1) { - for (int j = 0; j < inner; j += 1) { - if (i == j) { - break; // highlighting break → also the inner for - } - if (j == 0) { - continue; // highlighting continue → also the inner for - } - } - } - } - ``` - -
+ + +| Capability | Status | Issues | +| ---------------------------------------------------------------------------- | ----------- | ----------------------------------------------------------- | +| Highlight every reference to the symbol under the cursor in the current file | Unsupported | | +| Read/write classification for symbol highlights | Unsupported | | +| Control flow token highlighting | Unsupported | [clangd#1921](https://github.com/clangd/clangd/issues/1921) | + +### Highlight every reference to the symbol under the cursor in the current file + +Placing the cursor on `total` should light up its declaration and +every use in the file; the request is not implemented. + +```cpp +int total = 0; + +void accumulate(int amount) { + total = total + amount; +} +``` + +### Read/write classification for symbol highlights + +Each highlight should carry its access kind, so editors can tint +writes differently from reads. + +```cpp +void tally() { + int count = 0; // write + int next = count; // read + count = next; // write +} +``` + +### Control flow token highlighting + +Highlighting `break` or `continue` should also light up the loop or +`switch` it belongs to — and `return` / `throw` the function exits +they mark. + +```cpp +void drain(int outer, int inner) { + for (int i = 0; i < outer; i += 1) { + for (int j = 0; j < inner; j += 1) { + if (i == j) { + break; // highlighting break → also the inner for + } + if (j == 0) { + continue; // highlighting continue → also the inner for + } + } + } +} +``` ## Switch Source/Header - - -- [ ] Switch between a source file and its header + - From `widget.cpp` a single command should jump to `widget.h` and - back — the `textDocument/switchSourceHeader` request clangd clients - rely on is not implemented. +| Capability | Status | Issues | +| ------------------------------------------- | ----------- | ------ | +| Switch between a source file and its header | Unsupported | | -
- Example +### Switch between a source file and its header - ```cpp - // widget.h - class Widget { - void draw(); - }; +From `widget.cpp` a single command should jump to `widget.h` and +back — the `textDocument/switchSourceHeader` request clangd clients +rely on is not implemented. - // widget.cpp — #include "widget.h" - void Widget::draw() {} - ``` +```cpp +// widget.h +class Widget { + void draw(); +}; -
+// widget.cpp — #include "widget.h" +void Widget::draw() {} +``` diff --git a/en/clice/features/overview.md b/en/clice/features/overview.md index 8fc5e078..e0dbfaaf 100644 --- a/en/clice/features/overview.md +++ b/en/clice/features/overview.md @@ -15,7 +15,7 @@ Language Server Protocol features available when using clice as an editor backen | Feature | Status | Page | | ---------------- | ------------------------------------------ | ----------------------------------------- | -| Code Completion | 30 supported | [completion](./completion.md) | +| Code Completion | 31 supported | [completion](./completion.md) | | Hover | 34 supported · 21 partial · 11 unsupported | [hover](./hover.md) | | Signature Help | 14 supported | [signature-help](./signature-help.md) | | Code Navigation | 44 supported · 14 partial · 34 unsupported | [navigation](./navigation.md) | diff --git a/en/clice/features/semantic-tokens.md b/en/clice/features/semantic-tokens.md index 277d9dc5..83b921a1 100644 --- a/en/clice/features/semantic-tokens.md +++ b/en/clice/features/semantic-tokens.md @@ -1,6 +1,6 @@ # Semantic Tokens - @@ -14,257 +14,236 @@ configuration. Kinds derived from the token stream itself, independent of the AST. - + + +| Capability | Status | Issues | +| ------------------------------------- | ----------- | ----------------------------------------------------------- | +| Comments | Supported | | +| Literals | Supported | | +| Keywords | Supported | | +| Preprocessor directives | Supported | | +| Inactive regions | Supported | | +| Header names | Supported | | +| Inactive regions at the top of a file | Supported | | +| Literal prefixes and suffixes | Unsupported | | +| Escape sequences | Unsupported | | +| Declarator vs operator disambiguation | Unsupported | [clangd#1421](https://github.com/clangd/clangd/issues/1421) | +| Primitive token type | Supported | | +| Bracket token types | Unsupported | | + +### Comments + +line, block and doc comments, including multiline blocks + +```cpp +// A line comment. +/* a one-line block comment */ +/* + * a block comment + * spanning several lines + */ +/// a doc comment +int after_comments = 0; + +/* first +second */ int after_block = 1; +``` + +### Literals + +numbers, characters and strings, including raw strings + +```cpp +int decimal = 42; +int hexadecimal = 0xFF; +double floating = 3.14; +char letter = 'x'; +const char* text = "hello"; +const char* raw = R"(no "escapes" in here)"; +int after_raw = 1; + +const char* multiline = R"(line1 +line2 +)"; int after_closing = 2; +``` + +### Keywords + +Including alternative operator spellings and the contextual `final` / `override` + +```cpp +bool logic(bool a, bool b) { + return a and b or not a; +} + +struct Base { + virtual void act(); + virtual ~Base(); +}; + +struct Leaf final : Base { + void act() override; +}; + +struct Last : Base { + void act() final; +}; +``` + +### Preprocessor directives + +`#if` chains keep directive kinds; disabled branches keep lexical kinds; pragma arguments stay plain + +```cpp +int before_conditional = 0; + +#if 0 +int disabled_branch; +#else +int enabled_branch = 1; +#endif + +#define FLAG +#ifdef FLAG +int flagged = 2; +#endif + +#pragma pack(1) + +# +#define STRINGIZE(x) #x +const char* stringized = STRINGIZE(abc); +``` + +### Inactive regions + +Tokens in untaken branches keep their lexical kinds and carry the `inactive` modifier; unclassified tokens become plain `identifier` carriers, so even a lone `}` line dims + +```cpp +int before = 0; + +#if 0 +int simple = 1; +bare identifiers; +call(arg); +"string in dead code"; +// comment inside +#ifdef NESTED +int deeper = 2; +#endif +int tail = 3; +#endif + +#if defined(MISSING) +first_branch; +#elif 0 +elif_branch; +#else +int taken = 4; +#endif -- [x] Comments — line, block and doc comments, including multiline blocks +#if 0 +void edge() { + inner(5); +} +#endif +``` -
- Example +### Header names - ```cpp - // A line comment. - /* a one-line block comment */ - /* - * a block comment - * spanning several lines - */ - /// a doc comment - int after_comments = 0; +Quoted and angled `#include` filenames, including the split `# include` form - /* first - second */ int after_block = 1; - ``` +```cpp +#include "inc/angled.h" +#include +# include "inc/angled.h" -
+int after_includes = 0; +``` -- [x] Literals — numbers, characters and strings, including raw strings +### Inactive regions at the top of a file -
- Example +Untaken branches among the leading directives dim the same way - ```cpp - int decimal = 42; - int hexadecimal = 0xFF; - double floating = 3.14; - char letter = 'x'; - const char* text = "hello"; - const char* raw = R"(no "escapes" in here)"; - int after_raw = 1; +```cpp +#define KEEP 1 +#if 0 +#define DEAD 2 +#endif - const char* multiline = R"(line1 - line2 - )"; int after_closing = 2; - ``` +int after = KEEP; +``` -
+### Literal prefixes and suffixes -- [x] Keywords — including alternative operator spellings and the contextual `final` / `override` +Encoding prefixes, type suffixes, digit separators and UDL suffixes as distinct tokens -
- Example +```cpp +using size_type = decltype(sizeof(0)); +constexpr size_type operator""_kb(unsigned long long n) { + return n * 1024; +} - ```cpp - bool logic(bool a, bool b) { - return a and b or not a; - } +auto wide = L"wide string"; +auto utf8 = u8"utf-8 string"; +auto hex = 0xFF; +auto binary = 0b1010; +auto unsigned_suffix = 42u; +auto float_suffix = 3.14f; +auto separators = 1'000'000; +auto udl = 4_kb; +``` - struct Base { - virtual void act(); - virtual ~Base(); - }; +### Escape sequences - struct Leaf final : Base { - void act() override; - }; +Highlighted distinctly inside string and character literals + +```cpp +const char* escaped = "hello\nworld"; +char hex_escape = '\x41'; +``` - struct Last : Base { - void act() final; - }; - ``` +### Declarator vs operator disambiguation -
+`*`, `&`, `&&` as declarators vs arithmetic/logical operators -- [x] Preprocessor directives — `#if` chains keep directive kinds; disabled branches keep lexical kinds; pragma arguments stay plain +```cpp +int value = 1; +int* pointer = &value; +int& reference = value; +int product = value * value; +int masked = value & 1; +``` -
- Example +### Primitive token type - ```cpp - int before_conditional = 0; +A distinct kind for built-in types instead of plain `keyword` - #if 0 - int disabled_branch; - #else - int enabled_branch = 1; - #endif +```cpp +int number = 0; +float ratio = 0.5f; +void act(); +unsigned long long wide_number = 0; +__int128 extended_int = 0; +_Float16 extended_float = 0; +``` - #define FLAG - #ifdef FLAG - int flagged = 2; - #endif +### Bracket token types - #pragma pack(1) +Matching `()`, `[]`, `{}`, `<>` pairs as distinct kinds - # - #define STRINGIZE(x) #x - const char* stringized = STRINGIZE(abc); - ``` +```cpp +template +struct Grid { + T cells[4]; +}; -
+Grid grid{{1, 2, 3, 4}}; -- [x] Inactive regions — tokens in untaken branches keep their lexical kinds and carry the `inactive` modifier; unclassified tokens become plain `identifier` carriers, so even a lone `}` line dims - -
- Example - - ```cpp - int before = 0; - - #if 0 - int simple = 1; - bare identifiers; - call(arg); - "string in dead code"; - // comment inside - #ifdef NESTED - int deeper = 2; - #endif - int tail = 3; - #endif - - #if defined(MISSING) - first_branch; - #elif 0 - elif_branch; - #else - int taken = 4; - #endif - - #if 0 - void edge() { - inner(5); - } - #endif - ``` - -
- -- [x] Header names — quoted and angled `#include` filenames, including the split `# include` form - -
- Example - - ```cpp - #include "inc/angled.h" - #include - # include "inc/angled.h" - - int after_includes = 0; - ``` - -
- -- [x] Inactive regions at the top of a file — untaken branches among the leading directives dim the same way - -
- Example - - ```cpp - #define KEEP 1 - #if 0 - #define DEAD 2 - #endif - - int after = KEEP; - ``` - -
- -- [ ] Literal prefixes and suffixes — encoding prefixes, type suffixes, digit separators and UDL suffixes as distinct tokens - -
- Example - - ```cpp - using size_type = decltype(sizeof(0)); - constexpr size_type operator""_kb(unsigned long long n) { - return n * 1024; - } - - auto wide = L"wide string"; - auto utf8 = u8"utf-8 string"; - auto hex = 0xFF; - auto binary = 0b1010; - auto unsigned_suffix = 42u; - auto float_suffix = 3.14f; - auto separators = 1'000'000; - auto udl = 4_kb; - ``` - -
- -- [ ] Escape sequences — highlighted distinctly inside string and character literals - -
- Example - - ```cpp - const char* escaped = "hello\nworld"; - char hex_escape = '\x41'; - ``` - -
- -- [ ] Declarator vs operator disambiguation — `*`, `&`, `&&` as declarators vs arithmetic/logical operators ([clangd#1421](https://github.com/clangd/clangd/issues/1421)) - -
- Example - - ```cpp - int value = 1; - int* pointer = &value; - int& reference = value; - int product = value * value; - int masked = value & 1; - ``` - -
- -- [x] Primitive token type — a distinct kind for built-in types instead of plain `keyword` - -
- Example - - ```cpp - int number = 0; - float ratio = 0.5f; - void act(); - unsigned long long wide_number = 0; - __int128 extended_int = 0; - _Float16 extended_float = 0; - ``` - -
- -- [ ] Bracket token types — matching `()`, `[]`, `{}`, `<>` pairs as distinct kinds - -
- Example - - ```cpp - template - struct Grid { - T cells[4]; - }; - - Grid grid{{1, 2, 3, 4}}; - - int first(Grid& grid) { - return grid.cells[0]; - } - ``` - -
+int first(Grid& grid) { + return grid.cells[0]; +} +``` @@ -272,858 +251,785 @@ Kinds derived from the token stream itself, independent of the AST. Names classified by the declaration they define or reference. - - -- [x] Namespaces — definitions, references, nested namespaces and namespace aliases - -
- Example - - ```cpp - namespace demo { - namespace inner { - int value = 1; - } - } - - namespace demo::inner::more {} - - namespace alias = demo::inner; - - int use_alias = alias::value; - ``` - -
- -- [x] Types — class, struct, union, enum and type aliases, at definitions and references - -
- Example - - ```cpp - class Widget {}; - struct Point {}; - union Storage { - int i; - float f; - }; - enum Flags { FlagA }; - enum class Mode { Fast }; - - typedef Point PointAlias; - using WidgetAlias = Widget; - - Widget* make_widget(); - PointAlias origin; - Mode current = Mode::Fast; - ``` - -
- -- [x] Functions and methods — declarations, definitions and call sites - -
- Example - - ```cpp - int twice(int value); - - int twice(int value) { - return value * 2; - } - - struct Machine { - void start(); - static void reset(); - }; + + +| Capability | Status | Issues | +| ------------------------------------------ | --------- | -------------------------------------------------------------------------------------------------------------------- | +| Namespaces | Supported | | +| Types | Supported | | +| Functions and methods | Supported | | +| Variables | Supported | | +| Templates | Supported | | +| Concepts | Supported | | +| Labels | Supported | | +| Structured bindings | Supported | | +| Member initializer lists | Supported | [clangd#122](https://github.com/clangd/clangd/issues/122) | +| Using declarations | Supported | [clangd#2619](https://github.com/clangd/clangd/issues/2619) | +| Lambda init-captures | Supported | [clangd#868](https://github.com/clangd/clangd/issues/868) | +| `sizeof...` | Supported | [clangd#213](https://github.com/clangd/clangd/issues/213) | +| `using enum` | Supported | [clangd#1283](https://github.com/clangd/clangd/issues/1283) | +| Deduction guides | Supported | | +| Explicit instantiation | Supported | [clangd#316](https://github.com/clangd/clangd/issues/316) | +| Dependent names | Partial | [clangd#154](https://github.com/clangd/clangd/issues/154), [clangd#297](https://github.com/clangd/clangd/issues/297) | +| Variable templates | Supported | | +| Out-of-line member definitions | Supported | | +| Alias templates | Supported | | +| Template template parameters | Supported | | +| Lambda captures | Supported | | +| Range-based for | Supported | | +| Enum underlying types | Supported | | +| Friend declarations | Supported | | +| Dependent using declarations | Partial | | +| Function explicit instantiation directives | Partial | [llvm#191658](https://github.com/llvm/llvm-project/issues/191658) | +| Variable explicit instantiation directives | Partial | [llvm#191658](https://github.com/llvm/llvm-project/issues/191658) | +| Explicit instantiation member bodies | Supported | | + +### Namespaces + +definitions, references, nested namespaces and namespace aliases + +```cpp +namespace demo { +namespace inner { +int value = 1; +} +} + +namespace demo::inner::more {} + +namespace alias = demo::inner; + +int use_alias = alias::value; +``` + +### Types + +class, struct, union, enum and type aliases, at definitions and references + +```cpp +class Widget {}; +struct Point {}; +union Storage { + int i; + float f; +}; +enum Flags { FlagA }; +enum class Mode { Fast }; + +typedef Point PointAlias; +using WidgetAlias = Widget; + +Widget* make_widget(); +PointAlias origin; +Mode current = Mode::Fast; +``` + +### Functions and methods + +declarations, definitions and call sites + +```cpp +int twice(int value); + +int twice(int value) { + return value * 2; +} + +struct Machine { + void start(); + static void reset(); +}; + +void drive(Machine machine) { + machine.start(); + Machine::reset(); + int four = twice(2); +} +``` + +### Variables + +globals, locals, parameters, fields and enum members + +```cpp +struct Holder { + int field; + static int shared; +}; + +enum class State { Idle }; + +int global_value = 1; + +void touch(int param) { + int local = param + global_value; + Holder h; + h.field = local; + Holder::shared = h.field; + State state = State::Idle; +} +``` - void drive(Machine machine) { - machine.start(); - Machine::reset(); - int four = twice(2); - } - ``` +### Templates -
+Type and non-type template parameters, with the `templated` modifier on template names -- [x] Variables — globals, locals, parameters, fields and enum members +```cpp +template +struct Array { + T data[N]; +}; -
- Example +template +T identity(T value); - ```cpp - struct Holder { - int field; - static int shared; - }; +template +T identity(T value) { + return value; +} - enum class State { Idle }; +Array arr; +int result = identity(3); +``` - int global_value = 1; +### Concepts - void touch(int param) { - int local = param + global_value; - Holder h; - h.field = local; - Holder::shared = h.field; - State state = State::Idle; - } - ``` +Definitions and uses as template constraints -
+```cpp +template +concept Small = sizeof(T) <= 4; -- [x] Templates — type and non-type template parameters, with the `templated` modifier on template names +template +void use_small(T value); -
- Example +template + requires Small +void require_small(T value); +``` - ```cpp - template - struct Array { - T data[N]; - }; +### Labels - template - T identity(T value); +`goto` targets and label definitions - template - T identity(T value) { - return value; - } +```cpp +void retry(bool again) { + goto done; +done: + if (again) { + goto done; + } +} +``` - Array arr; - int result = identity(3); - ``` +### Structured bindings -
+Binding names at definition and use -- [x] Concepts — definitions and uses as template constraints +The opening `[` deliberately carries no token; only the binding names +themselves are highlighted. -
- Example +```cpp +struct Pair { + int first, second; +}; - ```cpp - template - concept Small = sizeof(T) <= 4; +void unpack() { + auto [a, b] = Pair{1, 2}; + int sum = a + b; +} +``` - template - void use_small(T value); +### Member initializer lists - template - requires Small - void require_small(T value); - ``` +Initialized fields highlighted as fields -
+```cpp +struct Widget { + int width; + int height; -- [x] Labels — `goto` targets and label definitions + Widget(int w, int h) : width(w), height(h) {} +}; +``` -
- Example +### Using declarations - ```cpp - void retry(bool again) { - goto done; - done: - if (again) { - goto done; - } - } - ``` +The introduced name keeps its target's kind -
+```cpp +namespace tools { +inline int helper() { + return 1; +} +struct Gadget {}; +} -- [x] Structured bindings — binding names at definition and use +using tools::helper; +using tools::Gadget; - The opening `[` deliberately carries no token; only the binding names - themselves are highlighted. +int used = helper(); +Gadget gadget; +``` -
- Example +### Lambda init-captures - ```cpp - struct Pair { - int first, second; - }; +The captured name highlighted as a variable - void unpack() { - auto [a, b] = Pair{1, 2}; - int sum = a + b; - } - ``` +```cpp +int compute(); -
+auto fn = [val = compute()] { + return val; +}; +``` -- [x] Member initializer lists — initialized fields highlighted as fields ([clangd#122](https://github.com/clangd/clangd/issues/122)) +### `sizeof...` -
- Example +The pack parameter keeps its type-parameter token - ```cpp - struct Widget { - int width; - int height; +```cpp +template +constexpr auto count = sizeof...(Ts); +``` - Widget(int w, int h) : width(w), height(h) {} - }; - ``` +### `using enum` -
+The enum name highlighted at the using site -- [x] Using declarations — the introduced name keeps its target's kind ([clangd#2619](https://github.com/clangd/clangd/issues/2619)) +```cpp +enum class Color { Red }; -
- Example +void paint() { + using enum Color; + auto c = Red; +} +``` - ```cpp - namespace tools { - inline int helper() { - return 1; - } - struct Gadget {}; - } +### Deduction guides - using tools::helper; - using tools::Gadget; +The guide name and the guided template highlighted - int used = helper(); - Gadget gadget; - ``` +```cpp +template +struct Vec { + template + Vec(It first, It last); +}; -
+template +Vec(It, It) -> Vec; +``` -- [x] Lambda init-captures — the captured name highlighted as a variable ([clangd#868](https://github.com/clangd/clangd/issues/868)) +### Explicit instantiation -
- Example +The instantiated template name and its written template arguments highlighted, on the extern declaration and the definition alike - ```cpp - int compute(); +```cpp +struct Widget {}; - auto fn = [val = compute()] { - return val; - }; - ``` +template +struct Holder { + T value; +}; -
+extern template struct Holder; -- [x] `sizeof...` — the pack parameter keeps its type-parameter token ([clangd#213](https://github.com/clangd/clangd/issues/213)) +template struct Holder; +``` -
- Example +### Dependent names - ```cpp - template - constexpr auto count = sizeof...(Ts); - ``` +Resolved through the primary template where one is known -
+Dependent members of a known template (`Box`) resolve to the primary +template's declarations and keep their kinds. Members of a bare template +parameter have no candidate declaration and currently get no token; +heuristic coloring for such names remains open. -- [x] `using enum` — the enum name highlighted at the using site ([clangd#1283](https://github.com/clangd/clangd/issues/1283)) +```cpp +template +struct Box { + using value_type = int; + static void reset(); + int size() const; +}; -
- Example +template +void resolved(Box box) { + typename Box::value_type item; + Box::reset(); + box.size(); +} - ```cpp - enum class Color { Red }; +template +void unresolved(T value) { + typename T::value_type item; + T::reset(); + value.size(); +} +``` - void paint() { - using enum Color; - auto c = Red; - } - ``` +### Variable templates -
+declarations, definitions, partial and full specializations -- [x] Deduction guides — the guide name and the guided template highlighted +```cpp +template +extern int pair_value; -
- Example +template +int pair_value = 2; - ```cpp - template - struct Vec { - template - Vec(It first, It last); - }; +template +extern int pair_value; - template - Vec(It, It) -> Vec; - ``` +template +int pair_value = 4; -
+template <> +int pair_value = 5; +``` -- [x] Explicit instantiation — the instantiated template name and its written template arguments highlighted, on the extern declaration and the definition alike ([clangd#316](https://github.com/clangd/clangd/issues/316)) +### Out-of-line member definitions -
- Example +Qualified names keep method kinds and modifiers - ```cpp - struct Widget {}; +```cpp +struct Gauge { + int read() const; + static void reset(); +}; - template - struct Holder { - T value; - }; +int Gauge::read() const { + return 0; +} - extern template struct Holder; +void Gauge::reset() {} +``` - template struct Holder; - ``` +### Alias templates -
+The alias name carries the type kind and the `templated` modifier -- [ ] Dependent names — resolved through the primary template where one is known _(partial)_ ([clangd#154](https://github.com/clangd/clangd/issues/154), [clangd#297](https://github.com/clangd/clangd/issues/297)) +```cpp +template +using Ptr = T*; - Dependent members of a known template (`Box`) resolve to the primary - template's declarations and keep their kinds. Members of a bare template - parameter have no candidate declaration and currently get no token; - heuristic coloring for such names remains open. +template +struct Box {}; -
- Example +template +using BoxPtr = Box*; - ```cpp - template - struct Box { - using value_type = int; - static void reset(); - int size() const; - }; +Ptr pointer = nullptr; +``` - template - void resolved(Box box) { - typename Box::value_type item; - Box::reset(); - box.size(); - } +### Template template parameters - template - void unresolved(T value) { - typename T::value_type item; - T::reset(); - value.size(); - } - ``` +Declared and used as types -
+```cpp +template +struct Holder {}; -- [x] Variable templates — declarations, definitions, partial and full specializations +template