mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-06 11:54:44 -06:00
fix(40994): change type for optional properties (#41011)
This commit is contained in:
parent
292b778204
commit
3754bb4455
@ -52,6 +52,6 @@ namespace ts.codefix {
|
||||
else {
|
||||
Debug.fail("fixPropertyOverrideAccessor codefix got unexpected error code " + code);
|
||||
}
|
||||
return generateAccessorFromProperty(file, startPosition, endPosition, context, Diagnostics.Generate_get_and_set_accessors.message);
|
||||
return generateAccessorFromProperty(file, context.program, startPosition, endPosition, context, Diagnostics.Generate_get_and_set_accessors.message);
|
||||
}
|
||||
}
|
||||
|
||||
@ -24,8 +24,8 @@ namespace ts.codefix {
|
||||
error: string
|
||||
};
|
||||
|
||||
export function generateAccessorFromProperty(file: SourceFile, start: number, end: number, context: textChanges.TextChangesContext, _actionName: string): FileTextChanges[] | undefined {
|
||||
const fieldInfo = getAccessorConvertiblePropertyAtPosition(file, start, end);
|
||||
export function generateAccessorFromProperty(file: SourceFile, program: Program, start: number, end: number, context: textChanges.TextChangesContext, _actionName: string): FileTextChanges[] | undefined {
|
||||
const fieldInfo = getAccessorConvertiblePropertyAtPosition(file, program, start, end);
|
||||
if (!fieldInfo || !fieldInfo.info) return undefined;
|
||||
|
||||
const changeTracker = textChanges.ChangeTracker.fromContext(context);
|
||||
@ -51,7 +51,7 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
|
||||
updateFieldDeclaration(changeTracker, file, declaration, fieldName, fieldModifiers);
|
||||
updateFieldDeclaration(changeTracker, file, declaration, type, fieldName, fieldModifiers);
|
||||
|
||||
const getAccessor = generateGetAccessor(fieldName, accessorName, type, accessorModifiers, isStatic, container);
|
||||
suppressLeadingAndTrailingTrivia(getAccessor);
|
||||
@ -112,7 +112,7 @@ namespace ts.codefix {
|
||||
return modifierFlags;
|
||||
}
|
||||
|
||||
export function getAccessorConvertiblePropertyAtPosition(file: SourceFile, start: number, end: number, considerEmptySpans = true): InfoOrError | undefined {
|
||||
export function getAccessorConvertiblePropertyAtPosition(file: SourceFile, program: Program, start: number, end: number, considerEmptySpans = true): InfoOrError | undefined {
|
||||
const node = getTokenAtPosition(file, start);
|
||||
const cursorRequest = start === end && considerEmptySpans;
|
||||
const declaration = findAncestor(node.parent, isAcceptedDeclaration);
|
||||
@ -145,7 +145,7 @@ namespace ts.codefix {
|
||||
info: {
|
||||
isStatic: hasStaticModifier(declaration),
|
||||
isReadonly: hasEffectiveReadonlyModifier(declaration),
|
||||
type: getTypeAnnotationNode(declaration),
|
||||
type: getDeclarationType(declaration, program),
|
||||
container: declaration.kind === SyntaxKind.Parameter ? declaration.parent.parent : declaration.parent,
|
||||
originalName: (<AcceptedNameType>declaration.name).text,
|
||||
declaration,
|
||||
@ -195,14 +195,14 @@ namespace ts.codefix {
|
||||
);
|
||||
}
|
||||
|
||||
function updatePropertyDeclaration(changeTracker: textChanges.ChangeTracker, file: SourceFile, declaration: PropertyDeclaration, fieldName: AcceptedNameType, modifiers: ModifiersArray | undefined) {
|
||||
function updatePropertyDeclaration(changeTracker: textChanges.ChangeTracker, file: SourceFile, declaration: PropertyDeclaration, type: TypeNode | undefined, fieldName: AcceptedNameType, modifiers: ModifiersArray | undefined) {
|
||||
const property = factory.updatePropertyDeclaration(
|
||||
declaration,
|
||||
declaration.decorators,
|
||||
modifiers,
|
||||
fieldName,
|
||||
declaration.questionToken || declaration.exclamationToken,
|
||||
declaration.type,
|
||||
type,
|
||||
declaration.initializer
|
||||
);
|
||||
changeTracker.replaceNode(file, declaration, property);
|
||||
@ -213,9 +213,9 @@ namespace ts.codefix {
|
||||
changeTracker.replacePropertyAssignment(file, declaration, assignment);
|
||||
}
|
||||
|
||||
function updateFieldDeclaration(changeTracker: textChanges.ChangeTracker, file: SourceFile, declaration: AcceptedDeclaration, fieldName: AcceptedNameType, modifiers: ModifiersArray | undefined) {
|
||||
function updateFieldDeclaration(changeTracker: textChanges.ChangeTracker, file: SourceFile, declaration: AcceptedDeclaration, type: TypeNode | undefined, fieldName: AcceptedNameType, modifiers: ModifiersArray | undefined) {
|
||||
if (isPropertyDeclaration(declaration)) {
|
||||
updatePropertyDeclaration(changeTracker, file, declaration, fieldName, modifiers);
|
||||
updatePropertyDeclaration(changeTracker, file, declaration, type, fieldName, modifiers);
|
||||
}
|
||||
else if (isPropertyAssignment(declaration)) {
|
||||
updatePropertyAssignmentDeclaration(changeTracker, file, declaration, fieldName);
|
||||
@ -251,6 +251,19 @@ namespace ts.codefix {
|
||||
});
|
||||
}
|
||||
|
||||
function getDeclarationType(declaration: AcceptedDeclaration, program: Program): TypeNode | undefined {
|
||||
const typeNode = getTypeAnnotationNode(declaration);
|
||||
if (isPropertyDeclaration(declaration) && typeNode && declaration.questionToken) {
|
||||
const typeChecker = program.getTypeChecker();
|
||||
const type = typeChecker.getTypeFromTypeNode(typeNode);
|
||||
if (!typeChecker.isTypeAssignableTo(typeChecker.getUndefinedType(), type)) {
|
||||
const types = isUnionTypeNode(typeNode) ? typeNode.types : [typeNode];
|
||||
return factory.createUnionTypeNode([...types, factory.createKeywordTypeNode(SyntaxKind.UndefinedKeyword)]);
|
||||
}
|
||||
}
|
||||
return typeNode;
|
||||
}
|
||||
|
||||
export function getAllSupers(decl: ClassOrInterface | undefined, checker: TypeChecker): readonly ClassOrInterface[] {
|
||||
const res: ClassLikeDeclaration[] = [];
|
||||
while (decl) {
|
||||
|
||||
@ -5,9 +5,9 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
|
||||
registerRefactor(actionName, {
|
||||
getEditsForAction(context, actionName) {
|
||||
if (!context.endPosition) return undefined;
|
||||
const info = codefix.getAccessorConvertiblePropertyAtPosition(context.file, context.startPosition, context.endPosition);
|
||||
const info = codefix.getAccessorConvertiblePropertyAtPosition(context.file, context.program, context.startPosition, context.endPosition);
|
||||
if (!info || !info.info) return undefined;
|
||||
const edits = codefix.generateAccessorFromProperty(context.file, context.startPosition, context.endPosition, context, actionName);
|
||||
const edits = codefix.generateAccessorFromProperty(context.file, context.program, context.startPosition, context.endPosition, context, actionName);
|
||||
if (!edits) return undefined;
|
||||
|
||||
const renameFilename = context.file.fileName;
|
||||
@ -19,7 +19,7 @@ namespace ts.refactor.generateGetAccessorAndSetAccessor {
|
||||
},
|
||||
getAvailableActions(context: RefactorContext): readonly ApplicableRefactorInfo[] {
|
||||
if (!context.endPosition) return emptyArray;
|
||||
const info = codefix.getAccessorConvertiblePropertyAtPosition(context.file, context.startPosition, context.endPosition, context.triggerReason === "invoked");
|
||||
const info = codefix.getAccessorConvertiblePropertyAtPosition(context.file, context.program, context.startPosition, context.endPosition, context.triggerReason === "invoked");
|
||||
if (!info) return emptyArray;
|
||||
|
||||
if (!info.error) {
|
||||
|
||||
@ -0,0 +1,24 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
////class A {
|
||||
//// /*a*/foo?: string;/*b*/
|
||||
////}
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Generate 'get' and 'set' accessors",
|
||||
actionName: "Generate 'get' and 'set' accessors",
|
||||
actionDescription: "Generate 'get' and 'set' accessors",
|
||||
newContent:
|
||||
`class A {
|
||||
private /*RENAME*/_foo?: string | undefined;
|
||||
public get foo(): string | undefined {
|
||||
return this._foo;
|
||||
}
|
||||
public set foo(value: string | undefined) {
|
||||
this._foo = value;
|
||||
}
|
||||
}`
|
||||
});
|
||||
@ -0,0 +1,24 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
////class A {
|
||||
//// /*a*/foo?: string | undefined;/*b*/
|
||||
////}
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Generate 'get' and 'set' accessors",
|
||||
actionName: "Generate 'get' and 'set' accessors",
|
||||
actionDescription: "Generate 'get' and 'set' accessors",
|
||||
newContent:
|
||||
`class A {
|
||||
private /*RENAME*/_foo?: string | undefined;
|
||||
public get foo(): string | undefined {
|
||||
return this._foo;
|
||||
}
|
||||
public set foo(value: string | undefined) {
|
||||
this._foo = value;
|
||||
}
|
||||
}`
|
||||
});
|
||||
@ -0,0 +1,26 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
////type Foo = undefined | null;
|
||||
////class A {
|
||||
//// /*a*/foo?: string | Foo;/*b*/
|
||||
////}
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Generate 'get' and 'set' accessors",
|
||||
actionName: "Generate 'get' and 'set' accessors",
|
||||
actionDescription: "Generate 'get' and 'set' accessors",
|
||||
newContent:
|
||||
`type Foo = undefined | null;
|
||||
class A {
|
||||
private /*RENAME*/_foo?: string | Foo;
|
||||
public get foo(): string | Foo {
|
||||
return this._foo;
|
||||
}
|
||||
public set foo(value: string | Foo) {
|
||||
this._foo = value;
|
||||
}
|
||||
}`
|
||||
});
|
||||
@ -0,0 +1,24 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @strict: true
|
||||
|
||||
////class A {
|
||||
//// /*a*/foo?: any;/*b*/
|
||||
////}
|
||||
|
||||
goTo.select("a", "b");
|
||||
edit.applyRefactor({
|
||||
refactorName: "Generate 'get' and 'set' accessors",
|
||||
actionName: "Generate 'get' and 'set' accessors",
|
||||
actionDescription: "Generate 'get' and 'set' accessors",
|
||||
newContent:
|
||||
`class A {
|
||||
private /*RENAME*/_foo?: any;
|
||||
public get foo(): any {
|
||||
return this._foo;
|
||||
}
|
||||
public set foo(value: any) {
|
||||
this._foo = value;
|
||||
}
|
||||
}`
|
||||
});
|
||||
Loading…
x
Reference in New Issue
Block a user