diff options
Diffstat (limited to 'src/lombok/eclipse/Eclipse.java')
-rw-r--r-- | src/lombok/eclipse/Eclipse.java | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/lombok/eclipse/Eclipse.java b/src/lombok/eclipse/Eclipse.java index 961b9536..baac26a9 100644 --- a/src/lombok/eclipse/Eclipse.java +++ b/src/lombok/eclipse/Eclipse.java @@ -1,12 +1,41 @@ package lombok.eclipse; +import java.lang.reflect.Method; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import lombok.core.AnnotationValues; +import lombok.core.TypeLibrary; +import lombok.core.TypeResolver; +import lombok.core.AST.Kind; +import lombok.core.AnnotationValues.AnnotationValue; +import lombok.eclipse.EclipseAST.Node; + import org.eclipse.core.runtime.ILog; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; +import org.eclipse.jdt.internal.compiler.ast.Annotation; +import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; +import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess; +import org.eclipse.jdt.internal.compiler.ast.Expression; +import org.eclipse.jdt.internal.compiler.ast.Literal; +import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; +import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; +import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; +import org.eclipse.jdt.internal.compiler.ast.TypeReference; +import org.eclipse.jdt.internal.compiler.lookup.TypeIds; import org.osgi.framework.Bundle; public class Eclipse { + private Eclipse() { + //Prevent instantiation + } + private static final String DEFAULT_BUNDLE = "org.eclipse.jdt.core"; public static void error(String message) { error(message, DEFAULT_BUNDLE, null); @@ -41,4 +70,103 @@ public class Eclipse { } return sb.toString(); } + + public static boolean annotationTypeMatches(Class<? extends java.lang.annotation.Annotation> type, Node node) { + if ( node.getKind() != Kind.ANNOTATION ) return false; + TypeReference typeRef = ((Annotation)node.get()).type; + if ( typeRef == null || typeRef.getTypeName() == null ) return false; + String typeName = toQualifiedName(typeRef.getTypeName()); + + TypeLibrary library = new TypeLibrary(); + library.addType(type.getName()); + TypeResolver resolver = new TypeResolver(library, node.getPackageDeclaration(), node.getImportStatements()); + Collection<String> typeMatches = resolver.findTypeMatches(node, typeName); + + for ( String match : typeMatches ) { + if ( match.equals(type.getName()) ) return true; + } + + return false; + } + + public static <A extends java.lang.annotation.Annotation> AnnotationValues<A> + createAnnotation(Class<A> type, final Node annotationNode) { + Annotation annotation = (Annotation) annotationNode.get(); + Map<String, AnnotationValue> values = new HashMap<String, AnnotationValue>(); + + final MemberValuePair[] pairs = annotation.memberValuePairs(); + for ( Method m : type.getDeclaredMethods() ) { + if ( !Modifier.isPublic(m.getModifiers()) ) continue; + String name = m.getName(); + List<String> raws = new ArrayList<String>(); + List<Object> guesses = new ArrayList<Object>(); + Expression fullExpression = null; + Expression[] expressions = null; + + if ( pairs != null ) for ( MemberValuePair pair : pairs ) { + char[] n = pair.name; + String mName = n == null ? "value" : new String(name); + if ( !mName.equals(name) ) continue; + fullExpression = pair.value; + } + + if ( fullExpression != null ) { + if ( fullExpression instanceof ArrayInitializer ) { + expressions = ((ArrayInitializer)fullExpression).expressions; + } else expressions = new Expression[] { fullExpression }; + for ( Expression ex : expressions ) { + StringBuffer sb = new StringBuffer(); + ex.print(0, sb); + raws.add(sb.toString()); + guesses.add(calculateValue(ex)); + } + } + + final Expression fullExpr = fullExpression; + final Expression[] exprs = expressions; + + values.put(name, new AnnotationValue(annotationNode, raws, guesses) { + @Override public void setError(String message, int valueIdx) { + Expression ex; + if ( valueIdx == -1 ) ex = fullExpr; + else ex = exprs[valueIdx]; + + int sourceStart = ex.sourceStart; + int sourceEnd = ex.sourceEnd; + + annotationNode.addError(message, sourceStart, sourceEnd); + } + }); + } + + return new AnnotationValues<A>(type, values, annotationNode); + } + + private static Object calculateValue(Expression e) { + if ( e instanceof Literal ) { + ((Literal)e).computeConstant(); + switch ( e.constant.typeID() ) { + case TypeIds.T_int: return e.constant.intValue(); + case TypeIds.T_byte: return e.constant.byteValue(); + case TypeIds.T_short: return e.constant.shortValue(); + case TypeIds.T_char: return e.constant.charValue(); + case TypeIds.T_float: return e.constant.floatValue(); + case TypeIds.T_double: return e.constant.doubleValue(); + case TypeIds.T_boolean: return e.constant.booleanValue(); + case TypeIds.T_long: return e.constant.longValue(); + case TypeIds.T_JavaLangString: return e.constant.stringValue(); + default: return null; + } + } else if ( e instanceof ClassLiteralAccess ) { + return Eclipse.toQualifiedName(((ClassLiteralAccess)e).type.getTypeName()); + } else if ( e instanceof SingleNameReference ) { + return new String(((SingleNameReference)e).token); + } else if ( e instanceof QualifiedNameReference ) { + String qName = Eclipse.toQualifiedName(((QualifiedNameReference)e).tokens); + int idx = qName.lastIndexOf('.'); + return idx == -1 ? qName : qName.substring(idx+1); + } + + return null; + } } |