mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
project configuration: added support for unloaded modules
Unloaded modules are removed from the project, they aren't shown in UI, all of their contents isn't indexed or compiled. List of unloaded modules is stored in projects workspace settings, so it isn't shared with other team members. (IDEA-27471)
This commit is contained in:
+10
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4" relativePaths="true">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module filepath="$PROJECT_DIR$/main.iml" fileurl="file://$PROJECT_DIR$/main.iml"/>
|
||||
<module filepath="$PROJECT_DIR$/util.iml" fileurl="file://$PROJECT_DIR$/util.iml"/>
|
||||
<module filepath="$PROJECT_DIR$/dep.iml" fileurl="file://$PROJECT_DIR$/dep.iml"/>
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UnloadedModulesList">
|
||||
<module name="util"/>
|
||||
<module name="dep"/>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module relativePaths="true" type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$/dep">
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="module" module-name="util" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module relativePaths="true" type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module relativePaths="true" type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$/util">
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.roots
|
||||
|
||||
import com.intellij.openapi.application.ex.PathManagerEx
|
||||
import com.intellij.openapi.module.ModuleManager
|
||||
import com.intellij.openapi.project.ex.ProjectManagerEx
|
||||
import com.intellij.openapi.project.impl.ProjectManagerImpl
|
||||
import com.intellij.openapi.roots.ModuleRootModificationUtil
|
||||
import com.intellij.openapi.util.io.FileUtil
|
||||
import com.intellij.openapi.vfs.VfsUtilCore
|
||||
import com.intellij.testFramework.ModuleTestCase
|
||||
import java.io.File
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class UnloadedModulesConfigurationTest : ModuleTestCase() {
|
||||
fun `test load project`() {
|
||||
val projectPath = File(PathManagerEx.getTestDataPath(), "moduleRootManager/unloadedModules").absolutePath
|
||||
val project = getProjectManager().loadAndOpenProject(projectPath)!!
|
||||
try {
|
||||
val moduleManager = ModuleManager.getInstance(project)
|
||||
assertEquals(3, moduleManager.allModuleDescriptions.size)
|
||||
assertEquals(2, moduleManager.unloadedModuleDescriptions.size)
|
||||
|
||||
val util = moduleManager.unloadedModuleDescriptions.find { it.name == "util" }!!
|
||||
val projectDirUrl = VfsUtilCore.pathToUrl(FileUtil.toSystemIndependentName(projectPath))
|
||||
assertEquals("$projectDirUrl/util", assertOneElement(util.contentRoots).url)
|
||||
assertEmpty(util.dependencyModuleNames)
|
||||
|
||||
val dep = moduleManager.unloadedModuleDescriptions.find { it.name == "dep" }!!
|
||||
assertEquals("$projectDirUrl/dep", assertOneElement(dep.contentRoots).url)
|
||||
assertEquals("util", assertOneElement(dep.dependencyModuleNames))
|
||||
}
|
||||
finally {
|
||||
getProjectManager().forceCloseProject(project, true)
|
||||
}
|
||||
}
|
||||
|
||||
fun `test set unloaded modules`() {
|
||||
val a = createModule("a")
|
||||
val b = createModule("b")
|
||||
ModuleRootModificationUtil.addDependency(a, b)
|
||||
val moduleManager = ModuleManager.getInstance(project)
|
||||
moduleManager.setUnloadedModules(listOf("a"))
|
||||
assertEquals("a", assertOneElement(moduleManager.unloadedModuleDescriptions).name)
|
||||
assertNull(moduleManager.findModuleByName("a"))
|
||||
assertNotNull(moduleManager.findModuleByName("b"))
|
||||
|
||||
moduleManager.setUnloadedModules(listOf("b"))
|
||||
assertEquals("b", assertOneElement(moduleManager.unloadedModuleDescriptions).name)
|
||||
assertNotNull(moduleManager.findModuleByName("a"))
|
||||
assertNull(moduleManager.findModuleByName("b"))
|
||||
}
|
||||
|
||||
private fun getProjectManager() = ProjectManagerEx.getInstanceEx() as ProjectManagerImpl
|
||||
}
|
||||
+14
-2
@@ -23,7 +23,9 @@ import org.jdom.Element;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.model.JpsElementChildRole;
|
||||
import org.jetbrains.jps.model.JpsElementFactory;
|
||||
import org.jetbrains.jps.model.JpsGlobal;
|
||||
import org.jetbrains.jps.model.JpsModel;
|
||||
import org.jetbrains.jps.model.ex.JpsElementChildRoleBase;
|
||||
import org.jetbrains.jps.model.serialization.impl.JpsPathVariablesConfigurationImpl;
|
||||
import org.jetbrains.jps.model.serialization.library.JpsLibraryTableSerializer;
|
||||
@@ -55,11 +57,21 @@ public class JpsGlobalLoader extends JpsLoaderBase {
|
||||
|
||||
public static void loadGlobalSettings(JpsGlobal global, String optionsPath) throws IOException {
|
||||
Path optionsDir = Paths.get(FileUtil.toCanonicalPath(optionsPath));
|
||||
new JpsGlobalLoader(global, Collections.emptyMap()).loadGlobalComponents(optionsDir, optionsDir.resolve("other.xml"), new PathVariablesSerializer());
|
||||
Map<String, String> pathVariables = JpsModelSerializationDataService.computeAllPathVariables(global);
|
||||
Map<String, String> pathVariables = loadPathVariables(global, optionsDir);
|
||||
new JpsGlobalLoader(global, pathVariables).load(optionsDir);
|
||||
}
|
||||
|
||||
private static Map<String, String> loadPathVariables(JpsGlobal global, Path optionsDir) {
|
||||
new JpsGlobalLoader(global, Collections.emptyMap()).loadGlobalComponents(optionsDir, optionsDir.resolve("other.xml"), new PathVariablesSerializer());
|
||||
return JpsModelSerializationDataService.computeAllPathVariables(global);
|
||||
}
|
||||
|
||||
public static Map<String, String> computeAllPathVariables(@NotNull String optionsPath) {
|
||||
JpsModel model = JpsElementFactory.getInstance().createModel();
|
||||
Path optionsDir = Paths.get(FileUtil.toCanonicalPath(optionsPath));
|
||||
return loadPathVariables(model.getGlobal(), optionsDir);
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated use {@link JpsModelSerializationDataService#getPathVariableValue(org.jetbrains.jps.model.JpsGlobal, String)} instead
|
||||
*/
|
||||
|
||||
+20
-7
@@ -124,7 +124,8 @@ public class JpsProjectLoader extends JpsLoaderBase {
|
||||
loadComponents(dir, defaultConfigFile, serializer, myProject);
|
||||
}
|
||||
}
|
||||
loadModules(loadRootElement(dir.resolve("modules.xml")), projectSdkType);
|
||||
Path workspaceFile = dir.resolve("workspace.xml");
|
||||
loadModules(loadRootElement(dir.resolve("modules.xml")), projectSdkType, workspaceFile);
|
||||
|
||||
Runnable timingLog = TimingLog.startActivity("loading project libraries");
|
||||
for (Path libraryFile : listXmlFiles(dir.resolve("libraries"))) {
|
||||
@@ -150,7 +151,7 @@ public class JpsProjectLoader extends JpsLoaderBase {
|
||||
for (Path configurationFile : listXmlFiles(dir.resolve("runConfigurations"))) {
|
||||
JpsRunConfigurationSerializer.loadRunConfigurations(myProject, loadRootElement(configurationFile));
|
||||
}
|
||||
JpsRunConfigurationSerializer.loadRunConfigurations(myProject, JDomSerializationUtil.findComponent(loadRootElement(dir.resolve("workspace.xml")), "RunManager"));
|
||||
JpsRunConfigurationSerializer.loadRunConfigurations(myProject, JDomSerializationUtil.findComponent(loadRootElement(workspaceFile), "RunManager"));
|
||||
runConfTimingLog.run();
|
||||
}
|
||||
}
|
||||
@@ -197,7 +198,7 @@ public class JpsProjectLoader extends JpsLoaderBase {
|
||||
}
|
||||
}
|
||||
}
|
||||
loadModules(iprRoot, projectSdkType);
|
||||
loadModules(iprRoot, projectSdkType, iwsFile);
|
||||
loadProjectLibraries(JDomSerializationUtil.findComponent(iprRoot, "libraryTable"));
|
||||
loadArtifacts(JDomSerializationUtil.findComponent(iprRoot, "ArtifactManager"));
|
||||
if (hasRunConfigurationSerializers()) {
|
||||
@@ -229,18 +230,25 @@ public class JpsProjectLoader extends JpsLoaderBase {
|
||||
JpsLibraryTableSerializer.loadLibraries(libraryTableElement, myProject.getLibraryCollection());
|
||||
}
|
||||
|
||||
private void loadModules(@Nullable Element root, final @Nullable JpsSdkType<?> projectSdkType) {
|
||||
private void loadModules(@Nullable Element root, final @Nullable JpsSdkType<?> projectSdkType, Path workspaceFile) {
|
||||
Runnable timingLog = TimingLog.startActivity("loading modules");
|
||||
Element componentRoot = JDomSerializationUtil.findComponent(root, "ProjectModuleManager");
|
||||
if (componentRoot == null) return;
|
||||
|
||||
Set<String> unloadedModules = new HashSet<>();
|
||||
if (Files.exists(workspaceFile)) {
|
||||
Element unloadedModulesList = JDomSerializationUtil.findComponent(loadRootElement(workspaceFile), "UnloadedModulesList");
|
||||
for (Element element : JDOMUtil.getChildren(unloadedModulesList, "module")) {
|
||||
unloadedModules.add(element.getAttributeValue("name"));
|
||||
}
|
||||
}
|
||||
|
||||
final Set<Path> foundFiles = new THashSet<>();
|
||||
final List<Path> moduleFiles = new ArrayList<>();
|
||||
for (Element moduleElement : JDOMUtil.getChildren(componentRoot.getChild("modules"), "module")) {
|
||||
final String path = moduleElement.getAttributeValue("filepath");
|
||||
final Path file = Paths.get(path);
|
||||
if (foundFiles.add(file)) {
|
||||
if (foundFiles.add(file) && !unloadedModules.contains(getModuleName(file))) {
|
||||
moduleFiles.add(file);
|
||||
}
|
||||
}
|
||||
@@ -285,7 +293,7 @@ public class JpsProjectLoader extends JpsLoaderBase {
|
||||
}
|
||||
|
||||
if (data == null) {
|
||||
LOG.info("Module '" + FileUtil.getNameWithoutExtension(file.getFileName().toString()) + "' is skipped: " + file.toAbsolutePath() + " doesn't exist");
|
||||
LOG.info("Module '" + getModuleName(file) + "' is skipped: " + file.toAbsolutePath() + " doesn't exist");
|
||||
}
|
||||
|
||||
return Pair.create(file, data);
|
||||
@@ -323,7 +331,7 @@ public class JpsProjectLoader extends JpsLoaderBase {
|
||||
@NotNull
|
||||
private static JpsModule loadModule(@NotNull Path file, @NotNull Element moduleRoot, List<String> paths,
|
||||
@Nullable JpsSdkType<?> projectSdkType, Map<String, String> pathVariables) {
|
||||
String name = FileUtil.getNameWithoutExtension(file.getFileName().toString());
|
||||
String name = getModuleName(file);
|
||||
final String typeId = moduleRoot.getAttributeValue("type");
|
||||
final JpsModulePropertiesSerializer<?> serializer = getModulePropertiesSerializer(typeId);
|
||||
final JpsModule module = createModule(name, moduleRoot, serializer);
|
||||
@@ -354,6 +362,11 @@ public class JpsProjectLoader extends JpsLoaderBase {
|
||||
return module;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static String getModuleName(@NotNull Path file) {
|
||||
return FileUtil.getNameWithoutExtension(file.getFileName().toString());
|
||||
}
|
||||
|
||||
static JpsMacroExpander createModuleMacroExpander(final Map<String, String> pathVariables, @NotNull Path moduleFile) {
|
||||
final JpsMacroExpander expander = new JpsMacroExpander(pathVariables);
|
||||
String moduleDirPath = PathMacroUtil.getModuleDir(moduleFile.toAbsolutePath().toString());
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4" relativePaths="true">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_5" assert-keyword="true" jdk-15="true" project-jdk-name="1.6"
|
||||
project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out"/>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4" relativePaths="true">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module filepath="$PROJECT_DIR$/main.iml" fileurl="file://$PROJECT_DIR$/main.iml"/>
|
||||
<module filepath="$PROJECT_DIR$/util.iml" fileurl="file://$PROJECT_DIR$/util.iml"/>
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="UnloadedModulesList">
|
||||
<module name="util"/>
|
||||
</component>
|
||||
</project>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module relativePaths="true" type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$">
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module relativePaths="true" type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$/util">
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
||||
+6
@@ -230,6 +230,12 @@ public class JpsProjectSerializationTest extends JpsSerializationTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testUnloadedModule() {
|
||||
String projectPath = "/jps/model-serialization/testData/unloadedModule";
|
||||
loadProject(projectPath);
|
||||
assertEquals("main", assertOneElement(myProject.getModules()).getName());
|
||||
}
|
||||
|
||||
private void doTestSaveLibrary(@NotNull Path libFile, String libName, JpsLibrary library) {
|
||||
Element actual = new Element("library");
|
||||
JpsLibraryTableSerializer.saveLibrary(library, actual, libName);
|
||||
|
||||
@@ -917,6 +917,7 @@
|
||||
|
||||
<projectService serviceInterface="com.intellij.openapi.module.ModulePointerManager"
|
||||
serviceImplementation="com.intellij.openapi.module.impl.ModulePointerManagerImpl"/>
|
||||
<projectService serviceImplementation="com.intellij.openapi.module.impl.UnloadedModulesListStorage"/>
|
||||
|
||||
<customFoldingProvider implementation="com.intellij.lang.customFolding.NetBeansCustomFoldingProvider"/>
|
||||
<customFoldingProvider implementation="com.intellij.lang.customFolding.VisualStudioCustomFoldingProvider"/>
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.module
|
||||
|
||||
import com.intellij.openapi.vfs.pointers.VirtualFilePointer
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
|
||||
/**
|
||||
* Represents a description of a module which may be either loaded into the project or unloaded. Use this class only if you need to process
|
||||
* all modules including unloaded, in other cases [Module] should be used instead.
|
||||
* @see [ModuleManager.getUnloadedModuleDescriptions]
|
||||
* @author nik
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
interface ModuleDescription {
|
||||
val name: String
|
||||
|
||||
/**
|
||||
* Names of the modules on which the current module depend.
|
||||
*/
|
||||
val dependencyModuleNames: List<String>
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
interface UnloadedModuleDescription : ModuleDescription {
|
||||
val contentRoots: List<VirtualFilePointer>
|
||||
}
|
||||
@@ -20,11 +20,13 @@ import com.intellij.openapi.util.InvalidDataException;
|
||||
import com.intellij.openapi.util.SimpleModificationTracker;
|
||||
import com.intellij.util.graph.Graph;
|
||||
import org.jdom.JDOMException;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
@@ -170,4 +172,20 @@ public abstract class ModuleManager extends SimpleModificationTracker {
|
||||
public abstract String[] getModuleGroupPath(@NotNull Module module);
|
||||
|
||||
public abstract boolean hasModuleGroups();
|
||||
|
||||
/**
|
||||
* @return description of all modules in the project including unloaded
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
public abstract Collection<ModuleDescription> getAllModuleDescriptions();
|
||||
|
||||
@ApiStatus.Experimental
|
||||
public abstract Collection<? extends UnloadedModuleDescription> getUnloadedModuleDescriptions();
|
||||
|
||||
/**
|
||||
* Specify list of modules which will be unloaded from the project. These modules won't be shown in UI, all of their contents will be excluded
|
||||
* from indexing and compilation.
|
||||
*/
|
||||
@ApiStatus.Experimental
|
||||
public abstract void setUnloadedModules(@NotNull List<String> unloadedModuleNames);
|
||||
}
|
||||
|
||||
@@ -48,4 +48,11 @@ class EmptyModuleManager(project: Project, messageBus: MessageBus) : ModuleManag
|
||||
override fun getModifiableModel() = throw UnsupportedOperationException()
|
||||
|
||||
override fun getModuleGroupPath(module: Module) = emptyArray<String>()
|
||||
|
||||
override fun setUnloadedModules(unloadedModuleNames: MutableList<String>) {
|
||||
}
|
||||
|
||||
override fun getAllModuleDescriptions() = emptyList<ModuleDescription>()
|
||||
|
||||
override fun getUnloadedModuleDescriptions() = emptyList<UnloadedModuleDescription>()
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.module.impl
|
||||
|
||||
import com.intellij.openapi.module.Module
|
||||
import com.intellij.openapi.module.ModuleDescription
|
||||
import com.intellij.openapi.roots.ModuleRootManager
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class LoadedModuleDescription(private val module: Module): ModuleDescription {
|
||||
override val name: String
|
||||
get() = module.name
|
||||
|
||||
override val dependencyModuleNames: List<String>
|
||||
get() = ModuleRootManager.getInstance(module).dependencyModuleNames.asList()
|
||||
}
|
||||
+77
-1
@@ -43,6 +43,8 @@ import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.StandardFileSystems;
|
||||
import com.intellij.openapi.vfs.VirtualFileManager;
|
||||
import com.intellij.openapi.vfs.pointers.VirtualFilePointer;
|
||||
import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager;
|
||||
import com.intellij.util.SmartList;
|
||||
import com.intellij.util.concurrency.AppExecutorUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
@@ -62,6 +64,7 @@ import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
@@ -86,6 +89,7 @@ public abstract class ModuleManagerImpl extends ModuleManager implements Disposa
|
||||
|
||||
private LinkedHashSet<ModulePath> myModulePathsToLoad;
|
||||
private final Set<ModulePath> myFailedModulePaths = new THashSet<>();
|
||||
private Map<String, UnloadedModuleDescriptionImpl> myUnloadedModules = new LinkedHashMap<>();
|
||||
|
||||
public static ModuleManagerImpl getInstanceImpl(Project project) {
|
||||
return (ModuleManagerImpl)getInstance(project);
|
||||
@@ -161,6 +165,22 @@ public abstract class ModuleManagerImpl extends ModuleManager implements Disposa
|
||||
public void loadState(Element state) {
|
||||
boolean isFirstLoadState = myModulePathsToLoad == null;
|
||||
myModulePathsToLoad = getPathsToModuleFiles(state);
|
||||
Set<String> unloadedModuleNames = new HashSet<>(UnloadedModulesListStorage.getInstance(myProject).getUnloadedModuleNames());
|
||||
Iterator<ModulePath> iterator = myModulePathsToLoad.iterator();
|
||||
List<ModulePath> unloadedModulePaths = new ArrayList<>();
|
||||
while (iterator.hasNext()) {
|
||||
ModulePath modulePath = iterator.next();
|
||||
if (unloadedModuleNames.contains(modulePath.getModuleName())) {
|
||||
unloadedModulePaths.add(modulePath);
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
List<UnloadedModuleDescriptionImpl> descriptions = UnloadedModuleDescriptionImpl.createFromPaths(unloadedModulePaths, this);
|
||||
myUnloadedModules.clear();
|
||||
for (UnloadedModuleDescriptionImpl description : descriptions) {
|
||||
myUnloadedModules.put(description.getName(), description);
|
||||
}
|
||||
|
||||
if (isFirstLoadState) {
|
||||
// someone else must call loadModules in a appropriate time (e.g. on projectComponentsInitialized)
|
||||
return;
|
||||
@@ -421,13 +441,16 @@ public abstract class ModuleManagerImpl extends ModuleManager implements Disposa
|
||||
public void writeExternal(@NotNull Element element) {
|
||||
final Module[] collection = getModules();
|
||||
|
||||
List<SaveItem> sorted = new ArrayList<>(collection.length + myFailedModulePaths.size());
|
||||
List<SaveItem> sorted = new ArrayList<>(collection.length + myFailedModulePaths.size() + myUnloadedModules.size());
|
||||
for (Module module : collection) {
|
||||
sorted.add(new ModuleSaveItem(module));
|
||||
}
|
||||
for (ModulePath modulePath : myFailedModulePaths) {
|
||||
sorted.add(new ModulePathSaveItem(modulePath));
|
||||
}
|
||||
for (UnloadedModuleDescriptionImpl description : myUnloadedModules.values()) {
|
||||
sorted.add(new ModulePathSaveItem(description.getModulePath()));
|
||||
}
|
||||
|
||||
if (!sorted.isEmpty()) {
|
||||
Collections.sort(sorted, Comparator.comparing(SaveItem::getModuleName));
|
||||
@@ -957,6 +980,59 @@ public abstract class ModuleManagerImpl extends ModuleManager implements Disposa
|
||||
return myModuleModel.hasModuleGroups();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<ModuleDescription> getAllModuleDescriptions() {
|
||||
Module[] modules = getModules();
|
||||
List<ModuleDescription> descriptions = new ArrayList<>(modules.length + myUnloadedModules.size());
|
||||
for (Module module : modules) {
|
||||
descriptions.add(new LoadedModuleDescription(module));
|
||||
}
|
||||
descriptions.addAll(myUnloadedModules.values());
|
||||
return descriptions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<? extends UnloadedModuleDescription> getUnloadedModuleDescriptions() {
|
||||
return myUnloadedModules.values();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setUnloadedModules(@NotNull List<String> unloadedModuleNames) {
|
||||
if (myUnloadedModules.keySet().equals(unloadedModuleNames)) {
|
||||
return;
|
||||
}
|
||||
|
||||
UnloadedModulesListStorage.getInstance(myProject).setUnloadedModuleNames(unloadedModuleNames);
|
||||
|
||||
final ModifiableModuleModel model = getModifiableModel();
|
||||
Map<String, UnloadedModuleDescriptionImpl> toLoad = new LinkedHashMap<>(myUnloadedModules);
|
||||
myUnloadedModules.clear();
|
||||
for (String name : unloadedModuleNames) {
|
||||
if (toLoad.containsKey(name)) {
|
||||
myUnloadedModules.put(name, toLoad.remove(name));
|
||||
}
|
||||
else {
|
||||
Module module = findModuleByName(name);
|
||||
if (module != null) {
|
||||
LoadedModuleDescription description = new LoadedModuleDescription(module);
|
||||
ModuleSaveItem saveItem = new ModuleSaveItem(module);
|
||||
ModulePath modulePath = new ModulePath(saveItem.getModuleFilePath(), saveItem.getGroupPathString());
|
||||
VirtualFilePointerManager pointerManager = VirtualFilePointerManager.getInstance();
|
||||
List<VirtualFilePointer> contentRoots = ContainerUtil.map(ModuleRootManager.getInstance(module).getContentRootUrls(), url -> pointerManager.create(url, this, null));
|
||||
UnloadedModuleDescriptionImpl unloadedModuleDescription = new UnloadedModuleDescriptionImpl(modulePath, description.getDependencyModuleNames(), contentRoots);
|
||||
model.disposeModule(module);
|
||||
myUnloadedModules.put(name, unloadedModuleDescription);
|
||||
}
|
||||
}
|
||||
}
|
||||
List<ModulePath> oldFailedPaths = new ArrayList<>(myFailedModulePaths);
|
||||
myModulePathsToLoad = toLoad.values().stream().map(d -> d.getModulePath()).collect(Collectors.toCollection(LinkedHashSet::new));
|
||||
loadModules((ModuleModelImpl)model);
|
||||
ApplicationManager.getApplication().runWriteAction(() -> model.commit());
|
||||
myFailedModulePaths.addAll(oldFailedPaths);
|
||||
myModulePathsToLoad.clear();
|
||||
}
|
||||
|
||||
public void setModuleGroupPath(Module module, String[] groupPath) {
|
||||
myModuleModel.setModuleGroupPath(module, groupPath);
|
||||
}
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.module.impl
|
||||
|
||||
import com.intellij.openapi.Disposable
|
||||
import com.intellij.openapi.application.PathManager
|
||||
import com.intellij.openapi.module.UnloadedModuleDescription
|
||||
import com.intellij.openapi.vfs.pointers.VirtualFilePointer
|
||||
import com.intellij.openapi.vfs.pointers.VirtualFilePointerManager
|
||||
import org.jetbrains.jps.model.module.JpsModule
|
||||
import org.jetbrains.jps.model.module.JpsModuleDependency
|
||||
import org.jetbrains.jps.model.serialization.JpsGlobalLoader
|
||||
import org.jetbrains.jps.model.serialization.JpsProjectLoader
|
||||
import java.nio.file.Paths
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
class UnloadedModuleDescriptionImpl(val modulePath: ModulePath,
|
||||
override val dependencyModuleNames: List<String>,
|
||||
override val contentRoots: List<VirtualFilePointer>) : UnloadedModuleDescription {
|
||||
override val name: String
|
||||
get() = modulePath.moduleName
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun createFromPaths(paths: List<ModulePath>, parentDisposable: Disposable): List<UnloadedModuleDescriptionImpl> {
|
||||
val pathVariables = JpsGlobalLoader.computeAllPathVariables(PathManager.getOptionsPath())
|
||||
val modules = JpsProjectLoader.loadModules(paths.map { Paths.get(it.path) }, null, pathVariables)
|
||||
val pathsByName = paths.associateBy { it.moduleName }
|
||||
return modules.map { create(pathsByName[it.name]!!, it, parentDisposable) }
|
||||
}
|
||||
|
||||
private fun create(path: ModulePath, module: JpsModule, parentDisposable: Disposable): UnloadedModuleDescriptionImpl {
|
||||
val dependencyModuleNames = module.dependenciesList.dependencies
|
||||
.filterIsInstance(JpsModuleDependency::class.java)
|
||||
.map { it.moduleReference.moduleName }
|
||||
|
||||
val pointerManager = VirtualFilePointerManager.getInstance()
|
||||
return UnloadedModuleDescriptionImpl(path, dependencyModuleNames, module.contentRootsList.urls.map {pointerManager.create(it, parentDisposable, null)})
|
||||
}
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2000-2017 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.openapi.module.impl;
|
||||
|
||||
import com.intellij.openapi.components.*;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.util.xmlb.XmlSerializerUtil;
|
||||
import com.intellij.util.xmlb.annotations.AbstractCollection;
|
||||
import com.intellij.util.xmlb.annotations.Property;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nik
|
||||
*/
|
||||
@State(name = "UnloadedModulesList", storages = {@Storage(StoragePathMacros.WORKSPACE_FILE)})
|
||||
public class UnloadedModulesListStorage implements PersistentStateComponent<UnloadedModulesListStorage> {
|
||||
@Property(surroundWithTag = false)
|
||||
@AbstractCollection(surroundWithTag = false, elementTag = "module", elementValueAttribute = "name")
|
||||
public List<String> moduleNames = new ArrayList<>();
|
||||
|
||||
static UnloadedModulesListStorage getInstance(@NotNull Project project) {
|
||||
return ServiceManager.getService(project, UnloadedModulesListStorage.class);
|
||||
}
|
||||
|
||||
public List<String> getUnloadedModuleNames() {
|
||||
return Collections.unmodifiableList(moduleNames);
|
||||
}
|
||||
|
||||
public void setUnloadedModuleNames(List<String> names) {
|
||||
moduleNames.clear();
|
||||
moduleNames.addAll(names);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public UnloadedModulesListStorage getState() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadState(UnloadedModulesListStorage state) {
|
||||
XmlSerializerUtil.copyBean(state, this);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user