| Index: compiler/java/com/google/dart/compiler/parser/DartParser.java
|
| diff --git a/compiler/java/com/google/dart/compiler/parser/DartParser.java b/compiler/java/com/google/dart/compiler/parser/DartParser.java
|
| index 869f1510367d8de79256492f4d16e6e26e58b46d..06f9faea14c06b346931151ffb674a41a49a4bde 100644
|
| --- a/compiler/java/com/google/dart/compiler/parser/DartParser.java
|
| +++ b/compiler/java/com/google/dart/compiler/parser/DartParser.java
|
| @@ -974,17 +974,18 @@ public class DartParser extends CompletionHooksParserBase {
|
| done(null);
|
| }
|
|
|
| - // Parse the argument definitions.
|
| - List<DartParameter> arguments = parseFormalParameterList();
|
| + // Parse the parameters definitions.
|
| + List<DartParameter> parameters = parseFormalParameterList();
|
|
|
| - if (arity != -1 && arguments.size() != arity) {
|
| - reportError(position(), ParserErrorCode.ILLEGAL_NUMBER_OF_ARGUMENTS);
|
| + if (arity != -1 && parameters.size() != arity) {
|
| + reportError(position(), ParserErrorCode.ILLEGAL_NUMBER_OF_PARAMETERS);
|
| }
|
|
|
| // Parse initializer expressions for constructors.
|
| List<DartInitializer> initializers = new ArrayList<DartInitializer>();
|
| if (match(Token.COLON) && !(isParsingInterface || modifiers.isFactory())) {
|
| - boolean isRedirectedConstructor = parseInitializers(initializers);
|
| + parseInitializers(initializers);
|
| + boolean isRedirectedConstructor = validateInitializers(parameters, initializers);
|
| if (isRedirectedConstructor) {
|
| modifiers = modifiers.makeRedirectedConstructor();
|
| }
|
| @@ -1001,7 +1002,7 @@ public class DartParser extends CompletionHooksParserBase {
|
| }
|
| }
|
|
|
| - DartFunction function = doneWithoutConsuming(new DartFunction(arguments, body, returnType));
|
| + DartFunction function = doneWithoutConsuming(new DartFunction(parameters, body, returnType));
|
| return DartMethodDefinition.create(name, function, modifiers, initializers, null);
|
| }
|
|
|
| @@ -1054,10 +1055,10 @@ public class DartParser extends CompletionHooksParserBase {
|
| * : (THIS '.')? identifier '=' conditionalExpression
|
| * | THIS ('.' identifier)? arguments
|
| * ;
|
| - * </pre>
|
| + * </pre>
|
| * @return true if initializer is a redirected constructor, false otherwise.
|
| */
|
| - private boolean parseInitializers(List<DartInitializer> initializers) {
|
| + private void parseInitializers(List<DartInitializer> initializers) {
|
| expect(Token.COLON);
|
| do {
|
| beginInitializer();
|
| @@ -1075,13 +1076,15 @@ public class DartParser extends CompletionHooksParserBase {
|
| boolean hasThisPrefix = optional(Token.THIS);
|
| if (hasThisPrefix) {
|
| if (match(Token.LPAREN)) {
|
| - return parseRedirectedConstructorInvocation(null, initializers);
|
| + parseRedirectedConstructorInvocation(null, initializers);
|
| + continue;
|
| }
|
| expect(Token.PERIOD);
|
| }
|
| DartIdentifier name = parseIdentifier();
|
| if (hasThisPrefix && match(Token.LPAREN)) {
|
| - return parseRedirectedConstructorInvocation(name, initializers);
|
| + parseRedirectedConstructorInvocation(name, initializers);
|
| + continue;
|
| } else {
|
| expect(Token.ASSIGN);
|
| boolean save = setAllowFunctionExpression(false);
|
| @@ -1091,20 +1094,87 @@ public class DartParser extends CompletionHooksParserBase {
|
| }
|
| }
|
| } while (optional(Token.COMMA));
|
| - return false;
|
| }
|
|
|
| - private boolean parseRedirectedConstructorInvocation(DartIdentifier name,
|
| - List<DartInitializer> initializers) {
|
| - if (initializers.isEmpty()) {
|
| - DartRedirectConstructorInvocation redirConstructor =
|
| + private void parseRedirectedConstructorInvocation(DartIdentifier name,
|
| + List<DartInitializer> initializers) {
|
| + DartRedirectConstructorInvocation redirConstructor =
|
| new DartRedirectConstructorInvocation(name, parseArguments());
|
| - initializers.add(done(new DartInitializer(null, doneWithoutConsuming(redirConstructor))));
|
| - return true;
|
| - } else {
|
| - reportUnexpectedToken(position(), Token.ASSIGN, Token.LPAREN);
|
| + initializers.add(done(new DartInitializer(null, doneWithoutConsuming(redirConstructor))));
|
| + }
|
| +
|
| + private boolean validateInitializers(List<DartParameter> parameters,
|
| + List<DartInitializer> initializers) {
|
| + // Try to find DartRedirectConstructorInvocation, check for multiple invocations.
|
| + // Check for DartSuperConstructorInvocation multiple invocations.
|
| + DartInitializer redirectInitializer = null;
|
| + boolean firstMultipleRedirectReported = false;
|
| + {
|
| + DartInitializer superInitializer = null;
|
| + boolean firstMultipleSuperReported = false;
|
| + for (DartInitializer initializer : initializers) {
|
| + if (initializer.isInvocation()) {
|
| + // DartSuperConstructorInvocation
|
| + DartExpression initializerInvocation = initializer.getValue();
|
| + if (initializerInvocation instanceof DartSuperConstructorInvocation) {
|
| + if (superInitializer != null) {
|
| + if (!firstMultipleSuperReported) {
|
| + reportError(superInitializer, ParserErrorCode.SUPER_CONSTRUCTOR_MULTIPLE);
|
| + firstMultipleSuperReported = true;
|
| + }
|
| + reportError(initializer, ParserErrorCode.SUPER_CONSTRUCTOR_MULTIPLE);
|
| + } else {
|
| + superInitializer = initializer;
|
| + }
|
| + }
|
| + // DartRedirectConstructorInvocation
|
| + if (initializerInvocation instanceof DartRedirectConstructorInvocation) {
|
| + if (redirectInitializer != null) {
|
| + if (!firstMultipleRedirectReported) {
|
| + reportError(redirectInitializer, ParserErrorCode.REDIRECTING_CONSTRUCTOR_MULTIPLE);
|
| + firstMultipleRedirectReported = true;
|
| + }
|
| + reportError(initializer, ParserErrorCode.REDIRECTING_CONSTRUCTOR_MULTIPLE);
|
| + } else {
|
| + redirectInitializer = initializer;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| + // If there is redirecting constructor, then there should be no other initializers.
|
| + if (redirectInitializer != null) {
|
| + boolean shouldRedirectInvocationReported = false;
|
| + // Implicit initializer in form of "this.id" parameter.
|
| + for (DartParameter parameter : parameters) {
|
| + if (parameter.getName() instanceof DartPropertyAccess) {
|
| + DartPropertyAccess propertyAccess = (DartPropertyAccess) parameter.getName();
|
| + if (propertyAccess.getQualifier() instanceof DartThisExpression) {
|
| + shouldRedirectInvocationReported = true;
|
| + reportError(
|
| + parameter,
|
| + ParserErrorCode.REDIRECTING_CONSTRUCTOR_PARAM);
|
| + }
|
| + }
|
| + }
|
| + // Iterate all initializers and mark all except of DartRedirectConstructorInvocation
|
| + for (DartInitializer initializer : initializers) {
|
| + if (!(initializer.getValue() instanceof DartRedirectConstructorInvocation)) {
|
| + shouldRedirectInvocationReported = true;
|
| + reportError(
|
| + initializer,
|
| + ParserErrorCode.REDIRECTING_CONSTRUCTOR_OTHER);
|
| + }
|
| + }
|
| + // Mark DartRedirectConstructorInvocation if needed.
|
| + if (shouldRedirectInvocationReported) {
|
| + reportError(
|
| + redirectInitializer,
|
| + ParserErrorCode.REDIRECTING_CONSTRUCTOR_ITSELF);
|
| + }
|
| }
|
| - return false;
|
| + // Done.
|
| + return redirectInitializer != null;
|
| }
|
|
|
| /**
|
|
|