Skip to content

Commit 43f71ca

Browse files
committed
Merge branch 'master' into test262RunnerUpdates
2 parents 804ede2 + c075fe1 commit 43f71ca

4 files changed

Lines changed: 92 additions & 110 deletions

File tree

src/compiler/parser.ts

Lines changed: 72 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,6 +1386,7 @@ module ts {
13861386
if (inGeneratorParameterContext()) {
13871387
setYieldContext(false);
13881388
}
1389+
13891390
node.expression = allowInAnd(parseExpression);
13901391
if (inGeneratorParameterContext()) {
13911392
setYieldContext(yieldContext);
@@ -1405,15 +1406,17 @@ module ts {
14051406
}
14061407

14071408
function parseAnyContextualModifier(): boolean {
1408-
return isModifier(token) && tryParse(() => {
1409-
if (token === SyntaxKind.ConstKeyword) {
1410-
// 'const' is only a modifier if followed by 'enum'.
1411-
return nextToken() === SyntaxKind.EnumKeyword;
1412-
}
1409+
return isModifier(token) && tryParse(nextTokenCanFollowContextualModifier);
1410+
}
14131411

1414-
nextToken();
1415-
return canFollowModifier();
1416-
});
1412+
function nextTokenCanFollowContextualModifier() {
1413+
if (token === SyntaxKind.ConstKeyword) {
1414+
// 'const' is only a modifier if followed by 'enum'.
1415+
return nextToken() === SyntaxKind.EnumKeyword;
1416+
}
1417+
1418+
nextToken();
1419+
return canFollowModifier();
14171420
}
14181421

14191422
function canFollowModifier(): boolean {
@@ -2531,56 +2534,55 @@ module ts {
25312534

25322535
function parseSimpleArrowFunctionExpression(identifier: Identifier): Expression {
25332536
Debug.assert(token === SyntaxKind.EqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>");
2537+
2538+
var node = <FunctionExpression>createNode(SyntaxKind.ArrowFunction, identifier.pos);
2539+
25342540
var parameter = <ParameterDeclaration>createNode(SyntaxKind.Parameter, identifier.pos);
2535-
parseExpected(SyntaxKind.EqualsGreaterThanToken);
25362541
parameter.name = identifier;
25372542
finishNode(parameter);
25382543

2539-
var parameters = <NodeArray<ParameterDeclaration>>[];
2540-
parameters.push(parameter);
2541-
parameters.pos = parameter.pos;
2542-
parameters.end = parameter.end;
2544+
node.parameters = <NodeArray<ParameterDeclaration>>[parameter];
2545+
node.parameters.pos = parameter.pos;
2546+
node.parameters.end = parameter.end;
25432547

2544-
var signature = <ParsedSignature>{ parameters: parameters };
2548+
parseExpected(SyntaxKind.EqualsGreaterThanToken);
2549+
node.body = parseArrowFunctionExpressionBody();
25452550

2546-
return parseArrowExpressionTail(identifier.pos, signature);
2551+
return finishNode(node);
25472552
}
25482553

25492554
function tryParseParenthesizedArrowFunctionExpression(): Expression {
2550-
// Indicates whether we are certain that we should parse an arrow expression.
25512555
var triState = isParenthesizedArrowFunctionExpression();
25522556

25532557
if (triState === Tristate.False) {
2558+
// It's definitely not a parenthesized arrow function expression.
25542559
return undefined;
25552560
}
25562561

2557-
var pos = getNodePos();
2558-
2559-
if (triState === Tristate.True) {
2560-
// Arrow function are never generators.
2561-
var sig = parseSignature(/*yieldAndGeneratorParameterContext:*/ false);
2562+
// If we definitely have an arrow function, then we can just parse one, not requiring a
2563+
// following => or { token. Otherwise, we *might* have an arrow function. Try to parse
2564+
// it out, but don't allow any ambiguity, and return 'undefined' if this could be an
2565+
// expression instead.
2566+
var arrowFunction = triState === Tristate.True
2567+
? parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity:*/ true)
2568+
: tryParse(parsePossibleParenthesizedArrowFunctionExpressionHead);
25622569

2563-
// If we have an arrow, then try to parse the body.
2564-
// Even if not, try to parse if we have an opening brace, just in case we're in an error state.
2565-
if (parseExpected(SyntaxKind.EqualsGreaterThanToken) || token === SyntaxKind.OpenBraceToken) {
2566-
return parseArrowExpressionTail(pos, sig);
2567-
}
2568-
else {
2569-
// If not, we're probably better off bailing out and returning a bogus function expression.
2570-
return makeFunctionExpression(SyntaxKind.ArrowFunction, pos, /*asteriskToken:*/ undefined, /*name:*/ undefined, sig, parseIdentifier(Diagnostics.Expression_expected));
2571-
}
2570+
if (!arrowFunction) {
2571+
// Didn't appear to actually be a parenthesized arrow function. Just bail out.
2572+
return undefined;
25722573
}
2573-
2574-
// *Maybe* we had an arrow function and we need to try to parse it out,
2575-
// rolling back and trying other parses if we fail.
2576-
var sig = tryParseSignatureIfArrowOrBraceFollows();
2577-
if (sig) {
2578-
parseExpected(SyntaxKind.EqualsGreaterThanToken);
2579-
return parseArrowExpressionTail(pos, sig);
2574+
2575+
// If we have an arrow, then try to parse the body. Even if not, try to parse if we
2576+
// have an opening brace, just in case we're in an error state.
2577+
if (parseExpected(SyntaxKind.EqualsGreaterThanToken) || token === SyntaxKind.OpenBraceToken) {
2578+
arrowFunction.body = parseArrowFunctionExpressionBody();
25802579
}
25812580
else {
2582-
return undefined;
2581+
// If not, we're probably better off bailing out and returning a bogus function expression.
2582+
arrowFunction.body = parseIdentifier();
25832583
}
2584+
2585+
return finishNode(arrowFunction);
25842586
}
25852587

25862588
// True -> We definitely expect a parenthesized arrow function here.
@@ -2662,34 +2664,37 @@ module ts {
26622664
}
26632665
}
26642666

2665-
function tryParseSignatureIfArrowOrBraceFollows(): ParsedSignature {
2666-
return tryParse(() => {
2667-
// Arrow functions are never generators.
2668-
var sig = parseSignature(/*yieldAndGeneratorParameterContext:*/ false);
2667+
function parsePossibleParenthesizedArrowFunctionExpressionHead() {
2668+
return parseParenthesizedArrowFunctionExpressionHead(/*allowAmbiguity:*/ false);
2669+
}
26692670

2670-
// Parsing a signature isn't enough.
2671-
// Parenthesized arrow signatures often look like other valid expressions.
2672-
// For instance:
2673-
// - "(x = 10)" is an assignment expression parsed as a signature with a default parameter value.
2674-
// - "(x,y)" is a comma expression parsed as a signature with two parameters.
2675-
// - "a ? (b): c" will have "(b):" parsed as a signature with a return type annotation.
2676-
//
2677-
// So we need just a bit of lookahead to ensure that it can only be a signature.
2678-
if (token === SyntaxKind.EqualsGreaterThanToken || token === SyntaxKind.OpenBraceToken) {
2679-
return sig;
2680-
}
2671+
function parseParenthesizedArrowFunctionExpressionHead(allowAmbiguity: boolean): FunctionExpression {
2672+
var node = <FunctionExpression>createNode(SyntaxKind.ArrowFunction);
2673+
// Arrow functions are never generators.
2674+
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ false, node);
26812675

2676+
// Parsing a signature isn't enough.
2677+
// Parenthesized arrow signatures often look like other valid expressions.
2678+
// For instance:
2679+
// - "(x = 10)" is an assignment expression parsed as a signature with a default parameter value.
2680+
// - "(x,y)" is a comma expression parsed as a signature with two parameters.
2681+
// - "a ? (b): c" will have "(b):" parsed as a signature with a return type annotation.
2682+
//
2683+
// So we need just a bit of lookahead to ensure that it can only be a signature.
2684+
if (!allowAmbiguity && token !== SyntaxKind.EqualsGreaterThanToken && token !== SyntaxKind.OpenBraceToken) {
2685+
// Returning undefined here will cause our caller to rewind to where we started from.
26822686
return undefined;
2683-
});
2684-
}
2687+
}
26852688

2686-
function parseArrowExpressionTail(pos: number, sig: ParsedSignature): FunctionExpression {
2687-
var body: Block | Expression;
2689+
return node;
2690+
}
26882691

2692+
function parseArrowFunctionExpressionBody(): Block | Expression {
26892693
if (token === SyntaxKind.OpenBraceToken) {
2690-
body = parseFunctionBlock(/*allowYield:*/ false, /* ignoreMissingOpenBrace */ false);
2694+
return parseFunctionBlock(/*allowYield:*/ false, /* ignoreMissingOpenBrace */ false);
26912695
}
2692-
else if (isStatement(/* inErrorRecovery */ true) && !isStartOfExpressionStatement() && token !== SyntaxKind.FunctionKeyword) {
2696+
2697+
if (isStatement(/* inErrorRecovery */ true) && !isStartOfExpressionStatement() && token !== SyntaxKind.FunctionKeyword) {
26932698
// Check if we got a plain statement (i.e. no expression-statements, no functions expressions/declarations)
26942699
//
26952700
// Here we try to recover from a potential error situation in the case where the
@@ -2704,13 +2709,10 @@ module ts {
27042709
// up preemptively closing the containing construct.
27052710
//
27062711
// Note: even when 'ignoreMissingOpenBrace' is passed as true, parseBody will still error.
2707-
body = parseFunctionBlock(/*allowYield:*/ false, /* ignoreMissingOpenBrace */ true);
2708-
}
2709-
else {
2710-
body = parseAssignmentExpressionOrHigher();
2712+
return parseFunctionBlock(/*allowYield:*/ false, /* ignoreMissingOpenBrace */ true);
27112713
}
27122714

2713-
return makeFunctionExpression(SyntaxKind.ArrowFunction, pos, /*asteriskToken:*/ undefined, /*name:*/ undefined, sig, body);
2715+
return parseAssignmentExpressionOrHigher();
27142716
}
27152717

27162718
function parseConditionalExpressionRest(leftOperand: Expression): Expression {
@@ -3233,15 +3235,13 @@ module ts {
32333235
// function * BindingIdentifier[Yield]opt (FormalParameters[Yield, GeneratorParameter]) { GeneratorBody[Yield] }
32343236
// FunctionExpression:
32353237
// function BindingIdentifieropt(FormalParameters) { FunctionBody }
3236-
3237-
var pos = getNodePos();
3238+
var node = <FunctionExpression>createNode(SyntaxKind.FunctionExpression);
32383239
parseExpected(SyntaxKind.FunctionKeyword);
3239-
var asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
3240-
var name = asteriskToken ? doInYieldContext(parseOptionalIdentifier) : parseOptionalIdentifier();
3241-
var sig = parseSignature(/*yieldAndGeneratorParameterContext:*/ !!asteriskToken);
3242-
3243-
var body = parseFunctionBlock(/*allowYield:*/ !!asteriskToken, /* ignoreMissingOpenBrace */ false);
3244-
return makeFunctionExpression(SyntaxKind.FunctionExpression, pos, asteriskToken, name, sig, body);
3240+
node.asteriskToken = parseOptionalToken(SyntaxKind.AsteriskToken);
3241+
node.name = node.asteriskToken ? doInYieldContext(parseOptionalIdentifier) : parseOptionalIdentifier();
3242+
fillSignature(SyntaxKind.ColonToken, /*yieldAndGeneratorParameterContext:*/ !!node.asteriskToken, node);
3243+
node.body = parseFunctionBlock(/*allowYield:*/ !!node.asteriskToken, /* ignoreMissingOpenBrace */ false);
3244+
return finishNode(node);
32453245
}
32463246

32473247
function parseOptionalIdentifier() {

src/services/services.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3807,6 +3807,10 @@ module ts {
38073807
return undefined;
38083808
}
38093809
}
3810+
else {
3811+
// unsupported modifier
3812+
return undefined;
3813+
}
38103814

38113815
var keywords: Node[] = [];
38123816
var modifierFlag: NodeFlags = getFlagFromModifier(modifier);

tests/baselines/reference/contextualTypeWithUnionTypeCallSignatures.js

Lines changed: 2 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -45,42 +45,6 @@ var x = function (a) { return a.toString(); };
4545
var x2 = function (a) { return a.toString(); }; // Like iWithCallSignatures
4646
var x2 = function (a) { return a; }; // Like iWithCallSignatures2
4747
// With call signatures of mismatching parameter type
48-
var x3 = function (a /*here a should be any*/) { return a.toString(); };
48+
var x3 = function (a) { return a.toString(); };
4949
// With call signature count mismatch
50-
var x4 = function (a //When used as a contextual type, a union type U has those members that are present in any of
51-
// its constituent types, with types that are unions of the respective members in the constituent types.
52-
53-
// Let S be the set of types in U that have call signatures.
54-
// If S is not empty and the sets of call signatures of the types in S are identical ignoring return types,
55-
// U has the same set of call signatures, but with return types that are unions of the return types of the respective call signatures from each type in S.
56-
57-
interface IWithNoCallSignatures {
58-
foo: string;
59-
}
60-
interface IWithCallSignatures {
61-
(a: number): string;
62-
}
63-
interface IWithCallSignatures2 {
64-
(a: number): number;
65-
}
66-
interface IWithCallSignatures3 {
67-
(b: string): number;
68-
}
69-
interface IWithCallSignatures4 {
70-
(a: number): string;
71-
(a: string, b: number): number;
72-
}
73-
74-
// With no call signature | callSignatures
75-
var x: IWithNoCallSignatures | IWithCallSignatures = a => a.toString();
76-
77-
// With call signatures with different return type
78-
var x2: IWithCallSignatures | IWithCallSignatures2 = a => a.toString(); // Like iWithCallSignatures
79-
var x2: IWithCallSignatures | IWithCallSignatures2 = a => a; // Like iWithCallSignatures2
80-
81-
// With call signatures of mismatching parameter type
82-
var x3: IWithCallSignatures | IWithCallSignatures3 = a => /*here a should be any*/ a.toString();
83-
84-
// With call signature count mismatch
85-
var x4: IWithCallSignatures | IWithCallSignatures4 = a =>
86-
) { return a.toString(); };
50+
var x4 = function (a) { return a.toString(); };
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
/////*1*/const enum E1 {
4+
//// v1,
5+
//// v2
6+
////}
7+
////
8+
/////*2*/const c = 0;
9+
10+
goTo.marker("1");
11+
verify.occurrencesAtPositionCount(0);
12+
13+
goTo.marker("2");
14+
verify.occurrencesAtPositionCount(0);

0 commit comments

Comments
 (0)