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

Side by Side Diff: lib/src/codegen/js_names.dart

Issue 1133593004: fixes #131, use before define from variables to classes (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: fix static fields Created 5 years, 7 months 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
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, 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 dev_compiler.src.codegen.js_names; 5 library dev_compiler.src.codegen.js_names;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 import 'package:dev_compiler/src/js/js_ast.dart'; 8 import 'package:dev_compiler/src/js/js_ast.dart';
9 9
10 /// Unique instance for temporary variables. Will be renamed consistently 10 /// Unique instance for temporary variables. Will be renamed consistently
11 /// across the entire file. Different instances will be named differently 11 /// across the entire file. Different instances will be named differently
12 /// even if they have the same name, this makes it safe to use in code 12 /// even if they have the same name, this makes it safe to use in code
13 /// generation without needing global knowledge. See [JSNamer]. 13 /// generation without needing global knowledge. See [JSNamer].
14 /// 14 ///
15 // TODO(jmesserly): move into js_ast? add a boolean to Identifier? 15 // TODO(jmesserly): move into js_ast? add a boolean to Identifier?
16 class TemporaryId extends Identifier { 16 class TemporaryId extends Identifier {
17 static int __id = 0;
Jennifer Messerly 2015/05/12 16:23:46 this helped for debugging, I could remove it thoug
18 final int _id = ++__id;
17 TemporaryId(String name) : super(name); 19 TemporaryId(String name) : super(name);
20 toString() => super.toString() + ' $_id';
21 }
22
23 /// Creates a qualified identifier, without determining for sure if it needs to
24 /// be qualified until [setQualified] is called.
25 ///
26 /// This expression is transparent to visiting after [setQualified].
27 class MaybeQualifiedId extends Expression {
28 Expression _expr;
29
30 final Identifier qualifier;
31 final Expression name;
32
33 MaybeQualifiedId(this.qualifier, this.name) {
34 _expr = new PropertyAccess(qualifier, name);
35 }
36
37 /// Helper to create an [Identifier] from something that starts as a property.
38 static identifier(LiteralString propertyName) =>
39 new Identifier(propertyName.valueWithoutQuotes);
40
41 void setQualified(bool qualified) {
42 if (!qualified && name is LiteralString) {
43 _expr = identifier(name);
44 }
45 }
46
47 int get precedenceLevel => _expr.precedenceLevel;
48
49 accept(NodeVisitor visitor) => _expr.accept(visitor);
50
51 void visitChildren(NodeVisitor visitor) => _expr.visitChildren(visitor);
18 } 52 }
19 53
20 /// This class has two purposes: 54 /// This class has two purposes:
21 /// 55 ///
22 /// * rename JS identifiers to avoid keywords. 56 /// * rename JS identifiers to avoid keywords.
23 /// * rename temporary variables to avoid colliding with user-specified names, 57 /// * rename temporary variables to avoid colliding with user-specified names,
24 /// or other temporaries 58 /// or other temporaries
25 /// 59 ///
26 /// Each instance of [JSTemporary] is treated as a unique variable, with its 60 /// Each instance of [TemporaryId] is treated as a unique variable, with its
27 /// `name` field simply the suggestion of what name to use. By contrast 61 /// `name` field simply the suggestion of what name to use. By contrast
28 /// [Identifiers] are never renamed unless they are an invalid identifier, like 62 /// [Identifiers] are never renamed unless they are an invalid identifier, like
29 /// `function` or `instanceof`, and their `name` field controls whether they 63 /// `function` or `instanceof`, and their `name` field controls whether they
30 /// refer to the same variable. 64 /// refer to the same variable.
31 class TemporaryNamer extends LocalNamer { 65 class TemporaryNamer extends LocalNamer {
32 final Map<Object, String> renames; 66 final Map<Object, String> renames;
33 67
34 TemporaryNamer(Node node) : renames = new _RenameVisitor.build(node).renames; 68 TemporaryNamer(Node node) : renames = new _RenameVisitor.build(node).renames;
35 69
36 String getName(Identifier node) { 70 String getName(Identifier node) {
(...skipping 26 matching lines...) Expand all
63 97
64 /// Nested functions, these are visited after everything else so the names 98 /// Nested functions, these are visited after everything else so the names
65 /// they might need are in scope. 99 /// they might need are in scope.
66 final functions = new List<FunctionExpression>(); 100 final functions = new List<FunctionExpression>();
67 101
68 _FunctionScope(this.parent); 102 _FunctionScope(this.parent);
69 } 103 }
70 104
71 /// Collects all names used in the visited tree. 105 /// Collects all names used in the visited tree.
72 class _RenameVisitor extends VariableDeclarationVisitor { 106 class _RenameVisitor extends VariableDeclarationVisitor {
73 final pendingRenames = new Map<Object, Set<_FunctionScope>>(); 107 final pendingRenames = new Map<Object, Set<_FunctionScope>>.identity();
74 final renames = new HashMap<Object, String>(); 108 final renames = new HashMap<Object, String>.identity();
75 109
76 final _FunctionScope rootScope = new _FunctionScope(null); 110 final _FunctionScope rootScope = new _FunctionScope(null);
77 _FunctionScope scope; 111 _FunctionScope scope;
78 112
79 _RenameVisitor.build(Node root) { 113 _RenameVisitor.build(Node root) {
80 scope = rootScope; 114 scope = rootScope;
81 root.accept(this); 115 root.accept(this);
82 _finishFunctions(); 116 _finishFunctions();
83 _finishNames(); 117 _finishNames();
84 } 118 }
(...skipping 23 matching lines...) Expand all
108 _markUsed(node, id, declScope); 142 _markUsed(node, id, declScope);
109 } 143 }
110 144
111 _markUsed(Identifier node, Object id, _FunctionScope declScope) { 145 _markUsed(Identifier node, Object id, _FunctionScope declScope) {
112 // If it needs rename, we can't add it to the used name set yet, instead we 146 // If it needs rename, we can't add it to the used name set yet, instead we
113 // will record all scopes it is visible in. 147 // will record all scopes it is visible in.
114 Set<_FunctionScope> usedIn = null; 148 Set<_FunctionScope> usedIn = null;
115 if (needsRename(node)) { 149 if (needsRename(node)) {
116 usedIn = pendingRenames.putIfAbsent(id, () => new HashSet()); 150 usedIn = pendingRenames.putIfAbsent(id, () => new HashSet());
117 } 151 }
118
119 for (var s = scope, end = declScope.parent; s != end; s = s.parent) { 152 for (var s = scope, end = declScope.parent; s != end; s = s.parent) {
120 if (usedIn != null) { 153 if (usedIn != null) {
121 usedIn.add(s); 154 usedIn.add(s);
122 } else { 155 } else {
123 s.used.add(node.name); 156 s.used.add(node.name);
124 } 157 }
125 } 158 }
126 } 159 }
127 160
128 visitFunctionExpression(FunctionExpression node) { 161 visitFunctionExpression(FunctionExpression node) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
177 candidate = '${name}\$$i'; 210 candidate = '${name}\$$i';
178 } 211 }
179 } 212 }
180 return candidate; 213 return candidate;
181 } 214 }
182 } 215 }
183 216
184 bool needsRename(Identifier node) => 217 bool needsRename(Identifier node) =>
185 node is TemporaryId || node.allowRename && invalidVariableName(node.name); 218 node is TemporaryId || node.allowRename && invalidVariableName(node.name);
186 219
187 Object /*String|JSTemporary*/ identifierKey(Identifier node) => 220 Object /*String|TemporaryId*/ identifierKey(Identifier node) =>
188 node is TemporaryId ? node : node.name; 221 node is TemporaryId ? node : node.name;
189 222
190 /// Returns true for invalid JS variable names, such as keywords. 223 /// Returns true for invalid JS variable names, such as keywords.
191 /// Also handles invalid variable names in strict mode, like "arguments". 224 /// Also handles invalid variable names in strict mode, like "arguments".
192 bool invalidVariableName(String keyword, {bool strictMode: true}) { 225 bool invalidVariableName(String keyword, {bool strictMode: true}) {
193 switch (keyword) { 226 switch (keyword) {
194 case "break": 227 case "break":
195 case "case": 228 case "case":
196 case "catch": 229 case "catch":
197 case "class": 230 case "class":
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 /// In particular, "caller" "callee" and "arguments" cannot be used. 271 /// In particular, "caller" "callee" and "arguments" cannot be used.
239 bool invalidStaticFieldName(String name) { 272 bool invalidStaticFieldName(String name) {
240 switch (name) { 273 switch (name) {
241 case "arguments": 274 case "arguments":
242 case "caller": 275 case "caller":
243 case "callee": 276 case "callee":
244 return true; 277 return true;
245 } 278 }
246 return false; 279 return false;
247 } 280 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698