aboutsummaryrefslogtreecommitdiff
path: root/src/utils/lombok/javac/Javac.java
blob: 75bb2dbfa7e7b463d6b3b14df0133ff35a0025d0 (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
103
104
105
106
107
108
109
110
111
112
113
114
/*
 * Copyright (C) 2009-2012 The Project Lombok Authors.
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package lombok.javac;

import java.util.regex.Pattern;

import com.sun.tools.javac.code.TypeTags;
import com.sun.tools.javac.tree.JCTree;
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;

/**
 * Container for static utility methods relevant to lombok's operation on javac.
 */
public class Javac {
	private Javac() {
		//prevent instantiation
	}
	
	/** Matches any of the 8 primitive names, such as {@code boolean}. */
	private static final Pattern PRIMITIVE_TYPE_NAME_PATTERN = Pattern.compile(
			"^(boolean|byte|short|int|long|float|double|char)$");
	
	/**
	 * Checks if the given expression (that really ought to refer to a type expression) represents a primitive type.
	 */
	public static boolean isPrimitive(JCExpression ref) {
		String typeName = ref.toString();
		return PRIMITIVE_TYPE_NAME_PATTERN.matcher(typeName).matches();
	}
	
	/**
	 * Turns an expression into a guessed intended literal. Only works for literals, as you can imagine.
	 * 
	 * Will for example turn a TrueLiteral into 'Boolean.valueOf(true)'.
	 */
	public static Object calculateGuess(JCExpression expr) {
		if (expr instanceof JCLiteral) {
			JCLiteral lit = (JCLiteral)expr;
			if (lit.getKind() == com.sun.source.tree.Tree.Kind.BOOLEAN_LITERAL) {
				return ((Number)lit.value).intValue() == 0 ? false : true;
			}
			return lit.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;
	}
	
	public static final int CTC_BOOLEAN = getCtcInt(TypeTags.class, "BOOLEAN");
	public static final int CTC_INT = getCtcInt(TypeTags.class, "INT");
	public static final int CTC_DOUBLE = getCtcInt(TypeTags.class, "DOUBLE");
	public static final int CTC_FLOAT = getCtcInt(TypeTags.class, "FLOAT");
	public static final int CTC_SHORT = getCtcInt(TypeTags.class, "SHORT");
	public static final int CTC_BYTE = getCtcInt(TypeTags.class, "BYTE");
	public static final int CTC_LONG = getCtcInt(TypeTags.class, "LONG");
	public static final int CTC_CHAR = getCtcInt(TypeTags.class, "CHAR");
	public static final int CTC_VOID = getCtcInt(TypeTags.class, "VOID");
	public static final int CTC_NONE = getCtcInt(TypeTags.class, "NONE");
	
	public static final int CTC_NOT_EQUAL = getCtcInt(JCTree.class, "NE");
	public static final int CTC_NOT = getCtcInt(JCTree.class, "NOT");
	public static final int CTC_BITXOR = getCtcInt(JCTree.class, "BITXOR");
	public static final int CTC_UNSIGNED_SHIFT_RIGHT = getCtcInt(JCTree.class, "USR");
	public static final int CTC_MUL = getCtcInt(JCTree.class, "MUL");
	public static final int CTC_PLUS = getCtcInt(JCTree.class, "PLUS");
	public static final int CTC_BOT = getCtcInt(TypeTags.class, "BOT");
	public static final int CTC_EQUAL = getCtcInt(JCTree.class, "EQ");
	
	/**
	 * Retrieves a compile time constant of type int from the specified class location.
	 * 
	 * Solves the problem of compile time constant inlining, resulting in lombok having the wrong value 
	 * (javac compiler changes private api constants from time to time)
	 * 
	 * @param ctcLocation location of the compile time constant
	 * @param identifier the name of the field of the compile time constant.
	 */
	public static int getCtcInt(Class<?> ctcLocation, String identifier) {
		try {
			return (Integer)ctcLocation.getField(identifier).get(null);
		} catch (NoSuchFieldException e) {
			throw new RuntimeException(e);
		} catch (IllegalAccessException e) {
			throw new RuntimeException(e);
		}
	}
}