diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 5818929d6e8..b6455304cdc 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -835,7 +835,6 @@ module ts { var lookAheadMode = LookAheadMode.NotLookingAhead; var inAmbientContext = false; - var inFunctionBody = false; function getLineStarts(): number[] { return lineStarts || (lineStarts = computeLineStarts(sourceText)); @@ -2062,7 +2061,7 @@ module ts { var body: Node; if (token === SyntaxKind.OpenBraceToken) { - body = parseBody(/* ignoreMissingOpenBrace */ false); + body = parseFunctionBlock(/* ignoreMissingOpenBrace */ false); } else if (isStatement(/* inErrorRecovery */ true) && !isStartOfExpressionStatement() && token !== SyntaxKind.FunctionKeyword) { // Check if we got a plain statement (i.e. no expression-statements, no functions expressions/declarations) @@ -2079,7 +2078,7 @@ module ts { // up preemptively closing the containing construct. // // Note: even when 'ignoreMissingOpenBrace' is passed as true, parseBody will still error. - body = parseBody(/* ignoreMissingOpenBrace */ true); + body = parseFunctionBlock(/* ignoreMissingOpenBrace */ true); } else { body = parseAssignmentExpression(noIn); @@ -2431,7 +2430,7 @@ module ts { node = createNode(SyntaxKind.PropertyAssignment, nodePos); node.name = propertyName; var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false); - var body = parseBody(/* ignoreMissingOpenBrace */ false); + var body = parseFunctionBlock(/* ignoreMissingOpenBrace */ false); // do not propagate property name as name for function expression // for scenarios like // var x = 1; @@ -2492,7 +2491,7 @@ module ts { parseExpected(SyntaxKind.FunctionKeyword); var name = isIdentifier() ? parseIdentifier() : undefined; var sig = parseSignature(SyntaxKind.CallSignature, SyntaxKind.ColonToken, /* returnTokenRequired */ false); - var body = parseBody(/* ignoreMissingOpenBrace */ false); + var body = parseFunctionBlock(/* ignoreMissingOpenBrace */ false); return makeFunctionExpression(SyntaxKind.FunctionExpression, pos, name, sig, body); } @@ -2530,13 +2529,9 @@ module ts { return finishNode(node); } - function parseBody(ignoreMissingOpenBrace: boolean): Block { - var saveInFunctionBody = inFunctionBody; - - inFunctionBody = true; + function parseFunctionBlock(ignoreMissingOpenBrace: boolean): Block { var block = parseBlock(ignoreMissingOpenBrace, /*checkForStrictMode*/ true); block.kind = SyntaxKind.FunctionBlock; - inFunctionBody = saveInFunctionBody; return block; } @@ -2660,18 +2655,15 @@ module ts { function parseReturnStatement(): ReturnStatement { var node = createNode(SyntaxKind.ReturnStatement); - var errorCountBeforeReturnStatement = file.parseDiagnostics.length; var returnTokenStart = scanner.getTokenPos(); var returnTokenLength = scanner.getTextPos() - returnTokenStart; parseExpected(SyntaxKind.ReturnKeyword); - if (!canParseSemicolon()) node.expression = parseExpression(); - parseSemicolon(); - - // In an ambient context, we will already give an error for having a statement. - if (!inFunctionBody && !inAmbientContext && errorCountBeforeReturnStatement === file.parseDiagnostics.length) { - grammarErrorAtPos(returnTokenStart, returnTokenLength, Diagnostics.A_return_statement_can_only_be_used_within_a_function_body); + if (!canParseSemicolon()) { + node.expression = parseExpression(); } + + parseSemicolon(); return finishNode(node); } @@ -2914,7 +2906,7 @@ module ts { function parseFunctionBlockOrSemicolon(): Block { if (token === SyntaxKind.OpenBraceToken) { - return parseBody(/* ignoreMissingOpenBrace */ false); + return parseFunctionBlock(/* ignoreMissingOpenBrace */ false); } if (canParseSemicolon()) { @@ -3045,7 +3037,7 @@ module ts { node.body = createMissingNode(); } else { - node.body = parseBody(/* ignoreMissingOpenBrace */ false); + node.body = parseFunctionBlock(/* ignoreMissingOpenBrace */ false); } return finishNode(node); @@ -3293,7 +3285,6 @@ module ts { if (parseOptional(SyntaxKind.ImplementsKeyword)) { node.implementedTypes = parseDelimitedList(ParsingContext.BaseTypeReferences, parseTypeReference); } - var errorCountBeforeClassBody = file.parseDiagnostics.length; if (parseExpected(SyntaxKind.OpenBraceToken)) { node.members = parseList(ParsingContext.ClassMembers, /*checkForStrictMode*/ false, parseClassMemberDeclaration); parseExpected(SyntaxKind.CloseBraceToken); @@ -3700,6 +3691,7 @@ module ts { // We're automatically in an ambient context if this is a .d.ts file. var inAmbientContext = fileExtensionIs(file.filename, ".d.ts"); + var inFunctionBlock = false; var parent: Node; visitNode(file); @@ -3709,6 +3701,11 @@ module ts { node.parent = parent; parent = node; + var savedInFunctionBlock = inFunctionBlock; + if (node.kind === SyntaxKind.FunctionBlock) { + inFunctionBlock = true; + } + var savedInAmbientContext = inAmbientContext if (node.flags & NodeFlags.Ambient) { inAmbientContext = true; @@ -3717,6 +3714,7 @@ module ts { checkNode(node); inAmbientContext = savedInAmbientContext; + inFunctionBlock = savedInFunctionBlock; parent = savedParent; } @@ -3724,7 +3722,7 @@ module ts { // First, check if you have a statement in a place where it is not allowed. We want // to do this before recursing, because we'd prefer to report these errors at the top // level instead of at some nested level. - if (checkForStatementInAmbientContext(node)) { + if (inAmbientContext && checkForStatementInAmbientContext(node)) { return; } @@ -3772,6 +3770,7 @@ module ts { case SyntaxKind.PostfixOperator: return visitPostfixOperator(node); case SyntaxKind.PrefixOperator: return visitPrefixOperator(node); case SyntaxKind.PropertyAssignment: return visitPropertyAssignment(node); + case SyntaxKind.ReturnStatement: return visitReturnStatement(node); case SyntaxKind.SetAccessor: return visitSetAccessor(node); case SyntaxKind.ShorthandPropertyAssignment: return visitShorthandPropertyAssignment(node); case SyntaxKind.SwitchStatement: return visitSwitchStatement(node); @@ -3814,27 +3813,25 @@ module ts { } function checkForStatementInAmbientContext(node: Node): boolean { - if (inAmbientContext) { - switch (node.kind) { - case SyntaxKind.Block: - case SyntaxKind.EmptyStatement: - case SyntaxKind.IfStatement: - case SyntaxKind.DoStatement: - case SyntaxKind.WhileStatement: - case SyntaxKind.ForStatement: - case SyntaxKind.ForInStatement: - case SyntaxKind.ContinueStatement: - case SyntaxKind.BreakStatement: - case SyntaxKind.ReturnStatement: - case SyntaxKind.WithStatement: - case SyntaxKind.SwitchStatement: - case SyntaxKind.ThrowStatement: - case SyntaxKind.TryStatement: - case SyntaxKind.DebuggerStatement: - case SyntaxKind.LabeledStatement: - case SyntaxKind.ExpressionStatement: - return grammarErrorOnFirstToken(node, Diagnostics.Statements_are_not_allowed_in_ambient_contexts); - } + switch (node.kind) { + case SyntaxKind.Block: + case SyntaxKind.EmptyStatement: + case SyntaxKind.IfStatement: + case SyntaxKind.DoStatement: + case SyntaxKind.WhileStatement: + case SyntaxKind.ForStatement: + case SyntaxKind.ForInStatement: + case SyntaxKind.ContinueStatement: + case SyntaxKind.BreakStatement: + case SyntaxKind.ReturnStatement: + case SyntaxKind.WithStatement: + case SyntaxKind.SwitchStatement: + case SyntaxKind.ThrowStatement: + case SyntaxKind.TryStatement: + case SyntaxKind.DebuggerStatement: + case SyntaxKind.LabeledStatement: + case SyntaxKind.ExpressionStatement: + return grammarErrorOnFirstToken(node, Diagnostics.Statements_are_not_allowed_in_ambient_contexts); } } @@ -4362,6 +4359,12 @@ module ts { } } + function visitReturnStatement(node: ReturnStatement) { + if (!inFunctionBlock) { + grammarErrorOnFirstToken(node, Diagnostics.A_return_statement_can_only_be_used_within_a_function_body); + } + } + function visitSetAccessor(node: MethodDeclaration) { checkTypeParameterList(node.typeParameters) || checkParameterList(node.parameters) || diff --git a/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.errors.txt b/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.errors.txt index c18dfb8e354..53d24b3d0f8 100644 --- a/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.errors.txt +++ b/tests/baselines/reference/constructorWithIncompleteTypeAnnotation.errors.txt @@ -7,14 +7,11 @@ tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(28,30): error TS tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(28,33): error TS1138: Parameter declaration expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(28,34): error TS1005: ';' expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(28,36): error TS1068: Unexpected token. A constructor, method, accessor, or property was expected. -tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(30,21): error TS1108: A 'return' statement can only be used within a function body. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(31,18): error TS1129: Statement expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(38,17): error TS1109: Expression expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(40,41): error TS1005: ';' expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(40,45): error TS1002: Unterminated string literal. -tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(43,21): error TS1108: A 'return' statement can only be used within a function body. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(46,13): error TS1005: 'try' expected. -tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(55,13): error TS1108: A 'return' statement can only be used within a function body. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(58,5): error TS1128: Declaration or statement expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(69,13): error TS1109: Expression expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(72,37): error TS1127: Invalid character. @@ -35,10 +32,8 @@ tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(234,14): error T tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(235,9): error TS1128: Declaration or statement expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(235,27): error TS1005: ',' expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(235,36): error TS1005: ';' expected. -tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(236,13): error TS1108: A 'return' statement can only be used within a function body. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(238,9): error TS1128: Declaration or statement expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(238,26): error TS1005: ';' expected. -tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(239,13): error TS1108: A 'return' statement can only be used within a function body. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(241,5): error TS1128: Declaration or statement expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(254,69): error TS1110: Type expected. tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(256,9): error TS1128: Declaration or statement expected. @@ -93,7 +88,7 @@ tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(259,29): error T tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(259,37): error TS2304: Cannot find name 'string'. -==== tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts (93 errors) ==== +==== tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts (88 errors) ==== declare module "fs" { export class File { constructor(filename: string); @@ -153,8 +148,6 @@ tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(259,37): error T !!! error TS2391: Function implementation is missing or not immediately following the declaration. return 1; - ~~~~~~ -!!! error TS1108: A 'return' statement can only be used within a function body. ^ ~ !!! error TS1129: Statement expected. @@ -188,8 +181,6 @@ tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(259,37): error T !!! error TS2304: Cannot find name 'retValue'. return 1; - ~~~~~~ -!!! error TS1108: A 'return' statement can only be used within a function body. } } catch (e) { @@ -208,8 +199,6 @@ tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(259,37): error T !!! error TS2304: Cannot find name 'console'. return 0; - ~~~~~~ -!!! error TS1108: A 'return' statement can only be used within a function body. } } @@ -453,8 +442,6 @@ tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(259,37): error T ~~~~~~ !!! error TS2304: Cannot find name 'number'. return val; - ~~~~~~ -!!! error TS1108: A 'return' statement can only be used within a function body. } public method2() { ~~~~~~ @@ -464,8 +451,6 @@ tests/cases/compiler/constructorWithIncompleteTypeAnnotation.ts(259,37): error T ~~~~~~~ !!! error TS2304: Cannot find name 'method2'. return 2 * this.method1(2); - ~~~~~~ -!!! error TS1108: A 'return' statement can only be used within a function body. } } ~ diff --git a/tests/baselines/reference/interfaceExtendingClass2.errors.txt b/tests/baselines/reference/interfaceExtendingClass2.errors.txt index 83cd97c72c0..1e07199686b 100644 --- a/tests/baselines/reference/interfaceExtendingClass2.errors.txt +++ b/tests/baselines/reference/interfaceExtendingClass2.errors.txt @@ -1,11 +1,10 @@ -tests/cases/conformance/interfaces/interfacesExtendingClasses/interfaceExtendingClass2.ts(13,13): error TS1108: A 'return' statement can only be used within a function body. tests/cases/conformance/interfaces/interfacesExtendingClasses/interfaceExtendingClass2.ts(13,13): error TS1131: Property or signature expected. tests/cases/conformance/interfaces/interfacesExtendingClasses/interfaceExtendingClass2.ts(14,9): error TS1128: Declaration or statement expected. tests/cases/conformance/interfaces/interfacesExtendingClasses/interfaceExtendingClass2.ts(15,5): error TS1128: Declaration or statement expected. tests/cases/conformance/interfaces/interfacesExtendingClasses/interfaceExtendingClass2.ts(11,5): error TS2411: Property 'a' of type '{ toString: () => {}; }' is not assignable to string index type 'Object'. -==== tests/cases/conformance/interfaces/interfacesExtendingClasses/interfaceExtendingClass2.ts (5 errors) ==== +==== tests/cases/conformance/interfaces/interfacesExtendingClasses/interfaceExtendingClass2.ts (4 errors) ==== class Foo { x: string; y() { } @@ -23,8 +22,6 @@ tests/cases/conformance/interfaces/interfacesExtendingClasses/interfaceExtending !!! error TS2411: Property 'a' of type '{ toString: () => {}; }' is not assignable to string index type 'Object'. return 1; ~~~~~~ -!!! error TS1108: A 'return' statement can only be used within a function body. - ~~~~~~ !!! error TS1131: Property or signature expected. }; ~ diff --git a/tests/baselines/reference/overloadOnConstAsTypeAnnotation.errors.txt b/tests/baselines/reference/overloadOnConstAsTypeAnnotation.errors.txt index 0d4cd775c56..70530d409b3 100644 --- a/tests/baselines/reference/overloadOnConstAsTypeAnnotation.errors.txt +++ b/tests/baselines/reference/overloadOnConstAsTypeAnnotation.errors.txt @@ -1,13 +1,10 @@ tests/cases/compiler/overloadOnConstAsTypeAnnotation.ts(1,37): error TS1005: ';' expected. -tests/cases/compiler/overloadOnConstAsTypeAnnotation.ts(1,42): error TS1108: A 'return' statement can only be used within a function body. tests/cases/compiler/overloadOnConstAsTypeAnnotation.ts(1,8): error TS2382: Specialized overload signature is not assignable to any non-specialized signature. -==== tests/cases/compiler/overloadOnConstAsTypeAnnotation.ts (3 errors) ==== +==== tests/cases/compiler/overloadOnConstAsTypeAnnotation.ts (2 errors) ==== var f: (x: 'hi') => number = ('hi') => { return 1; }; ~~ !!! error TS1005: ';' expected. - ~~~~~~ -!!! error TS1108: A 'return' statement can only be used within a function body. ~~~~~~~~~~~~~~~~~~~ !!! error TS2382: Specialized overload signature is not assignable to any non-specialized signature. \ No newline at end of file diff --git a/tests/baselines/reference/parserErrorRecovery_ModuleElement1.errors.txt b/tests/baselines/reference/parserErrorRecovery_ModuleElement1.errors.txt index ad23c21ec1b..4b8be3e17ad 100644 --- a/tests/baselines/reference/parserErrorRecovery_ModuleElement1.errors.txt +++ b/tests/baselines/reference/parserErrorRecovery_ModuleElement1.errors.txt @@ -1,19 +1,13 @@ -tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ModuleElements/parserErrorRecovery_ModuleElement1.ts(1,1): error TS1108: A 'return' statement can only be used within a function body. tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ModuleElements/parserErrorRecovery_ModuleElement1.ts(2,1): error TS1128: Declaration or statement expected. -tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ModuleElements/parserErrorRecovery_ModuleElement1.ts(3,1): error TS1108: A 'return' statement can only be used within a function body. tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ModuleElements/parserErrorRecovery_ModuleElement1.ts(4,1): error TS1128: Declaration or statement expected. -==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ModuleElements/parserErrorRecovery_ModuleElement1.ts (4 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/ModuleElements/parserErrorRecovery_ModuleElement1.ts (2 errors) ==== return foo; - ~~~~~~ -!!! error TS1108: A 'return' statement can only be used within a function body. } ~ !!! error TS1128: Declaration or statement expected. return bar; - ~~~~~~ -!!! error TS1108: A 'return' statement can only be used within a function body. } ~ !!! error TS1128: Declaration or statement expected. \ No newline at end of file diff --git a/tests/baselines/reference/parserErrorRecovery_VariableList1.errors.txt b/tests/baselines/reference/parserErrorRecovery_VariableList1.errors.txt index a42ffcdd474..b69cab688f0 100644 --- a/tests/baselines/reference/parserErrorRecovery_VariableList1.errors.txt +++ b/tests/baselines/reference/parserErrorRecovery_VariableList1.errors.txt @@ -1,8 +1,11 @@ +tests/cases/conformance/parser/ecmascript5/ErrorRecovery/VariableLists/parserErrorRecovery_VariableList1.ts(1,6): error TS1009: Trailing comma not allowed. tests/cases/conformance/parser/ecmascript5/ErrorRecovery/VariableLists/parserErrorRecovery_VariableList1.ts(2,1): error TS1108: A 'return' statement can only be used within a function body. -==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/VariableLists/parserErrorRecovery_VariableList1.ts (1 errors) ==== +==== tests/cases/conformance/parser/ecmascript5/ErrorRecovery/VariableLists/parserErrorRecovery_VariableList1.ts (2 errors) ==== var a, + ~ +!!! error TS1009: Trailing comma not allowed. return; ~~~~~~ !!! error TS1108: A 'return' statement can only be used within a function body. \ No newline at end of file diff --git a/tests/baselines/reference/propertyWrappedInTry.errors.txt b/tests/baselines/reference/propertyWrappedInTry.errors.txt index 36608ca7d86..0809067b33b 100644 --- a/tests/baselines/reference/propertyWrappedInTry.errors.txt +++ b/tests/baselines/reference/propertyWrappedInTry.errors.txt @@ -2,14 +2,13 @@ tests/cases/compiler/propertyWrappedInTry.ts(3,5): error TS1068: Unexpected toke tests/cases/compiler/propertyWrappedInTry.ts(5,9): error TS1129: Statement expected. tests/cases/compiler/propertyWrappedInTry.ts(11,5): error TS1128: Declaration or statement expected. tests/cases/compiler/propertyWrappedInTry.ts(11,18): error TS1005: ';' expected. -tests/cases/compiler/propertyWrappedInTry.ts(13,9): error TS1108: A 'return' statement can only be used within a function body. tests/cases/compiler/propertyWrappedInTry.ts(17,1): error TS1128: Declaration or statement expected. tests/cases/compiler/propertyWrappedInTry.ts(5,16): error TS2304: Cannot find name 'bar'. tests/cases/compiler/propertyWrappedInTry.ts(5,22): error TS2304: Cannot find name 'someInitThatMightFail'. tests/cases/compiler/propertyWrappedInTry.ts(11,12): error TS2304: Cannot find name 'baz'. -==== tests/cases/compiler/propertyWrappedInTry.ts (9 errors) ==== +==== tests/cases/compiler/propertyWrappedInTry.ts (8 errors) ==== class Foo { try { @@ -37,8 +36,6 @@ tests/cases/compiler/propertyWrappedInTry.ts(11,12): error TS2304: Cannot find n !!! error TS2304: Cannot find name 'baz'. return this.bar; // doesn't get rewritten to Foo.bar. - ~~~~~~ -!!! error TS1108: A 'return' statement can only be used within a function body. } diff --git a/tests/baselines/reference/switchStatementsWithMultipleDefaults.errors.txt b/tests/baselines/reference/switchStatementsWithMultipleDefaults.errors.txt index cd892f5faa2..9c46389e906 100644 --- a/tests/baselines/reference/switchStatementsWithMultipleDefaults.errors.txt +++ b/tests/baselines/reference/switchStatementsWithMultipleDefaults.errors.txt @@ -1,7 +1,9 @@ +tests/cases/compiler/switchStatementsWithMultipleDefaults.ts(9,5): error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement. +tests/cases/compiler/switchStatementsWithMultipleDefaults.ts(10,5): error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement. tests/cases/compiler/switchStatementsWithMultipleDefaults.ts(28,22): error TS1108: A 'return' statement can only be used within a function body. -==== tests/cases/compiler/switchStatementsWithMultipleDefaults.ts (1 errors) ==== +==== tests/cases/compiler/switchStatementsWithMultipleDefaults.ts (3 errors) ==== var x = 10; @@ -11,7 +13,11 @@ tests/cases/compiler/switchStatementsWithMultipleDefaults.ts(28,22): error TS110 default: // No issues. break; default: // Error; second 'default' clause. + ~~~~~~~~ +!!! error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement. default: // Error; third 'default' clause. + ~~~~~~~~ +!!! error TS1113: A 'default' clause cannot appear more than once in a 'switch' statement. case 3: x *= x; }