mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-76142: Gradle support - cannot update IDEA projects once one of build.gradle files changes
1. Module content root is really imported now; 2. Module content root is imported as a part of the module import now; 3. Unnecessary gradle project refresh is not triggered on 'import from gradle' now;
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
+55
-3
@@ -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<GradleContentRoot> contentRoots, @NotNull Module module) {
|
||||
// TODO den implement
|
||||
@SuppressWarnings("MethodMayBeStatic")
|
||||
public void importContentRoots(@NotNull final Iterable<GradleContentRoot> contentRoots, @NotNull final Module module) {
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
doImportContentRoots(contentRoots, module);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static void doImportContentRoots(@NotNull final Iterable<GradleContentRoot> 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;
|
||||
}
|
||||
}
|
||||
+22
-8
@@ -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<GradleModule> modules = new HashSet<GradleModule>();
|
||||
public final Set<GradleLibrary> libraries = new HashSet<GradleLibrary>();
|
||||
public final Set<GradleDependency> dependencies = new HashSet<GradleDependency>();
|
||||
public final CollectingVisitor visitor = new CollectingVisitor(this);
|
||||
public final Set<GradleModule> modules = new HashSet<GradleModule>();
|
||||
public final Set<GradleContentRoot> contentRoots = new HashSet<GradleContentRoot>();
|
||||
public final Set<GradleLibrary> libraries = new HashSet<GradleLibrary>();
|
||||
public final Set<GradleDependency> dependencies = new HashSet<GradleDependency>();
|
||||
public final CollectingVisitor visitor = new CollectingVisitor(this);
|
||||
|
||||
public boolean recursive;
|
||||
|
||||
@@ -243,6 +259,7 @@ public class GradleLocalNodeImportHelper {
|
||||
public List<GradleEntity> getAll() {
|
||||
List<GradleEntity> result = new ArrayList<GradleEntity>();
|
||||
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); }
|
||||
|
||||
+11
-2
@@ -366,12 +366,16 @@ public class GradleModulesImporter {
|
||||
|
||||
model = projectLibraryTable.getModifiableModel();
|
||||
List<ModifiableRootModel> modelsToCommit = new ArrayList<ModifiableRootModel>();
|
||||
Map<GradleLibrary, Library> libraryMappings = registerProjectLibraries(gradleProject, model);
|
||||
final GradleProjectEntityImportListener publisher
|
||||
= intellijProject.getMessageBus().syncPublisher(GradleProjectEntityImportListener.TOPIC);
|
||||
try {
|
||||
Map<GradleLibrary, Library> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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<SourceType, Collection<String>> 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();
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -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());
|
||||
|
||||
|
||||
+3
-7
@@ -132,7 +132,7 @@ public class GradleProjectStructureNodeComparator implements Comparator<GradlePr
|
||||
}
|
||||
i++;
|
||||
}
|
||||
result.set(UNKNOWN_WEIGHT);
|
||||
result.set(CONTENT_ROOT_WEIGHT);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -146,12 +146,8 @@ public class GradleProjectStructureNodeComparator implements Comparator<GradlePr
|
||||
}
|
||||
});
|
||||
}
|
||||
try {
|
||||
return result.get();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
final Integer i = result.get();
|
||||
return i == null ? UNKNOWN_WEIGHT : i;
|
||||
}
|
||||
|
||||
private int getWeight(@NotNull Module module, @NotNull Object entry) {
|
||||
|
||||
+21
-3
@@ -8,7 +8,7 @@ import org.picocontainer.MutablePicoContainer
|
||||
|
||||
import javax.swing.tree.TreeNode
|
||||
|
||||
import static org.junit.Assert.assertEquals
|
||||
import static org.junit.Assert.fail
|
||||
|
||||
/**
|
||||
* @author Denis Zhdanov
|
||||
@@ -28,7 +28,7 @@ public class GradleLocalNodeImportHelperTest extends AbstractGradleTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void libraryDependencyToModule() {
|
||||
public void "library dependency causes module and library to be transitively imported as well"() {
|
||||
doTest {
|
||||
project {
|
||||
module('module1', transitive: true, order: 0) { // Mark that the module should be imported
|
||||
@@ -41,6 +41,15 @@ public class GradleLocalNodeImportHelperTest extends AbstractGradleTest {
|
||||
} }
|
||||
}
|
||||
|
||||
@Test
|
||||
public void "module import covers content root"() {
|
||||
doTest {
|
||||
project {
|
||||
module('module1', initial: true, order: 0) {
|
||||
contentRoot('1', transitive: true, order: 1)
|
||||
} } }
|
||||
}
|
||||
|
||||
private def doTest(Closure c) {
|
||||
myHelper = container.getComponentInstance(GradleLocalNodeImportHelper)
|
||||
def compositeBuilder = new CompositeProjectBuilder(gradleBuilder: gradle, intellijBuilder: intellij)
|
||||
@@ -50,7 +59,16 @@ public class GradleLocalNodeImportHelperTest extends AbstractGradleTest {
|
||||
myHelper
|
||||
def nodes = collectNodes(treeModel.root as TreeNode, compositeBuilder.initial)
|
||||
def expectedEntities = compositeBuilder.expected.sort{ a, b -> 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 = []) {
|
||||
|
||||
+66
@@ -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"()
|
||||
} } }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user