From d2622e1a6269d4062b96078e73aa28d490d39423 Mon Sep 17 00:00:00 2001 From: Ivan Bessonov Date: Thu, 27 Oct 2016 14:42:38 +0300 Subject: [PATCH 1/2] Ability to store LANGUAGE_LEVEL in file user data, required for correct work of GWT client inclusion/exclusion patterns --- .../com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java b/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java index 2d1eb3c1bfcc..636e6f536b2c 100644 --- a/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java +++ b/java/java-impl/src/com/intellij/psi/impl/JavaPsiImplementationHelperImpl.java @@ -131,6 +131,9 @@ public class JavaPsiImplementationHelperImpl extends JavaPsiImplementationHelper public LanguageLevel getEffectiveLanguageLevel(@Nullable VirtualFile virtualFile) { if (virtualFile == null) return PsiUtil.getLanguageLevel(myProject); + final LanguageLevel fileLevel = virtualFile.getUserData(LanguageLevel.KEY); + if (fileLevel != null) return fileLevel; + final VirtualFile folder = virtualFile.getParent(); if (folder != null) { final LanguageLevel level = folder.getUserData(LanguageLevel.KEY); From 4e48ad69c832a7c68df8d643149201e7992f07f3 Mon Sep 17 00:00:00 2001 From: Eugene Zhuravlev Date: Thu, 27 Oct 2016 13:45:24 +0200 Subject: [PATCH 2/2] experimental asynchronous event processing --- .../impl/TranslatingCompilerFilesMonitor.java | 112 +++++++++++------- .../compiler/server/BuildManager.java | 17 ++- .../util/resources/misc/registry.properties | 2 + 3 files changed, 85 insertions(+), 46 deletions(-) diff --git a/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java b/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java index 923e6688ba27..1a89f0843d66 100644 --- a/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java +++ b/java/compiler/impl/src/com/intellij/compiler/impl/TranslatingCompilerFilesMonitor.java @@ -27,12 +27,16 @@ import com.intellij.openapi.project.ProjectUtil; import com.intellij.openapi.roots.ProjectRootManager; import com.intellij.openapi.util.Comparing; import com.intellij.openapi.util.io.FileUtil; +import com.intellij.openapi.util.registry.Registry; import com.intellij.openapi.vfs.*; import com.intellij.openapi.vfs.newvfs.NewVirtualFile; +import com.intellij.util.Consumer; import com.intellij.util.Function; +import com.intellij.util.concurrency.SequentialTaskExecutor; import gnu.trove.THashSet; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.ide.PooledThreadExecutor; import java.io.File; import java.util.Collection; @@ -53,6 +57,7 @@ import java.util.Set; */ public class TranslatingCompilerFilesMonitor implements ApplicationComponent { public static boolean ourDebugMode = false; + private static final SequentialTaskExecutor ourFSEventQueue = new SequentialTaskExecutor("_build_notify_queue_", PooledThreadExecutor.INSTANCE); public TranslatingCompilerFilesMonitor(VirtualFileManager vfsManager, Application application) { vfsManager.addVirtualFileListener(new MyVfsListener(), application); @@ -127,74 +132,75 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent { private static class MyVfsListener extends VirtualFileAdapter { public void propertyChanged(@NotNull final VirtualFilePropertyEvent event) { if (VirtualFile.PROP_NAME.equals(event.getPropertyName())) { - final VirtualFile eventFile = event.getFile(); - if (isInContentOfOpenedProject(eventFile)) { - final VirtualFile parent = event.getParent(); - if (parent != null) { - final String oldName = (String)event.getOldValue(); - final String root = parent.getPath() + "/" + oldName; - final Set toMark = new THashSet<>(FileUtil.FILE_HASHING_STRATEGY); - if (eventFile.isDirectory()) { - VfsUtilCore.visitChildrenRecursively(eventFile, new VirtualFileVisitor() { - private StringBuilder filePath = new StringBuilder(root); - - @Override - public boolean visitFile(@NotNull VirtualFile child) { - if (child.isDirectory()) { - if (!Comparing.equal(child, eventFile)) { - filePath.append("/").append(child.getName()); + processEventFile(event.getFile(), (eventFile)->{ + if (isInContentOfOpenedProject(eventFile)) { + final VirtualFile parent = event.getParent(); + if (parent != null) { + final String oldName = (String)event.getOldValue(); + final String root = parent.getPath() + "/" + oldName; + final Set toMark = new THashSet<>(FileUtil.FILE_HASHING_STRATEGY); + if (eventFile.isDirectory()) { + VfsUtilCore.visitChildrenRecursively(eventFile, new VirtualFileVisitor() { + private StringBuilder filePath = new StringBuilder(root); + + @Override + public boolean visitFile(@NotNull VirtualFile child) { + if (child.isDirectory()) { + if (!Comparing.equal(child, eventFile)) { + filePath.append("/").append(child.getName()); + } + } + else { + String childPath = filePath.toString(); + if (!Comparing.equal(child, eventFile)) { + childPath += "/" + child.getName(); + } + toMark.add(new File(childPath)); + } + return true; + } + + @Override + public void afterChildrenVisited(@NotNull VirtualFile file) { + if (file.isDirectory() && !Comparing.equal(file, eventFile)) { + filePath.delete(filePath.length() - file.getName().length() - 1, filePath.length()); } } - else { - String childPath = filePath.toString(); - if (!Comparing.equal(child, eventFile)) { - childPath += "/" + child.getName(); - } - toMark.add(new File(childPath)); - } - return true; - } - - @Override - public void afterChildrenVisited(@NotNull VirtualFile file) { - if (file.isDirectory() && !Comparing.equal(file, eventFile)) { - filePath.delete(filePath.length() - file.getName().length() - 1, filePath.length()); - } - } - }); + }); + } + else { + toMark.add(new File(root)); + } + notifyFilesDeleted(toMark); } - else { - toMark.add(new File(root)); - } - notifyFilesDeleted(toMark); + collectPathsAndNotify(eventFile, NOTIFY_CHANGED); } - collectPathsAndNotify(eventFile, NOTIFY_CHANGED); - } + }); } } public void contentsChanged(@NotNull final VirtualFileEvent event) { - collectPathsAndNotify(event.getFile(), NOTIFY_CHANGED); + processEventFile(event.getFile(), (eventFile)-> collectPathsAndNotify(eventFile, NOTIFY_CHANGED)); } public void fileCreated(@NotNull final VirtualFileEvent event) { - collectPathsAndNotify(event.getFile(), NOTIFY_CHANGED); + processEventFile(event.getFile(), (eventFile)-> collectPathsAndNotify(eventFile, NOTIFY_CHANGED)); } public void fileCopied(@NotNull final VirtualFileCopyEvent event) { - collectPathsAndNotify(event.getFile(), NOTIFY_CHANGED); + processEventFile(event.getFile(), (eventFile)-> collectPathsAndNotify(eventFile, NOTIFY_CHANGED)); } public void fileMoved(@NotNull VirtualFileMoveEvent event) { - collectPathsAndNotify(event.getFile(), NOTIFY_CHANGED); + processEventFile(event.getFile(), (eventFile)-> collectPathsAndNotify(eventFile, NOTIFY_CHANGED)); } public void beforeFileDeletion(@NotNull final VirtualFileEvent event) { - collectPathsAndNotify(event.getFile(), NOTIFY_DELETED); + processEventFile(event.getFile(), (eventFile)-> collectPathsAndNotify(eventFile, NOTIFY_DELETED)); } public void beforeFileMovement(@NotNull final VirtualFileMoveEvent event) { - collectPathsAndNotify(event.getFile(), NOTIFY_DELETED); + processEventFile(event.getFile(), (eventFile)-> collectPathsAndNotify(eventFile, NOTIFY_DELETED)); } } @@ -258,4 +264,20 @@ public class TranslatingCompilerFilesMonitor implements ApplicationComponent { } } + private static void processEventFile(final VirtualFile file, final Consumer consumer) { + if (Registry.is("build.manager.async.fs.events", false)) { + ourFSEventQueue.execute(()-> ApplicationManager.getApplication().runReadAction(()->{ + if (file.isValid()) { + consumer.consume(file); + } + else { + BuildManager.getInstance().clearState(); + } + })); + } + else { + consumer.consume(file); + } + } + } diff --git a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java index 7b2acf0ae6be..728a0a2b642a 100644 --- a/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java +++ b/java/compiler/impl/src/com/intellij/compiler/server/BuildManager.java @@ -106,7 +106,8 @@ import org.jetbrains.jps.incremental.Utils; import org.jetbrains.jps.model.java.JpsJavaSdkType; import org.jetbrains.jps.model.serialization.JpsGlobalLoader; -import javax.tools.*; +import javax.tools.JavaCompiler; +import javax.tools.ToolProvider; import java.awt.*; import java.io.File; import java.io.IOException; @@ -417,6 +418,20 @@ public class BuildManager implements Disposable { scheduleAutoMake(); } + public void clearState() { + final boolean cleared; + synchronized (myProjectDataMap) { + cleared = !myProjectDataMap.isEmpty(); + for (Map.Entry entry : myProjectDataMap.entrySet()) { + cancelPreloadedBuilds(entry.getKey()); + entry.getValue().dropChanges(); + } + } + if (cleared) { + scheduleAutoMake(); + } + } + public boolean isProjectWatched(Project project) { return myProjectDataMap.containsKey(getProjectPath(project)); } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index 4dda4ac17e20..f614cbebd47d 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -888,3 +888,5 @@ ide.projectView.globalOptions.description=Make Project View options such as auto compiler.ref.index=false compiler.ref.index.description=Enables find usages using references from compiler indices compiler.ref.index.restartRequired=true +build.manager.async.fs.events=false +build.manager.async.fs.events.description=Experimental: TranslatingCompilerFilesMonitor will process events from VFS asynchronously to minimize write-action duration