diff --git a/en/clice/features/overview.md b/en/clice/features/overview.md index 19e29e251..0c1a75561 100644 --- a/en/clice/features/overview.md +++ b/en/clice/features/overview.md @@ -26,7 +26,7 @@ Language Server Protocol features available when using clice as an editor backen | [Document Links](./document-links.md) | 7 supported · 1 partial | | [Document Symbols](./document-symbols.md) | 29 supported | | [Folding Ranges](./folding-ranges.md) | 19 supported | -| [Selection Ranges](./selection-ranges.md) | 10 supported | +| [Selection Ranges](./selection-ranges.md) | 14 supported | | [Formatting](./formatting.md) | 4 supported | | [C++20 Modules](./modules.md) | 7 supported | | [Header Contexts](./header-contexts.md) | 5 supported | diff --git a/en/clice/features/selection-ranges.md b/en/clice/features/selection-ranges.md index f04009fee..747ec633d 100644 --- a/en/clice/features/selection-ranges.md +++ b/en/clice/features/selection-ranges.md @@ -109,6 +109,50 @@ tests/selection_range/syntax_ranges/07_blocks + + +**Function signatures** + +A function's name is selected with its signature before the whole declaration + +The signature runs from the return type, or from the name of a +constructor, through the parameters and what the declaration adds after +them, such as `const noexcept`, a trailing return type, `override` or a +`requires` clause. + +```case +tests/selection_range/syntax_ranges/11_function_signatures +``` + + + + + +**Switch cases** + +A `case` label is selected with the statements it leads before the whole switch body + +```case +tests/selection_range/syntax_ranges/15_switch_cases +``` + + + + + +**Documented declarations** + +A declaration is selected with the comment documenting it, from inside either one + +Inside a block comment over several lines, the line under the cursor +comes first, without the `*` it begins with. + +```case +tests/selection_range/syntax_ranges/19_documented_declarations +``` + + + ## Text Ranges @@ -157,3 +201,26 @@ tests/selection_range/text_ranges/03_directives + +## Conditional Compilation + +Steps through the code of `#if` blocks, the branches the preprocessor skipped included. + + + + + +**Conditional blocks** + +The lines of a conditional's branch and the whole `#if` through `#endif` are selected after the code inside them + +A branch the preprocessor skipped gets the same steps, so its code can +be selected as a whole. + +```case +tests/selection_range/conditionals/03_conditional_blocks +``` + + + + diff --git a/sources/clice/cases/selection_range/conditionals/03_conditional_blocks.json b/sources/clice/cases/selection_range/conditionals/03_conditional_blocks.json new file mode 100644 index 000000000..48d129bfc --- /dev/null +++ b/sources/clice/cases/selection_range/conditionals/03_conditional_blocks.json @@ -0,0 +1,277 @@ +{ + "id": "selection_range/conditionals/03_conditional_blocks", + "topic": "selection_range", + "subtopic": "conditionals", + "title": "Conditional blocks", + "summary": "The lines of a conditional's branch and the whole `#if` through `#endif` are selected after the code inside them", + "prose": "A branch the preprocessor skipped gets the same steps, so its code can\nbe selected as a whole.", + "status": "supported", + "issues": [], + "files": [ + { + "path": "main.cpp", + "text": "#define FAST 1\n\nint pick(int value) {\n#if FAST\n value *= 2;\n return value;\n#else\n return value + 1;\n#endif\n}\n\n#ifdef FAST\nint fast_enabled = 1;\n#endif\n", + "markers": [ + { + "name": "active", + "begin": 74, + "end": 74, + "range": false + }, + { + "name": "skipped", + "begin": 98, + "end": 98, + "range": false + }, + { + "name": "directive", + "begin": 126, + "end": 126, + "range": false + } + ] + } + ], + "tests": [ + { + "name": "answers", + "blocks": [ + { + "label": "active", + "marker": "active", + "value": { + "selection_ranges": [ + { + "$place": "return ⟦value⟧;", + "path": "main.cpp", + "range": { + "start": { + "line": 5, + "character": 11 + }, + "end": { + "line": 5, + "character": 16 + } + } + }, + { + "$place": "⟦return value⟧;", + "path": "main.cpp", + "range": { + "start": { + "line": 5, + "character": 4 + }, + "end": { + "line": 5, + "character": 16 + } + } + }, + { + "$place": "⟦return value;⟧", + "path": "main.cpp", + "range": { + "start": { + "line": 5, + "character": 4 + }, + "end": { + "line": 5, + "character": 17 + } + } + }, + { + "$place": "⟦value *= 2; … return value;⟧ (2 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 4, + "character": 4 + }, + "end": { + "line": 5, + "character": 17 + } + } + }, + { + "$place": "⟦#if FAST … #endif⟧ (6 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 3, + "character": 0 + }, + "end": { + "line": 8, + "character": 6 + } + } + }, + { + "$place": "int pick(int value) ⟦{ … }⟧ (8 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 2, + "character": 20 + }, + "end": { + "line": 9, + "character": 1 + } + } + }, + { + "$place": "⟦int pick(int value) { … }⟧ (8 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 2, + "character": 0 + }, + "end": { + "line": 9, + "character": 1 + } + } + } + ] + } + }, + { + "label": "skipped", + "marker": "skipped", + "value": { + "selection_ranges": [ + { + "$place": "return ⟦value⟧ + 1;", + "path": "main.cpp", + "range": { + "start": { + "line": 7, + "character": 11 + }, + "end": { + "line": 7, + "character": 16 + } + } + }, + { + "$place": "⟦return value + 1;⟧", + "path": "main.cpp", + "range": { + "start": { + "line": 7, + "character": 4 + }, + "end": { + "line": 7, + "character": 21 + } + } + }, + { + "$place": "⟦#if FAST … #endif⟧ (6 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 3, + "character": 0 + }, + "end": { + "line": 8, + "character": 6 + } + } + }, + { + "$place": "int pick(int value) ⟦{ … }⟧ (8 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 2, + "character": 20 + }, + "end": { + "line": 9, + "character": 1 + } + } + }, + { + "$place": "⟦int pick(int value) { … }⟧ (8 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 2, + "character": 0 + }, + "end": { + "line": 9, + "character": 1 + } + } + } + ] + } + }, + { + "label": "directive", + "marker": "directive", + "value": { + "selection_ranges": [ + { + "$place": "#ifdef ⟦FAST⟧", + "path": "main.cpp", + "range": { + "start": { + "line": 11, + "character": 7 + }, + "end": { + "line": 11, + "character": 11 + } + } + }, + { + "$place": "⟦#ifdef FAST⟧", + "path": "main.cpp", + "range": { + "start": { + "line": 11, + "character": 0 + }, + "end": { + "line": 11, + "character": 11 + } + } + }, + { + "$place": "⟦#ifdef FAST … #endif⟧ (3 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 11, + "character": 0 + }, + "end": { + "line": 13, + "character": 6 + } + } + } + ] + } + } + ] + } + ] +} diff --git a/sources/clice/cases/selection_range/syntax_ranges/05_macro_arguments.json b/sources/clice/cases/selection_range/syntax_ranges/05_macro_arguments.json index cc5b830a6..3a466740b 100644 --- a/sources/clice/cases/selection_range/syntax_ranges/05_macro_arguments.json +++ b/sources/clice/cases/selection_range/syntax_ranges/05_macro_arguments.json @@ -25,6 +25,12 @@ "begin": 123, "end": 123, "range": false + }, + { + "name": "closing", + "begin": 135, + "end": 135, + "range": false } ] } @@ -216,6 +222,98 @@ } ] } + }, + { + "label": "closing", + "marker": "closing", + "value": { + "selection_ranges": [ + { + "$place": "return TWICE⟦(counter + 1)⟧;", + "path": "main.cpp", + "range": { + "start": { + "line": 6, + "character": 16 + }, + "end": { + "line": 6, + "character": 29 + } + } + }, + { + "$place": "return ⟦TWICE(counter + 1)⟧;", + "path": "main.cpp", + "range": { + "start": { + "line": 6, + "character": 11 + }, + "end": { + "line": 6, + "character": 29 + } + } + }, + { + "$place": "⟦return TWICE(counter + 1)⟧;", + "path": "main.cpp", + "range": { + "start": { + "line": 6, + "character": 4 + }, + "end": { + "line": 6, + "character": 29 + } + } + }, + { + "$place": "⟦return TWICE(counter + 1);⟧", + "path": "main.cpp", + "range": { + "start": { + "line": 6, + "character": 4 + }, + "end": { + "line": 6, + "character": 30 + } + } + }, + { + "$place": "int doubled() ⟦{ … }⟧ (3 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 5, + "character": 14 + }, + "end": { + "line": 7, + "character": 1 + } + } + }, + { + "$place": "⟦int doubled() { … }⟧ (3 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 5, + "character": 0 + }, + "end": { + "line": 7, + "character": 1 + } + } + } + ] + } } ] } diff --git a/sources/clice/cases/selection_range/syntax_ranges/11_function_signatures.json b/sources/clice/cases/selection_range/syntax_ranges/11_function_signatures.json new file mode 100644 index 000000000..510432c2f --- /dev/null +++ b/sources/clice/cases/selection_range/syntax_ranges/11_function_signatures.json @@ -0,0 +1,557 @@ +{ + "id": "selection_range/syntax_ranges/11_function_signatures", + "topic": "selection_range", + "subtopic": "syntax_ranges", + "title": "Function signatures", + "summary": "A function's name is selected with its signature before the whole declaration", + "prose": "The signature runs from the return type, or from the name of a\nconstructor, through the parameters and what the declaration adds after\nthem, such as `const noexcept`, a trailing return type, `override` or a\n`requires` clause.", + "status": "supported", + "issues": [], + "files": [ + { + "path": "main.cpp", + "text": "struct Clock {\n virtual long now() const = 0;\n};\n\nstruct Timer : Clock {\n Timer(int ticks);\n [[nodiscard]] long elapsed(int scale) const noexcept;\n const char* label() const;\n long now() const override { return 0; }\n};\n\nTimer::Timer(int ticks) {}\n\nauto tick(int step) -> long {\n return step;\n}\n\ntemplate \nT twice(T value) requires (sizeof(T) > 1) {\n return value + value;\n}\n", + "markers": [ + { + "name": "method", + "begin": 121, + "end": 121, + "range": false + }, + { + "name": "qualified", + "begin": 172, + "end": 172, + "range": false + }, + { + "name": "override", + "begin": 196, + "end": 196, + "range": false + }, + { + "name": "constructor", + "begin": 242, + "end": 242, + "range": false + }, + { + "name": "trailing", + "begin": 268, + "end": 268, + "range": false + }, + { + "name": "constrained", + "begin": 337, + "end": 337, + "range": false + } + ] + } + ], + "tests": [ + { + "name": "answers", + "blocks": [ + { + "label": "method", + "marker": "method", + "value": { + "selection_ranges": [ + { + "$place": "[[nodiscard]] long ⟦elapsed⟧(int scale) const noexcept;", + "path": "main.cpp", + "range": { + "start": { + "line": 6, + "character": 23 + }, + "end": { + "line": 6, + "character": 30 + } + } + }, + { + "$place": "[[nodiscard]] ⟦long elapsed(int scale) const noexcept⟧;", + "path": "main.cpp", + "range": { + "start": { + "line": 6, + "character": 18 + }, + "end": { + "line": 6, + "character": 56 + } + } + }, + { + "$place": "⟦[[nodiscard]] long elapsed(int scale) const noexcept⟧;", + "path": "main.cpp", + "range": { + "start": { + "line": 6, + "character": 4 + }, + "end": { + "line": 6, + "character": 56 + } + } + }, + { + "$place": "⟦[[nodiscard]] long elapsed(int scale) const noexcept;⟧", + "path": "main.cpp", + "range": { + "start": { + "line": 6, + "character": 4 + }, + "end": { + "line": 6, + "character": 57 + } + } + }, + { + "$place": "⟦Timer(int ticks); … long now() const override { return 0; }⟧ (4 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 5, + "character": 4 + }, + "end": { + "line": 8, + "character": 43 + } + } + }, + { + "$place": "struct Timer : Clock ⟦{ … }⟧ (6 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 4, + "character": 21 + }, + "end": { + "line": 9, + "character": 1 + } + } + }, + { + "$place": "⟦struct Timer : Clock { … }⟧ (6 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 9, + "character": 1 + } + } + }, + { + "$place": "⟦struct Timer : Clock { … };⟧ (6 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 9, + "character": 2 + } + } + } + ] + } + }, + { + "label": "qualified", + "marker": "qualified", + "value": { + "selection_ranges": [ + { + "$place": "const char* ⟦label⟧() const;", + "path": "main.cpp", + "range": { + "start": { + "line": 7, + "character": 16 + }, + "end": { + "line": 7, + "character": 21 + } + } + }, + { + "$place": "⟦const char* label() const⟧;", + "path": "main.cpp", + "range": { + "start": { + "line": 7, + "character": 4 + }, + "end": { + "line": 7, + "character": 29 + } + } + }, + { + "$place": "⟦const char* label() const;⟧", + "path": "main.cpp", + "range": { + "start": { + "line": 7, + "character": 4 + }, + "end": { + "line": 7, + "character": 30 + } + } + }, + { + "$place": "⟦Timer(int ticks); … long now() const override { return 0; }⟧ (4 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 5, + "character": 4 + }, + "end": { + "line": 8, + "character": 43 + } + } + }, + { + "$place": "struct Timer : Clock ⟦{ … }⟧ (6 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 4, + "character": 21 + }, + "end": { + "line": 9, + "character": 1 + } + } + }, + { + "$place": "⟦struct Timer : Clock { … }⟧ (6 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 9, + "character": 1 + } + } + }, + { + "$place": "⟦struct Timer : Clock { … };⟧ (6 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 9, + "character": 2 + } + } + } + ] + } + }, + { + "label": "override", + "marker": "override", + "value": { + "selection_ranges": [ + { + "$place": "long ⟦now⟧() const override { return 0; }", + "path": "main.cpp", + "range": { + "start": { + "line": 8, + "character": 9 + }, + "end": { + "line": 8, + "character": 12 + } + } + }, + { + "$place": "⟦long now() const override⟧ { return 0; }", + "path": "main.cpp", + "range": { + "start": { + "line": 8, + "character": 4 + }, + "end": { + "line": 8, + "character": 29 + } + } + }, + { + "$place": "⟦long now() const override { return 0; }⟧", + "path": "main.cpp", + "range": { + "start": { + "line": 8, + "character": 4 + }, + "end": { + "line": 8, + "character": 43 + } + } + }, + { + "$place": "⟦Timer(int ticks); … long now() const override { return 0; }⟧ (4 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 5, + "character": 4 + }, + "end": { + "line": 8, + "character": 43 + } + } + }, + { + "$place": "struct Timer : Clock ⟦{ … }⟧ (6 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 4, + "character": 21 + }, + "end": { + "line": 9, + "character": 1 + } + } + }, + { + "$place": "⟦struct Timer : Clock { … }⟧ (6 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 9, + "character": 1 + } + } + }, + { + "$place": "⟦struct Timer : Clock { … };⟧ (6 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 9, + "character": 2 + } + } + } + ] + } + }, + { + "label": "constructor", + "marker": "constructor", + "value": { + "selection_ranges": [ + { + "$place": "Timer::⟦Timer⟧(int ticks) {}", + "path": "main.cpp", + "range": { + "start": { + "line": 11, + "character": 7 + }, + "end": { + "line": 11, + "character": 12 + } + } + }, + { + "$place": "⟦Timer::Timer(int ticks)⟧ {}", + "path": "main.cpp", + "range": { + "start": { + "line": 11, + "character": 0 + }, + "end": { + "line": 11, + "character": 23 + } + } + }, + { + "$place": "⟦Timer::Timer(int ticks) {}⟧", + "path": "main.cpp", + "range": { + "start": { + "line": 11, + "character": 0 + }, + "end": { + "line": 11, + "character": 26 + } + } + } + ] + } + }, + { + "label": "trailing", + "marker": "trailing", + "value": { + "selection_ranges": [ + { + "$place": "auto ⟦tick⟧(int step) -> long {", + "path": "main.cpp", + "range": { + "start": { + "line": 13, + "character": 5 + }, + "end": { + "line": 13, + "character": 9 + } + } + }, + { + "$place": "⟦auto tick(int step) -> long⟧ {", + "path": "main.cpp", + "range": { + "start": { + "line": 13, + "character": 0 + }, + "end": { + "line": 13, + "character": 27 + } + } + }, + { + "$place": "⟦auto tick(int step) -> long { … }⟧ (3 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 13, + "character": 0 + }, + "end": { + "line": 15, + "character": 1 + } + } + } + ] + } + }, + { + "label": "constrained", + "marker": "constrained", + "value": { + "selection_ranges": [ + { + "$place": "T ⟦twice⟧(T value) requires (sizeof(T) > 1) {", + "path": "main.cpp", + "range": { + "start": { + "line": 18, + "character": 2 + }, + "end": { + "line": 18, + "character": 7 + } + } + }, + { + "$place": "⟦T twice(T value) requires (sizeof(T) > 1)⟧ {", + "path": "main.cpp", + "range": { + "start": { + "line": 18, + "character": 0 + }, + "end": { + "line": 18, + "character": 41 + } + } + }, + { + "$place": "⟦T twice(T value) requires (sizeof(T) > 1) { … }⟧ (3 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 18, + "character": 0 + }, + "end": { + "line": 20, + "character": 1 + } + } + }, + { + "$place": "⟦template … }⟧ (4 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 17, + "character": 0 + }, + "end": { + "line": 20, + "character": 1 + } + } + } + ] + } + } + ] + } + ] +} diff --git a/sources/clice/cases/selection_range/syntax_ranges/15_switch_cases.json b/sources/clice/cases/selection_range/syntax_ranges/15_switch_cases.json new file mode 100644 index 000000000..230680476 --- /dev/null +++ b/sources/clice/cases/selection_range/syntax_ranges/15_switch_cases.json @@ -0,0 +1,319 @@ +{ + "id": "selection_range/syntax_ranges/15_switch_cases", + "topic": "selection_range", + "subtopic": "syntax_ranges", + "title": "Switch cases", + "summary": "A `case` label is selected with the statements it leads before the whole switch body", + "prose": "", + "status": "supported", + "issues": [], + "files": [ + { + "path": "main.cpp", + "text": "int classify(int code) {\n switch(code) {\n case 0: return 0;\n case 1:\n case 2:\n code += 1;\n break;\n default: return -1;\n }\n return code;\n}\n", + "markers": [ + { + "name": "label", + "begin": 83, + "end": 83, + "range": false + }, + { + "name": "statement", + "begin": 137, + "end": 137, + "range": false + } + ] + } + ], + "tests": [ + { + "name": "answers", + "blocks": [ + { + "label": "label", + "marker": "label", + "value": { + "selection_ranges": [ + { + "$place": "case ⟦1⟧:", + "path": "main.cpp", + "range": { + "start": { + "line": 3, + "character": 13 + }, + "end": { + "line": 3, + "character": 14 + } + } + }, + { + "$place": "⟦case 1: … code += 1⟧ (3 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 3, + "character": 8 + }, + "end": { + "line": 5, + "character": 21 + } + } + }, + { + "$place": "⟦case 1: … code += 1;⟧ (3 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 3, + "character": 8 + }, + "end": { + "line": 5, + "character": 22 + } + } + }, + { + "$place": "⟦case 1: … break;⟧ (4 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 3, + "character": 8 + }, + "end": { + "line": 6, + "character": 18 + } + } + }, + { + "$place": "⟦case 0: return 0; … default: return -1;⟧ (6 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 2, + "character": 8 + }, + "end": { + "line": 7, + "character": 27 + } + } + }, + { + "$place": "switch(code) ⟦{ … }⟧ (8 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 1, + "character": 17 + }, + "end": { + "line": 8, + "character": 5 + } + } + }, + { + "$place": "⟦switch(code) { … }⟧ (8 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 1, + "character": 4 + }, + "end": { + "line": 8, + "character": 5 + } + } + }, + { + "$place": "⟦switch(code) { … return code;⟧ (9 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 1, + "character": 4 + }, + "end": { + "line": 9, + "character": 16 + } + } + }, + { + "$place": "int classify(int code) ⟦{ … }⟧ (11 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 0, + "character": 23 + }, + "end": { + "line": 10, + "character": 1 + } + } + }, + { + "$place": "⟦int classify(int code) { … }⟧ (11 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 0, + "character": 0 + }, + "end": { + "line": 10, + "character": 1 + } + } + } + ] + } + }, + { + "label": "statement", + "marker": "statement", + "value": { + "selection_ranges": [ + { + "$place": "⟦break⟧;", + "path": "main.cpp", + "range": { + "start": { + "line": 6, + "character": 12 + }, + "end": { + "line": 6, + "character": 17 + } + } + }, + { + "$place": "⟦break;⟧", + "path": "main.cpp", + "range": { + "start": { + "line": 6, + "character": 12 + }, + "end": { + "line": 6, + "character": 18 + } + } + }, + { + "$place": "⟦case 1: … break;⟧ (4 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 3, + "character": 8 + }, + "end": { + "line": 6, + "character": 18 + } + } + }, + { + "$place": "⟦case 0: return 0; … default: return -1;⟧ (6 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 2, + "character": 8 + }, + "end": { + "line": 7, + "character": 27 + } + } + }, + { + "$place": "switch(code) ⟦{ … }⟧ (8 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 1, + "character": 17 + }, + "end": { + "line": 8, + "character": 5 + } + } + }, + { + "$place": "⟦switch(code) { … }⟧ (8 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 1, + "character": 4 + }, + "end": { + "line": 8, + "character": 5 + } + } + }, + { + "$place": "⟦switch(code) { … return code;⟧ (9 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 1, + "character": 4 + }, + "end": { + "line": 9, + "character": 16 + } + } + }, + { + "$place": "int classify(int code) ⟦{ … }⟧ (11 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 0, + "character": 23 + }, + "end": { + "line": 10, + "character": 1 + } + } + }, + { + "$place": "⟦int classify(int code) { … }⟧ (11 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 0, + "character": 0 + }, + "end": { + "line": 10, + "character": 1 + } + } + } + ] + } + } + ] + } + ] +} diff --git a/sources/clice/cases/selection_range/syntax_ranges/19_documented_declarations.json b/sources/clice/cases/selection_range/syntax_ranges/19_documented_declarations.json new file mode 100644 index 000000000..15ca4e023 --- /dev/null +++ b/sources/clice/cases/selection_range/syntax_ranges/19_documented_declarations.json @@ -0,0 +1,487 @@ +{ + "id": "selection_range/syntax_ranges/19_documented_declarations", + "topic": "selection_range", + "subtopic": "syntax_ranges", + "title": "Documented declarations", + "summary": "A declaration is selected with the comment documenting it, from inside either one", + "prose": "Inside a block comment over several lines, the line under the cursor\ncomes first, without the `*` it begins with.", + "status": "supported", + "issues": [], + "files": [ + { + "path": "main.cpp", + "text": "/// The largest size a buffer takes.\nconstexpr int limit = 64;\n\nstruct Buffer {\n int used = 0; ///< Bytes in use.\n};\n\n/**\n * Copies the bytes over.\n * Returns how many it copied.\n */\nint copy(Buffer& to, const Buffer& from);\n\nint spare(const Buffer& buffer) {\n /// Bytes still free.\n int left = limit - buffer.used;\n return left;\n}\n", + "markers": [ + { + "name": "comment", + "begin": 23, + "end": 23, + "range": false + }, + { + "name": "member", + "begin": 88, + "end": 88, + "range": false + }, + { + "name": "line", + "begin": 139, + "end": 139, + "range": false + }, + { + "name": "parameter", + "begin": 221, + "end": 221, + "range": false + }, + { + "name": "local", + "begin": 297, + "end": 297, + "range": false + } + ] + } + ], + "tests": [ + { + "name": "answers", + "blocks": [ + { + "label": "comment", + "marker": "comment", + "value": { + "selection_ranges": [ + { + "$place": "/// ⟦The largest size a buffer takes.⟧", + "path": "main.cpp", + "range": { + "start": { + "line": 0, + "character": 4 + }, + "end": { + "line": 0, + "character": 36 + } + } + }, + { + "$place": "⟦/// The largest size a buffer takes.⟧", + "path": "main.cpp", + "range": { + "start": { + "line": 0, + "character": 0 + }, + "end": { + "line": 0, + "character": 36 + } + } + }, + { + "$place": "⟦/// The largest size a buffer takes. … constexpr int limit = 64;⟧ (2 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 0, + "character": 0 + }, + "end": { + "line": 1, + "character": 25 + } + } + } + ] + } + }, + { + "label": "member", + "marker": "member", + "value": { + "selection_ranges": [ + { + "$place": "int ⟦used⟧ = 0; ///< Bytes in use.", + "path": "main.cpp", + "range": { + "start": { + "line": 4, + "character": 8 + }, + "end": { + "line": 4, + "character": 12 + } + } + }, + { + "$place": "⟦int used = 0⟧; ///< Bytes in use.", + "path": "main.cpp", + "range": { + "start": { + "line": 4, + "character": 4 + }, + "end": { + "line": 4, + "character": 16 + } + } + }, + { + "$place": "⟦int used = 0;⟧ ///< Bytes in use.", + "path": "main.cpp", + "range": { + "start": { + "line": 4, + "character": 4 + }, + "end": { + "line": 4, + "character": 17 + } + } + }, + { + "$place": "⟦int used = 0; ///< Bytes in use.⟧", + "path": "main.cpp", + "range": { + "start": { + "line": 4, + "character": 4 + }, + "end": { + "line": 4, + "character": 36 + } + } + }, + { + "$place": "struct Buffer ⟦{ … }⟧ (3 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 3, + "character": 14 + }, + "end": { + "line": 5, + "character": 1 + } + } + }, + { + "$place": "⟦struct Buffer { … }⟧ (3 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 3, + "character": 0 + }, + "end": { + "line": 5, + "character": 1 + } + } + }, + { + "$place": "⟦struct Buffer { … };⟧ (3 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 3, + "character": 0 + }, + "end": { + "line": 5, + "character": 2 + } + } + } + ] + } + }, + { + "label": "line", + "marker": "line", + "value": { + "selection_ranges": [ + { + "$place": "* ⟦Copies the bytes over.⟧", + "path": "main.cpp", + "range": { + "start": { + "line": 8, + "character": 3 + }, + "end": { + "line": 8, + "character": 25 + } + } + }, + { + "$place": "⟦* Copies the bytes over. … * Returns how many it copied.⟧ (2 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 8, + "character": 1 + }, + "end": { + "line": 9, + "character": 30 + } + } + }, + { + "$place": "⟦/** … */⟧ (4 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 7, + "character": 0 + }, + "end": { + "line": 10, + "character": 3 + } + } + }, + { + "$place": "⟦/** … int copy(Buffer& to, const Buffer& from);⟧ (5 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 7, + "character": 0 + }, + "end": { + "line": 11, + "character": 41 + } + } + } + ] + } + }, + { + "label": "parameter", + "marker": "parameter", + "value": { + "selection_ranges": [ + { + "$place": "int copy(Buffer& to, const Buffer& ⟦from⟧);", + "path": "main.cpp", + "range": { + "start": { + "line": 11, + "character": 35 + }, + "end": { + "line": 11, + "character": 39 + } + } + }, + { + "$place": "int copy(Buffer& to, ⟦const Buffer& from⟧);", + "path": "main.cpp", + "range": { + "start": { + "line": 11, + "character": 21 + }, + "end": { + "line": 11, + "character": 39 + } + } + }, + { + "$place": "int copy(⟦Buffer& to, const Buffer& from⟧);", + "path": "main.cpp", + "range": { + "start": { + "line": 11, + "character": 9 + }, + "end": { + "line": 11, + "character": 39 + } + } + }, + { + "$place": "int copy⟦(Buffer& to, const Buffer& from)⟧;", + "path": "main.cpp", + "range": { + "start": { + "line": 11, + "character": 8 + }, + "end": { + "line": 11, + "character": 40 + } + } + }, + { + "$place": "⟦int copy(Buffer& to, const Buffer& from)⟧;", + "path": "main.cpp", + "range": { + "start": { + "line": 11, + "character": 0 + }, + "end": { + "line": 11, + "character": 40 + } + } + }, + { + "$place": "⟦int copy(Buffer& to, const Buffer& from);⟧", + "path": "main.cpp", + "range": { + "start": { + "line": 11, + "character": 0 + }, + "end": { + "line": 11, + "character": 41 + } + } + }, + { + "$place": "⟦/** … int copy(Buffer& to, const Buffer& from);⟧ (5 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 7, + "character": 0 + }, + "end": { + "line": 11, + "character": 41 + } + } + } + ] + } + }, + { + "label": "local", + "marker": "local", + "value": { + "selection_ranges": [ + { + "$place": "int ⟦left⟧ = limit - buffer.used;", + "path": "main.cpp", + "range": { + "start": { + "line": 15, + "character": 8 + }, + "end": { + "line": 15, + "character": 12 + } + } + }, + { + "$place": "⟦int left = limit - buffer.used⟧;", + "path": "main.cpp", + "range": { + "start": { + "line": 15, + "character": 4 + }, + "end": { + "line": 15, + "character": 34 + } + } + }, + { + "$place": "⟦int left = limit - buffer.used;⟧", + "path": "main.cpp", + "range": { + "start": { + "line": 15, + "character": 4 + }, + "end": { + "line": 15, + "character": 35 + } + } + }, + { + "$place": "⟦/// Bytes still free. … int left = limit - buffer.used;⟧ (2 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 14, + "character": 4 + }, + "end": { + "line": 15, + "character": 35 + } + } + }, + { + "$place": "⟦/// Bytes still free. … return left;⟧ (3 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 14, + "character": 4 + }, + "end": { + "line": 16, + "character": 16 + } + } + }, + { + "$place": "int spare(const Buffer& buffer) ⟦{ … }⟧ (5 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 13, + "character": 32 + }, + "end": { + "line": 17, + "character": 1 + } + } + }, + { + "$place": "⟦int spare(const Buffer& buffer) { … }⟧ (5 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 13, + "character": 0 + }, + "end": { + "line": 17, + "character": 1 + } + } + } + ] + } + } + ] + } + ] +} diff --git a/sources/clice/cases/selection_range/text_ranges/02_comments.json b/sources/clice/cases/selection_range/text_ranges/02_comments.json index 641ab0527..e501ec019 100644 --- a/sources/clice/cases/selection_range/text_ranges/02_comments.json +++ b/sources/clice/cases/selection_range/text_ranges/02_comments.json @@ -89,6 +89,20 @@ "character": 25 } } + }, + { + "$place": "⟦// The first line of a run, … int value = 0;⟧ (3 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 0, + "character": 0 + }, + "end": { + "line": 2, + "character": 14 + } + } } ] } @@ -125,6 +139,20 @@ "character": 29 } } + }, + { + "$place": "⟦/** A documentation block. */ … }⟧ (5 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 8, + "character": 1 + } + } } ] } @@ -162,6 +190,20 @@ } } }, + { + "$place": "⟦int count = 0; ///< a member note⟧", + "path": "main.cpp", + "range": { + "start": { + "line": 6, + "character": 4 + }, + "end": { + "line": 6, + "character": 37 + } + } + }, { "$place": "⟦int count = 0; ///< a member note … return value + count; // a trailing note⟧ (2 lines)", "path": "main.cpp", @@ -203,6 +245,20 @@ "character": 1 } } + }, + { + "$place": "⟦/** A documentation block. */ … }⟧ (5 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 8, + "character": 1 + } + } } ] } @@ -281,6 +337,20 @@ "character": 1 } } + }, + { + "$place": "⟦/** A documentation block. */ … }⟧ (5 lines)", + "path": "main.cpp", + "range": { + "start": { + "line": 4, + "character": 0 + }, + "end": { + "line": 8, + "character": 1 + } + } } ] } diff --git a/zh/clice/features/overview.md b/zh/clice/features/overview.md index 2b445017f..11d1b3ee5 100644 --- a/zh/clice/features/overview.md +++ b/zh/clice/features/overview.md @@ -26,7 +26,7 @@ clice 提供一套基于 LLVM/Clang 构建的 C++ 开发工具。本节介绍已 | [文档链接](./document-links.md) | 支持 7 项 · 部分支持 1 项 | | [文档符号](./document-symbols.md) | 支持 29 项 | | [折叠范围](./folding-ranges.md) | 支持 19 项 | -| [选择范围](./selection-ranges.md) | 支持 10 项 | +| [选择范围](./selection-ranges.md) | 支持 14 项 | | [格式化](./formatting.md) | 支持 4 项 | | [C++20 模块](./modules.md) | 支持 7 项 | | [头文件上下文](./header-contexts.md) | 支持 5 项 | diff --git a/zh/clice/features/selection-ranges.md b/zh/clice/features/selection-ranges.md index 73078d1e2..01d0f4c85 100644 --- a/zh/clice/features/selection-ranges.md +++ b/zh/clice/features/selection-ranges.md @@ -103,6 +103,46 @@ tests/selection_range/syntax_ranges/07_blocks + + +**函数签名** + +选区从函数名扩大到函数签名,再扩大到整个声明 + +签名从返回类型开始(构造函数从其名称开始),包括形参列表以及声明在其后添加的内容,例如 `const noexcept`、尾置返回类型、`override` 或 `requires` 子句。 + +```case +tests/selection_range/syntax_ranges/11_function_signatures +``` + + + + + +**switch 中的 case 分支** + +先选中 `case` 标签连同它下面的语句,再选中整个 switch 语句体 + +```case +tests/selection_range/syntax_ranges/15_switch_cases +``` + + + + + +**带文档注释的声明** + +无论从声明内部还是从其文档注释内部开始,选区都会扩大到声明连同其文档注释 + +在跨越多行的块注释中,先选中光标所在的那一行,不含行首的 `*`。 + +```case +tests/selection_range/syntax_ranges/19_documented_declarations +``` + + + ## 文本范围 @@ -150,3 +190,25 @@ tests/selection_range/text_ranges/03_directives + +## 条件编译 + +在 `#if` 块的代码中逐步扩大选区,预处理器跳过的分支也不例外。 + + + + + +**条件编译块** + +先选中分支内的代码,再依次选中该分支的各行和从 `#if` 到 `#endif` 的整个条件编译块 + +预处理器跳过的分支也有同样的选择步骤,因此可以整体选中其中的代码。 + +```case +tests/selection_range/conditionals/03_conditional_blocks +``` + + + +