mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
run injections in background upon commit document
+ closure friendly API
This commit is contained in:
+2
-2
@@ -113,11 +113,11 @@ public class HighlightVisitorImpl extends JavaElementVisitor implements Highligh
|
||||
}
|
||||
|
||||
private void registerReferencesFromInjectedFragments(final PsiElement element) {
|
||||
InjectedLanguageUtil.enumerate(element, myFile, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
InjectedLanguageUtil.enumerate(element, myFile, false, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
public void visit(@NotNull final PsiFile injectedPsi, @NotNull final List<PsiLanguageInjectionHost.Shred> places) {
|
||||
injectedPsi.accept(REGISTER_REFERENCES_VISITOR);
|
||||
}
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
|
||||
public boolean analyze(@NotNull final Runnable action, final boolean updateWholeFile, @NotNull final PsiFile file) {
|
||||
|
||||
@@ -131,7 +131,7 @@ public class VfsUtilTest extends IdeaTestCase {
|
||||
|
||||
public void testAsyncRefresh() throws Throwable {
|
||||
final Throwable[] ex = {null};
|
||||
JobUtil.invokeConcurrentlyUnderProgress(Arrays.asList(new Object[8]), new Processor<Object>() {
|
||||
JobUtil.invokeConcurrentlyUnderProgress(Arrays.asList(new Object[8]), ProgressManager.getInstance().getProgressIndicator(), false, new Processor<Object>() {
|
||||
@Override
|
||||
public boolean process(Object o) {
|
||||
try {
|
||||
@@ -142,7 +142,7 @@ public class VfsUtilTest extends IdeaTestCase {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, false, ProgressManager.getInstance().getProgressIndicator());
|
||||
});
|
||||
if (ex[0] != null) throw ex[0];
|
||||
}
|
||||
|
||||
|
||||
@@ -467,7 +467,7 @@ public class VirtualFilePointerTest extends IdeaTestCase {
|
||||
|
||||
private static void doit(final VirtualFilePointer pointer) {
|
||||
if (((VirtualFilePointerImpl)pointer).isDisposed()) return;
|
||||
boolean b = JobUtil.invokeConcurrentlyUnderProgress(Collections.nCopies(10, null), new Processor<Object>() {
|
||||
boolean b = JobUtil.invokeConcurrentlyUnderProgress(Collections.nCopies(10, null), null, false, new Processor<Object>() {
|
||||
@Override
|
||||
public boolean process(Object o) {
|
||||
ApplicationManager.getApplication().runReadAction(new Runnable() {
|
||||
@@ -481,7 +481,7 @@ public class VirtualFilePointerTest extends IdeaTestCase {
|
||||
|
||||
return true;
|
||||
}
|
||||
}, false, null);
|
||||
});
|
||||
assertTrue(b);
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -314,14 +314,14 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
}
|
||||
}
|
||||
};
|
||||
if (!JobUtil.invokeConcurrentlyUnderProgress(new ArrayList<PsiElement>(hosts), new Processor<PsiElement>() {
|
||||
if (!JobUtil.invokeConcurrentlyUnderProgress(new ArrayList<PsiElement>(hosts), progress, false, new Processor<PsiElement>() {
|
||||
@Override
|
||||
public boolean process(PsiElement element) {
|
||||
progress.checkCanceled();
|
||||
InjectedLanguageUtil.enumerate(element, myFile, visitor, false);
|
||||
InjectedLanguageUtil.enumerate(element, myFile, false, visitor);
|
||||
return true;
|
||||
}
|
||||
}, false, progress)) throw new ProcessCanceledException();
|
||||
})) throw new ProcessCanceledException();
|
||||
}
|
||||
|
||||
// returns false if canceled
|
||||
@@ -332,7 +332,7 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
final InjectedLanguageManager injectedLanguageManager = InjectedLanguageManager.getInstance(myProject);
|
||||
final TextAttributes injectedAttributes = myGlobalScheme.getAttributes(EditorColors.INJECTED_LANGUAGE_FRAGMENT);
|
||||
|
||||
return JobUtil.invokeConcurrentlyUnderProgress(new ArrayList<PsiFile>(injectedFiles), new Processor<PsiFile>() {
|
||||
return JobUtil.invokeConcurrentlyUnderProgress(new ArrayList<PsiFile>(injectedFiles), progress, myFailFastOnAcquireReadAction, new Processor<PsiFile>() {
|
||||
public boolean process(final PsiFile injectedPsi) {
|
||||
DocumentWindow documentWindow = (DocumentWindow)PsiDocumentManager.getInstance(myProject).getCachedDocument(injectedPsi);
|
||||
if (documentWindow == null) return true;
|
||||
@@ -383,7 +383,7 @@ public class GeneralHighlightingPass extends ProgressableTextEditorHighlightingP
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, myFailFastOnAcquireReadAction, progress);
|
||||
});
|
||||
}
|
||||
|
||||
private static TextRange getFixedTextRange(@NotNull DocumentWindow documentWindow, int startOffset) {
|
||||
|
||||
@@ -148,11 +148,11 @@ public class LineMarkersPass extends ProgressableTextEditorHighlightingPass impl
|
||||
|
||||
final Set<PsiFile> injectedFiles = new THashSet<PsiFile>();
|
||||
for (PsiElement element : elements) {
|
||||
InjectedLanguageUtil.enumerate(element, file, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
InjectedLanguageUtil.enumerate(element, file, false, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
public void visit(@NotNull final PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
|
||||
injectedFiles.add(injectedPsi);
|
||||
}
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
for (PsiFile injectedPsi : injectedFiles) {
|
||||
final Project project = injectedPsi.getProject();
|
||||
|
||||
+7
-7
@@ -239,7 +239,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
|
||||
@NotNull final List<PsiElement> elements,
|
||||
@NotNull final LocalInspectionToolSession session,
|
||||
@NotNull final List<Trinity<LocalInspectionTool, ProblemsHolder, PsiElementVisitor>> init) {
|
||||
boolean result = JobUtil.invokeConcurrentlyUnderProgress(tools, new Processor<LocalInspectionTool>() {
|
||||
boolean result = JobUtil.invokeConcurrentlyUnderProgress(tools, indicator, myFailFastOnAcquireReadAction, new Processor<LocalInspectionTool>() {
|
||||
public boolean process(final LocalInspectionTool tool) {
|
||||
indicator.checkCanceled();
|
||||
|
||||
@@ -268,7 +268,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
|
||||
applyIncrementally[0] = false; // do not apply incrementally outside visible range
|
||||
return true;
|
||||
}
|
||||
}, myFailFastOnAcquireReadAction, indicator);
|
||||
});
|
||||
if (!result) throw new ProcessCanceledException();
|
||||
inspectInjectedPsi(elements, tools, isOnTheFly, indicator, iManager, true);
|
||||
}
|
||||
@@ -321,7 +321,7 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
|
||||
return true;
|
||||
}
|
||||
};
|
||||
boolean result = JobUtil.invokeConcurrentlyUnderProgress(init, processor, myFailFastOnAcquireReadAction, indicator);
|
||||
boolean result = JobUtil.invokeConcurrentlyUnderProgress(init, indicator, myFailFastOnAcquireReadAction, processor);
|
||||
if (!result) {
|
||||
throw new ProcessCanceledException();
|
||||
}
|
||||
@@ -345,19 +345,19 @@ public class LocalInspectionsPass extends ProgressableTextEditorHighlightingPass
|
||||
final boolean inVisibleRange) {
|
||||
final Set<PsiFile> injected = new THashSet<PsiFile>();
|
||||
for (PsiElement element : elements) {
|
||||
InjectedLanguageUtil.enumerate(element, myFile, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
InjectedLanguageUtil.enumerate(element, myFile, false, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
|
||||
injected.add(injectedPsi);
|
||||
}
|
||||
}, false);
|
||||
});
|
||||
}
|
||||
if (injected.isEmpty()) return;
|
||||
if (!JobUtil.invokeConcurrentlyUnderProgress(new ArrayList<PsiFile>(injected), new Processor<PsiFile>() {
|
||||
if (!JobUtil.invokeConcurrentlyUnderProgress(new ArrayList<PsiFile>(injected), indicator, myFailFastOnAcquireReadAction, new Processor<PsiFile>() {
|
||||
public boolean process(final PsiFile injectedPsi) {
|
||||
doInspectInjectedPsi(injectedPsi, tools, onTheFly, indicator, iManager, inVisibleRange);
|
||||
return true;
|
||||
}
|
||||
}, myFailFastOnAcquireReadAction, indicator)) throw new ProcessCanceledException();
|
||||
})) throw new ProcessCanceledException();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+1
-1
@@ -267,7 +267,7 @@ public abstract class PassExecutorService implements Disposable {
|
||||
|
||||
private void submit(final ScheduledPass pass) {
|
||||
if (!pass.myUpdateProgress.isCanceled()) {
|
||||
Job<Void> job = JobUtil.submitToJobThread(pass, pass.myJobPriority, new Consumer<Future>() {
|
||||
Job<Void> job = JobUtil.submitToJobThread(pass.myJobPriority, pass, new Consumer<Future>() {
|
||||
@Override
|
||||
public void consume(Future future) {
|
||||
try {
|
||||
|
||||
+2
-2
@@ -107,7 +107,7 @@ public class BraceHighlightingHandler {
|
||||
final Project project = editor.getProject();
|
||||
if (project == null) return;
|
||||
final int offset = editor.getCaretModel().getOffset();
|
||||
JobUtil.submitToJobThread(new Runnable() {
|
||||
JobUtil.submitToJobThread(Job.DEFAULT_PRIORITY, new Runnable() {
|
||||
public void run() {
|
||||
final PsiFile injected;
|
||||
try {
|
||||
@@ -145,7 +145,7 @@ public class BraceHighlightingHandler {
|
||||
}
|
||||
}, ModalityState.stateForComponent(editor.getComponent()));
|
||||
}
|
||||
}, Job.DEFAULT_PRIORITY);
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean isReallyDisposed(Editor editor, Project project) {
|
||||
|
||||
+2
-2
@@ -546,7 +546,7 @@ public class GlobalInspectionContextImpl extends UserDataHolderBase implements G
|
||||
}
|
||||
pass.doInspectInBatch((InspectionManagerEx)manager, lTools);
|
||||
|
||||
JobUtil.invokeConcurrentlyUnderProgress(globalSimpleTools, new Processor<Tools>() {
|
||||
JobUtil.invokeConcurrentlyUnderProgress(globalSimpleTools, myProgressIndicator, false, new Processor<Tools>() {
|
||||
@Override
|
||||
public boolean process(Tools tools) {
|
||||
GlobalInspectionToolWrapper toolWrapper = (GlobalInspectionToolWrapper)tools.getTool();
|
||||
@@ -557,7 +557,7 @@ public class GlobalInspectionContextImpl extends UserDataHolderBase implements G
|
||||
CONVERT, toolWrapper);
|
||||
return true;
|
||||
}
|
||||
}, false, myProgressIndicator);
|
||||
});
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
throw e;
|
||||
|
||||
+4
-4
@@ -54,7 +54,7 @@ public abstract class ContributorsBasedGotoByModel implements ChooseByNameModel
|
||||
public String[] getNames(final boolean checkBoxState) {
|
||||
final Set<String> names = new ConcurrentHashSet<String>();
|
||||
|
||||
JobUtil.invokeConcurrentlyUnderProgress(filterDumb(myContributors), new Processor<ChooseByNameContributor>() {
|
||||
JobUtil.invokeConcurrentlyUnderProgress(filterDumb(myContributors), ProgressManager.getInstance().getProgressIndicator(), false, new Processor<ChooseByNameContributor>() {
|
||||
@Override
|
||||
public boolean process(ChooseByNameContributor contributor) {
|
||||
try {
|
||||
@@ -71,7 +71,7 @@ public abstract class ContributorsBasedGotoByModel implements ChooseByNameModel
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, false, ProgressManager.getInstance().getProgressIndicator());
|
||||
});
|
||||
|
||||
return ArrayUtil.toStringArray(names);
|
||||
}
|
||||
@@ -101,7 +101,7 @@ public abstract class ContributorsBasedGotoByModel implements ChooseByNameModel
|
||||
public Object[] getElementsByName(final String name, final boolean checkBoxState, final String pattern) {
|
||||
final List<NavigationItem> items = Collections.synchronizedList(new ArrayList<NavigationItem>());
|
||||
|
||||
JobUtil.invokeConcurrentlyUnderProgress(filterDumb(myContributors), new Processor<ChooseByNameContributor>() {
|
||||
JobUtil.invokeConcurrentlyUnderProgress(filterDumb(myContributors), ProgressManager.getInstance().getProgressIndicator(), false, new Processor<ChooseByNameContributor>() {
|
||||
@Override
|
||||
public boolean process(ChooseByNameContributor contributor) {
|
||||
try {
|
||||
@@ -124,7 +124,7 @@ public abstract class ContributorsBasedGotoByModel implements ChooseByNameModel
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}, false, ProgressManager.getInstance().getProgressIndicator());
|
||||
});
|
||||
|
||||
return ArrayUtil.toObjectArray(items);
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.event.DocumentEvent;
|
||||
import com.intellij.openapi.progress.ProcessCanceledException;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
@@ -44,6 +43,7 @@ import com.intellij.psi.impl.source.tree.FileElement;
|
||||
import com.intellij.psi.text.BlockSupport;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.containers.Queue;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
@@ -52,7 +52,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.TestOnly;
|
||||
|
||||
import javax.swing.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
@@ -127,20 +126,23 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
useIndicator(null);
|
||||
}
|
||||
|
||||
public boolean queueCommit(@NonNls @NotNull String reason, @NotNull Document document, @NotNull Project project, @Nullable DocumentEvent event) {
|
||||
log("queueCommit called", document, false, reason, event);
|
||||
public boolean queueCommit(@NotNull Project project, @NotNull Document document, @NonNls @NotNull Object reason) {
|
||||
log("queueCommit called", document, false, reason);
|
||||
assert !isDisposed : "already disposed";
|
||||
|
||||
if (!project.isInitialized()) return false;
|
||||
PsiFile psiFile = PsiDocumentManager.getInstance(project).getCachedPsiFile(document);
|
||||
if (psiFile == null) return false;
|
||||
|
||||
boolean added = doQueue(document, project, getCommitStage(document), reason, event);
|
||||
boolean added = doQueue(document, project, getCommitStage(document), reason);
|
||||
log("doQueue called", document, false, added);
|
||||
return added;
|
||||
}
|
||||
|
||||
private boolean doQueue(@NotNull Document document, @NotNull Project project, CommitStage start, @NonNls @NotNull String reason, @Nullable DocumentEvent event) {
|
||||
private boolean doQueue(@NotNull Document document,
|
||||
@NotNull Project project,
|
||||
CommitStage start,
|
||||
@NonNls @NotNull Object reason) {
|
||||
synchronized (documentsToCommit) {
|
||||
if (!changeCommitStage(document, start, CommitStage.QUEUED_TO_COMMIT, false)) return false;
|
||||
|
||||
@@ -163,7 +165,7 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
}
|
||||
ProgressIndicator indicator = new ProgressIndicatorBase();
|
||||
indicator.start();
|
||||
documentsToCommit.addLast(new CommitTask(document, project, indicator, reason, event));
|
||||
documentsToCommit.addLast(new CommitTask(document, project, indicator, reason));
|
||||
log("Queued", document, false, reason);
|
||||
return true;
|
||||
}
|
||||
@@ -172,6 +174,7 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
private final StringBuilder log = new StringBuilder();
|
||||
void log(@NonNls String msg, Document document, boolean synchronously, @NonNls Object... args) {
|
||||
if (debug()) {
|
||||
@NonNls
|
||||
String s = (SwingUtilities.isEventDispatchThread() ? " " : "") +
|
||||
msg + (synchronously ? " (sync)" : "") +
|
||||
(document == null ? "" : "; Document: " + System.identityHashCode(document) +
|
||||
@@ -218,19 +221,16 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
// running = false means document was removed from the queue, should ignore.
|
||||
// canceled = true means commit was canceled, should reschedule for later.
|
||||
private final ProgressIndicator indicator; // progress to commit this doc under.
|
||||
private final String reason;
|
||||
@Nullable private final DocumentEvent event;
|
||||
private final Object reason;
|
||||
|
||||
private CommitTask(@NotNull Document document,
|
||||
@NotNull Project project,
|
||||
@NotNull ProgressIndicator indicator,
|
||||
@NotNull String reason,
|
||||
@Nullable DocumentEvent event) {
|
||||
@NotNull Object reason) {
|
||||
this.document = document;
|
||||
this.project = project;
|
||||
this.indicator = indicator;
|
||||
this.reason = reason;
|
||||
this.event = event;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,7 +275,7 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
CommitStage commitStage = getCommitStage(document);
|
||||
Document[] uncommitted = null;
|
||||
if (commitStage != CommitStage.QUEUED_TO_COMMIT
|
||||
|| project.isDisposed() || !ArrayUtil.contains(document,(uncommitted = PsiDocumentManager.getInstance(project).getUncommittedDocuments()))) {
|
||||
|| project.isDisposed() || !ArrayUtil.contains(document, uncommitted = PsiDocumentManager.getInstance(project).getUncommittedDocuments())) {
|
||||
List<Document> documents = uncommitted == null ? null : Arrays.asList(uncommitted);
|
||||
log("Abandon and proceeding to next",document, false, commitStage, documents);
|
||||
continue;
|
||||
@@ -292,7 +292,7 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
Runnable finishRunnable = null;
|
||||
if (!success && !indicator.isCanceled()) {
|
||||
try {
|
||||
finishRunnable = commit(document, project, null, indicator, false, task.reason, task.event);
|
||||
finishRunnable = commit(document, project, null, indicator, false, task.reason);
|
||||
success = finishRunnable != null;
|
||||
log("DCT.commit returned", document, false, finishRunnable, indicator);
|
||||
}
|
||||
@@ -312,8 +312,7 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
}
|
||||
}
|
||||
catch (ProcessCanceledException e) {
|
||||
int i = 0; // leave queue unchanged
|
||||
cancel(e);
|
||||
cancel(e); // leave queue unchanged
|
||||
log("PCE", document, false, e);
|
||||
success = false;
|
||||
}
|
||||
@@ -332,7 +331,7 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
// reset status for queue back successfully
|
||||
changeCommitStage(document, CommitStage.WAITING_FOR_PSI_APPLY, CommitStage.QUEUED_TO_COMMIT, false);
|
||||
changeCommitStage(document, CommitStage.COMMITTED, CommitStage.QUEUED_TO_COMMIT, false);
|
||||
doQueue(document, project, CommitStage.QUEUED_TO_COMMIT, "re-added on failure", null);
|
||||
doQueue(document, project, CommitStage.QUEUED_TO_COMMIT, "re-added on failure");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -371,7 +370,7 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
ProgressIndicatorBase indicator = new ProgressIndicatorBase();
|
||||
indicator.start();
|
||||
log("About to commit sync", document, true, indicator);
|
||||
Runnable finish = commit(document, project, excludeFile, indicator, true, "Sync commit", null);
|
||||
Runnable finish = commit(document, project, excludeFile, indicator, true, "Sync commit");
|
||||
log("Committed sync", document, true, finish, indicator);
|
||||
|
||||
assert finish != null;
|
||||
@@ -383,13 +382,12 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
final PsiFile excludeFile,
|
||||
@NotNull final ProgressIndicator indicator,
|
||||
final boolean synchronously,
|
||||
@NotNull final String reason,
|
||||
@Nullable final DocumentEvent event) {
|
||||
@NotNull final Object reason) {
|
||||
final Runnable[] success = new Runnable[1];
|
||||
((ProgressManagerImpl)ProgressManager.getInstance()).executeProcessUnderProgress(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
success[0] = commitUnderProgress(document, project, excludeFile, indicator, synchronously, reason, event);
|
||||
success[0] = commitUnderProgress(document, project, excludeFile, indicator, synchronously, reason);
|
||||
}
|
||||
}, indicator);
|
||||
return success[0];
|
||||
@@ -411,9 +409,8 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
final PsiFile excludeFile,
|
||||
@NotNull final ProgressIndicator indicator,
|
||||
final boolean synchronously,
|
||||
@NotNull final String reason,
|
||||
@Nullable final DocumentEvent event) {
|
||||
final List<Processor<Document>> finishRunnables = new ArrayList<Processor<Document>>();
|
||||
@NotNull final Object reason) {
|
||||
final List<Processor<Document>> finishRunnables = new SmartList<Processor<Document>>();
|
||||
Runnable runnable = new Runnable() {
|
||||
public void run() {
|
||||
if (project.isDisposed()) return;
|
||||
@@ -432,7 +429,7 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
}
|
||||
};
|
||||
if (synchronously) {
|
||||
ApplicationManager.getApplication().assertIsDispatchThread();
|
||||
ApplicationManager.getApplication().assertWriteAccessAllowed();
|
||||
runnable.run();
|
||||
}
|
||||
else {
|
||||
@@ -458,45 +455,38 @@ public class DocumentCommitThread implements Runnable, Disposable {
|
||||
@Override
|
||||
public void run() {
|
||||
if (project.isDisposed()) return;
|
||||
ApplicationManager.getApplication().runWriteAction(new CommitToPsiFileAction(document, project) {
|
||||
public void run() {
|
||||
if (project.isDisposed()) return;
|
||||
PsiDocumentManagerImpl documentManager = (PsiDocumentManagerImpl)PsiDocumentManager.getInstance(project);
|
||||
|
||||
CommitStage stage = getCommitStage(document);
|
||||
log("Finish", document, synchronously, project);
|
||||
if (stage != (synchronously ? CommitStage.ABOUT_TO_BE_SYNC_COMMITTED : CommitStage.WAITING_FOR_PSI_APPLY)) {
|
||||
return; // there must be a synchronous commit sneaked in between queued commit and finish commit, or just document changed meanwhile
|
||||
}
|
||||
PsiDocumentManagerImpl documentManager = (PsiDocumentManagerImpl)PsiDocumentManager.getInstance(project);
|
||||
|
||||
boolean success = false;
|
||||
try {
|
||||
success = documentManager.finishCommit(document, finishRunnables, synchronously, reason, event);
|
||||
log("Finished", document, synchronously, success, Arrays.asList(documentManager.getUncommittedDocuments()));
|
||||
if (synchronously) {
|
||||
assert success;
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (success) {
|
||||
CommitStage before = getCommitStage(document);
|
||||
boolean changed = synchronously || changeCommitStage(document, CommitStage.WAITING_FOR_PSI_APPLY, CommitStage.COMMITTED, false);
|
||||
assert changed : "Before: " + before + "; after: " + getCommitStage(document);
|
||||
}
|
||||
}
|
||||
List<Document> unc = Arrays.asList(documentManager.getUncommittedDocuments());
|
||||
log("after call finish commit",document, synchronously, unc, success);
|
||||
if (synchronously || success) {
|
||||
assert !unc.contains(document) : unc;
|
||||
}
|
||||
if (!success) {
|
||||
// add document back to the queue
|
||||
log("Re-adding back", document, synchronously, success, documentManager.isCommitted(document), Arrays.asList(documentManager.getUncommittedDocuments()));
|
||||
boolean addedBack = queueCommit("Re-added back", document, project, null);
|
||||
assert addedBack;
|
||||
}
|
||||
CommitStage stage = getCommitStage(document);
|
||||
log("Finish", document, synchronously, project);
|
||||
if (stage != (synchronously ? CommitStage.ABOUT_TO_BE_SYNC_COMMITTED : CommitStage.WAITING_FOR_PSI_APPLY)) {
|
||||
return; // there must be a synchronous commit sneaked in between queued commit and finish commit, or just document changed meanwhile
|
||||
}
|
||||
|
||||
boolean success = false;
|
||||
try {
|
||||
success = documentManager.finishCommit(document, finishRunnables, synchronously, reason);
|
||||
log("Finished", document, synchronously, success, Arrays.asList(documentManager.getUncommittedDocuments()));
|
||||
if (synchronously) {
|
||||
assert success;
|
||||
}
|
||||
});
|
||||
}
|
||||
finally {
|
||||
if (success) {
|
||||
success = synchronously || changeCommitStage(document, CommitStage.WAITING_FOR_PSI_APPLY, CommitStage.COMMITTED, false);
|
||||
}
|
||||
}
|
||||
List<Document> unc = Arrays.asList(documentManager.getUncommittedDocuments());
|
||||
log("after call finish commit",document, synchronously, unc, success);
|
||||
if (synchronously || success) {
|
||||
assert !unc.contains(document) : unc;
|
||||
}
|
||||
if (!success) {
|
||||
// add document back to the queue
|
||||
boolean addedBack = queueCommit(project, document, "Re-added back");
|
||||
assert addedBack;
|
||||
}
|
||||
}
|
||||
};
|
||||
return finishRunnable;
|
||||
|
||||
@@ -18,7 +18,9 @@ package com.intellij.psi.impl;
|
||||
|
||||
import com.intellij.AppTopics;
|
||||
import com.intellij.injected.editor.DocumentWindow;
|
||||
import com.intellij.injected.editor.EditorWindow;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.openapi.application.Application;
|
||||
import com.intellij.openapi.application.ApplicationAdapter;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
@@ -46,7 +48,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.smartPointers.SmartPointerManagerImpl;
|
||||
import com.intellij.psi.impl.source.PostprocessReformattingAspect;
|
||||
import com.intellij.psi.impl.source.PsiFileImpl;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
|
||||
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl;
|
||||
import com.intellij.psi.text.BlockSupport;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.SmartList;
|
||||
@@ -312,59 +314,66 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec
|
||||
}
|
||||
|
||||
boolean finishCommit(@NotNull final Document document,
|
||||
@NotNull List<Processor<Document>> finishRunnables,
|
||||
boolean synchronously,
|
||||
@NotNull String reason,
|
||||
@Nullable DocumentEvent event) {
|
||||
@NotNull final List<Processor<Document>> finishRunnables,
|
||||
final boolean synchronously,
|
||||
@NotNull Object reason) {
|
||||
if (myProject.isDisposed()) return false;
|
||||
ApplicationManager.getApplication().assertWriteAccessAllowed();
|
||||
|
||||
assert !(document instanceof DocumentWindow);
|
||||
myIsCommitInProgress = true;
|
||||
boolean success = true;
|
||||
try {
|
||||
final FileViewProvider viewProvider = getCachedViewProvider(document);
|
||||
if (viewProvider != null) {
|
||||
for (Processor<Document> finishRunnable : finishRunnables) {
|
||||
success = finishRunnable.process(document);
|
||||
if (synchronously) {
|
||||
assert success;
|
||||
}
|
||||
if (!success) {
|
||||
break;
|
||||
final boolean[] ok = {true};
|
||||
ApplicationManager.getApplication().runWriteAction(new CommitToPsiFileAction(document, myProject) {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myProject.isDisposed()) return;
|
||||
EditorWindow.disposeInvalidEditors(); // in write action
|
||||
assert !(document instanceof DocumentWindow);
|
||||
myIsCommitInProgress = true;
|
||||
boolean success = true;
|
||||
try {
|
||||
final FileViewProvider viewProvider = getCachedViewProvider(document);
|
||||
if (viewProvider != null) {
|
||||
for (Processor<Document> finishRunnable : finishRunnables) {
|
||||
success = finishRunnable.process(document);
|
||||
if (synchronously) {
|
||||
assert success;
|
||||
}
|
||||
if (!success) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
viewProvider.contentsSynchronized();
|
||||
}
|
||||
ok[0] = success;
|
||||
}
|
||||
finally {
|
||||
myDocumentCommitThread.log("in PDI.finishDoc: ", document, synchronously, success, myUncommittedDocuments);
|
||||
if (success) {
|
||||
myUncommittedDocuments.remove(document);
|
||||
myDocumentCommitThread.log("in PDI.finishDoc: removed doc", document, synchronously, success, myUncommittedDocuments);
|
||||
}
|
||||
myIsCommitInProgress = false;
|
||||
myDocumentCommitThread.log("in PDI.finishDoc: exit", document, synchronously, success, myUncommittedDocuments);
|
||||
}
|
||||
viewProvider.contentsSynchronized();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
myDocumentCommitThread.log("in PDI.finishDoc: ",document, synchronously, success, myUncommittedDocuments);
|
||||
if (success) {
|
||||
myUncommittedDocuments.remove(document);
|
||||
myDocumentCommitThread.log("in PDI.finishDoc: removed doc",document, synchronously, success, myUncommittedDocuments);
|
||||
InjectedLanguageUtil.commitAllInjectedDocuments(document, myProject);
|
||||
}
|
||||
myIsCommitInProgress = false;
|
||||
myDocumentCommitThread.log("in PDI.finishDoc: exit",document, synchronously, success, myUncommittedDocuments);
|
||||
}
|
||||
});
|
||||
|
||||
if (success) {
|
||||
if (ok[0]) {
|
||||
((InjectedLanguageManagerImpl)InjectedLanguageManager.getInstance(myProject)).startRunInjectors(document, synchronously);
|
||||
// run after commit actions outside write action
|
||||
runAfterCommitActions(document);
|
||||
if (DebugUtil.DO_EXPENSIVE_CHECKS) {
|
||||
checkAllElementsValid(document, reason, event);
|
||||
checkAllElementsValid(document, reason);
|
||||
}
|
||||
}
|
||||
return success;
|
||||
return ok[0];
|
||||
}
|
||||
|
||||
private void checkAllElementsValid(@NotNull Document document, @NotNull final String reason, @Nullable final DocumentEvent event) {
|
||||
private void checkAllElementsValid(@NotNull Document document, @NotNull final Object reason) {
|
||||
final PsiFile psiFile = getCachedPsiFile(document);
|
||||
if (psiFile != null) {
|
||||
psiFile.accept(new PsiRecursiveElementWalkingVisitor() {
|
||||
@Override
|
||||
public void visitElement(PsiElement element) {
|
||||
if (!element.isValid()) {
|
||||
LOG.error("Commit to '"+psiFile.getVirtualFile()+"' lead to invalid element: "+element+ "; Reason: '"+reason+"'; Doc change event: "+event);
|
||||
LOG.error("Commit to '"+psiFile.getVirtualFile()+"' lead to invalid element: "+element+ "; Reason: '"+reason+"'");
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -616,7 +625,7 @@ public class PsiDocumentManagerImpl extends PsiDocumentManager implements Projec
|
||||
if (commitNecessary) {
|
||||
myUncommittedDocuments.add(document);
|
||||
|
||||
myDocumentCommitThread.queueCommit("Document changed", document, myProject, event);
|
||||
myDocumentCommitThread.queueCommit(myProject, document, event);
|
||||
}
|
||||
|
||||
// Consider that it's worth to perform complete re-parse instead of merge if the whole document text is replaced and
|
||||
|
||||
@@ -184,11 +184,11 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
PsiElement[] scopeElements = scope.getScope();
|
||||
final boolean ignoreInjectedPsi = scope.isIgnoreInjectedPsi();
|
||||
|
||||
return JobUtil.invokeConcurrentlyUnderProgress(Arrays.asList(scopeElements), new Processor<PsiElement>() {
|
||||
return JobUtil.invokeConcurrentlyUnderProgress(Arrays.asList(scopeElements), progress, false, new Processor<PsiElement>() {
|
||||
public boolean process(PsiElement scopeElement) {
|
||||
return processElementsWithWordInScopeElement(scopeElement, processor, text, caseSensitively, ignoreInjectedPsi, progress);
|
||||
}
|
||||
}, false, progress);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
final AtomicBoolean pceThrown = new AtomicBoolean(false);
|
||||
|
||||
final int size = files.size();
|
||||
boolean completed = JobUtil.invokeConcurrentlyUnderProgress(files, new Processor<VirtualFile>() {
|
||||
boolean completed = JobUtil.invokeConcurrentlyUnderProgress(files, progress, false, new Processor<VirtualFile>() {
|
||||
public boolean process(final VirtualFile vfile) {
|
||||
final PsiFile file = ApplicationManager.getApplication().runReadAction(new Computable<PsiFile>() {
|
||||
public PsiFile compute() {
|
||||
@@ -288,7 +288,7 @@ public class PsiSearchHelperImpl implements PsiSearchHelper {
|
||||
}
|
||||
return !canceled.get();
|
||||
}
|
||||
}, false, progress);
|
||||
});
|
||||
|
||||
if (pceThrown.get()) {
|
||||
throw new ProcessCanceledException();
|
||||
|
||||
+2
-2
@@ -65,7 +65,7 @@ class InjectedSelfElementInfo extends SelfElementInfo {
|
||||
final Ref<PsiElement> result = new Ref<PsiElement>();
|
||||
|
||||
final InjectedLanguageManager manager = InjectedLanguageManager.getInstance(getProject());
|
||||
InjectedLanguageUtil.enumerate(hostContext, hostContext.getContainingFile(), new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
InjectedLanguageUtil.enumerate(hostContext, hostContext.getContainingFile(), true, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
@Override
|
||||
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
|
||||
if (result.get() != null) return;
|
||||
@@ -78,7 +78,7 @@ class InjectedSelfElementInfo extends SelfElementInfo {
|
||||
result.set(element);
|
||||
}
|
||||
}
|
||||
}, true);
|
||||
});
|
||||
|
||||
return result.get();
|
||||
}
|
||||
|
||||
+5
-10
@@ -143,26 +143,21 @@ public class PostprocessReformattingAspect implements PomModelAspect, Disposable
|
||||
|
||||
private void decrementPostponedCounter() {
|
||||
if (--myPostponedCounter == 0) {
|
||||
if (!ApplicationManager.getApplication().isWriteAccessAllowed()) {
|
||||
if (ApplicationManager.getApplication().isWriteAccessAllowed()) {
|
||||
doPostponedFormatting();
|
||||
}
|
||||
else {
|
||||
ApplicationManager.getApplication().runWriteAction(new Runnable() {
|
||||
public void run() {
|
||||
doPostponedFormatting();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
doPostponedFormatting();
|
||||
}
|
||||
//myDisabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private final Object LOCK = new Object();
|
||||
|
||||
private void atomic(Runnable r) {
|
||||
synchronized (LOCK) {
|
||||
ProgressManager.getInstance().executeNonCancelableSection(r);
|
||||
}
|
||||
ProgressManager.getInstance().executeNonCancelableSection(r);
|
||||
}
|
||||
|
||||
public void update(final PomModelEvent event) {
|
||||
|
||||
+2
-2
@@ -98,14 +98,14 @@ public class InjectedFileViewProvider extends SingleRootFileViewProvider {
|
||||
PsiElement elementCopy = hostPsiFileCopy.getViewProvider().findElementAt(firstTextRange.getStartOffset(), hostFileLanguage);
|
||||
assert elementCopy != null;
|
||||
final Ref<FileViewProvider> provider = new Ref<FileViewProvider>();
|
||||
InjectedLanguageUtil.enumerate(elementCopy, hostPsiFileCopy, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
InjectedLanguageUtil.enumerate(elementCopy, hostPsiFileCopy, true, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
|
||||
Document document = documentManager.getCachedDocument(injectedPsi);
|
||||
if (document instanceof DocumentWindowImpl && oldDocumentWindow.areRangesEqual((DocumentWindowImpl)document)) {
|
||||
provider.set(injectedPsi.getViewProvider());
|
||||
}
|
||||
}
|
||||
}, true);
|
||||
});
|
||||
return provider.get();
|
||||
}
|
||||
|
||||
|
||||
+97
-11
@@ -16,6 +16,11 @@
|
||||
|
||||
package com.intellij.psi.impl.source.tree.injected;
|
||||
|
||||
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
|
||||
import com.intellij.codeInsight.daemon.impl.DaemonProgressIndicator;
|
||||
import com.intellij.concurrency.Job;
|
||||
import com.intellij.concurrency.JobUtil;
|
||||
import com.intellij.injected.editor.DocumentWindow;
|
||||
import com.intellij.injected.editor.DocumentWindowImpl;
|
||||
import com.intellij.injected.editor.VirtualFileWindow;
|
||||
import com.intellij.lang.Language;
|
||||
@@ -23,21 +28,24 @@ import com.intellij.lang.injection.InjectedLanguageManager;
|
||||
import com.intellij.lang.injection.MultiHostInjector;
|
||||
import com.intellij.lang.injection.MultiHostRegistrar;
|
||||
import com.intellij.openapi.Disposable;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.application.ex.ApplicationManagerEx;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.RangeMarker;
|
||||
import com.intellij.openapi.extensions.ExtensionPoint;
|
||||
import com.intellij.openapi.extensions.ExtensionPointListener;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.extensions.PluginDescriptor;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.DumbService;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.Disposer;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.ProperTextRange;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.*;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.PsiDocumentManagerImpl;
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.Processor;
|
||||
import com.intellij.util.containers.ConcurrentHashMap;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -51,11 +59,12 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
/**
|
||||
* @author cdr
|
||||
*/
|
||||
public class InjectedLanguageManagerImpl extends InjectedLanguageManager {
|
||||
public class InjectedLanguageManagerImpl extends InjectedLanguageManager implements Disposable{
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl");
|
||||
private final Project myProject;
|
||||
private final DumbService myDumbService;
|
||||
private final AtomicReference<MultiHostInjector> myPsiManagerRegisteredInjectorsAdapter = new AtomicReference<MultiHostInjector>();
|
||||
private volatile DaemonProgressIndicator myProgress;
|
||||
|
||||
public static InjectedLanguageManagerImpl getInstanceImpl(Project project) {
|
||||
return (InjectedLanguageManagerImpl)InjectedLanguageManager.getInstance(project);
|
||||
@@ -74,7 +83,7 @@ public class InjectedLanguageManagerImpl extends InjectedLanguageManager {
|
||||
public void extensionRemoved(@NotNull MultiHostInjector injector, @Nullable PluginDescriptor pluginDescriptor) {
|
||||
unregisterMultiHostInjector(injector);
|
||||
}
|
||||
});
|
||||
},this);
|
||||
final ExtensionPointListener<LanguageInjector> myListener = new ExtensionPointListener<LanguageInjector>() {
|
||||
public void extensionAdded(@NotNull LanguageInjector extension, @Nullable PluginDescriptor pluginDescriptor) {
|
||||
psiManagerInjectorsChanged();
|
||||
@@ -85,14 +94,91 @@ public class InjectedLanguageManagerImpl extends InjectedLanguageManager {
|
||||
}
|
||||
};
|
||||
final ExtensionPoint<LanguageInjector> psiManagerPoint = Extensions.getRootArea().getExtensionPoint(LanguageInjector.EXTENSION_POINT_NAME);
|
||||
psiManagerPoint.addExtensionPointListener(myListener);
|
||||
Disposer.register(project, new Disposable() {
|
||||
public void dispose() {
|
||||
psiManagerPoint.removeExtensionPointListener(myListener);
|
||||
psiManagerPoint.addExtensionPointListener(myListener,this);
|
||||
myProgress = new DaemonProgressIndicator();
|
||||
project.getMessageBus().connect(this).subscribe(DaemonCodeAnalyzer.DAEMON_EVENT_TOPIC, new DaemonCodeAnalyzer.DaemonListener() {
|
||||
@Override
|
||||
public void daemonFinished() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void daemonCancelEventOccurred() {
|
||||
myProgress.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose() {
|
||||
}
|
||||
|
||||
public boolean startRunInjectors(@NotNull Document hostDocument, final boolean synchronously) {
|
||||
if (myProject.isDisposed()) return true;
|
||||
assert synchronously || !ApplicationManager.getApplication().isWriteAccessAllowed();
|
||||
// use cached to avoid recreate PSI in alien project
|
||||
final PsiFile hostPsiFile = PsiDocumentManager.getInstance(myProject).getCachedPsiFile(hostDocument);
|
||||
if (hostPsiFile == null) return true;
|
||||
|
||||
final List<DocumentWindow> injected = InjectedLanguageUtil.getCachedInjectedDocuments(hostPsiFile);
|
||||
if (injected.isEmpty()) return true;
|
||||
|
||||
if (myProgress.isCanceled()) {
|
||||
myProgress = new DaemonProgressIndicator();
|
||||
}
|
||||
|
||||
final Computable<Boolean> commitRunnable = new Computable<Boolean>() {
|
||||
@Override
|
||||
public Boolean compute() {
|
||||
return JobUtil.invokeConcurrentlyUnderProgress(injected, myProgress, !synchronously, new Processor<DocumentWindow>() {
|
||||
@Override
|
||||
public boolean process(DocumentWindow documentWindow) {
|
||||
ProgressManager.checkCanceled();
|
||||
RangeMarker rangeMarker = documentWindow.getHostRanges()[0];
|
||||
PsiElement element = rangeMarker.isValid() ? hostPsiFile.findElementAt(rangeMarker.getStartOffset()) : null;
|
||||
if (element == null) {
|
||||
injected.remove(documentWindow);
|
||||
return true;
|
||||
}
|
||||
final DocumentWindow[] stillInjectedDocument = {null};
|
||||
// it is here where the reparse happens and old file contents replaced
|
||||
InjectedLanguageUtil.enumerate(element, hostPsiFile, true, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
|
||||
stillInjectedDocument[0] = (DocumentWindow)injectedPsi.getViewProvider().getDocument();
|
||||
PsiDocumentManagerImpl.checkConsistency(injectedPsi, stillInjectedDocument[0]);
|
||||
}
|
||||
});
|
||||
if (stillInjectedDocument[0] == null) {
|
||||
injected.remove(documentWindow);
|
||||
}
|
||||
else if (stillInjectedDocument[0] != documentWindow) {
|
||||
injected.remove(documentWindow);
|
||||
injected.add(stillInjectedDocument[0]);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
if (synchronously) {
|
||||
return commitRunnable.compute();
|
||||
}
|
||||
else {
|
||||
JobUtil.submitToJobThread(Job.DEFAULT_PRIORITY, new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ApplicationManagerEx.getApplicationEx().tryRunReadAction(new Runnable() {
|
||||
public void run() {
|
||||
commitRunnable.compute();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void psiManagerInjectorsChanged() {
|
||||
LanguageInjector[] extensions = Extensions.getExtensions(LanguageInjector.EXTENSION_POINT_NAME);
|
||||
if (extensions.length == 0) {
|
||||
@@ -210,7 +296,7 @@ public class InjectedLanguageManagerImpl extends InjectedLanguageManager {
|
||||
* @param rangeToEdit range in encoded(raw) PSI
|
||||
* @return list of ranges in encoded (raw) PSI
|
||||
*/
|
||||
@SuppressWarnings({"ConstantConditions"})
|
||||
@SuppressWarnings({"ConstantConditions", "unchecked"})
|
||||
@NotNull
|
||||
public List<TextRange> intersectWithAllEditableFragments(@NotNull PsiFile injectedPsi, @NotNull TextRange rangeToEdit) {
|
||||
Place shreds = InjectedLanguageUtil.getShreds(injectedPsi);
|
||||
|
||||
+9
-7
@@ -104,10 +104,13 @@ public class InjectedLanguageUtil {
|
||||
|
||||
public static void enumerate(@NotNull PsiElement host, @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) {
|
||||
PsiFile containingFile = host.getContainingFile();
|
||||
enumerate(host, containingFile, visitor, true);
|
||||
enumerate(host, containingFile, true, visitor);
|
||||
}
|
||||
|
||||
public static void enumerate(@NotNull PsiElement host, @NotNull PsiFile containingFile, @NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor, boolean probeUp) {
|
||||
public static void enumerate(@NotNull PsiElement host,
|
||||
@NotNull PsiFile containingFile,
|
||||
boolean probeUp,
|
||||
@NotNull PsiLanguageInjectionHost.InjectedPsiVisitor visitor) {
|
||||
//do not inject into nonphysical files except during completion
|
||||
if (!containingFile.isPhysical() && containingFile.getOriginalFile() == containingFile) {
|
||||
final PsiElement context = containingFile.getContext();
|
||||
@@ -193,7 +196,6 @@ public class InjectedLanguageUtil {
|
||||
final Project project = psiManager.getProject();
|
||||
InjectedLanguageManagerImpl injectedManager = InjectedLanguageManagerImpl.getInstanceImpl(project);
|
||||
if (injectedManager == null) return null; //for tests
|
||||
long modificationCount = psiManager.getModificationTracker().getModificationCount();
|
||||
MultiHostRegistrarImpl registrar = null;
|
||||
PsiElement current = element;
|
||||
nextParent:
|
||||
@@ -290,7 +292,7 @@ public class InjectedLanguageUtil {
|
||||
|
||||
private static PsiElement findInside(@NotNull PsiElement element, @NotNull PsiFile hostFile, final int hostOffset, @NotNull final PsiDocumentManager documentManager) {
|
||||
final Ref<PsiElement> out = new Ref<PsiElement>();
|
||||
enumerate(element, hostFile, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
enumerate(element, hostFile, true, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
|
||||
for (PsiLanguageInjectionHost.Shred place : places) {
|
||||
TextRange hostRange = place.host.getTextRange();
|
||||
@@ -303,7 +305,7 @@ public class InjectedLanguageUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
}, true);
|
||||
});
|
||||
return out.get();
|
||||
}
|
||||
|
||||
@@ -340,12 +342,12 @@ public class InjectedLanguageUtil {
|
||||
}
|
||||
final DocumentWindow[] stillInjectedDocument = {null};
|
||||
// it is here where the reparse happens and old file contents replaced
|
||||
enumerate(element, hostPsiFile, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
enumerate(element, hostPsiFile, true, new PsiLanguageInjectionHost.InjectedPsiVisitor() {
|
||||
public void visit(@NotNull PsiFile injectedPsi, @NotNull List<PsiLanguageInjectionHost.Shred> places) {
|
||||
stillInjectedDocument[0] = (DocumentWindow)injectedPsi.getViewProvider().getDocument();
|
||||
PsiDocumentManagerImpl.checkConsistency(injectedPsi, stillInjectedDocument[0]);
|
||||
}
|
||||
}, true);
|
||||
});
|
||||
if (stillInjectedDocument[0] == null) {
|
||||
injected.remove(i);
|
||||
}
|
||||
|
||||
@@ -106,7 +106,7 @@ public class DeferredIconImpl<T> implements DeferredIcon {
|
||||
paintingParentRec.set(((PaintingParent)pp).getChildRec(c));
|
||||
}
|
||||
|
||||
JobUtil.submitToJobThread(new Runnable() {
|
||||
JobUtil.submitToJobThread(Job.DEFAULT_PRIORITY, new Runnable() {
|
||||
public void run() {
|
||||
int oldWidth = myDelegateIcon.getIconWidth();
|
||||
myDelegateIcon = evaluate();
|
||||
@@ -153,7 +153,7 @@ public class DeferredIconImpl<T> implements DeferredIcon {
|
||||
}
|
||||
});
|
||||
}
|
||||
}, Job.DEFAULT_PRIORITY);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,8 +41,8 @@ public class JobUtil {
|
||||
}
|
||||
|
||||
private static <T> boolean invokeConcurrentlyForAll(@NotNull final List<T> things,
|
||||
@NotNull final Processor<T> thingProcessor,
|
||||
boolean failFastOnAcquireReadAction) throws ProcessCanceledException {
|
||||
boolean failFastOnAcquireReadAction,
|
||||
@NotNull final Processor<T> thingProcessor) throws ProcessCanceledException {
|
||||
final Job<String> job = new JobImpl<String>(Job.DEFAULT_PRIORITY, failFastOnAcquireReadAction);
|
||||
|
||||
final int chunkSize = Math.max(1, things.size() / JobSchedulerImpl.CORES_COUNT / 20);
|
||||
@@ -84,10 +84,11 @@ public class JobUtil {
|
||||
/**
|
||||
* Schedules concurrent execution of #thingProcessor over each element of #things and waits for completion
|
||||
* With checkCanceled in each thread delegated to our current progress
|
||||
*
|
||||
* @param things to process concurrently
|
||||
* @param thingProcessor to be invoked concurrently on each element from the collection
|
||||
* @param failFastOnAcquireReadAction if true, returns false when failed to acquire read action
|
||||
* @param progress
|
||||
* @param failFastOnAcquireReadAction if true, returns false when failed to acquire read action
|
||||
* @param thingProcessor to be invoked concurrently on each element from the collection
|
||||
* @return false if tasks have been canceled
|
||||
* or at least one processor returned false
|
||||
* or threw exception
|
||||
@@ -95,9 +96,9 @@ public class JobUtil {
|
||||
* @throws ProcessCanceledException if at least one task has thrown ProcessCanceledException
|
||||
*/
|
||||
public static <T> boolean invokeConcurrentlyUnderProgress(@NotNull List<T> things,
|
||||
@NotNull final Processor<T> thingProcessor,
|
||||
ProgressIndicator progress,
|
||||
boolean failFastOnAcquireReadAction,
|
||||
ProgressIndicator progress) throws ProcessCanceledException {
|
||||
@NotNull final Processor<T> thingProcessor) throws ProcessCanceledException {
|
||||
if (things.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
@@ -108,7 +109,7 @@ public class JobUtil {
|
||||
|
||||
// can be already wrapped
|
||||
final ProgressWrapper wrapper = progress instanceof ProgressWrapper ? (ProgressWrapper)progress : ProgressWrapper.wrap(progress);
|
||||
return invokeConcurrentlyForAll(things, new Processor<T>() {
|
||||
return invokeConcurrentlyForAll(things, failFastOnAcquireReadAction, new Processor<T>() {
|
||||
public boolean process(final T t) {
|
||||
final boolean[] result = new boolean[1];
|
||||
((ProgressManagerImpl)ProgressManager.getInstance()).executeProcessUnderProgress(new Runnable() {
|
||||
@@ -118,14 +119,14 @@ public class JobUtil {
|
||||
}, wrapper);
|
||||
return result[0];
|
||||
}
|
||||
}, failFastOnAcquireReadAction);
|
||||
});
|
||||
}
|
||||
|
||||
public static Job<Void> submitToJobThread(@NotNull final Runnable action, int priority) {
|
||||
return submitToJobThread(action, priority, null);
|
||||
public static Job<Void> submitToJobThread(int priority, @NotNull final Runnable action) {
|
||||
return submitToJobThread(priority, action, null);
|
||||
}
|
||||
|
||||
public static Job<Void> submitToJobThread(@NotNull final Runnable action, int priority, Consumer<Future> onDoneCallback) {
|
||||
public static Job<Void> submitToJobThread(int priority, @NotNull final Runnable action, Consumer<Future> onDoneCallback) {
|
||||
final JobImpl<Void> job = new JobImpl<Void>(priority, false);
|
||||
Callable<Void> callable = new Callable<Void>() {
|
||||
public Void call() throws Exception {
|
||||
|
||||
+2
-2
@@ -163,7 +163,7 @@ public class DuplicatePropertyInspection extends GlobalSimpleInspectionTool {
|
||||
final ProgressIndicator progress = ProgressWrapper.wrap(original);
|
||||
ProgressManager.getInstance().runProcess(new Runnable() {
|
||||
public void run() {
|
||||
if (!JobUtil.invokeConcurrentlyUnderProgress(properties, new Processor<IProperty>() {
|
||||
if (!JobUtil.invokeConcurrentlyUnderProgress(properties, progress, false, new Processor<IProperty>() {
|
||||
public boolean process(final IProperty property) {
|
||||
if (original != null) {
|
||||
if (original.isCanceled()) return false;
|
||||
@@ -173,7 +173,7 @@ public class DuplicatePropertyInspection extends GlobalSimpleInspectionTool {
|
||||
processTextUsages(processedKeyToFiles, property.getUnescapedKey(), processedValueToFiles, searchHelper, scope);
|
||||
return true;
|
||||
}
|
||||
}, false, progress)) throw new ProcessCanceledException();
|
||||
})) throw new ProcessCanceledException();
|
||||
|
||||
List<ProblemDescriptor> problemDescriptors = new ArrayList<ProblemDescriptor>();
|
||||
Map<String, Set<String>> keyToDifferentValues = new HashMap<String, Set<String>>();
|
||||
|
||||
Reference in New Issue
Block a user