From 5c7a1a647e2d89b152f5d9416eecac44fb266ef0 Mon Sep 17 00:00:00 2001 From: Dmitry Batkovich Date: Fri, 28 Oct 2016 15:39:20 +0300 Subject: [PATCH] javac ast indices: return vfs listener + process uncommitted changes --- .../CompilerReferenceServiceImpl.java | 6 +- .../backwardRefs/DirtyModulesHolder.java | 127 ++++++++++-------- .../psi/impl/PsiDocumentManagerBase.java | 2 +- 3 files changed, 79 insertions(+), 56 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerReferenceServiceImpl.java b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerReferenceServiceImpl.java index 013add71a911..a092eabb4f4b 100644 --- a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerReferenceServiceImpl.java +++ b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/CompilerReferenceServiceImpl.java @@ -23,6 +23,7 @@ import com.intellij.lang.injection.InjectedLanguageManager; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ReadAction; import com.intellij.openapi.compiler.*; +import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; @@ -33,6 +34,7 @@ import com.intellij.openapi.util.Couple; import com.intellij.openapi.util.ModificationTracker; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileWithId; +import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiNamedElement; @@ -71,12 +73,12 @@ public class CompilerReferenceServiceImpl extends CompilerReferenceService imple private volatile CompilerReferenceReader myReader; - public CompilerReferenceServiceImpl(Project project) { + public CompilerReferenceServiceImpl(Project project, FileDocumentManager fileDocumentManager, PsiDocumentManager psiDocumentManager) { super(project); myProjectFileIndex = ProjectRootManager.getInstance(project).getFileIndex(); myFileTypes = Stream.of(LanguageLightRefAdapter.INSTANCES).flatMap(a -> a.getFileTypes().stream()).collect(Collectors.toSet()); - myDirtyModulesHolder = new DirtyModulesHolder(this); + myDirtyModulesHolder = new DirtyModulesHolder(this, fileDocumentManager, psiDocumentManager); } @Override diff --git a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/DirtyModulesHolder.java b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/DirtyModulesHolder.java index 82a2dbbf051e..ed06b747dd04 100644 --- a/java/compiler/impl/src/com/intellij/compiler/backwardRefs/DirtyModulesHolder.java +++ b/java/compiler/impl/src/com/intellij/compiler/backwardRefs/DirtyModulesHolder.java @@ -15,18 +15,23 @@ */ package com.intellij.compiler.backwardRefs; +import com.intellij.openapi.application.ReadAction; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.util.UserDataHolderBase; -import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; +import com.intellij.openapi.vfs.*; +import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.search.GlobalSearchScope; import com.intellij.psi.util.CachedValueProvider; import com.intellij.psi.util.CachedValuesManager; import com.intellij.psi.util.PsiModificationTracker; +import com.intellij.util.ObjectUtils; import com.intellij.util.containers.ContainerUtil; +import com.intellij.util.containers.SmartHashSet; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import java.util.Collection; import java.util.Collections; import java.util.Set; @@ -34,14 +39,20 @@ import static com.intellij.psi.search.GlobalSearchScope.EMPTY_SCOPE; class DirtyModulesHolder extends UserDataHolderBase { private final CompilerReferenceServiceImpl myService; + private final FileDocumentManager myFileDocManager; + private final PsiDocumentManager myPsiDocManager; private final Set myChangedModules = ContainerUtil.newHashSet(); private final Set myChangedModulesDuringCompilation = ContainerUtil.newHashSet(); private final Object myLock = new Object(); private boolean myCompilationPhase; - public DirtyModulesHolder(@NotNull CompilerReferenceServiceImpl service){ + public DirtyModulesHolder(@NotNull CompilerReferenceServiceImpl service, + FileDocumentManager fileDocumentManager, + PsiDocumentManager psiDocumentManager){ myService = service; + myFileDocManager = fileDocumentManager; + myPsiDocManager = psiDocumentManager; } void compilerActivityStarted() { @@ -62,13 +73,23 @@ class DirtyModulesHolder extends UserDataHolderBase { } GlobalSearchScope getDirtyScope() { - return CachedValuesManager.getManager(myService.getProject()).getCachedValue(this, () -> { - synchronized (myLock) { - final GlobalSearchScope dirtyScope = - myChangedModules.stream().map(Module::getModuleWithDependentsScope).reduce(EMPTY_SCOPE, (s1, s2) -> s1.union(s2)); - return CachedValueProvider.Result.create(dirtyScope, PsiModificationTracker.MODIFICATION_COUNT, myService); + synchronized (myLock) { + final Set unCommittedModules = new SmartHashSet<>(0); + for (Document document : myFileDocManager.getUnsavedDocuments()) { + final Module m = getModuleForSourceContentFile(myFileDocManager.getFile(document)); + if (m != null && !myChangedModules.contains(m)) unCommittedModules.add(m); } - }); + for (Document document : ReadAction.compute(() -> myPsiDocManager.getUncommittedDocuments())) { + final Module m = getModuleForSourceContentFile(ObjectUtils.notNull(myPsiDocManager.getPsiFile(document)).getVirtualFile()); + if (m != null && !myChangedModules.contains(m)) unCommittedModules.add(m); + } + GlobalSearchScope dirtyCommittedScope = CachedValuesManager.getManager(myService.getProject()).getCachedValue(this, () -> + CachedValueProvider.Result.create(addModulesWithDependentToScope(myChangedModules, EMPTY_SCOPE), PsiModificationTracker.MODIFICATION_COUNT, myService)); + if (unCommittedModules.isEmpty()) { + return dirtyCommittedScope; + } + return addModulesWithDependentToScope(unCommittedModules, dirtyCommittedScope); + } } boolean contains(VirtualFile file) { @@ -76,71 +97,71 @@ class DirtyModulesHolder extends UserDataHolderBase { } void installVFSListener() { - PsiManager.getInstance(myService.getProject()).addPsiTreeChangeListener(new PsiTreeChangeAdapter() { + VirtualFileManager.getInstance().addVirtualFileListener(new VirtualFileAdapter() { @Override - public void beforeChildAddition(@NotNull PsiTreeChangeEvent event) { - psiChanged(event.getFile(), event.getParent()); + public void fileCreated(@NotNull VirtualFileEvent event) { + processChange(event.getFile()); } @Override - public void beforeChildRemoval(@NotNull PsiTreeChangeEvent event) { - psiChanged(event.getFile(), event.getParent()); + public void fileCopied(@NotNull VirtualFileCopyEvent event) { + processChange(event.getFile()); } @Override - public void beforeChildReplacement(@NotNull PsiTreeChangeEvent event) { - psiChanged(event.getFile(), event.getParent()); + public void fileMoved(@NotNull VirtualFileMoveEvent event) { + processChange(event.getFile()); } @Override - public void beforeChildMovement(@NotNull PsiTreeChangeEvent event) { - final PsiFile file = event.getFile(); - if (file != null) { - psiChanged(file, null); - } - else { - psiChanged(null, event.getOldParent()); - psiChanged(null, event.getNewParent()); + public void beforePropertyChange(@NotNull VirtualFilePropertyEvent event) { + if (VirtualFile.PROP_NAME.equals(event.getPropertyName()) || VirtualFile.PROP_SYMLINK_TARGET.equals(event.getPropertyName())) { + processChange(event.getFile()); } } @Override - public void beforeChildrenChange(@NotNull PsiTreeChangeEvent event) { - psiChanged(event.getFile(), event.getParent()); + public void beforeContentsChange(@NotNull VirtualFileEvent event) { + processChange(event.getFile()); } @Override - public void beforePropertyChange(@NotNull PsiTreeChangeEvent event) { - if (PsiTreeChangeEvent.PROP_UNLOADED_PSI.equals(event.getPropertyName()) || - PsiTreeChangeEvent.PROP_WRITABLE.equals(event.getPropertyName())) return; - psiChanged(event.getFile(), event.getParent()); + public void beforeFileDeletion(@NotNull VirtualFileEvent event) { + processChange(event.getFile()); } - private void psiChanged(@Nullable PsiFile psiFile, @Nullable PsiElement parent) { - final VirtualFile file; - if (psiFile != null) { - file = psiFile.getVirtualFile(); - } - else if (parent instanceof PsiFileSystemItem) { - file = ((PsiFileSystemItem)parent).getVirtualFile(); - } - else { - return; - } - if (myService.getFileIndex().isInSourceContent(file) && myService.getFileTypes().contains(file.getFileType())) { - final Module module = myService.getFileIndex().getModuleForFile(file); - if (module != null) { - synchronized (myLock) { - if (myCompilationPhase) { - myChangedModulesDuringCompilation.add(module); - } - else { - myChangedModules.add(module); - } + @Override + public void beforeFileMovement(@NotNull VirtualFileMoveEvent event) { + processChange(event.getFile()); + } + + private void processChange(VirtualFile file) { + fileChanged(file); + } + + void fileChanged(VirtualFile file) { + final Module module = getModuleForSourceContentFile(file); + if (module != null) { + synchronized (myLock) { + if (myCompilationPhase) { + myChangedModulesDuringCompilation.add(module); + } else { + myChangedModules.add(module); } } } } - }); + }, myService.getProject()); + } + + private Module getModuleForSourceContentFile(VirtualFile file) { + if (myService.getFileIndex().isInSourceContent(file) && myService.getFileTypes().contains(file.getFileType())) { + return myService.getFileIndex().getModuleForFile(file); + } + return null; + } + + private static GlobalSearchScope addModulesWithDependentToScope(Collection modules, GlobalSearchScope baseScope) { + return modules.stream().map(Module::getModuleWithDependentsScope).reduce(baseScope, (s1, s2) -> s1.union(s2)); } } diff --git a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java index 1189fe00d901..2ac0a6c9194c 100644 --- a/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java +++ b/platform/core-impl/src/com/intellij/psi/impl/PsiDocumentManagerBase.java @@ -756,7 +756,7 @@ public abstract class PsiDocumentManagerBase extends PsiDocumentManager implemen @Override @NotNull public Document[] getUncommittedDocuments() { - ApplicationManager.getApplication().assertIsDispatchThread(); + ApplicationManager.getApplication().assertReadAccessAllowed(); Document[] documents = myUncommittedDocuments.toArray(new Document[myUncommittedDocuments.size()]); return ArrayUtil.stripTrailingNulls(documents); }