mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 21:40:12 +01:00
Fix a collection of small language-server bugs in document_symbol. (#7581)
Don't CHECK-fail if the file contains mismatched braces and generates an unbalanced parse tree. Properly balance the start and end of symbols. This previously caused errors to be reported in clients such as VS Code. Compute a correct range for definitions. Don't assume we can find the matching `}` for an opening symbol, since some of our definitions are delimited by a `;` instead. Assisted-by: Gemini via Antigravity
This commit is contained in:
@@ -63,14 +63,26 @@ class SymbolStore {
|
||||
auto HasOpenSymbol() const -> bool { return !open_symbols_.empty(); }
|
||||
|
||||
// Completes a symbol, appending to parent list.
|
||||
auto EndSymbol() -> void {
|
||||
auto EndSymbol(const Lex::TokenizedBuffer* tokens = nullptr,
|
||||
std::optional<Lex::TokenIndex> end_token = std::nullopt)
|
||||
-> void {
|
||||
CARBON_CHECK(HasOpenSymbol());
|
||||
// Extend the range of the symbol to include the `end_token`, if one is
|
||||
// provided. For example, this extends function definitions to the `}` or,
|
||||
// for a terse function body, `;`.
|
||||
if (tokens && end_token) {
|
||||
auto [end_line, end_col] = tokens->GetEndLoc(*end_token);
|
||||
open_symbols_.back().range.end = {.line = end_line.index,
|
||||
.character = end_col - 1};
|
||||
}
|
||||
AddSymbol(open_symbols_.pop_back_val());
|
||||
}
|
||||
|
||||
// Returns final top level symbols.
|
||||
auto Collect() -> std::vector<clang::clangd::DocumentSymbol> {
|
||||
CARBON_CHECK(!HasOpenSymbol());
|
||||
while (HasOpenSymbol()) {
|
||||
EndSymbol();
|
||||
}
|
||||
return std::move(top_level_symbols_);
|
||||
}
|
||||
|
||||
@@ -93,8 +105,7 @@ static auto GetTokenRange(const Lex::TokenizedBuffer& tokens,
|
||||
};
|
||||
}
|
||||
|
||||
// Finds a spanning range for the provided definition / declaration ast node.
|
||||
// In the case of a definition start, will include the body as well.
|
||||
// Finds a spanning range for the provided parse node.
|
||||
static auto GetSymbolRange(const Parse::TreeAndSubtrees& tree_and_subtrees,
|
||||
const Parse::NodeId& ast_node)
|
||||
-> clang::clangd::Range {
|
||||
@@ -105,14 +116,7 @@ static auto GetSymbolRange(const Parse::TreeAndSubtrees& tree_and_subtrees,
|
||||
|
||||
auto start_token = tree_and_subtrees.tree().node_token(start_node);
|
||||
auto end_token = tree_and_subtrees.tree().node_token(ast_node);
|
||||
if (tokens.GetKind(end_token).is_opening_symbol()) {
|
||||
// DefinitionStart nodes use an opening token, so find its closing token to
|
||||
// span the entire class/function body.
|
||||
return GetTokenRange(tokens, start_token,
|
||||
tokens.GetMatchedClosingToken(end_token));
|
||||
} else {
|
||||
return GetTokenRange(tokens, start_token, end_token);
|
||||
}
|
||||
return GetTokenRange(tokens, start_token, end_token);
|
||||
}
|
||||
|
||||
auto HandleDocumentSymbol(
|
||||
@@ -140,11 +144,18 @@ auto HandleDocumentSymbol(
|
||||
symbol_kind = clang::clangd::SymbolKind::Function;
|
||||
break;
|
||||
case Parse::NodeKind::FunctionDefinitionStart:
|
||||
case Parse::NodeKind::BuiltinFunctionDefinitionStart:
|
||||
symbol_kind = clang::clangd::SymbolKind::Function;
|
||||
break;
|
||||
case Parse::NodeKind::Namespace:
|
||||
is_leaf = true;
|
||||
symbol_kind = clang::clangd::SymbolKind::Namespace;
|
||||
break;
|
||||
case Parse::NodeKind::InterfaceDecl:
|
||||
case Parse::NodeKind::NamedConstraintDecl:
|
||||
is_leaf = true;
|
||||
symbol_kind = clang::clangd::SymbolKind::Interface;
|
||||
break;
|
||||
case Parse::NodeKind::InterfaceDefinitionStart:
|
||||
case Parse::NodeKind::NamedConstraintDefinitionStart:
|
||||
symbol_kind = clang::clangd::SymbolKind::Interface;
|
||||
@@ -156,15 +167,21 @@ auto HandleDocumentSymbol(
|
||||
case Parse::NodeKind::ClassDefinitionStart:
|
||||
symbol_kind = clang::clangd::SymbolKind::Class;
|
||||
break;
|
||||
case Parse::NodeKind::ChoiceDefinitionStart:
|
||||
symbol_kind = clang::clangd::SymbolKind::Enum;
|
||||
break;
|
||||
|
||||
case Parse::NodeKind::FunctionDefinition:
|
||||
case Parse::NodeKind::FunctionTerseDefinition:
|
||||
case Parse::NodeKind::BuiltinFunctionDefinition:
|
||||
case Parse::NodeKind::NamedConstraintDefinition:
|
||||
case Parse::NodeKind::InterfaceDefinition:
|
||||
case Parse::NodeKind::ClassDefinition: {
|
||||
case Parse::NodeKind::ClassDefinition:
|
||||
case Parse::NodeKind::ChoiceDefinition: {
|
||||
if (symbols.HasOpenSymbol()) {
|
||||
// Symbols definition has completed, pop it from stack and add to
|
||||
// parent/root.
|
||||
symbols.EndSymbol();
|
||||
symbols.EndSymbol(&tokens, tree.node_token(node_id));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
// AUTOUPDATE
|
||||
// TIP: To test this file alone, run:
|
||||
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/language_server/testdata/document_symbol/choice.carbon
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/language_server/testdata/document_symbol/choice.carbon
|
||||
|
||||
// --- choice.carbon
|
||||
choice Colors {
|
||||
Red,
|
||||
Green,
|
||||
Blue
|
||||
}
|
||||
|
||||
// --- STDIN
|
||||
[[@LSP-CALL:initialize]]
|
||||
[[@LSP-NOTIFY:textDocument/didOpen:
|
||||
"textDocument": {
|
||||
"uri": "file:/choice.carbon",
|
||||
"languageId": "carbon",
|
||||
"text": "FROM_FILE_SPLIT"
|
||||
}
|
||||
]]
|
||||
[[@LSP-CALL:textDocument/documentSymbol:
|
||||
"textDocument": {"uri": "file:/choice.carbon"}
|
||||
]]
|
||||
[[@LSP-CALL:shutdown]]
|
||||
[[@LSP-NOTIFY:exit]]
|
||||
|
||||
// CHECK:STDOUT: Content-Length: 146{{\r}}
|
||||
// CHECK:STDOUT: {{\r}}
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "id": 1,
|
||||
// CHECK:STDOUT: "jsonrpc": "2.0",
|
||||
// CHECK:STDOUT: "result": {
|
||||
// CHECK:STDOUT: "capabilities": {
|
||||
// CHECK:STDOUT: "documentSymbolProvider": true,
|
||||
// CHECK:STDOUT: "textDocumentSync": 2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }Content-Length: 504{{\r}}
|
||||
// CHECK:STDOUT: {{\r}}
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "jsonrpc": "2.0",
|
||||
// CHECK:STDOUT: "method": "textDocument/publishDiagnostics",
|
||||
// CHECK:STDOUT: "params": {
|
||||
// CHECK:STDOUT: "diagnostics": [
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "message": "`Core.UInt` implicitly referenced here, but package `Core` not found",
|
||||
// CHECK:STDOUT: "range": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 15,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 0,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "severity": 1,
|
||||
// CHECK:STDOUT: "source": "carbon"
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: "uri": "file:///choice.carbon"
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }Content-Length: 465{{\r}}
|
||||
// CHECK:STDOUT: {{\r}}
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "id": 2,
|
||||
// CHECK:STDOUT: "jsonrpc": "2.0",
|
||||
// CHECK:STDOUT: "result": [
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "kind": 10,
|
||||
// CHECK:STDOUT: "name": "Colors",
|
||||
// CHECK:STDOUT: "range": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 1,
|
||||
// CHECK:STDOUT: "line": 4
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 0,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "selectionRange": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 13,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 7,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: }Content-Length: 51{{\r}}
|
||||
// CHECK:STDOUT: {{\r}}
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "id": 3,
|
||||
// CHECK:STDOUT: "jsonrpc": "2.0",
|
||||
// CHECK:STDOUT: "result": null
|
||||
// CHECK:STDOUT: }
|
||||
@@ -0,0 +1,177 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
// AUTOUPDATE
|
||||
// TIP: To test this file alone, run:
|
||||
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/language_server/testdata/document_symbol/fn_definition.carbon
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/language_server/testdata/document_symbol/fn_definition.carbon
|
||||
|
||||
// --- fn_definition.carbon
|
||||
fn None();
|
||||
fn Braced() {}
|
||||
fn Terse() => 42;
|
||||
fn Builtin() = "int.make_type_32";
|
||||
|
||||
// --- STDIN
|
||||
[[@LSP-CALL:initialize]]
|
||||
[[@LSP-NOTIFY:textDocument/didOpen:
|
||||
"textDocument": {
|
||||
"uri": "file:/fn_definition.carbon",
|
||||
"languageId": "carbon",
|
||||
"text": "FROM_FILE_SPLIT"
|
||||
}
|
||||
]]
|
||||
[[@LSP-CALL:textDocument/documentSymbol:
|
||||
"textDocument": {"uri": "file:/fn_definition.carbon"}
|
||||
]]
|
||||
[[@LSP-CALL:shutdown]]
|
||||
[[@LSP-NOTIFY:exit]]
|
||||
|
||||
// CHECK:STDOUT: Content-Length: 146{{\r}}
|
||||
// CHECK:STDOUT: {{\r}}
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "id": 1,
|
||||
// CHECK:STDOUT: "jsonrpc": "2.0",
|
||||
// CHECK:STDOUT: "result": {
|
||||
// CHECK:STDOUT: "capabilities": {
|
||||
// CHECK:STDOUT: "documentSymbolProvider": true,
|
||||
// CHECK:STDOUT: "textDocumentSync": 2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }Content-Length: 482{{\r}}
|
||||
// CHECK:STDOUT: {{\r}}
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "jsonrpc": "2.0",
|
||||
// CHECK:STDOUT: "method": "textDocument/publishDiagnostics",
|
||||
// CHECK:STDOUT: "params": {
|
||||
// CHECK:STDOUT: "diagnostics": [
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "message": "semantics TODO: `HandleTerseBodyArrow`",
|
||||
// CHECK:STDOUT: "range": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 13,
|
||||
// CHECK:STDOUT: "line": 2
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 11,
|
||||
// CHECK:STDOUT: "line": 2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "severity": 1,
|
||||
// CHECK:STDOUT: "source": "carbon"
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: "uri": "file:///fn_definition.carbon"
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }Content-Length: 1706{{\r}}
|
||||
// CHECK:STDOUT: {{\r}}
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "id": 2,
|
||||
// CHECK:STDOUT: "jsonrpc": "2.0",
|
||||
// CHECK:STDOUT: "result": [
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "kind": 12,
|
||||
// CHECK:STDOUT: "name": "None",
|
||||
// CHECK:STDOUT: "range": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 10,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 0,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "selectionRange": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 7,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 3,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "kind": 12,
|
||||
// CHECK:STDOUT: "name": "Braced",
|
||||
// CHECK:STDOUT: "range": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 14,
|
||||
// CHECK:STDOUT: "line": 1
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 0,
|
||||
// CHECK:STDOUT: "line": 1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "selectionRange": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 9,
|
||||
// CHECK:STDOUT: "line": 1
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 3,
|
||||
// CHECK:STDOUT: "line": 1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "kind": 12,
|
||||
// CHECK:STDOUT: "name": "Terse",
|
||||
// CHECK:STDOUT: "range": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 17,
|
||||
// CHECK:STDOUT: "line": 2
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 0,
|
||||
// CHECK:STDOUT: "line": 2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "selectionRange": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 8,
|
||||
// CHECK:STDOUT: "line": 2
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 3,
|
||||
// CHECK:STDOUT: "line": 2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "kind": 12,
|
||||
// CHECK:STDOUT: "name": "Builtin",
|
||||
// CHECK:STDOUT: "range": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 34,
|
||||
// CHECK:STDOUT: "line": 3
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 0,
|
||||
// CHECK:STDOUT: "line": 3
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "selectionRange": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 10,
|
||||
// CHECK:STDOUT: "line": 3
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 3,
|
||||
// CHECK:STDOUT: "line": 3
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: }Content-Length: 51{{\r}}
|
||||
// CHECK:STDOUT: {{\r}}
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "id": 3,
|
||||
// CHECK:STDOUT: "jsonrpc": "2.0",
|
||||
// CHECK:STDOUT: "result": null
|
||||
// CHECK:STDOUT: }
|
||||
@@ -0,0 +1,148 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
// AUTOUPDATE
|
||||
// TIP: To test this file alone, run:
|
||||
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/language_server/testdata/document_symbol/incomplete.carbon
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/language_server/testdata/document_symbol/incomplete.carbon
|
||||
|
||||
// --- incomplete.carbon
|
||||
class Incomplete {
|
||||
fn Foo() {
|
||||
|
||||
// --- STDIN
|
||||
[[@LSP-CALL:initialize]]
|
||||
[[@LSP-NOTIFY:textDocument/didOpen:
|
||||
"textDocument": {
|
||||
"uri": "file:/incomplete.carbon",
|
||||
"languageId": "carbon",
|
||||
"text": "FROM_FILE_SPLIT"
|
||||
}
|
||||
]]
|
||||
[[@LSP-CALL:textDocument/documentSymbol:
|
||||
"textDocument": {"uri": "file:/incomplete.carbon"}
|
||||
]]
|
||||
[[@LSP-CALL:shutdown]]
|
||||
[[@LSP-NOTIFY:exit]]
|
||||
|
||||
// CHECK:STDOUT: Content-Length: 146{{\r}}
|
||||
// CHECK:STDOUT: {{\r}}
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "id": 1,
|
||||
// CHECK:STDOUT: "jsonrpc": "2.0",
|
||||
// CHECK:STDOUT: "result": {
|
||||
// CHECK:STDOUT: "capabilities": {
|
||||
// CHECK:STDOUT: "documentSymbolProvider": true,
|
||||
// CHECK:STDOUT: "textDocumentSync": 2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }Content-Length: 1552{{\r}}
|
||||
// CHECK:STDOUT: {{\r}}
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "jsonrpc": "2.0",
|
||||
// CHECK:STDOUT: "method": "textDocument/publishDiagnostics",
|
||||
// CHECK:STDOUT: "params": {
|
||||
// CHECK:STDOUT: "diagnostics": [
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "message": "opening symbol without a corresponding closing symbol",
|
||||
// CHECK:STDOUT: "range": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 18,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 17,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "severity": 1,
|
||||
// CHECK:STDOUT: "source": "carbon"
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "message": "`class` declarations must either end with a `;` or have a `{ ... }` block for a definition",
|
||||
// CHECK:STDOUT: "range": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 18,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 17,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "severity": 1,
|
||||
// CHECK:STDOUT: "source": "carbon"
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "message": "opening symbol without a corresponding closing symbol",
|
||||
// CHECK:STDOUT: "range": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 12,
|
||||
// CHECK:STDOUT: "line": 1
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 11,
|
||||
// CHECK:STDOUT: "line": 1
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "severity": 1,
|
||||
// CHECK:STDOUT: "source": "carbon"
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "message": "semantics TODO: `handle invalid parse trees in `check``",
|
||||
// CHECK:STDOUT: "range": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 18,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 0,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "severity": 1,
|
||||
// CHECK:STDOUT: "source": "carbon"
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: ],
|
||||
// CHECK:STDOUT: "uri": "file:///incomplete.carbon"
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }Content-Length: 469{{\r}}
|
||||
// CHECK:STDOUT: {{\r}}
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "id": 2,
|
||||
// CHECK:STDOUT: "jsonrpc": "2.0",
|
||||
// CHECK:STDOUT: "result": [
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "kind": 5,
|
||||
// CHECK:STDOUT: "name": "Incomplete",
|
||||
// CHECK:STDOUT: "range": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 12,
|
||||
// CHECK:STDOUT: "line": 1
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 0,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "selectionRange": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 16,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 6,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: }Content-Length: 51{{\r}}
|
||||
// CHECK:STDOUT: {{\r}}
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "id": 3,
|
||||
// CHECK:STDOUT: "jsonrpc": "2.0",
|
||||
// CHECK:STDOUT: "result": null
|
||||
// CHECK:STDOUT: }
|
||||
@@ -0,0 +1,112 @@
|
||||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
|
||||
// Exceptions. See /LICENSE for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
// AUTOUPDATE
|
||||
// TIP: To test this file alone, run:
|
||||
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/language_server/testdata/document_symbol/namespace.carbon
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/language_server/testdata/document_symbol/namespace.carbon
|
||||
|
||||
// --- namespace.carbon
|
||||
namespace Foo;
|
||||
|
||||
fn Bar() {}
|
||||
|
||||
// --- STDIN
|
||||
[[@LSP-CALL:initialize]]
|
||||
[[@LSP-NOTIFY:textDocument/didOpen:
|
||||
"textDocument": {
|
||||
"uri": "file:/namespace.carbon",
|
||||
"languageId": "carbon",
|
||||
"text": "FROM_FILE_SPLIT"
|
||||
}
|
||||
]]
|
||||
[[@LSP-CALL:textDocument/documentSymbol:
|
||||
"textDocument": {"uri": "file:/namespace.carbon"}
|
||||
]]
|
||||
[[@LSP-CALL:shutdown]]
|
||||
[[@LSP-NOTIFY:exit]]
|
||||
|
||||
// CHECK:STDOUT: Content-Length: 146{{\r}}
|
||||
// CHECK:STDOUT: {{\r}}
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "id": 1,
|
||||
// CHECK:STDOUT: "jsonrpc": "2.0",
|
||||
// CHECK:STDOUT: "result": {
|
||||
// CHECK:STDOUT: "capabilities": {
|
||||
// CHECK:STDOUT: "documentSymbolProvider": true,
|
||||
// CHECK:STDOUT: "textDocumentSync": 2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }Content-Length: 149{{\r}}
|
||||
// CHECK:STDOUT: {{\r}}
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "jsonrpc": "2.0",
|
||||
// CHECK:STDOUT: "method": "textDocument/publishDiagnostics",
|
||||
// CHECK:STDOUT: "params": {
|
||||
// CHECK:STDOUT: "diagnostics": [],
|
||||
// CHECK:STDOUT: "uri": "file:///namespace.carbon"
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }Content-Length: 874{{\r}}
|
||||
// CHECK:STDOUT: {{\r}}
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "id": 2,
|
||||
// CHECK:STDOUT: "jsonrpc": "2.0",
|
||||
// CHECK:STDOUT: "result": [
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "kind": 3,
|
||||
// CHECK:STDOUT: "name": "Foo",
|
||||
// CHECK:STDOUT: "range": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 14,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 0,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "selectionRange": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 13,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 10,
|
||||
// CHECK:STDOUT: "line": 0
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "kind": 12,
|
||||
// CHECK:STDOUT: "name": "Bar",
|
||||
// CHECK:STDOUT: "range": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 11,
|
||||
// CHECK:STDOUT: "line": 2
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 0,
|
||||
// CHECK:STDOUT: "line": 2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "selectionRange": {
|
||||
// CHECK:STDOUT: "end": {
|
||||
// CHECK:STDOUT: "character": 6,
|
||||
// CHECK:STDOUT: "line": 2
|
||||
// CHECK:STDOUT: },
|
||||
// CHECK:STDOUT: "start": {
|
||||
// CHECK:STDOUT: "character": 3,
|
||||
// CHECK:STDOUT: "line": 2
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: }Content-Length: 51{{\r}}
|
||||
// CHECK:STDOUT: {{\r}}
|
||||
// CHECK:STDOUT: {
|
||||
// CHECK:STDOUT: "id": 3,
|
||||
// CHECK:STDOUT: "jsonrpc": "2.0",
|
||||
// CHECK:STDOUT: "result": null
|
||||
// CHECK:STDOUT: }
|
||||
Reference in New Issue
Block a user