| 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; |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 219 node = functionExpression.body; | 219 node = functionExpression.body; |
| 220 Token token = node.getBeginToken(); | 220 Token token = node.getBeginToken(); |
| 221 if (identical(token.stringValue, 'native')) return true; | 221 if (identical(token.stringValue, 'native')) return true; |
| 222 return false; | 222 return false; |
| 223 }); | 223 }); |
| 224 } | 224 } |
| 225 | 225 |
| 226 /// Returns the JSName annotation string or `null` if no JSName annotation is | 226 /// Returns the JSName annotation string or `null` if no JSName annotation is |
| 227 /// present. | 227 /// present. |
| 228 String _findJsNameFromAnnotation(Element element) { | 228 String _findJsNameFromAnnotation(Element element) { |
| 229 String name = null; | 229 String jsName = null; |
| 230 ClassElement annotationClass = | |
| 231 _compiler.commonElements.annotationJSNameClass; | |
| 232 for (MetadataAnnotation annotation in element.implementation.metadata) { | 230 for (MetadataAnnotation annotation in element.implementation.metadata) { |
| 233 annotation.ensureResolved(_compiler.resolution); | 231 annotation.ensureResolved(_compiler.resolution); |
| 234 ConstantValue value = | 232 ConstantValue value = |
| 235 _compiler.constants.getConstantValue(annotation.constant); | 233 _compiler.constants.getConstantValue(annotation.constant); |
| 236 if (!value.isConstructedObject) continue; | 234 String name = readAnnotationName( |
| 237 ConstructedConstantValue constructedObject = value; | 235 annotation, value, _compiler.commonElements.annotationJSNameClass); |
| 238 if (constructedObject.type.element != annotationClass) continue; | 236 if (jsName == null) { |
| 239 | 237 jsName = name; |
| 240 Iterable<ConstantValue> fields = constructedObject.fields.values; | 238 } else if (name != null) { |
| 241 // TODO(sra): Better validation of the constant. | 239 throw new SpannableAssertionFailure( |
| 242 if (fields.length != 1 || fields.single is! StringConstantValue) { | |
| 243 _reporter.internalError( | |
| 244 annotation, 'Annotations needs one string: ${annotation}'); | |
| 245 } | |
| 246 StringConstantValue specStringConstant = fields.single; | |
| 247 String specString = specStringConstant.toDartString().slowToString(); | |
| 248 if (name == null) { | |
| 249 name = specString; | |
| 250 } else { | |
| 251 _reporter.internalError( | |
| 252 annotation, 'Too many JSName annotations: ${annotation}'); | 240 annotation, 'Too many JSName annotations: ${annotation}'); |
| 253 } | 241 } |
| 254 } | 242 } |
| 255 return name; | 243 return jsName; |
| 256 } | 244 } |
| 257 | 245 |
| 258 @override | 246 @override |
| 259 NativeBehavior resolveJsCall(Send node, ForeignResolver resolver) { | 247 NativeBehavior resolveJsCall(Send node, ForeignResolver resolver) { |
| 260 return NativeBehavior.ofJsCallSend(node, _reporter, | 248 return NativeBehavior.ofJsCallSend(node, _reporter, |
| 261 _compiler.parsingContext, _compiler.commonElements, resolver); | 249 _compiler.parsingContext, _compiler.commonElements, resolver); |
| 262 } | 250 } |
| 263 | 251 |
| 264 @override | 252 @override |
| 265 NativeBehavior resolveJsEmbeddedGlobalCall( | 253 NativeBehavior resolveJsEmbeddedGlobalCall( |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 301 } | 289 } |
| 302 return null; | 290 return null; |
| 303 } | 291 } |
| 304 | 292 |
| 305 String apply( | 293 String apply( |
| 306 Compiler compiler, Element element, MetadataAnnotation annotation) { | 294 Compiler compiler, Element element, MetadataAnnotation annotation) { |
| 307 if (element.isClass) { | 295 if (element.isClass) { |
| 308 ClassElement cls = element; | 296 ClassElement cls = element; |
| 309 String native = getNativeAnnotation(annotation); | 297 String native = getNativeAnnotation(annotation); |
| 310 if (native != null) { | 298 if (native != null) { |
| 311 _nativeBasicDataBuilder.setNativeClassTagInfo(cls, native); | 299 String tagText = native.substring(1, native.length - 1); |
| 300 _nativeBasicDataBuilder.setNativeClassTagInfo(cls, tagText); |
| 312 return native; | 301 return native; |
| 313 } | 302 } |
| 314 } | 303 } |
| 315 return null; | 304 return null; |
| 316 } | 305 } |
| 317 | 306 |
| 318 void validate(Compiler compiler, Element element, | 307 void validate(Compiler compiler, Element element, |
| 319 MetadataAnnotation annotation, ConstantValue constant) { | 308 MetadataAnnotation annotation, ConstantValue constant) { |
| 320 ResolutionDartType annotationType = | 309 ResolutionDartType annotationType = |
| 321 constant.getType(compiler.commonElements); | 310 constant.getType(compiler.commonElements); |
| (...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 561 } | 550 } |
| 562 // Should be at '{', 'with', 'implements', '<' or 'native'. | 551 // Should be at '{', 'with', 'implements', '<' or 'native'. |
| 563 return id.lexeme; | 552 return id.lexeme; |
| 564 } | 553 } |
| 565 | 554 |
| 566 return _reporter.withCurrentElement(classElement, () { | 555 return _reporter.withCurrentElement(classElement, () { |
| 567 return scanForExtendsName(classElement.position); | 556 return scanForExtendsName(classElement.position); |
| 568 }); | 557 }); |
| 569 } | 558 } |
| 570 } | 559 } |
| 560 |
| 561 /// Extracts the name if [value] is a named annotation based on |
| 562 /// [annotationClass], otherwise returns `null`. |
| 563 String readAnnotationName( |
| 564 Spannable spannable, ConstantValue value, ClassEntity annotationClass) { |
| 565 if (!value.isConstructedObject) return null; |
| 566 ConstructedConstantValue constructedObject = value; |
| 567 if (constructedObject.type.element != annotationClass) return null; |
| 568 |
| 569 Iterable<ConstantValue> fields = constructedObject.fields.values; |
| 570 // TODO(sra): Better validation of the constant. |
| 571 if (fields.length != 1 || fields.single is! StringConstantValue) { |
| 572 throw new SpannableAssertionFailure( |
| 573 spannable, 'Annotations needs one string: ${value.toStructuredText()}'); |
| 574 } |
| 575 StringConstantValue specStringConstant = fields.single; |
| 576 return specStringConstant.toDartString().slowToString(); |
| 577 } |
| OLD | NEW |