4545import org .eclipse .jdt .core .IJavaElement ;
4646import org .eclipse .jdt .core .IJavaModelMarker ;
4747import org .eclipse .jdt .core .IJavaProject ;
48+ import org .eclipse .jdt .core .IMember ;
4849import org .eclipse .jdt .core .IPackageFragment ;
4950import org .eclipse .jdt .core .IProblemRequestor ;
51+ import org .eclipse .jdt .core .ISourceRange ;
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 <MemberInfo >> documentMemberInfos = 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 .documentMemberInfos .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,9 @@ public ICompilationUnit handleOpen(DidOpenTextDocumentParams params) {
402423 // see https://github.com/redhat-developer/vscode-java/issues/274
403424 checkPackageDeclaration (uri , unit );
404425 inferInvisibleProjectSourceRoot (unit );
426+ if (JavaLanguageServerPlugin .getPreferencesManager ().getPreferences ().getRenameReferencesEnabled ()) {
427+ this .documentMemberInfos .put (unit .getResource ().getLocationURI ().toString (), this .getMemberInfos (unit ));
428+ }
405429 } catch (JavaModelException e ) {
406430 JavaLanguageServerPlugin .logException ("Error while opening document. URI: " + uri , e );
407431 }
@@ -459,6 +483,87 @@ public ICompilationUnit handleChanged(DidChangeTextDocumentParams params) {
459483 return unit ;
460484 }
461485
486+ private void provideRenameReferencesMarkers (ICompilationUnit unit ) {
487+ String uri = unit .getResource ().getLocationURI ().toString ();
488+ List <MemberInfo > memberInfos = this .getMemberInfos (unit );
489+ try {
490+ if (this .documentMemberInfos .containsKey (uri )) {
491+ // delete existing markers
492+ List <IMarker > currentMarkers = this .documentMarkers .get (uri );
493+ if (currentMarkers != null ) {
494+ unit .getResource ().deleteMarkers (RENAME_REFERENCE_MARKER_ID , false , IResource .DEPTH_ONE );
495+ currentMarkers .clear ();
496+ } else {
497+ currentMarkers = new ArrayList <>();
498+ this .documentMarkers .put (uri , currentMarkers );
499+ }
500+ List <MemberInfo > cacheMemberInfos = this .documentMemberInfos .get (uri );
501+ if (cacheMemberInfos .size () == memberInfos .size ()) {
502+ for (int i = 0 ; i < memberInfos .size (); i ++) {
503+ MemberInfo memberInfo = memberInfos .get (i );
504+ String name = memberInfo .getName ();
505+ MemberInfo cacheMemberInfo = cacheMemberInfos .get (i );
506+ if (name == null ) {
507+ this .documentMemberInfos .put (uri , memberInfos );
508+ break ;
509+ }
510+ if (cacheMemberInfo .getName ().equals (name )) {
511+ continue ;
512+ }
513+ String message = Messages .format (CorrectionMessages .LocalCorrectionsSubProcessor_manual_rename_label , new String []{ cacheMemberInfo .getName (), name });
514+ IMarker marker = ResourceUtils .createInfoMarker (RENAME_REFERENCE_MARKER_ID , unit .getResource (), message , RENAME_REFERENCE_PROBLEM_ID , memberInfo .getNameRange ().getOffset (), memberInfo .getNameRange ().getOffset () + memberInfo .getNameRange ().getLength ());
515+ marker .setAttribute ("originalName" , cacheMemberInfo .getName ());
516+ marker .setAttribute ("newName" , name );
517+ currentMarkers .add (marker );
518+ }
519+ } else {
520+ // update the storage names list
521+ this .documentMemberInfos .put (uri , memberInfos );
522+ }
523+ } else {
524+ // initialize the storage names list
525+ this .documentMemberInfos .put (uri , memberInfos );
526+ }
527+ } catch (CoreException e ) {
528+ // Do nothing
529+ }
530+ }
531+
532+ private List <MemberInfo > getMemberInfos (ICompilationUnit unit ) {
533+ List <MemberInfo > members = new ArrayList <>();
534+ try {
535+ IType [] types = unit .getAllTypes ();
536+ for (IType type : types ) {
537+ for (IJavaElement child : type .getChildren ()) {
538+ if (child instanceof IMember member && Modifier .isPublic (member .getFlags ())) {
539+ members .add (new MemberInfo (member .getElementName (), member .getNameRange ()));
540+ }
541+ }
542+ }
543+ } catch (JavaModelException e ) {
544+ // do nothing
545+ }
546+ return members ;
547+ }
548+
549+ public void cleanRenameReferenceCache (ICompilationUnit unit ) {
550+ if (unit == null ) {
551+ return ;
552+ }
553+ IResource resource = unit .getResource ();
554+ if (resource == null ) {
555+ return ;
556+ }
557+ String uri = resource .getLocationURI ().toString ();
558+ this .documentMemberInfos .remove (uri );
559+ this .documentMarkers .remove (uri );
560+ try {
561+ unit .getResource ().deleteMarkers (RENAME_REFERENCE_MARKER_ID , false , IResource .DEPTH_ONE );
562+ } catch (CoreException e ) {
563+ // do nothing
564+ }
565+ }
566+
462567 public ICompilationUnit handleClosed (DidCloseTextDocumentParams params ) {
463568 String uri = params .getTextDocument ().getUri ();
464569 ICompilationUnit unit = JDTUtils .resolveCompilationUnit (uri );
@@ -735,4 +840,22 @@ public void checkChanged() {
735840
736841 }
737842
843+ private static class MemberInfo {
844+ private String name ;
845+ private ISourceRange nameRange ;
846+
847+ public MemberInfo (String name , ISourceRange nameRange ) {
848+ this .name = name ;
849+ this .nameRange = nameRange ;
850+ }
851+
852+ public String getName () {
853+ return name ;
854+ }
855+
856+ public ISourceRange getNameRange () {
857+ return nameRange ;
858+ }
859+ }
860+
738861}
0 commit comments