use of com.intellij.util.containers.ConcurrentList in project intellij-community by JetBrains.
the class InjectedLanguageManagerImpl method startRunInjectors.
@Override
public void startRunInjectors(@NotNull final Document hostDocument, final boolean synchronously) {
if (myProject.isDisposed())
return;
if (!synchronously && ApplicationManager.getApplication().isWriteAccessAllowed())
return;
// use cached to avoid recreate PSI in alien project
final PsiDocumentManager documentManager = PsiDocumentManager.getInstance(myProject);
final PsiFile hostPsiFile = documentManager.getCachedPsiFile(hostDocument);
if (hostPsiFile == null)
return;
final ConcurrentList<DocumentWindow> injected = InjectedLanguageUtil.getCachedInjectedDocuments(hostPsiFile);
if (injected.isEmpty())
return;
if (myProgress.isCanceled()) {
myProgress = new DaemonProgressIndicator();
}
final Set<DocumentWindow> newDocuments = Collections.synchronizedSet(new THashSet<>());
final Processor<DocumentWindow> commitProcessor = documentWindow -> {
if (myProject.isDisposed())
return false;
ProgressIndicator indicator = ProgressManager.getInstance().getProgressIndicator();
if (indicator != null && indicator.isCanceled())
return false;
if (documentManager.isUncommited(hostDocument) || !hostPsiFile.isValid())
return false;
InjectedLanguageUtil.enumerate(documentWindow, hostPsiFile, (injectedPsi, places) -> {
DocumentWindow newDocument = (DocumentWindow) injectedPsi.getViewProvider().getDocument();
if (newDocument != null) {
PsiDocumentManagerBase.checkConsistency(injectedPsi, newDocument);
newDocuments.add(newDocument);
}
});
return true;
};
final Runnable commitInjectionsRunnable = () -> {
if (myProgress.isCanceled())
return;
JobLauncher.getInstance().invokeConcurrentlyUnderProgress(new ArrayList<>(injected), myProgress, true, commitProcessor);
synchronized (ourInjectionPsiLock) {
injected.clear();
injected.addAll(newDocuments);
}
};
if (synchronously) {
if (Thread.holdsLock(PsiLock.LOCK)) {
// hack for the case when docCommit was called from within PSI modification, e.g. in formatter.
// we can't spawn threads to do injections there, otherwise a deadlock is imminent
ContainerUtil.process(new ArrayList<>(injected), commitProcessor);
} else {
commitInjectionsRunnable.run();
}
} else {
JobLauncher.getInstance().submitToJobThread(() -> ApplicationManagerEx.getApplicationEx().tryRunReadAction(commitInjectionsRunnable), null);
}
}
Aggregations