| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 import 'package:front_end/src/fasta/scanner.dart' | 5 import 'package:front_end/src/fasta/scanner.dart' |
| 6 show BeginGroupToken, StringToken, Token; | 6 show BeginGroupToken, StringToken, Token; |
| 7 import 'package:front_end/src/fasta/scanner.dart' as Tokens show EOF_TOKEN; | 7 import 'package:front_end/src/fasta/scanner.dart' as Tokens show EOF_TOKEN; |
| 8 | 8 |
| 9 import '../common.dart'; | 9 import '../common.dart'; |
| 10 import '../common_elements.dart' show CommonElements; | 10 import '../common_elements.dart' show CommonElements; |
| 11 import '../common/backend_api.dart'; | 11 import '../common/backend_api.dart'; |
| 12 import '../common/resolution.dart'; | 12 import '../common/resolution.dart'; |
| 13 import '../compiler.dart' show Compiler; | 13 import '../compiler.dart' show Compiler; |
| 14 import '../constants/values.dart'; | 14 import '../constants/values.dart'; |
| 15 import '../elements/elements.dart' | 15 import '../elements/elements.dart' |
| 16 show | 16 show |
| 17 ClassElement, | 17 ClassElement, |
| 18 Element, | 18 Element, |
| 19 FieldElement, | 19 FieldElement, |
| 20 LibraryElement, | 20 LibraryElement, |
| 21 MemberElement, | 21 MemberElement, |
| 22 MetadataAnnotation, | 22 MetadataAnnotation, |
| 23 MethodElement; | 23 MethodElement; |
| 24 import '../elements/entities.dart'; | 24 import '../elements/entities.dart'; |
| 25 import '../elements/modelx.dart' show FunctionElementX, MetadataAnnotationX; | 25 import '../elements/modelx.dart' show FunctionElementX, MetadataAnnotationX; |
| 26 import '../elements/resolution_types.dart' show ResolutionDartType; | 26 import '../elements/resolution_types.dart' show ResolutionDartType; |
| 27 import '../js_backend/js_backend.dart'; | 27 import '../js_backend/js_backend.dart'; |
| 28 import '../js_backend/native_data.dart'; | 28 import '../js_backend/native_data.dart'; |
| 29 import '../kernel/world_builder.dart' show KernelAnnotationProcessor; |
| 29 import '../patch_parser.dart'; | 30 import '../patch_parser.dart'; |
| 30 import '../tree/tree.dart'; | 31 import '../tree/tree.dart'; |
| 31 import 'behavior.dart'; | 32 import 'behavior.dart'; |
| 32 | 33 |
| 33 /// Class that performs the mechanics to investigate annotations in the code. | 34 /// Class that performs the mechanics to investigate annotations in the code. |
| 34 abstract class AnnotationProcessor { | 35 abstract class AnnotationProcessor { |
| 35 factory AnnotationProcessor(Compiler compiler) => | 36 factory AnnotationProcessor(Compiler compiler) => |
| 36 compiler.options.loadFromDill | 37 compiler.options.loadFromDill |
| 37 ? new _KernelAnnotationProcessor() | 38 // TODO(johnniwinther): Pass the [KernelWorldBuilder] to |
| 39 // [KernelAnnotationProcessor]. |
| 40 ? new KernelAnnotationProcessor(null) |
| 38 : new _ElementAnnotationProcessor(compiler); | 41 : new _ElementAnnotationProcessor(compiler); |
| 39 | 42 |
| 40 void extractNativeAnnotations( | 43 void extractNativeAnnotations( |
| 41 LibraryEntity library, NativeBasicDataBuilder nativeBasicDataBuilder); | 44 LibraryEntity library, NativeBasicDataBuilder nativeBasicDataBuilder); |
| 42 | 45 |
| 43 void extractJsInteropAnnotations( | 46 void extractJsInteropAnnotations( |
| 44 LibraryEntity library, NativeBasicDataBuilder nativeBasicDataBuilder); | 47 LibraryEntity library, NativeBasicDataBuilder nativeBasicDataBuilder); |
| 45 } | 48 } |
| 46 | 49 |
| 47 class _KernelAnnotationProcessor implements AnnotationProcessor { | |
| 48 void extractNativeAnnotations( | |
| 49 LibraryEntity entity, NativeBasicDataBuilder nativeBasicDataBuilder) { | |
| 50 throw new UnimplementedError( | |
| 51 '_KernelAnnotationProcessor.extractNativeAnnotations'); | |
| 52 } | |
| 53 | |
| 54 void extractJsInteropAnnotations( | |
| 55 LibraryEntity library, NativeBasicDataBuilder nativeBasicDataBuilder) { | |
| 56 throw new UnimplementedError( | |
| 57 '_KernelAnnotationProcessor.extractJsInteropAnnotations'); | |
| 58 } | |
| 59 } | |
| 60 | |
| 61 /// Original logic for annotation processing, which involves in some cases | 50 /// Original logic for annotation processing, which involves in some cases |
| 62 /// triggering pre-parsing and validation of the annotations. | 51 /// triggering pre-parsing and validation of the annotations. |
| 63 class _ElementAnnotationProcessor implements AnnotationProcessor { | 52 class _ElementAnnotationProcessor implements AnnotationProcessor { |
| 64 Compiler _compiler; | 53 Compiler _compiler; |
| 65 | 54 |
| 66 _ElementAnnotationProcessor(this._compiler); | 55 _ElementAnnotationProcessor(this._compiler); |
| 67 | 56 |
| 68 /// Check whether [cls] has a `@Native(...)` annotation, and if so, set its | 57 /// Check whether [cls] has a `@Native(...)` annotation, and if so, set its |
| 69 /// native name from the annotation. | 58 /// native name from the annotation. |
| 70 void extractNativeAnnotations( | 59 void extractNativeAnnotations( |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 node = functionExpression.body; | 276 node = functionExpression.body; |
| 288 Token token = node.getBeginToken(); | 277 Token token = node.getBeginToken(); |
| 289 if (identical(token.stringValue, 'native')) return true; | 278 if (identical(token.stringValue, 'native')) return true; |
| 290 return false; | 279 return false; |
| 291 }); | 280 }); |
| 292 } | 281 } |
| 293 | 282 |
| 294 /// Returns the JSName annotation string or `null` if no JSName annotation is | 283 /// Returns the JSName annotation string or `null` if no JSName annotation is |
| 295 /// present. | 284 /// present. |
| 296 String _findJsNameFromAnnotation(Element element) { | 285 String _findJsNameFromAnnotation(Element element) { |
| 297 String name = null; | 286 String jsName = null; |
| 298 ClassElement annotationClass = | |
| 299 _compiler.commonElements.annotationJSNameClass; | |
| 300 for (MetadataAnnotation annotation in element.implementation.metadata) { | 287 for (MetadataAnnotation annotation in element.implementation.metadata) { |
| 301 annotation.ensureResolved(_compiler.resolution); | 288 annotation.ensureResolved(_compiler.resolution); |
| 302 ConstantValue value = | 289 ConstantValue value = |
| 303 _compiler.constants.getConstantValue(annotation.constant); | 290 _compiler.constants.getConstantValue(annotation.constant); |
| 304 if (!value.isConstructedObject) continue; | 291 String name = readAnnotationName( |
| 305 ConstructedConstantValue constructedObject = value; | 292 annotation, value, _compiler.commonElements.annotationJSNameClass); |
| 306 if (constructedObject.type.element != annotationClass) continue; | 293 if (jsName == null) { |
| 307 | 294 jsName = name; |
| 308 Iterable<ConstantValue> fields = constructedObject.fields.values; | 295 } else if (name != null) { |
| 309 // TODO(sra): Better validation of the constant. | 296 throw new SpannableAssertionFailure( |
| 310 if (fields.length != 1 || fields.single is! StringConstantValue) { | |
| 311 _reporter.internalError( | |
| 312 annotation, 'Annotations needs one string: ${annotation}'); | |
| 313 } | |
| 314 StringConstantValue specStringConstant = fields.single; | |
| 315 String specString = specStringConstant.toDartString().slowToString(); | |
| 316 if (name == null) { | |
| 317 name = specString; | |
| 318 } else { | |
| 319 _reporter.internalError( | |
| 320 annotation, 'Too many JSName annotations: ${annotation}'); | 297 annotation, 'Too many JSName annotations: ${annotation}'); |
| 321 } | 298 } |
| 322 } | 299 } |
| 323 return name; | 300 return jsName; |
| 324 } | 301 } |
| 325 | 302 |
| 326 @override | 303 @override |
| 327 NativeBehavior resolveJsCall(Send node, ForeignResolver resolver) { | 304 NativeBehavior resolveJsCall(Send node, ForeignResolver resolver) { |
| 328 return NativeBehavior.ofJsCallSend(node, _reporter, | 305 return NativeBehavior.ofJsCallSend(node, _reporter, |
| 329 _compiler.parsingContext, _compiler.commonElements, resolver); | 306 _compiler.parsingContext, _compiler.commonElements, resolver); |
| 330 } | 307 } |
| 331 | 308 |
| 332 @override | 309 @override |
| 333 NativeBehavior resolveJsEmbeddedGlobalCall( | 310 NativeBehavior resolveJsEmbeddedGlobalCall( |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 } | 346 } |
| 370 return null; | 347 return null; |
| 371 } | 348 } |
| 372 | 349 |
| 373 String apply( | 350 String apply( |
| 374 Compiler compiler, Element element, MetadataAnnotation annotation) { | 351 Compiler compiler, Element element, MetadataAnnotation annotation) { |
| 375 if (element.isClass) { | 352 if (element.isClass) { |
| 376 ClassElement cls = element; | 353 ClassElement cls = element; |
| 377 String native = getNativeAnnotation(annotation); | 354 String native = getNativeAnnotation(annotation); |
| 378 if (native != null) { | 355 if (native != null) { |
| 379 _nativeBasicDataBuilder.setNativeClassTagInfo(cls, native); | 356 String tagText = native.substring(1, native.length - 1); |
| 357 _nativeBasicDataBuilder.setNativeClassTagInfo(cls, tagText); |
| 380 return native; | 358 return native; |
| 381 } | 359 } |
| 382 } | 360 } |
| 383 return null; | 361 return null; |
| 384 } | 362 } |
| 385 | 363 |
| 386 void validate(Compiler compiler, Element element, | 364 void validate(Compiler compiler, Element element, |
| 387 MetadataAnnotation annotation, ConstantValue constant) { | 365 MetadataAnnotation annotation, ConstantValue constant) { |
| 388 ResolutionDartType annotationType = | 366 ResolutionDartType annotationType = |
| 389 constant.getType(compiler.commonElements); | 367 constant.getType(compiler.commonElements); |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 609 } | 587 } |
| 610 // Should be at '{', 'with', 'implements', '<' or 'native'. | 588 // Should be at '{', 'with', 'implements', '<' or 'native'. |
| 611 return id.lexeme; | 589 return id.lexeme; |
| 612 } | 590 } |
| 613 | 591 |
| 614 return _reporter.withCurrentElement(classElement, () { | 592 return _reporter.withCurrentElement(classElement, () { |
| 615 return scanForExtendsName(classElement.position); | 593 return scanForExtendsName(classElement.position); |
| 616 }); | 594 }); |
| 617 } | 595 } |
| 618 } | 596 } |
| 597 |
| 598 /// Extracts the name if [value] is a named annotation based on |
| 599 /// [annotationClass], otherwise returns `null`. |
| 600 String readAnnotationName( |
| 601 Spannable spannable, ConstantValue value, ClassEntity annotationClass) { |
| 602 if (!value.isConstructedObject) return null; |
| 603 ConstructedConstantValue constructedObject = value; |
| 604 if (constructedObject.type.element != annotationClass) return null; |
| 605 |
| 606 Iterable<ConstantValue> fields = constructedObject.fields.values; |
| 607 // TODO(sra): Better validation of the constant. |
| 608 if (fields.length != 1 || fields.single is! StringConstantValue) { |
| 609 throw new SpannableAssertionFailure( |
| 610 spannable, 'Annotations needs one string: ${value.toStructuredText()}'); |
| 611 } |
| 612 StringConstantValue specStringConstant = fields.single; |
| 613 return specStringConstant.toDartString().slowToString(); |
| 614 } |
| OLD | NEW |