e48bdd8dd667c8556a357c950db77b28e4236379
[idea/community.git] / platform / core-api / src / com / intellij / psi / PsiDocumentManager.java
1 // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
2 package com.intellij.psi;
3
4 import com.intellij.openapi.application.ModalityState;
5 import com.intellij.openapi.editor.Document;
6 import com.intellij.openapi.project.Project;
7 import com.intellij.openapi.util.Computable;
8 import com.intellij.openapi.vfs.VirtualFile;
9 import org.jetbrains.annotations.NotNull;
10 import org.jetbrains.annotations.Nullable;
11
12 import java.util.Collection;
13 import java.util.EventListener;
14
15 /**
16  * Manages the relationship between documents and PSI trees.
17  */
18 public abstract class PsiDocumentManager {
19   /**
20    * Checks if the PSI tree for the specified document is up to date (its state reflects the latest changes made
21    * to the document content).
22    *
23    * @param document the document to check.
24    * @return true if the PSI tree for the document is up to date, false otherwise.
25    */
26   public abstract boolean isCommitted(@NotNull Document document);
27
28   /**
29    * Returns the document manager instance for the specified project.
30    *
31    * @param project the project for which the document manager is requested.
32    * @return the document manager instance.
33    */
34   public static PsiDocumentManager getInstance(@NotNull Project project) {
35     return project.getComponent(PsiDocumentManager.class);
36   }
37
38   /**
39    * Returns the PSI file for the specified document.
40    *
41    * @param document the document for which the PSI file is requested.
42    * @return the PSI file instance.
43    */
44   @Nullable
45   public abstract PsiFile getPsiFile(@NotNull Document document);
46
47   /**
48    * Returns the cached PSI file for the specified document.
49    *
50    * @param document the document for which the PSI file is requested.
51    * @return the PSI file instance, or {@code null} if there is currently no cached PSI tree for the file.
52    */
53   @Nullable
54   public abstract PsiFile getCachedPsiFile(@NotNull Document document);
55
56   /**
57    * Returns the document for the specified PSI file.
58    *
59    * @param file the file for which the document is requested.
60    * @return the document instance, or {@code null} if the file is binary or has no associated document.
61    */
62   @Nullable
63   public abstract Document getDocument(@NotNull PsiFile file);
64
65   /**
66    * Returns the cached document for the specified PSI file.
67    *
68    * @param file the file for which the document is requested.
69    * @return the document instance, or {@code null} if there is currently no cached document for the file.
70    */
71   @Nullable
72   public abstract Document getCachedDocument(@NotNull PsiFile file);
73
74   /**
75    * Commits (updates the PSI tree for) all modified but not committed documents.
76    * Before a modified document is committed, accessing its PSI may return elements
77    * corresponding to original (unmodified) state of the document.<p/>
78    *
79    * Should be called in UI thread in a write-safe context (see {@link com.intellij.openapi.application.TransactionGuard})
80    */
81   public abstract void commitAllDocuments();
82
83   /**
84    * If the document is committed, runs action synchronously, otherwise schedules to execute it right after it has been committed.
85    */
86   public abstract void performForCommittedDocument(@NotNull Document document, @NotNull Runnable action);
87
88   /**
89    * Updates the PSI tree for the specified document.
90    * Before a modified document is committed, accessing its PSI may return elements
91    * corresponding to original (unmodified) state of the document.<p/>
92    *
93    * Should be called in UI thread in a write-safe context (see {@link com.intellij.openapi.application.TransactionGuard}).
94    *
95    * @param document the document to commit.
96    */
97   public abstract void commitDocument(@NotNull Document document);
98
99   /**
100    * @return the document text that PSI should be based upon. For changed documents, it's their old text until the document is committed.
101    * This sequence is immutable.
102    * @see com.intellij.util.text.ImmutableCharSequence
103    */
104   @NotNull
105   public abstract CharSequence getLastCommittedText(@NotNull Document document);
106
107   /**
108    * @return for uncommitted documents, the last stamp before the document change: the same stamp that current PSI should have.
109    * For committed documents, just their stamp.
110    *
111    * @see Document#getModificationStamp()
112    * @see FileViewProvider#getModificationStamp()
113    */
114   public abstract long getLastCommittedStamp(@NotNull Document document);
115
116   /**
117    * Returns the document for specified PsiFile intended to be used when working with committed PSI, e.g. outside dispatch thread.
118    * @param file the file for which the document is requested.
119    * @return an immutable document corresponding to the current PSI state. For committed documents, the contents and timestamp are equal to
120    * the ones of {@link #getDocument(PsiFile)}. For uncommitted documents, the text is {@link #getLastCommittedText(Document)} and
121    * the modification stamp is {@link #getLastCommittedStamp(Document)}.
122    */
123   @Nullable
124   public abstract Document getLastCommittedDocument(@NotNull PsiFile file);
125
126   /**
127    * Returns the list of documents which have been modified but not committed.
128    *
129    * @return the list of uncommitted documents.
130    * @see #commitDocument(Document)
131    */
132   @NotNull
133   public abstract Document[] getUncommittedDocuments();
134
135   /**
136    * Checks if the specified document has been committed.
137    *
138    * @param document the document to check.
139    * @return true if the document was modified but not committed, false otherwise
140    * @see #commitDocument(Document)
141    */
142   public abstract boolean isUncommited(@NotNull Document document);
143
144   /**
145    * Checks if any modified documents have not been committed.
146    *
147    * @return true if there are uncommitted documents, false otherwise
148    */
149   public abstract boolean hasUncommitedDocuments();
150
151   /**
152    * Commits the documents and runs the specified operation, which does not return a value, in a read action.
153    * Can be called from a thread other than the Swing dispatch thread.
154    *
155    * @param runnable the operation to execute.
156    */
157   public abstract void commitAndRunReadAction(@NotNull Runnable runnable);
158
159   /**
160    * Commits the documents and runs the specified operation, which returns a value, in a read action.
161    * Can be called from a thread other than the Swing dispatch thread.
162    *
163    * @param computation the operation to execute.
164    * @return the value returned by the operation.
165    */
166   public abstract <T> T commitAndRunReadAction(@NotNull Computable<T> computation);
167
168   /**
169    * Reparses the specified set of files after an external configuration change that would cause them to be parsed differently
170    * (for example, a language level change in the settings).
171    *
172    * @param files the files to reparse.
173    * @param includeOpenFiles if true, the files opened in editor tabs will also be reparsed.
174    */
175   public abstract void reparseFiles(@NotNull final Collection<? extends VirtualFile> files, final boolean includeOpenFiles);
176
177   /**
178    * Listener for receiving notifications about creation of {@link Document} and {@link PsiFile} instances.
179    */
180   public interface Listener extends EventListener {
181     /**
182      * Called when a document instance is created for a file.
183      *
184      * @param document the created document instance.
185      * @param psiFile the file for which the document was created.
186      * @see PsiDocumentManager#getDocument(PsiFile)
187      */
188     void documentCreated(@NotNull Document document, @Nullable PsiFile psiFile);
189
190     /**
191      * Called when a file instance is created for a document.
192      *
193      * @param file the created file instance.
194      * @param document the document for which the file was created.
195      * @see PsiDocumentManager#getDocument(PsiFile)
196      */
197     default void fileCreated(@NotNull PsiFile file, @NotNull Document document) {
198     }
199   }
200
201   /**
202    * @deprecated Use message bus {@link Listener#TOPIC}.
203    */
204   @Deprecated
205   public abstract void addListener(@NotNull Listener listener);
206
207   /**
208    * @deprecated Use message bus {@link Listener#TOPIC}.
209    */
210   @Deprecated
211   public abstract void removeListener(@NotNull Listener listener);
212
213   /**
214    * Checks if the PSI tree corresponding to the specified document has been modified and the changes have not
215    * yet been applied to the document. Documents in that state cannot be modified directly, because such changes
216    * would conflict with the pending PSI changes. Changes made through PSI are always applied in the end of a write action,
217    * and can be applied in the middle of a write action by calling {@link #doPostponedOperationsAndUnblockDocument}.
218    *
219    * @param doc the document to check.
220    * @return true if the corresponding PSI has changes that haven't been applied to the document.
221    */
222   public abstract boolean isDocumentBlockedByPsi(@NotNull Document doc);
223
224   /**
225    * Applies pending changes made through the PSI to the specified document.
226    *
227    * @param doc the document to apply the changes to.
228    */
229   public abstract void doPostponedOperationsAndUnblockDocument(@NotNull Document doc);
230
231   /**
232    * Defer action until all documents are committed.
233    * Must be called from the EDT only.
234    *
235    * @param action to run when all documents committed
236    * @return true if action was run immediately (i.e. all documents are already committed)
237    */
238   public abstract boolean performWhenAllCommitted(@NotNull Runnable action);
239
240   /**
241    * Same as {@link #performLaterWhenAllCommitted(Runnable, ModalityState)} using {@link ModalityState#defaultModalityState()}
242    */
243   public abstract void performLaterWhenAllCommitted(@NotNull Runnable runnable);
244
245   /**
246    * Schedule the runnable to be executed on Swing thread when all the documents are committed at some later moment in a given modality state.
247    * The runnable is guaranteed to be invoked when no write action is running, and not immediately.
248    * If the project is disposed before such moment, the runnable is not run.
249    */
250   public abstract void performLaterWhenAllCommitted(@NotNull Runnable runnable, ModalityState modalityState);
251
252
253 }