comparison truffle/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java @ 21951:9c8c0937da41

Moving all sources into truffle subdirectory
author Jaroslav Tulach <jaroslav.tulach@oracle.com>
date Wed, 17 Jun 2015 10:58:08 +0200
parents graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/model/MessageContainer.java@476374f3fe9a
children dc83cc1f94f2
comparison
equal deleted inserted replaced
21950:2a5011c7e641 21951:9c8c0937da41
1 /*
2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23 package com.oracle.truffle.dsl.processor.model;
24
25 import java.util.*;
26
27 import javax.lang.model.element.*;
28 import javax.tools.Diagnostic.Kind;
29
30 import com.oracle.truffle.dsl.processor.*;
31 import com.oracle.truffle.dsl.processor.java.*;
32
33 public abstract class MessageContainer implements Iterable<MessageContainer> {
34
35 private final List<Message> messages = new ArrayList<>();
36
37 public final void addWarning(String text, Object... params) {
38 getMessages().add(new Message(null, null, this, String.format(text, params), Kind.WARNING));
39 }
40
41 public final void addWarning(AnnotationValue value, String text, Object... params) {
42 getMessages().add(new Message(null, value, this, String.format(text, params), Kind.WARNING));
43 }
44
45 public final void addError(String text, Object... params) {
46 addError(null, text, params);
47 }
48
49 public final void addError(AnnotationValue value, String text, Object... params) {
50 getMessages().add(new Message(null, value, this, String.format(text, params), Kind.ERROR));
51 }
52
53 public final void addError(AnnotationMirror mirror, AnnotationValue value, String text, Object... params) {
54 getMessages().add(new Message(mirror, value, this, String.format(text, params), Kind.ERROR));
55 }
56
57 protected List<MessageContainer> findChildContainers() {
58 return Collections.emptyList();
59 }
60
61 public abstract Element getMessageElement();
62
63 public MessageContainer getBaseContainer() {
64 return null;
65 }
66
67 public Iterator<MessageContainer> iterator() {
68 return findChildContainers().iterator();
69 }
70
71 public final void emitMessages(ProcessorContext context, Log log) {
72 emitMessagesImpl(context, log, new HashSet<MessageContainer>(), null);
73 }
74
75 private void emitMessagesImpl(ProcessorContext context, Log log, Set<MessageContainer> visitedSinks, List<Message> verifiedMessages) {
76 List<Message> childMessages;
77 if (verifiedMessages == null) {
78 childMessages = collectMessagesWithElementChildren(new HashSet<MessageContainer>(), getMessageElement());
79 } else {
80 childMessages = verifiedMessages;
81 }
82 verifyExpectedMessages(context, log, childMessages);
83
84 for (int i = getMessages().size() - 1; i >= 0; i--) {
85 emitDefault(context, log, getMessages().get(i));
86 }
87
88 for (MessageContainer sink : findChildContainers()) {
89 if (visitedSinks.contains(sink)) {
90 continue;
91 }
92
93 visitedSinks.add(sink);
94 if (sink.getMessageElement() == this.getMessageElement()) {
95 sink.emitMessagesImpl(context, log, visitedSinks, childMessages);
96 } else {
97 sink.emitMessagesImpl(context, log, visitedSinks, null);
98 }
99 }
100 }
101
102 private List<Message> collectMessagesWithElementChildren(Set<MessageContainer> visitedSinks, Element e) {
103 if (visitedSinks.contains(this)) {
104 return Collections.emptyList();
105 }
106 visitedSinks.add(this);
107
108 List<Message> foundMessages = new ArrayList<>();
109 if (getMessageElement() != null && ElementUtils.typeEquals(getMessageElement().asType(), e.asType())) {
110 foundMessages.addAll(getMessages());
111 }
112 for (MessageContainer sink : findChildContainers()) {
113 foundMessages.addAll(sink.collectMessagesWithElementChildren(visitedSinks, e));
114 }
115 return foundMessages;
116 }
117
118 private void verifyExpectedMessages(ProcessorContext context, Log log, List<Message> msgs) {
119 TypeElement expectError = context.getTruffleTypes().getExpectError();
120 if (expectError != null) {
121 Element element = getMessageElement();
122 if (element != null) {
123 AnnotationMirror mirror = ElementUtils.findAnnotationMirror(element.getAnnotationMirrors(), expectError.asType());
124 if (mirror != null) {
125 List<String> values = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
126 if (values == null) {
127 values = Collections.emptyList();
128 }
129 if (values.size() != msgs.size()) {
130 log.message(Kind.ERROR, element, mirror, ElementUtils.getAnnotationValue(mirror, "value"), String.format("Error count expected %s but was %s.", values.size(), msgs.size()));
131 }
132 }
133 }
134 }
135 }
136
137 private void emitDefault(ProcessorContext context, Log log, Message message) {
138 Kind kind = message.getKind();
139
140 Element messageElement = getMessageElement();
141 AnnotationMirror messageAnnotation = getMessageAnnotation();
142 AnnotationValue messageValue = getMessageAnnotationValue();
143 if (message.getAnnotationValue() != null) {
144 messageValue = message.getAnnotationValue();
145 }
146 if (message.getAnnotationMirror() != null) {
147 messageAnnotation = message.getAnnotationMirror();
148 }
149
150 String text = message.getText();
151
152 TypeElement expectError = context.getTruffleTypes().getExpectError();
153 if (expectError != null) {
154 AnnotationMirror mirror = ElementUtils.findAnnotationMirror(messageElement.getAnnotationMirrors(), expectError.asType());
155 if (mirror != null) {
156 List<String> expectedTexts = ElementUtils.getAnnotationValueList(String.class, mirror, "value");
157 boolean found = false;
158 for (String expectedText : expectedTexts) {
159 if (expectedText.endsWith("%") && text.startsWith(expectedText.substring(0, expectedText.length() - 1))) {
160 found = true;
161 break;
162 } else if (text.equals(expectedText)) {
163 found = true;
164 break;
165 }
166 }
167 if (!found) {
168 log.message(kind, messageElement, mirror, ElementUtils.getAnnotationValue(mirror, "value"), "Message expected one of '%s' but was '%s'.", expectedTexts, text);
169 } else {
170 return;
171 }
172
173 }
174 }
175
176 log.message(kind, messageElement, messageAnnotation, messageValue, text);
177 }
178
179 public AnnotationMirror getMessageAnnotation() {
180 return null;
181 }
182
183 public AnnotationValue getMessageAnnotationValue() {
184 return null;
185 }
186
187 public final boolean hasErrors() {
188 return hasErrorsImpl(new HashSet<MessageContainer>());
189 }
190
191 public final List<Message> collectMessages() {
192 List<Message> collectedMessages = new ArrayList<>();
193 collectMessagesImpl(collectedMessages, new HashSet<MessageContainer>());
194 return collectedMessages;
195 }
196
197 private void collectMessagesImpl(List<Message> collectedMessages, Set<MessageContainer> visitedSinks) {
198 collectedMessages.addAll(getMessages());
199 for (MessageContainer sink : findChildContainers()) {
200 if (visitedSinks.contains(sink)) {
201 return;
202 }
203
204 visitedSinks.add(sink);
205 sink.collectMessagesImpl(collectedMessages, visitedSinks);
206 }
207 }
208
209 private boolean hasErrorsImpl(Set<MessageContainer> visitedSinks) {
210 for (Message msg : getMessages()) {
211 if (msg.getKind() == Kind.ERROR) {
212 return true;
213 }
214 }
215 for (MessageContainer sink : findChildContainers()) {
216 if (visitedSinks.contains(sink)) {
217 return false;
218 }
219
220 visitedSinks.add(sink);
221
222 if (sink.hasErrorsImpl(visitedSinks)) {
223 return true;
224 }
225 }
226 return false;
227 }
228
229 public List<Message> getMessages() {
230 return messages;
231 }
232
233 public static final class Message {
234
235 private final MessageContainer originalContainer;
236 private final AnnotationMirror annotationMirror;
237 private final AnnotationValue annotationValue;
238 private final String text;
239 private final Kind kind;
240
241 public Message(AnnotationMirror annotationMirror, AnnotationValue annotationValue, MessageContainer originalContainer, String text, Kind kind) {
242 this.annotationMirror = annotationMirror;
243 this.annotationValue = annotationValue;
244 this.originalContainer = originalContainer;
245 this.text = text;
246 this.kind = kind;
247 }
248
249 public AnnotationMirror getAnnotationMirror() {
250 return annotationMirror;
251 }
252
253 public AnnotationValue getAnnotationValue() {
254 return annotationValue;
255 }
256
257 public MessageContainer getOriginalContainer() {
258 return originalContainer;
259 }
260
261 public String getText() {
262 return text;
263 }
264
265 public Kind getKind() {
266 return kind;
267 }
268
269 @Override
270 public String toString() {
271 return kind + ": " + text;
272 }
273
274 }
275
276 }