| 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 part of native; | 5 part of native; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * This could be an abstract class but we use it as a stub for the dart_backend. | 8 * This could be an abstract class but we use it as a stub for the dart_backend. |
| 9 */ | 9 */ |
| 10 class NativeEnqueuer { | 10 class NativeEnqueuer { |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 58 void logSummary(log(message)) {} | 58 void logSummary(log(message)) {} |
| 59 | 59 |
| 60 // Do not use annotations in dart2dart. | 60 // Do not use annotations in dart2dart. |
| 61 ClassElement get annotationCreatesClass => null; | 61 ClassElement get annotationCreatesClass => null; |
| 62 ClassElement get annotationReturnsClass => null; | 62 ClassElement get annotationReturnsClass => null; |
| 63 ClassElement get annotationJsNameClass => null; | 63 ClassElement get annotationJsNameClass => null; |
| 64 } | 64 } |
| 65 | 65 |
| 66 | 66 |
| 67 abstract class NativeEnqueuerBase implements NativeEnqueuer { | 67 abstract class NativeEnqueuerBase implements NativeEnqueuer { |
| 68 static final RegExp _identifier = new RegExp(r'^[a-zA-Z_$][a-zA-Z0-9_$]*$'); |
| 68 | 69 |
| 69 /** | 70 /** |
| 70 * The set of all native classes. Each native class is in [nativeClasses] and | 71 * The set of all native classes. Each native class is in [nativeClasses] and |
| 71 * exactly one of [unusedClasses], [pendingClasses] and [registeredClasses]. | 72 * exactly one of [unusedClasses], [pendingClasses] and [registeredClasses]. |
| 72 */ | 73 */ |
| 73 final Set<ClassElement> nativeClasses = new Set<ClassElement>(); | 74 final Set<ClassElement> nativeClasses = new Set<ClassElement>(); |
| 74 | 75 |
| 75 final Set<ClassElement> registeredClasses = new Set<ClassElement>(); | 76 final Set<ClassElement> registeredClasses = new Set<ClassElement>(); |
| 76 final Set<ClassElement> pendingClasses = new Set<ClassElement>(); | 77 final Set<ClassElement> pendingClasses = new Set<ClassElement>(); |
| 77 final Set<ClassElement> unusedClasses = new Set<ClassElement>(); | 78 final Set<ClassElement> unusedClasses = new Set<ClassElement>(); |
| (...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 // function or a non-method property in the prototype chain, must be coded | 393 // function or a non-method property in the prototype chain, must be coded |
| 393 // using a JS-call. | 394 // using a JS-call. |
| 394 if (element.isInstanceMember) { | 395 if (element.isInstanceMember) { |
| 395 setNativeName(element); | 396 setNativeName(element); |
| 396 } | 397 } |
| 397 } | 398 } |
| 398 } | 399 } |
| 399 | 400 |
| 400 handleMethodAnnotations(Element method) { | 401 handleMethodAnnotations(Element method) { |
| 401 if (isNativeMethod(method)) { | 402 if (isNativeMethod(method)) { |
| 402 setNativeName(method); | 403 if (method.isStatic) { |
| 404 setNativeNameForStaticMethod(method); |
| 405 } else { |
| 406 setNativeName(method); |
| 407 } |
| 403 } | 408 } |
| 404 } | 409 } |
| 405 | 410 |
| 406 /// Sets the native name of [element], either from an annotation, or | 411 /// Sets the native name of [element], either from an annotation, or |
| 407 /// defaulting to the Dart name. | 412 /// defaulting to the Dart name. |
| 408 void setNativeName(Element element) { | 413 void setNativeName(Element element) { |
| 409 String name = findJsNameFromAnnotation(element); | 414 String name = findJsNameFromAnnotation(element); |
| 410 if (name == null) name = element.name; | 415 if (name == null) name = element.name; |
| 411 element.setNative(name); | 416 element.setNative(name); |
| 412 } | 417 } |
| 413 | 418 |
| 419 /// Sets the native name of the static native method [element], using the |
| 420 /// following rules: |
| 421 /// 1. If [element] has a @JSName annotation that is an identifier, qualify |
| 422 /// that identifier to the @Native name of the enclosing class |
| 423 /// 2. If [element] has a @JSName annotation that is not an identifier, |
| 424 /// use the declared @JSName as the expression |
| 425 /// 3. If [element] does not have a @JSName annotation, qualify the name of |
| 426 /// the method with the @Native name of the enclosing class. |
| 427 void setNativeNameForStaticMethod(Element element) { |
| 428 String name = findJsNameFromAnnotation(element); |
| 429 if (name == null) name = element.name; |
| 430 if (isIdentifier(name)) { |
| 431 List<String> nativeNames = nativeTagsOfClassRaw(element.enclosingClass); |
| 432 if (nativeNames.length != 1) { |
| 433 compiler.internalError(element, |
| 434 'Unable to determine a native name for the enclosing class, ' |
| 435 'options: $nativeNames'); |
| 436 } |
| 437 element.setNative('${nativeNames[0]}.$name'); |
| 438 } else { |
| 439 element.setNative(name); |
| 440 } |
| 441 } |
| 442 |
| 443 bool isIdentifier(String s) => _identifier.hasMatch(s); |
| 444 |
| 414 bool isNativeMethod(FunctionElementX element) { | 445 bool isNativeMethod(FunctionElementX element) { |
| 415 if (!element.library.canUseNative) return false; | 446 if (!element.library.canUseNative) return false; |
| 416 // Native method? | 447 // Native method? |
| 417 return compiler.withCurrentElement(element, () { | 448 return compiler.withCurrentElement(element, () { |
| 418 Node node = element.parseNode(compiler); | 449 Node node = element.parseNode(compiler); |
| 419 if (node is! FunctionExpression) return false; | 450 if (node is! FunctionExpression) return false; |
| 420 FunctionExpression functionExpression = node; | 451 FunctionExpression functionExpression = node; |
| 421 node = functionExpression.body; | 452 node = functionExpression.body; |
| 422 Token token = node.getBeginToken(); | 453 Token token = node.getBeginToken(); |
| 423 if (identical(token.stringValue, 'native')) return true; | 454 if (identical(token.stringValue, 'native')) return true; |
| (...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 632 superclass, | 663 superclass, |
| 633 () => <ClassElement>[]); | 664 () => <ClassElement>[]); |
| 634 directSubtypes.add(cls); | 665 directSubtypes.add(cls); |
| 635 } | 666 } |
| 636 | 667 |
| 637 void logSummary(log(message)) { | 668 void logSummary(log(message)) { |
| 638 log('Compiled ${registeredClasses.length} native classes, ' | 669 log('Compiled ${registeredClasses.length} native classes, ' |
| 639 '${unusedClasses.length} native classes omitted.'); | 670 '${unusedClasses.length} native classes omitted.'); |
| 640 } | 671 } |
| 641 } | 672 } |
| OLD | NEW |