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

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

Issue 753803002: Use a poor man's incremental parser to perform incremental resolution. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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 | 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:math' as math;
8 9
9 import 'ast.dart'; 10 import 'ast.dart';
10 import 'element.dart'; 11 import 'element.dart';
11 import 'error.dart'; 12 import 'error.dart';
12 import 'java_engine.dart'; 13 import 'java_engine.dart';
13 import 'resolver.dart'; 14 import 'resolver.dart';
14 import 'scanner.dart'; 15 import 'scanner.dart';
15 import 'source.dart'; 16 import 'source.dart';
17 import 'parser.dart';
16 18
17 19
18 /** 20 /**
21 * Attempts to update [oldUnit] to the state that would correspond to [newCode].
22 * Returns `true` if success, or `false` otherwise.
23 * The [oldUnit] might be damaged.
24 */
25 bool poorMansIncrementalResolution(TypeProvider typeProvider,
26 CompilationUnit oldUnit, String newCode) {
27 try {
28 CompilationUnit newUnit = _parseUnit(newCode);
29 _TokenPair firstPair =
30 _findFirstDifferentToken(oldUnit.beginToken, newUnit.beginToken);
31 _TokenPair lastPair =
32 _findLastDifferentToken(oldUnit.endToken, newUnit.endToken);
33 if (firstPair != null && lastPair != null) {
34 AstNode oldNode = _findNodeWithTokens(oldUnit, firstPair.a, lastPair.a);
35 AstNode newNode = _findNodeWithTokens(newUnit, firstPair.b, lastPair.b);
36 // Try to find the smallest common node, a FunctionBody currently.
37 {
38 List<AstNode> oldParents = _getParents(oldNode);
Brian Wilkerson 2014/11/24 15:09:14 Why compute a list? Why not just walk up both pare
39 List<AstNode> newParents = _getParents(newNode);
40 int length = math.min(oldParents.length, newParents.length);
41 bool found = false;
42 for (int i = 0; i < length; i++) {
43 AstNode oldParent = oldParents[i];
44 AstNode newParent = newParents[i];
45 if (oldParent is FunctionBody &&
46 newParent is FunctionBody) {
47 oldNode = oldParent;
48 newNode = newParent;
49 found = true;
50 break;
51 }
52 }
53 if (!found) {
54 return false;
55 }
56 }
57 // replace node
58 NodeReplacer.replace(oldNode, newNode);
59 // update token references
60 firstPair.a.previous.setNext(firstPair.b);
61 lastPair.b.setNext(firstPair.a.next);
Paul Berry 2014/11/24 15:02:25 I think this should be: lastPair.b.setNext(last
scheglov 2014/11/24 18:59:06 Done.
62 // perform incremental resolution
63 // TODO(scheglov) update errors
64 AnalysisErrorListener errorListener = new BooleanErrorListener();
65 CompilationUnitElement oldUnitElement = oldUnit.element;
66 IncrementalResolver incrementalResolver = new IncrementalResolver(
67 errorListener,
68 typeProvider,
69 oldUnitElement.library,
70 oldUnitElement,
71 oldUnitElement.source,
72 oldNode.offset,
73 oldNode.length,
74 newNode.length);
75 incrementalResolver.resolve(newNode);
76 return true;
77 }
78 } catch (e) {
79 }
Paul Berry 2014/11/24 15:02:25 Can we report the exception using the "server.erro
scheglov 2014/11/24 18:59:05 We're in a wrong project to do this. I'll add TODO
80 return false;
81 }
82
83
84 List<AstNode> _getParents(AstNode node) {
85 List<AstNode> parents = <AstNode>[];
86 while (node != null) {
87 parents.insert(0, node);
88 node = node.parent;
89 }
90 return parents;
91 }
92
93 AstNode _findNodeWithTokens(AstNode root, Token first, Token last) {
94 int offset = first.offset;
95 int end = last.end;
96 NodeLocator nodeLocator = new NodeLocator.con2(offset, end);
97 return nodeLocator.searchWithin(root);
98 }
99
100
101 class _TokenPair {
102 final Token a;
Paul Berry 2014/11/24 15:02:25 It looks like all uses of _TokenPair use "a" to re
scheglov 2014/11/24 18:59:05 Done.
103 final Token b;
104 _TokenPair(this.a, this.b);
105 }
106
107
108 _TokenPair _findFirstDifferentToken(Token a, Token b) {
Paul Berry 2014/11/24 15:02:25 The same rename would be nice here too (and also i
scheglov 2014/11/24 18:59:05 Done.
109 // print('first ------------');
Paul Berry 2014/11/24 15:02:25 Commented out debug code should be removed (and al
scheglov 2014/11/24 18:59:05 I'd prefer to keep it in for some time and remove
110 while (true) {
111 // print('a: $a @ ${a.offset}');
112 // print('b: $b @ ${b.offset}');
113 if (!_equalToken(a, b, 0)) {
114 return new _TokenPair(a, b);
115 }
116 if (a.type == TokenType.EOF) {
Brian Wilkerson 2014/11/24 15:09:13 Why not make this part of the while loop's conditi
scheglov 2014/11/24 18:59:06 Done.
117 return null;
118 }
119 a = a.next;
120 b = b.next;
121 }
122 return null;
123 }
124
125
126 _TokenPair _findLastDifferentToken(Token a, Token b) {
127 // print('last ------------');
128 int delta = b.offset - a.offset;
129 while (a.previous != a && b.previous != b) {
130 // print('a: $a @ ${a.offset}');
131 // print('b: $b @ ${b.offset}');
132 if (!_equalToken(a, b, delta)) {
133 return new _TokenPair(a.next, b.next);
134 }
135 a.offset += delta;
136 a = a.previous;
137 b = b.previous;
138 }
Brian Wilkerson 2014/11/24 15:09:14 For what it's worth, I would find the code easier
scheglov 2014/11/24 18:59:06 Done.
139 }
140
141
142 bool _equalToken(Token a, Token b, int delta) {
143 if (a.type != b.type) {
144 return false;
145 }
146 if (b.offset - a.offset != delta) {
147 return false;
148 }
149 return a.lexeme == b.lexeme;
150 }
151
152
153 CompilationUnit _parseUnit(String code) {
154 // TODO(scheglov) remember and update errors
155 var errorListener = new BooleanErrorListener();
156 var reader = new CharSequenceReader(code);
157 var scanner = new Scanner(null, reader, errorListener);
158 var token = scanner.tokenize();
159 var parser = new Parser(null, errorListener);
160 return parser.parseCompilationUnit(token);
161 }
162
163
164 /**
19 * Instances of the class [DeclarationMatcher] determine whether the element 165 * Instances of the class [DeclarationMatcher] determine whether the element
20 * model defined by a given AST structure matches an existing element model. 166 * model defined by a given AST structure matches an existing element model.
21 */ 167 */
22 class DeclarationMatcher extends RecursiveAstVisitor { 168 class DeclarationMatcher extends RecursiveAstVisitor {
23 /** 169 /**
24 * The libary containing the AST nodes being visited. 170 * The libary containing the AST nodes being visited.
25 */ 171 */
26 LibraryElement _enclosingLibrary; 172 LibraryElement _enclosingLibrary;
27 173
28 /** 174 /**
(...skipping 418 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 List<DartType> typeArguments = type.typeArguments; 593 List<DartType> typeArguments = type.typeArguments;
448 if (nodeArgumentList == null) { 594 if (nodeArgumentList == null) {
449 _assertTrue(typeArguments.isEmpty); 595 _assertTrue(typeArguments.isEmpty);
450 } else { 596 } else {
451 List<TypeName> nodeArguments = nodeArgumentList.arguments; 597 List<TypeName> nodeArguments = nodeArgumentList.arguments;
452 _assertSameTypes(nodeArguments, typeArguments); 598 _assertSameTypes(nodeArguments, typeArguments);
453 } 599 }
454 } else if (type is TypeParameterType) { 600 } else if (type is TypeParameterType) {
455 _assertEquals(nodeName, type.name); 601 _assertEquals(nodeName, type.name);
456 // TODO(scheglov) it should be possible to rename type parameters 602 // TODO(scheglov) it should be possible to rename type parameters
603 } else if (type is VoidType) {
604 _assertEquals(nodeName, 'void');
605 // TODO(scheglov) add test for "void"
457 } else { 606 } else {
458 // TODO(scheglov) support other types 607 // TODO(scheglov) support other types
608 // print('node: $node type: $type type.type: ${type.runtimeType}');
459 _assertTrue(false); 609 _assertTrue(false);
460 } 610 }
461 } 611 }
462 612
463 void _assertSameTypes(List<TypeName> nodes, List<DartType> types) { 613 void _assertSameTypes(List<TypeName> nodes, List<DartType> types) {
464 int length = nodes.length; 614 int length = nodes.length;
465 _assertEquals(length, types.length); 615 _assertEquals(length, types.length);
466 for (int i = 0; i < length; i++) { 616 for (int i = 0; i < length; i++) {
467 _assertSameType(nodes[i], types[i]); 617 _assertSameType(nodes[i], types[i]);
468 } 618 }
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
541 if (element.displayName == name && element.nameOffset == offset) { 691 if (element.displayName == name && element.nameOffset == offset) {
542 return element; 692 return element;
543 } 693 }
544 } 694 }
545 return null; 695 return null;
546 } 696 }
547 697
548 void _gatherElements(Element element) { 698 void _gatherElements(Element element) {
549 _ElementsGatherer gatherer = new _ElementsGatherer(this); 699 _ElementsGatherer gatherer = new _ElementsGatherer(this);
550 element.accept(gatherer); 700 element.accept(gatherer);
551 // TODO(scheglov) push into CompilationUnitElement 701 // TODO(scheglov) what if a change in a directive?
552 if (identical(_enclosingUnit, _enclosingLibrary.definingCompilationUnit)) { 702 if (identical(element, _enclosingLibrary.definingCompilationUnit)) {
553 gatherer.addElements(_enclosingLibrary.imports); 703 gatherer.addElements(_enclosingLibrary.imports);
554 gatherer.addElements(_enclosingLibrary.exports); 704 gatherer.addElements(_enclosingLibrary.exports);
555 gatherer.addElements(_enclosingLibrary.parts); 705 gatherer.addElements(_enclosingLibrary.parts);
556 } 706 }
557 } 707 }
558 708
559 /** 709 /**
560 * Return the value of the given string literal, or `null` if the string is no t a constant 710 * Return the value of the given string literal, or `null` if the string is no t a constant
561 * string without any string interpolation. 711 * string without any string interpolation.
562 * 712 *
(...skipping 480 matching lines...) Expand 10 before | Expand all | Expand 10 after
1043 visitFunctionExpression(FunctionExpression node) { 1193 visitFunctionExpression(FunctionExpression node) {
1044 _elements[node] = node.element; 1194 _elements[node] = node.element;
1045 super.visitFunctionExpression(node); 1195 super.visitFunctionExpression(node);
1046 } 1196 }
1047 1197
1048 @override 1198 @override
1049 visitSimpleIdentifier(SimpleIdentifier node) { 1199 visitSimpleIdentifier(SimpleIdentifier node) {
1050 _elements[node] = node.staticElement; 1200 _elements[node] = node.staticElement;
1051 } 1201 }
1052 } 1202 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698