Skip to content
This repository was archived by the owner on Mar 25, 2021. It is now read-only.

Commit be293b0

Browse files
bowenniJosh Goldberg
authored andcommitted
Add a fixer for "unnecessary-constructor" rule. (#4694)
* Add a fixer for "unnecessary-constructor" rule. * Handle decorated parameters.
1 parent 1cb1a0a commit be293b0

File tree

3 files changed

+88
-1
lines changed

3 files changed

+88
-1
lines changed

src/rules/unnecessaryConstructorRule.ts

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import { isConstructorDeclaration, isParameterProperty } from "tsutils";
1919
import * as ts from "typescript";
2020

2121
import * as Lint from "../index";
22+
import { Replacement } from "../language/rule/rule";
2223

2324
export class Rule extends Lint.Rules.AbstractRule {
2425
public static metadata: Lint.IRuleMetadata = {
@@ -55,15 +56,28 @@ const isAccessRestrictingConstructor = (node: ts.ConstructorDeclaration): boolea
5556
// If this has any modifier that isn't public, it's doing something
5657
node.modifiers.some(modifier => modifier.kind !== ts.SyntaxKind.PublicKeyword);
5758

59+
const containsDecorator = (node: ts.ConstructorDeclaration): boolean =>
60+
node.parameters.some(p => p.decorators !== undefined);
61+
5862
function walk(context: Lint.WalkContext) {
5963
const callback = (node: ts.Node): void => {
6064
if (
6165
isConstructorDeclaration(node) &&
6266
isEmptyConstructor(node) &&
6367
!containsConstructorParameter(node) &&
68+
!containsDecorator(node) &&
6469
!isAccessRestrictingConstructor(node)
6570
) {
66-
context.addFailureAtNode(node, Rule.FAILURE_STRING);
71+
const replacements = [];
72+
// Since only one constructor implementation is allowed and the one found above is empty, all other overloads can be safely removed.
73+
for (const maybeConstructor of node.parent.members) {
74+
if (isConstructorDeclaration(maybeConstructor)) {
75+
replacements.push(
76+
Replacement.deleteFromTo(maybeConstructor.pos, maybeConstructor.end),
77+
);
78+
}
79+
}
80+
context.addFailureAtNode(node, Rule.FAILURE_STRING, replacements);
6781
} else {
6882
ts.forEachChild(node, callback);
6983
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
export class ExportedClass {
2+
}
3+
4+
class PublicConstructor {
5+
}
6+
7+
class ProtectedConstructor {
8+
protected constructor() { }
9+
}
10+
11+
class PrivateConstructor {
12+
private constructor() { }
13+
}
14+
15+
class SameLine { }
16+
17+
class WithPrecedingMember {
18+
public member: string;
19+
}
20+
21+
class WithFollowingMethod {
22+
public method() {}
23+
}
24+
25+
const classExpression = class {
26+
}
27+
28+
class ContainsContents {
29+
constructor() {
30+
console.log("Hello!");
31+
}
32+
}
33+
34+
class CallsSuper extends PublicConstructor {
35+
constructor() {
36+
super();
37+
}
38+
}
39+
40+
class ContainsParameter {
41+
}
42+
43+
class PrivateContainsParameter {
44+
private constructor(x: number) { }
45+
}
46+
47+
class ProtectedContainsParameter {
48+
protected constructor(x: number) { }
49+
}
50+
51+
class ContainsParameterDeclaration {
52+
constructor(public x: number) { }
53+
}
54+
55+
class ContainsParameterAndParameterDeclaration {
56+
constructor(x: number, public y: number) { }
57+
}
58+
59+
class ConstructorOverload {
60+
}
61+
62+
interface IConstructorSignature {
63+
new(): {};
64+
}
65+
66+
class DecoratedParameters {
67+
constructor(@Optional x: number) {}
68+
}
69+

test/rules/unnecessary-constructor/test.ts.lint

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,4 +79,8 @@ interface IConstructorSignature {
7979
new(): {};
8080
}
8181

82+
class DecoratedParameters {
83+
constructor(@Optional x: number) {}
84+
}
85+
8286
[0]: Remove unnecessary empty constructor.

0 commit comments

Comments
 (0)