diff --git a/accesstransformers/build.gradle b/accesstransformers/build.gradle new file mode 100644 index 0000000..b3d29f9 --- /dev/null +++ b/accesstransformers/build.gradle @@ -0,0 +1,15 @@ +plugins { + id "java-library" +} + +dependencies { + implementation project(":api") + implementation 'net.neoforged.accesstransformers:at-parser:11.0.0' + + testImplementation platform("org.junit:junit-bom:$junit_version") + testImplementation 'org.junit.jupiter:junit-jupiter' +} + +test { + useJUnitPlatform() +} diff --git a/accesstransformers/src/main/java/net/neoforged/jst/accesstransformers/AccessTransformersPlugin.java b/accesstransformers/src/main/java/net/neoforged/jst/accesstransformers/AccessTransformersPlugin.java new file mode 100644 index 0000000..4efd424 --- /dev/null +++ b/accesstransformers/src/main/java/net/neoforged/jst/accesstransformers/AccessTransformersPlugin.java @@ -0,0 +1,20 @@ +package net.neoforged.jst.accesstransformers; + +import net.neoforged.jst.api.SourceTransformer; +import net.neoforged.jst.api.SourceTransformerPlugin; + +/** + * Access transformers allow modifying the access of classes, fields and methods. + * Mods can use ATs to remove the final modifier, or increase the visibility of a method. + */ +public class AccessTransformersPlugin implements SourceTransformerPlugin { + @Override + public String getName() { + return "accesstransformers"; + } + + @Override + public SourceTransformer createTransformer() { + return new AccessTransformersTransformer(); + } +} diff --git a/accesstransformers/src/main/java/net/neoforged/jst/accesstransformers/AccessTransformersTransformer.java b/accesstransformers/src/main/java/net/neoforged/jst/accesstransformers/AccessTransformersTransformer.java new file mode 100644 index 0000000..0254ced --- /dev/null +++ b/accesstransformers/src/main/java/net/neoforged/jst/accesstransformers/AccessTransformersTransformer.java @@ -0,0 +1,37 @@ +package net.neoforged.jst.accesstransformers; + +import com.intellij.psi.PsiFile; +import net.neoforged.accesstransformer.parser.AccessTransformerFiles; +import net.neoforged.jst.api.Replacements; +import net.neoforged.jst.api.SourceTransformer; +import net.neoforged.jst.api.TransformContext; +import picocli.CommandLine; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.nio.file.Path; +import java.util.List; + +public class AccessTransformersTransformer implements SourceTransformer { + + @CommandLine.Option(names = "--access-transformer", required = true) + public List atFiles; + + private AccessTransformerFiles ats; + @Override + public void beforeRun(TransformContext context) { + ats = new AccessTransformerFiles(); + try { + for (Path path : atFiles) { + ats.loadFromPath(path); + } + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + } + + @Override + public void visitFile(PsiFile psiFile, Replacements replacements) { + new ApplyATsVisitor(ats, replacements).visitFile(psiFile); + } +} diff --git a/accesstransformers/src/main/java/net/neoforged/jst/accesstransformers/ApplyATsVisitor.java b/accesstransformers/src/main/java/net/neoforged/jst/accesstransformers/ApplyATsVisitor.java new file mode 100644 index 0000000..334ac85 --- /dev/null +++ b/accesstransformers/src/main/java/net/neoforged/jst/accesstransformers/ApplyATsVisitor.java @@ -0,0 +1,116 @@ +package net.neoforged.jst.accesstransformers; + +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiField; +import com.intellij.psi.PsiKeyword; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiModifier; +import com.intellij.psi.PsiModifierList; +import com.intellij.psi.PsiRecursiveElementVisitor; +import com.intellij.psi.util.ClassUtil; +import net.neoforged.accesstransformer.parser.AccessTransformerFiles; +import net.neoforged.accesstransformer.parser.Target; +import net.neoforged.accesstransformer.parser.Transformation; +import net.neoforged.jst.api.Replacements; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; +import java.util.EnumMap; +import java.util.List; +import java.util.Map; + +class ApplyATsVisitor extends PsiRecursiveElementVisitor { + private static final List ACCESS_MODIFIERS = List.of(PsiModifier.PUBLIC, PsiModifier.PRIVATE, PsiModifier.PROTECTED); + public static final EnumMap MODIFIER_TO_STRING = new EnumMap<>( + Map.of(Transformation.Modifier.PRIVATE, PsiModifier.PRIVATE, Transformation.Modifier.PUBLIC, PsiModifier.PUBLIC, Transformation.Modifier.PROTECTED, PsiModifier.PROTECTED) + ); + + private final AccessTransformerFiles ats; + private final Replacements replacements; + + public ApplyATsVisitor(AccessTransformerFiles ats, Replacements replacements) { + this.ats = ats; + this.replacements = replacements; + } + + @Override + public void visitElement(@NotNull PsiElement element) { + if (element instanceof PsiClass psiClass) { + if (psiClass.getQualifiedName() != null) { + String className = ClassUtil.getJVMClassName(psiClass); + if (!ats.containsClassTarget(className)) { + return; // Skip this class and all its children + } + + apply(ats.getAccessTransformers().get(new Target.ClassTarget(className)), psiClass.getModifierList()); + var fieldWildcard = ats.getAccessTransformers().get(new Target.WildcardFieldTarget(className)); + if (fieldWildcard != null) { + for (PsiField field : psiClass.getFields()) { + apply(fieldWildcard, field.getModifierList()); + } + } + + var methodWildcard = ats.getAccessTransformers().get(new Target.WildcardMethodTarget(className)); + if (methodWildcard != null) { + for (PsiMethod method : psiClass.getMethods()) { + apply(methodWildcard, method.getModifierList()); + } + } + } + } else if (element instanceof PsiField field) { + final var cls = field.getContainingClass(); + if (cls != null && cls.getQualifiedName() != null) { + String className = ClassUtil.getJVMClassName(cls); + apply(ats.getAccessTransformers().get(new Target.FieldTarget(className, field.getName())), field.getModifierList()); + } + } else if (element instanceof PsiMethod method) { + final var cls = method.getContainingClass(); + if (cls != null && cls.getQualifiedName() != null) { + String className = ClassUtil.getJVMClassName(cls); + apply(ats.getAccessTransformers().get(new Target.MethodTarget(className, method.getName(), ClassUtil.getAsmMethodSignature(method))), method.getModifierList()); + } + } + + element.acceptChildren(this); + } + + private void apply(@Nullable Transformation at, PsiModifierList modifiers) { + if (at == null || !at.isValid()) return; + + var targetAcc = at.modifier(); + if (targetAcc == Transformation.Modifier.DEFAULT || !modifiers.hasModifierProperty(MODIFIER_TO_STRING.get(targetAcc))) { + final var existingModifier = Arrays.stream(modifiers.getChildren()) + .filter(el -> el instanceof PsiKeyword) + .map(el -> (PsiKeyword) el) + .filter(kw -> ACCESS_MODIFIERS.contains(kw.getText())) + .findFirst(); + + if (targetAcc == Transformation.Modifier.DEFAULT) { + existingModifier.ifPresent(replacements::remove); + } else { + if (existingModifier.isPresent()) { + replacements.replace(existingModifier.get(), MODIFIER_TO_STRING.get(targetAcc)); + } else { + if (modifiers.getChildren().length == 0) { + // Empty modifiers are blank so we basically replace them + replacements.insertAfter(modifiers, MODIFIER_TO_STRING.get(targetAcc) + " "); + } else { + replacements.insertBefore(modifiers, MODIFIER_TO_STRING.get(targetAcc) + " "); + } + } + } + } + + var finalState = at.finalState(); + if (finalState == Transformation.FinalState.REMOVEFINAL && modifiers.hasModifierProperty(PsiModifier.FINAL)) { + Arrays.stream(modifiers.getChildren()) + .filter(el -> el instanceof PsiKeyword) + .map(el -> (PsiKeyword) el) + .filter(kw -> kw.getText().equals(PsiModifier.FINAL)) + .findFirst() + .ifPresent(replacements::remove); + } + } +} diff --git a/accesstransformers/src/main/resources/META-INF/services/net.neoforged.jst.api.SourceTransformerPlugin b/accesstransformers/src/main/resources/META-INF/services/net.neoforged.jst.api.SourceTransformerPlugin new file mode 100644 index 0000000..16e6b5f --- /dev/null +++ b/accesstransformers/src/main/resources/META-INF/services/net.neoforged.jst.api.SourceTransformerPlugin @@ -0,0 +1 @@ +net.neoforged.jst.accesstransformers.AccessTransformersPlugin diff --git a/api/src/main/java/net/neoforged/jst/api/Replacements.java b/api/src/main/java/net/neoforged/jst/api/Replacements.java index 556afcf..2885813 100644 --- a/api/src/main/java/net/neoforged/jst/api/Replacements.java +++ b/api/src/main/java/net/neoforged/jst/api/Replacements.java @@ -17,6 +17,18 @@ public void replace(PsiElement element, String newText) { add(new Replacement(element.getTextRange(), newText)); } + public void remove(PsiElement element) { + final int pos = element.getTextRange().getEndOffset(); + if (element.getContainingFile().getText().charAt(pos) == ' ') { + add(new Replacement(new TextRange( + element.getTextRange().getStartOffset(), + pos + 1 + ), "")); + } else { + replace(element, ""); + } + } + public void insertBefore(PsiElement element, String newText) { var startOffset = element.getTextRange().getStartOffset(); add(new Replacement(new TextRange( diff --git a/cli/build.gradle b/cli/build.gradle index 4e0fb22..0900153 100644 --- a/cli/build.gradle +++ b/cli/build.gradle @@ -19,6 +19,7 @@ dependencies { implementation project(":api") implementation "info.picocli:picocli:$picocli_version" implementation project(":parchment") + implementation project(":accesstransformers") testImplementation platform("org.junit:junit-bom:$junit_version") testImplementation 'org.junit.jupiter:junit-jupiter' @@ -29,6 +30,10 @@ test { useJUnitPlatform() } +shadowJar { + mergeServiceFiles() +} + assemble.configure { dependsOn shadowJar } diff --git a/settings.gradle b/settings.gradle index ac9f6c8..abff962 100644 --- a/settings.gradle +++ b/settings.gradle @@ -36,3 +36,4 @@ include 'api' include 'cli' include 'parchment' include 'tests' +include 'accesstransformers' diff --git a/tests/data/accesstransformer/classes/accesstransformer.cfg b/tests/data/accesstransformer/classes/accesstransformer.cfg new file mode 100644 index 0000000..f53af6f --- /dev/null +++ b/tests/data/accesstransformer/classes/accesstransformer.cfg @@ -0,0 +1,2 @@ +public C1 +default-f C2f diff --git a/tests/data/accesstransformer/classes/expected/C1.java b/tests/data/accesstransformer/classes/expected/C1.java new file mode 100644 index 0000000..65c03e4 --- /dev/null +++ b/tests/data/accesstransformer/classes/expected/C1.java @@ -0,0 +1,3 @@ +public class C1 { + +} diff --git a/tests/data/accesstransformer/classes/expected/C2f.java b/tests/data/accesstransformer/classes/expected/C2f.java new file mode 100644 index 0000000..fa5ba2f --- /dev/null +++ b/tests/data/accesstransformer/classes/expected/C2f.java @@ -0,0 +1,3 @@ +class C2f { + +} diff --git a/tests/data/accesstransformer/classes/source/C1.java b/tests/data/accesstransformer/classes/source/C1.java new file mode 100644 index 0000000..492c5d2 --- /dev/null +++ b/tests/data/accesstransformer/classes/source/C1.java @@ -0,0 +1,3 @@ +class C1 { + +} diff --git a/tests/data/accesstransformer/classes/source/C2f.java b/tests/data/accesstransformer/classes/source/C2f.java new file mode 100644 index 0000000..cdf8703 --- /dev/null +++ b/tests/data/accesstransformer/classes/source/C2f.java @@ -0,0 +1,3 @@ +final class C2f { + +} diff --git a/tests/data/accesstransformer/fields/accesstransformer.cfg b/tests/data/accesstransformer/fields/accesstransformer.cfg new file mode 100644 index 0000000..e7c0069 --- /dev/null +++ b/tests/data/accesstransformer/fields/accesstransformer.cfg @@ -0,0 +1,3 @@ +protected ABC s1 +public-f ABC s2 +public ABC b1 diff --git a/tests/data/accesstransformer/fields/expected/ABC.java b/tests/data/accesstransformer/fields/expected/ABC.java new file mode 100644 index 0000000..7aa1504 --- /dev/null +++ b/tests/data/accesstransformer/fields/expected/ABC.java @@ -0,0 +1,5 @@ +class ABC { + protected String s1; + public String s2 = ""; + public static boolean b1; +} diff --git a/tests/data/accesstransformer/fields/source/ABC.java b/tests/data/accesstransformer/fields/source/ABC.java new file mode 100644 index 0000000..df10592 --- /dev/null +++ b/tests/data/accesstransformer/fields/source/ABC.java @@ -0,0 +1,5 @@ +class ABC { + private String s1; + public final String s2 = ""; + protected static boolean b1; +} diff --git a/tests/data/accesstransformer/inner_classes/accesstransformer.cfg b/tests/data/accesstransformer/inner_classes/accesstransformer.cfg new file mode 100644 index 0000000..9e44386 --- /dev/null +++ b/tests/data/accesstransformer/inner_classes/accesstransformer.cfg @@ -0,0 +1,2 @@ +public com.example.RootClass$InnerClass1 +protected-f com.example.RootClass$InnerClass1$InnerClassNested diff --git a/tests/data/accesstransformer/inner_classes/expected/com/example/RootClass.java b/tests/data/accesstransformer/inner_classes/expected/com/example/RootClass.java new file mode 100644 index 0000000..7171187 --- /dev/null +++ b/tests/data/accesstransformer/inner_classes/expected/com/example/RootClass.java @@ -0,0 +1,9 @@ +package com.example; + +class RootClass { + public class InnerClass1 { + protected static class InnerClassNested { + + } + } +} diff --git a/tests/data/accesstransformer/inner_classes/source/com/example/RootClass.java b/tests/data/accesstransformer/inner_classes/source/com/example/RootClass.java new file mode 100644 index 0000000..65b14a7 --- /dev/null +++ b/tests/data/accesstransformer/inner_classes/source/com/example/RootClass.java @@ -0,0 +1,9 @@ +package com.example; + +class RootClass { + class InnerClass1 { + static final class InnerClassNested { + + } + } +} diff --git a/tests/data/accesstransformer/methods/accesstransformer.cfg b/tests/data/accesstransformer/methods/accesstransformer.cfg new file mode 100644 index 0000000..adff749 --- /dev/null +++ b/tests/data/accesstransformer/methods/accesstransformer.cfg @@ -0,0 +1,3 @@ +public-f ABC doThing()V +protected ABC ret(Z)I +default ABC m2(Ljava/lang/String;)V diff --git a/tests/data/accesstransformer/methods/expected/ABC.java b/tests/data/accesstransformer/methods/expected/ABC.java new file mode 100644 index 0000000..5598ac9 --- /dev/null +++ b/tests/data/accesstransformer/methods/expected/ABC.java @@ -0,0 +1,13 @@ +class ABC { + public void doThing() { + + } + + protected int ret(boolean b) { + return 0; + } + + static void m2(String str) { + + } +} diff --git a/tests/data/accesstransformer/methods/source/ABC.java b/tests/data/accesstransformer/methods/source/ABC.java new file mode 100644 index 0000000..5a60dea --- /dev/null +++ b/tests/data/accesstransformer/methods/source/ABC.java @@ -0,0 +1,13 @@ +class ABC { + public final void doThing() { + + } + + private int ret(boolean b) { + return 0; + } + + private static void m2(String str) { + + } +} diff --git a/tests/data/accesstransformer/wildcard/accesstransformer.cfg b/tests/data/accesstransformer/wildcard/accesstransformer.cfg new file mode 100644 index 0000000..cb512be --- /dev/null +++ b/tests/data/accesstransformer/wildcard/accesstransformer.cfg @@ -0,0 +1,2 @@ +default TestClass * +public TestClass *() diff --git a/tests/data/accesstransformer/wildcard/expected/TestClass.java b/tests/data/accesstransformer/wildcard/expected/TestClass.java new file mode 100644 index 0000000..6fe2277 --- /dev/null +++ b/tests/data/accesstransformer/wildcard/expected/TestClass.java @@ -0,0 +1,12 @@ +class TestClass { + String f1; + int f2; + + public void m1(int a) { + + } + + public static String m2(boolean ok) { + return "abc"; + } +} diff --git a/tests/data/accesstransformer/wildcard/source/TestClass.java b/tests/data/accesstransformer/wildcard/source/TestClass.java new file mode 100644 index 0000000..6f939d3 --- /dev/null +++ b/tests/data/accesstransformer/wildcard/source/TestClass.java @@ -0,0 +1,12 @@ +class TestClass { + private String f1; + private int f2; + + private void m1(int a) { + + } + + private static String m2(boolean ok) { + return "abc"; + } +} diff --git a/tests/data/external_refs/expected/TestClass.java b/tests/data/parchment/external_refs/expected/TestClass.java similarity index 100% rename from tests/data/external_refs/expected/TestClass.java rename to tests/data/parchment/external_refs/expected/TestClass.java diff --git a/tests/data/external_refs/parchment.json b/tests/data/parchment/external_refs/parchment.json similarity index 100% rename from tests/data/external_refs/parchment.json rename to tests/data/parchment/external_refs/parchment.json diff --git a/tests/data/external_refs/source/TestClass.java b/tests/data/parchment/external_refs/source/TestClass.java similarity index 100% rename from tests/data/external_refs/source/TestClass.java rename to tests/data/parchment/external_refs/source/TestClass.java diff --git a/tests/data/javadoc/expected/ExistingJavadoc.java b/tests/data/parchment/javadoc/expected/ExistingJavadoc.java similarity index 100% rename from tests/data/javadoc/expected/ExistingJavadoc.java rename to tests/data/parchment/javadoc/expected/ExistingJavadoc.java diff --git a/tests/data/javadoc/expected/NoExistingJavadoc.java b/tests/data/parchment/javadoc/expected/NoExistingJavadoc.java similarity index 100% rename from tests/data/javadoc/expected/NoExistingJavadoc.java rename to tests/data/parchment/javadoc/expected/NoExistingJavadoc.java diff --git a/tests/data/javadoc/parchment.json b/tests/data/parchment/javadoc/parchment.json similarity index 100% rename from tests/data/javadoc/parchment.json rename to tests/data/parchment/javadoc/parchment.json diff --git a/tests/data/javadoc/source/ExistingJavadoc.java b/tests/data/parchment/javadoc/source/ExistingJavadoc.java similarity index 100% rename from tests/data/javadoc/source/ExistingJavadoc.java rename to tests/data/parchment/javadoc/source/ExistingJavadoc.java diff --git a/tests/data/javadoc/source/NoExistingJavadoc.java b/tests/data/parchment/javadoc/source/NoExistingJavadoc.java similarity index 100% rename from tests/data/javadoc/source/NoExistingJavadoc.java rename to tests/data/parchment/javadoc/source/NoExistingJavadoc.java diff --git a/tests/data/nested/expected/DefaultPkgClass.java b/tests/data/parchment/nested/expected/DefaultPkgClass.java similarity index 100% rename from tests/data/nested/expected/DefaultPkgClass.java rename to tests/data/parchment/nested/expected/DefaultPkgClass.java diff --git a/tests/data/nested/expected/pkg/Outer.java b/tests/data/parchment/nested/expected/pkg/Outer.java similarity index 100% rename from tests/data/nested/expected/pkg/Outer.java rename to tests/data/parchment/nested/expected/pkg/Outer.java diff --git a/tests/data/nested/expected/pkg/SamePkgClass.java b/tests/data/parchment/nested/expected/pkg/SamePkgClass.java similarity index 100% rename from tests/data/nested/expected/pkg/SamePkgClass.java rename to tests/data/parchment/nested/expected/pkg/SamePkgClass.java diff --git a/tests/data/nested/parchment.json b/tests/data/parchment/nested/parchment.json similarity index 100% rename from tests/data/nested/parchment.json rename to tests/data/parchment/nested/parchment.json diff --git a/tests/data/nested/source/DefaultPkgClass.java b/tests/data/parchment/nested/source/DefaultPkgClass.java similarity index 100% rename from tests/data/nested/source/DefaultPkgClass.java rename to tests/data/parchment/nested/source/DefaultPkgClass.java diff --git a/tests/data/nested/source/pkg/Outer.java b/tests/data/parchment/nested/source/pkg/Outer.java similarity index 100% rename from tests/data/nested/source/pkg/Outer.java rename to tests/data/parchment/nested/source/pkg/Outer.java diff --git a/tests/data/nested/source/pkg/SamePkgClass.java b/tests/data/parchment/nested/source/pkg/SamePkgClass.java similarity index 100% rename from tests/data/nested/source/pkg/SamePkgClass.java rename to tests/data/parchment/nested/source/pkg/SamePkgClass.java diff --git a/tests/data/param_indices/expected/TestClass.java b/tests/data/parchment/param_indices/expected/TestClass.java similarity index 100% rename from tests/data/param_indices/expected/TestClass.java rename to tests/data/parchment/param_indices/expected/TestClass.java diff --git a/tests/data/param_indices/expected/TestEnum.java b/tests/data/parchment/param_indices/expected/TestEnum.java similarity index 100% rename from tests/data/param_indices/expected/TestEnum.java rename to tests/data/parchment/param_indices/expected/TestEnum.java diff --git a/tests/data/param_indices/parchment.json b/tests/data/parchment/param_indices/parchment.json similarity index 100% rename from tests/data/param_indices/parchment.json rename to tests/data/parchment/param_indices/parchment.json diff --git a/tests/data/param_indices/source/TestClass.java b/tests/data/parchment/param_indices/source/TestClass.java similarity index 100% rename from tests/data/param_indices/source/TestClass.java rename to tests/data/parchment/param_indices/source/TestClass.java diff --git a/tests/data/param_indices/source/TestEnum.java b/tests/data/parchment/param_indices/source/TestEnum.java similarity index 100% rename from tests/data/param_indices/source/TestEnum.java rename to tests/data/parchment/param_indices/source/TestEnum.java diff --git a/tests/data/partial_matches/expected/TestClass.java b/tests/data/parchment/partial_matches/expected/TestClass.java similarity index 100% rename from tests/data/partial_matches/expected/TestClass.java rename to tests/data/parchment/partial_matches/expected/TestClass.java diff --git a/tests/data/partial_matches/parchment.json b/tests/data/parchment/partial_matches/parchment.json similarity index 100% rename from tests/data/partial_matches/parchment.json rename to tests/data/parchment/partial_matches/parchment.json diff --git a/tests/data/partial_matches/source/TestClass.java b/tests/data/parchment/partial_matches/source/TestClass.java similarity index 100% rename from tests/data/partial_matches/source/TestClass.java rename to tests/data/parchment/partial_matches/source/TestClass.java diff --git a/tests/data/tsrg_file/expected/pkg/TestClass.java b/tests/data/parchment/tsrg_file/expected/pkg/TestClass.java similarity index 100% rename from tests/data/tsrg_file/expected/pkg/TestClass.java rename to tests/data/parchment/tsrg_file/expected/pkg/TestClass.java diff --git a/tests/data/tsrg_file/merged.tsrg b/tests/data/parchment/tsrg_file/merged.tsrg similarity index 100% rename from tests/data/tsrg_file/merged.tsrg rename to tests/data/parchment/tsrg_file/merged.tsrg diff --git a/tests/data/tsrg_file/source/pkg/TestClass.java b/tests/data/parchment/tsrg_file/source/pkg/TestClass.java similarity index 100% rename from tests/data/tsrg_file/source/pkg/TestClass.java rename to tests/data/parchment/tsrg_file/source/pkg/TestClass.java diff --git a/tests/src/test/java/net/neoforged/jst/tests/EmbeddedTest.java b/tests/src/test/java/net/neoforged/jst/tests/EmbeddedTest.java index ce4309d..fbd14cd 100644 --- a/tests/src/test/java/net/neoforged/jst/tests/EmbeddedTest.java +++ b/tests/src/test/java/net/neoforged/jst/tests/EmbeddedTest.java @@ -15,6 +15,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.FileTime; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -106,7 +107,7 @@ void archiveOutput() throws Exception { class FolderSource { @Test void singleFileOutput() { - var sourceFolder = testDataRoot.resolve("nested/source"); + var sourceFolder = testDataRoot.resolve("parchment/nested/source"); var outputFile = tempDir.resolve("Output.java"); // We do not have a unified exception here @@ -118,7 +119,7 @@ void singleFileOutput() { @Test void folderOutput() throws Exception { - var sourceFolder = testDataRoot.resolve("nested/source"); + var sourceFolder = testDataRoot.resolve("parchment/nested/source"); runTool(sourceFolder.toString(), tempDir.toString()); @@ -127,7 +128,7 @@ void folderOutput() throws Exception { @Test void archiveOutput() throws Exception { - var sourceFolder = testDataRoot.resolve("nested/source"); + var sourceFolder = testDataRoot.resolve("parchment/nested/source"); var outputFile = tempDir.resolve("archive.zip"); runTool(sourceFolder.toString(), "--out-format", "archive", outputFile.toString()); @@ -146,7 +147,7 @@ class ArchiveSource { @BeforeEach void setUp() throws IOException { inputFile = tempDir.resolve("input.zip"); - var sourceFolder = testDataRoot.resolve("nested/source"); + var sourceFolder = testDataRoot.resolve("parchment/nested/source"); zipDirectory(sourceFolder, inputFile, p -> true); expectedContent = truncateTimes(loadDirToMap(sourceFolder)); } @@ -174,7 +175,7 @@ void folderOutput() throws Exception { @Test void archiveOutput() throws Exception { - var sourceFolder = testDataRoot.resolve("nested/source"); + var sourceFolder = testDataRoot.resolve("parchment/nested/source"); var outputFile = tempDir.resolve("archive.zip"); runTool(sourceFolder.toString(), "--out-format", "archive", outputFile.toString()); @@ -184,46 +185,85 @@ void archiveOutput() throws Exception { } } - @Test - void testInnerAndLocalClasses() throws Exception { - runTest("nested", "parchment.json"); - } + @Nested + class Parchment { + @Test + void testInnerAndLocalClasses() throws Exception { + runParchmentTest("nested", "parchment.json"); + } - @Test - void testExternalReferences() throws Exception { - runTest("external_refs", "parchment.json"); - } + @Test + void testExternalReferences() throws Exception { + runParchmentTest("external_refs", "parchment.json"); + } - @Test - void testPartialMatches() throws Exception { - runTest("partial_matches", "parchment.json"); + @Test + void testPartialMatches() throws Exception { + runParchmentTest("partial_matches", "parchment.json"); + } + + @Test + void testParamIndices() throws Exception { + runParchmentTest("param_indices", "parchment.json"); + } + + @Test + void testJavadoc() throws Exception { + runParchmentTest("javadoc", "parchment.json"); + } + + @Test + void testTsrgMappings() throws Exception { + runParchmentTest("tsrg_file", "merged.tsrg"); + } } - @Test - void testParamIndices() throws Exception { - runTest("param_indices", "parchment.json"); + @Nested + class AccessTransformer { + @Test + void testFields() throws Exception { + runATTest("fields"); + } + + @Test + void testMethods() throws Exception { + runATTest("methods"); + } + + @Test + void testClasses() throws Exception { + runATTest("classes"); + } + + @Test + void testInnerClasses() throws Exception { + runATTest("inner_classes"); + } + + @Test + void testWildcard() throws Exception { + runATTest("wildcard"); + } } - @Test - void testJavadoc() throws Exception { - runTest("javadoc", "parchment.json"); + protected final void runATTest(String testDirName) throws Exception { + testDirName = "accesstransformer/" + testDirName; + runTest(testDirName, "--enable-accesstransformers", "--access-transformer", testDataRoot.resolve(testDirName).resolve("accesstransformer.cfg").toString()); } - @Test - void testTsrgMappings() throws Exception { - runTest("tsrg_file", "merged.tsrg"); + protected final void runParchmentTest(String testDirName, String mappingsFilename) throws Exception { + testDirName = "parchment/" + testDirName; + runTest(testDirName, "--enable-parchment", "--parchment-mappings", testDataRoot.resolve(testDirName).resolve(mappingsFilename).toString()); } - protected final void runTest(String testDirName, String mappingsFilename) throws Exception { + protected final void runTest(String testDirName, String... args) throws Exception { var testDir = testDataRoot.resolve(testDirName); - var mappingsFile = testDir.resolve(mappingsFilename); var sourceDir = testDir.resolve("source"); var expectedDir = testDir.resolve("expected"); var inputFile = tempDir.resolve("input.jar"); - zipDirectory(sourceDir, inputFile, path -> { - return Files.isDirectory(path) || path.getFileName().toString().endsWith(".java"); - }); + zipDirectory(sourceDir, inputFile, path -> + Files.isDirectory(path) || path.getFileName().toString().endsWith(".java")); var outputFile = tempDir.resolve("output.jar"); @@ -232,16 +272,14 @@ protected final void runTest(String testDirName, String mappingsFilename) throws var librariesFile = tempDir.resolve("libraries.txt"); Files.write(librariesFile, List.of("-e=" + junitJarPath)); - runTool( + final List arguments = new ArrayList<>(Arrays.asList( "--max-queue-depth=1", "--libraries-list", - librariesFile.toString(), - "--enable-parchment", - "--parchment-mappings", - mappingsFile.toString(), - inputFile.toString(), - outputFile.toString() - ); + librariesFile.toString())); + arguments.addAll(Arrays.asList(args)); + arguments.add(inputFile.toString()); + arguments.add(outputFile.toString()); + runTool(arguments.toArray(String[]::new)); try (var zipFile = new ZipFile(outputFile.toFile())) { var it = zipFile.entries().asIterator();