[fixes #1538] Use Enter and MemberEnter to update type mirrors

This commit is contained in:
Rawi01 committed 2021-02-01 09:14:41 +01:00
1 parent 3d3a4c322a
commit 06efa58762
9 files changed
+78 -133

No files matched your search

@@ -28,8 +28,6 @@ import static lombok.javac.handlers.JavacHandlerUtil.*;
import org.mangosdk.spi.ProviderFor;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCBlock;
@@ -57,7 +55,6 @@ import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.configuration.CheckerFrameworkVersion;
import lombok.delombok.LombokOptionsFactory;
import lombok.javac.Javac;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
@@ -249,30 +246,17 @@ public class HandleConstructor {
if (noArgs && noArgsConstructorExists(typeNode)) return;
ListBuffer<Type> argTypes = new ListBuffer<Type>();
for (JavacNode fieldNode : fields) {
Type mirror = getMirrorForFieldType(fieldNode);
if (mirror == null) {
argTypes = null;
break;
}
argTypes.append(mirror);
}
List<Type> argTypes_ = argTypes == null ? null : argTypes.toList();
if (!(skipIfConstructorExists != SkipIfConstructorExists.NO && constructorExists(typeNode) != MemberExistsResult.NOT_EXISTS)) {
JCMethodDecl constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, onConstructor, typeNode, fields, allToDefault, source);
injectMethod(typeNode, constr, argTypes_, Javac.createVoidType(typeNode.getSymbolTable(), CTC_VOID));
injectMethod(typeNode, constr);
}
generateStaticConstructor(staticConstrRequired, typeNode, staticName, level, allToDefault, fields, source, argTypes_);
generateStaticConstructor(staticConstrRequired, typeNode, staticName, level, allToDefault, fields, source);
}
private void generateStaticConstructor(boolean staticConstrRequired, JavacNode typeNode, String staticName, AccessLevel level, boolean allToDefault, List<JavacNode> fields, JavacNode source, List<Type> argTypes_) {
private void generateStaticConstructor(boolean staticConstrRequired, JavacNode typeNode, String staticName, AccessLevel level, boolean allToDefault, List<JavacNode> fields, JavacNode source) {
if (staticConstrRequired) {
ClassSymbol sym = ((JCClassDecl) typeNode.get()).sym;
Type returnType = sym == null ? null : sym.type;
JCMethodDecl staticConstr = createStaticConstructor(staticName, level, typeNode, allToDefault ? List.<JavacNode>nil() : fields, source);
injectMethod(typeNode, staticConstr, argTypes_, returnType);
injectMethod(typeNode, staticConstr);
}
}
@@ -47,7 +47,6 @@ import lombok.javac.JavacTreeMaker.TypeTag;
import org.mangosdk.spi.ProviderFor;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCBinary;
@@ -219,7 +218,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
long access = toJavacModifier(level) | (fieldDecl.mods.flags & Flags.STATIC);
injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker(), source, lazy, onMethod), List.<Type>nil(), getMirrorForFieldType(fieldNode));
injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker(), source, lazy, onMethod));
}
public JCMethodDecl createGetter(long access, JavacNode field, JavacTreeMaker treeMaker, JavacNode source, boolean lazy, List<JCAnnotation> onMethod) {
@@ -41,8 +41,6 @@ import lombok.javac.JavacTreeMaker;
import org.mangosdk.spi.ProviderFor;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCAssign;
import com.sun.tools.javac.tree.JCTree.JCBlock;
@@ -188,17 +186,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
long access = toJavacModifier(level) | (fieldDecl.mods.flags & Flags.STATIC);
JCMethodDecl createdSetter = createSetter(access, fieldNode, fieldNode.getTreeMaker(), sourceNode, onMethod, onParam);
Type fieldType = getMirrorForFieldType(fieldNode);
Type returnType;
if (shouldReturnThis(fieldNode)) {
ClassSymbol sym = ((JCClassDecl) fieldNode.up().get()).sym;
returnType = sym == null ? null : sym.type;
} else {
returnType = Javac.createVoidType(fieldNode.getSymbolTable(), CTC_VOID);
}
injectMethod(fieldNode.up(), createdSetter, fieldType == null ? null : List.of(fieldType), returnType);
injectMethod(fieldNode.up(), createdSetter);
}
public static JCMethodDecl createSetter(long access, JavacNode field, JavacTreeMaker treeMaker, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
@@ -585,7 +585,7 @@ public class HandleSuperBuilder extends JavacAnnotationHandler<SuperBuilder> {
null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>nil(),
maker.Block(0L, statements.toList()), null), job.sourceNode);
injectMethod(job.parentType, constr, null, Javac.createVoidType(job.builderType.getSymbolTable(), CTC_VOID));
injectMethod(job.parentType, constr);
}
private JCMethodDecl generateBuilderMethod(SuperBuilderJob job) {
@@ -22,13 +22,11 @@
package lombok.javac.handlers;
import static lombok.core.handlers.HandlerUtil.handleExperimentalFlagUsage;
import static lombok.javac.Javac.CTC_VOID;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import org.mangosdk.spi.ProviderFor;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCBlock;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
@@ -46,7 +44,6 @@ import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
import lombok.experimental.UtilityClass;
import lombok.javac.Javac;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
@@ -147,7 +144,7 @@ public class HandleUtilityClass extends JavacAnnotationHandler<UtilityClass> {
JCBlock block = maker.Block(0L, createThrowStatement(typeNode, maker));
JCMethodDecl methodDef = maker.MethodDef(mods, name, null, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), block, null);
JCMethodDecl constructor = recursiveSetGeneratedBy(methodDef, typeNode);
JavacHandlerUtil.injectMethod(typeNode, constructor, List.<Type>nil(), Javac.createVoidType(typeNode.getSymbolTable(), CTC_VOID));
JavacHandlerUtil.injectMethod(typeNode, constructor);
}
private List<JCStatement> createThrowStatement(JavacNode typeNode, JavacTreeMaker maker) {
@@ -41,8 +41,6 @@ import lombok.javac.handlers.JavacHandlerUtil.CopyJavadoc;
import org.mangosdk.spi.ProviderFor;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCBlock;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
@@ -212,11 +210,8 @@ public class HandleWith extends JavacAnnotationHandler<With> {
JCMethodDecl createdWith = createWith(access, fieldNode, fieldNode.getTreeMaker(), source, onMethod, onParam, makeAbstract);
createRelevantNonNullAnnotation(fieldNode, createdWith);
ClassSymbol sym = ((JCClassDecl) fieldNode.up().get()).sym;
Type returnType = sym == null ? null : sym.type;
recursiveSetGeneratedBy(createdWith, source);
injectMethod(typeNode, createdWith, List.<Type>of(getMirrorForFieldType(fieldNode)), returnType);
injectMethod(typeNode, createdWith);
}
public JCMethodDecl createWith(long access, JavacNode field, JavacTreeMaker maker, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam, boolean makeAbstract) {
@@ -46,8 +46,6 @@ import org.mangosdk.spi.ProviderFor;
import com.sun.tools.javac.code.BoundKind;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCBlock;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
@@ -206,11 +204,8 @@ public class HandleWithBy extends JavacAnnotationHandler<WithBy> {
long access = toJavacModifier(level);
JCMethodDecl createdWithBy = createWithBy(access, fieldNode, fieldNode.getTreeMaker(), source, onMethod, makeAbstract);
ClassSymbol sym = ((JCClassDecl) fieldNode.up().get()).sym;
Type returnType = sym == null ? null : sym.type;
recursiveSetGeneratedBy(createdWithBy, source);
injectMethod(typeNode, createdWithBy, List.<Type>of(getMirrorForFieldType(fieldNode)), returnType);
injectMethod(typeNode, createdWithBy);
}
private static final LombokImmutableList<String> NAME_JUF_FUNCTION = LombokImmutableList.of("java", "util", "function", "Function");
@@ -37,19 +37,18 @@ import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import javax.lang.model.element.Element;
import com.sun.tools.javac.code.Attribute;
import com.sun.tools.javac.code.BoundKind;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Scope;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.code.Symbol.MethodSymbol;
import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.code.Type.MethodType;
import com.sun.tools.javac.comp.Annotate;
import com.sun.tools.javac.comp.AttrContext;
import com.sun.tools.javac.comp.Enter;
import com.sun.tools.javac.comp.Env;
import com.sun.tools.javac.comp.MemberEnter;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree;
@@ -1012,12 +1011,6 @@ public class JavacHandlerUtil {
return call;
}
public static Type getMirrorForFieldType(JavacNode fieldNode) {
Element fieldElement = fieldNode.getElement();
if (fieldElement instanceof VarSymbol) return ((VarSymbol) fieldElement).type;
return null;
}
/**
* Adds the given new field declaration to the provided type AST Node.
* The field carries the &#64;{@link SuppressWarnings}("all") annotation.
@@ -1073,6 +1066,8 @@ public class JavacHandlerUtil {
insertAfter.tail = fieldEntry;
}
EnterReflect.memberEnter(field, typeNode);
return typeNode.add(field, Kind.FIELD);
}
@@ -1148,24 +1143,6 @@ public class JavacHandlerUtil {
}
}
}
static class JCAnnotationReflect {
private static Field ATTRIBUTE;
static {
try {
ATTRIBUTE = Permit.getField(JCAnnotation.class, "attribute");
} catch (Exception ignore) {}
}
static Attribute.Compound getAttribute(JCAnnotation jcAnnotation) {
try {
return (Attribute.Compound) ATTRIBUTE.get(jcAnnotation);
} catch (Exception e) {
return null;
}
}
}
// jdk9 support, types have changed, names stay the same
static class ClassSymbolMembersField {
@@ -1206,8 +1183,10 @@ public class JavacHandlerUtil {
}
}
public static void injectMethod(JavacNode typeNode, JCMethodDecl method) {
injectMethod(typeNode, method, null, null);
@Deprecated
public static void injectMethod(JavacNode typeNode, JCMethodDecl method, List<Type> paramTypes, Type returnType) {
injectMethod(typeNode, method);
}
/**
@@ -1216,9 +1195,7 @@ public class JavacHandlerUtil {
*
* Also takes care of updating the JavacAST.
*/
public static void injectMethod(JavacNode typeNode, JCMethodDecl method, List<Type> paramTypes, Type returnType) {
Context context = typeNode.getContext();
Symtab symtab = Symtab.instance(context);
public static void injectMethod(JavacNode typeNode, JCMethodDecl method) {
JCClassDecl type = (JCClassDecl) typeNode.get();
if (method.getName().contentEquals("<init>")) {
@@ -1242,55 +1219,11 @@ public class JavacHandlerUtil {
addGenerated(method.mods, typeNode, typeNode.getNodeFor(getGeneratedBy(method)), typeNode.getContext());
type.defs = type.defs.append(method);
List<Symbol.VarSymbol> params = null;
if (method.getParameters() != null && !method.getParameters().isEmpty()) {
ListBuffer<Symbol.VarSymbol> newParams = new ListBuffer<Symbol.VarSymbol>();
for (int i = 0; i < method.getParameters().size(); i++) {
JCTree.JCVariableDecl param = method.getParameters().get(i);
if (param.sym == null) {
Type paramType = paramTypes == null ? param.getType().type : paramTypes.get(i);
VarSymbol varSymbol = new VarSymbol(param.mods.flags, param.name, paramType, symtab.noSymbol);
varSymbol.adr = 1 << i;
List<JCAnnotation> annotations = param.getModifiers().getAnnotations();
if (annotations != null && !annotations.isEmpty()) {
ListBuffer<Attribute.Compound> newAnnotations = new ListBuffer<Attribute.Compound>();
for (JCAnnotation jcAnnotation : annotations) {
Attribute.Compound attribute = JCAnnotationReflect.getAttribute(jcAnnotation);
if (attribute != null) {
newAnnotations.append(attribute);
}
}
if (annotations.length() == newAnnotations.length()) {
varSymbol.appendAttributes(newAnnotations.toList());
}
}
newParams.append(varSymbol);
} else {
newParams.append(param.sym);
}
}
params = newParams.toList();
if (params.length() != method.getParameters().length()) params = null;
}
fixMethodMirror(typeNode.getContext(), typeNode.getElement(), method.getModifiers().flags, method.getName(), paramTypes, params, returnType);
EnterReflect.memberEnter(method, typeNode);
typeNode.add(method, Kind.METHOD);
}
private static void fixMethodMirror(Context context, Element typeMirror, long access, Name methodName, List<Type> paramTypes, List<Symbol.VarSymbol> params, Type returnType) {
if (typeMirror == null || paramTypes == null || returnType == null) return;
ClassSymbol cs = (ClassSymbol) typeMirror;
MethodSymbol methodSymbol = new MethodSymbol(access, methodName, new MethodType(paramTypes, returnType, List.<Type>nil(), Symtab.instance(context).methodClass), cs);
if (params != null && !params.isEmpty()) {
methodSymbol.params = params;
for (VarSymbol varSymbol : params) {
varSymbol.owner = methodSymbol;
}
}
ClassSymbolMembersField.enter(cs, methodSymbol);
}
/**
* Adds an inner type (class, interface, enum) to the given type. Cannot inject top-level types.
*
@@ -1303,9 +1236,55 @@ public class JavacHandlerUtil {
addSuppressWarningsAll(type.mods, typeNode, typeNode.getNodeFor(getGeneratedBy(type)), typeNode.getContext());
addGenerated(type.mods, typeNode, typeNode.getNodeFor(getGeneratedBy(type)), typeNode.getContext());
typeDecl.defs = typeDecl.defs.append(type);
EnterReflect.classEnter(type, typeNode);
return typeNode.add(type, Kind.TYPE);
}
static class EnterReflect {
private static final Method classEnter;
private static final Method memberEnter;
private static final Method blockAnnotations;
private static final Method unblockAnnotations;
static {
classEnter = Permit.permissiveGetMethod(Enter.class, "classEnter", JCTree.class, Env.class);
memberEnter = Permit.permissiveGetMethod(MemberEnter.class, "memberEnter", JCTree.class, Env.class);
Method block = Permit.permissiveGetMethod(Annotate.class, "blockAnnotations");
if (block == null) block = Permit.permissiveGetMethod(Annotate.class, "enterStart");
blockAnnotations = block;
Method unblock = Permit.permissiveGetMethod(Annotate.class, "unblockAnnotations");
if (unblock == null) unblock = Permit.permissiveGetMethod(Annotate.class, "enterDone");
unblockAnnotations = unblock;
}
static Type classEnter(JCTree tree, JavacNode parent) {
Enter enter = Enter.instance(parent.getContext());
Env<AttrContext> classEnv = enter.getEnv((TypeSymbol) parent.getElement());
Type type = (Type) Permit.invokeSneaky(classEnter, enter, tree, classEnv);
if (type == null) return null;
type.complete();
return type;
}
static void memberEnter(JCTree tree, JavacNode parent) {
Context context = parent.getContext();
MemberEnter me = MemberEnter.instance(context);
Annotate annotate = Annotate.instance(context);
Enter enter = Enter.instance(context);
Env<AttrContext> classEnv = enter.getEnv((TypeSymbol) parent.getElement());
if (classEnv == null) return;
Permit.invokeSneaky(blockAnnotations, annotate);
Permit.invokeSneaky(memberEnter, me, tree, classEnv);
Permit.invokeSneaky(unblockAnnotations, annotate);
}
}
public static long addFinalIfNeeded(long flags, Context context) {
boolean addFinal = LombokOptionsFactory.getDelombokOptions(context).getFormatPreferences().generateFinalParams();
+8
View File
@@ -122,6 +122,14 @@ public class Permit {
return setAccessible(m);
}
public static Method permissiveGetMethod(Class<?> c, String mName, Class<?>... parameterTypes) {
try {
return getMethod(c, mName, parameterTypes);
} catch (Exception ignore) {
return null;
}
}
public static Field getField(Class<?> c, String fName) throws NoSuchFieldException {
Field f = null;
Class<?> oc = c;