diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/GradleDiffUtil.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/GradleDiffUtil.java index de8e4ccdb7dd..ba30c1996dbd 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/GradleDiffUtil.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/diff/GradleDiffUtil.java @@ -45,6 +45,9 @@ public class GradleDiffUtil { @Override public void visit(@NotNull GradleModule module) { context.register(new GradleModulePresenceChange(module, null)); + for (GradleContentRoot root : module.getContentRoots()) { + root.invite(this); + } for (GradleDependency dependency : module.getDependencies()) { dependency.invite(this); } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleContentRootImporter.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleContentRootImporter.java index 7e4ab14eb5e0..7a228cb60335 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleContentRootImporter.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleContentRootImporter.java @@ -1,8 +1,15 @@ package org.jetbrains.plugins.gradle.importing; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.module.Module; +import com.intellij.openapi.roots.ContentEntry; +import com.intellij.openapi.roots.ModifiableRootModel; +import com.intellij.openapi.roots.ModuleRootManager; +import com.intellij.openapi.vfs.LocalFileSystem; +import com.intellij.util.ui.UIUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.gradle.model.gradle.GradleContentRoot; +import org.jetbrains.plugins.gradle.model.gradle.SourceType; import java.util.Collections; @@ -18,7 +25,52 @@ public class GradleContentRootImporter { importContentRoots(Collections.singleton(contentRoot), module); } - public void importContentRoots(@NotNull Iterable contentRoots, @NotNull Module module) { - // TODO den implement + @SuppressWarnings("MethodMayBeStatic") + public void importContentRoots(@NotNull final Iterable contentRoots, @NotNull final Module module) { + UIUtil.invokeLaterIfNeeded(new Runnable() { + @Override + public void run() { + doImportContentRoots(contentRoots, module); + } + }); } -} + + private static void doImportContentRoots(@NotNull final Iterable contentRoots, @NotNull final Module module) { + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + final ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module); + final ModifiableRootModel model = moduleRootManager.getModifiableModel(); + final GradleProjectEntityImportListener publisher = module.getProject().getMessageBus() + .syncPublisher(GradleProjectEntityImportListener.TOPIC); + for (GradleContentRoot root : contentRoots) { + publisher.onImportStart(root); + } + try { + for (GradleContentRoot contentRoot : contentRoots) { + ContentEntry contentEntry = model.addContentEntry(toVfsUrl(contentRoot.getRootPath())); + for (String path : contentRoot.getPaths(SourceType.SOURCE)) { + contentEntry.addSourceFolder(toVfsUrl(path), false); + } + for (String path : contentRoot.getPaths(SourceType.TEST)) { + contentEntry.addSourceFolder(toVfsUrl(path), true); + } + for (String path : contentRoot.getPaths(SourceType.EXCLUDED)) { + contentEntry.addExcludeFolder(toVfsUrl(path)); + } + } + } + finally { + model.commit(); + for (GradleContentRoot root : contentRoots) { + publisher.onImportEnd(root); + } + } + } + }); + } + + private static String toVfsUrl(@NotNull String path) { + return LocalFileSystem.PROTOCOL_PREFIX + path; + } +} \ No newline at end of file diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleLocalNodeImportHelper.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleLocalNodeImportHelper.java index f7ae2ecbbe71..be3a748a582d 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleLocalNodeImportHelper.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleLocalNodeImportHelper.java @@ -9,8 +9,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.plugins.gradle.config.GradleTextAttributes; import org.jetbrains.plugins.gradle.model.GradleEntityType; import org.jetbrains.plugins.gradle.model.gradle.*; +import org.jetbrains.plugins.gradle.model.id.GradleContentRootId; import org.jetbrains.plugins.gradle.model.id.GradleEntityId; import org.jetbrains.plugins.gradle.model.id.GradleEntityIdMapper; +import org.jetbrains.plugins.gradle.model.intellij.ModuleAwareContentRoot; import org.jetbrains.plugins.gradle.sync.GradleProjectStructureHelper; import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode; import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNodeDescriptor; @@ -136,11 +138,24 @@ public class GradleLocalNodeImportHelper { if (!context.recursive) { return; } + for (GradleContentRoot contentRoot : module.getContentRoots()) { + contentRoot.invite(context.visitor); + } for (GradleDependency dependency : module.getDependencies()) { dependency.invite(context.visitor); } } + private void collectContentRoots(@NotNull GradleContentRoot contentRoot, @NotNull Context context) { + final GradleContentRootId id = GradleEntityIdMapper.mapEntityToId(contentRoot); + final ModuleAwareContentRoot intellijContentRoot = myProjectStructureHelper.findIntellijContentRoot(id); + if (intellijContentRoot != null) { + // Already imported. + return; + } + context.contentRoots.add(contentRoot); + } + private void collectModuleDependencyEntities(@NotNull GradleModuleDependency dependency, @NotNull Context context) { final ModuleOrderEntry intellijModuleDependency = myProjectStructureHelper.findIntellijModuleDependency(dependency); if (intellijModuleDependency != null) { @@ -232,10 +247,11 @@ public class GradleLocalNodeImportHelper { private class Context { - public final Set modules = new HashSet(); - public final Set libraries = new HashSet(); - public final Set dependencies = new HashSet(); - public final CollectingVisitor visitor = new CollectingVisitor(this); + public final Set modules = new HashSet(); + public final Set contentRoots = new HashSet(); + public final Set libraries = new HashSet(); + public final Set dependencies = new HashSet(); + public final CollectingVisitor visitor = new CollectingVisitor(this); public boolean recursive; @@ -243,6 +259,7 @@ public class GradleLocalNodeImportHelper { public List getAll() { List result = new ArrayList(); result.addAll(modules); + result.addAll(contentRoots); result.addAll(libraries); result.addAll(dependencies); return result; @@ -258,10 +275,7 @@ public class GradleLocalNodeImportHelper { @Override public void visit(@NotNull GradleProject project) { } @Override public void visit(@NotNull GradleModule module) { collectModuleEntities(module, myContext); } - @Override - public void visit(@NotNull GradleContentRoot contentRoot) { - // TODO den implement - } + @Override public void visit(@NotNull GradleContentRoot contentRoot) { collectContentRoots(contentRoot, myContext); } @Override public void visit(@NotNull GradleLibrary library) { /* Assuming that a library may be imported only as a dependency */ } @Override public void visit(@NotNull GradleModuleDependency dependency) { collectModuleDependencyEntities(dependency, myContext); } @Override public void visit(@NotNull GradleLibraryDependency dependency) { collectLibraryDependencyEntities(dependency, myContext); } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java index c6edb9243c52..95e9e1d01124 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/importing/GradleModulesImporter.java @@ -366,12 +366,16 @@ public class GradleModulesImporter { model = projectLibraryTable.getModifiableModel(); List modelsToCommit = new ArrayList(); + Map libraryMappings = registerProjectLibraries(gradleProject, model); + final GradleProjectEntityImportListener publisher + = intellijProject.getMessageBus().syncPublisher(GradleProjectEntityImportListener.TOPIC); try { - Map libraryMappings = registerProjectLibraries(gradleProject, model); if (libraryMappings == null) { return; } - + for (GradleLibrary library : libraryMappings.keySet()) { + publisher.onImportStart(library); + } modelsToCommit.addAll(configureModulesLibraryDependencies(moduleMappings, libraryMappings, gradleProject)); } finally { @@ -379,6 +383,11 @@ public class GradleModulesImporter { ProjectRootManager projectRootManager = ProjectRootManager.getInstance(intellijProject); ModifiableRootModel[] modelsAsArray = modelsToCommit.toArray(new ModifiableRootModel[modelsToCommit.size()]); projectRootManager.multiCommit(modelsAsArray); + if (libraryMappings != null) { + for (GradleLibrary library : libraryMappings.keySet()) { + publisher.onImportEnd(library); + } + } } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/gradle/GradleContentRoot.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/gradle/GradleContentRoot.java index 66aeca75faaf..87056cee830a 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/model/gradle/GradleContentRoot.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/model/gradle/GradleContentRoot.java @@ -99,11 +99,13 @@ public class GradleContentRoot extends AbstractGradleEntity { @Override public String toString() { - StringBuilder buffer = new StringBuilder(); + StringBuilder buffer = new StringBuilder("content root:"); for (Map.Entry> entry : myData.entrySet()) { - buffer.append(entry.getKey().toString().toLowerCase()).append(": ").append(entry.getValue()).append("; "); + buffer.append(entry.getKey().toString().toLowerCase()).append("=").append(entry.getValue()).append("|"); + } + if (!myData.isEmpty()) { + buffer.setLength(buffer.length() - 1); } - buffer.setLength(buffer.length() - 2); return buffer.toString(); } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesDetector.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesDetector.java index d6a4010eb9b3..b948571593d8 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesDetector.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesDetector.java @@ -52,7 +52,7 @@ public class GradleProjectStructureChangesDetector extends AbstractProjectCompon @Override public void onImportEnd(@NotNull Object entity) { - myImportCounter.incrementAndGet(); + myImportCounter.decrementAndGet(); } }); } @@ -65,7 +65,7 @@ public class GradleProjectStructureChangesDetector extends AbstractProjectCompon @Override public void rootsChanged(ModuleRootEvent event) { - if (myImportCounter.incrementAndGet() <= 0) { + if (myImportCounter.get() <= 0) { scheduleUpdate(); } } diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java index 149081873205..eff339847cd4 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesPanel.java @@ -65,6 +65,7 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel { protected JComponent buildContent() { JPanel result = new JPanel(new GridBagLayout()); myTreeModel = new GradleProjectStructureTreeModel(getProject(), myContext); + myTreeModel.processCurrentChanges(myContext.getChangesModel().getChanges()); myTree = new Tree(myTreeModel); applyInitialAppearance(myTree, (DefaultMutableTreeNode)myTreeModel.getRoot()); diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNodeComparator.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNodeComparator.java index ba275db55101..5b174cca344c 100644 --- a/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNodeComparator.java +++ b/plugins/gradle/src/org/jetbrains/plugins/gradle/ui/GradleProjectStructureNodeComparator.java @@ -132,7 +132,7 @@ public class GradleProjectStructureNodeComparator implements Comparator a[0].compareTo(b[0]) }.collect { it[1] } - assertEquals(expectedEntities, myHelper.deriveEntitiesToImport(nodes)) + def actual = myHelper.deriveEntitiesToImport(nodes) + if (expectedEntities == actual) { + return + } + fail("""\ +Mismatched 'import nodes with dependencies'. + Initial: ${out -> nodes.each { out << "\n * $it"}} + Expected ordered graph: ${out -> expectedEntities.eachWithIndex { val, i -> out << "\n $i) $val"}} + Actual ordered grapth: ${out -> actual.eachWithIndex { val, i -> out << "\n $i) $val"}} +""") } private List collectNodes(TreeNode node, initial, holder = []) { diff --git a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesModelTest.groovy b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesModelTest.groovy index ded1d7efe92f..b204a65226d5 100644 --- a/plugins/gradle/testSources/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesModelTest.groovy +++ b/plugins/gradle/testSources/org/jetbrains/plugins/gradle/sync/GradleProjectStructureChangesModelTest.groovy @@ -599,4 +599,70 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest { "content-root:3"() } } } } + + @Test + public void "module removal at intellij"() { + Closure initial = { + project { + module { + contentRoot('1') + dependencies { + library('lib1') + } } } } + init(gradle: initial, intellij: initial) + checkChanges { } + checkTree { + project { + module { + "content-root"() + dependencies { + lib1() + } } } } + + setState(intellij: { project { }}) + def m = gradle.modules.values().flatten().first() + checkChanges { + presence { + module(gradle: m) + contentRoot(gradle: gradle.contentRoots[m]) + libraryDependency(gradle: gradle.libraryDependencies[m]) + } } + checkTree { + project { + module('gradle') { + "content-root"('gradle') + dependencies { + lib1('gradle') + } } } } + } + + @Test + public void "content root is correctly highlighted after importing gradle local module"() { + Closure completeProject = { + project { + module { + contentRoot('1') + } } } + init(gradle: completeProject, intellij: { project { }}) + def m = gradle.modules.values().flatten().first() + checkChanges { + presence { + module(gradle: m) + contentRoot(gradle: gradle.contentRoots[m]) + } } + checkTree { + project { + module('gradle') { + "content-root"('gradle') + } } } + + // Import the whole module. + setState(gradle: completeProject, intellij: completeProject) + checkChanges { } + checkTree { + project { + module() { + "content-root"() + } } } + } }