aboutsummaryrefslogtreecommitdiff
path: root/src/lombok/eclipse/EclipseASTVisitor.java
blob: a9b4e706658d21dcf1be244a656ec58029f03c42 (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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
package lombok.eclipse;

import java.lang.reflect.Modifier;

import lombok.eclipse.EclipseAST.Node;

import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.Argument;
import org.eclipse.jdt.internal.compiler.ast.Block;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Initializer;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;

//TODO
public interface EclipseASTVisitor {
	/**
	 * Called at the very beginning and end.
	 */
	void visitCompilationUnit(Node top, CompilationUnitDeclaration unit);
	void endVisitCompilationUnit(Node top, CompilationUnitDeclaration unit);
	
	/**
	 * Called when visiting a type (a class, interface, annotation, enum, etcetera).
	 */
	void visitType(Node typeNode, TypeDeclaration type);
	void visitAnnotationOnType(Node typeNode, TypeDeclaration type, Annotation annotation);
	void endVisitType(Node typeNode, TypeDeclaration type);
	
	/**
	 * Called when visiting a field of a class.
	 * Even though in eclipse initializers (both instance and static) are represented as Initializer objects,
	 * which are a subclass of FieldDeclaration, those do NOT result in a call to this method. They result
	 * in a call to the visitInitializer method.
	 */
	void visitField(Node fieldNode, FieldDeclaration field);
	void visitAnnotationOnField(Node fieldNode, FieldDeclaration Field, Annotation annotation);
	void endVisitField(Node fieldNode, FieldDeclaration field);
	
	/**
	 * Called for static and instance initializers. You can tell the difference via the modifier flag on the
	 * ASTNode (8 for static, 0 for not static). The content is in the 'block', not in the 'initialization',
	 * which would always be null for an initializer instance.
	 */
	void visitInitializer(Node initializerNode, Initializer initializer);
	void endVisitInitializer(Node initializerNode, Initializer initializer);
	
	/**
	 * Called for both methods (MethodDeclaration) and constructors (ConstructorDeclaration), but not for
	 * Clinit objects, which are a vestigial eclipse thing that never contain anything. Static initializers
	 * show up as 'Initializer', in the visitInitializer method, with modifier bit STATIC set.
	 */
	void visitMethod(Node methodNode, AbstractMethodDeclaration method);
	void visitAnnotationOnMethod(Node methodNode, AbstractMethodDeclaration method, Annotation annotation);
	void endVisitMethod(Node methodNode, AbstractMethodDeclaration method);
	
	/**
	 * Visits a local declaration - that is, something like 'int x = 10;' on the method level. Also called
	 * for method parameter (those would be Arguments, a subclass of LocalDeclaration).
	 */
	void visitLocal(Node localNode, LocalDeclaration local);
	void visitAnnotationOnLocal(Node localNode, LocalDeclaration local, Annotation annotation);
	void endVisitLocal(Node localNode, LocalDeclaration local);
	
	/**
	 * Visits a statement that isn't any of the other visit methods (e.g. TypeDeclaration).
	 * @param node
	 * @param statement
	 */
	void visitStatement(Node statementNode, Statement statement);
	void endVisitStatement(Node statementNode, Statement statement);
	
	public static class EclipseASTPrinter implements EclipseASTVisitor {
		int indent = 0;
		private void print(String text, Object... params) {
			StringBuilder sb = new StringBuilder();
			for ( int i = 0 ; i < indent ; i++ ) sb.append("  ");
			System.out.printf(sb.append(text).append('\n').toString(), params);
		}
		
		private String str(char[] c) {
			if ( c == null ) return "(NULL)";
			else return new String(c);
		}
		
		private String str(TypeReference type) {
			if ( type == null ) return "(NULL)";
			char[][] c = type.getTypeName();
			StringBuilder sb = new StringBuilder();
			boolean first = true;
			for ( char[] d : c ) {
				sb.append(first ? "" : ".").append(new String(d));
				first = false;
			}
			return sb.toString();
		}
		
		@Override public void visitCompilationUnit(Node node, CompilationUnitDeclaration unit) {
			System.out.println("---------------------------------------------------------");
			System.out.println(node.isCompleteParse() ? "COMPLETE" : "incomplete");
			
			print("<CUD %s>", node.getFileName());
			indent++;
		}
		
		@Override public void endVisitCompilationUnit(Node node, CompilationUnitDeclaration unit) {
			indent--;
			print("</CUD>");
		}
		
		@Override public void visitType(Node node, TypeDeclaration type) {
			print("<TYPE %s>", str(type.name));
			indent++;
		}
		
		@Override public void visitAnnotationOnType(Node node, TypeDeclaration type, Annotation annotation) {
			print("<ANNOTATION: %s />", annotation);
		}
		
		@Override public void endVisitType(Node node, TypeDeclaration type) {
			indent--;
			print("</TYPE %s>", str(type.name));
		}
		
		@Override public void visitInitializer(Node node, Initializer initializer) {
			Block block = initializer.block;
			boolean s = (block != null && block.statements != null);
			print("<%s INITIALIZER: %s>",
					(initializer.modifiers & Modifier.STATIC) > 0 ? "static" : "instance",
							s ? "filled" : "blank");
			indent++;
		}
		
		@Override public void endVisitInitializer(Node node, Initializer initializer) {
			indent--;
			print("</%s INITIALIZER>", (initializer.modifiers & Modifier.STATIC) > 0 ? "static" : "instance");
		}
		
		@Override public void visitField(Node node, FieldDeclaration field) {
			print("<FIELD %s %s = %s>", str(field.type), str(field.name), field.initialization);
			indent++;
		}
		
		@Override public void visitAnnotationOnField(Node node, FieldDeclaration field, Annotation annotation) {
			print("<ANNOTATION: %s />", annotation);
		}
		
		@Override public void endVisitField(Node node, FieldDeclaration field) {
			indent--;
			print("</FIELD %s %s>", str(field.type), str(field.name));
		}
		
		@Override public void visitMethod(Node node, AbstractMethodDeclaration method) {
			String type = method instanceof ConstructorDeclaration ? "CONSTRUCTOR" : "METHOD";
			print("<%s %s: %s>", type, str(method.selector), method.statements != null ? "filled" : "blank");
			indent++;
		}
		
		@Override public void visitAnnotationOnMethod(Node node, AbstractMethodDeclaration method, Annotation annotation) {
			print("<ANNOTATION: %s />", annotation);
		}
		
		@Override public void endVisitMethod(Node node, AbstractMethodDeclaration method) {
			String type = method instanceof ConstructorDeclaration ? "CONSTRUCTOR" : "METHOD";
			indent--;
			print("</%s %s>", type, str(method.selector));
		}
		
		@Override public void visitLocal(Node node, LocalDeclaration local) {
			String type = local instanceof Argument ? "ARGUMENT" : "LOCAL";
			print("<%s %s %s = %s>", type, str(local.type), str(local.name), local.initialization);
			indent++;
		}
		
		@Override public void visitAnnotationOnLocal(Node node, LocalDeclaration local, Annotation annotation) {
			print("<ANNOTATION: %s />", annotation);
		}
		
		@Override public void endVisitLocal(Node node, LocalDeclaration local) {
			String type = local instanceof Argument ? "ARGUMENT" : "LOCAL";
			indent--;
			print("</%s %s %s>", type, str(local.type), str(local.name));
		}
		
		@Override public void visitStatement(Node node, Statement statement) {
			print("<%s>", statement.getClass());
			indent++;
		}
		
		@Override public void endVisitStatement(Node node, Statement statement) {
			indent--;
			print("</%s>", statement.getClass());
		}
	}
}