From e6bbfa9db1e3f419384f8fd3ba3187beab912b98 Mon Sep 17 00:00:00 2001 From: Vladimir Krivosheev Date: Sat, 5 Sep 2015 13:24:11 +0200 Subject: [PATCH] =?UTF-8?q?don't=20schedule=20"checkUnknownMacros"=20for?= =?UTF-8?q?=20each=20module=20using=20project=20post=20start=20up=20activi?= =?UTF-8?q?ty=20=E2=80=94=20=20in=20any=20case=20we=20check=20it=20for=20p?= =?UTF-8?q?roject=20post=20start=20up?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/ProjectStoreImpl.kt | 2 - .../src/ProjectWithModulesStoreImpl.kt | 19 +-- .../module/impl/ModuleManagerComponent.java | 8 +- .../pathMacros/PathMacroConfigurable.java | 3 +- .../components/impl/stores/IProjectStore.java | 6 - .../components/impl/stores/StorageUtil.java | 155 ++++++++++-------- .../project/impl/ProjectManagerImpl.java | 8 +- .../TrackingPathMacroSubstitutor.java | 7 +- .../components/impl/BasePathMacroManager.java | 9 +- 9 files changed, 106 insertions(+), 111 deletions(-) diff --git a/platform/configuration-store-impl/src/ProjectStoreImpl.kt b/platform/configuration-store-impl/src/ProjectStoreImpl.kt index 0ec530a25f79..92d7d2b22143 100644 --- a/platform/configuration-store-impl/src/ProjectStoreImpl.kt +++ b/platform/configuration-store-impl/src/ProjectStoreImpl.kt @@ -54,8 +54,6 @@ open class ProjectStoreImpl(override val project: ProjectImpl, private val pathM assert(!project.isDefault()) } - override fun getSubstitutors() = listOf(storageManager.getMacroSubstitutor()) - override fun optimizeTestLoading() = project.isOptimiseTestLoadSpeed() override final fun getPathMacroManagerForDefaults() = pathMacroManager diff --git a/platform/configuration-store-impl/src/ProjectWithModulesStoreImpl.kt b/platform/configuration-store-impl/src/ProjectWithModulesStoreImpl.kt index de47c5a3fb3d..ee88d24f9a4a 100644 --- a/platform/configuration-store-impl/src/ProjectWithModulesStoreImpl.kt +++ b/platform/configuration-store-impl/src/ProjectWithModulesStoreImpl.kt @@ -17,7 +17,6 @@ package com.intellij.configurationStore import com.intellij.openapi.components.PathMacroManager import com.intellij.openapi.components.StateStorage.SaveSession -import com.intellij.openapi.components.TrackingPathMacroSubstitutor import com.intellij.openapi.components.impl.stores.IComponentStore import com.intellij.openapi.components.stateStore import com.intellij.openapi.module.Module @@ -26,8 +25,6 @@ import com.intellij.openapi.project.impl.ProjectImpl import com.intellij.openapi.project.impl.ProjectStoreClassProvider import com.intellij.openapi.util.Pair import com.intellij.openapi.vfs.VirtualFile -import com.intellij.util.SmartList -import com.intellij.util.containers.ContainerUtil class PlatformLangProjectStoreClassProvider : ProjectStoreClassProvider { override fun getProjectStoreClass(isDefaultProject: Boolean): Class { @@ -36,22 +33,10 @@ class PlatformLangProjectStoreClassProvider : ProjectStoreClassProvider { } class ProjectWithModulesStoreImpl(project: ProjectImpl, pathMacroManager: PathMacroManager) : ProjectStoreImpl(project, pathMacroManager) { - override fun getSubstitutors(): List { - val result = SmartList() - ContainerUtil.addIfNotNull(result, storageManager.getMacroSubstitutor()) - - for (module in getPersistentModules()) { - ContainerUtil.addIfNotNull(result, module.stateStore.getStateStorageManager().getMacroSubstitutor()) - } - return result - } - - private fun getPersistentModules() = ModuleManager.getInstance(project)?.getModules() ?: Module.EMPTY_ARRAY - - override protected fun beforeSave(readonlyFiles: List>) { + override fun beforeSave(readonlyFiles: List>) { super.beforeSave(readonlyFiles) - for (module in getPersistentModules()) { + for (module in (ModuleManager.getInstance(project)?.getModules() ?: Module.EMPTY_ARRAY)) { module.stateStore.save(readonlyFiles) } } diff --git a/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleManagerComponent.java b/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleManagerComponent.java index 3cc712c996c3..9ff1dbe3f797 100644 --- a/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleManagerComponent.java +++ b/platform/lang-impl/src/com/intellij/openapi/module/impl/ModuleManagerComponent.java @@ -25,7 +25,6 @@ import com.intellij.openapi.components.State; import com.intellij.openapi.components.Storage; import com.intellij.openapi.components.StoragePathMacros; import com.intellij.openapi.components.StorageScheme; -import com.intellij.openapi.components.impl.stores.StorageUtil; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.module.Module; import com.intellij.openapi.module.ModuleType; @@ -40,7 +39,6 @@ import com.intellij.util.messages.MessageBusConnection; import com.intellij.util.messages.MessageHandler; import org.jetbrains.annotations.NotNull; -import java.io.IOException; import java.lang.reflect.Method; import java.util.List; @@ -119,10 +117,8 @@ public class ModuleManagerComponent extends ModuleManagerImpl { @NotNull @Override - protected ModuleEx createAndLoadModule(@NotNull String filePath) throws IOException { - ModuleImpl module = new ModuleImpl(filePath, myProject); - StorageUtil.checkUnknownMacros(module, myProject); - return module; + protected ModuleEx createAndLoadModule(@NotNull String filePath) { + return new ModuleImpl(filePath, myProject); } @Override diff --git a/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroConfigurable.java b/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroConfigurable.java index 063ec0908ada..9b63f3d11910 100644 --- a/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroConfigurable.java +++ b/platform/platform-impl/src/com/intellij/application/options/pathMacros/PathMacroConfigurable.java @@ -16,7 +16,6 @@ package com.intellij.application.options.pathMacros; import com.intellij.openapi.application.ApplicationBundle; -import com.intellij.openapi.components.ComponentsPackage; import com.intellij.openapi.components.impl.stores.StorageUtil; import com.intellij.openapi.options.Configurable; import com.intellij.openapi.options.ConfigurationException; @@ -48,7 +47,7 @@ public class PathMacroConfigurable implements SearchableConfigurable, Configurab myEditor.commit(); for (Project project : ProjectManager.getInstance().getOpenProjects()) { - StorageUtil.checkUnknownMacros(ComponentsPackage.getStateStore(project), project, false); + StorageUtil.checkUnknownMacros(project, false); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IProjectStore.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IProjectStore.java index 66c346e7d103..c711e37c40a2 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IProjectStore.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/IProjectStore.java @@ -16,14 +16,11 @@ package com.intellij.openapi.components.impl.stores; import com.intellij.openapi.components.StorageScheme; -import com.intellij.openapi.components.TrackingPathMacroSubstitutor; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; - public interface IProjectStore extends IComponentStore { @Nullable VirtualFile getProjectBaseDir(); @@ -37,9 +34,6 @@ public interface IProjectStore extends IComponentStore { @NotNull String getProjectName(); - @NotNull - List getSubstitutors(); - @NotNull StorageScheme getStorageScheme(); diff --git a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java index 81ee31baf8fa..f8618a452d0f 100644 --- a/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java +++ b/platform/platform-impl/src/com/intellij/openapi/components/impl/stores/StorageUtil.java @@ -24,11 +24,12 @@ import com.intellij.openapi.components.ComponentManager; import com.intellij.openapi.components.ComponentsPackage; import com.intellij.openapi.components.TrackingPathMacroSubstitutor; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectBundle; import com.intellij.openapi.project.ex.ProjectManagerEx; import com.intellij.openapi.project.impl.ProjectMacrosUtil; -import com.intellij.openapi.startup.StartupManager; import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.util.text.StringUtil; @@ -55,32 +56,18 @@ public class StorageUtil { private StorageUtil() { } - public static void checkUnknownMacros(@NotNull final ComponentManager componentManager, @NotNull final Project project) { - Application application = ApplicationManager.getApplication(); - if (application.isHeadlessEnvironment() || application.isUnitTestMode()) { - return; - } - - // should be invoked last - StartupManager.getInstance(project).runWhenProjectIsInitialized(new Runnable() { - @Override - public void run() { - notifyUnknownMacros(ComponentsPackage.getStateStore(componentManager), project, null); - } - }); - } - - public static void notifyUnknownMacros(@NotNull final IComponentStore store, @NotNull final Project project, @Nullable final String componentName) { - TrackingPathMacroSubstitutor substitutor = store.getStateStorageManager().getMacroSubstitutor(); + public static void notifyUnknownMacros(@NotNull final IComponentStore store, @NotNull final Project project, @NotNull final String componentName) { + final TrackingPathMacroSubstitutor substitutor = store.getStateStorageManager().getMacroSubstitutor(); if (substitutor == null) { return; } - final LinkedHashSet macros = new LinkedHashSet(substitutor.getUnknownMacros(componentName)); - if (macros.isEmpty()) { + Set immutableMacros = substitutor.getUnknownMacros(componentName); + if (immutableMacros.isEmpty()) { return; } + final Set macros = new LinkedHashSet(immutableMacros); AppUIUtil.invokeOnEdt(new Runnable() { @Override public void run() { @@ -101,77 +88,109 @@ public class StorageUtil { } LOG.debug("Reporting unknown path macros " + macros + " in component " + componentName); - String format = "

%s %s undefined. Fix it

"; - String productName = ApplicationNamesInfo.getInstance().getProductName(); - String content = String.format(format, StringUtil.join(macros, ", "), macros.size() == 1 ? "is" : "are") + - "
Path variables are used to substitute absolute paths " + - "in " + productName + " project files " + - "and allow project file sharing in version control systems.
" + - "Some of the files describing the current project settings contain unknown path variables " + - "and " + productName + " cannot restore those paths."; - new UnknownMacroNotification("Load Error", "Load error: undefined path variables", content, NotificationType.ERROR, - new NotificationListener() { - @Override - public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { - checkUnknownMacros(store, project, true); - } - }, macros).notify(project); + doNotify(macros, project, Collections.singletonMap(substitutor, store)); } }, project.getDisposed()); } - public static void checkUnknownMacros(@NotNull IComponentStore store, @NotNull Project project, boolean showDialog) { - // default project doesn't have it - List substitutors; - if (store instanceof IProjectStore) { - substitutors = ((IProjectStore)store).getSubstitutors(); - } - else { - substitutors = Collections.emptyList(); - } - Set unknownMacros = new THashSet(); - for (TrackingPathMacroSubstitutor substitutor : substitutors) { - unknownMacros.addAll(substitutor.getUnknownMacros(null)); + private static void doNotify(@NotNull final Set macros, @NotNull final Project project, + @NotNull final Map substitutorToStore) { + String format = "

%s %s undefined. Fix it

"; + String productName = ApplicationNamesInfo.getInstance().getProductName(); + String content = String.format(format, StringUtil.join(macros, ", "), macros.size() == 1 ? "is" : "are") + + "
Path variables are used to substitute absolute paths " + + "in " + productName + " project files " + + "and allow project file sharing in version control systems.
" + + "Some of the files describing the current project settings contain unknown path variables " + + "and " + productName + " cannot restore those paths."; + new UnknownMacroNotification("Load Error", "Load error: undefined path variables", content, NotificationType.ERROR, + new NotificationListener() { + @Override + public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { + checkUnknownMacros(project, true, macros, substitutorToStore); + } + }, macros).notify(project); + } + + public static void checkUnknownMacros(@NotNull Project project, boolean notify) { + // use linked set/map to get stable results + Set unknownMacros = new LinkedHashSet(); + Map substitutorToStore = ContainerUtil.newLinkedHashMap(); + collect(project, unknownMacros, substitutorToStore); + for (Module module : ModuleManager.getInstance(project).getModules()) { + collect(module, unknownMacros, substitutorToStore); } - if (unknownMacros.isEmpty() || showDialog && !ProjectMacrosUtil.checkMacros(project, new THashSet(unknownMacros))) { + if (unknownMacros.isEmpty()) { return; } - final PathMacros pathMacros = PathMacros.getInstance(); - final Set macrosToInvalidate = new THashSet(unknownMacros); - for (Iterator it = macrosToInvalidate.iterator(); it.hasNext(); ) { + if (notify) { + doNotify(unknownMacros, project, substitutorToStore); + return; + } + + checkUnknownMacros(project, false, unknownMacros, substitutorToStore); + } + + private static void checkUnknownMacros(@NotNull Project project, + boolean showDialog, + @NotNull Set unknownMacros, + @NotNull Map substitutorToStore) { + if (unknownMacros.isEmpty() || (showDialog && !ProjectMacrosUtil.checkMacros(project, new THashSet(unknownMacros)))) { + return; + } + + PathMacros pathMacros = PathMacros.getInstance(); + for (Iterator it = unknownMacros.iterator(); it.hasNext(); ) { String macro = it.next(); if (StringUtil.isEmptyOrSpaces(pathMacros.getValue(macro)) && !pathMacros.isIgnoredMacroName(macro)) { it.remove(); } } - if (macrosToInvalidate.isEmpty()) { + if (unknownMacros.isEmpty()) { return; } - Set components = new THashSet(); - for (TrackingPathMacroSubstitutor substitutor : substitutors) { - components.addAll(substitutor.getComponents(macrosToInvalidate)); - } + for (Map.Entry entry : substitutorToStore.entrySet()) { + TrackingPathMacroSubstitutor substitutor = entry.getKey(); + Set components = substitutor.getComponents(unknownMacros); + IComponentStore store = entry.getValue(); + if (store.isReloadPossible(components)) { + substitutor.invalidateUnknownMacros(unknownMacros); - if (store.isReloadPossible(components)) { - for (TrackingPathMacroSubstitutor substitutor : substitutors) { - substitutor.invalidateUnknownMacros(macrosToInvalidate); - } - - for (UnknownMacroNotification notification : NotificationsManager.getNotificationsManager().getNotificationsOfType(UnknownMacroNotification.class, project)) { - if (macrosToInvalidate.containsAll(notification.getMacros())) { - notification.expire(); + for (UnknownMacroNotification notification : NotificationsManager.getNotificationsManager().getNotificationsOfType(UnknownMacroNotification.class, project)) { + if (unknownMacros.containsAll(notification.getMacros())) { + notification.expire(); + } } - } - store.reloadStates(components, project.getMessageBus()); + store.reloadStates(components, project.getMessageBus()); + } + else if (Messages.showYesNoDialog(project, "Component could not be reloaded. Reload project?", "Configuration Changed", + Messages.getQuestionIcon()) == Messages.YES) { + ProjectManagerEx.getInstanceEx().reloadProject(project); + } } - else if (Messages.showYesNoDialog(project, "Component could not be reloaded. Reload project?", "Configuration Changed", Messages.getQuestionIcon()) == Messages.YES) { - ProjectManagerEx.getInstanceEx().reloadProject(project); + } + + private static void collect(@NotNull ComponentManager componentManager, + @NotNull Set unknownMacros, + @NotNull Map substitutorToStore) { + IComponentStore store = ComponentsPackage.getStateStore(componentManager); + TrackingPathMacroSubstitutor substitutor = store.getStateStorageManager().getMacroSubstitutor(); + if (substitutor == null) { + return; } + + Set macros = substitutor.getUnknownMacros(null); + if (macros.isEmpty()) { + return; + } + + unknownMacros.addAll(macros); + substitutorToStore.put(substitutor, store); } @NotNull diff --git a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java index ae065e430ca8..30c25c643d8c 100644 --- a/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/project/impl/ProjectManagerImpl.java @@ -28,6 +28,7 @@ import com.intellij.notification.NotificationListener; import com.intellij.notification.NotificationType; import com.intellij.notification.NotificationsManager; import com.intellij.openapi.Disposable; +import com.intellij.openapi.application.Application; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ApplicationNamesInfo; import com.intellij.openapi.application.ModalityState; @@ -387,6 +388,11 @@ public class ProjectManagerImpl extends ProjectManagerEx implements Disposable { public void run() { if (!project.isDisposed()) { startupManager.runPostStartupActivities(); + + Application application = ApplicationManager.getApplication(); + if (!(application.isHeadlessEnvironment() || application.isUnitTestMode())) { + StorageUtil.checkUnknownMacros(project, true); + } } } }); @@ -399,8 +405,6 @@ public class ProjectManagerImpl extends ProjectManagerEx implements Disposable { return false; } - StorageUtil.checkUnknownMacros(project, project); - return true; } diff --git a/platform/projectModel-impl/src/com/intellij/openapi/components/TrackingPathMacroSubstitutor.java b/platform/projectModel-impl/src/com/intellij/openapi/components/TrackingPathMacroSubstitutor.java index 48f33feb7936..e236a6af7e1d 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/components/TrackingPathMacroSubstitutor.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/components/TrackingPathMacroSubstitutor.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2012 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,10 +23,11 @@ import java.util.Set; public interface TrackingPathMacroSubstitutor extends PathMacroSubstitutor { @NotNull - Collection getUnknownMacros(@Nullable String componentName); + Set getUnknownMacros(@Nullable String componentName); + // Mutable set @NotNull - Collection getComponents(@NotNull Collection macros); + Set getComponents(@NotNull Collection macros); void addUnknownMacros(@NotNull String componentName, @NotNull Collection unknownMacros); diff --git a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/BasePathMacroManager.java b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/BasePathMacroManager.java index e57ea73a937f..351d579290e7 100644 --- a/platform/projectModel-impl/src/com/intellij/openapi/components/impl/BasePathMacroManager.java +++ b/platform/projectModel-impl/src/com/intellij/openapi/components/impl/BasePathMacroManager.java @@ -35,7 +35,6 @@ import com.intellij.openapi.vfs.VirtualFileSystem; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.MultiMap; import com.intellij.util.containers.SmartHashSet; -import gnu.trove.THashSet; import org.jdom.Element; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -217,7 +216,7 @@ public class BasePathMacroManager extends PathMacroManager { @NotNull @Override - public Collection getComponents(@NotNull Collection macros) { + public Set getComponents(@NotNull Collection macros) { synchronized (myLock) { Set result = new SmartHashSet(); for (String macro : macros) { @@ -229,10 +228,10 @@ public class BasePathMacroManager extends PathMacroManager { @NotNull @Override - public Collection getUnknownMacros(@Nullable String componentName) { + public Set getUnknownMacros(@Nullable String componentName) { synchronized (myLock) { - Collection list = componentName == null ? myMacroToComponentNames.keySet() : myComponentNameToMacros.get(componentName); - return ContainerUtil.isEmpty(list) ? Collections.emptyList() : new THashSet(list); + Set list = componentName == null ? myMacroToComponentNames.keySet() : (Set)myComponentNameToMacros.get(componentName); + return ContainerUtil.isEmpty(list) ? Collections.emptySet() : Collections.unmodifiableSet(list); } }