diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/BaseJDTLanguageServer.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/BaseJDTLanguageServer.java index b83b5595d9..d0aa5f7b32 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/BaseJDTLanguageServer.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/BaseJDTLanguageServer.java @@ -21,6 +21,8 @@ import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jdt.ls.core.internal.JavaClientConnection.JavaLanguageClient; +import org.eclipse.jdt.ls.core.internal.handlers.CompletionHandler; +import org.eclipse.jdt.ls.core.internal.preferences.PreferenceManager; import org.eclipse.lsp4j.Registration; import org.eclipse.lsp4j.RegistrationParams; import org.eclipse.lsp4j.Unregistration; @@ -75,6 +77,10 @@ public void registerCapability(String id, String method, Object options) { } } + public CompletionHandler createCompletionHandler(PreferenceManager preferences) { + return new CompletionHandler(preferences); + } + protected void toggleCapability(boolean enabled, String id, String capability, Object options) { if (enabled) { registerCapability(id, capability, options); diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/JDTDelegateCommandHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/JDTDelegateCommandHandler.java index 60fc5f01f4..46bce7ccba 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/JDTDelegateCommandHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/JDTDelegateCommandHandler.java @@ -191,7 +191,7 @@ public Object executeCommand(String commandId, List arguments, IProgress return false; } case "java.completion.onDidSelect": - CompletionHandler completionHandler = new CompletionHandler(JavaLanguageServerPlugin.getPreferencesManager()); + CompletionHandler completionHandler = JavaLanguageServerPlugin.getInstance().getProtocol().createCompletionHandler(JavaLanguageServerPlugin.getPreferencesManager()); String requestId = (String) arguments.get(0); String proposalId = (String) arguments.get(1); completionHandler.onDidCompletionItemSelect(requestId, proposalId); diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/JavaLanguageServerPlugin.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/JavaLanguageServerPlugin.java index dbc02eed0b..0ec352ba23 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/JavaLanguageServerPlugin.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/JavaLanguageServerPlugin.java @@ -366,13 +366,15 @@ public IProxyService getProxyService() { return null; } - private void startConnection() throws IOException { + private void startConnection(BaseJDTLanguageServer protocol) throws IOException { TelemetryManager telemetryManager = new TelemetryManager(); boolean firstTimeInitialization = ProjectUtils.getAllProjects().length == 0; telemetryManager.onLanguageServerStart(System.currentTimeMillis(), firstTimeInitialization); Launcher launcher; ExecutorService executorService = getExecutorService(); - if (JDTEnvironmentUtils.isSyntaxServer()) { + if (protocol != null) { + this.protocol = protocol; + } else if (JDTEnvironmentUtils.isSyntaxServer()) { protocol = new SyntaxLanguageServer(contentProviderManager, projectsManager, preferenceManager); } else { protocol = new JDTLanguageServer(projectsManager, preferenceManager, telemetryManager); @@ -488,10 +490,10 @@ public static void sendStatus(ServiceStatus serverStatus, String status) { } } - static void startLanguageServer(LanguageServerApplication newLanguageServer) throws IOException { + public static void startLanguageServer(LanguageServerApplication newLanguageServer, BaseJDTLanguageServer protocol) throws IOException { if (pluginInstance != null) { pluginInstance.languageServer = newLanguageServer; - pluginInstance.startConnection(); + pluginInstance.startConnection(protocol); } } diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/LanguageServerApplication.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/LanguageServerApplication.java index 8a54a5d058..965e7bc647 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/LanguageServerApplication.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/LanguageServerApplication.java @@ -17,6 +17,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; +import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.text.SimpleDateFormat; @@ -44,7 +45,7 @@ public class LanguageServerApplication implements IApplication { @Override public Object start(IApplicationContext context) throws Exception { prepareStreams(); - JavaLanguageServerPlugin.startLanguageServer(this); + startLanguageServer(); if (JavaLanguageServerPlugin.getInstance().getProtocol() instanceof JDTLanguageServer server) { progressReporterManager = server.getProgressReporterManager(); if (progressReporterManager != null) { @@ -69,6 +70,10 @@ public Object start(IApplicationContext context) throws Exception { return IApplication.EXIT_OK; } + protected void startLanguageServer() throws IOException { + JavaLanguageServerPlugin.startLanguageServer(this, null); + } + @Override public void stop() { synchronized (waitLock) { diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/BaseDocumentLifeCycleHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/BaseDocumentLifeCycleHandler.java index d5d8edd524..2d7de123dd 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/BaseDocumentLifeCycleHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/BaseDocumentLifeCycleHandler.java @@ -165,7 +165,7 @@ public boolean belongsTo(Object family) { public abstract ICompilationUnit resolveCompilationUnit(String uri); - protected void triggerValidation(ICompilationUnit cu) throws JavaModelException { + public void triggerValidation(ICompilationUnit cu) throws JavaModelException { triggerValidation(cu, getDocumentLifecycleDelay()); } diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandler.java index 4a6172ebdb..86ff6fb461 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/CompletionHandler.java @@ -116,8 +116,7 @@ public Either, CompletionList> completion(CompletionParams long startTime = System.currentTimeMillis(); CompletionList $ = null; try { - ICompilationUnit unit = JDTUtils.resolveCompilationUnit(params.getTextDocument().getUri()); - $ = this.computeContentAssist(unit, params, monitor); + $ = completeContentAssist(params, monitor); } catch (OperationCanceledException ignorable) { // No need to pollute logs when query is cancelled monitor.setCanceled(true); @@ -172,6 +171,11 @@ public Either, CompletionList> completion(CompletionParams return Either.forRight($); } + protected CompletionList completeContentAssist(CompletionParams params, IProgressMonitor monitor) throws JavaModelException { + ICompilationUnit unit = JDTUtils.resolveCompilationUnit(params.getTextDocument().getUri()); + return this.computeContentAssist(unit, params, monitor); + } + @SuppressWarnings("unchecked") public void onDidCompletionItemSelect(String requestId, String proposalId) throws CoreException { triggerSignatureHelp(); diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/InitHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/InitHandler.java index 91569da93c..5ecd14119a 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/InitHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/InitHandler.java @@ -67,7 +67,7 @@ /** * Handler for the VS Code extension initialization */ -final public class InitHandler extends BaseInitHandler { +public class InitHandler extends BaseInitHandler { private static final String BUNDLES_KEY = "bundles"; private JavaClientConnection connection; diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java index 9e47bbeb09..1d858c0a07 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/JDTLanguageServer.java @@ -282,7 +282,7 @@ public ProgressReporterManager getProgressReporterManager() { public CompletableFuture initialize(InitializeParams params) { logInfo(">> initialize"); status = ServiceStatus.Starting; - InitHandler handler = new InitHandler(pm, preferenceManager, client, commandHandler, telemetryManager); + InitHandler handler = createInitHandler(); return CompletableFuture.completedFuture(handler.initialize(params)); } @@ -335,7 +335,7 @@ public IStatus run(IProgressMonitor monitor) { JobHelpers.waitForBuildJobs(60 * 60 * 1000); // 1 hour telemetryManager.onBuildFinished(System.currentTimeMillis()); - workspaceDiagnosticsHandler = new WorkspaceDiagnosticsHandler(JDTLanguageServer.this.client, pm, preferenceManager.getClientPreferences(), documentLifeCycleHandler); + workspaceDiagnosticsHandler = createWorkspaceDiagnosticsHandler(); workspaceDiagnosticsHandler.addResourceChangeListener(); workspaceDiagnosticsHandler.publishDiagnostics(monitor); classpathUpdateHandler = new ClasspathUpdateHandler(JDTLanguageServer.this.client, documentLifeCycleHandler); @@ -627,7 +627,7 @@ public CompletableFuture executeCommand(ExecuteCommandParams params) { public CompletableFuture, CompletionList>> completion(CompletionParams position) { debugTrace(">> document/completion"); try { - CompletionHandler handler = new CompletionHandler(preferenceManager); + CompletionHandler handler = createCompletionHandler(preferenceManager); IProgressMonitor monitor = new NullProgressMonitor(); if (Boolean.getBoolean(JAVA_LSP_JOIN_ON_COMPLETION)) { waitForLifecycleJobs(monitor); @@ -1264,4 +1264,15 @@ public boolean isEventHandlerEmpty() { return this.workspaceEventHandler.isEmpty(); } + protected DocumentLifeCycleHandler getDocumentLifeCycleHandler() { + return documentLifeCycleHandler; + } + + public InitHandler createInitHandler() { + return new InitHandler(pm, preferenceManager, client, commandHandler, telemetryManager); + } + + public WorkspaceDiagnosticsHandler createWorkspaceDiagnosticsHandler() { + return new WorkspaceDiagnosticsHandler(client, pm, preferenceManager.getClientPreferences(), documentLifeCycleHandler); + } } diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandler.java index 40feb23c67..b4a8e96ce2 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/WorkspaceDiagnosticsHandler.java @@ -75,7 +75,7 @@ * */ @SuppressWarnings("restriction") -public final class WorkspaceDiagnosticsHandler implements IResourceChangeListener, IResourceDeltaVisitor { +public class WorkspaceDiagnosticsHandler implements IResourceChangeListener, IResourceDeltaVisitor { public static final String PROJECT_CONFIGURATION_IS_NOT_UP_TO_DATE_WITH_POM_XML = "Project configuration is not up-to-date with pom.xml, requires an update."; private final JavaClientConnection connection; @@ -209,7 +209,7 @@ else if (projectsManager.isBuildFile(file)) { return false; } - private void publishMarkers(IProject project, IMarker[] markers) throws CoreException { + protected void publishMarkers(IProject project, IMarker[] markers) throws CoreException { Range range = new Range(new Position(0, 0), new Position(0, 0)); List projectMarkers = new ArrayList<>(markers.length); @@ -447,7 +447,7 @@ public static List toDiagnosticsArray(IDocument document, IMarker[] return diagnostics; } - private static boolean isInteresting(IMarker marker) { + protected static boolean isInteresting(IMarker marker) { return JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences().excludedMarkerTypes().stream().noneMatch(markerType -> { try { return marker.isSubtypeOf(markerType); @@ -584,11 +584,11 @@ private static DiagnosticSeverity convertSeverity(int severity) { return DiagnosticSeverity.Information; } - private void cleanUpDiagnostics(IResource resource) { + protected void cleanUpDiagnostics(IResource resource) { cleanUpDiagnostics(resource, false); } - private void cleanUpDiagnostics(IResource resource, boolean addTrailingSlash) { + protected void cleanUpDiagnostics(IResource resource, boolean addTrailingSlash) { String uri = JDTUtils.getFileURI(resource); if (uri != null) { if (addTrailingSlash && !uri.endsWith("/")) { @@ -598,7 +598,7 @@ private void cleanUpDiagnostics(IResource resource, boolean addTrailingSlash) { } } - private boolean isSupportedDiagnosticsResource(IResource resource) { + protected boolean isSupportedDiagnosticsResource(IResource resource) { if (resource.getType() == IResource.PROJECT) { return true; } diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/PreferenceManager.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/PreferenceManager.java index 7fd239a070..9c81e02da4 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/PreferenceManager.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/preferences/PreferenceManager.java @@ -76,6 +76,8 @@ */ public class PreferenceManager { + private static final boolean KEEP_JDT_PREFERENCES = Boolean.getBoolean("org.eclipse.jdt.ls_keepJDTPreferences"); + private Preferences preferences ; private static final String CUSTOM_CODE_TEMPLATES = IConstants.PLUGIN_ID + ".custom_code_templates"; private ClientPreferences clientPreferences; @@ -95,9 +97,6 @@ public PreferenceManager() { * functionality. */ public static void initialize() { - // Update JavaCore options - initializeJavaCoreOptions(); - // Initialize default preferences IEclipsePreferences defEclipsePrefs = DefaultScope.INSTANCE.getNode(IConstants.PLUGIN_ID); defEclipsePrefs.put("org.eclipse.jdt.ui.typefilter.enabled", ""); @@ -105,8 +104,6 @@ public static void initialize() { defEclipsePrefs.put(MembersOrderPreferenceCacheCommon.APPEARANCE_MEMBER_SORT_ORDER, JavaLanguageServerPlugin.DEFAULT_MEMBER_SORT_ORDER); defEclipsePrefs.put(MembersOrderPreferenceCacheCommon.APPEARANCE_VISIBILITY_SORT_ORDER, JavaLanguageServerPlugin.DEFAULT_VISIBILITY_SORT_ORDER); defEclipsePrefs.put(CodeGenerationSettingsConstants.CODEGEN_USE_OVERRIDE_ANNOTATION, Boolean.TRUE.toString()); - IEclipsePreferences fDefaultPreferenceStore = DefaultScope.INSTANCE.getNode(JavaManipulation.getPreferenceNodeId()); - fDefaultPreferenceStore.put(JavaManipulationPlugin.CODEASSIST_FAVORITE_STATIC_MEMBERS, String.join(";", Preferences.JAVA_COMPLETION_FAVORITE_MEMBERS_DEFAULT)); defEclipsePrefs.put(StubUtility.CODEGEN_KEYWORD_THIS, Boolean.FALSE.toString()); defEclipsePrefs.put(StubUtility.CODEGEN_IS_FOR_GETTERS, Boolean.TRUE.toString()); @@ -120,6 +117,16 @@ public static void initialize() { defEclipsePrefs.put("recommenders.chain.ignore_types", ""); //$NON-NLS-1$ defEclipsePrefs.put("PREF_USE_IMPLEMENTORS", Boolean.TRUE.toString()); + if (KEEP_JDT_PREFERENCES) { + return; + } + + // Update JavaCore options + initializeJavaCoreOptions(); + + IEclipsePreferences fDefaultPreferenceStore = DefaultScope.INSTANCE.getNode(JavaManipulation.getPreferenceNodeId()); + fDefaultPreferenceStore.put(JavaManipulationPlugin.CODEASSIST_FAVORITE_STATIC_MEMBERS, String.join(";", Preferences.JAVA_COMPLETION_FAVORITE_MEMBERS_DEFAULT)); + ContextTypeRegistry registry = new ContextTypeRegistry(); // Register standard context types from JDT CodeTemplateContextType.registerContextTypes(registry); diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/syntaxserver/SyntaxLanguageServer.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/syntaxserver/SyntaxLanguageServer.java index 0137116927..2ae2eec4e2 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/syntaxserver/SyntaxLanguageServer.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/syntaxserver/SyntaxLanguageServer.java @@ -413,7 +413,7 @@ public CompletableFuture hover(HoverParams position) { @Override public CompletableFuture, CompletionList>> completion(CompletionParams position) { logInfo(">> document/completion"); - CompletionHandler handler = new CompletionHandler(preferenceManager); + CompletionHandler handler = JavaLanguageServerPlugin.getInstance().getProtocol().createCompletionHandler(preferenceManager); final IProgressMonitor[] monitors = new IProgressMonitor[1]; CompletableFuture, CompletionList>> result = computeAsync((monitor) -> { monitors[0] = monitor;