1212import com .intellij .openapi .vfs .VirtualFile ;
1313import com .intellij .psi .PsiDocumentManager ;
1414import com .intellij .psi .PsiFile ;
15+ import com .intellij .psi .PsiInvalidElementAccessException ;
1516import com .intellij .util .Alarm ;
1617import com .intellij .util .AlarmFactory ;
1718import com .intellij .util .indexing .FileBasedIndex ;
2223import org .digma .intellij .plugin .model .discovery .DocumentInfo ;
2324import org .digma .intellij .plugin .model .discovery .MethodUnderCaret ;
2425import org .digma .intellij .plugin .psi .LanguageService ;
26+ import org .digma .intellij .plugin .psi .LanguageServiceLocator ;
2527import org .digma .intellij .plugin .ui .CaretContextService ;
2628import org .jetbrains .annotations .NotNull ;
2729
@@ -41,60 +43,91 @@ class DocumentChangeListener {
4143 private final DocumentInfoService documentInfoService ;
4244 private final CaretContextService caretContextService ;
4345
44- private final Alarm documentChangeAlarm ;
45-
4646 private final Map <VirtualFile , Disposable > disposables = new HashMap <>();
4747
4848 DocumentChangeListener (Project project ) {
4949 this .project = project ;
5050 documentInfoService = project .getService (DocumentInfoService .class );
5151 caretContextService = project .getService (CaretContextService .class );
52- documentChangeAlarm = AlarmFactory .getInstance ().create ();
5352 }
5453
55- void maybeAddDocumentListener (Editor editor , PsiFile psiFile , LanguageService languageService ) {
56- if (disposables .containsKey (psiFile .getVirtualFile ())) {
54+ void maybeAddDocumentListener (@ NotNull Editor editor ) {
55+
56+ if (editor .isDisposed ()) {
57+ Log .log (LOGGER ::debug , "not installing document listener for {} because it is disposed" , editor );
5758 return ;
5859 }
5960
60- addDocumentListener (editor , psiFile , languageService );
61- }
61+ Document document = editor .getDocument ();
62+ PsiFile psiFile = PsiDocumentManager .getInstance (project ).getPsiFile (document );
63+ //probably should never happen
64+ if (psiFile == null ) {
65+ return ;
66+ }
6267
63- private void addDocumentListener ( @ NotNull Editor editor , @ NotNull PsiFile psiFile , @ NotNull LanguageService languageService ) {
68+ VirtualFile virtualFile = psiFile . getVirtualFile ();
6469
65- if ( editor . isDisposed ()) {
66- Log . log ( LOGGER :: debug , "not installing document listener for {} because it is disposed" , editor );
70+ //this is a check if this document already has a document listener
71+ if ( disposables . containsKey ( virtualFile )) {
6772 return ;
6873 }
6974
75+ addDocumentListener (editor , virtualFile );
76+ }
77+
78+ private void addDocumentListener (@ NotNull Editor editor , @ NotNull VirtualFile virtualFile ) {
79+
7080 Document document = editor .getDocument ();
7181
7282 Disposable parentDisposable = Disposer .newDisposable ();
73- disposables .put (psiFile . getVirtualFile () , parentDisposable );
74- Log .log (LOGGER ::debug , "adding document listener for file:{}" , psiFile . getVirtualFile () );
83+ disposables .put (virtualFile , parentDisposable );
84+ Log .log (LOGGER ::debug , "adding document listener for file:{}" , virtualFile );
7585
7686 document .addDocumentListener (new DocumentListener () {
87+
88+ private final Alarm documentChangeAlarm = AlarmFactory .getInstance ().create ();
89+
7790 @ Override
7891 public void documentChanged (@ NotNull DocumentEvent event ) {
7992
93+ if (project .isDisposed ()) {
94+ return ;
95+ }
96+
8097 documentChangeAlarm .cancelAllRequests ();
8198 documentChangeAlarm .addRequest (() ->
82- processDocumentChanged (editor , psiFile , languageService ), 300 );
99+ {
100+ //this code is always executed in smart mode because the listener is installed only in smart mode
101+ PsiFile fileToQuery = PsiDocumentManager .getInstance (project ).getPsiFile (event .getDocument ());
102+ //probably should never happen
103+ if (fileToQuery == null ) {
104+ return ;
105+ }
106+ try {
107+
108+ processDocumentChanged (editor , fileToQuery );
109+ } catch (PsiInvalidElementAccessException e ) {
110+ Log .debugWithException (LOGGER , e , "exception while processing file: {}, {}" , fileToQuery .getVirtualFile (), e .getMessage ());
111+ }
112+
113+ }, 500 );
83114
84115 }
85116 }, parentDisposable );
86117 }
87118
88119
89- private void processDocumentChanged (@ NotNull Editor editor , @ NotNull PsiFile psiFile , @ NotNull LanguageService languageService ) {
120+ private void processDocumentChanged (@ NotNull Editor editor , @ NotNull PsiFile psiFile ) {
90121
91- if (project .isDisposed ()){
122+ if (project .isDisposed ()) {
92123 return ;
93124 }
94125
95126
96-
97127 PsiDocumentManager .getInstance (project ).performLaterWhenAllCommitted (() -> {
128+
129+ LanguageService languageService = LanguageServiceLocator .getInstance (project ).locate (psiFile .getLanguage ());
130+
98131 DocumentInfo documentInfo ;
99132 try {
100133 Map <Integer , DocumentInfo > documentInfoMap =
@@ -113,6 +146,7 @@ private void processDocumentChanged(@NotNull Editor editor, @NotNull PsiFile psi
113146
114147 } catch (IndexNotReadyException e ) {
115148 //IndexNotReadyException will be thrown on dumb mode, when indexing is still in progress.
149+ //usually it should not happen because the listener is installed only in smart mode.
116150 documentInfo = languageService .buildDocumentInfo (psiFile );
117151 }
118152
@@ -124,7 +158,7 @@ private void processDocumentChanged(@NotNull Editor editor, @NotNull PsiFile psi
124158
125159 MethodUnderCaret methodUnderCaret = languageService .detectMethodUnderCaret (project , psiFile , editor .getCaretModel ().getOffset ());
126160
127- update (languageService ,psiFile , documentInfo , methodUnderCaret );
161+ update (languageService , psiFile , documentInfo , methodUnderCaret );
128162
129163 });
130164 }
@@ -137,7 +171,7 @@ private void update(@NotNull LanguageService languageService, @NotNull PsiFile p
137171 //contextChanged will update the UI and must run after documentInfoService.addCodeObjects is finished
138172 //enrichDocumentInfo is meant mainly to discover spans. the DocumentInfoIndex can
139173 // not discover spans because there is no reference resolving during file based index.
140- languageService .enrichDocumentInfo (documentInfo ,psiFile );
174+ languageService .enrichDocumentInfo (documentInfo , psiFile );
141175 documentInfoService .addCodeObjects (psiFile , documentInfo );
142176 caretContextService .contextChanged (methodUnderCaret );
143177 });
0 commit comments