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