Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(413)

Side by Side Diff: pkg/analyzer/lib/src/dart/analysis/driver.dart

Issue 2446803003: Actually compute AnalysisResult(s). (Closed)
Patch Set: Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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';
11 import 'package:analyzer/error/error.dart'; 11 import 'package:analyzer/error/error.dart';
12 import 'package:analyzer/error/listener.dart'; 12 import 'package:analyzer/error/listener.dart';
13 import 'package:analyzer/file_system/file_system.dart'; 13 import 'package:analyzer/file_system/file_system.dart';
14 import 'package:analyzer/src/context/context.dart'; 14 import 'package:analyzer/src/context/context.dart';
15 import 'package:analyzer/src/context/source.dart'; 15 import 'package:analyzer/src/context/source.dart';
16 import 'package:analyzer/src/dart/analysis/byte_store.dart'; 16 import 'package:analyzer/src/dart/analysis/byte_store.dart';
17 import 'package:analyzer/src/dart/error/todo_codes.dart';
18 import 'package:analyzer/src/dart/scanner/reader.dart'; 17 import 'package:analyzer/src/dart/scanner/reader.dart';
19 import 'package:analyzer/src/dart/scanner/scanner.dart'; 18 import 'package:analyzer/src/dart/scanner/scanner.dart';
20 import 'package:analyzer/src/generated/engine.dart' 19 import 'package:analyzer/src/generated/engine.dart'
21 show AnalysisContext, AnalysisEngine, AnalysisOptions, ChangeSet; 20 show AnalysisContext, AnalysisEngine, AnalysisOptions, ChangeSet;
22 import 'package:analyzer/src/generated/parser.dart'; 21 import 'package:analyzer/src/generated/parser.dart';
23 import 'package:analyzer/src/generated/source.dart'; 22 import 'package:analyzer/src/generated/source.dart';
24 import 'package:analyzer/src/generated/utilities_dart.dart'; 23 import 'package:analyzer/src/generated/utilities_dart.dart';
25 import 'package:analyzer/src/summary/api_signature.dart'; 24 import 'package:analyzer/src/summary/api_signature.dart';
26 import 'package:analyzer/src/summary/flat_buffers.dart' as fb;
27 import 'package:analyzer/src/summary/format.dart'; 25 import 'package:analyzer/src/summary/format.dart';
28 import 'package:analyzer/src/summary/idl.dart'; 26 import 'package:analyzer/src/summary/idl.dart';
29 import 'package:analyzer/src/summary/link.dart'; 27 import 'package:analyzer/src/summary/link.dart';
30 import 'package:analyzer/src/summary/package_bundle_reader.dart'; 28 import 'package:analyzer/src/summary/package_bundle_reader.dart';
31 import 'package:analyzer/src/summary/summarize_ast.dart'; 29 import 'package:analyzer/src/summary/summarize_ast.dart';
32 import 'package:analyzer/src/summary/summarize_elements.dart'; 30 import 'package:analyzer/src/summary/summarize_elements.dart';
33 import 'package:analyzer/src/util/fast_uri.dart'; 31 import 'package:analyzer/src/util/fast_uri.dart';
34 import 'package:convert/convert.dart'; 32 import 'package:convert/convert.dart';
35 import 'package:crypto/crypto.dart'; 33 import 'package:crypto/crypto.dart';
36 34
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
178 /** 176 /**
179 * Return the [Stream] that produces [AnalysisResult]s for added files. 177 * Return the [Stream] that produces [AnalysisResult]s for added files.
180 * 178 *
181 * Analysis starts when the client starts listening to the stream, and stops 179 * Analysis starts when the client starts listening to the stream, and stops
182 * when the client cancels the subscription. 180 * when the client cancels the subscription.
183 * 181 *
184 * When the client starts listening, the analysis state transitions to 182 * When the client starts listening, the analysis state transitions to
185 * "analyzing" and an analysis result is produced for every added file prior 183 * "analyzing" and an analysis result is produced for every added file prior
186 * to the next time the analysis state transitions to "idle". 184 * to the next time the analysis state transitions to "idle".
187 * 185 *
188 * Invocation of [addFile] or [changeFile] might result in producing more 186 * At least one analysis result is produced for every file passed to
189 * analysis results that reflect the new current file state. 187 * [addFile] or [changeFile] prior to the next time the analysis state
188 * transitions to "idle". Analysis results for other files are produced
189 * only if the changes affect analysis results of other files.
190 * 190 *
191 * More than one result might be produced for the same file, even if the 191 * More than one result might be produced for the same file, even if the
192 * client does not change the state of the files. 192 * client does not change the state of the files.
193 * 193 *
194 * Results might be produced even for files that have never been added 194 * Results might be produced even for files that have never been added
195 * using [addFile], for example when [getResult] was called for a file. 195 * using [addFile], for example when [getResult] was called for a file.
196 */ 196 */
197 Stream<AnalysisResult> get results async* { 197 Stream<AnalysisResult> get results async* {
198 try { 198 try {
199 while (true) { 199 while (true) {
200 // TODO(scheglov) implement state transitioning 200 // TODO(scheglov) implement state transitioning
201 await for (String why in _hasWorkStreamController.stream) { 201 await for (String why in _hasWorkStreamController.stream) {
202 _verifyUnlinkedSignatureOfChangedFiles(); 202 _verifyUnlinkedSignatureOfChangedFiles();
203 203
204 // Analyze the first file in the general queue. 204 // Analyze the first file in the general queue.
205 if (_filesToAnalyze.isNotEmpty) { 205 if (_filesToAnalyze.isNotEmpty) {
206 _logger.run('Analyze ${_filesToAnalyze.length} files', () { 206 PerformanceLogSection analysisSection =
207 _logger.enter('Analyze ${_filesToAnalyze.length} files');
208 try {
209 // TODO(scheglov) The loop is strange for now.
Brian Wilkerson 2016/10/26 06:45:03 Describe what needs to be done to fix the strangen
207 while (_filesToAnalyze.isNotEmpty) { 210 while (_filesToAnalyze.isNotEmpty) {
208 String path = _filesToAnalyze.first; 211 String path = _filesToAnalyze.first;
209 _filesToAnalyze.remove(path); 212 _filesToAnalyze.remove(path);
210 _File file = _fileForPath(path); 213 _File file = _fileForPath(path);
211 _computeAndPrintErrors(file); 214 AnalysisResult result = _computeAnalysisResult(file);
212 // TODO(scheglov) yield the result 215 yield result;
213 } 216 }
214 }); 217 } finally {
218 analysisSection.exit();
219 }
215 } 220 }
216 } 221 }
217 // TODO(scheglov) implement 222 // TODO(scheglov) implement
218 } 223 }
219 } finally { 224 } finally {
220 print('The stream was cancelled.'); 225 print('The stream was cancelled.');
221 } 226 }
222 } 227 }
223 228
224 /** 229 /**
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
311 * add [UnlinkedUnit] with wrong URI. 316 * add [UnlinkedUnit] with wrong URI.
312 * 317 *
313 * We need to clean this up. 318 * We need to clean this up.
314 */ 319 */
315 void _addToStoreUnlinked( 320 void _addToStoreUnlinked(
316 SummaryDataStore store, String uri, UnlinkedUnit unlinked) { 321 SummaryDataStore store, String uri, UnlinkedUnit unlinked) {
317 store.unlinkedMap[uri] = unlinked; 322 store.unlinkedMap[uri] = unlinked;
318 } 323 }
319 324
320 /** 325 /**
321 * TODO(scheglov) replace with actual [AnalysisResult] computing. 326 * Compute the [AnalysisResult] for the [file].
322 */ 327 */
323 List<String> _computeAndPrintErrors(_File file) { 328 AnalysisResult _computeAnalysisResult(_File file) {
324 // TODO(scheglov) Computing resolved unit fails for these units. 329 // TODO(scheglov) Computing resolved unit fails for these units.
325 // pkg/analyzer/lib/plugin/embedded_resolver_provider.dart 330 // pkg/analyzer/lib/plugin/embedded_resolver_provider.dart
326 // pkg/analyzer/lib/plugin/embedded_resolver_provider.dart 331 // pkg/analyzer/lib/plugin/embedded_resolver_provider.dart
327 if (file.path.endsWith( 332 if (file.path.endsWith(
328 'pkg/analyzer/lib/plugin/embedded_resolver_provider.dart') || 333 'pkg/analyzer/lib/plugin/embedded_resolver_provider.dart') ||
329 file.path.endsWith('pkg/analyzer/lib/source/embedder.dart') || 334 file.path.endsWith('pkg/analyzer/lib/source/embedder.dart') ||
330 file.path.endsWith('pkg/analyzer/lib/src/generated/ast.dart') || 335 file.path.endsWith('pkg/analyzer/lib/src/generated/ast.dart') ||
331 file.path.endsWith('pkg/analyzer/lib/src/generated/element.dart') || 336 file.path.endsWith('pkg/analyzer/lib/src/generated/element.dart') ||
332 file.path 337 file.path
333 .endsWith('pkg/analyzer/lib/src/generated/element_handle.dart') || 338 .endsWith('pkg/analyzer/lib/src/generated/element_handle.dart') ||
334 file.path.endsWith('pkg/analyzer/lib/src/generated/error.dart') || 339 file.path.endsWith('pkg/analyzer/lib/src/generated/error.dart') ||
335 file.path.endsWith('pkg/analyzer/lib/src/generated/scanner.dart') || 340 file.path.endsWith('pkg/analyzer/lib/src/generated/scanner.dart') ||
336 file.path.endsWith('pkg/analyzer/lib/src/generated/sdk_io.dart') || 341 file.path.endsWith('pkg/analyzer/lib/src/generated/sdk_io.dart') ||
337 file.path.endsWith('pkg/analyzer/lib/src/generated/visitors.dart') || 342 file.path.endsWith('pkg/analyzer/lib/src/generated/visitors.dart') ||
338 file.path.endsWith('pkg/analyzer/test/generated/constant_test.dart') || 343 file.path.endsWith('pkg/analyzer/test/generated/constant_test.dart') ||
339 file.path.endsWith('pkg/analyzer/test/source/embedder_test.dart')) { 344 file.path.endsWith('pkg/analyzer/test/source/embedder_test.dart')) {
340 return []; 345 return new AnalysisResult(
346 file.path, file.uri, null, file.contentHash, null, []);
341 } 347 }
342 348
343 List<String> errorStrings = _logger.run('Compute errors $file', () { 349 return _logger.run('Compute analysis result for $file', () {
344 _LibraryContext libraryContext = _createLibraryContext(file); 350 _LibraryContext libraryContext = _createLibraryContext(file);
345
346 String errorsKey;
347 {
348 ApiSignature signature = new ApiSignature();
349 signature.addString(libraryContext.node.dependencySignature);
350 signature.addString(file.contentHash);
351 errorsKey = '${signature.toHex()}.errors';
352 }
353
354 {
355 List<int> bytes = _byteStore.get(errorsKey);
356 if (bytes != null) {
357 fb.BufferContext bp = new fb.BufferContext.fromBytes(bytes);
358 int table = bp.derefObject(0);
359 return const fb.ListReader<String>(const fb.StringReader())
360 .vTableGet(bp, table, 0);
361 }
362 }
363
364 AnalysisContext analysisContext = _createAnalysisContext(libraryContext); 351 AnalysisContext analysisContext = _createAnalysisContext(libraryContext);
365 analysisContext.setContents(file.source, file.content); 352 analysisContext.setContents(file.source, file.content);
366 try { 353 // TODO(scheglov) Add support for parts.
367 // Compute resolved unit. 354 CompilationUnit resolvedUnit =
368 // _logger.runTimed('Computed resolved unit', () { 355 analysisContext.resolveCompilationUnit2(file.source, file.source);
369 // analysisContext.resolveCompilationUnit2( 356 List<AnalysisError> errors = analysisContext.computeErrors(file.source);
370 // libraryContext.file.source, libraryContext.file.source); 357 return new AnalysisResult(file.path, file.uri, file.content,
371 // }); 358 file.contentHash, resolvedUnit, errors);
372 // Compute errors.
373 List<AnalysisError> errors = _logger.run('Compute errors', () {
374 return analysisContext.computeErrors(file.source);
375 });
376 List<String> errorStrings = errors
377 .where((error) => error.errorCode is! TodoCode)
378 .map((error) => error.toString())
379 .toList();
380 {
381 fb.Builder fbBuilder = new fb.Builder();
382 var exportedOffset = fbBuilder.writeList(errorStrings
383 .map((errorStr) => fbBuilder.writeString(errorStr))
384 .toList());
385 fbBuilder.startTable();
386 fbBuilder.addOffset(0, exportedOffset);
387 var offset = fbBuilder.endTable();
388 List<int> bytes = fbBuilder.finish(offset, 'CErr');
389 _byteStore.put(errorsKey, bytes);
390 }
391
392 return errorStrings;
393 } finally {
394 analysisContext.dispose();
395 }
396 }); 359 });
397
398 if (errorStrings.isNotEmpty) {
399 errorStrings.forEach((errorString) => print('\t$errorString'));
400 } else {
401 print('\tNO ERRORS');
402 }
403 return errorStrings;
404 } 360 }
405 361
406 AnalysisContext _createAnalysisContext(_LibraryContext libraryContext) { 362 AnalysisContext _createAnalysisContext(_LibraryContext libraryContext) {
407 AnalysisContextImpl analysisContext = 363 AnalysisContextImpl analysisContext =
408 AnalysisEngine.instance.createAnalysisContext(); 364 AnalysisEngine.instance.createAnalysisContext();
409 365
410 analysisContext.sourceFactory = 366 analysisContext.sourceFactory =
411 new SourceFactory((_sourceFactory as SourceFactoryImpl).resolvers); 367 new SourceFactory((_sourceFactory as SourceFactoryImpl).resolvers);
412 analysisContext.resultProvider = 368 analysisContext.resultProvider =
413 new InputPackagesResultProvider(analysisContext, libraryContext.store); 369 new InputPackagesResultProvider(analysisContext, libraryContext.store);
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
665 /** 621 /**
666 * This class is used to gather and print performance information. 622 * This class is used to gather and print performance information.
667 */ 623 */
668 class PerformanceLog { 624 class PerformanceLog {
669 final StringSink sink; 625 final StringSink sink;
670 int _level = 0; 626 int _level = 0;
671 627
672 PerformanceLog(this.sink); 628 PerformanceLog(this.sink);
673 629
674 /** 630 /**
631 * Enter a new execution section, which starts at one point of code, runs
632 * some time, and then ends at the other point of code.
633 *
634 * The client must call [PerformanceLogSection.exit] for every [enter].
635 */
636 PerformanceLogSection enter(String msg) {
637 writeln('+++ $msg.');
638 _level++;
639 return new PerformanceLogSection(this, msg);
640 }
641
642 /**
675 * Return the result of the function [f] invocation and log the elapsed time. 643 * Return the result of the function [f] invocation and log the elapsed time.
676 * 644 *
677 * Each invocation of [run] creates a new enclosed section in the log, 645 * Each invocation of [run] creates a new enclosed section in the log,
678 * which begins with printing [msg], then any log output produced during 646 * which begins with printing [msg], then any log output produced during
679 * [f] invocation, and ends with printing [msg] with the elapsed time. 647 * [f] invocation, and ends with printing [msg] with the elapsed time.
680 */ 648 */
681 /*=T*/ run/*<T>*/(String msg, /*=T*/ f()) { 649 /*=T*/ run/*<T>*/(String msg, /*=T*/ f()) {
682 Stopwatch timer = new Stopwatch()..start(); 650 Stopwatch timer = new Stopwatch()..start();
683 try { 651 try {
684 writeln('+++ $msg.'); 652 writeln('+++ $msg.');
685 _level++; 653 _level++;
686 return f(); 654 return f();
687 } finally { 655 } finally {
688 _level--; 656 _level--;
689 int ms = timer.elapsedMilliseconds; 657 int ms = timer.elapsedMilliseconds;
690 writeln('--- $msg in $ms ms.'); 658 writeln('--- $msg in $ms ms.');
691 } 659 }
692 } 660 }
693 661
694 /** 662 /**
695 * Write a new line into the log 663 * Write a new line into the log
696 */ 664 */
697 void writeln(String msg) { 665 void writeln(String msg) {
698 String indent = '\t' * _level; 666 String indent = '\t' * _level;
699 sink.writeln('$indent$msg'); 667 sink.writeln('$indent$msg');
700 } 668 }
701 } 669 }
702 670
703 /** 671 /**
672 * The performance measurement section for operations that start and end
673 * at different place in code, so cannot be run using [PerformanceLog.run].
674 *
675 * The client must call [exit] for every [PerformanceLog.enter].
676 */
677 class PerformanceLogSection {
Brian Wilkerson 2016/10/26 06:45:03 Consider moving logging into a separate library.
678 final PerformanceLog _logger;
679 final String _msg;
680 final Stopwatch _timer = new Stopwatch()..start();
681
682 PerformanceLogSection(this._logger, this._msg);
683
684 /**
685 * Stop the timer, log the time.
686 */
687 void exit() {
688 _timer.stop();
689 _logger._level--;
690 int ms = _timer.elapsedMilliseconds;
691 _logger.writeln('--- $_msg in $ms ms.');
692 }
693 }
694
695 /**
704 * Information about a file being analyzed, explicitly or implicitly. 696 * Information about a file being analyzed, explicitly or implicitly.
705 * 697 *
706 * It keeps a consistent view on its [content], [contentHash] and [unit]. 698 * It keeps a consistent view on its [content], [contentHash] and [unit].
707 * 699 *
708 * Instances of this class may only be used during computing a single analysis 700 * Instances of this class may only be used during computing a single analysis
709 * result and should not be cached anywhere. We need this limitation to prevent 701 * result and should not be cached anywhere. We need this limitation to prevent
710 * references from caches to the resolved [unit], so to element models, etc. 702 * references from caches to the resolved [unit], so to element models, etc.
711 * The data structures should be short lived - computed, returned to the client, 703 * The data structures should be short lived - computed, returned to the client,
712 * processed there and quickly thrown away. 704 * processed there and quickly thrown away.
713 */ 705 */
(...skipping 268 matching lines...) Expand 10 before | Expand all | Expand 10 after
982 } 974 }
983 } 975 }
984 for (UnlinkedExportPublic export in unit.publicNamespace.exports) { 976 for (UnlinkedExportPublic export in unit.publicNamespace.exports) {
985 referenced.exported.add(export.uri); 977 referenced.exported.add(export.uri);
986 } 978 }
987 return referenced; 979 return referenced;
988 } 980 }
989 981
990 _ReferencedUris._(); 982 _ReferencedUris._();
991 } 983 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698