fabiomfv@google.com 2011-11-08 15:56:45 +00:00
parent 70da4ae316
commit f95d52d827
7 changed files with 115 additions and 85 deletions

View file

@ -869,21 +869,16 @@ public class GenerateJavascriptAST {
functionStack.push(constructor.getFunction());
jsNewDeclarationsStack.push(new HashSet<JsName>());
JsInvocation constructorInvocation = maybeGenerateSuperOrRedirectCall(constructor);
boolean hasConstructorInvocation = constructorInvocation != null;
Iterator<DartInitializer> iterator = initializers.iterator();
Iterator<DartField> fieldIterator = fieldInitializers.iterator();
List<JsStatement> jsInitializers = initFunction.getBody().getStatements();
// Do the field inline initializers first. If there are any assignments in the initializer
// list, they will be the last assignments.
List<JsStatement> jsInitializers = initFunction.getBody().getStatements();
Iterator<DartField> fieldIterator = fieldInitializers.iterator();
while (fieldIterator.hasNext()) {
JsExpression initializer = generateInlineFieldInitializer(fieldIterator.next());
jsInitializers.add(initializer.makeStmt());
jsInitializers.add(generateInlineFieldInitializer(fieldIterator.next()).makeStmt());
}
DartInvocation initInvocation = null;
Iterator<DartInitializer> iterator = initializers.iterator();
while (iterator.hasNext()) {
DartInitializer initializer = iterator.next();
if (!initializer.isInvocation()) {
@ -893,7 +888,8 @@ public class GenerateJavascriptAST {
}
}
if (hasConstructorInvocation) {
JsInvocation constructorInvocation = maybeGenerateSuperOrRedirectCall(constructor);
if (constructorInvocation != null) {
// Call the super initializer function in the initializer.
// Compute the super constructor initializer to call.
ConstructorElement superElement = (ConstructorElement) initInvocation.getSymbol();

View file

@ -1023,44 +1023,70 @@ public class DartParser extends CompletionHooksParserBase {
/**
* <pre>
* initializers
* : ':' superCallOrFirstFieldInitializer (',' fieldInitializer)*
* | THIS ('.' identifier) formalParameterList
* ;
*
* fieldInitializer
* : (THIS '.')? identifier '=' conditionalExpression
* ;
*
* superCallOrFirstFieldInitializer
* : SUPER arguments | SUPER '.' identifier arguments
* | fieldInitializer
* ;
*
* fieldInitializer
* : (THIS '.')? identifier '=' conditionalExpression
* | THIS ('.' identifier)? arguments
* ;
* </pre>
*
* @return true if initializer is a redirected constructor, false otherwise.
*/
private boolean parseFieldInitializersOrRedirectedConstructor(List<DartInitializer> inits) {
private boolean parseInitializers(List<DartInitializer> initializers) {
expect(Token.COLON);
do {
beginFieldInitializerOrRedirectedConstructor();
beginInitializer();
if (match(Token.SUPER)) {
beginSuperInitializer();
expect(Token.SUPER);
DartIdentifier constructor = null;
if (optional(Token.PERIOD)) {
constructor = parseIdentifier();
}
DartSuperConstructorInvocation superInvocation =
new DartSuperConstructorInvocation(constructor, parseArguments());
initializers.add(done(new DartInitializer(null, done(superInvocation))));
} else {
boolean hasThisPrefix = optional(Token.THIS);
if (hasThisPrefix) {
if (match(Token.LPAREN)) {
return parseRedirectedConstructorInvocation(null, inits);
return parseRedirectedConstructorInvocation(null, initializers);
}
expect(Token.PERIOD);
}
DartIdentifier name = parseIdentifier();
if (hasThisPrefix && match(Token.LPAREN)) {
return parseRedirectedConstructorInvocation(name, inits);
return parseRedirectedConstructorInvocation(name, initializers);
} else {
expect(Token.ASSIGN);
boolean save = setAllowFunctionExpression(false);
DartExpression initExpr = parseExpression();
setAllowFunctionExpression(save);
inits.add(done(new DartInitializer(name, initExpr)));
initializers.add(done(new DartInitializer(name, initExpr)));
}
}
} while (optional(Token.COMMA));
return false;
}
private boolean parseRedirectedConstructorInvocation(DartIdentifier name,
List<DartInitializer> inits) {
if (inits.isEmpty()) {
DartInvocation call =
doneWithoutConsuming(new DartRedirectConstructorInvocation(name, parseArguments()));
inits.add(done(new DartInitializer(null, call)));
List<DartInitializer> initializers) {
if (initializers.isEmpty()) {
DartRedirectConstructorInvocation redirConstructor =
new DartRedirectConstructorInvocation(name, parseArguments());
initializers.add(done(new DartInitializer(null, doneWithoutConsuming(redirConstructor))));
return true;
} else {
reportUnexpectedToken(position(), Token.ASSIGN, Token.LPAREN);
@ -1068,42 +1094,6 @@ public class DartParser extends CompletionHooksParserBase {
return false;
}
/**
* <pre>
* initializers : ':' superCallOrFirstFieldInitializer (',' fieldInitializer)*
* | THIS ('.' identifier) formalParameterList ;
*
* fieldInitializer : (THIS '.')? identifier '=' conditionalExpression ;
*
* superCallOrFirstFieldInitializer : SUPER arguments | SUPER '.' identifier
* arguments | fieldInitializer ;
* <pre>
*
* @return true if initializer is a redirect constructor, false otherwise.
*/
private boolean parseInitializers(List<DartInitializer> initializers) {
expect(Token.COLON);
boolean callSuper = false;
if (match(Token.SUPER)) {
beginInitializer();
beginSuperInitializer();
expect(Token.SUPER);
callSuper = true;
DartIdentifier constructor = null;
if (optional(Token.PERIOD)) {
// Calling a super named constructor.
constructor = parseIdentifier();
}
DartSuperConstructorInvocation call =
done(new DartSuperConstructorInvocation(constructor, parseArguments()));
initializers.add(done(new DartInitializer(null, call)));
}
if (!callSuper || optional(Token.COMMA)) {
return parseFieldInitializersOrRedirectedConstructor(initializers);
}
return false;
}
/**
* <pre>
* variableDeclaration

View file

@ -1333,13 +1333,15 @@ public class Resolver {
}
private void resolveInitializers(DartMethodDefinition node) {
assert null != node;
Iterator<DartInitializer> initializers = node.getInitializers().iterator();
ConstructorElement constructorElement = null;
while (initializers.hasNext()) {
DartInitializer initializer = initializers.next();
Element element = resolve(initializer);
if (ElementKind.of(element) == ElementKind.CONSTRUCTOR) {
if ((ElementKind.of(element) == ElementKind.CONSTRUCTOR) && initializer.isInvocation()) {
if (constructorElement != null) {
onError(initializer, ResolverErrorCode.SUPER_INVOCATION_NOT_UNIQUE);
}
constructorElement = (ConstructorElement) element;
}
}

View file

@ -98,6 +98,7 @@ public enum ResolverErrorCode implements ErrorCode {
STATIC_METHOD_ACCESS_SUPER("Cannot use 'super' in a static method"),
STATIC_METHOD_ACCESS_THIS("Cannot use 'this' in a static method"),
SUPER_OUTSIDE_OF_METHOD("Cannot use 'super' outside of a method"),
SUPER_INVOCATION_NOT_UNIQUE("'super' must be called only once in the initialization list"),
TOP_LEVEL_METHOD_ACCESS_SUPER("Cannot use 'super' in a top-level method"),
TOP_LEVEL_METHOD_ACCESS_THIS("Cannot use 'this' in a top-level method"),
TYPE_NOT_ASSIGNMENT_COMPATIBLE("%s is not assignable to %s"),

View file

@ -10,6 +10,7 @@ import com.google.dart.compiler.ErrorCode;
import com.google.dart.compiler.ast.DartUnit;
import com.google.dart.compiler.testing.TestCompilerContext;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
@ -22,17 +23,16 @@ public class NegativeResolverTest extends CompilerTestCase {
final ErrorCode errorCode;
final int line;
final int column;
public ErrorExpectation(ErrorCode errorCode, int line, int column) {
this.errorCode = errorCode;
this.line = line;
this.column = column;
}
}
private static ErrorExpectation errEx(ErrorCode errorCode, int line, int column) {
return new ErrorExpectation(errorCode, line, column);
}
public void checkNumErrors(String fileName, int expectedErrorCount) {
@ -40,8 +40,30 @@ public class NegativeResolverTest extends CompilerTestCase {
resolve(unit);
assertEquals(new ArrayList<DartCompilationError>(), typeErrors);
if (errors.size() != expectedErrorCount) {
fail(String.format("Expected %s errors, but got %s: %s",
expectedErrorCount, errors.size(), errors));
fail(String.format("Expected %s errors, but got %s: %s", expectedErrorCount, errors.size(),
errors));
}
}
public void checkNumErrors(String fileName, ErrorExpectation ...expectedErrors) {
DartUnit unit = parseUnit(fileName);
resolve(unit);
assertEquals(expectedErrors.length, errors.size());
for (int i = 0; i < expectedErrors.length; i++) {
ErrorExpectation expectedError = expectedErrors[i];
DartCompilationError actualError = errors.get(i);
if (actualError.getErrorCode() != expectedError.errorCode
|| actualError.getLineNumber() != expectedError.line
|| actualError.getColumnNumber() != expectedError.column) {
fail(String.format(
"Expected %s:%s:%s, but got %s:%s:%s",
expectedError.errorCode,
expectedError.line,
expectedError.column,
actualError.getErrorCode(),
actualError.getLineNumber(),
actualError.getColumnNumber()));
}
}
}
@ -254,6 +276,11 @@ public class NegativeResolverTest extends CompilerTestCase {
checkNumErrors("RawTypesNegativeTest.dart", 4);
}
public void testSuperMultipleInvocationsTest() {
checkNumErrors("SuperMultipleInvocationsTest.dart",
errEx(ResolverErrorCode.SUPER_INVOCATION_NOT_UNIQUE, 14, 52));
}
private TestCompilerContext getContext() {
return new TestCompilerContext() {
@Override

View file

@ -0,0 +1,15 @@
// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file
// 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.
class A {
int a;
A(this.a);
A.foo(int x, int y);
}
class B extends A {
int b1;
int b2;
B(int x) : this.b1 = x, super(x), this.b2 = x, super.foo(x, x);
}

View file

@ -47,7 +47,6 @@ LangGuideTest/02_Language_Constructs/02_11_Exceptions/A04/t01: Fail
LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Const_Expressions/A02/t01: Fail # Bug 5371670.
LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Const_Expressions/A04/t01: Fail # Bug 5371670.
LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A03/t01: Fail # Bug 5371670.
LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A05/t01: Fail
LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A06/t04: Fail # Bug 5371670.
LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A10/t01: Fail # Bug 5371670.
LangGuideTest/02_Language_Constructs/02_1_Class/02_1_Class_Construction/A13/t01: Fail # Bug 5371670.