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

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

Issue 1633003002: Add --modules=node support (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: regen sdk and expectations Created 4 years, 11 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_codegen; 5 library dev_compiler.src.codegen.js_codegen;
6 6
7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet; 7 import 'dart:collection' show HashSet, HashMap, SplayTreeSet;
8 8
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator;
10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; 10 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator;
11 import 'package:analyzer/src/generated/constant.dart'; 11 import 'package:analyzer/src/generated/constant.dart';
12 import 'package:analyzer/src/generated/element.dart'; 12 import 'package:analyzer/src/generated/element.dart';
13 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; 13 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
14 import 'package:analyzer/src/generated/scanner.dart' 14 import 'package:analyzer/src/generated/scanner.dart'
15 show StringToken, Token, TokenType; 15 show StringToken, Token, TokenType;
16 import 'package:analyzer/src/generated/type_system.dart' 16 import 'package:analyzer/src/generated/type_system.dart'
17 show StrongTypeSystemImpl; 17 show StrongTypeSystemImpl;
18 import 'package:analyzer/src/task/dart.dart' show PublicNamespaceBuilder; 18 import 'package:analyzer/src/task/dart.dart' show PublicNamespaceBuilder;
19 19
20 import 'ast_builder.dart' show AstBuilder; 20 import 'ast_builder.dart' show AstBuilder;
21 import 'reify_coercions.dart' show CoercionReifier, Tuple2; 21 import 'reify_coercions.dart' show CoercionReifier, Tuple2;
22 22
23 // TODO(jmesserly): import from its own package 23 // TODO(jmesserly): import from its own package
24 import '../js/js_ast.dart' as JS; 24 import '../js/js_ast.dart' as JS;
25 import '../js/js_ast.dart' show js; 25 import '../js/js_ast.dart' show js;
26 26
27 import '../closure/closure_annotator.dart' show ClosureAnnotator; 27 import '../closure/closure_annotator.dart' show ClosureAnnotator;
28 import '../compiler.dart' show AbstractCompiler; 28 import '../compiler.dart' show AbstractCompiler, corelibUriOrder;
29 import '../info.dart'; 29 import '../info.dart';
30 import '../options.dart' show CodegenOptions; 30 import '../options.dart' show CodegenOptions;
31 import '../utils.dart'; 31 import '../utils.dart';
32 32
33 import 'code_generator.dart'; 33 import 'code_generator.dart';
34 import 'js_field_storage.dart'; 34 import 'js_field_storage.dart';
35 import 'js_interop.dart'; 35 import 'js_interop.dart';
36 import 'js_names.dart' as JS; 36 import 'js_names.dart' as JS;
37 import 'js_metalet.dart' as JS; 37 import 'js_metalet.dart' as JS;
38 import 'js_module_item_order.dart'; 38 import 'js_module_item_order.dart';
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
73 Expression _cascadeTarget; 73 Expression _cascadeTarget;
74 74
75 /// The variable for the current catch clause 75 /// The variable for the current catch clause
76 SimpleIdentifier _catchParameter; 76 SimpleIdentifier _catchParameter;
77 77
78 /// In an async* function, this represents the stream controller parameter. 78 /// In an async* function, this represents the stream controller parameter.
79 JS.TemporaryId _asyncStarController; 79 JS.TemporaryId _asyncStarController;
80 80
81 /// Imported libraries, and the temporaries used to refer to them. 81 /// Imported libraries, and the temporaries used to refer to them.
82 final _imports = new Map<LibraryElement, JS.TemporaryId>(); 82 final _imports = new Map<LibraryElement, JS.TemporaryId>();
83 final _exports = new Set<String>(); 83 final _exports = <String, String>{};
84 final _lazyFields = <VariableDeclaration>[]; 84 final _lazyFields = <VariableDeclaration>[];
85 final _properties = <FunctionDeclaration>[]; 85 final _properties = <FunctionDeclaration>[];
86 final _privateNames = new HashMap<String, JS.TemporaryId>(); 86 final _privateNames = new HashMap<String, JS.TemporaryId>();
87 final _moduleItems = <JS.Statement>[]; 87 final _moduleItems = <JS.Statement>[];
88 final _temps = new HashMap<Element, JS.TemporaryId>(); 88 final _temps = new HashMap<Element, JS.TemporaryId>();
89 final _qualifiedIds = new List<Tuple2<Element, JS.MaybeQualifiedId>>(); 89 final _qualifiedIds = new List<Tuple2<Element, JS.MaybeQualifiedId>>();
90 90
91 /// The name for the library's exports inside itself. 91 /// The name for the library's exports inside itself.
92 /// `exports` was chosen as the most similar to ES module patterns. 92 /// `exports` was chosen as the most similar to ES module patterns.
93 final _dartxVar = new JS.Identifier('dartx'); 93 final _dartxVar = new JS.Identifier('dartx');
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
172 _flushLibraryProperties(_moduleItems); 172 _flushLibraryProperties(_moduleItems);
173 173
174 // Mark all qualified names as qualified or not, depending on if they need 174 // Mark all qualified names as qualified or not, depending on if they need
175 // to be loaded lazily or not. 175 // to be loaded lazily or not.
176 for (var elementIdPairs in _qualifiedIds) { 176 for (var elementIdPairs in _qualifiedIds) {
177 var element = elementIdPairs.e0; 177 var element = elementIdPairs.e0;
178 var id = elementIdPairs.e1; 178 var id = elementIdPairs.e1;
179 id.setQualified(!_loader.isLoaded(element)); 179 id.setQualified(!_loader.isLoaded(element));
180 } 180 }
181 181
182 var moduleBuilder = new ModuleBuilder( 182 var moduleBuilder = new ModuleBuilder(options.moduleFormat);
183 compiler.getModuleName(currentLibrary.source.uri),
184 _jsModuleValue,
185 _exportsVar,
186 options.moduleFormat);
187
188 _exports.forEach(moduleBuilder.addExport); 183 _exports.forEach(moduleBuilder.addExport);
189 184
190 var items = <JS.ModuleItem>[]; 185 var items = <JS.ModuleItem>[];
191 if (!_isDartRuntime) { 186 if (!_isDartRuntime) {
187 if (currentLibrary.source.isInSystemLibrary) {
188 // Force the import order of runtime libs.
189 // TODO(ochafik): Reduce this to a minimum.
190 for (var lib in corelibUriOrder.reversed) {
191 moduleBuilder.addImport(lib.replaceAll(':', '/'), null);
192 }
193 }
192 moduleBuilder.addImport('dart/_runtime', _runtimeLibVar); 194 moduleBuilder.addImport('dart/_runtime', _runtimeLibVar);
193 195
194 var dartxImport = 196 var dartxImport =
195 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]); 197 js.statement("let # = #.dartx;", [_dartxVar, _runtimeLibVar]);
196 items.add(dartxImport); 198 items.add(dartxImport);
197 } 199 }
198 items.addAll(_moduleItems); 200 items.addAll(_moduleItems);
199 201
200 _imports.forEach((LibraryElement lib, JS.TemporaryId temp) { 202 _imports.forEach((LibraryElement lib, JS.TemporaryId temp) {
201 moduleBuilder.addImport(compiler.getModuleName(lib.source.uri), temp, 203 moduleBuilder.addImport(compiler.getModuleName(lib.source.uri), temp,
202 isLazy: _isDartRuntime || !_loader.libraryIsLoaded(lib)); 204 isLazy: _isDartRuntime || !_loader.libraryIsLoaded(lib));
203 }); 205 });
204 206
205 // TODO(jmesserly): scriptTag support. 207 // TODO(jmesserly): scriptTag support.
206 // Enable this if we know we're targetting command line environment? 208 // Enable this if we know we're targetting command line environment?
207 // It doesn't work in browser. 209 // It doesn't work in browser.
208 // var jsBin = compiler.options.runnerOptions.v8Binary; 210 // var jsBin = compiler.options.runnerOptions.v8Binary;
209 // String scriptTag = null; 211 // String scriptTag = null;
210 // if (library.library.scriptTag != null) scriptTag = '/usr/bin/env $jsBin'; 212 // if (library.library.scriptTag != null) scriptTag = '/usr/bin/env $jsBin';
211 return moduleBuilder.build(items); 213 return moduleBuilder.build(
214 compiler.getModuleName(currentLibrary.source.uri),
215 _jsModuleValue,
216 _exportsVar,
217 items);
212 } 218 }
213 219
214 void _emitModuleItem(AstNode node) { 220 void _emitModuleItem(AstNode node) {
215 // Attempt to group adjacent fields/properties. 221 // Attempt to group adjacent fields/properties.
216 if (node is! VariableDeclaration) _flushLazyFields(_moduleItems); 222 if (node is! VariableDeclaration) _flushLazyFields(_moduleItems);
217 if (node is! FunctionDeclaration) _flushLibraryProperties(_moduleItems); 223 if (node is! FunctionDeclaration) _flushLibraryProperties(_moduleItems);
218 224
219 var code = _visit(node); 225 var code = _visit(node);
220 if (code != null) _moduleItems.add(code); 226 if (code != null) _moduleItems.add(code);
221 } 227 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
259 .where((s) => !currentLibNames.containsKey(s)) 265 .where((s) => !currentLibNames.containsKey(s))
260 .map((s) => js.string(s, "'"))); 266 .map((s) => js.string(s, "'")));
261 } 267 }
262 if (hide != null) { 268 if (hide != null) {
263 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'"))); 269 hiddenNames.addAll(hide.hiddenNames.map((i) => js.string(i.name, "'")));
264 } 270 }
265 args.add(new JS.ArrayInitializer(shownNames)); 271 args.add(new JS.ArrayInitializer(shownNames));
266 args.add(new JS.ArrayInitializer(hiddenNames)); 272 args.add(new JS.ArrayInitializer(hiddenNames));
267 } 273 }
268 274
269 // When we compile _runtime.js, we need to source export_ from _utils.js: 275 _moduleItems.add(js.statement('dart.export_(#);', [args]));
270 _moduleItems.add(js.statement('dart.export(#);', [args]));
271 } 276 }
272 277
273 JS.Identifier _initSymbol(JS.Identifier id) { 278 JS.Identifier _initSymbol(JS.Identifier id) {
274 var s = 279 var s =
275 js.statement('const # = $_SYMBOL(#);', [id, js.string(id.name, "'")]); 280 js.statement('const # = $_SYMBOL(#);', [id, js.string(id.name, "'")]);
276 _moduleItems.add(s); 281 _moduleItems.add(s);
277 return id; 282 return id;
278 } 283 }
279 284
280 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core, 285 // TODO(jmesserly): this is a temporary workaround for `Symbol` in core,
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
523 return js.statement( 528 return js.statement(
524 'dart.defineLazyClass(#, { get #() { #; return #; } });', 529 'dart.defineLazyClass(#, { get #() { #; return #; } });',
525 [_exportsVar, _propertyName(name), body, name]); 530 [_exportsVar, _propertyName(name), body, name]);
526 } 531 }
527 532
528 if (isPublic(name)) _addExport(name); 533 if (isPublic(name)) _addExport(name);
529 534
530 if (genericDef != null) { 535 if (genericDef != null) {
531 var dynType = fillDynamicTypeArgs(type, types); 536 var dynType = fillDynamicTypeArgs(type, types);
532 var genericInst = _emitTypeName(dynType, lowerGeneric: true); 537 var genericInst = _emitTypeName(dynType, lowerGeneric: true);
533 return js.statement('{ #; let # = #; }', [genericDef, name, genericInst]); 538 return js
539 .statement('{ #; const # = #; }', [genericDef, name, genericInst]);
534 } 540 }
535 return body; 541 return body;
536 } 542 }
537 543
538 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) { 544 JS.Statement _emitGenericClassDef(ParameterizedType type, JS.Statement body) {
539 var name = type.name; 545 var name = type.name;
540 var genericName = '$name\$'; 546 var genericName = '$name\$';
541 var typeParams = _boundTypeParametersOf(type).map((p) => p.name); 547 var typeParams = _boundTypeParametersOf(type).map((p) => p.name);
542 if (isPublic(name)) _exports.add(genericName); 548 if (isPublic(name)) _addExport(genericName);
543 return js.statement('const # = dart.generic(function(#) { #; return #; });', 549 return js.statement('const # = dart.generic(function(#) { #; return #; });',
544 [genericName, typeParams, body, name]); 550 [genericName, typeParams, body, name]);
545 } 551 }
546 552
547 final _hasDeferredSupertype = new HashSet<ClassElement>(); 553 final _hasDeferredSupertype = new HashSet<ClassElement>();
548 554
549 bool _deferIfNeeded(DartType type, ClassElement current) { 555 bool _deferIfNeeded(DartType type, ClassElement current) {
550 if (type is ParameterizedType) { 556 if (type is ParameterizedType) {
551 var typeArguments = type.typeArguments; 557 var typeArguments = type.typeArguments;
552 for (var typeArg in typeArguments) { 558 for (var typeArg in typeArguments) {
(...skipping 725 matching lines...) Expand 10 before | Expand all | Expand 10 after
1278 1284
1279 if (node.isGetter || node.isSetter) { 1285 if (node.isGetter || node.isSetter) {
1280 // Add these later so we can use getter/setter syntax. 1286 // Add these later so we can use getter/setter syntax.
1281 _properties.add(node); 1287 _properties.add(node);
1282 return null; 1288 return null;
1283 } 1289 }
1284 1290
1285 var body = <JS.Statement>[]; 1291 var body = <JS.Statement>[];
1286 _flushLibraryProperties(body); 1292 _flushLibraryProperties(body);
1287 1293
1288 var name = _getJSExportName(node.element) ?? node.name.name; 1294 var name = node.name.name;
1289 1295
1290 var fn = _visit(node.functionExpression); 1296 var fn = _visit(node.functionExpression);
1291 1297
1292 if (currentLibrary.source.isInSystemLibrary && 1298 if (currentLibrary.source.isInSystemLibrary &&
1293 _isInlineJSFunction(node.functionExpression)) { 1299 _isInlineJSFunction(node.functionExpression)) {
1294 fn = _simplifyPassThroughArrowFunCallBody(fn); 1300 fn = _simplifyPassThroughArrowFunCallBody(fn);
1295 } 1301 }
1296 1302
1297 var id = new JS.Identifier(name); 1303 var id = new JS.Identifier(name);
1298 body.add(annotate(new JS.FunctionDeclaration(id, fn), node.element)); 1304 body.add(annotate(new JS.FunctionDeclaration(id, fn), node.element));
1299 if (!_isDartRuntime) { 1305 if (!_isDartRuntime) {
1300 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true) 1306 body.add(_emitFunctionTagged(id, node.element.type, topLevel: true)
1301 .toStatement()); 1307 .toStatement());
1302 } 1308 }
1303 1309
1304 if (isPublic(name)) _addExport(name); 1310 if (isPublic(name)) {
1311 _addExport(name, _getJSExportName(node.element) ?? name);
1312 }
1305 return _statement(body); 1313 return _statement(body);
1306 } 1314 }
1307 1315
1308 bool _isInlineJSFunction(FunctionExpression functionExpression) { 1316 bool _isInlineJSFunction(FunctionExpression functionExpression) {
1309 var body = functionExpression.body; 1317 var body = functionExpression.body;
1310 if (body is ExpressionFunctionBody) { 1318 if (body is ExpressionFunctionBody) {
1311 return _isJSInvocation(body.expression); 1319 return _isJSInvocation(body.expression);
1312 } else if (body is BlockFunctionBody) { 1320 } else if (body is BlockFunctionBody) {
1313 if (body.block.statements.length == 1) { 1321 if (body.block.statements.length == 1) {
1314 var stat = body.block.statements.single; 1322 var stat = body.block.statements.single;
(...skipping 413 matching lines...) Expand 10 before | Expand all | Expand 10 after
1728 var genericName = _emitTopLevelName(element, suffix: '\$'); 1736 var genericName = _emitTopLevelName(element, suffix: '\$');
1729 return js.call('#(#)', [genericName, jsArgs]); 1737 return js.call('#(#)', [genericName, jsArgs]);
1730 } 1738 }
1731 } 1739 }
1732 1740
1733 return _emitTopLevelName(element); 1741 return _emitTopLevelName(element);
1734 } 1742 }
1735 1743
1736 JS.Expression _emitTopLevelName(Element e, {String suffix: ''}) { 1744 JS.Expression _emitTopLevelName(Element e, {String suffix: ''}) {
1737 var libName = _libraryName(e.library); 1745 var libName = _libraryName(e.library);
1738 var nameExpr = _propertyName((_getJSExportName(e) ?? e.name) + suffix);
1739 1746
1740 // Always qualify: 1747 // Always qualify:
1741 // * mutable top-level fields 1748 // * mutable top-level fields
1742 // * elements from other libraries 1749 // * elements from other libraries
1743 bool mutableTopLevel = e is TopLevelVariableElement && 1750 bool mutableTopLevel = e is TopLevelVariableElement &&
1744 !e.isConst && 1751 !e.isConst &&
1745 !_isFinalJSDecl(e.computeNode()); 1752 !_isFinalJSDecl(e.computeNode());
1746 bool fromAnotherLibrary = e.library != currentLibrary; 1753 bool fromAnotherLibrary = e.library != currentLibrary;
1754 var nameExpr;
1755 if (fromAnotherLibrary) {
1756 nameExpr = _propertyName((_getJSExportName(e) ?? e.name) + suffix);
1757 } else {
1758 nameExpr = _propertyName(e.name + suffix);
1759 }
1747 if (mutableTopLevel || fromAnotherLibrary) { 1760 if (mutableTopLevel || fromAnotherLibrary) {
1748 return new JS.PropertyAccess(libName, nameExpr); 1761 return new JS.PropertyAccess(libName, nameExpr);
1749 } 1762 }
1750 1763
1751 var id = new JS.MaybeQualifiedId(libName, nameExpr); 1764 var id = new JS.MaybeQualifiedId(libName, nameExpr);
1752 _qualifiedIds.add(new Tuple2(e, id)); 1765 _qualifiedIds.add(new Tuple2(e, id));
1753 return id; 1766 return id;
1754 } 1767 }
1755 1768
1756 @override 1769 @override
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after
2129 /// [visitTopLevelVariableDeclaration]. 2142 /// [visitTopLevelVariableDeclaration].
2130 @override 2143 @override
2131 visitFieldDeclaration(FieldDeclaration node) { 2144 visitFieldDeclaration(FieldDeclaration node) {
2132 if (!node.isStatic) return; 2145 if (!node.isStatic) return;
2133 2146
2134 for (var f in node.fields.variables) { 2147 for (var f in node.fields.variables) {
2135 _loader.loadDeclaration(f, f.element); 2148 _loader.loadDeclaration(f, f.element);
2136 } 2149 }
2137 } 2150 }
2138 2151
2139 _addExport(String name) { 2152 _addExport(String name, [String exportName]) {
2140 if (!_exports.add(name)) throw 'Duplicate top level name found: $name'; 2153 if (_exports.containsKey(name))
2154 throw 'Duplicate top level name found: $name';
2155 _exports[name] = exportName ?? name;
2141 } 2156 }
2142 2157
2143 @override 2158 @override
2144 JS.Statement visitVariableDeclarationStatement( 2159 JS.Statement visitVariableDeclarationStatement(
2145 VariableDeclarationStatement node) { 2160 VariableDeclarationStatement node) {
2146 // Special case a single variable with an initializer. 2161 // Special case a single variable with an initializer.
2147 // This helps emit cleaner code for things like: 2162 // This helps emit cleaner code for things like:
2148 // var result = []..add(1)..add(2); 2163 // var result = []..add(1)..add(2);
2149 if (node.variables.variables.length == 1) { 2164 if (node.variables.variables.length == 1) {
2150 var v = node.variables.variables.single; 2165 var v = node.variables.variables.single;
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
2192 jsInit = _visitInitializer(field); 2207 jsInit = _visitInitializer(field);
2193 eagerInit = false; 2208 eagerInit = false;
2194 } 2209 }
2195 2210
2196 // Treat `final x = JS('', '...')` as a const (non-lazy) to help compile 2211 // Treat `final x = JS('', '...')` as a const (non-lazy) to help compile
2197 // runtime helpers. 2212 // runtime helpers.
2198 var isJSTopLevel = field.isFinal && _isFinalJSDecl(field); 2213 var isJSTopLevel = field.isFinal && _isFinalJSDecl(field);
2199 if (isJSTopLevel) eagerInit = true; 2214 if (isJSTopLevel) eagerInit = true;
2200 2215
2201 var fieldName = field.name.name; 2216 var fieldName = field.name.name;
2217 var exportName = fieldName;
2202 if (element is TopLevelVariableElement) { 2218 if (element is TopLevelVariableElement) {
2203 fieldName = _getJSExportName(element) ?? fieldName; 2219 exportName = _getJSExportName(element) ?? fieldName;
2204 } 2220 }
2205 if ((field.isConst && eagerInit && element is TopLevelVariableElement) || 2221 if ((field.isConst && eagerInit && element is TopLevelVariableElement) ||
2206 isJSTopLevel) { 2222 isJSTopLevel) {
2207 // constant fields don't change, so we can generate them as `let` 2223 // constant fields don't change, so we can generate them as `let`
2208 // but add them to the module's exports. However, make sure we generate 2224 // but add them to the module's exports. However, make sure we generate
2209 // anything they depend on first. 2225 // anything they depend on first.
2210 2226
2211 if (isPublic(fieldName)) _addExport(fieldName); 2227 if (isPublic(fieldName)) _addExport(fieldName, exportName);
2212 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let'; 2228 var declKeyword = field.isConst || field.isFinal ? 'const' : 'let';
2213 return annotateVariable( 2229 return annotateVariable(
2214 js.statement( 2230 js.statement(
2215 '$declKeyword # = #;', [new JS.Identifier(fieldName), jsInit]), 2231 '$declKeyword # = #;', [new JS.Identifier(fieldName), jsInit]),
2216 field.element); 2232 field.element);
2217 } 2233 }
2218 2234
2219 if (eagerInit && !JS.invalidStaticFieldName(fieldName)) { 2235 if (eagerInit && !JS.invalidStaticFieldName(fieldName)) {
2220 return annotateVariable( 2236 return annotateVariable(
2221 js.statement('# = #;', [_visit(field.name), jsInit]), field.element); 2237 js.statement('# = #;', [_visit(field.name), jsInit]), field.element);
(...skipping 1370 matching lines...) Expand 10 before | Expand all | Expand 10 after
3592 3608
3593 /// A special kind of element created by the compiler, signifying a temporary 3609 /// A special kind of element created by the compiler, signifying a temporary
3594 /// variable. These objects use instance equality, and should be shared 3610 /// variable. These objects use instance equality, and should be shared
3595 /// everywhere in the tree where they are treated as the same variable. 3611 /// everywhere in the tree where they are treated as the same variable.
3596 class TemporaryVariableElement extends LocalVariableElementImpl { 3612 class TemporaryVariableElement extends LocalVariableElementImpl {
3597 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); 3613 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name);
3598 3614
3599 int get hashCode => identityHashCode(this); 3615 int get hashCode => identityHashCode(this);
3600 bool operator ==(Object other) => identical(this, other); 3616 bool operator ==(Object other) => identical(this, other);
3601 } 3617 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698