From 3ac487fbf3ab689910efb4cdd43cb89baa0b474a Mon Sep 17 00:00:00 2001 From: Vaclav Haisman Date: Sun, 2 Aug 2026 15:28:27 +0200 Subject: [PATCH 1/3] Handle dependencies used only through inner classes Fixes apache/maven-dependency-plugin#1345 --- .../consumer/pom.xml | 96 +++++++++++++++++++ .../src/main/kotlin/consumer/Example.kt | 27 ++++++ .../kotlinInnerClassReference/library/pom.xml | 34 +++++++ .../library/src/main/java/library/Outer.java | 23 +++++ src/it/kotlinInnerClassReference/pom.xml | 36 +++++++ .../kotlinInnerClassReference/verify.groovy | 34 +++++++ .../analyzer/CollectorClassFileVisitor.java | 6 +- .../analyzer/asm/ResultCollector.java | 6 +- .../CollectorClassFileVisitorTest.java | 8 ++ .../analyzer/asm/ResultCollectorTest.java | 26 +++++ 10 files changed, 291 insertions(+), 5 deletions(-) create mode 100644 src/it/kotlinInnerClassReference/consumer/pom.xml create mode 100644 src/it/kotlinInnerClassReference/consumer/src/main/kotlin/consumer/Example.kt create mode 100644 src/it/kotlinInnerClassReference/library/pom.xml create mode 100644 src/it/kotlinInnerClassReference/library/src/main/java/library/Outer.java create mode 100644 src/it/kotlinInnerClassReference/pom.xml create mode 100644 src/it/kotlinInnerClassReference/verify.groovy diff --git a/src/it/kotlinInnerClassReference/consumer/pom.xml b/src/it/kotlinInnerClassReference/consumer/pom.xml new file mode 100644 index 00000000..7807dfb5 --- /dev/null +++ b/src/it/kotlinInnerClassReference/consumer/pom.xml @@ -0,0 +1,96 @@ + + + + + + 4.0.0 + + + org.apache.maven.shared.dependency-analyzer.tests + kotlin-inner-class-reference + 1.0 + + + kotlin-consumer + + + + org.apache.maven.shared.dependency-analyzer.tests + nested-class-library + ${project.version} + + + org.jetbrains.kotlin + kotlin-stdlib + 1.7.21 + + + + + + + org.jetbrains.kotlin + kotlin-maven-plugin + 1.7.21 + + + compile + + compile + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.3.0 + + + kotlin-sources + initialize + + add-source + + + + src/main/kotlin + + + + + + + org.apache.maven.shared.dependency-analyzer.tests + maven-mock-plugin + 1.0 + + + + mock-analyze + + + + + + + diff --git a/src/it/kotlinInnerClassReference/consumer/src/main/kotlin/consumer/Example.kt b/src/it/kotlinInnerClassReference/consumer/src/main/kotlin/consumer/Example.kt new file mode 100644 index 00000000..62f35b32 --- /dev/null +++ b/src/it/kotlinInnerClassReference/consumer/src/main/kotlin/consumer/Example.kt @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 consumer + +import library.Outer + +class Example { + fun createInner() { + Outer.Inner() + } +} diff --git a/src/it/kotlinInnerClassReference/library/pom.xml b/src/it/kotlinInnerClassReference/library/pom.xml new file mode 100644 index 00000000..0f36940d --- /dev/null +++ b/src/it/kotlinInnerClassReference/library/pom.xml @@ -0,0 +1,34 @@ + + + + + + 4.0.0 + + + org.apache.maven.shared.dependency-analyzer.tests + kotlin-inner-class-reference + 1.0 + + + nested-class-library + diff --git a/src/it/kotlinInnerClassReference/library/src/main/java/library/Outer.java b/src/it/kotlinInnerClassReference/library/src/main/java/library/Outer.java new file mode 100644 index 00000000..2e0aca18 --- /dev/null +++ b/src/it/kotlinInnerClassReference/library/src/main/java/library/Outer.java @@ -0,0 +1,23 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 library; + +public class Outer { + public static class Inner {} +} diff --git a/src/it/kotlinInnerClassReference/pom.xml b/src/it/kotlinInnerClassReference/pom.xml new file mode 100644 index 00000000..552992ae --- /dev/null +++ b/src/it/kotlinInnerClassReference/pom.xml @@ -0,0 +1,36 @@ + + + + + + 4.0.0 + + org.apache.maven.shared.dependency-analyzer.tests + kotlin-inner-class-reference + 1.0 + pom + + + library + consumer + + diff --git a/src/it/kotlinInnerClassReference/verify.groovy b/src/it/kotlinInnerClassReference/verify.groovy new file mode 100644 index 00000000..e2208059 --- /dev/null +++ b/src/it/kotlinInnerClassReference/verify.groovy @@ -0,0 +1,34 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +def analysis = new File( basedir, 'consumer/target/analysis.txt' ).text + +def expected = ''' +UsedDeclaredArtifacts: + org.apache.maven.shared.dependency-analyzer.tests:nested-class-library:jar:1.0:compile + org.jetbrains.kotlin:kotlin-stdlib:jar:1.7.21:compile + +UsedUndeclaredArtifactsWithClasses: + +UnusedDeclaredArtifacts: + +TestArtifactsWithNonTestScope: +''' + +assert analysis == expected diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitor.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitor.java index 4af2ff4e..a3535c4b 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitor.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitor.java @@ -49,8 +49,10 @@ public CollectorClassFileVisitor(ClassesPatterns excludedClasses) { @Override public void visitClass(String className, InputStream in) { // inner classes have equivalent compilation requirement as container class - if (className.indexOf('$') < 0 && !excludedClasses.isMatch(className)) { - classes.add(className); + int innerClassSeparator = className.indexOf('$'); + String containerClass = innerClassSeparator < 0 ? className : className.substring(0, innerClassSeparator); + if (!excludedClasses.isMatch(containerClass)) { + classes.add(containerClass); } } diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java index 65e39373..734e6f94 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java @@ -109,9 +109,9 @@ void addType(final String usedByClass, final Type t) { */ public void add(final String usedByClass, final String name) { // inner classes have equivalent compilation requirement as container class - if (name.indexOf('$') < 0) { - classUsages.add(new DependencyUsage(name, usedByClass)); - } + int innerClassSeparator = name.indexOf('$'); + String containerClass = innerClassSeparator < 0 ? name : name.substring(0, innerClassSeparator); + classUsages.add(new DependencyUsage(containerClass, usedByClass)); } void addNames(final String usedByClass, final String[] names) { diff --git a/src/test/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitorTest.java b/src/test/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitorTest.java index 9ae1faf4..2f3c5e12 100644 --- a/src/test/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitorTest.java +++ b/src/test/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitorTest.java @@ -51,4 +51,12 @@ void testVisitClass() { assertThat(visitor.getClasses()).isEqualTo(expected); } + + @Test + void testVisitInnerClassAsContainer() { + visitor.visitClass("a.b.Outer$Inner", null); + visitor.visitClass("x.y.Outer$Inner$Nested", null); + + assertThat(visitor.getClasses()).containsExactlyInAnyOrder("a.b.Outer", "x.y.Outer"); + } } diff --git a/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollectorTest.java b/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollectorTest.java index 562ab396..ec8fdebc 100644 --- a/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollectorTest.java +++ b/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollectorTest.java @@ -18,6 +18,7 @@ */ package org.apache.maven.shared.dependency.analyzer.asm; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; @@ -31,6 +32,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; +import org.objectweb.asm.ClassWriter; +import org.objectweb.asm.MethodVisitor; +import org.objectweb.asm.Opcodes; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatCode; @@ -121,4 +125,26 @@ void testInnerClassAsContainer() throws IOException { } assertThat(dependencies).contains("java.lang.System"); } + + @Test + void testInnerClassWithoutContainerClassInConstantPool() { + ClassWriter writer = new ClassWriter(0); + writer.visit(Opcodes.V17, Opcodes.ACC_PUBLIC, "consumer/Example", null, "java/lang/Object", null); + + MethodVisitor method = writer.visitMethod(Opcodes.ACC_PUBLIC, "use", "()V", null, null); + method.visitCode(); + method.visitTypeInsn(Opcodes.NEW, "dependency/Outer$Inner"); + method.visitInsn(Opcodes.DUP); + method.visitMethodInsn(Opcodes.INVOKESPECIAL, "dependency/Outer$Inner", "", "()V", false); + method.visitInsn(Opcodes.POP); + method.visitInsn(Opcodes.RETURN); + method.visitMaxs(2, 1); + method.visitEnd(); + writer.visitEnd(); + + DependencyClassFileVisitor visitor = new DependencyClassFileVisitor(); + visitor.visitClass("consumer.Example", new ByteArrayInputStream(writer.toByteArray())); + + assertThat(visitor.getDependencies()).contains("dependency.Outer").doesNotContain("dependency.Outer$Inner"); + } } From 11b77eabb1067bdc1a31f080112f9050d40c7711 Mon Sep 17 00:00:00 2001 From: Vaclav Haisman Date: Sun, 2 Aug 2026 15:42:37 +0200 Subject: [PATCH 2/3] Preserve dollar signs in top-level class names --- .../consumer/pom.xml | 59 +++++++++++++++++++ .../src/main/java/consumer/Example.java | 27 +++++++++ .../library/pom.xml | 34 +++++++++++ .../src/main/java/library/Dollar$Class.java | 21 +++++++ src/it/topLevelDollarClassReference/pom.xml | 36 +++++++++++ .../verify.groovy | 33 +++++++++++ .../analyzer/CollectorClassFileVisitor.java | 8 +-- .../analyzer/asm/ResultCollector.java | 6 +- .../CollectorClassFileVisitorTest.java | 4 +- .../analyzer/DefaultClassAnalyzerTest.java | 15 +++++ .../analyzer/asm/ResultCollectorTest.java | 9 +-- 11 files changed, 235 insertions(+), 17 deletions(-) create mode 100644 src/it/topLevelDollarClassReference/consumer/pom.xml create mode 100644 src/it/topLevelDollarClassReference/consumer/src/main/java/consumer/Example.java create mode 100644 src/it/topLevelDollarClassReference/library/pom.xml create mode 100644 src/it/topLevelDollarClassReference/library/src/main/java/library/Dollar$Class.java create mode 100644 src/it/topLevelDollarClassReference/pom.xml create mode 100644 src/it/topLevelDollarClassReference/verify.groovy diff --git a/src/it/topLevelDollarClassReference/consumer/pom.xml b/src/it/topLevelDollarClassReference/consumer/pom.xml new file mode 100644 index 00000000..1476bf61 --- /dev/null +++ b/src/it/topLevelDollarClassReference/consumer/pom.xml @@ -0,0 +1,59 @@ + + + + + + 4.0.0 + + + org.apache.maven.shared.dependency-analyzer.tests + top-level-dollar-class-reference + 1.0 + + + dollar-class-consumer + + + + org.apache.maven.shared.dependency-analyzer.tests + dollar-class-library + ${project.version} + + + + + + + org.apache.maven.shared.dependency-analyzer.tests + maven-mock-plugin + 1.0 + + + + mock-analyze + + + + + + + diff --git a/src/it/topLevelDollarClassReference/consumer/src/main/java/consumer/Example.java b/src/it/topLevelDollarClassReference/consumer/src/main/java/consumer/Example.java new file mode 100644 index 00000000..820ae369 --- /dev/null +++ b/src/it/topLevelDollarClassReference/consumer/src/main/java/consumer/Example.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 consumer; + +import library.Dollar$Class; + +public class Example { + public Dollar$Class create() { + return new Dollar$Class(); + } +} diff --git a/src/it/topLevelDollarClassReference/library/pom.xml b/src/it/topLevelDollarClassReference/library/pom.xml new file mode 100644 index 00000000..2050f8a0 --- /dev/null +++ b/src/it/topLevelDollarClassReference/library/pom.xml @@ -0,0 +1,34 @@ + + + + + + 4.0.0 + + + org.apache.maven.shared.dependency-analyzer.tests + top-level-dollar-class-reference + 1.0 + + + dollar-class-library + diff --git a/src/it/topLevelDollarClassReference/library/src/main/java/library/Dollar$Class.java b/src/it/topLevelDollarClassReference/library/src/main/java/library/Dollar$Class.java new file mode 100644 index 00000000..66d2d7c6 --- /dev/null +++ b/src/it/topLevelDollarClassReference/library/src/main/java/library/Dollar$Class.java @@ -0,0 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 library; + +public class Dollar$Class {} diff --git a/src/it/topLevelDollarClassReference/pom.xml b/src/it/topLevelDollarClassReference/pom.xml new file mode 100644 index 00000000..8f537e9d --- /dev/null +++ b/src/it/topLevelDollarClassReference/pom.xml @@ -0,0 +1,36 @@ + + + + + + 4.0.0 + + org.apache.maven.shared.dependency-analyzer.tests + top-level-dollar-class-reference + 1.0 + pom + + + library + consumer + + diff --git a/src/it/topLevelDollarClassReference/verify.groovy b/src/it/topLevelDollarClassReference/verify.groovy new file mode 100644 index 00000000..e2bd5a4d --- /dev/null +++ b/src/it/topLevelDollarClassReference/verify.groovy @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +def analysis = new File( basedir, 'consumer/target/analysis.txt' ).text + +def expected = ''' +UsedDeclaredArtifacts: + org.apache.maven.shared.dependency-analyzer.tests:dollar-class-library:jar:1.0:compile + +UsedUndeclaredArtifactsWithClasses: + +UnusedDeclaredArtifacts: + +TestArtifactsWithNonTestScope: +''' + +assert analysis == expected diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitor.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitor.java index a3535c4b..e7b52d3a 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitor.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitor.java @@ -48,11 +48,9 @@ public CollectorClassFileVisitor(ClassesPatterns excludedClasses) { /** {@inheritDoc} */ @Override public void visitClass(String className, InputStream in) { - // inner classes have equivalent compilation requirement as container class - int innerClassSeparator = className.indexOf('$'); - String containerClass = innerClassSeparator < 0 ? className : className.substring(0, innerClassSeparator); - if (!excludedClasses.isMatch(containerClass)) { - classes.add(containerClass); + // '$' is legal in a top-level class name, so nesting cannot be inferred from the binary name. + if (!excludedClasses.isMatch(className)) { + classes.add(className); } } diff --git a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java index 734e6f94..e416531b 100644 --- a/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java +++ b/src/main/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollector.java @@ -108,10 +108,8 @@ void addType(final String usedByClass, final Type t) { * @param name a {@link java.lang.String} object. */ public void add(final String usedByClass, final String name) { - // inner classes have equivalent compilation requirement as container class - int innerClassSeparator = name.indexOf('$'); - String containerClass = innerClassSeparator < 0 ? name : name.substring(0, innerClassSeparator); - classUsages.add(new DependencyUsage(containerClass, usedByClass)); + // '$' is legal in a top-level class name, so nesting cannot be inferred from the binary name. + classUsages.add(new DependencyUsage(name, usedByClass)); } void addNames(final String usedByClass, final String[] names) { diff --git a/src/test/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitorTest.java b/src/test/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitorTest.java index 2f3c5e12..015dfc82 100644 --- a/src/test/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitorTest.java +++ b/src/test/java/org/apache/maven/shared/dependency/analyzer/CollectorClassFileVisitorTest.java @@ -53,10 +53,10 @@ void testVisitClass() { } @Test - void testVisitInnerClassAsContainer() { + void testVisitClassesContainingDollar() { visitor.visitClass("a.b.Outer$Inner", null); visitor.visitClass("x.y.Outer$Inner$Nested", null); - assertThat(visitor.getClasses()).containsExactlyInAnyOrder("a.b.Outer", "x.y.Outer"); + assertThat(visitor.getClasses()).containsExactlyInAnyOrder("a.b.Outer$Inner", "x.y.Outer$Inner$Nested"); } } diff --git a/src/test/java/org/apache/maven/shared/dependency/analyzer/DefaultClassAnalyzerTest.java b/src/test/java/org/apache/maven/shared/dependency/analyzer/DefaultClassAnalyzerTest.java index 5edb864e..96f9ab92 100644 --- a/src/test/java/org/apache/maven/shared/dependency/analyzer/DefaultClassAnalyzerTest.java +++ b/src/test/java/org/apache/maven/shared/dependency/analyzer/DefaultClassAnalyzerTest.java @@ -24,6 +24,7 @@ import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; +import java.util.Collections; import java.util.HashSet; import java.util.Set; import java.util.jar.JarOutputStream; @@ -91,6 +92,20 @@ void testAnalyzeBadJar() throws IOException { } } + @Test + void testAnalyzeDirectoryPreservesDollarClassNames() throws IOException { + Path directory = Files.createDirectories(tempDir.resolve("classes/library")); + Files.write(directory.resolve("Dollar$Class.class"), new byte[0]); + Files.write(directory.resolve("Outer$Inner.class"), new byte[0]); + + DefaultClassAnalyzer analyzer = new DefaultClassAnalyzer(); + Set actualClasses = analyzer.analyze( + tempDir.resolve("classes").toUri().toURL(), + new ClassesPatterns(Collections.singleton("library\\.Outer\\$Inner"))); + + assertThat(actualClasses).containsExactly("library.Dollar$Class"); + } + private void addZipEntry(JarOutputStream out, String fileName, String content) throws IOException { out.putNextEntry(new ZipEntry(fileName)); byte[] bytes = content.getBytes(StandardCharsets.UTF_8); diff --git a/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollectorTest.java b/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollectorTest.java index ec8fdebc..0fb7bd88 100644 --- a/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollectorTest.java +++ b/src/test/java/org/apache/maven/shared/dependency/analyzer/asm/ResultCollectorTest.java @@ -118,12 +118,9 @@ void testNoMethodHandle() throws IOException { } @Test - void testInnerClassAsContainer() throws IOException { + void testInnerClassNamePreserved() throws IOException { Set dependencies = getDependencies(InnerClassCase.class); - for (String dependency : dependencies) { - assertThat(dependency).doesNotContain("$"); - } - assertThat(dependencies).contains("java.lang.System"); + assertThat(dependencies).contains("java.lang.System", "java.lang.invoke.MethodHandles$Lookup"); } @Test @@ -145,6 +142,6 @@ void testInnerClassWithoutContainerClassInConstantPool() { DependencyClassFileVisitor visitor = new DependencyClassFileVisitor(); visitor.visitClass("consumer.Example", new ByteArrayInputStream(writer.toByteArray())); - assertThat(visitor.getDependencies()).contains("dependency.Outer").doesNotContain("dependency.Outer$Inner"); + assertThat(visitor.getDependencies()).contains("dependency.Outer$Inner").doesNotContain("dependency.Outer"); } } From b8d6f0c94f1ee8ee2654bd9a1b44e4e56ba29a0c Mon Sep 17 00:00:00 2001 From: Vaclav Haisman Date: Mon, 10 Aug 2026 17:59:59 +0200 Subject: [PATCH 3/3] Update Kotlin test fixture --- src/it/kotlinInnerClassReference/consumer/pom.xml | 8 ++++++-- src/it/kotlinInnerClassReference/verify.groovy | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/it/kotlinInnerClassReference/consumer/pom.xml b/src/it/kotlinInnerClassReference/consumer/pom.xml index 7807dfb5..77866321 100644 --- a/src/it/kotlinInnerClassReference/consumer/pom.xml +++ b/src/it/kotlinInnerClassReference/consumer/pom.xml @@ -32,6 +32,10 @@ kotlin-consumer + + 2.4.10 + + org.apache.maven.shared.dependency-analyzer.tests @@ -41,7 +45,7 @@ org.jetbrains.kotlin kotlin-stdlib - 1.7.21 + ${kotlin.version} @@ -50,7 +54,7 @@ org.jetbrains.kotlin kotlin-maven-plugin - 1.7.21 + ${kotlin.version} compile diff --git a/src/it/kotlinInnerClassReference/verify.groovy b/src/it/kotlinInnerClassReference/verify.groovy index e2208059..b7c782c0 100644 --- a/src/it/kotlinInnerClassReference/verify.groovy +++ b/src/it/kotlinInnerClassReference/verify.groovy @@ -22,7 +22,7 @@ def analysis = new File( basedir, 'consumer/target/analysis.txt' ).text def expected = ''' UsedDeclaredArtifacts: org.apache.maven.shared.dependency-analyzer.tests:nested-class-library:jar:1.0:compile - org.jetbrains.kotlin:kotlin-stdlib:jar:1.7.21:compile + org.jetbrains.kotlin:kotlin-stdlib:jar:2.4.10:compile UsedUndeclaredArtifactsWithClasses: