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 00a64a7368..083d87b2dc 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 @@ -16,12 +16,14 @@ import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; @@ -77,8 +79,11 @@ import org.eclipse.lsp4j.DidSaveTextDocumentParams; import org.eclipse.lsp4j.Position; import org.eclipse.lsp4j.Range; +import org.eclipse.lsp4j.RenameFile; import org.eclipse.lsp4j.TextDocumentContentChangeEvent; +import org.eclipse.lsp4j.WorkspaceEdit; import org.eclipse.lsp4j.jsonrpc.ResponseErrorException; +import org.eclipse.lsp4j.jsonrpc.messages.Either; import org.eclipse.lsp4j.jsonrpc.messages.ResponseError; import org.eclipse.osgi.util.NLS; import org.eclipse.text.edits.DeleteEdit; @@ -91,6 +96,7 @@ public abstract class BaseDocumentLifeCycleHandler { public static final String DOCUMENT_LIFE_CYCLE_JOBS = "DocumentLifeCycleJobs"; public static final String PUBLISH_DIAGNOSTICS_JOBS = "DocumentLifeCyclePublishDiagnosticsJobs"; + public static final String RENAME_FILE_TO_TYPE = "renameFileToType"; /** * The max & init value of adaptive debounce time for document lifecycle job. @@ -355,7 +361,8 @@ public void didChange(DidChangeTextDocumentParams params) { } public void didSave(DidSaveTextDocumentParams params) { - lastSyncedDocumentLengths.remove(params.getTextDocument().getUri()); + String documentUri = params.getTextDocument().getUri(); + lastSyncedDocumentLengths.remove(documentUri); IFile file = JDTUtils.findFile(params.getTextDocument().getUri()); if (file != null && !Objects.equals(ProjectsManager.getDefaultProject(), file.getProject())) { // no need for a workspace runnable, change is trivial @@ -371,6 +378,25 @@ public void didSave(DidSaveTextDocumentParams params) { } } + public static void handleFileRenameForTypeDeclaration(String documentUri) { + ICompilationUnit cu = JDTUtils.resolveCompilationUnit(documentUri); + CompilationUnit astRoot = CoreASTProvider.getInstance().getAST(cu, CoreASTProvider.WAIT_YES, null); + IProblem[] problems = astRoot.getProblems(); + Optional desiredProblem = Arrays.stream(problems).filter(p -> p.getID() == IProblem.PublicClassMustMatchFileName).findFirst(); + if (desiredProblem.isPresent()) { + IProblem renameProblem = desiredProblem.get(); + String newName = renameProblem.getArguments()[1]; + String oldName = cu.getElementName(); + String newUri = documentUri.replace(oldName, newName + ".java"); + WorkspaceEdit edit = new WorkspaceEdit(List.of(Either.forRight(new RenameFile(documentUri, newUri)))); + edit.setChanges(Collections.emptyMap()); + final boolean applyNow = JavaLanguageServerPlugin.getPreferencesManager().getClientPreferences().isWorkspaceApplyEditSupported(); + if (applyNow) { + JavaLanguageServerPlugin.getInstance().getClientConnection().applyWorkspaceEdit(edit); + } + } + } + public ICompilationUnit handleOpen(DidOpenTextDocumentParams params) { String uri = params.getTextDocument().getUri(); ICompilationUnit unit = resolveCompilationUnit(uri); 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 75680f38ff..80420414ae 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 @@ -20,6 +20,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; @@ -933,6 +934,19 @@ public CompletableFuture> willSaveWaitUntil(WillSaveTextDocumentP public void didSave(DidSaveTextDocumentParams params) { debugTrace(">> document/didSave"); documentLifeCycleHandler.didSave(params); + String documentUri = params.getTextDocument().getUri(); + Preferences preferences = preferenceManager.getPreferences(); + List lspCleanups = Collections.emptyList(); + if (preferences.getCleanUpActionsOnSaveEnabled()) { + lspCleanups = preferences.getCleanUpActions(); + } + + if (lspCleanups.contains(BaseDocumentLifeCycleHandler.RENAME_FILE_TO_TYPE)) { + computeAsync((monitor) -> { + DocumentLifeCycleHandler.handleFileRenameForTypeDeclaration(documentUri); + return null; + }); + } } @Override diff --git a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/SaveActionHandler.java b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/SaveActionHandler.java index a5a16db212..7caf6dbf82 100644 --- a/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/SaveActionHandler.java +++ b/org.eclipse.jdt.ls.core/src/org/eclipse/jdt/ls/core/internal/handlers/SaveActionHandler.java @@ -80,6 +80,7 @@ public List willSaveWaitUntil(WillSaveTextDocumentParams params, IProg Collection jdtSettingCleanups = getCleanupsFromJDTUIPreferences(jdtUiPreferences); cleanUpIds.addAll(canUseInternalSettings ? jdtSettingCleanups : lspCleanups); + cleanUpIds.remove(BaseDocumentLifeCycleHandler.RENAME_FILE_TO_TYPE); List cleanUpEdits = cleanUpRegistry.getEditsForAllActiveCleanUps(params.getTextDocument(), new ArrayList<>(cleanUpIds), monitor); edit.addAll(cleanUpEdits); return edit; @@ -102,6 +103,7 @@ public WorkspaceEdit performManualCleanupActions(TextDocumentIdentifier doc, IPr Collection jdtSettingCleanups = getCleanupsFromJDTUIPreferences(jdtUiPreferences); cleanUpIds.addAll(canUseInternalSettings ? jdtSettingCleanups : lspCleanups); + cleanUpIds.remove(BaseDocumentLifeCycleHandler.RENAME_FILE_TO_TYPE); List cleanUpEdits = cleanUpRegistry.getEditsForAllActiveCleanUps(doc, new ArrayList<>(cleanUpIds), monitor); edit.addAll(cleanUpEdits); Map> editMap = new HashMap<>(); 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 e41d3046ce..a5457ef35c 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 @@ -180,7 +180,11 @@ public boolean visit(IResourceDelta delta) throws CoreException { } if (!cu.isWorkingCopy()) { markers = resource.findMarkers(null, false, IResource.DEPTH_ONE); - document = JsonRpcHelpers.toDocument(cu.getBuffer()); + try { + document = JsonRpcHelpers.toDocument(cu.getBuffer()); + } catch (JavaModelException e) { + // do nothing + } } else if (handler != null) { handler.triggerValidation(cu); }