| 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; | 7 import 'dart:collection' show HashSet; |
| 8 import 'dart:io' show Directory, File; | 8 import 'dart:io' show Directory, File; |
| 9 | 9 |
| 10 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; | 10 import 'package:analyzer/analyzer.dart' hide ConstantEvaluator; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 import 'package:dev_compiler/src/checker/rules.dart'; | 27 import 'package:dev_compiler/src/checker/rules.dart'; |
| 28 import 'package:dev_compiler/src/info.dart'; | 28 import 'package:dev_compiler/src/info.dart'; |
| 29 import 'package:dev_compiler/src/options.dart'; | 29 import 'package:dev_compiler/src/options.dart'; |
| 30 import 'package:dev_compiler/src/report.dart'; | 30 import 'package:dev_compiler/src/report.dart'; |
| 31 import 'package:dev_compiler/src/utils.dart'; | 31 import 'package:dev_compiler/src/utils.dart'; |
| 32 import 'code_generator.dart'; | 32 import 'code_generator.dart'; |
| 33 | 33 |
| 34 // This must match the optional parameter name used in runtime.js | 34 // This must match the optional parameter name used in runtime.js |
| 35 const String _jsNamedParameterName = r'opt$'; | 35 const String _jsNamedParameterName = r'opt$'; |
| 36 | 36 |
| 37 bool _isAnnotationType(Annotation m, String name) => m.name.name == name; |
| 38 |
| 39 Annotation _getAnnotation(AnnotatedNode node, String name) => node.metadata |
| 40 .firstWhere((annotation) => _isAnnotationType(annotation, name), |
| 41 orElse: () => null); |
| 42 |
| 43 Annotation _getJsNameAnnotation(AnnotatedNode node) => |
| 44 _getAnnotation(node, "JsName"); |
| 45 |
| 37 class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { | 46 class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { |
| 38 final LibraryInfo libraryInfo; | 47 final LibraryInfo libraryInfo; |
| 39 final TypeRules rules; | 48 final TypeRules rules; |
| 40 | 49 |
| 41 /// The variable for the target of the current `..` cascade expression. | 50 /// The variable for the target of the current `..` cascade expression. |
| 42 SimpleIdentifier _cascadeTarget; | 51 SimpleIdentifier _cascadeTarget; |
| 43 /// The variable for the current catch clause | 52 /// The variable for the current catch clause |
| 44 String _catchParameter; | 53 String _catchParameter; |
| 45 | 54 |
| 46 ClassDeclaration currentClass; | 55 ClassDeclaration currentClass; |
| 47 ConstantEvaluator _constEvaluator; | 56 ConstantEvaluator _constEvaluator; |
| 48 | 57 |
| 49 final _exports = <String>[]; | 58 final _exports = <String>[]; |
| 50 final _lazyFields = <VariableDeclaration>[]; | 59 final _lazyFields = <VariableDeclaration>[]; |
| 51 final _properties = <FunctionDeclaration>[]; | 60 final _properties = <FunctionDeclaration>[]; |
| 52 final _privateNames = new HashSet<String>(); | 61 final _privateNames = new HashSet<String>(); |
| 53 final _pendingPrivateNames = <String>[]; | 62 final _pendingPrivateNames = <String>[]; |
| 54 | 63 |
| 55 JSCodegenVisitor(LibraryInfo libraryInfo, TypeRules rules) | 64 JSCodegenVisitor(LibraryInfo libraryInfo, TypeRules rules) |
| 56 : libraryInfo = libraryInfo, | 65 : libraryInfo = libraryInfo, |
| 57 rules = rules; | 66 rules = rules; |
| 58 | 67 |
| 59 Element get currentLibrary => libraryInfo.library; | 68 Element get currentLibrary => libraryInfo.library; |
| 60 | 69 |
| 61 JS.Program generateLibrary( | 70 JS.Program generateLibrary( |
| 62 Iterable<CompilationUnit> units, CheckerReporter reporter) { | 71 Iterable<CompilationUnit> units, CheckerReporter reporter) { |
| 72 var unit = units.first; |
| 73 var jsDefaultValue = '{}'; |
| 74 if (unit.directives.isNotEmpty) { |
| 75 var annotation = _getJsNameAnnotation(unit.directives.first); |
| 76 if (annotation != null) { |
| 77 var arguments = annotation.arguments.arguments; |
| 78 if (!arguments.isEmpty) { |
| 79 var namedExpression = arguments.first as NamedExpression; |
| 80 var literal = namedExpression.expression as SimpleStringLiteral; |
| 81 jsDefaultValue = literal.stringValue; |
| 82 } |
| 83 } |
| 84 } |
| 63 var body = <JS.Statement>[]; | 85 var body = <JS.Statement>[]; |
| 64 for (var unit in units) { | 86 for (var unit in units) { |
| 65 // TODO(jmesserly): this is needed because RestrictedTypeRules can send | 87 // TODO(jmesserly): this is needed because RestrictedTypeRules can send |
| 66 // messages to CheckerReporter, for things like missing types. | 88 // messages to CheckerReporter, for things like missing types. |
| 67 // We should probably refactor so this can't happen. | 89 // We should probably refactor so this can't happen. |
| 68 var source = unit.element.source; | 90 var source = unit.element.source; |
| 69 _constEvaluator = new ConstantEvaluator(source, rules.provider); | 91 _constEvaluator = new ConstantEvaluator(source, rules.provider); |
| 70 reporter.enterSource(source); | 92 reporter.enterSource(source); |
| 71 body.add(_visit(unit)); | 93 body.add(_visit(unit)); |
| 72 reporter.leaveSource(); | 94 reporter.leaveSource(); |
| 73 } | 95 } |
| 74 | 96 |
| 75 if (_exports.isNotEmpty) body.add(js.comment('Exports:')); | 97 if (_exports.isNotEmpty) body.add(js.comment('Exports:')); |
| 76 | 98 |
| 77 // TODO(jmesserly): make these immutable in JS? | 99 // TODO(jmesserly): make these immutable in JS? |
| 78 for (var name in _exports) { | 100 for (var name in _exports) { |
| 79 body.add(js.statement('$_EXPORTS.# = #;', [name, name])); | 101 body.add(js.statement('$_EXPORTS.# = #;', [name, name])); |
| 80 } | 102 } |
| 81 | 103 |
| 82 var name = jsLibraryName(libraryInfo.library); | 104 var name = jsLibraryName(libraryInfo.library); |
| 105 |
| 106 var defaultValue = js.call(jsDefaultValue); |
| 83 return new JS.Program([ | 107 return new JS.Program([ |
| 84 js.statement('var #;', name), | 108 js.statement('var #;', name), |
| 85 js.statement("(function($_EXPORTS) { 'use strict'; #; })(# || (# = {}));", | 109 js.statement("(function($_EXPORTS) { 'use strict'; #; })(# || (# = #));", |
| 86 [body, name, name]) | 110 [body, name, name, defaultValue]) |
| 87 ]); | 111 ]); |
| 88 } | 112 } |
| 89 | 113 |
| 90 JS.Statement _initPrivateSymbol(String name) => | 114 JS.Statement _initPrivateSymbol(String name) => |
| 91 js.statement('let # = Symbol(#);', [name, js.string(name, "'")]); | 115 js.statement('let # = Symbol(#);', [name, js.string(name, "'")]); |
| 92 | 116 |
| 93 @override | 117 @override |
| 94 JS.Statement visitCompilationUnit(CompilationUnit node) { | 118 JS.Statement visitCompilationUnit(CompilationUnit node) { |
| 95 // TODO(jmesserly): scriptTag, directives. | 119 // TODO(jmesserly): scriptTag, directives. |
| 96 var body = <JS.Statement>[]; | 120 var body = <JS.Statement>[]; |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 224 var dynInst = js.statement('let # = #(#);', [name, genericName, typeArgs]); | 248 var dynInst = js.statement('let # = #(#);', [name, genericName, typeArgs]); |
| 225 | 249 |
| 226 // TODO(jmesserly): is it worth exporting both names? Alternatively we could | 250 // TODO(jmesserly): is it worth exporting both names? Alternatively we could |
| 227 // put the generic type constructor on the <dynamic> instance. | 251 // put the generic type constructor on the <dynamic> instance. |
| 228 if (isPublic(name)) _exports.add('${name}\$'); | 252 if (isPublic(name)) _exports.add('${name}\$'); |
| 229 return new JS.Block([genericDef, dynInst]); | 253 return new JS.Block([genericDef, dynInst]); |
| 230 } | 254 } |
| 231 | 255 |
| 232 @override | 256 @override |
| 233 JS.Statement visitClassDeclaration(ClassDeclaration node) { | 257 JS.Statement visitClassDeclaration(ClassDeclaration node) { |
| 258 if (_getJsNameAnnotation(node) != null) return null; |
| 259 |
| 234 currentClass = node; | 260 currentClass = node; |
| 235 | 261 |
| 236 var body = <JS.Statement>[]; | 262 var body = <JS.Statement>[]; |
| 237 | 263 |
| 238 var name = node.name.name; | 264 var name = node.name.name; |
| 239 var ctors = <ConstructorDeclaration>[]; | 265 var ctors = <ConstructorDeclaration>[]; |
| 240 var fields = <FieldDeclaration>[]; | 266 var fields = <FieldDeclaration>[]; |
| 241 var staticFields = <FieldDeclaration>[]; | 267 var staticFields = <FieldDeclaration>[]; |
| 242 for (var member in node.members) { | 268 for (var member in node.members) { |
| 243 if (member is ConstructorDeclaration) { | 269 if (member is ConstructorDeclaration) { |
| (...skipping 1795 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2039 | 2065 |
| 2040 // TODO(jmesserly): in many cases marking the end will be unncessary. | 2066 // TODO(jmesserly): in many cases marking the end will be unncessary. |
| 2041 printer.mark(_location(node.end)); | 2067 printer.mark(_location(node.end)); |
| 2042 } | 2068 } |
| 2043 | 2069 |
| 2044 String _getIdentifier(AstNode node) { | 2070 String _getIdentifier(AstNode node) { |
| 2045 if (node is SimpleIdentifier) return node.name; | 2071 if (node is SimpleIdentifier) return node.name; |
| 2046 return null; | 2072 return null; |
| 2047 } | 2073 } |
| 2048 } | 2074 } |
| OLD | NEW |