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