mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-04-17 01:49:41 -05:00
fix(58360): Cheese being inserted on TypeScript Quick Fix (#58365)
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
26
tests/cases/fourslash/codeFixAddMissingParam17.ts
Normal file
26
tests/cases/fourslash/codeFixAddMissingParam17.ts
Normal 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) {}`,
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user