feat(33792): add new quick fix service to handle missing call in condition (#37152)

This commit is contained in:
Alexander T 2020-03-13 22:38:44 +02:00 committed by GitHub
parent 47b60ece0b
commit fc30095e8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 376 additions and 0 deletions

View File

@ -5377,6 +5377,14 @@
"category": "Message",
"code": 95066
},
"Add missing call parentheses": {
"category": "Message",
"code": 95067
},
"Add all missing call parentheses": {
"category": "Message",
"code": 95068
},
"Add 'unknown' conversion for non-overlapping types": {
"category": "Message",
"code": 95069

View File

@ -0,0 +1,45 @@
/* @internal */
namespace ts.codefix {
const fixId = "fixMissingCallParentheses";
const errorCodes = [
Diagnostics.This_condition_will_always_return_true_since_the_function_is_always_defined_Did_you_mean_to_call_it_instead.code,
];
registerCodeFix({
errorCodes,
fixIds: [fixId],
getCodeActions(context) {
const { sourceFile, span } = context;
const callName = getCallName(sourceFile, span.start);
if (!callName) return;
const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, callName));
return [createCodeFixAction(fixId, changes, Diagnostics.Add_missing_call_parentheses, fixId, Diagnostics.Add_all_missing_call_parentheses)];
},
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => {
const callName = getCallName(diag.file, diag.start);
if (callName) doChange(changes, diag.file, callName);
})
});
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, name: Identifier | PrivateIdentifier): void {
changes.replaceNodeWithText(sourceFile, name, `${ name.text }()`);
}
function getCallName(sourceFile: SourceFile, start: number): Identifier | PrivateIdentifier | undefined {
const token = getTokenAtPosition(sourceFile, start);
if (isPropertyAccessExpression(token.parent)) {
let current: PropertyAccessExpression = token.parent;
while (isPropertyAccessExpression(current.parent)) {
current = current.parent;
}
return current.name;
}
if (isIdentifier(token)) {
return token;
}
return undefined;
}
}

View File

@ -80,6 +80,7 @@
"codefixes/fixUnreachableCode.ts",
"codefixes/fixUnusedLabel.ts",
"codefixes/fixJSDocTypes.ts",
"codefixes/fixMissingCallParentheses.ts",
"codefixes/fixAwaitInSyncFunction.ts",
"codefixes/disableJsDiagnostics.ts",
"codefixes/helpers.ts",

View File

@ -0,0 +1,19 @@
/// <reference path='fourslash.ts'/>
// @strictNullChecks: true
////function foo(fn: () => boolean) {
//// fn/**/ ? console.log('test') : undefined;
////}
verify.codeFixAvailable([
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
]);
verify.codeFix({
description: ts.Diagnostics.Add_missing_call_parentheses.message,
index: 0,
newFileContent:
`function foo(fn: () => boolean) {
fn() ? console.log('test') : undefined;
}`,
});

View File

@ -0,0 +1,29 @@
/// <reference path='fourslash.ts'/>
// @strictNullChecks: true
////class Foo {
//// #test = () => true;
//// run() {
//// if (this.#test/**/) {
//// console.log('test')
//// }
//// }
////}
verify.codeFixAvailable([
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
]);
verify.codeFix({
description: ts.Diagnostics.Add_missing_call_parentheses.message,
index: 0,
newFileContent:
`class Foo {
#test = () => true;
run() {
if (this.#test()) {
console.log('test')
}
}
}`,
});

View File

@ -0,0 +1,55 @@
/// <reference path='fourslash.ts'/>
// @strictNullChecks: true
////class Foo {
//// #test = () => true;
//// run() {
//// if (this.#test) {
//// console.log('test')
//// }
//// }
////}
////
////function foo() {
//// function test() { return Math.random() > 0.5; }
//// test ? console.log('test') : undefined;
////}
////
////function foo() {
//// const x = {
//// foo: {
//// bar() { return true; }
//// }
//// }
//// x.foo.bar ? console.log('test') : undefined;
//// if (x.foo.bar) {}
////}
verify.codeFixAll({
fixAllDescription: ts.Diagnostics.Add_all_missing_call_parentheses.message,
fixId: "fixMissingCallParentheses",
newFileContent:
`class Foo {
#test = () => true;
run() {
if (this.#test()) {
console.log('test')
}
}
}
function foo() {
function test() { return Math.random() > 0.5; }
test() ? console.log('test') : undefined;
}
function foo() {
const x = {
foo: {
bar() { return true; }
}
}
x.foo.bar() ? console.log('test') : undefined;
if (x.foo.bar()) {}
}`,
});

View File

@ -0,0 +1,21 @@
/// <reference path='fourslash.ts'/>
// @strictNullChecks: true
////function foo() {
//// function test() { return Math.random() > 0.5; }
//// test/**/ ? console.log('test') : undefined;
////}
verify.codeFixAvailable([
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
]);
verify.codeFix({
description: ts.Diagnostics.Add_missing_call_parentheses.message,
index: 0,
newFileContent:
`function foo() {
function test() { return Math.random() > 0.5; }
test() ? console.log('test') : undefined;
}`,
});

View File

@ -0,0 +1,29 @@
/// <reference path='fourslash.ts'/>
// @strictNullChecks: true
////function foo() {
//// const x = {
//// foo: {
//// bar() { return true; }
//// }
//// }
//// x.foo.bar/**/ ? console.log('test') : undefined;
////}
verify.codeFixAvailable([
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
]);
verify.codeFix({
description: ts.Diagnostics.Add_missing_call_parentheses.message,
index: 0,
newFileContent:
`function foo() {
const x = {
foo: {
bar() { return true; }
}
}
x.foo.bar() ? console.log('test') : undefined;
}`,
});

View File

@ -0,0 +1,30 @@
/// <reference path='fourslash.ts'/>
// @strictNullChecks: true
////class Foo {
//// test() {
//// return true;
//// }
//// run() {
//// this.test/**/ ? console.log('test') : undefined;
//// }
////}
verify.codeFixAvailable([
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
]);
verify.codeFix({
description: ts.Diagnostics.Add_missing_call_parentheses.message,
index: 0,
newFileContent:
`class Foo {
test() {
return true;
}
run() {
this.test() ? console.log('test') : undefined;
}
}`,
});

View File

@ -0,0 +1,25 @@
/// <reference path='fourslash.ts'/>
// @strictNullChecks: true
////class Foo {
//// #test = () => true;
//// run() {
//// this.#test/**/ ? console.log('test') : undefined;
//// }
////}
verify.codeFixAvailable([
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
]);
verify.codeFix({
description: ts.Diagnostics.Add_missing_call_parentheses.message,
index: 0,
newFileContent:
`class Foo {
#test = () => true;
run() {
this.#test() ? console.log('test') : undefined;
}
}`,
});

View File

@ -0,0 +1,23 @@
/// <reference path='fourslash.ts'/>
// @strictNullChecks: true
////function foo(fn: () => boolean) {
//// if (fn/**/) {
//// console.log('test');
//// }
////}
verify.codeFixAvailable([
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
]);
verify.codeFix({
description: ts.Diagnostics.Add_missing_call_parentheses.message,
index: 0,
newFileContent:
`function foo(fn: () => boolean) {
if (fn()) {
console.log('test');
}
}`,
});

View File

@ -0,0 +1,25 @@
/// <reference path='fourslash.ts'/>
// @strictNullChecks: true
////function foo() {
//// function test() { return Math.random() > 0.5; }
//// if (test/**/) {
//// console.log('test')
//// }
////}
verify.codeFixAvailable([
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
]);
verify.codeFix({
description: ts.Diagnostics.Add_missing_call_parentheses.message,
index: 0,
newFileContent:
`function foo() {
function test() { return Math.random() > 0.5; }
if (test()) {
console.log('test')
}
}`,
});

View File

@ -0,0 +1,33 @@
/// <reference path='fourslash.ts'/>
// @strictNullChecks: true
////function foo() {
//// const x = {
//// foo: {
//// bar() { return true; }
//// }
//// }
//// if (x.foo.bar/**/) {
//// console.log('test')
//// }
////}
verify.codeFixAvailable([
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
]);
verify.codeFix({
description: ts.Diagnostics.Add_missing_call_parentheses.message,
index: 0,
newFileContent:
`function foo() {
const x = {
foo: {
bar() { return true; }
}
}
if (x.foo.bar()) {
console.log('test')
}
}`,
});

View File

@ -0,0 +1,33 @@
/// <reference path='fourslash.ts'/>
// @strictNullChecks: true
////function foo() {
//// const x = {
//// foo: {
//// bar() { return true; }
//// }
//// }
//// if (x.foo.bar/**/) {
//// console.log('test')
//// }
////}
verify.codeFixAvailable([
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
]);
verify.codeFix({
description: ts.Diagnostics.Add_missing_call_parentheses.message,
index: 0,
newFileContent:
`function foo() {
const x = {
foo: {
bar() { return true; }
}
}
if (x.foo.bar()) {
console.log('test')
}
}`,
});