comparison graal/com.oracle.truffle.dsl.processor/src/com/oracle/truffle/dsl/processor/template/MessageContainer.java @ 11467:43eab069ca9b

Truffle-DSL: improved error recovery of type systems and improved error testability infrastructure.
author Christian Humer <christian.humer@gmail.com>
date Thu, 29 Aug 2013 19:19:00 +0200
parents 4830676526e3
children f15d955897b7
comparison
equal deleted inserted replaced
11466:4830676526e3 11467:43eab069ca9b
50 } 50 }
51 51
52 public abstract Element getMessageElement(); 52 public abstract Element getMessageElement();
53 53
54 public final void emitMessages(ProcessorContext context, TypeElement baseElement, Log log) { 54 public final void emitMessages(ProcessorContext context, TypeElement baseElement, Log log) {
55 emitMessagesImpl(context, baseElement, log, new HashSet<MessageContainer>()); 55 emitMessagesImpl(context, baseElement, log, new HashSet<MessageContainer>(), null);
56 } 56 }
57 57
58 private void emitMessagesImpl(ProcessorContext context, TypeElement baseElement, Log log, Set<MessageContainer> visitedSinks) { 58 private void emitMessagesImpl(ProcessorContext context, TypeElement baseElement, Log log, Set<MessageContainer> visitedSinks, List<Message> verifiedMessages) {
59 List<Message> childMessages;
60 if (verifiedMessages == null) {
61 childMessages = collectMessagesWithElementChildren(new HashSet<MessageContainer>(), getMessageElement());
62 } else {
63 childMessages = verifiedMessages;
64 }
65 verifyExpectedMessages(context, log, childMessages);
66
67 for (Message message : getMessages()) {
68 emitDefault(context, baseElement, log, message);
69 }
70
71 for (MessageContainer sink : findChildContainers()) {
72 if (visitedSinks.contains(sink)) {
73 continue;
74 }
75
76 visitedSinks.add(sink);
77 if (sink.getMessageElement() == this.getMessageElement()) {
78 sink.emitMessagesImpl(context, baseElement, log, visitedSinks, childMessages);
79 } else {
80 sink.emitMessagesImpl(context, baseElement, log, visitedSinks, null);
81 }
82 }
83 }
84
85 private List<Message> collectMessagesWithElementChildren(Set<MessageContainer> visitedSinks, Element e) {
86 if (visitedSinks.contains(this)) {
87 return Collections.emptyList();
88 }
89 visitedSinks.add(this);
90
91 List<Message> foundMessages = new ArrayList<>();
92 if (Utils.typeEquals(getMessageElement().asType(), e.asType())) {
93 foundMessages.addAll(getMessages());
94 }
95 for (MessageContainer sink : findChildContainers()) {
96 foundMessages.addAll(sink.collectMessagesWithElementChildren(visitedSinks, e));
97 }
98 return foundMessages;
99 }
100
101 private void verifyExpectedMessages(ProcessorContext context, Log log, List<Message> msgs) {
59 TypeElement expectError = context.getTruffleTypes().getExpectError(); 102 TypeElement expectError = context.getTruffleTypes().getExpectError();
60 if (expectError != null) { 103 if (expectError != null) {
61 Element element = getMessageElement(); 104 Element element = getMessageElement();
62 AnnotationMirror mirror = Utils.findAnnotationMirror(element.getAnnotationMirrors(), expectError); 105 AnnotationMirror mirror = Utils.findAnnotationMirror(element.getAnnotationMirrors(), expectError);
63 if (mirror != null) { 106 if (mirror != null) {
64 List<String> values = Utils.getAnnotationValueList(String.class, mirror, "value"); 107 List<String> values = Utils.getAnnotationValueList(String.class, mirror, "value");
65 if (values == null) { 108 if (values == null) {
66 values = Collections.emptyList(); 109 values = Collections.emptyList();
67 } 110 }
68 List<Message> msgs = getMessages();
69 if (values.size() != msgs.size()) { 111 if (values.size() != msgs.size()) {
70 log.message(Kind.ERROR, element, mirror, Utils.getAnnotationValue(mirror, "value"), String.format("Error count expected %s but was %s.", values.size(), msgs.size())); 112 log.message(Kind.ERROR, element, mirror, Utils.getAnnotationValue(mirror, "value"), String.format("Error count expected %s but was %s.", values.size(), msgs.size()));
71 } 113 }
72 } 114 }
73 }
74
75 for (Message message : getMessages()) {
76 emitDefault(context, baseElement, log, message);
77 }
78
79 for (MessageContainer sink : findChildContainers()) {
80 if (visitedSinks.contains(sink)) {
81 continue;
82 }
83
84 visitedSinks.add(sink);
85 sink.emitMessagesImpl(context, baseElement, log, visitedSinks);
86 } 115 }
87 } 116 }
88 117
89 private void emitDefault(ProcessorContext context, TypeElement baseType, Log log, Message message) { 118 private void emitDefault(ProcessorContext context, TypeElement baseType, Log log, Message message) {
90 Kind kind = message.getKind(); 119 Kind kind = message.getKind();
97 } 126 }
98 127
99 String text = message.getText(); 128 String text = message.getText();
100 129
101 TypeElement rootEnclosing = Utils.findRootEnclosingType(getMessageElement()); 130 TypeElement rootEnclosing = Utils.findRootEnclosingType(getMessageElement());
102 if (rootEnclosing == null || !Utils.typeEquals(baseType.asType(), rootEnclosing.asType()) || this != message.getOriginalContainer()) { 131 TypeElement baseEnclosing = Utils.findRootEnclosingType(baseType);
132 if (rootEnclosing == null || !Utils.typeEquals(baseEnclosing.asType(), rootEnclosing.asType()) || this != message.getOriginalContainer()) {
103 // redirect message 133 // redirect message
104 MessageContainer original = message.getOriginalContainer(); 134 MessageContainer original = message.getOriginalContainer();
105 messageElement = baseType; 135 messageElement = baseType;
106 messageAnnotation = null; 136 messageAnnotation = null;
107 messageValue = null; 137 messageValue = null;
111 TypeElement expectError = context.getTruffleTypes().getExpectError(); 141 TypeElement expectError = context.getTruffleTypes().getExpectError();
112 if (expectError != null) { 142 if (expectError != null) {
113 AnnotationMirror mirror = Utils.findAnnotationMirror(messageElement.getAnnotationMirrors(), expectError); 143 AnnotationMirror mirror = Utils.findAnnotationMirror(messageElement.getAnnotationMirrors(), expectError);
114 if (mirror != null) { 144 if (mirror != null) {
115 List<String> expectedTexts = Utils.getAnnotationValueList(String.class, mirror, "value"); 145 List<String> expectedTexts = Utils.getAnnotationValueList(String.class, mirror, "value");
116 if (!expectedTexts.contains(text)) { 146 boolean found = false;
117 log.message(kind, messageElement, mirror, Utils.getAnnotationValue(mirror, "value"), String.format("Message expected one of '%s' but was '%s'.", expectedTexts, text)); 147 for (String expectedText : expectedTexts) {
148 if (expectedText.endsWith("%") && text.startsWith(expectedText.substring(0, expectedText.length() - 1))) {
149 found = true;
150 break;
151 } else if (text.equals(expectedText)) {
152 found = true;
153 break;
154 }
155 }
156 if (!found) {
157 log.message(kind, messageElement, mirror, Utils.getAnnotationValue(mirror, "value"), "Message expected one of '%s' but was '%s'.", expectedTexts, text);
118 } else { 158 } else {
119 return; 159 return;
120 } 160 }
161
121 } 162 }
122 } 163 }
123 164
124 log.message(kind, messageElement, messageAnnotation, messageValue, text); 165 log.message(kind, messageElement, messageAnnotation, messageValue, text);
125 } 166 }