| OLD | NEW | 
|---|
| 1 // Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 import 'dart:async'; | 5 import 'dart:async'; | 
| 6 import 'dart:collection'; | 6 import 'dart:collection'; | 
| 7 import 'dart:convert'; | 7 import 'dart:convert'; | 
| 8 | 8 | 
| 9 import 'package:analyzer/dart/ast/ast.dart'; | 9 import 'package:analyzer/dart/ast/ast.dart'; | 
| 10 import 'package:analyzer/dart/ast/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; | 
| (...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 159   /** | 159   /** | 
| 160    * Mapping from library URIs to the dependency signature of the library. | 160    * Mapping from library URIs to the dependency signature of the library. | 
| 161    */ | 161    */ | 
| 162   final _dependencySignatureMap = <Uri, String>{}; | 162   final _dependencySignatureMap = <Uri, String>{}; | 
| 163 | 163 | 
| 164   /** | 164   /** | 
| 165    * The monitor that is signalled when there is work to do. | 165    * The monitor that is signalled when there is work to do. | 
| 166    */ | 166    */ | 
| 167   final _Monitor _hasWork = new _Monitor(); | 167   final _Monitor _hasWork = new _Monitor(); | 
| 168 | 168 | 
|  | 169   /** | 
|  | 170    * The controller for the [status] stream. | 
|  | 171    */ | 
|  | 172   final _statusController = new StreamController<AnalysisStatus>(); | 
|  | 173 | 
|  | 174   /** | 
|  | 175    * The last status sent to the [status] stream. | 
|  | 176    */ | 
|  | 177   AnalysisStatus _currentStatus = AnalysisStatus.IDLE; | 
|  | 178 | 
| 169   AnalysisDriver(this._logger, this._resourceProvider, this._byteStore, | 179   AnalysisDriver(this._logger, this._resourceProvider, this._byteStore, | 
| 170       this._contentCache, this._sourceFactory, this._analysisOptions) { | 180       this._contentCache, this._sourceFactory, this._analysisOptions) { | 
| 171     _sdkBundle = _sourceFactory.dartSdk.getLinkedBundle(); | 181     _sdkBundle = _sourceFactory.dartSdk.getLinkedBundle(); | 
| 172   } | 182   } | 
| 173 | 183 | 
| 174   /** | 184   /** | 
| 175    * Set the list of files that the driver should try to analyze sooner. | 185    * Set the list of files that the driver should try to analyze sooner. | 
| 176    * | 186    * | 
| 177    * Every path in the list must be absolute and normalized. | 187    * Every path in the list must be absolute and normalized. | 
| 178    * | 188    * | 
| 179    * The driver will produce the results through the [results] stream. The | 189    * The driver will produce the results through the [results] stream. The | 
| 180    * exact order in which results are produced is not defined, neither | 190    * exact order in which results are produced is not defined, neither | 
| 181    * between priority files, nor between priority and non-priority files. | 191    * between priority files, nor between priority and non-priority files. | 
| 182    */ | 192    */ | 
| 183   void set priorityFiles(List<String> priorityPaths) { | 193   void set priorityFiles(List<String> priorityPaths) { | 
| 184     _priorityFiles.clear(); | 194     _priorityFiles.clear(); | 
| 185     _priorityFiles.addAll(priorityPaths); | 195     _priorityFiles.addAll(priorityPaths); | 
|  | 196     _transitionToAnalyzing(); | 
| 186     _hasWork.notify(); | 197     _hasWork.notify(); | 
| 187   } | 198   } | 
| 188 | 199 | 
| 189   /** | 200   /** | 
| 190    * Return the [Stream] that produces [AnalysisResult]s for added files. | 201    * Return the [Stream] that produces [AnalysisResult]s for added files. | 
| 191    * | 202    * | 
| 192    * Analysis starts when the client starts listening to the stream, and stops | 203    * Analysis starts when the client starts listening to the stream, and stops | 
| 193    * when the client cancels the subscription. | 204    * when the client cancels the subscription. | 
| 194    * | 205    * | 
| 195    * When the client starts listening, the analysis state transitions to | 206    * When the client starts listening, the analysis state transitions to | 
| (...skipping 11 matching lines...) Expand all  Loading... | 
| 207    * | 218    * | 
| 208    * Results might be produced even for files that have never been added | 219    * Results might be produced even for files that have never been added | 
| 209    * using [addFile], for example when [getResult] was called for a file. | 220    * using [addFile], for example when [getResult] was called for a file. | 
| 210    */ | 221    */ | 
| 211   Stream<AnalysisResult> get results async* { | 222   Stream<AnalysisResult> get results async* { | 
| 212     try { | 223     try { | 
| 213       PerformanceLogSection analysisSection = null; | 224       PerformanceLogSection analysisSection = null; | 
| 214       while (true) { | 225       while (true) { | 
| 215         await _hasWork.signal; | 226         await _hasWork.signal; | 
| 216 | 227 | 
| 217         // TODO(scheglov) implement state transitioning |  | 
| 218         if (analysisSection == null) { | 228         if (analysisSection == null) { | 
| 219           analysisSection = _logger.enter('Analyzing'); | 229           analysisSection = _logger.enter('Analyzing'); | 
| 220         } | 230         } | 
| 221 | 231 | 
| 222         // Verify all changed files one at a time. | 232         // Verify all changed files one at a time. | 
| 223         if (_changedFiles.isNotEmpty) { | 233         if (_changedFiles.isNotEmpty) { | 
| 224           String path = _removeFirst(_changedFiles); | 234           String path = _removeFirst(_changedFiles); | 
| 225           _verifyApiSignatureOfChangedFile(path); | 235           _verifyApiSignatureOfChangedFile(path); | 
| 226           // Repeat the processing loop. | 236           // Repeat the processing loop. | 
| 227           _hasWork.notify(); | 237           _hasWork.notify(); | 
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 265           AnalysisResult result = _computeAnalysisResult(path, withUnit: false); | 275           AnalysisResult result = _computeAnalysisResult(path, withUnit: false); | 
| 266           yield result; | 276           yield result; | 
| 267           // Repeat the processing loop. | 277           // Repeat the processing loop. | 
| 268           _hasWork.notify(); | 278           _hasWork.notify(); | 
| 269           continue; | 279           continue; | 
| 270         } | 280         } | 
| 271 | 281 | 
| 272         // There is nothing to do. | 282         // There is nothing to do. | 
| 273         analysisSection.exit(); | 283         analysisSection.exit(); | 
| 274         analysisSection = null; | 284         analysisSection = null; | 
|  | 285         _transitionToIdle(); | 
| 275       } | 286       } | 
| 276     } finally { | 287     } finally { | 
| 277       print('The stream was cancelled.'); | 288       print('The stream was cancelled.'); | 
| 278     } | 289     } | 
| 279   } | 290   } | 
| 280 | 291 | 
| 281   /** | 292   /** | 
|  | 293    * Return the stream that produces [AnalysisStatus] events. | 
|  | 294    */ | 
|  | 295   Stream<AnalysisStatus> get status => _statusController.stream; | 
|  | 296 | 
|  | 297   /** | 
| 282    * Add the file with the given [path] to the set of files to analyze. | 298    * Add the file with the given [path] to the set of files to analyze. | 
| 283    * | 299    * | 
| 284    * The [path] must be absolute and normalized. | 300    * The [path] must be absolute and normalized. | 
| 285    * | 301    * | 
| 286    * The results of analysis are eventually produced by the [results] stream. | 302    * The results of analysis are eventually produced by the [results] stream. | 
| 287    */ | 303    */ | 
| 288   void addFile(String path) { | 304   void addFile(String path) { | 
| 289     _explicitFiles.add(path); | 305     _explicitFiles.add(path); | 
| 290     _filesToAnalyze.add(path); | 306     _filesToAnalyze.add(path); | 
|  | 307     _transitionToAnalyzing(); | 
| 291     _hasWork.notify(); | 308     _hasWork.notify(); | 
| 292   } | 309   } | 
| 293 | 310 | 
| 294   /** | 311   /** | 
| 295    * The file with the given [path] might have changed - updated, added or | 312    * The file with the given [path] might have changed - updated, added or | 
| 296    * removed. Or not, we don't know. Or it might have, but then changed back. | 313    * removed. Or not, we don't know. Or it might have, but then changed back. | 
| 297    * | 314    * | 
| 298    * The [path] must be absolute and normalized. | 315    * The [path] must be absolute and normalized. | 
| 299    * | 316    * | 
| 300    * The [path] can be any file - explicitly or implicitly analyzed, or neither. | 317    * The [path] can be any file - explicitly or implicitly analyzed, or neither. | 
| 301    * | 318    * | 
| 302    * Causes the analysis state to transition to "analyzing" (if it is not in | 319    * Causes the analysis state to transition to "analyzing" (if it is not in | 
| 303    * that state already). Schedules the file contents for [path] to be read | 320    * that state already). Schedules the file contents for [path] to be read | 
| 304    * into the current file state prior to the next time the analysis state | 321    * into the current file state prior to the next time the analysis state | 
| 305    * transitions to "idle". | 322    * transitions to "idle". | 
| 306    * | 323    * | 
| 307    * Invocation of this method will not prevent a [Future] returned from | 324    * Invocation of this method will not prevent a [Future] returned from | 
| 308    * [getResult] from completing with a result, but the result is not | 325    * [getResult] from completing with a result, but the result is not | 
| 309    * guaranteed to be consistent with the new current file state after this | 326    * guaranteed to be consistent with the new current file state after this | 
| 310    * [changeFile] invocation. | 327    * [changeFile] invocation. | 
| 311    */ | 328    */ | 
| 312   void changeFile(String path) { | 329   void changeFile(String path) { | 
| 313     _changedFiles.add(path); | 330     _changedFiles.add(path); | 
| 314     _filesToAnalyze.add(path); | 331     _filesToAnalyze.add(path); | 
|  | 332     _transitionToAnalyzing(); | 
| 315     _hasWork.notify(); | 333     _hasWork.notify(); | 
| 316   } | 334   } | 
| 317 | 335 | 
| 318   /** | 336   /** | 
| 319    * Return the [Future] that completes with a [AnalysisResult] for the file | 337    * Return the [Future] that completes with a [AnalysisResult] for the file | 
| 320    * with the given [path]. | 338    * with the given [path]. | 
| 321    * | 339    * | 
| 322    * The [path] must be absolute and normalized. | 340    * The [path] must be absolute and normalized. | 
| 323    * | 341    * | 
| 324    * The [path] can be any file - explicitly or implicitly analyzed, or neither. | 342    * The [path] can be any file - explicitly or implicitly analyzed, or neither. | 
| 325    * | 343    * | 
| 326    * Causes the analysis state to transition to "analyzing" (if it is not in | 344    * Causes the analysis state to transition to "analyzing" (if it is not in | 
| 327    * that state already), the driver will read the file and produce the analysis | 345    * that state already), the driver will read the file and produce the analysis | 
| 328    * result for it, which is consistent with the current file state (including | 346    * result for it, which is consistent with the current file state (including | 
| 329    * the new state of the file), prior to the next time the analysis state | 347    * the new state of the file), prior to the next time the analysis state | 
| 330    * transitions to "idle". | 348    * transitions to "idle". | 
| 331    */ | 349    */ | 
| 332   Future<AnalysisResult> getResult(String path) { | 350   Future<AnalysisResult> getResult(String path) { | 
| 333     var completer = new Completer<AnalysisResult>(); | 351     var completer = new Completer<AnalysisResult>(); | 
| 334     _requestedFiles | 352     _requestedFiles | 
| 335         .putIfAbsent(path, () => <Completer<AnalysisResult>>[]) | 353         .putIfAbsent(path, () => <Completer<AnalysisResult>>[]) | 
| 336         .add(completer); | 354         .add(completer); | 
|  | 355     _transitionToAnalyzing(); | 
| 337     _hasWork.notify(); | 356     _hasWork.notify(); | 
| 338     return completer.future; | 357     return completer.future; | 
| 339   } | 358   } | 
| 340 | 359 | 
| 341   /** | 360   /** | 
| 342    * Remove the file with the given [path] from the list of files to analyze. | 361    * Remove the file with the given [path] from the list of files to analyze. | 
| 343    * | 362    * | 
| 344    * The [path] must be absolute and normalized. | 363    * The [path] must be absolute and normalized. | 
| 345    * | 364    * | 
| 346    * The results of analysis of the file might still be produced by the | 365    * The results of analysis of the file might still be produced by the | 
| (...skipping 266 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 613   /** | 632   /** | 
| 614    * Return the [Source] for the given [path] in [_sourceFactory]. | 633    * Return the [Source] for the given [path] in [_sourceFactory]. | 
| 615    */ | 634    */ | 
| 616   Source _sourceForPath(String path) { | 635   Source _sourceForPath(String path) { | 
| 617     Source fileSource = _resourceProvider.getFile(path).createSource(); | 636     Source fileSource = _resourceProvider.getFile(path).createSource(); | 
| 618     Uri uri = _sourceFactory.restoreUri(fileSource); | 637     Uri uri = _sourceFactory.restoreUri(fileSource); | 
| 619     return _resourceProvider.getFile(path).createSource(uri); | 638     return _resourceProvider.getFile(path).createSource(uri); | 
| 620   } | 639   } | 
| 621 | 640 | 
| 622   /** | 641   /** | 
|  | 642    * Send a notifications to the [status] stream that the driver started | 
|  | 643    * analyzing. | 
|  | 644    */ | 
|  | 645   void _transitionToAnalyzing() { | 
|  | 646     if (_currentStatus != AnalysisStatus.ANALYZING) { | 
|  | 647       _currentStatus = AnalysisStatus.ANALYZING; | 
|  | 648       _statusController.add(AnalysisStatus.ANALYZING); | 
|  | 649     } | 
|  | 650   } | 
|  | 651 | 
|  | 652   /** | 
|  | 653    * Send a notifications to the [status] stream that the driver is idle. | 
|  | 654    */ | 
|  | 655   void _transitionToIdle() { | 
|  | 656     if (_currentStatus != AnalysisStatus.IDLE) { | 
|  | 657       _currentStatus = AnalysisStatus.IDLE; | 
|  | 658       _statusController.add(AnalysisStatus.IDLE); | 
|  | 659     } | 
|  | 660   } | 
|  | 661 | 
|  | 662   /** | 
| 623    * Verify the API signature for the file with the given [path], and decide | 663    * Verify the API signature for the file with the given [path], and decide | 
| 624    * which linked libraries should be invalidated, and files reanalyzed. | 664    * which linked libraries should be invalidated, and files reanalyzed. | 
| 625    * | 665    * | 
| 626    * TODO(scheglov) I see that adding a local var changes (full) API signature. | 666    * TODO(scheglov) I see that adding a local var changes (full) API signature. | 
| 627    */ | 667    */ | 
| 628   void _verifyApiSignatureOfChangedFile(String path) { | 668   void _verifyApiSignatureOfChangedFile(String path) { | 
| 629     _logger.run('Verify API signature of $path', () { | 669     _logger.run('Verify API signature of $path', () { | 
| 630       String oldSignature = _fileApiSignatureMap[path]; | 670       String oldSignature = _fileApiSignatureMap[path]; | 
| 631       // Compute the new API signature. | 671       // Compute the new API signature. | 
| 632       // _File.forResolution() also updates the content hash in the cache. | 672       // _File.forResolution() also updates the content hash in the cache. | 
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 697   /** | 737   /** | 
| 698    * The full list of computed analysis errors, both syntactic and semantic. | 738    * The full list of computed analysis errors, both syntactic and semantic. | 
| 699    */ | 739    */ | 
| 700   final List<AnalysisError> errors; | 740   final List<AnalysisError> errors; | 
| 701 | 741 | 
| 702   AnalysisResult(this.path, this.uri, this.content, this.contentHash, this.unit, | 742   AnalysisResult(this.path, this.uri, this.content, this.contentHash, this.unit, | 
| 703       this.errors); | 743       this.errors); | 
| 704 } | 744 } | 
| 705 | 745 | 
| 706 /** | 746 /** | 
|  | 747  * The status of [AnalysisDriver] | 
|  | 748  */ | 
|  | 749 class AnalysisStatus { | 
|  | 750   static const IDLE = const AnalysisStatus._(false); | 
|  | 751   static const ANALYZING = const AnalysisStatus._(true); | 
|  | 752 | 
|  | 753   final bool _analyzing; | 
|  | 754 | 
|  | 755   const AnalysisStatus._(this._analyzing); | 
|  | 756 | 
|  | 757   /** | 
|  | 758    * Return `true` is the driver is analyzing. | 
|  | 759    */ | 
|  | 760   bool get isAnalyzing => _analyzing; | 
|  | 761 | 
|  | 762   /** | 
|  | 763    * Return `true` is the driver is idle. | 
|  | 764    */ | 
|  | 765   bool get isIdle => !_analyzing; | 
|  | 766 } | 
|  | 767 | 
|  | 768 /** | 
| 707  * This class is used to gather and print performance information. | 769  * This class is used to gather and print performance information. | 
| 708  */ | 770  */ | 
| 709 class PerformanceLog { | 771 class PerformanceLog { | 
| 710   final StringSink sink; | 772   final StringSink sink; | 
| 711   int _level = 0; | 773   int _level = 0; | 
| 712 | 774 | 
| 713   PerformanceLog(this.sink); | 775   PerformanceLog(this.sink); | 
| 714 | 776 | 
| 715   /** | 777   /** | 
| 716    * Enter a new execution section, which starts at one point of code, runs | 778    * Enter a new execution section, which starts at one point of code, runs | 
| (...skipping 395 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 1112       } | 1174       } | 
| 1113     } | 1175     } | 
| 1114     for (UnlinkedExportPublic export in unit.publicNamespace.exports) { | 1176     for (UnlinkedExportPublic export in unit.publicNamespace.exports) { | 
| 1115       referenced.exported.add(export.uri); | 1177       referenced.exported.add(export.uri); | 
| 1116     } | 1178     } | 
| 1117     return referenced; | 1179     return referenced; | 
| 1118   } | 1180   } | 
| 1119 | 1181 | 
| 1120   _ReferencedUris._(); | 1182   _ReferencedUris._(); | 
| 1121 } | 1183 } | 
| OLD | NEW | 
|---|