Skip to content

Commit 7b55b32

Browse files
authored
Flag to inherit access transformers on methods (#1)
Useful for modifying methods exposed by types with a lot of children to avoid specifying them all.
1 parent 9a1b6c9 commit 7b55b32

File tree

18 files changed

+146
-10
lines changed

18 files changed

+146
-10
lines changed

README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,9 @@ Plugin - parchment
102102
Plugin - accesstransformers
103103
--access-transformer=<atFiles>
104104
105+
--access-transformer-inherit-method
106+
Whether or not access transformers on methods should be inherited from
107+
parent types
105108
--access-transformer-validation=<validation>
106109
The level of validation to use for ats
107110
--enable-accesstransformers

accesstransformers/src/main/java/net/neoforged/jst/accesstransformers/AccessTransformersTransformer.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@ public class AccessTransformersTransformer implements SourceTransformer {
2525
@CommandLine.Option(names = "--access-transformer-validation", description = "The level of validation to use for ats")
2626
public AccessTransformerValidation validation = AccessTransformerValidation.LOG;
2727

28+
@CommandLine.Option(
29+
names = "--access-transformer-inherit-method",
30+
description = "Whether or not access transformers on methods should be inherited from parent types"
31+
)
32+
public boolean inheritMethodAccessTransformers = false;
33+
2834
private AccessTransformerFiles ats;
2935
private Map<Target, Transformation> pendingATs;
3036
private Logger logger;
@@ -64,7 +70,13 @@ public boolean afterRun(TransformContext context) {
6470

6571
@Override
6672
public void visitFile(PsiFile psiFile, Replacements replacements) {
67-
var visitor = new ApplyATsVisitor(ats, replacements, pendingATs, logger);
73+
var visitor = new ApplyATsVisitor(
74+
ats,
75+
replacements,
76+
pendingATs,
77+
this.inheritMethodAccessTransformers,
78+
logger
79+
);
6880
visitor.visitFile(psiFile);
6981
if (visitor.errored) {
7082
errored = true;

accesstransformers/src/main/java/net/neoforged/jst/accesstransformers/ApplyATsVisitor.java

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
import com.intellij.psi.PsiRecursiveElementVisitor;
1515
import com.intellij.psi.PsiWhiteSpace;
1616
import com.intellij.psi.util.ClassUtil;
17-
import com.intellij.psi.util.PsiClassUtil;
1817
import net.neoforged.accesstransformer.parser.AccessTransformerFiles;
1918
import net.neoforged.accesstransformer.parser.Target;
2019
import net.neoforged.accesstransformer.parser.Transformation;
@@ -46,12 +45,20 @@ class ApplyATsVisitor extends PsiRecursiveElementVisitor {
4645
private final AccessTransformerFiles ats;
4746
private final Replacements replacements;
4847
private final Map<Target, Transformation> pendingATs;
48+
private final boolean inheritMethodATs;
4949
private final Logger logger;
5050
boolean errored = false;
5151

52-
public ApplyATsVisitor(AccessTransformerFiles ats, Replacements replacements, Map<Target, Transformation> pendingATs, Logger logger) {
52+
public ApplyATsVisitor(
53+
AccessTransformerFiles ats,
54+
Replacements replacements,
55+
Map<Target, Transformation> pendingATs,
56+
boolean inheritMethodATs,
57+
Logger logger
58+
) {
5359
this.ats = ats;
5460
this.replacements = replacements;
61+
this.inheritMethodATs = inheritMethodATs;
5562
this.logger = logger;
5663
this.pendingATs = pendingATs;
5764
}
@@ -61,7 +68,25 @@ public void visitElement(@NotNull PsiElement element) {
6168
if (element instanceof PsiClass psiClass) {
6269
if (psiClass.getQualifiedName() != null) {
6370
String className = ClassUtil.getJVMClassName(psiClass);
64-
if (!ats.containsClassTarget(className)) {
71+
boolean shouldBeSkipped = !ats.containsClassTarget(className);
72+
73+
// Classes may need changing that are not in the source at set.
74+
// Check if any of this classe's parents are in the source at set first to potentially inherit their ATs.
75+
if (shouldBeSkipped && this.inheritMethodATs) {
76+
for (
77+
PsiClass parentType = psiClass.getSuperClass();
78+
parentType != null;
79+
parentType = parentType.getSuperClass()
80+
) {
81+
if (this.ats.containsClassTarget(ClassUtil.getJVMClassName(parentType))) {
82+
// Process class as we inherit method ATs and we found *some* AT.
83+
// Heuristic isn't perfect, but the alternative would be scanning *all* method targets for the parent owning type.
84+
shouldBeSkipped = false;
85+
break;
86+
}
87+
}
88+
}
89+
if (shouldBeSkipped) {
6590
// Skip this class and its children, but not the inner classes
6691
for (PsiClass innerClass : psiClass.getInnerClasses()) {
6792
visitElement(innerClass);
@@ -106,10 +131,20 @@ public void visitElement(@NotNull PsiElement element) {
106131
apply(pendingATs.remove(new Target.FieldTarget(className, field.getName())), field, cls);
107132
}
108133
} else if (element instanceof PsiMethod method) {
109-
final var cls = method.getContainingClass();
110-
if (cls != null && cls.getQualifiedName() != null) {
111-
String className = ClassUtil.getJVMClassName(cls);
112-
apply(pendingATs.remove(method(className, method)), method, cls);
134+
final var owningType = method.getContainingClass();
135+
if (owningType != null) {
136+
// Locate transformation by searching owning type and its parents.
137+
// Remove if this is AT is defined for its immediate owning type.
138+
Transformation foundTransformation = this.pendingATs.remove(method(ClassUtil.getJVMClassName(owningType), method));
139+
PsiClass definedForSuperType = owningType;
140+
for (;
141+
this.inheritMethodATs && foundTransformation == null && definedForSuperType != null && definedForSuperType.getQualifiedName() != null;
142+
definedForSuperType = definedForSuperType.getSuperClass()
143+
) {
144+
foundTransformation = this.ats.getAccessTransformers().get(method(ClassUtil.getJVMClassName(definedForSuperType), method));
145+
}
146+
147+
apply(foundTransformation, method, owningType);
113148
}
114149
}
115150

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
public Parent flag()Z
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class Child extends Parent {
2+
@Override
3+
public boolean flag() {
4+
return true;
5+
}
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class Grandchild extends Child {
2+
@Override
3+
public boolean flag() {
4+
return false;
5+
}
6+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class Parent {
2+
public boolean flag() {
3+
return false;
4+
}
5+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class Child extends Parent {
2+
@Override
3+
protected boolean flag() {
4+
return true;
5+
}
6+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class Grandchild extends Child {
2+
@Override
3+
protected boolean flag() {
4+
return false;
5+
}
6+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
class Parent {
2+
protected boolean flag() {
3+
return false;
4+
}
5+
}

0 commit comments

Comments
 (0)