use of org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference in project lombok by rzwitserloot.
the class HandleBuilder method handle.
@Override
public void handle(AnnotationValues<Builder> annotation, Annotation ast, EclipseNode annotationNode) {
long p = (long) ast.sourceStart << 32 | ast.sourceEnd;
Builder builderInstance = annotation.getInstance();
// These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them.
boolean fluent = toBoolean(annotation.getActualExpression("fluent"), true);
boolean chain = toBoolean(annotation.getActualExpression("chain"), true);
String builderMethodName = builderInstance.builderMethodName();
String buildMethodName = builderInstance.buildMethodName();
String builderClassName = builderInstance.builderClassName();
String toBuilderMethodName = "toBuilder";
boolean toBuilder = builderInstance.toBuilder();
List<char[]> typeArgsForToBuilder = null;
if (builderMethodName == null)
builderMethodName = "builder";
if (buildMethodName == null)
builderMethodName = "build";
if (builderClassName == null)
builderClassName = "";
if (!checkName("builderMethodName", builderMethodName, annotationNode))
return;
if (!checkName("buildMethodName", buildMethodName, annotationNode))
return;
if (!builderClassName.isEmpty()) {
if (!checkName("builderClassName", builderClassName, annotationNode))
return;
}
EclipseNode parent = annotationNode.up();
List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>();
TypeReference returnType;
TypeParameter[] typeParams;
TypeReference[] thrownExceptions;
char[] nameOfStaticBuilderMethod;
EclipseNode tdParent;
EclipseNode fillParametersFrom = parent.get() instanceof AbstractMethodDeclaration ? parent : null;
boolean addCleaning = false;
boolean isStatic = true;
if (parent.get() instanceof TypeDeclaration) {
tdParent = parent;
TypeDeclaration td = (TypeDeclaration) tdParent.get();
List<EclipseNode> allFields = new ArrayList<EclipseNode>();
@SuppressWarnings("deprecation") boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation(lombok.experimental.Value.class, parent));
for (EclipseNode fieldNode : HandleConstructor.findAllFields(tdParent)) {
FieldDeclaration fd = (FieldDeclaration) fieldNode.get();
// Value will only skip making a field final if it has an explicit @NonFinal annotation, so we check for that.
if (fd.initialization != null && valuePresent && !hasAnnotation(NonFinal.class, fieldNode))
continue;
BuilderFieldData bfd = new BuilderFieldData();
bfd.rawName = fieldNode.getName().toCharArray();
bfd.name = removePrefixFromField(fieldNode);
bfd.type = fd.type;
bfd.singularData = getSingularData(fieldNode, ast);
addObtainVia(bfd, fieldNode);
builderFields.add(bfd);
allFields.add(fieldNode);
}
new HandleConstructor().generateConstructor(tdParent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER, Collections.<Annotation>emptyList(), annotationNode);
returnType = namePlusTypeParamsToTypeReference(td.name, td.typeParameters, p);
typeParams = td.typeParameters;
thrownExceptions = null;
nameOfStaticBuilderMethod = null;
if (builderClassName.isEmpty())
builderClassName = new String(td.name) + "Builder";
} else if (parent.get() instanceof ConstructorDeclaration) {
ConstructorDeclaration cd = (ConstructorDeclaration) parent.get();
if (cd.typeParameters != null && cd.typeParameters.length > 0) {
annotationNode.addError("@Builder is not supported on constructors with constructor type parameters.");
return;
}
tdParent = parent.up();
TypeDeclaration td = (TypeDeclaration) tdParent.get();
returnType = namePlusTypeParamsToTypeReference(td.name, td.typeParameters, p);
typeParams = td.typeParameters;
thrownExceptions = cd.thrownExceptions;
nameOfStaticBuilderMethod = null;
if (builderClassName.isEmpty())
builderClassName = new String(cd.selector) + "Builder";
} else if (parent.get() instanceof MethodDeclaration) {
MethodDeclaration md = (MethodDeclaration) parent.get();
tdParent = parent.up();
isStatic = md.isStatic();
if (toBuilder) {
final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type.";
char[] token;
char[][] pkg = null;
if (md.returnType.dimensions() > 0) {
annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
return;
}
if (md.returnType instanceof SingleTypeReference) {
token = ((SingleTypeReference) md.returnType).token;
} else if (md.returnType instanceof QualifiedTypeReference) {
pkg = ((QualifiedTypeReference) md.returnType).tokens;
token = pkg[pkg.length];
char[][] pkg_ = new char[pkg.length - 1][];
System.arraycopy(pkg, 0, pkg_, 0, pkg_.length);
pkg = pkg_;
} else {
annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
return;
}
if (pkg != null && !equals(parent.getPackageDeclaration(), pkg)) {
annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
return;
}
if (tdParent == null || !equals(tdParent.getName(), token)) {
annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
return;
}
TypeParameter[] tpOnType = ((TypeDeclaration) tdParent.get()).typeParameters;
TypeParameter[] tpOnMethod = md.typeParameters;
TypeReference[][] tpOnRet_ = null;
if (md.returnType instanceof ParameterizedSingleTypeReference) {
tpOnRet_ = new TypeReference[1][];
tpOnRet_[0] = ((ParameterizedSingleTypeReference) md.returnType).typeArguments;
} else if (md.returnType instanceof ParameterizedQualifiedTypeReference) {
tpOnRet_ = ((ParameterizedQualifiedTypeReference) md.returnType).typeArguments;
}
if (tpOnRet_ != null)
for (int i = 0; i < tpOnRet_.length - 1; i++) {
if (tpOnRet_[i] != null && tpOnRet_[i].length > 0) {
annotationNode.addError("@Builder(toBuilder=true) is not supported if returning a type with generics applied to an intermediate.");
return;
}
}
TypeReference[] tpOnRet = tpOnRet_ == null ? null : tpOnRet_[tpOnRet_.length - 1];
typeArgsForToBuilder = new ArrayList<char[]>();
if (tpOnMethod != null)
for (TypeParameter onMethod : tpOnMethod) {
int pos = -1;
if (tpOnRet != null)
for (int i = 0; i < tpOnRet.length; i++) {
if (tpOnRet[i].getClass() != SingleTypeReference.class)
continue;
if (!Arrays.equals(((SingleTypeReference) tpOnRet[i]).token, onMethod.name))
continue;
pos = i;
}
if (pos == -1 || tpOnType == null || tpOnType.length <= pos) {
annotationNode.addError("@Builder(toBuilder=true) requires that each type parameter on the static method is part of the typeargs of the return value. Type parameter " + new String(onMethod.name) + " is not part of the return type.");
return;
}
typeArgsForToBuilder.add(tpOnType[pos].name);
}
}
returnType = copyType(md.returnType, ast);
typeParams = md.typeParameters;
thrownExceptions = md.thrownExceptions;
nameOfStaticBuilderMethod = md.selector;
if (builderClassName.isEmpty()) {
char[] token;
if (md.returnType instanceof QualifiedTypeReference) {
char[][] tokens = ((QualifiedTypeReference) md.returnType).tokens;
token = tokens[tokens.length - 1];
} else if (md.returnType instanceof SingleTypeReference) {
token = ((SingleTypeReference) md.returnType).token;
if (!(md.returnType instanceof ParameterizedSingleTypeReference) && typeParams != null) {
for (TypeParameter tp : typeParams) {
if (Arrays.equals(tp.name, token)) {
annotationNode.addError("@Builder requires specifying 'builderClassName' if used on methods with a type parameter as return type.");
return;
}
}
}
} else {
annotationNode.addError("Unexpected kind of return type on annotated method. Specify 'builderClassName' to solve this problem.");
return;
}
if (Character.isLowerCase(token[0])) {
char[] newToken = new char[token.length];
System.arraycopy(token, 1, newToken, 1, token.length - 1);
newToken[0] = Character.toTitleCase(token[0]);
token = newToken;
}
builderClassName = new String(token) + "Builder";
}
} else {
annotationNode.addError("@Builder is only supported on types, constructors, and methods.");
return;
}
if (fillParametersFrom != null) {
for (EclipseNode param : fillParametersFrom.down()) {
if (param.getKind() != Kind.ARGUMENT)
continue;
BuilderFieldData bfd = new BuilderFieldData();
Argument arg = (Argument) param.get();
bfd.rawName = arg.name;
bfd.name = arg.name;
bfd.type = arg.type;
bfd.singularData = getSingularData(param, ast);
addObtainVia(bfd, param);
builderFields.add(bfd);
}
}
EclipseNode builderType = findInnerClass(tdParent, builderClassName);
if (builderType == null) {
builderType = makeBuilderClass(isStatic, tdParent, builderClassName, typeParams, ast);
} else {
TypeDeclaration builderTypeDeclaration = (TypeDeclaration) builderType.get();
if (isStatic && (builderTypeDeclaration.modifiers & ClassFileConstants.AccStatic) == 0) {
annotationNode.addError("Existing Builder must be a static inner class.");
return;
} else if (!isStatic && (builderTypeDeclaration.modifiers & ClassFileConstants.AccStatic) != 0) {
annotationNode.addError("Existing Builder must be a non-static inner class.");
return;
}
sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderType, annotationNode);
/* generate errors for @Singular BFDs that have one already defined node. */
{
for (BuilderFieldData bfd : builderFields) {
SingularData sd = bfd.singularData;
if (sd == null)
continue;
EclipseSingularizer singularizer = sd.getSingularizer();
if (singularizer == null)
continue;
if (singularizer.checkForAlreadyExistingNodesAndGenerateError(builderType, sd)) {
bfd.singularData = null;
}
}
}
}
for (BuilderFieldData bfd : builderFields) {
if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
if (bfd.singularData.getSingularizer().requiresCleaning()) {
addCleaning = true;
break;
}
}
if (bfd.obtainVia != null) {
if (bfd.obtainVia.field().isEmpty() == bfd.obtainVia.method().isEmpty()) {
bfd.obtainViaNode.addError("The syntax is either @ObtainVia(field = \"fieldName\") or @ObtainVia(method = \"methodName\").");
return;
}
if (bfd.obtainVia.method().isEmpty() && bfd.obtainVia.isStatic()) {
bfd.obtainViaNode.addError("@ObtainVia(isStatic = true) is not valid unless 'method' has been set.");
return;
}
}
}
generateBuilderFields(builderType, builderFields, ast);
if (addCleaning) {
FieldDeclaration cleanDecl = new FieldDeclaration(CLEAN_FIELD_NAME, 0, -1);
cleanDecl.declarationSourceEnd = -1;
cleanDecl.modifiers = ClassFileConstants.AccPrivate;
cleanDecl.type = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
injectFieldAndMarkGenerated(builderType, cleanDecl);
}
if (constructorExists(builderType) == MemberExistsResult.NOT_EXISTS) {
ConstructorDeclaration cd = HandleConstructor.createConstructor(AccessLevel.PACKAGE, builderType, Collections.<EclipseNode>emptyList(), false, annotationNode, Collections.<Annotation>emptyList());
if (cd != null)
injectMethod(builderType, cd);
}
for (BuilderFieldData bfd : builderFields) {
makeSetterMethodsForBuilder(builderType, bfd, annotationNode, fluent, chain);
}
if (methodExists(buildMethodName, builderType, -1) == MemberExistsResult.NOT_EXISTS) {
MethodDeclaration md = generateBuildMethod(isStatic, buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning, ast);
if (md != null)
injectMethod(builderType, md);
}
if (methodExists("toString", builderType, 0) == MemberExistsResult.NOT_EXISTS) {
List<EclipseNode> fieldNodes = new ArrayList<EclipseNode>();
for (BuilderFieldData bfd : builderFields) {
fieldNodes.addAll(bfd.createdFields);
}
MethodDeclaration md = HandleToString.createToString(builderType, fieldNodes, true, false, ast, FieldAccess.ALWAYS_FIELD);
if (md != null)
injectMethod(builderType, md);
}
if (addCleaning) {
MethodDeclaration cleanMethod = generateCleanMethod(builderFields, builderType, ast);
if (cleanMethod != null)
injectMethod(builderType, cleanMethod);
}
if (methodExists(builderMethodName, tdParent, -1) == MemberExistsResult.NOT_EXISTS) {
MethodDeclaration md = generateBuilderMethod(isStatic, builderMethodName, builderClassName, tdParent, typeParams, ast);
if (md != null)
injectMethod(tdParent, md);
}
if (toBuilder)
switch(methodExists(toBuilderMethodName, tdParent, 0)) {
case EXISTS_BY_USER:
annotationNode.addWarning("Not generating toBuilder() as it already exists.");
break;
case NOT_EXISTS:
TypeParameter[] tps = typeParams;
if (typeArgsForToBuilder != null) {
tps = new TypeParameter[typeArgsForToBuilder.size()];
for (int i = 0; i < tps.length; i++) {
tps[i] = new TypeParameter();
tps[i].name = typeArgsForToBuilder.get(i);
}
}
MethodDeclaration md = generateToBuilderMethod(toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast);
if (md != null)
injectMethod(tdParent, md);
}
}
use of org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference in project lombok by rzwitserloot.
the class HandleConstructor method createConstructorProperties.
public static Annotation[] createConstructorProperties(ASTNode source, Collection<EclipseNode> fields) {
if (fields.isEmpty())
return null;
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long) pS << 32 | pE;
long[] poss = new long[3];
Arrays.fill(poss, p);
QualifiedTypeReference constructorPropertiesType = new QualifiedTypeReference(JAVA_BEANS_CONSTRUCTORPROPERTIES, poss);
setGeneratedBy(constructorPropertiesType, source);
SingleMemberAnnotation ann = new SingleMemberAnnotation(constructorPropertiesType, pS);
ann.declarationSourceEnd = pE;
ArrayInitializer fieldNames = new ArrayInitializer();
fieldNames.sourceStart = pS;
fieldNames.sourceEnd = pE;
fieldNames.expressions = new Expression[fields.size()];
int ctr = 0;
for (EclipseNode field : fields) {
char[] fieldName = removePrefixFromField(field);
fieldNames.expressions[ctr] = new StringLiteral(fieldName, pS, pE, 0);
setGeneratedBy(fieldNames.expressions[ctr], source);
ctr++;
}
ann.memberValue = fieldNames;
setGeneratedBy(ann, source);
setGeneratedBy(ann.memberValue, source);
return new Annotation[] { ann };
}
use of org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference in project lombok by rzwitserloot.
the class HandleLog method createTypeReference.
public static TypeReference createTypeReference(String typeName, Annotation source) {
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long) pS << 32 | pE;
TypeReference typeReference;
if (typeName.contains(".")) {
char[][] typeNameTokens = fromQualifiedName(typeName);
long[] pos = new long[typeNameTokens.length];
Arrays.fill(pos, p);
typeReference = new QualifiedTypeReference(typeNameTokens, pos);
} else {
typeReference = null;
}
setGeneratedBy(typeReference, source);
return typeReference;
}
use of org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference in project lombok by rzwitserloot.
the class HandleUtilityClass method createPrivateDefaultConstructor.
private void createPrivateDefaultConstructor(EclipseNode typeNode, EclipseNode sourceNode) {
ASTNode source = sourceNode.get();
TypeDeclaration typeDeclaration = ((TypeDeclaration) typeNode.get());
long p = (long) source.sourceStart << 32 | source.sourceEnd;
ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) typeNode.top().get()).compilationResult);
constructor.modifiers = ClassFileConstants.AccPrivate;
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;
AllocationExpression exception = new AllocationExpression();
setGeneratedBy(exception, source);
long[] ps = new long[JAVA_LANG_UNSUPPORTED_OPERATION_EXCEPTION.length];
Arrays.fill(ps, p);
exception.type = new QualifiedTypeReference(JAVA_LANG_UNSUPPORTED_OPERATION_EXCEPTION, ps);
setGeneratedBy(exception.type, source);
exception.arguments = new Expression[] { new StringLiteral(UNSUPPORTED_MESSAGE, source.sourceStart, source.sourceEnd, 0) };
setGeneratedBy(exception.arguments[0], source);
ThrowStatement throwStatement = new ThrowStatement(exception, source.sourceStart, source.sourceEnd);
setGeneratedBy(throwStatement, source);
constructor.statements = new Statement[] { throwStatement };
injectMethod(typeNode, constructor);
}
use of org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference in project lombok by rzwitserloot.
the class EclipseGuavaSingularizer method appendBuildCode.
@Override
public void appendBuildCode(SingularData data, EclipseNode builderType, List<Statement> statements, char[] targetVariableName) {
TypeReference varType = new QualifiedTypeReference(fromQualifiedName(data.getTargetFqn()), NULL_POSS);
String simpleTypeName = getSimpleTargetTypeName(data);
int agrumentsCount = getTypeArgumentsCount();
varType = addTypeArgs(agrumentsCount, false, builderType, varType, data.getTypeArgs());
MessageSend emptyInvoke;
{
//ImmutableX.of()
emptyInvoke = new MessageSend();
emptyInvoke.selector = new char[] { 'o', 'f' };
emptyInvoke.receiver = new QualifiedNameReference(makeGuavaTypeName(simpleTypeName, false), NULL_POSS, 0, 0);
emptyInvoke.typeArguments = createTypeArgs(agrumentsCount, false, builderType, data.getTypeArgs());
}
MessageSend invokeBuild;
{
//this.pluralName.build();
invokeBuild = new MessageSend();
invokeBuild.selector = new char[] { 'b', 'u', 'i', 'l', 'd' };
FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
thisDotField.receiver = new ThisReference(0, 0);
invokeBuild.receiver = thisDotField;
}
Expression isNull;
{
//this.pluralName == null
FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
thisDotField.receiver = new ThisReference(0, 0);
isNull = new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.EQUAL_EQUAL);
}
Expression init = new ConditionalExpression(isNull, emptyInvoke, invokeBuild);
LocalDeclaration varDefStat = new LocalDeclaration(data.getPluralName(), 0, 0);
varDefStat.type = varType;
varDefStat.initialization = init;
statements.add(varDefStat);
}
Aggregations