mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Add a code fixer for --isolatedDeclarations errors (#58260)
Co-authored-by: Andrew Branch <andrewbranch@users.noreply.github.com>
This commit is contained in:
@@ -1611,6 +1611,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
getBaseTypes,
|
||||
getBaseTypeOfLiteralType,
|
||||
getWidenedType,
|
||||
getWidenedLiteralType,
|
||||
getTypeFromTypeNode: nodeIn => {
|
||||
const node = getParseTreeNode(nodeIn, isTypeNode);
|
||||
return node ? getTypeFromTypeNode(node) : errorType;
|
||||
|
||||
@@ -7336,6 +7336,46 @@
|
||||
"category": "Message",
|
||||
"code": 90061
|
||||
},
|
||||
"Add annotation of type '{0}'": {
|
||||
"category": "Message",
|
||||
"code": 90062
|
||||
},
|
||||
"Add return type '{0}'": {
|
||||
"category": "Message",
|
||||
"code": 90063
|
||||
},
|
||||
"Extract base class to variable": {
|
||||
"category": "Message",
|
||||
"code": 90064
|
||||
},
|
||||
"Extract default export to variable": {
|
||||
"category": "Message",
|
||||
"code": 90065
|
||||
},
|
||||
"Extract binding expressions to variable": {
|
||||
"category": "Message",
|
||||
"code": 90066
|
||||
},
|
||||
"Add all missing type annotations": {
|
||||
"category": "Message",
|
||||
"code": 90067
|
||||
},
|
||||
"Add satisfies and an inline type assertion with '{0}'": {
|
||||
"category": "Message",
|
||||
"code": 90068
|
||||
},
|
||||
"Extract to variable and replace with '{0} as typeof {0}'": {
|
||||
"category": "Message",
|
||||
"code": 90069
|
||||
},
|
||||
"Mark array literal as const": {
|
||||
"category": "Message",
|
||||
"code": 90070
|
||||
},
|
||||
"Annotate types of properties expando function in a namespace": {
|
||||
"category": "Message",
|
||||
"code": 90071
|
||||
},
|
||||
|
||||
"Convert function to an ES2015 class": {
|
||||
"category": "Message",
|
||||
|
||||
@@ -5022,6 +5022,8 @@ export interface TypeChecker {
|
||||
getBaseTypeOfLiteralType(type: Type): Type;
|
||||
getWidenedType(type: Type): Type;
|
||||
/** @internal */
|
||||
getWidenedLiteralType(type: Type): Type;
|
||||
/** @internal */
|
||||
getPromisedTypeOfPromise(promise: Type, errorNode?: Node): Type | undefined;
|
||||
/** @internal */
|
||||
getAwaitedType(type: Type): Type | undefined;
|
||||
|
||||
@@ -50,6 +50,7 @@ export * from "../codefixes/fixUnreachableCode";
|
||||
export * from "../codefixes/fixUnusedLabel";
|
||||
export * from "../codefixes/fixJSDocTypes";
|
||||
export * from "../codefixes/fixMissingCallParentheses";
|
||||
export * from "../codefixes/fixMissingTypeAnnotationOnExports";
|
||||
export * from "../codefixes/fixAwaitInSyncFunction";
|
||||
export * from "../codefixes/fixPropertyOverrideAccessor";
|
||||
export * from "../codefixes/inferFromUsage";
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
DiagnosticWithLocation,
|
||||
FileTextChanges,
|
||||
flatMap,
|
||||
getEmitDeclarations,
|
||||
isString,
|
||||
map,
|
||||
TextChange,
|
||||
@@ -124,9 +125,15 @@ export function eachDiagnostic(context: CodeFixAllContext, errorCodes: readonly
|
||||
}
|
||||
|
||||
function getDiagnostics({ program, sourceFile, cancellationToken }: CodeFixContextBase) {
|
||||
return [
|
||||
const diagnostics = [
|
||||
...program.getSemanticDiagnostics(sourceFile, cancellationToken),
|
||||
...program.getSyntacticDiagnostics(sourceFile, cancellationToken),
|
||||
...computeSuggestionDiagnostics(sourceFile, program, cancellationToken),
|
||||
];
|
||||
if (getEmitDeclarations(program.getCompilerOptions())) {
|
||||
diagnostics.push(
|
||||
...program.getDeclarationDiagnostics(sourceFile, cancellationToken),
|
||||
);
|
||||
}
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -61,7 +61,6 @@ import {
|
||||
hasEffectiveModifier,
|
||||
hasSyntacticModifier,
|
||||
Identifier,
|
||||
identifierToKeywordKind,
|
||||
isArray,
|
||||
isArrowFunction,
|
||||
isAssignmentExpression,
|
||||
@@ -92,7 +91,6 @@ import {
|
||||
isModuleBlock,
|
||||
isParenthesizedTypeNode,
|
||||
isPartOfTypeNode,
|
||||
isPrivateIdentifier,
|
||||
isPropertyAccessExpression,
|
||||
isPropertyDeclaration,
|
||||
isQualifiedName,
|
||||
@@ -161,6 +159,7 @@ import {
|
||||
VisitResult,
|
||||
} from "../_namespaces/ts";
|
||||
import {
|
||||
getIdentifierForNode,
|
||||
refactorKindBeginsWith,
|
||||
registerRefactor,
|
||||
} from "../_namespaces/ts.refactor";
|
||||
@@ -1374,9 +1373,7 @@ function extractConstantInScope(
|
||||
|
||||
// Make a unique name for the extracted variable
|
||||
const file = scope.getSourceFile();
|
||||
const localNameText = isPropertyAccessExpression(node) && !isClassLike(scope) && !checker.resolveName(node.name.text, node, SymbolFlags.Value, /*excludeGlobals*/ false) && !isPrivateIdentifier(node.name) && !identifierToKeywordKind(node.name)
|
||||
? node.name.text
|
||||
: getUniqueName(isClassLike(scope) ? "newProperty" : "newLocal", file);
|
||||
const localNameText = getIdentifierForNode(node, scope, checker, file);
|
||||
const isJS = isInJSFile(scope);
|
||||
|
||||
let variableType = isJS || !checker.isContextSensitive(node)
|
||||
|
||||
@@ -1,12 +1,22 @@
|
||||
import {
|
||||
ClassLikeDeclaration,
|
||||
codefix,
|
||||
Debug,
|
||||
findAncestor,
|
||||
FunctionLikeDeclaration,
|
||||
getUniqueName,
|
||||
identifierToKeywordKind,
|
||||
isAnyImportOrRequireStatement,
|
||||
isClassLike,
|
||||
isPrivateIdentifier,
|
||||
isPropertyAccessExpression,
|
||||
ModuleBlock,
|
||||
Node,
|
||||
Program,
|
||||
skipAlias,
|
||||
SourceFile,
|
||||
Symbol,
|
||||
SymbolFlags,
|
||||
TypeChecker,
|
||||
} from "../_namespaces/ts";
|
||||
import { addImportsForMovedSymbols } from "./moveToFile";
|
||||
@@ -39,6 +49,18 @@ export function refactorKindBeginsWith(known: string, requested: string | undefi
|
||||
return known.substr(0, requested.length) === requested;
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to come up with a unique name for a given node within the scope for the
|
||||
* use of being used as a property/variable name.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
export function getIdentifierForNode(node: Node, scope: FunctionLikeDeclaration | SourceFile | ModuleBlock | ClassLikeDeclaration, checker: TypeChecker, file: SourceFile) {
|
||||
return isPropertyAccessExpression(node) && !isClassLike(scope) && !checker.resolveName(node.name.text, node, SymbolFlags.Value, /*excludeGlobals*/ false) && !isPrivateIdentifier(node.name) && !identifierToKeywordKind(node.name)
|
||||
? node.name.text
|
||||
: getUniqueName(isClassLike(scope) ? "newProperty" : "newLocal", file);
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function addTargetFileImports(
|
||||
oldFile: SourceFile,
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
////function foo() { return 42; }
|
||||
////export const g = foo();
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add annotation of type 'number'",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo() { return 42; }
|
||||
export const g: number = foo();`,
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
////function foo() {
|
||||
//// return { x: 1, y: 1 };
|
||||
////}
|
||||
////export default foo();
|
||||
|
||||
verify.codeFix({
|
||||
description: "Extract default export to variable",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo() {
|
||||
return { x: 1, y: 1 };
|
||||
}
|
||||
const _default_1: {
|
||||
x: number;
|
||||
y: number;
|
||||
} = foo();
|
||||
export default _default_1;`,
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
//// function mixin<T extends new (...a: any) => any>(ctor: T): T {
|
||||
//// return ctor;
|
||||
//// }
|
||||
//// class Point2D { x = 0; y = 0; }
|
||||
//// export class Point3D extends mixin(Point2D) { z = 0; }
|
||||
|
||||
verify.codeFix({
|
||||
description: ts.Diagnostics.Extract_base_class_to_variable.message,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function mixin<T extends new (...a: any) => any>(ctor: T): T {
|
||||
return ctor;
|
||||
}
|
||||
class Point2D { x = 0; y = 0; }
|
||||
const Point3DBase: typeof Point2D = mixin(Point2D);
|
||||
export class Point3D extends Point3DBase { z = 0; }`
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
//// function foo() {
|
||||
//// return { x: 1, y: 1 };
|
||||
//// }
|
||||
//// export const { x, y } = foo();
|
||||
|
||||
verify.codeFix({
|
||||
description: ts.Diagnostics.Extract_binding_expressions_to_variable.message,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo() {
|
||||
return { x: 1, y: 1 };
|
||||
}
|
||||
const dest = foo();
|
||||
export const x: number = dest.x;
|
||||
export const y: number = dest.y;`
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
//// function foo() {
|
||||
//// return { x: 1, y: 1 };
|
||||
//// }
|
||||
//// export const { x: abcd, y: defg } = foo();
|
||||
|
||||
verify.codeFix({
|
||||
description: ts.Diagnostics.Extract_binding_expressions_to_variable.message,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo() {
|
||||
return { x: 1, y: 1 };
|
||||
}
|
||||
const dest = foo();
|
||||
export const abcd: number = dest.x;
|
||||
export const defg: number = dest.y;`
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
//// function foo() {
|
||||
//// return { x: 1, y: 1};
|
||||
//// }
|
||||
//// export const { x, y = 0} = foo(), z= 42;
|
||||
|
||||
verify.codeFix({
|
||||
description: ts.Diagnostics.Extract_binding_expressions_to_variable.message,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo() {
|
||||
return { x: 1, y: 1};
|
||||
}
|
||||
const dest = foo();
|
||||
export const x: number = dest.x;
|
||||
const temp = dest.y;
|
||||
export const y: number = temp === undefined ? 0 : dest.y;
|
||||
export const z = 42;`});
|
||||
@@ -0,0 +1,21 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
//// function foo() {
|
||||
//// return { x: 1, y: 1 } as const;
|
||||
//// }
|
||||
//// export const { x, y = 0 } = foo();
|
||||
|
||||
verify.codeFix({
|
||||
description: ts.Diagnostics.Extract_binding_expressions_to_variable.message,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo() {
|
||||
return { x: 1, y: 1 } as const;
|
||||
}
|
||||
const dest = foo();
|
||||
export const x: 1 = dest.x;
|
||||
const temp = dest.y;
|
||||
export const y: 1 | 0 = temp === undefined ? 0 : dest.y;`
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
//// function foo() {
|
||||
//// return { x: 1, y: {42: {dd: "45"}, b: 2} };
|
||||
//// }
|
||||
//// function foo3(): "42" {
|
||||
//// return "42";
|
||||
//// }
|
||||
//// export const { x: a , y: { [foo3()]: {dd: e} } } = foo();
|
||||
|
||||
verify.codeFix({
|
||||
description: ts.Diagnostics.Extract_binding_expressions_to_variable.message,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo() {
|
||||
return { x: 1, y: {42: {dd: "45"}, b: 2} };
|
||||
}
|
||||
function foo3(): "42" {
|
||||
return "42";
|
||||
}
|
||||
const dest = foo();
|
||||
export const a: number = dest.x;
|
||||
const _a = foo3();
|
||||
export const e: string = (dest.y)[_a].dd;`
|
||||
});
|
||||
@@ -0,0 +1,13 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// @lib: es2019
|
||||
//// export const a = Symbol();
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add annotation of type 'unique symbol'",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`export const a: unique symbol = Symbol();`
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
//// function foo() { return 42; }
|
||||
//// export class A {
|
||||
//// readonly a = () => foo();
|
||||
//// }
|
||||
|
||||
verify.codeFixAvailable([
|
||||
{ description: "Add return type 'number'" },
|
||||
]);
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add return type 'number'",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo() { return 42; }
|
||||
export class A {
|
||||
readonly a = (): number => foo();
|
||||
}`
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// @lib: es2019
|
||||
////export const a = {
|
||||
//// z: Symbol()
|
||||
////} as const;
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add annotation of type '{ readonly z: symbol; }'`,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`export const a: {
|
||||
readonly z: symbol;
|
||||
} = {
|
||||
z: Symbol()
|
||||
} as const;`
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
////const a = 42;
|
||||
////const b = 43;
|
||||
////export function foo() { return a + b; }
|
||||
|
||||
verify.codeFixAvailable([
|
||||
{ description: "Add return type 'number'" }
|
||||
]);
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add return type 'number'",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`const a = 42;
|
||||
const b = 43;
|
||||
export function foo(): number { return a + b; }`,
|
||||
});
|
||||
@@ -0,0 +1,21 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// @lib: es2019
|
||||
//// export function foo () {
|
||||
//// return Symbol();
|
||||
//// }
|
||||
|
||||
verify.codeFixAvailable([
|
||||
{ description: "Add return type 'symbol'" }
|
||||
]);
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add return type 'symbol'",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`export function foo (): symbol {
|
||||
return Symbol();
|
||||
}`
|
||||
});
|
||||
@@ -0,0 +1,52 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// @lib: es2019
|
||||
|
||||
/////**
|
||||
//// * Test
|
||||
//// */
|
||||
////export function foo(): number { return 0; }
|
||||
/////**
|
||||
////* Docs
|
||||
////*/
|
||||
////export const bar = (a = foo()) =>
|
||||
//// a;
|
||||
////// Trivia
|
||||
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add return type 'number'",
|
||||
index: 0,
|
||||
applyChanges: true,
|
||||
newFileContent:
|
||||
`/**
|
||||
* Test
|
||||
*/
|
||||
export function foo(): number { return 0; }
|
||||
/**
|
||||
* Docs
|
||||
*/
|
||||
export const bar = (a = foo()): number =>
|
||||
a;
|
||||
// Trivia`
|
||||
});
|
||||
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add annotation of type 'number'",
|
||||
index: 0,
|
||||
applyChanges: true,
|
||||
newFileContent:
|
||||
`/**
|
||||
* Test
|
||||
*/
|
||||
export function foo(): number { return 0; }
|
||||
/**
|
||||
* Docs
|
||||
*/
|
||||
export const bar = (a: number = foo()): number =>
|
||||
a;
|
||||
// Trivia`
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// @lib: es2019
|
||||
/////**
|
||||
//// * Test
|
||||
//// */
|
||||
////export function foo(){}
|
||||
|
||||
verify.codeFixAvailable([
|
||||
{ description: "Add return type 'void'" }
|
||||
]);
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add return type 'void'",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`/**
|
||||
* Test
|
||||
*/
|
||||
export function foo(): void{}`
|
||||
});
|
||||
@@ -0,0 +1,41 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
////function mixin<T extends new (...a: any) => any>(ctor: T): T {
|
||||
//// return ctor;
|
||||
////}
|
||||
////class Point2D { x = 0; y = 0; }
|
||||
////interface I{}
|
||||
////export class Point3D extends
|
||||
//// /** Base class */
|
||||
//// mixin(Point2D)
|
||||
//// // Test
|
||||
//// implements I
|
||||
//// {
|
||||
//// z = 0;
|
||||
////}
|
||||
|
||||
verify.codeFixAvailable([
|
||||
{ description: ts.Diagnostics.Extract_base_class_to_variable.message }
|
||||
]);
|
||||
|
||||
verify.codeFix({
|
||||
description: ts.Diagnostics.Extract_base_class_to_variable.message,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function mixin<T extends new (...a: any) => any>(ctor: T): T {
|
||||
return ctor;
|
||||
}
|
||||
class Point2D { x = 0; y = 0; }
|
||||
interface I{}
|
||||
const Point3DBase: typeof Point2D =
|
||||
/** Base class */
|
||||
mixin(Point2D);
|
||||
export class Point3D extends Point3DBase
|
||||
// Test
|
||||
implements I
|
||||
{
|
||||
z = 0;
|
||||
}`
|
||||
});
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
////function mixin<T extends new (...a: any) => any>(ctor: T): T {
|
||||
//// return ctor;
|
||||
////}
|
||||
////class Point2D { x = 0; y = 0; }
|
||||
////export class Point3D2 extends mixin(Point2D) {
|
||||
//// z = 0;
|
||||
////}
|
||||
|
||||
verify.codeFixAvailable([
|
||||
{ description: ts.Diagnostics.Extract_base_class_to_variable.message }
|
||||
]);
|
||||
|
||||
verify.codeFix({
|
||||
description: ts.Diagnostics.Extract_base_class_to_variable.message,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function mixin<T extends new (...a: any) => any>(ctor: T): T {
|
||||
return ctor;
|
||||
}
|
||||
class Point2D { x = 0; y = 0; }
|
||||
const Point3D2Base: typeof Point2D = mixin(Point2D);
|
||||
export class Point3D2 extends Point3D2Base {
|
||||
z = 0;
|
||||
}`
|
||||
});
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
////function mixin<T extends new (...a: any) => any>(ctor: T): T {
|
||||
//// return ctor;
|
||||
////}
|
||||
////class Point2D { x = 0; y = 0; }
|
||||
////export class Point3D3 extends mixin(Point2D) /* DD*/ {
|
||||
//// z = 0;
|
||||
////}
|
||||
|
||||
verify.codeFixAvailable([
|
||||
{ description: ts.Diagnostics.Extract_base_class_to_variable.message }
|
||||
]);
|
||||
|
||||
verify.codeFix({
|
||||
description: ts.Diagnostics.Extract_base_class_to_variable.message,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function mixin<T extends new (...a: any) => any>(ctor: T): T {
|
||||
return ctor;
|
||||
}
|
||||
class Point2D { x = 0; y = 0; }
|
||||
const Point3D3Base: typeof Point2D = mixin(Point2D) /* DD*/;
|
||||
export class Point3D3 extends Point3D3Base {
|
||||
z = 0;
|
||||
}`
|
||||
});
|
||||
@@ -0,0 +1,31 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// fileName: code.ts
|
||||
////export const extensions = {
|
||||
//// /**
|
||||
//// */
|
||||
//// fn: <T>(actualValue: T, expectedValue: T) => {
|
||||
//// return actualValue === expectedValue
|
||||
//// },
|
||||
//// fn2: function<T>(actualValue: T, expectedValue: T) {
|
||||
//// return actualValue === expectedValue
|
||||
//// }
|
||||
////}
|
||||
|
||||
verify.codeFixAll({
|
||||
fixId: "fixMissingTypeAnnotationOnExports",
|
||||
fixAllDescription: ts.Diagnostics.Add_all_missing_type_annotations.message,
|
||||
newFileContent:
|
||||
`export const extensions = {
|
||||
/**
|
||||
*/
|
||||
fn: <T>(actualValue: T, expectedValue: T): boolean => {
|
||||
return actualValue === expectedValue
|
||||
},
|
||||
fn2: function<T>(actualValue: T, expectedValue: T): boolean {
|
||||
return actualValue === expectedValue
|
||||
}
|
||||
}`
|
||||
})
|
||||
@@ -0,0 +1,21 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// fileName: code.ts
|
||||
////let p = { x: 1, y: 2}
|
||||
////const a = 1, b = 10, { x, y } = p, c = 1;
|
||||
////export { x, y }
|
||||
////export const d = a + b + c;
|
||||
|
||||
verify.codeFixAll({
|
||||
fixId: "fixMissingTypeAnnotationOnExports",
|
||||
fixAllDescription: ts.Diagnostics.Add_all_missing_type_annotations.message,
|
||||
newFileContent:
|
||||
`let p = { x: 1, y: 2}
|
||||
const x: number = p.x;
|
||||
const y: number = p.y;
|
||||
const a = 1, b = 10, c = 1;
|
||||
export { x, y }
|
||||
export const d: number = a + b + c;`
|
||||
})
|
||||
@@ -0,0 +1,111 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// fileName: code.ts
|
||||
////export const sessionLoader = {
|
||||
//// async loadSession() {
|
||||
//// if (Math.random() > 0.5) {
|
||||
//// return {
|
||||
//// PROP_1: {
|
||||
//// name: false,
|
||||
//// },
|
||||
//// PROPERTY_2: {
|
||||
//// name: 1,
|
||||
//// },
|
||||
//// PROPERTY_3: {
|
||||
//// name: 1
|
||||
//// },
|
||||
//// PROPERTY_4: {
|
||||
//// name: 315,
|
||||
//// },
|
||||
//// };
|
||||
//// }
|
||||
////
|
||||
//// return {
|
||||
//// PROP_1: {
|
||||
//// name: false,
|
||||
//// },
|
||||
//// PROPERTY_2: {
|
||||
//// name: undefined,
|
||||
//// },
|
||||
//// PROPERTY_3: {
|
||||
//// },
|
||||
//// PROPERTY_4: {
|
||||
//// name: 576,
|
||||
//// },
|
||||
//// };
|
||||
//// },
|
||||
////};
|
||||
|
||||
|
||||
const description = "Add return type 'Promise<{\n PROP_1: {\n name: boolean;\n };\n PROPERTY_2: {\n name: number;\n };\n PROPERTY_3: {\n name: number;\n };\n PROPE...'";
|
||||
verify.codeFixAvailable([
|
||||
{ description }
|
||||
]);
|
||||
|
||||
verify.codeFix({
|
||||
description,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`export const sessionLoader = {
|
||||
async loadSession(): Promise<{
|
||||
PROP_1: {
|
||||
name: boolean;
|
||||
};
|
||||
PROPERTY_2: {
|
||||
name: number;
|
||||
};
|
||||
PROPERTY_3: {
|
||||
name: number;
|
||||
};
|
||||
PROPERTY_4: {
|
||||
name: number;
|
||||
};
|
||||
} | {
|
||||
PROP_1: {
|
||||
name: boolean;
|
||||
};
|
||||
PROPERTY_2: {
|
||||
name: any;
|
||||
};
|
||||
PROPERTY_3: {
|
||||
name?: undefined;
|
||||
};
|
||||
PROPERTY_4: {
|
||||
name: number;
|
||||
};
|
||||
}> {
|
||||
if (Math.random() > 0.5) {
|
||||
return {
|
||||
PROP_1: {
|
||||
name: false,
|
||||
},
|
||||
PROPERTY_2: {
|
||||
name: 1,
|
||||
},
|
||||
PROPERTY_3: {
|
||||
name: 1
|
||||
},
|
||||
PROPERTY_4: {
|
||||
name: 315,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
PROP_1: {
|
||||
name: false,
|
||||
},
|
||||
PROPERTY_2: {
|
||||
name: undefined,
|
||||
},
|
||||
PROPERTY_3: {
|
||||
},
|
||||
PROPERTY_4: {
|
||||
name: 576,
|
||||
},
|
||||
};
|
||||
},
|
||||
};`
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// fileName: code.ts
|
||||
////function getString() {
|
||||
//// return ""
|
||||
////}
|
||||
////export const exp = {
|
||||
//// prop: getString()
|
||||
////};
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add satisfies and an inline type assertion with 'string'",
|
||||
index: 1,
|
||||
newFileContent:
|
||||
`function getString() {
|
||||
return ""
|
||||
}
|
||||
export const exp = {
|
||||
prop: getString() satisfies string as string
|
||||
};`
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
////const a = 42;
|
||||
////const b = 42;
|
||||
////export class C {
|
||||
//// //making sure comments are not changed
|
||||
//// property =a+b; // comment should stay here
|
||||
////}
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add annotation of type 'number'",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`const a = 42;
|
||||
const b = 42;
|
||||
export class C {
|
||||
//making sure comments are not changed
|
||||
property: number =a+b; // comment should stay here
|
||||
}`,
|
||||
});
|
||||
@@ -0,0 +1,28 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
|
||||
// @Filename: /person-code.ts
|
||||
////export type Person = { x: string; }
|
||||
////export function getPerson() : Person {
|
||||
//// return null!
|
||||
////}
|
||||
|
||||
// @Filename: /code.ts
|
||||
////import { getPerson } from "./person-code";
|
||||
////export const exp = {
|
||||
//// person: getPerson()
|
||||
////};
|
||||
|
||||
goTo.file("/code.ts");
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add satisfies and an inline type assertion with 'Person'",
|
||||
index: 1,
|
||||
newFileContent:
|
||||
`import { getPerson, Person } from "./person-code";
|
||||
export const exp = {
|
||||
person: getPerson() satisfies Person as Person
|
||||
};`
|
||||
});
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
|
||||
// @Filename: /person-code.ts
|
||||
////export type Person = { x: string; }
|
||||
////export function getPerson() : Person {
|
||||
//// return null!
|
||||
////}
|
||||
|
||||
// @Filename: /code.ts
|
||||
////import { getPerson } from "./person-code";
|
||||
////export default {
|
||||
//// person: getPerson()
|
||||
////};
|
||||
|
||||
goTo.file("/code.ts");
|
||||
verify.codeFixAvailable([
|
||||
{
|
||||
"description": "Extract default export to variable"
|
||||
},
|
||||
{
|
||||
"description": "Add satisfies and an inline type assertion with 'Person'"
|
||||
},
|
||||
{
|
||||
"description": "Extract to variable and replace with 'newLocal as typeof newLocal'"
|
||||
}
|
||||
])
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add satisfies and an inline type assertion with 'Person'",
|
||||
index: 1,
|
||||
newFileContent:
|
||||
`import { getPerson, Person } from "./person-code";
|
||||
export default {
|
||||
person: getPerson() satisfies Person as Person
|
||||
};`
|
||||
});
|
||||
@@ -0,0 +1,29 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// @Filename: /code.ts
|
||||
////const x = 1;
|
||||
////export default {
|
||||
//// x
|
||||
////};
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add satisfies and an inline type assertion with 'number'",
|
||||
index: 1,
|
||||
newFileContent:
|
||||
`const x = 1;
|
||||
export default {
|
||||
x: x as number
|
||||
};`
|
||||
});
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add satisfies and an inline type assertion with 'typeof x'",
|
||||
index: 2,
|
||||
newFileContent:
|
||||
`const x = 1;
|
||||
export default {
|
||||
x: x as typeof x
|
||||
};`
|
||||
});
|
||||
@@ -0,0 +1,26 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
|
||||
// @Filename: /code.ts
|
||||
////export class Foo {
|
||||
//// m() {
|
||||
//// }
|
||||
////}
|
||||
|
||||
verify.codeFixAvailable([
|
||||
{
|
||||
"description": "Add return type 'void'"
|
||||
},
|
||||
])
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add return type 'void'",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`export class Foo {
|
||||
m(): void {
|
||||
}
|
||||
}`
|
||||
});
|
||||
@@ -0,0 +1,65 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
|
||||
// @Filename: /code.ts
|
||||
////const Start = {
|
||||
//// A: 'A',
|
||||
//// B: 'B',
|
||||
////} as const;
|
||||
////
|
||||
////const End = {
|
||||
//// Y: "Y",
|
||||
//// Z: "Z"
|
||||
////} as const;
|
||||
////export const All_Part1 = {};
|
||||
////function getPart() {
|
||||
//// return { M: "Z"}
|
||||
////}
|
||||
////
|
||||
////export const All = {
|
||||
//// x: 1,
|
||||
//// ...Start,
|
||||
//// y: 1,
|
||||
//// ...getPart(),
|
||||
//// ...End,
|
||||
//// z: 1,
|
||||
////};
|
||||
verify.codeFix({
|
||||
description: "Add annotation of type 'typeof All_Part1_1 & typeof Start & typeof All_Part3 & typeof All_Part4 & typeof End & typeof All_Part6'" ,
|
||||
index: 1,
|
||||
newFileContent:
|
||||
`const Start = {
|
||||
A: 'A',
|
||||
B: 'B',
|
||||
} as const;
|
||||
|
||||
const End = {
|
||||
Y: "Y",
|
||||
Z: "Z"
|
||||
} as const;
|
||||
export const All_Part1 = {};
|
||||
function getPart() {
|
||||
return { M: "Z"}
|
||||
}
|
||||
|
||||
const All_Part1_1 = {
|
||||
x: 1
|
||||
};
|
||||
const All_Part3 = {
|
||||
y: 1
|
||||
};
|
||||
const All_Part4 = getPart();
|
||||
const All_Part6 = {
|
||||
z: 1
|
||||
};
|
||||
export const All: typeof All_Part1_1 & typeof Start & typeof All_Part3 & typeof All_Part4 & typeof End & typeof All_Part6 = {
|
||||
...All_Part1_1,
|
||||
...Start,
|
||||
...All_Part3,
|
||||
...All_Part4,
|
||||
...End,
|
||||
...All_Part6
|
||||
};`
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
|
||||
// @Filename: /code.ts
|
||||
////const foo = { a: 1 }
|
||||
////export const exported = foo;
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add annotation of type 'typeof foo'" ,
|
||||
index: 1,
|
||||
newFileContent:
|
||||
`const foo = { a: 1 }
|
||||
export const exported: typeof foo = foo;`
|
||||
});
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
|
||||
// @Filename: /code.ts
|
||||
////const A = "A"
|
||||
////const B = "B"
|
||||
////export const AB = Math.random()? A: B;
|
||||
verify.codeFixAvailable([
|
||||
{
|
||||
"description": "Add annotation of type '\"A\" | \"B\"'"
|
||||
},
|
||||
{
|
||||
"description": "Add annotation of type 'typeof A | typeof B'"
|
||||
},
|
||||
{
|
||||
"description": "Add annotation of type 'string'"
|
||||
},
|
||||
{
|
||||
"description": "Add satisfies and an inline type assertion with '\"A\" | \"B\"'"
|
||||
},
|
||||
{
|
||||
"description": "Add satisfies and an inline type assertion with 'typeof A | typeof B'"
|
||||
},
|
||||
{
|
||||
"description": "Add satisfies and an inline type assertion with 'string'"
|
||||
}
|
||||
])
|
||||
verify.codeFix({
|
||||
description: "Add satisfies and an inline type assertion with 'typeof A | typeof B'" ,
|
||||
index: 4,
|
||||
newFileContent:
|
||||
`const A = "A"
|
||||
const B = "B"
|
||||
export const AB = (Math.random() ? A : B) satisfies typeof A | typeof B as typeof A | typeof B;`
|
||||
});
|
||||
@@ -0,0 +1,72 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
|
||||
// @Filename: /code.ts
|
||||
////const Start = [
|
||||
//// 'A',
|
||||
//// 'B',
|
||||
////] as const;
|
||||
////
|
||||
////const End = [
|
||||
//// "Y",
|
||||
//// "Z"
|
||||
////] as const;
|
||||
////export const All_Part1 = {};
|
||||
////function getPart() {
|
||||
//// return ["Z"]
|
||||
////}
|
||||
////
|
||||
////export const All = [
|
||||
//// 1,
|
||||
//// ...Start,
|
||||
//// 1,
|
||||
//// ...getPart(),
|
||||
//// ...End,
|
||||
//// 1,
|
||||
////] as const;
|
||||
verify.codeFix({
|
||||
description: `Add annotation of type '[...typeof All_Part1_1, ...typeof Start, ...typeof All_Part3, ...typeof All_Part4, ...typeof End, ...typeof All_Part6]'` ,
|
||||
index: 1,
|
||||
newFileContent:
|
||||
`const Start = [
|
||||
'A',
|
||||
'B',
|
||||
] as const;
|
||||
|
||||
const End = [
|
||||
"Y",
|
||||
"Z"
|
||||
] as const;
|
||||
export const All_Part1 = {};
|
||||
function getPart() {
|
||||
return ["Z"]
|
||||
}
|
||||
|
||||
const All_Part1_1 = [
|
||||
1
|
||||
] as const;
|
||||
const All_Part3 = [
|
||||
1
|
||||
] as const;
|
||||
const All_Part4 = getPart() as const;
|
||||
const All_Part6 = [
|
||||
1
|
||||
] as const;
|
||||
export const All: [
|
||||
...typeof All_Part1_1,
|
||||
...typeof Start,
|
||||
...typeof All_Part3,
|
||||
...typeof All_Part4,
|
||||
...typeof End,
|
||||
...typeof All_Part6
|
||||
] = [
|
||||
...All_Part1_1,
|
||||
...Start,
|
||||
...All_Part3,
|
||||
...All_Part4,
|
||||
...End,
|
||||
...All_Part6
|
||||
] as const;`
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// @lib: es2019
|
||||
|
||||
// @Filename: /code.ts
|
||||
////const u: unique symbol = Symbol();
|
||||
////export const fn = () => ({ u } as const);
|
||||
|
||||
verify.codeFix({
|
||||
description:
|
||||
`Add return type '{ readonly u: typeof u; }'` ,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`const u: unique symbol = Symbol();
|
||||
export const fn = (): {
|
||||
readonly u: typeof u;
|
||||
} => ({ u } as const);`
|
||||
});
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// @lib: es2019
|
||||
|
||||
// @Filename: /code.ts
|
||||
////let c: string[] = [];
|
||||
////export let o = {
|
||||
//// p: [
|
||||
//// ...c
|
||||
//// ]
|
||||
////}
|
||||
|
||||
verify.codeFix({
|
||||
description: `Mark array literal as const`,
|
||||
applyChanges: true,
|
||||
index: 2,
|
||||
newFileContent:
|
||||
`let c: string[] = [];
|
||||
export let o = {
|
||||
p: [
|
||||
...c
|
||||
] as const
|
||||
}`
|
||||
});
|
||||
|
||||
verify.codeFix({
|
||||
description: `Extract to variable and replace with 'newLocal as typeof newLocal'`,
|
||||
applyChanges: true,
|
||||
index: 1,
|
||||
newFileContent:
|
||||
`let c: string[] = [];
|
||||
const newLocal = [
|
||||
...c
|
||||
] as const;
|
||||
export let o = {
|
||||
p: newLocal as typeof newLocal
|
||||
}`
|
||||
});
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add annotation of type 'readonly string[]'`,
|
||||
applyChanges: true,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`let c: string[] = [];
|
||||
const newLocal: readonly string[] = [
|
||||
...c
|
||||
] as const;
|
||||
export let o = {
|
||||
p: newLocal as typeof newLocal
|
||||
}`
|
||||
});
|
||||
@@ -0,0 +1,25 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
////const a = 42;
|
||||
////const b = 42;
|
||||
////export class C {
|
||||
//// method() { return a + b };
|
||||
////}
|
||||
|
||||
verify.codeFixAvailable([
|
||||
{ description: "Add return type 'number'" },
|
||||
]);
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add return type 'number'",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`const a = 42;
|
||||
const b = 42;
|
||||
export class C {
|
||||
method(): number { return a + b };
|
||||
}`,
|
||||
|
||||
});
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// @lib: es2019
|
||||
|
||||
// @Filename: /code.ts
|
||||
////let c: string[] = [];
|
||||
////export let o = {
|
||||
//// p: Math.random() ? []: [
|
||||
//// ...c
|
||||
//// ]
|
||||
////}
|
||||
|
||||
verify.codeFix({
|
||||
description: `Extract to variable and replace with 'newLocal as typeof newLocal'`,
|
||||
applyChanges: true,
|
||||
index: 2,
|
||||
newFileContent:
|
||||
`let c: string[] = [];
|
||||
const newLocal = Math.random() ? [] : [
|
||||
...c
|
||||
];
|
||||
export let o = {
|
||||
p: newLocal as typeof newLocal
|
||||
}`
|
||||
});
|
||||
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add annotation of type 'string[]'`,
|
||||
applyChanges: true,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`let c: string[] = [];
|
||||
const newLocal: string[] = Math.random() ? [] : [
|
||||
...c
|
||||
];
|
||||
export let o = {
|
||||
p: newLocal as typeof newLocal
|
||||
}`
|
||||
});
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// @lib: es2019
|
||||
|
||||
// @Filename: /code.ts
|
||||
////enum E {
|
||||
//// A = "foo".length
|
||||
////}
|
||||
verify.codeFixAvailable([])
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// @lib: es2019
|
||||
|
||||
// @Filename: /code.ts
|
||||
////class A {
|
||||
//// static readonly p1 = Symbol();
|
||||
////}
|
||||
verify.codeFix({
|
||||
description: "Add annotation of type 'unique symbol'",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`class A {
|
||||
static readonly p1: unique symbol = Symbol();
|
||||
}`
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// @lib: es2019
|
||||
|
||||
// @Filename: /code.ts
|
||||
////const foo = () => {}
|
||||
////foo/*a*/["a"] = "A";
|
||||
////foo["b"] = "C"
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add annotation of type '{ (): void; a: string; b: string; }'",
|
||||
index: 1,
|
||||
newFileContent:
|
||||
`const foo: {
|
||||
(): void;
|
||||
a: string;
|
||||
b: string;
|
||||
} = () => {}
|
||||
foo["a"] = "A";
|
||||
foo["b"] = "C"`
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// @lib: es2019
|
||||
|
||||
// @Filename: /code.ts
|
||||
////function foo(): void {}
|
||||
////foo.x = 1;
|
||||
////foo.y = 1;
|
||||
|
||||
verify.codeFix({
|
||||
description: "Annotate types of properties expando function in a namespace",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo(): void {}
|
||||
declare namespace foo {
|
||||
export var x: number;
|
||||
export var y: number;
|
||||
}
|
||||
foo.x = 1;
|
||||
foo.y = 1;`
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// @lib: es2019
|
||||
|
||||
// @Filename: /code.ts
|
||||
////function foo(): void {}
|
||||
////// cannot name this property because it's an invalid variable name.
|
||||
////foo["@bar"] = 42;
|
||||
////foo.x = 1;
|
||||
|
||||
verify.codeFix({
|
||||
description: "Annotate types of properties expando function in a namespace",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo(): void {}
|
||||
declare namespace foo {
|
||||
export var x: number;
|
||||
}
|
||||
// cannot name this property because it's an invalid variable name.
|
||||
foo["@bar"] = 42;
|
||||
foo.x = 1;`
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// @lib: es2019
|
||||
|
||||
// @Filename: /code.ts
|
||||
////function foo(): void {}
|
||||
////// x already exists, so do not generate code for 'x'
|
||||
////foo.x = 1;
|
||||
////foo.y = 1;
|
||||
////namespace foo {
|
||||
//// export let x = 42;
|
||||
////}
|
||||
|
||||
verify.codeFix({
|
||||
description: "Annotate types of properties expando function in a namespace",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo(): void {}
|
||||
declare namespace foo {
|
||||
export var y: number;
|
||||
}
|
||||
// x already exists, so do not generate code for 'x'
|
||||
foo.x = 1;
|
||||
foo.y = 1;
|
||||
namespace foo {
|
||||
export let x = 42;
|
||||
}`
|
||||
});
|
||||
@@ -0,0 +1,23 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// @lib: es2019
|
||||
|
||||
// @Filename: /code.ts
|
||||
////const foo = (): void => {}
|
||||
////foo.a = "A";
|
||||
////foo.b = "C"
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add annotation of type '{ (): void; a: string; b: string; }'",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`const foo: {
|
||||
(): void;
|
||||
a: string;
|
||||
b: string;
|
||||
} = (): void => {}
|
||||
foo.a = "A";
|
||||
foo.b = "C"`
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// @lib: es2019
|
||||
|
||||
// @Filename: /code.ts
|
||||
//// export default 1 + 1;
|
||||
|
||||
verify.codeFix({
|
||||
description: "Extract default export to variable",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`const _default_1: number = 1 + 1;
|
||||
export default _default_1;`
|
||||
});
|
||||
@@ -0,0 +1,67 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
|
||||
// @Filename: /code.ts
|
||||
|
||||
//// function classDecorator<T extends Function> (value: T, context: ClassDecoratorContext) {}
|
||||
//// function methodDecorator<This> (
|
||||
//// target: (...args: number[])=> number,
|
||||
//// context: ClassMethodDecoratorContext<This, (this: This, ...args: number[]) => number>) {}
|
||||
//// function getterDecorator(value: Function, context: ClassGetterDecoratorContext) {}
|
||||
//// function setterDecorator(value: Function, context: ClassSetterDecoratorContext) {}
|
||||
//// function fieldDecorator(value: undefined, context: ClassFieldDecoratorContext) {}
|
||||
//// function foo() { return 42;}
|
||||
////
|
||||
//// @classDecorator
|
||||
//// export class A {
|
||||
//// @methodDecorator
|
||||
//// sum(...args: number[]) {
|
||||
//// return args.reduce((a, b) => a + b, 0);
|
||||
//// }
|
||||
//// getSelf() {
|
||||
//// return this;
|
||||
//// }
|
||||
//// @getterDecorator
|
||||
//// get a() {
|
||||
//// return foo();
|
||||
//// }
|
||||
//// @setterDecorator
|
||||
//// set a(value) {}
|
||||
////
|
||||
//// @fieldDecorator classProp = foo();
|
||||
//// }
|
||||
|
||||
verify.codeFixAll({
|
||||
fixId: "fixMissingTypeAnnotationOnExports",
|
||||
fixAllDescription: ts.Diagnostics.Add_all_missing_type_annotations.message,
|
||||
newFileContent:
|
||||
`function classDecorator<T extends Function> (value: T, context: ClassDecoratorContext) {}
|
||||
function methodDecorator<This> (
|
||||
target: (...args: number[])=> number,
|
||||
context: ClassMethodDecoratorContext<This, (this: This, ...args: number[]) => number>) {}
|
||||
function getterDecorator(value: Function, context: ClassGetterDecoratorContext) {}
|
||||
function setterDecorator(value: Function, context: ClassSetterDecoratorContext) {}
|
||||
function fieldDecorator(value: undefined, context: ClassFieldDecoratorContext) {}
|
||||
function foo() { return 42;}
|
||||
|
||||
@classDecorator
|
||||
export class A {
|
||||
@methodDecorator
|
||||
sum(...args: number[]): number {
|
||||
return args.reduce((a, b) => a + b, 0);
|
||||
}
|
||||
getSelf(): this {
|
||||
return this;
|
||||
}
|
||||
@getterDecorator
|
||||
get a(): number {
|
||||
return foo();
|
||||
}
|
||||
@setterDecorator
|
||||
set a(value) {}
|
||||
|
||||
@fieldDecorator classProp: number = foo();
|
||||
}`
|
||||
});
|
||||
+66
@@ -0,0 +1,66 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
// @experimentalDecorators: true
|
||||
|
||||
// @Filename: /code.ts
|
||||
|
||||
//// function classDecorator<T extends Function>() { return (target: T) => target; }
|
||||
//// function methodDecorator() { return (target: any, key: string, descriptor: PropertyDescriptor) => descriptor;}
|
||||
//// function parameterDecorator() { return (target: any, key: string, idx: number) => {};}
|
||||
//// function getterDecorator() { return (target: any, key: string) => {}; }
|
||||
//// function setterDecorator() { return (target: any, key: string) => {}; }
|
||||
//// function fieldDecorator() { return (target: any, key: string) => {}; }
|
||||
//// function foo() { return 42; }
|
||||
////
|
||||
//// @classDecorator()
|
||||
//// export class A {
|
||||
//// @methodDecorator()
|
||||
//// sum(...args: number[]) {
|
||||
//// return args.reduce((a, b) => a + b, 0);
|
||||
//// }
|
||||
//// getSelf() {
|
||||
//// return this;
|
||||
//// }
|
||||
//// passParameter(@parameterDecorator() param = foo()) {}
|
||||
//// @getterDecorator()
|
||||
//// get a() {
|
||||
//// return foo();
|
||||
//// }
|
||||
//// @setterDecorator()
|
||||
//// set a(value) {}
|
||||
//// @fieldDecorator() classProp = foo();
|
||||
//// }
|
||||
|
||||
verify.codeFixAll({
|
||||
fixId: "fixMissingTypeAnnotationOnExports",
|
||||
fixAllDescription: ts.Diagnostics.Add_all_missing_type_annotations.message,
|
||||
newFileContent:
|
||||
`function classDecorator<T extends Function>() { return (target: T) => target; }
|
||||
function methodDecorator() { return (target: any, key: string, descriptor: PropertyDescriptor) => descriptor;}
|
||||
function parameterDecorator() { return (target: any, key: string, idx: number) => {};}
|
||||
function getterDecorator() { return (target: any, key: string) => {}; }
|
||||
function setterDecorator() { return (target: any, key: string) => {}; }
|
||||
function fieldDecorator() { return (target: any, key: string) => {}; }
|
||||
function foo() { return 42; }
|
||||
|
||||
@classDecorator()
|
||||
export class A {
|
||||
@methodDecorator()
|
||||
sum(...args: number[]): number {
|
||||
return args.reduce((a, b) => a + b, 0);
|
||||
}
|
||||
getSelf(): this {
|
||||
return this;
|
||||
}
|
||||
passParameter(@parameterDecorator() param: number = foo()): void {}
|
||||
@getterDecorator()
|
||||
get a(): number {
|
||||
return foo();
|
||||
}
|
||||
@setterDecorator()
|
||||
set a(value) {}
|
||||
@fieldDecorator() classProp: number = foo();
|
||||
}`
|
||||
});
|
||||
@@ -0,0 +1,24 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
////const a = 42;
|
||||
////const b = 42;
|
||||
////export class C {
|
||||
//// get property() { return a + b; }
|
||||
////}
|
||||
|
||||
verify.codeFixAvailable([
|
||||
{ description: "Add return type 'number'" }
|
||||
]);
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add return type 'number'",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`const a = 42;
|
||||
const b = 42;
|
||||
export class C {
|
||||
get property(): number { return a + b; }
|
||||
}`,
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
////function foo(): number[] { return [42]; }
|
||||
////export const c = [...foo()];
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add annotation of type 'number[]'",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo(): number[] { return [42]; }
|
||||
export const c: number[] = [...foo()];`,
|
||||
});
|
||||
@@ -0,0 +1,16 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
////function foo(): number[] { return [42]; }
|
||||
////export const c = { foo: foo() };
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add annotation of type '{ foo: number[]; }'`,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo(): number[] { return [42]; }
|
||||
export const c: {
|
||||
foo: number[];
|
||||
} = { foo: foo() };`,
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
////function foo() {return 42;}
|
||||
////export const g = function () { return foo(); };
|
||||
|
||||
verify.codeFixAvailable([
|
||||
{ description: "Add return type 'number'" },
|
||||
]);
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add return type 'number'",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo() {return 42;}
|
||||
export const g = function (): number { return foo(); };`,
|
||||
});
|
||||
@@ -0,0 +1,20 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @isolatedDeclarations: true
|
||||
// @declaration: true
|
||||
////function foo( ){
|
||||
//// return 42;
|
||||
////}
|
||||
////const a = foo();
|
||||
////export = a;
|
||||
|
||||
verify.codeFix({
|
||||
description: "Add annotation of type 'number'",
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo( ){
|
||||
return 42;
|
||||
}
|
||||
const a: number = foo();
|
||||
export = a;`,
|
||||
});
|
||||
Reference in New Issue
Block a user