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

Side by Side Diff: pkg/analyzer/lib/src/generated/incremental_resolver.dart

Issue 774983003: Add logging to the incremental resolver. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years 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 | Annotate | Revision Log
OLDNEW
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 engine.incremental_resolver; 5 library engine.incremental_resolver;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 import 'dart:io';
Brian Wilkerson 2014/12/03 15:05:17 Won't this pull in a dependency on dart:io that so
8 import 'dart:math' as math; 9 import 'dart:math' as math;
9 10
10 import 'package:analyzer/src/generated/error_verifier.dart';
11 import 'package:analyzer/src/generated/utilities_dart.dart';
12
13 import 'ast.dart'; 11 import 'ast.dart';
14 import 'element.dart'; 12 import 'element.dart';
15 import 'engine.dart'; 13 import 'engine.dart';
16 import 'error.dart'; 14 import 'error.dart';
15 import 'error_verifier.dart';
17 import 'java_engine.dart'; 16 import 'java_engine.dart';
18 import 'parser.dart'; 17 import 'parser.dart';
19 import 'resolver.dart'; 18 import 'resolver.dart';
20 import 'scanner.dart'; 19 import 'scanner.dart';
21 import 'source.dart'; 20 import 'source.dart';
21 import 'utilities_dart.dart';
22
23
24 _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.
25 String _loggerSpec = null;
26
27
28 void _initLogger(String spec) {
29 // check if the same logging specification
30 if (spec == _loggerSpec) {
31 return;
32 }
33 _loggerSpec = spec;
34 // check for null
35 _logger = new _NullLogger();
36 if (spec == null) {
37 return;
38 }
39 // create logger
40 if (spec == 'console') {
41 _logger = new _StringSinkLogger(console.log);
42 }
43 if (spec.startsWith('file:')) {
44 String fileName = spec.substring('file:'.length);
45 File file = new File(fileName);
46 IOSink sink = file.openWrite();
47 _logger = new _StringSinkLogger(sink);
48 }
49 }
22 50
23 51
24 /** 52 /**
25 * Instances of the class [DeclarationMatcher] determine whether the element 53 * Instances of the class [DeclarationMatcher] determine whether the element
26 * model defined by a given AST structure matches an existing element model. 54 * model defined by a given AST structure matches an existing element model.
27 */ 55 */
28 class DeclarationMatcher extends RecursiveAstVisitor { 56 class DeclarationMatcher extends RecursiveAstVisitor {
29 /** 57 /**
30 * The libary containing the AST nodes being visited. 58 * The libary containing the AST nodes being visited.
31 */ 59 */
(...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after
905 int _updateEndOld; 933 int _updateEndOld;
906 int _updateEndNew; 934 int _updateEndNew;
907 935
908 List<AnalysisError> _newScanErrors = <AnalysisError>[]; 936 List<AnalysisError> _newScanErrors = <AnalysisError>[];
909 List<AnalysisError> _newParseErrors = <AnalysisError>[]; 937 List<AnalysisError> _newParseErrors = <AnalysisError>[];
910 List<AnalysisError> _newResolveErrors = <AnalysisError>[]; 938 List<AnalysisError> _newResolveErrors = <AnalysisError>[];
911 List<AnalysisError> _newVerifyErrors = <AnalysisError>[]; 939 List<AnalysisError> _newVerifyErrors = <AnalysisError>[];
912 List<AnalysisError> _newHints = <AnalysisError>[]; 940 List<AnalysisError> _newHints = <AnalysisError>[];
913 941
914 PoorMansIncrementalResolver(this._typeProvider, this._unitSource, 942 PoorMansIncrementalResolver(this._typeProvider, this._unitSource,
915 this._librarySource, this._entry); 943 this._librarySource, this._entry, String logSpec) {
944 _initLogger(logSpec);
945 }
916 946
917 /** 947 /**
918 * Attempts to update [oldUnit] to the state corresponding to [newCode]. 948 * Attempts to update [oldUnit] to the state corresponding to [newCode].
919 * Returns `true` if success, or `false` otherwise. 949 * Returns `true` if success, or `false` otherwise.
920 * The [oldUnit] might be damaged. 950 * The [oldUnit] might be damaged.
921 */ 951 */
922 bool resolve(CompilationUnit oldUnit, String newCode) { 952 bool resolve(CompilationUnit oldUnit, String newCode) {
953 _logger.enter('resolve $_unitSource');
954 _logger.log(oldUnit != null ? 'has oldUnit' : 'oldUnit is null');
923 try { 955 try {
924 CompilationUnit newUnit = _parseUnit(newCode); 956 CompilationUnit newUnit = _parseUnit(newCode);
925 _TokenPair firstPair = 957 _TokenPair firstPair =
926 _findFirstDifferentToken(oldUnit.beginToken, newUnit.beginToken); 958 _findFirstDifferentToken(oldUnit.beginToken, newUnit.beginToken);
927 _TokenPair lastPair = 959 _TokenPair lastPair =
928 _findLastDifferentToken(oldUnit.endToken, newUnit.endToken); 960 _findLastDifferentToken(oldUnit.endToken, newUnit.endToken);
929 if (firstPair != null && lastPair != null) { 961 if (firstPair != null && lastPair != null) {
930 int firstOffsetOld = firstPair.oldToken.offset; 962 int firstOffsetOld = firstPair.oldToken.offset;
931 int firstOffsetNew = firstPair.newToken.offset; 963 int firstOffsetNew = firstPair.newToken.offset;
932 int lastOffsetOld = lastPair.oldToken.end; 964 int lastOffsetOld = lastPair.oldToken.end;
933 int lastOffsetNew = lastPair.newToken.end; 965 int lastOffsetNew = lastPair.newToken.end;
934 int beginOffsetOld = math.min(firstOffsetOld, lastOffsetOld); 966 int beginOffsetOld = math.min(firstOffsetOld, lastOffsetOld);
935 int endOffsetOld = math.max(firstOffsetOld, lastOffsetOld); 967 int endOffsetOld = math.max(firstOffsetOld, lastOffsetOld);
936 int beginOffsetNew = math.min(firstOffsetNew, lastOffsetNew); 968 int beginOffsetNew = math.min(firstOffsetNew, lastOffsetNew);
937 int endOffsetNew = math.max(firstOffsetNew, lastOffsetNew); 969 int endOffsetNew = math.max(firstOffsetNew, lastOffsetNew);
938 // check for a whitespace only change 970 // check for a whitespace only change
939 if (identical(lastPair.oldToken, firstPair.oldToken) && 971 if (identical(lastPair.oldToken, firstPair.oldToken) &&
940 identical(lastPair.newToken, firstPair.newToken)) { 972 identical(lastPair.newToken, firstPair.newToken)) {
941 _updateOffset = beginOffsetOld - 1; 973 _updateOffset = beginOffsetOld - 1;
942 _updateEndOld = endOffsetOld; 974 _updateEndOld = endOffsetOld;
943 _updateDelta = newUnit.length - oldUnit.length; 975 _updateDelta = newUnit.length - oldUnit.length;
944 if (firstPair.atComment && lastPair.atComment) { 976 if (firstPair.atComment && lastPair.atComment) {
977 _logger.log('Comment change.');
945 _resolveComment(oldUnit, newUnit, firstPair); 978 _resolveComment(oldUnit, newUnit, firstPair);
946 } else { 979 } else {
980 _logger.log('Whitespace change.');
947 _shiftTokens(firstPair.oldToken); 981 _shiftTokens(firstPair.oldToken);
948 IncrementalResolver._updateElementNameOffsets( 982 IncrementalResolver._updateElementNameOffsets(
949 oldUnit.element, 983 oldUnit.element,
950 _updateOffset, 984 _updateOffset,
951 _updateDelta); 985 _updateDelta);
952 _updateEntry(); 986 _updateEntry();
953 } 987 }
988 _logger.log('Success.');
954 return true; 989 return true;
955 } 990 }
956 // Find nodes covering the "old" and "new" token ranges. 991 // Find nodes covering the "old" and "new" token ranges.
957 AstNode oldNode = 992 AstNode oldNode =
958 _findNodeCovering(oldUnit, beginOffsetOld, endOffsetOld); 993 _findNodeCovering(oldUnit, beginOffsetOld, endOffsetOld);
959 AstNode newNode = 994 AstNode newNode =
960 _findNodeCovering(newUnit, beginOffsetNew, endOffsetNew); 995 _findNodeCovering(newUnit, beginOffsetNew, endOffsetNew);
961 // print('oldNode: $oldNode'); 996 _logger.log('oldNode: $oldNode');
962 // print('newNode: $newNode'); 997 _logger.log('newNode: $newNode');
963 // Try to find the smallest common node, a FunctionBody currently. 998 // Try to find the smallest common node, a FunctionBody currently.
964 { 999 {
965 List<AstNode> oldParents = _getParents(oldNode); 1000 List<AstNode> oldParents = _getParents(oldNode);
966 List<AstNode> newParents = _getParents(newNode); 1001 List<AstNode> newParents = _getParents(newNode);
967 int length = math.min(oldParents.length, newParents.length); 1002 int length = math.min(oldParents.length, newParents.length);
968 bool found = false; 1003 bool found = false;
969 for (int i = 0; i < length; i++) { 1004 for (int i = 0; i < length; i++) {
970 AstNode oldParent = oldParents[i]; 1005 AstNode oldParent = oldParents[i];
971 AstNode newParent = newParents[i]; 1006 AstNode newParent = newParents[i];
972 if (oldParent is FunctionDeclaration && 1007 if (oldParent is FunctionDeclaration &&
973 newParent is FunctionDeclaration || 1008 newParent is FunctionDeclaration ||
974 oldParent is MethodDeclaration && newParent is MethodDeclaration || 1009 oldParent is MethodDeclaration && newParent is MethodDeclaration ||
975 oldParent is ConstructorDeclaration && newParent is ConstructorD eclaration) { 1010 oldParent is ConstructorDeclaration && newParent is ConstructorD eclaration) {
976 oldNode = oldParent; 1011 oldNode = oldParent;
977 newNode = newParent; 1012 newNode = newParent;
978 found = true; 1013 found = true;
979 } 1014 }
980 if (oldParent is FunctionBody && newParent is FunctionBody) { 1015 if (oldParent is FunctionBody && newParent is FunctionBody) {
981 oldNode = oldParent; 1016 oldNode = oldParent;
982 newNode = newParent; 1017 newNode = newParent;
983 found = true; 1018 found = true;
984 break; 1019 break;
985 } 1020 }
986 } 1021 }
987 if (!found) { 1022 if (!found) {
1023 _logger.log('Failure: no enclosing function body or executable.');
988 return false; 1024 return false;
989 } 1025 }
990 } 1026 }
991 // print('oldNode: $oldNode'); 1027 _logger.log('oldNode: $oldNode');
992 // print('newNode: $newNode'); 1028 _logger.log('newNode: $newNode');
993 // prepare update range 1029 // prepare update range
994 _updateOffset = oldNode.offset; 1030 _updateOffset = oldNode.offset;
995 _updateEndOld = oldNode.end; 1031 _updateEndOld = oldNode.end;
996 _updateEndNew = newNode.end; 1032 _updateEndNew = newNode.end;
997 _updateDelta = _updateEndNew - _updateEndOld; 1033 _updateDelta = _updateEndNew - _updateEndOld;
998 // replace node 1034 // replace node
999 NodeReplacer.replace(oldNode, newNode); 1035 NodeReplacer.replace(oldNode, newNode);
1000 // update token references 1036 // update token references
1001 { 1037 {
1002 Token oldBeginToken = _getBeginTokenNotComment(oldNode); 1038 Token oldBeginToken = _getBeginTokenNotComment(oldNode);
(...skipping 12 matching lines...) Expand all
1015 _typeProvider, 1051 _typeProvider,
1016 oldUnitElement, 1052 oldUnitElement,
1017 _updateOffset, 1053 _updateOffset,
1018 oldNode.length, 1054 oldNode.length,
1019 newNode.length); 1055 newNode.length);
1020 incrementalResolver.resolve(newNode); 1056 incrementalResolver.resolve(newNode);
1021 _newResolveErrors = incrementalResolver._resolveErrors; 1057 _newResolveErrors = incrementalResolver._resolveErrors;
1022 _newVerifyErrors = incrementalResolver._verifyErrors; 1058 _newVerifyErrors = incrementalResolver._verifyErrors;
1023 _newHints = incrementalResolver._hints; 1059 _newHints = incrementalResolver._hints;
1024 _updateEntry(); 1060 _updateEntry();
1025 // print('Successfully incrementally resolved.'); 1061 _logger.log('Success.');
1026 return true; 1062 return true;
1027 } 1063 }
1028 } catch (e) { 1064 } catch (e, st) {
1029 // TODO(scheglov) find a way to log these exceptions 1065 _logger.log(e);
1030 // print(e); 1066 _logger.log(st);
1031 // print(st); 1067 _logger.log('Failure: exception.');
1068 } finally {
1069 _logger.exit();
1032 } 1070 }
1033 return false; 1071 return false;
1034 } 1072 }
1035 1073
1036 CompilationUnit _parseUnit(String code) { 1074 CompilationUnit _parseUnit(String code) {
1037 Token token = _scan(code); 1075 Token token = _scan(code);
1038 RecordingErrorListener errorListener = new RecordingErrorListener(); 1076 RecordingErrorListener errorListener = new RecordingErrorListener();
1039 Parser parser = new Parser(_unitSource, errorListener); 1077 Parser parser = new Parser(_unitSource, errorListener);
1040 CompilationUnit unit = parser.parseCompilationUnit(token); 1078 CompilationUnit unit = parser.parseCompilationUnit(token);
1041 _newParseErrors = errorListener.errors; 1079 _newParseErrors = errorListener.errors;
1042 return unit; 1080 return unit;
1043 } 1081 }
1044 1082
1045 void _resolveComment(CompilationUnit oldUnit, CompilationUnit newUnit, 1083 void _resolveComment(CompilationUnit oldUnit, CompilationUnit newUnit,
1046 _TokenPair firstPair) { 1084 _TokenPair firstPair) {
1047 Token oldToken = firstPair.oldToken; 1085 Token oldToken = firstPair.oldToken;
1048 int offset = oldToken.precedingComments.offset; 1086 CommentToken precedingComments = oldToken.precedingComments;
1087 int offset = precedingComments.offset;
1088 _logger.log('offset: $offset');
1049 Comment oldComment = _findNodeCovering(oldUnit, offset, offset); 1089 Comment oldComment = _findNodeCovering(oldUnit, offset, offset);
1050 Comment newComment = _findNodeCovering(newUnit, offset, offset); 1090 Comment newComment = _findNodeCovering(newUnit, offset, offset);
1091 _logger.log('oldComment.beginToken: ${oldComment.beginToken}');
1092 _logger.log('newComment.beginToken: ${newComment.beginToken}');
1051 _updateOffset = oldToken.offset - 1; 1093 _updateOffset = oldToken.offset - 1;
1052 // update token references 1094 // update token references
1053 _shiftTokens(firstPair.oldToken); 1095 _shiftTokens(firstPair.oldToken);
1054 _setPrecedingComments(oldToken, newComment.tokens.first); 1096 _setPrecedingComments(oldToken, newComment.tokens.first);
1055 // replace node 1097 // replace node
1056 NodeReplacer.replace(oldComment, newComment); 1098 NodeReplacer.replace(oldComment, newComment);
1057 // update elements 1099 // update elements
1058 IncrementalResolver._updateElementNameOffsets( 1100 IncrementalResolver._updateElementNameOffsets(
1059 oldUnit.element, 1101 oldUnit.element,
1060 _updateOffset, 1102 _updateOffset,
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after
1540 super.visitFunctionExpression(node); 1582 super.visitFunctionExpression(node);
1541 } 1583 }
1542 1584
1543 @override 1585 @override
1544 visitSimpleIdentifier(SimpleIdentifier node) { 1586 visitSimpleIdentifier(SimpleIdentifier node) {
1545 _elements[node] = node.staticElement; 1587 _elements[node] = node.staticElement;
1546 } 1588 }
1547 } 1589 }
1548 1590
1549 1591
1592 /**
1593 * A simple hierarchical logger.
1594 */
1595 abstract class _Logger {
1596 /**
1597 * Mark an enter to a new section with the given [name].
1598 */
1599 void enter(String name);
1600
1601 /**
1602 * Mark an exit from the current sections, logs the duration.
1603 */
1604 void exit();
1605
1606 /**
1607 * Logs the given [message].
1608 */
1609 void log(Object obj);
1610 }
1611
1612
1613 class _LoggerSection {
1614 final DateTime start = new DateTime.now();
1615 final String indent;
1616 final String name;
1617 _LoggerSection(this.indent, this.name);
1618 }
1619
1620
1621 /**
1622 * A [_Logger] that does nothing.
1623 */
1624 class _NullLogger implements _Logger {
1625 @override
1626 void enter(String name) {
1627 }
1628
1629 @override
1630 void exit() {
1631 }
1632
1633 @override
1634 void log(Object obj) {
1635 }
1636 }
1637
1638
1639 /**
1640 * A [_Logger] that writes to a [StringSink].
1641 */
1642 class _StringSinkLogger implements _Logger {
1643 static const int MAX_LINE_LENGTH = 512;
1644 final StringSink sink;
1645 final List<_LoggerSection> sectionStack = <_LoggerSection>[];
1646 _LoggerSection section = new _LoggerSection('', 'ROOT');
1647
1648 _StringSinkLogger(this.sink);
1649
1650 @override
1651 void enter(String name) {
1652 log('+++ $name');
1653 sectionStack.add(section);
1654 section = new _LoggerSection(section.indent + '\t', name);
1655 }
1656
1657 @override
1658 void exit() {
1659 DateTime now = new DateTime.now();
1660 Duration duration = now.difference(section.start);
1661 String message = '--- ${section.name} in ${duration.inMilliseconds} ms';
1662 section = sectionStack.removeLast();
1663 log(message);
1664 }
1665
1666 @override
1667 void log(Object obj) {
1668 DateTime now = new DateTime.now();
1669 String indent = section.indent;
1670 String objStr = _getObjectString(obj);
1671 String line = '[$now] $indent$objStr';
1672 sink.writeln(line);
1673 }
1674
1675 String _getObjectString(Object obj) {
1676 if (obj == null) {
1677 return 'null';
1678 }
1679 String str = obj.toString();
1680 if (str.length < MAX_LINE_LENGTH) {
1681 return str;
1682 }
1683 return str.split('\n').map((String line) {
1684 if (line.length > MAX_LINE_LENGTH) {
1685 line = line.substring(0, MAX_LINE_LENGTH) + '...';
1686 }
1687 return line;
1688 }).join('\n');
1689 }
1690 }
1691
1692
1550 class _TokenPair { 1693 class _TokenPair {
1551 final Token oldToken; 1694 final Token oldToken;
1552 final Token newToken; 1695 final Token newToken;
1553 final bool atComment; 1696 final bool atComment;
1554 _TokenPair(this.oldToken, this.newToken, [this.atComment = false]); 1697 _TokenPair(this.oldToken, this.newToken, [this.atComment = false]);
1555 } 1698 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698