OLD | NEW |
---|---|
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; |
(...skipping 345 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
356 | 356 |
357 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name), | 357 var classExpr = new JS.ClassExpression(new JS.Identifier(type.name), |
358 _classHeritage(classElem), _emitClassMethods(node, ctors, fields)); | 358 _classHeritage(classElem), _emitClassMethods(node, ctors, fields)); |
359 | 359 |
360 String jsPeerName; | 360 String jsPeerName; |
361 var jsPeer = findAnnotation(classElem, _isJsPeerInterface); | 361 var jsPeer = findAnnotation(classElem, _isJsPeerInterface); |
362 if (jsPeer != null) { | 362 if (jsPeer != null) { |
363 jsPeerName = getConstantField(jsPeer, 'name', types.stringType); | 363 jsPeerName = getConstantField(jsPeer, 'name', types.stringType); |
364 } | 364 } |
365 | 365 |
366 var body = _finishClassMembers( | 366 var body = _finishClassMembers(classElem, classExpr, ctors, fields, methods, |
367 classElem, classExpr, ctors, fields, methods, jsPeerName); | 367 node.metadata, jsPeerName); |
368 | 368 |
369 var result = _finishClassDef(type, body); | 369 var result = _finishClassDef(type, body); |
370 | 370 |
371 if (jsPeerName != null) { | 371 if (jsPeerName != null) { |
372 // This class isn't allowed to be lazy, because we need to set up | 372 // This class isn't allowed to be lazy, because we need to set up |
373 // the native JS type eagerly at this point. | 373 // the native JS type eagerly at this point. |
374 // If we wanted to support laziness, we could defer the hookup until | 374 // If we wanted to support laziness, we could defer the hookup until |
375 // the end of the Dart library cycle load. | 375 // the end of the Dart library cycle load. |
376 assert(_loader.isLoaded(classElem)); | 376 assert(_loader.isLoaded(classElem)); |
377 | 377 |
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
534 var parentType = findSupertype(t, _implementsIterable); | 534 var parentType = findSupertype(t, _implementsIterable); |
535 if (parentType != null) return null; | 535 if (parentType != null) return null; |
536 | 536 |
537 // Otherwise, emit the adapter method, which wraps the Dart iterator in | 537 // Otherwise, emit the adapter method, which wraps the Dart iterator in |
538 // an ES6 iterator. | 538 // an ES6 iterator. |
539 return new JS.Method(js.call('$_SYMBOL.iterator'), js.call( | 539 return new JS.Method(js.call('$_SYMBOL.iterator'), js.call( |
540 'function() { return new dart.JsIterator(this.#); }', | 540 'function() { return new dart.JsIterator(this.#); }', |
541 [_emitMemberName('iterator', type: t)])); | 541 [_emitMemberName('iterator', type: t)])); |
542 } | 542 } |
543 | 543 |
544 JS.Expression _instantiateAnnotation(Annotation node) { | |
545 var element = node.element; | |
546 if (element is ConstructorElement) { | |
547 return _emitInstanceCreationExpression( | |
548 element, element.returnType, node.constructorName, node.arguments, tru e); | |
Jennifer Messerly
2015/06/09 23:29:53
./tool/format.sh ? :)
vsm
2015/06/10 13:28:27
Done. Sorry - uploaded too early.
| |
549 } else { | |
550 return _visit(node.name); | |
551 } | |
552 } | |
553 | |
544 /// Emit class members that need to come after the class declaration, such | 554 /// Emit class members that need to come after the class declaration, such |
545 /// as static fields. See [_emitClassMethods] for things that are emitted | 555 /// as static fields. See [_emitClassMethods] for things that are emitted |
546 /// inside the ES6 `class { ... }` node. | 556 /// inside the ES6 `class { ... }` node. |
547 JS.Statement _finishClassMembers(ClassElement classElem, | 557 JS.Statement _finishClassMembers(ClassElement classElem, |
548 JS.ClassExpression cls, List<ConstructorDeclaration> ctors, | 558 JS.ClassExpression cls, List<ConstructorDeclaration> ctors, |
549 List<FieldDeclaration> fields, List<MethodDeclaration> methods, | 559 List<FieldDeclaration> fields, List<MethodDeclaration> methods, |
550 String jsPeerName) { | 560 List<Annotation> metadata, String jsPeerName) { |
551 var name = classElem.name; | 561 var name = classElem.name; |
552 var body = <JS.Statement>[]; | 562 var body = <JS.Statement>[]; |
553 | 563 |
554 if (jsPeerName != null) { | 564 if (jsPeerName != null) { |
555 var dartxNames = []; | 565 var dartxNames = []; |
556 for (var m in methods) { | 566 for (var m in methods) { |
557 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { | 567 if (!m.isAbstract && !m.isStatic && m.element.isPublic) { |
558 dartxNames.add(_elementMemberName(m.element, allowExtensions: false)); | 568 dartxNames.add(_elementMemberName(m.element, allowExtensions: false)); |
559 } | 569 } |
560 } | 570 } |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
620 var property = | 630 var property = |
621 new JS.Property(memberName, new JS.ArrayInitializer(parts)); | 631 new JS.Property(memberName, new JS.ArrayInitializer(parts)); |
622 if (node.isStatic) { | 632 if (node.isStatic) { |
623 tStatics.add(property); | 633 tStatics.add(property); |
624 sNames.add(memberName); | 634 sNames.add(memberName); |
625 } else { | 635 } else { |
626 tMethods.add(property); | 636 tMethods.add(property); |
627 } | 637 } |
628 } | 638 } |
629 } | 639 } |
640 | |
630 var tCtors = []; | 641 var tCtors = []; |
631 for (ConstructorDeclaration node in ctors) { | 642 for (ConstructorDeclaration node in ctors) { |
632 var memberName = _constructorName(node.element); | 643 var memberName = _constructorName(node.element); |
633 var element = node.element; | 644 var element = node.element; |
634 var parts = | 645 var parts = |
635 _emitFunctionTypeParts(element.type, dynamicIsBottom: false); | 646 _emitFunctionTypeParts(element.type, dynamicIsBottom: false); |
636 var property = | 647 var property = |
637 new JS.Property(memberName, new JS.ArrayInitializer(parts)); | 648 new JS.Property(memberName, new JS.ArrayInitializer(parts)); |
638 tCtors.add(property); | 649 tCtors.add(property); |
639 } | 650 } |
651 | |
640 build(name, elements) { | 652 build(name, elements) { |
641 var o = | 653 var o = |
642 new JS.ObjectInitializer(elements, multiline: elements.length > 1); | 654 new JS.ObjectInitializer(elements, multiline: elements.length > 1); |
643 var e = js.call('() => #', o); | 655 var e = js.call('() => #', o); |
644 var p = new JS.Property(_propertyName(name), e); | 656 var p = new JS.Property(_propertyName(name), e); |
645 return p; | 657 return p; |
646 } | 658 } |
647 var sigFields = []; | 659 var sigFields = []; |
648 if (!tCtors.isEmpty) sigFields.add(build('constructors', tCtors)); | 660 if (!tCtors.isEmpty) sigFields.add(build('constructors', tCtors)); |
649 if (!tMethods.isEmpty) sigFields.add(build('methods', tMethods)); | 661 if (!tMethods.isEmpty) sigFields.add(build('methods', tMethods)); |
(...skipping 18 matching lines...) Expand all Loading... | |
668 var methodNames = []; | 680 var methodNames = []; |
669 for (var e in extensions) { | 681 for (var e in extensions) { |
670 methodNames.add(_elementMemberName(e)); | 682 methodNames.add(_elementMemberName(e)); |
671 } | 683 } |
672 body.add(js.statement('dart.defineExtensionMembers(#, #);', [ | 684 body.add(js.statement('dart.defineExtensionMembers(#, #);', [ |
673 name, | 685 name, |
674 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4) | 686 new JS.ArrayInitializer(methodNames, multiline: methodNames.length > 4) |
675 ])); | 687 ])); |
676 } | 688 } |
677 | 689 |
690 // Metadata | |
691 if (metadata.isNotEmpty) { | |
692 body.add(js.statement('#[dart.metadata] = () => #;', [ | |
693 name, | |
694 new JS.ArrayInitializer(metadata.map(_instantiateAnnotation).toList()) | |
695 ])); | |
696 } | |
697 | |
678 return _statement(body); | 698 return _statement(body); |
679 } | 699 } |
680 | 700 |
681 List<ExecutableElement> _extensionsToImplement(ClassElement element) { | 701 List<ExecutableElement> _extensionsToImplement(ClassElement element) { |
682 var members = <ExecutableElement>[]; | 702 var members = <ExecutableElement>[]; |
683 if (_extensionTypes.contains(element)) return members; | 703 if (_extensionTypes.contains(element)) return members; |
684 | 704 |
685 // Collect all extension types we implement. | 705 // Collect all extension types we implement. |
686 var type = element.type; | 706 var type = element.type; |
687 var types = new Set<ClassElement>(); | 707 var types = new Set<ClassElement>(); |
(...skipping 1048 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1736 | 1756 |
1737 void _flushLibraryProperties(List<JS.Statement> body) { | 1757 void _flushLibraryProperties(List<JS.Statement> body) { |
1738 if (_properties.isEmpty) return; | 1758 if (_properties.isEmpty) return; |
1739 body.add(js.statement('dart.copyProperties(#, { # });', [ | 1759 body.add(js.statement('dart.copyProperties(#, { # });', [ |
1740 _exportsVar, | 1760 _exportsVar, |
1741 _properties.map(_emitTopLevelProperty) | 1761 _properties.map(_emitTopLevelProperty) |
1742 ])); | 1762 ])); |
1743 _properties.clear(); | 1763 _properties.clear(); |
1744 } | 1764 } |
1745 | 1765 |
1746 @override | 1766 _emitConstructorName(ConstructorElement element, DartType type, SimpleIdentifi er name) { |
Jennifer Messerly
2015/06/09 23:29:53
return type?
vsm
2015/06/10 13:28:27
Done.
| |
1747 visitConstructorName(ConstructorName node) { | 1767 var typeName = _emitTypeName(type); |
1748 var typeName = _visit(node.type); | 1768 if (name != null || element.isFactory) { |
1749 var element = node.staticElement; | |
1750 if (node.name != null || element.isFactory) { | |
1751 var namedCtor = _constructorName(element); | 1769 var namedCtor = _constructorName(element); |
1752 return new JS.PropertyAccess(typeName, namedCtor); | 1770 return new JS.PropertyAccess(typeName, namedCtor); |
1753 } | 1771 } |
1754 return typeName; | 1772 return typeName; |
1755 } | 1773 } |
1756 | 1774 |
1757 @override | 1775 @override |
1776 visitConstructorName(ConstructorName node) { | |
1777 return _emitConstructorName(node.staticElement, node.type.type, node.name); | |
1778 } | |
1779 | |
1780 _emitInstanceCreationExpression(ConstructorElement element, DartType type, Sim pleIdentifier name, | |
1781 ArgumentList argumentList, bool isConst) { | |
1782 emitNew() { | |
1783 JS.Expression ctor; | |
1784 bool isFactory = false; | |
1785 // var element = node.staticElement; | |
1786 if (element == null) { | |
1787 // TODO(jmesserly): this only happens if we had a static error. | |
1788 // Should we generate a throw instead? | |
1789 ctor = _emitTypeName(type); | |
1790 if (name != null) { | |
1791 ctor = new JS.PropertyAccess(ctor, _propertyName(name.name)); | |
1792 } | |
1793 } else { | |
1794 ctor = _emitConstructorName(element, type, name); | |
1795 isFactory = element.isFactory; | |
1796 } | |
1797 var args = _visit(argumentList); | |
1798 return isFactory ? new JS.Call(ctor, args) : new JS.New(ctor, args); | |
1799 } | |
1800 if (isConst) return _emitConst(emitNew); | |
1801 return emitNew(); | |
1802 } | |
1803 | |
1804 @override | |
1758 visitInstanceCreationExpression(InstanceCreationExpression node) { | 1805 visitInstanceCreationExpression(InstanceCreationExpression node) { |
1759 emitNew() { | 1806 var element = node.staticElement; |
1760 JS.Expression ctor; | 1807 var constructor = node.constructorName; |
1761 bool isFactory = false; | 1808 var name = constructor.name; |
1762 var element = node.staticElement; | 1809 var type = constructor.type.type; |
1763 if (element == null) { | 1810 return _emitInstanceCreationExpression( |
1764 // TODO(jmesserly): this only happens if we had a static error. | 1811 element, type, name, node.argumentList, node.isConst); |
1765 // Should we generate a throw instead? | |
1766 ctor = _visit(node.constructorName.type); | |
1767 var ctorName = node.constructorName.name; | |
1768 if (ctorName != null) { | |
1769 ctor = new JS.PropertyAccess(ctor, _propertyName(ctorName.name)); | |
1770 } | |
1771 } else { | |
1772 ctor = _visit(node.constructorName); | |
1773 isFactory = element.isFactory; | |
1774 } | |
1775 var args = _visit(node.argumentList); | |
1776 return isFactory ? new JS.Call(ctor, args) : new JS.New(ctor, args); | |
1777 } | |
1778 if (node.isConst) return _emitConst(node, emitNew); | |
1779 return emitNew(); | |
1780 } | 1812 } |
1781 | 1813 |
1782 /// True if this type is built-in to JS, and we use the values unwrapped. | 1814 /// True if this type is built-in to JS, and we use the values unwrapped. |
1783 /// For these types we generate a calling convention via static | 1815 /// For these types we generate a calling convention via static |
1784 /// "extension methods". This allows types to be extended without adding | 1816 /// "extension methods". This allows types to be extended without adding |
1785 /// extensions directly on the prototype. | 1817 /// extensions directly on the prototype. |
1786 bool _isJSBuiltinType(DartType t) => | 1818 bool _isJSBuiltinType(DartType t) => |
1787 typeIsPrimitiveInJS(t) || rules.isStringType(t); | 1819 typeIsPrimitiveInJS(t) || rules.isStringType(t); |
1788 | 1820 |
1789 bool typeIsPrimitiveInJS(DartType t) => rules.isIntType(t) || | 1821 bool typeIsPrimitiveInJS(DartType t) => rules.isIntType(t) || |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1869 var jsExpr = _visit(expr); | 1901 var jsExpr = _visit(expr); |
1870 if (_isNonNullableExpression(expr)) return jsExpr; | 1902 if (_isNonNullableExpression(expr)) return jsExpr; |
1871 return js.call('dart.notNull(#)', jsExpr); | 1903 return js.call('dart.notNull(#)', jsExpr); |
1872 } | 1904 } |
1873 | 1905 |
1874 @override | 1906 @override |
1875 JS.Expression visitBinaryExpression(BinaryExpression node) { | 1907 JS.Expression visitBinaryExpression(BinaryExpression node) { |
1876 var op = node.operator; | 1908 var op = node.operator; |
1877 var left = node.leftOperand; | 1909 var left = node.leftOperand; |
1878 var right = node.rightOperand; | 1910 var right = node.rightOperand; |
1911 | |
1879 var leftType = getStaticType(left); | 1912 var leftType = getStaticType(left); |
1880 var rightType = getStaticType(right); | 1913 var rightType = getStaticType(right); |
1881 | 1914 |
1882 var code; | 1915 var code; |
1883 if (op.type.isEqualityOperator) { | 1916 if (op.type.isEqualityOperator) { |
1884 // If we statically know LHS or RHS is null we can generate a clean check. | 1917 // If we statically know LHS or RHS is null we can generate a clean check. |
1885 // We can also do this if both sides are the same primitive type. | 1918 // We can also do this if both sides are the same primitive type. |
1886 if (_canUsePrimitiveEquality(left, right)) { | 1919 if (_canUsePrimitiveEquality(left, right)) { |
1887 code = op.type == TokenType.EQ_EQ ? '# == #' : '# != #'; | 1920 code = op.type == TokenType.EQ_EQ ? '# == #' : '# != #'; |
1888 } else { | 1921 } else { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1938 // LocalVariableElementImpl, so we could repurpose to mean "temp". | 1971 // LocalVariableElementImpl, so we could repurpose to mean "temp". |
1939 // * add a new property to LocalVariableElementImpl. | 1972 // * add a new property to LocalVariableElementImpl. |
1940 // * create a new subtype of LocalVariableElementImpl to mark a temp. | 1973 // * create a new subtype of LocalVariableElementImpl to mark a temp. |
1941 var id = | 1974 var id = |
1942 new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, name, -1)); | 1975 new SimpleIdentifier(new StringToken(TokenType.IDENTIFIER, name, -1)); |
1943 id.staticElement = new TemporaryVariableElement.forNode(id); | 1976 id.staticElement = new TemporaryVariableElement.forNode(id); |
1944 id.staticType = type; | 1977 id.staticType = type; |
1945 return id; | 1978 return id; |
1946 } | 1979 } |
1947 | 1980 |
1948 JS.Expression _emitConst(Expression node, JS.Expression expr()) { | 1981 JS.Expression _emitConst(JS.Expression expr()) { |
1949 // TODO(jmesserly): emit the constants at top level if possible. | 1982 // TODO(jmesserly): emit the constants at top level if possible. |
1950 // This wasn't quite working, so disabled for now. | 1983 // This wasn't quite working, so disabled for now. |
1951 return js.call('dart.const(#)', expr()); | 1984 return js.call('dart.const(#)', expr()); |
1952 } | 1985 } |
1953 | 1986 |
1954 /// Returns a new expression, which can be be used safely *once* on the | 1987 /// Returns a new expression, which can be be used safely *once* on the |
1955 /// left hand side, and *once* on the right side of an assignment. | 1988 /// left hand side, and *once* on the right side of an assignment. |
1956 /// For example: `expr1[expr2] += y` can be compiled as | 1989 /// For example: `expr1[expr2] += y` can be compiled as |
1957 /// `expr1[expr2] = expr1[expr2] + y`. | 1990 /// `expr1[expr2] = expr1[expr2] + y`. |
1958 /// | 1991 /// |
(...skipping 470 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2429 visitNullLiteral(NullLiteral node) => new JS.LiteralNull(); | 2462 visitNullLiteral(NullLiteral node) => new JS.LiteralNull(); |
2430 | 2463 |
2431 @override | 2464 @override |
2432 visitSymbolLiteral(SymbolLiteral node) { | 2465 visitSymbolLiteral(SymbolLiteral node) { |
2433 emitSymbol() { | 2466 emitSymbol() { |
2434 // TODO(vsm): When we canonicalize, we need to treat private symbols | 2467 // TODO(vsm): When we canonicalize, we need to treat private symbols |
2435 // correctly. | 2468 // correctly. |
2436 var name = js.string(node.components.join('.'), "'"); | 2469 var name = js.string(node.components.join('.'), "'"); |
2437 return new JS.New(_emitTypeName(types.symbolType), [name]); | 2470 return new JS.New(_emitTypeName(types.symbolType), [name]); |
2438 } | 2471 } |
2439 return _emitConst(node, emitSymbol); | 2472 return _emitConst(emitSymbol); |
2440 } | 2473 } |
2441 | 2474 |
2442 @override | 2475 @override |
2443 visitListLiteral(ListLiteral node) { | 2476 visitListLiteral(ListLiteral node) { |
2444 emitList() { | 2477 emitList() { |
2445 JS.Expression list = new JS.ArrayInitializer(_visitList(node.elements)); | 2478 JS.Expression list = new JS.ArrayInitializer(_visitList(node.elements)); |
2446 ParameterizedType type = node.staticType; | 2479 ParameterizedType type = node.staticType; |
2447 var elementType = type.typeArguments.single; | 2480 var elementType = type.typeArguments.single; |
2448 if (elementType != types.dynamicType) { | 2481 if (elementType != types.dynamicType) { |
2449 list = js.call('dart.list(#, #)', [list, _emitTypeName(elementType)]); | 2482 list = js.call('dart.list(#, #)', [list, _emitTypeName(elementType)]); |
2450 } | 2483 } |
2451 return list; | 2484 return list; |
2452 } | 2485 } |
2453 if (node.constKeyword != null) return _emitConst(node, emitList); | 2486 if (node.constKeyword != null) return _emitConst(emitList); |
2454 return emitList(); | 2487 return emitList(); |
2455 } | 2488 } |
2456 | 2489 |
2457 @override | 2490 @override |
2458 visitMapLiteral(MapLiteral node) { | 2491 visitMapLiteral(MapLiteral node) { |
2459 // TODO(jmesserly): we can likely make these faster. | 2492 // TODO(jmesserly): we can likely make these faster. |
2460 emitMap() { | 2493 emitMap() { |
2461 var entries = node.entries; | 2494 var entries = node.entries; |
2462 var mapArguments = null; | 2495 var mapArguments = null; |
2463 if (entries.isEmpty) { | 2496 if (entries.isEmpty) { |
(...skipping 11 matching lines...) Expand all Loading... | |
2475 var values = []; | 2508 var values = []; |
2476 for (var e in entries) { | 2509 for (var e in entries) { |
2477 values.add(_visit(e.key)); | 2510 values.add(_visit(e.key)); |
2478 values.add(_visit(e.value)); | 2511 values.add(_visit(e.value)); |
2479 } | 2512 } |
2480 mapArguments = new JS.ArrayInitializer(values); | 2513 mapArguments = new JS.ArrayInitializer(values); |
2481 } | 2514 } |
2482 // TODO(jmesserly): add generic types args. | 2515 // TODO(jmesserly): add generic types args. |
2483 return js.call('dart.map(#)', [mapArguments]); | 2516 return js.call('dart.map(#)', [mapArguments]); |
2484 } | 2517 } |
2485 if (node.constKeyword != null) return _emitConst(node, emitMap); | 2518 if (node.constKeyword != null) return _emitConst(emitMap); |
2486 return emitMap(); | 2519 return emitMap(); |
2487 } | 2520 } |
2488 | 2521 |
2489 @override | 2522 @override |
2490 JS.LiteralString visitSimpleStringLiteral(SimpleStringLiteral node) => | 2523 JS.LiteralString visitSimpleStringLiteral(SimpleStringLiteral node) => |
2491 js.escapedString(node.value, node.isSingleQuoted ? "'" : '"'); | 2524 js.escapedString(node.value, node.isSingleQuoted ? "'" : '"'); |
2492 | 2525 |
2493 @override | 2526 @override |
2494 JS.Expression visitAdjacentStrings(AdjacentStrings node) => | 2527 JS.Expression visitAdjacentStrings(AdjacentStrings node) => |
2495 _visitListToBinary(node.strings, '+'); | 2528 _visitListToBinary(node.strings, '+'); |
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2738 | 2771 |
2739 /// A special kind of element created by the compiler, signifying a temporary | 2772 /// A special kind of element created by the compiler, signifying a temporary |
2740 /// variable. These objects use instance equality, and should be shared | 2773 /// variable. These objects use instance equality, and should be shared |
2741 /// everywhere in the tree where they are treated as the same variable. | 2774 /// everywhere in the tree where they are treated as the same variable. |
2742 class TemporaryVariableElement extends LocalVariableElementImpl { | 2775 class TemporaryVariableElement extends LocalVariableElementImpl { |
2743 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); | 2776 TemporaryVariableElement.forNode(Identifier name) : super.forNode(name); |
2744 | 2777 |
2745 int get hashCode => identityHashCode(this); | 2778 int get hashCode => identityHashCode(this); |
2746 bool operator ==(Object other) => identical(this, other); | 2779 bool operator ==(Object other) => identical(this, other); |
2747 } | 2780 } |
OLD | NEW |