Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 3fb57a5

Browse files
armano2JamesHenry
authored andcommitted
feat(eslint-plugin): add eslint rule no-useless-constructor (typescript-eslint#167)
1 parent 00d020d commit 3fb57a5

File tree

4 files changed

+260
-1
lines changed

4 files changed

+260
-1
lines changed

packages/eslint-plugin/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,9 +121,10 @@ Install [`eslint-config-prettier`](https://github.com/prettier/eslint-config-pre
121121
| [`@typescript-eslint/no-this-alias`](./docs/rules/no-this-alias.md) | Disallow aliasing `this` (`no-this-assignment` from TSLint) | | |
122122
| [`@typescript-eslint/no-triple-slash-reference`](./docs/rules/no-triple-slash-reference.md) | Disallow `/// <reference path="" />` comments (`no-reference` from TSLint) | :heavy_check_mark: | |
123123
| [`@typescript-eslint/no-type-alias`](./docs/rules/no-type-alias.md) | Disallow the use of type aliases (`interface-over-type-literal` from TSLint) | | |
124-
| [`@typescript-eslint/no-unnecessary-type-assertion`](./docs/rules/no-unnecessary-type-assertion.md) | Warns if a type assertion does not change the type of an expression (`no-unnecessary-type-assertion` from TSLint) | | :wrench: |
124+
| [`@typescript-eslint/no-unnecessary-type-assertion`](./docs/rules/no-unnecessary-type-assertion.md) | Warns if a type assertion does not change the type of an expression (`no-unnecessary-type-assertion` from TSLint) | | :wrench: |
125125
| [`@typescript-eslint/no-unused-vars`](./docs/rules/no-unused-vars.md) | Disallow unused variables (`no-unused-variable` from TSLint) | :heavy_check_mark: | |
126126
| [`@typescript-eslint/no-use-before-define`](./docs/rules/no-use-before-define.md) | Disallow the use of variables before they are defined | :heavy_check_mark: | |
127+
| [`@typescript-eslint/no-useless-constructor`](./docs/rules/no-useless-constructor.md) | Disallow unnecessary constructors | | |
127128
| [`@typescript-eslint/no-var-requires`](./docs/rules/no-var-requires.md) | Disallows the use of require statements except in import statements (`no-var-requires` from TSLint) | :heavy_check_mark: | |
128129
| [`@typescript-eslint/prefer-interface`](./docs/rules/prefer-interface.md) | Prefer an interface declaration over a type literal (type T = { ... }) (`interface-over-type-literal` from TSLint) | :heavy_check_mark: | :wrench: |
129130
| [`@typescript-eslint/prefer-namespace-keyword`](./docs/rules/prefer-namespace-keyword.md) | Require the use of the `namespace` keyword instead of the `module` keyword to declare custom TypeScript modules. (`no-internal-module` from TSLint) | :heavy_check_mark: | :wrench: |
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Disallow unnecessary constructors (no-useless-constructor)
2+
3+
ES2015 provides a default class constructor if one is not specified. As such, it is unnecessary to provide an empty constructor or one that simply delegates into its parent class, as in the following examples:
4+
5+
```js
6+
class A {
7+
constructor() {}
8+
}
9+
10+
class A extends B {
11+
constructor(value) {
12+
super(value);
13+
}
14+
}
15+
```
16+
17+
## Rule Details
18+
19+
This rule flags class constructors that can be safely removed without changing how the class works.
20+
21+
## Examples
22+
23+
Examples of **incorrect** code for this rule:
24+
25+
```js
26+
/*eslint no-useless-constructor: "error"*/
27+
28+
class A {
29+
constructor() {}
30+
}
31+
32+
class A extends B {
33+
constructor(...args) {
34+
super(...args);
35+
}
36+
}
37+
```
38+
39+
Examples of **correct** code for this rule:
40+
41+
```js
42+
/*eslint no-useless-constructor: "error"*/
43+
44+
class A {}
45+
46+
class A {
47+
constructor() {
48+
doSomething();
49+
}
50+
}
51+
52+
class A extends B {
53+
constructor() {
54+
super('foo');
55+
}
56+
}
57+
58+
class A extends B {
59+
constructor() {
60+
super();
61+
doSomething();
62+
}
63+
}
64+
65+
class A extends B {
66+
constructor(protected name: string) {}
67+
}
68+
69+
class A extends B {
70+
protected constructor() {}
71+
}
72+
```
73+
74+
## When Not To Use It
75+
76+
If you don't want to be notified about unnecessary constructors, you can safely disable this rule.
77+
78+
<sup>Taken with ❤️ [from ESLint core](https://github.com/eslint/eslint/blob/master/docs/rules/no-useless-constructor.md)</sup>
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/**
2+
* @fileoverview Disallow unnecessary constructors
3+
* @author Armano <https://github.com/armano2>
4+
*/
5+
'use strict';
6+
7+
const baseRule = require('eslint/lib/rules/no-useless-constructor');
8+
const util = require('../util');
9+
10+
//------------------------------------------------------------------------------
11+
// Rule Definition
12+
//------------------------------------------------------------------------------
13+
14+
/**
15+
* Check if method with accessibility is not useless
16+
* @param {MethodDefinition} node
17+
* @returns {boolean}
18+
*/
19+
function checkAccessibility(node) {
20+
switch (node.accessibility) {
21+
case 'protected':
22+
case 'private':
23+
return false;
24+
case 'public':
25+
if (
26+
node.parent.type === 'ClassBody' &&
27+
node.parent.parent &&
28+
node.parent.parent.superClass
29+
) {
30+
return false;
31+
}
32+
break;
33+
}
34+
return true;
35+
}
36+
37+
/**
38+
* Check if method is not unless due to typescript parameter properties
39+
* @param {MethodDefinition} node
40+
* @returns {boolean}
41+
*/
42+
function checkParams(node) {
43+
return (
44+
!node.value.params ||
45+
!node.value.params.some(param => param.type === 'TSParameterProperty')
46+
);
47+
}
48+
49+
module.exports = Object.assign({}, baseRule, {
50+
meta: {
51+
type: 'problem',
52+
docs: {
53+
description: 'Disallow unnecessary constructors',
54+
category: 'ECMAScript 6',
55+
url: util.metaDocsUrl('no-useless-constructor')
56+
},
57+
schema: baseRule.meta.schema,
58+
messages: baseRule.meta.messages
59+
},
60+
61+
create(context) {
62+
const rules = baseRule.create(context);
63+
64+
//----------------------------------------------------------------------
65+
// Public
66+
//----------------------------------------------------------------------
67+
return {
68+
MethodDefinition(node) {
69+
if (
70+
node.value &&
71+
node.value.type === 'FunctionExpression' &&
72+
checkAccessibility(node) &&
73+
checkParams(node)
74+
) {
75+
rules.MethodDefinition(node);
76+
}
77+
}
78+
};
79+
}
80+
});
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
'use strict';
2+
3+
//------------------------------------------------------------------------------
4+
// Requirements
5+
//------------------------------------------------------------------------------
6+
7+
const rule = require('../../../lib/rules/no-useless-constructor'),
8+
RuleTester = require('eslint').RuleTester;
9+
10+
const ruleTester = new RuleTester({
11+
parserOptions: {
12+
ecmaVersion: 6,
13+
sourceType: 'module'
14+
},
15+
parser: '@typescript-eslint/parser'
16+
});
17+
18+
const error = { message: 'Useless constructor.', type: 'MethodDefinition' };
19+
20+
ruleTester.run('no-useless-constructor', rule, {
21+
valid: [
22+
'class A { }',
23+
'class A { constructor(){ doSomething(); } }',
24+
'class A extends B { constructor(){} }',
25+
"class A extends B { constructor(){ super('foo'); } }",
26+
'class A extends B { constructor(foo, bar){ super(foo, bar, 1); } }',
27+
'class A extends B { constructor(){ super(); doSomething(); } }',
28+
'class A extends B { constructor(...args){ super(...args); doSomething(); } }',
29+
'class A { dummyMethod(){ doSomething(); } }',
30+
'class A extends B.C { constructor() { super(foo); } }',
31+
'class A extends B.C { constructor([a, b, c]) { super(...arguments); } }',
32+
'class A extends B.C { constructor(a = f()) { super(...arguments); } }',
33+
'class A extends B { constructor(a, b, c) { super(a, b); } }',
34+
'class A extends B { constructor(foo, bar){ super(foo); } }',
35+
'class A extends B { constructor(test) { super(); } }',
36+
'class A extends B { constructor() { foo; } }',
37+
'class A extends B { constructor(foo, bar) { super(bar); } }',
38+
// https://github.com/typescript-eslint/typescript-eslint/issues/15
39+
'declare class A { constructor(); }',
40+
'class A { constructor(); }',
41+
'abstract class A { constructor(); }',
42+
'abstract class A { abstract constructor(); }',
43+
// https://github.com/typescript-eslint/typescript-eslint/issues/48
44+
'class A { constructor(private name: string) {} }',
45+
'class A { constructor(public name: string) {} }',
46+
'class A { constructor(protected name: string) {} }',
47+
// https://github.com/typescript-eslint/typescript-eslint/pull/167#discussion_r252638401
48+
'class A { private constructor() {} }',
49+
'class A { protected constructor() {} }',
50+
'class A extends B { public constructor() {} }',
51+
'class A extends B { protected constructor(foo, bar) { super(bar); } }',
52+
'class A extends B { private constructor(foo, bar) { super(bar); } }',
53+
'class A extends B { public constructor(foo){ super(foo); } }',
54+
'class A extends B { public constructor(foo){} }'
55+
],
56+
invalid: [
57+
{
58+
code: 'class A { constructor(){} }',
59+
errors: [error]
60+
},
61+
{
62+
code: "class A { 'constructor'(){} }",
63+
errors: [error]
64+
},
65+
{
66+
code: 'class A extends B { constructor() { super(); } }',
67+
errors: [error]
68+
},
69+
{
70+
code: 'class A extends B { constructor(foo){ super(foo); } }',
71+
errors: [error]
72+
},
73+
{
74+
code: 'class A extends B { constructor(foo, bar){ super(foo, bar); } }',
75+
errors: [error]
76+
},
77+
{
78+
code: 'class A extends B { constructor(...args){ super(...args); } }',
79+
errors: [error]
80+
},
81+
{
82+
code: 'class A extends B.C { constructor() { super(...arguments); } }',
83+
errors: [error]
84+
},
85+
{
86+
code:
87+
'class A extends B { constructor(a, b, ...c) { super(...arguments); } }',
88+
errors: [error]
89+
},
90+
{
91+
code:
92+
'class A extends B { constructor(a, b, ...c) { super(a, b, ...c); } }',
93+
errors: [error]
94+
},
95+
{
96+
code: 'class A { public constructor() {} }',
97+
errors: [error]
98+
}
99+
]
100+
});

0 commit comments

Comments
 (0)