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.span_test; | |
6 | |
7 import 'package:unittest/unittest.dart'; | |
8 import 'package:source_maps/span.dart'; | |
9 | |
10 const String TEST_FILE = ''' | |
11 +23456789_ | |
12 + _123456789_123456789_123456789_123456789_123456789_123456789_123456789_ | |
13 + _123456789_1 | |
14 123+56789_123456789_1234567 | |
15 1234+6789_1234 | |
16 12345+789_123456789_12345 | |
17 123456+89_123456789_123456789_123456789_123456789_123456789_123456789_123456789 | |
18 1234567+9_123456789_123456789_123456789_123456789_123456789_123456789_123 | |
19 12345678+_123456789_123456789_123456789_123456789_1 | |
20 123456789+123456789_123456789_12345678 | |
21 123456789_+23456789_123456789_123456789_123 | |
22 123456789_1+3456789_123456789 | |
23 '''; | |
24 | |
25 List<int> newLines = TEST_FILE.split('\n').map((s) => s.length).toList(); | |
26 | |
27 main() { | |
28 var file = new SourceFile.text('file', TEST_FILE); | |
29 span(int start, int end) => file.span(start, end); | |
30 loc(int offset) => file.location(offset); | |
31 | |
32 test('validate test input', () { | |
33 expect(newLines, | |
34 const [10, 80, 31, 27, 14, 25, 79, 73, 51, 38, 43, 29, 0]); | |
35 }); | |
36 | |
37 test('get line and column', () { | |
38 line(int n) => file.getLine(n); | |
39 col(int n) => file.getColumn(file.getLine(n), n); | |
40 | |
41 expect(line(8), 0); | |
42 expect(line(10), 0); | |
43 expect(line(11), 1); | |
44 expect(line(12), 1); | |
45 expect(line(91), 1); | |
46 expect(line(92), 2); | |
47 expect(line(93), 2); | |
48 expect(col(11), 0); | |
49 expect(col(12), 1); | |
50 expect(col(91), 80); | |
51 expect(col(92), 0); | |
52 expect(col(93), 1); | |
53 | |
54 int j = 0; | |
55 int lineOffset = 0; | |
56 for (int i = 0; i < TEST_FILE.length; i++) { | |
57 if (i > lineOffset + newLines[j]) { | |
58 lineOffset += newLines[j] + 1; | |
59 j++; | |
60 } | |
61 expect(line(i), j, reason: 'position: $i'); | |
62 expect(col(i), i - lineOffset, reason: 'position: $i'); | |
63 } | |
64 }); | |
65 | |
66 test('get text', () { | |
67 // fifth line (including 4 new lines), columns 2 .. 11 | |
68 var line = 10 + 80 + 31 + 27 + 4; | |
69 expect(file.getText(line + 2, line + 11), '34+6789_1'); | |
70 }); | |
71 | |
72 group('location message', () { | |
73 test('first line', () { | |
74 expect(file.getLocationMessage('the message', 1, 3), | |
75 'line 1, column 2 of file: the message\n' | |
76 '+23456789_\n' | |
77 ' ^^'); | |
78 }); | |
79 | |
80 test('in the middle of the file', () { | |
81 // fifth line (including 4 new lines), columns 2 .. 11 | |
82 var line = 10 + 80 + 31 + 27 + 4; | |
83 expect(file.getLocationMessage('the message', line + 2, line + 11), | |
84 'line 5, column 3 of file: the message\n' | |
85 '1234+6789_1234\n' | |
86 ' ^^^^^^^^^'); | |
87 }); | |
88 | |
89 test('no file url', () { | |
90 var line = 10 + 80 + 31 + 27 + 4; | |
91 expect(new SourceFile.text(null, TEST_FILE).getLocationMessage( | |
92 'the message', line + 2, line + 11), | |
93 'line 5, column 3: the message\n' | |
94 '1234+6789_1234\n' | |
95 ' ^^^^^^^^^'); | |
96 }); | |
97 | |
98 test('penultimate line', () { | |
99 // We search '\n' backwards twice because last line is \n terminated: | |
100 int index = TEST_FILE.lastIndexOf('\n'); | |
101 var start = TEST_FILE.lastIndexOf('\n', index - 1) - 3; | |
102 expect(file.getLocationMessage('the message', start, start + 2), | |
103 'line 11, column 41 of file: the message\n' | |
104 '123456789_+23456789_123456789_123456789_123\n' | |
105 ' ^^'); | |
106 }); | |
107 | |
108 test('last line', () { | |
109 var start = TEST_FILE.lastIndexOf('\n') - 2; | |
110 expect(file.getLocationMessage('the message', start, start + 1), | |
111 'line 12, column 28 of file: the message\n' | |
112 '123456789_1+3456789_123456789\n' | |
113 ' ^'); | |
114 }); | |
115 | |
116 group('no trailing empty-line at the end -', () { | |
117 var text = TEST_FILE.substring(0, TEST_FILE.length - 1); | |
118 var file2 = new SourceFile.text('file', text); | |
119 | |
120 test('penultimate line', () { | |
121 var start = text.lastIndexOf('\n') - 3; | |
122 expect(file2.getLocationMessage('the message', start, start + 2), | |
123 'line 11, column 41 of file: the message\n' | |
124 '123456789_+23456789_123456789_123456789_123\n' | |
125 ' ^^'); | |
126 }); | |
127 | |
128 test('last line', () { | |
129 var start = text.length - 2; | |
130 expect(file2.getLocationMessage('the message', start, start + 1), | |
131 'line 12, column 28 of file: the message\n' | |
132 '123456789_1+3456789_123456789\n' | |
133 ' ^'); | |
134 }); | |
135 }); | |
136 | |
137 test('single line', () { | |
138 var text = "this is a single line"; | |
139 int start = text.indexOf(' ') + 1; | |
140 var file2 = new SourceFile.text('file', text); | |
141 expect(file2.getLocationMessage('the message', start, start + 2), | |
142 'line 1, column ${start + 1} of file: the message\n' | |
143 'this is a single line\n' | |
144 ' ^^'); | |
145 }); | |
146 }); | |
147 | |
148 test('location getters', () { | |
149 expect(loc(8).line, 0); | |
150 expect(loc(8).column, 8); | |
151 expect(loc(9).line, 0); | |
152 expect(loc(9).column, 9); | |
153 expect(loc(8).formatString, 'file:1:9'); | |
154 expect(loc(12).line, 1); | |
155 expect(loc(12).column, 1); | |
156 expect(loc(95).line, 2); | |
157 expect(loc(95).column, 3); | |
158 }); | |
159 | |
160 test('location compare', () { | |
161 var list = [9, 8, 11, 14, 6, 6, 1, 1].map((n) => loc(n)).toList(); | |
162 list.sort(); | |
163 var lastOffset = 0; | |
164 for (var location in list) { | |
165 expect(location.offset, greaterThanOrEqualTo(lastOffset)); | |
166 lastOffset = location.offset; | |
167 } | |
168 }); | |
169 | |
170 test('span getters', () { | |
171 expect(span(8, 9).start.line, 0); | |
172 expect(span(8, 9).start.column, 8); | |
173 expect(span(8, 9).end.line, 0); | |
174 expect(span(8, 9).end.column, 9); | |
175 expect(span(8, 9).text, '9'); | |
176 expect(span(8, 9).isIdentifier, false); | |
177 expect(span(8, 9).formatLocation, 'file:1:9'); | |
178 | |
179 var line = 10 + 80 + 31 + 27 + 4; | |
180 expect(span(line + 2, line + 11).getLocationMessage('the message'), | |
181 'line 5, column 3 of file: the message\n' | |
182 '1234+6789_1234\n' | |
183 ' ^^^^^^^^^'); | |
184 | |
185 expect(span(12, 95).start.line, 1); | |
186 expect(span(12, 95).start.column, 1); | |
187 expect(span(12, 95).end.line, 2); | |
188 expect(span(12, 95).end.column, 3); | |
189 expect(span(12, 95).text, | |
190 '+ _123456789_123456789_123456789_123456789_123456789_1234567' | |
191 '89_123456789_\n +'); | |
192 expect(span(12, 95).formatLocation, 'file:2:2'); | |
193 }); | |
194 | |
195 test('span union', () { | |
196 var union = new FileSpan.union(span(8, 9), span(12, 95)); | |
197 expect(union.start.offset, 8); | |
198 expect(union.start.line, 0); | |
199 expect(union.start.column, 8); | |
200 expect(union.end.offset, 95); | |
201 expect(union.end.line, 2); | |
202 expect(union.end.column, 3); | |
203 expect(union.text, | |
204 '9_\n' | |
205 ' + _123456789_123456789_123456789_123456789_123456789_' | |
206 '123456789_123456789_\n +'); | |
207 expect(union.formatLocation, 'file:1:9'); | |
208 }); | |
209 | |
210 test('span compare', () { | |
211 var list = [span(9, 10), span(8, 9), span(11, 12), span(14, 19), | |
212 span(6, 12), span(6, 8), span(1, 9), span(1, 2)]; | |
213 list.sort(); | |
214 var lastStart = 0; | |
215 var lastEnd = 0; | |
216 for (var span in list) { | |
217 expect(span.start.offset, greaterThanOrEqualTo(lastStart)); | |
218 if (span.start.offset == lastStart) { | |
219 expect(span.end.offset, greaterThanOrEqualTo(lastEnd)); | |
220 } | |
221 lastStart = span.start.offset; | |
222 lastEnd = span.end.offset; | |
223 } | |
224 }); | |
225 | |
226 test('range check for large offsets', () { | |
227 var start = TEST_FILE.length; | |
228 expect(file.getLocationMessage('the message', start, start + 9), | |
229 'line 13, column 1 of file: the message\n'); | |
230 }); | |
231 | |
232 group('file segment', () { | |
233 var baseOffset = 123; | |
234 var segmentText = TEST_FILE.substring(baseOffset, TEST_FILE.length - 100); | |
235 var segment = new SourceFileSegment('file', segmentText, loc(baseOffset)); | |
236 sline(int n) => segment.getLine(n); | |
237 scol(int n) => segment.getColumn(segment.getLine(n), n); | |
238 line(int n) => file.getLine(n); | |
239 col(int n) => file.getColumn(file.getLine(n), n); | |
240 | |
241 test('get line and column', () { | |
242 int j = 0; | |
243 int lineOffset = 0; | |
244 for (int i = baseOffset; i < segmentText.length; i++) { | |
245 if (i > lineOffset + newLines[j]) { | |
246 lineOffset += newLines[j] + 1; | |
247 j++; | |
248 } | |
249 expect(segment.location(i - baseOffset).offset, i); | |
250 expect(segment.location(i - baseOffset).line, line(i)); | |
251 expect(segment.location(i - baseOffset).column, col(i)); | |
252 expect(segment.span(i - baseOffset).start.offset, i); | |
253 expect(segment.span(i - baseOffset).start.line, line(i)); | |
254 expect(segment.span(i - baseOffset).start.column, col(i)); | |
255 | |
256 expect(sline(i), line(i)); | |
257 expect(scol(i), col(i)); | |
258 } | |
259 }); | |
260 | |
261 test('get text', () { | |
262 var start = 10 + 80 + 31 + 27 + 4 + 2; | |
263 expect(segment.getText(start, start + 9), file.getText(start, start + 9)); | |
264 }); | |
265 | |
266 group('location message', () { | |
267 test('first line', () { | |
268 var start = baseOffset + 7; | |
269 expect(segment.getLocationMessage('the message', start, start + 2), | |
270 file.getLocationMessage('the message', start, start + 2)); | |
271 }); | |
272 | |
273 test('in a middle line', () { | |
274 // Example from another test above: | |
275 var start = 10 + 80 + 31 + 27 + 4 + 2; | |
276 expect(segment.getLocationMessage('the message', start, start + 9), | |
277 file.getLocationMessage('the message', start, start + 9)); | |
278 }); | |
279 | |
280 test('last segment line', () { | |
281 var start = segmentText.length - 4; | |
282 expect(segment.getLocationMessage('the message', start, start + 2), | |
283 file.getLocationMessage('the message', start, start + 2)); | |
284 }); | |
285 | |
286 test('past segment, same as last segment line', () { | |
287 var start = segmentText.length; | |
288 expect(segment.getLocationMessage('the message', start, start + 2), | |
289 file.getLocationMessage('the message', start, start + 2)); | |
290 | |
291 start = segmentText.length + 20; | |
292 expect(segment.getLocationMessage('the message', start, start + 2), | |
293 file.getLocationMessage('the message', start, start + 2)); | |
294 }); | |
295 | |
296 test('past segment, past its line', () { | |
297 var start = TEST_FILE.length - 2; | |
298 expect(file.getLocationMessage('the message', start, start + 1), | |
299 'line 12, column 29 of file: the message\n' | |
300 '123456789_1+3456789_123456789\n' | |
301 ' ^'); | |
302 | |
303 // The answer below is different because the segment parsing only knows | |
304 // about the 10 lines it has (and nothing about the possible extra lines | |
305 // afterwards) | |
306 expect(segment.getLocationMessage('the message', start, start + 1), | |
307 'line 11, column 1 of file: the message\n'); | |
308 }); | |
309 }); | |
310 }); | |
311 | |
312 test('span isIdentifier defaults to false', () { | |
313 var start = new TestLocation(0); | |
314 var end = new TestLocation(1); | |
315 expect(new TestSpan(start, end).isIdentifier, false); | |
316 expect(file.span(8, 9, null).isIdentifier, false); | |
317 expect(new FixedSpan('', 8, 1, 8, isIdentifier: null).isIdentifier, false); | |
318 }); | |
319 | |
320 test('span/location implement == and hashCode', () { | |
321 expect(identical(span(10, 14), span(10, 14)), isFalse); | |
322 expect(span(10, 14), equals(span(10, 14))); | |
323 expect(span(10, 14).hashCode, span(10, 14).hashCode); | |
324 | |
325 expect(identical(loc(13), loc(13)), isFalse); | |
326 expect(loc(13), equals(loc(13))); | |
327 expect(loc(13).hashCode, loc(13).hashCode); | |
328 }); | |
329 } | |
330 | |
331 class TestSpan extends Span { | |
332 TestSpan(Location start, Location end) : super(start, end, null); | |
333 get text => null; | |
334 } | |
335 | |
336 class TestLocation extends Location { | |
337 String get sourceUrl => ''; | |
338 TestLocation(int offset) : super(offset); | |
339 get line => 0; | |
340 get column => 0; | |
341 } | |
OLD | NEW |