Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(435)

Side by Side Diff: pkg/compiler/lib/src/resolution/resolution_strategy.dart

Issue 2852603003: Move JsInteropAnalysis.onQueueClosed to AnnotationProcessor.processJsInteropAnnotation (Closed)
Patch Set: Register anonymous classes correctly + add test Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file 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 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 library dart2js.resolution_strategy; 5 library dart2js.resolution_strategy;
6 6
7 import '../common.dart'; 7 import '../common.dart';
8 import '../common_elements.dart'; 8 import '../common_elements.dart';
9 import '../common/backend_api.dart'; 9 import '../common/backend_api.dart';
10 import '../common/names.dart'; 10 import '../common/names.dart';
11 import '../common/resolution.dart'; 11 import '../common/resolution.dart';
12 import '../common/tasks.dart'; 12 import '../common/tasks.dart';
13 import '../constants/values.dart';
13 import '../compiler.dart'; 14 import '../compiler.dart';
14 import '../elements/elements.dart'; 15 import '../elements/elements.dart';
15 import '../elements/entities.dart'; 16 import '../elements/entities.dart';
16 import '../elements/modelx.dart'; 17 import '../elements/modelx.dart';
17 import '../elements/resolution_types.dart'; 18 import '../elements/resolution_types.dart';
18 import '../environment.dart'; 19 import '../environment.dart';
19 import '../enqueue.dart'; 20 import '../enqueue.dart';
20 import '../frontend_strategy.dart'; 21 import '../frontend_strategy.dart';
21 import '../js_backend/backend.dart'; 22 import '../js_backend/backend.dart';
22 import '../js_backend/backend_usage.dart'; 23 import '../js_backend/backend_usage.dart';
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 /// very early in the compilation pipeline, typically this is before resolution 425 /// very early in the compilation pipeline, typically this is before resolution
425 /// is complete. Because of that this processor does a lightweight parse of the 426 /// is complete. Because of that this processor does a lightweight parse of the
426 /// annotation (which is restricted to a limited subset of the annotation 427 /// annotation (which is restricted to a limited subset of the annotation
427 /// syntax), and, once resolution completes, it validates that the parsed 428 /// syntax), and, once resolution completes, it validates that the parsed
428 /// annotations correspond to the correct element. 429 /// annotations correspond to the correct element.
429 class _ElementAnnotationProcessor implements AnnotationProcessor { 430 class _ElementAnnotationProcessor implements AnnotationProcessor {
430 Compiler _compiler; 431 Compiler _compiler;
431 432
432 _ElementAnnotationProcessor(this._compiler); 433 _ElementAnnotationProcessor(this._compiler);
433 434
435 CommonElements get _commonElements => _compiler.commonElements;
436
434 /// Check whether [cls] has a `@Native(...)` annotation, and if so, set its 437 /// Check whether [cls] has a `@Native(...)` annotation, and if so, set its
435 /// native name from the annotation. 438 /// native name from the annotation.
436 void extractNativeAnnotations( 439 void extractNativeAnnotations(
437 LibraryElement library, NativeBasicDataBuilder nativeBasicDataBuilder) { 440 LibraryElement library, NativeBasicDataBuilder nativeBasicDataBuilder) {
438 library.forEachLocalMember((Element element) { 441 library.forEachLocalMember((Element element) {
439 if (element.isClass) { 442 if (element.isClass) {
440 EagerAnnotationHandler.checkAnnotation(_compiler, element, 443 EagerAnnotationHandler.checkAnnotation(_compiler, element,
441 new NativeAnnotationHandler(nativeBasicDataBuilder)); 444 new NativeAnnotationHandler(nativeBasicDataBuilder));
442 } 445 }
443 }); 446 });
(...skipping 11 matching lines...) Expand all
455 } 458 }
456 library.forEachLocalMember((Element element) { 459 library.forEachLocalMember((Element element) {
457 if (element.isClass) { 460 if (element.isClass) {
458 ClassElement cls = element; 461 ClassElement cls = element;
459 if (checkJsInteropAnnotation(element)) { 462 if (checkJsInteropAnnotation(element)) {
460 nativeBasicDataBuilder.markAsJsInteropClass(cls); 463 nativeBasicDataBuilder.markAsJsInteropClass(cls);
461 } 464 }
462 } 465 }
463 }); 466 });
464 } 467 }
468
469 void processJsInteropAnnotations(
470 NativeBasicData nativeBasicData, NativeDataBuilder nativeDataBuilder) {
471 if (_commonElements.jsAnnotationClass == null) return;
472
473 ClassElement cls = _commonElements.jsAnnotationClass;
474 FieldElement nameField = cls.lookupMember('name');
475
476 /// Resolves the metadata of [element] and returns the name of the `JS(...)`
477 /// annotation for js interop, if found.
478 String processJsInteropAnnotation(Element element) {
479 for (MetadataAnnotation annotation in element.implementation.metadata) {
480 // TODO(johnniwinther): Avoid processing unresolved elements.
481 if (annotation.constant == null) continue;
482 ConstantValue constant =
483 _compiler.constants.getConstantValue(annotation.constant);
484 if (constant == null || constant is! ConstructedConstantValue) continue;
485 ConstructedConstantValue constructedConstant = constant;
486 if (constructedConstant.type.element ==
487 _commonElements.jsAnnotationClass) {
488 ConstantValue value = constructedConstant.fields[nameField];
489 String name;
490 if (value.isString) {
491 StringConstantValue stringValue = value;
492 name = stringValue.primitiveValue.slowToString();
493 } else {
494 // TODO(jacobr): report a warning if the value is not a String.
495 name = '';
496 }
497 return name;
498 }
499 }
500 return null;
501 }
502
503 void checkFunctionParameters(MethodElement fn) {
504 if (fn.hasFunctionSignature &&
505 fn.functionSignature.optionalParametersAreNamed) {
506 _compiler.reporter.reportErrorMessage(
507 fn,
508 MessageKind.JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS,
509 {'method': fn.name});
510 }
511 }
512
513 bool hasAnonymousAnnotation(Element element) {
514 if (_commonElements.jsAnonymousClass == null) return false;
515 return element.metadata.any((MetadataAnnotation annotation) {
516 ConstantValue constant =
517 _compiler.constants.getConstantValue(annotation.constant);
518 if (constant == null || constant is! ConstructedConstantValue)
519 return false;
520 ConstructedConstantValue constructedConstant = constant;
521 return constructedConstant.type.element ==
522 _commonElements.jsAnonymousClass;
523 });
524 }
525
526 void processJsInteropAnnotationsInLibrary(LibraryElement library) {
527 String libraryName = processJsInteropAnnotation(library);
528 if (libraryName != null) {
529 nativeDataBuilder.setJsInteropLibraryName(library, libraryName);
530 }
531 library.implementation.forEachLocalMember((Element element) {
532 if (element is MemberElement) {
533 String memberName = processJsInteropAnnotation(element);
534 if (memberName != null) {
535 nativeDataBuilder.setJsInteropMemberName(element, memberName);
536 if (element is MethodElement) {
537 checkFunctionParameters(element);
538 }
539 }
540 }
541
542 if (!element.isClass) return;
543
544 ClassElement classElement = element;
545 String className = processJsInteropAnnotation(classElement);
546 if (className != null) {
547 nativeDataBuilder.setJsInteropClassName(classElement, className);
548 }
549 if (!nativeBasicData.isJsInteropClass(classElement)) return;
550
551 bool isAnonymous = hasAnonymousAnnotation(classElement);
552 if (isAnonymous) {
553 nativeDataBuilder.markJsInteropClassAsAnonymous(classElement);
554 }
555
556 // Skip classes that are completely unreachable. This should only happen
557 // when all of jsinterop types are unreachable from main.
558 if (!_compiler.resolutionWorldBuilder.isImplemented(classElement)) {
559 return;
560 }
561
562 if (!classElement
563 .implementsInterface(_commonElements.jsJavaScriptObjectClass)) {
564 _compiler.reporter.reportErrorMessage(classElement,
565 MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, {
566 'cls': classElement.name,
567 'superclass': classElement.superclass.name
568 });
569 }
570
571 classElement
572 .forEachMember((ClassElement classElement, MemberElement member) {
573 String memberName = processJsInteropAnnotation(member);
574 if (memberName != null) {
575 nativeDataBuilder.setJsInteropMemberName(member, memberName);
576 }
577
578 if (!member.isSynthesized &&
579 nativeBasicData.isJsInteropClass(classElement) &&
580 member is MethodElement) {
581 MethodElement fn = member;
582 if (!fn.isExternal &&
583 !fn.isAbstract &&
584 !fn.isConstructor &&
585 !fn.isStatic) {
586 _compiler.reporter.reportErrorMessage(
587 fn,
588 MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER,
589 {'cls': classElement.name, 'member': member.name});
590 }
591
592 if (fn.isFactoryConstructor && isAnonymous) {
593 fn.functionSignature
594 .orderedForEachParameter((ParameterElement parameter) {
595 if (!parameter.isNamed) {
596 _compiler.reporter.reportErrorMessage(
597 parameter,
598 MessageKind
599 .JS_OBJECT_LITERAL_CONSTRUCTOR_WITH_POSITIONAL_ARGUMEN TS,
600 {'parameter': parameter.name, 'cls': classElement.name});
601 }
602 });
603 } else {
604 checkFunctionParameters(fn);
605 }
606 }
607 });
608 });
609 }
610
611 _compiler.libraryLoader.libraries
612 .forEach(processJsInteropAnnotationsInLibrary);
613 }
465 } 614 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/kernel/native_basic_data.dart ('k') | pkg/compiler/lib/src/ssa/builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698