Skip to content

Commit fe26370

Browse files
Merge pull request #27019 from iliashkolyar/codefix_add_missing_new_operator
Codefix: add quick fix for missing 'new' operator
2 parents 24759b8 + 047b76f commit fe26370

10 files changed

+168
-1
lines changed

src/compiler/diagnosticMessages.json

+8-1
Original file line numberDiff line numberDiff line change
@@ -4748,7 +4748,6 @@
47484748
"category": "Message",
47494749
"code": 95062
47504750
},
4751-
47524751
"Add missing enum member '{0}'": {
47534752
"category": "Message",
47544753
"code": 95063
@@ -4780,5 +4779,13 @@
47804779
"Add 'unknown' to all conversions of non-overlapping types": {
47814780
"category": "Message",
47824781
"code": 95070
4782+
},
4783+
"Add missing 'new' operator to call": {
4784+
"category": "Message",
4785+
"code": 95071
4786+
},
4787+
"Add missing 'new' operator to all calls": {
4788+
"category": "Message",
4789+
"code": 95072
47834790
}
47844791
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* @internal */
2+
namespace ts.codefix {
3+
const fixId = "addMissingNewOperator";
4+
const errorCodes = [Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new.code];
5+
registerCodeFix({
6+
errorCodes,
7+
getCodeActions(context) {
8+
const { sourceFile, span } = context;
9+
const changes = textChanges.ChangeTracker.with(context, t => addMissingNewOperator(t, sourceFile, span));
10+
return [createCodeFixAction(fixId, changes, Diagnostics.Add_missing_new_operator_to_call, fixId, Diagnostics.Add_missing_new_operator_to_all_calls)];
11+
},
12+
fixIds: [fixId],
13+
getAllCodeActions: context => codeFixAll(context, errorCodes, (changes, diag) =>
14+
addMissingNewOperator(changes, context.sourceFile, diag)),
15+
});
16+
17+
function addMissingNewOperator(changes: textChanges.ChangeTracker, sourceFile: SourceFile, span: TextSpan): void {
18+
const call = cast(findAncestorMatchingSpan(sourceFile, span), isCallExpression);
19+
const newExpression = createNew(call.expression, call.typeArguments, call.arguments);
20+
21+
changes.replaceNode(sourceFile, call, newExpression);
22+
}
23+
24+
function findAncestorMatchingSpan(sourceFile: SourceFile, span: TextSpan): Node {
25+
let token = getTokenAtPosition(sourceFile, span.start);
26+
const end = textSpanEnd(span);
27+
while (token.end < end) {
28+
token = token.parent;
29+
}
30+
return token;
31+
}
32+
}

src/services/tsconfig.json

+1
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"codefixes/importFixes.ts",
5656
"codefixes/fixSpelling.ts",
5757
"codefixes/fixAddMissingMember.ts",
58+
"codefixes/fixAddMissingNewOperator.ts",
5859
"codefixes/fixCannotFindModule.ts",
5960
"codefixes/fixClassDoesntImplementInheritedAbstractMember.ts",
6061
"codefixes/fixClassSuperMustPrecedeThisAccess.ts",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////class C {
4+
////}
5+
////var c = C();
6+
7+
verify.codeFix({
8+
description: "Add missing 'new' operator to call",
9+
index: 0,
10+
newFileContent:
11+
`class C {
12+
}
13+
var c = new C();`
14+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////class C {
4+
////}
5+
////let x = (() => C)()();
6+
7+
verify.codeFix({
8+
description: "Add missing 'new' operator to call",
9+
index: 0,
10+
newFileContent:
11+
`class C {
12+
}
13+
let x = new ((() => C)())();`
14+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////class C {
4+
////}
5+
////let x = [C];
6+
////let a = x[0]();
7+
8+
verify.codeFix({
9+
description: "Add missing 'new' operator to call",
10+
index: 0,
11+
newFileContent:
12+
`class C {
13+
}
14+
let x = [C];
15+
let a = new x[0]();`
16+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////class C {
4+
////}
5+
////class D {
6+
////}
7+
////let x = (true ? C : D)();
8+
9+
verify.codeFix({
10+
description: "Add missing 'new' operator to call",
11+
index: 0,
12+
newFileContent:
13+
`class C {
14+
}
15+
class D {
16+
}
17+
let x = new (true ? C : D)();`
18+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////class C {
4+
////}
5+
////
6+
////function foo() {
7+
//// return C;
8+
////}
9+
////
10+
////foo()!();
11+
12+
13+
verify.codeFix({
14+
description: "Add missing 'new' operator to call",
15+
index: 0,
16+
newFileContent:
17+
`class C {
18+
}
19+
20+
function foo() {
21+
return C;
22+
}
23+
24+
new (foo()!)();`
25+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////class C {
4+
//// constructor(num?: number) {}
5+
////}
6+
////var a = C();
7+
////var b = C(3);
8+
9+
verify.codeFixAll({
10+
fixId: "addMissingNewOperator",
11+
fixAllDescription: "Add missing 'new' operator to all calls",
12+
newFileContent:
13+
`class C {
14+
constructor(num?: number) {}
15+
}
16+
var a = new C();
17+
var b = new C(3);`
18+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
/// <reference path='fourslash.ts' />
2+
3+
////class C<T = number> {
4+
//// x?: T;
5+
//// constructor(x: T) { this.x = x; }
6+
////}
7+
////let a = C(1, 2, 3);
8+
////let b = C<string>("hello");
9+
////let c = C<boolean>();
10+
11+
verify.codeFixAll({
12+
fixId: "addMissingNewOperator",
13+
fixAllDescription: "Add missing 'new' operator to all calls",
14+
newFileContent:
15+
`class C<T = number> {
16+
x?: T;
17+
constructor(x: T) { this.x = x; }
18+
}
19+
let a = new C(1, 2, 3);
20+
let b = new C<string>("hello");
21+
let c = new C<boolean>();`
22+
});

0 commit comments

Comments
 (0)