Merge pull request #18747 from Microsoft/refactor-jsdoc-types-to-typescript

Refactor jsdoc types to typescript
This commit is contained in:
Nathan Shively-Sanders 2017-10-13 10:21:54 -07:00 committed by GitHub
commit 22769d95e1
26 changed files with 629 additions and 14 deletions

View file

@ -3758,12 +3758,20 @@
"category": "Message",
"code": 95008
},
"Infer type of '{0}' from usage.": {
"Annotate with type from JSDoc": {
"category": "Message",
"code": 95009
},
"Infer parameter types from usage.": {
"Annotate with types from JSDoc": {
"category": "Message",
"code": 95010
},
"Infer type of '{0}' from usage.": {
"category": "Message",
"code": 95011
},
"Infer parameter types from usage.": {
"category": "Message",
"code": 95012
}
}

View file

@ -546,6 +546,8 @@ namespace ts {
return emitTypeReference(<TypeReferenceNode>node);
case SyntaxKind.FunctionType:
return emitFunctionType(<FunctionTypeNode>node);
case SyntaxKind.JSDocFunctionType:
return emitJSDocFunctionType(node as JSDocFunctionType);
case SyntaxKind.ConstructorType:
return emitConstructorType(<ConstructorTypeNode>node);
case SyntaxKind.TypeQuery:
@ -574,6 +576,20 @@ namespace ts {
return emitMappedType(<MappedTypeNode>node);
case SyntaxKind.LiteralType:
return emitLiteralType(<LiteralTypeNode>node);
case SyntaxKind.JSDocAllType:
write("*");
return;
case SyntaxKind.JSDocUnknownType:
write("?");
return;
case SyntaxKind.JSDocNullableType:
return emitJSDocNullableType(node as JSDocNullableType);
case SyntaxKind.JSDocNonNullableType:
return emitJSDocNonNullableType(node as JSDocNonNullableType);
case SyntaxKind.JSDocOptionalType:
return emitJSDocOptionalType(node as JSDocOptionalType);
case SyntaxKind.JSDocVariadicType:
return emitJSDocVariadicType(node as JSDocVariadicType);
// Binding patterns
case SyntaxKind.ObjectBindingPattern:
@ -914,9 +930,16 @@ namespace ts {
emitDecorators(node, node.decorators);
emitModifiers(node, node.modifiers);
emitIfPresent(node.dotDotDotToken);
emit(node.name);
if (node.name) {
emit(node.name);
}
emitIfPresent(node.questionToken);
emitWithPrefix(": ", node.type);
if (node.parent && node.parent.kind === SyntaxKind.JSDocFunctionType && !node.name) {
emit(node.type);
}
else {
emitWithPrefix(": ", node.type);
}
emitExpressionWithPrefix(" = ", node.initializer);
}
@ -1035,6 +1058,29 @@ namespace ts {
emit(node.type);
}
function emitJSDocFunctionType(node: JSDocFunctionType) {
write("function");
emitParameters(node, node.parameters);
write(":");
emit(node.type);
}
function emitJSDocNullableType(node: JSDocNullableType) {
write("?");
emit(node.type);
}
function emitJSDocNonNullableType(node: JSDocNonNullableType) {
write("!");
emit(node.type);
}
function emitJSDocOptionalType(node: JSDocOptionalType) {
emit(node.type);
write("=");
}
function emitConstructorType(node: ConstructorTypeNode) {
write("new ");
emitTypeParameters(node, node.typeParameters);
@ -1060,6 +1106,11 @@ namespace ts {
write("[]");
}
function emitJSDocVariadicType(node: JSDocVariadicType) {
write("...");
emit(node.type);
}
function emitTupleType(node: TupleTypeNode) {
write("[");
emitList(node, node.elementTypes, ListFormat.TupleTypeElements);

View file

@ -2700,11 +2700,11 @@ namespace ts {
* Gets the effective type annotation of a variable, parameter, or property. If the node was
* parsed in a JavaScript file, gets the type annotation from JSDoc.
*/
export function getEffectiveTypeAnnotationNode(node: VariableLikeDeclaration): TypeNode | undefined {
export function getEffectiveTypeAnnotationNode(node: VariableLikeDeclaration, checkJSDoc?: boolean): TypeNode | undefined {
if (node.type) {
return node.type;
}
if (isInJavaScriptFile(node)) {
if (checkJSDoc || isInJavaScriptFile(node)) {
return getJSDocType(node);
}
}
@ -2713,11 +2713,11 @@ namespace ts {
* Gets the effective return type annotation of a signature. If the node was parsed in a
* JavaScript file, gets the return type annotation from JSDoc.
*/
export function getEffectiveReturnTypeNode(node: SignatureDeclaration): TypeNode | undefined {
export function getEffectiveReturnTypeNode(node: SignatureDeclaration, checkJSDoc?: boolean): TypeNode | undefined {
if (node.type) {
return node.type;
}
if (isInJavaScriptFile(node)) {
if (checkJSDoc || isInJavaScriptFile(node)) {
return getJSDocReturnType(node);
}
}
@ -2726,11 +2726,11 @@ namespace ts {
* Gets the effective type parameters. If the node was parsed in a
* JavaScript file, gets the type parameters from the `@template` tag from JSDoc.
*/
export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters): ReadonlyArray<TypeParameterDeclaration> {
export function getEffectiveTypeParameterDeclarations(node: DeclarationWithTypeParameters, checkJSDoc?: boolean): ReadonlyArray<TypeParameterDeclaration> {
if (node.typeParameters) {
return node.typeParameters;
}
if (isInJavaScriptFile(node)) {
if (checkJSDoc || isInJavaScriptFile(node)) {
const templateTag = getJSDocTemplateTag(node);
return templateTag && templateTag.typeParameters;
}
@ -2740,9 +2740,9 @@ namespace ts {
* Gets the effective type annotation of the value parameter of a set accessor. If the node
* was parsed in a JavaScript file, gets the type annotation from JSDoc.
*/
export function getEffectiveSetAccessorTypeAnnotationNode(node: SetAccessorDeclaration): TypeNode {
export function getEffectiveSetAccessorTypeAnnotationNode(node: SetAccessorDeclaration, checkJSDoc?: boolean): TypeNode {
const parameter = getSetAccessorValueParameter(node);
return parameter && getEffectiveTypeAnnotationNode(parameter);
return parameter && getEffectiveTypeAnnotationNode(parameter, checkJSDoc);
}
export function emitNewLineBeforeLeadingComments(lineMap: ReadonlyArray<number>, writer: EmitTextWriter, node: TextRange, leadingComments: ReadonlyArray<CommentRange>) {
@ -5130,7 +5130,14 @@ namespace ts {
|| kind === SyntaxKind.UndefinedKeyword
|| kind === SyntaxKind.NullKeyword
|| kind === SyntaxKind.NeverKeyword
|| kind === SyntaxKind.ExpressionWithTypeArguments;
|| kind === SyntaxKind.ExpressionWithTypeArguments
|| kind === SyntaxKind.JSDocAllType
|| kind === SyntaxKind.JSDocUnknownType
|| kind === SyntaxKind.JSDocNullableType
|| kind === SyntaxKind.JSDocNonNullableType
|| kind === SyntaxKind.JSDocOptionalType
|| kind === SyntaxKind.JSDocFunctionType
|| kind === SyntaxKind.JSDocVariadicType;
}
/**

View file

@ -0,0 +1,226 @@
/* @internal */
namespace ts.refactor.annotateWithTypeFromJSDoc {
const actionName = "annotate";
const annotateTypeFromJSDoc: Refactor = {
name: "Annotate with type from JSDoc",
description: Diagnostics.Annotate_with_type_from_JSDoc.message,
getEditsForAction: getEditsForAnnotation,
getAvailableActions
};
const annotateFunctionFromJSDoc: Refactor = {
name: "Annotate with types from JSDoc",
description: Diagnostics.Annotate_with_types_from_JSDoc.message,
getEditsForAction: getEditsForFunctionAnnotation,
getAvailableActions
};
type DeclarationWithType =
| FunctionLikeDeclaration
| VariableDeclaration
| ParameterDeclaration
| PropertySignature
| PropertyDeclaration;
registerRefactor(annotateTypeFromJSDoc);
registerRefactor(annotateFunctionFromJSDoc);
function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
if (isInJavaScriptFile(context.file)) {
return undefined;
}
const node = getTokenAtPosition(context.file, context.startPosition, /*includeJsDocComment*/ false);
const decl = findAncestor(node, isDeclarationWithType);
if (!decl || decl.type) {
return undefined;
}
const jsdocType = getJSDocType(decl);
const isFunctionWithJSDoc = isFunctionLikeDeclaration(decl) && (getJSDocReturnType(decl) || decl.parameters.some(p => !!getJSDocType(p)));
const refactor = (isFunctionWithJSDoc || jsdocType && decl.kind === SyntaxKind.Parameter) ? annotateFunctionFromJSDoc :
jsdocType ? annotateTypeFromJSDoc :
undefined;
if (refactor) {
return [{
name: refactor.name,
description: refactor.description,
actions: [
{
description: refactor.description,
name: actionName
}
]
}];
}
}
function getEditsForAnnotation(context: RefactorContext, action: string): RefactorEditInfo | undefined {
if (actionName !== action) {
return Debug.fail(`actionName !== action: ${actionName} !== ${action}`);
}
const sourceFile = context.file;
const token = getTokenAtPosition(sourceFile, context.startPosition, /*includeJsDocComment*/ false);
const decl = findAncestor(token, isDeclarationWithType);
const jsdocType = getJSDocType(decl);
if (!decl || !jsdocType || decl.type) {
return Debug.fail(`!decl || !jsdocType || decl.type: !${decl} || !${jsdocType} || ${decl.type}`);
}
const changeTracker = textChanges.ChangeTracker.fromContext(context);
const declarationWithType = addType(decl, transformJSDocType(jsdocType) as TypeNode);
suppressLeadingAndTrailingTrivia(declarationWithType);
changeTracker.replaceRange(sourceFile, { pos: decl.getStart(), end: decl.end }, declarationWithType);
return {
edits: changeTracker.getChanges(),
renameFilename: undefined,
renameLocation: undefined
};
}
function getEditsForFunctionAnnotation(context: RefactorContext, action: string): RefactorEditInfo | undefined {
if (actionName !== action) {
return Debug.fail(`actionName !== action: ${actionName} !== ${action}`);
}
const sourceFile = context.file;
const token = getTokenAtPosition(sourceFile, context.startPosition, /*includeJsDocComment*/ false);
const decl = findAncestor(token, isFunctionLikeDeclaration);
const changeTracker = textChanges.ChangeTracker.fromContext(context);
const functionWithType = addTypesToFunctionLike(decl);
suppressLeadingAndTrailingTrivia(functionWithType);
changeTracker.replaceRange(sourceFile, { pos: decl.getStart(), end: decl.end }, functionWithType);
return {
edits: changeTracker.getChanges(),
renameFilename: undefined,
renameLocation: undefined
};
}
function isDeclarationWithType(node: Node): node is DeclarationWithType {
return isFunctionLikeDeclaration(node) ||
node.kind === SyntaxKind.VariableDeclaration ||
node.kind === SyntaxKind.Parameter ||
node.kind === SyntaxKind.PropertySignature ||
node.kind === SyntaxKind.PropertyDeclaration;
}
function addTypesToFunctionLike(decl: FunctionLikeDeclaration) {
const typeParameters = getEffectiveTypeParameterDeclarations(decl, /*checkJSDoc*/ true);
const parameters = decl.parameters.map(
p => createParameter(p.decorators, p.modifiers, p.dotDotDotToken, p.name, p.questionToken, transformJSDocType(getEffectiveTypeAnnotationNode(p, /*checkJSDoc*/ true)) as TypeNode, p.initializer));
const returnType = transformJSDocType(getEffectiveReturnTypeNode(decl, /*checkJSDoc*/ true)) as TypeNode;
switch (decl.kind) {
case SyntaxKind.FunctionDeclaration:
return createFunctionDeclaration(decl.decorators, decl.modifiers, decl.asteriskToken, decl.name, typeParameters, parameters, returnType, decl.body);
case SyntaxKind.Constructor:
return createConstructor(decl.decorators, decl.modifiers, parameters, decl.body);
case SyntaxKind.FunctionExpression:
return createFunctionExpression(decl.modifiers, decl.asteriskToken, (decl as FunctionExpression).name, typeParameters, parameters, returnType, decl.body);
case SyntaxKind.ArrowFunction:
return createArrowFunction(decl.modifiers, typeParameters, parameters, returnType, decl.equalsGreaterThanToken, decl.body);
case SyntaxKind.MethodDeclaration:
return createMethod(decl.decorators, decl.modifiers, decl.asteriskToken, decl.name, decl.questionToken, typeParameters, parameters, returnType, decl.body);
case SyntaxKind.GetAccessor:
return createGetAccessor(decl.decorators, decl.modifiers, decl.name, decl.parameters, returnType, decl.body);
case SyntaxKind.SetAccessor:
return createSetAccessor(decl.decorators, decl.modifiers, decl.name, parameters, decl.body);
default:
return Debug.assertNever(decl, `Unexpected SyntaxKind: ${(decl as any).kind}`);
}
}
function addType(decl: DeclarationWithType, jsdocType: TypeNode) {
switch (decl.kind) {
case SyntaxKind.VariableDeclaration:
return createVariableDeclaration(decl.name, jsdocType, decl.initializer);
case SyntaxKind.PropertySignature:
return createPropertySignature(decl.modifiers, decl.name, decl.questionToken, jsdocType, decl.initializer);
case SyntaxKind.PropertyDeclaration:
return createProperty(decl.decorators, decl.modifiers, decl.name, decl.questionToken, jsdocType, decl.initializer);
default:
return Debug.fail(`Unexpected SyntaxKind: ${decl.kind}`);
}
}
function transformJSDocType(node: Node): Node | undefined {
if (node === undefined) {
return undefined;
}
switch (node.kind) {
case SyntaxKind.JSDocAllType:
case SyntaxKind.JSDocUnknownType:
return createTypeReferenceNode("any", emptyArray);
case SyntaxKind.JSDocOptionalType:
return transformJSDocOptionalType(node as JSDocOptionalType);
case SyntaxKind.JSDocNonNullableType:
return transformJSDocType((node as JSDocNonNullableType).type);
case SyntaxKind.JSDocNullableType:
return transformJSDocNullableType(node as JSDocNullableType);
case SyntaxKind.JSDocVariadicType:
return transformJSDocVariadicType(node as JSDocVariadicType);
case SyntaxKind.JSDocFunctionType:
return transformJSDocFunctionType(node as JSDocFunctionType);
case SyntaxKind.Parameter:
return transformJSDocParameter(node as ParameterDeclaration);
case SyntaxKind.TypeReference:
return transformJSDocTypeReference(node as TypeReferenceNode);
default:
return visitEachChild(node, transformJSDocType, /*context*/ undefined) as TypeNode;
}
}
function transformJSDocOptionalType(node: JSDocOptionalType) {
return createUnionTypeNode([visitNode(node.type, transformJSDocType), createTypeReferenceNode("undefined", emptyArray)]);
}
function transformJSDocNullableType(node: JSDocNullableType) {
return createUnionTypeNode([visitNode(node.type, transformJSDocType), createTypeReferenceNode("null", emptyArray)]);
}
function transformJSDocVariadicType(node: JSDocVariadicType) {
return createArrayTypeNode(visitNode(node.type, transformJSDocType));
}
function transformJSDocFunctionType(node: JSDocFunctionType) {
const parameters = node.parameters && node.parameters.map(transformJSDocType);
return createFunctionTypeNode(emptyArray, parameters as ParameterDeclaration[], node.type);
}
function transformJSDocParameter(node: ParameterDeclaration) {
const index = node.parent.parameters.indexOf(node);
const isRest = node.type.kind === SyntaxKind.JSDocVariadicType && index === node.parent.parameters.length - 1;
const name = node.name || (isRest ? "rest" : "arg" + index);
const dotdotdot = isRest ? createToken(SyntaxKind.DotDotDotToken) : node.dotDotDotToken;
return createParameter(node.decorators, node.modifiers, dotdotdot, name, node.questionToken, visitNode(node.type, transformJSDocType), node.initializer);
}
function transformJSDocTypeReference(node: TypeReferenceNode) {
let name = node.typeName;
let args = node.typeArguments;
if (isIdentifier(node.typeName)) {
let text = node.typeName.text;
switch (node.typeName.text) {
case "String":
case "Boolean":
case "Object":
case "Number":
text = text.toLowerCase();
break;
case "array":
case "date":
case "promise":
text = text[0].toUpperCase() + text.slice(1);
break;
}
name = createIdentifier(text);
if ((text === "Array" || text === "Promise") && !node.typeArguments) {
args = createNodeArray([createTypeReferenceNode("any", emptyArray)]);
}
else {
args = visitNodes(node.typeArguments, transformJSDocType);
}
}
return createTypeReferenceNode(name, args);
}
}

View file

@ -269,4 +269,4 @@ namespace ts.refactor.convertFunctionToES6Class {
return filter(source.modifiers, modifier => modifier.kind === kind);
}
}
}
}

View file

@ -1,2 +1,3 @@
/// <reference path="annotateWithTypeFromJSDoc.ts" />
/// <reference path="convertFunctionToEs6Class.ts" />
/// <reference path="extractSymbol.ts" />

View file

@ -0,0 +1,10 @@
/// <reference path='fourslash.ts' />
// @Filename: test123.ts
/////** @type {number} */
////var /*1*/x;
verify.applicableRefactorAvailableAtMarker('1');
verify.fileAfterApplyingRefactorAtMarker('1',
`/** @type {number} */
var x: number;`, 'Annotate with type from JSDoc', 'annotate');

View file

@ -0,0 +1,15 @@
/// <reference path='fourslash.ts' />
/////**
//// * @param {?} x
//// * @returns {number}
//// */
////var f = /*1*/(/*2*/x) => x
verify.applicableRefactorAvailableAtMarker('1');
verify.fileAfterApplyingRefactorAtMarker('1',
`/**
* @param {?} x
* @returns {number}
*/
var f = (x: any): number => x`, 'Annotate with types from JSDoc', 'annotate');

View file

@ -0,0 +1,15 @@
/// <reference path='fourslash.ts' />
/////**
//// * @param {?} x
//// * @returns {number}
//// */
////var f = /*1*/(/*2*/x) => x
verify.applicableRefactorAvailableAtMarker('2');
verify.fileAfterApplyingRefactorAtMarker('2',
`/**
* @param {?} x
* @returns {number}
*/
var f = (x: any): number => x`, 'Annotate with types from JSDoc', 'annotate');

View file

@ -0,0 +1,18 @@
/// <reference path='fourslash.ts' />
////class C {
//// /**
//// * @return {...*}
//// */
//// /*1*/m(x) {
//// }
////}
verify.applicableRefactorAvailableAtMarker('1');
verify.fileAfterApplyingRefactorAtMarker('1',
`class C {
/**
* @return {...*}
*/
m(x): any[] {
}
}`, 'Annotate with types from JSDoc', 'annotate');

View file

@ -0,0 +1,11 @@
/// <reference path='fourslash.ts' />
////class C {
//// /** @return {number} */
//// get /*1*/c() { return 12 }
////}
verify.applicableRefactorAvailableAtMarker('1');
verify.fileAfterApplyingRefactorAtMarker('1',
`class C {
/** @return {number} */
get c(): number { return 12; }
}`, 'Annotate with types from JSDoc', 'annotate');

View file

@ -0,0 +1,11 @@
/// <reference path='fourslash.ts' />
/////** @return {number} */
////function f() {
//// /*1*/return 12;
////}
verify.applicableRefactorAvailableAtMarker('1');
verify.fileAfterApplyingRefactorAtMarker('1',
`/** @return {number} */
function f(): number {
return 12;
}`, 'Annotate with types from JSDoc', 'annotate');

View file

@ -0,0 +1,30 @@
/// <reference path='fourslash.ts' />
// @strict: true
/////**
//// * @param {Boolean} x
//// * @param {String} y
//// * @param {Number} z
//// * @param {Object} alpha
//// * @param {date} beta
//// * @param {promise} gamma
//// * @param {array} delta
//// * @param {Array<number>} epsilon
//// * @param {promise<String>} zeta
//// */
////function f(/*1*/x, /*2*/y, /*3*/z, /*4*/alpha, /*5*/beta, /*6*/gamma, /*7*/delta, /*8*/epsilon, /*9*/zeta) {
////}
verify.applicableRefactorAvailableAtMarker('9');
verify.fileAfterApplyingRefactorAtMarker('9',
`/**
* @param {Boolean} x
* @param {String} y
* @param {Number} z
* @param {Object} alpha
* @param {date} beta
* @param {promise} gamma
* @param {array} delta
* @param {Array<number>} epsilon
* @param {promise<String>} zeta
*/
function f(x: boolean, y: string, z: number, alpha: object, beta: Date, gamma: Promise<any>, delta: Array<any>, epsilon: Array<number>, zeta: Promise<string>) {
}`, 'Annotate with types from JSDoc', 'annotate');

View file

@ -0,0 +1,9 @@
/// <reference path='fourslash.ts' />
// @strict: true
/////** @type {function(*, ...number, ...boolean): void} */
////var /*1*/x = (x, ys, ...zs) => { };
verify.applicableRefactorAvailableAtMarker('1');
verify.fileAfterApplyingRefactorAtMarker('1',
`/** @type {function(*, ...number, ...boolean): void} */
var x: (arg0: any, arg1: number[], ...rest: boolean[]) => void = (x, ys, ...zs) => { };`, 'Annotate with type from JSDoc', 'annotate');

View file

@ -0,0 +1,18 @@
/// <reference path='fourslash.ts' />
////class C {
//// /**
//// * @param {number} x - the first parameter
//// */
//// constructor(/*1*/x) {
//// }
////}
verify.applicableRefactorAvailableAtMarker('1');
verify.fileAfterApplyingRefactorAtMarker('1',
`class C {
/**
* @param {number} x - the first parameter
*/
constructor(x: number) {
}
}`, 'Annotate with types from JSDoc', 'annotate');

View file

@ -0,0 +1,11 @@
/// <reference path='fourslash.ts' />
////class C {
//// /** @param {number} value */
//// set c(/*1*/value) { return 12 }
////}
verify.applicableRefactorAvailableAtMarker('1');
verify.fileAfterApplyingRefactorAtMarker('1',
`class C {
/** @param {number} value */
set c(value: number) { return 12; }
}`, 'Annotate with types from JSDoc', 'annotate');

View file

@ -0,0 +1,19 @@
/// <reference path='fourslash.ts' />
// @strict: true
/////**
//// * @template T
//// * @param {number} a
//// * @param {T} b
//// */
////function /*1*/f(a, b) {
////}
verify.applicableRefactorAvailableAtMarker('1');
verify.fileAfterApplyingRefactorAtMarker('1',
`/**
* @template T
* @param {number} a
* @param {T} b
*/
function f<T>(a: number, b: T) {
}`, 'Annotate with types from JSDoc', 'annotate');

View file

@ -0,0 +1,6 @@
/// <reference path='fourslash.ts' />
// @Filename: test123.ts
/////** @type {number} */
////var /*1*/x: string;
verify.not.applicableRefactorAvailableAtMarker('1');

View file

@ -0,0 +1,17 @@
/// <reference path='fourslash.ts' />
// @strict: true
/////**
//// * @param {number} a
//// * @param {T} b
//// */
////function /*1*/f<T>(a, b) {
////}
verify.applicableRefactorAvailableAtMarker('1');
verify.fileAfterApplyingRefactorAtMarker('1',
`/**
* @param {number} a
* @param {T} b
*/
function f<T>(a: number, b: T) {
}`, 'Annotate with types from JSDoc', 'annotate');

View file

@ -0,0 +1,28 @@
/// <reference path='fourslash.ts' />
/////**
//// * @param {number} x - the first parameter
//// * @param {{ a: string, b: Date }} y - the most complex parameter
//// * @param z - the best parameter
//// * @param alpha - the other best parameter
//// * @param {*} beta - I have no idea how this got here
//// */
////function f(/*1*/x, /*2*/y, /*3*/z: string, /*4*/alpha, /*5*/beta) {
////}
verify.not.applicableRefactorAvailableAtMarker('3');
verify.not.applicableRefactorAvailableAtMarker('4');
verify.applicableRefactorAvailableAtMarker('1');
verify.fileAfterApplyingRefactorAtMarker('1',
`/**
* @param {number} x - the first parameter
* @param {{ a: string, b: Date }} y - the most complex parameter
* @param z - the best parameter
* @param alpha - the other best parameter
* @param {*} beta - I have no idea how this got here
*/
function f(x: number, y: {
a: string;
b: Date;
}, z: string, alpha, beta: any) {
}`, 'Annotate with types from JSDoc', 'annotate');

View file

@ -0,0 +1,29 @@
/// <reference path='fourslash.ts' />
// @strict: true
/////**
//// * @param {*} x
//// * @param {?} y
//// * @param {number=} z
//// * @param {...number} alpha
//// * @param {function(this:{ a: string}, string, number): boolean} beta
//// * @param {number?} gamma
//// * @param {number!} delta
//// */
////function f(/*1*/x, /*2*/y, /*3*/z, /*4*/alpha, /*5*/beta, /*6*/gamma, /*7*/delta) {
////}
verify.applicableRefactorAvailableAtMarker('5');
verify.fileAfterApplyingRefactorAtMarker('5',
`/**
* @param {*} x
* @param {?} y
* @param {number=} z
* @param {...number} alpha
* @param {function(this:{ a: string}, string, number): boolean} beta
* @param {number?} gamma
* @param {number!} delta
*/
function f(x: any, y: any, z: number | undefined, alpha: number[], beta: (this: {
a: string;
}, arg1: string, arg2: number) => boolean, gamma: number | null, delta: number) {
}`, 'Annotate with types from JSDoc', 'annotate');

View file

@ -0,0 +1,13 @@
/// <reference path='fourslash.ts' />
////class C {
//// /** @type {number | null} */
//// /*1*/p = null
////}
verify.applicableRefactorAvailableAtMarker('1');
verify.fileAfterApplyingRefactorAtMarker('1',
`class C {
/** @type {number | null} */
p: number | null = null;
}`, 'Annotate with type from JSDoc', 'annotate');

View file

@ -0,0 +1,13 @@
/// <reference path='fourslash.ts' />
////declare class C {
//// /** @type {number | null} */
//// /*1*/p;
////}
verify.applicableRefactorAvailableAtMarker('1');
verify.fileAfterApplyingRefactorAtMarker('1',
`declare class C {
/** @type {number | null} */
p: number | null;
}`, 'Annotate with type from JSDoc', 'annotate');

View file

@ -0,0 +1,17 @@
/// <reference path='fourslash.ts' />
/////**
//// * @param {number} x
//// * @returns {number}
//// */
/////*1*/function f(x) {
////}
verify.applicableRefactorAvailableAtMarker('1');
verify.fileAfterApplyingRefactorAtMarker('1',
`/**
* @param {number} x
* @returns {number}
*/
function f(x: number): number {
}`, 'Annotate with types from JSDoc', 'annotate');

View file

@ -0,0 +1,17 @@
/// <reference path='fourslash.ts' />
/////**
//// * @param {number} x
//// * @returns {number}
//// */
////var f = /*1*/function (x) {
////}
verify.applicableRefactorAvailableAtMarker('1');
verify.fileAfterApplyingRefactorAtMarker('1',
`/**
* @param {number} x
* @returns {number}
*/
var f = function(x: number): number {
}`, 'Annotate with types from JSDoc', 'annotate');

View file

@ -0,0 +1,15 @@
/// <reference path='fourslash.ts' />
/////**
//// * @param {?} x
//// * @returns {number}
//// */
////var f = /*1*/x => x
verify.applicableRefactorAvailableAtMarker('1');
verify.fileAfterApplyingRefactorAtMarker('1',
`/**
* @param {?} x
* @returns {number}
*/
var f = (x: any): number => x`, 'Annotate with types from JSDoc', 'annotate');