[Gradle] Show dependencies graph on the Gradle tool window IDEA-218166
authorVladislav.Soroka <Vladislav.Soroka@jetbrains.com>
Wed, 11 Dec 2019 14:12:26 +0000 (17:12 +0300)
committerintellij-monorepo-bot <intellij-monorepo-bot-no-reply@jetbrains.com>
Wed, 22 Jan 2020 18:07:02 +0000 (18:07 +0000)
GitOrigin-RevId: f6645da0834fd67ca1e52f3ea9e500b250f049a3

31 files changed:
platform/external-system-api/src/com/intellij/openapi/externalSystem/model/ProjectKeys.java
platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalProjectsStructure.java
platform/external-system-impl/src/com/intellij/openapi/externalSystem/view/ExternalSystemViewDefaultContributor.java
platform/external-system-rt/intellij.platform.externalSystem.rt.iml
platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/AbstractDependencyNode.java [new file with mode: 0644]
platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ArtifactDependencyNode.java [new file with mode: 0644]
platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ArtifactDependencyNodeImpl.java [moved from plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/ArtifactComponentNode.java with 56% similarity]
platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ComponentDependencies.java [new file with mode: 0644]
platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ComponentDependenciesImpl.java [new file with mode: 0644]
platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/DependencyNode.java [new file with mode: 0644]
platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/DependencyScopeNode.java [new file with mode: 0644]
platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ProjectDependencies.java [new file with mode: 0644]
platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ProjectDependenciesImpl.java [new file with mode: 0644]
platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ProjectDependencyNode.java [new file with mode: 0644]
platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ProjectDependencyNodeImpl.java [new file with mode: 0644]
platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ReferenceNode.java [new file with mode: 0644]
platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/UnknownDependencyNode.java [new file with mode: 0644]
plugins/gradle/java/src/service/project/JavaGradleProjectResolver.java
plugins/gradle/plugin-resources/META-INF/plugin.xml
plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/view/GradleViewContributor.java [deleted file]
plugins/gradle/src/org/jetbrains/plugins/gradle/service/task/GradleTaskManager.java
plugins/gradle/tooling-extension-impl/src/META-INF/services/org.jetbrains.plugins.gradle.tooling.ModelBuilderService
plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/DependencyGraphModelBuilderImpl.groovy [new file with mode: 0644]
plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/AbstractComponentNode.java [deleted file]
plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/BaseComponentNode.java [deleted file]
plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/ComponentNode.java [deleted file]
plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/ConfigurationNode.java [deleted file]
plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/DependenciesReport.groovy
plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/DependencyNodeDeserializer.java [moved from plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/ComponentNodeDeserializer.java with 53% similarity]
plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/ProjectComponentNode.java [deleted file]
plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/ReferenceNode.java [deleted file]

index 842dd8e72fb561369a1450c458481cbe40baa950..f1a4a06f6b4ab271dac3432ab805cae1ff419e04 100644 (file)
@@ -16,6 +16,7 @@
 package com.intellij.openapi.externalSystem.model;
 
 import com.intellij.openapi.externalSystem.model.project.*;
+import com.intellij.openapi.externalSystem.model.project.dependencies.ProjectDependencies;
 import com.intellij.openapi.externalSystem.model.project.settings.ConfigurationData;
 import com.intellij.openapi.externalSystem.model.task.TaskData;
 import org.jetbrains.annotations.NotNull;
@@ -38,6 +39,8 @@ public class ProjectKeys {
 
   @NotNull public static final Key<TestData>              TEST = Key.create(TestData.class, 450);
 
+  @NotNull public static final Key<ProjectDependencies>   DEPENDENCIES_GRAPH = Key.create(ProjectDependencies.class, 500);
+
   private ProjectKeys() {
   }
 }
index 5db192d18b7f471a5d1229d16d08a66f12dda2a0..8288b15ba0d2d90b4372d81abab6048da67a5749 100644 (file)
@@ -75,10 +75,14 @@ public class ExternalProjectsStructure extends SimpleTreeStructure implements Di
     tree.setShowsRootHandles(true);
   }
 
-  public void select(SimpleNode node) {
+  public void select(@NotNull SimpleNode node) {
     myTreeModel.select(node, myTree, path -> {});
   }
 
+  public void expand(@NotNull SimpleNode node) {
+    myTreeModel.expand(node, myTree, path -> {});
+  }
+
   protected Class<? extends ExternalSystemNode>[] getVisibleNodesClasses() {
     return null;
   }
index 8ab0cce895715621d7fe827da3a5fa31e9af106c..dc5fde9bfd949caf64d9e1aeadb49ca84ef3080f 100644 (file)
@@ -8,6 +8,7 @@ import com.intellij.openapi.externalSystem.model.Key;
 import com.intellij.openapi.externalSystem.model.ProjectKeys;
 import com.intellij.openapi.externalSystem.model.ProjectSystemId;
 import com.intellij.openapi.externalSystem.model.project.*;
+import com.intellij.openapi.externalSystem.model.project.dependencies.*;
 import com.intellij.openapi.externalSystem.model.task.TaskData;
 import com.intellij.openapi.externalSystem.service.project.IdeModelsProviderImpl;
 import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
@@ -20,6 +21,7 @@ import com.intellij.openapi.roots.ui.configuration.ProjectSettingsService;
 import com.intellij.openapi.util.io.FileUtil;
 import com.intellij.openapi.util.text.StringUtil;
 import com.intellij.pom.Navigatable;
+import com.intellij.ui.treeStructure.SimpleTree;
 import com.intellij.util.ObjectUtils;
 import com.intellij.util.SmartList;
 import com.intellij.util.containers.ContainerUtil;
@@ -27,7 +29,9 @@ import com.intellij.util.containers.MultiMap;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 
+import java.awt.event.InputEvent;
 import java.io.File;
+import java.text.MessageFormat;
 import java.util.*;
 import java.util.function.Supplier;
 
@@ -40,6 +44,7 @@ public class ExternalSystemViewDefaultContributor extends ExternalSystemViewCont
 
   private static final Key<?>[] KEYS = new Key[]{
     ProjectKeys.MODULE,
+    ProjectKeys.DEPENDENCIES_GRAPH,
     ProjectKeys.MODULE_DEPENDENCY,
     ProjectKeys.LIBRARY_DEPENDENCY,
     ProjectKeys.TASK
@@ -90,6 +95,25 @@ public class ExternalSystemViewDefaultContributor extends ExternalSystemViewCont
   private static void addDependenciesNode(@NotNull ExternalProjectsView externalProjectsView,
                                           @NotNull MultiMap<Key<?>, DataNode<?>> dataNodes,
                                           @NotNull List<? super ExternalSystemNode<?>> result) {
+    final Collection<DataNode<?>> depsGraph = dataNodes.get(ProjectKeys.DEPENDENCIES_GRAPH);
+    if (!depsGraph.isEmpty()) {
+      final ExternalSystemNode<?> depNode = new MyDependenciesNode(externalProjectsView);
+      for (DataNode<?> dataNode : depsGraph) {
+        if (!(dataNode.getData() instanceof ProjectDependencies)) continue;
+
+        ProjectDependencies projectDependencies = (ProjectDependencies)dataNode.getData();
+        for (ComponentDependencies componentDependencies : projectDependencies.getComponentsDependencies()) {
+          depNode.add(new DependencyScopeExternalSystemNode(externalProjectsView, componentDependencies.getCompileDependenciesGraph()));
+          depNode.add(new DependencyScopeExternalSystemNode(externalProjectsView, componentDependencies.getRuntimeDependenciesGraph()));
+        }
+      }
+
+      if (depNode.hasChildren()) {
+        result.add(depNode);
+      }
+      return;
+    }
+
     final Collection<DataNode<?>> moduleDeps = dataNodes.get(ProjectKeys.MODULE_DEPENDENCY);
     final Collection<DataNode<?>> libDeps = dataNodes.get(ProjectKeys.LIBRARY_DEPENDENCY);
 
@@ -201,6 +225,144 @@ public class ExternalSystemViewDefaultContributor extends ExternalSystemViewCont
     }
   }
 
+  private static class DependencyScopeExternalSystemNode extends ExternalSystemNode<Object> {
+    private final DependencyScopeNode myDependenciesGraph;
+    private final Map<Long, DependencyNode> myDependencyNodeMap = new HashMap<>();
+
+    DependencyScopeExternalSystemNode(@NotNull ExternalProjectsView externalProjectsView,
+                                      @NotNull DependencyScopeNode dependenciesGraph) {
+      super(externalProjectsView, null);
+      myDependenciesGraph = dependenciesGraph;
+    }
+
+    @Override
+    public String getName() {
+      return myDependenciesGraph.getScope();
+    }
+
+    @Override
+    protected void update(@NotNull PresentationData presentation) {
+      super.update(presentation);
+      presentation.setIcon(AllIcons.Nodes.PpLibFolder);
+      String description = myDependenciesGraph.getDescription();
+      if (description != null) {
+        setNameAndTooltip(getName(), description, (String)null);
+      }
+    }
+
+    @NotNull
+    @Override
+    protected List<ExternalSystemNode<?>> doBuildChildren() {
+      buildNodesMap(myDependencyNodeMap, myDependenciesGraph);
+      List<ExternalSystemNode<?>> myChildNodes = new ArrayList<>();
+      for (DependencyNode dependency : myDependenciesGraph.getDependencies()) {
+        myChildNodes.add(new DependencyExternalSystemNode(getExternalProjectsView(), dependency, myDependencyNodeMap));
+      }
+      return myChildNodes;
+    }
+
+    private static void buildNodesMap(@NotNull Map<Long, DependencyNode> dependencyNodeMap, @NotNull DependencyNode node) {
+      for (DependencyNode child : node.getDependencies()) {
+        if (child instanceof ReferenceNode) continue;
+        dependencyNodeMap.put(child.getId(), child);
+        buildNodesMap(dependencyNodeMap, child);
+      }
+    }
+  }
+
+  private static class DependencyExternalSystemNode extends ExternalSystemNode<Object> {
+    @NotNull
+    private final DependencyNode myDependencyNode;
+    @NotNull
+    private final Map<Long, DependencyNode> myDependencyNodeMap;
+    @Nullable
+    private DependencyNode myReferencedNode;
+    private final String myName;
+
+    DependencyExternalSystemNode(@NotNull ExternalProjectsView externalProjectsView,
+                                 @NotNull DependencyNode dependencyNode,
+                                 @NotNull Map<Long, DependencyNode> dependencyNodeMap) {
+      super(externalProjectsView, null);
+      myDependencyNode = dependencyNode;
+      myDependencyNodeMap = dependencyNodeMap;
+      if (myDependencyNode instanceof ReferenceNode) {
+        myReferencedNode = myDependencyNodeMap.get(myDependencyNode.getId());
+      }
+      if (myReferencedNode != null) {
+        myName = MessageFormat.format("{0}{1}",
+                                      myReferencedNode.getDisplayName(),
+                                      myReferencedNode.getDependencies().isEmpty() ? "" : " (*)");
+      }
+      else {
+        myName = myDependencyNode.getDisplayName();
+      }
+    }
+
+    @Override
+    public String getName() {
+      return myName;
+    }
+
+    @Override
+    protected void update(@NotNull PresentationData presentation) {
+      super.update(presentation);
+      boolean isProjectDependency = myDependencyNode instanceof ProjectDependencyNode || myReferencedNode instanceof ProjectDependencyNode;
+      presentation.setIcon(isProjectDependency ? getUiAware().getProjectIcon() : AllIcons.Nodes.PpLib);
+      String tooltip = "Dependencies omitted (listed previously). <br/>" +
+                       "Press Enter or left mouse button double click to navigate to dependencies.";
+      setNameAndTooltip(getName(), tooltip, (String)null);
+    }
+
+    @NotNull
+    @Override
+    protected List<ExternalSystemNode<?>> doBuildChildren() {
+      if (myReferencedNode != null) {
+        return Collections.emptyList();
+      }
+      List<ExternalSystemNode<?>> myChildNodes = new ArrayList<>();
+      for (DependencyNode dependency : myDependencyNode.getDependencies()) {
+        myChildNodes.add(new DependencyExternalSystemNode(getExternalProjectsView(), dependency, myDependencyNodeMap));
+      }
+      return myChildNodes;
+    }
+
+    @Override
+    public void handleDoubleClickOrEnter(SimpleTree tree, InputEvent inputEvent) {
+      if (myReferencedNode == null) {
+        super.handleDoubleClickOrEnter(tree, inputEvent);
+      }
+      else {
+        selectAndExpandReferencedNode();
+      }
+    }
+
+    private void selectAndExpandReferencedNode() {
+      ExternalProjectsStructure structure = getStructure();
+      if (structure == null) return;
+      DependencyScopeExternalSystemNode scopeNode = findParent(DependencyScopeExternalSystemNode.class);
+      if (scopeNode == null) return;
+
+      DependencyExternalSystemNode referencedNode = findReferencedNode(scopeNode);
+      if (referencedNode != null) {
+        structure.select(referencedNode);
+        structure.expand(referencedNode);
+      }
+    }
+
+    @Nullable
+    private DependencyExternalSystemNode findReferencedNode(ExternalSystemNode<?> node) {
+      for (ExternalSystemNode<?> child : node.getChildren()) {
+        if (child instanceof DependencyExternalSystemNode &&
+            ((DependencyExternalSystemNode)child).myDependencyNode == myReferencedNode) {
+          return (DependencyExternalSystemNode)child;
+        }
+        DependencyExternalSystemNode referencedNode = findReferencedNode(child);
+        if (referencedNode != null) return referencedNode;
+      }
+      return null;
+    }
+  }
+
   private static abstract class DependencyDataExternalSystemNode<T extends DependencyData<?>> extends ExternalSystemNode<T> {
 
     private final Navigatable myNavigatable;
index d530bef4b953b9bf92e6425993ef4f15b0497bc6..c32bdedd1bd4003e8937966c0e4770d5c13cfc80 100644 (file)
@@ -8,5 +8,6 @@
     <orderEntry type="jdk" jdkName="IDEA jdk" jdkType="JavaSDK" />
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="library" name="jetbrains-annotations-java5" level="project" />
+    <orderEntry type="module" module-name="intellij.platform.objectSerializer.annotations" />
   </component>
 </module>
\ No newline at end of file
diff --git a/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/AbstractDependencyNode.java b/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/AbstractDependencyNode.java
new file mode 100644 (file)
index 0000000..2cef87d
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.openapi.externalSystem.model.project.dependencies;
+
+import java.io.Serializable;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+public abstract class AbstractDependencyNode implements DependencyNode, Serializable {
+  private final long id;
+  private final Set<DependencyNode> dependencies = new LinkedHashSet<DependencyNode>();
+  private String resolutionState;
+
+  protected AbstractDependencyNode(long id) {this.id = id;}
+
+  @Override
+  public long getId() {
+    return id;
+  }
+
+  @Override
+  public Set<DependencyNode> getDependencies() {
+    return dependencies;
+  }
+
+  @Override
+  public String getResolutionState() {
+    return resolutionState;
+  }
+
+  public void setResolutionState(String resolutionState) {
+    this.resolutionState = resolutionState;
+  }
+}
diff --git a/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ArtifactDependencyNode.java b/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ArtifactDependencyNode.java
new file mode 100644 (file)
index 0000000..d65d063
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.openapi.externalSystem.model.project.dependencies;
+
+import org.jetbrains.annotations.NotNull;
+
+public interface ArtifactDependencyNode extends DependencyNode {
+  @NotNull
+  String getGroup();
+
+  @NotNull
+  String getModule();
+
+  @NotNull
+  String getVersion();
+}
@@ -1,38 +1,44 @@
 // Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
-package org.jetbrains.plugins.gradle.tooling.tasks;
+package com.intellij.openapi.externalSystem.model.project.dependencies;
 
+import com.intellij.serialization.PropertyMapping;
 import org.jetbrains.annotations.NotNull;
 
-public class ArtifactComponentNode extends AbstractComponentNode {
+public class ArtifactDependencyNodeImpl extends AbstractDependencyNode implements ArtifactDependencyNode {
 
   private final String group;
   private final String module;
   private final String version;
 
-  public ArtifactComponentNode(long id, @NotNull String group, @NotNull String module, @NotNull String version) {
+  @PropertyMapping({"id", "group", "module", "version"})
+  public ArtifactDependencyNodeImpl(long id, @NotNull String group, @NotNull String module, @NotNull String version) {
     super(id);
     this.group = group;
     this.module = module;
     this.version = version;
   }
 
+  @Override
   @NotNull
   public String getGroup() {
     return group;
   }
 
+  @Override
   @NotNull
   public String getModule() {
     return module;
   }
 
+  @Override
   @NotNull
   public String getVersion() {
     return version;
   }
 
+  @NotNull
   @Override
-  String getDisplayName() {
+  public String getDisplayName() {
     return group + ':' + module + ':' + version;
   }
 }
diff --git a/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ComponentDependencies.java b/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ComponentDependencies.java
new file mode 100644 (file)
index 0000000..e484a1f
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.openapi.externalSystem.model.project.dependencies;
+
+import org.jetbrains.annotations.NotNull;
+
+public interface ComponentDependencies {
+  @NotNull
+  String getComponentName();
+
+  @NotNull
+  DependencyScopeNode getCompileDependenciesGraph();
+
+  @NotNull
+  DependencyScopeNode getRuntimeDependenciesGraph();
+}
diff --git a/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ComponentDependenciesImpl.java b/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ComponentDependenciesImpl.java
new file mode 100644 (file)
index 0000000..2c77670
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.openapi.externalSystem.model.project.dependencies;
+
+import com.intellij.serialization.PropertyMapping;
+import org.jetbrains.annotations.NotNull;
+
+import java.io.Serializable;
+
+public class ComponentDependenciesImpl implements ComponentDependencies, Serializable {
+
+  private final String componentName;
+  private final DependencyScopeNode compileDependencies;
+  private final DependencyScopeNode runtimeDependencies;
+
+  @PropertyMapping({"componentName", "compileDependencies", "runtimeDependencies"})
+  public ComponentDependenciesImpl(@NotNull String componentName,
+                                   @NotNull DependencyScopeNode compileDependencies,
+                                   @NotNull DependencyScopeNode runtimeDependencies) {
+    this.componentName = componentName;
+    this.compileDependencies = compileDependencies;
+    this.runtimeDependencies = runtimeDependencies;
+  }
+
+  @NotNull
+  @Override
+  public String getComponentName() {
+    return componentName;
+  }
+
+  @NotNull
+  @Override
+  public DependencyScopeNode getCompileDependenciesGraph() {
+    return compileDependencies;
+  }
+
+  @NotNull
+  @Override
+  public DependencyScopeNode getRuntimeDependenciesGraph() {
+    return runtimeDependencies;
+  }
+}
diff --git a/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/DependencyNode.java b/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/DependencyNode.java
new file mode 100644 (file)
index 0000000..f59766c
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.openapi.externalSystem.model.project.dependencies;
+
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.util.Set;
+
+public interface DependencyNode {
+  long getId();
+
+  @NotNull
+  String getDisplayName();
+
+  @Nullable
+  String getResolutionState();
+
+  Set<DependencyNode> getDependencies();
+}
diff --git a/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/DependencyScopeNode.java b/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/DependencyScopeNode.java
new file mode 100644 (file)
index 0000000..ad75f51
--- /dev/null
@@ -0,0 +1,36 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.openapi.externalSystem.model.project.dependencies;
+
+import com.intellij.serialization.PropertyMapping;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+public class DependencyScopeNode extends AbstractDependencyNode {
+  private final String scope;
+  private final String displayName;
+  private final String description;
+
+  @PropertyMapping({"id", "scope", "displayName", "description"})
+  public DependencyScopeNode(long id, @NotNull String scope, @NotNull String displayName, @Nullable String description) {
+    super(id);
+    this.displayName = displayName;
+    this.scope = scope;
+    this.description = description;
+  }
+
+  @NotNull
+  public String getScope() {
+    return scope;
+  }
+
+  @NotNull
+  @Override
+  public String getDisplayName() {
+    return displayName;
+  }
+
+  @Nullable
+  public String getDescription() {
+    return description;
+  }
+}
diff --git a/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ProjectDependencies.java b/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ProjectDependencies.java
new file mode 100644 (file)
index 0000000..87dfffc
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.openapi.externalSystem.model.project.dependencies;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.util.List;
+
+public interface ProjectDependencies {
+  @NotNull
+  List<ComponentDependencies> getComponentsDependencies();
+}
diff --git a/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ProjectDependenciesImpl.java b/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ProjectDependenciesImpl.java
new file mode 100644 (file)
index 0000000..30810ca
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.openapi.externalSystem.model.project.dependencies;
+
+import org.jetbrains.annotations.NotNull;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ProjectDependenciesImpl implements ProjectDependencies, Serializable {
+  private final List<ComponentDependencies> dependencies = new ArrayList<ComponentDependencies>(0);
+
+  @NotNull
+  @Override
+  public List<ComponentDependencies> getComponentsDependencies() {
+    return dependencies;
+  }
+
+  public void add(ComponentDependencies componentDependencies) {
+    dependencies.add(componentDependencies);
+  }
+}
diff --git a/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ProjectDependencyNode.java b/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ProjectDependencyNode.java
new file mode 100644 (file)
index 0000000..ac2bc38
--- /dev/null
@@ -0,0 +1,6 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.openapi.externalSystem.model.project.dependencies;
+
+public interface ProjectDependencyNode extends DependencyNode {
+  String getProjectName();
+}
diff --git a/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ProjectDependencyNodeImpl.java b/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ProjectDependencyNodeImpl.java
new file mode 100644 (file)
index 0000000..02ec5de
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.openapi.externalSystem.model.project.dependencies;
+
+import com.intellij.serialization.PropertyMapping;
+import org.jetbrains.annotations.NotNull;
+
+public class ProjectDependencyNodeImpl extends AbstractDependencyNode implements ProjectDependencyNode {
+
+  private final String projectName;
+
+  @PropertyMapping({"id", "projectName"})
+  public ProjectDependencyNodeImpl(long id, String projectName) {
+    super(id);
+    this.projectName = projectName;
+  }
+
+  @Override
+  public String getProjectName() {
+    return projectName;
+  }
+
+  @NotNull
+  @Override
+  public String getDisplayName() {
+    return "project " + projectName;
+  }
+}
diff --git a/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ReferenceNode.java b/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/ReferenceNode.java
new file mode 100644 (file)
index 0000000..40793fe
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.openapi.externalSystem.model.project.dependencies;
+
+import com.intellij.serialization.PropertyMapping;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Set;
+
+public class ReferenceNode implements DependencyNode, Serializable {
+  private final long id;
+
+  @PropertyMapping({"id"})
+  public ReferenceNode(long id) {this.id = id;}
+
+  @Override
+  public long getId() {
+    return id;
+  }
+
+  @NotNull
+  @Override
+  public String getDisplayName() {
+    return "*";
+  }
+
+  @Nullable
+  @Override
+  public String getResolutionState() {
+    return null;
+  }
+
+  @Override
+  public Set<DependencyNode> getDependencies() {
+    return Collections.emptySet();
+  }
+}
diff --git a/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/UnknownDependencyNode.java b/platform/external-system-rt/src/com/intellij/openapi/externalSystem/model/project/dependencies/UnknownDependencyNode.java
new file mode 100644 (file)
index 0000000..058c06a
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package com.intellij.openapi.externalSystem.model.project.dependencies;
+
+import com.intellij.serialization.PropertyMapping;
+import org.jetbrains.annotations.NotNull;
+
+public class UnknownDependencyNode extends AbstractDependencyNode {
+  private final String name;
+
+  @PropertyMapping({"id", "name"})
+  public UnknownDependencyNode(long id, String name) {
+    super(id);
+    this.name = name;
+  }
+
+  @NotNull
+  @Override
+  public String getDisplayName() {
+    return name;
+  }
+}
index deef4d73bd434b9c37329b8d27de6421fae58d70..d6cdb5ee77024b659017cec5395bc2a3a0451bb7 100644 (file)
@@ -5,8 +5,10 @@ import com.intellij.execution.CommandLineUtil;
 import com.intellij.externalSystem.JavaProjectData;
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.externalSystem.model.DataNode;
+import com.intellij.openapi.externalSystem.model.ProjectKeys;
 import com.intellij.openapi.externalSystem.model.project.ModuleData;
 import com.intellij.openapi.externalSystem.model.project.ProjectData;
+import com.intellij.openapi.externalSystem.model.project.dependencies.ProjectDependencies;
 import com.intellij.openapi.externalSystem.rt.execution.ForkedDebuggerConfiguration;
 import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
 import com.intellij.openapi.externalSystem.util.ExternalSystemConstants;
@@ -84,6 +86,7 @@ public class JavaGradleProjectResolver extends AbstractProjectResolverExtension
   public void populateModuleExtraModels(@NotNull IdeaModule gradleModule, @NotNull DataNode<ModuleData> ideModule) {
     populateBuildScriptClasspathData(gradleModule, ideModule);
     populateAnnotationProcessorData(gradleModule, ideModule);
+    populateDependenciesGraphData(gradleModule, ideModule);
     nextResolver.populateModuleExtraModels(gradleModule, ideModule);
   }
 
@@ -165,7 +168,8 @@ public class JavaGradleProjectResolver extends AbstractProjectResolverExtension
     if (buildScriptClasspathModel != null) {
       classpathEntries = ContainerUtil.map(
         buildScriptClasspathModel.getClasspath(),
-        (Function<ClasspathEntryModel, BuildScriptClasspathData.ClasspathEntry>)model -> BuildScriptClasspathData.ClasspathEntry.create(model.getClasses(), model.getSources(), model.getJavadoc()));
+        (Function<ClasspathEntryModel, BuildScriptClasspathData.ClasspathEntry>)model -> BuildScriptClasspathData.ClasspathEntry
+          .create(model.getClasses(), model.getSources(), model.getJavadoc()));
     }
     else {
       classpathEntries = ContainerUtil.emptyList();
@@ -175,6 +179,14 @@ public class JavaGradleProjectResolver extends AbstractProjectResolverExtension
     ideModule.createChild(BuildScriptClasspathData.KEY, buildScriptClasspathData);
   }
 
+  private void populateDependenciesGraphData(@NotNull IdeaModule gradleModule,
+                                             @NotNull DataNode<ModuleData> ideModule) {
+    final ProjectDependencies projectDependencies = resolverCtx.getExtraProject(gradleModule, ProjectDependencies.class);
+    if (projectDependencies != null) {
+      ideModule.createChild(ProjectKeys.DEPENDENCIES_GRAPH, projectDependencies);
+    }
+  }
+
   @Override
   public void enhanceTaskProcessing(@NotNull List<String> taskNames,
                                     @NotNull Consumer<String> initScriptConsumer,
@@ -250,6 +262,6 @@ public class JavaGradleProjectResolver extends AbstractProjectResolverExtension
   @NotNull
   @Override
   public Set<Class<?>> getExtraProjectModelClasses() {
-    return Collections.singleton(AnnotationProcessingModel.class);
+    return ContainerUtil.set(AnnotationProcessingModel.class, ProjectDependencies.class);
   }
 }
index eb768743ab4ad5548c13aebf69b7be558b50d70f..9b560f2bcbdd46ddc100062be84fb8ada797846a 100644 (file)
@@ -87,7 +87,6 @@
     <externalProjectDataService implementation="org.jetbrains.plugins.gradle.service.project.data.CompositeBuildDataService"/>
     <externalProjectDataService implementation="org.jetbrains.plugins.gradle.service.project.data.GradleExtensionsDataService"/>
     <externalProjectDataService implementation="org.jetbrains.plugins.gradle.service.project.data.PerformanceTraceDataService"/>
-    <externalSystemViewContributor implementation="org.jetbrains.plugins.gradle.service.project.view.GradleViewContributor"/>
     <externalProjectStructureCustomizer implementation="org.jetbrains.plugins.gradle.service.project.GradleProjectStructureCustomizer"/>
     <externalIconProvider key="GRADLE" implementationClass="org.jetbrains.plugins.gradle.ui.GradleIconProvider"/>
     <externalExecutionAware key="GRADLE" implementationClass="org.jetbrains.plugins.gradle.service.execution.GradleExecutionAware"/>
diff --git a/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/view/GradleViewContributor.java b/plugins/gradle/src/org/jetbrains/plugins/gradle/service/project/view/GradleViewContributor.java
deleted file mode 100644 (file)
index 8a7ac60..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright 2000-2015 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.service.project.view;
-
-import com.intellij.icons.AllIcons;
-import com.intellij.ide.projectView.PresentationData;
-import com.intellij.openapi.externalSystem.model.DataNode;
-import com.intellij.openapi.externalSystem.model.Key;
-import com.intellij.openapi.externalSystem.model.ProjectKeys;
-import com.intellij.openapi.externalSystem.model.ProjectSystemId;
-import com.intellij.openapi.externalSystem.model.project.ModuleData;
-import com.intellij.openapi.externalSystem.util.Order;
-import com.intellij.openapi.externalSystem.view.ExternalProjectsView;
-import com.intellij.openapi.externalSystem.view.ExternalSystemNode;
-import com.intellij.openapi.externalSystem.view.ExternalSystemViewContributor;
-import com.intellij.openapi.util.text.StringUtil;
-import com.intellij.util.SmartList;
-import com.intellij.util.containers.MultiMap;
-import org.jetbrains.annotations.NotNull;
-import org.jetbrains.annotations.Nullable;
-import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData;
-import org.jetbrains.plugins.gradle.util.GradleConstants;
-
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.List;
-
-/**
- * @author Vladislav.Soroka
- */
-public class GradleViewContributor extends ExternalSystemViewContributor {
-  private static final Key<?>[] KEYS = new Key[]{
-    GradleSourceSetData.KEY,
-  };
-
-
-  @NotNull
-  @Override
-  public ProjectSystemId getSystemId() {
-    return GradleConstants.SYSTEM_ID;
-  }
-
-  @NotNull
-  @Override
-  public List<Key<?>> getKeys() {
-    return Arrays.asList(KEYS);
-  }
-
-  @NotNull
-  @Override
-  public List<ExternalSystemNode<?>> createNodes(ExternalProjectsView externalProjectsView, MultiMap<Key<?>, DataNode<?>> dataNodes) {
-    final List<ExternalSystemNode<?>> result = new SmartList<>();
-    addCustomSourceSetsNodes(externalProjectsView, dataNodes, result);
-    return result;
-  }
-
-  @Nullable
-  @Override
-  public String getDisplayName(@NotNull DataNode node) {
-    if (ProjectKeys.MODULE.equals(node.getKey())) {
-      return ((ModuleData)node.getData()).getId();
-    }
-    return super.getDisplayName(node);
-  }
-
-  private static void addCustomSourceSetsNodes(@NotNull ExternalProjectsView externalProjectsView,
-                                               @NotNull MultiMap<Key<?>, DataNode<?>> dataNodes,
-                                               @NotNull List<ExternalSystemNode<?>> result) {
-    final Collection<DataNode<?>> sourceSetsDataNodes = dataNodes.get(GradleSourceSetData.KEY);
-    if (!sourceSetsDataNodes.isEmpty()) {
-      final ExternalSystemNode sourceSetsNode = new SourceSetsNode(externalProjectsView);
-      for (DataNode<?> dataNode : sourceSetsDataNodes) {
-        //noinspection unchecked
-        sourceSetsNode.add(new SourceSetNode(externalProjectsView, (DataNode<GradleSourceSetData>)dataNode));
-      }
-      result.add(sourceSetsNode);
-    }
-  }
-
-  @Order(ExternalSystemNode.BUILTIN_TASKS_DATA_NODE_ORDER - 1)
-  private static class SourceSetsNode extends ExternalSystemNode {
-    SourceSetsNode(ExternalProjectsView externalProjectsView) {
-      //noinspection unchecked
-      super(externalProjectsView, null, null);
-    }
-
-    @Override
-    protected void update(@NotNull PresentationData presentation) {
-      super.update(presentation);
-      presentation.setIcon(AllIcons.Nodes.ModuleGroup);
-    }
-
-    @Override
-    public String getName() {
-      return "Source Sets";
-    }
-  }
-
-  private static class SourceSetNode extends ExternalSystemNode<GradleSourceSetData> {
-
-    SourceSetNode(ExternalProjectsView externalProjectsView, DataNode<GradleSourceSetData> dataNode) {
-      super(externalProjectsView, null, dataNode);
-    }
-
-    @Override
-    protected void update(@NotNull PresentationData presentation) {
-      super.update(presentation);
-      presentation.setIcon(AllIcons.Modules.SourceFolder);
-
-      final GradleSourceSetData data = getData();
-      if (data != null) {
-        setNameAndTooltip(getName(), null);
-      }
-    }
-
-    @Override
-    public String getName() {
-      final GradleSourceSetData data = getData();
-      return data != null ? StringUtil.substringAfter(data.getExternalName(), ":") : "";
-    }
-  }
-}
index abfc5708b637c6dff9ffd0ade4afa85ddbbd2b72..8b3162d1b3b4211b95b514c2c5da33ef486851d4 100644 (file)
@@ -254,7 +254,7 @@ public class GradleTaskManager extends BaseExternalSystemTaskManager<GradleExecu
                                    @Nullable TaskCallback callback) {
 
     String taskName = taskClass.getSimpleName();
-    String paths = GradleExecutionHelper.getToolingExtensionsJarPaths(set(taskClass, GsonBuilder.class));
+    String paths = GradleExecutionHelper.getToolingExtensionsJarPaths(set(taskClass, GsonBuilder.class, ExternalSystemException.class));
     String initScript = "initscript {\n" +
                         "  dependencies {\n" +
                         "    classpath files(" + paths + ")\n" +
index 7eee4e7f9403881cb703b3c0776d4b3576d22ef0..ec4a979ea600eb35d668e272f5c89ff14ac996c6 100644 (file)
@@ -19,6 +19,7 @@ org.jetbrains.plugins.gradle.tooling.builder.EarModelBuilderImpl
 org.jetbrains.plugins.gradle.tooling.builder.ModelBuildScriptClasspathBuilderImpl
 org.jetbrains.plugins.gradle.tooling.builder.ScalaModelBuilderImpl
 org.jetbrains.plugins.gradle.tooling.builder.ExternalProjectBuilderImpl
+org.jetbrains.plugins.gradle.tooling.builder.DependencyGraphModelBuilderImpl
 org.jetbrains.plugins.gradle.tooling.builder.ExternalTestsModelBuilderImpl
 org.jetbrains.plugins.gradle.tooling.builder.ProjectExtensionsDataBuilderImpl
 org.jetbrains.plugins.gradle.tooling.builder.IntelliJSettingsBuilder
diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/DependencyGraphModelBuilderImpl.groovy b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/builder/DependencyGraphModelBuilderImpl.groovy
new file mode 100644 (file)
index 0000000..18a6cbd
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
+package org.jetbrains.plugins.gradle.tooling.builder
+
+import com.intellij.openapi.externalSystem.model.project.dependencies.ComponentDependenciesImpl
+import com.intellij.openapi.externalSystem.model.project.dependencies.DependencyScopeNode
+import com.intellij.openapi.externalSystem.model.project.dependencies.ProjectDependencies
+import com.intellij.openapi.externalSystem.model.project.dependencies.ProjectDependenciesImpl
+import groovy.transform.CompileStatic
+import org.gradle.api.Project
+import org.gradle.util.GradleVersion
+import org.jetbrains.annotations.NotNull
+import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder
+import org.jetbrains.plugins.gradle.tooling.ModelBuilderService
+import org.jetbrains.plugins.gradle.tooling.tasks.DependenciesReport
+import org.jetbrains.plugins.gradle.tooling.util.JavaPluginUtil
+
+@CompileStatic
+class DependencyGraphModelBuilderImpl implements ModelBuilderService {
+  def compileClasspathConfigurationAvailable = GradleVersion.current().baseVersion >= GradleVersion.version("2.12")
+  def runtimeClasspathConfigurationAvailable = GradleVersion.current().baseVersion >= GradleVersion.version("3.4")
+
+  @Override
+  boolean canBuild(String modelName) {
+    return ProjectDependencies.name == modelName
+  }
+
+  @Override
+  Object buildAll(String modelName, Project project) {
+    def resolveSourceSetDependencies = System.properties.'idea.resolveSourceSetDependencies' as boolean
+    if (!resolveSourceSetDependencies) return null
+
+    def sourceSetContainer = JavaPluginUtil.getSourceSetContainer(project)
+    if (sourceSetContainer == null) return null
+
+    ProjectDependenciesImpl dependencies = new ProjectDependenciesImpl()
+    for (sourceSet in sourceSetContainer) {
+      def compileConfigurationName =
+        compileClasspathConfigurationAvailable ? sourceSet.compileClasspathConfigurationName : sourceSet.compileConfigurationName
+      def compileConfiguration = project.configurations.findByName(compileConfigurationName)
+      if (compileConfiguration == null) continue
+
+      def runtimeConfigurationName =
+        runtimeClasspathConfigurationAvailable ? sourceSet.runtimeClasspathConfigurationName : sourceSet.runtimeConfigurationName
+      def runtimeConfiguration = project.configurations.findByName(runtimeConfigurationName)
+      if (runtimeConfiguration == null) continue
+
+      DependencyScopeNode compileScopeNode = DependenciesReport.buildDependenciesGraph(compileConfiguration, project)
+      DependencyScopeNode runtimeScopeNode = DependenciesReport.buildDependenciesGraph(runtimeConfiguration, project)
+
+      if (!compileScopeNode.dependencies.isEmpty() || !runtimeScopeNode.dependencies.isEmpty()) {
+        dependencies.add(new ComponentDependenciesImpl(sourceSet.name, compileScopeNode, runtimeScopeNode))
+      }
+    }
+
+    return dependencies.componentsDependencies.isEmpty() ? null : dependencies
+  }
+
+
+  @NotNull
+  @Override
+  ErrorMessageBuilder getErrorMessageBuilder(@NotNull Project project, @NotNull Exception e) {
+    return ErrorMessageBuilder.create(project, e, "Dependency graph model errors")
+  }
+}
diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/AbstractComponentNode.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/AbstractComponentNode.java
deleted file mode 100644 (file)
index 43a2723..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
-package org.jetbrains.plugins.gradle.tooling.tasks;
-
-import java.util.LinkedHashSet;
-import java.util.Set;
-
-public abstract class AbstractComponentNode implements ComponentNode {
-  private final long id;
-  private final Set<ComponentNode> children = new LinkedHashSet<ComponentNode>();
-  private String state;
-
-  protected AbstractComponentNode(long id) {this.id = id;}
-
-  @Override
-  public long getId() {
-    return id;
-  }
-
-  abstract String getDisplayName();
-
-  public Set<ComponentNode> getChildren() {
-    return children;
-  }
-
-  public String getState() {
-    return state;
-  }
-
-  public void setState(String state) {
-    this.state = state;
-  }
-}
diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/BaseComponentNode.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/BaseComponentNode.java
deleted file mode 100644 (file)
index 920f48b..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
-package org.jetbrains.plugins.gradle.tooling.tasks;
-
-public class BaseComponentNode extends AbstractComponentNode {
-  private final String name;
-
-  public BaseComponentNode(long id, String name) {
-    super(id);
-    this.name = name;
-  }
-
-  @Override
-  public String getDisplayName() {
-    return name;
-  }
-}
diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/ComponentNode.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/ComponentNode.java
deleted file mode 100644 (file)
index 3e7d9af..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
-package org.jetbrains.plugins.gradle.tooling.tasks;
-
-public interface ComponentNode {
-  long getId();
-}
diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/ConfigurationNode.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/ConfigurationNode.java
deleted file mode 100644 (file)
index f2cfa31..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
-package org.jetbrains.plugins.gradle.tooling.tasks;
-
-public class ConfigurationNode extends AbstractComponentNode {
-  private final String projectPath;
-  private final String configurationName;
-
-  public ConfigurationNode(long id, String projectPath, String configurationName) {
-    super(id);
-    this.projectPath = projectPath;
-    this.configurationName = configurationName;
-  }
-
-  public String getConfigurationName() {
-    return configurationName;
-  }
-
-  @Override
-  String getDisplayName() {
-    return "project " + projectPath + " (" + configurationName + ")";
-  }
-}
index c4b75e8dc47cc2d6252ecdcca6040a5642d419b4..f945e46e4ffd8b90bdd37c537be8492a81667591 100644 (file)
@@ -2,8 +2,10 @@
 package org.jetbrains.plugins.gradle.tooling.tasks
 
 import com.google.gson.GsonBuilder
+import com.intellij.openapi.externalSystem.model.project.dependencies.*
 import groovy.transform.CompileStatic
 import org.gradle.api.DefaultTask
+import org.gradle.api.Project
 import org.gradle.api.artifacts.Configuration
 import org.gradle.api.artifacts.component.ModuleComponentIdentifier
 import org.gradle.api.artifacts.component.ProjectComponentIdentifier
@@ -13,6 +15,7 @@ import org.gradle.api.tasks.OutputFile
 import org.gradle.api.tasks.TaskAction
 import org.gradle.api.tasks.diagnostics.internal.graph.nodes.RenderableDependency
 import org.gradle.api.tasks.diagnostics.internal.graph.nodes.RenderableModuleResult
+import org.gradle.util.GradleVersion
 
 @CompileStatic
 class DependenciesReport extends DefaultTask {
@@ -32,67 +35,88 @@ class DependenciesReport extends DefaultTask {
       configurationList = new ArrayList<>()
       for (configurationName in configurations) {
         def configuration = project.configurations.findByName(configurationName)
-        if(configuration != null) {
+        if (configuration != null) {
           configurationList.add(configuration)
         }
       }
     }
 
-    List<ConfigurationNode> graph = []
+    def projectNameFunction = new ProjectNameFunction()
+    List<DependencyScopeNode> graph = []
     for (configuration in configurationList) {
       if (!configuration.isCanBeResolved()) continue
-      graph.add(buildDependenciesGraph(configuration, project.path))
+      graph.add(doBuildDependenciesGraph(configuration, project, projectNameFunction))
     }
     outputFile.parentFile.mkdirs()
     outputFile.text = new GsonBuilder().create().toJson(graph)
   }
 
-  static ConfigurationNode buildDependenciesGraph(Configuration configuration, String projectPath) {
+  static DependencyScopeNode buildDependenciesGraph(Configuration configuration, Project project) {
+    return doBuildDependenciesGraph(configuration, project, new ProjectNameFunction())
+  }
+
+  private static DependencyScopeNode doBuildDependenciesGraph(Configuration configuration,
+                                                              Project project,
+                                                              ProjectNameFunction projectNameFunction) {
+    if (!project.configurations.contains(configuration)) {
+      throw new IllegalArgumentException("configurations of the project should be used")
+    }
     ResolutionResult resolutionResult = configuration.getIncoming().getResolutionResult()
     RenderableDependency root = new RenderableModuleResult(resolutionResult.root)
     String configurationName = configuration.name
     IdGenerator idGenerator = new IdGenerator()
     long id = idGenerator.getId(root, configurationName)
-    AbstractComponentNode node = new ConfigurationNode(id, projectPath, configurationName)
-    node.setState(root.resolutionState.name())
+    String scopeDisplayName = "project " + project.path + " (" + configurationName + ")"
+    DependencyScopeNode node = new DependencyScopeNode(id, configurationName, scopeDisplayName, configuration.getDescription())
+    node.setResolutionState(root.resolutionState.name())
+    Map<Object, DependencyNode> added = [:]
     for (RenderableDependency child in root.getChildren()) {
-      node.children.add(toNode(child, configurationName, [:], idGenerator))
+      node.dependencies.add(toNode(child, configurationName, added, idGenerator, projectNameFunction))
     }
     return node
   }
 
-  static private ComponentNode toNode(RenderableDependency dependency,
-                                      String configurationName,
-                                      Map<Object, ComponentNode> added,
-                                      IdGenerator idGenerator) {
+  static private DependencyNode toNode(RenderableDependency dependency,
+                                       String configurationName,
+                                       Map<Object, DependencyNode> added,
+                                       IdGenerator idGenerator,
+                                       ProjectNameFunction projectNameFunction) {
     long id = idGenerator.getId(dependency, configurationName)
-    ComponentNode alreadySeenNode = added.get(id)
+    DependencyNode alreadySeenNode = added.get(id)
     if (alreadySeenNode != null) {
       return new ReferenceNode(id)
     }
 
-    AbstractComponentNode node
+    AbstractDependencyNode node
     if (dependency.id instanceof ProjectComponentIdentifier) {
       ProjectComponentIdentifier projectId = dependency.id as ProjectComponentIdentifier
-      node = new ProjectComponentNode(id, projectId.projectPath)
+      node = new ProjectDependencyNodeImpl(id, projectNameFunction.fun(projectId))
     }
     else if (dependency.id instanceof ModuleComponentIdentifier) {
       ModuleComponentIdentifier moduleId = dependency.id as ModuleComponentIdentifier
-      node = new ArtifactComponentNode(id, moduleId.group, moduleId.module, moduleId.version)
+      node = new ArtifactDependencyNodeImpl(id, moduleId.group, moduleId.module, moduleId.version)
     }
     else {
-      node = new BaseComponentNode(id, dependency.name)
+      node = new UnknownDependencyNode(id, dependency.name)
     }
-    node.setState(dependency.resolutionState.name())
+    node.setResolutionState(dependency.resolutionState.name())
     added.put(id, node)
     Iterator<? extends RenderableDependency> iterator = dependency.getChildren().iterator()
-    while(iterator.hasNext()) {
+    while (iterator.hasNext()) {
       RenderableDependency child = iterator.next()
-      node.children.add(toNode(child, configurationName, added, idGenerator))
+      node.dependencies.add(toNode(child, configurationName, added, idGenerator, projectNameFunction))
     }
     return node
   }
 
+  static class ProjectNameFunction {
+    def is45OrNewer = GradleVersion.current() >= GradleVersion.version("4.5")
+
+    String fun(ProjectComponentIdentifier identifier) {
+      return is45OrNewer ? identifier.projectName : identifier.projectPath
+    }
+  }
+
   private static class IdGenerator {
     private Map<String, Long> idMap = new HashMap<>()
     private long value
@@ -100,7 +124,7 @@ class DependenciesReport extends DefaultTask {
     private long getId(RenderableDependency dependency, String configurationName) {
       def key = dependency.id.toString() + '_' + configurationName
       def id = idMap.get(key)
-      if(id == null) {
+      if (id == null) {
         idMap[key] = ++value
         id = value
       }
@@ -2,28 +2,29 @@
 package org.jetbrains.plugins.gradle.tooling.tasks;
 
 import com.google.gson.*;
+import com.intellij.openapi.externalSystem.model.project.dependencies.*;
 
 import java.lang.reflect.Type;
 
-public class ComponentNodeDeserializer implements JsonDeserializer<ComponentNode> {
+public class DependencyNodeDeserializer implements JsonDeserializer<DependencyNode> {
 
   @Override
-  public ComponentNode deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
+  public DependencyNode deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
     JsonObject jsonObject = json.getAsJsonObject();
     if (jsonObject.get("configurationName") != null) {
-      return context.deserialize(json, ConfigurationNode.class);
+      return context.deserialize(json, DependencyScopeNode.class);
     }
     else if (jsonObject.get("projectPath") != null) {
-      return context.deserialize(json, ProjectComponentNode.class);
+      return context.deserialize(json, ProjectDependencyNodeImpl.class);
     }
     else if (jsonObject.get("module") != null) {
-      return context.deserialize(json, ArtifactComponentNode.class);
+      return context.deserialize(json, ArtifactDependencyNodeImpl.class);
     }
     else if (jsonObject.size() == 1 && jsonObject.get("id") != null) {
       return context.deserialize(json, ReferenceNode.class);
     }
     else {
-      return context.deserialize(json, BaseComponentNode.class);
+      return context.deserialize(json, UnknownDependencyNode.class);
     }
   }
 }
\ No newline at end of file
diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/ProjectComponentNode.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/ProjectComponentNode.java
deleted file mode 100644 (file)
index c5c9fd9..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
-package org.jetbrains.plugins.gradle.tooling.tasks;
-
-public class ProjectComponentNode extends AbstractComponentNode {
-
-  private final String projectPath;
-
-  public ProjectComponentNode(long id, String projectPath) {
-    super(id);
-    this.projectPath = projectPath;
-  }
-
-  public String getProjectPath() {
-    return projectPath;
-  }
-
-  @Override
-  String getDisplayName() {
-    return "project " + projectPath;
-  }
-}
diff --git a/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/ReferenceNode.java b/plugins/gradle/tooling-extension-impl/src/org/jetbrains/plugins/gradle/tooling/tasks/ReferenceNode.java
deleted file mode 100644 (file)
index 6e318c7..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
-package org.jetbrains.plugins.gradle.tooling.tasks;
-
-public class ReferenceNode implements ComponentNode {
-  private final long id;
-
-  public ReferenceNode(long id) {this.id = id;}
-
-  @Override
-  public long getId() {
-    return id;
-  }
-}