Skip to content

Commit

Permalink
support rename references
Browse files Browse the repository at this point in the history
Signed-off-by: Shi Chen <[email protected]>
  • Loading branch information
CsCherrYY committed Feb 22, 2023
1 parent 0e79bc4 commit 83d814d
Show file tree
Hide file tree
Showing 11 changed files with 214 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -383,4 +383,17 @@ public static IMarker createWarningMarker(String type, IResource resource, Strin
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING);
return marker;
}

/**
* Creates a simple info marker with the given type, id and status message to the given resource.
*/
public static IMarker createInfoMarker(String type, IResource resource, String message, int id, int start, int end) throws CoreException {
IMarker marker = resource.createMarker(type);
marker.setAttribute(IJavaModelMarker.ID, id);
marker.setAttribute(IMarker.MESSAGE, message);
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_INFO);
marker.setAttribute(IMarker.CHAR_START, start);
marker.setAttribute(IMarker.CHAR_END, end);
return marker;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ private CorrectionMessages() {
public static String LocalCorrectionsSubProcessor_hiding_field_label;
public static String LocalCorrectionsSubProcessor_rename_var_label;
public static String LocalCorrectionsSubProcessor_hiding_argument_label;
public static String LocalCorrectionsSubProcessor_manual_rename_label;
public static String LocalCorrectionsSubProcessor_setparenteses_description;
public static String LocalCorrectionsSubProcessor_setparenteses_instanceof_description;
public static String LocalCorrectionsSubProcessor_InferGenericTypeArguments;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ LocalCorrectionsSubProcessor_hiding_local_label=Rename local variable ''{0}''
LocalCorrectionsSubProcessor_hiding_field_label=Rename field ''{0}''
LocalCorrectionsSubProcessor_rename_var_label=Rename ''{0}''
LocalCorrectionsSubProcessor_hiding_argument_label=Rename argument ''{0}''
LocalCorrectionsSubProcessor_manual_rename_label=Rename usages of ''{0}'' to ''{1}''
LocalCorrectionsSubProcessor_setparenteses_description=Put ''{0}'' expression in parentheses
LocalCorrectionsSubProcessor_InferGenericTypeArguments=Infer Generic Type Arguments...
LocalCorrectionsSubProcessor_InferGenericTypeArguments_description=Start the 'Infer Generic Type Arguments' refactoring
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
import org.eclipse.jdt.ls.core.internal.corrections.proposals.ReplaceCorrectionProposal;
import org.eclipse.jdt.ls.core.internal.corrections.proposals.TypeMismatchSubProcessor;
import org.eclipse.jdt.ls.core.internal.corrections.proposals.UnresolvedElementsSubProcessor;
import org.eclipse.jdt.ls.core.internal.handlers.BaseDocumentLifeCycleHandler;
import org.eclipse.jdt.ls.core.internal.handlers.DocumentLifeCycleHandler;
import org.eclipse.jdt.ls.core.internal.handlers.OrganizeImportsHandler;
import org.eclipse.jdt.ls.core.internal.text.correction.ModifierCorrectionSubProcessor;
import org.eclipse.lsp4j.CodeActionKind;
Expand All @@ -75,7 +77,7 @@ private static int moveBack(int offset, int start, String ignoreCharacters, ICom
return start;
}

public List<ChangeCorrectionProposal> getCorrections(CodeActionParams params, IInvocationContext context, IProblemLocationCore[] locations) throws CoreException {
public List<ChangeCorrectionProposal> getCorrections(CodeActionParams params, IInvocationContext context, IProblemLocationCore[] locations, DocumentLifeCycleHandler documentLifeCycleHandler) throws CoreException {
if (locations == null || locations.length == 0) {
return Collections.emptyList();
}
Expand All @@ -84,7 +86,7 @@ public List<ChangeCorrectionProposal> getCorrections(CodeActionParams params, II
for (int i = 0; i < locations.length; i++) {
IProblemLocationCore curr = locations[i];
if (handledProblems(curr, locations, handledProblems)) {
process(params, context, curr, resultingCollections);
process(params, context, curr, resultingCollections, documentLifeCycleHandler);
}
}
return resultingCollections;
Expand All @@ -107,7 +109,7 @@ private static boolean handledProblems(IProblemLocationCore location, IProblemLo
return handledProblems.add(problemId);
}

private void process(CodeActionParams params, IInvocationContext context, IProblemLocationCore problem, Collection<ChangeCorrectionProposal> proposals) throws CoreException {
private void process(CodeActionParams params, IInvocationContext context, IProblemLocationCore problem, Collection<ChangeCorrectionProposal> proposals, DocumentLifeCycleHandler documentLifeCycleHandler) throws CoreException {
int id = problem.getProblemId();
if (id == 0) { // no proposals for none-problem locations
return;
Expand Down Expand Up @@ -668,7 +670,9 @@ private void process(CodeActionParams params, IInvocationContext context, IProbl
// TypeAnnotationSubProcessor.addMoveTypeAnnotationToTypeProposal(context,
// problem, proposals);
// break;

case BaseDocumentLifeCycleHandler.RENAME_REFERENCE_PROBLEM_ID:
LocalCorrectionsSubProcessor.getManualRenameCorrectionProposals(context, problem, proposals, documentLifeCycleHandler);
break;
default:
String str = problem.toString();
System.out.println(str);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,16 @@
package org.eclipse.jdt.ls.core.internal.corrections.proposals;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IType;
Expand Down Expand Up @@ -101,7 +105,9 @@
import org.eclipse.jdt.internal.ui.fix.UnnecessaryCodeCleanUpCore;
import org.eclipse.jdt.internal.ui.text.correction.IProblemLocationCore;
import org.eclipse.jdt.internal.ui.util.ASTHelper;
import org.eclipse.jdt.ls.core.internal.JDTUtils;
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
import org.eclipse.jdt.ls.core.internal.Messages;
import org.eclipse.jdt.ls.core.internal.corext.refactoring.surround.ExceptionAnalyzer;
import org.eclipse.jdt.ls.core.internal.corext.refactoring.surround.SurroundWithTryCatchRefactoring;
import org.eclipse.jdt.ls.core.internal.corrections.CorrectionMessages;
Expand All @@ -111,13 +117,18 @@
import org.eclipse.jdt.ls.core.internal.corrections.proposals.ChangeMethodSignatureProposal.ChangeDescription;
import org.eclipse.jdt.ls.core.internal.corrections.proposals.ChangeMethodSignatureProposal.InsertDescription;
import org.eclipse.jdt.ls.core.internal.corrections.proposals.ChangeMethodSignatureProposal.RemoveDescription;
import org.eclipse.jdt.ls.core.internal.handlers.BaseDocumentLifeCycleHandler;
import org.eclipse.jdt.ls.core.internal.handlers.DocumentLifeCycleHandler;
import org.eclipse.jdt.ls.core.internal.text.correction.CUCorrectionCommandProposal;
import org.eclipse.jdt.ls.core.internal.text.correction.ModifierCorrectionSubProcessor;
import org.eclipse.jdt.ls.core.internal.text.correction.QuickAssistProcessor;
import org.eclipse.lsp4j.CodeActionKind;
import org.eclipse.lsp4j.Range;

public class LocalCorrectionsSubProcessor {

private static final String ADD_STATIC_ACCESS_ID = "org.eclipse.jdt.ui.correction.changeToStatic"; //$NON-NLS-1$
private static final String RENAME_REFERENCES_COMMAND = "java.action.renameReferences";

public static void addUncaughtExceptionProposals(IInvocationContext context, IProblemLocationCore problem, Collection<ChangeCorrectionProposal> proposals) throws CoreException {
ICompilationUnit cu = context.getCompilationUnit();
Expand Down Expand Up @@ -1109,4 +1120,33 @@ public static void addValueForAnnotationProposals(IInvocationContext context, IP
}
}

public static void getManualRenameCorrectionProposals(IInvocationContext context, IProblemLocationCore problem, Collection<ChangeCorrectionProposal> proposals, DocumentLifeCycleHandler documentLifeCycleHandler) throws CoreException {
if (!JavaLanguageServerPlugin.getPreferencesManager().getPreferences().getRenameReferencesEnabled()) {
return;
}
ICompilationUnit cu = context.getCompilationUnit();
if (cu == null) {
return;
}
IResource resource = cu.getResource();
if (resource == null) {
return;
}
IMarker[] markers = resource.findMarkers(BaseDocumentLifeCycleHandler.RENAME_REFERENCE_MARKER_ID, false, IResource.DEPTH_ONE);
Arrays.stream(markers).forEach(marker -> {
try {
if (Objects.equals(problem.getOffset(), marker.getAttribute(IMarker.CHAR_START)) && Objects.equals(problem.getOffset() + problem.getLength(), marker.getAttribute(IMarker.CHAR_END))) {
String originalName = (String) marker.getAttribute("OriginalName");
String newName = (String) marker.getAttribute("newName");
Range range = JDTUtils.toRange(cu, problem.getOffset(), problem.getLength());
if (originalName != null && newName != null) {
String label = Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_manual_rename_label, new String[]{ originalName, newName });
proposals.add(new CUCorrectionCommandProposal(label, CodeActionKind.QuickFix, cu, IProposalRelevance.RENAME_REFACTORING_QUICK_FIX, RENAME_REFERENCES_COMMAND, Arrays.asList(cu.getResource().getLocationURI().toString(), originalName, newName, range)));
}
}
} catch (CoreException e) {
// Do nothing
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
Expand All @@ -45,22 +46,29 @@
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaModelMarker;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IProblemRequestor;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.WorkingCopyOwner;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.manipulation.CoreASTProvider;
import org.eclipse.jdt.internal.core.OpenableElementInfo;
import org.eclipse.jdt.internal.core.PackageFragment;
import org.eclipse.jdt.ls.core.internal.DocumentAdapter;
import org.eclipse.jdt.ls.core.internal.IConstants;
import org.eclipse.jdt.ls.core.internal.JDTUtils;
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
import org.eclipse.jdt.ls.core.internal.JobHelpers;
import org.eclipse.jdt.ls.core.internal.Messages;
import org.eclipse.jdt.ls.core.internal.MovingAverage;
import org.eclipse.jdt.ls.core.internal.ProjectUtils;
import org.eclipse.jdt.ls.core.internal.ResourceUtils;
import org.eclipse.jdt.ls.core.internal.corrections.CorrectionMessages;
import org.eclipse.jdt.ls.core.internal.corrections.DiagnosticsHelper;
import org.eclipse.jdt.ls.core.internal.managers.InvisibleProjectImporter;
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager;
Expand Down Expand Up @@ -102,6 +110,9 @@ public abstract class BaseDocumentLifeCycleHandler {
*/
private static final long PUBLISH_DIAGNOSTICS_MAX_DEBOUNCE = 2000; /*ms*/

public static final String RENAME_REFERENCE_MARKER_ID = IConstants.PLUGIN_ID + ".renameReferenceMarker";
public static final int RENAME_REFERENCE_PROBLEM_ID = IProblem.Syntax + 2000;

private CoreASTProvider sharedASTProvider;
private WorkspaceJob validationTimer;
private WorkspaceJob publishDiagnosticsJob;
Expand All @@ -110,6 +121,9 @@ public abstract class BaseDocumentLifeCycleHandler {
private MovingAverage movingAverageForValidation = new MovingAverage(DOCUMENT_LIFECYCLE_MAX_DEBOUNCE);
private MovingAverage movingAverageForDiagnostics = new MovingAverage(PUBLISH_DIAGNOSTICS_MIN_DEBOUNCE);

private Map<String, List<String>> documentOriginalNames = new HashMap<>();
private Map<String, List<IMarker>> documentMarkers = new HashMap<>();

public BaseDocumentLifeCycleHandler(boolean delayValidation) {
this.sharedASTProvider = CoreASTProvider.getInstance();
if (delayValidation) {
Expand Down Expand Up @@ -179,7 +193,7 @@ private long getDocumentLifecycleDelay() {
*/
private long getPublishDiagnosticsDelay() {
return Math.min(
Math.max(PUBLISH_DIAGNOSTICS_MIN_DEBOUNCE, Math.round(1.5 * movingAverageForDiagnostics.value)),
Math.max(PUBLISH_DIAGNOSTICS_MIN_DEBOUNCE, Math.round(1.5 * movingAverageForDiagnostics.value)),
PUBLISH_DIAGNOSTICS_MAX_DEBOUNCE
);
}
Expand Down Expand Up @@ -302,11 +316,18 @@ public IProblemRequestor getProblemRequestor(ICompilationUnit workingCopy) {

};
int flags = ICompilationUnit.FORCE_PROBLEM_DETECTION | ICompilationUnit.ENABLE_BINDINGS_RECOVERY | ICompilationUnit.ENABLE_STATEMENTS_RECOVERY;
if (JavaLanguageServerPlugin.getPreferencesManager().getPreferences().getRenameReferencesEnabled()) {
provideRenameReferencesMarkers(unit);
}
unit.reconcile(ICompilationUnit.NO_AST, flags, wcOwner, monitor);
}

public void didClose(DidCloseTextDocumentParams params) {
documentVersions.remove(params.getTextDocument().getUri());
ICompilationUnit cu = JDTUtils.resolveCompilationUnit(params.getTextDocument().getUri());
if (cu != null) {
this.documentOriginalNames.remove(cu.getResource().getLocationURI().toString());
}
ISchedulingRule rule = JDTUtils.getRule(params.getTextDocument().getUri());
try {
ResourcesPlugin.getWorkspace().run(new IWorkspaceRunnable() {
Expand Down Expand Up @@ -402,6 +423,18 @@ public ICompilationUnit handleOpen(DidOpenTextDocumentParams params) {
// see https://github.com/redhat-developer/vscode-java/issues/274
checkPackageDeclaration(uri, unit);
inferInvisibleProjectSourceRoot(unit);
List<String> memberNames = new ArrayList<>();
if (JavaLanguageServerPlugin.getPreferencesManager().getPreferences().getRenameReferencesEnabled()) {
IType[] types = unit.getAllTypes();
for (IType type : types) {
for (IJavaElement child : type.getChildren()) {
if (child instanceof IMember member && Modifier.isPublic(member.getFlags())) {
memberNames.add(member.getElementName());
}
}
}
this.documentOriginalNames.put(unit.getResource().getLocationURI().toString(), memberNames);
}
} catch (JavaModelException e) {
JavaLanguageServerPlugin.logException("Error while opening document. URI: " + uri, e);
}
Expand Down Expand Up @@ -459,6 +492,77 @@ public ICompilationUnit handleChanged(DidChangeTextDocumentParams params) {
return unit;
}

private void provideRenameReferencesMarkers(ICompilationUnit unit) {
String uri = unit.getResource().getLocationURI().toString();
List<IMember> members = new ArrayList<>();
try {
IType[] types = unit.getAllTypes();
for (IType type : types) {
for (IJavaElement child : type.getChildren()) {
if (child instanceof IMember member && Modifier.isPublic(member.getFlags())) {
members.add(member);
}
}
}
if (this.documentOriginalNames.containsKey(uri)) {
// delete existing markers
List<IMarker> currentMarkers = this.documentMarkers.get(uri);
if (currentMarkers != null) {
unit.getResource().deleteMarkers(RENAME_REFERENCE_MARKER_ID, false, IResource.DEPTH_ONE);
currentMarkers.clear();
} else {
currentMarkers = new ArrayList<>();
this.documentMarkers.put(uri, currentMarkers);
}
List<String> existingMemberNames = this.documentOriginalNames.get(uri);
if (existingMemberNames.size() == members.size()) {
for (int i = 0; i < members.size(); i++) {
IMember member = members.get(i);
String existingMemberName = existingMemberNames.get(i);
String newName = member.getElementName();
if (newName == null) {
this.documentOriginalNames.put(uri, members.stream().map(m -> m.getElementName()).collect(Collectors.toList()));
break;
}
if (existingMemberName.equals(newName)) {
continue;
}
String message = Messages.format(CorrectionMessages.LocalCorrectionsSubProcessor_manual_rename_label, new String[]{ existingMemberName, newName });
IMarker marker = ResourceUtils.createInfoMarker(RENAME_REFERENCE_MARKER_ID, unit.getResource(), message, RENAME_REFERENCE_PROBLEM_ID, member.getNameRange().getOffset(), member.getNameRange().getOffset() + member.getNameRange().getLength());
marker.setAttribute("OriginalName", existingMemberName);
marker.setAttribute("newName", newName);
currentMarkers.add(marker);
}
} else {
// update the storage names list, since it's outdated
this.documentOriginalNames.put(uri, members.stream().map(m -> m.getElementName()).collect(Collectors.toList()));
}
} else {
this.documentOriginalNames.put(uri, members.stream().map(m -> m.getElementName()).collect(Collectors.toList()));
}
} catch (Exception e) {
// Do nothing
}
}

public void cleanRenameReferenceCache(ICompilationUnit unit) {
if (unit == null) {
return;
}
IResource resource = unit.getResource();
if (resource == null) {
return;
}
String uri = resource.getLocationURI().toString();
this.documentOriginalNames.remove(uri);
this.documentMarkers.remove(uri);
try {
unit.getResource().deleteMarkers(RENAME_REFERENCE_MARKER_ID, false, IResource.DEPTH_ONE);
} catch (CoreException e) {
// do nothing
}
}

public ICompilationUnit handleClosed(DidCloseTextDocumentParams params) {
String uri = params.getTextDocument().getUri();
ICompilationUnit unit = JDTUtils.resolveCompilationUnit(uri);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ public class CodeActionHandler {
private NonProjectFixProcessor nonProjectFixProcessor;

private PreferenceManager preferenceManager;
private DocumentLifeCycleHandler documentLifeCycleHandler;

public CodeActionHandler(PreferenceManager preferenceManager) {
this.preferenceManager = preferenceManager;
Expand All @@ -91,6 +92,11 @@ public CodeActionHandler(PreferenceManager preferenceManager) {
this.nonProjectFixProcessor = new NonProjectFixProcessor(preferenceManager);
}

public CodeActionHandler(PreferenceManager preferenceManager, DocumentLifeCycleHandler documentLifeCycleHandler) {
this(preferenceManager);
this.documentLifeCycleHandler = documentLifeCycleHandler;
}

public List<Either<Command, CodeAction>> getCodeActionCommands(CodeActionParams params, IProgressMonitor monitor) {
if (monitor.isCanceled()) {
return Collections.emptyList();
Expand Down Expand Up @@ -159,7 +165,7 @@ public List<Either<Command, CodeAction>> getCodeActionCommands(CodeActionParams
if (containsKind(codeActionKinds, CodeActionKind.QuickFix)) {
try {
codeActions.addAll(nonProjectFixProcessor.getCorrections(params, context, locations));
List<ChangeCorrectionProposal> quickfixProposals = this.quickFixProcessor.getCorrections(params, context, locations);
List<ChangeCorrectionProposal> quickfixProposals = this.quickFixProcessor.getCorrections(params, context, locations, documentLifeCycleHandler);
this.quickFixProcessor.addAddAllMissingImportsProposal(context, quickfixProposals);
Set<ChangeCorrectionProposal> quickSet = new TreeSet<>(comparator);
quickSet.addAll(quickfixProposals);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ public CompletableFuture<List<Either<SymbolInformation, DocumentSymbol>>> docume
@Override
public CompletableFuture<List<Either<Command, CodeAction>>> codeAction(CodeActionParams params) {
logInfo(">> document/codeAction");
CodeActionHandler handler = new CodeActionHandler(this.preferenceManager);
CodeActionHandler handler = new CodeActionHandler(this.preferenceManager, this.documentLifeCycleHandler);
return computeAsync((monitor) -> {
waitForLifecycleJobs(monitor);
return handler.getCodeActionCommands(params, monitor);
Expand Down Expand Up @@ -803,7 +803,7 @@ public CompletableFuture<Either<Range, PrepareRenameResult>> prepareRename(Prepa
@Override
public CompletableFuture<WorkspaceEdit> rename(RenameParams params) {
logInfo(">> document/rename");
RenameHandler handler = new RenameHandler(preferenceManager);
RenameHandler handler = new RenameHandler(preferenceManager, this.documentLifeCycleHandler);
return computeAsync((monitor) -> {
waitForLifecycleJobs(monitor);
return handler.rename(params, monitor);
Expand Down
Loading

0 comments on commit 83d814d

Please sign in to comment.