Skip to content

Commit fc30095

Browse files
authored
feat(33792): add new quick fix service to handle missing call in condition (#37152)
1 parent 47b60ec commit fc30095

14 files changed

+376
-0
lines changed

src/compiler/diagnosticMessages.json

+8
Original file line numberDiff line numberDiff line change
@@ -5377,6 +5377,14 @@
53775377
"category": "Message",
53785378
"code": 95066
53795379
},
5380+
"Add missing call parentheses": {
5381+
"category": "Message",
5382+
"code": 95067
5383+
},
5384+
"Add all missing call parentheses": {
5385+
"category": "Message",
5386+
"code": 95068
5387+
},
53805388
"Add 'unknown' conversion for non-overlapping types": {
53815389
"category": "Message",
53825390
"code": 95069
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/* @internal */
2+
namespace ts.codefix {
3+
const fixId = "fixMissingCallParentheses";
4+
const errorCodes = [
5+
Diagnostics.This_condition_will_always_return_true_since_the_function_is_always_defined_Did_you_mean_to_call_it_instead.code,
6+
];
7+
8+
registerCodeFix({
9+
errorCodes,
10+
fixIds: [fixId],
11+
getCodeActions(context) {
12+
const { sourceFile, span } = context;
13+
const callName = getCallName(sourceFile, span.start);
14+
if (!callName) return;
15+
16+
const changes = textChanges.ChangeTracker.with(context, t => doChange(t, context.sourceFile, callName));
17+
return [createCodeFixAction(fixId, changes, Diagnostics.Add_missing_call_parentheses, fixId, Diagnostics.Add_all_missing_call_parentheses)];
18+
},
19+
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) => {
20+
const callName = getCallName(diag.file, diag.start);
21+
if (callName) doChange(changes, diag.file, callName);
22+
})
23+
});
24+
25+
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, name: Identifier | PrivateIdentifier): void {
26+
changes.replaceNodeWithText(sourceFile, name, `${ name.text }()`);
27+
}
28+
29+
function getCallName(sourceFile: SourceFile, start: number): Identifier | PrivateIdentifier | undefined {
30+
const token = getTokenAtPosition(sourceFile, start);
31+
if (isPropertyAccessExpression(token.parent)) {
32+
let current: PropertyAccessExpression = token.parent;
33+
while (isPropertyAccessExpression(current.parent)) {
34+
current = current.parent;
35+
}
36+
return current.name;
37+
}
38+
39+
if (isIdentifier(token)) {
40+
return token;
41+
}
42+
43+
return undefined;
44+
}
45+
}

src/services/tsconfig.json

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@
8080
"codefixes/fixUnreachableCode.ts",
8181
"codefixes/fixUnusedLabel.ts",
8282
"codefixes/fixJSDocTypes.ts",
83+
"codefixes/fixMissingCallParentheses.ts",
8384
"codefixes/fixAwaitInSyncFunction.ts",
8485
"codefixes/disableJsDiagnostics.ts",
8586
"codefixes/helpers.ts",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
// @strictNullChecks: true
4+
////function foo(fn: () => boolean) {
5+
//// fn/**/ ? console.log('test') : undefined;
6+
////}
7+
8+
verify.codeFixAvailable([
9+
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
10+
]);
11+
12+
verify.codeFix({
13+
description: ts.Diagnostics.Add_missing_call_parentheses.message,
14+
index: 0,
15+
newFileContent:
16+
`function foo(fn: () => boolean) {
17+
fn() ? console.log('test') : undefined;
18+
}`,
19+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
// @strictNullChecks: true
4+
////class Foo {
5+
//// #test = () => true;
6+
//// run() {
7+
//// if (this.#test/**/) {
8+
//// console.log('test')
9+
//// }
10+
//// }
11+
////}
12+
13+
verify.codeFixAvailable([
14+
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
15+
]);
16+
17+
verify.codeFix({
18+
description: ts.Diagnostics.Add_missing_call_parentheses.message,
19+
index: 0,
20+
newFileContent:
21+
`class Foo {
22+
#test = () => true;
23+
run() {
24+
if (this.#test()) {
25+
console.log('test')
26+
}
27+
}
28+
}`,
29+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
// @strictNullChecks: true
4+
////class Foo {
5+
//// #test = () => true;
6+
//// run() {
7+
//// if (this.#test) {
8+
//// console.log('test')
9+
//// }
10+
//// }
11+
////}
12+
////
13+
////function foo() {
14+
//// function test() { return Math.random() > 0.5; }
15+
//// test ? console.log('test') : undefined;
16+
////}
17+
////
18+
////function foo() {
19+
//// const x = {
20+
//// foo: {
21+
//// bar() { return true; }
22+
//// }
23+
//// }
24+
//// x.foo.bar ? console.log('test') : undefined;
25+
//// if (x.foo.bar) {}
26+
////}
27+
28+
verify.codeFixAll({
29+
fixAllDescription: ts.Diagnostics.Add_all_missing_call_parentheses.message,
30+
fixId: "fixMissingCallParentheses",
31+
newFileContent:
32+
`class Foo {
33+
#test = () => true;
34+
run() {
35+
if (this.#test()) {
36+
console.log('test')
37+
}
38+
}
39+
}
40+
41+
function foo() {
42+
function test() { return Math.random() > 0.5; }
43+
test() ? console.log('test') : undefined;
44+
}
45+
46+
function foo() {
47+
const x = {
48+
foo: {
49+
bar() { return true; }
50+
}
51+
}
52+
x.foo.bar() ? console.log('test') : undefined;
53+
if (x.foo.bar()) {}
54+
}`,
55+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
// @strictNullChecks: true
4+
////function foo() {
5+
//// function test() { return Math.random() > 0.5; }
6+
//// test/**/ ? console.log('test') : undefined;
7+
////}
8+
9+
verify.codeFixAvailable([
10+
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
11+
]);
12+
13+
verify.codeFix({
14+
description: ts.Diagnostics.Add_missing_call_parentheses.message,
15+
index: 0,
16+
newFileContent:
17+
`function foo() {
18+
function test() { return Math.random() > 0.5; }
19+
test() ? console.log('test') : undefined;
20+
}`,
21+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
// @strictNullChecks: true
4+
////function foo() {
5+
//// const x = {
6+
//// foo: {
7+
//// bar() { return true; }
8+
//// }
9+
//// }
10+
//// x.foo.bar/**/ ? console.log('test') : undefined;
11+
////}
12+
13+
verify.codeFixAvailable([
14+
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
15+
]);
16+
17+
verify.codeFix({
18+
description: ts.Diagnostics.Add_missing_call_parentheses.message,
19+
index: 0,
20+
newFileContent:
21+
`function foo() {
22+
const x = {
23+
foo: {
24+
bar() { return true; }
25+
}
26+
}
27+
x.foo.bar() ? console.log('test') : undefined;
28+
}`,
29+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
// @strictNullChecks: true
4+
////class Foo {
5+
//// test() {
6+
//// return true;
7+
//// }
8+
//// run() {
9+
//// this.test/**/ ? console.log('test') : undefined;
10+
//// }
11+
////}
12+
13+
verify.codeFixAvailable([
14+
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
15+
]);
16+
17+
verify.codeFix({
18+
description: ts.Diagnostics.Add_missing_call_parentheses.message,
19+
index: 0,
20+
newFileContent:
21+
`class Foo {
22+
test() {
23+
return true;
24+
}
25+
run() {
26+
this.test() ? console.log('test') : undefined;
27+
}
28+
}`,
29+
});
30+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
// @strictNullChecks: true
4+
////class Foo {
5+
//// #test = () => true;
6+
//// run() {
7+
//// this.#test/**/ ? console.log('test') : undefined;
8+
//// }
9+
////}
10+
11+
verify.codeFixAvailable([
12+
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
13+
]);
14+
15+
verify.codeFix({
16+
description: ts.Diagnostics.Add_missing_call_parentheses.message,
17+
index: 0,
18+
newFileContent:
19+
`class Foo {
20+
#test = () => true;
21+
run() {
22+
this.#test() ? console.log('test') : undefined;
23+
}
24+
}`,
25+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
// @strictNullChecks: true
4+
////function foo(fn: () => boolean) {
5+
//// if (fn/**/) {
6+
//// console.log('test');
7+
//// }
8+
////}
9+
10+
verify.codeFixAvailable([
11+
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
12+
]);
13+
14+
verify.codeFix({
15+
description: ts.Diagnostics.Add_missing_call_parentheses.message,
16+
index: 0,
17+
newFileContent:
18+
`function foo(fn: () => boolean) {
19+
if (fn()) {
20+
console.log('test');
21+
}
22+
}`,
23+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
// @strictNullChecks: true
4+
////function foo() {
5+
//// function test() { return Math.random() > 0.5; }
6+
//// if (test/**/) {
7+
//// console.log('test')
8+
//// }
9+
////}
10+
11+
verify.codeFixAvailable([
12+
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
13+
]);
14+
15+
verify.codeFix({
16+
description: ts.Diagnostics.Add_missing_call_parentheses.message,
17+
index: 0,
18+
newFileContent:
19+
`function foo() {
20+
function test() { return Math.random() > 0.5; }
21+
if (test()) {
22+
console.log('test')
23+
}
24+
}`,
25+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/// <reference path='fourslash.ts'/>
2+
3+
// @strictNullChecks: true
4+
////function foo() {
5+
//// const x = {
6+
//// foo: {
7+
//// bar() { return true; }
8+
//// }
9+
//// }
10+
//// if (x.foo.bar/**/) {
11+
//// console.log('test')
12+
//// }
13+
////}
14+
15+
verify.codeFixAvailable([
16+
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
17+
]);
18+
19+
verify.codeFix({
20+
description: ts.Diagnostics.Add_missing_call_parentheses.message,
21+
index: 0,
22+
newFileContent:
23+
`function foo() {
24+
const x = {
25+
foo: {
26+
bar() { return true; }
27+
}
28+
}
29+
if (x.foo.bar()) {
30+
console.log('test')
31+
}
32+
}`,
33+
});

0 commit comments

Comments
 (0)