IDEA-76142: Gradle support - cannot update IDEA projects once one of build.gradle files changes

1. 'Sync project structure' tree nodes sorting algorithm is corrected in order to always keep gradle-local entities on top;
2. Corresponding tests are corrected;
3. 'Conflict gradle-local' entities are highlighted accordingly after the import;
This commit is contained in:
Denis.Zhdanov
2012-02-21 11:06:29 +04:00
parent 72d28ee49d
commit 60e29df111
6 changed files with 103 additions and 21 deletions
@@ -15,8 +15,7 @@ public abstract class GradleAbstractDependencyStructureChangesCalculator<G exten
implements GradleStructureChangesCalculator<G, I>
{
@Override
public void calculate(@NotNull G gradleEntity, @NotNull I intellijEntity, @NotNull GradleChangesCalculationContext context)
{
public void calculate(@NotNull G gradleEntity, @NotNull I intellijEntity, @NotNull GradleChangesCalculationContext context) {
// TODO den process common dependency properties here.
doCalculate(gradleEntity, intellijEntity, context);
}
@@ -49,8 +49,8 @@ public class GradleProjectStructureChangesPanel extends GradleToolWindowPanel {
UIUtil.invokeLaterIfNeeded(new Runnable() {
@Override
public void run() {
myTreeModel.update(currentChanges);
myTreeModel.processObsoleteChanges(ContainerUtil.subtract(oldChanges, currentChanges));
myTreeModel.processCurrentChanges(currentChanges);
}
});
}
@@ -160,7 +160,7 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
*
* @param changes collections that contains all changes between the current gradle and intellij project structures
*/
public void update(@NotNull Collection<GradleProjectStructureChange> changes) {
public void processCurrentChanges(@NotNull Collection<GradleProjectStructureChange> changes) {
for (GradleProjectStructureChange change : changes) {
change.invite(myNewChangesDispatcher);
}
@@ -353,7 +353,7 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
moduleNode.removeFromParent();
}
else {
moduleNode.getDescriptor().setAttributes(GradleTextAttributes.GRADLE_NO_CHANGE);
moduleNode.setAttributes(GradleTextAttributes.GRADLE_NO_CHANGE);
}
}
@@ -387,7 +387,6 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
@Override public void visit(@NotNull GradleModulePresenceChange change) { processNewModulePresenceChange(change); }
@Override public void visit(@NotNull GradleLibraryDependencyPresenceChange change) { processNewLibraryDependencyPresenceChange(change); }
@Override public void visit(@NotNull GradleModuleDependencyPresenceChange change) { processNewModuleDependencyPresenceChange(change); }
@Override public void visit(@NotNull GradleMismatchedLibraryPathChange change) { processNewMismatchedLibraryPathChange(change); }
}
@@ -103,17 +103,18 @@ public class GradleProjectStructureNode<T extends GradleEntityId> extends Defaul
* Does nothing if given node is not a child of the current node.
*
* @param child target child node
* @return <code>true</code> if child position was changed; <code>false</code> otherwise
*/
public void correctChildPositionIfNecessary(@NotNull GradleProjectStructureNode<?> child) {
public boolean correctChildPositionIfNecessary(@NotNull GradleProjectStructureNode<?> child) {
int currentPosition = -1;
int desiredPosition = getChildCount();
int desiredPosition = -1;
for (int i = 0; i < getChildCount(); i++) {
GradleProjectStructureNode<?> node = getChildAt(i);
if (node == child) {
currentPosition = i;
continue;
}
if (NODE_COMPARATOR.compare(child, node) <= 0) {
if (desiredPosition < 0 && NODE_COMPARATOR.compare(child, node) <= 0) {
desiredPosition = i;
if (currentPosition >= 0) {
break;
@@ -122,16 +123,20 @@ public class GradleProjectStructureNode<T extends GradleEntityId> extends Defaul
}
if (currentPosition < 0) {
// Given node is not a child of the current node.
return;
return false;
}
if (desiredPosition < 0) {
desiredPosition = getChildCount();
}
if (currentPosition < desiredPosition) {
desiredPosition--;
}
if (currentPosition == desiredPosition) {
return;
return false;
}
remove(currentPosition);
insert(child, desiredPosition);
return true;
}
/**
@@ -231,7 +236,15 @@ public class GradleProjectStructureNode<T extends GradleEntityId> extends Defaul
public void setAttributes(@NotNull TextAttributesKey key) {
myDescriptor.setAttributes(key);
onNodeChanged(this);
final GradleProjectStructureNode<?> parent = getParent();
if (parent == null) {
onNodeChanged(this);
return;
}
boolean positionChanged = parent.correctChildPositionIfNecessary(this);
if (!positionChanged) {
onNodeChanged(this);
}
}
public void addListener(@NotNull Listener listener) {
@@ -34,7 +34,10 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
module {
dependencies {
library("lib1")
} } } }
} } } },
changesSorter: { a, b ->
b.gradleEntity.dependencyName.compareTo(a.gradleEntity.dependencyName)
}
)
// Check that the initial projects state is correctly parsed.
@@ -214,12 +217,13 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
} }
checkTree {
project {
module1()
module2('gradle') {
dependencies {
lib1('gradle')
lib2('gradle')
} } } }
} }
module1()
} }
}
@Test
@@ -241,8 +245,8 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
} }
checkTree {
project {
module1()
module2('gradle')
module1()
} }
// Emulate import gradle module to intellij.
@@ -294,13 +298,13 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
} }
checkTree {
project {
module1() {
dependencies {
lib1('conflict')
} }
module2('gradle') {
dependencies {
lib1('gradle') // This is the point of the test. We don't expect to see 'conflict' here.
} }
module1() {
dependencies {
lib1('conflict')
} } } }
}
@@ -480,4 +484,71 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
module2('intellij')
} } } }
}
@Test
public void "mismatched library path is highlighted after importing local library dependency"() {
init(
gradle: {
project {
module('module1') {
dependencies {
library('lib1', bin: ['1'])
} }
module('module2') {
dependencies {
library('lib1')
} } } },
intellij: {
project {
module('module1') {
dependencies {
library('lib1', bin: ['2'])
} } } }
)
checkChanges {
presence {
module(gradle: gradle.modules['module2'])
libraryDependency(gradle: gradle.libraryDependencies[gradle.modules['module2']])
}
libraryConflict(entity: intellij.libraries['lib1']) {
binaryPath(gradle: '1', intellij: ['2'])
} }
checkTree {
project {
module2('gradle') {
dependencies {
lib1('gradle')
} }
module1 {
dependencies {
lib1('conflict')
} } } }
// Emulate importing missing module and library dependencies. Expecting to see the newly imported library dependency node
// highlighted as 'conflict' now.
setState(intellij: {
project {
module('module1') {
dependencies {
library('lib1', bin: ['2'])
} }
module('module2') {
dependencies {
library('lib1')
} } } })
checkChanges {
libraryConflict(entity: intellij.libraries['lib1']) {
binaryPath(gradle: '1', intellij: ['2'])
} }
checkTree {
project {
module1 {
dependencies {
lib1('conflict')
} }
module2() {
dependencies {
lib1('conflict')
} } } }
}
}
@@ -59,8 +59,8 @@ public abstract class AbstractGradleTest {
protected def init(map = [:]) {
treeModel = container.getComponentInstance(GradleProjectStructureTreeModel) as GradleProjectStructureTreeModel
changesModel.addListener({ old, current ->
treeModel.update(sortChanges(current))
treeModel.processObsoleteChanges(sortChanges(ContainerUtil.subtract(old, current)));
treeModel.processCurrentChanges(sortChanges(current))
} as GradleProjectStructureChangeListener)
setState(map, false)
treeModel.rebuild()