Merge pull request #9995 from Microsoft/jsdoc-string-literal-types

JSDoc string literal types
This commit is contained in:
Nathan Shively-Sanders
2016-08-17 10:25:58 -07:00
committed by GitHub
8 changed files with 136 additions and 3 deletions

View File

@@ -5552,6 +5552,8 @@ namespace ts {
return getTypeFromThisTypeNode(node);
case SyntaxKind.LiteralType:
return getTypeFromLiteralTypeNode(<LiteralTypeNode>node);
case SyntaxKind.JSDocLiteralType:
return getTypeFromLiteralTypeNode((<JSDocLiteralType>node).literal);
case SyntaxKind.TypeReference:
case SyntaxKind.JSDocTypeReference:
return getTypeFromTypeReference(<TypeReferenceNode>node);

View File

@@ -417,6 +417,8 @@ namespace ts {
case SyntaxKind.JSDocPropertyTag:
return visitNode(cbNode, (<JSDocPropertyTag>node).typeExpression) ||
visitNode(cbNode, (<JSDocPropertyTag>node).name);
case SyntaxKind.JSDocLiteralType:
return visitNode(cbNode, (<JSDocLiteralType>node).literal);
}
}
@@ -5889,9 +5891,13 @@ namespace ts {
case SyntaxKind.SymbolKeyword:
case SyntaxKind.VoidKeyword:
return parseTokenNode<JSDocType>();
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
case SyntaxKind.TrueKeyword:
case SyntaxKind.FalseKeyword:
return parseJSDocLiteralType();
}
// TODO (drosen): Parse string literal types in JSDoc as well.
return parseJSDocTypeReference();
}
@@ -6070,6 +6076,12 @@ namespace ts {
return finishNode(result);
}
function parseJSDocLiteralType(): JSDocLiteralType {
const result = <JSDocLiteralType>createNode(SyntaxKind.JSDocLiteralType);
result.literal = parseLiteralTypeNode();
return finishNode(result);
}
function parseJSDocUnknownOrNullableType(): JSDocUnknownType | JSDocNullableType {
const pos = scanner.getStartPos();
// skip the ?

View File

@@ -350,6 +350,7 @@ namespace ts {
JSDocTypedefTag,
JSDocPropertyTag,
JSDocTypeLiteral,
JSDocLiteralType,
// Synthesized list
SyntaxList,
@@ -380,9 +381,9 @@ namespace ts {
LastBinaryOperator = CaretEqualsToken,
FirstNode = QualifiedName,
FirstJSDocNode = JSDocTypeExpression,
LastJSDocNode = JSDocTypeLiteral,
LastJSDocNode = JSDocLiteralType,
FirstJSDocTagNode = JSDocComment,
LastJSDocTagNode = JSDocTypeLiteral
LastJSDocTagNode = JSDocLiteralType
}
export const enum NodeFlags {
@@ -1502,6 +1503,10 @@ namespace ts {
type: JSDocType;
}
export interface JSDocLiteralType extends JSDocType {
literal: LiteralTypeNode;
}
export type JSDocTypeReferencingNode = JSDocThisType | JSDocConstructorType | JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType;
// @kind(SyntaxKind.JSDocRecordMember)

View File

@@ -0,0 +1,24 @@
//// [in.js]
/**
* @param {'literal'} p1
* @param {"literal"} p2
* @param {'literal' | 'other'} p3
* @param {'literal' | number} p4
* @param {12 | true | 'str'} p5
*/
function f(p1, p2, p3, p4, p5) {
return p1 + p2 + p3 + p4 + p5 + '.';
}
//// [out.js]
/**
* @param {'literal'} p1
* @param {"literal"} p2
* @param {'literal' | 'other'} p3
* @param {'literal' | number} p4
* @param {12 | true | 'str'} p5
*/
function f(p1, p2, p3, p4, p5) {
return p1 + p2 + p3 + p4 + p5 + '.';
}

View File

@@ -0,0 +1,24 @@
=== tests/cases/conformance/jsdoc/in.js ===
/**
* @param {'literal'} p1
* @param {"literal"} p2
* @param {'literal' | 'other'} p3
* @param {'literal' | number} p4
* @param {12 | true | 'str'} p5
*/
function f(p1, p2, p3, p4, p5) {
>f : Symbol(f, Decl(in.js, 0, 0))
>p1 : Symbol(p1, Decl(in.js, 7, 11))
>p2 : Symbol(p2, Decl(in.js, 7, 14))
>p3 : Symbol(p3, Decl(in.js, 7, 18))
>p4 : Symbol(p4, Decl(in.js, 7, 22))
>p5 : Symbol(p5, Decl(in.js, 7, 26))
return p1 + p2 + p3 + p4 + p5 + '.';
>p1 : Symbol(p1, Decl(in.js, 7, 11))
>p2 : Symbol(p2, Decl(in.js, 7, 14))
>p3 : Symbol(p3, Decl(in.js, 7, 18))
>p4 : Symbol(p4, Decl(in.js, 7, 22))
>p5 : Symbol(p5, Decl(in.js, 7, 26))
}

View File

@@ -0,0 +1,30 @@
=== tests/cases/conformance/jsdoc/in.js ===
/**
* @param {'literal'} p1
* @param {"literal"} p2
* @param {'literal' | 'other'} p3
* @param {'literal' | number} p4
* @param {12 | true | 'str'} p5
*/
function f(p1, p2, p3, p4, p5) {
>f : (p1: "literal", p2: "literal", p3: "literal" | "other", p4: number | "literal", p5: true | 12 | "str") => string
>p1 : "literal"
>p2 : "literal"
>p3 : "literal" | "other"
>p4 : number | "literal"
>p5 : true | 12 | "str"
return p1 + p2 + p3 + p4 + p5 + '.';
>p1 + p2 + p3 + p4 + p5 + '.' : string
>p1 + p2 + p3 + p4 + p5 : string
>p1 + p2 + p3 + p4 : string
>p1 + p2 + p3 : string
>p1 + p2 : string
>p1 : "literal"
>p2 : "literal"
>p3 : "literal" | "other"
>p4 : number | "literal"
>p5 : true | 12 | "str"
>'.' : string
}

View File

@@ -0,0 +1,13 @@
// @allowJs: true
// @filename: in.js
// @out: out.js
/**
* @param {'literal'} p1
* @param {"literal"} p2
* @param {'literal' | 'other'} p3
* @param {'literal' | number} p4
* @param {12 | true | 'str'} p5
*/
function f(p1, p2, p3, p4, p5) {
return p1 + p2 + p3 + p4 + p5 + '.';
}

View File

@@ -0,0 +1,23 @@
/// <reference path='fourslash.ts'/>
// @allowJs: true
// @Filename: in.js
/////** I am documentation
//// * @param {'literal'} p1
//// * @param {"literal"} p2
//// * @param {'other1' | 'other2'} p3
//// * @param {'literal' | number} p4
//// * @param {12 | true} p5
//// */
////function f(p1, p2, p3, p4, p5) {
//// return p1 + p2 + p3 + p4 + p5 + '.';
////}
////f/*1*/('literal', 'literal', "o/*2*/ther1", 12);
goTo.marker('1');
verify.quickInfoExists();
verify.quickInfoIs('function f(p1: "literal", p2: "literal", p3: "other1" | "other2", p4: number | "literal", p5: true | 12): string', 'I am documentation');
goTo.marker('2');
verify.completionListContains("other1");
verify.completionListContains("other2");
verify.memberListCount(2);