| Index: pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
|
| diff --git a/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart b/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
|
| index e14a90b27be0b4eec4b6507cbf03ce9d39c82c0e..6502d42f02335e5a4f50d6d9be84dc6f5000b5f8 100644
|
| --- a/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
|
| +++ b/pkg/compiler/lib/src/js_backend/no_such_method_registry.dart
|
| @@ -4,10 +4,11 @@
|
|
|
| import '../common.dart';
|
| import '../common/names.dart' show Identifiers, Names, Selectors;
|
| -import '../compiler.dart' show Compiler;
|
| +import '../common_elements.dart';
|
| import '../elements/elements.dart';
|
| +import '../types/types.dart';
|
| import '../tree/tree.dart';
|
| -import 'backend.dart';
|
| +import 'backend_helpers.dart';
|
|
|
| /**
|
| * Categorizes `noSuchMethod` implementations.
|
| @@ -68,14 +69,10 @@ class NoSuchMethodRegistry {
|
| /// The implementations that have not yet been categorized.
|
| final Set<MethodElement> _uncategorizedImpls = new Set<MethodElement>();
|
|
|
| - final JavaScriptBackend _backend;
|
| - final Compiler _compiler;
|
| + final BackendHelpers _helpers;
|
| + final NoSuchMethodResolver _resolver;
|
|
|
| - NoSuchMethodRegistry(JavaScriptBackend backend)
|
| - : this._backend = backend,
|
| - this._compiler = backend.compiler;
|
| -
|
| - DiagnosticReporter get reporter => _compiler.reporter;
|
| + NoSuchMethodRegistry(this._helpers, this._resolver);
|
|
|
| bool get hasThrowingNoSuchMethod => throwingImpls.isNotEmpty;
|
| bool get hasComplexNoSuchMethod => otherImpls.isNotEmpty;
|
| @@ -92,24 +89,30 @@ class NoSuchMethodRegistry {
|
| /// Now that type inference is complete, split category D into two
|
| /// subcategories: D1, those that have no return type, and D2, those
|
| /// that have a return type.
|
| - void onTypeInferenceComplete() {
|
| - otherImpls.forEach(_subcategorizeOther);
|
| + void onTypeInferenceComplete(GlobalTypeInferenceResults results) {
|
| + otherImpls.forEach((MethodElement element) {
|
| + if (results.resultOf(element).throwsAlways) {
|
| + complexNoReturnImpls.add(element);
|
| + } else {
|
| + complexReturningImpls.add(element);
|
| + }
|
| + });
|
| }
|
|
|
| /// Emits a diagnostic
|
| - void emitDiagnostic() {
|
| + void emitDiagnostic(DiagnosticReporter reporter) {
|
| throwingImpls.forEach((e) {
|
| - if (!_hasForwardingSyntax(e)) {
|
| + if (!_resolver.hasForwardingSyntax(e)) {
|
| reporter.reportHintMessage(e, MessageKind.DIRECTLY_THROWING_NSM);
|
| }
|
| });
|
| complexNoReturnImpls.forEach((e) {
|
| - if (!_hasForwardingSyntax(e)) {
|
| + if (!_resolver.hasForwardingSyntax(e)) {
|
| reporter.reportHintMessage(e, MessageKind.COMPLEX_THROWING_NSM);
|
| }
|
| });
|
| complexReturningImpls.forEach((e) {
|
| - if (!_hasForwardingSyntax(e)) {
|
| + if (!_resolver.hasForwardingSyntax(e)) {
|
| reporter.reportHintMessage(e, MessageKind.COMPLEX_RETURNING_NSM);
|
| }
|
| });
|
| @@ -123,14 +126,6 @@ class NoSuchMethodRegistry {
|
| return otherImpls.contains(element);
|
| }
|
|
|
| - _subcategorizeOther(MethodElement element) {
|
| - if (_compiler.globalInference.results.resultOf(element).throwsAlways) {
|
| - complexNoReturnImpls.add(element);
|
| - } else {
|
| - complexReturningImpls.add(element);
|
| - }
|
| - }
|
| -
|
| NsmCategory _categorizeImpl(MethodElement element) {
|
| assert(element.name == Identifiers.noSuchMethod_);
|
| if (defaultImpls.contains(element)) {
|
| @@ -149,10 +144,10 @@ class NoSuchMethodRegistry {
|
| notApplicableImpls.add(element);
|
| return NsmCategory.NOT_APPLICABLE;
|
| }
|
| - if (isDefaultNoSuchMethodImplementation(element)) {
|
| + if (_helpers.isDefaultNoSuchMethodImplementation(element)) {
|
| defaultImpls.add(element);
|
| return NsmCategory.DEFAULT;
|
| - } else if (_hasForwardingSyntax(element)) {
|
| + } else if (_resolver.hasForwardingSyntax(element)) {
|
| // If the implementation is 'noSuchMethod(x) => super.noSuchMethod(x);'
|
| // then it is in the same category as the super call.
|
| Element superCall =
|
| @@ -176,7 +171,7 @@ class NoSuchMethodRegistry {
|
| break;
|
| }
|
| return category;
|
| - } else if (_hasThrowingSyntax(element)) {
|
| + } else if (_resolver.hasThrowingSyntax(element)) {
|
| throwingImpls.add(element);
|
| return NsmCategory.THROWING;
|
| } else {
|
| @@ -184,15 +179,33 @@ class NoSuchMethodRegistry {
|
| return NsmCategory.OTHER;
|
| }
|
| }
|
| +}
|
|
|
| - bool isDefaultNoSuchMethodImplementation(MethodElement element) {
|
| - ClassElement classElement = element.enclosingClass;
|
| - return classElement == _compiler.commonElements.objectClass ||
|
| - classElement == _backend.helpers.jsInterceptorClass ||
|
| - classElement == _backend.helpers.jsNullClass;
|
| - }
|
| +enum NsmCategory {
|
| + DEFAULT,
|
| + THROWING,
|
| + NOT_APPLICABLE,
|
| + OTHER,
|
| +}
|
| +
|
| +/// Interface for determining the form of a `noSuchMethod` implementation.
|
| +abstract class NoSuchMethodResolver {
|
| + /// Computes whether [method] is of the form
|
| + ///
|
| + /// noSuchMethod(i) => super.noSuchMethod(i);
|
| + ///
|
| + bool hasForwardingSyntax(MethodElement method);
|
|
|
| - bool _hasForwardingSyntax(MethodElement element) {
|
| + /// Computes whether [method] is of the form
|
| + ///
|
| + /// noSuchMethod(i) => throw new Error();
|
| + ///
|
| + bool hasThrowingSyntax(MethodElement method);
|
| +}
|
| +
|
| +/// AST-based implementation of [NoSuchMethodResolver].
|
| +class NoSuchMethodResolverImpl implements NoSuchMethodResolver {
|
| + bool hasForwardingSyntax(MethodElement element) {
|
| // At this point we know that this is signature-compatible with
|
| // Object.noSuchMethod, but it may have more than one argument as long as
|
| // it only has one required argument.
|
| @@ -242,7 +255,7 @@ class NoSuchMethodRegistry {
|
| return false;
|
| }
|
|
|
| - bool _hasThrowingSyntax(MethodElement element) {
|
| + bool hasThrowingSyntax(MethodElement element) {
|
| if (!element.hasResolvedAst) {
|
| // TODO(johnniwinther): Why do we see unresolved elements here?
|
| return false;
|
| @@ -267,10 +280,3 @@ class NoSuchMethodRegistry {
|
| return false;
|
| }
|
| }
|
| -
|
| -enum NsmCategory {
|
| - DEFAULT,
|
| - THROWING,
|
| - NOT_APPLICABLE,
|
| - OTHER,
|
| -}
|
|
|