mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-10 18:04:18 -05:00
add support of codefix for Strict Class Initialization (#21528)
* add support of add undefined type to propertyDeclaration * add support of add Definite Assignment Assertions to propertyDeclaration * add support of add Initializer to propertyDeclaration * remove useless parameter * fix PropertyDeclaration emit missing exclamationToken * merge fixes and fix * fix unnecessary type assert
This commit is contained in:
@@ -15889,7 +15889,7 @@ namespace ts {
|
||||
|
||||
// Referencing abstract properties within their own constructors is not allowed
|
||||
if ((flags & ModifierFlags.Abstract) && isThisProperty(node) && symbolHasNonMethodDeclaration(prop)) {
|
||||
const declaringClassDeclaration = <ClassLikeDeclaration>getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop));
|
||||
const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop));
|
||||
if (declaringClassDeclaration && isNodeWithinConstructorOfClass(node, declaringClassDeclaration)) {
|
||||
error(errorNode, Diagnostics.Abstract_property_0_in_class_1_cannot_be_accessed_in_the_constructor, symbolToString(prop), getTextOfIdentifierOrLiteral(declaringClassDeclaration.name));
|
||||
return false;
|
||||
@@ -15905,7 +15905,7 @@ namespace ts {
|
||||
|
||||
// Private property is accessible if the property is within the declaring class
|
||||
if (flags & ModifierFlags.Private) {
|
||||
const declaringClassDeclaration = <ClassLikeDeclaration>getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop));
|
||||
const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(getParentOfSymbol(prop));
|
||||
if (!isNodeWithinClass(node, declaringClassDeclaration)) {
|
||||
error(errorNode, Diagnostics.Property_0_is_private_and_only_accessible_within_class_1, symbolToString(prop), typeToString(getDeclaringClass(prop)));
|
||||
return false;
|
||||
@@ -17627,7 +17627,7 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
const declaringClassDeclaration = <ClassLikeDeclaration>getClassLikeDeclarationOfSymbol(declaration.parent.symbol);
|
||||
const declaringClassDeclaration = getClassLikeDeclarationOfSymbol(declaration.parent.symbol);
|
||||
const declaringClass = <InterfaceType>getDeclaredTypeOfSymbol(declaration.parent.symbol);
|
||||
|
||||
// A private or protected constructor can only be instantiated within its own class (or a subclass, for protected)
|
||||
@@ -23115,7 +23115,7 @@ namespace ts {
|
||||
if (signatures.length) {
|
||||
const declaration = signatures[0].declaration;
|
||||
if (declaration && hasModifier(declaration, ModifierFlags.Private)) {
|
||||
const typeClassDeclaration = <ClassLikeDeclaration>getClassLikeDeclarationOfSymbol(type.symbol);
|
||||
const typeClassDeclaration = getClassLikeDeclarationOfSymbol(type.symbol);
|
||||
if (!isNodeWithinClass(node, typeClassDeclaration)) {
|
||||
error(node, Diagnostics.Cannot_extend_a_class_0_Class_constructor_is_marked_as_private, getFullyQualifiedName(type.symbol));
|
||||
}
|
||||
|
||||
@@ -3965,5 +3965,17 @@
|
||||
"Convert to ES6 module": {
|
||||
"category": "Message",
|
||||
"code": 95017
|
||||
},
|
||||
"Add 'undefined' type to property '{0}'": {
|
||||
"category": "Message",
|
||||
"code": 95018
|
||||
},
|
||||
"Add initializer to property '{0}'": {
|
||||
"category": "Message",
|
||||
"code": 95019
|
||||
},
|
||||
"Add definite assignment assertion to property '{0}'": {
|
||||
"category": "Message",
|
||||
"code": 95020
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1024,6 +1024,7 @@ namespace ts {
|
||||
emitModifiers(node, node.modifiers);
|
||||
emit(node.name);
|
||||
emitIfPresent(node.questionToken);
|
||||
emitIfPresent(node.exclamationToken);
|
||||
emitTypeAnnotation(node.type);
|
||||
emitInitializer(node.initializer);
|
||||
writeSemicolon();
|
||||
|
||||
@@ -3738,7 +3738,7 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getClassLikeDeclarationOfSymbol(symbol: Symbol): Declaration | undefined {
|
||||
export function getClassLikeDeclarationOfSymbol(symbol: Symbol): ClassLikeDeclaration | undefined {
|
||||
return find(symbol.declarations, isClassLike);
|
||||
}
|
||||
|
||||
|
||||
142
src/services/codefixes/fixStrictClassInitialization.ts
Normal file
142
src/services/codefixes/fixStrictClassInitialization.ts
Normal file
@@ -0,0 +1,142 @@
|
||||
/* @internal */
|
||||
namespace ts.codefix {
|
||||
const fixIdAddDefiniteAssignmentAssertions = "addMissingPropertyDefiniteAssignmentAssertions";
|
||||
const fixIdAddUndefinedType = "addMissingPropertyUndefinedType";
|
||||
const fixIdAddInitializer = "addMissingPropertyInitializer";
|
||||
const errorCodes = [Diagnostics.Property_0_has_no_initializer_and_is_not_definitely_assigned_in_the_constructor.code];
|
||||
registerCodeFix({
|
||||
errorCodes,
|
||||
getCodeActions: (context) => {
|
||||
const propertyDeclaration = getPropertyDeclaration(context.sourceFile, context.span.start);
|
||||
if (!propertyDeclaration) return;
|
||||
|
||||
const newLineCharacter = getNewLineOrDefaultFromHost(context.host, context.formatContext.options);
|
||||
const result = [
|
||||
getActionForAddMissingUndefinedType(context, propertyDeclaration),
|
||||
getActionForAddMissingDefiniteAssignmentAssertion(context, propertyDeclaration, newLineCharacter)
|
||||
];
|
||||
|
||||
append(result, getActionForAddMissingInitializer(context, propertyDeclaration, newLineCharacter));
|
||||
|
||||
return result;
|
||||
},
|
||||
fixIds: [fixIdAddDefiniteAssignmentAssertions, fixIdAddUndefinedType, fixIdAddInitializer],
|
||||
getAllCodeActions: context => {
|
||||
const newLineCharacter = getNewLineOrDefaultFromHost(context.host, context.formatContext.options);
|
||||
|
||||
return codeFixAll(context, errorCodes, (changes, diag) => {
|
||||
const propertyDeclaration = getPropertyDeclaration(diag.file, diag.start);
|
||||
if (!propertyDeclaration) return;
|
||||
|
||||
switch (context.fixId) {
|
||||
case fixIdAddDefiniteAssignmentAssertions:
|
||||
addDefiniteAssignmentAssertion(changes, diag.file, propertyDeclaration, newLineCharacter);
|
||||
break;
|
||||
case fixIdAddUndefinedType:
|
||||
addUndefinedType(changes, diag.file, propertyDeclaration);
|
||||
break;
|
||||
case fixIdAddInitializer:
|
||||
const checker = context.program.getTypeChecker();
|
||||
const initializer = getInitializer(checker, propertyDeclaration);
|
||||
if (!initializer) return;
|
||||
|
||||
addInitializer(changes, diag.file, propertyDeclaration, initializer, newLineCharacter);
|
||||
break;
|
||||
default:
|
||||
Debug.fail(JSON.stringify(context.fixId));
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
function getPropertyDeclaration (sourceFile: SourceFile, pos: number): PropertyDeclaration | undefined {
|
||||
const token = getTokenAtPosition(sourceFile, pos, /*includeJsDocComment*/ false);
|
||||
return isIdentifier(token) ? cast(token.parent, isPropertyDeclaration) : undefined;
|
||||
}
|
||||
|
||||
function getActionForAddMissingDefiniteAssignmentAssertion (context: CodeFixContext, propertyDeclaration: PropertyDeclaration, newLineCharacter: string): CodeFixAction {
|
||||
const description = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_definite_assignment_assertion_to_property_0), [propertyDeclaration.getText()]);
|
||||
const changes = textChanges.ChangeTracker.with(context, t => addDefiniteAssignmentAssertion(t, context.sourceFile, propertyDeclaration, newLineCharacter));
|
||||
return { description, changes, fixId: fixIdAddDefiniteAssignmentAssertions };
|
||||
}
|
||||
|
||||
function addDefiniteAssignmentAssertion(changeTracker: textChanges.ChangeTracker, propertyDeclarationSourceFile: SourceFile, propertyDeclaration: PropertyDeclaration, newLineCharacter: string): void {
|
||||
const property = updateProperty(
|
||||
propertyDeclaration,
|
||||
propertyDeclaration.decorators,
|
||||
propertyDeclaration.modifiers,
|
||||
propertyDeclaration.name,
|
||||
createToken(SyntaxKind.ExclamationToken),
|
||||
propertyDeclaration.type,
|
||||
propertyDeclaration.initializer
|
||||
);
|
||||
changeTracker.replaceNode(propertyDeclarationSourceFile, propertyDeclaration, property, { suffix: newLineCharacter });
|
||||
}
|
||||
|
||||
function getActionForAddMissingUndefinedType (context: CodeFixContext, propertyDeclaration: PropertyDeclaration): CodeFixAction {
|
||||
const description = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_undefined_type_to_property_0), [propertyDeclaration.name.getText()]);
|
||||
const changes = textChanges.ChangeTracker.with(context, t => addUndefinedType(t, context.sourceFile, propertyDeclaration));
|
||||
return { description, changes, fixId: fixIdAddUndefinedType };
|
||||
}
|
||||
|
||||
function addUndefinedType(changeTracker: textChanges.ChangeTracker, propertyDeclarationSourceFile: SourceFile, propertyDeclaration: PropertyDeclaration): void {
|
||||
const undefinedTypeNode = createKeywordTypeNode(SyntaxKind.UndefinedKeyword);
|
||||
const types = isUnionTypeNode(propertyDeclaration.type) ? propertyDeclaration.type.types.concat(undefinedTypeNode) : [propertyDeclaration.type, undefinedTypeNode];
|
||||
changeTracker.replaceNode(propertyDeclarationSourceFile, propertyDeclaration.type, createUnionTypeNode(types));
|
||||
}
|
||||
|
||||
function getActionForAddMissingInitializer (context: CodeFixContext, propertyDeclaration: PropertyDeclaration, newLineCharacter: string): CodeFixAction | undefined {
|
||||
const checker = context.program.getTypeChecker();
|
||||
const initializer = getInitializer(checker, propertyDeclaration);
|
||||
if (!initializer) return undefined;
|
||||
|
||||
const description = formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_initializer_to_property_0), [propertyDeclaration.name.getText()]);
|
||||
const changes = textChanges.ChangeTracker.with(context, t => addInitializer(t, context.sourceFile, propertyDeclaration, initializer, newLineCharacter));
|
||||
return { description, changes, fixId: fixIdAddInitializer };
|
||||
}
|
||||
|
||||
function addInitializer (changeTracker: textChanges.ChangeTracker, propertyDeclarationSourceFile: SourceFile, propertyDeclaration: PropertyDeclaration, initializer: Expression, newLineCharacter: string): void {
|
||||
const property = updateProperty(
|
||||
propertyDeclaration,
|
||||
propertyDeclaration.decorators,
|
||||
propertyDeclaration.modifiers,
|
||||
propertyDeclaration.name,
|
||||
propertyDeclaration.questionToken,
|
||||
propertyDeclaration.type,
|
||||
initializer
|
||||
);
|
||||
changeTracker.replaceNode(propertyDeclarationSourceFile, propertyDeclaration, property, { suffix: newLineCharacter });
|
||||
}
|
||||
|
||||
function getInitializer(checker: TypeChecker, propertyDeclaration: PropertyDeclaration): Expression | undefined {
|
||||
return getDefaultValueFromType(checker, checker.getTypeFromTypeNode(propertyDeclaration.type));
|
||||
}
|
||||
|
||||
function getDefaultValueFromType (checker: TypeChecker, type: Type): Expression | undefined {
|
||||
if (type.flags & TypeFlags.String) {
|
||||
return createLiteral("");
|
||||
}
|
||||
else if (type.flags & TypeFlags.Number) {
|
||||
return createNumericLiteral("0");
|
||||
}
|
||||
else if (type.flags & TypeFlags.Boolean) {
|
||||
return createFalse();
|
||||
}
|
||||
else if (type.flags & TypeFlags.Literal) {
|
||||
return createLiteral((<LiteralType>type).value);
|
||||
}
|
||||
else if (type.flags & TypeFlags.Union) {
|
||||
return firstDefined((<UnionType>type).types, t => getDefaultValueFromType(checker, t));
|
||||
}
|
||||
else if (getObjectFlags(type) & ObjectFlags.Class) {
|
||||
const classDeclaration = getClassLikeDeclarationOfSymbol(type.symbol);
|
||||
if (!classDeclaration || hasModifier(classDeclaration, ModifierFlags.Abstract)) return undefined;
|
||||
|
||||
const constructorDeclaration = find<ClassElement, ConstructorDeclaration>(classDeclaration.members, (m): m is ConstructorDeclaration => isConstructorDeclaration(m) && !!m.body)!;
|
||||
if (constructorDeclaration && constructorDeclaration.parameters.length) return undefined;
|
||||
|
||||
return createNew(createIdentifier(type.symbol.name), /*typeArguments*/ undefined, /*argumentsArray*/ undefined);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -17,4 +17,4 @@
|
||||
/// <reference path='helpers.ts' />
|
||||
/// <reference path='inferFromUsage.ts' />
|
||||
/// <reference path="fixInvalidImportSyntax.ts" />
|
||||
|
||||
/// <reference path="fixStrictClassInitialization.ts" />
|
||||
|
||||
40
tests/cases/fourslash/codeFixClassPropertyInitialization.ts
Normal file
40
tests/cases/fourslash/codeFixClassPropertyInitialization.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
//// abstract class A { abstract a (); }
|
||||
////
|
||||
//// class TT { constructor () {} }
|
||||
////
|
||||
//// class AT extends A { a () {} }
|
||||
////
|
||||
//// class Foo {}
|
||||
////
|
||||
//// class T {
|
||||
////
|
||||
//// a: string;
|
||||
////
|
||||
//// static b: string;
|
||||
////
|
||||
//// private c: string;
|
||||
////
|
||||
//// d: number | undefined;
|
||||
////
|
||||
//// e: string | number;
|
||||
////
|
||||
//// f: 1;
|
||||
////
|
||||
//// g: "123" | "456";
|
||||
////
|
||||
//// h: boolean;
|
||||
////
|
||||
//// i: TT;
|
||||
////
|
||||
//// j: A;
|
||||
////
|
||||
//// k: AT;
|
||||
////
|
||||
//// l: Foo;
|
||||
//// }
|
||||
|
||||
verify.codeFixAvailable()
|
||||
15
tests/cases/fourslash/codeFixClassPropertyInitialization1.ts
Normal file
15
tests/cases/fourslash/codeFixClassPropertyInitialization1.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
//// class T {
|
||||
//// a: string;
|
||||
//// }
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add 'undefined' type to property 'a'`,
|
||||
newFileContent: `class T {
|
||||
a: string | undefined;
|
||||
}`,
|
||||
index: 0
|
||||
})
|
||||
@@ -0,0 +1,15 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
//// class T {
|
||||
//// a: "a" | 2;
|
||||
//// }
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add initializer to property 'a'`,
|
||||
newFileContent: `class T {
|
||||
a: "a" | 2 = "a";
|
||||
}`,
|
||||
index: 2
|
||||
})
|
||||
@@ -0,0 +1,19 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
//// class TT { constructor () {} }
|
||||
////
|
||||
//// class T {
|
||||
//// a: TT;
|
||||
//// }
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add initializer to property 'a'`,
|
||||
newFileContent: `class TT { constructor () {} }
|
||||
|
||||
class T {
|
||||
a: TT = new TT;
|
||||
}`,
|
||||
index: 2
|
||||
})
|
||||
@@ -0,0 +1,23 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
//// abstract class A { abstract a (); }
|
||||
////
|
||||
//// class AT extends A { a () {} }
|
||||
////
|
||||
//// class T {
|
||||
//// a: AT;
|
||||
//// }
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add initializer to property 'a'`,
|
||||
newFileContent: `abstract class A { abstract a (); }
|
||||
|
||||
class AT extends A { a () {} }
|
||||
|
||||
class T {
|
||||
a: AT = new AT;
|
||||
}`,
|
||||
index: 2
|
||||
})
|
||||
@@ -0,0 +1,19 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
//// class TT { }
|
||||
////
|
||||
//// class T {
|
||||
//// a: TT;
|
||||
//// }
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add initializer to property 'a'`,
|
||||
newFileContent: `class TT { }
|
||||
|
||||
class T {
|
||||
a: TT = new TT;
|
||||
}`,
|
||||
index: 2
|
||||
})
|
||||
15
tests/cases/fourslash/codeFixClassPropertyInitialization2.ts
Normal file
15
tests/cases/fourslash/codeFixClassPropertyInitialization2.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
//// class T {
|
||||
//// a: string;
|
||||
//// }
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add definite assignment assertion to property 'a: string;'`,
|
||||
newFileContent: `class T {
|
||||
a!: string;
|
||||
}`,
|
||||
index: 1
|
||||
})
|
||||
15
tests/cases/fourslash/codeFixClassPropertyInitialization3.ts
Normal file
15
tests/cases/fourslash/codeFixClassPropertyInitialization3.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
//// class T {
|
||||
//// a: string;
|
||||
//// }
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add initializer to property 'a'`,
|
||||
newFileContent: `class T {
|
||||
a: string = "";
|
||||
}`,
|
||||
index: 2
|
||||
})
|
||||
15
tests/cases/fourslash/codeFixClassPropertyInitialization4.ts
Normal file
15
tests/cases/fourslash/codeFixClassPropertyInitialization4.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
//// class T {
|
||||
//// a: number;
|
||||
//// }
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add initializer to property 'a'`,
|
||||
newFileContent: `class T {
|
||||
a: number = 0;
|
||||
}`,
|
||||
index: 2
|
||||
})
|
||||
15
tests/cases/fourslash/codeFixClassPropertyInitialization5.ts
Normal file
15
tests/cases/fourslash/codeFixClassPropertyInitialization5.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
//// class T {
|
||||
//// a: boolean;
|
||||
//// }
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add initializer to property 'a'`,
|
||||
newFileContent: `class T {
|
||||
a: boolean = false;
|
||||
}`,
|
||||
index: 2
|
||||
})
|
||||
15
tests/cases/fourslash/codeFixClassPropertyInitialization6.ts
Normal file
15
tests/cases/fourslash/codeFixClassPropertyInitialization6.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
//// class T {
|
||||
//// a: "1";
|
||||
//// }
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add initializer to property 'a'`,
|
||||
newFileContent: `class T {
|
||||
a: "1" = "1";
|
||||
}`,
|
||||
index: 2
|
||||
})
|
||||
15
tests/cases/fourslash/codeFixClassPropertyInitialization7.ts
Normal file
15
tests/cases/fourslash/codeFixClassPropertyInitialization7.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
//// class T {
|
||||
//// a: 2;
|
||||
//// }
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add initializer to property 'a'`,
|
||||
newFileContent: `class T {
|
||||
a: 2 = 2;
|
||||
}`,
|
||||
index: 2
|
||||
})
|
||||
15
tests/cases/fourslash/codeFixClassPropertyInitialization8.ts
Normal file
15
tests/cases/fourslash/codeFixClassPropertyInitialization8.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
//// class T {
|
||||
//// a: string | number;
|
||||
//// }
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add initializer to property 'a'`,
|
||||
newFileContent: `class T {
|
||||
a: string | number = "";
|
||||
}`,
|
||||
index: 2
|
||||
})
|
||||
15
tests/cases/fourslash/codeFixClassPropertyInitialization9.ts
Normal file
15
tests/cases/fourslash/codeFixClassPropertyInitialization9.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
//// class T {
|
||||
//// a: 1 | 2;
|
||||
//// }
|
||||
|
||||
verify.codeFix({
|
||||
description: `Add initializer to property 'a'`,
|
||||
newFileContent: `class T {
|
||||
a: 1 | 2 = 1;
|
||||
}`,
|
||||
index: 2
|
||||
})
|
||||
@@ -0,0 +1,76 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
//// abstract class A { abstract a (); }
|
||||
////
|
||||
//// class TT { constructor () {} }
|
||||
////
|
||||
//// class AT extends A { a () {} }
|
||||
////
|
||||
//// class Foo {}
|
||||
////
|
||||
//// class T {
|
||||
////
|
||||
//// a: string;
|
||||
////
|
||||
//// static b: string;
|
||||
////
|
||||
//// private c: string;
|
||||
////
|
||||
//// d: number | undefined;
|
||||
////
|
||||
//// e: string | number;
|
||||
////
|
||||
//// f: 1;
|
||||
////
|
||||
//// g: "123" | "456";
|
||||
////
|
||||
//// h: boolean;
|
||||
////
|
||||
//// i: TT;
|
||||
////
|
||||
//// j: A;
|
||||
////
|
||||
//// k: AT;
|
||||
////
|
||||
//// l: Foo;
|
||||
//// }
|
||||
|
||||
verify.codeFixAll({
|
||||
fixId: 'addMissingPropertyDefiniteAssignmentAssertions',
|
||||
newFileContent: `abstract class A { abstract a (); }
|
||||
|
||||
class TT { constructor () {} }
|
||||
|
||||
class AT extends A { a () {} }
|
||||
|
||||
class Foo {}
|
||||
|
||||
class T {
|
||||
|
||||
a!: string;
|
||||
|
||||
static b: string;
|
||||
|
||||
private c!: string;
|
||||
|
||||
d: number | undefined;
|
||||
|
||||
e!: string | number;
|
||||
|
||||
f!: 1;
|
||||
|
||||
g!: "123" | "456";
|
||||
|
||||
h!: boolean;
|
||||
|
||||
i!: TT;
|
||||
|
||||
j!: A;
|
||||
|
||||
k!: AT;
|
||||
|
||||
l!: Foo;
|
||||
}`
|
||||
});
|
||||
@@ -0,0 +1,76 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
//// abstract class A { abstract a (); }
|
||||
////
|
||||
//// class TT { constructor () {} }
|
||||
////
|
||||
//// class AT extends A { a () {} }
|
||||
////
|
||||
//// class Foo {}
|
||||
////
|
||||
//// class T {
|
||||
////
|
||||
//// a: string;
|
||||
////
|
||||
//// static b: string;
|
||||
////
|
||||
//// private c: string;
|
||||
////
|
||||
//// d: number | undefined;
|
||||
////
|
||||
//// e: string | number;
|
||||
////
|
||||
//// f: 1;
|
||||
////
|
||||
//// g: "123" | "456";
|
||||
////
|
||||
//// h: boolean;
|
||||
////
|
||||
//// i: TT;
|
||||
////
|
||||
//// j: A;
|
||||
////
|
||||
//// k: AT;
|
||||
////
|
||||
//// l: Foo;
|
||||
//// }
|
||||
|
||||
verify.codeFixAll({
|
||||
fixId: 'addMissingPropertyUndefinedType',
|
||||
newFileContent: `abstract class A { abstract a (); }
|
||||
|
||||
class TT { constructor () {} }
|
||||
|
||||
class AT extends A { a () {} }
|
||||
|
||||
class Foo {}
|
||||
|
||||
class T {
|
||||
|
||||
a: string | undefined;
|
||||
|
||||
static b: string;
|
||||
|
||||
private c: string | undefined;
|
||||
|
||||
d: number | undefined;
|
||||
|
||||
e: string | number | undefined;
|
||||
|
||||
f: 1 | undefined;
|
||||
|
||||
g: "123" | "456" | undefined;
|
||||
|
||||
h: boolean | undefined;
|
||||
|
||||
i: TT | undefined;
|
||||
|
||||
j: A | undefined;
|
||||
|
||||
k: AT | undefined;
|
||||
|
||||
l: Foo | undefined;
|
||||
}`
|
||||
});
|
||||
@@ -0,0 +1,76 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
//// abstract class A { abstract a (); }
|
||||
////
|
||||
//// class TT { constructor () {} }
|
||||
////
|
||||
//// class AT extends A { a () {} }
|
||||
////
|
||||
//// class Foo {}
|
||||
////
|
||||
//// class T {
|
||||
////
|
||||
//// a: string;
|
||||
////
|
||||
//// static b: string;
|
||||
////
|
||||
//// private c: string;
|
||||
////
|
||||
//// d: number | undefined;
|
||||
////
|
||||
//// e: string | number;
|
||||
////
|
||||
//// f: 1;
|
||||
////
|
||||
//// g: "123" | "456";
|
||||
////
|
||||
//// h: boolean;
|
||||
////
|
||||
//// i: TT;
|
||||
////
|
||||
//// j: A;
|
||||
////
|
||||
//// k: AT;
|
||||
////
|
||||
//// l: Foo;
|
||||
//// }
|
||||
|
||||
verify.codeFixAll({
|
||||
fixId: 'addMissingPropertyInitializer',
|
||||
newFileContent: `abstract class A { abstract a (); }
|
||||
|
||||
class TT { constructor () {} }
|
||||
|
||||
class AT extends A { a () {} }
|
||||
|
||||
class Foo {}
|
||||
|
||||
class T {
|
||||
|
||||
a: string = "";
|
||||
|
||||
static b: string;
|
||||
|
||||
private c: string = "";
|
||||
|
||||
d: number | undefined;
|
||||
|
||||
e: string | number = "";
|
||||
|
||||
f: 1 = 1;
|
||||
|
||||
g: "123" | "456" = "123";
|
||||
|
||||
h: boolean = false;
|
||||
|
||||
i: TT = new TT;
|
||||
|
||||
j: A;
|
||||
|
||||
k: AT = new AT;
|
||||
|
||||
l: Foo = new Foo;
|
||||
}`
|
||||
});
|
||||
Reference in New Issue
Block a user