aboutsummaryrefslogtreecommitdiff
path: root/src/lombok/javac/Javac.java
blob: 801e7a230bcaa86607393b258dfe082a414dbc4c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package lombok.javac;

import java.lang.annotation.Annotation;
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.javac.JavacAST.Node;

import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCAssign;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCIdent;
import com.sun.tools.javac.tree.JCTree.JCLiteral;
import com.sun.tools.javac.tree.JCTree.JCNewArray;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;

public class Javac {
	private Javac() {
		//prevent instantiation
	}
	
	public static boolean annotationTypeMatches(Class<? extends Annotation> type, Node node) {
		if ( node.getKind() != Kind.ANNOTATION ) return false;
		String typeName = ((JCAnnotation)node.get()).annotationType.toString();
		
		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 Annotation> AnnotationValues<A> createAnnotation(Class<A> type, final Node node) {
		Map<String, AnnotationValue> values = new HashMap<String, AnnotationValue>();
		JCAnnotation anno = (JCAnnotation) node.get();
		List<JCExpression> arguments = anno.getArguments();
		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>();
			final List<DiagnosticPosition> positions = new ArrayList<DiagnosticPosition>();
			
			for ( JCExpression arg : arguments ) {
				JCAssign assign = (JCAssign) arg;
				String mName = assign.lhs.toString();
				if ( !mName.equals(name) ) continue;
				JCExpression rhs = assign.rhs;
				if ( rhs instanceof JCNewArray ) {
					List<JCExpression> elems = ((JCNewArray)rhs).elems;
					for  ( JCExpression inner : elems ) {
						raws.add(inner.toString());
						guesses.add(calculateGuess(inner));
						positions.add(inner.pos());
					}
				} else {
					raws.add(rhs.toString());
					guesses.add(calculateGuess(rhs));
					positions.add(rhs.pos());
				}
			}
			
			values.put(name, new AnnotationValue(node, raws, guesses) {
				@Override public void setError(String message, int valueIdx) {
					node.addError(message, positions.get(valueIdx));
				}
			});
		}
		
		return new AnnotationValues<A>(type, values, node);
	}
	
	private static Object calculateGuess(JCExpression expr) {
		if ( expr instanceof JCLiteral ) {
			return ((JCLiteral)expr).value;
		} else if ( expr instanceof JCIdent || expr instanceof JCFieldAccess ) {
			String x = expr.toString();
			if ( x.endsWith(".class") ) x = x.substring(0, x.length() - 6);
			else {
				int idx = x.lastIndexOf('.');
				if ( idx > -1 ) x = x.substring(idx + 1);
			}
			return x;
		} else return null;
	}
}