Skip to content

Commit

Permalink
Automated g4 rollback of changelist 121864559.
Browse files Browse the repository at this point in the history
*** Reason for rollback ***

Parse errors inside switch statements.

*** Original change description ***

Allow TypeScript syntax in arrow function parameters and return types

Merges pull request #1378 from Dominator008/closure-compiler
Closes #1378

***
-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=121875679
  • Loading branch information
blickly committed May 9, 2016
1 parent 7a8706c commit bfaf718
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 100 deletions.
66 changes: 14 additions & 52 deletions src/com/google/javascript/jscomp/parsing/parser/Parser.java
Expand Up @@ -123,9 +123,7 @@
import java.util.ArrayDeque;
import java.util.EnumSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

/**
* Parses a javascript file.
Expand Down Expand Up @@ -174,7 +172,6 @@ public class Parser {
private final CommentRecorder commentRecorder = new CommentRecorder();
private final ArrayDeque<Boolean> inGeneratorContext = new ArrayDeque<>();
private FeatureSet features = FeatureSet.ES3;
private final Set<Token> colonTypeTokens = new LinkedHashSet<>();

public Parser(
Config config, ErrorReporter errorReporter,
Expand Down Expand Up @@ -1043,11 +1040,15 @@ private ParseTree parseArrowFunctionTail(
SourcePosition start,
GenericTypeListTree generics,
FormalParameterListTree formalParameterList,
ParseTree returnType,
Expression expressionIn) {

inGeneratorContext.addLast(false);

ParseTree returnType = null;
if (peek(TokenType.COLON)) {
returnType = parseTypeAnnotation();
}

if (peekImplicitSemiColon()) {
reportError("No newline allowed before '=>'");
}
Expand All @@ -1056,7 +1057,7 @@ private ParseTree parseArrowFunctionTail(
if (peek(TokenType.OPEN_CURLY)) {
functionBody = parseFunctionBody();
} else {
functionBody = parseAssignment(expressionIn, false);
functionBody = parseAssignment(expressionIn);
}

FunctionDeclarationTree declaration = new FunctionDeclarationTree(
Expand Down Expand Up @@ -1891,7 +1892,7 @@ private ImmutableList<ParseTree> parseCaseClauses() {
switch (peekType()) {
case CASE:
eat(TokenType.CASE);
ParseTree expression = parse(Expression.NORMAL, false);
ParseTree expression = parseExpression();
eat(TokenType.COLON);
ImmutableList<ParseTree> statements = parseCaseStatementsOpt();
result.add(new CaseClauseTree(getTreeLocation(start), expression, statements));
Expand Down Expand Up @@ -2594,12 +2595,8 @@ private boolean peekExpression() {
}

private ParseTree parse(Expression expressionIn) {
return parse(expressionIn, true);
}

private ParseTree parse(Expression expressionIn, boolean mayHaveColonType) {
SourcePosition start = getTreeStartLocation();
ParseTree result = parseAssignment(expressionIn, mayHaveColonType);
ParseTree result = parseAssignment(expressionIn);
if (peek(TokenType.COMMA) && !peek(1, TokenType.SPREAD)) {
ImmutableList.Builder<ParseTree> exprs = ImmutableList.builder();
exprs.add(result);
Expand All @@ -2622,44 +2619,17 @@ private boolean peekAssignmentExpression() {
}

private ParseTree parseAssignment(Expression expressionIn) {
return parseAssignment(expressionIn, true);
}

private void reportInvalidColonTypes() {
for (Token colon : colonTypeTokens) {
reportError(colon, "invalid location for colon type expression");
}
colonTypeTokens.clear();
}

private ParseTree parseAssignment(Expression expressionIn, boolean mayHaveColonType) {
if (peek(TokenType.YIELD) && inGeneratorContext()) {
return parseYield(expressionIn);
}

SourcePosition start = getTreeStartLocation();
GenericTypeListTree generics = maybeParseGenericTypes();
// TODO(blickly): Allow TypeScript syntax in arrow function parameters
ParseTree left = parseConditional(expressionIn);

ParseTree returnType = null;
if (peek(TokenType.COLON) && mayHaveColonType) {
colonTypeTokens.add(peekToken());
returnType = parseTypeAnnotation();
}

if (peek(TokenType.ARROW)) {
FormalParameterListTree params = transformArrowFunctionParameters(start, left);
colonTypeTokens.clear();
if (peek(TokenType.COLON)) {
parseTypeAnnotation();
}
return parseArrowFunctionTail(start, generics, params, returnType, expressionIn);
return parseArrowFunctionTail(start, null, params, expressionIn);
}

if (generics != null) {
reportError("invalid location for generics");
}

if (left.type == ParseTreeType.FORMAL_PARAMETER_LIST) {
reportError("invalid paren expression");
}
Expand All @@ -2670,17 +2640,9 @@ private ParseTree parseAssignment(Expression expressionIn, boolean mayHaveColonT
reportError("invalid assignment target");
}
Token operator = nextToken();
ParseTree right = parseAssignment(expressionIn, mayHaveColonType);
ParseTree right = parseAssignment(expressionIn);
return new BinaryOperatorTree(getTreeLocation(start), left, operator, right);
}

if (peek(TokenType.CLOSE_PAREN)) {
if (!peek(1, TokenType.ARROW) && !peek(1, TokenType.COLON)) {
reportInvalidColonTypes();
}
} else if (!peek(TokenType.COMMA)) {
reportInvalidColonTypes();
}
return left;
}

Expand All @@ -2693,7 +2655,7 @@ private FormalParameterListTree transformArrowFunctionParameters(
case PAREN_EXPRESSION:
resetScanner(tree);
// If we fail to parse as an ArrowFunction paramater list then
// parseFormalParameterList will take care of reporting errors.
// parseFormalParameterList will take care reporting errors.
return parseFormalParameterList(ParamContext.IMPLEMENTATION);
case FORMAL_PARAMETER_LIST:
return tree.asFormalParameterList();
Expand Down Expand Up @@ -2777,9 +2739,9 @@ private ParseTree parseConditional(Expression expressionIn) {
ParseTree condition = parseLogicalOR(expressionIn);
if (peek(TokenType.QUESTION)) {
eat(TokenType.QUESTION);
ParseTree left = parseAssignment(expressionIn, false);
ParseTree left = parseAssignment(expressionIn);
eat(TokenType.COLON);
ParseTree right = parseAssignment(expressionIn, false);
ParseTree right = parseAssignment(expressionIn);
return new ConditionalExpressionTree(
getTreeLocation(start), condition, left, right);
}
Expand Down
Expand Up @@ -254,7 +254,7 @@ public void testGenericClass() {

public void testGenericFunction() {
test("function foo<T>() {}", "/** @template T */ function foo() {}");
test("var x = <K, V>(p) => 3;", "var x = /** @template K, V */ (p) => 3");
// test("var x = <K, V>(p) => 3;", "var x = /** @template K, V */ (p) => 3");
test("class Foo { f<T>() {} }", "class Foo { /** @template T */ f() {} }");
test("(function<T>() {})();", "(/** @template T */ function() {})();");
test("function* foo<T>() {}", "/** @template T */ function* foo() {}");
Expand Down
15 changes: 0 additions & 15 deletions test/com/google/javascript/jscomp/parsing/ParserTest.java
Expand Up @@ -227,21 +227,6 @@ public void testNonDuplicateLabelCrossFunction() {
parse("foo:(function(){foo:2})");
}

public void testConditional() {
parse("1 ? 2 ? 3 : 4 : 5;");
parse("1 ? (x,y,z) : n;");

mode = LanguageMode.ECMASCRIPT6;
expectedFeatures = FeatureSet.ES6_IMPL;
Node hook = parse(LINE_JOINER.join(
"function f(cond) {",
" return cond ?",
" (v = 7, f = () => v) :",
" n => 2 * n;",
"}")).getFirstChild().getLastChild().getFirstFirstChild();
assertNode(hook).hasType(Token.HOOK);
}

public void testLinenoCharnoAssign1() throws Exception {
Node assign = parse("a = b").getFirstFirstChild();

Expand Down
37 changes: 5 additions & 32 deletions test/com/google/javascript/jscomp/parsing/TypeSyntaxTest.java
Expand Up @@ -152,7 +152,7 @@ public void testFunctionParamDeclaration_destructuringObject() {
parse("function foo({x}: any) {\n}");
}

public void testFunctionParamDeclaration_arrow() {
public void disabled_testFunctionParamDeclaration_arrow() {
Node fn = parse("(x: string) => 'hello' + x;").getFirstFirstChild();
Node param = fn.getSecondChild().getFirstChild();
assertDeclaredType("string type", stringType(), param);
Expand All @@ -172,7 +172,7 @@ public void testFunctionReturn() {
assertDeclaredType("string type", stringType(), fn);
}

public void testFunctionReturn_arrow() {
public void disabled_testFunctionReturn_arrow() {
Node fn = parse("(): string => 'hello';").getFirstFirstChild();
assertDeclaredType("string type", stringType(), fn);
}
Expand Down Expand Up @@ -314,7 +314,7 @@ public void testFunctionType() {
parse("var n: (p1: string, p2: number) => boolean;");
parse("var n: () => () => number;");
parse("var n: (p1: string) => {};");
parse("(number): () => number => number;");
// parse("(number): () => number => number;");

Node ast = parse("var n: (p1: string, p2: number) => boolean[];");
TypeDeclarationNode function = (TypeDeclarationNode)
Expand Down Expand Up @@ -510,7 +510,7 @@ public void testGenericClass() {

public void testGenericFunction() {
parse("function foo<T>() {\n}");
parse("var x = <K, V>(p) => 3;");
// parse("var x = <K, V>(p) => 3;");
parse("class Foo {\n f<T>() {\n }\n}");
parse("(function<T>() {\n})();");
parse("function* foo<T>() {\n}");
Expand All @@ -522,40 +522,13 @@ public void testGenericFunction() {
expectErrors("Parse error. 'identifier' expected");
parse("function foo<>() {\n}");

expectErrors("Parse error. invalid location for generics");
parse("var x = <T>(5 + 7);");

// Typecasting, not supported yet.
expectErrors("Parse error. invalid location for generics");
expectErrors("Parse error. primary expression expected");
parse("var x = <T>((p:T) => 3);");

testNotEs6Typed("function foo<T>() {}", "generics");
}

public void testColonTypeInArrowFunction() {
parse("(x: string) => 'hello';");
parse("(x: number = 1) => 'hello';");
parse("(x: string): string => 'hello';");
parse("(x: string, y: number): string => 'hello';");
parse("1 ? (x: number) => '2' : (y: boolean) => 3 ? 4 : 5;");
parse("var x = (y: number, z = (w: number) => 1) => 2;");
}

public void testInvalidColonType() {
expectErrors("Parse error. invalid location for colon type expression");
parse("var x = 3 : number;");
expectErrors("Parse error. invalid location for colon type expression");
parse("var x = (3 : number);");
expectErrors("Parse error. invalid location for colon type expression");
parse("var x = (x : number);");
expectErrors("Parse error. invalid location for colon type expression");
parse("var x = ((y): number);");
expectErrors("Parse error. invalid location for colon type expression");
parse("var x = ((y: string, x: number): number);");
expectErrors("Parse error. invalid arrow function parameters");
parse("var x = 3 : number => 4;");
}

public void testImplements() {
parse("class Foo implements Bar, Baz {\n}");
parse("class Foo extends Bar implements Baz {\n}");
Expand Down

1 comment on commit bfaf718

@Dominator008
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@blickly Is there a test case?

Please sign in to comment.