diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index c48485f1c89a..41de887da500 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -458,7 +458,6 @@ CARBON_DIAGNOSTIC_KIND(LanguageServerUnsupportedNotification) // Document handling. CARBON_DIAGNOSTIC_KIND(LanguageServerOpenDuplicateFile) -CARBON_DIAGNOSTIC_KIND(LanguageServerUnsupportedChanges) CARBON_DIAGNOSTIC_KIND(LanguageServerCloseUnknownFile) CARBON_DIAGNOSTIC_KIND(LanguageServerDiagnosticInWrongFile) diff --git a/toolchain/language_server/context.h b/toolchain/language_server/context.h index 16f573a6d216..d55062e546ec 100644 --- a/toolchain/language_server/context.h +++ b/toolchain/language_server/context.h @@ -33,6 +33,8 @@ class Context { auto SetText(Context& context, std::optional version, llvm::StringRef text) -> void; + auto text() const -> llvm::StringRef { return source_->text(); } + auto tree_and_subtrees() const -> const Parse::TreeAndSubtrees& { return *tree_and_subtrees_; } diff --git a/toolchain/language_server/handle_initialize.cpp b/toolchain/language_server/handle_initialize.cpp index b1adf0188e05..3516e1329fe1 100644 --- a/toolchain/language_server/handle_initialize.cpp +++ b/toolchain/language_server/handle_initialize.cpp @@ -12,7 +12,7 @@ auto HandleInitialize( llvm::function_ref)->void> on_done) -> void { llvm::json::Object capabilities{{"documentSymbolProvider", true}, - {"textDocumentSync", /*Full=*/1}}; + {"textDocumentSync", /*Incremental=*/2}}; llvm::json::Object reply{{"capabilities", std::move(capabilities)}}; on_done(reply); } diff --git a/toolchain/language_server/handle_text_document.cpp b/toolchain/language_server/handle_text_document.cpp index 84653c99c3e1..99f300962981 100644 --- a/toolchain/language_server/handle_text_document.cpp +++ b/toolchain/language_server/handle_text_document.cpp @@ -26,6 +26,74 @@ auto HandleDidOpenTextDocument( } } +// Takes start and end positions and returns a tuple with start and end +// offsets. Positions are based on row and column numbers in the source +// code. We often need to know the offsets when modifying strings, so +// this function helps us calculate the offsets. It assumes that the start +// position comes before the end position. +static auto PositionToIndex(const std::string& contents, + const clang::clangd::Position& start, + const clang::clangd::Position& end) + -> std::tuple { + size_t start_index = 0; + size_t end_index = 0; + + for (auto line_number : llvm::seq(end.line)) { + const size_t newline_index = contents.find('\n', end_index); + + CARBON_CHECK(newline_index != std::string::npos, + "Line number greater than number of lines in the file"); + + end_index = newline_index + 1; + + // This condition won't be met if start.line == end.line + // so we need to also check this outside the loop. + if (line_number == start.line) { + start_index = end_index; + } + } + + if (start.line == end.line) { + start_index = end_index; + } + + start_index += start.character; + end_index += end.character; + + CARBON_CHECK(end_index <= contents.size(), + "Position greater than source code size"); + + return {start_index, end_index}; +} + +// LSP allows full and incremental document synchronization. It sends the +// entire source code when doing full sync. However, when doing incremental +// sync, it only sends the list of changes to be performed on the source +// code. It is necessary to apply changes in the order in which they are +// received. These changes can have one of 1) full document or 2) start +// position, end position, and the text which replaces original text between +// these start and end positions. If the range property is absent, then we +// do full sync. Otherwise, we calculate start and end offsets and replace +// the contents between them with the text we received in change.text. +static auto ApplyChanges( + std::string& source, + const std::vector& + content_changes) -> void { + for (const auto& change : content_changes) { + // If range is not present, then we replace entire text. + if (!change.range) { + source = change.text; + continue; + } + + // TODO: Use lexer line number data but avoid re-lexing multiple times. + auto [start_index, end_index] = + PositionToIndex(source, change.range->start, change.range->end); + + source.replace(start_index, end_index - start_index, change.text); + } +} + auto HandleDidChangeTextDocument( Context& context, const clang::clangd::DidChangeTextDocumentParams& params) -> void { @@ -35,17 +103,12 @@ auto HandleDidChangeTextDocument( return; } - // Full text is sent if full sync is specified in capabilities. - if (params.contentChanges.size() != 1) { - CARBON_DIAGNOSTIC(LanguageServerUnsupportedChanges, Warning, - "received unsupported contentChanges count: {0}", int); - context.file_emitter().Emit(filename, LanguageServerUnsupportedChanges, - params.contentChanges.size()); - return; - } if (auto* file = context.LookupFile(filename)) { - file->SetText(context, params.textDocument.version, - params.contentChanges[0].text); + // We copy the document to a new string, apply changes to the string, and + // set the string as the new text. + std::string source = file->text().str(); + ApplyChanges(source, params.contentChanges); + file->SetText(context, params.textDocument.version, source); } } diff --git a/toolchain/language_server/testdata/basics/fail_shutdown_without_exit.carbon b/toolchain/language_server/testdata/basics/fail_shutdown_without_exit.carbon index b9e4d21de627..e2a37b7c9716 100644 --- a/toolchain/language_server/testdata/basics/fail_shutdown_without_exit.carbon +++ b/toolchain/language_server/testdata/basics/fail_shutdown_without_exit.carbon @@ -23,7 +23,7 @@ // CHECK:STDOUT: "result": { // CHECK:STDOUT: "capabilities": { // CHECK:STDOUT: "documentSymbolProvider": true, -// CHECK:STDOUT: "textDocumentSync": 1 +// CHECK:STDOUT: "textDocumentSync": 2 // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: }Content-Length: 51{{\r}} diff --git a/toolchain/language_server/testdata/basics/initialize.carbon b/toolchain/language_server/testdata/basics/initialize.carbon index 899ccb163f69..2b3e36c51348 100644 --- a/toolchain/language_server/testdata/basics/initialize.carbon +++ b/toolchain/language_server/testdata/basics/initialize.carbon @@ -23,7 +23,7 @@ // CHECK:STDOUT: "result": { // CHECK:STDOUT: "capabilities": { // CHECK:STDOUT: "documentSymbolProvider": true, -// CHECK:STDOUT: "textDocumentSync": 1 +// CHECK:STDOUT: "textDocumentSync": 2 // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: }Content-Length: 51{{\r}} diff --git a/toolchain/language_server/testdata/basics/notify_parse_error.carbon b/toolchain/language_server/testdata/basics/notify_parse_error.carbon index 0ee79ac29449..2928e3564f61 100644 --- a/toolchain/language_server/testdata/basics/notify_parse_error.carbon +++ b/toolchain/language_server/testdata/basics/notify_parse_error.carbon @@ -27,7 +27,7 @@ // CHECK:STDOUT: "result": { // CHECK:STDOUT: "capabilities": { // CHECK:STDOUT: "documentSymbolProvider": true, -// CHECK:STDOUT: "textDocumentSync": 1 +// CHECK:STDOUT: "textDocumentSync": 2 // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: }Content-Length: 51{{\r}} diff --git a/toolchain/language_server/testdata/document_symbol/basics.carbon b/toolchain/language_server/testdata/document_symbol/basics.carbon index 4b6e3c2b19d8..a0f1c9cb7aa6 100644 --- a/toolchain/language_server/testdata/document_symbol/basics.carbon +++ b/toolchain/language_server/testdata/document_symbol/basics.carbon @@ -44,7 +44,7 @@ // CHECK:STDOUT: "result": { // CHECK:STDOUT: "capabilities": { // CHECK:STDOUT: "documentSymbolProvider": true, -// CHECK:STDOUT: "textDocumentSync": 1 +// CHECK:STDOUT: "textDocumentSync": 2 // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: }Content-Length: 145{{\r}} diff --git a/toolchain/language_server/testdata/document_symbol/language.carbon b/toolchain/language_server/testdata/document_symbol/language.carbon index 00ed58d25c70..694882022157 100644 --- a/toolchain/language_server/testdata/document_symbol/language.carbon +++ b/toolchain/language_server/testdata/document_symbol/language.carbon @@ -28,7 +28,7 @@ // CHECK:STDOUT: "result": { // CHECK:STDOUT: "capabilities": { // CHECK:STDOUT: "documentSymbolProvider": true, -// CHECK:STDOUT: "textDocumentSync": 1 +// CHECK:STDOUT: "textDocumentSync": 2 // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: }Content-Length: 51{{\r}} diff --git a/toolchain/language_server/testdata/document_symbol/unknown.carbon b/toolchain/language_server/testdata/document_symbol/unknown.carbon index 017efd915a55..4f512c5c7849 100644 --- a/toolchain/language_server/testdata/document_symbol/unknown.carbon +++ b/toolchain/language_server/testdata/document_symbol/unknown.carbon @@ -28,7 +28,7 @@ // CHECK:STDOUT: "result": { // CHECK:STDOUT: "capabilities": { // CHECK:STDOUT: "documentSymbolProvider": true, -// CHECK:STDOUT: "textDocumentSync": 1 +// CHECK:STDOUT: "textDocumentSync": 2 // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: }Content-Length: 51{{\r}} diff --git a/toolchain/language_server/testdata/text_document/change_count.carbon b/toolchain/language_server/testdata/text_document/change_count.carbon deleted file mode 100644 index 79d11917b8cf..000000000000 --- a/toolchain/language_server/testdata/text_document/change_count.carbon +++ /dev/null @@ -1,67 +0,0 @@ -// 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/text_document/change_count.carbon -// TIP: To dump output, run: -// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/language_server/testdata/text_document/change_count.carbon - -// --- STDIN -[[@LSP-CALL:initialize]] -[[@LSP-NOTIFY:textDocument/didOpen: - "textDocument": {"uri": "file:/test.carbon", "languageId": "carbon", - "text": "// Empty"} -]] -[[@LSP-NOTIFY:textDocument/didChange: - "textDocument": {"uri": "file:/test.carbon"}, - "contentChanges": [] -]] -[[@LSP-NOTIFY:textDocument/didChange: - "textDocument": {"uri": "file:/test.carbon"}, - "contentChanges": [ - {"range": {"start": {"line": 5, "character": 23 }, - "end": {"line": 6, "character": 0 }}, - "text": "a"}, - {"range": {"start": {"line": 5, "character": 23 }, - "end": {"line": 6, "character": 0 }}, - "text": "a"} - ] -]] -[[@LSP-CALL:shutdown]] -[[@LSP-NOTIFY:exit]] - -// --- AUTOUPDATE-SPLIT - -// CHECK:STDERR: /test.carbon: warning: received unsupported contentChanges count: 0 [LanguageServerUnsupportedChanges] -// CHECK:STDERR: -// CHECK:STDERR: /test.carbon: warning: received unsupported contentChanges count: 2 [LanguageServerUnsupportedChanges] -// CHECK:STDERR: -// 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": 1 -// CHECK:STDOUT: } -// CHECK:STDOUT: } -// CHECK:STDOUT: }Content-Length: 144{{\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:///test.carbon" -// CHECK:STDOUT: } -// CHECK:STDOUT: }Content-Length: 51{{\r}} -// CHECK:STDOUT: {{\r}} -// CHECK:STDOUT: { -// CHECK:STDOUT: "id": 2, -// CHECK:STDOUT: "jsonrpc": "2.0", -// CHECK:STDOUT: "result": null -// CHECK:STDOUT: } diff --git a/toolchain/language_server/testdata/text_document/change_unknown.carbon b/toolchain/language_server/testdata/text_document/change_unknown.carbon index b397d7e6640c..1eb0521b6fab 100644 --- a/toolchain/language_server/testdata/text_document/change_unknown.carbon +++ b/toolchain/language_server/testdata/text_document/change_unknown.carbon @@ -29,7 +29,7 @@ // CHECK:STDOUT: "result": { // CHECK:STDOUT: "capabilities": { // CHECK:STDOUT: "documentSymbolProvider": true, -// CHECK:STDOUT: "textDocumentSync": 1 +// CHECK:STDOUT: "textDocumentSync": 2 // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: }Content-Length: 51{{\r}} diff --git a/toolchain/language_server/testdata/text_document/close_unknown.carbon b/toolchain/language_server/testdata/text_document/close_unknown.carbon index 9397e3959df7..a57d6ef2ac47 100644 --- a/toolchain/language_server/testdata/text_document/close_unknown.carbon +++ b/toolchain/language_server/testdata/text_document/close_unknown.carbon @@ -28,7 +28,7 @@ // CHECK:STDOUT: "result": { // CHECK:STDOUT: "capabilities": { // CHECK:STDOUT: "documentSymbolProvider": true, -// CHECK:STDOUT: "textDocumentSync": 1 +// CHECK:STDOUT: "textDocumentSync": 2 // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: }Content-Length: 51{{\r}} diff --git a/toolchain/language_server/testdata/text_document/diagnostics.carbon b/toolchain/language_server/testdata/text_document/diagnostics.carbon index 0c01fb601010..1b0a8a218152 100644 --- a/toolchain/language_server/testdata/text_document/diagnostics.carbon +++ b/toolchain/language_server/testdata/text_document/diagnostics.carbon @@ -34,7 +34,7 @@ // CHECK:STDOUT: "result": { // CHECK:STDOUT: "capabilities": { // CHECK:STDOUT: "documentSymbolProvider": true, -// CHECK:STDOUT: "textDocumentSync": 1 +// CHECK:STDOUT: "textDocumentSync": 2 // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: }Content-Length: 1164{{\r}} diff --git a/toolchain/language_server/testdata/text_document/incremental_sync.carbon b/toolchain/language_server/testdata/text_document/incremental_sync.carbon new file mode 100644 index 000000000000..7b7f989254e9 --- /dev/null +++ b/toolchain/language_server/testdata/text_document/incremental_sync.carbon @@ -0,0 +1,290 @@ +// 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/text_document/incremental_sync.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/language_server/testdata/text_document/incremental_sync.carbon + +// --- STDIN +[[@LSP-CALL:initialize]] +[[@LSP-NOTIFY:textDocument/didOpen: + "textDocument": {"uri": "file:/test.carbon", "languageId": "carbon", + "text": "fn SecondFunCTIonNNN() {}\n\nfn ThirdFn() {}\n"} +]] +[[@LSP-NOTIFY:textDocument/didChange: + "textDocument": {"uri": "file:/test.carbon"}, + "contentChanges": [ + {"range": {"start": {"line": 0, "character": 17}, + "end": {"line": 0, "character": 20}}, + "text": ""}, + {"range": {"start": {"line": 0, "character": 12}, + "end": {"line": 0, "character": 13}}, + "text": "c"}, + {"range": {"start": {"line": 0, "character": 13}, + "end": {"line": 0, "character": 15}}, + "text": "ti"}, + {"range": {"start": {"line": 2, "character": 9}, + "end": {"line": 2, "character": 9}}, + "text": "u"}, + {"range": {"start": {"line": 2, "character": 11}, + "end": {"line": 2, "character": 11}}, + "text": "ction"} + ] +]] +[[@LSP-NOTIFY:textDocument/didChange: + "textDocument": {"uri": "file:/test.carbon"}, + "contentChanges": [ + {"range": {"start": {"line": 3, "character": 0}, + "end": {"line": 3, "character": 0}}, + "text": "\nfn FourthFunction() {}\n"} + ] +]] +[[@LSP-NOTIFY:textDocument/didChange: + "textDocument": {"uri": "file:/test.carbon"}, + "contentChanges": [ + {"range": {"start": {"line": 0, "character": 0}, + "end": {"line": 0, "character": 0}}, + "text": "fn FirstFunction() {}\n\n"} + ] +]] +[[@LSP-CALL:textDocument/documentSymbol: + "textDocument": {"uri": "file:/test.carbon"} +]] +[[@LSP-NOTIFY:textDocument/didChange: + "textDocument": {"uri": "file:/test.carbon"}, + "contentChanges": [ + {"text": "fn Foo() {}\n\nfn Bar() {}\n"} + ] +]] +[[@LSP-CALL:textDocument/documentSymbol: + "textDocument": {"uri": "file:/test.carbon"} +]] +[[@LSP-CALL:shutdown]] +[[@LSP-NOTIFY:exit]] + +// --- AUTOUPDATE-SPLIT + +// 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: 144{{\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:///test.carbon" +// CHECK:STDOUT: } +// CHECK:STDOUT: }Content-Length: 144{{\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:///test.carbon" +// CHECK:STDOUT: } +// CHECK:STDOUT: }Content-Length: 144{{\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:///test.carbon" +// CHECK:STDOUT: } +// CHECK:STDOUT: }Content-Length: 144{{\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:///test.carbon" +// CHECK:STDOUT: } +// CHECK:STDOUT: }Content-Length: 1741{{\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": "FirstFunction", +// CHECK:STDOUT: "range": { +// CHECK:STDOUT: "end": { +// CHECK:STDOUT: "character": 21, +// 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": 16, +// 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": "SecondFunction", +// CHECK:STDOUT: "range": { +// CHECK:STDOUT: "end": { +// CHECK:STDOUT: "character": 22, +// 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": 17, +// 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": "ThirdFunction", +// CHECK:STDOUT: "range": { +// CHECK:STDOUT: "end": { +// CHECK:STDOUT: "character": 21, +// CHECK:STDOUT: "line": 4 +// CHECK:STDOUT: }, +// CHECK:STDOUT: "start": { +// CHECK:STDOUT: "character": 0, +// CHECK:STDOUT: "line": 4 +// CHECK:STDOUT: } +// CHECK:STDOUT: }, +// CHECK:STDOUT: "selectionRange": { +// CHECK:STDOUT: "end": { +// CHECK:STDOUT: "character": 16, +// CHECK:STDOUT: "line": 4 +// CHECK:STDOUT: }, +// CHECK:STDOUT: "start": { +// CHECK:STDOUT: "character": 3, +// CHECK:STDOUT: "line": 4 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: }, +// CHECK:STDOUT: { +// CHECK:STDOUT: "kind": 12, +// CHECK:STDOUT: "name": "FourthFunction", +// CHECK:STDOUT: "range": { +// CHECK:STDOUT: "end": { +// CHECK:STDOUT: "character": 22, +// CHECK:STDOUT: "line": 6 +// CHECK:STDOUT: }, +// CHECK:STDOUT: "start": { +// CHECK:STDOUT: "character": 0, +// CHECK:STDOUT: "line": 6 +// CHECK:STDOUT: } +// CHECK:STDOUT: }, +// CHECK:STDOUT: "selectionRange": { +// CHECK:STDOUT: "end": { +// CHECK:STDOUT: "character": 17, +// CHECK:STDOUT: "line": 6 +// CHECK:STDOUT: }, +// CHECK:STDOUT: "start": { +// CHECK:STDOUT: "character": 3, +// CHECK:STDOUT: "line": 6 +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: ] +// CHECK:STDOUT: }Content-Length: 144{{\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:///test.carbon" +// CHECK:STDOUT: } +// CHECK:STDOUT: }Content-Length: 873{{\r}} +// CHECK:STDOUT: {{\r}} +// CHECK:STDOUT: { +// CHECK:STDOUT: "id": 3, +// CHECK:STDOUT: "jsonrpc": "2.0", +// CHECK:STDOUT: "result": [ +// CHECK:STDOUT: { +// CHECK:STDOUT: "kind": 12, +// CHECK:STDOUT: "name": "Foo", +// CHECK:STDOUT: "range": { +// CHECK:STDOUT: "end": { +// CHECK:STDOUT: "character": 11, +// 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": 6, +// 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": "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": 4, +// CHECK:STDOUT: "jsonrpc": "2.0", +// CHECK:STDOUT: "result": null +// CHECK:STDOUT: } diff --git a/toolchain/language_server/testdata/text_document/open_change_close.carbon b/toolchain/language_server/testdata/text_document/open_change_close.carbon index 8b54f1c12aa3..a65b51bc2f52 100644 --- a/toolchain/language_server/testdata/text_document/open_change_close.carbon +++ b/toolchain/language_server/testdata/text_document/open_change_close.carbon @@ -34,7 +34,7 @@ // CHECK:STDOUT: "result": { // CHECK:STDOUT: "capabilities": { // CHECK:STDOUT: "documentSymbolProvider": true, -// CHECK:STDOUT: "textDocumentSync": 1 +// CHECK:STDOUT: "textDocumentSync": 2 // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: }Content-Length: 144{{\r}} diff --git a/toolchain/language_server/testdata/text_document/open_duplicate.carbon b/toolchain/language_server/testdata/text_document/open_duplicate.carbon index 4f48a05babe5..68959071c987 100644 --- a/toolchain/language_server/testdata/text_document/open_duplicate.carbon +++ b/toolchain/language_server/testdata/text_document/open_duplicate.carbon @@ -33,7 +33,7 @@ // CHECK:STDOUT: "result": { // CHECK:STDOUT: "capabilities": { // CHECK:STDOUT: "documentSymbolProvider": true, -// CHECK:STDOUT: "textDocumentSync": 1 +// CHECK:STDOUT: "textDocumentSync": 2 // CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: }Content-Length: 144{{\r}}