OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library trydart.poi; | 5 library trydart.poi; |
6 | 6 |
7 import 'dart:async' show | 7 import 'dart:async' show |
8 Completer, | 8 Completer, |
9 Future, | 9 Future, |
10 Stream; | 10 Stream; |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 /// really need. | 93 /// really need. |
94 bool isVerbose = false; | 94 bool isVerbose = false; |
95 | 95 |
96 /// When true (the default value) print serialized scope information at the | 96 /// When true (the default value) print serialized scope information at the |
97 /// provided position. | 97 /// provided position. |
98 const bool PRINT_SCOPE_INFO = | 98 const bool PRINT_SCOPE_INFO = |
99 const bool.fromEnvironment('PRINT_SCOPE_INFO', defaultValue: true); | 99 const bool.fromEnvironment('PRINT_SCOPE_INFO', defaultValue: true); |
100 | 100 |
101 Stopwatch wallClock = new Stopwatch(); | 101 Stopwatch wallClock = new Stopwatch(); |
102 | 102 |
| 103 Compiler cachedCompiler; |
| 104 |
103 /// Iterator for reading lines from [io.stdin]. | 105 /// Iterator for reading lines from [io.stdin]. |
104 class StdinIterator implements Iterator<String> { | 106 class StdinIterator implements Iterator<String> { |
105 String current; | 107 String current; |
106 | 108 |
107 bool moveNext() { | 109 bool moveNext() { |
108 current = io.stdin.readLineSync(); | 110 current = io.stdin.readLineSync(); |
109 return true; | 111 return true; |
110 } | 112 } |
111 } | 113 } |
112 | 114 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
176 return prompt('Position: ').then((String position) { | 178 return prompt('Position: ').then((String position) { |
177 return parseUserInput(fileName, position, inputProvider, handler); | 179 return parseUserInput(fileName, position, inputProvider, handler); |
178 }); | 180 }); |
179 }); | 181 }); |
180 } | 182 } |
181 | 183 |
182 /// Create an input provider that implements the behavior documented at | 184 /// Create an input provider that implements the behavior documented at |
183 /// [simulateMutation]. | 185 /// [simulateMutation]. |
184 api.CompilerInputProvider simulateMutation( | 186 api.CompilerInputProvider simulateMutation( |
185 String fileName, | 187 String fileName, |
186 SourceFileProvider inputProvider) { | 188 api.CompilerInputProvider inputProvider) { |
187 Uri script = Uri.base.resolveUri(new Uri.file(fileName)); | 189 Uri script = Uri.base.resolveUri(new Uri.file(fileName)); |
188 int count = poiCount; | 190 int count = poiCount; |
189 Future cache; | 191 Future cache; |
190 String cachedFileName = script.toFilePath(); | 192 String cachedFileName = script.toFilePath(); |
191 int counter = ++globalCounter; | 193 int counter = ++globalCounter; |
192 return (Uri uri) { | 194 return (Uri uri) { |
193 if (counter != globalCounter) throw 'Using old provider'; | 195 if (counter != globalCounter) throw 'Using old provider'; |
194 printVerbose('fake inputProvider#$counter($uri): $poiCount $count'); | 196 printVerbose('fake inputProvider#$counter($uri): $poiCount $count'); |
195 if (uri == script) { | 197 if (uri == script) { |
196 if (poiCount == count) { | 198 if (poiCount == count) { |
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
259 wallClock.reset(); | 261 wallClock.reset(); |
260 return parseUserInput(fileName, positionString, inputProvider, handler); | 262 return parseUserInput(fileName, positionString, inputProvider, handler); |
261 }); | 263 }); |
262 } | 264 } |
263 | 265 |
264 printWallClock("\n\n\nparseUserInput('$fileName', '$positionString')"); | 266 printWallClock("\n\n\nparseUserInput('$fileName', '$positionString')"); |
265 | 267 |
266 Uri script = Uri.base.resolveUri(new Uri.file(fileName)); | 268 Uri script = Uri.base.resolveUri(new Uri.file(fileName)); |
267 if (positionString == null) return null; | 269 if (positionString == null) return null; |
268 int position = int.parse( | 270 int position = int.parse( |
269 positionString, onError: (_) => print('Please enter an integer.')); | 271 positionString, onError: (_) { print('Please enter an integer.'); }); |
270 if (position == null) return repeat(); | 272 if (position == null) return repeat(); |
271 | 273 |
272 inputProvider(script); | 274 inputProvider(script); |
273 if (isVerbose) { | 275 if (isVerbose) { |
274 handler( | 276 handler( |
275 script, position, position + 1, | 277 script, position, position + 1, |
276 'Point of interest. ' | 278 'Point of interest. ' |
277 'Cursor is immediately before highlighted character.', | 279 'Cursor is immediately before highlighted character.', |
278 api.Diagnostic.HINT); | 280 api.Diagnostic.HINT); |
279 } | 281 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
319 print("Didn't talk to Dart Mind, no identifier at POI ($token)."); | 321 print("Didn't talk to Dart Mind, no identifier at POI ($token)."); |
320 } | 322 } |
321 return repeat(); | 323 return repeat(); |
322 } | 324 } |
323 }); | 325 }); |
324 } | 326 } |
325 | 327 |
326 /// Find the token corresponding to [position] in [element]. The method only | 328 /// Find the token corresponding to [position] in [element]. The method only |
327 /// works for instances of [PartialElement] or [LibraryElement]. Support for | 329 /// works for instances of [PartialElement] or [LibraryElement]. Support for |
328 /// [LibraryElement] is currently limited, and works only for named libraries. | 330 /// [LibraryElement] is currently limited, and works only for named libraries. |
329 Token findToken(Element element, int position) { | 331 Token findToken(modelx.ElementX element, int position) { |
330 Token beginToken; | 332 Token beginToken; |
331 if (element is PartialElement) { | 333 if (element is PartialElement) { |
332 beginToken = element.beginToken; | 334 beginToken = (element as PartialElement).beginToken; |
333 } else if (element is PartialClassElement) { | 335 } else if (element is PartialClassElement) { |
334 beginToken = element.beginToken; | 336 beginToken = element.beginToken; |
335 } else if (element.isLibrary) { | 337 } else if (element.isLibrary) { |
336 // TODO(ahe): Generalize support for library elements (and update above | 338 // TODO(ahe): Generalize support for library elements (and update above |
337 // documentation). | 339 // documentation). |
338 LibraryElement lib = element; | 340 modelx.LibraryElementX lib = element; |
339 var tag = lib.libraryTag; | 341 var tag = lib.libraryTag; |
340 if (tag != null) { | 342 if (tag != null) { |
341 beginToken = tag.libraryKeyword; | 343 beginToken = tag.libraryKeyword; |
342 } | 344 } |
343 } else { | 345 } else { |
344 beginToken = element.position; | 346 beginToken = element.position; |
345 } | 347 } |
346 if (beginToken == null) return null; | 348 if (beginToken == null) return null; |
347 for (Token token = beginToken; token.kind != EOF_TOKEN; token = token.next) { | 349 for (Token token = beginToken; token.kind != EOF_TOKEN; token = token.next) { |
348 if (token.charOffset < position && position <= token.next.charOffset) { | 350 if (token.charOffset < position && position <= token.next.charOffset) { |
349 return token; | 351 return token; |
350 } | 352 } |
351 } | 353 } |
352 return null; | 354 return null; |
353 } | 355 } |
354 | 356 |
355 Compiler cachedCompiler; | |
356 | |
357 Future<Element> runPoi( | 357 Future<Element> runPoi( |
358 Uri script, int position, | 358 Uri script, |
| 359 int position, |
359 api.CompilerInputProvider inputProvider, | 360 api.CompilerInputProvider inputProvider, |
360 api.DiagnosticHandler handler) { | 361 api.DiagnosticHandler handler) { |
361 | |
362 Uri libraryRoot = Uri.base.resolve('sdk/'); | 362 Uri libraryRoot = Uri.base.resolve('sdk/'); |
363 Uri packageRoot = Uri.base.resolveUri( | 363 Uri packageRoot = Uri.base.resolveUri( |
364 new Uri.file('${Platform.packageRoot}/')); | 364 new Uri.file('${Platform.packageRoot}/')); |
365 | 365 |
366 var options = [ | 366 var options = [ |
367 '--analyze-main', | 367 '--analyze-main', |
368 '--analyze-only', | 368 '--analyze-only', |
369 '--no-source-maps', | 369 '--no-source-maps', |
370 '--verbose', | 370 '--verbose', |
371 '--categories=Client,Server', | 371 '--categories=Client,Server', |
372 '--incremental-support', | 372 '--incremental-support', |
373 '--disable-type-inference', | 373 '--disable-type-inference', |
374 ]; | 374 ]; |
375 | 375 |
376 cachedCompiler = reuseCompiler( | 376 return reuseCompiler( |
377 diagnosticHandler: handler, | 377 diagnosticHandler: handler, |
378 inputProvider: inputProvider, | 378 inputProvider: inputProvider, |
379 options: options, | 379 options: options, |
380 cachedCompiler: cachedCompiler, | 380 cachedCompiler: cachedCompiler, |
381 libraryRoot: libraryRoot, | 381 libraryRoot: libraryRoot, |
382 packageRoot: packageRoot, | 382 packageRoot: packageRoot, |
383 packagesAreImmutable: true); | 383 packagesAreImmutable: true).then((Compiler newCompiler) { |
| 384 var filter = new ScriptOnlyFilter(script); |
| 385 newCompiler.enqueuerFilter = filter; |
| 386 return runPoiInternal(newCompiler, script, position); |
| 387 }); |
| 388 } |
384 | 389 |
385 cachedCompiler.enqueuerFilter = new ScriptOnlyFilter(script); | 390 Future<Element> runPoiInternal( |
| 391 Compiler newCompiler, |
| 392 Uri uri, |
| 393 int position) { |
| 394 cachedCompiler = newCompiler; |
386 | 395 |
387 return cachedCompiler.run(script).then((success) { | 396 return cachedCompiler.run(uri).then((success) { |
388 if (success != true) { | 397 if (success != true) { |
389 throw 'Compilation failed'; | 398 throw 'Compilation failed'; |
390 } | 399 } |
391 return findPosition(position, cachedCompiler.mainApp); | 400 return findPosition(position, cachedCompiler.mainApp); |
392 }); | 401 }); |
393 } | 402 } |
394 | 403 |
395 Element findPosition(int position, Element element) { | 404 Element findPosition(int position, Element element) { |
396 FindPositionVisitor visitor = new FindPositionVisitor(position, element); | 405 FindPositionVisitor visitor = new FindPositionVisitor(position, element); |
397 element.accept(visitor); | 406 element.accept(visitor); |
398 return visitor.element; | 407 return visitor.element; |
399 } | 408 } |
400 | 409 |
401 String scopeInformation(Element element, int position) { | 410 String scopeInformation(Element element, int position) { |
402 ScopeInformationVisitor visitor = | 411 ScopeInformationVisitor visitor = |
403 new ScopeInformationVisitor(element, position); | 412 new ScopeInformationVisitor(element, position); |
404 element.accept(visitor); | 413 element.accept(visitor); |
405 return '${visitor.buffer}'; | 414 return '${visitor.buffer}'; |
406 } | 415 } |
407 | 416 |
408 class FindPositionVisitor extends ElementVisitor { | 417 class FindPositionVisitor extends ElementVisitor { |
409 final int position; | 418 final int position; |
410 Element element; | 419 Element element; |
411 | 420 |
412 FindPositionVisitor(this.position, this.element); | 421 FindPositionVisitor(this.position, this.element); |
413 | 422 |
414 visitElement(Element e) { | 423 visitElement(Element e) { |
415 if (e is PartialElement) { | 424 if (e is PartialElement) { |
416 if (e.beginToken.charOffset <= position && | 425 if ((e as PartialElement).beginToken.charOffset <= position && |
417 position < e.endToken.next.charOffset) { | 426 position < (e as PartialElement).endToken.next.charOffset) { |
418 element = e; | 427 element = e; |
419 } | 428 } |
420 } | 429 } |
421 } | 430 } |
422 | 431 |
423 visitClassElement(ClassElement e) { | 432 visitClassElement(ClassElement e) { |
424 if (e is PartialClassElement) { | 433 if (e is PartialClassElement) { |
425 if (e.beginToken.charOffset <= position && | 434 if (e.beginToken.charOffset <= position && |
426 position < e.endToken.next.charOffset) { | 435 position < e.endToken.next.charOffset) { |
427 element = e; | 436 element = e; |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
697 buffer.write('\n'); | 706 buffer.write('\n'); |
698 indented.write('}'); | 707 indented.write('}'); |
699 } | 708 } |
700 } | 709 } |
701 | 710 |
702 modelx.ScopeX localScope(modelx.LibraryElementX element) => element.localScope; | 711 modelx.ScopeX localScope(modelx.LibraryElementX element) => element.localScope; |
703 | 712 |
704 modelx.ImportScope importScope(modelx.LibraryElementX element) { | 713 modelx.ImportScope importScope(modelx.LibraryElementX element) { |
705 return element.importScope; | 714 return element.importScope; |
706 } | 715 } |
OLD | NEW |