Delete NativeDataResolver

Change-Id: I91d2e1cb8d03bb1d0da7e175c810fa3cf3216962
Reviewed-on: https://dart-review.googlesource.com/54901
Reviewed-by: Sigmund Cherem <sigmund@google.com>
This commit is contained in:
Johnni Winther 2018-05-15 08:37:29 +00:00 committed by commit-bot@chromium.org
parent a86621318d
commit 351b90cb59
6 changed files with 10 additions and 641 deletions

View file

@ -5,31 +5,8 @@
library dart2js.backend_api;
import '../common/resolution.dart' show ResolutionImpact;
import '../constants/expressions.dart' show ConstantExpression;
import '../elements/resolution_types.dart'
show ResolutionDartType, ResolutionInterfaceType;
import '../tree/tree.dart' show Node;
import '../universe/world_impact.dart' show WorldImpact;
/// Interface for resolving native data for a target specific element.
abstract class NativeRegistry {
/// Registers [nativeData] as part of the resolution impact.
void registerNativeData(dynamic nativeData);
}
/// Interface for resolving calls to foreign functions.
abstract class ForeignResolver {
/// Returns the constant expression of [node], or `null` if [node] is not
/// a constant expression.
ConstantExpression getConstant(Node node);
/// Registers [type] as instantiated.
void registerInstantiatedType(ResolutionInterfaceType type);
/// Resolves [typeName] to a type in the context of [node].
ResolutionDartType resolveTypeFromString(Node node, String typeName);
}
/// Target-specific transformation for resolution world impacts.
///
/// This processes target-agnostic [ResolutionImpact]s and creates [WorldImpact]

View file

@ -31,11 +31,9 @@ import '../mirrors_used.dart';
import '../options.dart' show CompilerOptions;
import '../parser/parser_task.dart';
import '../resolution/resolution.dart';
import '../tree/tree.dart' show Send, TypeAnnotation;
import '../universe/call_structure.dart' show CallStructure;
import '../tree/tree.dart' show TypeAnnotation;
import '../universe/world_impact.dart' show WorldImpact;
import '../universe/feature.dart';
import 'backend_api.dart';
import 'work.dart' show WorkItem;
/// [WorkItem] used exclusively by the [ResolutionEnqueuer].
@ -81,22 +79,6 @@ abstract class Target {
/// classes or members being eagerly resolved.
bool isTargetSpecificLibrary(LibraryElement element);
/// Resolve target specific information for [element] and register it with
/// [registry].
void resolveNativeMember(MemberElement element, NativeRegistry registry) {}
/// Processes [element] for resolution and returns the [MethodElement] that
/// defines the implementation of [element].
MethodElement resolveExternalFunction(MethodElement element) => element;
/// Called when resolving a call to a foreign function. If a non-null value
/// is returned, this is stored as native data for [node] in the resolved
/// AST.
dynamic resolveForeignCall(Send node, Element element,
CallStructure callStructure, ForeignResolver resolver) {
return null;
}
/// Returns `true` if [element] is a default implementation of `noSuchMethod`
/// used by the target.
bool isDefaultNoSuchMethod(MethodElement element);

View file

@ -5,8 +5,7 @@
library js_backend.backend;
import '../common.dart';
import '../common/backend_api.dart'
show ForeignResolver, NativeRegistry, ImpactTransformer;
import '../common/backend_api.dart' show ImpactTransformer;
import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
import '../common/names.dart' show Uris;
import '../common/resolution.dart' show Resolution, Target;
@ -14,14 +13,11 @@ import '../common/tasks.dart' show CompilerTask;
import '../common_elements.dart' show CommonElements, ElementEnvironment;
import '../compiler.dart' show Compiler;
import '../constants/constant_system.dart';
import '../constants/expressions.dart';
import '../constants/values.dart';
import '../deferred_load.dart' show DeferredLoadTask, OutputUnitData;
import '../dump_info.dart' show DumpInfoTask;
import '../elements/elements.dart';
import '../elements/entities.dart';
import '../elements/names.dart';
import '../elements/resolution_types.dart';
import '../elements/types.dart';
import '../enqueue.dart'
show
@ -41,10 +37,8 @@ import '../js_emitter/js_emitter.dart' show CodeEmitterTask;
import '../js_emitter/sorter.dart' show Sorter;
import '../library_loader.dart' show LoadedLibraries;
import '../native/native.dart' as native;
import '../native/resolver.dart';
import '../ssa/ssa.dart' show SsaFunctionCompiler;
import '../tracer.dart';
import '../tree/tree.dart';
import '../types/types.dart';
import '../universe/call_structure.dart' show CallStructure;
import '../universe/class_hierarchy_builder.dart'
@ -412,7 +406,6 @@ class JavaScriptBackend {
NativeDataBuilderImpl _nativeDataBuilder;
NativeDataBuilder get nativeDataBuilder => _nativeDataBuilder;
final NativeDataResolver _nativeDataResolver;
OneShotInterceptorData _oneShotInterceptorData;
BackendUsageBuilder _backendUsageBuilder;
MirrorsDataImpl _mirrorsData;
@ -436,8 +429,7 @@ class JavaScriptBackend {
bool useNewSourceInfo: false})
: this.sourceInformationStrategy =
compiler.backendStrategy.sourceInformationStrategy,
constantCompilerTask = new JavaScriptConstantTask(compiler),
_nativeDataResolver = new NativeDataResolverImpl(compiler) {
constantCompilerTask = new JavaScriptConstantTask(compiler) {
CommonElements commonElements = compiler.frontendStrategy.commonElements;
_target = new JavaScriptBackendTarget(this);
_mirrorsData = compiler.frontendStrategy.createMirrorsDataBuilder();
@ -562,23 +554,6 @@ class JavaScriptBackend {
return constantCompilerTask.jsConstantCompiler;
}
MethodElement resolveExternalFunction(MethodElement element) {
if (isForeign(compiler.frontendStrategy.commonElements, element)) {
return element;
}
if (_nativeDataResolver.isJsInteropMember(element)) {
if (element.memberName == const PublicName('[]') ||
element.memberName == const PublicName('[]=')) {
reporter.reportErrorMessage(
element, MessageKind.JS_INTEROP_INDEX_NOT_SUPPORTED);
}
return element;
}
return patchResolverTask.measure(() {
return patchResolverTask.resolveExternalFunction(element);
});
}
bool isForeign(CommonElements commonElements, Element element) =>
element.library == commonElements.foreignLibrary;
@ -652,38 +627,6 @@ class JavaScriptBackend {
_outputUnitData = compiler.backendStrategy.convertOutputUnitData(data);
}
/// Called when resolving a call to a foreign function.
native.NativeBehavior resolveForeignCall(Send node, Element element,
CallStructure callStructure, ForeignResolver resolver) {
if (element.name == JS) {
return _nativeDataResolver.resolveJsCall(node, resolver);
} else if (element.name == JS_EMBEDDED_GLOBAL) {
return _nativeDataResolver.resolveJsEmbeddedGlobalCall(node, resolver);
} else if (element.name == JS_BUILTIN) {
return _nativeDataResolver.resolveJsBuiltinCall(node, resolver);
} else if (element.name == JS_INTERCEPTOR_CONSTANT) {
// The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names
// a class that will be instantiated outside the program by attaching a
// native class dispatch record referencing the interceptor.
if (!node.argumentsNode.isEmpty) {
Node argument = node.argumentsNode.nodes.head;
ConstantExpression constant = resolver.getConstant(argument);
if (constant != null && constant.kind == ConstantExpressionKind.TYPE) {
TypeConstantExpression typeConstant = constant;
if (typeConstant.type is ResolutionInterfaceType) {
resolver.registerInstantiatedType(typeConstant.type);
// No native behavior for this call.
return null;
}
}
}
reporter.reportErrorMessage(
node, MessageKind.WRONG_ARGUMENT_FOR_JS_INTERCEPTOR_CONSTANT);
}
// No native behavior for this call.
return null;
}
ResolutionEnqueuer createResolutionEnqueuer(
CompilerTask task, Compiler compiler) {
ElementEnvironment elementEnvironment =
@ -1344,22 +1287,6 @@ class JavaScriptBackendTarget extends Target {
return _backend.isTargetSpecificLibrary(element);
}
@override
void resolveNativeMember(MemberElement element, NativeRegistry registry) {
return _backend._nativeDataResolver.resolveNativeMember(element, registry);
}
@override
MethodElement resolveExternalFunction(MethodElement element) {
return _backend.resolveExternalFunction(element);
}
@override
dynamic resolveForeignCall(Send node, Element element,
CallStructure callStructure, ForeignResolver resolver) {
return _backend.resolveForeignCall(node, element, callStructure, resolver);
}
@override
bool isDefaultNoSuchMethod(MethodElement element) {
return _commonElements.isDefaultNoSuchMethodImplementation(element);

View file

@ -3,18 +3,13 @@
// BSD-style license that can be found in the LICENSE file.
import '../common.dart';
import '../common/backend_api.dart' show ForeignResolver;
import '../common/resolution.dart' show ParsingContext;
import '../constants/values.dart';
import '../common_elements.dart' show CommonElements, ElementEnvironment;
import '../elements/entities.dart';
import '../elements/resolution_types.dart';
import '../elements/types.dart';
import '../js/js.dart' as js;
import '../js_backend/native_data.dart' show NativeBasicData;
import '../tree/tree.dart';
import '../universe/side_effects.dart' show SideEffects;
import '../util/util.dart';
import 'js.dart';
typedef dynamic /*DartType|SpecialType*/ TypeLookup(String typeString,
@ -492,61 +487,6 @@ class NativeBehavior {
return sideEffects;
}
/// Returns a [TypeLookup] that uses [resolver] to perform lookup and [node]
/// as position for errors.
static TypeLookup _typeLookup(
Node node, DiagnosticReporter reporter, ForeignResolver resolver) {
ResolutionDartType lookup(String name, {bool required}) {
ResolutionDartType type = resolver.resolveTypeFromString(node, name);
if (type == null && required) {
reporter.reportErrorMessage(
node, MessageKind.GENERIC, {'text': "Type '$name' not found."});
}
return type;
}
return lookup;
}
/// Compute the [NativeBehavior] for a [Send] node calling the 'JS' function.
static NativeBehavior ofJsCallSend(
Send jsCall,
DiagnosticReporter reporter,
ParsingContext parsing,
CommonElements commonElements,
ForeignResolver resolver) {
var argNodes = jsCall.arguments;
if (argNodes.isEmpty || argNodes.tail.isEmpty) {
reporter.reportErrorMessage(jsCall, MessageKind.WRONG_ARGUMENT_FOR_JS);
return new NativeBehavior();
}
dynamic specArgument = argNodes.head;
if (specArgument is! StringNode || specArgument.isInterpolation) {
reporter.reportErrorMessage(
specArgument, MessageKind.WRONG_ARGUMENT_FOR_JS_FIRST);
return new NativeBehavior();
}
dynamic codeArgument = argNodes.tail.head;
if (codeArgument is! StringNode || codeArgument.isInterpolation) {
reporter.reportErrorMessage(
codeArgument, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND);
return new NativeBehavior();
}
String specString = specArgument.dartString.slowToString();
String codeString = codeArgument.dartString.slowToString();
return ofJsCall(
specString,
codeString,
_typeLookup(specArgument, reporter, resolver),
specArgument,
reporter,
commonElements);
}
/// Compute the [NativeBehavior] for a call to the 'JS' function with the
/// given [specString] and [codeString] (first and second arguments).
static NativeBehavior ofJsCall(
@ -633,50 +573,6 @@ class NativeBehavior {
nullType: commonElements.nullType);
}
static NativeBehavior ofJsBuiltinCallSend(
Send jsBuiltinCall,
DiagnosticReporter reporter,
CommonElements commonElements,
ForeignResolver resolver) {
NativeBehavior behavior = new NativeBehavior();
behavior.sideEffects.setTo(new SideEffects());
// The first argument of a JS-embedded global call is a string encoding
// the type of the code.
//
// 'Type1|Type2'. A union type.
// '=Object'. A JavaScript Object, no subtype.
Link<Node> argNodes = jsBuiltinCall.arguments;
if (argNodes.isEmpty) {
reporter.internalError(
jsBuiltinCall, "JS builtin expression has no type.");
}
// We don't check the given name. That needs to be done at a later point.
// This is, because we want to allow non-literals (like references to
// enums) as names.
if (argNodes.tail.isEmpty) {
reporter.internalError(jsBuiltinCall, "JS builtin is missing name.");
}
LiteralString specLiteral = argNodes.head.asLiteralString();
if (specLiteral == null) {
// TODO(sra): We could accept a type identifier? e.g. JS(bool, '1<2'). It
// is not very satisfactory because it does not work for void, dynamic.
reporter.internalError(argNodes.head, "Unexpected first argument.");
}
String specString = specLiteral.dartString.slowToString();
return ofJsBuiltinCall(
specString,
_typeLookup(jsBuiltinCall, reporter, resolver),
jsBuiltinCall,
reporter,
commonElements);
}
static NativeBehavior ofJsBuiltinCall(
String specString,
TypeLookup lookupType,
@ -690,60 +586,6 @@ class NativeBehavior {
return behavior;
}
static NativeBehavior ofJsEmbeddedGlobalCallSend(
Send jsEmbeddedGlobalCall,
DiagnosticReporter reporter,
CommonElements commonElements,
ForeignResolver resolver) {
NativeBehavior behavior = new NativeBehavior();
// TODO(sra): Allow the use site to override these defaults.
// Embedded globals are usually pre-computed data structures or JavaScript
// functions that never change.
behavior.sideEffects.setTo(new SideEffects.empty());
behavior.throwBehavior = NativeThrowBehavior.NEVER;
// The first argument of a JS-embedded global call is a string encoding
// the type of the code.
//
// 'Type1|Type2'. A union type.
// '=Object'. A JavaScript Object, no subtype.
Link<Node> argNodes = jsEmbeddedGlobalCall.arguments;
if (argNodes.isEmpty) {
reporter.internalError(
jsEmbeddedGlobalCall, "JS embedded global expression has no type.");
}
// We don't check the given name. That needs to be done at a later point.
// This is, because we want to allow non-literals (like references to
// enums) as names.
if (argNodes.tail.isEmpty) {
reporter.internalError(
jsEmbeddedGlobalCall, "JS embedded global is missing name.");
}
if (!argNodes.tail.tail.isEmpty) {
reporter.internalError(argNodes.tail.tail.head,
'JS embedded global has more than 2 arguments');
}
LiteralString specLiteral = argNodes.head.asLiteralString();
if (specLiteral == null) {
// TODO(sra): We could accept a type identifier? e.g. JS(bool, '1<2'). It
// is not very satisfactory because it does not work for void, dynamic.
reporter.internalError(argNodes.head, "Unexpected first argument.");
}
String specString = specLiteral.dartString.slowToString();
return ofJsEmbeddedGlobalCall(
specString,
_typeLookup(jsEmbeddedGlobalCall, reporter, resolver),
jsEmbeddedGlobalCall,
reporter,
commonElements);
}
static NativeBehavior ofJsEmbeddedGlobalCall(
String specString,
TypeLookup lookupType,
@ -766,7 +608,7 @@ class NativeBehavior {
String typeString, TypeLookup lookupType) {
if (typeString == '=Object') return SpecialType.JsObject;
if (typeString == 'dynamic') {
return const ResolutionDynamicType();
return const DynamicType();
}
int index = typeString.indexOf('<');
var type = lookupType(typeString, required: index == -1);
@ -779,7 +621,7 @@ class NativeBehavior {
return type;
}
}
return const ResolutionDynamicType();
return const DynamicType();
}
}

View file

@ -2,74 +2,17 @@
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'package:front_end/src/fasta/scanner.dart' show StringToken, Token;
import 'package:front_end/src/fasta/scanner.dart' as Tokens show EOF_TOKEN;
import 'package:front_end/src/scanner/token.dart' show BeginToken;
import '../common.dart';
import '../common_elements.dart' show CommonElements, ElementEnvironment;
import '../common/backend_api.dart';
import '../common/resolution.dart';
import '../compiler.dart' show Compiler;
import '../constants/values.dart';
import '../elements/elements.dart'
show
ClassElement,
Element,
FieldElement,
MemberElement,
MetadataAnnotation,
MethodElement;
import '../elements/entities.dart';
import '../elements/modelx.dart' show FunctionElementX, MetadataAnnotationX;
import '../elements/resolution_types.dart' show ResolutionDartType;
import '../js_backend/js_backend.dart';
import '../js_backend/native_data.dart';
import '../patch_parser.dart';
import '../tree/tree.dart';
import 'behavior.dart';
/// Interface for computing native members.
abstract class NativeMemberResolver {
/// Computes whether [element] is native or JsInterop and, if so, registers
/// its [NativeBehavior]s to [registry].
void resolveNativeMember(MemberEntity element, [NativeRegistry registry]);
}
/// Interface for computing native members and [NativeBehavior]s in member code
/// based on the AST.
abstract class NativeDataResolver implements NativeMemberResolver {
/// Returns `true` if [element] is a JsInterop member.
bool isJsInteropMember(MemberElement element);
/// Computes the [NativeBehavior] for a `JS` call, which can be an
/// instantiation point for types.
///
/// For example, the following code instantiates and returns native classes
/// that are `_DOMWindowImpl` or a subtype.
///
/// JS('_DOMWindowImpl', 'window')
///
NativeBehavior resolveJsCall(Send node, ForeignResolver resolver);
/// Computes the [NativeBehavior] for a `JS_EMBEDDED_GLOBAL` call, which can
/// be an instantiation point for types.
///
/// For example, the following code instantiates and returns a String class
///
/// JS_EMBEDDED_GLOBAL('String', 'foo')
///
NativeBehavior resolveJsEmbeddedGlobalCall(
Send node, ForeignResolver resolver);
/// Computes the [NativeBehavior] for a `JS_BUILTIN` call, which can be an
/// instantiation point for types.
///
/// For example, the following code instantiates and returns a String class
///
/// JS_BUILTIN('String', 'int2string', 0)
///
NativeBehavior resolveJsBuiltinCall(Send node, ForeignResolver resolver);
/// Computes whether [element] is native or JsInterop.
void resolveNativeMember(MemberEntity element);
}
abstract class NativeMemberResolverBase implements NativeMemberResolver {
@ -90,7 +33,7 @@ abstract class NativeMemberResolverBase implements NativeMemberResolver {
NativeBehavior computeNativeFieldStoreBehavior(covariant FieldEntity field);
@override
void resolveNativeMember(MemberEntity element, [NativeRegistry registry]) {
void resolveNativeMember(MemberEntity element) {
bool isJsInterop = isJsInteropMember(element);
if (element.isFunction ||
element.isConstructor ||
@ -102,7 +45,6 @@ abstract class NativeMemberResolverBase implements NativeMemberResolver {
NativeBehavior behavior =
computeNativeMethodBehavior(method, isJsInterop: isJsInterop);
nativeDataBuilder.setNativeMethodBehavior(method, behavior);
registry?.registerNativeData(behavior);
}
} else if (element.isField) {
FieldEntity field = element;
@ -115,13 +57,6 @@ abstract class NativeMemberResolverBase implements NativeMemberResolver {
nativeDataBuilder.setNativeFieldLoadBehavior(field, fieldLoadBehavior);
nativeDataBuilder.setNativeFieldStoreBehavior(
field, fieldStoreBehavior);
// TODO(sra): Process fields for storing separately.
// We have to handle both loading and storing to the field because we
// only get one look at each member and there might be a load or store
// we have not seen yet.
registry?.registerNativeData(fieldLoadBehavior);
registry?.registerNativeData(fieldStoreBehavior);
}
}
}
@ -208,178 +143,6 @@ abstract class NativeMemberResolverBase implements NativeMemberResolver {
}
}
class NativeDataResolverImpl extends NativeMemberResolverBase
implements NativeDataResolver {
final Compiler _compiler;
NativeDataResolverImpl(this._compiler);
JavaScriptBackend get _backend => _compiler.backend;
DiagnosticReporter get _reporter => _compiler.reporter;
ElementEnvironment get elementEnvironment =>
_compiler.resolution.elementEnvironment;
CommonElements get commonElements => _compiler.resolution.commonElements;
NativeBasicData get nativeBasicData =>
_compiler.frontendStrategy.nativeBasicData;
NativeDataBuilder get nativeDataBuilder => _backend.nativeDataBuilder;
@override
bool isJsInteropMember(MemberElement element) {
// TODO(johnniwinther): Avoid computing this twice for external function;
// once from JavaScriptBackendTarget.resolveExternalFunction and once
// through JavaScriptBackendTarget.resolveNativeMember.
bool isJsInterop =
checkJsInteropMemberAnnotations(_compiler, element, nativeDataBuilder);
// TODO(johnniwinther): Avoid this duplication of logic from
// NativeData.isJsInterop.
if (!isJsInterop && element is MethodElement && element.isExternal) {
if (element.enclosingClass != null) {
isJsInterop = nativeBasicData.isJsInteropClass(element.enclosingClass);
} else {
isJsInterop = nativeBasicData.isJsInteropLibrary(element.library);
}
}
return isJsInterop;
}
@override
NativeBehavior computeNativeMethodBehavior(MethodElement function,
{bool isJsInterop}) {
return null;
}
@override
NativeBehavior computeNativeFieldLoadBehavior(FieldElement field,
{bool isJsInterop}) {
return null;
}
@override
NativeBehavior computeNativeFieldStoreBehavior(FieldElement field) {
return null;
}
@override
bool isNativeMethod(FunctionElementX element) {
if (!_backend.canLibraryUseNative(element.library)) return false;
// Native method?
return _reporter.withCurrentElement(element, () {
Node node = element.parseNode(_compiler.resolution.parsingContext);
if (node is! FunctionExpression) return false;
FunctionExpression functionExpression = node;
node = functionExpression.body;
Token token = node.getBeginToken();
if (identical(token.stringValue, 'native')) {
element.isMarkedNative = true;
return true;
}
return false;
});
}
@override
NativeBehavior resolveJsCall(Send node, ForeignResolver resolver) {
return NativeBehavior.ofJsCallSend(
node, _reporter, _compiler.parsingContext, commonElements, resolver);
}
@override
NativeBehavior resolveJsEmbeddedGlobalCall(
Send node, ForeignResolver resolver) {
return NativeBehavior.ofJsEmbeddedGlobalCallSend(
node, _reporter, commonElements, resolver);
}
@override
NativeBehavior resolveJsBuiltinCall(Send node, ForeignResolver resolver) {
return NativeBehavior.ofJsBuiltinCallSend(
node, _reporter, commonElements, resolver);
}
}
/// Annotation handler for pre-resolution detection of `@Native(...)`
/// annotations.
class NativeAnnotationHandler extends EagerAnnotationHandler<String> {
final NativeBasicDataBuilder _nativeBasicDataBuilder;
NativeAnnotationHandler(this._nativeBasicDataBuilder);
String getNativeAnnotation(MetadataAnnotationX annotation) {
if (annotation.beginToken != null &&
annotation.beginToken.next.lexeme == 'Native') {
// Skipping '@', 'Native', and '('.
Token argument = annotation.beginToken.next.next.next;
if (argument is StringToken) {
return argument.lexeme;
}
}
return null;
}
String apply(
Compiler compiler, Element element, MetadataAnnotation annotation) {
if (element.isClass) {
ClassElement cls = element;
String native = getNativeAnnotation(annotation);
if (native != null) {
String tagText = native.substring(1, native.length - 1);
_nativeBasicDataBuilder.setNativeClassTagInfo(cls, tagText);
return native;
}
}
return null;
}
void validate(Compiler compiler, Element element,
MetadataAnnotation annotation, ConstantValue constant) {
ResolutionDartType annotationType =
constant.getType(compiler.resolution.commonElements);
if (annotationType.element !=
compiler.resolution.commonElements.nativeAnnotationClass) {
DiagnosticReporter reporter = compiler.reporter;
reporter.internalError(annotation, 'Invalid @Native(...) annotation.');
}
}
}
bool checkJsInteropMemberAnnotations(Compiler compiler, MemberElement element,
NativeDataBuilder nativeDataBuilder) {
bool isJsInterop = EagerAnnotationHandler.checkAnnotation(
compiler, element, const JsInteropAnnotationHandler());
if (isJsInterop) {
nativeDataBuilder.markAsJsInteropMember(element);
}
return isJsInterop;
}
/// Annotation handler for pre-resolution detection of `@JS(...)`
/// annotations.
class JsInteropAnnotationHandler implements EagerAnnotationHandler<bool> {
const JsInteropAnnotationHandler();
bool hasJsNameAnnotation(MetadataAnnotationX annotation) =>
annotation.beginToken != null &&
annotation.beginToken.next.lexeme == 'JS';
bool apply(
Compiler compiler, Element element, MetadataAnnotation annotation) {
return hasJsNameAnnotation(annotation);
}
@override
void validate(Compiler compiler, Element element,
MetadataAnnotation annotation, ConstantValue constant) {
ResolutionDartType type =
constant.getType(compiler.resolution.commonElements);
if (type.element != compiler.resolution.commonElements.jsAnnotationClass) {
compiler.reporter
.internalError(annotation, 'Invalid @JS(...) annotation.');
}
}
bool get defaultResult => false;
}
/// Determines all native classes in a set of libraries.
abstract class NativeClassFinder {
/// Returns the set of all native classes declared in [libraries].
@ -494,98 +257,6 @@ class BaseNativeClassFinder implements NativeClassFinder {
}
}
/// Native class finder that extends [BaseNativeClassFinder] to handle
/// unresolved classes encountered during the native classes computation.
class ResolutionNativeClassFinder extends BaseNativeClassFinder {
final DiagnosticReporter _reporter;
final Resolution _resolution;
ResolutionNativeClassFinder(
this._resolution,
this._reporter,
ElementEnvironment elementEnvironment,
CommonElements commonElements,
NativeBasicData nativeBasicData)
: super(elementEnvironment, nativeBasicData);
void _processNativeClass(
ClassElement classElement, Set<ClassEntity> nativeClasses) {
// Resolve class to ensure the class has valid inheritance info.
classElement.ensureResolved(_resolution);
super._processNativeClass(classElement, nativeClasses);
}
/**
* Returns the source string of the class named in the extends clause, or
* `null` if there is no extends clause.
*/
String _findExtendsNameOfClass(ClassElement classElement) {
if (classElement.isResolved) {
ClassElement superClass = classElement.superclass;
while (superClass != null) {
if (!superClass.isUnnamedMixinApplication) {
return superClass.name;
}
superClass = superClass.superclass;
}
return null;
}
// "class B extends A ... {}" --> "A"
// "class B extends foo.A ... {}" --> "A"
// "class B<T> extends foo.A<T,T> with M1, M2 ... {}" --> "A"
// We want to avoid calling classElement.parseNode on every class. Doing so
// will slightly increase parse time and size and cause compiler errors and
// warnings to me emitted in more unused code.
// An alternative to this code is to extend the API of ClassElement to
// expose the name of the extended element.
// Pattern match the above cases in the token stream.
// [abstract] class X extends [id.]* id
Token skipTypeParameters(Token token) {
BeginToken beginGroupToken = token;
Token endToken = beginGroupToken.endGroup;
return endToken.next;
//for (;;) {
// token = token.next;
// if (token.stringValue == '>') return token.next;
// if (token.stringValue == '<') return skipTypeParameters(token);
//}
}
String scanForExtendsName(Token token) {
if (token.stringValue == 'abstract') token = token.next;
if (token.stringValue != 'class') return null;
token = token.next;
if (!token.isIdentifier) return null;
token = token.next;
// class F<X extends B<X>> extends ...
if (token.stringValue == '<') {
token = skipTypeParameters(token);
}
if (token.stringValue != 'extends') return null;
token = token.next;
Token id = token;
while (token.kind != Tokens.EOF_TOKEN) {
token = token.next;
if (token.stringValue != '.') break;
token = token.next;
if (!token.isIdentifier) return null;
id = token;
}
// Should be at '{', 'with', 'implements', '<' or 'native'.
return id.lexeme;
}
return _reporter.withCurrentElement(classElement, () {
return scanForExtendsName(classElement.position);
});
}
}
/// Returns `true` if [value] is named annotation based on [annotationClass].
bool isAnnotation(
Spannable spannable, ConstantValue value, ClassEntity annotationClass) {

View file

@ -5,7 +5,6 @@
library dart2js.resolution.registry;
import '../common.dart';
import '../common/backend_api.dart' show ForeignResolver, NativeRegistry;
import '../common/resolution.dart' show ResolutionImpact, Target;
import '../constants/expressions.dart';
import '../diagnostics/source_span.dart';
@ -24,7 +23,7 @@ import '../util/util.dart' show Setlet;
import 'tree_elements.dart' show TreeElementMapping;
class ResolutionWorldImpactBuilder extends WorldImpactBuilderImpl
implements NativeRegistry, ResolutionImpact {
implements ResolutionImpact {
final String name;
EnumSet<Feature> _features;
Setlet<MapLiteralUse> _mapLiterals;
@ -383,15 +382,7 @@ class ResolutionRegistry {
}
void registerForeignCall(
Node node, Element element, CallStructure callStructure) {
var nativeData = target.resolveForeignCall(
node, element, callStructure, new ForeignResolutionResolver(this));
if (nativeData != null) {
// Split impact from resolution result.
mapping.registerNativeData(node, nativeData);
impactBuilder.registerNativeData(nativeData);
}
}
Node node, Element element, CallStructure callStructure) {}
void registerDynamicUse(DynamicUse dynamicUse) {
impactBuilder.registerDynamicUse(dynamicUse);
@ -425,24 +416,3 @@ class ResolutionRegistry {
impactBuilder.registerSeenClass(seenClass);
}
}
class ForeignResolutionResolver implements ForeignResolver {
final ResolutionRegistry registry;
ForeignResolutionResolver(this.registry);
@override
ConstantExpression getConstant(Node node) {
return registry.getConstant(node);
}
@override
void registerInstantiatedType(ResolutionInterfaceType type) {
registry.registerInstantiation(type);
}
@override
ResolutionDartType resolveTypeFromString(Node node, String typeName) {
return null;
}
}