Skip to content

Commit c218d37

Browse files
authored
Merge pull request #9995 from Microsoft/jsdoc-string-literal-types
JSDoc string literal types
2 parents 0006371 + 3c32478 commit c218d37

File tree

8 files changed

+136
-3
lines changed

8 files changed

+136
-3
lines changed

src/compiler/checker.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5552,6 +5552,8 @@ namespace ts {
55525552
return getTypeFromThisTypeNode(node);
55535553
case SyntaxKind.LiteralType:
55545554
return getTypeFromLiteralTypeNode(<LiteralTypeNode>node);
5555+
case SyntaxKind.JSDocLiteralType:
5556+
return getTypeFromLiteralTypeNode((<JSDocLiteralType>node).literal);
55555557
case SyntaxKind.TypeReference:
55565558
case SyntaxKind.JSDocTypeReference:
55575559
return getTypeFromTypeReference(<TypeReferenceNode>node);

src/compiler/parser.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,8 @@ namespace ts {
417417
case SyntaxKind.JSDocPropertyTag:
418418
return visitNode(cbNode, (<JSDocPropertyTag>node).typeExpression) ||
419419
visitNode(cbNode, (<JSDocPropertyTag>node).name);
420+
case SyntaxKind.JSDocLiteralType:
421+
return visitNode(cbNode, (<JSDocLiteralType>node).literal);
420422
}
421423
}
422424

@@ -5889,9 +5891,13 @@ namespace ts {
58895891
case SyntaxKind.SymbolKeyword:
58905892
case SyntaxKind.VoidKeyword:
58915893
return parseTokenNode<JSDocType>();
5894+
case SyntaxKind.StringLiteral:
5895+
case SyntaxKind.NumericLiteral:
5896+
case SyntaxKind.TrueKeyword:
5897+
case SyntaxKind.FalseKeyword:
5898+
return parseJSDocLiteralType();
58925899
}
58935900

5894-
// TODO (drosen): Parse string literal types in JSDoc as well.
58955901
return parseJSDocTypeReference();
58965902
}
58975903

@@ -6070,6 +6076,12 @@ namespace ts {
60706076
return finishNode(result);
60716077
}
60726078

6079+
function parseJSDocLiteralType(): JSDocLiteralType {
6080+
const result = <JSDocLiteralType>createNode(SyntaxKind.JSDocLiteralType);
6081+
result.literal = parseLiteralTypeNode();
6082+
return finishNode(result);
6083+
}
6084+
60736085
function parseJSDocUnknownOrNullableType(): JSDocUnknownType | JSDocNullableType {
60746086
const pos = scanner.getStartPos();
60756087
// skip the ?

src/compiler/types.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ namespace ts {
350350
JSDocTypedefTag,
351351
JSDocPropertyTag,
352352
JSDocTypeLiteral,
353+
JSDocLiteralType,
353354

354355
// Synthesized list
355356
SyntaxList,
@@ -380,9 +381,9 @@ namespace ts {
380381
LastBinaryOperator = CaretEqualsToken,
381382
FirstNode = QualifiedName,
382383
FirstJSDocNode = JSDocTypeExpression,
383-
LastJSDocNode = JSDocTypeLiteral,
384+
LastJSDocNode = JSDocLiteralType,
384385
FirstJSDocTagNode = JSDocComment,
385-
LastJSDocTagNode = JSDocTypeLiteral
386+
LastJSDocTagNode = JSDocLiteralType
386387
}
387388

388389
export const enum NodeFlags {
@@ -1502,6 +1503,10 @@ namespace ts {
15021503
type: JSDocType;
15031504
}
15041505

1506+
export interface JSDocLiteralType extends JSDocType {
1507+
literal: LiteralTypeNode;
1508+
}
1509+
15051510
export type JSDocTypeReferencingNode = JSDocThisType | JSDocConstructorType | JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType;
15061511

15071512
// @kind(SyntaxKind.JSDocRecordMember)
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//// [in.js]
2+
/**
3+
* @param {'literal'} p1
4+
* @param {"literal"} p2
5+
* @param {'literal' | 'other'} p3
6+
* @param {'literal' | number} p4
7+
* @param {12 | true | 'str'} p5
8+
*/
9+
function f(p1, p2, p3, p4, p5) {
10+
return p1 + p2 + p3 + p4 + p5 + '.';
11+
}
12+
13+
14+
//// [out.js]
15+
/**
16+
* @param {'literal'} p1
17+
* @param {"literal"} p2
18+
* @param {'literal' | 'other'} p3
19+
* @param {'literal' | number} p4
20+
* @param {12 | true | 'str'} p5
21+
*/
22+
function f(p1, p2, p3, p4, p5) {
23+
return p1 + p2 + p3 + p4 + p5 + '.';
24+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
=== tests/cases/conformance/jsdoc/in.js ===
2+
/**
3+
* @param {'literal'} p1
4+
* @param {"literal"} p2
5+
* @param {'literal' | 'other'} p3
6+
* @param {'literal' | number} p4
7+
* @param {12 | true | 'str'} p5
8+
*/
9+
function f(p1, p2, p3, p4, p5) {
10+
>f : Symbol(f, Decl(in.js, 0, 0))
11+
>p1 : Symbol(p1, Decl(in.js, 7, 11))
12+
>p2 : Symbol(p2, Decl(in.js, 7, 14))
13+
>p3 : Symbol(p3, Decl(in.js, 7, 18))
14+
>p4 : Symbol(p4, Decl(in.js, 7, 22))
15+
>p5 : Symbol(p5, Decl(in.js, 7, 26))
16+
17+
return p1 + p2 + p3 + p4 + p5 + '.';
18+
>p1 : Symbol(p1, Decl(in.js, 7, 11))
19+
>p2 : Symbol(p2, Decl(in.js, 7, 14))
20+
>p3 : Symbol(p3, Decl(in.js, 7, 18))
21+
>p4 : Symbol(p4, Decl(in.js, 7, 22))
22+
>p5 : Symbol(p5, Decl(in.js, 7, 26))
23+
}
24+
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
=== tests/cases/conformance/jsdoc/in.js ===
2+
/**
3+
* @param {'literal'} p1
4+
* @param {"literal"} p2
5+
* @param {'literal' | 'other'} p3
6+
* @param {'literal' | number} p4
7+
* @param {12 | true | 'str'} p5
8+
*/
9+
function f(p1, p2, p3, p4, p5) {
10+
>f : (p1: "literal", p2: "literal", p3: "literal" | "other", p4: number | "literal", p5: true | 12 | "str") => string
11+
>p1 : "literal"
12+
>p2 : "literal"
13+
>p3 : "literal" | "other"
14+
>p4 : number | "literal"
15+
>p5 : true | 12 | "str"
16+
17+
return p1 + p2 + p3 + p4 + p5 + '.';
18+
>p1 + p2 + p3 + p4 + p5 + '.' : string
19+
>p1 + p2 + p3 + p4 + p5 : string
20+
>p1 + p2 + p3 + p4 : string
21+
>p1 + p2 + p3 : string
22+
>p1 + p2 : string
23+
>p1 : "literal"
24+
>p2 : "literal"
25+
>p3 : "literal" | "other"
26+
>p4 : number | "literal"
27+
>p5 : true | 12 | "str"
28+
>'.' : string
29+
}
30+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// @allowJs: true
2+
// @filename: in.js
3+
// @out: out.js
4+
/**
5+
* @param {'literal'} p1
6+
* @param {"literal"} p2
7+
* @param {'literal' | 'other'} p3
8+
* @param {'literal' | number} p4
9+
* @param {12 | true | 'str'} p5
10+
*/
11+
function f(p1, p2, p3, p4, p5) {
12+
return p1 + p2 + p3 + p4 + p5 + '.';
13+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/// <reference path='fourslash.ts'/>
2+
// @allowJs: true
3+
// @Filename: in.js
4+
/////** I am documentation
5+
//// * @param {'literal'} p1
6+
//// * @param {"literal"} p2
7+
//// * @param {'other1' | 'other2'} p3
8+
//// * @param {'literal' | number} p4
9+
//// * @param {12 | true} p5
10+
//// */
11+
////function f(p1, p2, p3, p4, p5) {
12+
//// return p1 + p2 + p3 + p4 + p5 + '.';
13+
////}
14+
////f/*1*/('literal', 'literal', "o/*2*/ther1", 12);
15+
16+
goTo.marker('1');
17+
verify.quickInfoExists();
18+
verify.quickInfoIs('function f(p1: "literal", p2: "literal", p3: "other1" | "other2", p4: number | "literal", p5: true | 12): string', 'I am documentation');
19+
20+
goTo.marker('2');
21+
verify.completionListContains("other1");
22+
verify.completionListContains("other2");
23+
verify.memberListCount(2);

0 commit comments

Comments
 (0)