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

Unified Diff: pkg/compiler/lib/src/resolution/members.dart

Issue 1232613003: Refactoring handle type literals. (Closed) Base URL: https://github.com/dart-lang/sdk.git@master
Patch Set: Created 5 years, 5 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 | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/resolution/members.dart
diff --git a/pkg/compiler/lib/src/resolution/members.dart b/pkg/compiler/lib/src/resolution/members.dart
index cf1f65ce2b2ce0dd4beeb6f7adb01f52c40deffa..96961f3d213ceb3e8fb10c8b5a040cf6468dc1dc 100644
--- a/pkg/compiler/lib/src/resolution/members.dart
+++ b/pkg/compiler/lib/src/resolution/members.dart
@@ -1775,6 +1775,145 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
}
}
+ /// Handle access to a type literal of type variable [element]. Like `T` or
+ /// `T()` where 'T' is type variable.
+ // TODO(johnniwinther): Remove [name] when [Selector] is not required for the
+ // the [GetStructure].
+ // TODO(johnniwinther): Remove [element] when it is no longer needed for
+ // evaluating constants.
+ ResolutionResult handleTypeVariableTypeLiteralAccess(
+ Send node,
+ Name name,
+ TypeVariableElement element) {
+ if (!Elements.hasAccessToTypeVariables(enclosingElement)) {
+ compiler.reportError(node,
+ MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
+ {'typeVariableName': node.selector});
+ // TODO(johnniwinther): Add another access semantics for this.
+ }
+ registry.registerClassUsingVariableExpression(element.enclosingClass);
+ registry.registerTypeVariableExpression();
+
+ AccessSemantics semantics =
+ new StaticAccess.typeParameterTypeLiteral(element);
+ registry.useElement(node, element);
+ registry.registerTypeLiteral(node, element.type);
+
+ if (node.isCall) {
+ CallStructure callStructure =
+ resolveArguments(node.argumentsNode).callStructure;
+ Selector selector = callStructure.callSelector;
+ // TODO(johnniwinther): Remove this when all information goes through
+ // the [SendStructure].
+ registry.setSelector(node, selector);
+
+ registry.registerSendStructure(node,
+ new InvokeStructure(semantics, selector));
+ } else {
+ // TODO(johnniwinther): Avoid the need for a [Selector] here.
+ registry.registerSendStructure(node,
+ new GetStructure(semantics,
+ new Selector(SelectorKind.GETTER, name, CallStructure.NO_ARGS)));
+ }
+ return const NoneResult();
+ }
+
+ /// Handle access to a constant type literal of [type].
+ // TODO(johnniwinther): Remove [name] when [Selector] is not required for the
+ // the [GetStructure].
+ // TODO(johnniwinther): Remove [element] when it is no longer needed for
+ // evaluating constants.
+ ResolutionResult handleConstantTypeLiteralAccess(
+ Send node,
+ Name name,
+ TypeDeclarationElement element,
+ DartType type,
+ ConstantAccess semantics) {
+ registry.useElement(node, element);
+ registry.registerTypeLiteral(node, type);
+
+ if (node.isCall) {
+ CallStructure callStructure =
+ resolveArguments(node.argumentsNode).callStructure;
+ Selector selector = callStructure.callSelector;
+ // TODO(johnniwinther): Remove this when all information goes through
+ // the [SendStructure].
+ registry.setSelector(node, selector);
+
+ // The node itself is not a constant but we register the selector (the
+ // identifier that refers to the class/typedef) as a constant.
+ registry.useElement(node.selector, element);
+ analyzeConstantDeferred(node.selector, enforceConst: false);
+
+ registry.registerSendStructure(node,
+ new InvokeStructure(semantics, selector));
+ return const NoneResult();
+ } else {
+ analyzeConstantDeferred(node, enforceConst: false);
+
+ // TODO(johnniwinther): Avoid the need for a [Selector] here.
+ registry.registerSendStructure(node,
+ new GetStructure(semantics,
+ new Selector(SelectorKind.GETTER, name, CallStructure.NO_ARGS)));
+ return new ConstantResult(node, semantics.constant);
+ }
+ }
+
+ /// Handle access to a type literal of a typedef. Like `F` or
+ /// `F()` where 'F' is typedef.
+ ResolutionResult handleTypedefTypeLiteralAccess(
+ Send node,
+ Name name,
+ TypedefElement typdef) {
+ typdef.ensureResolved(compiler);
+ DartType type = typdef.rawType;
+ ConstantExpression constant = new TypeConstantExpression(type);
+ AccessSemantics semantics = new ConstantAccess.typedefTypeLiteral(constant);
+ return handleConstantTypeLiteralAccess(node, name, typdef, type, semantics);
+ }
+
+ /// Handle access to a type literal of the type 'dynamic'. Like `dynamic` or
+ /// `dynamic()`.
+ ResolutionResult handleDynamicTypeLiteralAccess(Send node) {
+ DartType type = const DynamicType();
+ ConstantExpression constant = new TypeConstantExpression(
+ // TODO(johnniwinther): Use [type] when evaluation of constants is done
+ // directly on the constant expressions.
+ node.isCall ? coreTypes.typeType : type);
+ AccessSemantics semantics = new ConstantAccess.dynamicTypeLiteral(constant);
+ return handleConstantTypeLiteralAccess(
+ node, const PublicName('dynamic'), compiler.typeClass, type, semantics);
+ }
+
+ /// Handle access to a type literal of a class. Like `C` or
+ /// `C()` where 'C' is class.
+ ResolutionResult handleClassTypeLiteralAccess(
+ Send node,
+ Name name,
+ ClassElement cls) {
+ DartType type = cls.rawType;
+ ConstantExpression constant = new TypeConstantExpression(type);
+ AccessSemantics semantics = new ConstantAccess.classTypeLiteral(constant);
+ return handleConstantTypeLiteralAccess(node, name, cls, type, semantics);
+ }
+
+ /// Handle a [Send] that resolves to a [prefix]. Like `prefix` in
+ /// `prefix.Class` or `prefix` in `prefix()`, the latter being a compile time
+ /// error.
+ ResolutionResult handleClassSend(
+ Send node,
+ Name name,
+ ClassElement cls) {
+ cls.ensureResolved(compiler);
+ if (sendIsMemberAccess) {
+ registry.useElement(node, cls);
+ return new ElementResult(cls);
+ } else {
+ // `C` or `C()` where 'C' is a class.
+ return handleClassTypeLiteralAccess(node, name, cls);
+ }
+ }
+
/// Handle qualified [Send] where the receiver resolves to a [prefix],
/// like `prefix.toplevelFunction()` or `prefix.Class.staticField` where
/// `prefix` is a library prefix.
@@ -1816,7 +1955,6 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
return new ElementResult(prefix);
}
-
/// Handle qualified [Send] where the receiver resolves to an [Element], like
/// `a.b` where `a` is a local, field, class, or prefix, etc.
ResolutionResult handleResolvedQualifiedSend(
@@ -1826,7 +1964,8 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
} else if (element.isClass) {
return handleStaticMemberAccess(node, name, element);
}
- return oldVisitSend(node);
+ // TODO(johnniwinther): Use the [element].
+ return handleDynamicPropertyAccess(node, name);
}
/// Handle dynamic access of [semantics].
@@ -2100,6 +2239,15 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
// of parse errors to make [element] erroneous. Fix this!
member.computeType(compiler);
+
+ if (member == compiler.mirrorSystemGetNameFunction &&
+ !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) {
+ compiler.reportHint(
+ node.selector, MessageKind.STATIC_FUNCTION_BLOAT,
+ {'class': compiler.mirrorSystemClass.name,
+ 'name': compiler.mirrorSystemGetNameFunction.name});
+ }
+
Selector selector;
AccessSemantics semantics =
computeStaticOrTopLevelAccessSemantics(node, member);
@@ -2232,10 +2380,14 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
return handleStaticInstanceSend(node, name, element);
}
}
- if (element.isClass || element.isTypedef) {
- return oldVisitSend(node);
+ if (element.isClass) {
+ // `C`, `C()`, or 'C.b` where 'C' is a class.
+ return handleClassSend(node, name, element);
+ } else if (element.isTypedef) {
+ // `F` or `F()` where 'F' is a typedef.
+ return handleTypedefTypeLiteralAccess(node, name, element);
} else if (element.isTypeVariable) {
- return oldVisitSend(node);
+ return handleTypeVariableTypeLiteralAccess(node, name, element);
} else if (element.isPrefix) {
return handleLibraryPrefix(node, name, element);
} else if (element.isLocal) {
@@ -2261,16 +2413,16 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
} else if (text == 'this') {
// `this()`.
return handleThisAccess(node);
- } else if (text == 'dynamic') {
- // `dynamic` || `dynamic()`.
- // TODO(johnniwinther): Handle dynamic type literal access.
- return oldVisitSend(node);
}
// `name` or `name()`
Name name = new Name(text, enclosingElement.library);
Element element = lookupInScope(compiler, node, scope, text);
if (element == null) {
- if (inInstanceContext) {
+ if (text == 'dynamic') {
+ // `dynamic` or `dynamic()` where 'dynamic' is not declared in the
+ // current scope.
+ return handleDynamicTypeLiteralAccess(node);
+ } else if (inInstanceContext) {
// Implicitly `this.name`.
return handleThisPropertyAccess(node, name);
} else {
@@ -2307,101 +2459,6 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
}
}
- ResolutionResult oldVisitSend(Send node) {
- bool oldSendIsMemberAccess = sendIsMemberAccess;
- sendIsMemberAccess = node.isPropertyAccess || node.isCall;
-
- ResolutionResult result = resolveSend(node);
- sendIsMemberAccess = oldSendIsMemberAccess;
-
- Element target = result.element;
-
- if (target != null
- && target == compiler.mirrorSystemGetNameFunction
- && !compiler.mirrorUsageAnalyzerTask.hasMirrorUsage(enclosingElement)) {
- compiler.reportHint(
- node.selector, MessageKind.STATIC_FUNCTION_BLOAT,
- {'class': compiler.mirrorSystemClass.name,
- 'name': compiler.mirrorSystemGetNameFunction.name});
- }
-
- if (target != null) {
- if (target.isErroneous) {
- registry.registerThrowNoSuchMethod();
- } else if (target.isAbstractField) {
- AbstractFieldElement field = target;
- target = field.getter;
- if (target == null) {
- if (!inInstanceContext || field.isTopLevel || field.isStatic) {
- registry.registerThrowNoSuchMethod();
- target = reportAndCreateErroneousElement(node.selector, field.name,
- MessageKind.CANNOT_RESOLVE_GETTER, const {});
- }
- }
- } else if (target.isTypeVariable) {
- ClassElement cls = target.enclosingClass;
- assert(enclosingElement.enclosingClass == cls);
- if (!Elements.hasAccessToTypeVariables(enclosingElement)) {
- compiler.reportError(node,
- MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER,
- {'typeVariableName': node.selector});
- }
- registry.registerClassUsingVariableExpression(cls);
- registry.registerTypeVariableExpression();
- registerTypeLiteralAccess(node, target);
- } else if (target.impliesType && (!sendIsMemberAccess || node.isCall)) {
- registerTypeLiteralAccess(node, target);
- }
- registerPotentialAccessInClosure(node, target);
- }
-
- resolveArguments(node.argumentsNode);
-
- // If the selector is null, it means that we will not be generating
- // code for this as a send.
- Selector selector = registry.getSelector(node);
- if (selector == null) return const NoneResult();
-
- if (node.isCall) {
- if (Elements.isUnresolved(target) ||
- target.isGetter ||
- target.isField ||
- Elements.isClosureSend(node, target)) {
- // If we don't know what we're calling or if we are calling a getter,
- // we need to register that fact that we may be calling a closure
- // with the same arguments.
- Selector call = new Selector.callClosureFrom(selector);
- registry.registerDynamicInvocation(
- new UniverseSelector(selector, null));
- } else if (target.impliesType) {
- // We call 'call()' on a Type instance returned from the reference to a
- // class or typedef literal. We do not need to register this call as a
- // dynamic invocation, because we statically know what the target is.
- } else {
- if (target is FunctionElement) {
- FunctionElement function = target;
- function.computeType(compiler);
- }
- if (!selector.applies(target, compiler.world)) {
- registry.registerThrowNoSuchMethod();
- if (node.isSuperCall) {
- internalError(node, "Unexpected super call $node");
- }
- }
- }
-
- handleForeignCall(node, target, selector);
- }
-
- registry.useElement(node, target);
- registerSend(selector, target);
- if (node.isPropertyAccess && Elements.isStaticOrTopLevelFunction(target)) {
- registry.registerGetOfStaticFunction(target.declaration);
- }
- return node.isPropertyAccess
- ? new ResolutionResult.forElement(target) : const NoneResult();
- }
-
// TODO(johnniwinther): Move this to the backend resolution callbacks.
void handleForeignCall(Send node, Element target, Selector selector) {
if (target != null && compiler.backend.isForeign(target)) {
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698