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

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

Issue 2855593002: Revert "Move JsInteropAnalysis.onQueueClosed to AnnotationProcessor.processJsInteropAnnotation" (Closed)
Patch Set: 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';
14 import '../compiler.dart'; 13 import '../compiler.dart';
15 import '../elements/elements.dart'; 14 import '../elements/elements.dart';
16 import '../elements/entities.dart'; 15 import '../elements/entities.dart';
17 import '../elements/modelx.dart'; 16 import '../elements/modelx.dart';
18 import '../elements/resolution_types.dart'; 17 import '../elements/resolution_types.dart';
19 import '../environment.dart'; 18 import '../environment.dart';
20 import '../enqueue.dart'; 19 import '../enqueue.dart';
21 import '../frontend_strategy.dart'; 20 import '../frontend_strategy.dart';
22 import '../js_backend/backend.dart'; 21 import '../js_backend/backend.dart';
23 import '../js_backend/backend_usage.dart'; 22 import '../js_backend/backend_usage.dart';
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 /// very early in the compilation pipeline, typically this is before resolution 424 /// very early in the compilation pipeline, typically this is before resolution
426 /// is complete. Because of that this processor does a lightweight parse of the 425 /// is complete. Because of that this processor does a lightweight parse of the
427 /// annotation (which is restricted to a limited subset of the annotation 426 /// annotation (which is restricted to a limited subset of the annotation
428 /// syntax), and, once resolution completes, it validates that the parsed 427 /// syntax), and, once resolution completes, it validates that the parsed
429 /// annotations correspond to the correct element. 428 /// annotations correspond to the correct element.
430 class _ElementAnnotationProcessor implements AnnotationProcessor { 429 class _ElementAnnotationProcessor implements AnnotationProcessor {
431 Compiler _compiler; 430 Compiler _compiler;
432 431
433 _ElementAnnotationProcessor(this._compiler); 432 _ElementAnnotationProcessor(this._compiler);
434 433
435 CommonElements get _commonElements => _compiler.commonElements;
436
437 /// Check whether [cls] has a `@Native(...)` annotation, and if so, set its 434 /// Check whether [cls] has a `@Native(...)` annotation, and if so, set its
438 /// native name from the annotation. 435 /// native name from the annotation.
439 void extractNativeAnnotations( 436 void extractNativeAnnotations(
440 LibraryElement library, NativeBasicDataBuilder nativeBasicDataBuilder) { 437 LibraryElement library, NativeBasicDataBuilder nativeBasicDataBuilder) {
441 library.forEachLocalMember((Element element) { 438 library.forEachLocalMember((Element element) {
442 if (element.isClass) { 439 if (element.isClass) {
443 EagerAnnotationHandler.checkAnnotation(_compiler, element, 440 EagerAnnotationHandler.checkAnnotation(_compiler, element,
444 new NativeAnnotationHandler(nativeBasicDataBuilder)); 441 new NativeAnnotationHandler(nativeBasicDataBuilder));
445 } 442 }
446 }); 443 });
(...skipping 11 matching lines...) Expand all
458 } 455 }
459 library.forEachLocalMember((Element element) { 456 library.forEachLocalMember((Element element) {
460 if (element.isClass) { 457 if (element.isClass) {
461 ClassElement cls = element; 458 ClassElement cls = element;
462 if (checkJsInteropAnnotation(element)) { 459 if (checkJsInteropAnnotation(element)) {
463 nativeBasicDataBuilder.markAsJsInteropClass(cls); 460 nativeBasicDataBuilder.markAsJsInteropClass(cls);
464 } 461 }
465 } 462 }
466 }); 463 });
467 } 464 }
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 nativeDataBuilder.markJsInteropClassAsAnonymous(classElement);
553
554 // Skip classes that are completely unreachable. This should only happen
555 // when all of jsinterop types are unreachable from main.
556 if (!_compiler.resolutionWorldBuilder.isImplemented(classElement)) {
557 return;
558 }
559
560 if (!classElement
561 .implementsInterface(_commonElements.jsJavaScriptObjectClass)) {
562 _compiler.reporter.reportErrorMessage(classElement,
563 MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, {
564 'cls': classElement.name,
565 'superclass': classElement.superclass.name
566 });
567 }
568
569 classElement
570 .forEachMember((ClassElement classElement, MemberElement member) {
571 String memberName = processJsInteropAnnotation(member);
572 if (memberName != null) {
573 nativeDataBuilder.setJsInteropMemberName(member, memberName);
574 }
575
576 if (!member.isSynthesized &&
577 nativeBasicData.isJsInteropClass(classElement) &&
578 member is MethodElement) {
579 MethodElement fn = member;
580 if (!fn.isExternal &&
581 !fn.isAbstract &&
582 !fn.isConstructor &&
583 !fn.isStatic) {
584 _compiler.reporter.reportErrorMessage(
585 fn,
586 MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER,
587 {'cls': classElement.name, 'member': member.name});
588 }
589
590 if (fn.isFactoryConstructor && isAnonymous) {
591 fn.functionSignature
592 .orderedForEachParameter((ParameterElement parameter) {
593 if (!parameter.isNamed) {
594 _compiler.reporter.reportErrorMessage(
595 parameter,
596 MessageKind
597 .JS_OBJECT_LITERAL_CONSTRUCTOR_WITH_POSITIONAL_ARGUMEN TS,
598 {'parameter': parameter.name, 'cls': classElement.name});
599 }
600 });
601 } else {
602 checkFunctionParameters(fn);
603 }
604 }
605 });
606 });
607 }
608
609 _compiler.libraryLoader.libraries
610 .forEach(processJsInteropAnnotationsInLibrary);
611 }
612 } 465 }
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