| 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 |