Fail closed on ambiguous simple types in implementation widening
Prevent getImplementations("Name") from widening to unrelated classes when multiple types share the same simple name across packages.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -442,6 +442,12 @@ public class CodebaseContext {
|
|||||||
}
|
}
|
||||||
if (!visited.add(cleanName)) return;
|
if (!visited.add(cleanName)) return;
|
||||||
|
|
||||||
|
// Fail closed on ambiguous simple type names: we must not pick an arbitrary FQN and widen
|
||||||
|
// to unrelated implementations across packages.
|
||||||
|
if (cleanName != null && !cleanName.contains(".") && ambiguousSimpleNames.contains(cleanName)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Try direct match
|
// Try direct match
|
||||||
List<String> directImpls = interfaceToImpls.get(cleanName);
|
List<String> directImpls = interfaceToImpls.get(cleanName);
|
||||||
|
|
||||||
|
|||||||
@@ -250,6 +250,29 @@ class CodebaseContextTest {
|
|||||||
assertThat(context.getEnumValues("b.OrderEvent")).containsExactly("b.OrderEvent.SHIP");
|
assertThat(context.getEnumValues("b.OrderEvent")).containsExactly("b.OrderEvent.SHIP");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void getImplementationsShouldFailClosedForAmbiguousSimpleTypeName() throws IOException {
|
||||||
|
Files.createDirectories(tempDir.resolve("a"));
|
||||||
|
Files.createDirectories(tempDir.resolve("b"));
|
||||||
|
Files.writeString(tempDir.resolve("a/Service.java"),
|
||||||
|
"package a; public interface Service {}");
|
||||||
|
Files.writeString(tempDir.resolve("a/AServiceImpl.java"),
|
||||||
|
"package a; public class AServiceImpl implements Service {}");
|
||||||
|
Files.writeString(tempDir.resolve("b/Service.java"),
|
||||||
|
"package b; public interface Service {}");
|
||||||
|
Files.writeString(tempDir.resolve("b/BServiceImpl.java"),
|
||||||
|
"package b; public class BServiceImpl implements Service {}");
|
||||||
|
|
||||||
|
CodebaseContext context = new CodebaseContext();
|
||||||
|
context.scan(tempDir);
|
||||||
|
|
||||||
|
assertThat(context.getImplementations("Service"))
|
||||||
|
.as("ambiguous simple interface name must not widen to arbitrary impls")
|
||||||
|
.isEmpty();
|
||||||
|
assertThat(context.getImplementations("a.Service")).contains("a.AServiceImpl");
|
||||||
|
assertThat(context.getImplementations("b.Service")).contains("b.BServiceImpl");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void shouldFindClassWithFullyQualifiedAnnotation() throws IOException {
|
void shouldFindClassWithFullyQualifiedAnnotation() throws IOException {
|
||||||
String source = """
|
String source = """
|
||||||
|
|||||||
Reference in New Issue
Block a user