| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
| 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. |
| 4 |
| 5 library dart2js.resolution_strategy; |
| 6 |
| 7 import '../common.dart'; |
| 8 import '../common_elements.dart'; |
| 9 import '../common/resolution.dart'; |
| 10 import '../common/tasks.dart'; |
| 11 import '../compiler.dart'; |
| 12 import '../elements/elements.dart'; |
| 13 import '../elements/entities.dart'; |
| 14 import '../elements/resolution_types.dart'; |
| 15 import '../environment.dart'; |
| 16 import '../frontend_strategy.dart'; |
| 17 import '../library_loader.dart'; |
| 18 import '../native/resolver.dart'; |
| 19 import '../js_backend/native_data.dart'; |
| 20 import '../serialization/task.dart'; |
| 21 import '../patch_parser.dart'; |
| 22 import '../resolved_uri_translator.dart'; |
| 23 import '../universe/call_structure.dart'; |
| 24 |
| 25 /// [FrontendStrategy] that loads '.dart' files and creates a resolved element |
| 26 /// model using the resolver. |
| 27 class ResolutionFrontEndStrategy implements FrontEndStrategy { |
| 28 final Compiler _compiler; |
| 29 final ElementEnvironment elementEnvironment; |
| 30 AnnotationProcessor _annotationProcessor; |
| 31 |
| 32 ResolutionFrontEndStrategy(this._compiler) |
| 33 : elementEnvironment = new _CompilerElementEnvironment(_compiler); |
| 34 |
| 35 LibraryLoaderTask createLibraryLoader( |
| 36 ResolvedUriTranslator uriTranslator, |
| 37 ScriptLoader scriptLoader, |
| 38 ElementScanner scriptScanner, |
| 39 LibraryDeserializer deserializer, |
| 40 PatchResolverFunction patchResolverFunc, |
| 41 PatchParserTask patchParser, |
| 42 Environment environment, |
| 43 DiagnosticReporter reporter, |
| 44 Measurer measurer) { |
| 45 return new ResolutionLibraryLoaderTask( |
| 46 uriTranslator, |
| 47 scriptLoader, |
| 48 scriptScanner, |
| 49 deserializer, |
| 50 patchResolverFunc, |
| 51 patchParser, |
| 52 environment, |
| 53 reporter, |
| 54 measurer); |
| 55 } |
| 56 |
| 57 AnnotationProcessor get annotationProcesser => |
| 58 _annotationProcessor ??= new _ElementAnnotationProcessor(_compiler); |
| 59 } |
| 60 |
| 61 /// An element environment base on a [Compiler]. |
| 62 class _CompilerElementEnvironment implements ElementEnvironment { |
| 63 final Compiler _compiler; |
| 64 |
| 65 _CompilerElementEnvironment(this._compiler); |
| 66 |
| 67 LibraryProvider get _libraryProvider => _compiler.libraryLoader; |
| 68 Resolution get _resolution => _compiler.resolution; |
| 69 |
| 70 ResolutionDynamicType get dynamicType => const ResolutionDynamicType(); |
| 71 |
| 72 @override |
| 73 LibraryEntity get mainLibrary => _compiler.mainApp; |
| 74 |
| 75 @override |
| 76 FunctionEntity get mainFunction => _compiler.mainFunction; |
| 77 |
| 78 @override |
| 79 Iterable<LibraryEntity> get libraries => _compiler.libraryLoader.libraries; |
| 80 |
| 81 @override |
| 82 ResolutionInterfaceType getThisType(ClassElement cls) { |
| 83 cls.ensureResolved(_resolution); |
| 84 return cls.thisType; |
| 85 } |
| 86 |
| 87 @override |
| 88 ResolutionInterfaceType getRawType(ClassElement cls) { |
| 89 cls.ensureResolved(_resolution); |
| 90 return cls.rawType; |
| 91 } |
| 92 |
| 93 @override |
| 94 ResolutionDartType getTypeVariableBound(TypeVariableElement typeVariable) { |
| 95 return typeVariable.bound; |
| 96 } |
| 97 |
| 98 @override |
| 99 ResolutionInterfaceType createInterfaceType( |
| 100 ClassElement cls, List<ResolutionDartType> typeArguments) { |
| 101 cls.ensureResolved(_resolution); |
| 102 return cls.thisType.createInstantiation(typeArguments); |
| 103 } |
| 104 |
| 105 @override |
| 106 bool isSubtype(ResolutionDartType a, ResolutionDartType b) { |
| 107 return _compiler.types.isSubtype(a, b); |
| 108 } |
| 109 |
| 110 @override |
| 111 MemberElement lookupClassMember(ClassElement cls, String name, |
| 112 {bool setter: false, bool required: false}) { |
| 113 cls.ensureResolved(_resolution); |
| 114 Element member = cls.implementation.lookupLocalMember(name); |
| 115 if (member != null && member.isAbstractField) { |
| 116 AbstractFieldElement abstractField = member; |
| 117 if (setter) { |
| 118 member = abstractField.setter; |
| 119 } else { |
| 120 member = abstractField.getter; |
| 121 } |
| 122 if (member == null && required) { |
| 123 throw new SpannableAssertionFailure( |
| 124 cls, |
| 125 "The class '${cls.name}' does not contain required " |
| 126 "${setter ? 'setter' : 'getter'}: '$name'."); |
| 127 } |
| 128 } |
| 129 if (member == null && required) { |
| 130 throw new SpannableAssertionFailure( |
| 131 cls, |
| 132 "The class '${cls.name}' does not " |
| 133 "contain required member: '$name'."); |
| 134 } |
| 135 return member?.declaration; |
| 136 } |
| 137 |
| 138 @override |
| 139 ConstructorElement lookupConstructor(ClassElement cls, String name, |
| 140 {bool required: false}) { |
| 141 cls.ensureResolved(_resolution); |
| 142 ConstructorElement constructor = cls.implementation.lookupConstructor(name); |
| 143 if (constructor == null && required) { |
| 144 throw new SpannableAssertionFailure( |
| 145 cls, |
| 146 "The class '${cls.name}' does not contain " |
| 147 "required constructor: '$name'."); |
| 148 } |
| 149 return constructor?.declaration; |
| 150 } |
| 151 |
| 152 @override |
| 153 void forEachClassMember( |
| 154 ClassElement cls, void f(ClassElement declarer, MemberElement member)) { |
| 155 cls.ensureResolved(_resolution); |
| 156 cls.forEachMember((ClassElement declarer, MemberElement member) { |
| 157 if (member.isSynthesized) return; |
| 158 if (member.isMalformed) return; |
| 159 f(declarer, member); |
| 160 }, includeSuperAndInjectedMembers: true); |
| 161 } |
| 162 |
| 163 @override |
| 164 ClassEntity getSuperClass(ClassElement cls) => cls.superclass; |
| 165 |
| 166 @override |
| 167 void forEachSupertype( |
| 168 ClassElement cls, void f(ResolutionInterfaceType supertype)) { |
| 169 cls.allSupertypes |
| 170 .forEach((ResolutionInterfaceType supertype) => f(supertype)); |
| 171 } |
| 172 |
| 173 @override |
| 174 void forEachMixin(ClassElement cls, void f(ClassElement mixin)) { |
| 175 for (; cls != null; cls = cls.superclass) { |
| 176 if (cls.isMixinApplication) { |
| 177 MixinApplicationElement mixinApplication = cls; |
| 178 f(mixinApplication.mixin); |
| 179 } |
| 180 } |
| 181 } |
| 182 |
| 183 @override |
| 184 MemberElement lookupLibraryMember(LibraryElement library, String name, |
| 185 {bool setter: false, bool required: false}) { |
| 186 Element member = library.implementation.findLocal(name); |
| 187 if (member != null && member.isAbstractField) { |
| 188 AbstractFieldElement abstractField = member; |
| 189 if (setter) { |
| 190 member = abstractField.setter; |
| 191 } else { |
| 192 member = abstractField.getter; |
| 193 } |
| 194 if (member == null && required) { |
| 195 throw new SpannableAssertionFailure( |
| 196 library, |
| 197 "The library '${library.canonicalUri}' does not contain required " |
| 198 "${setter ? 'setter' : 'getter'}: '$name'."); |
| 199 } |
| 200 } |
| 201 if (member == null && required) { |
| 202 throw new SpannableAssertionFailure( |
| 203 member, |
| 204 "The library '${library.libraryName}' does not " |
| 205 "contain required member: '$name'."); |
| 206 } |
| 207 return member?.declaration; |
| 208 } |
| 209 |
| 210 @override |
| 211 ClassElement lookupClass(LibraryElement library, String name, |
| 212 {bool required: false}) { |
| 213 ClassElement cls = library.implementation.findLocal(name); |
| 214 if (cls == null && required) { |
| 215 throw new SpannableAssertionFailure( |
| 216 cls, |
| 217 "The library '${library.libraryName}' does not " |
| 218 "contain required class: '$name'."); |
| 219 } |
| 220 return cls?.declaration; |
| 221 } |
| 222 |
| 223 @override |
| 224 void forEachClass(LibraryElement library, void f(ClassElement cls)) { |
| 225 library.implementation.forEachLocalMember((member) { |
| 226 if (member.isClass) { |
| 227 f(member); |
| 228 } |
| 229 }); |
| 230 } |
| 231 |
| 232 @override |
| 233 LibraryElement lookupLibrary(Uri uri, {bool required: false}) { |
| 234 LibraryElement library = _libraryProvider.lookupLibrary(uri); |
| 235 // If the script of the library is synthesized, the library does not exist |
| 236 // and we do not try to load the helpers. |
| 237 // |
| 238 // This could for example happen if dart:async is disabled, then loading it |
| 239 // should not try to find the given element. |
| 240 if (library != null && library.isSynthesized) { |
| 241 return null; |
| 242 } |
| 243 if (library == null && required) { |
| 244 throw new SpannableAssertionFailure( |
| 245 library, "The library '${uri}' was not found."); |
| 246 } |
| 247 return library; |
| 248 } |
| 249 |
| 250 @override |
| 251 CallStructure getCallStructure(MethodElement method) { |
| 252 ResolutionFunctionType type = method.computeType(_resolution); |
| 253 return new CallStructure( |
| 254 type.parameterTypes.length + |
| 255 type.optionalParameterTypes.length + |
| 256 type.namedParameterTypes.length, |
| 257 type.namedParameters); |
| 258 } |
| 259 |
| 260 @override |
| 261 bool isDeferredLoadLibraryGetter(MemberElement member) { |
| 262 return member.isDeferredLoaderGetter; |
| 263 } |
| 264 |
| 265 @override |
| 266 ResolutionFunctionType getFunctionType(MethodElement method) { |
| 267 method.computeType(_resolution); |
| 268 return method.type; |
| 269 } |
| 270 |
| 271 @override |
| 272 ResolutionFunctionType getLocalFunctionType(LocalFunctionElement function) { |
| 273 return function.type; |
| 274 } |
| 275 |
| 276 @override |
| 277 ResolutionDartType getUnaliasedType(ResolutionDartType type) { |
| 278 type.computeUnaliased(_resolution); |
| 279 return type.unaliased; |
| 280 } |
| 281 } |
| 282 |
| 283 /// AST-based logic for processing annotations. These annotations are processed |
| 284 /// very early in the compilation pipeline, typically this is before resolution |
| 285 /// is complete. Because of that this processor does a lightweight parse of the |
| 286 /// annotation (which is restricted to a limited subset of the annotation |
| 287 /// syntax), and, once resolution completes, it validates that the parsed |
| 288 /// annotations correspond to the correct element. |
| 289 class _ElementAnnotationProcessor implements AnnotationProcessor { |
| 290 Compiler _compiler; |
| 291 |
| 292 _ElementAnnotationProcessor(this._compiler); |
| 293 |
| 294 /// Check whether [cls] has a `@Native(...)` annotation, and if so, set its |
| 295 /// native name from the annotation. |
| 296 void extractNativeAnnotations( |
| 297 LibraryElement library, NativeBasicDataBuilder nativeBasicDataBuilder) { |
| 298 library.forEachLocalMember((Element element) { |
| 299 if (element.isClass) { |
| 300 EagerAnnotationHandler.checkAnnotation(_compiler, element, |
| 301 new NativeAnnotationHandler(nativeBasicDataBuilder)); |
| 302 } |
| 303 }); |
| 304 } |
| 305 |
| 306 void extractJsInteropAnnotations( |
| 307 LibraryElement library, NativeBasicDataBuilder nativeBasicDataBuilder) { |
| 308 bool checkJsInteropAnnotation(Element element) { |
| 309 return EagerAnnotationHandler.checkAnnotation( |
| 310 _compiler, element, const JsInteropAnnotationHandler()); |
| 311 } |
| 312 |
| 313 if (checkJsInteropAnnotation(library)) { |
| 314 nativeBasicDataBuilder.markAsJsInteropLibrary(library); |
| 315 } |
| 316 library.forEachLocalMember((Element element) { |
| 317 if (element.isClass) { |
| 318 ClassElement cls = element; |
| 319 if (checkJsInteropAnnotation(element)) { |
| 320 nativeBasicDataBuilder.markAsJsInteropClass(cls); |
| 321 } |
| 322 } |
| 323 }); |
| 324 } |
| 325 } |
| OLD | NEW |