diff --git a/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/specs/NoModuleKeyRegressionSpecTest.java b/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/specs/NoModuleKeyRegressionSpecTest.java new file mode 100644 index 00000000..a61897ed --- /dev/null +++ b/prometeu-compiler/prometeu-build-pipeline/src/test/java/p/studio/compiler/specs/NoModuleKeyRegressionSpecTest.java @@ -0,0 +1,75 @@ +package p.studio.compiler.specs; + +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Pattern; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +class NoModuleKeyRegressionSpecTest { + private static final Pattern FORBIDDEN_IDENTIFIERS = Pattern.compile("\\bmoduleKey\\b|\\bcalleeModuleKey\\b"); + private static final List STRUCTURAL_SOURCE_ROOTS = List.of( + "prometeu-compiler/prometeu-frontend-api/src/main/java/p/studio/compiler/models", + "prometeu-compiler/prometeu-compiler-core/src/main/java/p/studio/compiler/source/tables", + "prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs", + "prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/services", + "prometeu-compiler/prometeu-build-pipeline/src/main/java/p/studio/compiler/backend/irvm"); + + @Test + void structuralContractsMustNotReintroduceLegacyModuleKeyIdentifiers() throws IOException { + final var repoRoot = locateRepoRoot(); + final var violations = new ArrayList(); + for (final var rootRelativePath : STRUCTURAL_SOURCE_ROOTS) { + final var root = repoRoot.resolve(rootRelativePath); + if (!Files.isDirectory(root)) { + continue; + } + try (Stream files = Files.walk(root)) { + files.filter(path -> Files.isRegularFile(path) && path.toString().endsWith(".java")) + .forEach(path -> recordViolation(path, repoRoot, violations)); + } + } + + assertTrue( + violations.isEmpty(), + "legacy moduleKey identifier is forbidden in structural FE/BE contracts:\n" + String.join("\n", violations)); + } + + private void recordViolation( + final Path path, + final Path repoRoot, + final ArrayList violations) { + final String content; + try { + content = Files.readString(path); + } catch (IOException e) { + throw new IllegalStateException("failed to read source file: " + path, e); + } + final var matcher = FORBIDDEN_IDENTIFIERS.matcher(content); + if (matcher.find()) { + final var relativePath = repoRoot.relativize(path).toString().replace('\\', '/'); + violations.add(relativePath + " (" + matcher.group() + ")"); + } + } + + private Path locateRepoRoot() { + var cursor = Path.of(System.getProperty("user.dir")).toAbsolutePath().normalize(); + while (cursor != null) { + final var hasDocs = Files.isDirectory(cursor.resolve("docs/general/specs")); + final var hasCompiler = Files.isDirectory(cursor.resolve("prometeu-compiler")); + if (hasDocs && hasCompiler) { + return cursor; + } + cursor = cursor.getParent(); + } + fail("could not locate repository root from working directory"); + throw new IllegalStateException("unreachable"); + } +}