mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
fix(32297): add quick-fix action to delete parameter destructuring elements (#38764)
This commit is contained in:
@@ -5155,10 +5155,6 @@
|
||||
"category": "Message",
|
||||
"code": 90008
|
||||
},
|
||||
"Remove destructuring": {
|
||||
"category": "Message",
|
||||
"code": 90009
|
||||
},
|
||||
"Remove variable statement": {
|
||||
"category": "Message",
|
||||
"code": 90010
|
||||
@@ -5275,6 +5271,14 @@
|
||||
"category": "Message",
|
||||
"code": 90038
|
||||
},
|
||||
"Remove unused destructuring declaration": {
|
||||
"category": "Message",
|
||||
"code": 90039
|
||||
},
|
||||
"Remove unused declarations for: '{0}'": {
|
||||
"category": "Message",
|
||||
"code": 90041
|
||||
},
|
||||
"Declare a private field named '{0}'.": {
|
||||
"category": "Message",
|
||||
"code": 90053
|
||||
|
||||
@@ -34,18 +34,33 @@ namespace ts.codefix {
|
||||
const changes = textChanges.ChangeTracker.with(context, t => t.delete(sourceFile, importDecl));
|
||||
return [createDeleteFix(changes, [Diagnostics.Remove_import_from_0, showModuleSpecifier(importDecl)])];
|
||||
}
|
||||
const delDestructure = textChanges.ChangeTracker.with(context, t =>
|
||||
tryDeleteFullDestructure(token, t, sourceFile, checker, sourceFiles, /*isFixAll*/ false));
|
||||
if (delDestructure.length) {
|
||||
return [createDeleteFix(delDestructure, Diagnostics.Remove_destructuring)];
|
||||
|
||||
if (isObjectBindingPattern(token.parent)) {
|
||||
if (isParameter(token.parent.parent)) {
|
||||
const elements = token.parent.elements;
|
||||
const diagnostic: [DiagnosticMessage, string] = [
|
||||
elements.length > 1 ? Diagnostics.Remove_unused_declarations_for_Colon_0 : Diagnostics.Remove_unused_declaration_for_Colon_0,
|
||||
map(elements, e => e.getText(sourceFile)).join(", ")
|
||||
];
|
||||
return [
|
||||
createDeleteFix(textChanges.ChangeTracker.with(context, t =>
|
||||
deleteDestructuringElements(t, sourceFile, <ObjectBindingPattern>token.parent)), diagnostic)
|
||||
];
|
||||
}
|
||||
return [
|
||||
createDeleteFix(textChanges.ChangeTracker.with(context, t =>
|
||||
t.delete(sourceFile, token.parent.parent)), Diagnostics.Remove_unused_destructuring_declaration)
|
||||
];
|
||||
}
|
||||
const delVar = textChanges.ChangeTracker.with(context, t => tryDeleteFullVariableStatement(sourceFile, token, t));
|
||||
if (delVar.length) {
|
||||
return [createDeleteFix(delVar, Diagnostics.Remove_variable_statement)];
|
||||
|
||||
if (canDeleteEntireVariableStatement(sourceFile, token)) {
|
||||
return [
|
||||
createDeleteFix(textChanges.ChangeTracker.with(context, t =>
|
||||
deleteEntireVariableStatement(t, sourceFile, <VariableDeclarationList>token.parent)), Diagnostics.Remove_variable_statement)
|
||||
];
|
||||
}
|
||||
|
||||
const result: CodeFixAction[] = [];
|
||||
|
||||
if (token.kind === SyntaxKind.InferKeyword) {
|
||||
const changes = textChanges.ChangeTracker.with(context, t => changeInferToUnknown(t, sourceFile, token));
|
||||
const name = cast(token.parent, isInferTypeNode).typeParameter.name.text;
|
||||
@@ -79,7 +94,9 @@ namespace ts.codefix {
|
||||
tryPrefixDeclaration(changes, diag.code, sourceFile, token);
|
||||
break;
|
||||
case fixIdDelete: {
|
||||
if (token.kind === SyntaxKind.InferKeyword) break; // Can't delete
|
||||
if (token.kind === SyntaxKind.InferKeyword) {
|
||||
break; // Can't delete
|
||||
}
|
||||
const importDecl = tryGetFullImport(token);
|
||||
if (importDecl) {
|
||||
changes.delete(sourceFile, importDecl);
|
||||
@@ -90,8 +107,18 @@ namespace ts.codefix {
|
||||
else if (token.kind === SyntaxKind.LessThanToken) {
|
||||
deleteTypeParameters(changes, sourceFile, token);
|
||||
}
|
||||
else if (!tryDeleteFullDestructure(token, changes, sourceFile, checker, sourceFiles, /*isFixAll*/ true) &&
|
||||
!tryDeleteFullVariableStatement(sourceFile, token, changes)) {
|
||||
else if (isObjectBindingPattern(token.parent)) {
|
||||
if (isParameter(token.parent.parent)) {
|
||||
deleteDestructuringElements(changes, sourceFile, token.parent);
|
||||
}
|
||||
else {
|
||||
changes.delete(sourceFile, token.parent.parent);
|
||||
}
|
||||
}
|
||||
else if (canDeleteEntireVariableStatement(sourceFile, token)) {
|
||||
deleteEntireVariableStatement(changes, sourceFile, <VariableDeclarationList>token.parent);
|
||||
}
|
||||
else {
|
||||
tryDeleteDeclaration(sourceFile, token, changes, checker, sourceFiles, /*isFixAll*/ true);
|
||||
}
|
||||
break;
|
||||
@@ -125,25 +152,16 @@ namespace ts.codefix {
|
||||
return token.kind === SyntaxKind.ImportKeyword ? tryCast(token.parent, isImportDeclaration) : undefined;
|
||||
}
|
||||
|
||||
function tryDeleteFullDestructure(token: Node, changes: textChanges.ChangeTracker, sourceFile: SourceFile, checker: TypeChecker, sourceFiles: readonly SourceFile[], isFixAll: boolean): boolean {
|
||||
if (token.kind !== SyntaxKind.OpenBraceToken || !isObjectBindingPattern(token.parent)) return false;
|
||||
const decl = token.parent.parent;
|
||||
if (decl.kind === SyntaxKind.Parameter) {
|
||||
tryDeleteParameter(changes, sourceFile, decl, checker, sourceFiles, isFixAll);
|
||||
}
|
||||
else {
|
||||
changes.delete(sourceFile, decl);
|
||||
}
|
||||
return true;
|
||||
function canDeleteEntireVariableStatement(sourceFile: SourceFile, token: Node): boolean {
|
||||
return isVariableDeclarationList(token.parent) && first(token.parent.getChildren(sourceFile)) === token;
|
||||
}
|
||||
|
||||
function tryDeleteFullVariableStatement(sourceFile: SourceFile, token: Node, changes: textChanges.ChangeTracker): boolean {
|
||||
const declarationList = tryCast(token.parent, isVariableDeclarationList);
|
||||
if (declarationList && declarationList.getChildren(sourceFile)[0] === token) {
|
||||
changes.delete(sourceFile, declarationList.parent.kind === SyntaxKind.VariableStatement ? declarationList.parent : declarationList);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
function deleteEntireVariableStatement(changes: textChanges.ChangeTracker, sourceFile: SourceFile, node: VariableDeclarationList) {
|
||||
changes.delete(sourceFile, node.parent.kind === SyntaxKind.VariableStatement ? node.parent : node);
|
||||
}
|
||||
|
||||
function deleteDestructuringElements(changes: textChanges.ChangeTracker, sourceFile: SourceFile, node: ObjectBindingPattern) {
|
||||
forEach(node.elements, n => changes.delete(sourceFile, n));
|
||||
}
|
||||
|
||||
function tryPrefixDeclaration(changes: textChanges.ChangeTracker, errorCode: number, sourceFile: SourceFile, token: Node): void {
|
||||
@@ -205,7 +223,7 @@ namespace ts.codefix {
|
||||
}
|
||||
}
|
||||
|
||||
function tryDeleteParameter(changes: textChanges.ChangeTracker, sourceFile: SourceFile, p: ParameterDeclaration, checker: TypeChecker, sourceFiles: readonly SourceFile[], isFixAll: boolean): void {
|
||||
function tryDeleteParameter(changes: textChanges.ChangeTracker, sourceFile: SourceFile, p: ParameterDeclaration, checker: TypeChecker, sourceFiles: readonly SourceFile[], isFixAll = false): void {
|
||||
if (mayDeleteParameter(p, checker, isFixAll)) {
|
||||
if (p.modifiers && p.modifiers.length > 0
|
||||
&& (!isIdentifier(p.name) || FindAllReferences.Core.isSymbolReferencedInFile(p.name, checker, sourceFile))) {
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
verify.codeFixAll({
|
||||
fixId: "unusedIdentifier_delete",
|
||||
fixAllDescription: "Delete all unused declarations",
|
||||
fixAllDescription: ts.Diagnostics.Delete_all_unused_declarations.message,
|
||||
newFileContent:
|
||||
`import { used1 } from "foo";
|
||||
import { used2 } from "foo";
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
verify.codeFixAll({
|
||||
fixId: "unusedIdentifier_delete",
|
||||
fixAllDescription: "Delete all unused declarations",
|
||||
fixAllDescription: ts.Diagnostics.Delete_all_unused_declarations.message,
|
||||
newFileContent:
|
||||
`/** Parameter doc comment */
|
||||
function f() {}
|
||||
|
||||
@@ -5,6 +5,6 @@
|
||||
|
||||
verify.codeFixAll({
|
||||
fixId: "unusedIdentifier_delete",
|
||||
fixAllDescription: "Delete all unused declarations",
|
||||
fixAllDescription: ts.Diagnostics.Delete_all_unused_declarations.message,
|
||||
newFileContent: "export {};\n",
|
||||
});
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
|
||||
verify.codeFixAll({
|
||||
fixId: "unusedIdentifier_delete",
|
||||
fixAllDescription: "Delete all unused declarations",
|
||||
fixAllDescription: ts.Diagnostics.Delete_all_unused_declarations.message,
|
||||
newFileContent:
|
||||
`
|
||||
export class C {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
////const { x, y } = o;
|
||||
|
||||
verify.codeFix({
|
||||
description: "Remove destructuring",
|
||||
description: ts.Diagnostics.Remove_unused_destructuring_declaration.message,
|
||||
newFileContent:
|
||||
`export {};
|
||||
`,
|
||||
|
||||
@@ -12,11 +12,11 @@
|
||||
|
||||
verify.codeFixAll({
|
||||
fixId: "unusedIdentifier_delete",
|
||||
fixAllDescription: "Delete all unused declarations",
|
||||
fixAllDescription: ts.Diagnostics.Delete_all_unused_declarations.message,
|
||||
newFileContent:
|
||||
`const { a } = o;
|
||||
a;
|
||||
export function f({ a }) {
|
||||
export function f({ a }, { }) {
|
||||
a;
|
||||
}`,
|
||||
});
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
////for (const { x } of o) {}
|
||||
|
||||
verify.codeFix({
|
||||
description: "Remove destructuring",
|
||||
description: ts.Diagnostics.Remove_unused_destructuring_declaration.message,
|
||||
newFileContent:
|
||||
`for (const {} of o) {}`,
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
////const { x: { a, b } } = o;
|
||||
|
||||
verify.codeFix({
|
||||
description: "Remove destructuring",
|
||||
description: ts.Diagnostics.Remove_unused_destructuring_declaration.message,
|
||||
newFileContent:
|
||||
`export {};
|
||||
const { } = o;`,
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
verify.codeFixAll({
|
||||
fixId: "unusedIdentifier_delete",
|
||||
fixAllDescription: "Delete all unused declarations",
|
||||
fixAllDescription: ts.Diagnostics.Delete_all_unused_declarations.message,
|
||||
newFileContent:
|
||||
`{
|
||||
const { x } = o;
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @noUnusedLocals: true
|
||||
// @noUnusedParameters: true
|
||||
|
||||
////export function f({ x, y }, a) {
|
||||
//// a;
|
||||
////}
|
||||
|
||||
verify.codeFix({
|
||||
description: [ts.Diagnostics.Remove_unused_declarations_for_Colon_0.message, "x, y"],
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`export function f({ }, a) {
|
||||
a;
|
||||
}`,
|
||||
});
|
||||
@@ -4,7 +4,7 @@
|
||||
// @noUnusedParameters: true
|
||||
|
||||
////function f(a, b, { x, y }) { b; }
|
||||
////f(0, 1, 2);
|
||||
////f(0, 1, { x: 1, y: 1 });
|
||||
////
|
||||
////class C {
|
||||
//// m(a, b, c) { b; }
|
||||
@@ -23,10 +23,10 @@
|
||||
|
||||
verify.codeFixAll({
|
||||
fixId: "unusedIdentifier_delete",
|
||||
fixAllDescription: "Delete all unused declarations",
|
||||
fixAllDescription: ts.Diagnostics.Delete_all_unused_declarations.message,
|
||||
newFileContent:
|
||||
`function f(b) { b; }
|
||||
f(1);
|
||||
`function f(b, { }) { b; }
|
||||
f(1, { x: 1, y: 1 });
|
||||
|
||||
class C {
|
||||
m(b) { b; }
|
||||
|
||||
Reference in New Issue
Block a user