Summary
dependency:analyze -Dverbose prints every dependency in both the warning section and the "Ignored" section when no ignoredDependencies are configured. The "Ignored" section should be empty (or omitted) in this case.
Root cause
AbstractAnalyzeMojo.filterDependencies() at line 563 returns the full input artifacts set when excludes is null or empty:
if (excludes == null || excludes.length == 0) {
return artifacts;
}
The method's contract is: given a source set and exclude patterns, remove artifacts that match an exclude pattern from the source (via Iterator.remove()) and return the removed (excluded) artifacts in a new set. When no patterns are given, nothing can match, so the method should return an empty set — nothing was excluded. Returning the full artifacts set instead tells every caller "everything was excluded."
This affects all 8 call sites in the analyze goal (lines 363, 365, 367, 368, 369, 372, 374, 375). With default configuration (no ignoredDependencies, ignoredUsedUndeclaredDependencies, etc. set), every artifact flows into the corresponding ignored* set, and with -Dverbose the same artifacts appear duplicated under both the warning and ignored sections.
The mutation loop (it.remove()) is correctly skipped in this path, so the real warning output is not suppressed — but the ignored section is filled with noise.
To reproduce
reproducer-verbose-duplicate.tar.gz
Extract and rebuild the plugin from source:
git clone https://github.com/apache/maven-dependency-plugin.git
cd maven-dependency-plugin
mvn -DskipTests '-Dmaven.compiler.release=' install
cd ..
tar xzf reproducer-verbose-duplicate.tar.gz
cd dep-analyze-verbose-repro
mvn org.apache.maven.plugins:maven-dependency-plugin:3.11.0:analyze -Dverbose
Observe that commons-lang3 and commons-text each appear in both the warning section and the ignored section — even though no ignoredDependencies is configured.
Expected behavior
With no ignoredDependencies configured, the "Ignored" sections should be not printed at all.
[INFO]
[INFO] --- dependency:3.11.0:analyze (default-cli) @ dep-analyze-verbose-repro ---
[WARNING] Used undeclared dependencies found:
[WARNING] org.apache.commons:commons-lang3:jar:3.12.0:compile
[WARNING] class org.apache.commons.lang3.StringUtils
[WARNING] Unused declared dependencies found:
[WARNING] org.apache.commons:commons-text:jar:1.10.0:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
Actual output
[INFO]
[INFO] --- dependency:3.11.0:analyze (default-cli) @ dep-analyze-verbose-repro ---
[WARNING] Used undeclared dependencies found:
[WARNING] org.apache.commons:commons-lang3:jar:3.12.0:compile
[WARNING] class org.apache.commons.lang3.StringUtils
[WARNING] Unused declared dependencies found:
[WARNING] org.apache.commons:commons-text:jar:1.10.0:compile
[INFO] Ignored used undeclared dependencies:
[INFO] org.apache.commons:commons-lang3:jar:3.12.0:compile
[INFO] Ignored unused declared dependencies:
[INFO] org.apache.commons:commons-text:jar:1.10.0:compile
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
Proposed fix
The fix is a one-line change in filterDependencies:
// line 563 of AbstractAnalyzeMojo.java
if (excludes == null || excludes.length == 0) {
return Collections.emptySet();
}
This returns an empty set when no exclude patterns are provided, correctly communicating "nothing was excluded" to all callers.
Summary
dependency:analyze -Dverboseprints every dependency in both the warning section and the "Ignored" section when noignoredDependenciesare configured. The "Ignored" section should be empty (or omitted) in this case.Root cause
AbstractAnalyzeMojo.filterDependencies()at line 563 returns the full inputartifactsset whenexcludesis null or empty:The method's contract is: given a source set and exclude patterns, remove artifacts that match an exclude pattern from the source (via
Iterator.remove()) and return the removed (excluded) artifacts in a new set. When no patterns are given, nothing can match, so the method should return an empty set — nothing was excluded. Returning the fullartifactsset instead tells every caller "everything was excluded."This affects all 8 call sites in the
analyzegoal (lines 363, 365, 367, 368, 369, 372, 374, 375). With default configuration (noignoredDependencies,ignoredUsedUndeclaredDependencies, etc. set), every artifact flows into the correspondingignored*set, and with-Dverbosethe same artifacts appear duplicated under both the warning and ignored sections.The mutation loop (
it.remove()) is correctly skipped in this path, so the real warning output is not suppressed — but the ignored section is filled with noise.To reproduce
reproducer-verbose-duplicate.tar.gz
Extract and rebuild the plugin from source:
Observe that
commons-lang3andcommons-texteach appear in both the warning section and the ignored section — even though noignoredDependenciesis configured.Expected behavior
With no
ignoredDependenciesconfigured, the "Ignored" sections should be not printed at all.Actual output
Proposed fix
The fix is a one-line change in
filterDependencies:This returns an empty set when no exclude patterns are provided, correctly communicating "nothing was excluded" to all callers.