diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json
index a74d39fd07d3d..d8545e015290d 100644
--- a/src/compiler/diagnosticMessages.json
+++ b/src/compiler/diagnosticMessages.json
@@ -3830,6 +3830,10 @@
"category": "Suggestion",
"code": 80003
},
+ "JSDoc types may be moved to TypeScript types.": {
+ "category": "Suggestion",
+ "code": 80004
+ },
"Add missing 'super()' call": {
"category": "Message",
diff --git a/src/services/refactors/annotateWithTypeFromJSDoc.ts b/src/services/codefixes/annotateWithTypeFromJSDoc.ts
similarity index 64%
rename from src/services/refactors/annotateWithTypeFromJSDoc.ts
rename to src/services/codefixes/annotateWithTypeFromJSDoc.ts
index 3258da4636a51..c92fabeab96f7 100644
--- a/src/services/refactors/annotateWithTypeFromJSDoc.ts
+++ b/src/services/codefixes/annotateWithTypeFromJSDoc.ts
@@ -1,108 +1,66 @@
/* @internal */
-namespace ts.refactor.annotateWithTypeFromJSDoc {
- const refactorName = "Annotate with type from JSDoc";
- const actionName = "annotate";
- const description = Diagnostics.Annotate_with_type_from_JSDoc.message;
- registerRefactor(refactorName, { getEditsForAction, getAvailableActions });
+namespace ts.codefix {
+ const fixId = "annotateWithTypeFromJSDoc";
+ const errorCodes = [Diagnostics.JSDoc_types_may_be_moved_to_TypeScript_types.code];
+ registerCodeFix({
+ errorCodes,
+ getCodeActions(context) {
+ const decl = getDeclaration(context.sourceFile, context.span.start);
+ if (!decl) return;
+ const description = getLocaleSpecificMessage(Diagnostics.Annotate_with_type_from_JSDoc);
+ const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, decl));
+ return [{ description, changes, fixId }];
+ },
+ fixIds: [fixId],
+ getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => {
+ const decl = getDeclaration(diag.file!, diag.start!);
+ if (decl) doChange(changes, diag.file!, decl);
+ }),
+ });
+
+ function getDeclaration(file: SourceFile, pos: number): DeclarationWithType | undefined {
+ const name = getTokenAtPosition(file, pos, /*includeJsDocComment*/ false);
+ // For an arrow function with no name, 'name' lands on the first parameter.
+ return tryCast(isParameter(name.parent) ? name.parent.parent : name.parent, parameterShouldGetTypeFromJSDoc);
+ }
type DeclarationWithType =
| FunctionLikeDeclaration
| VariableDeclaration
- | ParameterDeclaration
| PropertySignature
| PropertyDeclaration;
- function getAvailableActions(context: RefactorContext): ApplicableRefactorInfo[] | undefined {
- if (isInJavaScriptFile(context.file)) {
- return undefined;
- }
-
- const node = getTokenAtPosition(context.file, context.startPosition, /*includeJsDocComment*/ false);
- if (hasUsableJSDoc(findAncestor(node, isDeclarationWithType))) {
- return [{
- name: refactorName,
- description,
- actions: [
- {
- description,
- name: actionName
- }
- ]
- }];
- }
+ export function parameterShouldGetTypeFromJSDoc(node: Node): node is DeclarationWithType {
+ return isDeclarationWithType(node) && hasUsableJSDoc(node);
}
- function hasUsableJSDoc(decl: DeclarationWithType): boolean {
- if (!decl) {
- return false;
- }
- if (isFunctionLikeDeclaration(decl)) {
- return decl.parameters.some(hasUsableJSDoc) || (!decl.type && !!getJSDocReturnType(decl));
- }
- return !decl.type && !!getJSDocType(decl);
+ function hasUsableJSDoc(decl: DeclarationWithType | ParameterDeclaration): boolean {
+ return isFunctionLikeDeclaration(decl)
+ ? decl.parameters.some(hasUsableJSDoc) || (!decl.type && !!getJSDocReturnType(decl))
+ : !decl.type && !!getJSDocType(decl);
}
- function getEditsForAction(context: RefactorContext, action: string): RefactorEditInfo | undefined {
- if (actionName !== action) {
- return Debug.fail(`actionName !== action: ${actionName} !== ${action}`);
- }
- 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)));
- if (isFunctionWithJSDoc || jsdocType && decl.kind === SyntaxKind.Parameter) {
- return getEditsForFunctionAnnotation(context);
- }
- else if (jsdocType) {
- return getEditsForAnnotation(context);
+ function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, decl: DeclarationWithType): void {
+ if (isFunctionLikeDeclaration(decl) && (getJSDocReturnType(decl) || decl.parameters.some(p => !!getJSDocType(p)))) {
+ findAncestor(decl, isFunctionLike);
+ const fn = findAncestor(decl, isFunctionLikeDeclaration);
+ const functionWithType = addTypesToFunctionLike(fn);
+ suppressLeadingAndTrailingTrivia(functionWithType);
+ changes.replaceNode(sourceFile, fn, functionWithType, textChanges.useNonAdjustedPositions);
+ return;
}
else {
- Debug.assert(!!refactor, "No applicable refactor found.");
- }
- }
-
- function getEditsForAnnotation(context: RefactorContext): RefactorEditInfo | undefined {
- 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 jsdocType = Debug.assertDefined(getJSDocType(decl)); // If not defined, shouldn't have been an error to fix
+ Debug.assert(!decl.type); // If defined, shouldn't have been an error to fix.
+ const declarationWithType = addType(decl, transformJSDocType(jsdocType) as TypeNode);
+ suppressLeadingAndTrailingTrivia(declarationWithType);
+ changes.replaceNode(sourceFile, decl, declarationWithType, textChanges.useNonAdjustedPositions);
}
-
- const changeTracker = textChanges.ChangeTracker.fromContext(context);
- const declarationWithType = addType(decl, transformJSDocType(jsdocType) as TypeNode);
- suppressLeadingAndTrailingTrivia(declarationWithType);
- changeTracker.replaceNode(sourceFile, decl, declarationWithType, textChanges.useNonAdjustedPositions);
- return {
- edits: changeTracker.getChanges(),
- renameFilename: undefined,
- renameLocation: undefined
- };
- }
-
- function getEditsForFunctionAnnotation(context: RefactorContext): RefactorEditInfo | undefined {
- 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.replaceNode(sourceFile, decl, functionWithType, textChanges.useNonAdjustedPositions);
- 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;
}
diff --git a/src/services/codefixes/fixes.ts b/src/services/codefixes/fixes.ts
index 43313011bd22c..50a0afd392500 100644
--- a/src/services/codefixes/fixes.ts
+++ b/src/services/codefixes/fixes.ts
@@ -1,4 +1,5 @@
///
+///
///
///
///
diff --git a/src/services/refactors/refactors.ts b/src/services/refactors/refactors.ts
index 0e5158563c83a..da2f08a8e9fcf 100644
--- a/src/services/refactors/refactors.ts
+++ b/src/services/refactors/refactors.ts
@@ -1,2 +1 @@
-///
///
diff --git a/src/services/suggestionDiagnostics.ts b/src/services/suggestionDiagnostics.ts
index 602b7e2529783..3de43d7d40f92 100644
--- a/src/services/suggestionDiagnostics.ts
+++ b/src/services/suggestionDiagnostics.ts
@@ -9,21 +9,28 @@ namespace ts {
diags.push(createDiagnosticForNode(sourceFile.commonJsModuleIndicator, Diagnostics.File_is_a_CommonJS_module_it_may_be_converted_to_an_ES6_module));
}
+ const isJsFile = isSourceFileJavaScript(sourceFile);
+
function check(node: Node) {
switch (node.kind) {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
- const symbol = node.symbol;
- if (symbol.members && (symbol.members.size > 0)) {
- diags.push(createDiagnosticForNode(isVariableDeclaration(node.parent) ? node.parent.name : node, Diagnostics.This_constructor_function_may_be_converted_to_a_class_declaration));
+ if (isJsFile) {
+ const symbol = node.symbol;
+ if (symbol.members && (symbol.members.size > 0)) {
+ diags.push(createDiagnosticForNode(isVariableDeclaration(node.parent) ? node.parent.name : node, Diagnostics.This_constructor_function_may_be_converted_to_a_class_declaration));
+ }
}
break;
}
+
+ if (!isJsFile && codefix.parameterShouldGetTypeFromJSDoc(node)) {
+ diags.push(createDiagnosticForNode(node.name || node, Diagnostics.JSDoc_types_may_be_moved_to_TypeScript_types));
+ }
+
node.forEachChild(check);
}
- if (isInJavaScriptFile(sourceFile)) {
- check(sourceFile);
- }
+ check(sourceFile);
if (getAllowSyntheticDefaultImports(program.getCompilerOptions())) {
for (const importNode of sourceFile.imports) {
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc1.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc1.ts
index 99cf5f8db1c15..ef626fd358d52 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc1.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc1.ts
@@ -2,9 +2,16 @@
// @Filename: test123.ts
/////** @type {number} */
-////var /*1*/x;
+////var [|x|];
-verify.applicableRefactorAvailableAtMarker('1');
-verify.fileAfterApplyingRefactorAtMarker('1',
+verify.getSuggestionDiagnostics([{
+ message: "JSDoc types may be moved to TypeScript types.",
+ code: 80004,
+}]);
+
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`/** @type {number} */
-var x: number;`, 'Annotate with type from JSDoc', 'annotate');
+var x: number;`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc10.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc10.ts
index f90c61c33d94d..2bd1df5c6e6b3 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc10.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc10.ts
@@ -4,12 +4,14 @@
//// * @param {?} x
//// * @returns {number}
//// */
-////var f = /*1*/(/*2*/x) => x
+////var f = (x) => x
-verify.applicableRefactorAvailableAtMarker('1');
-verify.fileAfterApplyingRefactorAtMarker('1',
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`/**
* @param {?} x
* @returns {number}
*/
-var f = (x: any): number => x`, 'Annotate with type from JSDoc', 'annotate');
+var f = (x: any): number => x`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc11.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc11.ts
index f0ab5f3013e5b..2bd1df5c6e6b3 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc11.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc11.ts
@@ -4,12 +4,14 @@
//// * @param {?} x
//// * @returns {number}
//// */
-////var f = /*1*/(/*2*/x) => x
+////var f = (x) => x
-verify.applicableRefactorAvailableAtMarker('2');
-verify.fileAfterApplyingRefactorAtMarker('2',
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`/**
* @param {?} x
* @returns {number}
*/
-var f = (x: any): number => x`, 'Annotate with type from JSDoc', 'annotate');
+var f = (x: any): number => x`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts
index fc9b7c2a17eae..e7893fd99046a 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc12.ts
@@ -4,15 +4,18 @@
//// /**
//// * @return {...*}
//// */
-//// /*1*/m(x) {
+//// m(x) {
//// }
////}
-verify.applicableRefactorAvailableAtMarker('1');
-verify.fileAfterApplyingRefactorAtMarker('1',
+
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`class C {
/**
* @return {...*}
*/
m(x): any[] {
}
-}`, 'Annotate with type from JSDoc', 'annotate');
+}`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc13.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc13.ts
index da147548b2775..0f4b8596d7e26 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc13.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc13.ts
@@ -1,11 +1,14 @@
///
////class C {
//// /** @return {number} */
-//// get /*1*/c() { return 12 }
+//// get c() { return 12 }
////}
-verify.applicableRefactorAvailableAtMarker('1');
-verify.fileAfterApplyingRefactorAtMarker('1',
+
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`class C {
/** @return {number} */
get c(): number { return 12; }
-}`, 'Annotate with type from JSDoc', 'annotate');
+}`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc14.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc14.ts
index 5020d0f11cf1b..a8a73a9a620f5 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc14.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc14.ts
@@ -1,11 +1,14 @@
///
/////** @return {number} */
////function f() {
-//// /*1*/return 12;
+//// return 12;
////}
-verify.applicableRefactorAvailableAtMarker('1');
-verify.fileAfterApplyingRefactorAtMarker('1',
+
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`/** @return {number} */
function f(): number {
return 12;
-}`, 'Annotate with type from JSDoc', 'annotate');
+}`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc15.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc15.ts
index 1389e800f5a71..8072f0547de67 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc15.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc15.ts
@@ -11,10 +11,12 @@
//// * @param {Array} epsilon
//// * @param {promise} zeta
//// */
-////function f(/*1*/x, /*2*/y, /*3*/z, /*4*/alpha, /*5*/beta, /*6*/gamma, /*7*/delta, /*8*/epsilon, /*9*/zeta) {
+////function f(x, y, z, alpha, beta, gamma, delta, epsilon, zeta) {
////}
-verify.applicableRefactorAvailableAtMarker('9');
-verify.fileAfterApplyingRefactorAtMarker('9',
+
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`/**
* @param {Boolean} x
* @param {String} y
@@ -27,4 +29,5 @@ verify.fileAfterApplyingRefactorAtMarker('9',
* @param {promise} zeta
*/
function f(x: boolean, y: string, z: number, alpha: object, beta: Date, gamma: Promise, delta: Array, epsilon: Array, zeta: Promise) {
-}`, 'Annotate with type from JSDoc', 'annotate');
+}`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc16.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc16.ts
index a332a84d9109d..ab57b32aaacc2 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc16.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc16.ts
@@ -1,9 +1,11 @@
///
// @strict: true
/////** @type {function(*, ...number, ...boolean): void} */
-////var /*1*/x = (x, ys, ...zs) => { };
+////var x = (x, ys, ...zs) => { };
-verify.applicableRefactorAvailableAtMarker('1');
-verify.fileAfterApplyingRefactorAtMarker('1',
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`/** @type {function(*, ...number, ...boolean): void} */
-var x: (arg0: any, arg1: number[], ...rest: boolean[]) => void = (x, ys, ...zs) => { };`, 'Annotate with type from JSDoc', 'annotate');
+var x: (arg0: any, arg1: number[], ...rest: boolean[]) => void = (x, ys, ...zs) => { };`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc17.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc17.ts
index ec26a9d1de7bb..2382cc18a272f 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc17.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc17.ts
@@ -3,16 +3,18 @@
//// /**
//// * @param {number} x - the first parameter
//// */
-//// constructor(/*1*/x) {
+//// constructor(x) {
//// }
////}
-verify.applicableRefactorAvailableAtMarker('1');
-verify.fileAfterApplyingRefactorAtMarker('1',
+
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`class C {
/**
* @param {number} x - the first parameter
*/
constructor(x: number) {
}
-}`, 'Annotate with type from JSDoc', 'annotate');
-
+}`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc18.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc18.ts
index 10d3192583dac..844015d456e3a 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc18.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc18.ts
@@ -1,11 +1,14 @@
///
////class C {
//// /** @param {number} value */
-//// set c(/*1*/value) { return 12 }
+//// set c(value) { return 12 }
////}
-verify.applicableRefactorAvailableAtMarker('1');
-verify.fileAfterApplyingRefactorAtMarker('1',
+
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`class C {
/** @param {number} value */
set c(value: number) { return 12; }
-}`, 'Annotate with type from JSDoc', 'annotate');
+}`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc19.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc19.ts
index a47522fe03ca1..96e351ed2baa6 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc19.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc19.ts
@@ -5,15 +5,17 @@
//// * @param {number} a
//// * @param {T} b
//// */
-////function /*1*/f(a, b) {
+////function f(a, b) {
////}
-verify.applicableRefactorAvailableAtMarker('1');
-verify.fileAfterApplyingRefactorAtMarker('1',
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`/**
* @template T
* @param {number} a
* @param {T} b
*/
function f(a: number, b: T) {
-}`, 'Annotate with type from JSDoc', 'annotate');
+}`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc2.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc2.ts
index 85f28de4a9973..8c5fe0b459547 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc2.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc2.ts
@@ -2,5 +2,6 @@
// @Filename: test123.ts
/////** @type {number} */
-////var /*1*/x: string;
-verify.not.applicableRefactorAvailableAtMarker('1');
+////var [|x|]: string;
+
+verify.getSuggestionDiagnostics([]);
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc20.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc20.ts
index 093966231fdd2..a54936b1ea610 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc20.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc20.ts
@@ -7,11 +7,13 @@
////function /*1*/f(a, b) {
////}
-verify.applicableRefactorAvailableAtMarker('1');
-verify.fileAfterApplyingRefactorAtMarker('1',
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`/**
* @param {number} a
* @param {T} b
*/
function f(a: number, b: T) {
-}`, 'Annotate with type from JSDoc', 'annotate');
+}`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc21.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc21.ts
index b54f83070c4ab..67d7e09994994 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc21.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc21.ts
@@ -3,19 +3,19 @@
/////**
//// * @return {number}
//// */
-////function /*1*/f(x, y) {
+////function [|f|](x, y) {
////}
////
/////**
//// * @return {number}
//// */
-////function /*2*/g(x, y): number {
+////function g(x, y): number {
//// return 0;
////}
/////**
//// * @param {number} x
//// */
-////function /*3*/h(x: number, y): number {
+////function h(x: number, y): number {
//// return 0;
////}
////
@@ -23,22 +23,25 @@
//// * @param {number} x
//// * @param {string} y
//// */
-////function /*4*/i(x: number, y: string) {
+////function i(x: number, y: string) {
////}
/////**
//// * @param {number} x
//// * @return {boolean}
//// */
-////function /*5*/j(x: number, y): boolean {
+////function j(x: number, y): boolean {
//// return true;
////}
-verify.not.applicableRefactorAvailableAtMarker('2');
-verify.not.applicableRefactorAvailableAtMarker('3');
-verify.not.applicableRefactorAvailableAtMarker('4');
-verify.not.applicableRefactorAvailableAtMarker('5');
-verify.applicableRefactorAvailableAtMarker('1');
-verify.fileAfterApplyingRefactorAtMarker('1',
+// Only first location triggers a suggestion
+verify.getSuggestionDiagnostics([{
+ message: "JSDoc types may be moved to TypeScript types.",
+ code: 80004,
+}]);
+
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`/**
* @return {number}
*/
@@ -70,4 +73,5 @@ function i(x: number, y: string) {
*/
function j(x: number, y): boolean {
return true;
-}`, 'Annotate with type from JSDoc', 'annotate');
+}`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc22.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc22.ts
index d00705848c642..9da43e5099a6f 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc22.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc22.ts
@@ -3,12 +3,15 @@
////
/////** @param {Object} sb
//// * @param {Object} ns */
-////function /*1*/f(sb, ns) {
+////function f(sb, ns) {
////}
-verify.applicableRefactorAvailableAtMarker('1');
-verify.fileAfterApplyingRefactorAtMarker('1',
+
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`
/** @param {Object} sb
* @param {Object} ns */
function f(sb: { [s: string]: boolean; }, ns: { [n: number]: string; }) {
-}`, 'Annotate with type from JSDoc', 'annotate');
+}`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts
index 9413e6046c9e4..0eedc937198b4 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc3.ts
@@ -6,13 +6,17 @@
//// * @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) {
+////function [|f|](x, y, z: string, alpha, beta) {
////}
-verify.not.applicableRefactorAvailableAtMarker('3');
-verify.not.applicableRefactorAvailableAtMarker('4');
-verify.applicableRefactorAvailableAtMarker('1');
-verify.fileAfterApplyingRefactorAtMarker('1',
+verify.getSuggestionDiagnostics([{
+ message: "JSDoc types may be moved to TypeScript types.",
+ code: 80004,
+}]);
+
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`/**
* @param {number} x - the first parameter
* @param {{ a: string, b: Date }} y - the most complex parameter
@@ -21,5 +25,5 @@ verify.fileAfterApplyingRefactorAtMarker('1',
* @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 type from JSDoc', 'annotate');
-
+}`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts
index ad06bbbc699f2..31825eea3f97f 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc4.ts
@@ -9,11 +9,12 @@
//// * @param {number?} gamma
//// * @param {number!} delta
//// */
-////function f(/*1*/x, /*2*/y, /*3*/z, /*4*/alpha, /*5*/beta, /*6*/gamma, /*7*/delta) {
+////function [|f|](x, y, z, alpha, beta, gamma, delta) {
////}
-verify.applicableRefactorAvailableAtMarker('5');
-verify.fileAfterApplyingRefactorAtMarker('5',
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`/**
* @param {*} x
* @param {?} y
@@ -24,4 +25,5 @@ verify.fileAfterApplyingRefactorAtMarker('5',
* @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 type from JSDoc', 'annotate');
+}`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc5.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc5.ts
index 1ae2949ef3ca4..3a072fabed31c 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc5.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc5.ts
@@ -2,12 +2,14 @@
////class C {
//// /** @type {number | null} */
-//// /*1*/p = null
+//// p = null
////}
-verify.applicableRefactorAvailableAtMarker('1');
-verify.fileAfterApplyingRefactorAtMarker('1',
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`class C {
/** @type {number | null} */
p: number | null = null;
-}`, 'Annotate with type from JSDoc', 'annotate');
+}`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc6.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc6.ts
index 53e8170533df6..9d11eb8d4457a 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc6.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc6.ts
@@ -2,12 +2,14 @@
////declare class C {
//// /** @type {number | null} */
-//// /*1*/p;
+//// p;
////}
-verify.applicableRefactorAvailableAtMarker('1');
-verify.fileAfterApplyingRefactorAtMarker('1',
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`declare class C {
/** @type {number | null} */
p: number | null;
-}`, 'Annotate with type from JSDoc', 'annotate');
+}`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc7.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc7.ts
index 68df14c2b52a8..e242b53228d4b 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc7.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc7.ts
@@ -4,14 +4,16 @@
//// * @param {number} x
//// * @returns {number}
//// */
-/////*1*/function f(x) {
+////function f(x) {
////}
-verify.applicableRefactorAvailableAtMarker('1');
-verify.fileAfterApplyingRefactorAtMarker('1',
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`/**
* @param {number} x
* @returns {number}
*/
function f(x: number): number {
-}`, 'Annotate with type from JSDoc', 'annotate');
+}`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc8.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc8.ts
index 7381b2f288073..1516817b92c16 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc8.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc8.ts
@@ -4,14 +4,16 @@
//// * @param {number} x
//// * @returns {number}
//// */
-////var f = /*1*/function (x) {
+////var f = function (x) {
////}
-verify.applicableRefactorAvailableAtMarker('1');
-verify.fileAfterApplyingRefactorAtMarker('1',
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`/**
* @param {number} x
* @returns {number}
*/
var f = function(x: number): number {
-}`, 'Annotate with type from JSDoc', 'annotate');
+}`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc9.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc9.ts
index 704d3681b3d3b..d1517a2c00941 100644
--- a/tests/cases/fourslash/annotateWithTypeFromJSDoc9.ts
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc9.ts
@@ -4,12 +4,14 @@
//// * @param {?} x
//// * @returns {number}
//// */
-////var f = /*1*/x => x
+////var f = x => x
-verify.applicableRefactorAvailableAtMarker('1');
-verify.fileAfterApplyingRefactorAtMarker('1',
+verify.codeFix({
+ description: "Annotate with type from JSDoc",
+ newFileContent:
`/**
* @param {?} x
* @returns {number}
*/
-var f = (x: any): number => x`, 'Annotate with type from JSDoc', 'annotate');
+var f = (x: any): number => x`,
+});
diff --git a/tests/cases/fourslash/annotateWithTypeFromJSDoc_all.ts b/tests/cases/fourslash/annotateWithTypeFromJSDoc_all.ts
new file mode 100644
index 0000000000000..60e10980bb97b
--- /dev/null
+++ b/tests/cases/fourslash/annotateWithTypeFromJSDoc_all.ts
@@ -0,0 +1,16 @@
+///
+
+// @Filename: test123.ts
+/////** @type {number} */
+////var [|x|];
+/////** @type {string} */
+////var [|y|];
+
+verify.codeFixAll({
+ fixId: "annotateWithTypeFromJSDoc",
+ newFileContent:
+`/** @type {number} */
+var x: number;
+/** @type {string} */
+var y: string;`,
+});