Merge branch 'enter-types-methods-fields' of git://github.com/Rawi01/lombok into Rawi01-enter-types-methods-fields

This commit is contained in:
Reinier Zwitserloot
2021-04-18 05:45:28 +02:00
9 changed files with 186 additions and 125 deletions
@@ -26,8 +26,6 @@ import static lombok.javac.Javac.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
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;
@@ -55,7 +53,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;
@@ -243,30 +240,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);
}
}
@@ -46,7 +46,6 @@ import lombok.javac.JavacTreeMaker.TypeTag;
import lombok.spi.Provides;
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;
@@ -214,7 +213,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) {
@@ -40,8 +40,6 @@ import lombok.javac.JavacTreeMaker;
import lombok.spi.Provides;
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;
@@ -184,17 +182,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) {
@@ -583,7 +583,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,11 +22,9 @@
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 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;
@@ -44,7 +42,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;
@@ -141,7 +138,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) {
@@ -40,8 +40,6 @@ import lombok.javac.handlers.JavacHandlerUtil.CopyJavadoc;
import lombok.spi.Provides;
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;
@@ -211,11 +209,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) {
@@ -45,8 +45,6 @@ import lombok.spi.Provides;
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;
@@ -204,11 +202,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,19 @@ 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;
@@ -1010,12 +1010,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.
@@ -1071,6 +1065,8 @@ public class JavacHandlerUtil {
insertAfter.tail = fieldEntry;
}
EnterReflect.memberEnter(field, typeNode);
return typeNode.add(field, Kind.FIELD);
}
@@ -1148,19 +1144,30 @@ public class JavacHandlerUtil {
}
static class JCAnnotationReflect {
private static Field ATTRIBUTE;
private static final Field ATTRIBUTE;
static {
try {
ATTRIBUTE = Permit.getField(JCAnnotation.class, "attribute");
} catch (Exception ignore) {}
ATTRIBUTE = Permit.permissiveGetField(JCAnnotation.class, "attribute");
}
static Attribute.Compound getAttribute(JCAnnotation jcAnnotation) {
try {
return (Attribute.Compound) ATTRIBUTE.get(jcAnnotation);
} catch (Exception e) {
return null;
if (ATTRIBUTE != null) {
try {
return (Attribute.Compound) ATTRIBUTE.get(jcAnnotation);
} catch (Exception e) {
// Ignore
}
}
return null;
}
static void setAttribute(JCAnnotation jcAnnotation, Attribute.Compound attribute) {
if (ATTRIBUTE != null) {
try {
Permit.set(ATTRIBUTE, jcAnnotation, attribute);
} catch (Exception e) {
// Ignore
}
}
}
}
@@ -1204,8 +1211,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);
}
/**
@@ -1214,9 +1223,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>")) {
@@ -1240,55 +1247,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.
*
@@ -1301,9 +1264,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();
@@ -1802,10 +1811,49 @@ public class JavacHandlerUtil {
addError(errorName, annotationNode);
}
}
for (JCAnnotation annotation : result) {
clearTypes(annotation);
}
ast.args = params.toList();
return result.toList();
}
/**
* Removes all type information from the provided tree.
*/
private static void clearTypes(JCTree tree) {
tree.accept(new TreeScanner() {
@Override public void scan(JCTree tree) {
tree.type = null;
super.scan(tree);
}
@Override public void visitClassDef(JCClassDecl tree) {
tree.sym = null;
super.visitClassDef(tree);
}
@Override public void visitMethodDef(JCMethodDecl tree) {
tree.sym = null;
super.visitMethodDef(tree);
}
@Override public void visitVarDef(JCVariableDecl tree) {
tree.sym = null;
super.visitVarDef(tree);
}
@Override public void visitSelect(JCFieldAccess tree) {
tree.sym = null;
super.visitSelect(tree);
}
@Override public void visitIdent(JCIdent tree) {
tree.sym = null;
super.visitIdent(tree);
}
@Override public void visitAnnotation(JCAnnotation tree) {
JCAnnotationReflect.setAttribute(tree, null);
super.visitAnnotation(tree);
}
});
}
private static void addError(String errorName, JavacNode node) {
if (node.getLatestJavaSpecSupported() < 8) {
node.addError("The correct format up to JDK7 is " + errorName + "=@__({@SomeAnnotation, @SomeOtherAnnotation}))");
+57 -2
View File
@@ -35,19 +35,21 @@ import java.util.Deque;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import com.sun.source.util.TreePath;
import com.sun.source.util.Trees;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.code.Symbol;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCAssign;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
@@ -57,11 +59,12 @@ import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCModifiers;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.JCTree.TypeBoundKind;
import com.sun.tools.javac.tree.TreeScanner;
import lombok.delombok.Delombok;
import lombok.javac.CapturingDiagnosticListener;
import lombok.javac.Javac;
import lombok.javac.CapturingDiagnosticListener.CompilerMessage;
import lombok.javac.Javac;
public class RunTestsViaDelombok extends AbstractRunTests {
private Delombok delombok = new Delombok();
@@ -78,6 +81,7 @@ public class RunTestsViaDelombok extends AbstractRunTests {
delombok.setDiagnosticsListener(new CapturingDiagnosticListener(file, messages));
if (checkPositions) delombok.addAdditionalAnnotationProcessor(new ValidatePositionProcessor(version));
delombok.addAdditionalAnnotationProcessor(new ValidateTypesProcessor());
delombok.addFile(file.getAbsoluteFile().getParentFile(), file.getName());
delombok.setSourcepath(file.getAbsoluteFile().getParent());
@@ -178,6 +182,57 @@ public class RunTestsViaDelombok extends AbstractRunTests {
}
}
public static class ValidateTypesProcessor extends TreeProcessor {
@Override void processCompilationUnit(final JCCompilationUnit unit) {
final Stack<JCTree> parents = new Stack<JCTree>();
parents.add(unit);
unit.accept(new TreeScanner() {
private JCTree parent;
@Override public void scan(JCTree tree) {
parent = parents.peek();
parents.push(tree);
super.scan(tree);
parents.pop();
}
@Override public void visitClassDef(JCClassDecl tree) {
// Skip anonymous or local classes, they have no symbol
if (!(parent instanceof JCClassDecl || parent instanceof JCCompilationUnit)) return;
validateSymbol(tree, tree.sym);
super.visitClassDef(tree);
};
@Override public void visitMethodDef(JCMethodDecl tree) {
validateSymbol(tree, tree.sym);
super.visitMethodDef(tree);
}
@Override public void visitVarDef(JCVariableDecl tree) {
// Skip non-field variables
if (!(parent instanceof JCClassDecl)) return;
validateSymbol(tree, tree.sym);
super.visitVarDef(tree);
}
private void validateSymbol(JCTree tree, Symbol sym) {
if (sym == null) {
fail("Missing symbol for " + tree);
}
// Skip top level classes
if (sym.owner.getKind() == ElementKind.PACKAGE) return;
if (!sym.owner.getEnclosedElements().contains(sym)) {
fail(tree + " not added to parent");
}
}
});
}
}
public static abstract class TreeProcessor extends AbstractProcessor {
private Trees trees;
@Override public synchronized void init(ProcessingEnvironment processingEnv) {