2121import java .util .List ;
2222import java .util .Map ;
2323import java .util .Set ;
24+ import java .util .stream .Collectors ;
2425
2526import org .eclipse .core .resources .IFile ;
2627import org .eclipse .core .resources .IMarker ;
4546import org .eclipse .jdt .core .IJavaElement ;
4647import org .eclipse .jdt .core .IJavaModelMarker ;
4748import org .eclipse .jdt .core .IJavaProject ;
49+ import org .eclipse .jdt .core .IMember ;
4850import org .eclipse .jdt .core .IPackageFragment ;
4951import org .eclipse .jdt .core .IProblemRequestor ;
52+ import org .eclipse .jdt .core .IType ;
5053import org .eclipse .jdt .core .JavaCore ;
5154import org .eclipse .jdt .core .JavaModelException ;
5255import org .eclipse .jdt .core .WorkingCopyOwner ;
5356import org .eclipse .jdt .core .compiler .IProblem ;
5457import org .eclipse .jdt .core .dom .CompilationUnit ;
58+ import org .eclipse .jdt .core .dom .Modifier ;
5559import org .eclipse .jdt .core .manipulation .CoreASTProvider ;
5660import org .eclipse .jdt .internal .core .OpenableElementInfo ;
5761import org .eclipse .jdt .internal .core .PackageFragment ;
5862import org .eclipse .jdt .ls .core .internal .DocumentAdapter ;
63+ import org .eclipse .jdt .ls .core .internal .IConstants ;
5964import org .eclipse .jdt .ls .core .internal .JDTUtils ;
6065import org .eclipse .jdt .ls .core .internal .JavaLanguageServerPlugin ;
6166import org .eclipse .jdt .ls .core .internal .JobHelpers ;
67+ import org .eclipse .jdt .ls .core .internal .Messages ;
6268import org .eclipse .jdt .ls .core .internal .MovingAverage ;
6369import org .eclipse .jdt .ls .core .internal .ProjectUtils ;
70+ import org .eclipse .jdt .ls .core .internal .ResourceUtils ;
71+ import org .eclipse .jdt .ls .core .internal .corrections .CorrectionMessages ;
6472import org .eclipse .jdt .ls .core .internal .corrections .DiagnosticsHelper ;
6573import org .eclipse .jdt .ls .core .internal .managers .InvisibleProjectImporter ;
6674import org .eclipse .jdt .ls .core .internal .managers .ProjectsManager ;
@@ -102,6 +110,9 @@ public abstract class BaseDocumentLifeCycleHandler {
102110 */
103111 private static final long PUBLISH_DIAGNOSTICS_MAX_DEBOUNCE = 2000 ; /*ms*/
104112
113+ public static final String RENAME_REFERENCE_MARKER_ID = IConstants .PLUGIN_ID + ".renameReferenceMarker" ;
114+ public static final int RENAME_REFERENCE_PROBLEM_ID = IProblem .Syntax + 2000 ;
115+
105116 private CoreASTProvider sharedASTProvider ;
106117 private WorkspaceJob validationTimer ;
107118 private WorkspaceJob publishDiagnosticsJob ;
@@ -110,6 +121,9 @@ public abstract class BaseDocumentLifeCycleHandler {
110121 private MovingAverage movingAverageForValidation = new MovingAverage (DOCUMENT_LIFECYCLE_MAX_DEBOUNCE );
111122 private MovingAverage movingAverageForDiagnostics = new MovingAverage (PUBLISH_DIAGNOSTICS_MIN_DEBOUNCE );
112123
124+ private Map <String , List <String >> documentOriginalNames = new HashMap <>();
125+ private Map <String , List <IMarker >> documentMarkers = new HashMap <>();
126+
113127 public BaseDocumentLifeCycleHandler (boolean delayValidation ) {
114128 this .sharedASTProvider = CoreASTProvider .getInstance ();
115129 if (delayValidation ) {
@@ -179,7 +193,7 @@ private long getDocumentLifecycleDelay() {
179193 */
180194 private long getPublishDiagnosticsDelay () {
181195 return Math .min (
182- Math .max (PUBLISH_DIAGNOSTICS_MIN_DEBOUNCE , Math .round (1.5 * movingAverageForDiagnostics .value )),
196+ Math .max (PUBLISH_DIAGNOSTICS_MIN_DEBOUNCE , Math .round (1.5 * movingAverageForDiagnostics .value )),
183197 PUBLISH_DIAGNOSTICS_MAX_DEBOUNCE
184198 );
185199 }
@@ -302,11 +316,18 @@ public IProblemRequestor getProblemRequestor(ICompilationUnit workingCopy) {
302316
303317 };
304318 int flags = ICompilationUnit .FORCE_PROBLEM_DETECTION | ICompilationUnit .ENABLE_BINDINGS_RECOVERY | ICompilationUnit .ENABLE_STATEMENTS_RECOVERY ;
319+ if (JavaLanguageServerPlugin .getPreferencesManager ().getPreferences ().getRenameReferencesEnabled ()) {
320+ provideRenameReferencesMarkers (unit );
321+ }
305322 unit .reconcile (ICompilationUnit .NO_AST , flags , wcOwner , monitor );
306323 }
307324
308325 public void didClose (DidCloseTextDocumentParams params ) {
309326 documentVersions .remove (params .getTextDocument ().getUri ());
327+ ICompilationUnit cu = JDTUtils .resolveCompilationUnit (params .getTextDocument ().getUri ());
328+ if (cu != null ) {
329+ this .documentOriginalNames .remove (cu .getResource ().getLocationURI ().toString ());
330+ }
310331 ISchedulingRule rule = JDTUtils .getRule (params .getTextDocument ().getUri ());
311332 try {
312333 ResourcesPlugin .getWorkspace ().run (new IWorkspaceRunnable () {
@@ -402,6 +423,18 @@ public ICompilationUnit handleOpen(DidOpenTextDocumentParams params) {
402423 // see https://github.com/redhat-developer/vscode-java/issues/274
403424 checkPackageDeclaration (uri , unit );
404425 inferInvisibleProjectSourceRoot (unit );
426+ List <String > memberNames = new ArrayList <>();
427+ if (JavaLanguageServerPlugin .getPreferencesManager ().getPreferences ().getRenameReferencesEnabled ()) {
428+ IType [] types = unit .getAllTypes ();
429+ for (IType type : types ) {
430+ for (IJavaElement child : type .getChildren ()) {
431+ if (child instanceof IMember member && Modifier .isPublic (member .getFlags ())) {
432+ memberNames .add (member .getElementName ());
433+ }
434+ }
435+ }
436+ this .documentOriginalNames .put (unit .getResource ().getLocationURI ().toString (), memberNames );
437+ }
405438 } catch (JavaModelException e ) {
406439 JavaLanguageServerPlugin .logException ("Error while opening document. URI: " + uri , e );
407440 }
@@ -459,6 +492,77 @@ public ICompilationUnit handleChanged(DidChangeTextDocumentParams params) {
459492 return unit ;
460493 }
461494
495+ private void provideRenameReferencesMarkers (ICompilationUnit unit ) {
496+ String uri = unit .getResource ().getLocationURI ().toString ();
497+ List <IMember > members = new ArrayList <>();
498+ try {
499+ IType [] types = unit .getAllTypes ();
500+ for (IType type : types ) {
501+ for (IJavaElement child : type .getChildren ()) {
502+ if (child instanceof IMember member && Modifier .isPublic (member .getFlags ())) {
503+ members .add (member );
504+ }
505+ }
506+ }
507+ if (this .documentOriginalNames .containsKey (uri )) {
508+ // delete existing markers
509+ List <IMarker > currentMarkers = this .documentMarkers .get (uri );
510+ if (currentMarkers != null ) {
511+ unit .getResource ().deleteMarkers (RENAME_REFERENCE_MARKER_ID , false , IResource .DEPTH_ONE );
512+ currentMarkers .clear ();
513+ } else {
514+ currentMarkers = new ArrayList <>();
515+ this .documentMarkers .put (uri , currentMarkers );
516+ }
517+ List <String > existingMemberNames = this .documentOriginalNames .get (uri );
518+ if (existingMemberNames .size () == members .size ()) {
519+ for (int i = 0 ; i < members .size (); i ++) {
520+ IMember member = members .get (i );
521+ String existingMemberName = existingMemberNames .get (i );
522+ String newName = member .getElementName ();
523+ if (newName == null ) {
524+ this .documentOriginalNames .put (uri , members .stream ().map (m -> m .getElementName ()).collect (Collectors .toList ()));
525+ break ;
526+ }
527+ if (existingMemberName .equals (newName )) {
528+ continue ;
529+ }
530+ String message = Messages .format (CorrectionMessages .LocalCorrectionsSubProcessor_manual_rename_label , new String []{ existingMemberName , newName });
531+ IMarker marker = ResourceUtils .createInfoMarker (RENAME_REFERENCE_MARKER_ID , unit .getResource (), message , RENAME_REFERENCE_PROBLEM_ID , member .getNameRange ().getOffset (), member .getNameRange ().getOffset () + member .getNameRange ().getLength ());
532+ marker .setAttribute ("OriginalName" , existingMemberName );
533+ marker .setAttribute ("newName" , newName );
534+ currentMarkers .add (marker );
535+ }
536+ } else {
537+ // update the storage names list, since it's outdated
538+ this .documentOriginalNames .put (uri , members .stream ().map (m -> m .getElementName ()).collect (Collectors .toList ()));
539+ }
540+ } else {
541+ this .documentOriginalNames .put (uri , members .stream ().map (m -> m .getElementName ()).collect (Collectors .toList ()));
542+ }
543+ } catch (Exception e ) {
544+ // Do nothing
545+ }
546+ }
547+
548+ public void cleanRenameReferenceCache (ICompilationUnit unit ) {
549+ if (unit == null ) {
550+ return ;
551+ }
552+ IResource resource = unit .getResource ();
553+ if (resource == null ) {
554+ return ;
555+ }
556+ String uri = resource .getLocationURI ().toString ();
557+ this .documentOriginalNames .remove (uri );
558+ this .documentMarkers .remove (uri );
559+ try {
560+ unit .getResource ().deleteMarkers (RENAME_REFERENCE_MARKER_ID , false , IResource .DEPTH_ONE );
561+ } catch (CoreException e ) {
562+ // do nothing
563+ }
564+ }
565+
462566 public ICompilationUnit handleClosed (DidCloseTextDocumentParams params ) {
463567 String uri = params .getTextDocument ().getUri ();
464568 ICompilationUnit unit = JDTUtils .resolveCompilationUnit (uri );
0 commit comments