blob: ef3800dfa4898c485a78dbe04e2aefa890c0dc2b [file] [log] [blame]
/*
* Copyright 2000-2013 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.ProjectTopics;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.module.ModifiableModuleModel;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.StdModuleTypes;
import com.intellij.openapi.roots.impl.ModifiableModelCommitter;
import com.intellij.openapi.project.ModuleAdapter;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.testFramework.ModuleTestCase;
import com.intellij.util.messages.MessageBusConnection;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* @author dsl
*/
public class MultiModuleEditingTest extends ModuleTestCase {
private static final String TEST_PATH = PathManagerEx.getTestDataPath() +
"/moduleRootManager/multiModuleEditing".replace('/', File.separatorChar);
@Override
protected void setUpModule() {
}
@Override
protected void setUpJdk() {
}
public void testAddTwoModules() throws Exception {
final MessageBusConnection connection = myProject.getMessageBus().connect();
final MyModuleListener moduleListener = new MyModuleListener();
connection.subscribe(ProjectTopics.MODULES, moduleListener);
final ModuleManager moduleManager = ModuleManager.getInstance(myProject);
final Module moduleA;
final Module moduleB;
{
final ModifiableModuleModel modifiableModel = moduleManager.getModifiableModel();
moduleA = modifiableModel.newModule("a.iml", StdModuleTypes.JAVA.getId());
moduleB = modifiableModel.newModule("b.iml", StdModuleTypes.JAVA.getId());
assertEquals("Changes are not applied until commit", 0, moduleManager.getModules().length);
//noinspection SSBasedInspection
moduleListener.assertCorrectEvents(new String[0][]);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
modifiableModel.commit();
}
});
}
assertEquals(2, moduleManager.getModules().length);
assertTrue(moduleManager.findModuleByName("a").equals(moduleA));
assertTrue(moduleManager.findModuleByName("b").equals(moduleB));
moduleListener.assertCorrectEvents(new String[][]{{"+a", "+b"}});
{
final ModifiableModuleModel modifiableModel = moduleManager.getModifiableModel();
modifiableModel.disposeModule(moduleA);
modifiableModel.disposeModule(moduleB);
assertEquals("Changes are not applied until commit", 2, moduleManager.getModules().length);
moduleListener.assertCorrectEvents(new String[][]{{"+a", "+b"}});
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
modifiableModel.commit();
}
});
}
assertEquals(0, moduleManager.getModules().length);
moduleListener.assertCorrectEvents(new String[][]{{"+a", "+b"}, {"-a", "-b"}});
connection.disconnect();
}
public void testRootsEditing() {
final MessageBusConnection connection = myProject.getMessageBus().connect();
final ModuleManager moduleManager = ModuleManager.getInstance(myProject);
final MyModuleListener moduleListener = new MyModuleListener();
connection.subscribe(ProjectTopics.MODULES, moduleListener);
final Module moduleA;
final Module moduleB;
{
final ModifiableModuleModel moduleModel = moduleManager.getModifiableModel();
moduleA = moduleModel.newModule("a.iml", StdModuleTypes.JAVA.getId());
moduleB = moduleModel.newModule("b.iml", StdModuleTypes.JAVA.getId());
final ModifiableRootModel rootModelA = ModuleRootManager.getInstance(moduleA).getModifiableModel();
final ModifiableRootModel rootModelB = ModuleRootManager.getInstance(moduleB).getModifiableModel();
rootModelB.addModuleOrderEntry(moduleA);
final ContentEntry contentEntryA = rootModelA.addContentEntry(getVirtualFileInTestData("a"));
contentEntryA.addSourceFolder(getVirtualFileInTestData("a/src"), false);
final ContentEntry contentEntryB = rootModelB.addContentEntry(getVirtualFileInTestData("b"));
contentEntryB.addSourceFolder(getVirtualFileInTestData("b/src"), false);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
ModifiableModelCommitter.multiCommit(new ModifiableRootModel[]{rootModelB, rootModelA}, moduleModel);
}
});
}
final JavaPsiFacade psiManager = getJavaFacade();
assertNull(psiManager.findClass("j.B", GlobalSearchScope.moduleWithDependenciesScope(moduleA)));
assertNull(psiManager.findClass("q.A", GlobalSearchScope.moduleScope(moduleB)));
assertNotNull(psiManager.findClass("q.A", GlobalSearchScope.moduleScope(moduleA)));
assertNotNull(psiManager.findClass("q.A", GlobalSearchScope.moduleWithDependenciesScope(moduleB)));
assertNotNull(psiManager.findClass("j.B", GlobalSearchScope.moduleScope(moduleB)));
assertNotNull(psiManager.findClass("j.B", GlobalSearchScope.moduleWithDependenciesScope(moduleB)));
moduleManager.disposeModule(moduleB);
moduleManager.disposeModule(moduleA);
moduleListener.assertCorrectEvents(new String[][]{{"+b", "+a"}, {"-b"}, {"-a"}});
connection.disconnect();
}
public void testRenaming() throws Exception{
final ModuleManager moduleManager = ModuleManager.getInstance(myProject);
final Module moduleA;
final Module moduleB;
{
final ModifiableModuleModel moduleModel = moduleManager.getModifiableModel();
moduleA = moduleModel.newModule("a.iml", StdModuleTypes.JAVA.getId());
moduleB = moduleModel.newModule("b.iml", StdModuleTypes.JAVA.getId());
final Module moduleC = moduleModel.newModule("c.iml", StdModuleTypes.JAVA.getId());
final ModifiableRootModel rootModelB = ModuleRootManager.getInstance(moduleB).getModifiableModel();
rootModelB.addModuleOrderEntry(moduleC);
moduleModel.disposeModule(moduleC);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
ModifiableModelCommitter.multiCommit(new ModifiableRootModel[]{rootModelB}, moduleModel);
}
});
}
final ModuleRootManager rootManagerB = ModuleRootManager.getInstance(moduleB);
assertEquals(0, rootManagerB.getDependencies().length);
final String[] dependencyModuleNames = rootManagerB.getDependencyModuleNames();
assertEquals(1, dependencyModuleNames.length);
assertEquals("c", dependencyModuleNames[0]);
{
final ModifiableModuleModel moduleModel = moduleManager.getModifiableModel();
moduleModel.renameModule(moduleA, "c");
moduleModel.commit();
}
assertEquals(1, rootManagerB.getDependencies().length);
assertEquals(moduleA, rootManagerB.getDependencies()[0]);
assertEquals("c", moduleA.getName());
moduleManager.disposeModule(moduleA);
moduleManager.disposeModule(moduleB);
}
private VirtualFile getVirtualFileInTestData(final String relativeVfsPath) {
return WriteCommandAction.runWriteCommandAction(null, new Computable<VirtualFile>() {
@Override
public VirtualFile compute() {
final String path =
TEST_PATH + File.separatorChar + getTestName(true) + File.separatorChar + relativeVfsPath.replace('/', File.separatorChar);
final VirtualFile result = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(path));
assertNotNull("File " + path + " doen\'t exist", result);
return result;
}
});
}
private static class MyModuleListener extends ModuleAdapter {
private final List<String> myLog = new ArrayList<String>();
@Override
public void moduleRemoved(Project project, Module module) {
myLog.add("-" + module.getName());
}
@Override
public void moduleAdded(Project project, Module module) {
myLog.add("+" + module.getName());
}
public void assertCorrectEvents(String[][] expected) {
int runningIndex = 0;
for (int chunkIndex = 0; chunkIndex < expected.length; chunkIndex++) {
String[] chunk = expected[chunkIndex];
final List<String> expectedChunkList = new ArrayList<String>(Arrays.asList(chunk));
int nextIndex = runningIndex + chunk.length;
assertTrue("Expected chunk " + expectedChunkList.toString(), nextIndex <= myLog.size());
final List<String> actualChunkList = new ArrayList<String>(myLog.subList(runningIndex, nextIndex));
Collections.sort(expectedChunkList);
Collections.sort(actualChunkList);
assertEquals("Chunk " + chunkIndex, expectedChunkList.toString(), actualChunkList.toString());
runningIndex = nextIndex;
}
assertEquals("More events than needed", runningIndex, myLog.size());
}
}
}