Chromium Code Reviews| Index: pkg/analyzer/lib/src/generated/incremental_resolver.dart |
| diff --git a/pkg/analyzer/lib/src/generated/incremental_resolver.dart b/pkg/analyzer/lib/src/generated/incremental_resolver.dart |
| index 7f9d12e101a03f26746bdc872937269784612fb9..8cdcef4c750e1de0aafa53ec4cd96c84e308d976 100644 |
| --- a/pkg/analyzer/lib/src/generated/incremental_resolver.dart |
| +++ b/pkg/analyzer/lib/src/generated/incremental_resolver.dart |
| @@ -5,20 +5,48 @@ |
| library engine.incremental_resolver; |
| import 'dart:collection'; |
| +import 'dart:io'; |
|
Brian Wilkerson
2014/12/03 15:05:17
Won't this pull in a dependency on dart:io that so
|
| import 'dart:math' as math; |
| -import 'package:analyzer/src/generated/error_verifier.dart'; |
| -import 'package:analyzer/src/generated/utilities_dart.dart'; |
| - |
| import 'ast.dart'; |
| import 'element.dart'; |
| import 'engine.dart'; |
| import 'error.dart'; |
| +import 'error_verifier.dart'; |
| import 'java_engine.dart'; |
| import 'parser.dart'; |
| import 'resolver.dart'; |
| import 'scanner.dart'; |
| import 'source.dart'; |
| +import 'utilities_dart.dart'; |
| + |
| + |
| +_Logger _logger = new _NullLogger(); |
|
Brian Wilkerson
2014/12/03 15:05:17
The logger should be moved to a separate library (
scheglov
2014/12/03 15:58:09
Done.
|
| +String _loggerSpec = null; |
| + |
| + |
| +void _initLogger(String spec) { |
| + // check if the same logging specification |
| + if (spec == _loggerSpec) { |
| + return; |
| + } |
| + _loggerSpec = spec; |
| + // check for null |
| + _logger = new _NullLogger(); |
| + if (spec == null) { |
| + return; |
| + } |
| + // create logger |
| + if (spec == 'console') { |
| + _logger = new _StringSinkLogger(console.log); |
| + } |
| + if (spec.startsWith('file:')) { |
| + String fileName = spec.substring('file:'.length); |
| + File file = new File(fileName); |
| + IOSink sink = file.openWrite(); |
| + _logger = new _StringSinkLogger(sink); |
| + } |
| +} |
| /** |
| @@ -912,7 +940,9 @@ class PoorMansIncrementalResolver { |
| List<AnalysisError> _newHints = <AnalysisError>[]; |
| PoorMansIncrementalResolver(this._typeProvider, this._unitSource, |
| - this._librarySource, this._entry); |
| + this._librarySource, this._entry, String logSpec) { |
| + _initLogger(logSpec); |
| + } |
| /** |
| * Attempts to update [oldUnit] to the state corresponding to [newCode]. |
| @@ -920,6 +950,8 @@ class PoorMansIncrementalResolver { |
| * The [oldUnit] might be damaged. |
| */ |
| bool resolve(CompilationUnit oldUnit, String newCode) { |
| + _logger.enter('resolve $_unitSource'); |
| + _logger.log(oldUnit != null ? 'has oldUnit' : 'oldUnit is null'); |
| try { |
| CompilationUnit newUnit = _parseUnit(newCode); |
| _TokenPair firstPair = |
| @@ -942,8 +974,10 @@ class PoorMansIncrementalResolver { |
| _updateEndOld = endOffsetOld; |
| _updateDelta = newUnit.length - oldUnit.length; |
| if (firstPair.atComment && lastPair.atComment) { |
| + _logger.log('Comment change.'); |
| _resolveComment(oldUnit, newUnit, firstPair); |
| } else { |
| + _logger.log('Whitespace change.'); |
| _shiftTokens(firstPair.oldToken); |
| IncrementalResolver._updateElementNameOffsets( |
| oldUnit.element, |
| @@ -951,6 +985,7 @@ class PoorMansIncrementalResolver { |
| _updateDelta); |
| _updateEntry(); |
| } |
| + _logger.log('Success.'); |
| return true; |
| } |
| // Find nodes covering the "old" and "new" token ranges. |
| @@ -958,8 +993,8 @@ class PoorMansIncrementalResolver { |
| _findNodeCovering(oldUnit, beginOffsetOld, endOffsetOld); |
| AstNode newNode = |
| _findNodeCovering(newUnit, beginOffsetNew, endOffsetNew); |
| -// print('oldNode: $oldNode'); |
| -// print('newNode: $newNode'); |
| + _logger.log('oldNode: $oldNode'); |
| + _logger.log('newNode: $newNode'); |
| // Try to find the smallest common node, a FunctionBody currently. |
| { |
| List<AstNode> oldParents = _getParents(oldNode); |
| @@ -985,11 +1020,12 @@ class PoorMansIncrementalResolver { |
| } |
| } |
| if (!found) { |
| + _logger.log('Failure: no enclosing function body or executable.'); |
| return false; |
| } |
| } |
| -// print('oldNode: $oldNode'); |
| -// print('newNode: $newNode'); |
| + _logger.log('oldNode: $oldNode'); |
| + _logger.log('newNode: $newNode'); |
| // prepare update range |
| _updateOffset = oldNode.offset; |
| _updateEndOld = oldNode.end; |
| @@ -1022,13 +1058,15 @@ class PoorMansIncrementalResolver { |
| _newVerifyErrors = incrementalResolver._verifyErrors; |
| _newHints = incrementalResolver._hints; |
| _updateEntry(); |
| -// print('Successfully incrementally resolved.'); |
| + _logger.log('Success.'); |
| return true; |
| } |
| - } catch (e) { |
| - // TODO(scheglov) find a way to log these exceptions |
| -// print(e); |
| -// print(st); |
| + } catch (e, st) { |
| + _logger.log(e); |
| + _logger.log(st); |
| + _logger.log('Failure: exception.'); |
| + } finally { |
| + _logger.exit(); |
| } |
| return false; |
| } |
| @@ -1045,9 +1083,13 @@ class PoorMansIncrementalResolver { |
| void _resolveComment(CompilationUnit oldUnit, CompilationUnit newUnit, |
| _TokenPair firstPair) { |
| Token oldToken = firstPair.oldToken; |
| - int offset = oldToken.precedingComments.offset; |
| + CommentToken precedingComments = oldToken.precedingComments; |
| + int offset = precedingComments.offset; |
| + _logger.log('offset: $offset'); |
| Comment oldComment = _findNodeCovering(oldUnit, offset, offset); |
| Comment newComment = _findNodeCovering(newUnit, offset, offset); |
| + _logger.log('oldComment.beginToken: ${oldComment.beginToken}'); |
| + _logger.log('newComment.beginToken: ${newComment.beginToken}'); |
| _updateOffset = oldToken.offset - 1; |
| // update token references |
| _shiftTokens(firstPair.oldToken); |
| @@ -1547,6 +1589,107 @@ class _ElementsRestorer extends RecursiveAstVisitor { |
| } |
| +/** |
| + * A simple hierarchical logger. |
| + */ |
| +abstract class _Logger { |
| + /** |
| + * Mark an enter to a new section with the given [name]. |
| + */ |
| + void enter(String name); |
| + |
| + /** |
| + * Mark an exit from the current sections, logs the duration. |
| + */ |
| + void exit(); |
| + |
| + /** |
| + * Logs the given [message]. |
| + */ |
| + void log(Object obj); |
| +} |
| + |
| + |
| +class _LoggerSection { |
| + final DateTime start = new DateTime.now(); |
| + final String indent; |
| + final String name; |
| + _LoggerSection(this.indent, this.name); |
| +} |
| + |
| + |
| +/** |
| + * A [_Logger] that does nothing. |
| + */ |
| +class _NullLogger implements _Logger { |
| + @override |
| + void enter(String name) { |
| + } |
| + |
| + @override |
| + void exit() { |
| + } |
| + |
| + @override |
| + void log(Object obj) { |
| + } |
| +} |
| + |
| + |
| +/** |
| + * A [_Logger] that writes to a [StringSink]. |
| + */ |
| +class _StringSinkLogger implements _Logger { |
| + static const int MAX_LINE_LENGTH = 512; |
| + final StringSink sink; |
| + final List<_LoggerSection> sectionStack = <_LoggerSection>[]; |
| + _LoggerSection section = new _LoggerSection('', 'ROOT'); |
| + |
| + _StringSinkLogger(this.sink); |
| + |
| + @override |
| + void enter(String name) { |
| + log('+++ $name'); |
| + sectionStack.add(section); |
| + section = new _LoggerSection(section.indent + '\t', name); |
| + } |
| + |
| + @override |
| + void exit() { |
| + DateTime now = new DateTime.now(); |
| + Duration duration = now.difference(section.start); |
| + String message = '--- ${section.name} in ${duration.inMilliseconds} ms'; |
| + section = sectionStack.removeLast(); |
| + log(message); |
| + } |
| + |
| + @override |
| + void log(Object obj) { |
| + DateTime now = new DateTime.now(); |
| + String indent = section.indent; |
| + String objStr = _getObjectString(obj); |
| + String line = '[$now] $indent$objStr'; |
| + sink.writeln(line); |
| + } |
| + |
| + String _getObjectString(Object obj) { |
| + if (obj == null) { |
| + return 'null'; |
| + } |
| + String str = obj.toString(); |
| + if (str.length < MAX_LINE_LENGTH) { |
| + return str; |
| + } |
| + return str.split('\n').map((String line) { |
| + if (line.length > MAX_LINE_LENGTH) { |
| + line = line.substring(0, MAX_LINE_LENGTH) + '...'; |
| + } |
| + return line; |
| + }).join('\n'); |
| + } |
| +} |
| + |
| + |
| class _TokenPair { |
| final Token oldToken; |
| final Token newToken; |