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:
nik
2017-05-31 11:38:01 +03:00
parent 82a17a56b5
commit 8b233d5590
22 changed files with 488 additions and 10 deletions
@@ -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>
@@ -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
}
@@ -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
*/
@@ -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>
@@ -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>()
}
@@ -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()
}
@@ -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);
}
@@ -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)})
}
}
}
@@ -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);
}
}