Java Code Examples for lombok.javac.JavacNode#get()

The following examples show how to use lombok.javac.JavacNode#get() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: HandleFieldDefaults.java    From EasyMPermission with MIT License 6 votes vote down vote up
public void setFieldDefaultsForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level, boolean makeFinal) {
	JCVariableDecl field = (JCVariableDecl) fieldNode.get();
	if (level != null && level != AccessLevel.NONE) {
		if ((field.mods.flags & (Flags.PUBLIC | Flags.PRIVATE | Flags.PROTECTED)) == 0) {
			if (!hasAnnotationAndDeleteIfNeccessary(PackagePrivate.class, fieldNode)) {
				field.mods.flags |= toJavacModifier(level);
			}
		}
	}
	
	if (makeFinal && (field.mods.flags & Flags.FINAL) == 0) {
		if (!hasAnnotationAndDeleteIfNeccessary(NonFinal.class, fieldNode)) {
			field.mods.flags |= Flags.FINAL;
		}
	}
	
	fieldNode.rebuild();
}
 
Example 2
Source File: JavacHandlerUtil.java    From EasyMPermission with MIT License 6 votes vote down vote up
public static JCExpression cloneSelfType(JavacNode childOfType) {
	JavacNode typeNode = childOfType;
	JavacTreeMaker maker = childOfType.getTreeMaker();
	while (typeNode != null && typeNode.getKind() != Kind.TYPE) typeNode = typeNode.up();
	if (typeNode != null && typeNode.get() instanceof JCClassDecl) {
		JCClassDecl type = (JCClassDecl) typeNode.get();
		ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
		if (!type.typarams.isEmpty()) {
			for (JCTypeParameter tp : type.typarams) {
				typeArgs.append(maker.Ident(tp.name));
			}
			return maker.TypeApply(maker.Ident(type.name), typeArgs.toList());
		} else {
			return maker.Ident(type.name);
		}
	} else {
		return null;
	}
}
 
Example 3
Source File: JavacHandlerUtil.java    From EasyMPermission with MIT License 6 votes vote down vote up
/**
 * Given a list of field names and a node referring to a type, finds each name in the list that does not match a field within the type.
 */
public static List<Integer> createListOfNonExistentFields(List<String> list, JavacNode type, boolean excludeStandard, boolean excludeTransient) {
	boolean[] matched = new boolean[list.size()];
	
	for (JavacNode child : type.down()) {
		if (list.isEmpty()) break;
		if (child.getKind() != Kind.FIELD) continue;
		JCVariableDecl field = (JCVariableDecl)child.get();
		if (excludeStandard) {
			if ((field.mods.flags & Flags.STATIC) != 0) continue;
			if (field.name.toString().startsWith("$")) continue;
		}
		if (excludeTransient && (field.mods.flags & Flags.TRANSIENT) != 0) continue;
		
		int idx = list.indexOf(child.getName());
		if (idx > -1) matched[idx] = true;
	}
	
	ListBuffer<Integer> problematic = new ListBuffer<Integer>();
	for (int i = 0 ; i < list.size() ; i++) {
		if (!matched[i]) problematic.append(i);
	}
	
	return problematic.toList();
}
 
Example 4
Source File: JavacHandlerUtil.java    From EasyMPermission with MIT License 5 votes vote down vote up
/**
 * Returns the type of the field, unless a getter exists for this field, in which case the return type of the getter is returned.
 * 
 * @see #createFieldAccessor(TreeMaker, JavacNode, FieldAccess)
 */
static JCExpression getFieldType(JavacNode field, FieldAccess fieldAccess) {
	boolean lookForGetter = lookForGetter(field, fieldAccess);
	
	GetterMethod getter = lookForGetter ? findGetter(field) : null;
	
	if (getter == null) {
		return ((JCVariableDecl)field.get()).vartype;
	}
	
	return getter.type;
}
 
Example 5
Source File: HandleFieldDefaults.java    From EasyMPermission with MIT License 5 votes vote down vote up
public boolean generateFieldDefaultsForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean makeFinal, boolean checkForTypeLevelFieldDefaults) {
	if (checkForTypeLevelFieldDefaults) {
		if (hasAnnotation(FieldDefaults.class, typeNode)) {
			//The annotation will make it happen, so we can skip it.
			return true;
		}
	}
	
	JCClassDecl typeDecl = null;
	if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get();
	long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags;
	boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION)) != 0;
	
	if (typeDecl == null || notAClass) {
		errorNode.addError("@FieldDefaults is only supported on a class or an enum.");
		return false;
	}
	
	for (JavacNode field : typeNode.down()) {
		if (field.getKind() != Kind.FIELD) continue;
		JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
		//Skip fields that start with $
		if (fieldDecl.name.toString().startsWith("$")) continue;
		
		setFieldDefaultsForField(field, errorNode.get(), level, makeFinal);
	}
	
	return true;
}
 
Example 6
Source File: HandleBuilder.java    From EasyMPermission with MIT License 5 votes vote down vote up
private void makeSimpleSetterMethodForBuilder(JavacNode builderType, JavacNode fieldNode, JavacNode source, boolean fluent, boolean chain) {
	Name fieldName = ((JCVariableDecl) fieldNode.get()).name;
	
	for (JavacNode child : builderType.down()) {
		if (child.getKind() != Kind.METHOD) continue;
		Name existingName = ((JCMethodDecl) child.get()).name;
		if (existingName.equals(fieldName)) return;
	}
	
	String setterName = fluent ? fieldNode.getName() : HandlerUtil.buildAccessorName("set", fieldNode.getName());
	
	JavacTreeMaker maker = fieldNode.getTreeMaker();
	JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, fieldNode, maker, setterName, chain, source, List.<JCAnnotation>nil(), List.<JCAnnotation>nil());
	injectMethod(builderType, newMethod);
}
 
Example 7
Source File: SingletonJavacHandler.java    From tutorials with MIT License 5 votes vote down vote up
private JCTree.JCBlock addReturnBlock(JavacTreeMaker singletonClassTreeMaker, JavacNode holderInnerClass) {

        JCTree.JCClassDecl holderInnerClassDecl = (JCTree.JCClassDecl) holderInnerClass.get();
        JavacTreeMaker holderInnerClassTreeMaker = holderInnerClass.getTreeMaker();
        JCTree.JCIdent holderInnerClassType = holderInnerClassTreeMaker.Ident(holderInnerClassDecl.name);

        JCTree.JCFieldAccess instanceVarAccess = holderInnerClassTreeMaker.Select(holderInnerClassType, holderInnerClass.toName("INSTANCE"));
        JCTree.JCReturn returnValue = singletonClassTreeMaker.Return(instanceVarAccess);

        ListBuffer<JCTree.JCStatement> statements = new ListBuffer<>();
        statements.append(returnValue);

        return singletonClassTreeMaker.Block(0L, statements.toList());
    }
 
Example 8
Source File: HandleExtensionMethod.java    From EasyMPermission with MIT License 5 votes vote down vote up
private void handleMethodCall(final JCMethodInvocation methodCall) {
	JavacNode methodCallNode = annotationNode.getAst().get(methodCall);
	
	if (methodCallNode == null) {
		// This should mean the node does not exist in the source at all. This is the case for generated nodes, such as implicit super() calls.
		return;
	}
	
	JavacNode surroundingType = upToTypeNode(methodCallNode);
	
	TypeSymbol surroundingTypeSymbol = ((JCClassDecl)surroundingType.get()).sym;
	JCExpression receiver = receiverOf(methodCall);
	String methodName = methodNameOf(methodCall);
	
	if ("this".equals(methodName) || "super".equals(methodName)) return;
	Type resolvedMethodCall = CLASS_AND_METHOD.resolveMember(methodCallNode, methodCall);
	if (resolvedMethodCall == null) return;
	if (!suppressBaseMethods && !(resolvedMethodCall instanceof ErrorType)) return;
	Type receiverType = CLASS_AND_METHOD.resolveMember(methodCallNode, receiver);
	if (receiverType == null) return;
	if (receiverType.tsym.toString().endsWith(receiver.toString())) return;
	
	Types types = Types.instance(annotationNode.getContext());
	for (Extension extension : extensions) {
		TypeSymbol extensionProvider = extension.extensionProvider;
		if (surroundingTypeSymbol == extensionProvider) continue;
		for (MethodSymbol extensionMethod : extension.extensionMethods) {
			if (!methodName.equals(extensionMethod.name.toString())) continue;
			Type extensionMethodType = extensionMethod.type;
			if (!MethodType.class.isInstance(extensionMethodType) && !ForAll.class.isInstance(extensionMethodType)) continue;
			Type firstArgType = types.erasure(extensionMethodType.asMethodType().argtypes.get(0));
			if (!types.isAssignable(receiverType, firstArgType)) continue;
			methodCall.args = methodCall.args.prepend(receiver);
			methodCall.meth = chainDotsString(annotationNode, extensionProvider.toString() + "." + methodName);
			return;
		}
	}
}
 
Example 9
Source File: HandleValue.java    From EasyMPermission with MIT License 5 votes vote down vote up
@Override public void handle(AnnotationValues<Value> annotation, JCAnnotation ast, JavacNode annotationNode) {
	@SuppressWarnings("deprecation")
	Class<? extends Annotation> oldExperimentalValue = lombok.experimental.Value.class;
	
	handleFlagUsage(annotationNode, ConfigurationKeys.VALUE_FLAG_USAGE, "@Value");
	
	deleteAnnotationIfNeccessary(annotationNode, Value.class, oldExperimentalValue);
	JavacNode typeNode = annotationNode.up();
	boolean notAClass = !isClass(typeNode);
	
	if (notAClass) {
		annotationNode.addError("@Value is only supported on a class.");
		return;
	}
	
	String staticConstructorName = annotation.getInstance().staticConstructor();
	
	if (!hasAnnotationAndDeleteIfNeccessary(NonFinal.class, typeNode)) {
		JCModifiers jcm = ((JCClassDecl) typeNode.get()).mods;
		if ((jcm.flags & Flags.FINAL) == 0) {
			jcm.flags |= Flags.FINAL;
			typeNode.rebuild();
		}
	}
	new HandleFieldDefaults().generateFieldDefaultsForType(typeNode, annotationNode, AccessLevel.PRIVATE, true, true);
	
	// TODO move this to the end OR move it to the top in eclipse.
	new HandleConstructor().generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, staticConstructorName, SkipIfConstructorExists.YES, annotationNode);
	new HandleGetter().generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
	new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode);
	new HandleToString().generateToStringForType(typeNode, annotationNode);
}
 
Example 10
Source File: HandleGetter.java    From EasyMPermission with MIT License 5 votes vote down vote up
public boolean fieldQualifiesForGetterGeneration(JavacNode field) {
	if (field.getKind() != Kind.FIELD) return false;
	JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
	//Skip fields that start with $
	if (fieldDecl.name.toString().startsWith("$")) return false;
	//Skip static fields.
	if ((fieldDecl.mods.flags & Flags.STATIC) != 0) return false;
	return true;
}
 
Example 11
Source File: SingletonJavacHandler.java    From tutorials with MIT License 5 votes vote down vote up
private void addInstanceVar(JavacNode singletonClass, JavacTreeMaker singletonClassTM, JavacNode holderClass) {
    JCTree.JCModifiers fieldMod = singletonClassTM.Modifiers(Flags.PRIVATE | Flags.STATIC | Flags.FINAL);

    JCTree.JCClassDecl singletonClassDecl = (JCTree.JCClassDecl) singletonClass.get();
    JCTree.JCIdent singletonClassType = singletonClassTM.Ident(singletonClassDecl.name);

    JCTree.JCNewClass newKeyword = singletonClassTM.NewClass(null, List.nil(), singletonClassType, List.nil(), null);

    JCTree.JCVariableDecl instanceVar = singletonClassTM.VarDef(fieldMod, singletonClass.toName("INSTANCE"), singletonClassType, newKeyword);
    JavacHandlerUtil.injectField(holderClass, instanceVar);
}
 
Example 12
Source File: JavacHandlerUtil.java    From EasyMPermission with MIT License 5 votes vote down vote up
/**
 * Generates a new statement that checks if the given variable is null, and if so, throws a specified exception with the
 * variable name as message.
 * 
 * @param exName The name of the exception to throw; normally {@code java.lang.NullPointerException}.
 */
public static JCStatement generateNullCheck(JavacTreeMaker maker, JavacNode variable, JavacNode source) {
	NullCheckExceptionType exceptionType = source.getAst().readConfiguration(ConfigurationKeys.NON_NULL_EXCEPTION_TYPE);
	if (exceptionType == null) exceptionType = NullCheckExceptionType.NULL_POINTER_EXCEPTION;
	
	JCVariableDecl varDecl = (JCVariableDecl) variable.get();
	if (isPrimitive(varDecl.vartype)) return null;
	Name fieldName = varDecl.name;
	JCExpression exType = genTypeRef(variable, exceptionType.getExceptionType());
	JCExpression exception = maker.NewClass(null, List.<JCExpression>nil(), exType, List.<JCExpression>of(maker.Literal(exceptionType.toExceptionMessage(fieldName.toString()))), null);
	JCStatement throwStatement = maker.Throw(exception);
	JCBlock throwBlock = maker.Block(0, List.of(throwStatement));
	return maker.If(maker.Binary(CTC_EQUAL, maker.Ident(fieldName), maker.Literal(CTC_BOT, null)), throwBlock, null);
}
 
Example 13
Source File: JavacHandlerUtil.java    From EasyMPermission with MIT License 5 votes vote down vote up
/**
 * Adds an inner type (class, interface, enum) to the given type. Cannot inject top-level types.
 * 
 * @param typeNode parent type to inject new type into
 * @param type New type (class, interface, etc) to inject.
 * @return 
 */
public static JavacNode injectType(JavacNode typeNode, final JCClassDecl type) {
	JCClassDecl typeDecl = (JCClassDecl) typeNode.get();
	addSuppressWarningsAll(type.mods, typeNode, type.pos, getGeneratedBy(type), typeNode.getContext());
	addGenerated(type.mods, typeNode, type.pos, getGeneratedBy(type), typeNode.getContext());
	typeDecl.defs = typeDecl.defs.append(type);
	return typeNode.add(type, Kind.TYPE);
}
 
Example 14
Source File: HandleWither.java    From EasyMPermission with MIT License 5 votes vote down vote up
public void generateWitherForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean checkForTypeLevelWither) {
	if (checkForTypeLevelWither) {
		if (hasAnnotation(Wither.class, typeNode)) {
			//The annotation will make it happen, so we can skip it.
			return;
		}
	}
	
	JCClassDecl typeDecl = null;
	if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get();
	long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags;
	boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0;
	
	if (typeDecl == null || notAClass) {
		errorNode.addError("@Wither is only supported on a class or a field.");
		return;
	}
	
	for (JavacNode field : typeNode.down()) {
		if (field.getKind() != Kind.FIELD) continue;
		JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
		//Skip fields that start with $
		if (fieldDecl.name.toString().startsWith("$")) continue;
		//Skip static fields.
		if ((fieldDecl.mods.flags & Flags.STATIC) != 0) continue;
		//Skip final initialized fields.
		if ((fieldDecl.mods.flags & Flags.FINAL) != 0 && fieldDecl.init != null) continue;
		
		generateWitherForField(field, errorNode.get(), level);
	}
}
 
Example 15
Source File: JavacHandlerUtil.java    From EasyMPermission with MIT License 5 votes vote down vote up
static JCExpression createFieldAccessor(JavacTreeMaker maker, JavacNode field, FieldAccess fieldAccess, JCExpression receiver) {
	boolean lookForGetter = lookForGetter(field, fieldAccess);
	
	GetterMethod getter = lookForGetter ? findGetter(field) : null;
	JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
	
	if (getter == null) {
		if (receiver == null) {
			if ((fieldDecl.mods.flags & Flags.STATIC) == 0) {
				receiver = maker.Ident(field.toName("this"));
			} else {
				JavacNode containerNode = field.up();
				if (containerNode != null && containerNode.get() instanceof JCClassDecl) {
					JCClassDecl container = (JCClassDecl) field.up().get();
					receiver = maker.Ident(container.name);
				}
			}
		}
		
		return receiver == null ? maker.Ident(fieldDecl.name) : maker.Select(receiver, fieldDecl.name);
	}
	
	if (receiver == null) receiver = maker.Ident(field.toName("this"));
	JCMethodInvocation call = maker.Apply(List.<JCExpression>nil(),
			maker.Select(receiver, getter.name), List.<JCExpression>nil());
	return call;
}
 
Example 16
Source File: JavacHandlerUtil.java    From EasyMPermission with MIT License 5 votes vote down vote up
/**
 * Adds the given new method declaration to the provided type AST Node.
 * Can also inject constructors.
 * 
 * Also takes care of updating the JavacAST.
 */
public static void injectMethod(JavacNode typeNode, JCMethodDecl method) {
	JCClassDecl type = (JCClassDecl) typeNode.get();
	
	if (method.getName().contentEquals("<init>")) {
		//Scan for default constructor, and remove it.
		int idx = 0;
		for (JCTree def : type.defs) {
			if (def instanceof JCMethodDecl) {
				if ((((JCMethodDecl)def).mods.flags & Flags.GENERATEDCONSTR) != 0) {
					JavacNode tossMe = typeNode.getNodeFor(def);
					if (tossMe != null) tossMe.up().removeChild(tossMe);
					type.defs = addAllButOne(type.defs, idx);
					if (type.sym != null && type.sym.members_field != null) {
						 type.sym.members_field.remove(((JCMethodDecl)def).sym);
					}
					break;
				}
			}
			idx++;
		}
	}
	
	addSuppressWarningsAll(method.mods, typeNode, method.pos, getGeneratedBy(method), typeNode.getContext());
	addGenerated(method.mods, typeNode, method.pos, getGeneratedBy(method), typeNode.getContext());
	type.defs = type.defs.append(method);
	
	typeNode.add(method, Kind.METHOD);
}
 
Example 17
Source File: HandleColumn.java    From sqlitemagic with Apache License 2.0 5 votes vote down vote up
@Override
public void handle(AnnotationValues<Column> annotation, JCTree.JCAnnotation ast, JavacNode annotationNode) {
  // FIXME: 9.04.16 remove
  JavacNode node = annotationNode.up();
  if (node.getKind() == AST.Kind.FIELD) {
    JCTree.JCVariableDecl fieldDec = (JCTree.JCVariableDecl) node.get();
    if ((fieldDec.mods.flags & Flags.PRIVATE) != 0 && (fieldDec.mods.flags & (Flags.STATIC | Flags.FINAL)) == 0) {
      fieldDec.mods.flags &= ~Flags.PRIVATE;
    }
    node.rebuild();
  }
}
 
Example 18
Source File: HandleGetter.java    From EasyMPermission with MIT License 4 votes vote down vote up
public void createGetterForField(AccessLevel level,
		JavacNode fieldNode, JavacNode source, boolean whineIfExists, boolean lazy, List<JCAnnotation> onMethod) {
	if (fieldNode.getKind() != Kind.FIELD) {
		source.addError("@Getter is only supported on a class or a field.");
		return;
	}
	
	JCVariableDecl fieldDecl = (JCVariableDecl)fieldNode.get();
	
	if (lazy) {
		if ((fieldDecl.mods.flags & Flags.PRIVATE) == 0 || (fieldDecl.mods.flags & Flags.FINAL) == 0) {
			source.addError("'lazy' requires the field to be private and final.");
			return;
		}
		if (fieldDecl.init == null) {
			source.addError("'lazy' requires field initialization.");
			return;
		}
	}
	
	String methodName = toGetterName(fieldNode);
	
	if (methodName == null) {
		source.addWarning("Not generating getter for this field: It does not fit your @Accessors prefix list.");
		return;
	}
	
	for (String altName : toAllGetterNames(fieldNode)) {
		switch (methodExists(altName, fieldNode, false, 0)) {
		case EXISTS_BY_LOMBOK:
			return;
		case EXISTS_BY_USER:
			if (whineIfExists) {
				String altNameExpl = "";
				if (!altName.equals(methodName)) altNameExpl = String.format(" (%s)", altName);
				source.addWarning(
					String.format("Not generating %s(): A method with that name already exists%s", methodName, altNameExpl));
			}
			return;
		default:
		case NOT_EXISTS:
			//continue scanning the other alt names.
		}
	}
	
	long access = toJavacModifier(level) | (fieldDecl.mods.flags & Flags.STATIC);
	
	injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker(), source.get(), lazy, onMethod));
}
 
Example 19
Source File: HandleGetter.java    From EasyMPermission with MIT License 4 votes vote down vote up
public JCMethodDecl createGetter(long access, JavacNode field, JavacTreeMaker treeMaker, JCTree source, boolean lazy, List<JCAnnotation> onMethod) {
	JCVariableDecl fieldNode = (JCVariableDecl) field.get();
	
	// Remember the type; lazy will change it
	JCExpression methodType = copyType(treeMaker, fieldNode);
	// Generate the methodName; lazy will change the field type
	Name methodName = field.toName(toGetterName(field));
	
	List<JCStatement> statements;
	JCTree toClearOfMarkers = null;
	if (lazy && !inNetbeansEditor(field)) {
		toClearOfMarkers = fieldNode.init;
		statements = createLazyGetterBody(treeMaker, field, source);
	} else {
		statements = createSimpleGetterBody(treeMaker, field);
	}
	
	JCBlock methodBody = treeMaker.Block(0, statements);
	
	List<JCTypeParameter> methodGenericParams = List.nil();
	List<JCVariableDecl> parameters = List.nil();
	List<JCExpression> throwsClauses = List.nil();
	JCExpression annotationMethodDefaultValue = null;
	
	List<JCAnnotation> nonNulls = findAnnotations(field, NON_NULL_PATTERN);
	List<JCAnnotation> nullables = findAnnotations(field, NULLABLE_PATTERN);
	
	List<JCAnnotation> delegates = findDelegatesAndRemoveFromField(field);
	
	List<JCAnnotation> annsOnMethod = copyAnnotations(onMethod).appendList(nonNulls).appendList(nullables);
	if (isFieldDeprecated(field)) {
		annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.<JCExpression>nil()));
	}
	
	JCMethodDecl decl = recursiveSetGeneratedBy(treeMaker.MethodDef(treeMaker.Modifiers(access, annsOnMethod), methodName, methodType,
			methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source, field.getContext());
	
	if (toClearOfMarkers != null) recursiveSetGeneratedBy(toClearOfMarkers, null, null);
	decl.mods.annotations = decl.mods.annotations.appendList(delegates);
	
	copyJavadoc(field, decl, CopyJavadoc.GETTER);
	return decl;
}
 
Example 20
Source File: HandleWither.java    From EasyMPermission with MIT License 4 votes vote down vote up
public JCMethodDecl createWither(long access, JavacNode field, JavacTreeMaker maker, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
	String witherName = toWitherName(field);
	if (witherName == null) return null;
	
	JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
	
	ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
	List<JCAnnotation> nonNulls = findAnnotations(field, NON_NULL_PATTERN);
	List<JCAnnotation> nullables = findAnnotations(field, NULLABLE_PATTERN);
	
	Name methodName = field.toName(witherName);
	List<JCAnnotation> annsOnParam = copyAnnotations(onParam).appendList(nonNulls).appendList(nullables);
	
	long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, field.getContext());
	JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, annsOnParam), fieldDecl.name, fieldDecl.vartype, null);
	
	JCExpression selfType = cloneSelfType(field);
	if (selfType == null) return null;
	
	ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
	for (JavacNode child : field.up().down()) {
		if (child.getKind() != Kind.FIELD) continue;
		JCVariableDecl childDecl = (JCVariableDecl) child.get();
		// Skip fields that start with $
		if (childDecl.name.toString().startsWith("$")) continue;
		long fieldFlags = childDecl.mods.flags;
		// Skip static fields.
		if ((fieldFlags & Flags.STATIC) != 0) continue;
		// Skip initialized final fields.
		if (((fieldFlags & Flags.FINAL) != 0) && childDecl.init != null) continue;
		if (child.get() == field.get()) {
			args.append(maker.Ident(fieldDecl.name));
		} else {
			args.append(createFieldAccessor(maker, child, FieldAccess.ALWAYS_FIELD));
		}
	}
	
	JCNewClass newClass = maker.NewClass(null, List.<JCExpression>nil(), selfType, args.toList(), null);
	JCExpression identityCheck = maker.Binary(CTC_EQUAL, createFieldAccessor(maker, field, FieldAccess.ALWAYS_FIELD), maker.Ident(fieldDecl.name));
	JCConditional conditional = maker.Conditional(identityCheck, maker.Ident(field.toName("this")), newClass);
	JCReturn returnStatement = maker.Return(conditional);
	
	if (nonNulls.isEmpty()) {
		statements.append(returnStatement);
	} else {
		JCStatement nullCheck = generateNullCheck(maker, field, source);
		if (nullCheck != null) statements.append(nullCheck);
		statements.append(returnStatement);
	}
	
	JCExpression returnType = cloneSelfType(field);
	
	JCBlock methodBody = maker.Block(0, statements.toList());
	List<JCTypeParameter> methodGenericParams = List.nil();
	List<JCVariableDecl> parameters = List.of(param);
	List<JCExpression> throwsClauses = List.nil();
	JCExpression annotationMethodDefaultValue = null;
	
	List<JCAnnotation> annsOnMethod = copyAnnotations(onMethod);
	
	if (isFieldDeprecated(field)) {
		annsOnMethod = annsOnMethod.prepend(maker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.<JCExpression>nil()));
	}
	JCMethodDecl decl = recursiveSetGeneratedBy(maker.MethodDef(maker.Modifiers(access, annsOnMethod), methodName, returnType,
			methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source.get(), field.getContext());
	copyJavadoc(field, decl, CopyJavadoc.WITHER);
	return decl;
}