use of org.eclipse.jdt.internal.compiler.ast.TypeDeclaration in project lombok by rzwitserloot.
the class HandleUtilityClass method checkLegality.
private static boolean checkLegality(EclipseNode typeNode, EclipseNode errorNode) {
TypeDeclaration typeDecl = null;
if (typeNode.get() instanceof TypeDeclaration)
typeDecl = (TypeDeclaration) typeNode.get();
int modifiers = typeDecl == null ? 0 : typeDecl.modifiers;
boolean notAClass = (modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0;
if (typeDecl == null || notAClass) {
errorNode.addError("@UtilityClass is only supported on a class (can't be an interface, enum, or annotation).");
return false;
}
// It might be an inner class. This is okay, but only if it is / can be a static inner class. Thus, all of its parents have to be static inner classes until the top-level.
EclipseNode typeWalk = typeNode;
while (true) {
typeWalk = typeWalk.up();
switch(typeWalk.getKind()) {
case TYPE:
if ((((TypeDeclaration) typeWalk.get()).modifiers & (ClassFileConstants.AccStatic | ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0)
continue;
if (typeWalk.up().getKind() == Kind.COMPILATION_UNIT)
return true;
errorNode.addError("@UtilityClass automatically makes the class static, however, this class cannot be made static.");
return false;
case COMPILATION_UNIT:
return true;
default:
errorNode.addError("@UtilityClass cannot be placed on a method local or anonymous inner class, or any class nested in such a class.");
return false;
}
}
}
use of org.eclipse.jdt.internal.compiler.ast.TypeDeclaration in project lombok by rzwitserloot.
the class HandleValue method handle.
public void handle(AnnotationValues<Value> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.VALUE_FLAG_USAGE, "@Value");
Value ann = annotation.getInstance();
EclipseNode typeNode = annotationNode.up();
TypeDeclaration typeDecl = null;
if (typeNode.get() instanceof TypeDeclaration)
typeDecl = (TypeDeclaration) typeNode.get();
int modifiers = typeDecl == null ? 0 : typeDecl.modifiers;
boolean notAClass = (modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0;
if (typeDecl == null || notAClass) {
annotationNode.addError("@Value is only supported on a class.");
return;
}
// Make class final.
if (!hasAnnotation(NonFinal.class, typeNode)) {
if ((typeDecl.modifiers & ClassFileConstants.AccFinal) == 0) {
typeDecl.modifiers |= ClassFileConstants.AccFinal;
typeNode.rebuild();
}
}
new HandleFieldDefaults().generateFieldDefaultsForType(typeNode, annotationNode, AccessLevel.PRIVATE, true, true);
//Careful: Generate the public static constructor (if there is one) LAST, so that any attempt to
//'find callers' on the annotation node will find callers of the constructor, which is by far the
//most useful of the many methods built by @Value. This trick won't work for the non-static constructor,
//for whatever reason, though you can find callers of that one by focusing on the class name itself
//and hitting 'find callers'.
new HandleGetter().generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode);
new HandleToString().generateToStringForType(typeNode, annotationNode);
new HandleConstructor().generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, ann.staticConstructor(), SkipIfConstructorExists.YES, Collections.<Annotation>emptyList(), annotationNode);
}
use of org.eclipse.jdt.internal.compiler.ast.TypeDeclaration in project lombok by rzwitserloot.
the class HandleWither method generateWitherForType.
public boolean generateWitherForType(EclipseNode typeNode, EclipseNode pos, AccessLevel level, boolean checkForTypeLevelWither) {
if (checkForTypeLevelWither) {
if (hasAnnotation(Wither.class, typeNode)) {
//The annotation will make it happen, so we can skip it.
return true;
}
}
TypeDeclaration typeDecl = null;
if (typeNode.get() instanceof TypeDeclaration)
typeDecl = (TypeDeclaration) typeNode.get();
int modifiers = typeDecl == null ? 0 : typeDecl.modifiers;
boolean notAClass = (modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0;
if (typeDecl == null || notAClass) {
pos.addError("@Wither is only supported on a class or a field.");
return false;
}
for (EclipseNode field : typeNode.down()) {
if (field.getKind() != Kind.FIELD)
continue;
FieldDeclaration fieldDecl = (FieldDeclaration) field.get();
if (!filterField(fieldDecl))
continue;
//Skip final fields.
if ((fieldDecl.modifiers & ClassFileConstants.AccFinal) != 0 && fieldDecl.initialization != null)
continue;
generateWitherForField(field, pos, level);
}
return true;
}
use of org.eclipse.jdt.internal.compiler.ast.TypeDeclaration in project lombok by rzwitserloot.
the class EclipseHandlerUtil method methodExists.
/**
* Checks if there is a method with the provided name. In case of multiple methods (overloading), only
* the first method decides if EXISTS_BY_USER or EXISTS_BY_LOMBOK is returned.
*
* @param methodName the method name to check for.
* @param node Any node that represents the Type (TypeDeclaration) to look in, or any child node thereof.
* @param caseSensitive If the search should be case sensitive.
* @param params The number of parameters the method should have; varargs count as 0-*. Set to -1 to find any method with the appropriate name regardless of parameter count.
*/
public static MemberExistsResult methodExists(String methodName, EclipseNode node, boolean caseSensitive, int params) {
while (node != null && !(node.get() instanceof TypeDeclaration)) {
node = node.up();
}
if (node != null && node.get() instanceof TypeDeclaration) {
TypeDeclaration typeDecl = (TypeDeclaration) node.get();
if (typeDecl.methods != null)
top: for (AbstractMethodDeclaration def : typeDecl.methods) {
if (def instanceof MethodDeclaration) {
char[] mName = def.selector;
if (mName == null)
continue;
boolean nameEquals = caseSensitive ? methodName.equals(new String(mName)) : methodName.equalsIgnoreCase(new String(mName));
if (nameEquals) {
if (params > -1) {
int minArgs = 0;
int maxArgs = 0;
if (def.arguments != null && def.arguments.length > 0) {
minArgs = def.arguments.length;
if ((def.arguments[def.arguments.length - 1].type.bits & ASTNode.IsVarArgs) != 0) {
minArgs--;
maxArgs = Integer.MAX_VALUE;
} else {
maxArgs = minArgs;
}
}
if (params < minArgs || params > maxArgs)
continue;
}
if (isTolerate(node, def))
continue top;
return getGeneratedBy(def) == null ? MemberExistsResult.EXISTS_BY_USER : MemberExistsResult.EXISTS_BY_LOMBOK;
}
}
}
}
return MemberExistsResult.NOT_EXISTS;
}
use of org.eclipse.jdt.internal.compiler.ast.TypeDeclaration in project lombok by rzwitserloot.
the class EclipseHandlerUtil method injectField.
/**
* Inserts a field into an existing type. The type must represent a {@code TypeDeclaration}.
*/
public static EclipseNode injectField(EclipseNode type, FieldDeclaration field) {
TypeDeclaration parent = (TypeDeclaration) type.get();
if (parent.fields == null) {
parent.fields = new FieldDeclaration[1];
parent.fields[0] = field;
} else {
int size = parent.fields.length;
FieldDeclaration[] newArray = new FieldDeclaration[size + 1];
System.arraycopy(parent.fields, 0, newArray, 0, size);
int index = 0;
for (; index < size; index++) {
FieldDeclaration f = newArray[index];
if (isEnumConstant(f) || isGenerated(f))
continue;
break;
}
System.arraycopy(newArray, index, newArray, index + 1, size - index);
newArray[index] = field;
parent.fields = newArray;
}
if (isEnumConstant(field) || (field.modifiers & Modifier.STATIC) != 0) {
if (!hasClinit(parent)) {
parent.addClinit();
}
}
return type.add(field, Kind.FIELD);
}
Aggregations