OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 library test_utils; | |
6 | |
7 import 'package:unittest/unittest.dart'; | |
8 | |
9 import 'package:analyzer_experimental/src/generated/java_core.dart' show CharSeq
uence; | |
10 import 'package:analyzer_experimental/src/generated/engine.dart' show AnalysisCo
ntext, AnalysisContextImpl; | |
11 import 'package:analyzer_experimental/src/generated/source.dart'; | |
12 import 'package:analyzer_experimental/src/generated/error.dart'; | |
13 import 'package:analyzer_experimental/src/generated/scanner.dart'; | |
14 import 'package:analyzer_experimental/src/generated/ast.dart'; | |
15 import 'package:analyzer_experimental/src/generated/parser.dart'; | |
16 | |
17 | |
18 /// Instances of the class [_GatheringErrorListener] implement an error listener | |
19 /// that collects all of the errors passed to it for later examination. | |
20 class _GatheringErrorListener implements AnalysisErrorListener { | |
21 | |
22 /// The source being parsed. | |
23 String _rawSource; | |
24 | |
25 /// The source being parsed after inserting a marker at the beginning and end | |
26 /// of the range of the most recent error. | |
27 String _markedSource; | |
28 | |
29 /// A list containing the errors that were collected. | |
30 final List<AnalysisError> _errors = new List<AnalysisError>(); | |
31 | |
32 /// A table mapping sources to the line information for the source. | |
33 final Map<Source, LineInfo> _lineInfoMap = new Map<Source, LineInfo>(); | |
34 | |
35 void onError(AnalysisError error) { | |
36 if (_rawSource != null) { | |
37 var left = error.offset; | |
38 var right = left + error.length - 1; | |
39 _markedSource = '${_rawSource.substring(0, left)}^${_rawSource.substring(l
eft, right)}^${_rawSource.substring(right)}'; | |
40 } | |
41 _errors.add(error); | |
42 } | |
43 | |
44 | |
45 /// Sets the line information associated with the given source to the given | |
46 /// information. | |
47 void setLineInfo(Source source, List<int> lineStarts) { | |
48 _lineInfoMap[source] = new LineInfo(lineStarts); | |
49 } | |
50 | |
51 | |
52 /// Asserts that the number of errors that have been gathered matches the | |
53 /// number of errors that are given and that they have the expected error | |
54 /// codes. The order in which the errors were gathered is ignored. | |
55 void expectErrors(List<ErrorCode> expectedErrorCodes) { | |
56 var builder = new StringBuffer(); | |
57 var expectedCounts = new Map<ErrorCode, int>(); | |
58 | |
59 for (var code in expectedErrorCodes) { | |
60 var count = expectedCounts[code]; | |
61 if (count == null) { | |
62 count = 1; | |
63 } else { | |
64 count = count + 1; | |
65 } | |
66 expectedCounts[code] = count; | |
67 } | |
68 | |
69 var errorsByCode = new Map<ErrorCode, List<AnalysisError>>(); | |
70 for (var error in _errors) { | |
71 var code = error.errorCode; | |
72 var list = errorsByCode[code]; | |
73 if (list == null) { | |
74 list = new List<AnalysisError>(); | |
75 errorsByCode[code] = list; | |
76 } | |
77 list.add(error); | |
78 } | |
79 | |
80 for (var entry in _getMapEntrySet(expectedCounts)) { | |
81 var code = entry.getKey(); | |
82 var expectedCount = entry.getValue(); | |
83 var actualCount; | |
84 | |
85 var list = errorsByCode.remove(code); | |
86 if (list == null) { | |
87 actualCount = 0; | |
88 } else { | |
89 actualCount = list.length; | |
90 } | |
91 | |
92 if (actualCount != expectedCount) { | |
93 if (builder.length == 0) { | |
94 builder.write('Expected '); | |
95 } else { | |
96 builder.write('; '); | |
97 } | |
98 builder.write(expectedCount); | |
99 builder.write(' errors of type '); | |
100 builder.write(code); | |
101 builder.write(', found '); | |
102 builder.write(actualCount); | |
103 } | |
104 } | |
105 | |
106 for (var entry in _getMapEntrySet(errorsByCode)) { | |
107 var code = entry.getKey(); | |
108 var actualErrors = entry.getValue(); | |
109 var actualCount = actualErrors.length; | |
110 | |
111 if (builder.length == 0) { | |
112 builder.write('Expected '); | |
113 } else { | |
114 builder.write('; '); | |
115 } | |
116 | |
117 builder.write('0 errors of type '); | |
118 builder.write(code); | |
119 builder.write(', found '); | |
120 builder.write(actualCount); | |
121 builder.write(' ('); | |
122 | |
123 for (int i = 0; i < actualErrors.length; i++) { | |
124 var error = actualErrors[i]; | |
125 if (i > 0) { | |
126 builder.write(', '); | |
127 } | |
128 builder.write(error.offset); | |
129 } | |
130 | |
131 builder.write(')'); | |
132 } | |
133 | |
134 if (builder.length > 0) { | |
135 fail(builder.toString()); | |
136 } | |
137 } | |
138 | |
139 } | |
140 | |
141 | |
142 Set<_MapEntry> _getMapEntrySet(Map m) { | |
143 var result = new Set(); | |
144 m.forEach((k, v) { | |
145 result.add(new _MapEntry(k, v)); | |
146 }); | |
147 return result; | |
148 } | |
149 | |
150 | |
151 class _MapEntry<K, V> { | |
152 K _key; | |
153 V _value; | |
154 _MapEntry(this._key, this._value); | |
155 K getKey() => _key; | |
156 V getValue() => _value; | |
157 } | |
158 | |
159 | |
160 class _TestSource implements Source { | |
161 | |
162 bool operator == (Object object) => object is _TestSource; | |
163 | |
164 AnalysisContext get context => _unsupported(); | |
165 | |
166 void getContents(Source_ContentReceiver receiver) => _unsupported(); | |
167 | |
168 String get fullName => _unsupported(); | |
169 | |
170 String get shortName => _unsupported(); | |
171 | |
172 String get encoding => _unsupported(); | |
173 | |
174 int get modificationStamp =>_unsupported(); | |
175 | |
176 UriKind get uriKind => _unsupported(); | |
177 | |
178 bool exists() => true; | |
179 | |
180 bool get isInSystemLibrary => _unsupported(); | |
181 | |
182 Source resolve(String uri) => _unsupported(); | |
183 | |
184 Source resolveRelative(Uri uri) => _unsupported(); | |
185 | |
186 } | |
187 | |
188 | |
189 _unsupported() => throw new _UnsupportedOperationException(); | |
190 | |
191 class _UnsupportedOperationException implements Exception { | |
192 String toString() => 'UnsupportedOperationException'; | |
193 } | |
194 | |
195 | |
196 /// Parse the given [source] as a statement and assert, if provided, that | |
197 /// exactly a given set of [expectedErrorCodes] are encountered. | |
198 Statement parseStatement(String source, [List<ErrorCode> expectedErrorCodes]) { | |
199 | |
200 var listener = new _GatheringErrorListener(); | |
201 var reader = new CharSequenceReader(new CharSequence(source)); | |
202 var scanner = new Scanner(null, reader, listener); | |
203 listener.setLineInfo(new _TestSource(), scanner.lineStarts); | |
204 | |
205 var token = scanner.tokenize(); | |
206 var parser = new Parser(null, listener); | |
207 var statement = parser.parseStatement(token); | |
208 expect(statement, isNotNull); | |
209 | |
210 if (expectedErrorCodes != null) { | |
211 listener.expectErrors(expectedErrorCodes); | |
212 } | |
213 | |
214 return statement; | |
215 } | |
OLD | NEW |