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

Unified 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, 8 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 side-by-side diff with in-line comments
Download patch
« 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 »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/resolution/resolution_strategy.dart
diff --git a/pkg/compiler/lib/src/resolution/resolution_strategy.dart b/pkg/compiler/lib/src/resolution/resolution_strategy.dart
index b71bd4c056d0f2f2ce23a81b10703ac096c2ae92..32800d8307c086e9fb321063992df02492b017f5 100644
--- a/pkg/compiler/lib/src/resolution/resolution_strategy.dart
+++ b/pkg/compiler/lib/src/resolution/resolution_strategy.dart
@@ -10,6 +10,7 @@ import '../common/backend_api.dart';
import '../common/names.dart';
import '../common/resolution.dart';
import '../common/tasks.dart';
+import '../constants/values.dart';
import '../compiler.dart';
import '../elements/elements.dart';
import '../elements/entities.dart';
@@ -431,6 +432,8 @@ class _ElementAnnotationProcessor implements AnnotationProcessor {
_ElementAnnotationProcessor(this._compiler);
+ CommonElements get _commonElements => _compiler.commonElements;
+
/// Check whether [cls] has a `@Native(...)` annotation, and if so, set its
/// native name from the annotation.
void extractNativeAnnotations(
@@ -462,4 +465,150 @@ class _ElementAnnotationProcessor implements AnnotationProcessor {
}
});
}
+
+ void processJsInteropAnnotations(
+ NativeBasicData nativeBasicData, NativeDataBuilder nativeDataBuilder) {
+ if (_commonElements.jsAnnotationClass == null) return;
+
+ ClassElement cls = _commonElements.jsAnnotationClass;
+ FieldElement nameField = cls.lookupMember('name');
+
+ /// Resolves the metadata of [element] and returns the name of the `JS(...)`
+ /// annotation for js interop, if found.
+ String processJsInteropAnnotation(Element element) {
+ for (MetadataAnnotation annotation in element.implementation.metadata) {
+ // TODO(johnniwinther): Avoid processing unresolved elements.
+ if (annotation.constant == null) continue;
+ ConstantValue constant =
+ _compiler.constants.getConstantValue(annotation.constant);
+ if (constant == null || constant is! ConstructedConstantValue) continue;
+ ConstructedConstantValue constructedConstant = constant;
+ if (constructedConstant.type.element ==
+ _commonElements.jsAnnotationClass) {
+ ConstantValue value = constructedConstant.fields[nameField];
+ String name;
+ if (value.isString) {
+ StringConstantValue stringValue = value;
+ name = stringValue.primitiveValue.slowToString();
+ } else {
+ // TODO(jacobr): report a warning if the value is not a String.
+ name = '';
+ }
+ return name;
+ }
+ }
+ return null;
+ }
+
+ void checkFunctionParameters(MethodElement fn) {
+ if (fn.hasFunctionSignature &&
+ fn.functionSignature.optionalParametersAreNamed) {
+ _compiler.reporter.reportErrorMessage(
+ fn,
+ MessageKind.JS_INTEROP_METHOD_WITH_NAMED_ARGUMENTS,
+ {'method': fn.name});
+ }
+ }
+
+ bool hasAnonymousAnnotation(Element element) {
+ if (_commonElements.jsAnonymousClass == null) return false;
+ return element.metadata.any((MetadataAnnotation annotation) {
+ ConstantValue constant =
+ _compiler.constants.getConstantValue(annotation.constant);
+ if (constant == null || constant is! ConstructedConstantValue)
+ return false;
+ ConstructedConstantValue constructedConstant = constant;
+ return constructedConstant.type.element ==
+ _commonElements.jsAnonymousClass;
+ });
+ }
+
+ void processJsInteropAnnotationsInLibrary(LibraryElement library) {
+ String libraryName = processJsInteropAnnotation(library);
+ if (libraryName != null) {
+ nativeDataBuilder.setJsInteropLibraryName(library, libraryName);
+ }
+ library.implementation.forEachLocalMember((Element element) {
+ if (element is MemberElement) {
+ String memberName = processJsInteropAnnotation(element);
+ if (memberName != null) {
+ nativeDataBuilder.setJsInteropMemberName(element, memberName);
+ if (element is MethodElement) {
+ checkFunctionParameters(element);
+ }
+ }
+ }
+
+ if (!element.isClass) return;
+
+ ClassElement classElement = element;
+ String className = processJsInteropAnnotation(classElement);
+ if (className != null) {
+ nativeDataBuilder.setJsInteropClassName(classElement, className);
+ }
+ if (!nativeBasicData.isJsInteropClass(classElement)) return;
+
+ bool isAnonymous = hasAnonymousAnnotation(classElement);
+ if (isAnonymous) {
+ nativeDataBuilder.markJsInteropClassAsAnonymous(classElement);
+ }
+
+ // Skip classes that are completely unreachable. This should only happen
+ // when all of jsinterop types are unreachable from main.
+ if (!_compiler.resolutionWorldBuilder.isImplemented(classElement)) {
+ return;
+ }
+
+ if (!classElement
+ .implementsInterface(_commonElements.jsJavaScriptObjectClass)) {
+ _compiler.reporter.reportErrorMessage(classElement,
+ MessageKind.JS_INTEROP_CLASS_CANNOT_EXTEND_DART_CLASS, {
+ 'cls': classElement.name,
+ 'superclass': classElement.superclass.name
+ });
+ }
+
+ classElement
+ .forEachMember((ClassElement classElement, MemberElement member) {
+ String memberName = processJsInteropAnnotation(member);
+ if (memberName != null) {
+ nativeDataBuilder.setJsInteropMemberName(member, memberName);
+ }
+
+ if (!member.isSynthesized &&
+ nativeBasicData.isJsInteropClass(classElement) &&
+ member is MethodElement) {
+ MethodElement fn = member;
+ if (!fn.isExternal &&
+ !fn.isAbstract &&
+ !fn.isConstructor &&
+ !fn.isStatic) {
+ _compiler.reporter.reportErrorMessage(
+ fn,
+ MessageKind.JS_INTEROP_CLASS_NON_EXTERNAL_MEMBER,
+ {'cls': classElement.name, 'member': member.name});
+ }
+
+ if (fn.isFactoryConstructor && isAnonymous) {
+ fn.functionSignature
+ .orderedForEachParameter((ParameterElement parameter) {
+ if (!parameter.isNamed) {
+ _compiler.reporter.reportErrorMessage(
+ parameter,
+ MessageKind
+ .JS_OBJECT_LITERAL_CONSTRUCTOR_WITH_POSITIONAL_ARGUMENTS,
+ {'parameter': parameter.name, 'cls': classElement.name});
+ }
+ });
+ } else {
+ checkFunctionParameters(fn);
+ }
+ }
+ });
+ });
+ }
+
+ _compiler.libraryLoader.libraries
+ .forEach(processJsInteropAnnotationsInLibrary);
+ }
}
« 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