void (@NotNull Project project) { if (ApplicationManager.getApplication().isHeadlessEnvironment()) { return; } MessageBusConnection connection = project.getMessageBus().connect(); connection.subscribe(WorkspaceModelTopics.CHANGED, new WSModelChangeListener(project)); connection.subscribe(ModuleRootListener.TOPIC, new ModuleRootListener() { @Override public void rootsChanged(@NotNull ModuleRootEvent event) { if (!event.isCausedByWorkspaceModelChangesOnly()) { // only process events that are not covered by events from the workspace model final Object source = event.getSource(); if (source instanceof Project) { getInstance().clearState((Project)source); } } } }); connection.subscribe(ExecutionManager.EXECUTION_TOPIC, new ExecutionListener() { @Override public void processStarting(@NotNull String executorId, @NotNull ExecutionEnvironment env) { getInstance().cancelAutoMakeTasks(env.getProject()); // make sure to cancel all automake requests waiting in the build queue } @Override public void processStarted(@NotNull String executorId, @NotNull ExecutionEnvironment env, @NotNull ProcessHandler handler) { // make sure to cancel all automake requests added to the build queue after processStaring and before this event getInstance().cancelAutoMakeTasks(env.getProject()); } @Override public void processNotStarted(@NotNull String executorId, @NotNull ExecutionEnvironment env) { // augmenting reaction to `processTerminated()`: in case any automake requests were canceled before the process start getInstance().scheduleAutoMake(); } @Override public void processTerminated(@NotNull String executorId, @NotNull ExecutionEnvironment env, @NotNull ProcessHandler handler, int exitCode) { getInstance().scheduleAutoMake(); } }); connection.subscribe(CompilerTopics.COMPILATION_STATUS, new CompilationStatusListener() { private final Set<String> myRootsToRefresh = CollectionFactory.createFilePathSet(); @Override public void automakeCompilationFinished(int errors, int warnings, @NotNull CompileContext compileContext) { if (!compileContext.getProgressIndicator().isCanceled()) { refreshSources(compileContext); } } @Override public void compilationFinished(boolean aborted, int errors, int warnings, @NotNull CompileContext compileContext) { refreshSources(compileContext); } private void refreshSources(CompileContext compileContext) { if (project.isDisposed()) { return; } final Set<String> candidates = CollectionFactory.createFilePathSet(); synchronized (myRootsToRefresh) { candidates.addAll(myRootsToRefresh); myRootsToRefresh.clear(); } if (candidates.isEmpty() && !compileContext.isAnnotationProcessorsEnabled()) { return; } ApplicationManager.getApplication().executeOnPooledThread(() -> { if (project.isDisposed()) { return; } if (compileContext.isAnnotationProcessorsEnabled()) { // annotation processors may have re-generated code final CompilerConfiguration config = CompilerConfiguration.getInstance(project); try { for (Module module : ReadAction.nonBlocking(() -> compileContext.getCompileScope().getAffectedModules()).executeSynchronously()) { if (project.isDisposed()) { return; } if (module.isDisposed()) { continue; } if (config.getAnnotationProcessingConfiguration(module).isEnabled()) { final String productionPath = CompilerPaths.getAnnotationProcessorsGenerationPath(module, false); if (productionPath != null) { candidates.add(productionPath); } final String testsPath = CompilerPaths.getAnnotationProcessorsGenerationPath(module, true); if (testsPath != null) { candidates.add(testsPath); } } } } catch (ProcessCanceledException ignored) { } catch (Throwable e) { LOG.info(e); } } if (candidates.isEmpty()) { return; } CompilerUtil.refreshOutputRoots(candidates); LocalFileSystem lfs = LocalFileSystem.getInstance(); try { Collection<VirtualFile> toRefresh = ReadAction.nonBlocking(() -> { if (project.isDisposed()) { return Collections.<VirtualFile>emptySet(); } ProjectFileIndex fileIndex = ProjectRootManager.getInstance(project).getFileIndex(); return candidates.stream().map(lfs::findFileByPath).filter(root -> root != null && fileIndex.isInSourceContent(root)).collect(Collectors.toSet()); }).executeSynchronously(); if (!toRefresh.isEmpty()) { lfs.refreshFiles(toRefresh, true, true, null); } } catch (ProcessCanceledException ignored) { } catch (Throwable e) { LOG.info(e); } }); } @Override public void fileGenerated(@NotNull String outputRoot, @NotNull String relativePath) { synchronized (myRootsToRefresh) { myRootsToRefresh.add(outputRoot); } } }); String projectPath = getProjectPath(project); Disposer.register(project, () -> { BuildManager buildManager = getInstance(); buildManager.cancelPreloadedBuilds(projectPath); buildManager.myProjectDataMap.remove(projectPath); }); BuildProcessParametersProvider.EP_NAME.addChangeListener(project, () -> getInstance().cancelAllPreloadedBuilds(), null); getInstance().runCommand(() -> { updateUsageFile(project, getInstance().getProjectSystemDirectory(project)); }); // run automake after a project opened getInstance().scheduleAutoMake(); }