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 | 2 |
3 // for details. All rights reserved. Use of this source code is governed by a | 3 // for details. All rights reserved. Use of this source code is governed by a |
4 // BSD-style license that can be found in the LICENSE file. | 4 // BSD-style license that can be found in the LICENSE file. |
5 | 5 |
6 import 'dart:collection' show HashMap, HashSet; | 6 import 'dart:collection' show HashMap, HashSet; |
7 import 'dart:math' show min, max; | 7 import 'dart:math' show min, max; |
8 | 8 |
9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
10 import 'package:analyzer/dart/ast/ast.dart'; | 10 import 'package:analyzer/dart/ast/ast.dart'; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
46 import 'js_metalet.dart' as JS; | 46 import 'js_metalet.dart' as JS; |
47 import 'js_names.dart' as JS; | 47 import 'js_names.dart' as JS; |
48 import 'js_typeref_codegen.dart' show JsTypeRefCodegen; | 48 import 'js_typeref_codegen.dart' show JsTypeRefCodegen; |
49 import 'module_builder.dart' show pathToJSIdentifier; | 49 import 'module_builder.dart' show pathToJSIdentifier; |
50 import 'nullable_type_inference.dart' show NullableTypeInference; | 50 import 'nullable_type_inference.dart' show NullableTypeInference; |
51 import 'property_model.dart'; | 51 import 'property_model.dart'; |
52 import 'reify_coercions.dart' show CoercionReifier; | 52 import 'reify_coercions.dart' show CoercionReifier; |
53 import 'side_effect_analysis.dart' show ConstFieldVisitor, isStateless; | 53 import 'side_effect_analysis.dart' show ConstFieldVisitor, isStateless; |
54 import 'type_utilities.dart'; | 54 import 'type_utilities.dart'; |
55 | 55 |
56 class CodeGenerator extends GeneralizingAstVisitor | 56 /// The code generator for Dart Dev Compiler. |
57 with ClosureAnnotator, JsTypeRefCodegen, NullableTypeInference { | 57 /// |
58 /// Takes as input resolved Dart ASTs for every compilation unit in every | |
59 /// library in the module. Produces a single JavaScript AST for the module as | |
60 /// output, along with its source map. | |
61 /// | |
62 /// This class attempts to preserve identifier names and structure of the input | |
63 /// Dart code, whenever this is possible to do in the generated code. | |
64 // | |
65 // TODO(jmesserly): we should use separate visitors for statements and | |
66 // expressions. Declarations are handled directly, and many minor component | |
67 // AST nodes aren't visited, so the visitor pattern isn't helping except for | |
68 // expressions (which result in JS.Expression) and statements | |
69 // (which result in (JS.Statement). | |
70 class CodeGenerator extends Object | |
71 with ClosureAnnotator, JsTypeRefCodegen, NullableTypeInference | |
72 implements AstVisitor<JS.Node> { | |
58 final AnalysisContext context; | 73 final AnalysisContext context; |
59 final SummaryDataStore summaryData; | 74 final SummaryDataStore summaryData; |
60 | 75 |
61 final CompilerOptions options; | 76 final CompilerOptions options; |
62 final StrongTypeSystemImpl rules; | 77 final StrongTypeSystemImpl rules; |
63 | 78 |
64 /// The set of libraries we are currently compiling, and the temporaries used | 79 /// The set of libraries we are currently compiling, and the temporaries used |
65 /// to refer to them. | 80 /// to refer to them. |
66 /// | 81 /// |
67 /// We sometimes special case codegen for a single library, as it simplifies | 82 /// We sometimes special case codegen for a single library, as it simplifies |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
232 null, | 247 null, |
233 sdk is SummaryBasedDartSdk | 248 sdk is SummaryBasedDartSdk |
234 ? sdk.bundle | 249 ? sdk.bundle |
235 : (sdk as FolderBasedDartSdk).getSummarySdkBundle(true)); | 250 : (sdk as FolderBasedDartSdk).getSummarySdkBundle(true)); |
236 } | 251 } |
237 | 252 |
238 var assembler = new PackageBundleAssembler(); | 253 var assembler = new PackageBundleAssembler(); |
239 assembler.recordDependencies(summaryData); | 254 assembler.recordDependencies(summaryData); |
240 | 255 |
241 var uriToUnit = new Map<String, UnlinkedUnit>.fromIterable(units, | 256 var uriToUnit = new Map<String, UnlinkedUnit>.fromIterable(units, |
242 key: (u) => u.element.source.uri.toString(), value: (unit) { | 257 key: (u) => u.element.source.uri.toString(), |
243 var unlinked = serializeAstUnlinked(unit); | 258 value: (unit) { |
244 assembler.addUnlinkedUnit(unit.element.source, unlinked); | 259 var unlinked = serializeAstUnlinked(unit); |
245 return unlinked; | 260 assembler.addUnlinkedUnit(unit.element.source, unlinked); |
246 }); | 261 return unlinked; |
262 }); | |
247 | 263 |
248 summary_link | 264 summary_link |
249 .link( | 265 .link( |
250 uriToUnit.keys.toSet(), | 266 uriToUnit.keys.toSet(), |
251 (uri) => summaryData.linkedMap[uri], | 267 (uri) => summaryData.linkedMap[uri], |
252 (uri) => summaryData.unlinkedMap[uri] ?? uriToUnit[uri], | 268 (uri) => summaryData.unlinkedMap[uri] ?? uriToUnit[uri], |
253 context.declaredVariables.get, | 269 context.declaredVariables.get, |
254 true) | 270 true) |
255 .forEach(assembler.addLinkedLibrary); | 271 .forEach(assembler.addLinkedLibrary); |
256 | 272 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
322 } | 338 } |
323 | 339 |
324 // Add implicit dart:core dependency so it is first. | 340 // Add implicit dart:core dependency so it is first. |
325 emitLibraryName(dartCoreLibrary); | 341 emitLibraryName(dartCoreLibrary); |
326 | 342 |
327 // Visit each compilation unit and emit its code. | 343 // Visit each compilation unit and emit its code. |
328 // | 344 // |
329 // NOTE: declarations are not necessarily emitted in this order. | 345 // NOTE: declarations are not necessarily emitted in this order. |
330 // Order will be changed as needed so the resulting code can execute. | 346 // Order will be changed as needed so the resulting code can execute. |
331 // This is done by forward declaring items. | 347 // This is done by forward declaring items. |
332 compilationUnits.forEach(_emitCompilationUnit); | 348 compilationUnits.forEach(visitCompilationUnit); |
333 assert(_deferredProperties.isEmpty); | 349 assert(_deferredProperties.isEmpty); |
334 | 350 |
335 // Visit directives (for exports) | 351 // Visit directives (for exports) |
336 compilationUnits.forEach(_emitExportDirectives); | 352 compilationUnits.forEach(_emitExportDirectives); |
337 | 353 |
338 // Declare imports | 354 // Declare imports |
339 _finishImports(items); | 355 _finishImports(items); |
340 | 356 |
341 // Discharge the type table cache variables and | 357 // Discharge the type table cache variables and |
342 // hoisted definitions. | 358 // hoisted definitions. |
(...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
558 void _declareBeforeUse(TypeDefiningElement e) { | 574 void _declareBeforeUse(TypeDefiningElement e) { |
559 if (e == null) return; | 575 if (e == null) return; |
560 | 576 |
561 var topLevel = _topLevelElements; | 577 var topLevel = _topLevelElements; |
562 if (topLevel.isNotEmpty && identical(currentElement, topLevel.last)) { | 578 if (topLevel.isNotEmpty && identical(currentElement, topLevel.last)) { |
563 // If the item is from our library, try to emit it now. | 579 // If the item is from our library, try to emit it now. |
564 _emitTypeDeclaration(e); | 580 _emitTypeDeclaration(e); |
565 } | 581 } |
566 } | 582 } |
567 | 583 |
568 void _emitCompilationUnit(CompilationUnit unit) { | 584 @override |
585 visitCompilationUnit(CompilationUnit unit) { | |
569 // NOTE: this method isn't the right place to initialize | 586 // NOTE: this method isn't the right place to initialize |
570 // per-compilation-unit state. Declarations can be visited out of order, | 587 // per-compilation-unit state. Declarations can be visited out of order, |
571 // this is only to catch things that haven't been emitted yet. | 588 // this is only to catch things that haven't been emitted yet. |
572 // | 589 // |
573 // See _emitTypeDeclaration. | 590 // See _emitTypeDeclaration. |
574 var library = unit.element.library; | 591 var library = unit.element.library; |
575 bool internalSdk = isSdkInternalRuntime(library); | 592 bool internalSdk = isSdkInternalRuntime(library); |
576 _currentElements.add(library); | 593 _currentElements.add(library); |
577 | 594 |
578 List<VariableDeclaration> fields; | 595 List<VariableDeclaration> fields; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
614 | 631 |
615 void _emitExportDirectives(CompilationUnit unit) { | 632 void _emitExportDirectives(CompilationUnit unit) { |
616 for (var directive in unit.directives) { | 633 for (var directive in unit.directives) { |
617 _currentElements.add(directive.element); | 634 _currentElements.add(directive.element); |
618 directive.accept(this); | 635 directive.accept(this); |
619 _currentElements.removeLast(); | 636 _currentElements.removeLast(); |
620 } | 637 } |
621 } | 638 } |
622 | 639 |
623 @override | 640 @override |
624 void visitLibraryDirective(LibraryDirective node) {} | 641 visitLibraryDirective(LibraryDirective node) => null; |
625 | 642 |
626 @override | 643 @override |
627 void visitImportDirective(ImportDirective node) { | 644 visitImportDirective(ImportDirective node) { |
628 // We don't handle imports here. | 645 // We don't handle imports here. |
629 // | 646 // |
630 // Instead, we collect imports whenever we need to generate a reference | 647 // Instead, we collect imports whenever we need to generate a reference |
631 // to another library. This has the effect of collecting the actually used | 648 // to another library. This has the effect of collecting the actually used |
632 // imports. | 649 // imports. |
633 // | 650 // |
634 // TODO(jmesserly): if this is a prefixed import, consider adding the prefix | 651 // TODO(jmesserly): if this is a prefixed import, consider adding the prefix |
635 // as an alias? | 652 // as an alias? |
653 return null; | |
636 } | 654 } |
637 | 655 |
638 @override | 656 @override |
639 void visitPartDirective(PartDirective node) {} | 657 visitPartDirective(PartDirective node) => null; |
640 | 658 |
641 @override | 659 @override |
642 void visitPartOfDirective(PartOfDirective node) {} | 660 visitPartOfDirective(PartOfDirective node) => null; |
643 | 661 |
644 @override | 662 @override |
645 void visitExportDirective(ExportDirective node) { | 663 visitExportDirective(ExportDirective node) { |
646 ExportElement element = node.element; | 664 ExportElement element = node.element; |
647 var currentLibrary = element.library; | 665 var currentLibrary = element.library; |
648 | 666 |
649 var currentNames = currentLibrary.publicNamespace.definedNames; | 667 var currentNames = currentLibrary.publicNamespace.definedNames; |
650 var exportedNames = | 668 var exportedNames = |
651 new NamespaceBuilder().createExportNamespaceForDirective(element); | 669 new NamespaceBuilder().createExportNamespaceForDirective(element); |
652 | 670 |
653 // We only need to export main as it is the only method part of the | 671 // We only need to export main as it is the only method part of the |
654 // publicly exposed JS API for a library. | 672 // publicly exposed JS API for a library. |
655 // TODO(jacobr): add a library level annotation indicating that all | 673 // TODO(jacobr): add a library level annotation indicating that all |
656 // contents of a library need to be exposed to JS. | 674 // contents of a library need to be exposed to JS. |
657 // https://github.com/dart-lang/sdk/issues/26368 | 675 // https://github.com/dart-lang/sdk/issues/26368 |
658 var export = exportedNames.get('main'); | 676 var export = exportedNames.get('main'); |
659 | 677 |
660 if (export is FunctionElement) { | 678 if (export is FunctionElement) { |
661 // Don't allow redefining names from this library. | 679 // Don't allow redefining names from this library. |
662 if (currentNames.containsKey(export.name)) return; | 680 if (currentNames.containsKey(export.name)) return null; |
663 | 681 |
664 var name = _emitTopLevelName(export); | 682 var name = _emitTopLevelName(export); |
665 _moduleItems.add(js.statement( | 683 _moduleItems.add(js.statement( |
666 '#.# = #;', [emitLibraryName(currentLibrary), name.selector, name])); | 684 '#.# = #;', [emitLibraryName(currentLibrary), name.selector, name])); |
667 } | 685 } |
668 } | 686 } |
669 | 687 |
670 @override | 688 @override |
671 visitAsExpression(AsExpression node) { | 689 visitAsExpression(AsExpression node) { |
672 Expression fromExpr = node.expression; | 690 Expression fromExpr = node.expression; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
748 var typeFormals = element.typeParameters; | 766 var typeFormals = element.typeParameters; |
749 if (typeFormals.isNotEmpty) { | 767 if (typeFormals.isNotEmpty) { |
750 return _defineClassTypeArguments(element, typeFormals, | 768 return _defineClassTypeArguments(element, typeFormals, |
751 js.statement('const # = #;', [element.name, body])); | 769 js.statement('const # = #;', [element.name, body])); |
752 } else { | 770 } else { |
753 return js.statement('# = #;', [_emitTopLevelName(element), body]); | 771 return js.statement('# = #;', [_emitTopLevelName(element), body]); |
754 } | 772 } |
755 } | 773 } |
756 | 774 |
757 @override | 775 @override |
776 visitGenericTypeAlias(GenericTypeAlias node) { | |
777 throw new UnimplementedError('Generic type aliases are not implemented. ' | |
778 'See https://github.com/dart-lang/sdk/issues/27971'); | |
779 } | |
780 | |
781 @override | |
758 JS.Expression visitTypeName(TypeName node) { | 782 JS.Expression visitTypeName(TypeName node) { |
759 if (node.type == null) { | 783 if (node.type == null) { |
760 // TODO(jmesserly): if the type fails to resolve, should we generate code | 784 // TODO(jmesserly): if the type fails to resolve, should we generate code |
761 // that throws instead? | 785 // that throws instead? |
762 assert(options.unsafeForceCompile || options.replCompile); | 786 assert(options.unsafeForceCompile || options.replCompile); |
763 return _callHelper('dynamic'); | 787 return _callHelper('dynamic'); |
764 } | 788 } |
765 return _emitType(node.type); | 789 return _emitType(node.type); |
766 } | 790 } |
767 | 791 |
(...skipping 21 matching lines...) Expand all Loading... | |
789 [jsParams, _constructorName(parentCtor), jsParams]) as JS.Fun; | 813 [jsParams, _constructorName(parentCtor), jsParams]) as JS.Fun; |
790 methods.add(new JS.Method(_constructorName(ctor), fun)); | 814 methods.add(new JS.Method(_constructorName(ctor), fun)); |
791 } | 815 } |
792 } | 816 } |
793 | 817 |
794 var typeFormals = element.typeParameters; | 818 var typeFormals = element.typeParameters; |
795 var isGeneric = typeFormals.isNotEmpty; | 819 var isGeneric = typeFormals.isNotEmpty; |
796 var className = isGeneric ? element.name : _emitTopLevelName(element); | 820 var className = isGeneric ? element.name : _emitTopLevelName(element); |
797 JS.Statement declareInterfaces(JS.Statement decl) { | 821 JS.Statement declareInterfaces(JS.Statement decl) { |
798 if (element.interfaces.isNotEmpty) { | 822 if (element.interfaces.isNotEmpty) { |
799 var body = [decl] | 823 var body = [decl]..add(js.statement('#[#.implements] = () => #;', [ |
800 ..add(js.statement('#[#.implements] = () => #;', [ | |
801 className, | 824 className, |
802 _runtimeModule, | 825 _runtimeModule, |
803 new JS.ArrayInitializer( | 826 new JS.ArrayInitializer( |
804 new List<JS.Expression>.from(element.interfaces.map(_emitType))) | 827 new List<JS.Expression>.from(element.interfaces.map(_emitType))) |
805 ])); | 828 ])); |
806 decl = _statement(body); | 829 decl = _statement(body); |
807 } | 830 } |
808 return decl; | 831 return decl; |
809 } | 832 } |
810 | 833 |
(...skipping 1255 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2066 var redirect = node.redirectedConstructor; | 2089 var redirect = node.redirectedConstructor; |
2067 if (redirect != null) { | 2090 if (redirect != null) { |
2068 var newKeyword = | 2091 var newKeyword = |
2069 resolutionMap.staticElementForConstructorReference(redirect).isFactory | 2092 resolutionMap.staticElementForConstructorReference(redirect).isFactory |
2070 ? '' | 2093 ? '' |
2071 : 'new'; | 2094 : 'new'; |
2072 // Pass along all arguments verbatim, and let the callee handle them. | 2095 // Pass along all arguments verbatim, and let the callee handle them. |
2073 // TODO(jmesserly): we'll need something different once we have | 2096 // TODO(jmesserly): we'll need something different once we have |
2074 // rest/spread support, but this should work for now. | 2097 // rest/spread support, but this should work for now. |
2075 var params = | 2098 var params = |
2076 visitFormalParameterList(node.parameters, destructure: false); | 2099 _emitFormalParameterList(node.parameters, destructure: false); |
2077 | 2100 |
2078 var fun = new JS.Fun( | 2101 var fun = new JS.Fun( |
2079 params, | 2102 params, |
2080 js.statement('{ return $newKeyword #(#); }', | 2103 js.statement( |
2081 [_visit(redirect) as JS.Node, params]), | 2104 '{ return $newKeyword #(#); }', [_visit(redirect), params]), |
2082 returnType: returnType); | 2105 returnType: returnType); |
2083 return annotate( | 2106 return annotate( |
2084 new JS.Method(name, fun, isStatic: true), node, node.element); | 2107 new JS.Method(name, fun, isStatic: true), node, node.element); |
2085 } | 2108 } |
2086 | 2109 |
2087 var params = visitFormalParameterList(node.parameters); | 2110 var params = _emitFormalParameterList(node.parameters); |
2088 | 2111 |
2089 // Factory constructors are essentially static methods. | 2112 // Factory constructors are essentially static methods. |
2090 if (node.factoryKeyword != null) { | 2113 if (node.factoryKeyword != null) { |
2091 var body = <JS.Statement>[]; | 2114 var body = <JS.Statement>[]; |
2092 var init = _emitArgumentInitializers(node, constructor: true); | 2115 var init = _emitArgumentInitializers(node, constructor: true); |
2093 if (init != null) body.add(init); | 2116 if (init != null) body.add(init); |
2094 body.add(_visit(node.body)); | 2117 body.add(_visit(node.body)); |
2095 var fun = new JS.Fun(params, new JS.Block(body), returnType: returnType); | 2118 var fun = new JS.Fun(params, new JS.Block(body), returnType: returnType); |
2096 return annotate( | 2119 return annotate( |
2097 new JS.Method(name, fun, isStatic: true), node, node.element); | 2120 new JS.Method(name, fun, isStatic: true), node, node.element); |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2170 @override | 2193 @override |
2171 JS.Statement visitRedirectingConstructorInvocation( | 2194 JS.Statement visitRedirectingConstructorInvocation( |
2172 RedirectingConstructorInvocation node) { | 2195 RedirectingConstructorInvocation node) { |
2173 var ctor = resolutionMap.staticElementForConstructorReference(node); | 2196 var ctor = resolutionMap.staticElementForConstructorReference(node); |
2174 var cls = ctor.enclosingElement; | 2197 var cls = ctor.enclosingElement; |
2175 // We can't dispatch to the constructor with `this.new` as that might hit a | 2198 // We can't dispatch to the constructor with `this.new` as that might hit a |
2176 // derived class constructor with the same name. | 2199 // derived class constructor with the same name. |
2177 return js.statement('#.prototype.#.call(this, #);', [ | 2200 return js.statement('#.prototype.#.call(this, #);', [ |
2178 new JS.Identifier(cls.name), | 2201 new JS.Identifier(cls.name), |
2179 _constructorName(ctor), | 2202 _constructorName(ctor), |
2180 _visit(node.argumentList) | 2203 _emitArgumentList(node.argumentList) |
2181 ]); | 2204 ]); |
2182 } | 2205 } |
2183 | 2206 |
2184 JS.Statement _superConstructorCall(ClassElement element, | 2207 JS.Statement _superConstructorCall(ClassElement element, |
2185 [SuperConstructorInvocation node]) { | 2208 [SuperConstructorInvocation node]) { |
2186 if (element.supertype == null) { | 2209 if (element.supertype == null) { |
2187 assert(element.type.isObject || options.unsafeForceCompile); | 2210 assert(element.type.isObject || options.unsafeForceCompile); |
2188 return null; | 2211 return null; |
2189 } | 2212 } |
2190 | 2213 |
(...skipping 11 matching lines...) Expand all Loading... | |
2202 // we don't have a default constructor in the supertype. | 2225 // we don't have a default constructor in the supertype. |
2203 assert(options.unsafeForceCompile); | 2226 assert(options.unsafeForceCompile); |
2204 return null; | 2227 return null; |
2205 } | 2228 } |
2206 | 2229 |
2207 if (superCtor.name == '' && !_hasUnnamedSuperConstructor(element)) { | 2230 if (superCtor.name == '' && !_hasUnnamedSuperConstructor(element)) { |
2208 return null; | 2231 return null; |
2209 } | 2232 } |
2210 | 2233 |
2211 var name = _constructorName(superCtor); | 2234 var name = _constructorName(superCtor); |
2212 var args = node != null ? _visit(node.argumentList) : []; | 2235 var args = node != null ? _emitArgumentList(node.argumentList) : []; |
2213 return annotate(js.statement('super.#(#);', [name, args]), node); | 2236 return annotate(js.statement('super.#(#);', [name, args]), node); |
2214 } | 2237 } |
2215 | 2238 |
2216 bool _hasUnnamedSuperConstructor(ClassElement e) { | 2239 bool _hasUnnamedSuperConstructor(ClassElement e) { |
2217 var supertype = e.supertype; | 2240 var supertype = e.supertype; |
2218 if (supertype == null) return false; | 2241 if (supertype == null) return false; |
2219 if (_hasUnnamedConstructor(supertype.element)) return true; | 2242 if (_hasUnnamedConstructor(supertype.element)) return true; |
2220 for (var mixin in e.mixins) { | 2243 for (var mixin in e.mixins) { |
2221 if (_hasUnnamedConstructor(mixin.element)) return true; | 2244 if (_hasUnnamedConstructor(mixin.element)) return true; |
2222 } | 2245 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2262 if (element is FieldFormalParameterElement) { | 2285 if (element is FieldFormalParameterElement) { |
2263 fields[element.field] = _emitSimpleIdentifier(p.identifier); | 2286 fields[element.field] = _emitSimpleIdentifier(p.identifier); |
2264 } | 2287 } |
2265 } | 2288 } |
2266 | 2289 |
2267 // Run constructor field initializers such as `: foo = bar.baz` | 2290 // Run constructor field initializers such as `: foo = bar.baz` |
2268 for (var init in ctor.initializers) { | 2291 for (var init in ctor.initializers) { |
2269 if (init is ConstructorFieldInitializer) { | 2292 if (init is ConstructorFieldInitializer) { |
2270 var element = init.fieldName.staticElement as FieldElement; | 2293 var element = init.fieldName.staticElement as FieldElement; |
2271 fields[element] = _visit(init.expression); | 2294 fields[element] = _visit(init.expression); |
2295 } else if (init is AssertInitializer) { | |
2296 throw new UnimplementedError( | |
2297 'Assert initializers are not implemented. ' | |
2298 'See https://github.com/dart-lang/sdk/issues/27809'); | |
2272 } | 2299 } |
2273 } | 2300 } |
2274 } | 2301 } |
2275 | 2302 |
2276 for (var f in fields.keys) unsetFields.remove(f); | 2303 for (var f in fields.keys) unsetFields.remove(f); |
2277 | 2304 |
2278 // Initialize all remaining fields | 2305 // Initialize all remaining fields |
2279 unsetFields.forEach((element, fieldNode) { | 2306 unsetFields.forEach((element, fieldNode) { |
2280 JS.Expression value; | 2307 JS.Expression value; |
2281 if (fieldNode.initializer != null) { | 2308 if (fieldNode.initializer != null) { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2383 } | 2410 } |
2384 } | 2411 } |
2385 | 2412 |
2386 JS.Fun _emitNativeFunctionBody(MethodDeclaration node) { | 2413 JS.Fun _emitNativeFunctionBody(MethodDeclaration node) { |
2387 String name = | 2414 String name = |
2388 getAnnotationName(node.element, isJSAnnotation) ?? node.name.name; | 2415 getAnnotationName(node.element, isJSAnnotation) ?? node.name.name; |
2389 if (node.isGetter) { | 2416 if (node.isGetter) { |
2390 return new JS.Fun([], js.statement('{ return this.#; }', [name])); | 2417 return new JS.Fun([], js.statement('{ return this.#; }', [name])); |
2391 } else if (node.isSetter) { | 2418 } else if (node.isSetter) { |
2392 var params = | 2419 var params = |
2393 visitFormalParameterList(node.parameters, destructure: false); | 2420 _emitFormalParameterList(node.parameters, destructure: false); |
2394 return new JS.Fun( | 2421 return new JS.Fun( |
2395 params, js.statement('{ this.# = #; }', [name, params.last])); | 2422 params, js.statement('{ this.# = #; }', [name, params.last])); |
2396 } else { | 2423 } else { |
2397 return js.call( | 2424 return js.call( |
2398 'function (...args) { return this.#.apply(this, args); }', name); | 2425 'function (...args) { return this.#.apply(this, args); }', name); |
2399 } | 2426 } |
2400 } | 2427 } |
2401 | 2428 |
2402 JS.Method _emitMethodDeclaration(InterfaceType type, MethodDeclaration node) { | 2429 JS.Method _emitMethodDeclaration(InterfaceType type, MethodDeclaration node) { |
2403 if (node.isAbstract) { | 2430 if (node.isAbstract) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2443 if (JS.Return.foundIn(fn)) { | 2470 if (JS.Return.foundIn(fn)) { |
2444 // If a return is inside body, transform `(params) { body }` to | 2471 // If a return is inside body, transform `(params) { body }` to |
2445 // `(params) { (() => { body })(); return value; }`. | 2472 // `(params) { (() => { body })(); return value; }`. |
2446 // TODO(jmesserly): we could instead generate the return differently, | 2473 // TODO(jmesserly): we could instead generate the return differently, |
2447 // and avoid the immediately invoked function. | 2474 // and avoid the immediately invoked function. |
2448 body = new JS.Call(new JS.ArrowFun([], fn.body), []).toStatement(); | 2475 body = new JS.Call(new JS.ArrowFun([], fn.body), []).toStatement(); |
2449 } | 2476 } |
2450 // Rewrite the function to include the return. | 2477 // Rewrite the function to include the return. |
2451 return new JS.Fun( | 2478 return new JS.Fun( |
2452 fn.params, new JS.Block([body, new JS.Return(fn.params.last)]), | 2479 fn.params, new JS.Block([body, new JS.Return(fn.params.last)]), |
2453 typeParams: fn.typeParams, | 2480 typeParams: fn.typeParams, returnType: fn.returnType) |
2454 returnType: fn.returnType)..sourceInformation = fn.sourceInformation; | 2481 ..sourceInformation = fn.sourceInformation; |
2455 } | 2482 } |
2456 | 2483 |
2457 @override | 2484 @override |
2458 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { | 2485 JS.Statement visitFunctionDeclaration(FunctionDeclaration node) { |
2459 assert(node.parent is CompilationUnit); | 2486 assert(node.parent is CompilationUnit); |
2460 | 2487 |
2461 if (_externalOrNative(node)) return null; | 2488 if (_externalOrNative(node)) return null; |
2462 | 2489 |
2463 if (node.isGetter || node.isSetter) { | 2490 if (node.isGetter || node.isSetter) { |
2464 PropertyAccessorElement element = node.element; | 2491 PropertyAccessorElement element = node.element; |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2649 var fn = _emitFunctionBody(node.element, node.parameters, node.body); | 2676 var fn = _emitFunctionBody(node.element, node.parameters, node.body); |
2650 return annotate(_makeGenericFunction(fn), node); | 2677 return annotate(_makeGenericFunction(fn), node); |
2651 } | 2678 } |
2652 | 2679 |
2653 JS.Fun _emitFunctionBody(ExecutableElement element, | 2680 JS.Fun _emitFunctionBody(ExecutableElement element, |
2654 FormalParameterList parameters, FunctionBody body) { | 2681 FormalParameterList parameters, FunctionBody body) { |
2655 FunctionType type = element.type; | 2682 FunctionType type = element.type; |
2656 | 2683 |
2657 // normal function (sync), vs (sync*, async, async*) | 2684 // normal function (sync), vs (sync*, async, async*) |
2658 var stdFn = !(element.isAsynchronous || element.isGenerator); | 2685 var stdFn = !(element.isAsynchronous || element.isGenerator); |
2659 var formals = visitFormalParameterList(parameters, destructure: stdFn); | 2686 var formals = _emitFormalParameterList(parameters, destructure: stdFn); |
2660 var code = (stdFn) | 2687 var code = (stdFn) |
2661 ? _visit(body) | 2688 ? _visit(body) |
2662 : new JS.Block( | 2689 : new JS.Block( |
2663 [_emitGeneratorFunctionBody(element, parameters, body).toReturn()]); | 2690 [_emitGeneratorFunctionBody(element, parameters, body).toReturn()]); |
2664 var typeFormals = _emitTypeFormals(type.typeFormals); | 2691 var typeFormals = _emitTypeFormals(type.typeFormals); |
2665 var returnType = emitTypeRef(type.returnType); | 2692 var returnType = emitTypeRef(type.returnType); |
2666 if (type.typeFormals.isNotEmpty) { | 2693 if (type.typeFormals.isNotEmpty) { |
2667 code = new JS.Block(<JS.Statement>[ | 2694 code = new JS.Block(<JS.Statement>[ |
2668 new JS.Block(_typeTable.discharge(type.typeFormals)), | 2695 new JS.Block(_typeTable.discharge(type.typeFormals)), |
2669 code | 2696 code |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2702 // In the body of a `sync*` and `async`, `yield`/`await` are both generated | 2729 // In the body of a `sync*` and `async`, `yield`/`await` are both generated |
2703 // simply as `yield`. | 2730 // simply as `yield`. |
2704 // | 2731 // |
2705 // `async*` uses the `dart.asyncStar` helper, and also has an extra `stream` | 2732 // `async*` uses the `dart.asyncStar` helper, and also has an extra `stream` |
2706 // argument to the generator, which is used for passing values to the | 2733 // argument to the generator, which is used for passing values to the |
2707 // _AsyncStarStreamController implementation type. | 2734 // _AsyncStarStreamController implementation type. |
2708 // `yield` is specially generated inside `async*`, see visitYieldStatement. | 2735 // `yield` is specially generated inside `async*`, see visitYieldStatement. |
2709 // `await` is generated as `yield`. | 2736 // `await` is generated as `yield`. |
2710 // runtime/_generators.js has an example of what the code is generated as. | 2737 // runtime/_generators.js has an example of what the code is generated as. |
2711 var savedController = _asyncStarController; | 2738 var savedController = _asyncStarController; |
2712 var jsParams = visitFormalParameterList(parameters); | 2739 var jsParams = _emitFormalParameterList(parameters); |
2713 if (kind == 'asyncStar') { | 2740 if (kind == 'asyncStar') { |
2714 _asyncStarController = new JS.TemporaryId('stream'); | 2741 _asyncStarController = new JS.TemporaryId('stream'); |
2715 jsParams.insert(0, _asyncStarController); | 2742 jsParams.insert(0, _asyncStarController); |
2716 } else { | 2743 } else { |
2717 _asyncStarController = null; | 2744 _asyncStarController = null; |
2718 } | 2745 } |
2719 var savedSuperAllowed = _superAllowed; | 2746 var savedSuperAllowed = _superAllowed; |
2720 _superAllowed = false; | 2747 _superAllowed = false; |
2721 // Visit the body with our async* controller set. | 2748 // Visit the body with our async* controller set. |
2722 var jsBody = _visit(body); | 2749 var jsBody = _visit(body); |
2723 _superAllowed = savedSuperAllowed; | 2750 _superAllowed = savedSuperAllowed; |
2724 _asyncStarController = savedController; | 2751 _asyncStarController = savedController; |
2725 | 2752 |
2726 DartType returnType = _getExpectedReturnType(element); | 2753 DartType returnType = _getExpectedReturnType(element); |
2727 JS.Expression gen = new JS.Fun(jsParams, jsBody, | 2754 JS.Expression gen = new JS.Fun(jsParams, jsBody, |
2728 isGenerator: true, returnType: emitTypeRef(returnType)); | 2755 isGenerator: true, returnType: emitTypeRef(returnType)); |
2729 if (JS.This.foundIn(gen)) { | 2756 if (JS.This.foundIn(gen)) { |
2730 gen = js.call('#.bind(this)', gen); | 2757 gen = js.call('#.bind(this)', gen); |
2731 } | 2758 } |
2732 | 2759 |
2733 var T = _emitType(returnType); | 2760 var T = _emitType(returnType); |
2734 return _callHelper('#(#)', [ | 2761 return _callHelper('#(#)', [ |
2735 kind, | 2762 kind, |
2736 [gen, T]..addAll(visitFormalParameterList(parameters, destructure: false)) | 2763 [gen, T]..addAll(_emitFormalParameterList(parameters, destructure: false)) |
2737 ]); | 2764 ]); |
2738 } | 2765 } |
2739 | 2766 |
2740 @override | 2767 @override |
2741 JS.Statement visitFunctionDeclarationStatement( | 2768 JS.Statement visitFunctionDeclarationStatement( |
2742 FunctionDeclarationStatement node) { | 2769 FunctionDeclarationStatement node) { |
2743 var func = node.functionDeclaration; | 2770 var func = node.functionDeclaration; |
2744 if (func.isGetter || func.isSetter) { | 2771 if (func.isGetter || func.isSetter) { |
2745 return js.comment('Unimplemented function get/set statement: $node'); | 2772 return js.comment('Unimplemented function get/set statement: $node'); |
2746 } | 2773 } |
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3374 JS.Expression target; | 3401 JS.Expression target; |
3375 if (element is TemporaryVariableElement) { | 3402 if (element is TemporaryVariableElement) { |
3376 // If this is one of our compiler's temporary variables, use its JS form. | 3403 // If this is one of our compiler's temporary variables, use its JS form. |
3377 target = element.jsVariable; | 3404 target = element.jsVariable; |
3378 } else if (element is ParameterElement) { | 3405 } else if (element is ParameterElement) { |
3379 target = _emitParameter(element); | 3406 target = _emitParameter(element); |
3380 } else { | 3407 } else { |
3381 target = new JS.Identifier(element.name); | 3408 target = new JS.Identifier(element.name); |
3382 } | 3409 } |
3383 | 3410 |
3384 return _visit(rhs).toAssignExpression(annotate(target, node)); | 3411 return _visit<JS.Expression>(rhs) |
3412 .toAssignExpression(annotate(target, node)); | |
3385 } | 3413 } |
3386 | 3414 |
3387 /// Emits assignment to library scope element [element]. | 3415 /// Emits assignment to library scope element [element]. |
3388 JS.Expression _emitSetTopLevel( | 3416 JS.Expression _emitSetTopLevel( |
3389 Expression lhs, Element element, Expression rhs) { | 3417 Expression lhs, Element element, Expression rhs) { |
3390 return _visit(rhs) | 3418 return _visit<JS.Expression>(rhs) |
3391 .toAssignExpression(annotate(_emitTopLevelName(element), lhs)); | 3419 .toAssignExpression(annotate(_emitTopLevelName(element), lhs)); |
3392 } | 3420 } |
3393 | 3421 |
3394 /// Emits assignment to a static field element or property. | 3422 /// Emits assignment to a static field element or property. |
3395 JS.Expression _emitSetStaticProperty( | 3423 JS.Expression _emitSetStaticProperty( |
3396 Expression lhs, Element element, Expression rhs) { | 3424 Expression lhs, Element element, Expression rhs) { |
3397 // For static methods, we add the raw type name, without generics or | 3425 // For static methods, we add the raw type name, without generics or |
3398 // library prefix. We don't need those because static calls can't use | 3426 // library prefix. We don't need those because static calls can't use |
3399 // the generic type. | 3427 // the generic type. |
3400 ClassElement classElement = element.enclosingElement; | 3428 ClassElement classElement = element.enclosingElement; |
3401 var type = classElement.type; | 3429 var type = classElement.type; |
3402 var dynType = _emitStaticAccess(type); | 3430 var dynType = _emitStaticAccess(type); |
3403 var member = _emitMemberName(element.name, | 3431 var member = _emitMemberName(element.name, |
3404 isStatic: true, type: type, element: element); | 3432 isStatic: true, type: type, element: element); |
3405 return _visit(rhs).toAssignExpression( | 3433 return _visit<JS.Expression>(rhs).toAssignExpression( |
3406 annotate(new JS.PropertyAccess(dynType, member), lhs)); | 3434 annotate(new JS.PropertyAccess(dynType, member), lhs)); |
3407 } | 3435 } |
3408 | 3436 |
3409 /// Emits an assignment to the [element] property of instance referenced by | 3437 /// Emits an assignment to the [element] property of instance referenced by |
3410 /// [jsTarget]. | 3438 /// [jsTarget]. |
3411 JS.Expression _emitWriteInstanceProperty(Expression lhs, | 3439 JS.Expression _emitWriteInstanceProperty(Expression lhs, |
3412 JS.Expression jsTarget, Element element, JS.Expression value) { | 3440 JS.Expression jsTarget, Element element, JS.Expression value) { |
3413 String memberName = element.name; | 3441 String memberName = element.name; |
3414 var type = (element.enclosingElement as ClassElement).type; | 3442 var type = (element.enclosingElement as ClassElement).type; |
3415 var name = _emitMemberName(memberName, type: type, element: element); | 3443 var name = _emitMemberName(memberName, type: type, element: element); |
3416 return value.toAssignExpression( | 3444 return value.toAssignExpression( |
3417 annotate(new JS.PropertyAccess(jsTarget, name), lhs)); | 3445 annotate(new JS.PropertyAccess(jsTarget, name), lhs)); |
3418 } | 3446 } |
3419 | 3447 |
3420 JS.Expression _emitSetSuper(Expression lhs, SuperExpression target, | 3448 JS.Expression _emitSetSuper(Expression lhs, SuperExpression target, |
3421 SimpleIdentifier id, Expression rhs) { | 3449 SimpleIdentifier id, Expression rhs) { |
3422 // TODO(sra): Determine whether and access helper is required for the | 3450 // TODO(sra): Determine whether and access helper is required for the |
3423 // setter. For now fall back on the r-value path. | 3451 // setter. For now fall back on the r-value path. |
3424 return _visit(rhs).toAssignExpression(_visit(lhs)); | 3452 return _visit<JS.Expression>(rhs).toAssignExpression(_visit(lhs)); |
3425 } | 3453 } |
3426 | 3454 |
3427 JS.Expression _emitNullSafeSet(PropertyAccess node, Expression right) { | 3455 JS.Expression _emitNullSafeSet(PropertyAccess node, Expression right) { |
3428 // Emit `obj?.prop = expr` as: | 3456 // Emit `obj?.prop = expr` as: |
3429 // | 3457 // |
3430 // (_ => _ == null ? null : _.prop = expr)(obj). | 3458 // (_ => _ == null ? null : _.prop = expr)(obj). |
3431 // | 3459 // |
3432 // We could use a helper, e.g.: `nullSafeSet(e1, _ => _.v = e2)` | 3460 // We could use a helper, e.g.: `nullSafeSet(e1, _ => _.v = e2)` |
3433 // | 3461 // |
3434 // However with MetaLet, we get clean code in statement or void context, | 3462 // However with MetaLet, we get clean code in statement or void context, |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3491 } | 3519 } |
3492 if (node.methodName.name == 'call') { | 3520 if (node.methodName.name == 'call') { |
3493 var targetType = resolutionMap.staticTypeForExpression(target); | 3521 var targetType = resolutionMap.staticTypeForExpression(target); |
3494 if (targetType is FunctionType) { | 3522 if (targetType is FunctionType) { |
3495 // Call methods on function types should be handled as regular function | 3523 // Call methods on function types should be handled as regular function |
3496 // invocations. | 3524 // invocations. |
3497 return _emitFunctionCall(node, node.target); | 3525 return _emitFunctionCall(node, node.target); |
3498 } | 3526 } |
3499 if (targetType.isDartCoreFunction || targetType.isDynamic) { | 3527 if (targetType.isDartCoreFunction || targetType.isDynamic) { |
3500 // TODO(vsm): Can a call method take generic type parameters? | 3528 // TODO(vsm): Can a call method take generic type parameters? |
3501 return _emitDynamicInvoke(node, _visit(target), | 3529 return _emitDynamicInvoke( |
3502 _visit(node.argumentList) as List<JS.Expression>); | 3530 node, _visit(target), _emitArgumentList(node.argumentList)); |
3503 } | 3531 } |
3504 } | 3532 } |
3505 | 3533 |
3506 return _emitMethodCall(target, node); | 3534 return _emitMethodCall(target, node); |
3507 } | 3535 } |
3508 | 3536 |
3509 JS.Expression _emitMethodCall(Expression target, MethodInvocation node) { | 3537 JS.Expression _emitMethodCall(Expression target, MethodInvocation node) { |
3510 var args = _visit(node.argumentList) as List<JS.Expression>; | 3538 var args = _emitArgumentList(node.argumentList); |
3511 var typeArgs = _emitInvokeTypeArguments(node); | 3539 var typeArgs = _emitInvokeTypeArguments(node); |
3512 | 3540 |
3513 if (target is SuperExpression && !_superAllowed) { | 3541 if (target is SuperExpression && !_superAllowed) { |
3514 return _emitSuperHelperCall(typeArgs, args, target, node); | 3542 return _emitSuperHelperCall(typeArgs, args, target, node); |
3515 } | 3543 } |
3516 | 3544 |
3517 return _emitMethodCallInternal(target, node, args, typeArgs); | 3545 return _emitMethodCallInternal(target, node, args, typeArgs); |
3518 } | 3546 } |
3519 | 3547 |
3520 JS.Expression _emitSuperHelperCall(List<JS.Expression> typeArgs, | 3548 JS.Expression _emitSuperHelperCall(List<JS.Expression> typeArgs, |
(...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3640 } | 3668 } |
3641 | 3669 |
3642 /// Emits a function call, to a top-level function, local function, or | 3670 /// Emits a function call, to a top-level function, local function, or |
3643 /// an expression. | 3671 /// an expression. |
3644 JS.Expression _emitFunctionCall(InvocationExpression node, | 3672 JS.Expression _emitFunctionCall(InvocationExpression node, |
3645 [Expression function]) { | 3673 [Expression function]) { |
3646 if (function == null) { | 3674 if (function == null) { |
3647 function = node.function; | 3675 function = node.function; |
3648 } | 3676 } |
3649 var fn = _visit(function); | 3677 var fn = _visit(function); |
3650 var args = _visit(node.argumentList) as List<JS.Expression>; | 3678 var args = _emitArgumentList(node.argumentList); |
3651 if (isDynamicInvoke(function)) { | 3679 if (isDynamicInvoke(function)) { |
3652 return _emitDynamicInvoke(node, fn, args); | 3680 return _emitDynamicInvoke(node, fn, args); |
3653 } else { | 3681 } else { |
3654 return new JS.Call(_applyInvokeTypeArguments(fn, node), args); | 3682 return new JS.Call(_applyInvokeTypeArguments(fn, node), args); |
3655 } | 3683 } |
3656 } | 3684 } |
3657 | 3685 |
3658 JS.Expression _applyInvokeTypeArguments( | 3686 JS.Expression _applyInvokeTypeArguments( |
3659 JS.Expression target, InvocationExpression node) { | 3687 JS.Expression target, InvocationExpression node) { |
3660 var typeArgs = _emitInvokeTypeArguments(node); | 3688 var typeArgs = _emitInvokeTypeArguments(node); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3789 } | 3817 } |
3790 return null; | 3818 return null; |
3791 } | 3819 } |
3792 | 3820 |
3793 @override | 3821 @override |
3794 JS.Expression visitFunctionExpressionInvocation( | 3822 JS.Expression visitFunctionExpressionInvocation( |
3795 FunctionExpressionInvocation node) => | 3823 FunctionExpressionInvocation node) => |
3796 _emitFunctionCall(node); | 3824 _emitFunctionCall(node); |
3797 | 3825 |
3798 @override | 3826 @override |
3799 List<JS.Expression> visitArgumentList(ArgumentList node) { | 3827 visitArgumentList(ArgumentList node) { |
3828 assert(false); | |
vsm
2017/04/14 13:14:39
Should this just be in your unreachable list below
Jennifer Messerly
2017/04/14 17:03:58
yes! oops :) done
| |
3829 } | |
3830 | |
3831 List<JS.Expression> _emitArgumentList(ArgumentList node) { | |
3800 var args = <JS.Expression>[]; | 3832 var args = <JS.Expression>[]; |
3801 var named = <JS.Property>[]; | 3833 var named = <JS.Property>[]; |
3802 for (var arg in node.arguments) { | 3834 for (var arg in node.arguments) { |
3803 if (arg is NamedExpression) { | 3835 if (arg is NamedExpression) { |
3804 named.add(_visit(arg)); | 3836 named.add(_visit(arg)); |
3805 } else if (arg is MethodInvocation && isJsSpreadInvocation(arg)) { | 3837 } else if (arg is MethodInvocation && isJsSpreadInvocation(arg)) { |
3806 args.add( | 3838 args.add( |
3807 new JS.RestParameter(_visit(arg.argumentList.arguments.single))); | 3839 new JS.RestParameter(_visit(arg.argumentList.arguments.single))); |
3808 } else { | 3840 } else { |
3809 args.add(_visit(arg)); | 3841 args.add(_visit(arg)); |
3810 } | 3842 } |
3811 } | 3843 } |
3812 if (named.isNotEmpty) { | 3844 if (named.isNotEmpty) { |
3813 args.add(new JS.ObjectInitializer(named)); | 3845 args.add(new JS.ObjectInitializer(named)); |
3814 } | 3846 } |
3815 return args; | 3847 return args; |
3816 } | 3848 } |
3817 | 3849 |
3818 @override | 3850 @override |
3819 JS.Property visitNamedExpression(NamedExpression node) { | 3851 JS.Property visitNamedExpression(NamedExpression node) { |
3820 assert(node.parent is ArgumentList); | 3852 assert(node.parent is ArgumentList); |
3821 return new JS.Property( | 3853 return new JS.Property( |
3822 _propertyName(node.name.label.name), _visit(node.expression)); | 3854 _propertyName(node.name.label.name), _visit(node.expression)); |
3823 } | 3855 } |
3824 | 3856 |
3825 @override | 3857 List<JS.Parameter> _emitFormalParameterList(FormalParameterList node, |
3826 List<JS.Parameter> visitFormalParameterList(FormalParameterList node, | |
3827 {bool destructure: true}) { | 3858 {bool destructure: true}) { |
3828 if (node == null) return []; | 3859 if (node == null) return []; |
3829 | 3860 |
3830 destructure = destructure && options.destructureNamedParams; | 3861 destructure = destructure && options.destructureNamedParams; |
3831 | 3862 |
3832 var result = <JS.Parameter>[]; | 3863 var result = <JS.Parameter>[]; |
3833 var namedVars = <JS.DestructuredVariable>[]; | 3864 var namedVars = <JS.DestructuredVariable>[]; |
3834 var hasNamedArgsConflictingWithObjectProperties = false; | 3865 var hasNamedArgsConflictingWithObjectProperties = false; |
3835 var needsOpts = false; | 3866 var needsOpts = false; |
3836 | 3867 |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3973 JS.Statement visitVariableDeclarationStatement( | 4004 JS.Statement visitVariableDeclarationStatement( |
3974 VariableDeclarationStatement node) { | 4005 VariableDeclarationStatement node) { |
3975 // Special case a single variable with an initializer. | 4006 // Special case a single variable with an initializer. |
3976 // This helps emit cleaner code for things like: | 4007 // This helps emit cleaner code for things like: |
3977 // var result = []..add(1)..add(2); | 4008 // var result = []..add(1)..add(2); |
3978 var variables = node.variables.variables; | 4009 var variables = node.variables.variables; |
3979 if (variables.length == 1) { | 4010 if (variables.length == 1) { |
3980 var v = variables[0]; | 4011 var v = variables[0]; |
3981 if (v.initializer != null) { | 4012 if (v.initializer != null) { |
3982 var name = new JS.Identifier(v.name.name); | 4013 var name = new JS.Identifier(v.name.name); |
3983 return _visit(v.initializer).toVariableDeclaration(name); | 4014 return _visit<JS.Expression>(v.initializer).toVariableDeclaration(name); |
3984 } | 4015 } |
3985 } | 4016 } |
3986 return _visit(node.variables).toStatement(); | 4017 return _visit<JS.Expression>(node.variables).toStatement(); |
3987 } | 4018 } |
3988 | 4019 |
3989 @override | 4020 @override |
3990 visitVariableDeclarationList(VariableDeclarationList node) { | 4021 visitVariableDeclarationList(VariableDeclarationList node) { |
3991 return new JS.VariableDeclarationList( | 4022 return new JS.VariableDeclarationList( |
3992 'let', _visitList(node.variables) as List<JS.VariableInitialization>); | 4023 'let', _visitList(node.variables) as List<JS.VariableInitialization>); |
3993 } | 4024 } |
3994 | 4025 |
3995 @override | 4026 @override |
3996 visitVariableDeclaration(VariableDeclaration node) { | 4027 visitVariableDeclaration(VariableDeclaration node) { |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4115 hoistType: options.hoistInstanceCreation); | 4146 hoistType: options.hoistInstanceCreation); |
4116 if (name != null) { | 4147 if (name != null) { |
4117 ctor = new JS.PropertyAccess(ctor, _propertyName(name.name)); | 4148 ctor = new JS.PropertyAccess(ctor, _propertyName(name.name)); |
4118 } | 4149 } |
4119 } else { | 4150 } else { |
4120 ctor = _emitConstructorName(element, type, name); | 4151 ctor = _emitConstructorName(element, type, name); |
4121 isFactory = element.isFactory; | 4152 isFactory = element.isFactory; |
4122 var classElem = element.enclosingElement; | 4153 var classElem = element.enclosingElement; |
4123 isNative = _isJSNative(classElem); | 4154 isNative = _isJSNative(classElem); |
4124 } | 4155 } |
4125 var args = _visit(argumentList) as List<JS.Expression>; | 4156 var args = _emitArgumentList(argumentList); |
4126 // Native factory constructors are JS constructors - use new here. | 4157 // Native factory constructors are JS constructors - use new here. |
4127 return isFactory && !isNative | 4158 return isFactory && !isNative |
4128 ? new JS.Call(ctor, args) | 4159 ? new JS.Call(ctor, args) |
4129 : new JS.New(ctor, args); | 4160 : new JS.New(ctor, args); |
4130 } | 4161 } |
4131 | 4162 |
4132 if (element != null && _isObjectLiteral(element.enclosingElement)) { | 4163 if (element != null && _isObjectLiteral(element.enclosingElement)) { |
4133 return _emitObjectLiteral(argumentList); | 4164 return _emitObjectLiteral(argumentList); |
4134 } | 4165 } |
4135 if (isConst) return _emitConst(emitNew); | 4166 if (isConst) return _emitConst(emitNew); |
4136 return emitNew(); | 4167 return emitNew(); |
4137 } | 4168 } |
4138 | 4169 |
4139 bool _isObjectLiteral(ClassElement classElem) { | 4170 bool _isObjectLiteral(ClassElement classElem) { |
4140 return findAnnotation(classElem, isPublicJSAnnotation) != null && | 4171 return findAnnotation(classElem, isPublicJSAnnotation) != null && |
4141 findAnnotation(classElem, isJSAnonymousAnnotation) != null; | 4172 findAnnotation(classElem, isJSAnonymousAnnotation) != null; |
4142 } | 4173 } |
4143 | 4174 |
4144 bool _isJSNative(ClassElement classElem) => | 4175 bool _isJSNative(ClassElement classElem) => |
4145 findAnnotation(classElem, isPublicJSAnnotation) != null; | 4176 findAnnotation(classElem, isPublicJSAnnotation) != null; |
4146 | 4177 |
4147 JS.Expression _emitObjectLiteral(ArgumentList argumentList) { | 4178 JS.Expression _emitObjectLiteral(ArgumentList argumentList) { |
4148 var args = _visit(argumentList) as List<JS.Expression>; | 4179 var args = _emitArgumentList(argumentList); |
4149 if (args.isEmpty) { | 4180 if (args.isEmpty) { |
4150 return js.call('{}'); | 4181 return js.call('{}'); |
4151 } | 4182 } |
4152 assert(args.single is JS.ObjectInitializer); | 4183 assert(args.single is JS.ObjectInitializer); |
4153 return args.single; | 4184 return args.single; |
4154 } | 4185 } |
4155 | 4186 |
4156 @override | 4187 @override |
4157 visitInstanceCreationExpression(InstanceCreationExpression node) { | 4188 visitInstanceCreationExpression(InstanceCreationExpression node) { |
4158 var element = resolutionMap.staticElementForConstructorReference(node); | 4189 var element = resolutionMap.staticElementForConstructorReference(node); |
(...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4735 var operatorName = op.lexeme; | 4766 var operatorName = op.lexeme; |
4736 // Use the name from the Dart spec. | 4767 // Use the name from the Dart spec. |
4737 if (operatorName == '-') operatorName = 'unary-'; | 4768 if (operatorName == '-') operatorName = 'unary-'; |
4738 return _emitSend(expr, operatorName, []); | 4769 return _emitSend(expr, operatorName, []); |
4739 } | 4770 } |
4740 | 4771 |
4741 // Cascades can contain [IndexExpression], [MethodInvocation] and | 4772 // Cascades can contain [IndexExpression], [MethodInvocation] and |
4742 // [PropertyAccess]. The code generation for those is handled in their | 4773 // [PropertyAccess]. The code generation for those is handled in their |
4743 // respective visit methods. | 4774 // respective visit methods. |
4744 @override | 4775 @override |
4745 JS.Node visitCascadeExpression(CascadeExpression node) { | 4776 visitCascadeExpression(CascadeExpression node) { |
4746 var savedCascadeTemp = _cascadeTarget; | 4777 var savedCascadeTemp = _cascadeTarget; |
4747 | 4778 |
4748 var vars = <JS.MetaLetVariable, JS.Expression>{}; | 4779 var vars = <JS.MetaLetVariable, JS.Expression>{}; |
4749 _cascadeTarget = _bindValue(vars, '_', node.target, context: node); | 4780 _cascadeTarget = _bindValue(vars, '_', node.target, context: node); |
4750 var sections = _visitList(node.cascadeSections) as List<JS.Expression>; | 4781 var sections = _visitList(node.cascadeSections) as List<JS.Expression>; |
4751 sections.add(_visit(_cascadeTarget)); | 4782 sections.add(_visit(_cascadeTarget)); |
4752 var result = new JS.MetaLet(vars, sections, statelessResult: true); | 4783 var result = new JS.MetaLet(vars, sections, statelessResult: true); |
4753 _cascadeTarget = savedCascadeTemp; | 4784 _cascadeTarget = savedCascadeTemp; |
4754 return result; | 4785 return result; |
4755 } | 4786 } |
4756 | 4787 |
4757 @override | 4788 @override |
4758 visitParenthesizedExpression(ParenthesizedExpression node) => | 4789 visitParenthesizedExpression(ParenthesizedExpression node) => |
4759 // The printer handles precedence so we don't need to. | 4790 // The printer handles precedence so we don't need to. |
4760 _visit(node.expression); | 4791 _visit(node.expression); |
4761 | 4792 |
4762 @override | 4793 @override |
4763 visitFormalParameter(FormalParameter node) { | 4794 visitDefaultFormalParameter(DefaultFormalParameter node) { |
4795 return _emitParameter(node.element, declaration: true); | |
4796 } | |
4797 | |
4798 JS.Parameter _emitNormalFormalParameter(NormalFormalParameter node) { | |
4764 var id = _emitParameter(node.element, declaration: true); | 4799 var id = _emitParameter(node.element, declaration: true); |
4765 var isRestArg = findAnnotation(node.element, isJsRestAnnotation) != null; | 4800 var isRestArg = findAnnotation(node.element, isJsRestAnnotation) != null; |
4766 return isRestArg ? new JS.RestParameter(id) : id; | 4801 return isRestArg ? new JS.RestParameter(id) : id; |
4767 } | 4802 } |
4768 | 4803 |
4769 @override | 4804 @override |
4805 visitSimpleFormalParameter(SimpleFormalParameter node) => | |
4806 _emitNormalFormalParameter(node); | |
4807 | |
4808 @override | |
4809 visitFieldFormalParameter(FieldFormalParameter node) => | |
4810 _emitNormalFormalParameter(node); | |
4811 | |
4812 @override | |
4813 visitFunctionTypedFormalParameter(FunctionTypedFormalParameter node) => | |
4814 _emitNormalFormalParameter(node); | |
4815 | |
4816 @override | |
4770 JS.This visitThisExpression(ThisExpression node) => new JS.This(); | 4817 JS.This visitThisExpression(ThisExpression node) => new JS.This(); |
4771 | 4818 |
4772 @override | 4819 @override |
4773 JS.Super visitSuperExpression(SuperExpression node) => new JS.Super(); | 4820 JS.Super visitSuperExpression(SuperExpression node) => new JS.Super(); |
4774 | 4821 |
4775 @override | 4822 @override |
4776 visitPrefixedIdentifier(PrefixedIdentifier node) { | 4823 visitPrefixedIdentifier(PrefixedIdentifier node) { |
4777 if (_isDeferredLoadLibrary(node.prefix, node.identifier)) { | 4824 if (_isDeferredLoadLibrary(node.prefix, node.identifier)) { |
4778 // We are tearing off "loadLibrary" on a library prefix. | 4825 // We are tearing off "loadLibrary" on a library prefix. |
4779 return _callHelper('loadLibrary'); | 4826 return _callHelper('loadLibrary'); |
(...skipping 627 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5407 @override | 5454 @override |
5408 JS.LiteralString visitSimpleStringLiteral(SimpleStringLiteral node) => | 5455 JS.LiteralString visitSimpleStringLiteral(SimpleStringLiteral node) => |
5409 js.escapedString(node.value, node.isSingleQuoted ? "'" : '"'); | 5456 js.escapedString(node.value, node.isSingleQuoted ? "'" : '"'); |
5410 | 5457 |
5411 @override | 5458 @override |
5412 JS.Expression visitAdjacentStrings(AdjacentStrings node) => | 5459 JS.Expression visitAdjacentStrings(AdjacentStrings node) => |
5413 _visitListToBinary(node.strings, '+'); | 5460 _visitListToBinary(node.strings, '+'); |
5414 | 5461 |
5415 @override | 5462 @override |
5416 JS.Expression visitStringInterpolation(StringInterpolation node) { | 5463 JS.Expression visitStringInterpolation(StringInterpolation node) { |
5464 var strings = <String>[]; | |
5465 var interpolations = <JS.Expression>[]; | |
5466 | |
5467 var expectString = true; | |
5468 for (var e in node.elements) { | |
5469 if (e is InterpolationString) { | |
5470 assert(expectString); | |
5471 expectString = false; | |
5472 | |
5473 // Escape the string as necessary for use in the eventual `` quotes. | |
5474 // TODO(jmesserly): this call adds quotes, and then we strip them off. | |
5475 var str = js.escapedString(e.value, '`').value; | |
5476 strings.add(str.substring(1, str.length - 1)); | |
5477 } else { | |
5478 assert(!expectString); | |
5479 expectString = true; | |
5480 interpolations.add(_visit(e)); | |
5481 } | |
5482 } | |
5417 return new JS.TaggedTemplate( | 5483 return new JS.TaggedTemplate( |
5418 _callHelper('str'), new JS.TemplateString(_visitList(node.elements))); | 5484 _callHelper('str'), new JS.TemplateString(strings, interpolations)); |
5419 } | 5485 } |
5420 | 5486 |
5421 @override | 5487 @override |
5422 String visitInterpolationString(InterpolationString node) { | |
5423 // TODO(jmesserly): this call adds quotes, and then we strip them off. | |
5424 var str = js.escapedString(node.value, '`').value; | |
5425 return str.substring(1, str.length - 1); | |
5426 } | |
5427 | |
5428 @override | |
5429 visitInterpolationExpression(InterpolationExpression node) => | 5488 visitInterpolationExpression(InterpolationExpression node) => |
5430 _visit(node.expression); | 5489 _visit(node.expression); |
5431 | 5490 |
5432 @override | 5491 @override |
5433 visitBooleanLiteral(BooleanLiteral node) => js.boolean(node.value); | 5492 visitBooleanLiteral(BooleanLiteral node) => js.boolean(node.value); |
5434 | 5493 |
5435 @override | 5494 T _visit<T extends JS.Node>(AstNode node) { |
5436 JS.Expression visitExpression(Expression node) => | |
5437 _unimplementedCall('Unimplemented ${node.runtimeType}: $node'); | |
5438 | |
5439 JS.Expression _unimplementedCall(String comment) { | |
5440 return _callHelper('throw(#)', [js.escapedString(comment)]); | |
5441 } | |
5442 | |
5443 @override | |
5444 visitNode(AstNode node) { | |
5445 // TODO(jmesserly): verify this is unreachable. | |
5446 throw 'Unimplemented ${node.runtimeType}: $node'; | |
5447 } | |
5448 | |
5449 _visit(AstNode node) { | |
5450 if (node == null) return null; | 5495 if (node == null) return null; |
5451 var result = node.accept(this); | 5496 var result = node.accept(this); |
5452 return result is JS.Node ? annotate(result, node) : result; | 5497 return result != null ? annotate(result, node) : null; |
5453 } | 5498 } |
5454 | 5499 |
5455 // TODO(jmesserly): we should make sure this only returns JS AST nodes. | 5500 // TODO(jmesserly): we should make sure this only returns JS AST nodes. |
5456 List/*<R>*/ _visitList/*<T extends AstNode, R>*/(Iterable/*<T>*/ nodes) { | 5501 List/*<R>*/ _visitList/*<T extends AstNode, R>*/(Iterable/*<T>*/ nodes) { |
5457 if (nodes == null) return null; | 5502 if (nodes == null) return null; |
5458 var result = /*<R>*/ []; | 5503 var result = /*<R>*/ []; |
5459 for (var node in nodes) result.add(_visit(node) as dynamic/*=R*/); | 5504 for (var node in nodes) result.add(_visit(node) as dynamic/*=R*/); |
5460 return result; | 5505 return result; |
5461 } | 5506 } |
5462 | 5507 |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5603 useExtension = baseType is InterfaceType && | 5648 useExtension = baseType is InterfaceType && |
5604 _isSymbolizedMember(baseType, name, alwaysSymbolizeNative); | 5649 _isSymbolizedMember(baseType, name, alwaysSymbolizeNative); |
5605 } | 5650 } |
5606 | 5651 |
5607 return useExtension | 5652 return useExtension |
5608 ? js.call('#.#', [_extensionSymbolsModule, result]) | 5653 ? js.call('#.#', [_extensionSymbolsModule, result]) |
5609 : result; | 5654 : result; |
5610 } | 5655 } |
5611 | 5656 |
5612 var _forwardingCache = new HashMap<Element, Map<String, ExecutableElement>>(); | 5657 var _forwardingCache = new HashMap<Element, Map<String, ExecutableElement>>(); |
5658 | |
5613 Element _lookupForwardedMember(ClassElement element, String name) { | 5659 Element _lookupForwardedMember(ClassElement element, String name) { |
5614 // We only care about public methods. | 5660 // We only care about public methods. |
5615 if (name.startsWith('_')) return null; | 5661 if (name.startsWith('_')) return null; |
5616 | 5662 |
5617 var map = _forwardingCache.putIfAbsent(element, () => {}); | 5663 var map = _forwardingCache.putIfAbsent(element, () => {}); |
5618 if (map.containsKey(name)) return map[name]; | 5664 if (map.containsKey(name)) return map[name]; |
5619 | 5665 |
5620 // Note, for a public member, the library should not matter. | 5666 // Note, for a public member, the library should not matter. |
5621 var library = element.library; | 5667 var library = element.library; |
5622 var member = element.lookUpMethod(name, library) ?? | 5668 var member = element.lookUpMethod(name, library) ?? |
(...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5830 return whitelisted.contains(name); | 5876 return whitelisted.contains(name); |
5831 } | 5877 } |
5832 } | 5878 } |
5833 | 5879 |
5834 // Dynamic calls are less risky so there is no need to whitelist at the | 5880 // Dynamic calls are less risky so there is no need to whitelist at the |
5835 // method level. | 5881 // method level. |
5836 if (isCall && _uncheckedWhitelistCalls.contains(filename)) return true; | 5882 if (isCall && _uncheckedWhitelistCalls.contains(filename)) return true; |
5837 | 5883 |
5838 return path.endsWith(".template.dart"); | 5884 return path.endsWith(".template.dart"); |
5839 } | 5885 } |
5886 | |
5887 _unreachable(AstNode node) { | |
5888 throw new UnsupportedError( | |
5889 'tried to generate an unreachable node: `$node`'); | |
5890 } | |
5891 | |
5892 /// Unused, see methods for emitting declarations. | |
5893 @override | |
5894 visitAnnotation(node) => _unreachable(node); | |
5895 | |
5896 /// Unused, see [_emitFieldInitializers]. | |
5897 @override | |
5898 visitAssertInitializer(node) => _unreachable(node); | |
5899 | |
5900 /// Not visited, but maybe they should be? | |
5901 /// See <https://github.com/dart-lang/sdk/issues/29347> | |
5902 @override | |
5903 visitComment(node) => _unreachable(node); | |
5904 | |
5905 /// Not visited, but maybe they should be? | |
5906 /// See <https://github.com/dart-lang/sdk/issues/29347> | |
5907 @override | |
5908 visitCommentReference(node) => _unreachable(node); | |
5909 | |
5910 /// Unused, handled by imports/exports. | |
5911 @override | |
5912 visitConfiguration(node) => _unreachable(node); | |
5913 | |
5914 /// Unusued, see [_emitConstructor]. | |
5915 @override | |
5916 visitConstructorDeclaration(node) => _unreachable(node); | |
5917 | |
5918 /// Unusued, see [_emitFieldInitializers]. | |
5919 @override | |
5920 visitConstructorFieldInitializer(node) => _unreachable(node); | |
5921 | |
5922 /// Unusued. Handled in [visitForEachStatement]. | |
5923 @override | |
5924 visitDeclaredIdentifier(node) => _unreachable(node); | |
5925 | |
5926 /// Unused, handled by imports/exports. | |
5927 @override | |
5928 visitDottedName(node) => _unreachable(node); | |
5929 | |
5930 /// Unused, handled by [visitEnumDeclaration]. | |
5931 @override | |
5932 visitEnumConstantDeclaration(node) => _unreachable(node); // see | |
5933 | |
5934 /// Unused, see [_emitClassHeritage]. | |
5935 @override | |
5936 visitExtendsClause(node) => _unreachable(node); | |
5937 | |
5938 /// Unused, see [_emitFormalParameterList]. | |
5939 @override | |
5940 visitFormalParameterList(node) => _unreachable(node); | |
5941 | |
5942 /// Unused, handled by imports/exports. | |
5943 @override | |
5944 visitShowCombinator(node) => _unreachable(node); | |
5945 | |
5946 /// Unused, handled by imports/exports. | |
5947 @override | |
5948 visitHideCombinator(node) => _unreachable(node); | |
5949 | |
5950 /// Unused, see [_emitClassHeritage]. | |
5951 @override | |
5952 visitImplementsClause(node) => _unreachable(node); | |
5953 | |
5954 /// Unused, handled by [visitStringInterpolation]. | |
5955 @override | |
5956 visitInterpolationString(node) => _unreachable(node); | |
5957 | |
5958 /// Unused, labels are handled by containing statements. | |
5959 @override | |
5960 visitLabel(node) => _unreachable(node); | |
5961 | |
5962 /// Unused, handled by imports/exports. | |
5963 @override | |
5964 visitLibraryIdentifier(node) => _unreachable(node); | |
5965 | |
5966 /// Unused, see [visitMapLiteral]. | |
5967 @override | |
5968 visitMapLiteralEntry(node) => _unreachable(node); | |
5969 | |
5970 /// Unused, see [_emitMethodDeclaration]. | |
5971 @override | |
5972 visitMethodDeclaration(node) => _unreachable(node); | |
5973 | |
5974 /// Unused, these are not visited. | |
5975 @override | |
5976 visitNativeClause(node) => _unreachable(node); | |
5977 | |
5978 /// Unused, these are not visited. | |
5979 @override | |
5980 visitNativeFunctionBody(node) => _unreachable(node); | |
5981 | |
5982 /// Unused, handled by [_emitConstructor]. | |
5983 @override | |
5984 visitSuperConstructorInvocation(node) => _unreachable(node); | |
5985 | |
5986 /// Unused, this can be handled when emitting the module if needed. | |
5987 @override | |
5988 visitScriptTag(node) => _unreachable(node); | |
5989 | |
5990 /// Unused, see [_emitType]. | |
5991 @override | |
5992 visitTypeArgumentList(node) => _unreachable(node); | |
5993 | |
5994 /// Unused, see [_emitType]. | |
5995 @override | |
5996 visitTypeParameter(node) => _unreachable(node); | |
5997 | |
5998 /// Unused, see [_emitType]. | |
5999 @override | |
6000 visitGenericFunctionType(node) => _unreachable(node); | |
6001 | |
6002 /// Unused, see [_emitType]. | |
6003 @override | |
6004 visitTypeParameterList(node) => _unreachable(node); | |
6005 | |
6006 /// Unused, see [_emitClassHeritage]. | |
6007 @override | |
6008 visitWithClause(node) => _unreachable(node); | |
5840 } | 6009 } |
5841 | 6010 |
5842 /// Choose a canonical name from the [library] element. | 6011 /// Choose a canonical name from the [library] element. |
5843 /// | 6012 /// |
5844 /// This never uses the library's name (the identifier in the `library` | 6013 /// This never uses the library's name (the identifier in the `library` |
5845 /// declaration) as it doesn't have any meaningful rules enforced. | 6014 /// declaration) as it doesn't have any meaningful rules enforced. |
5846 String jsLibraryName(String libraryRoot, LibraryElement library) { | 6015 String jsLibraryName(String libraryRoot, LibraryElement library) { |
5847 var uri = library.source.uri; | 6016 var uri = library.source.uri; |
5848 if (uri.scheme == 'dart') { | 6017 if (uri.scheme == 'dart') { |
5849 return uri.path; | 6018 return uri.path; |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5950 if (targetIdentifier.staticElement is! PrefixElement) return false; | 6119 if (targetIdentifier.staticElement is! PrefixElement) return false; |
5951 var prefix = targetIdentifier.staticElement as PrefixElement; | 6120 var prefix = targetIdentifier.staticElement as PrefixElement; |
5952 | 6121 |
5953 // The library the prefix is referring to must come from a deferred import. | 6122 // The library the prefix is referring to must come from a deferred import. |
5954 var containingLibrary = resolutionMap | 6123 var containingLibrary = resolutionMap |
5955 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) | 6124 .elementDeclaredByCompilationUnit(target.root as CompilationUnit) |
5956 .library; | 6125 .library; |
5957 var imports = containingLibrary.getImportsWithPrefix(prefix); | 6126 var imports = containingLibrary.getImportsWithPrefix(prefix); |
5958 return imports.length == 1 && imports[0].isDeferred; | 6127 return imports.length == 1 && imports[0].isDeferred; |
5959 } | 6128 } |
OLD | NEW |