From fcb67f7b4d5be9da7b08c5d4ac4cf6d1f921afdb Mon Sep 17 00:00:00 2001 From: Jaime Wren Date: Tue, 30 Jan 2024 17:35:24 +0100 Subject: [PATCH] IJ-CR-131092 the first step in Dart macro support: introduce DartAnalysisServerService.lspMessage_dart_textDocumentContent() close #903 (cherry picked from commit 1c825c586c0197369497d129a0040c2eeb7b9ddc) GitOrigin-RevId: ef50e62cad6e50daf55b483088cf79b8c6b1cf8d --- .../analyzer/DartAnalysisServerService.java | 32 +++++++++++++ .../DartLspTextDocumentContentConsumer.java | 28 +++++++++++ .../remote/RemoteAnalysisServerImpl.java | 14 ++++++ .../DartLspTextDocumentContentProcessor.java | 47 +++++++++++++++++++ .../remote/utilities/RequestUtilities.java | 40 ++++++++++++++++ 5 files changed, 161 insertions(+) create mode 100644 Dart/thirdPartySrc/analysisServer/com/google/dart/server/DartLspTextDocumentContentConsumer.java create mode 100644 Dart/thirdPartySrc/analysisServer/com/google/dart/server/internal/remote/processor/DartLspTextDocumentContentProcessor.java diff --git a/Dart/src/com/jetbrains/lang/dart/analyzer/DartAnalysisServerService.java b/Dart/src/com/jetbrains/lang/dart/analyzer/DartAnalysisServerService.java index cda272dfcd1..79b8e4070f6 100644 --- a/Dart/src/com/jetbrains/lang/dart/analyzer/DartAnalysisServerService.java +++ b/Dart/src/com/jetbrains/lang/dart/analyzer/DartAnalysisServerService.java @@ -116,6 +116,7 @@ public final class DartAnalysisServerService implements Disposable { private static final long EXECUTION_CREATE_CONTEXT_TIMEOUT = TimeUnit.SECONDS.toMillis(1); private static final long EXECUTION_MAP_URI_TIMEOUT = TimeUnit.SECONDS.toMillis(1); private static final long ANALYSIS_IN_TESTS_TIMEOUT = TimeUnit.SECONDS.toMillis(10); + private static final long LSP_MESSAGE_TEXT_DOCUMENT_CONTENT_TIMEOUT = TimeUnit.SECONDS.toMillis(50); private static final long TESTS_TIMEOUT_COEFF = 10; private static final Logger LOG = Logger.getInstance(DartAnalysisServerService.class); @@ -2034,6 +2035,37 @@ public void onError(final RequestError error) { return resultRef.get(); } + // LSP over Legacy Dart Analysis Server protocols + public @Nullable String lspMessage_dart_textDocumentContent(@NotNull String uri) { + RemoteAnalysisServerImpl server = myServer; + if (server == null) { + return null; + } + + Ref resultRef = new Ref<>(); + CountDownLatch latch = new CountDownLatch(1); + server.lspMessage_dart_textDocumentContent(uri, new DartLspTextDocumentContentConsumer() { + @Override + public void computedDocumentContents(String contents) { + resultRef.set(contents); + latch.countDown(); + } + + @Override + public void onError(RequestError error) { + logError("lspMessage_dart_textDocumentContent()", uri, error); + latch.countDown(); + } + }); + + awaitForLatchCheckingCanceled(server, latch, LSP_MESSAGE_TEXT_DOCUMENT_CONTENT_TIMEOUT); + + if (latch.getCount() > 0) { + logTookTooLongMessage("lspMessage_dart_textDocumentContent", LSP_MESSAGE_TEXT_DOCUMENT_CONTENT_TIMEOUT, uri); + } + return resultRef.get(); + } + private void startServer(@NotNull final DartSdk sdk) { if (DartPubActionBase.isInProgress()) return; // DartPubActionBase will start the server itself when finished diff --git a/Dart/thirdPartySrc/analysisServer/com/google/dart/server/DartLspTextDocumentContentConsumer.java b/Dart/thirdPartySrc/analysisServer/com/google/dart/server/DartLspTextDocumentContentConsumer.java new file mode 100644 index 00000000000..cf56922b30c --- /dev/null +++ b/Dart/thirdPartySrc/analysisServer/com/google/dart/server/DartLspTextDocumentContentConsumer.java @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2024, the Dart project authors. + * + * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.dart.server; + +import org.dartlang.analysis.server.protocol.RequestError; + +public interface DartLspTextDocumentContentConsumer extends Consumer { + + public void computedDocumentContents(String contents); + + /** + * If the file contents can't be sent back, some {@link RequestError} is passed back instead. + * + * @param requestError the reason why a result was not passed back + */ + public void onError(RequestError requestError); +} \ No newline at end of file diff --git a/Dart/thirdPartySrc/analysisServer/com/google/dart/server/internal/remote/RemoteAnalysisServerImpl.java b/Dart/thirdPartySrc/analysisServer/com/google/dart/server/internal/remote/RemoteAnalysisServerImpl.java index c6e7ec06d81..624cd629c46 100644 --- a/Dart/thirdPartySrc/analysisServer/com/google/dart/server/internal/remote/RemoteAnalysisServerImpl.java +++ b/Dart/thirdPartySrc/analysisServer/com/google/dart/server/internal/remote/RemoteAnalysisServerImpl.java @@ -606,6 +606,14 @@ public void received() { stopServer(); } + // + // LSP over Legacy Dart Analysis Server protocol + // + public void lspMessage_dart_textDocumentContent(String uri, DartLspTextDocumentContentConsumer consumer) { + String id = generateUniqueId(); + sendRequestToServer(id, RequestUtilities.generateLSPMessage_dart_textDocumentContent(id, uri), consumer); + } + /** * Starts the analysis server. * @@ -929,6 +937,12 @@ else if (consumer instanceof BasicConsumer) { else if (consumer instanceof JsonConsumer) { ((JsonConsumer)consumer).onResponse(resultObject, requestError); } + // + // LSP over Legacy DAS Dart Analysis Server protocol + // + else if (consumer instanceof DartLspTextDocumentContentConsumer) { + new DartLspTextDocumentContentProcessor((DartLspTextDocumentContentConsumer)consumer).process(resultObject, requestError); + } synchronized (consumerMapLock) { consumerMap.remove(idString); diff --git a/Dart/thirdPartySrc/analysisServer/com/google/dart/server/internal/remote/processor/DartLspTextDocumentContentProcessor.java b/Dart/thirdPartySrc/analysisServer/com/google/dart/server/internal/remote/processor/DartLspTextDocumentContentProcessor.java new file mode 100644 index 00000000000..a8c28c468f4 --- /dev/null +++ b/Dart/thirdPartySrc/analysisServer/com/google/dart/server/internal/remote/processor/DartLspTextDocumentContentProcessor.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2024, the Dart project authors. + * + * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.eclipse.org/legal/epl-v10.html + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + */ +package com.google.dart.server.internal.remote.processor; + +import com.google.dart.server.DartLspTextDocumentContentConsumer; +import com.google.gson.JsonObject; + +import org.dartlang.analysis.server.protocol.RequestError; + +/** + * Instances of {@code DartLspTextDocumentContentProcessor} translate JSON result objects for a given + * {@link LSPDartTextDocumentContentConsumer}. + * + * @coverage dart.server.remote + */ +public class DartLspTextDocumentContentProcessor extends ResultProcessor { + + private final DartLspTextDocumentContentConsumer consumer; + + public DartLspTextDocumentContentProcessor(DartLspTextDocumentContentConsumer consumer) { + this.consumer = consumer; + } + + public void process(JsonObject resultObject, RequestError requestError) { + if (resultObject != null) { + // Example: {"lspResponse":{"id":"1","jsonrpc":"2.0","result":{"content":"file contents"}}} + JsonObject lspResponse = resultObject.getAsJsonObject("lspResponse"); + JsonObject innerResultObject = lspResponse.getAsJsonObject("result"); + final String contents = innerResultObject.get("content").getAsString(); + consumer.computedDocumentContents(contents); + } + if (requestError != null) { + consumer.onError(requestError); + } + } +} \ No newline at end of file diff --git a/Dart/thirdPartySrc/analysisServer/com/google/dart/server/internal/remote/utilities/RequestUtilities.java b/Dart/thirdPartySrc/analysisServer/com/google/dart/server/internal/remote/utilities/RequestUtilities.java index e04ae76e36d..0f45954e0dc 100644 --- a/Dart/thirdPartySrc/analysisServer/com/google/dart/server/internal/remote/utilities/RequestUtilities.java +++ b/Dart/thirdPartySrc/analysisServer/com/google/dart/server/internal/remote/utilities/RequestUtilities.java @@ -1199,6 +1199,46 @@ private static String getRequestMethod(JsonObject request) { return null; } + // + // LSP over Legacy DAS (Dart Analysis Server) protocol below + // + public static final String LSP_DART_TEXT_DOCUMENT_CONTENT = "dart/textDocumentContent"; + + private static final String LSP_HANDLE = "lsp.handle"; + + public static final String LSP_JSONRPC = "jsonrpc"; + + public static final String LSP_JSONROC_VERSION = "2.0"; + + public static final String LSP_MESSAGE = "lspMessage"; + + /** + * Generate and return a LSP over Legacy DAS request. + * + * Example: + * {"id":"2","method":"lsp.handle","params": + * {"lspMessage": + * {"id":0,"jsonrpc":"2.0","method":"dart/textDocumentContent","params": + * {"position":{"character":7,"line":1}, + * "textDocument":{"uri":"some-uri"}}}}} + */ + private static JsonObject generateLSPMessage(String idValue, String lspMethod, JsonObject lspParams) { + JsonObject lspMessageParams = new JsonObject(); + lspMessageParams.addProperty(ID, idValue); + lspMessageParams.addProperty(LSP_JSONRPC, LSP_JSONROC_VERSION); + lspMessageParams.addProperty(METHOD, lspMethod); + lspMessageParams.add(PARAMS, lspParams); + JsonObject lspMessage = new JsonObject(); + lspMessage.add(LSP_MESSAGE, lspMessageParams); + return buildJsonObjectRequest(idValue, LSP_HANDLE, lspMessage); + } + + public static JsonObject generateLSPMessage_dart_textDocumentContent(String idValue, String uri) { + JsonObject lspParams = new JsonObject(); + lspParams.addProperty("uri", uri); + return generateLSPMessage(idValue, LSP_DART_TEXT_DOCUMENT_CONTENT, lspParams); + } + private RequestUtilities() { } }