Fail closed on ambiguous simple-name type compatibility

Reject cross-package class matching and enum parameter compatibility when
types share an ambiguous simple name but differ by package-qualified FQN.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-14 05:46:54 +02:00
parent 82f4e5c087
commit 6401a58c20
5 changed files with 66 additions and 7 deletions

View File

@@ -30,4 +30,22 @@ class TypeResolverTest {
assertThat(resolver.getParameterIndex("com.example.StateMachine.sendEvent", "e")).isEqualTo(-1);
assertThat(resolver.getParameterIndex("com.example.StateMachine.sendEvent", "payload")).isEqualTo(-1);
}
@Test
void shouldFailClosedOnAmbiguousSimpleTypeCompatibility(@TempDir Path tempDir) throws Exception {
Files.createDirectories(tempDir.resolve("a"));
Files.createDirectories(tempDir.resolve("b"));
Files.writeString(tempDir.resolve("a/OrderEvent.java"),
"package a; public enum OrderEvent { PAY }");
Files.writeString(tempDir.resolve("b/OrderEvent.java"),
"package b; public enum OrderEvent { SHIP }");
CodebaseContext context = new CodebaseContext();
context.scan(tempDir);
TypeResolver resolver = new TypeResolver(context);
assertThat(resolver.isTypeCompatible("a.OrderEvent", "OrderEvent")).isFalse();
assertThat(resolver.isTypeCompatible("a.OrderEvent", "b.OrderEvent")).isFalse();
assertThat(resolver.isTypeCompatible("a.OrderEvent", "a.OrderEvent")).isTrue();
}
}

View File

@@ -275,6 +275,22 @@ class CodebaseContextTest {
assertThat(context.getImplementations("b.Service")).containsExactly("b.BServiceImpl");
}
@Test
void areSameTypeOrUnambiguousSimpleMatchShouldFailClosedForAmbiguousTypes() throws IOException {
Files.createDirectories(tempDir.resolve("a"));
Files.createDirectories(tempDir.resolve("b"));
Files.writeString(tempDir.resolve("a/Dispatcher.java"),
"package a; public class Dispatcher { public void dispatch() {} }");
Files.writeString(tempDir.resolve("b/Dispatcher.java"),
"package b; public class Dispatcher { public void dispatch() {} }");
CodebaseContext context = new CodebaseContext();
context.scan(tempDir);
assertThat(context.areSameTypeOrUnambiguousSimpleMatch("a.Dispatcher", "b.Dispatcher")).isFalse();
assertThat(context.areClassesPolymorphicallyCompatible("a.Dispatcher", "b.Dispatcher")).isFalse();
}
@Test
void shouldFindClassWithFullyQualifiedAnnotation() throws IOException {
String source = """