Skip to content

Commit 4d8663c

Browse files
authored
Merge pull request #18117 from Microsoft/jsdoc-dotdotdot-binds-tighter-than-postfix
Jsdoc ... binds tighter than postfix ?!
2 parents ae3f29a + a0504fc commit 4d8663c

File tree

5 files changed

+82
-53
lines changed

5 files changed

+82
-53
lines changed

src/compiler/parser.ts

Lines changed: 39 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -2180,7 +2180,7 @@ namespace ts {
21802180
function parseJSDocNodeWithType(kind: SyntaxKind.JSDocVariadicType | SyntaxKind.JSDocNonNullableType): TypeNode {
21812181
const result = createNode(kind) as JSDocVariadicType | JSDocNonNullableType;
21822182
nextToken();
2183-
result.type = parseType();
2183+
result.type = parseNonArrayType();
21842184
return finishNode(result);
21852185
}
21862186

@@ -2733,47 +2733,51 @@ namespace ts {
27332733
return token() === SyntaxKind.CloseParenToken || isStartOfParameter() || isStartOfType();
27342734
}
27352735

2736-
function parseJSDocPostfixTypeOrHigher(): TypeNode {
2737-
const type = parseNonArrayType();
2738-
const kind = getKind(token());
2739-
if (!kind) return type;
2740-
nextToken();
2741-
2742-
const postfix = createNode(kind, type.pos) as JSDocOptionalType | JSDocNonNullableType | JSDocNullableType;
2743-
postfix.type = type;
2744-
return finishNode(postfix);
2745-
2746-
function getKind(tokenKind: SyntaxKind): SyntaxKind | undefined {
2747-
switch (tokenKind) {
2736+
function parsePostfixTypeOrHigher(): TypeNode {
2737+
let type = parseNonArrayType();
2738+
while (!scanner.hasPrecedingLineBreak()) {
2739+
switch (token()) {
27482740
case SyntaxKind.EqualsToken:
27492741
// only parse postfix = inside jsdoc, because it's ambiguous elsewhere
2750-
return contextFlags & NodeFlags.JSDoc ? SyntaxKind.JSDocOptionalType : undefined;
2742+
if (!(contextFlags & NodeFlags.JSDoc)) {
2743+
return type;
2744+
}
2745+
type = createJSDocPostfixType(SyntaxKind.JSDocOptionalType, type);
2746+
break;
27512747
case SyntaxKind.ExclamationToken:
2752-
return SyntaxKind.JSDocNonNullableType;
2748+
type = createJSDocPostfixType(SyntaxKind.JSDocNonNullableType, type);
2749+
break;
27532750
case SyntaxKind.QuestionToken:
2754-
return SyntaxKind.JSDocNullableType;
2751+
type = createJSDocPostfixType(SyntaxKind.JSDocNullableType, type);
2752+
break;
2753+
case SyntaxKind.OpenBracketToken:
2754+
parseExpected(SyntaxKind.OpenBracketToken);
2755+
if (isStartOfType()) {
2756+
const node = createNode(SyntaxKind.IndexedAccessType, type.pos) as IndexedAccessTypeNode;
2757+
node.objectType = type;
2758+
node.indexType = parseType();
2759+
parseExpected(SyntaxKind.CloseBracketToken);
2760+
type = finishNode(node);
2761+
}
2762+
else {
2763+
const node = createNode(SyntaxKind.ArrayType, type.pos) as ArrayTypeNode;
2764+
node.elementType = type;
2765+
parseExpected(SyntaxKind.CloseBracketToken);
2766+
type = finishNode(node);
2767+
}
2768+
break;
2769+
default:
2770+
return type;
27552771
}
27562772
}
2773+
return type;
27572774
}
27582775

2759-
function parseArrayTypeOrHigher(): TypeNode {
2760-
let type = parseJSDocPostfixTypeOrHigher();
2761-
while (!scanner.hasPrecedingLineBreak() && parseOptional(SyntaxKind.OpenBracketToken)) {
2762-
if (isStartOfType()) {
2763-
const node = <IndexedAccessTypeNode>createNode(SyntaxKind.IndexedAccessType, type.pos);
2764-
node.objectType = type;
2765-
node.indexType = parseType();
2766-
parseExpected(SyntaxKind.CloseBracketToken);
2767-
type = finishNode(node);
2768-
}
2769-
else {
2770-
const node = <ArrayTypeNode>createNode(SyntaxKind.ArrayType, type.pos);
2771-
node.elementType = type;
2772-
parseExpected(SyntaxKind.CloseBracketToken);
2773-
type = finishNode(node);
2774-
}
2775-
}
2776-
return type;
2776+
function createJSDocPostfixType(kind: SyntaxKind, type: TypeNode) {
2777+
nextToken();
2778+
const postfix = createNode(kind, type.pos) as JSDocOptionalType | JSDocNonNullableType | JSDocNullableType;
2779+
postfix.type = type;
2780+
return finishNode(postfix);
27772781
}
27782782

27792783
function parseTypeOperator(operator: SyntaxKind.KeyOfKeyword) {
@@ -2789,7 +2793,7 @@ namespace ts {
27892793
case SyntaxKind.KeyOfKeyword:
27902794
return parseTypeOperator(SyntaxKind.KeyOfKeyword);
27912795
}
2792-
return parseArrayTypeOrHigher();
2796+
return parsePostfixTypeOrHigher();
27932797
}
27942798

27952799
function parseUnionOrIntersectionType(kind: SyntaxKind.UnionType | SyntaxKind.IntersectionType, parseConstituentType: () => TypeNode, operator: SyntaxKind.BarToken | SyntaxKind.AmpersandToken): TypeNode {

tests/baselines/reference/jsdocPrefixPostfixParsing.symbols

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,28 @@
88
* @param {(number[])?} c - number[] | null
99
* @param {?...number} d - number[] | null
1010
* @param {...?number} e - (number | null)[]
11-
* @param {...number?} f - (number | null)[]
11+
* @param {...number?} f - number[] | null
12+
* @param {...number!?} g - number[] | null
13+
* @param {...number?!} h - number[] | null
14+
* @param {...number[]} i - number[][]
15+
* @param {...number![]?} j - number[][] | null
16+
* @param {...number?[]!} k - (number[] | null)[]
1217
*/
13-
function f(x, y, z, a, b, c, d, e, f) {
18+
function f(x, y, z, a, b, c, d, e, f, g, h, i, j, k) {
1419
>f : Symbol(f, Decl(prefixPostfix.js, 0, 0))
15-
>x : Symbol(x, Decl(prefixPostfix.js, 11, 11))
16-
>y : Symbol(y, Decl(prefixPostfix.js, 11, 13))
17-
>z : Symbol(z, Decl(prefixPostfix.js, 11, 16))
18-
>a : Symbol(a, Decl(prefixPostfix.js, 11, 19))
19-
>b : Symbol(b, Decl(prefixPostfix.js, 11, 22))
20-
>c : Symbol(c, Decl(prefixPostfix.js, 11, 25))
21-
>d : Symbol(d, Decl(prefixPostfix.js, 11, 28))
22-
>e : Symbol(e, Decl(prefixPostfix.js, 11, 31))
23-
>f : Symbol(f, Decl(prefixPostfix.js, 11, 34))
20+
>x : Symbol(x, Decl(prefixPostfix.js, 16, 11))
21+
>y : Symbol(y, Decl(prefixPostfix.js, 16, 13))
22+
>z : Symbol(z, Decl(prefixPostfix.js, 16, 16))
23+
>a : Symbol(a, Decl(prefixPostfix.js, 16, 19))
24+
>b : Symbol(b, Decl(prefixPostfix.js, 16, 22))
25+
>c : Symbol(c, Decl(prefixPostfix.js, 16, 25))
26+
>d : Symbol(d, Decl(prefixPostfix.js, 16, 28))
27+
>e : Symbol(e, Decl(prefixPostfix.js, 16, 31))
28+
>f : Symbol(f, Decl(prefixPostfix.js, 16, 34))
29+
>g : Symbol(g, Decl(prefixPostfix.js, 16, 37))
30+
>h : Symbol(h, Decl(prefixPostfix.js, 16, 40))
31+
>i : Symbol(i, Decl(prefixPostfix.js, 16, 43))
32+
>j : Symbol(j, Decl(prefixPostfix.js, 16, 46))
33+
>k : Symbol(k, Decl(prefixPostfix.js, 16, 49))
2434
}
2535

tests/baselines/reference/jsdocPrefixPostfixParsing.types

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,15 @@
88
* @param {(number[])?} c - number[] | null
99
* @param {?...number} d - number[] | null
1010
* @param {...?number} e - (number | null)[]
11-
* @param {...number?} f - (number | null)[]
11+
* @param {...number?} f - number[] | null
12+
* @param {...number!?} g - number[] | null
13+
* @param {...number?!} h - number[] | null
14+
* @param {...number[]} i - number[][]
15+
* @param {...number![]?} j - number[][] | null
16+
* @param {...number?[]!} k - (number[] | null)[]
1217
*/
13-
function f(x, y, z, a, b, c, d, e, f) {
14-
>f : (x: number[], y: number[], z: number[], a: (number | null)[], b: number[] | null, c: number[] | null, d: number[] | null, ...e: (number | null)[], ...f: (number | null)[]) => void
18+
function f(x, y, z, a, b, c, d, e, f, g, h, i, j, k) {
19+
>f : (x: number[], y: number[], z: number[], a: (number | null)[], b: number[] | null, c: number[] | null, d: number[] | null, ...e: (number | null)[], f: number[] | null, g: number[] | null, h: number[] | null, i: number[][], j: number[][] | null, k: (number[] | null)[]) => void
1520
>x : number[]
1621
>y : number[]
1722
>z : number[]
@@ -20,6 +25,11 @@ function f(x, y, z, a, b, c, d, e, f) {
2025
>c : number[] | null
2126
>d : number[] | null
2227
>e : (number | null)[]
23-
>f : (number | null)[]
28+
>f : number[] | null
29+
>g : number[] | null
30+
>h : number[] | null
31+
>i : number[][]
32+
>j : number[][] | null
33+
>k : (number[] | null)[]
2434
}
2535

tests/cases/conformance/jsdoc/jsdocPrefixPostfixParsing.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@
1515
* @param {(number[])?} c - number[] | null
1616
* @param {?...number} d - number[] | null
1717
* @param {...?number} e - (number | null)[]
18-
* @param {...number?} f - (number | null)[]
18+
* @param {...number?} f - number[] | null
19+
* @param {...number!?} g - number[] | null
20+
* @param {...number?!} h - number[] | null
21+
* @param {...number[]} i - number[][]
22+
* @param {...number![]?} j - number[][] | null
23+
* @param {...number?[]!} k - (number[] | null)[]
1924
*/
20-
function f(x, y, z, a, b, c, d, e, f) {
25+
function f(x, y, z, a, b, c, d, e, f, g, h, i, j, k) {
2126
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
// @strict: true
22
/// <reference path='fourslash.ts' />
33
////type T = [|...number?|];
4-
verify.rangeAfterCodeFix("(number | null)[]");
4+
verify.rangeAfterCodeFix("number[] | null", /*includeWhiteSpace*/ false, /*errorCode*/ 8020, 0);

0 commit comments

Comments
 (0)