1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.compiler.plugin;
18
19 import javax.annotation.processing.SupportedAnnotationTypes;
20 import javax.annotation.processing.SupportedSourceVersion;
21 import javax.lang.model.SourceVersion;
22 import javax.lang.model.element.Element;
23 import javax.tools.Diagnostic;
24 import java.util.EnumSet;
25 import java.util.Set;
26
27 import com.sun.source.tree.CompilationUnitTree;
28 import com.sun.source.tree.IdentifierTree;
29 import com.sun.source.tree.MemberSelectTree;
30 import com.sun.source.tree.NewClassTree;
31 import com.sun.source.tree.Tree;
32 import com.sun.source.util.JavacTask;
33 import com.sun.source.util.Plugin;
34 import com.sun.source.util.TaskEvent;
35 import com.sun.source.util.TaskEvent.Kind;
36 import com.sun.source.util.TaskListener;
37 import com.sun.source.util.TreePath;
38 import com.sun.source.util.TreeScanner;
39 import com.sun.source.util.Trees;
40 import org.orekit.annotation.DefaultDataContext;
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55 @SupportedAnnotationTypes("org.orekit.annotation.DefaultDataContext")
56 @SupportedSourceVersion(SourceVersion.RELEASE_8)
57 public class DefaultDataContextPlugin implements Plugin, TaskListener {
58
59
60 static final String MESSAGE = "Use of the default data context from a scope not " +
61 "annotated with @DefaultDataContext. This code may be unintentionally " +
62 "using the default data context.";
63
64 private static final Class<DefaultDataContext> ANNOTATION = DefaultDataContext.class;
65
66
67 private Trees trees;
68
69
70
71
72
73
74
75
76 public DefaultDataContextPlugin() {
77
78 }
79
80 @Override
81 public String getName() {
82 return "dataContextPlugin";
83 }
84
85 @Override
86 public synchronized void init(final JavacTask javacTask, final String... args) {
87 javacTask.addTaskListener(this);
88 trees = Trees.instance(javacTask);
89 }
90
91 @Override
92 public void started(final TaskEvent taskEvent) {
93 }
94
95 @Override
96 public void finished(final TaskEvent taskEvent) {
97 if (taskEvent.getKind() == Kind.ANALYZE) {
98 final CompilationUnitTree root = taskEvent.getCompilationUnit();
99 root.accept(new AnnotationTreeScanner(root), null);
100 }
101 }
102
103
104 private class AnnotationTreeScanner extends TreeScanner<Void, Void> {
105
106
107 private final CompilationUnitTree root;
108
109
110
111
112
113
114 AnnotationTreeScanner(final CompilationUnitTree root) {
115 this.root = root;
116 }
117
118 @Override
119 public Void visitIdentifier(final IdentifierTree identifierTree,
120 final Void aVoid) {
121 check(identifierTree);
122 return super.visitIdentifier(identifierTree, aVoid);
123 }
124
125 @Override
126 public Void visitMemberSelect(final MemberSelectTree memberSelectTree,
127 final Void aVoid) {
128 check(memberSelectTree);
129 return super.visitMemberSelect(memberSelectTree, aVoid);
130 }
131
132 @Override
133 public Void visitNewClass(final NewClassTree newClassTree, final Void aVoid) {
134 check(newClassTree);
135 return super.visitNewClass(newClassTree, aVoid);
136 }
137
138
139
140
141
142
143
144 private void check(final Tree tree) {
145 final Element element = trees.getElement(trees.getPath(root, tree));
146 check(tree, element);
147 }
148
149
150
151
152
153
154
155 private void check(final Tree tree, final Element element) {
156
157 if (isAnyElementAnnotated(element)) {
158
159
160 if (!isAnyElementAnnotated(trees.getPath(root, tree))) {
161
162 final String message = MESSAGE + " Used: " + element.getKind() + " " + element;
163 trees.printMessage(Diagnostic.Kind.WARNING, message, tree, root);
164 }
165 }
166 }
167
168
169
170
171
172
173
174
175
176 private boolean isAnyElementAnnotated(final Element element) {
177 Element e = element;
178 while (e != null) {
179 if (e.getAnnotation(ANNOTATION) != null) {
180 return true;
181 }
182 e = e.getEnclosingElement();
183 }
184 return false;
185 }
186
187
188
189
190
191
192
193
194
195 private boolean isAnyElementAnnotated(final TreePath path) {
196
197 final Set<Tree.Kind> toCheck = EnumSet.of(
198 Tree.Kind.METHOD, Tree.Kind.CLASS, Tree.Kind.VARIABLE,
199 Tree.Kind.INTERFACE, Tree.Kind.ENUM);
200 TreePath next = path;
201 while (next != null) {
202 if (toCheck.contains(next.getLeaf().getKind())) {
203 if (trees.getElement(next).getAnnotation(ANNOTATION) != null) {
204 return true;
205 }
206 }
207 next = next.getParentPath();
208 }
209 return false;
210 }
211
212 }
213
214 }