fix(58360): Cheese being inserted on TypeScript Quick Fix (#58365)

This commit is contained in:
Oleksandr T
2024-04-30 01:29:46 +03:00
committed by GitHub
parent c763c277eb
commit dc316afea4
2 changed files with 64 additions and 9 deletions

View File

@@ -12,8 +12,10 @@ import {
FunctionDeclaration,
FunctionExpression,
FunctionLikeDeclaration,
getEmitScriptTarget,
getNameOfAccessExpression,
getNameOfDeclaration,
getSourceFileOfNode,
getTokenAtPosition,
isAccessExpression,
isCallExpression,
@@ -22,6 +24,7 @@ import {
isPropertyDeclaration,
isSourceFileFromLibrary,
isVariableDeclaration,
LanguageServiceHost,
last,
lastOrUndefined,
length,
@@ -32,6 +35,7 @@ import {
ParameterDeclaration,
Program,
QuestionToken,
ScriptTarget,
some,
SourceFile,
SyntaxKind,
@@ -39,11 +43,16 @@ import {
Type,
TypeChecker,
TypeNode,
UserPreferences,
} from "../_namespaces/ts";
import {
codeFixAll,
createCodeFixAction,
createImportAdder,
ImportAdder,
importSymbols,
registerCodeFix,
tryGetAutoImportableReferenceFromTypeNode,
} from "../_namespaces/ts.codefix";
const addMissingParamFixId = "addMissingParam";
@@ -65,7 +74,7 @@ registerCodeFix({
actions,
createCodeFixAction(
addMissingParamFixId,
textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, declarations, newParameters)),
textChanges.ChangeTracker.with(context, t => doChange(t, context.program, context.preferences, context.host, declarations, newParameters)),
[length(newParameters) > 1 ? Diagnostics.Add_missing_parameters_to_0 : Diagnostics.Add_missing_parameter_to_0, name],
addMissingParamFixId,
Diagnostics.Add_all_missing_parameters,
@@ -78,7 +87,7 @@ registerCodeFix({
actions,
createCodeFixAction(
addOptionalParamFixId,
textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, declarations, newOptionalParameters)),
textChanges.ChangeTracker.with(context, t => doChange(t, context.program, context.preferences, context.host, declarations, newOptionalParameters)),
[length(newOptionalParameters) > 1 ? Diagnostics.Add_optional_parameters_to_0 : Diagnostics.Add_optional_parameter_to_0, name],
addOptionalParamFixId,
Diagnostics.Add_all_optional_parameters,
@@ -94,10 +103,10 @@ registerCodeFix({
if (info) {
const { declarations, newParameters, newOptionalParameters } = info;
if (context.fixId === addMissingParamFixId) {
doChange(changes, context.sourceFile, declarations, newParameters);
doChange(changes, context.program, context.preferences, context.host, declarations, newParameters);
}
if (context.fixId === addOptionalParamFixId) {
doChange(changes, context.sourceFile, declarations, newOptionalParameters);
doChange(changes, context.program, context.preferences, context.host, declarations, newOptionalParameters);
}
}
}),
@@ -218,17 +227,22 @@ function typeToTypeNode(checker: TypeChecker, type: Type, enclosingDeclaration:
function doChange(
changes: textChanges.ChangeTracker,
sourceFile: SourceFile,
program: Program,
preferences: UserPreferences,
host: LanguageServiceHost,
declarations: ConvertibleSignatureDeclaration[],
newParameters: ParameterInfo[],
) {
const scriptTarget = getEmitScriptTarget(program.getCompilerOptions());
forEach(declarations, declaration => {
const sourceFile = getSourceFileOfNode(declaration);
const importAdder = createImportAdder(sourceFile, program, preferences, host);
if (length(declaration.parameters)) {
changes.replaceNodeRangeWithNodes(
sourceFile,
first(declaration.parameters),
last(declaration.parameters),
updateParameters(declaration, newParameters),
updateParameters(importAdder, scriptTarget, declaration, newParameters),
{
joiner: ", ",
indentation: 0,
@@ -238,7 +252,7 @@ function doChange(
);
}
else {
forEach(updateParameters(declaration, newParameters), (parameter, index) => {
forEach(updateParameters(importAdder, scriptTarget, declaration, newParameters), (parameter, index) => {
if (length(declaration.parameters) === 0 && index === 0) {
changes.insertNodeAt(sourceFile, declaration.parameters.end, parameter);
}
@@ -247,6 +261,7 @@ function doChange(
}
});
}
importAdder.writeFixes(changes);
});
}
@@ -262,7 +277,12 @@ function isConvertibleSignatureDeclaration(node: Node): node is ConvertibleSigna
}
}
function updateParameters(node: ConvertibleSignatureDeclaration, newParameters: readonly ParameterInfo[]) {
function updateParameters(
importAdder: ImportAdder,
scriptTarget: ScriptTarget,
node: ConvertibleSignatureDeclaration,
newParameters: readonly ParameterInfo[],
) {
const parameters = map(node.parameters, p =>
factory.createParameterDeclaration(
p.modifiers,
@@ -283,7 +303,7 @@ function updateParameters(node: ConvertibleSignatureDeclaration, newParameters:
declaration.dotDotDotToken,
declaration.name,
prev && prev.questionToken ? factory.createToken(SyntaxKind.QuestionToken) : declaration.questionToken,
declaration.type,
getParameterType(importAdder, declaration.type, scriptTarget),
declaration.initializer,
),
);
@@ -325,3 +345,12 @@ function createParameter(name: string, type: TypeNode, questionToken: QuestionTo
function isOptionalPos(declarations: ConvertibleSignatureDeclaration[], pos: number) {
return length(declarations) && some(declarations, d => pos < length(d.parameters) && !!d.parameters[pos] && d.parameters[pos].questionToken === undefined);
}
function getParameterType(importAdder: ImportAdder, typeNode: TypeNode | undefined, scriptTarget: ScriptTarget) {
const importableReference = tryGetAutoImportableReferenceFromTypeNode(typeNode, scriptTarget);
if (importableReference) {
importSymbols(importAdder, importableReference.symbols);
return importableReference.typeNode;
}
return typeNode;
}

View File

@@ -0,0 +1,26 @@
/// <reference path="fourslash.ts" />
// @filename: /a.ts
//// export class A {}
// @filename: /b.ts
//// export function f(a: any) {}
// @filename: /c.ts
//// import { A } from './a';
//// import { f } from './b';
////
//// f({}, new A());
goTo.file("/c.ts");
verify.codeFix({
description: [ts.Diagnostics.Add_missing_parameter_to_0.message, "f"],
index: 0,
newFileContent: {
"/b.ts":
`import { A } from "./a";
export function f(a: any, p0: A) {}`,
},
});