Skip to content

Commit 394836e

Browse files
author
John Messerly
committed
fixes #259, clone ast before mutation
[email protected] Review URL: https://codereview.chromium.org/1245013005 .
1 parent 9fe41d1 commit 394836e

File tree

9 files changed

+56
-23
lines changed

9 files changed

+56
-23
lines changed

pkg/dev_compiler/lib/src/checker/checker.dart

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1001,7 +1001,11 @@ class CodeChecker extends RecursiveAstVisitor {
10011001
reporter.onError(error);
10021002

10031003
if (info is CoercionInfo) {
1004-
assert(CoercionInfo.get(info.node) == null);
1004+
// TODO(jmesserly): if we're run again on the same AST, we'll produce the
1005+
// same annotations. This should be harmless. This might go away once
1006+
// CodeChecker is integrated better with analyzer, as it will know that
1007+
// checking has already been performed.
1008+
// assert(CoercionInfo.get(info.node) == null);
10051009
CoercionInfo.set(info.node, info);
10061010
}
10071011
}

pkg/dev_compiler/lib/src/codegen/js_codegen.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2802,6 +2802,8 @@ class JSGenerator extends CodeGenerator {
28022802
}
28032803

28042804
String generateLibrary(LibraryUnit unit) {
2805+
// Clone the AST first, so we can mutate it.
2806+
unit = unit.clone();
28052807
var library = unit.library.element.library;
28062808
var fields = findFieldsNeedingStorage(unit);
28072809
var codegen =

pkg/dev_compiler/lib/src/codegen/reify_coercions.dart

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -111,37 +111,31 @@ class CoercionReifier extends analyzer.GeneralizingAstVisitor<Object> {
111111
// to discharging the collected definitions.
112112
// Returns the set of new type identifiers added by the reifier
113113
Map<Identifier, NewTypeIdDesc> reify() {
114-
_library.partsThenLibrary.forEach(generateUnit);
114+
_library.partsThenLibrary.forEach(visitCompilationUnit);
115115
return _tm.addedTypes;
116116
}
117117

118-
void generateUnit(CompilationUnit unit) {
119-
visitCompilationUnit(unit);
120-
}
121-
122118
@override
123119
Object visitExpression(Expression node) {
124120
var info = CoercionInfo.get(node);
125121
if (info is InferredTypeBase) {
126-
return _visitInferredTypeBase(info);
122+
return _visitInferredTypeBase(info, node);
127123
} else if (info is DownCast) {
128-
return _visitDownCast(info);
124+
return _visitDownCast(info, node);
129125
}
130126
return super.visitExpression(node);
131127
}
132128

133129
///////////////// Private //////////////////////////////////
134130
135-
Object _visitInferredTypeBase(InferredTypeBase node) {
136-
var expr = node.node;
131+
Object _visitInferredTypeBase(InferredTypeBase node, Expression expr) {
137132
var success = _inferrer.inferExpression(expr, node.type, <String>[]);
138133
assert(success);
139134
expr.visitChildren(this);
140135
return null;
141136
}
142137

143-
Object _visitDownCast(DownCast node) {
144-
var expr = node.node;
138+
Object _visitDownCast(DownCast node, Expression expr) {
145139
var parent = expr.parent;
146140
expr.visitChildren(this);
147141
Expression newE = _cm.coerceExpression(expr, node.cast);

pkg/dev_compiler/lib/src/compiler.dart

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -128,19 +128,10 @@ class BatchCompiler extends AbstractCompiler {
128128
if (_jsGen != null) {
129129
var unit = units.first;
130130
var parts = units.skip(1).toList();
131-
132-
// TODO(jmesserly): this hack is to avoid compiling the same compilation
133-
// unit to JS twice. We mutate the AST, so it's not safe to run more than
134-
// once on the same unit.
135-
if (unit.getProperty(_propertyName) == true) return;
136-
unit.setProperty(_propertyName, true);
137-
138131
_jsGen.generateLibrary(new LibraryUnit(unit, parts));
139132
}
140133
}
141134

142-
static const String _propertyName = 'dev_compiler.BatchCompiler.isCompiled';
143-
144135
void compileHtml(Source source) {
145136
// TODO(jmesserly): reuse DartScriptsTask instead of copy/paste.
146137
var contents = context.getContents(source);

pkg/dev_compiler/lib/src/info.dart

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ library dev_compiler.src.info;
99
import 'package:analyzer/src/generated/ast.dart';
1010
import 'package:analyzer/src/generated/element.dart';
1111
import 'package:analyzer/src/generated/error.dart';
12+
import 'package:analyzer/src/generated/parser.dart';
1213

1314
import 'package:dev_compiler/src/checker/rules.dart';
1415
import 'package:dev_compiler/src/utils.dart' as utils;
@@ -53,6 +54,43 @@ class LibraryUnit {
5354
yield* parts;
5455
yield library;
5556
}
57+
58+
/// Creates a clone of this library's AST.
59+
LibraryUnit clone() {
60+
return new LibraryUnit(
61+
_cloneUnit(library), parts.map(_cloneUnit).toList(growable: false));
62+
}
63+
64+
static CompilationUnit _cloneUnit(CompilationUnit oldNode) {
65+
var newNode = oldNode.accept(new _AstCloner());
66+
ResolutionCopier.copyResolutionData(oldNode, newNode);
67+
return newNode;
68+
}
69+
}
70+
71+
class _AstCloner extends AstCloner {
72+
void _cloneProperties(AstNode clone, AstNode node) {
73+
if (clone != null) {
74+
CoercionInfo.set(clone, CoercionInfo.get(node));
75+
DynamicInvoke.set(clone, DynamicInvoke.get(node));
76+
}
77+
}
78+
79+
@override
80+
AstNode cloneNode(AstNode node) {
81+
var clone = super.cloneNode(node);
82+
_cloneProperties(clone, node);
83+
return clone;
84+
}
85+
86+
@override
87+
List cloneNodeList(List list) {
88+
var clone = super.cloneNodeList(list);
89+
for (int i = 0, len = list.length; i < len; i++) {
90+
_cloneProperties(clone[i], list[i]);
91+
}
92+
return clone;
93+
}
5694
}
5795

5896
// The abstract type of coercions mapping one type to another.

pkg/dev_compiler/pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ description: >
66
author: Dart Dev Compiler team <[email protected]>
77
homepage: https://github.com/dart-lang/dev_compiler
88
dependencies:
9-
analyzer: ^0.25.1
9+
analyzer: ^0.25.3-alpha.2
1010
args: ^0.13.0
1111
cli_util: ^0.0.1
1212
crypto: ^0.9.0

pkg/dev_compiler/test/codegen/expect/sunflower/dom.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
dart_library.library('sunflower/dom', window, /* Imports */[
1+
dart_library.library('dom', window, /* Imports */[
22
"dart_runtime/dart",
33
'dart/core'
44
], /* Lazy imports */[
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
// Messages from compiling syncstar_yield_test.dart
2+
info: [DynamicCast] expected (dynamic) will need runtime check to cast to type String (test/codegen/expect.dart, line 97, col 51)
3+
info: [DynamicCast] actual (dynamic) will need runtime check to cast to type String (test/codegen/expect.dart, line 97, col 61)
24
info: [DynamicInvoke] check(e) requires dynamic invoke (test/codegen/expect.dart, line 372, col 14)
35
info: [DynamicCast] p (dynamic) will need runtime check to cast to type num (test/codegen/syncstar_yield_test.dart, line 17, col 28)

pkg/dev_compiler/test/codegen/expect/syncstar_yieldstar_test.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
// Messages from compiling syncstar_yieldstar_test.dart
2+
info: [DynamicCast] expected (dynamic) will need runtime check to cast to type String (test/codegen/expect.dart, line 97, col 51)
3+
info: [DynamicCast] actual (dynamic) will need runtime check to cast to type String (test/codegen/expect.dart, line 97, col 61)
24
info: [DynamicInvoke] check(e) requires dynamic invoke (test/codegen/expect.dart, line 372, col 14)
35
info: [DynamicCast] foo().take(9).toList() (dynamic) will need runtime check to cast to type List<dynamic> (test/codegen/syncstar_yieldstar_test.dart, line 28, col 53)
46
info: [DynamicInvoke] foo().take(9).toList() requires dynamic invoke (test/codegen/syncstar_yieldstar_test.dart, line 28, col 53)

0 commit comments

Comments
 (0)