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

Commit

Permalink
Add a fixer for "unnecessary-constructor" rule. (#4694)
Browse files Browse the repository at this point in the history
* Add a fixer for "unnecessary-constructor" rule.

* Handle decorated parameters.
  • Loading branch information
bowenni authored and Josh Goldberg committed May 5, 2019
1 parent 1cb1a0a commit be293b0
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 1 deletion.
16 changes: 15 additions & 1 deletion src/rules/unnecessaryConstructorRule.ts
Expand Up @@ -19,6 +19,7 @@ import { isConstructorDeclaration, isParameterProperty } from "tsutils";
import * as ts from "typescript";

import * as Lint from "../index";
import { Replacement } from "../language/rule/rule";

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

const containsDecorator = (node: ts.ConstructorDeclaration): boolean =>
node.parameters.some(p => p.decorators !== undefined);

function walk(context: Lint.WalkContext) {
const callback = (node: ts.Node): void => {
if (
isConstructorDeclaration(node) &&
isEmptyConstructor(node) &&
!containsConstructorParameter(node) &&
!containsDecorator(node) &&
!isAccessRestrictingConstructor(node)
) {
context.addFailureAtNode(node, Rule.FAILURE_STRING);
const replacements = [];
// Since only one constructor implementation is allowed and the one found above is empty, all other overloads can be safely removed.
for (const maybeConstructor of node.parent.members) {
if (isConstructorDeclaration(maybeConstructor)) {
replacements.push(
Replacement.deleteFromTo(maybeConstructor.pos, maybeConstructor.end),
);
}
}
context.addFailureAtNode(node, Rule.FAILURE_STRING, replacements);
} else {
ts.forEachChild(node, callback);
}
Expand Down
69 changes: 69 additions & 0 deletions test/rules/unnecessary-constructor/test.ts.fix
@@ -0,0 +1,69 @@
export class ExportedClass {
}

class PublicConstructor {
}

class ProtectedConstructor {
protected constructor() { }
}

class PrivateConstructor {
private constructor() { }
}

class SameLine { }

class WithPrecedingMember {
public member: string;
}

class WithFollowingMethod {
public method() {}
}

const classExpression = class {
}

class ContainsContents {
constructor() {
console.log("Hello!");
}
}

class CallsSuper extends PublicConstructor {
constructor() {
super();
}
}

class ContainsParameter {
}

class PrivateContainsParameter {
private constructor(x: number) { }
}

class ProtectedContainsParameter {
protected constructor(x: number) { }
}

class ContainsParameterDeclaration {
constructor(public x: number) { }
}

class ContainsParameterAndParameterDeclaration {
constructor(x: number, public y: number) { }
}

class ConstructorOverload {
}

interface IConstructorSignature {
new(): {};
}

class DecoratedParameters {
constructor(@Optional x: number) {}
}

4 changes: 4 additions & 0 deletions test/rules/unnecessary-constructor/test.ts.lint
Expand Up @@ -79,4 +79,8 @@ interface IConstructorSignature {
new(): {};
}

class DecoratedParameters {
constructor(@Optional x: number) {}
}

[0]: Remove unnecessary empty constructor.

0 comments on commit be293b0

Please sign in to comment.