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 /// Analysis to determine how to generate code for typed JavaScript interop. | 5 /// Analysis to determine how to generate code for typed JavaScript interop. |
6 library compiler.src.js_backend.js_interop_analysis; | 6 library compiler.src.js_backend.js_interop_analysis; |
7 | 7 |
8 import '../common.dart'; | 8 import '../common.dart'; |
9 import '../constants/values.dart' | 9 import '../constants/values.dart' |
10 show ConstantValue, ConstructedConstantValue, StringConstantValue; | 10 show ConstantValue, ConstructedConstantValue, StringConstantValue; |
11 import '../elements/resolution_types.dart' | 11 import '../elements/resolution_types.dart' |
12 show ResolutionDartType, ResolutionDynamicType, ResolutionFunctionType; | 12 show ResolutionDartType, ResolutionDynamicType, ResolutionFunctionType; |
13 import '../diagnostics/messages.dart' show MessageKind; | 13 import '../diagnostics/messages.dart' show MessageKind; |
14 import '../elements/elements.dart' | 14 import '../elements/elements.dart' |
15 show | 15 show |
16 ClassElement, | 16 ClassElement, |
17 Element, | 17 Element, |
18 FieldElement, | 18 FieldElement, |
19 FunctionElement, | 19 FunctionElement, |
20 LibraryElement, | 20 LibraryElement, |
21 ParameterElement, | 21 ParameterElement, |
| 22 MethodElement, |
22 MetadataAnnotation; | 23 MetadataAnnotation; |
23 import '../js/js.dart' as jsAst; | 24 import '../js/js.dart' as jsAst; |
24 import '../js/js.dart' show js; | 25 import '../js/js.dart' show js; |
25 import '../universe/selector.dart' show Selector; | 26 import '../universe/selector.dart' show Selector; |
26 import '../universe/world_builder.dart' show SelectorConstraints; | 27 import '../universe/world_builder.dart' show SelectorConstraints; |
27 import 'backend_helpers.dart' show BackendHelpers; | 28 import 'backend_helpers.dart' show BackendHelpers; |
28 import 'js_backend.dart' show JavaScriptBackend; | 29 import 'js_backend.dart' show JavaScriptBackend; |
29 | 30 |
30 class JsInteropAnalysis { | 31 class JsInteropAnalysis { |
31 final JavaScriptBackend backend; | 32 final JavaScriptBackend backend; |
(...skipping 29 matching lines...) Expand all Loading... |
61 // TODO(johnniwinther): Avoid processing unresolved elements. | 62 // TODO(johnniwinther): Avoid processing unresolved elements. |
62 if (annotation.constant == null) continue; | 63 if (annotation.constant == null) continue; |
63 ConstantValue constant = | 64 ConstantValue constant = |
64 backend.compiler.constants.getConstantValue(annotation.constant); | 65 backend.compiler.constants.getConstantValue(annotation.constant); |
65 if (constant == null || constant is! ConstructedConstantValue) continue; | 66 if (constant == null || constant is! ConstructedConstantValue) continue; |
66 ConstructedConstantValue constructedConstant = constant; | 67 ConstructedConstantValue constructedConstant = constant; |
67 if (constructedConstant.type.element == helpers.jsAnnotationClass) { | 68 if (constructedConstant.type.element == helpers.jsAnnotationClass) { |
68 ConstantValue value = constructedConstant.fields[nameField]; | 69 ConstantValue value = constructedConstant.fields[nameField]; |
69 if (value.isString) { | 70 if (value.isString) { |
70 StringConstantValue stringValue = value; | 71 StringConstantValue stringValue = value; |
71 backend.nativeClassDataBuilder | 72 backend.nativeDataBuilder |
72 .setJsInteropName(e, stringValue.primitiveValue.slowToString()); | 73 .setJsInteropName(e, stringValue.primitiveValue.slowToString()); |
73 } else { | 74 } else { |
74 // TODO(jacobr): report a warning if the value is not a String. | 75 // TODO(jacobr): report a warning if the value is not a String. |
75 backend.nativeClassDataBuilder.setJsInteropName(e, ''); | 76 backend.nativeDataBuilder.setJsInteropName(e, ''); |
76 } | 77 } |
77 enabledJsInterop = true; | 78 enabledJsInterop = true; |
78 return; | 79 return; |
79 } | 80 } |
80 } | 81 } |
81 } | 82 } |
82 | 83 |
83 bool hasAnonymousAnnotation(Element element) { | 84 bool hasAnonymousAnnotation(Element element) { |
84 if (backend.helpers.jsAnonymousClass == null) return false; | 85 if (backend.helpers.jsAnonymousClass == null) return false; |
85 return element.metadata.any((MetadataAnnotation annotation) { | 86 return element.metadata.any((MetadataAnnotation annotation) { |
(...skipping 14 matching lines...) Expand all Loading... |
100 fn, | 101 fn, |
101 MessageKind.JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS, | 102 MessageKind.JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS, |
102 {'method': fn.name}); | 103 {'method': fn.name}); |
103 } | 104 } |
104 } | 105 } |
105 | 106 |
106 void processJsInteropAnnotationsInLibrary(LibraryElement library) { | 107 void processJsInteropAnnotationsInLibrary(LibraryElement library) { |
107 processJsInteropAnnotation(library); | 108 processJsInteropAnnotation(library); |
108 library.implementation.forEachLocalMember((Element element) { | 109 library.implementation.forEachLocalMember((Element element) { |
109 processJsInteropAnnotation(element); | 110 processJsInteropAnnotation(element); |
110 if (!backend.nativeData.isJsInterop(element)) return; | 111 if (element is MethodElement) { |
111 if (element is FunctionElement) { | 112 if (!backend.nativeData.isJsInteropMember(element)) return; |
112 _checkFunctionParameters(element); | 113 _checkFunctionParameters(element); |
113 } | 114 } |
114 | 115 |
115 if (!element.isClass) return; | 116 if (!element.isClass) return; |
116 | 117 |
117 ClassElement classElement = element; | 118 ClassElement classElement = element; |
| 119 if (!backend.nativeData.isJsInteropClass(classElement)) return; |
118 | 120 |
119 // Skip classes that are completely unreachable. This should only happen | 121 // Skip classes that are completely unreachable. This should only happen |
120 // when all of jsinterop types are unreachable from main. | 122 // when all of jsinterop types are unreachable from main. |
121 if (!backend.compiler.resolutionWorldBuilder | 123 if (!backend.compiler.resolutionWorldBuilder |
122 .isImplemented(classElement)) { | 124 .isImplemented(classElement)) { |
123 return; | 125 return; |
124 } | 126 } |
125 | 127 |
126 if (!classElement.implementsInterface(helpers.jsJavaScriptObjectClass)) { | 128 if (!classElement.implementsInterface(helpers.jsJavaScriptObjectClass)) { |
127 backend.reporter.reportErrorMessage(classElement, | 129 backend.reporter.reportErrorMessage(classElement, |
128 MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, { | 130 MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, { |
129 'cls': classElement.name, | 131 'cls': classElement.name, |
130 'superclass': classElement.superclass.name | 132 'superclass': classElement.superclass.name |
131 }); | 133 }); |
132 } | 134 } |
133 | 135 |
134 classElement.forEachMember((ClassElement classElement, Element member) { | 136 classElement.forEachMember((ClassElement classElement, Element member) { |
135 processJsInteropAnnotation(member); | 137 processJsInteropAnnotation(member); |
136 | 138 |
137 if (!member.isSynthesized && | 139 if (!member.isSynthesized && |
138 backend.nativeData.isJsInterop(classElement) && | 140 backend.nativeData.isJsInteropClass(classElement) && |
139 member is FunctionElement) { | 141 member is FunctionElement) { |
140 FunctionElement fn = member; | 142 FunctionElement fn = member; |
141 if (!fn.isExternal && | 143 if (!fn.isExternal && |
142 !fn.isAbstract && | 144 !fn.isAbstract && |
143 !fn.isConstructor && | 145 !fn.isConstructor && |
144 !fn.isStatic) { | 146 !fn.isStatic) { |
145 backend.reporter.reportErrorMessage( | 147 backend.reporter.reportErrorMessage( |
146 fn, | 148 fn, |
147 MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER, | 149 MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER, |
148 {'cls': classElement.name, 'member': member.name}); | 150 {'cls': classElement.name, 'member': member.name}); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
195 ResolutionFunctionType buildJsFunctionType() { | 197 ResolutionFunctionType buildJsFunctionType() { |
196 // TODO(jacobr): consider using codegenWorldBuilder.isChecks to determine th
e | 198 // TODO(jacobr): consider using codegenWorldBuilder.isChecks to determine th
e |
197 // range of positional arguments that need to be supported by JavaScript | 199 // range of positional arguments that need to be supported by JavaScript |
198 // function types. | 200 // function types. |
199 return new ResolutionFunctionType.synthesized( | 201 return new ResolutionFunctionType.synthesized( |
200 const ResolutionDynamicType(), | 202 const ResolutionDynamicType(), |
201 [], | 203 [], |
202 new List<ResolutionDartType>.filled(16, const ResolutionDynamicType())); | 204 new List<ResolutionDartType>.filled(16, const ResolutionDynamicType())); |
203 } | 205 } |
204 } | 206 } |
OLD | NEW |