ibabiankou commented on a change in pull request #144:
URL: https://github.com/apache/maven-resolver/pull/144#discussion_r785445022



##########
File path: 
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/NodeQueue.java
##########
@@ -19,58 +19,53 @@
  * under the License.
  */
 
-import java.util.Arrays;
-
 import org.eclipse.aether.artifact.Artifact;
 import org.eclipse.aether.graph.DependencyNode;
 
+import java.util.ArrayDeque;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Queue;
+
+
 /**
  * @see DefaultDependencyCollector
  */
-final class NodeStack
+final class NodeQueue
 {
-
-    @SuppressWarnings( {"unchecked", "checkstyle:magicnumber" } )
-    // CHECKSTYLE_OFF: MagicNumber
-    private DependencyNode[] nodes = new DependencyNode[96];
-    // CHECKSTYLE_ON: MagicNumber
-
-    private int size;
+    Queue<DependencyNode> queue = new ArrayDeque<>();
 
     public DependencyNode top()
     {
-        if ( size <= 0 )
-        {
-            throw new IllegalStateException( "stack empty" );
-        }
-        return nodes[size - 1];
+        return queue.element();
     }
 
     public void push( DependencyNode node )
     {
-        if ( size >= nodes.length )
-        {
-            DependencyNode[] tmp = new DependencyNode[size + 64];
-            System.arraycopy( nodes, 0, tmp, 0, nodes.length );
-            nodes = tmp;
-        }
-        nodes[size++] = node;
+        queue.add( node );
     }
 
-    public void pop()
+    public DependencyNode remove()
     {
-        if ( size <= 0 )
-        {
-            throw new IllegalStateException( "stack empty" );
-        }
-        size--;
+        return queue.remove();
+    }
+
+    public DependencyNode poll()

Review comment:
       Method seems to be unused.

##########
File path: 
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollector.java
##########
@@ -253,13 +253,28 @@ public CollectResult collectDependencies( 
RepositorySystemSession session, Colle
             DefaultVersionFilterContext versionContext = new 
DefaultVersionFilterContext( session );
 
             Args args = new Args( session, trace, pool, nodes, context, 
versionContext, request );
-            Results results = new Results( result, session );
 
-            process( args, results, dependencies, repositories,
-                     depSelector != null ? depSelector.deriveChildSelector( 
context ) : null,
-                     depManager != null ? depManager.deriveChildManager( 
context ) : null,
-                     depTraverser != null ? depTraverser.deriveChildTraverser( 
context ) : null,
-                     verFilter != null ? verFilter.deriveChildFilter( context 
) : null );
+            DataPool.DependencyNodeTraceContext rootTraceContext =
+                    new DataPool.DependencyNodeTraceContext(
+                            depSelector != null ? 
depSelector.deriveChildSelector( context ) : null,
+                            depManager != null ? 
depManager.deriveChildManager( context ) : null,
+                            depTraverser != null ? 
depTraverser.deriveChildTraverser( context ) : null,
+                            verFilter != null ? verFilter.deriveChildFilter( 
context ) : null, repositories,
+                            dependencies,
+                            managedDependencies, args.pool.getAllNodes( node 
), traverse );
+            rootTraceContext.isRoot = true;
+            args.pool.putTraceContext( node, rootTraceContext );
+
+            Results results = new Results( result, session );
+            while ( !args.nodes.isEmpty() )
+            {
+                DependencyNode current = args.nodes.top();
+                if ( current != null )
+                {
+                    processNode( args, results, current );
+                    args.nodes.remove();
+                }
+            }

Review comment:
       This `null` check seems to be redundant here. We never put `null` into 
the queue and `top()` would throw an exception if the queue is empty, which 
should never be the case according to the while loop. 
   ```suggestion
               while ( !args.nodes.isEmpty() )
               {
                   processNode( args, results, args.nodes.remove() );
               }
   ```

##########
File path: 
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollector.java
##########
@@ -343,36 +358,75 @@ private static String getId( Artifact a )
         return a.getGroupId() + ':' + a.getArtifactId() + ':' + 
a.getClassifier() + ':' + a.getExtension();
     }
 
+    private void processNode( Args args, Results results, DependencyNode 
current )
+    {
+        DataPool.DependencyNodeTraceContext traceContext = 
args.pool.getTraceContext( current );
+        if ( traceContext == null || !traceContext.recursive )
+        {
+            return;
+        }
+
+        DependencySelector selector = traceContext.depSelector;
+        DependencyManager manager = traceContext.depManager;
+        DependencyTraverser traverser = traceContext.depTraverser;
+        VersionFilter filter = traceContext.verFilter;
+
+        if ( traceContext.isRoot )
+        {
+            //Should not cache the children of root node just like original 
DFS solution

Review comment:
       Let's try to figure out why this is important and add a comment 
explaining why it should not be cached (rather than referencing old logic that 
is not easily available). Otherwise, let's drop this part, I don't see how 
caching might harm here.

##########
File path: 
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/NodeQueue.java
##########
@@ -19,58 +19,53 @@
  * under the License.
  */
 
-import java.util.Arrays;
-
 import org.eclipse.aether.artifact.Artifact;
 import org.eclipse.aether.graph.DependencyNode;
 
+import java.util.ArrayDeque;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Queue;
+
+
 /**
  * @see DefaultDependencyCollector
  */
-final class NodeStack
+final class NodeQueue

Review comment:
       This class is merely a wrapper around the queue now and the `find` 
method has little to do with the queue.
   I would move the find method to `DefaultDependencyCycle` (It also can be a 
static utility method) and delete this class in favor of using Queue directly. 
   

##########
File path: 
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollector.java
##########
@@ -343,36 +358,75 @@ private static String getId( Artifact a )
         return a.getGroupId() + ':' + a.getArtifactId() + ':' + 
a.getClassifier() + ':' + a.getExtension();
     }
 
+    private void processNode( Args args, Results results, DependencyNode 
current )
+    {
+        DataPool.DependencyNodeTraceContext traceContext = 
args.pool.getTraceContext( current );
+        if ( traceContext == null || !traceContext.recursive )
+        {
+            return;
+        }
+
+        DependencySelector selector = traceContext.depSelector;
+        DependencyManager manager = traceContext.depManager;
+        DependencyTraverser traverser = traceContext.depTraverser;
+        VersionFilter filter = traceContext.verFilter;
+
+        if ( traceContext.isRoot )
+        {
+            //Should not cache the children of root node just like original 
DFS solution
+            process( args, results, traceContext );
+            return;
+        }
+
+        Object key =
+                args.pool.toKey( current.getArtifact(), 
traceContext.repositories, selector, manager, traverser,
+                        filter );
+
+        if ( args.pool.getChildren( key ) != null )
+        {
+            current.setChildren( args.pool.getChildren( key ) );
+        }
+        else
+        {
+            process( args, results, traceContext );
+            args.pool.putChildren( key, current.getChildren() );
+        }
+    }
+
     @SuppressWarnings( "checkstyle:parameternumber" )
-    private void process( final Args args, Results results, List<Dependency> 
dependencies,
-                          List<RemoteRepository> repositories, 
DependencySelector depSelector,
-                          DependencyManager depManager, DependencyTraverser 
depTraverser, VersionFilter verFilter )
+    private void process( final Args args, Results results, 
DataPool.DependencyNodeTraceContext traceContext )
     {
-        for ( Dependency dependency : dependencies )
+
+        for ( Dependency dependency : traceContext.dependencies )
         {
-            processDependency( args, results, repositories, depSelector, 
depManager, depTraverser, verFilter,
-                               dependency );
+            processDependency( args, results, traceContext,
+                    dependency );

Review comment:
       nit: this should be on the same line now (same holds for a few other 
places).
   ```suggestion
               processDependency( args, results, traceContext, dependency );
   ```

##########
File path: 
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DataPool.java
##########
@@ -182,6 +187,89 @@ public void putChildren( Object key, List<DependencyNode> 
children )
         nodes.put( key, children );
     }
 
+    public DependencyNodeTraceContext getTraceContext( DependencyNode node )
+    {
+        return nodeTraceContexts.get( node );
+    }
+
+    public void putTraceContext( DependencyNode node, 
DependencyNodeTraceContext context )
+    {
+        nodeTraceContexts.put( node, context );
+    }
+
+    public void putParent( DependencyNode node, DependencyNode parent )
+    {
+        nodeParents.put( node, parent );
+    }
+
+
+    /**
+     * Get all parents of current node (including current node) following the 
top-down sequence (parent -> child)
+     *
+     * @return
+     */
+    public List<DependencyNode> getAllNodes( DependencyNode current )
+    {
+        return getAllNodes( current, true );
+    }
+
+    public List<DependencyNode> getAllNodes( DependencyNode current, boolean 
reverse )
+    {
+        List<DependencyNode> nodes = new ArrayList<>();
+        nodes.add( current );
+
+        DependencyNode parent = nodeParents.get( current );
+        while ( parent != null )
+        {
+            nodes.add( parent );
+            parent = nodeParents.get( parent );
+        }
+
+        if ( reverse )
+        {
+            Collections.reverse( nodes );
+        }
+        return nodes;
+    }
+
+    /**
+     * Trace the objects required for inheritance
+     */
+    static final class DependencyNodeTraceContext
+    {
+        DependencySelector depSelector;
+        DependencyManager depManager;
+        DependencyTraverser depTraverser;
+        VersionFilter verFilter;
+        List<RemoteRepository> repositories;
+        List<Dependency> dependencies;
+        List<Dependency> managedDependencies;
+        List<DependencyNode> allNodes;
+        boolean isRoot;
+        boolean recursive;
+
+        @SuppressWarnings( "checkstyle:parameternumber" )
+        DependencyNodeTraceContext( DependencySelector depSelector,
+                                    DependencyManager depManager,
+                                    DependencyTraverser depTraverser,
+                                    VersionFilter verFilter,
+                                    List<RemoteRepository> repositories,
+                                    List<Dependency> dependencies,
+                                    List<Dependency> managedDependencies, 
List<DependencyNode> allNodes,
+                                    boolean recursive )

Review comment:
       It looks like this parameter is always `true`, therefore can be deleted.

##########
File path: 
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollector.java
##########
@@ -343,36 +358,75 @@ private static String getId( Artifact a )
         return a.getGroupId() + ':' + a.getArtifactId() + ':' + 
a.getClassifier() + ':' + a.getExtension();
     }
 
+    private void processNode( Args args, Results results, DependencyNode 
current )
+    {
+        DataPool.DependencyNodeTraceContext traceContext = 
args.pool.getTraceContext( current );
+        if ( traceContext == null || !traceContext.recursive )
+        {
+            return;
+        }
+
+        DependencySelector selector = traceContext.depSelector;
+        DependencyManager manager = traceContext.depManager;
+        DependencyTraverser traverser = traceContext.depTraverser;
+        VersionFilter filter = traceContext.verFilter;
+
+        if ( traceContext.isRoot )
+        {
+            //Should not cache the children of root node just like original 
DFS solution
+            process( args, results, traceContext );
+            return;
+        }
+
+        Object key =
+                args.pool.toKey( current.getArtifact(), 
traceContext.repositories, selector, manager, traverser,
+                        filter );
+
+        if ( args.pool.getChildren( key ) != null )
+        {
+            current.setChildren( args.pool.getChildren( key ) );
+        }
+        else
+        {
+            process( args, results, traceContext );
+            args.pool.putChildren( key, current.getChildren() );
+        }
+    }
+
     @SuppressWarnings( "checkstyle:parameternumber" )
-    private void process( final Args args, Results results, List<Dependency> 
dependencies,
-                          List<RemoteRepository> repositories, 
DependencySelector depSelector,
-                          DependencyManager depManager, DependencyTraverser 
depTraverser, VersionFilter verFilter )
+    private void process( final Args args, Results results, 
DataPool.DependencyNodeTraceContext traceContext )
     {
-        for ( Dependency dependency : dependencies )
+
+        for ( Dependency dependency : traceContext.dependencies )
         {
-            processDependency( args, results, repositories, depSelector, 
depManager, depTraverser, verFilter,
-                               dependency );
+            processDependency( args, results, traceContext,
+                    dependency );
         }
     }
 
     @SuppressWarnings( "checkstyle:parameternumber" )
-    private void processDependency( Args args, Results results, 
List<RemoteRepository> repositories,
-                                    DependencySelector depSelector, 
DependencyManager depManager,
-                                    DependencyTraverser depTraverser, 
VersionFilter verFilter, Dependency dependency )
+    private void processDependency( Args args, Results results, 
DataPool.DependencyNodeTraceContext traceContext,
+                                    Dependency dependency )
     {
 
         List<Artifact> relocations = Collections.emptyList();
-        processDependency( args, results, repositories, depSelector, 
depManager, depTraverser, verFilter, dependency,
-                           relocations, false );
+        boolean disableVersionManagement = false;
+        processDependency( args, results, traceContext, dependency,
+                relocations, disableVersionManagement );

Review comment:
       `disableVersionManagement` was inlined in the previous commit, why 
change it back? 
   The method itself is used in one place only, I would drop it entirely.

##########
File path: 
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DataPool.java
##########
@@ -71,6 +72,10 @@
 
     private final Map<Object, List<DependencyNode>> nodes = new HashMap<>( 256 
);
 
+    private Map<DependencyNode, DependencyNodeTraceContext> nodeTraceContexts 
= new HashMap<>( 256 );
+
+    private Map<DependencyNode, DependencyNode> nodeParents = new HashMap<>( 
256 );
+

Review comment:
       It looks like we can avoid having these two maps:
   1. `nodeTraceContexts` : Trace context already has the dependency node in 
it, so by keeping these contexts in the queue instead of the nodes we can drop 
this map.
   2. `nodeParents` : The context already has all the parents of the node, so 
if we merely add there the node of the next level, we can drop this map.

##########
File path: 
maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollector.java
##########
@@ -343,36 +358,75 @@ private static String getId( Artifact a )
         return a.getGroupId() + ':' + a.getArtifactId() + ':' + 
a.getClassifier() + ':' + a.getExtension();
     }
 
+    private void processNode( Args args, Results results, DependencyNode 
current )
+    {
+        DataPool.DependencyNodeTraceContext traceContext = 
args.pool.getTraceContext( current );
+        if ( traceContext == null || !traceContext.recursive )
+        {
+            return;
+        }

Review comment:
       IIUC this can not happen.




-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


Reply via email to