@@ -55,57 +55,131 @@ module.exports = Components.detect(function(context, components, utils) {
5555 }
5656
5757 /**
58- * Checks whether the constructor body is a redundant super call.
58+ * Checks whether a given array of statements is a single call of `super` .
5959 * @see ESLint no-useless-constructor rule
60- * @param {Array } body - constructor body content.
61- * @param {Array } ctorParams - The params to check against super call.
62- * @returns {boolean } true if the construtor body is redundant
60+ * @param {ASTNode[] } body - An array of statements to check.
61+ * @returns {boolean } `true` if the body is a single call of `super`.
6362 */
64- function isRedundantSuperCall ( body , ctorParams ) {
65- if (
66- body . length !== 1 ||
67- body [ 0 ] . type !== 'ExpressionStatement' ||
68- body [ 0 ] . expression . callee . type !== 'Super'
69- ) {
63+ function isSingleSuperCall ( body ) {
64+ return (
65+ body . length === 1 &&
66+ body [ 0 ] . type === 'ExpressionStatement' &&
67+ body [ 0 ] . expression . type === 'CallExpression' &&
68+ body [ 0 ] . expression . callee . type === 'Super'
69+ ) ;
70+ }
71+
72+ /**
73+ * Checks whether a given node is a pattern which doesn't have any side effects.
74+ * Default parameters and Destructuring parameters can have side effects.
75+ * @see ESLint no-useless-constructor rule
76+ * @param {ASTNode } node - A pattern node.
77+ * @returns {boolean } `true` if the node doesn't have any side effects.
78+ */
79+ function isSimple ( node ) {
80+ return node . type === 'Identifier' || node . type === 'RestElement' ;
81+ }
82+
83+ /**
84+ * Checks whether a given array of expressions is `...arguments` or not.
85+ * `super(...arguments)` passes all arguments through.
86+ * @see ESLint no-useless-constructor rule
87+ * @param {ASTNode[] } superArgs - An array of expressions to check.
88+ * @returns {boolean } `true` if the superArgs is `...arguments`.
89+ */
90+ function isSpreadArguments ( superArgs ) {
91+ return (
92+ superArgs . length === 1 &&
93+ superArgs [ 0 ] . type === 'SpreadElement' &&
94+ superArgs [ 0 ] . argument . type === 'Identifier' &&
95+ superArgs [ 0 ] . argument . name === 'arguments'
96+ ) ;
97+ }
98+
99+ /**
100+ * Checks whether given 2 nodes are identifiers which have the same name or not.
101+ * @see ESLint no-useless-constructor rule
102+ * @param {ASTNode } ctorParam - A node to check.
103+ * @param {ASTNode } superArg - A node to check.
104+ * @returns {boolean } `true` if the nodes are identifiers which have the same
105+ * name.
106+ */
107+ function isValidIdentifierPair ( ctorParam , superArg ) {
108+ return (
109+ ctorParam . type === 'Identifier' &&
110+ superArg . type === 'Identifier' &&
111+ ctorParam . name === superArg . name
112+ ) ;
113+ }
114+
115+ /**
116+ * Checks whether given 2 nodes are a rest/spread pair which has the same values.
117+ * @see ESLint no-useless-constructor rule
118+ * @param {ASTNode } ctorParam - A node to check.
119+ * @param {ASTNode } superArg - A node to check.
120+ * @returns {boolean } `true` if the nodes are a rest/spread pair which has the
121+ * same values.
122+ */
123+ function isValidRestSpreadPair ( ctorParam , superArg ) {
124+ return (
125+ ctorParam . type === 'RestElement' &&
126+ superArg . type === 'SpreadElement' &&
127+ isValidIdentifierPair ( ctorParam . argument , superArg . argument )
128+ ) ;
129+ }
130+
131+ /**
132+ * Checks whether given 2 nodes have the same value or not.
133+ * @see ESLint no-useless-constructor rule
134+ * @param {ASTNode } ctorParam - A node to check.
135+ * @param {ASTNode } superArg - A node to check.
136+ * @returns {boolean } `true` if the nodes have the same value or not.
137+ */
138+ function isValidPair ( ctorParam , superArg ) {
139+ return (
140+ isValidIdentifierPair ( ctorParam , superArg ) ||
141+ isValidRestSpreadPair ( ctorParam , superArg )
142+ ) ;
143+ }
144+
145+ /**
146+ * Checks whether the parameters of a constructor and the arguments of `super()`
147+ * have the same values or not.
148+ * @see ESLint no-useless-constructor rule
149+ * @param {ASTNode } ctorParams - The parameters of a constructor to check.
150+ * @param {ASTNode } superArgs - The arguments of `super()` to check.
151+ * @returns {boolean } `true` if those have the same values.
152+ */
153+ function isPassingThrough ( ctorParams , superArgs ) {
154+ if ( ctorParams . length !== superArgs . length ) {
70155 return false ;
71156 }
72157
73- var superArgs = body [ 0 ] . expression . arguments ;
74- var firstSuperArg = superArgs [ 0 ] ;
75- var lastSuperArgIndex = superArgs . length - 1 ;
76- var lastSuperArg = superArgs [ lastSuperArgIndex ] ;
77- var isSimpleParameterList = ctorParams . every ( function ( param ) {
78- return param . type === 'Identifier' || param . type === 'RestElement' ;
79- } ) ;
80-
81- /**
82- * Checks if a super argument is the same with constructor argument
83- * @param {ASTNode } arg argument node
84- * @param {number } index argument index
85- * @returns {boolean } true if the arguments are same, false otherwise
86- */
87- function isSameIdentifier ( arg , index ) {
88- return (
89- arg . type === 'Identifier' &&
90- arg . name === ctorParams [ index ] . name
91- ) ;
158+ for ( var i = 0 ; i < ctorParams . length ; ++ i ) {
159+ if ( ! isValidPair ( ctorParams [ i ] , superArgs [ i ] ) ) {
160+ return false ;
161+ }
92162 }
93163
94- var spreadsArguments =
95- superArgs . length === 1 &&
96- firstSuperArg . type === 'SpreadElement' &&
97- firstSuperArg . argument . name === 'arguments' ;
98-
99- var passesParamsAsArgs =
100- superArgs . length === ctorParams . length &&
101- superArgs . every ( isSameIdentifier ) ||
102- superArgs . length <= ctorParams . length &&
103- superArgs . slice ( 0 , - 1 ) . every ( isSameIdentifier ) &&
104- lastSuperArg . type === 'SpreadElement' &&
105- ctorParams [ lastSuperArgIndex ] . type === 'RestElement' &&
106- lastSuperArg . argument . name === ctorParams [ lastSuperArgIndex ] . argument . name ;
107-
108- return isSimpleParameterList && ( spreadsArguments || passesParamsAsArgs ) ;
164+ return true ;
165+ }
166+
167+ /**
168+ * Checks whether the constructor body is a redundant super call.
169+ * @see ESLint no-useless-constructor rule
170+ * @param {Array } body - constructor body content.
171+ * @param {Array } ctorParams - The params to check against super call.
172+ * @returns {boolean } true if the construtor body is redundant
173+ */
174+ function isRedundantSuperCall ( body , ctorParams ) {
175+ return (
176+ isSingleSuperCall ( body ) &&
177+ ctorParams . every ( isSimple ) &&
178+ (
179+ isSpreadArguments ( body [ 0 ] . expression . arguments ) ||
180+ isPassingThrough ( ctorParams , body [ 0 ] . expression . arguments )
181+ )
182+ ) ;
109183 }
110184
111185 /**
0 commit comments