IDEA-97472 Gradle: Provide jar-level library management facilities

This commit is contained in:
Denis.Zhdanov
2012-12-13 18:11:48 +04:00
parent f5fae5391a
commit 39f4d2b0b2
37 changed files with 954 additions and 459 deletions
@@ -34,6 +34,7 @@ gradle.import.structure.settings.label.scope=Scope:
gradle.import.structure.settings.label.root.source=Source roots:
gradle.import.structure.settings.label.root.test=Test roots:
gradle.import.structure.settings.label.root.excluded=Excluded roots:
gradle.import.structure.settings.label.jar.path=Path:
gradle.import.structure.settings.label.library.path.binary=Binary paths
gradle.import.structure.settings.label.library.path.source=Source paths
gradle.import.structure.settings.label.library.path.doc=Doc paths
@@ -65,6 +66,7 @@ gradle.sync.change.type.confirmed=Confirmed settings diff
gradle.sync.change.entity.type.module=module
gradle.sync.change.entity.type.module.dependency=module dependency
gradle.sync.change.entity.type.library.dependency=library dependency
gradle.sync.change.entity.type.jar=jar
gradle.sync.change.dependency.scope=scope change for {0}
gradle.sync.change.dependency.exported='exported' value change for {0}
gradle.sync.change.library.path=library ''{0}'' binary path
+1 -1
View File
@@ -48,6 +48,7 @@
<!--Import services-->
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.manage.GradleModuleManager"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.manage.GradleLibraryManager"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.manage.GradleJarManager"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.manage.GradleContentRootManager"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.manage.GradleDependencyManager"/>
@@ -63,7 +64,6 @@
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.sync.conflict.GradleConflictControlFactory"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.sync.conflict.GradleProjectConflictControlFactory"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.sync.conflict.GradleCommonDependencyConflictControlFactory"/>
<applicationService serviceImplementation="org.jetbrains.plugins.gradle.sync.conflict.GradleLibraryDependencyConflictControlFactory"/>
<projectService serviceImplementation="org.jetbrains.plugins.gradle.config.GradleSettings"/>
<projectService serviceImplementation="org.jetbrains.plugins.gradle.config.GradleLocalSettings"/>
@@ -10,6 +10,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.diff.contentroot.GradleContentRootPresenceChange;
import org.jetbrains.plugins.gradle.diff.dependency.GradleLibraryDependencyPresenceChange;
import org.jetbrains.plugins.gradle.diff.dependency.GradleModuleDependencyPresenceChange;
import org.jetbrains.plugins.gradle.diff.library.GradleJarPresenceChange;
import org.jetbrains.plugins.gradle.diff.module.GradleModulePresenceChange;
import org.jetbrains.plugins.gradle.model.gradle.*;
import org.jetbrains.plugins.gradle.model.intellij.IntellijEntityVisitor;
@@ -68,6 +69,11 @@ public class GradleDiffUtil {
// Don't show library nodes.
}
@Override
public void visit(@NotNull GradleJar jar) {
context.register(new GradleJarPresenceChange(jar.getId(), null));
}
@Override
public void visit(@NotNull GradleModuleDependency dependency) {
context.register(new GradleModuleDependencyPresenceChange(dependency, null));
@@ -17,11 +17,8 @@ package org.jetbrains.plugins.gradle.diff;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.diff.contentroot.GradleContentRootPresenceChange;
import org.jetbrains.plugins.gradle.diff.dependency.GradleDependencyExportedChange;
import org.jetbrains.plugins.gradle.diff.dependency.GradleDependencyScopeChange;
import org.jetbrains.plugins.gradle.diff.dependency.GradleLibraryDependencyPresenceChange;
import org.jetbrains.plugins.gradle.diff.dependency.GradleModuleDependencyPresenceChange;
import org.jetbrains.plugins.gradle.diff.library.GradleMismatchedLibraryPathChange;
import org.jetbrains.plugins.gradle.diff.dependency.*;
import org.jetbrains.plugins.gradle.diff.library.GradleJarPresenceChange;
import org.jetbrains.plugins.gradle.diff.module.GradleModulePresenceChange;
import org.jetbrains.plugins.gradle.diff.project.GradleLanguageLevelChange;
import org.jetbrains.plugins.gradle.diff.project.GradleProjectRenameChange;
@@ -38,8 +35,8 @@ public interface GradleProjectStructureChangeVisitor {
void visit(@NotNull GradleModulePresenceChange change);
void visit(@NotNull GradleContentRootPresenceChange change);
void visit(@NotNull GradleLibraryDependencyPresenceChange change);
void visit(@NotNull GradleJarPresenceChange change);
void visit(@NotNull GradleModuleDependencyPresenceChange change);
void visit(@NotNull GradleMismatchedLibraryPathChange change);
void visit(@NotNull GradleDependencyScopeChange change);
void visit(@NotNull GradleDependencyExportedChange change);
}
@@ -2,11 +2,8 @@ package org.jetbrains.plugins.gradle.diff;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.diff.contentroot.GradleContentRootPresenceChange;
import org.jetbrains.plugins.gradle.diff.dependency.GradleDependencyExportedChange;
import org.jetbrains.plugins.gradle.diff.dependency.GradleDependencyScopeChange;
import org.jetbrains.plugins.gradle.diff.dependency.GradleLibraryDependencyPresenceChange;
import org.jetbrains.plugins.gradle.diff.dependency.GradleModuleDependencyPresenceChange;
import org.jetbrains.plugins.gradle.diff.library.GradleMismatchedLibraryPathChange;
import org.jetbrains.plugins.gradle.diff.dependency.*;
import org.jetbrains.plugins.gradle.diff.library.GradleJarPresenceChange;
import org.jetbrains.plugins.gradle.diff.module.GradleModulePresenceChange;
import org.jetbrains.plugins.gradle.diff.project.GradleLanguageLevelChange;
import org.jetbrains.plugins.gradle.diff.project.GradleProjectRenameChange;
@@ -37,11 +34,11 @@ public abstract class GradleProjectStructureChangeVisitorAdapter implements Grad
}
@Override
public void visit(@NotNull GradleModuleDependencyPresenceChange change) {
public void visit(@NotNull GradleJarPresenceChange change) {
}
@Override
public void visit(@NotNull GradleMismatchedLibraryPathChange change) {
public void visit(@NotNull GradleModuleDependencyPresenceChange change) {
}
@Override
@@ -0,0 +1,26 @@
package org.jetbrains.plugins.gradle.diff.library;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.diff.GradleAbstractEntityPresenceChange;
import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChangeVisitor;
import org.jetbrains.plugins.gradle.model.id.GradleJarId;
import org.jetbrains.plugins.gradle.util.GradleBundle;
/**
* @author Denis Zhdanov
* @since 12/11/12 7:52 PM
*/
public class GradleJarPresenceChange extends GradleAbstractEntityPresenceChange<GradleJarId> {
public GradleJarPresenceChange(@Nullable GradleJarId gradleEntity,
@Nullable GradleJarId intellijEntity) throws IllegalArgumentException
{
super(GradleBundle.message("gradle.sync.change.entity.type.jar"), gradleEntity, intellijEntity);
}
@Override
public void invite(@NotNull GradleProjectStructureChangeVisitor visitor) {
visitor.visit(this);
}
}
@@ -7,8 +7,11 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.config.PlatformFacade;
import org.jetbrains.plugins.gradle.diff.GradleChangesCalculationContext;
import org.jetbrains.plugins.gradle.diff.GradleStructureChangesCalculator;
import org.jetbrains.plugins.gradle.model.GradleEntityOwner;
import org.jetbrains.plugins.gradle.model.gradle.GradleLibrary;
import org.jetbrains.plugins.gradle.model.gradle.LibraryPathType;
import org.jetbrains.plugins.gradle.model.id.GradleJarId;
import org.jetbrains.plugins.gradle.model.id.GradleLibraryId;
import org.jetbrains.plugins.gradle.util.GradleUtil;
import java.util.HashSet;
@@ -40,8 +43,18 @@ public class GradleLibraryStructureChangesCalculator implements GradleStructureC
}
}
if (!gradleBinaryPaths.equals(intellijBinaryPaths)) {
context.register(new GradleMismatchedLibraryPathChange(intellijEntity, gradleBinaryPaths, intellijBinaryPaths));
if (!gradleBinaryPaths.isEmpty()) {
GradleLibraryId libraryId = new GradleLibraryId(GradleEntityOwner.GRADLE, gradleEntity.getName());
for (String path : gradleBinaryPaths) {
context.register(new GradleJarPresenceChange(new GradleJarId(path, libraryId), null));
}
}
if (!intellijBinaryPaths.isEmpty()) {
GradleLibraryId libraryId = new GradleLibraryId(GradleEntityOwner.INTELLIJ, GradleUtil.getLibraryName(intellijEntity));
for (String path : intellijBinaryPaths) {
context.register(new GradleJarPresenceChange(null, new GradleJarId(path, libraryId)));
}
}
}
@@ -1,34 +0,0 @@
package org.jetbrains.plugins.gradle.diff.library;
import com.intellij.openapi.roots.libraries.Library;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.diff.GradleAbstractConflictingPropertyChange;
import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChangeVisitor;
import org.jetbrains.plugins.gradle.model.id.GradleEntityIdMapper;
import org.jetbrains.plugins.gradle.util.GradleBundle;
import org.jetbrains.plugins.gradle.util.GradleUtil;
import java.util.Set;
/**
* @author Denis Zhdanov
* @since 2/2/12 1:32 PM
*/
public class GradleMismatchedLibraryPathChange extends GradleAbstractConflictingPropertyChange<Set<String>> {
public GradleMismatchedLibraryPathChange(@NotNull Library entity,
@NotNull Set<String> gradleValue,
@NotNull Set<String> intellijValue)
throws IllegalArgumentException
{
super(GradleEntityIdMapper.mapEntityToId(entity),
GradleBundle.message("gradle.sync.change.library.path", GradleUtil.getLibraryName(entity)),
gradleValue,
intellijValue);
}
@Override
public void invite(@NotNull GradleProjectStructureChangeVisitor visitor) {
visitor.visit(this);
}
}
@@ -0,0 +1,173 @@
/*
* Copyright 2000-2012 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 org.jetbrains.plugins.gradle.manage;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTable;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.config.PlatformFacade;
import org.jetbrains.plugins.gradle.model.gradle.GradleJar;
import org.jetbrains.plugins.gradle.model.id.GradleLibraryId;
import org.jetbrains.plugins.gradle.util.GradleLog;
import org.jetbrains.plugins.gradle.util.GradleUtil;
import java.io.File;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* @author Denis Zhdanov
* @since 12/13/12 1:04 PM
*/
public class GradleJarManager {
@NotNull private final PlatformFacade myPlatformFacade;
public GradleJarManager(@NotNull PlatformFacade facade) {
myPlatformFacade = facade;
}
public void importJar(@NotNull final GradleJar jar, @NotNull final Project project) {
GradleUtil.executeProjectChangeAction(project, jar, new Runnable() {
@Override
public void run() {
LibraryTable table = myPlatformFacade.getProjectLibraryTable(project);
Library library = table.getLibraryByName(jar.getLibraryId().getLibraryName());
if (library == null) {
return;
}
Library.ModifiableModel model = library.getModifiableModel();
try {
for (VirtualFile file : model.getFiles(OrderRootType.CLASSES)) {
if (jar.getPath().equals(file.getPath())) {
return;
}
}
VirtualFile virtualFile = LocalFileSystem.getInstance().findFileByIoFile(new File(jar.getPath()));
if (virtualFile == null) {
//GradleLog.LOG.warn(
// String.format("Can't find %s of the library '%s' at path '%s'", entry.getKey(), libraryName, file.getAbsolutePath())
//);
return;
}
if (virtualFile.isDirectory()) {
model.addRoot(virtualFile, OrderRootType.CLASSES);
}
else {
VirtualFile jarRoot = JarFileSystem.getInstance().getJarRootForLocalFile(virtualFile);
if (jarRoot == null) {
GradleLog.LOG.warn(String.format(
"Can't parse contents of the jar file at path '%s' for the library '%s''", jar.getPath(), library.getName()
));
return;
}
model.addRoot(jarRoot, OrderRootType.CLASSES);
}
}
finally {
model.commit();
}
}
});
}
public void removeJars(@NotNull Collection<GradleJar> jars, @NotNull Project project) {
if (jars.isEmpty()) {
return;
}
Map<GradleLibraryId, List<GradleJar>> jarsByLibraries = ContainerUtilRt.newHashMap();
for (GradleJar jar : jars) {
List<GradleJar> list = jarsByLibraries.get(jar.getLibraryId());
if (list == null) {
jarsByLibraries.put(jar.getLibraryId(), list = ContainerUtilRt.newArrayList());
}
list.add(jar);
}
LibraryTable libraryTable = myPlatformFacade.getProjectLibraryTable(project);
for (Map.Entry<GradleLibraryId, List<GradleJar>> entry : jarsByLibraries.entrySet()) {
Library library = libraryTable.getLibraryByName(entry.getKey().getLibraryName());
if (library == null) {
continue;
}
Set<GradleJar> libraryJars = ContainerUtilRt.newHashSet(entry.getValue());
for (GradleJar jar : entry.getValue()) {
boolean valid = false;
for (VirtualFile file : library.getFiles(OrderRootType.CLASSES)) {
if (jar.getPath().equals(GradleUtil.getLocalFileSystemPath(file))) {
valid = true;
break;
}
}
if (!valid) {
libraryJars.remove(jar);
}
}
if (!libraryJars.isEmpty()) {
removeLibraryJars(libraryJars, project);
}
}
}
/**
* Removes given jars from IDE project structure assuming that they belong to the same library.
*
* @param jars jars to remove
* @param project current project
*/
private void removeLibraryJars(@NotNull final Set<GradleJar> jars, @NotNull final Project project) {
GradleUtil.executeProjectChangeAction(project, jars, new Runnable() {
@Override
public void run() {
LibraryTable libraryTable = myPlatformFacade.getProjectLibraryTable(project);
GradleLibraryId libraryId = jars.iterator().next().getLibraryId();
Library library = libraryTable.getLibraryByName(libraryId.getLibraryName());
if (library == null) {
return;
}
Set<String> pathsToRemove = ContainerUtil.map2Set(jars, new Function<GradleJar, String>() {
@Override
public String fun(GradleJar jar) {
return jar.getPath();
}
});
Library.ModifiableModel model = library.getModifiableModel();
try {
for (VirtualFile file : model.getFiles(OrderRootType.CLASSES)) {
if (pathsToRemove.contains(GradleUtil.getLocalFileSystemPath(file))) {
model.removeRoot(file.getUrl(), OrderRootType.CLASSES);
}
}
}
finally {
model.commit();
}
}
});
}
}
@@ -6,6 +6,7 @@ import com.intellij.openapi.roots.ExportableOrderEntry;
import com.intellij.openapi.roots.LibraryOrderEntry;
import com.intellij.openapi.roots.ModuleOrderEntry;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.containers.Stack;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.config.GradleTextAttributes;
@@ -55,6 +56,7 @@ public class GradleLocalNodeManageHelper {
@NotNull private final GradleEntityIdMapper myIdMapper;
@NotNull private final GradleModuleManager myModuleManager;
@NotNull private final GradleLibraryManager myLibraryManager;
@NotNull private final GradleJarManager myJarManager;
@NotNull private final GradleDependencyManager myModuleDependencyManager;
@NotNull private final GradleContentRootManager myContentRootManager;
@@ -62,12 +64,14 @@ public class GradleLocalNodeManageHelper {
@NotNull GradleEntityIdMapper idMapper,
@NotNull GradleModuleManager moduleManager,
@NotNull GradleLibraryManager libraryManager,
@NotNull GradleJarManager jarManager,
@NotNull GradleDependencyManager moduleDependencyManager,
@NotNull GradleContentRootManager contentRootManager)
{
myProjectStructureHelper = projectStructureHelper;
myIdMapper = idMapper;
myModuleManager = moduleManager;
myJarManager = jarManager;
myModuleDependencyManager = moduleDependencyManager;
myLibraryManager = libraryManager;
myContentRootManager = contentRootManager;
@@ -232,6 +236,11 @@ public class GradleLocalNodeManageHelper {
myLibraryManager.importLibrary(library, myProjectStructureHelper.getProject());
}
@Override
public void visit(@NotNull GradleJar jar) {
myJarManager.importJar(jar, myProjectStructureHelper.getProject());
}
@Override
public void visit(@NotNull GradleModuleDependency dependency) {
final Module module = myProjectStructureHelper.findIntellijModule(dependency.getOwnerModule());
@@ -251,11 +260,12 @@ public class GradleLocalNodeManageHelper {
}
public void removeNodes(@NotNull Collection<GradleProjectStructureNode<?>> nodes) {
final List<Library> libraries = new ArrayList<Library>();
final List<Module> modules = new ArrayList<Module>();
final List<ModuleAwareContentRoot> contentRoots = new ArrayList<ModuleAwareContentRoot>();
final List<ExportableOrderEntry> dependencies = new ArrayList<ExportableOrderEntry>();
IntellijEntityVisitor visitor = new IntellijEntityVisitor() {
final List<Library> libraries = ContainerUtilRt.newArrayList();
final List<Module> modules = ContainerUtilRt.newArrayList();
final List<ModuleAwareContentRoot> contentRoots = ContainerUtilRt.newArrayList();
final List<ExportableOrderEntry> dependencies = ContainerUtilRt.newArrayList();
final List<GradleJar> jars = ContainerUtilRt.newArrayList();
IntellijEntityVisitor intellijVisitor = new IntellijEntityVisitor() {
@Override public void visit(@NotNull Project project) { }
@Override public void visit(@NotNull Module module) { modules.add(module); }
@Override public void visit(@NotNull ModuleAwareContentRoot contentRoot) { contentRoots.add(contentRoot); }
@@ -263,6 +273,13 @@ public class GradleLocalNodeManageHelper {
@Override public void visit(@NotNull ModuleOrderEntry moduleDependency) { dependencies.add(moduleDependency); }
@Override public void visit(@NotNull Library library) { libraries.add(library); }
};
GradleEntityVisitor gradleVisitor = new GradleEntityVisitorAdapter() {
@Override
public void visit(@NotNull GradleJar jar) {
jars.add(jar);
}
};
for (GradleProjectStructureNode<?> node : nodes) {
GradleProjectStructureNodeDescriptor<? extends GradleEntityId> descriptor = node.getDescriptor();
@@ -270,11 +287,15 @@ public class GradleLocalNodeManageHelper {
continue;
}
Object entity = myIdMapper.mapIdToEntity(descriptor.getElement());
if (entity != null) {
GradleUtil.dispatch(entity, visitor);
if (entity instanceof GradleEntity) {
((GradleEntity)entity).invite(gradleVisitor);
}
else if (entity != null) {
GradleUtil.dispatch(entity, intellijVisitor);
}
}
myJarManager.removeJars(jars, myProjectStructureHelper.getProject());
myContentRootManager.removeContentRoots(contentRoots);
myModuleDependencyManager.removeDependencies(dependencies);
myModuleManager.removeModules(modules);
@@ -284,10 +305,11 @@ public class GradleLocalNodeManageHelper {
private class Context {
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 Set<GradleModule> modules = ContainerUtilRt.newHashSet();
public final Set<GradleContentRoot> contentRoots = ContainerUtilRt.newHashSet();
public final Set<GradleLibrary> libraries = ContainerUtilRt.newHashSet();
public final Set<GradleJar> jars = ContainerUtilRt.newHashSet();
public final Set<GradleDependency> dependencies = ContainerUtilRt.newHashSet();
public final CollectingVisitor gradleVisitor = new CollectingVisitor(this);
public boolean recursive;
@@ -297,6 +319,7 @@ public class GradleLocalNodeManageHelper {
result.addAll(modules);
result.addAll(contentRoots);
result.addAll(libraries);
result.addAll(jars);
result.addAll(dependencies);
return result;
}
@@ -315,5 +338,6 @@ public class GradleLocalNodeManageHelper {
@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); }
@Override public void visit(@NotNull GradleJar jar) { myContext.jars.add(jar); }
}
}
@@ -24,8 +24,8 @@ public class GradleContentRootSettings implements GradleProjectStructureNodeSett
ROOT_TYPE_TITLES.put(SourceType.EXCLUDED, GradleBundle.message("gradle.import.structure.settings.label.root.excluded"));
assert ROOT_TYPE_TITLES.size() == SourceType.values().length;
}
private final JComponent myComponent;
@NotNull private final JComponent myComponent;
public GradleContentRootSettings(@NotNull GradleContentRoot contentRoot) {
GradleProjectSettingsBuilder builder = new GradleProjectSettingsBuilder();
@@ -33,7 +33,7 @@ public class GradleContentRootSettings implements GradleProjectStructureNodeSett
Collection<String> paths = contentRoot.getPaths(sourceType);
if (paths.isEmpty()) {
continue;
}
}
builder.add(new JLabel(ROOT_TYPE_TITLES.get(sourceType)));
for (String path : paths) {
NamePathComponent component = new NamePathComponent("", " ", "", "", false);
@@ -45,7 +45,7 @@ public class GradleContentRootSettings implements GradleProjectStructureNodeSett
}
myComponent = builder.build();
}
@Override
public boolean validate() {
return true;
@@ -0,0 +1,59 @@
/*
* Copyright 2000-2012 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 org.jetbrains.plugins.gradle.manage.wizard.adjust;
import com.intellij.ide.util.projectWizard.NamePathComponent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.model.gradle.GradleJar;
import org.jetbrains.plugins.gradle.util.GradleBundle;
import javax.swing.*;
/**
* @author Denis Zhdanov
* @since 12/12/12 2:16 PM
*/
public class GradleJarSettings implements GradleProjectStructureNodeSettings {
@NotNull private final JComponent myComponent;
public GradleJarSettings(@NotNull GradleJar jar) {
GradleProjectSettingsBuilder builder = new GradleProjectSettingsBuilder();
builder.add(new JLabel(GradleBundle.message("gradle.import.structure.settings.label.jar.path")));
NamePathComponent component = new NamePathComponent("", " ", "", "", false);
component.setNameComponentVisible(false);
component.setPath(jar.getPath());
component.getPathPanel().setEditable(false);
builder.add(component, GradleProjectSettingsBuilder.InsetSize.SMALL);
myComponent = builder.build();
}
@Override
public boolean validate() {
return true;
}
@Override
public void refresh() {
}
@NotNull
@Override
public JComponent getComponent() {
return myComponent;
}
}
@@ -18,7 +18,7 @@ public class GradleLibraryDependencySettings implements GradleProjectStructureNo
private final JComponent myComponent;
public GradleLibraryDependencySettings(@NotNull GradleLibraryDependency dependency) {
myLibrarySettings = new GradleLibrarySettings(dependency.getTarget());
myLibrarySettings = new GradleLibrarySettings();
GradleProjectSettingsBuilder builder = new GradleProjectSettingsBuilder();
builder.add(myLibrarySettings.getComponent(), GradleProjectSettingsBuilder.InsetSize.NONE);
@@ -1,15 +1,8 @@
package org.jetbrains.plugins.gradle.manage.wizard.adjust;
import com.intellij.ide.util.projectWizard.NamePathComponent;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.plugins.gradle.model.gradle.GradleLibrary;
import org.jetbrains.plugins.gradle.model.gradle.LibraryPathType;
import org.jetbrains.plugins.gradle.util.GradleBundle;
import javax.swing.*;
import java.util.EnumMap;
import java.util.Map;
import java.util.Set;
/**
* @author Denis Zhdanov
@@ -17,51 +10,19 @@ import java.util.Set;
*/
public class GradleLibrarySettings implements GradleProjectStructureNodeSettings {
private static final Map<LibraryPathType, String> PATH_TITLES = new EnumMap<LibraryPathType, String>(LibraryPathType.class);
static {
PATH_TITLES.put(LibraryPathType.BINARY, GradleBundle.message("gradle.import.structure.settings.label.library.path.binary"));
PATH_TITLES.put(LibraryPathType.SOURCE, GradleBundle.message("gradle.import.structure.settings.label.library.path.source"));
PATH_TITLES.put(LibraryPathType.DOC, GradleBundle.message("gradle.import.structure.settings.label.library.path.doc"));
assert PATH_TITLES.size() == LibraryPathType.values().length;
private final JComponent myComponent;
public GradleLibrarySettings() {
myComponent = new JPanel();
}
private final GradleLibrary myLibrary;
private final JComponent myComponent;
private final JTextField myNameControl;
public GradleLibrarySettings(@NotNull GradleLibrary library) {
myLibrary = library;
GradleProjectSettingsBuilder builder = new GradleProjectSettingsBuilder();
myNameControl = GradleAdjustImportSettingsUtil.configureNameControl(builder, library);
setupLibraryPaths(builder);
myComponent = builder.build();
}
private void setupLibraryPaths(@NotNull GradleProjectSettingsBuilder builder) {
for (LibraryPathType pathType : LibraryPathType.values()) {
Set<String> paths = myLibrary.getPaths(pathType);
if (paths.isEmpty()) {
continue;
}
builder.add(new JLabel(PATH_TITLES.get(pathType)));
for (String path : paths) {
NamePathComponent component = new NamePathComponent("", " ", "", "", false);
component.setNameComponentVisible(false);
component.setPath(path);
component.getPathPanel().setEditable(false);
builder.add(component, GradleProjectSettingsBuilder.InsetSize.SMALL);
}
}
}
@Override
public boolean validate() {
return GradleAdjustImportSettingsUtil.validate(myLibrary, myNameControl);
return true;
}
@Override
public void refresh() {
myNameControl.setText(myLibrary.getName());
}
@NotNull
@@ -55,6 +55,11 @@ public class GradleProjectStructureFactory {
text.set(library.getName());
}
@Override
public void visit(@NotNull GradleJar jar) {
text.set(GradleUtil.extractNameFromPath(jar.getPath()));
}
@Override
public void visit(@NotNull GradleModuleDependency dependency) {
visit(dependency.getTarget());
@@ -95,8 +100,12 @@ public class GradleProjectStructureFactory {
@Override
public void visit(@NotNull GradleLibrary library) {
setupController(library, treeModel, treeNodes);
result.set(new GradleLibrarySettings(library));
result.set(new GradleLibrarySettings());
}
@Override
public void visit(@NotNull GradleJar jar) {
result.set(new GradleJarSettings(jar));
}
@Override
@@ -12,7 +12,8 @@ import javax.swing.*;
*/
public enum GradleEntityType {
PROJECT(GradleIcons.PROJECT_ICON), MODULE(AllIcons.Nodes.Module), MODULE_DEPENDENCY(AllIcons.Nodes.Module),
LIBRARY(AllIcons.Nodes.PpLib), LIBRARY_DEPENDENCY(AllIcons.Nodes.PpLib), CONTENT_ROOT(null), SYNTHETIC(null);
LIBRARY(AllIcons.Nodes.PpLib), LIBRARY_DEPENDENCY(AllIcons.Nodes.PpLib), CONTENT_ROOT(null), SYNTHETIC(null),
JAR(AllIcons.FileTypes.Archive);
@Nullable private final Icon myIcon;
@@ -12,6 +12,7 @@ public interface GradleEntityVisitor {
void visit(@NotNull GradleModule module);
void visit(@NotNull GradleContentRoot contentRoot);
void visit(@NotNull GradleLibrary library);
void visit(@NotNull GradleJar jar);
void visit(@NotNull GradleModuleDependency dependency);
void visit(@NotNull GradleLibraryDependency dependency);
}
@@ -23,6 +23,10 @@ public abstract class GradleEntityVisitorAdapter implements GradleEntityVisitor
public void visit(@NotNull GradleLibrary library) {
}
@Override
public void visit(@NotNull GradleJar jar) {
}
@Override
public void visit(@NotNull GradleModuleDependency dependency) {
}
@@ -0,0 +1,99 @@
package org.jetbrains.plugins.gradle.model.gradle;
import com.intellij.openapi.roots.libraries.Library;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.model.GradleEntityOwner;
import org.jetbrains.plugins.gradle.model.id.GradleJarId;
import org.jetbrains.plugins.gradle.model.id.GradleLibraryId;
import org.jetbrains.plugins.gradle.util.GradleUtil;
/**
* @author Denis Zhdanov
* @since 12/11/12 3:07 PM
*/
public class GradleJar extends AbstractNamedGradleEntity {
@NotNull private final String myPath;
@Nullable private final Library myIntellijLibrary;
@Nullable private final GradleLibrary myGradleLibrary;
public GradleJar(@NotNull String path, @Nullable Library intellijLibrary, @Nullable GradleLibrary gradleLibrary) {
super(GradleUtil.extractNameFromPath(path));
assert intellijLibrary == null ^ gradleLibrary == null;
myPath = path;
myIntellijLibrary = intellijLibrary;
myGradleLibrary = gradleLibrary;
}
@NotNull
public String getPath() {
return myPath;
}
@NotNull
public GradleJarId getId() {
return new GradleJarId(myPath, getLibraryId());
}
@NotNull
public GradleLibraryId getLibraryId() {
if (myIntellijLibrary != null) {
return new GradleLibraryId(GradleEntityOwner.INTELLIJ, GradleUtil.getLibraryName(myIntellijLibrary));
}
assert myGradleLibrary != null;
return new GradleLibraryId(GradleEntityOwner.GRADLE, myGradleLibrary.getName());
}
@Override
public void invite(@NotNull GradleEntityVisitor visitor) {
visitor.visit(this);
}
@NotNull
@Override
public GradleJar clone(@NotNull GradleEntityCloneContext context) {
return new GradleJar(myPath, myIntellijLibrary, myGradleLibrary == null ? null : context.getLibrary(myGradleLibrary));
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + myPath.hashCode();
result = 31 * result + (myIntellijLibrary != null ? myIntellijLibrary.hashCode() : 0);
result = 31 * result + (myGradleLibrary != null ? myGradleLibrary.hashCode() : 0);
return result;
}
@Override
public boolean equals(Object o) {
if (!super.equals(o)) return false;
GradleJar that = (GradleJar)o;
if (!myPath.equals(that.myPath)) return false;
if (myGradleLibrary != null ? !myGradleLibrary.equals(that.myGradleLibrary) : that.myGradleLibrary != null) return false;
if (myIntellijLibrary == null && that.myIntellijLibrary != null) {
return false;
}
else if (myIntellijLibrary != null) {
if (that.myIntellijLibrary == null) {
return false;
}
else if (!GradleUtil.getLibraryName(myIntellijLibrary).equals(GradleUtil.getLibraryName(that.myIntellijLibrary))) {
return false;
}
}
return true;
}
@SuppressWarnings("ConstantConditions")
@Override
public String toString() {
return String.format(
"jar at '%s'. Belongs to library '%s'",
myPath, myIntellijLibrary == null ? myGradleLibrary.getName() : GradleUtil.getLibraryName(myIntellijLibrary)
);
}
}
@@ -75,6 +75,11 @@ public class GradleEntityIdMapper {
public void visit(@NotNull GradleLibrary library) {
result.set(new GradleLibraryId(GradleEntityOwner.GRADLE, library.getName()));
}
@Override
public void visit(@NotNull GradleJar jar) {
result.set(jar.getId());
}
});
}
@@ -0,0 +1,70 @@
package org.jetbrains.plugins.gradle.model.id;
import com.intellij.openapi.roots.libraries.Library;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.model.GradleEntityType;
import org.jetbrains.plugins.gradle.model.gradle.GradleJar;
import org.jetbrains.plugins.gradle.model.gradle.GradleLibrary;
import org.jetbrains.plugins.gradle.util.GradleProjectStructureContext;
/**
* @author Denis Zhdanov
* @since 12/11/12 3:04 PM
*/
public class GradleJarId extends GradleAbstractEntityId {
@NotNull private final String myPath;
@NotNull private final GradleLibraryId myLibraryId;
public GradleJarId(@NotNull String path, @NotNull GradleLibraryId libraryId) {
super(GradleEntityType.JAR, libraryId.getOwner());
myPath = path;
myLibraryId = libraryId;
}
@NotNull
public String getPath() {
return myPath;
}
@NotNull
public GradleLibraryId getLibraryId() {
return myLibraryId;
}
@Nullable
@Override
public Object mapToEntity(@NotNull GradleProjectStructureContext context) {
Library intellijLibrary = context.getProjectStructureHelper().findIntellijLibrary(myLibraryId.getLibraryName(), myPath);
if (intellijLibrary != null) {
return new GradleJar(myPath, intellijLibrary, null);
}
GradleLibrary gradleLibrary = context.getProjectStructureHelper().findGradleLibrary(myLibraryId.getLibraryName(), myPath);
if (gradleLibrary != null) {
return new GradleJar(myPath, null, gradleLibrary);
}
return null;
}
@Override
public int hashCode() {
int result = super.hashCode();
result = 31 * result + myPath.hashCode();
return result;
}
@Override
public boolean equals(Object o) {
if (!super.equals(o)) return false;
GradleJarId that = (GradleJarId)o;
return myPath.equals(that.myPath);
}
@Override
public String toString() {
return String.format("jar '%s'", myPath);
}
}
@@ -17,7 +17,12 @@ public class GradleLibraryId extends GradleAbstractEntityId {
super(GradleEntityType.LIBRARY, owner);
myLibraryName = libraryName;
}
@NotNull
public String getLibraryName() {
return myLibraryName;
}
@Override
public Object mapToEntity(@NotNull GradleProjectStructureContext context) {
switch (getOwner()) {
@@ -12,9 +12,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.config.PlatformFacade;
import org.jetbrains.plugins.gradle.model.gradle.*;
import org.jetbrains.plugins.gradle.model.id.GradleContentRootId;
import org.jetbrains.plugins.gradle.model.id.GradleLibraryDependencyId;
import org.jetbrains.plugins.gradle.model.id.GradleModuleDependencyId;
import org.jetbrains.plugins.gradle.model.id.*;
import org.jetbrains.plugins.gradle.model.intellij.ModuleAwareContentRoot;
import org.jetbrains.plugins.gradle.util.GradleUtil;
@@ -148,6 +146,20 @@ public class GradleProjectStructureHelper extends AbstractProjectComponent {
}
return null;
}
@Nullable
public Library findIntellijLibrary(@NotNull String libraryName, @NotNull String jarPath) {
Library library = findIntellijLibrary(libraryName);
if (library == null) {
return null;
}
for (VirtualFile file : library.getFiles(OrderRootType.CLASSES)) {
if (jarPath.equals(GradleUtil.getLocalFileSystemPath(file))) {
return library;
}
}
return null;
}
@Nullable
public LibraryOrderEntry findIntellijLibraryDependency(@NotNull final String moduleName, @NotNull final String libraryName) {
@@ -189,6 +201,11 @@ public class GradleProjectStructureHelper extends AbstractProjectComponent {
return null;
}
@Nullable
public GradleLibrary findGradleLibrary(@NotNull final GradleLibraryId id) {
return findGradleLibrary(id.getLibraryName());
}
@Nullable
public GradleLibrary findGradleLibrary(@NotNull final String libraryName) {
final GradleProject project = myModel.getGradleProject();
@@ -202,6 +219,15 @@ public class GradleProjectStructureHelper extends AbstractProjectComponent {
}
return null;
}
@Nullable
public GradleLibrary findGradleLibrary(@NotNull String libraryName, @NotNull String jarPath) {
GradleLibrary library = findGradleLibrary(libraryName);
if (library == null) {
return null;
}
return library.getPaths(LibraryPathType.BINARY).contains(jarPath) ? library : null;
}
@Nullable
public GradleLibraryDependency findGradleLibraryDependency(@NotNull final String moduleName, @NotNull final String libraryName) {
@@ -294,4 +320,18 @@ public class GradleProjectStructureHelper extends AbstractProjectComponent {
}
return null;
}
@Nullable
public GradleJar findIntellijJar(@NotNull GradleJarId jarId) {
Library library = findIntellijLibrary(jarId.getLibraryId().getLibraryName());
if (library == null) {
return null;
}
for (VirtualFile file : library.getFiles(OrderRootType.CLASSES)) {
if (jarId.getPath().equals(GradleUtil.getLocalFileSystemPath(file))) {
return new GradleJar(jarId.getPath(), library, null);
}
}
return null;
}
}
@@ -4,8 +4,12 @@ import com.intellij.openapi.editor.colors.TextAttributesKey;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.Function;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
import com.intellij.util.containers.hash.HashMap;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
@@ -22,12 +26,14 @@ import org.jetbrains.plugins.gradle.diff.dependency.GradleDependencyExportedChan
import org.jetbrains.plugins.gradle.diff.dependency.GradleDependencyScopeChange;
import org.jetbrains.plugins.gradle.diff.dependency.GradleLibraryDependencyPresenceChange;
import org.jetbrains.plugins.gradle.diff.dependency.GradleModuleDependencyPresenceChange;
import org.jetbrains.plugins.gradle.diff.library.GradleMismatchedLibraryPathChange;
import org.jetbrains.plugins.gradle.diff.library.GradleJarPresenceChange;
import org.jetbrains.plugins.gradle.diff.module.GradleModulePresenceChange;
import org.jetbrains.plugins.gradle.diff.project.GradleLanguageLevelChange;
import org.jetbrains.plugins.gradle.diff.project.GradleProjectRenameChange;
import org.jetbrains.plugins.gradle.model.GradleEntityOwner;
import org.jetbrains.plugins.gradle.model.gradle.GradleLibrary;
import org.jetbrains.plugins.gradle.model.gradle.GradleModule;
import org.jetbrains.plugins.gradle.model.gradle.LibraryPathType;
import org.jetbrains.plugins.gradle.model.id.*;
import org.jetbrains.plugins.gradle.model.intellij.ModuleAwareContentRoot;
import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode;
@@ -54,19 +60,7 @@ import java.util.*;
public class GradleProjectStructureTreeModel extends DefaultTreeModel {
private static final Function<GradleEntityId, GradleEntityId> SELF_MAPPER = new Function.Self<GradleEntityId, GradleEntityId>();
private static final Function<GradleEntityId, GradleEntityId> LIBRARY_DEPENDENCY_TO_LIBRARY_MAPPER
= new Function<GradleEntityId, GradleEntityId>()
{
@Override
public GradleEntityId fun(GradleEntityId id) {
if (id instanceof GradleLibraryDependencyId) {
return ((GradleLibraryDependencyId)id).getLibraryId();
}
return id;
}
};
/**
* <pre>
* ...
@@ -119,14 +113,16 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
final Runnable task = new Runnable() {
@Override
public void run() {
Collection<GradleProjectStructureChange> c = ContainerUtil.subtract(oldChanges, currentChanges);
List<GradleProjectStructureChange> currentChangesToUse = ContainerUtilRt.newArrayList(currentChanges);
Collection<GradleProjectStructureChange> obsoleteChangesToUse = ContainerUtil.subtract(oldChanges, currentChanges);
if (myChangesComparator != null) {
List<GradleProjectStructureChange> toSort = new ArrayList<GradleProjectStructureChange>(c);
List<GradleProjectStructureChange> toSort = ContainerUtilRt.newArrayList(obsoleteChangesToUse);
Collections.sort(toSort, myChangesComparator);
c = toSort;
obsoleteChangesToUse = toSort;
Collections.sort(currentChangesToUse, myChangesComparator);
}
processObsoleteChanges(c);
processCurrentChanges(currentChanges);
processObsoleteChanges(obsoleteChangesToUse);
processCurrentChanges(currentChangesToUse);
}
};
if (myProcessChangesAtTheSameThread) {
@@ -157,7 +153,8 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
GradleProjectStructureNode<GradleProjectId> root = buildNode(projectId, getProject().getName());
setRoot(root);
final Collection<Module> modules = myPlatformFacade.getModules(getProject());
final List<GradleProjectStructureNode<?>> dependencies = new ArrayList<GradleProjectStructureNode<?>>();
final List<GradleProjectStructureNode<?>> dependencies = ContainerUtilRt.newArrayList();
final List<Pair<GradleProjectStructureNode<GradleLibraryDependencyId>, Library>> libraryDependencies = ContainerUtilRt.newArrayList();
RootPolicy<Object> visitor = new RootPolicy<Object>() {
@Override
public Object visitModuleOrderEntry(ModuleOrderEntry moduleOrderEntry, Object value) {
@@ -172,12 +169,15 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
return value;
}
GradleLibraryDependencyId id = GradleEntityIdMapper.mapEntityToId(libraryOrderEntry);
dependencies.add(buildNode(id, id.getDependencyName()));
GradleProjectStructureNode<GradleLibraryDependencyId> dependencyNode = buildNode(id, id.getDependencyName());
libraryDependencies.add(Pair.create(dependencyNode, libraryOrderEntry.getLibrary()));
dependencies.add(dependencyNode);
return value;
}
};
for (Module module : modules) {
dependencies.clear();
libraryDependencies.clear();
final GradleModuleId moduleId = GradleEntityIdMapper.mapEntityToId(module);
final GradleProjectStructureNode<GradleModuleId> moduleNode = buildNode(moduleId, moduleId.getModuleName());
myModules.put(module.getName(), moduleNode); // Assuming that module names are unique.
@@ -201,11 +201,34 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
for (GradleProjectStructureNode<?> dependency : dependencies) {
dependenciesNode.add(dependency);
}
// The general idea is to add jar nodes when all tree nodes above have already been initialized.
if (!libraryDependencies.isEmpty()) {
for (Pair<GradleProjectStructureNode<GradleLibraryDependencyId>, Library> p : libraryDependencies) {
populateLibraryDependencyNode(p.first, p.second);
}
}
}
processCurrentChanges(myChangesModel.getChanges());
filterNodes(root);
}
private void populateLibraryDependencyNode(@NotNull GradleProjectStructureNode<GradleLibraryDependencyId> node,
@Nullable Library library)
{
if (library == null) {
return;
}
GradleLibraryId libraryId = node.getDescriptor().getElement().getLibraryId();
for (VirtualFile file : library.getFiles(OrderRootType.CLASSES)) {
GradleJarId jarId = new GradleJarId(GradleUtil.getLocalFileSystemPath(file), libraryId);
GradleProjectStructureNode<GradleJarId> jarNode = buildNode(jarId, GradleUtil.extractNameFromPath(jarId.getPath()));
jarNode.getDescriptor().setToolTip(jarId.getPath());
node.add(jarNode);
}
}
@TestOnly
public void setProcessChangesAtTheSameThread(boolean processChangesAtTheSameThread) {
myProcessChangesAtTheSameThread = processChangesAtTheSameThread;
@@ -436,10 +459,6 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
getRoot().addConflictChange(change);
}
private void processNewMismatchedLibraryPathChange(@NotNull GradleMismatchedLibraryPathChange change) {
processDependencyConflictChange(change, LIBRARY_DEPENDENCY_TO_LIBRARY_MAPPER, false);
}
private void processNewDependencyScopeChange(@NotNull GradleDependencyScopeChange change) {
processDependencyConflictChange(change, SELF_MAPPER, false);
}
@@ -449,14 +468,88 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
}
private void processNewLibraryDependencyPresenceChange(@NotNull GradleLibraryDependencyPresenceChange change) {
processNewDependencyPresenceChange(change);
GradleProjectStructureNode<GradleLibraryDependencyId> dependencyNode = processNewDependencyPresenceChange(change);
GradleLibraryDependencyId id = change.getGradleEntity();
if (dependencyNode != null && id != null) {
GradleLibrary library = myProjectStructureHelper.findGradleLibrary(id.getLibraryId());
if (library != null) {
GradleLibraryId libraryId = dependencyNode.getDescriptor().getElement().getLibraryId();
for (String path : library.getPaths(LibraryPathType.BINARY)) {
GradleJarId jarId = new GradleJarId(path, libraryId);
GradleProjectStructureNode<GradleJarId> jarNode = buildNode(jarId, GradleUtil.extractNameFromPath(jarId.getPath()));
jarNode.setAttributes(GradleTextAttributes.GRADLE_LOCAL_CHANGE);
jarNode.getDescriptor().setToolTip(jarId.getPath());
dependencyNode.add(jarNode);
}
}
}
}
private void processJarPresenceChange(@NotNull GradleJarPresenceChange change, boolean obsolete) {
GradleJarId jarId = change.getGradleEntity();
TextAttributesKey attributes = GradleTextAttributes.GRADLE_LOCAL_CHANGE;
if (jarId == null) {
jarId = change.getIntellijEntity();
attributes = GradleTextAttributes.INTELLIJ_LOCAL_CHANGE;
assert jarId != null;
}
if (obsolete) {
attributes = GradleTextAttributes.NO_CHANGE;
}
for (Map.Entry<String, GradleProjectStructureNode<GradleSyntheticId>> entry : myModuleDependencies.entrySet()) {
Collection<GradleProjectStructureNode<GradleLibraryDependencyId>> libraryDependencies
= entry.getValue().getChildren(GradleLibraryDependencyId.class);
insideModule:
for (GradleProjectStructureNode<GradleLibraryDependencyId> libraryDependencyNode : libraryDependencies) {
if (!libraryDependencyNode.getDescriptor().getElement().getLibraryId().equals(jarId.getLibraryId())) {
continue;
}
for (GradleProjectStructureNode<GradleJarId> jarNode : libraryDependencyNode.getChildren(GradleJarId.class)) {
if (jarNode.getDescriptor().getElement().equals(jarId)) {
if (obsolete && myProjectStructureHelper.findIntellijJar(jarId) == null) {
// It was a gradle-local change which is now obsolete. Remove the jar node then.
jarNode.removeFromParent();
}
else {
jarNode.setAttributes(attributes);
}
break insideModule;
}
}
if (obsolete) {
continue;
}
// There is a possible case that both gradle and intellij have a library with the same name but different jar sets.
// We don't want to show intellij-local jars for the gradle-local module which uses that library then.
if (jarId.getOwner() == GradleEntityOwner.INTELLIJ
&& myModules.get(entry.getKey()).getDescriptor().getAttributes() == GradleTextAttributes.GRADLE_LOCAL_CHANGE)
{
continue;
}
// When control flow reaches this place that means that this is a new jar attached to a library. Hence, we need to add a node.
GradleProjectStructureNode<GradleJarId> newNode = buildNode(jarId, GradleUtil.extractNameFromPath(jarId.getPath()));
newNode.setAttributes(attributes);
newNode.getDescriptor().setToolTip(jarId.getPath());
if (passFilters(newNode)) {
libraryDependencyNode.add(newNode);
}
}
}
}
private void processNewModuleDependencyPresenceChange(@NotNull GradleModuleDependencyPresenceChange change) {
processNewDependencyPresenceChange(change);
}
private <I extends GradleAbstractDependencyId> void processNewDependencyPresenceChange(
@SuppressWarnings("unchecked")
@Nullable
private <I extends GradleAbstractDependencyId> GradleProjectStructureNode<I> processNewDependencyPresenceChange(
@NotNull GradleAbstractEntityPresenceChange<I> change)
{
I id = change.getGradleEntity();
@@ -467,21 +560,25 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
}
assert id != null;
final GradleProjectStructureNode<GradleSyntheticId> dependenciesNode = getDependenciesNode(id.getOwnerModuleId());
for (GradleProjectStructureNode<? extends GradleAbstractDependencyId> node : dependenciesNode.getChildren(id.getClass())) {
Class<I> clazz = (Class<I>)id.getClass();
for (GradleProjectStructureNode<I> node : dependenciesNode.getChildren(clazz)) {
if (id.equals(node.getDescriptor().getElement())) {
node.setAttributes(attributes);
return;
return node;
}
}
GradleProjectStructureNode<I> newNode = buildNode(id, id.getDependencyName());
dependenciesNode.add(newNode);
newNode.setAttributes(attributes);
if (!passFilters(newNode)) {
newNode.removeFromParent();
removeModuleDependencyNodeIfEmpty(dependenciesNode, id.getOwnerModuleId());
removeModuleNodeIfEmpty(getModuleNode(id.getOwnerModuleId()));
if (passFilters(newNode)) {
return newNode;
}
newNode.removeFromParent();
removeModuleDependencyNodeIfEmpty(dependenciesNode, id.getOwnerModuleId());
removeModuleNodeIfEmpty(getModuleNode(id.getOwnerModuleId()));
return null;
}
private void processNewModulePresenceChange(@NotNull GradleModulePresenceChange change) {
@@ -537,10 +634,6 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
getRoot().removeConflictChange(change);
}
private void processObsoleteMismatchedLibraryPathChange(@NotNull GradleMismatchedLibraryPathChange change) {
processDependencyConflictChange(change, LIBRARY_DEPENDENCY_TO_LIBRARY_MAPPER, true);
}
private void processObsoleteDependencyScopeChange(@NotNull GradleDependencyScopeChange change) {
processDependencyConflictChange(change, SELF_MAPPER, true);
}
@@ -740,8 +833,8 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
@Override public void visit(@NotNull GradleModulePresenceChange change) { processNewModulePresenceChange(change); }
@Override public void visit(@NotNull GradleContentRootPresenceChange change) { processNewContentRootPresenceChange(change); }
@Override public void visit(@NotNull GradleLibraryDependencyPresenceChange change) { processNewLibraryDependencyPresenceChange(change); }
@Override public void visit(@NotNull GradleJarPresenceChange change) { processJarPresenceChange(change, false); }
@Override public void visit(@NotNull GradleModuleDependencyPresenceChange change) { processNewModuleDependencyPresenceChange(change); }
@Override public void visit(@NotNull GradleMismatchedLibraryPathChange change) { processNewMismatchedLibraryPathChange(change); }
@Override public void visit(@NotNull GradleDependencyScopeChange change) { processNewDependencyScopeChange(change); }
@Override public void visit(@NotNull GradleDependencyExportedChange change) { processNewDependencyExportedChange(change);
}
@@ -755,10 +848,10 @@ public class GradleProjectStructureTreeModel extends DefaultTreeModel {
@Override public void visit(@NotNull GradleLibraryDependencyPresenceChange change) {
processObsoleteLibraryDependencyPresenceChange(change);
}
@Override public void visit(@NotNull GradleJarPresenceChange change) { processJarPresenceChange(change, true); }
@Override public void visit(@NotNull GradleModuleDependencyPresenceChange change) {
processObsoleteModuleDependencyPresenceChange(change);
}
@Override public void visit(@NotNull GradleMismatchedLibraryPathChange change) { processObsoleteMismatchedLibraryPathChange(change); }
@Override public void visit(@NotNull GradleDependencyScopeChange change) { processObsoleteDependencyScopeChange(change); }
@Override public void visit(@NotNull GradleDependencyExportedChange change) { processObsoleteDependencyExportedChange(change); }
}
@@ -32,14 +32,11 @@ import java.util.Collection;
public class GradleConflictControlFactory {
@NotNull private final GradleProjectConflictControlFactory myProjectFactory;
@NotNull private final GradleLibraryDependencyConflictControlFactory myLibraryDependencyFactory;
@NotNull private final GradleCommonDependencyConflictControlFactory myCommonDependencyFactory;
public GradleConflictControlFactory(@NotNull GradleProjectConflictControlFactory factory,
@NotNull GradleLibraryDependencyConflictControlFactory libraryFactory,
@NotNull GradleCommonDependencyConflictControlFactory commonDependencyFactory) {
myProjectFactory = factory;
myLibraryDependencyFactory = libraryFactory;
myCommonDependencyFactory = commonDependencyFactory;
}
@@ -70,7 +67,6 @@ public class GradleConflictControlFactory {
@Override
public void visit(@NotNull LibraryOrderEntry libraryDependency) {
result.set(myLibraryDependencyFactory.getControl(libraryDependency, changes));
}
@Override
@@ -1,134 +0,0 @@
package org.jetbrains.plugins.gradle.sync.conflict;
import com.intellij.icons.AllIcons;
import com.intellij.openapi.roots.LibraryOrderEntry;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.SeparatorFactory;
import com.intellij.ui.treeStructure.Tree;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.gradle.config.GradleTextAttributes;
import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChange;
import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChangeVisitor;
import org.jetbrains.plugins.gradle.diff.GradleProjectStructureChangeVisitorAdapter;
import org.jetbrains.plugins.gradle.diff.library.GradleMismatchedLibraryPathChange;
import org.jetbrains.plugins.gradle.model.id.GradleSyntheticId;
import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode;
import org.jetbrains.plugins.gradle.util.GradleBundle;
import org.jetbrains.plugins.gradle.util.GradleUtil;
import javax.swing.*;
import javax.swing.tree.DefaultTreeModel;
import java.awt.*;
import java.util.Collection;
import java.util.Set;
/**
* Provides UI control for representing library setup conflicts.
* <p/>
* Thread-safe.
*
* @author Denis Zhdanov
* @since 3/2/12 4:12 PM
*/
public class GradleLibraryDependencyConflictControlFactory {
@NotNull private final GradleCommonDependencyConflictControlFactory myCommonPropertiesFactory;
public GradleLibraryDependencyConflictControlFactory(@NotNull GradleCommonDependencyConflictControlFactory factory) {
myCommonPropertiesFactory = factory;
}
@SuppressWarnings("MethodMayBeStatic")
@Nullable
public JComponent getControl(@NotNull LibraryOrderEntry libraryDependency, Collection<GradleProjectStructureChange> changes) {
final Ref<GradleMismatchedLibraryPathChange> pathChangeRef = new Ref<GradleMismatchedLibraryPathChange>();
GradleProjectStructureChangeVisitor visitor = new GradleProjectStructureChangeVisitorAdapter() {
@Override
public void visit(@NotNull GradleMismatchedLibraryPathChange change) {
pathChangeRef.set(change);
}
};
for (GradleProjectStructureChange change : changes) {
if (!pathChangeRef.isNull()) {
break;
}
change.invite(visitor);
}
JComponent commonChangesControl = myCommonPropertiesFactory.getControl(libraryDependency, changes);
final GradleMismatchedLibraryPathChange pathChange = pathChangeRef.get();
if (commonChangesControl == null && pathChange == null) {
return null;
}
if (pathChange == null) {
return commonChangesControl;
}
final Library library = libraryDependency.getLibrary();
if (library == null) {
return commonChangesControl;
}
final JComponent pathConflictControl = getPathConflictControl(library, pathChange);
if (commonChangesControl == null) {
return pathConflictControl;
}
JPanel result = new JPanel(new GridBagLayout());
GridBagConstraints constraints = new GridBagConstraints();
constraints.weightx = 1;
constraints.fill = GridBagConstraints.HORIZONTAL;
constraints.anchor = GridBagConstraints.NORTHWEST;
constraints.gridwidth = GridBagConstraints.REMAINDER;
final JComponent commonSeparator =
SeparatorFactory.createSeparator(GradleBundle.message("gradle.sync.change.dependency.common.title"), commonChangesControl);
commonSeparator.setBackground(pathConflictControl.getBackground());
result.add(commonSeparator, constraints);
result.add(commonChangesControl, constraints);
final JComponent pathSeparator =
SeparatorFactory.createSeparator(GradleBundle.message("gradle.sync.change.library.path.title"), pathConflictControl);
pathSeparator.setBackground(pathConflictControl.getBackground());
result.add(pathSeparator, constraints);
result.add(pathConflictControl, constraints);
return result;
}
private static JComponent getPathConflictControl(@NotNull Library library, @NotNull GradleMismatchedLibraryPathChange pathChange) {
GradleProjectStructureNode<GradleSyntheticId> root = new GradleProjectStructureNode<GradleSyntheticId>(
GradleUtil.buildSyntheticDescriptor(GradleUtil.getLibraryName(library), AllIcons.Nodes.PpLib)
);
for (String path : pathChange.getGradleValue()) {
final GradleProjectStructureNode<GradleSyntheticId> node = buildPathNode(path);
node.setAttributes(GradleTextAttributes.GRADLE_LOCAL_CHANGE);
root.add(node);
}
final Set<String> intellijLocalBinaries = pathChange.getIntellijValue();
for (VirtualFile libRoot : library.getFiles(OrderRootType.CLASSES)) {
final String path = GradleUtil.getLocalFileSystemPath(libRoot);
GradleProjectStructureNode<GradleSyntheticId> node = buildPathNode(path);
if (intellijLocalBinaries.contains(path)) {
node.setAttributes(GradleTextAttributes.INTELLIJ_LOCAL_CHANGE);
}
root.add(node);
}
DefaultTreeModel model = new DefaultTreeModel(root);
return new Tree(model);
}
private static GradleProjectStructureNode<GradleSyntheticId> buildPathNode(@NotNull String path) {
final int i = path.lastIndexOf('/');
final String name = i < 0 || i >= path.length() - 1 ? path : path.substring(i + 1);
final GradleProjectStructureNode<GradleSyntheticId> result
= new GradleProjectStructureNode<GradleSyntheticId>(GradleUtil.buildSyntheticDescriptor(name, AllIcons.Nodes.PpJar));
result.getDescriptor().setToolTip(path);
return result;
}
}
@@ -30,15 +30,16 @@ import java.util.Comparator;
*/
public class GradleProjectStructureNodeComparator implements Comparator<GradleProjectStructureNode<?>> {
private static final int PROJECT_WEIGHT = 0;
private static final int PROJECT_WEIGHT = 0;
private static final int MODULE_WEIGHT = 1;
private static final int CONTENT_ROOT_WEIGHT = 2;
private static final int SYNTHETIC_WEIGHT = 3;
private static final int MODULE_DEPENDENCY_WEIGHT = 4;
private static final int LIBRARY_DEPENDENCY_WEIGHT = 5;
private static final int LIBRARY_WEIGHT = 6;
private static final int JAR_WEIGHT = 7;
private static final int UNKNOWN_WEIGHT = 20;
@NotNull private final GradleProjectStructureContext myContext;
public GradleProjectStructureNodeComparator(@NotNull GradleProjectStructureContext context) {
@@ -100,6 +101,11 @@ public class GradleProjectStructureNodeComparator implements Comparator<GradlePr
result.set(LIBRARY_WEIGHT);
}
@Override
public void visit(@NotNull GradleJar jar) {
result.set(JAR_WEIGHT);
}
@Override
public void visit(@NotNull GradleModuleDependency dependency) {
result.set(MODULE_DEPENDENCY_WEIGHT);
@@ -71,5 +71,6 @@ public class GradleProjectStructureNodeDescriptor<T extends GradleEntityId> exte
public void setToolTip(@NotNull String text) {
getTemplatePresentation().setTooltip(text);
update();
}
}
@@ -406,22 +406,9 @@ public class GradleUtil {
if (result != null) {
return result;
}
String[] endingsToStrip = { "/", "!", ".jar" };
StringBuilder buffer = new StringBuilder();
for (OrderRootType type : OrderRootType.getAllTypes()) {
for (String url : library.getUrls(type)) {
buffer.setLength(0);
buffer.append(url);
for (String ending : endingsToStrip) {
if (buffer.lastIndexOf(ending) == buffer.length() - ending.length()) {
buffer.setLength(buffer.length() - ending.length());
}
}
final int i = buffer.lastIndexOf(PATH_SEPARATOR);
if (i < 0 || i >= buffer.length() - 1) {
continue;
}
String candidate = buffer.substring(i + 1);
String candidate = extractNameFromPath(url);
if (!StringUtil.isEmpty(candidate)) {
return candidate;
}
@@ -431,6 +418,32 @@ public class GradleUtil {
return "unknown-lib";
}
@NotNull
public static String extractNameFromPath(@NotNull String path) {
String strippedPath = stripPath(path);
final int i = strippedPath.lastIndexOf(PATH_SEPARATOR);
final String result;
if (i < 0 || i >= strippedPath.length() - 1) {
result = strippedPath;
}
else {
result = strippedPath.substring(i + 1);
}
return result;
}
@NotNull
private static String stripPath(@NotNull String path) {
String[] endingsToStrip = { "/", "!", ".jar" };
StringBuilder buffer = new StringBuilder(path);
for (String ending : endingsToStrip) {
if (buffer.lastIndexOf(ending) == buffer.length() - ending.length()) {
buffer.setLength(buffer.length() - ending.length());
}
}
return buffer.toString();
}
/**
* Tries to find the current {@link GradleProjectStructureTreeModel} instance.
*
@@ -23,6 +23,7 @@ public class GradleLocalNodeManageHelperTest extends AbstractGradleTest {
container.registerComponentImplementation(GradleLocalNodeManageHelper)
container.registerComponentImplementation(GradleModuleManager)
container.registerComponentImplementation(GradleLibraryManager)
container.registerComponentImplementation(GradleJarManager)
container.registerComponentImplementation(GradleDependencyManager)
container.registerComponentImplementation(GradleContentRootManager)
}
@@ -49,7 +50,8 @@ public class GradleLocalNodeManageHelperTest extends AbstractGradleTest {
contentRoot('1', transitive: true, order: 1)
} } }
}
@SuppressWarnings("GroovyAssignabilityCheck")
private def doTest(Closure c) {
myHelper = container.getComponentInstance(GradleLocalNodeManageHelper)
def compositeBuilder = new CompositeProjectBuilder(gradleBuilder: gradle, intellijBuilder: intellij)
@@ -2,11 +2,12 @@ package org.jetbrains.plugins.gradle.sync;
import com.intellij.testFramework.SkipInHeadlessEnvironment
import org.jetbrains.plugins.gradle.diff.library.GradleJarPresenceChange
import org.jetbrains.plugins.gradle.diff.module.GradleModulePresenceChange
import org.jetbrains.plugins.gradle.testutil.AbstractGradleTest
import org.junit.Test
import static org.junit.Assert.assertEquals
import org.jetbrains.plugins.gradle.diff.library.GradleMismatchedLibraryPathChange
import org.jetbrains.plugins.gradle.diff.dependency.GradleLibraryDependencyPresenceChange
import org.jetbrains.plugins.gradle.config.GradleTextAttributes
@@ -107,28 +108,30 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
module {
dependencies {
library("lib1")
library("lib2", bin: ['1', '2'])
} } } },
library("lib2", bin: ['jar1', 'jar2']) } } } },
intellij: {
project {
module {
dependencies {
library("lib1")
library("lib2", bin: ['2', '3'])
} } } }
)
library("lib2", bin: ['jar2', 'jar3']) } } } })
checkChanges {
libraryConflict(entity: intellij.libraries['lib2']) {
binaryPath(gradle: '1', intellij: ['3'])
} }
presence {
jar(gradle: [findJarId('jar1')])
jar(intellij: [findJarId('jar3')])
}
}
checkTree {
project {
module {
dependencies {
lib1()
lib2('conflict')
} } } }
lib2 {
jar1('gradle')
jar2()
jar3('intellij') } } } } }
// Remove one difference from the library setup and check that the corresponding node is still marked as conflicted
setState(
@@ -137,27 +140,28 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
module {
dependencies {
library("lib1")
library("lib2", bin: ['2'])
} } } },
library("lib2", bin: ['jar2']) } } } },
intellij: {
project {
module {
dependencies {
library("lib1")
library("lib2", bin: ['2', '3'])
} } } }
)
library("lib2", bin: ['jar2', 'jar3']) } } } })
checkChanges {
libraryConflict(entity: intellij.libraryDependencies.values().flatten().find {it.library.name == 'lib2' }.library) {
binaryPath(gradle: null, intellij: '3')
} }
presence {
jar(intellij: [findJarId('jar3')])
}
}
checkTree {
project {
module {
dependencies {
lib1()
lib2('conflict')
} } } }
lib2 {
jar2()
jar3('intellij') } } } } }
// Match the remaining change and check that the corresponding node is not marked as conflicted anymore.
setState(
@@ -166,24 +170,102 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
module {
dependencies {
library("lib1")
library("lib2", bin: ['2', '3'])
library("lib2", bin: ['jar2', 'jar3'])
} } } },
intellij: {
project {
module {
dependencies {
library("lib1")
library("lib2", bin: ['2', '3'])
} } } }
)
library("lib2", bin: ['jar2', 'jar3']) } } } })
checkChanges { } // No changes
checkTree {
project {
module {
dependencies {
lib1()
lib2()
} } } }
lib2 {
jar2()
jar3() } } } } }
}
@Test
public void "gradle-local module which library setup differs from intellij when jar presence change goes first"() {
init(
gradle: {
project {
module('module1') {
dependencies {
library("lib1", bin: ['jar1', 'jar2']) }}
module('module2') {
dependencies {
library("lib1", bin: ['jar1', 'jar2']) } } } },
intellij: {
project {
module('module1') {
dependencies {
library("lib1", bin: ['jar2', 'jar3']) } } } },
changesSorter: changeByClassSorter([
(GradleJarPresenceChange) : 1,
(GradleLibraryDependencyPresenceChange) : 2,
(GradleModulePresenceChange) : 3,
])
)
checkChanges {
presence {
jar(gradle: [findJarId('jar1')])
jar(intellij: [findJarId('jar3')])
library(gradle: gradle.libraryDependencies[gradle.modules['module2']].find { it.name == "lib1" })
module(gradle: gradle.modules['module2'])
}
}
checkTree {
project {
module2('gradle') {
dependencies {
lib1('gradle') {
jar1('gradle')
jar2('gradle')} } }
module1 {
dependencies {
lib1 {
jar1('gradle')
jar2()
jar3('intellij') } } } } }
}
@Test
public void "adding intellij-local jar"() {
Closure initialProject = {
project {
module {
dependencies {
library('lib1', bin: ['jar1'])} } } }
init(gradle: initialProject, intellij: initialProject)
checkChanges {} // empty
setState(
intellij: {
project {
module {
dependencies {
library('lib1', bin: ['jar1', 'jar2'])
} } } }
)
checkChanges {
presence {
jar(intellij: [findJarId('jar2')])
} }
checkTree {
project {
module {
dependencies {
lib1 {
jar1()
jar2('intellij')} } } } }
}
@Test
@@ -271,42 +353,42 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
project {
module('module1') {
dependencies {
library('lib1', bin: ['1'])
} }
library('lib1', bin: ['jar1']) } }
module('module2') {
dependencies {
library('lib1')
} } } },
library('lib1') } } } },
intellij: {
project {
module('module1') {
dependencies {
library('lib1', bin: ['2'])
} } } },
library('lib1', bin: ['jar2']) } } } },
changesSorter: changeByClassSorter([
(GradleMismatchedLibraryPathChange) : 2,
(GradleLibraryDependencyPresenceChange) : 1
(GradleModulePresenceChange) : 1,
(GradleLibraryDependencyPresenceChange) : 2,
(GradleJarPresenceChange) : 3,
])
)
checkChanges {
presence {
module(gradle: gradle.modules['module2'])
jar(gradle: [findJarId('jar1')])
jar(intellij: [findJarId('jar2')])
libraryDependency(gradle: gradle.libraryDependencies[gradle.modules['module2']].first())
}
libraryConflict(entity: intellij.libraries['lib1']) {
binaryPath(gradle: ['1'], intellij: ['2'])
} }
}
checkTree {
project {
module2('gradle') {
dependencies {
lib1('gradle') // This is the point of the test. We don't expect to see 'conflict' here.
} }
lib1('gradle') {
jar1('gradle') } } }
module1() {
dependencies {
lib1('conflict')
} } } }
lib1 {
jar1('gradle')
jar2('intellij') } } } } }
}
@Test
@@ -486,73 +568,6 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
} } } }
}
@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')
} } } }
}
@Test
public void "local content root importing"() {
init(
@@ -791,7 +806,6 @@ public class GradleProjectStructureChangesModelTest extends AbstractGradleTest {
project {
module2 {
dependencies {
lib1('conflict')
module1('conflict')
} } } }
@@ -2,6 +2,9 @@ package org.jetbrains.plugins.gradle.testutil
import com.intellij.openapi.editor.colors.TextAttributesKey
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.OrderRootType
import com.intellij.openapi.roots.libraries.Library
import org.jetbrains.annotations.NotNull
import org.jetbrains.plugins.gradle.action.AbstractGradleSyncTreeFilterAction
import org.jetbrains.plugins.gradle.config.GradleColorAndFontDescriptorsProvider
import org.jetbrains.plugins.gradle.config.PlatformFacade
@@ -12,12 +15,18 @@ import org.jetbrains.plugins.gradle.diff.dependency.GradleModuleDependencyStruct
import org.jetbrains.plugins.gradle.diff.library.GradleLibraryStructureChangesCalculator
import org.jetbrains.plugins.gradle.diff.module.GradleModuleStructureChangesCalculator
import org.jetbrains.plugins.gradle.diff.project.GradleProjectStructureChangesCalculator
import org.jetbrains.plugins.gradle.model.GradleEntityOwner
import org.jetbrains.plugins.gradle.model.gradle.GradleLibrary
import org.jetbrains.plugins.gradle.model.gradle.LibraryPathType
import org.jetbrains.plugins.gradle.model.id.GradleEntityIdMapper
import org.jetbrains.plugins.gradle.model.id.GradleJarId
import org.jetbrains.plugins.gradle.model.id.GradleLibraryId
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureChangesModel
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureHelper
import org.jetbrains.plugins.gradle.sync.GradleProjectStructureTreeModel
import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNodeFilter
import org.jetbrains.plugins.gradle.util.GradleProjectStructureContext
import org.jetbrains.plugins.gradle.util.GradleUtil
import org.junit.Before
import org.picocontainer.MutablePicoContainer
import org.picocontainer.defaults.DefaultPicoContainer
@@ -32,10 +41,10 @@ public abstract class AbstractGradleTest {
GradleProjectStructureChangesModel changesModel
GradleProjectStructureTreeModel treeModel
def gradle
def intellij
GradleProjectBuilder gradle
IntellijProjectBuilder intellij
def changesBuilder
def treeChecker
ProjectStructureChecker treeChecker
def container
private Map<TextAttributesKey, GradleProjectStructureNodeFilter> treeFilters = [:]
@@ -123,7 +132,7 @@ public abstract class AbstractGradleTest {
treeChecker.check(expected, treeModel.root)
}
protected Closure changeByClassSorter(Map<Class<?>, Integer> rules) {
protected static Closure changeByClassSorter(Map<Class<?>, Integer> rules) {
{ a, b ->
def weightA = rules[a.class] ?: Integer.MAX_VALUE
def weightB = rules[b.class] ?: Integer.MAX_VALUE
@@ -139,4 +148,35 @@ public abstract class AbstractGradleTest {
protected def applyTreeFilter(TextAttributesKey toShow) {
treeModel.addFilter(treeFilters[toShow])
}
@NotNull
protected GradleJarId findJarId(@NotNull String path) {
String pathToUse = GradleUtil.toCanonicalPath(path)
for (GradleLibrary library in (gradle.libraries.values() as Collection<GradleLibrary>)) {
for (libPath in library.getPaths(LibraryPathType.BINARY)) {
if (libPath == pathToUse) {
return new GradleJarId(pathToUse, new GradleLibraryId(GradleEntityOwner.GRADLE, library.name))
}
}
}
for (Library library in (intellij.libraries.values() as Collection<Library>)) {
for (jarFile in library.getFiles(OrderRootType.CLASSES)) {
if (pathToUse == jarFile.path) {
return new GradleJarId(pathToUse, new GradleLibraryId(GradleEntityOwner.INTELLIJ, library.name))
}
}
}
String errorMessage = """
Can't build an id object for given jar path ($path).
Available gradle libraries:
${gradle.libraries.values().collect { GradleLibrary lib -> "${lib.name}: ${lib.getPaths(LibraryPathType.BINARY)}" }.join('\n ') }
Available intellij libraries:
${intellij.libraries.values().collect { Library lib -> "${lib.name}: ${lib.getFiles(OrderRootType.CLASSES).collect{it.path}}" }
.join('\n ')}
"""
throw new IllegalArgumentException(errorMessage)
}
}
@@ -1,13 +1,10 @@
package org.jetbrains.plugins.gradle.testutil;
package org.jetbrains.plugins.gradle.testutil
import org.jetbrains.plugins.gradle.diff.dependency.GradleLibraryDependencyPresenceChange
import org.jetbrains.plugins.gradle.diff.library.GradleMismatchedLibraryPathChange
import com.intellij.openapi.roots.libraries.Library
import org.jetbrains.plugins.gradle.util.GradleUtil
import org.jetbrains.plugins.gradle.diff.module.GradleModulePresenceChange
import org.jetbrains.plugins.gradle.diff.dependency.GradleModuleDependencyPresenceChange
import org.jetbrains.plugins.gradle.diff.contentroot.GradleContentRootPresenceChange
import org.jetbrains.plugins.gradle.diff.dependency.GradleLibraryDependencyPresenceChange
import org.jetbrains.plugins.gradle.diff.dependency.GradleModuleDependencyPresenceChange
import org.jetbrains.plugins.gradle.diff.library.GradleJarPresenceChange
import org.jetbrains.plugins.gradle.diff.module.GradleModulePresenceChange
/**
* @author Denis Zhdanov
@@ -58,11 +55,9 @@ public class ChangeBuilder extends BuilderSupport {
changes.addAll attributes.gradle.collect { new GradleContentRootPresenceChange(it, null)}
changes.addAll attributes.intellij.collect { new GradleContentRootPresenceChange(null, it)}
return changes
case "binaryPath":
// Assuming that we're processing library binary path conflict here
register(new GradleMismatchedLibraryPathChange(
current as Library, collectPaths(attributes.gradle), collectPaths(attributes.intellij)
))
case "jar":
changes.addAll attributes.gradle.collect { new GradleJarPresenceChange(it, null) }
changes.addAll attributes.intellij.collect { new GradleJarPresenceChange(null, it) }
}
changes
}
@@ -79,15 +74,4 @@ public class ChangeBuilder extends BuilderSupport {
changes << change
changes
}
private def collectPaths(paths) {
if (!paths) {
return [].toSet()
}
paths.collect { toCanonicalPath(it) }.toSet()
}
private def toCanonicalPath(String path) {
path ? GradleUtil.toCanonicalPath(path) : path
}
}
@@ -54,6 +54,7 @@ class GradleProjectBuilder extends AbstractProjectBuilder {
protected createLibrary(String name, Map paths) {
def result = new GradleLibrary(name)
applyLibraryPaths(result, paths)
project.addLibrary(result)
result
}
@@ -1,5 +1,6 @@
package org.jetbrains.plugins.gradle.testutil
import com.intellij.openapi.fileTypes.FileTypes
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ContentEntry
@@ -107,7 +108,10 @@ class IntellijProjectBuilder extends AbstractProjectBuilder {
@Override
protected reset() { }
private def asVirtualFile(path) {
[getPath: { GradleUtil.toCanonicalPath(path) }] as VirtualFile
private static def asVirtualFile(path) {
[
getPath: { GradleUtil.toCanonicalPath(path) },
getFileType: { FileTypes.UNKNOWN }
] as VirtualFile
}
}
@@ -2,6 +2,10 @@ package org.jetbrains.plugins.gradle.testutil
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import org.jetbrains.annotations.NotNull
import org.jetbrains.plugins.gradle.model.id.GradleEntityId
import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNode
import javax.swing.tree.DefaultMutableTreeNode
import org.jetbrains.plugins.gradle.config.GradleTextAttributes
import org.jetbrains.plugins.gradle.ui.GradleProjectStructureNodeDescriptor
@@ -44,15 +48,26 @@ class ProjectStructureChecker {
check it as Node, actual.getChildAt(childIndex++) as DefaultMutableTreeNode
}
if (childIndex < actual.childCount) {
fail("Unexpected nodes detected: ${(childIndex..<actual.childCount).collect { actual.getChildAt(it) }.join(', ')}")
def transform = { nodePath(actual.getChildAt(it) as GradleProjectStructureNode<? extends GradleEntityId>) }
fail("Unexpected nodes detected: ${(childIndex..<actual.childCount).collect(transform, ).join(', ')}")
}
}
private void checkName(Node expected, GradleProjectStructureNodeDescriptor actual) {
@NotNull
private static String nodePath(@NotNull GradleProjectStructureNode<? extends GradleEntityId> node) {
StringBuilder result = new StringBuilder("'${node.descriptor.name}")
for (GradleProjectStructureNode<? extends GradleEntityId> n = node.parent; n != null; n = n.parent) {
result.append(" -> ${n.descriptor.name}")
}
result.append("'")
result.toString()
}
private static void checkName(Node expected, GradleProjectStructureNodeDescriptor actual) {
if (AbstractProjectBuilder.SAME_TOKEN == actual.toString() || expected.name() == actual.toString()) {
return
}
def clazz = BUILT_IN[expected.name()]
def clazz = BUILT_IN[expected.name().toString()]
if (clazz == null || !clazz.isAssignableFrom(actual.element.class)) {
Assert.fail(
"Failed node name check. Expected to find name '${expected.name()}'" + (clazz ? " or user object of type ${clazz.simpleName}" : "")
@@ -61,8 +76,8 @@ class ProjectStructureChecker {
}
}
def checkMarkup(Node node, GradleProjectStructureNodeDescriptor descriptor) {
def expectedMarkup = COLORS[node.children().find {it instanceof CharSequence}]?: GradleTextAttributes.NO_CHANGE
static def checkMarkup(Node node, GradleProjectStructureNodeDescriptor descriptor) {
def expectedMarkup = COLORS[node.children().find {it instanceof CharSequence}.toString()]?: GradleTextAttributes.NO_CHANGE
assertEquals("node '$descriptor'", expectedMarkup, descriptor.attributes)
if (descriptor.element.type != GradleEntityType.SYNTHETIC) {
@@ -12,6 +12,8 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import javax.swing.*;
/**
* @author Denis Zhdanov
* @since 01/17/2012
@@ -59,8 +61,8 @@ public class RichTextControlBuilderTest {
public void completeMetaInfo() {
String text = String.format("this is a test text with two inline meta-datas: {@%s meta \t text} and {@%s}", META_KEY, META_KEY);
myMockery.checking(new Expectations() {{
one(myProcessor).process("meta \t text");
one(myProcessor).process("");
one(myProcessor).process("meta \t text"); will(returnValue(new JLabel("")));
one(myProcessor).process(""); will(returnValue(new JLabel("")));
}});
myBuilder.setText(text);
}