Refactoring resolution of local access and unqualified access of statics

BUG=
R=karlklose@google.com

Review URL: https://codereview.chromium.org//1149403009
This commit is contained in:
Johnni Winther 2015-06-08 11:53:59 +02:00
parent 6cc3bd1124
commit 58896b74ce
11 changed files with 496 additions and 83 deletions

View file

@ -546,7 +546,8 @@ abstract class Enqueuer {
*/
void registerStaticUse(Element element) {
if (element == null) return;
assert(invariant(element, element.isDeclaration));
assert(invariant(element, element.isDeclaration,
message: "Element ${element} is not the declaration."));
if (Elements.isStaticOrTopLevel(element) && element.isField) {
universe.registerStaticFieldUse(element);
}

View file

@ -53,6 +53,12 @@ void _trace(String message, {bool condition(String stackTrace), int limit,
}
}
/// Creates a function to use as an `condition` argument in [trace] that filters
/// stack traces that contains any of the [exceptions].
traceExceptions(List<String> exceptions) {
return (String stackTrace) => !exceptions.any(stackTrace.contains);
}
/// Function signature of [traceAndReport].
typedef void TraceAndReport(Compiler compiler, Spannable node, String message,
{bool condition(String stackTrace), int limit,

View file

@ -1695,6 +1695,26 @@ class SimpleTypeInferrerVisitor<T>
return handleStaticFieldOrGetterInvoke(node, getter);
}
@override
T visitStaticSetterInvoke(
ast.Send node,
MethodElement setter,
ast.NodeList arguments,
CallStructure callStructure,
_) {
return handleInvalidStaticInvoke(node);
}
@override
T visitTopLevelSetterInvoke(
ast.Send node,
MethodElement setter,
ast.NodeList arguments,
CallStructure callStructure,
_) {
return handleInvalidStaticInvoke(node);
}
@override
T visitUnresolvedInvoke(
ast.Send node,
@ -1870,6 +1890,22 @@ class SimpleTypeInferrerVisitor<T>
return handleStaticGetterGet(node, getter);
}
@override
T visitStaticSetterGet(
ast.Send node,
MethodElement setter,
_) {
return types.dynamicType;
}
@override
T visitTopLevelSetterGet(
ast.Send node,
MethodElement setter,
_) {
return types.dynamicType;
}
@override
T visitUnresolvedGet(
ast.Send node,

View file

@ -804,7 +804,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
}
/// Compute the [AccessSemantics] corresponding to a super access of [target].
AccessSemantics computeSuperAccess(Spannable node, Element target) {
AccessSemantics computeSuperAccessSemantics(Spannable node, Element target) {
if (target.isErroneous) {
return new StaticAccess.unresolvedSuper(target);
} else if (target.isGetter) {
@ -812,7 +812,11 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
} else if (target.isSetter) {
return new StaticAccess.superSetter(target);
} else if (target.isField) {
return new StaticAccess.superField(target);
if (target.isFinal) {
return new StaticAccess.superFinalField(target);
} else {
return new StaticAccess.superField(target);
}
} else {
assert(invariant(node, target.isFunction,
message: "Unexpected super target '$target'."));
@ -820,6 +824,78 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
}
}
/// Compute the [AccessSemantics] corresponding to a local access of [target].
AccessSemantics computeLocalAccessSemantics(Spannable node,
LocalElement target) {
if (target.isParameter) {
if (target.isFinal || target.isConst) {
return new StaticAccess.finalParameter(target);
} else {
return new StaticAccess.parameter(target);
}
} else if (target.isVariable) {
if (target.isFinal || target.isConst) {
return new StaticAccess.finalLocalVariable(target);
} else {
return new StaticAccess.localVariable(target);
}
} else {
assert(invariant(node, target.isFunction,
message: "Unexpected local target '$target'."));
return new StaticAccess.localFunction(target);
}
}
/// Compute the [AccessSemantics] corresponding to a static or toplevel access
/// of [target].
AccessSemantics computeStaticOrTopLevelAccessSemantics(
Spannable node,
Element target) {
target = target.declaration;
if (target.isErroneous) {
// This handles elements with parser errors.
// TODO(johnniwinther): Elements with parse error should not set
// [isErroneous] to `true`.
return new StaticAccess.unresolved(target);
}
if (target.isStatic) {
if (target.isGetter) {
return new StaticAccess.staticGetter(target);
} else if (target.isSetter) {
return new StaticAccess.staticSetter(target);
} else if (target.isField) {
if (target.isFinal || target.isConst) {
return new StaticAccess.finalStaticField(target);
} else {
return new StaticAccess.staticField(target);
}
} else {
assert(invariant(node, target.isFunction,
message: "Unexpected static target '$target'."));
return new StaticAccess.staticMethod(target);
}
} else {
assert(invariant(node, target.isTopLevel,
message: "Unexpected statically resolved target '$target'."));
if (target.isGetter) {
return new StaticAccess.topLevelGetter(target);
} else if (target.isSetter) {
return new StaticAccess.topLevelSetter(target);
} else if (target.isField) {
if (target.isFinal) {
return new StaticAccess.finalTopLevelField(target);
} else {
return new StaticAccess.topLevelField(target);
}
} else {
assert(invariant(node, target.isFunction,
message: "Unexpected top level target '$target'."));
return new StaticAccess.topLevelMethod(target);
}
}
}
/// Compute the [AccessSemantics] for accessing the name of [selector] on the
/// super class.
///
@ -836,9 +912,11 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
/// foo => super.name; // Access to the setter.
/// }
///
AccessSemantics computeSuperSemantics(Spannable node,
Selector selector,
{Name alternateName}) {
AccessSemantics computeSuperAccessSemanticsForSelector(
Spannable node,
Selector selector,
{Name alternateName}) {
Name name = selector.memberName;
// TODO(johnniwinther): Ensure correct behavior if currentClass is a
// patch.
@ -860,7 +938,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
registry.registerDynamicInvocation(selector);
registry.registerSuperNoSuchMethod();
}
return computeSuperAccess(node, target);
return computeSuperAccessSemantics(node, target);
}
/// Resolve [node] as subexpression that is _not_ the prefix of a member
@ -938,7 +1016,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
AccessSemantics semantics;
if (node.isSuperCall) {
if (checkSuperAccess(node)) {
semantics = computeSuperSemantics(node, selector);
semantics = computeSuperAccessSemanticsForSelector(node, selector);
// TODO(johnniwinther): Add information to [AccessSemantics] about
// whether it is erroneous.
if (semantics.kind == AccessKind.SUPER_METHOD) {
@ -1037,7 +1115,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
if (node.isSuperCall) {
if (checkSuperAccess(node)) {
semantics = computeSuperSemantics(node, selector);
semantics = computeSuperAccessSemanticsForSelector(node, selector);
// TODO(johnniwinther): Add information to [AccessSemantics] about
// whether it is erroneous.
if (semantics.kind == AccessKind.SUPER_METHOD) {
@ -1201,7 +1279,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
selector = new Selector(SelectorKind.GETTER, name, callStructure);
}
if (checkSuperAccess(node)) {
AccessSemantics semantics = computeSuperSemantics(
AccessSemantics semantics = computeSuperAccessSemanticsForSelector(
node, selector, alternateName: name.setter);
if (node.isCall) {
bool isIncompatibleInvoke = false;
@ -1219,6 +1297,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
}
break;
case AccessKind.SUPER_FIELD:
case AccessKind.SUPER_FINAL_FIELD:
case AccessKind.SUPER_GETTER:
registry.registerStaticUse(semantics.element);
selector = callStructure.callSelector;
@ -1244,6 +1323,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
registry.registerStaticUse(semantics.element);
break;
case AccessKind.SUPER_FIELD:
case AccessKind.SUPER_FINAL_FIELD:
case AccessKind.SUPER_GETTER:
registry.registerStaticUse(semantics.element);
break;
@ -1353,6 +1433,12 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
// TODO(johnniwinther): Support unresolved top level access as an
// [AccessSemantics].
AccessSemantics accessSemantics = new StaticAccess.unresolved(element);
return handleErroneousAccess(node, name, element, accessSemantics);
}
/// Handle erroneous access of [element] of the given [accessSemantics].
ResolutionResult handleErroneousAccess(
Send node, Name name, Element element, AccessSemantics accessSemantics) {
SendStructure sendStructure;
Selector selector;
if (node.isCall) {
@ -1375,6 +1461,242 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
return null;
}
/// Handle access to an ambiguous element, that is, a name imported twice.
ResolutionResult handleAmbiguousSend(
Send node,
Name name,
AmbiguousElement element) {
compiler.reportError(
node, element.messageKind, element.messageArguments);
element.diagnose(enclosingElement, compiler);
ErroneousElement error = new ErroneousElementX(
element.messageKind,
element.messageArguments,
name.text,
enclosingElement);
// TODO(johnniwinther): Support ambiguous access as an [AccessSemantics].
AccessSemantics accessSemantics = new StaticAccess.unresolved(error);
return handleErroneousAccess(node, name, error, accessSemantics);
}
/// Handle access of an instance [member] from a non-instance context.
ResolutionResult handleStaticInstanceSend(
Send node, Name name, MemberElement member) {
compiler.reportError(
node, MessageKind.NO_INSTANCE_AVAILABLE, {'name': member.name});
ErroneousElement error = new ErroneousElementX(
MessageKind.NO_INSTANCE_AVAILABLE,
{'name': name},
name.text,
enclosingElement);
// TODO(johnniwinther): Support static instance access as an
// [AccessSemantics].
AccessSemantics accessSemantics = new StaticAccess.unresolved(error);
return handleErroneousAccess(node, name, error, accessSemantics);
}
/// Handle access of a parameter, local variable or local function.
ResolutionResult handleLocalAccess(Send node, Name name, Element element) {
AccessSemantics semantics = computeLocalAccessSemantics(node, element);
Selector selector;
CallStructure callStructure = CallStructure.NO_ARGS;
if (node.isCall) {
callStructure = resolveArguments(node.argumentsNode);
selector = new Selector(SelectorKind.CALL, name, callStructure);
} else {
selector = new Selector(SelectorKind.GETTER, name, callStructure);
}
if (node.isCall) {
bool isIncompatibleInvoke = false;
switch (semantics.kind) {
case AccessKind.LOCAL_FUNCTION:
LocalFunctionElementX function = semantics.element;
function.computeSignature(compiler);
if (!callStructure.signatureApplies(function)) {
registry.registerThrowNoSuchMethod();
registry.registerDynamicInvocation(selector);
isIncompatibleInvoke = true;
}
break;
case AccessKind.PARAMETER:
case AccessKind.FINAL_PARAMETER:
case AccessKind.LOCAL_VARIABLE:
case AccessKind.FINAL_LOCAL_VARIABLE:
selector = callStructure.callSelector;
registry.registerDynamicInvocation(selector);
break;
default:
internalError(node,
"Unexpected local access $semantics.");
break;
}
registry.registerSendStructure(node,
isIncompatibleInvoke
? new IncompatibleInvokeStructure(semantics, selector)
: new InvokeStructure(semantics, selector));
} else {
registry.registerSendStructure(node,
new GetStructure(semantics, selector));
}
// TODO(johnniwinther): Remove these when all information goes through
// the [SendStructure].
registry.useElement(node, element);
registry.setSelector(node, selector);
registerPotentialAccessInClosure(node, element);
return node.isPropertyAccess ? new ElementResult(element) : null;
}
/// Handle access of a static or top level [element].
ResolutionResult handleStaticOrTopLevelAccess(
Send node, Name name, Element element) {
if (element.isAbstractField) {
AbstractFieldElement abstractField = element;
if (abstractField.getter != null) {
element = abstractField.getter;
} else {
element = abstractField.setter;
}
}
Selector selector;
CallStructure callStructure = CallStructure.NO_ARGS;
if (node.isCall) {
callStructure = resolveArguments(node.argumentsNode);
selector = new Selector(SelectorKind.CALL, name, callStructure);
} else {
selector = new Selector(SelectorKind.GETTER, name, callStructure);
}
AccessSemantics semantics =
computeStaticOrTopLevelAccessSemantics(node, element);
if (node.isCall) {
bool isIncompatibleInvoke = false;
switch (semantics.kind) {
case AccessKind.STATIC_METHOD:
case AccessKind.TOPLEVEL_METHOD:
MethodElementX method = semantics.element;
method.computeSignature(compiler);
if (!callStructure.signatureApplies(method)) {
registry.registerThrowNoSuchMethod();
registry.registerDynamicInvocation(selector);
isIncompatibleInvoke = true;
} else {
registry.registerStaticUse(semantics.element);
handleForeignCall(node, semantics.element, selector);
}
break;
case AccessKind.STATIC_FIELD:
case AccessKind.FINAL_STATIC_FIELD:
case AccessKind.STATIC_GETTER:
case AccessKind.TOPLEVEL_FIELD:
case AccessKind.FINAL_TOPLEVEL_FIELD:
case AccessKind.TOPLEVEL_GETTER:
registry.registerStaticUse(semantics.element);
selector = callStructure.callSelector;
registry.registerDynamicInvocation(selector);
break;
case AccessKind.STATIC_SETTER:
case AccessKind.TOPLEVEL_SETTER:
case AccessKind.UNRESOLVED:
registry.registerThrowNoSuchMethod();
element = reportAndCreateErroneousElement(
node.selector, name.text,
MessageKind.CANNOT_RESOLVE_GETTER, const {});
break;
default:
internalError(node,
"Unexpected statically resolved access $semantics.");
break;
}
registry.registerSendStructure(node,
isIncompatibleInvoke
? new IncompatibleInvokeStructure(semantics, selector)
: new InvokeStructure(semantics, selector));
} else {
switch (semantics.kind) {
case AccessKind.STATIC_METHOD:
case AccessKind.TOPLEVEL_METHOD:
// TODO(johnniwinther): Method this should be registered as a
// closurization.
registry.registerStaticUse(semantics.element);
registry.registerGetOfStaticFunction(semantics.element);
break;
case AccessKind.STATIC_FIELD:
case AccessKind.FINAL_STATIC_FIELD:
case AccessKind.STATIC_GETTER:
case AccessKind.TOPLEVEL_FIELD:
case AccessKind.FINAL_TOPLEVEL_FIELD:
case AccessKind.TOPLEVEL_GETTER:
registry.registerStaticUse(semantics.element);
break;
case AccessKind.STATIC_SETTER:
case AccessKind.TOPLEVEL_SETTER:
case AccessKind.UNRESOLVED:
registry.registerThrowNoSuchMethod();
element = reportAndCreateErroneousElement(
node.selector, name.text,
MessageKind.CANNOT_RESOLVE_GETTER, const {});
break;
default:
internalError(node,
"Unexpected statically resolved access $semantics.");
break;
}
registry.registerSendStructure(node,
new GetStructure(semantics, selector));
}
// TODO(johnniwinther): Remove these when all information goes through
// the [SendStructure].
registry.useElement(node, element);
registry.setSelector(node, selector);
return node.isPropertyAccess ? new ElementResult(element) : null;
}
/// Handle access to resolved [element].
ResolutionResult handleResolvedSend(Send node, Name name, Element element) {
if (element.isAmbiguous) {
return handleAmbiguousSend(node, name, element);
}
if (element.isErroneous) {
// This handles elements with parser errors.
// TODO(johnniwinther): Elements with parse error should not set
// [isErroneous] to `true`.
assert(invariant(node, element is! ErroneousElement,
message: "Unexpected erroneous element $element."));
return handleErroneousAccess(node, name, element,
new StaticAccess.unresolved(element));
}
if (element.isInstanceMember) {
if (inInstanceContext) {
// TODO(johnniwinther): Maybe use the found [element].
return handleThisPropertyAccess(node, name);
} else {
return handleStaticInstanceSend(node, name, element);
}
}
if (element.isClass || element.isTypedef) {
return oldVisitSend(node);
} else if (element.isTypeVariable) {
return oldVisitSend(node);
} else if (element.isPrefix) {
return oldVisitSend(node);
} else if (element.isLocal) {
return handleLocalAccess(node, name, element);
} else if (element.isStatic || element.isTopLevel) {
return handleStaticOrTopLevelAccess(node, name, element);
}
return internalError(node, "Unexpected resolved send: $element");
}
/// Handle an unqualified [Send], that is where the `node.receiver` is null,
/// like `a`, `a()`, `this()`, `assert()`, and `(){}()`.
ResolutionResult handleUnqualifiedSend(Send node) {
@ -1407,19 +1729,33 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
ErroneousElement error = reportCannotResolve(node, text);
return handleUnresolvedAccess(node, name, error);
}
} else {
return handleResolvedSend(node, name, element);
}
return oldVisitSend(node);
}
ResolutionResult visitSend(Send node) {
if (node.isOperator) {
// `a && b`, `a + b`, `-a`, or `a is T`.
return handleOperatorSend(node);
} else if (node.receiver != null) {
// `a.b`.
return handleQualifiedSend(node);
} else {
// `a`.
return handleUnqualifiedSend(node);
}
return oldVisitSend(node);
}
/// Regigster read access of [target] inside a closure.
void registerPotentialAccessInClosure(Send node, Element target) {
if (isPotentiallyMutableTarget(target)) {
if (enclosingElement != target.enclosingElement) {
for (Node scope in promotionScope) {
registry.setAccessedByClosureIn(scope, target, node);
}
}
}
}
ResolutionResult oldVisitSend(Send node) {
@ -1467,13 +1803,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
} else if (target.impliesType && (!sendIsMemberAccess || node.isCall)) {
registerTypeLiteralAccess(node, target);
}
if (isPotentiallyMutableTarget(target)) {
if (enclosingElement != target.enclosingElement) {
for (Node scope in promotionScope) {
registry.setAccessedByClosureIn(scope, target, node);
}
}
}
registerPotentialAccessInClosure(node, target);
}
bool resolvedArguments = false;
@ -1511,23 +1841,7 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
}
}
if (target != null && compiler.backend.isForeign(target)) {
if (selector.name == 'JS') {
registry.registerJsCall(node, this);
} else if (selector.name == 'JS_EMBEDDED_GLOBAL') {
registry.registerJsEmbeddedGlobalCall(node, this);
} else if (selector.name == 'JS_BUILTIN') {
registry.registerJsBuiltinCall(node, this);
} else if (selector.name == 'JS_INTERCEPTOR_CONSTANT') {
if (!node.argumentsNode.isEmpty) {
Node argument = node.argumentsNode.nodes.head;
if (argumentsToJsInterceptorConstant == null) {
argumentsToJsInterceptorConstant = new Set<Node>();
}
argumentsToJsInterceptorConstant.add(argument);
}
}
}
handleForeignCall(node, target, selector);
}
registry.useElement(node, target);
@ -1538,6 +1852,27 @@ class ResolverVisitor extends MappingVisitor<ResolutionResult> {
return node.isPropertyAccess ? new ElementResult(target) : null;
}
// TODO(johnniwinther): Move this to the backend resolution callbacks.
void handleForeignCall(Send node, Element target, Selector selector) {
if (target != null && compiler.backend.isForeign(target)) {
if (selector.name == 'JS') {
registry.registerJsCall(node, this);
} else if (selector.name == 'JS_EMBEDDED_GLOBAL') {
registry.registerJsEmbeddedGlobalCall(node, this);
} else if (selector.name == 'JS_BUILTIN') {
registry.registerJsBuiltinCall(node, this);
} else if (selector.name == 'JS_INTERCEPTOR_CONSTANT') {
if (!node.argumentsNode.isEmpty) {
Node argument = node.argumentsNode.nodes.head;
if (argumentsToJsInterceptorConstant == null) {
argumentsToJsInterceptorConstant = new Set<Node>();
}
argumentsToJsInterceptorConstant.add(argument);
}
}
}
}
/// Callback for native enqueuer to parse a type. Returns [:null:] on error.
DartType resolveTypeFromString(Node node, String typeName) {
Element element = lookupInScope(compiler, node, scope, typeName);

View file

@ -983,7 +983,7 @@ class CommonResolverVisitor<R> extends Visitor<R> {
compiler.reportWarning(node, kind, arguments);
}
void internalError(Spannable node, message) {
internalError(Spannable node, message) {
compiler.internalError(node, message);
}

View file

@ -1322,9 +1322,12 @@ class SsaBuilder extends NewResolvedVisitor {
bool meetsHardConstraints() {
if (compiler.disableInlining) return false;
assert(selector != null
|| Elements.isStaticOrTopLevel(element)
|| element.isGenerativeConstructorBody);
assert(invariant(
currentNode != null ? currentNode : element,
selector != null ||
Elements.isStaticOrTopLevel(element) ||
element.isGenerativeConstructorBody,
message: "Missing selector for inlining of $element."));
if (selector != null && !selector.applies(function, compiler.world)) {
return false;
}
@ -3246,8 +3249,7 @@ class SsaBuilder extends NewResolvedVisitor {
return pop();
}
String noSuchMethodTargetSymbolString(ErroneousElement error,
[String prefix]) {
String noSuchMethodTargetSymbolString(Element error, [String prefix]) {
String result = error.name;
if (prefix == "set") return "$result=";
return result;
@ -3288,14 +3290,18 @@ class SsaBuilder extends NewResolvedVisitor {
node);
}
void handleInvalidStaticGet(ast.Send node, Element element) {
generateThrowNoSuchMethod(
node,
noSuchMethodTargetSymbolString(element, 'get'),
argumentNodes: const Link<ast.Node>());
}
/// Generate read access of an unresolved static or top level entity.
void generateStaticUnresolvedGet(ast.Send node, Element element) {
if (element is ErroneousElement) {
// An erroneous element indicates an unresolved static getter.
generateThrowNoSuchMethod(
node,
noSuchMethodTargetSymbolString(element, 'get'),
argumentNodes: const Link<ast.Node>());
handleInvalidStaticGet(node, element);
} else {
// This happens when [element] has parse errors.
assert(invariant(node, element == null || element.isErroneous));
@ -5146,6 +5152,22 @@ class SsaBuilder extends NewResolvedVisitor {
generateCallInvoke(node, pop());
}
@override
void visitTopLevelSetterGet(
ast.Send node,
MethodElement setter,
_) {
handleInvalidStaticGet(node, setter);
}
@override
void visitStaticSetterGet(
ast.Send node,
MethodElement setter,
_) {
handleInvalidStaticGet(node, setter);
}
@override
void visitUnresolvedGet(
ast.Send node,
@ -5154,6 +5176,32 @@ class SsaBuilder extends NewResolvedVisitor {
generateStaticUnresolvedGet(node, element);
}
void handleInvalidStaticInvoke(ast.Send node, Element element) {
generateThrowNoSuchMethod(node,
noSuchMethodTargetSymbolString(element),
argumentNodes: node.arguments);
}
@override
void visitStaticSetterInvoke(
ast.Send node,
MethodElement setter,
ast.NodeList arguments,
CallStructure callStructure,
_) {
handleInvalidStaticInvoke(node, setter);
}
@override
void visitTopLevelSetterInvoke(
ast.Send node,
MethodElement setter,
ast.NodeList arguments,
CallStructure callStructure,
_) {
handleInvalidStaticInvoke(node, setter);
}
@override
void visitUnresolvedInvoke(
ast.Send node,
@ -5164,9 +5212,7 @@ class SsaBuilder extends NewResolvedVisitor {
if (element is ErroneousElement) {
// An erroneous element indicates that the funciton could not be
// resolved (a warning has been issued).
generateThrowNoSuchMethod(node,
noSuchMethodTargetSymbolString(element),
argumentNodes: node.arguments);
handleInvalidStaticInvoke(node, element);
} else {
// TODO(ahe): Do something like [generateWrongArgumentCountError].
stack.add(graph.addConstantNull(compiler));

View file

@ -38,7 +38,7 @@ main() {
"memory:library.dart:41:45:'hest' is defined here.:info",
"memory:main.dart:0:22:'hest' is imported here.:info",
"memory:main.dart:23:46:'hest' is imported here.:info",
"memory:main.dart:86:90:Duplicate import of 'hest'.:error"
"memory:main.dart:86:92:Duplicate import of 'hest'.:error"
];
Expect.listEquals(expected, diagnostics);
Expect.isTrue(compiler.compilationFailed);

View file

@ -337,7 +337,7 @@ Future testLocalsThree() {
Expect.equals(null, element);
MethodScope scope = visitor.scope;
Expect.equals(0, scope.elements.length);
Expect.equals(3, map(visitor).length);
Expect.equals(2, map(visitor).length);
List<Element> elements = map(visitor).values.toList();
Expect.equals(elements[0], elements[1]);
});
@ -366,7 +366,7 @@ Future testLocalsFive() {
Expect.equals(null, element);
MethodScope scope = visitor.scope;
Expect.equals(0, scope.elements.length);
Expect.equals(6, map(visitor).length);
Expect.equals(4, map(visitor).length);
Block thenPart = tree.thenPart;
List statements1 = thenPart.statements.nodes.toList();
@ -419,7 +419,7 @@ Future testFor() {
MethodScope scope = visitor.scope;
Expect.equals(0, scope.elements.length);
Expect.equals(9, map(visitor).length);
Expect.equals(7, map(visitor).length);
VariableDefinitions initializer = tree.initializer;
Node iNode = initializer.definitions.nodes.head;
@ -437,35 +437,27 @@ Future testFor() {
// for (int i = 0; i < 10; i = i + 1) { i = 5; };
// ^
checkIdentifier(iElement, nodes[1], elements[1]);
// for (int i = 0; i < 10; i = i + 1) { i = 5; };
// ^
checkSend(iElement, nodes[2], elements[2]);
checkSend(iElement, nodes[1], elements[1]);
// for (int i = 0; i < 10; i = i + 1) { i = 5; };
// ^
checkIdentifier(iElement, nodes[3], elements[3]);
checkIdentifier(iElement, nodes[2], elements[2]);
// for (int i = 0; i < 10; i = i + 1) { i = 5; };
// ^
checkIdentifier(iElement, nodes[4], elements[4]);
// for (int i = 0; i < 10; i = i + 1) { i = 5; };
// ^
checkSend(iElement, nodes[5], elements[5]);
checkSend(iElement, nodes[3], elements[3]);
// for (int i = 0; i < 10; i = i + 1) { i = 5; };
// ^^^^^^^^^
checkSendSet(iElement, nodes[6], elements[6]);
checkSendSet(iElement, nodes[4], elements[4]);
// for (int i = 0; i < 10; i = i + 1) { i = 5; };
// ^
checkIdentifier(iElement, nodes[7], elements[7]);
checkIdentifier(iElement, nodes[5], elements[5]);
// for (int i = 0; i < 10; i = i + 1) { i = 5; };
// ^^^^^
checkSendSet(iElement, nodes[8], elements[8]);
checkSendSet(iElement, nodes[6], elements[6]);
});
}
@ -927,7 +919,7 @@ Future testInitializers() {
int bar;
A() : this.foo = bar;
}""";
return resolveConstructor(script, "A a = new A();", "A", "", 3,
return resolveConstructor(script, "A a = new A();", "A", "", 2,
expectedWarnings: [],
expectedErrors: [MessageKind.NO_INSTANCE_AVAILABLE]);
},

View file

@ -184,11 +184,6 @@ const List<VisitKind> UNTESTABLE_KINDS = const <VisitKind>[
VisitKind.VISIT_SUPER_METHOD_SETTER_COMPOUND,
VisitKind.VISIT_SUPER_METHOD_SETTER_PREFIX,
VisitKind.VISIT_SUPER_METHOD_SETTER_POSTFIX,
// Invalid use of setters is currently reported through an erroneous element.
VisitKind.VISIT_STATIC_SETTER_INVOKE,
VisitKind.VISIT_STATIC_SETTER_GET,
VisitKind.VISIT_TOP_LEVEL_SETTER_GET,
VisitKind.VISIT_TOP_LEVEL_SETTER_INVOKE,
// The constant expressions of assignment to constant type literals cannot be
// handled the compile constant evaluator.
VisitKind.VISIT_CLASS_TYPE_LITERAL_SET,

View file

@ -350,8 +350,9 @@ const Map<String, List<Test>> SEND_TESTS = const {
m() => o;
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_GET,
name: 'o')),
const Visit(VisitKind.VISIT_STATIC_SETTER_GET,
element: 'setter(C#o)')),
const Test.clazz(
'''
class C {
@ -462,8 +463,8 @@ const Map<String, List<Test>> SEND_TESTS = const {
m() { o(null, 42); }
}
''',
const Visit(VisitKind.VISIT_UNRESOLVED_INVOKE,
name: 'o',
const Visit(VisitKind.VISIT_STATIC_SETTER_INVOKE,
element: 'setter(C#o)',
arguments: '(null,42)')),
const Test.clazz(
'''
@ -720,8 +721,8 @@ const Map<String, List<Test>> SEND_TESTS = const {
set o(_) {}
m() => o;
''',
const Visit(VisitKind.VISIT_UNRESOLVED_GET,
name: 'o')),
const Visit(VisitKind.VISIT_TOP_LEVEL_SETTER_GET,
element: 'setter(o)')),
const Test.prefix(
'''
set o(_) {}
@ -786,8 +787,8 @@ const Map<String, List<Test>> SEND_TESTS = const {
set o(_) {}
m() => o(null, 42);
''',
const Visit(VisitKind.VISIT_UNRESOLVED_INVOKE,
name: 'o',
const Visit(VisitKind.VISIT_TOP_LEVEL_SETTER_INVOKE,
element: 'setter(o)',
arguments: '(null,42)')),
const Test.prefix(
'''

View file

@ -618,7 +618,7 @@ main() {
returnNum1(true);
returnNum2(true);
returnInt1(true);
returnInt2(true);
returnInt2();
returnInt3(true);
returnInt4();
returnDouble(true);
@ -667,7 +667,7 @@ main() {
returnAsTypedef();
returnTopLevelGetter();
testDeadCode();
testLabeledIf();
testLabeledIf(true);
testSwitch1();
testSwitch2();
testSwitch3();
@ -727,6 +727,7 @@ main() {
void main() {
Uri uri = new Uri(scheme: 'source');
var compiler = compilerFor(TEST, uri);
compiler.diagnosticHandler = createHandler(compiler, TEST);
asyncTest(() => compiler.runCompiler(uri).then((_) {
var typesTask = compiler.typesTask;
var typesInferrer = typesTask.typesInferrer;