stack overflow fixes

This commit is contained in:
2026-06-08 18:28:08 +02:00
parent a4a3493b42
commit ebb9fb5425
4 changed files with 239 additions and 60 deletions

View File

@@ -0,0 +1,91 @@
package click.kamil.springstatemachineexporter;
import click.kamil.springstatemachineexporter.ast.common.CodebaseContext;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import static org.assertj.core.api.Assertions.assertThat;
public class ResolutionRobustnessTest {
@Test
void testStackOverflowPreventionWithCyclicInheritance(@TempDir Path tempDir) throws IOException {
Path fooDir = tempDir.resolve("com/foo");
Files.createDirectories(fooDir);
// Cyclic inheritance: Config extends Config
Files.writeString(fooDir.resolve("Config.java"),
"package com.foo;\n" +
"public class Config extends Config {\n" +
" public void configure() {}\n" +
"}");
CodebaseContext context = new CodebaseContext();
context.scan(tempDir);
TypeDeclaration td = context.getTypeDeclaration("com.foo.Config");
assertThat(td).isNotNull();
// This should not throw StackOverflowError
boolean result = context.extendsStateMachineConfigurerAdapter(td);
assertThat(result).isFalse();
}
@Test
void testShadowingResolution(@TempDir Path tempDir) throws IOException {
// Package com.foo has a class Config
Path fooDir = tempDir.resolve("com/foo");
Files.createDirectories(fooDir);
Files.writeString(fooDir.resolve("Config.java"), "package com.foo; public class Config {}");
// Package com.bar also has a class Config
Path barDir = tempDir.resolve("com/bar");
Files.createDirectories(barDir);
Files.writeString(barDir.resolve("Config.java"), "package com.bar; public class Config {}");
// App class imports com.bar.Config
Path appDir = tempDir.resolve("com/app");
Files.createDirectories(appDir);
String appSource = "package com.app;\n" +
"import com.bar.Config;\n" +
"public class App extends Config {}";
Path appFile = appDir.resolve("App.java");
Files.writeString(appFile, appSource);
CodebaseContext context = new CodebaseContext();
context.scan(tempDir);
TypeDeclaration appTd = context.getTypeDeclaration("com.app.App");
assertThat(appTd).isNotNull();
// Resolution in App.java context should pick com.bar.Config due to import
TypeDeclaration resolvedTd = context.getTypeDeclaration("Config", (CompilationUnit) appTd.getRoot());
assertThat(context.getFqn(resolvedTd)).isEqualTo("com.bar.Config");
}
@Test
void testAmbiguityHandling(@TempDir Path tempDir) throws IOException {
// Two classes with same name in different packages, no imports in context
Files.createDirectories(tempDir.resolve("p1"));
Files.writeString(tempDir.resolve("p1/X.java"), "package p1; public class X {}");
Files.createDirectories(tempDir.resolve("p2"));
Files.writeString(tempDir.resolve("p2/X.java"), "package p2; public class X {}");
CodebaseContext context = new CodebaseContext();
context.scan(tempDir);
// Ambiguous simple name should return null to prevent incorrect resolution
TypeDeclaration td = context.getTypeDeclaration("X");
assertThat(td).isNull();
// Exact FQN should still work
assertThat(context.getTypeDeclaration("p1.X")).isNotNull();
assertThat(context.getTypeDeclaration("p2.X")).isNotNull();
}
}