Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,354 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.jetbrains.lang.dart.analyzer;

import com.google.dart.server.*;
import com.google.dart.server.internal.remote.RemoteAnalysisServerImpl;
import com.google.gson.JsonObject;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import org.dartlang.analysis.server.protocol.ImportedElements;
import org.dartlang.analysis.server.protocol.RefactoringOptions;
import org.dartlang.analysis.server.protocol.RequestError;
import org.dartlang.analysis.server.protocol.RuntimeCompletionExpression;
import org.dartlang.analysis.server.protocol.RuntimeCompletionVariable;
import org.dartlang.analysis.server.protocol.SourceEdit;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.List;
import java.util.Map;
import java.util.function.Function;

abstract class AbstractDartAnalysisClient implements DartAnalysisClient {
protected final @NotNull Project myProject;
protected final @NotNull RemoteAnalysisServerImpl myServer;
private final @NotNull LspTransport myLspTransport;

protected AbstractDartAnalysisClient(@NotNull Project project,
@NotNull AnalysisServerSocket socket,
@NotNull Function<RemoteAnalysisServerImpl, LspTransport> lspTransportFactory) {
myProject = project;
myServer = new DartAnalysisServerImpl(project, socket);
myLspTransport = lspTransportFactory.apply(myServer);
}

@Override
public void start() throws Exception {
myServer.start();
}

@Override
public boolean isSocketOpen() {
return myServer.isSocketOpen();
}

@Override
public void shutdown() {
try {
myServer.server_shutdown();
}
finally {
myLspTransport.dispose();
}
}

@Override
public void addAnalysisServerListener(@NotNull AnalysisServerListener listener) {
myServer.addAnalysisServerListener(listener);
}

@Override
public void removeAnalysisServerListener(@NotNull AnalysisServerListener listener) {
myServer.removeAnalysisServerListener(listener);
}

@Override
public void addRequestListener(@NotNull RequestListener listener) {
myServer.addRequestListener(listener);
}

@Override
public void removeRequestListener(@NotNull RequestListener listener) {
myServer.removeRequestListener(listener);
}

@Override
public void addResponseListener(@NotNull ResponseListener listener) {
myServer.addResponseListener(listener);
}

@Override
public void removeResponseListener(@NotNull ResponseListener listener) {
myServer.removeResponseListener(listener);
}

@Override
public void addStatusListener(@NotNull AnalysisServerStatusListener listener) {
myServer.addStatusListener(listener);
}

@Override
public void completion_setSubscriptions(@NotNull List<String> subscriptions) {
myServer.completion_setSubscriptions(subscriptions);
}

@Override
public void analysis_updateContent(@NotNull Map<String, Object> files, @NotNull UpdateContentConsumer consumer) {
myLspTransport.updateContent(files, consumer);
}

@Override
public void analysis_setAnalysisRoots(@NotNull List<String> included, @NotNull List<String> excluded, Map<String, String> packageRoots) {
myServer.analysis_setAnalysisRoots(included, excluded, packageRoots);
}

@Override
public void analysis_getHover(@NotNull String file, int offset, @NotNull GetHoverConsumer consumer) {
myServer.analysis_getHover(file, offset, consumer);
}

@Override
public void analysis_getNavigation(@NotNull String file, int offset, int length, @NotNull GetNavigationConsumer consumer) {
myServer.analysis_getNavigation(file, offset, length, consumer);
}

@Override
public void edit_getAssists(@NotNull String file, int offset, int length, @NotNull GetAssistsConsumer consumer) {
myServer.edit_getAssists(file, offset, length, consumer);
}

@Override
public void edit_isPostfixCompletionApplicable(@NotNull String file,
@NotNull String key,
int offset,
@NotNull IsPostfixCompletionApplicableConsumer consumer) {
myServer.edit_isPostfixCompletionApplicable(file, key, offset, consumer);
}

@Override
public void edit_listPostfixCompletionTemplates(@NotNull ListPostfixCompletionTemplatesConsumer consumer) {
myServer.edit_listPostfixCompletionTemplates(consumer);
}

@Override
public void edit_getPostfixCompletion(@NotNull String file,
@NotNull String key,
int offset,
@NotNull GetPostfixCompletionConsumer consumer) {
myServer.edit_getPostfixCompletion(file, key, offset, consumer);
}

@Override
public void edit_getStatementCompletion(@NotNull String file, int offset, @NotNull GetStatementCompletionConsumer consumer) {
myServer.edit_getStatementCompletion(file, offset, consumer);
}

@Override
public void diagnostic_getServerPort(@NotNull GetServerPortConsumer consumer) {
myLspTransport.diagnosticServer(consumer);
}

@Override
public void edit_getFixes(@NotNull String file, int offset, @NotNull GetFixesConsumer consumer) {
myServer.edit_getFixes(file, offset, consumer);
}

@Override
public void search_findElementReferences(@NotNull String file,
int offset,
boolean includePotential,
@NotNull FindElementReferencesConsumer consumer) {
myServer.search_findElementReferences(file, offset, includePotential, consumer);
}

@Override
public void search_getTypeHierarchy(@NotNull String file, int offset, boolean superOnly, @NotNull GetTypeHierarchyConsumer consumer) {
myServer.search_getTypeHierarchy(file, offset, superOnly, consumer);
}

@Override
public void completion_getSuggestionDetails(@NotNull String file,
int id,
@NotNull String label,
int offset,
@NotNull GetSuggestionDetailsConsumer consumer) {
myServer.completion_getSuggestionDetails(file, id, label, offset, consumer);
}

@Override
public void completion_getSuggestionDetails2(@NotNull String file,
int offset,
@NotNull String completion,
@NotNull String libraryUri,
@NotNull GetSuggestionDetailsConsumer2 consumer) {
myServer.completion_getSuggestionDetails2(file, offset, completion, libraryUri, consumer);
}

@Override
public void completion_getSuggestions(@NotNull String file, int offset, @NotNull GetSuggestionsConsumer consumer) {
myServer.completion_getSuggestions(file, offset, consumer);
}

@Override
public void completion_getSuggestions2(@NotNull String file,
int offset,
int maxResults,
@NotNull String completionCaseMatchingMode,
@NotNull String completionMode,
int invocationCount,
int timeout,
@NotNull GetSuggestionsConsumer2 consumer) {
myServer.completion_getSuggestions2(file, offset, maxResults, completionCaseMatchingMode, completionMode, invocationCount, timeout, consumer);
}

@Override
public void edit_format(@NotNull String file,
int selectionOffset,
int selectionLength,
int lineLength,
@NotNull FormatConsumer consumer) {
String fileUri = VirtualFileManager.constructUrl("file", file);
String fileContent = readFileContent(file);
if (fileContent != null) {
myLspTransport.format(fileUri, fileContent, selectionOffset, selectionLength, lineLength, new LspTransport.FormatHandler() {
@Override
public void computedFormat(@NotNull List<SourceEdit> edits, int selOffset, int selLen) {
consumer.computedFormat(edits, selOffset, selLen);
}

@Override
public void onError(@NotNull RequestError requestError) {
consumer.onError(requestError);
}
});
}
else {
myServer.edit_format(file, selectionOffset, selectionLength, lineLength, consumer);
}
}

@Override
public void analysis_getImportedElements(@NotNull String file, int offset, int length, @NotNull GetImportedElementsConsumer consumer) {
myServer.analysis_getImportedElements(file, offset, length, consumer);
}

@Override
public void edit_importElements(@NotNull String file,
@NotNull List<ImportedElements> elements,
int offset,
@NotNull ImportElementsConsumer consumer) {
myServer.edit_importElements(file, elements, offset, consumer);
}

@Override
public void edit_getRefactoring(@NotNull String kind,
@NotNull String file,
int offset,
int length,
boolean validateOnly,
RefactoringOptions options,
@NotNull GetRefactoringConsumer consumer) {
myServer.edit_getRefactoring(kind, file, offset, length, validateOnly, options, consumer);
}

@Override
public void edit_organizeDirectives(@NotNull String file, @NotNull OrganizeDirectivesConsumer consumer) {
myServer.edit_organizeDirectives(file, consumer);
}

@Override
public void edit_sortMembers(@NotNull String file, @NotNull SortMembersConsumer consumer) {
myServer.edit_sortMembers(file, consumer);
}

@Override
public void analysis_reanalyze() {
myLspTransport.reanalyze();
}

@Override
public void analysis_setPriorityFiles(@NotNull List<String> files) {
myServer.analysis_setPriorityFiles(files);
}

@Override
public void analysis_setSubscriptions(@NotNull Map<String, List<String>> subscriptions) {
myServer.analysis_setSubscriptions(subscriptions);
}

@Override
public void execution_createContext(@NotNull String contextRoot, @NotNull CreateContextConsumer consumer) {
myServer.execution_createContext(contextRoot, consumer);
}

@Override
public void execution_deleteContext(@NotNull String contextId) {
myServer.execution_deleteContext(contextId);
}

@Override
public void execution_getSuggestions(@NotNull String code,
int offset,
@NotNull String contextFile,
int contextOffset,
@NotNull List<RuntimeCompletionVariable> variables,
List<RuntimeCompletionExpression> expressions,
@NotNull GetRuntimeCompletionConsumer consumer) {
myServer.execution_getSuggestions(code, offset, contextFile, contextOffset, variables, expressions, consumer);
}

@Override
public void execution_mapUri(@NotNull String id, String file, String uri, @NotNull MapUriConsumer consumer) {
myServer.execution_mapUri(id, file, uri, consumer);
}

@Override
public void server_setSubscriptions(@NotNull List<String> subscriptions) {
myServer.server_setSubscriptions(subscriptions);
}

@Override
public void requestTextDocumentContent(@NotNull String fileUri,
@NotNull TextDocumentContentHandler handler) {
myLspTransport.requestTextDocumentContent(fileUri, handler);
}

@Override
public void connectToDtd(@NotNull String uri) {
myLspTransport.connectToDtd(uri);
}

@Override
public void configureServerFeatures(boolean supportsUris, boolean supportsWorkspaceApplyEdits) {
myLspTransport.configureServerFeatures(supportsUris, supportsWorkspaceApplyEdits);
}

@Override
public @NotNull String generateUniqueId() {
return myServer.generateUniqueId();
}

@Override
public void sendRequestToServer(@NotNull String id, @NotNull JsonObject request) {
myServer.sendRequestToServer(id, request);
}

@Override
public void sendRequestToServer(@NotNull String id, @NotNull JsonObject request, @NotNull Consumer consumer) {
myServer.sendRequestToServer(id, request, consumer);
}

private @Nullable String readFileContent(@NotNull String filePath) {
return ReadAction.compute(() -> {
VirtualFile vf = LocalFileSystem.getInstance().findFileByPath(filePath);
if (vf == null) return null;
Document doc = FileDocumentManager.getInstance().getDocument(vf);
return doc != null ? doc.getText() : null;
});
}
}
Loading