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

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

Issue 1084783005: use Analyzer's computed constants instead of pattern matching the annotation AST (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | lib/src/utils.dart » ('j') | lib/src/utils.dart » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dev_compiler.src.codegen.js_codegen; 5 library dev_compiler.src.codegen.js_codegen;
6 6
7 import 'dart:collection' show HashSet, HashMap; 7 import 'dart:collection' show HashSet, HashMap;
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 15 matching lines...) Expand all
26 26
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/utils.dart'; 30 import 'package:dev_compiler/src/utils.dart';
31 31
32 import 'code_generator.dart'; 32 import 'code_generator.dart';
33 import 'js_names.dart'; 33 import 'js_names.dart';
34 import 'js_metalet.dart'; 34 import 'js_metalet.dart';
35 35
36 bool _isAnnotationType(Annotation m, String name) => m.name.name == name;
37
38 Annotation _getAnnotation(AnnotatedNode node, String name) => node.metadata
39 .firstWhere((annotation) => _isAnnotationType(annotation, name),
40 orElse: () => null);
41
42 Annotation _getJsNameAnnotation(AnnotatedNode node) =>
43 _getAnnotation(node, "JsName");
44
45 // TODO(jacobr): we would like to do something like the following
46 // but we don't have summary support yet.
47 // bool _supportJsExtensionMethod(AnnotatedNode node) =>
48 // _getAnnotation(node, "SupportJsExtensionMethod") != null;
49
50 class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor { 36 class JSCodegenVisitor extends GeneralizingAstVisitor with ConversionVisitor {
51 final LibraryInfo libraryInfo; 37 final LibraryInfo libraryInfo;
52 final TypeRules rules; 38 final TypeRules rules;
53 39
54 /// The variable for the target of the current `..` cascade expression. 40 /// The variable for the target of the current `..` cascade expression.
55 SimpleIdentifier _cascadeTarget; 41 SimpleIdentifier _cascadeTarget;
56 /// The variable for the current catch clause 42 /// The variable for the current catch clause
57 SimpleIdentifier _catchParameter; 43 SimpleIdentifier _catchParameter;
58 44
59 ClassDeclaration currentClass; 45 ClassDeclaration currentClass;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
115 LibraryElement get currentLibrary => libraryInfo.library; 101 LibraryElement get currentLibrary => libraryInfo.library;
116 102
117 /// The name for the library's exports inside itself. 103 /// The name for the library's exports inside itself.
118 /// This much be a constant because we interpolate it into template strings, 104 /// This much be a constant because we interpolate it into template strings,
119 /// and otherwise it would break caching for them. 105 /// and otherwise it would break caching for them.
120 /// `exports` was chosen as the most similar to ES module patterns. 106 /// `exports` was chosen as the most similar to ES module patterns.
121 final JSTemporary _exportsVar = new JSTemporary('exports'); 107 final JSTemporary _exportsVar = new JSTemporary('exports');
122 final JSTemporary _namedArgTemp = new JSTemporary('opts'); 108 final JSTemporary _namedArgTemp = new JSTemporary('opts');
123 109
124 JS.Program emitLibrary(LibraryUnit library) { 110 JS.Program emitLibrary(LibraryUnit library) {
125 var jsDefaultValue = '{}'; 111 String jsDefaultValue = null;
126 var unit = library.library; 112 var unit = library.library;
127 if (unit.directives.isNotEmpty) { 113 if (unit.directives.isNotEmpty) {
128 var annotation = _getJsNameAnnotation(unit.directives.first); 114 var libraryDir = unit.directives.first;
129 if (annotation != null) { 115 if (libraryDir is LibraryDirective) {
130 var arguments = annotation.arguments.arguments; 116 var jsName = getAnnotationValue(libraryDir, _isJsNameAnnotation);
131 if (!arguments.isEmpty) { 117 jsDefaultValue = getStringConstantField(jsName, 'name');
132 var namedExpression = arguments.first as NamedExpression;
133 var literal = namedExpression.expression as SimpleStringLiteral;
134 jsDefaultValue = literal.stringValue;
135 }
136 } 118 }
137 } 119 }
120 if (jsDefaultValue == null) jsDefaultValue = '{}';
121
138 var body = <JS.Statement>[]; 122 var body = <JS.Statement>[];
139 123
140 // Collect classes we need to emit, used for: 124 // Collect classes we need to emit, used for:
141 // * tracks what we've emitted so we don't emit twice 125 // * tracks what we've emitted so we don't emit twice
142 // * provides a mapping from ClassElement back to the ClassDeclaration. 126 // * provides a mapping from ClassElement back to the ClassDeclaration.
143 for (var unit in library.partsThenLibrary) { 127 for (var unit in library.partsThenLibrary) {
144 for (var decl in unit.declarations) { 128 for (var decl in unit.declarations) {
145 if (decl is ClassDeclaration || 129 if (decl is ClassDeclaration ||
146 decl is ClassTypeAlias || 130 decl is ClassTypeAlias ||
147 decl is FunctionTypeAlias) { 131 decl is FunctionTypeAlias) {
(...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 310
327 var name = node.name.name; 311 var name = node.name.name;
328 var heritage = 312 var heritage =
329 js.call('dart.mixin(#)', [_visitList(node.withClause.mixinTypes)]); 313 js.call('dart.mixin(#)', [_visitList(node.withClause.mixinTypes)]);
330 var classDecl = new JS.ClassDeclaration( 314 var classDecl = new JS.ClassDeclaration(
331 new JS.ClassExpression(new JS.Identifier(name), heritage, [])); 315 new JS.ClassExpression(new JS.Identifier(name), heritage, []));
332 316
333 return _finishClassDef(type, classDecl); 317 return _finishClassDef(type, classDecl);
334 } 318 }
335 319
336 JS.Statement _emitJsType(ClassDeclaration node, Annotation jsName) { 320 JS.Statement _emitJsType(String dartClassName, DartObjectImpl jsName) {
337 var dartName = node.name.name; 321 var jsTypeName = getStringConstantField(jsName, 'name');
338 var jsTypeName = _getLiteralStringNamedArg(jsName, 'name');
339 322
340 if (jsTypeName != null && jsTypeName != dartName) { 323 if (jsTypeName != null && jsTypeName != dartClassName) {
341 // We export the JS type as if it was a Dart type. For example this allows 324 // We export the JS type as if it was a Dart type. For example this allows
342 // `dom.InputElement` to actually be HTMLInputElement. 325 // `dom.InputElement` to actually be HTMLInputElement.
343 // TODO(jmesserly): if we had the JsName on the Element, we could just 326 // TODO(jmesserly): if we had the JsName on the Element, we could just
344 // generate it correctly when we refer to it. 327 // generate it correctly when we refer to it.
345 if (isPublic(dartName)) _addExport(dartName); 328 if (isPublic(dartClassName)) _addExport(dartClassName);
346 return js.statement('let # = #;', [dartName, jsTypeName]); 329 return js.statement('let # = #;', [dartClassName, jsTypeName]);
347 } 330 }
348 return null; 331 return null;
349 } 332 }
350 333
351 @override 334 @override
352 JS.Statement visitClassDeclaration(ClassDeclaration node) { 335 JS.Statement visitClassDeclaration(ClassDeclaration node) {
353 // If we've already emitted this class, skip it. 336 // If we've already emitted this class, skip it.
354 var type = node.element.type; 337 var type = node.element.type;
355 if (_pendingClasses.remove(node.element) == null) return null; 338 if (_pendingClasses.remove(node.element) == null) return null;
356 339
357 var jsName = _getJsNameAnnotation(node); 340 var jsName = getAnnotationValue(node, _isJsNameAnnotation);
358 if (jsName != null) return _emitJsType(node, jsName); 341 if (jsName != null) return _emitJsType(node.name.name, jsName);
359 342
360 currentClass = node; 343 currentClass = node;
361 344
362 var ctors = <ConstructorDeclaration>[]; 345 var ctors = <ConstructorDeclaration>[];
363 var fields = <FieldDeclaration>[]; 346 var fields = <FieldDeclaration>[];
364 var staticFields = <FieldDeclaration>[]; 347 var staticFields = <FieldDeclaration>[];
365 for (var member in node.members) { 348 for (var member in node.members) {
366 if (member is ConstructorDeclaration) { 349 if (member is ConstructorDeclaration) {
367 ctors.add(member); 350 ctors.add(member);
368 } else if (member is FieldDeclaration) { 351 } else if (member is FieldDeclaration) {
(...skipping 2218 matching lines...) Expand 10 before | Expand all | Expand 10 after
2587 identical(parent.methodName, node)) return; 2570 identical(parent.methodName, node)) return;
2588 if (parent is ConstructorName) return; 2571 if (parent is ConstructorName) return;
2589 if (parent is Label) return; 2572 if (parent is Label) return;
2590 2573
2591 if (node.inSetterContext() && node.staticElement == _variable) { 2574 if (node.inSetterContext() && node.staticElement == _variable) {
2592 _potentiallyMutated = true; 2575 _potentiallyMutated = true;
2593 } 2576 }
2594 } 2577 }
2595 } 2578 }
2596 2579
2597 String _getLiteralStringNamedArg(Annotation annotation, String argName) { 2580 bool _isJsNameAnnotation(DartObjectImpl value) {
2598 if (annotation.arguments != null) { 2581 var type = value.type;
2599 var args = annotation.arguments.arguments; 2582 var library = type.element.library;
2600 if (args.isNotEmpty && args[0] is NamedExpression) { 2583 // TODO(jmesserly): move JsName to dart:js
Jacob 2015/04/14 20:54:33 until we move it to dart:js can't we just be permi
Jennifer Messerly 2015/04/15 00:21:26 hmmm. The current situation does indeed seem odd.
2601 NamedExpression named = args[0]; 2584 return type.name == 'JsName' && (library.isDartCore || library.name == 'dom');
2602 if (named.name.label.name == argName &&
2603 named.expression is StringLiteral) {
2604 return (named.expression as StringLiteral).stringValue;
2605 }
2606 }
2607 }
2608 return null;
2609 } 2585 }
2586
2587 // TODO(jacobr): we would like to do something like the following
2588 // but we don't have summary support yet.
2589 // bool _supportJsExtensionMethod(AnnotatedNode node) =>
2590 // _getAnnotation(node, "SupportJsExtensionMethod") != null;
OLDNEW
« no previous file with comments | « no previous file | lib/src/utils.dart » ('j') | lib/src/utils.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698