From 01ed33fe397b06b9779b323ad5540cbb5b98973b Mon Sep 17 00:00:00 2001 From: Matyrobbrt Date: Fri, 19 Jun 2026 01:31:59 +0300 Subject: [PATCH] Prevent importing classes with the same name as any classes in the file Avoids the possibility of an interface injection such as the one below causing a recursive class declaration ```json "com/mojang/blaze3d/pipeline/RenderPipeline$Snippet": [ "net/fabricmc/fabric/api/client/rendering/v1/FabricRenderPipeline$Snippet" ], "com/mojang/blaze3d/pipeline/RenderPipeline$Builder": [ "net/fabricmc/fabric/api/client/rendering/v1/FabricRenderPipeline$Builder" ], ``` --- .../net/neoforged/jst/api/ImportHelper.java | 12 +++++++++++ .../neoforged/jst/cli/ImportHelperTest.java | 20 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/api/src/main/java/net/neoforged/jst/api/ImportHelper.java b/api/src/main/java/net/neoforged/jst/api/ImportHelper.java index 0a92b0d..afc4e87 100644 --- a/api/src/main/java/net/neoforged/jst/api/ImportHelper.java +++ b/api/src/main/java/net/neoforged/jst/api/ImportHelper.java @@ -86,6 +86,18 @@ public ImportHelper(PsiJavaFile psiFile) { } } } + + // To avoid any ambiguity, we cannot import a class with the same name as any of the classes in the file + for (PsiClass topLevelClass : psiFile.getClasses()) { + markClassNamesAsUsed(topLevelClass); + } + } + + private void markClassNamesAsUsed(PsiClass topLevelClass) { + importedNames.put(topLevelClass.getName(), topLevelClass.getQualifiedName()); + for (PsiClass inner : topLevelClass.getAllInnerClasses()) { + markClassNamesAsUsed(inner); + } } @VisibleForTesting diff --git a/cli/src/test/java/net/neoforged/jst/cli/ImportHelperTest.java b/cli/src/test/java/net/neoforged/jst/cli/ImportHelperTest.java index 70f6384..4f018dc 100644 --- a/cli/src/test/java/net/neoforged/jst/cli/ImportHelperTest.java +++ b/cli/src/test/java/net/neoforged/jst/cli/ImportHelperTest.java @@ -111,6 +111,26 @@ class MyClass { }"""); } + @Test + void testCannotImportNamesInFile() { + var helper = getImportHelper(""" +package com.test; + +class MyClass { + interface InnerClass { + interface SubInner { + + } + } +}"""); + + assertFalse(helper.canImport("MyClass")); + assertFalse(helper.canImport("InnerClass")); + assertFalse(helper.canImport("SubInner")); + + assertTrue(helper.canImport("UnrelatedClassName")); + } + private ImportHelper getImportHelper(@Language("JAVA") String javaCode) { var file = parseSingleFile(javaCode); return new ImportHelper(file);