use of org.eclipse.jdt.internal.compiler.ast.ThisReference in project lombok by rzwitserloot.
the class HandleBuilder method generateCleanMethod.
private MethodDeclaration generateCleanMethod(BuilderJob job) {
List<Statement> statements = new ArrayList<Statement>();
for (BuilderFieldData bfd : job.builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, job.builderType, statements);
}
}
FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0);
thisUnclean.receiver = new ThisReference(0, 0);
statements.add(new Assignment(thisUnclean, new FalseLiteral(0, 0), 0));
MethodDeclaration decl = job.createNewMethodDeclaration();
decl.selector = CLEAN_METHOD_NAME;
decl.modifiers = ClassFileConstants.AccPrivate;
decl.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
decl.returnType = TypeReference.baseTypeReference(TypeIds.T_void, 0);
decl.statements = statements.toArray(new Statement[0]);
decl.traverse(new SetGeneratedByVisitor(job.source), (ClassScope) null);
return decl;
}
use of org.eclipse.jdt.internal.compiler.ast.ThisReference in project lombok by rzwitserloot.
the class HandleBuilder method generateToBuilderMethod.
private MethodDeclaration generateToBuilderMethod(BuilderJob job, TypeParameter[] typeParameters, String prefix) {
int pS = job.source.sourceStart, pE = job.source.sourceEnd;
long p = job.getPos();
MethodDeclaration out = job.createNewMethodDeclaration();
out.selector = TO_BUILDER_METHOD_NAME;
out.modifiers = toEclipseModifier(job.accessOuters);
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.returnType = job.createBuilderTypeReference();
if (job.checkerFramework.generateUnique()) {
int len = out.returnType.getTypeName().length;
out.returnType.annotations = new Annotation[len][];
out.returnType.annotations[len - 1] = new Annotation[] { generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__UNIQUE) };
}
AllocationExpression invoke = new AllocationExpression();
invoke.type = job.createBuilderTypeReference();
Expression receiver = invoke;
List<Statement> preStatements = null;
List<Statement> postStatements = null;
for (BuilderFieldData bfd : job.builderFields) {
String setterName = new String(bfd.name);
String setterPrefix = !prefix.isEmpty() ? prefix : job.oldFluent ? "" : "set";
if (!setterPrefix.isEmpty())
setterName = HandlerUtil.buildAccessorName(job.sourceNode, setterPrefix, setterName);
MessageSend ms = new MessageSend();
Expression[] tgt = new Expression[bfd.singularData == null ? 1 : 2];
if (bfd.obtainVia == null || !bfd.obtainVia.field().isEmpty()) {
char[] fieldName = bfd.obtainVia == null ? bfd.rawName : bfd.obtainVia.field().toCharArray();
for (int i = 0; i < tgt.length; i++) {
FieldReference fr = new FieldReference(fieldName, 0);
fr.receiver = new ThisReference(0, 0);
tgt[i] = fr;
}
} else {
String obtainName = bfd.obtainVia.method();
boolean obtainIsStatic = bfd.obtainVia.isStatic();
MessageSend obtainExpr = new MessageSend();
if (obtainIsStatic) {
if (typeParameters != null && typeParameters.length > 0) {
obtainExpr.typeArguments = new TypeReference[typeParameters.length];
for (int j = 0; j < typeParameters.length; j++) {
obtainExpr.typeArguments[j] = new SingleTypeReference(typeParameters[j].name, 0);
}
}
obtainExpr.receiver = generateNameReference(job.parentType, 0);
} else {
obtainExpr.receiver = new ThisReference(0, 0);
}
obtainExpr.selector = obtainName.toCharArray();
if (obtainIsStatic)
obtainExpr.arguments = new Expression[] { new ThisReference(0, 0) };
for (int i = 0; i < tgt.length; i++) tgt[i] = new SingleNameReference(bfd.name, 0L);
// javac appears to cache the type of JCMethodInvocation expressions based on position, meaning, if you have 2 ObtainVia-based method invokes on different types, you get bizarre type mismatch errors.
// going via a local variable declaration solves the problem. We copy this behaviour
// for ecj so we match what javac's handler does.
LocalDeclaration ld = new LocalDeclaration(bfd.name, 0, 0);
ld.modifiers = ClassFileConstants.AccFinal;
ld.type = EclipseHandlerUtil.copyType(bfd.type, job.source);
ld.initialization = obtainExpr;
if (preStatements == null)
preStatements = new ArrayList<Statement>();
preStatements.add(ld);
}
ms.selector = setterName.toCharArray();
if (bfd.singularData == null) {
ms.arguments = tgt;
ms.receiver = receiver;
receiver = ms;
} else {
ms.arguments = new Expression[] { tgt[1] };
ms.receiver = new SingleNameReference(BUILDER_TEMP_VAR, p);
EqualExpression isNotNull = new EqualExpression(tgt[0], new NullLiteral(pS, pE), OperatorIds.NOT_EQUAL);
if (postStatements == null)
postStatements = new ArrayList<Statement>();
postStatements.add(new IfStatement(isNotNull, ms, pS, pE));
}
}
int preSs = preStatements == null ? 0 : preStatements.size();
int postSs = postStatements == null ? 0 : postStatements.size();
if (postSs > 0) {
out.statements = new Statement[preSs + postSs + 2];
for (int i = 0; i < preSs; i++) out.statements[i] = preStatements.get(i);
for (int i = 0; i < postSs; i++) out.statements[preSs + 1 + i] = postStatements.get(i);
LocalDeclaration b = new LocalDeclaration(BUILDER_TEMP_VAR, pS, pE);
out.statements[preSs] = b;
b.modifiers |= ClassFileConstants.AccFinal;
b.type = job.createBuilderTypeReference();
b.type.sourceStart = pS;
b.type.sourceEnd = pE;
b.initialization = receiver;
out.statements[preSs + postSs + 1] = new ReturnStatement(new SingleNameReference(BUILDER_TEMP_VAR, p), pS, pE);
} else {
out.statements = new Statement[preSs + 1];
for (int i = 0; i < preSs; i++) out.statements[i] = preStatements.get(i);
out.statements[preSs] = new ReturnStatement(receiver, pS, pE);
}
createRelevantNonNullAnnotation(job.parentType, out);
out.traverse(new SetGeneratedByVisitor(job.source), ((TypeDeclaration) job.parentType.get()).scope);
return out;
}
use of org.eclipse.jdt.internal.compiler.ast.ThisReference in project lombok by rzwitserloot.
the class HandleConstructor method createConstructor.
@SuppressWarnings("deprecation")
public static ConstructorDeclaration createConstructor(AccessLevel level, EclipseNode type, Collection<EclipseNode> fieldsToParam, boolean forceDefaults, EclipseNode sourceNode, List<Annotation> onConstructor) {
ASTNode source = sourceNode.get();
TypeDeclaration typeDeclaration = ((TypeDeclaration) type.get());
long p = (long) source.sourceStart << 32 | source.sourceEnd;
boolean isEnum = (((TypeDeclaration) type.get()).modifiers & ClassFileConstants.AccEnum) != 0;
if (isEnum)
level = AccessLevel.PRIVATE;
List<EclipseNode> fieldsToDefault = fieldsNeedingBuilderDefaults(type, fieldsToParam);
List<EclipseNode> fieldsToExplicit = forceDefaults ? fieldsNeedingExplicitDefaults(type, fieldsToParam) : Collections.<EclipseNode>emptyList();
boolean addConstructorProperties;
if (fieldsToParam.isEmpty()) {
addConstructorProperties = false;
} else {
Boolean v = type.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_ADD_CONSTRUCTOR_PROPERTIES);
addConstructorProperties = v != null ? v.booleanValue() : Boolean.FALSE.equals(type.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES));
}
ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
constructor.modifiers = toEclipseModifier(level);
constructor.selector = typeDeclaration.name;
constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
constructor.constructorCall.sourceStart = source.sourceStart;
constructor.constructorCall.sourceEnd = source.sourceEnd;
constructor.thrownExceptions = null;
constructor.typeParameters = null;
constructor.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart;
constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd;
constructor.arguments = null;
List<Argument> params = new ArrayList<Argument>();
List<Statement> assigns = new ArrayList<Statement>();
List<Statement> nullChecks = new ArrayList<Statement>();
for (EclipseNode fieldNode : fieldsToParam) {
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
char[] rawName = field.name;
char[] fieldName = removePrefixFromField(fieldNode);
FieldReference thisX = new FieldReference(rawName, p);
int s = (int) (p >> 32);
int e = (int) p;
thisX.receiver = new ThisReference(s, e);
Expression assignmentExpr = new SingleNameReference(fieldName, p);
Assignment assignment = new Assignment(thisX, assignmentExpr, (int) p);
assignment.sourceStart = (int) (p >> 32);
assignment.sourceEnd = assignment.statementEnd = (int) (p >> 32);
assigns.add(assignment);
long fieldPos = (((long) field.sourceStart) << 32) | field.sourceEnd;
Argument parameter = new Argument(fieldName, fieldPos, copyType(field.type, source), Modifier.FINAL);
Annotation[] copyableAnnotations = findCopyableAnnotations(fieldNode);
if (hasNonNullAnnotations(fieldNode)) {
Statement nullCheck = generateNullCheck(parameter, sourceNode, null);
if (nullCheck != null)
nullChecks.add(nullCheck);
}
parameter.annotations = copyAnnotations(source, copyableAnnotations);
params.add(parameter);
}
for (EclipseNode fieldNode : fieldsToExplicit) {
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
char[] rawName = field.name;
FieldReference thisX = new FieldReference(rawName, p);
int s = (int) (p >> 32);
int e = (int) p;
thisX.receiver = new ThisReference(s, e);
Expression assignmentExpr = getDefaultExpr(field.type, s, e);
Assignment assignment = new Assignment(thisX, assignmentExpr, (int) p);
assignment.sourceStart = (int) (p >> 32);
assignment.sourceEnd = assignment.statementEnd = (int) (p >> 32);
assigns.add(assignment);
}
for (EclipseNode fieldNode : fieldsToDefault) {
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
char[] rawName = field.name;
FieldReference thisX = new FieldReference(rawName, p);
int s = (int) (p >> 32);
int e = (int) p;
thisX.receiver = new ThisReference(s, e);
MessageSend inv = new MessageSend();
inv.sourceStart = source.sourceStart;
inv.sourceEnd = source.sourceEnd;
inv.receiver = new SingleNameReference(((TypeDeclaration) type.get()).name, 0L);
inv.selector = prefixWith(DEFAULT_PREFIX, removePrefixFromField(fieldNode));
Assignment assignment = new Assignment(thisX, inv, (int) p);
assignment.sourceStart = (int) (p >> 32);
assignment.sourceEnd = assignment.statementEnd = (int) (p >> 32);
assigns.add(assignment);
}
nullChecks.addAll(assigns);
constructor.statements = nullChecks.isEmpty() ? null : nullChecks.toArray(new Statement[0]);
constructor.arguments = params.isEmpty() ? null : params.toArray(new Argument[0]);
/* Generate annotations that must be put on the generated method, and attach them. */
{
Annotation[] constructorProperties = null;
if (addConstructorProperties && !isLocalType(type))
constructorProperties = createConstructorProperties(source, fieldsToParam);
constructor.annotations = copyAnnotations(source, onConstructor.toArray(new Annotation[0]), constructorProperties);
}
constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope);
return constructor;
}
use of org.eclipse.jdt.internal.compiler.ast.ThisReference in project lombok by rzwitserloot.
the class HandleSuperBuilder method generateFillValuesMethod.
/**
* Generates a <code>$fillValuesFrom()</code> method in the abstract builder class that looks
* like this:
* <pre>
* protected B $fillValuesFrom(final C instance) {
* super.$fillValuesFrom(instance);
* Foobar.FoobarBuilder.$fillValuesFromInstanceIntoBuilder(instance, this);
* return self();
* }
* </pre>
*/
private MethodDeclaration generateFillValuesMethod(SuperBuilderJob job, boolean inherited, String builderGenericName, String classGenericName) {
MethodDeclaration out = job.createNewMethodDeclaration();
out.selector = FILL_VALUES_METHOD_NAME;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.modifiers = ClassFileConstants.AccProtected;
if (inherited)
out.annotations = new Annotation[] { makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, job.parentType.get()) };
out.returnType = new SingleTypeReference(builderGenericName.toCharArray(), 0);
TypeReference builderType = new SingleTypeReference(classGenericName.toCharArray(), 0);
out.arguments = new Argument[] { new Argument(INSTANCE_VARIABLE_NAME, 0, builderType, Modifier.FINAL) };
List<Statement> body = new ArrayList<Statement>();
if (inherited) {
// Call super.
MessageSend callToSuper = new MessageSend();
callToSuper.receiver = new SuperReference(0, 0);
callToSuper.selector = FILL_VALUES_METHOD_NAME;
callToSuper.arguments = new Expression[] { new SingleNameReference(INSTANCE_VARIABLE_NAME, 0) };
body.add(callToSuper);
}
// Call the builder implemention's helper method that actually fills the values from the instance.
MessageSend callStaticFillValuesMethod = new MessageSend();
callStaticFillValuesMethod.receiver = generateNameReference(job.parentType, job.builderAbstractClassNameArr, 0);
callStaticFillValuesMethod.selector = FILL_VALUES_STATIC_METHOD_NAME;
callStaticFillValuesMethod.arguments = new Expression[] { new SingleNameReference(INSTANCE_VARIABLE_NAME, 0), new ThisReference(0, 0) };
body.add(callStaticFillValuesMethod);
// Return self().
MessageSend returnCall = new MessageSend();
returnCall.receiver = ThisReference.implicitThis();
returnCall.selector = SELF_METHOD_NAME;
body.add(new ReturnStatement(returnCall, 0, 0));
out.statements = body.isEmpty() ? null : body.toArray(new Statement[0]);
return out;
}
use of org.eclipse.jdt.internal.compiler.ast.ThisReference in project lombok by rzwitserloot.
the class HandleSuperBuilder method generateBuilderBasedConstructor.
/**
* Generates a constructor that has a builder as the only parameter.
* The values from the builder are used to initialize the fields of new instances.
*
* @param callBuilderBasedSuperConstructor
* If {@code true}, the constructor will explicitly call a super
* constructor with the builder as argument. Requires
* {@code builderClassAsParameter != null}.
*/
private void generateBuilderBasedConstructor(BuilderJob job, boolean callBuilderBasedSuperConstructor) {
TypeDeclaration typeDeclaration = ((TypeDeclaration) job.parentType.get());
long p = job.getPos();
ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) job.parentType.top().get()).compilationResult);
constructor.modifiers = toEclipseModifier(AccessLevel.PROTECTED);
constructor.selector = typeDeclaration.name;
if (callBuilderBasedSuperConstructor) {
constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.Super);
constructor.constructorCall.arguments = new Expression[] { new SingleNameReference(BUILDER_VARIABLE_NAME, p) };
} else {
constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
}
constructor.constructorCall.sourceStart = job.source.sourceStart;
constructor.constructorCall.sourceEnd = job.source.sourceEnd;
constructor.thrownExceptions = null;
constructor.typeParameters = null;
constructor.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = job.source.sourceStart;
constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = job.source.sourceEnd;
TypeReference[] wildcards = new TypeReference[] { new Wildcard(Wildcard.UNBOUND), new Wildcard(Wildcard.UNBOUND) };
TypeReference builderType = generateParameterizedTypeReference(job.parentType, job.builderClassNameArr, false, mergeToTypeReferences(job.typeParams, wildcards), p);
constructor.arguments = new Argument[] { new Argument(BUILDER_VARIABLE_NAME, p, builderType, Modifier.FINAL) };
List<Statement> statements = new ArrayList<Statement>();
for (BuilderFieldData fieldNode : job.builderFields) {
FieldReference fieldInThis = new FieldReference(fieldNode.rawName, p);
int s = (int) (p >> 32);
int e = (int) p;
fieldInThis.receiver = new ThisReference(s, e);
Expression assignmentExpr;
if (fieldNode.singularData != null && fieldNode.singularData.getSingularizer() != null) {
fieldNode.singularData.getSingularizer().appendBuildCode(fieldNode.singularData, job.parentType, statements, fieldNode.builderFieldName, BUILDER_VARIABLE_NAME_STRING);
assignmentExpr = new SingleNameReference(fieldNode.builderFieldName, p);
} else {
char[][] variableInBuilder = new char[][] { BUILDER_VARIABLE_NAME, fieldNode.builderFieldName };
long[] positions = new long[] { p, p };
assignmentExpr = new QualifiedNameReference(variableInBuilder, positions, s, e);
}
Statement assignment = new Assignment(fieldInThis, assignmentExpr, (int) p);
// In case of @Builder.Default, set the value to the default if it was NOT set in the builder.
if (fieldNode.nameOfSetFlag != null) {
char[][] setVariableInBuilder = new char[][] { BUILDER_VARIABLE_NAME, fieldNode.nameOfSetFlag };
long[] positions = new long[] { p, p };
QualifiedNameReference setVariableInBuilderRef = new QualifiedNameReference(setVariableInBuilder, positions, s, e);
MessageSend defaultMethodCall = new MessageSend();
defaultMethodCall.sourceStart = job.source.sourceStart;
defaultMethodCall.sourceEnd = job.source.sourceEnd;
defaultMethodCall.receiver = generateNameReference(job.parentType, 0L);
defaultMethodCall.selector = fieldNode.nameOfDefaultProvider;
defaultMethodCall.typeArguments = typeParameterNames(((TypeDeclaration) job.parentType.get()).typeParameters);
Statement defaultAssignment = new Assignment(fieldInThis, defaultMethodCall, (int) p);
IfStatement ifBlockForDefault = new IfStatement(setVariableInBuilderRef, assignment, defaultAssignment, s, e);
statements.add(ifBlockForDefault);
} else {
statements.add(assignment);
}
if (hasNonNullAnnotations(fieldNode.originalFieldNode)) {
Statement nullCheck = generateNullCheck((FieldDeclaration) fieldNode.originalFieldNode.get(), job.sourceNode, null);
if (nullCheck != null)
statements.add(nullCheck);
}
}
constructor.statements = statements.isEmpty() ? null : statements.toArray(new Statement[0]);
if (job.checkerFramework.generateSideEffectFree()) {
constructor.annotations = new Annotation[] { generateNamedAnnotation(job.source, CheckerFrameworkVersion.NAME__SIDE_EFFECT_FREE) };
}
constructor.traverse(new SetGeneratedByVisitor(job.source), typeDeclaration.scope);
injectMethod(job.parentType, constructor);
}
Aggregations