| Index: pkg/compiler/lib/src/native/behavior.dart
|
| diff --git a/pkg/compiler/lib/src/native/behavior.dart b/pkg/compiler/lib/src/native/behavior.dart
|
| index 57ef61a02df98506e5e15e2799ff48ef0ceb6582..86096300d62254086991f5033e4501bcaa1de793 100644
|
| --- a/pkg/compiler/lib/src/native/behavior.dart
|
| +++ b/pkg/compiler/lib/src/native/behavior.dart
|
| @@ -6,6 +6,7 @@ import '../common.dart';
|
| import '../common/backend_api.dart' show ForeignResolver;
|
| import '../common/resolution.dart' show ParsingContext, Resolution;
|
| import '../compiler.dart' show Compiler;
|
| +import '../constants/expressions.dart';
|
| import '../constants/values.dart';
|
| import '../core_types.dart' show CoreTypes;
|
| import '../dart_types.dart';
|
| @@ -18,6 +19,8 @@ import '../util/util.dart';
|
| import 'enqueue.dart';
|
| import 'js.dart';
|
|
|
| +typedef dynamic /*DartType|SpecialType*/ TypeLookup(String typeString);
|
| +
|
| /// This class is a temporary work-around until we get a more powerful DartType.
|
| class SpecialType {
|
| final String name;
|
| @@ -263,7 +266,7 @@ class NativeBehavior {
|
| void setThrows(NativeThrowBehavior throwKind),
|
| void setIsAllocation(bool isAllocation),
|
| void setUseGvn(bool useGvn),
|
| - dynamic resolveType(String typeString),
|
| + TypeLookup lookupType,
|
| List typesReturned,
|
| List typesInstantiated,
|
| objectType,
|
| @@ -306,7 +309,7 @@ class NativeBehavior {
|
| return;
|
| }
|
| for (final typeString in typesString.split('|')) {
|
| - onType(resolveType(typeString.trim()));
|
| + onType(_parseType(typeString.trim(), spannable, reporter, lookupType));
|
| }
|
| }
|
|
|
| @@ -486,49 +489,61 @@ class NativeBehavior {
|
| return sideEffects;
|
| }
|
|
|
| - static NativeBehavior ofJsCall(Send jsCall, DiagnosticReporter reporter,
|
| - ParsingContext parsing, CoreTypes coreTypes, ForeignResolver resolver) {
|
| - // The first argument of a JS-call is a string encoding various attributes
|
| - // of the code.
|
| - //
|
| - // 'Type1|Type2'. A union type.
|
| - // '=Object'. A JavaScript Object, no subtype.
|
| -
|
| - NativeBehavior behavior = new NativeBehavior();
|
| + /// Returns a [TypeLookup] that uses [resolver] to perform lookup and [node]
|
| + /// as position for errors.
|
| + static TypeLookup _typeLookup(Node node, ForeignResolver resolver) {
|
| + return (String name) => resolver.resolveTypeFromString(node, name);
|
| + }
|
|
|
| + /// Compute the [NativeBehavior] for a [Send] node calling the 'JS' function.
|
| + static NativeBehavior ofJsCallSend(Send jsCall, DiagnosticReporter reporter,
|
| + ParsingContext parsing, CoreTypes coreTypes, ForeignResolver resolver) {
|
| var argNodes = jsCall.arguments;
|
| if (argNodes.isEmpty || argNodes.tail.isEmpty) {
|
| - reporter.reportErrorMessage(jsCall, MessageKind.GENERIC,
|
| - {'text': "JS expression takes two or more arguments."});
|
| - return behavior;
|
| + reporter.reportErrorMessage(jsCall, MessageKind.WRONG_ARGUMENT_FOR_JS);
|
| + return new NativeBehavior();
|
| }
|
|
|
| var specArgument = argNodes.head;
|
| if (specArgument is! StringNode || specArgument.isInterpolation) {
|
| - reporter.reportErrorMessage(specArgument, MessageKind.GENERIC,
|
| - {'text': "JS first argument must be a string literal."});
|
| - return behavior;
|
| + reporter.reportErrorMessage(
|
| + specArgument, MessageKind.WRONG_ARGUMENT_FOR_JS_FIRST);
|
| + return new NativeBehavior();
|
| }
|
|
|
| var codeArgument = argNodes.tail.head;
|
| if (codeArgument is! StringNode || codeArgument.isInterpolation) {
|
| - reporter.reportErrorMessage(codeArgument, MessageKind.GENERIC,
|
| - {'text': "JS second argument must be a string literal."});
|
| - return behavior;
|
| + reporter.reportErrorMessage(
|
| + codeArgument, MessageKind.WRONG_ARGUMENT_FOR_JS_SECOND);
|
| + return new NativeBehavior();
|
| }
|
|
|
| - behavior.codeTemplateText = codeArgument.dartString.slowToString();
|
| - behavior.codeTemplate = js.js.parseForeignJS(behavior.codeTemplateText);
|
| -
|
| String specString = specArgument.dartString.slowToString();
|
| + String codeString = codeArgument.dartString.slowToString();
|
|
|
| - dynamic resolveType(String typeString) {
|
| - return _parseType(
|
| - typeString,
|
| - parsing,
|
| - (name) => resolver.resolveTypeFromString(specArgument, name),
|
| - specArgument);
|
| - }
|
| + return ofJsCall(specString, codeString, _typeLookup(specArgument, resolver),
|
| + specArgument, reporter, coreTypes);
|
| + }
|
| +
|
| + /// Compute the [NativeBehavior] for a call to the 'JS' function with the
|
| + /// given [specString] and [codeString] (first and second arguments).
|
| + static NativeBehavior ofJsCall(
|
| + String specString,
|
| + String codeString,
|
| + TypeLookup lookupType,
|
| + Spannable spannable,
|
| + DiagnosticReporter reporter,
|
| + CoreTypes coreTypes) {
|
| + // The first argument of a JS-call is a string encoding various attributes
|
| + // of the code.
|
| + //
|
| + // 'Type1|Type2'. A union type.
|
| + // '=Object'. A JavaScript Object, no subtype.
|
| +
|
| + NativeBehavior behavior = new NativeBehavior();
|
| +
|
| + behavior.codeTemplateText = codeString;
|
| + behavior.codeTemplate = js.js.parseForeignJS(behavior.codeTemplateText);
|
|
|
| bool sideEffectsAreEncodedInSpecString = false;
|
|
|
| @@ -551,12 +566,12 @@ class NativeBehavior {
|
| behavior.useGvn = useGvn;
|
| }
|
|
|
| - processSpecString(reporter, specArgument, specString,
|
| + processSpecString(reporter, spannable, specString,
|
| setSideEffects: setSideEffects,
|
| setThrows: setThrows,
|
| setIsAllocation: setIsAllocation,
|
| setUseGvn: setUseGvn,
|
| - resolveType: resolveType,
|
| + lookupType: lookupType,
|
| typesReturned: behavior.typesReturned,
|
| typesInstantiated: behavior.typesInstantiated,
|
| objectType: coreTypes.objectType,
|
| @@ -576,40 +591,51 @@ class NativeBehavior {
|
|
|
| static void _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal(
|
| NativeBehavior behavior,
|
| - Send jsBuiltinOrEmbeddedGlobalCall,
|
| + Spannable spannable,
|
| + String specString,
|
| + TypeLookup lookupType,
|
| DiagnosticReporter reporter,
|
| - ParsingContext parsing,
|
| CoreTypes coreTypes,
|
| - ForeignResolver resolver,
|
| - {bool isBuiltin,
|
| - List<String> validTags}) {
|
| + {List<String> validTags}) {
|
| + void setSideEffects(SideEffects newEffects) {
|
| + behavior.sideEffects.setTo(newEffects);
|
| + }
|
| +
|
| + processSpecString(reporter, spannable, specString,
|
| + validTags: validTags,
|
| + lookupType: lookupType,
|
| + setSideEffects: setSideEffects,
|
| + typesReturned: behavior.typesReturned,
|
| + typesInstantiated: behavior.typesInstantiated,
|
| + objectType: coreTypes.objectType,
|
| + nullType: coreTypes.nullType);
|
| + }
|
| +
|
| + static NativeBehavior ofJsBuiltinCallSend(
|
| + Send jsBuiltinCall,
|
| + DiagnosticReporter reporter,
|
| + CoreTypes coreTypes,
|
| + 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.
|
|
|
| - String builtinOrGlobal = isBuiltin ? "builtin" : "embedded global";
|
| -
|
| - Link<Node> argNodes = jsBuiltinOrEmbeddedGlobalCall.arguments;
|
| + Link<Node> argNodes = jsBuiltinCall.arguments;
|
| if (argNodes.isEmpty) {
|
| - reporter.internalError(jsBuiltinOrEmbeddedGlobalCall,
|
| - "JS $builtinOrGlobal expression has no type.");
|
| + 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(jsBuiltinOrEmbeddedGlobalCall,
|
| - 'JS $builtinOrGlobal is missing name.');
|
| - }
|
| -
|
| - if (!isBuiltin) {
|
| - if (!argNodes.tail.tail.isEmpty) {
|
| - reporter.internalError(argNodes.tail.tail.head,
|
| - 'JS embedded global has more than 2 arguments');
|
| - }
|
| + reporter.internalError(jsBuiltinCall, "JS builtin is missing name.");
|
| }
|
|
|
| LiteralString specLiteral = argNodes.head.asLiteralString();
|
| @@ -621,48 +647,26 @@ class NativeBehavior {
|
|
|
| String specString = specLiteral.dartString.slowToString();
|
|
|
| - dynamic resolveType(String typeString) {
|
| - return _parseType(
|
| - typeString,
|
| - parsing,
|
| - (name) => resolver.resolveTypeFromString(specLiteral, name),
|
| - jsBuiltinOrEmbeddedGlobalCall);
|
| - }
|
| -
|
| - void setSideEffects(SideEffects newEffects) {
|
| - behavior.sideEffects.setTo(newEffects);
|
| - }
|
| -
|
| - processSpecString(reporter, jsBuiltinOrEmbeddedGlobalCall, specString,
|
| - validTags: validTags,
|
| - resolveType: resolveType,
|
| - setSideEffects: setSideEffects,
|
| - typesReturned: behavior.typesReturned,
|
| - typesInstantiated: behavior.typesInstantiated,
|
| - objectType: coreTypes.objectType,
|
| - nullType: coreTypes.nullType);
|
| + return ofJsBuiltinCall(specString, _typeLookup(jsBuiltinCall, resolver),
|
| + jsBuiltinCall, reporter, coreTypes);
|
| }
|
|
|
| static NativeBehavior ofJsBuiltinCall(
|
| - Send jsBuiltinCall,
|
| + String specString,
|
| + TypeLookup lookupType,
|
| + Spannable spannable,
|
| DiagnosticReporter reporter,
|
| - ParsingContext parsing,
|
| - CoreTypes coreTypes,
|
| - ForeignResolver resolver) {
|
| + CoreTypes coreTypes) {
|
| NativeBehavior behavior = new NativeBehavior();
|
| behavior.sideEffects.setTo(new SideEffects());
|
| -
|
| _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal(
|
| - behavior, jsBuiltinCall, reporter, parsing, coreTypes, resolver,
|
| - isBuiltin: true);
|
| -
|
| + behavior, spannable, specString, lookupType, reporter, coreTypes);
|
| return behavior;
|
| }
|
|
|
| - static NativeBehavior ofJsEmbeddedGlobalCall(
|
| + static NativeBehavior ofJsEmbeddedGlobalCallSend(
|
| Send jsEmbeddedGlobalCall,
|
| DiagnosticReporter reporter,
|
| - ParsingContext parsing,
|
| CoreTypes coreTypes,
|
| ForeignResolver resolver) {
|
| NativeBehavior behavior = new NativeBehavior();
|
| @@ -672,18 +676,97 @@ class NativeBehavior {
|
| behavior.sideEffects.setTo(new SideEffects.empty());
|
| behavior.throwBehavior = NativeThrowBehavior.NEVER;
|
|
|
| - _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal(
|
| - behavior, jsEmbeddedGlobalCall, reporter, parsing, coreTypes, resolver,
|
| - isBuiltin: false, validTags: const ['returns', 'creates']);
|
| + // 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, resolver),
|
| + jsEmbeddedGlobalCall,
|
| + reporter,
|
| + coreTypes);
|
| + }
|
|
|
| + static NativeBehavior ofJsEmbeddedGlobalCall(
|
| + String specString,
|
| + TypeLookup lookupType,
|
| + Spannable spannable,
|
| + DiagnosticReporter reporter,
|
| + CoreTypes coreTypes) {
|
| + 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;
|
| + _fillNativeBehaviorOfBuiltinOrEmbeddedGlobal(
|
| + behavior, spannable, specString, lookupType, reporter, coreTypes,
|
| + validTags: ['returns', 'creates']);
|
| return behavior;
|
| }
|
|
|
| - static NativeBehavior ofMethod(FunctionElement method, Compiler compiler) {
|
| - FunctionType type = method.computeType(compiler.resolution);
|
| + static NativeBehavior ofMethodElement(
|
| + FunctionElement element, Compiler compiler) {
|
| + FunctionType type = element.computeType(compiler.resolution);
|
| + List<ConstantExpression> metadata = <ConstantExpression>[];
|
| + for (MetadataAnnotation annotation in element.implementation.metadata) {
|
| + annotation.ensureResolved(compiler.resolution);
|
| + metadata.add(annotation.constant);
|
| + }
|
| +
|
| + DartType lookup(String name) {
|
| + Element e = element.buildScope().lookup(name);
|
| + if (e == null) return null;
|
| + if (e is! ClassElement) return null;
|
| + ClassElement cls = e;
|
| + cls.ensureResolved(compiler.resolution);
|
| + return cls.thisType;
|
| + }
|
| +
|
| + return ofMethod(element, type, metadata, lookup, compiler,
|
| + isJsInterop: compiler.backend.isJsInterop(element));
|
| + }
|
| +
|
| + static NativeBehavior ofMethod(
|
| + Spannable spannable,
|
| + FunctionType type,
|
| + List<ConstantExpression> metadata,
|
| + TypeLookup lookupType,
|
| + Compiler compiler,
|
| + {bool isJsInterop}) {
|
| var behavior = new NativeBehavior();
|
| var returnType = type.returnType;
|
| - bool isInterop = compiler.backend.isJsInterop(method);
|
| // Note: For dart:html and other internal libraries we maintain, we can
|
| // trust the return type and use it to limit what we enqueue. We have to
|
| // be more conservative about JS interop types and assume they can return
|
| @@ -694,7 +777,7 @@ class NativeBehavior {
|
| // but otherwise we would include a lot of code by default).
|
| // TODO(sigmund,sra): consider doing something better for numeric types.
|
| behavior.typesReturned.add(
|
| - !isInterop || compiler.options.trustJSInteropTypeAnnotations
|
| + !isJsInterop || compiler.options.trustJSInteropTypeAnnotations
|
| ? returnType
|
| : const DynamicType());
|
| if (!type.returnType.isVoid) {
|
| @@ -702,7 +785,7 @@ class NativeBehavior {
|
| behavior.typesReturned.add(compiler.coreTypes.nullType);
|
| }
|
| behavior._capture(type, compiler.resolution,
|
| - isInterop: isInterop, compiler: compiler);
|
| + isInterop: isJsInterop, compiler: compiler);
|
|
|
| for (DartType type in type.optionalParameterTypes) {
|
| behavior._escape(type, compiler.resolution);
|
| @@ -711,31 +794,64 @@ class NativeBehavior {
|
| behavior._escape(type, compiler.resolution);
|
| }
|
|
|
| - behavior._overrideWithAnnotations(method, compiler);
|
| + behavior._overrideWithAnnotations(
|
| + spannable, metadata, lookupType, compiler);
|
| return behavior;
|
| }
|
|
|
| - static NativeBehavior ofFieldLoad(MemberElement field, Compiler compiler) {
|
| + static NativeBehavior ofFieldElementLoad(
|
| + MemberElement element, Compiler compiler) {
|
| + Resolution resolution = compiler.resolution;
|
| + DartType type = element.computeType(resolution);
|
| + List<ConstantExpression> metadata = <ConstantExpression>[];
|
| + for (MetadataAnnotation annotation in element.implementation.metadata) {
|
| + annotation.ensureResolved(compiler.resolution);
|
| + metadata.add(annotation.constant);
|
| + }
|
| +
|
| + DartType lookup(String name) {
|
| + Element e = element.buildScope().lookup(name);
|
| + if (e == null) return null;
|
| + if (e is! ClassElement) return null;
|
| + ClassElement cls = e;
|
| + cls.ensureResolved(compiler.resolution);
|
| + return cls.thisType;
|
| + }
|
| +
|
| + return ofFieldLoad(element, type, metadata, lookup, compiler,
|
| + isJsInterop: compiler.backend.isJsInterop(element));
|
| + }
|
| +
|
| + static NativeBehavior ofFieldLoad(
|
| + Spannable spannable,
|
| + DartType type,
|
| + List<ConstantExpression> metadata,
|
| + TypeLookup lookupType,
|
| + Compiler compiler,
|
| + {bool isJsInterop}) {
|
| Resolution resolution = compiler.resolution;
|
| - DartType type = field.computeType(resolution);
|
| var behavior = new NativeBehavior();
|
| - bool isInterop = compiler.backend.isJsInterop(field);
|
| // TODO(sigmund,sra): consider doing something better for numeric types.
|
| behavior.typesReturned.add(
|
| - !isInterop || compiler.options.trustJSInteropTypeAnnotations
|
| + !isJsInterop || compiler.options.trustJSInteropTypeAnnotations
|
| ? type
|
| : const DynamicType());
|
| // Declared types are nullable.
|
| behavior.typesReturned.add(resolution.coreTypes.nullType);
|
| behavior._capture(type, resolution,
|
| - isInterop: isInterop, compiler: compiler);
|
| - behavior._overrideWithAnnotations(field, compiler);
|
| + isInterop: isJsInterop, compiler: compiler);
|
| + behavior._overrideWithAnnotations(
|
| + spannable, metadata, lookupType, compiler);
|
| return behavior;
|
| }
|
|
|
| - static NativeBehavior ofFieldStore(MemberElement field, Compiler compiler) {
|
| - Resolution resolution = compiler.resolution;
|
| + static NativeBehavior ofFieldElementStore(
|
| + MemberElement field, Resolution resolution) {
|
| DartType type = field.computeType(resolution);
|
| + return ofFieldStore(type, resolution);
|
| + }
|
| +
|
| + static NativeBehavior ofFieldStore(DartType type, Resolution resolution) {
|
| var behavior = new NativeBehavior();
|
| behavior._escape(type, resolution);
|
| // We don't override the default behaviour - the annotations apply to
|
| @@ -743,23 +859,18 @@ class NativeBehavior {
|
| return behavior;
|
| }
|
|
|
| - void _overrideWithAnnotations(Element element, Compiler compiler) {
|
| - if (element.implementation.metadata.isEmpty) return;
|
| -
|
| - DartType lookup(String name) {
|
| - Element e = element.buildScope().lookup(name);
|
| - if (e == null) return null;
|
| - if (e is! ClassElement) return null;
|
| - ClassElement cls = e;
|
| - cls.ensureResolved(compiler.resolution);
|
| - return cls.thisType;
|
| - }
|
| + void _overrideWithAnnotations(
|
| + Spannable spannable,
|
| + Iterable<ConstantExpression> metadata,
|
| + TypeLookup lookupType,
|
| + Compiler compiler) {
|
| + if (metadata.isEmpty) return;
|
|
|
| NativeEnqueuer enqueuer = compiler.enqueuer.resolution.nativeEnqueuer;
|
| - var creates =
|
| - _collect(element, compiler, enqueuer.annotationCreatesClass, lookup);
|
| - var returns =
|
| - _collect(element, compiler, enqueuer.annotationReturnsClass, lookup);
|
| + var creates = _collect(spannable, metadata, compiler,
|
| + enqueuer.annotationCreatesClass, lookupType);
|
| + var returns = _collect(spannable, metadata, compiler,
|
| + enqueuer.annotationReturnsClass, lookupType);
|
|
|
| if (creates != null) {
|
| typesInstantiated
|
| @@ -778,14 +889,12 @@ class NativeBehavior {
|
| * [annotationClass].
|
| * Returns `null` if no constraints.
|
| */
|
| - static _collect(Element element, Compiler compiler, Element annotationClass,
|
| - lookup(str)) {
|
| + static _collect(Spannable spannable, Iterable<ConstantExpression> metadata,
|
| + Compiler compiler, Element annotationClass, TypeLookup lookupType) {
|
| DiagnosticReporter reporter = compiler.reporter;
|
| var types = null;
|
| - for (MetadataAnnotation annotation in element.implementation.metadata) {
|
| - annotation.ensureResolved(compiler.resolution);
|
| - ConstantValue value =
|
| - compiler.constants.getConstantValue(annotation.constant);
|
| + for (ConstantExpression constant in metadata) {
|
| + ConstantValue value = compiler.constants.getConstantValue(constant);
|
| if (!value.isConstructedObject) continue;
|
| ConstructedConstantValue constructedObject = value;
|
| if (constructedObject.type.element != annotationClass) continue;
|
| @@ -793,14 +902,13 @@ class NativeBehavior {
|
| Iterable<ConstantValue> fields = constructedObject.fields.values;
|
| // TODO(sra): Better validation of the constant.
|
| if (fields.length != 1 || !fields.single.isString) {
|
| - reporter.internalError(
|
| - annotation, 'Annotations needs one string: ${annotation.node}');
|
| + reporter.internalError(spannable,
|
| + 'Annotations needs one string: ${constant.toStructuredText()}');
|
| }
|
| StringConstantValue specStringConstant = fields.single;
|
| String specString = specStringConstant.toDartString().slowToString();
|
| for (final typeString in specString.split('|')) {
|
| - var type =
|
| - _parseType(typeString, compiler.parsingContext, lookup, annotation);
|
| + var type = _parseType(typeString, spannable, reporter, lookupType);
|
| if (types == null) types = [];
|
| types.add(type);
|
| }
|
| @@ -874,34 +982,28 @@ class NativeBehavior {
|
| }
|
| }
|
|
|
| - static dynamic _parseType(String typeString, ParsingContext parsing,
|
| - lookup(name), locationNodeOrElement) {
|
| - DiagnosticReporter reporter = parsing.reporter;
|
| + static dynamic /*DartType|SpecialType*/ _parseType(String typeString,
|
| + Spannable spannable, DiagnosticReporter reporter, TypeLookup lookupType) {
|
| if (typeString == '=Object') return SpecialType.JsObject;
|
| if (typeString == 'dynamic') {
|
| return const DynamicType();
|
| }
|
| - var type = lookup(typeString);
|
| + var type = lookupType(typeString);
|
| if (type != null) return type;
|
|
|
| int index = typeString.indexOf('<');
|
| if (index < 1) {
|
| - reporter.reportErrorMessage(_errorNode(locationNodeOrElement, parsing),
|
| - MessageKind.GENERIC, {'text': "Type '$typeString' not found."});
|
| + reporter.reportErrorMessage(spannable, MessageKind.GENERIC,
|
| + {'text': "Type '$typeString' not found."});
|
| return const DynamicType();
|
| }
|
| - type = lookup(typeString.substring(0, index));
|
| + type = lookupType(typeString.substring(0, index));
|
| if (type != null) {
|
| // TODO(sra): Parse type parameters.
|
| return type;
|
| }
|
| - reporter.reportErrorMessage(_errorNode(locationNodeOrElement, parsing),
|
| - MessageKind.GENERIC, {'text': "Type '$typeString' not found."});
|
| + reporter.reportErrorMessage(spannable, MessageKind.GENERIC,
|
| + {'text': "Type '$typeString' not found."});
|
| return const DynamicType();
|
| }
|
| -
|
| - static _errorNode(locationNodeOrElement, ParsingContext parsing) {
|
| - if (locationNodeOrElement is Node) return locationNodeOrElement;
|
| - return locationNodeOrElement.parseNode(parsing);
|
| - }
|
| }
|
|
|