From 38bd88cb59381209144f05e3af9f5aa17e1c797a Mon Sep 17 00:00:00 2001 From: Will Binns-Smith Date: Thu, 6 Jul 2017 23:21:50 -0700 Subject: [PATCH] Re-modernize and cleanup with node 4-compatible features --- lib/rules/no-unused-state.js | 92 ++-- tests/lib/rules/no-unused-state.js | 814 +++++++++++++---------------- 2 files changed, 412 insertions(+), 494 deletions(-) diff --git a/lib/rules/no-unused-state.js b/lib/rules/no-unused-state.js index d8bd433505..ca26d18973 100644 --- a/lib/rules/no-unused-state.js +++ b/lib/rules/no-unused-state.js @@ -9,7 +9,7 @@ 'use strict'; -var Components = require('../util/Components'); +const Components = require('../util/Components'); // Descend through all wrapping TypeCastExpressions and return the expression // that was cast. @@ -40,10 +40,10 @@ function isThisExpression(node) { function getInitialClassInfo() { return { // Set of nodes where state fields were defined. - stateFields: [], + stateFields: new Set(), // Set of names of state fields that we've seen used. - usedStateFields: [], + usedStateFields: new Set(), // Names of local variables that may be pointing to this.state. To // track this properly, we would need to keep track of all locals, @@ -69,21 +69,21 @@ module.exports = { // not yet encountered any use of this.state which we have chosen not to // analyze. If we encounter any such usage (like this.state being spread as // JSX attributes), then this is again set to null. - var classInfo = null; + let classInfo = null; // Returns true if the given node is possibly a reference to `this.state`. function isStateReference(node) { node = uncast(node); - var isDirectStateReference = + const isDirectStateReference = node.type === 'MemberExpression' && isThisExpression(node.object) && node.property.name === 'state'; - var isAliasedStateReference = + const isAliasedStateReference = node.type === 'Identifier' && classInfo.aliases && - classInfo.aliases.indexOf(node.name) >= 0; + classInfo.aliases.has(node.name); return isDirectStateReference || isAliasedStateReference; } @@ -91,35 +91,35 @@ module.exports = { // Takes an ObjectExpression node and adds all named Property nodes to the // current set of state fields. function addStateFields(node) { - node.properties.forEach(function(prop) { + for (const prop of node.properties) { if (prop.type === 'Property' && getName(prop.key) !== null) { - classInfo.stateFields.push(prop); + classInfo.stateFields.add(prop); } - }); + } } // Adds the name of the given node as a used state field if the node is an // Identifier or a Literal. Other node types are ignored. function addUsedStateField(node) { - var name = getName(node); + const name = getName(node); if (name) { - classInfo.usedStateFields.push(name); + classInfo.usedStateFields.add(name); } } // Records used state fields and new aliases for an ObjectPattern which // destructures `this.state`. function handleStateDestructuring(node) { - node.properties.forEach(function(prop) { + for (const prop of node.properties) { if (prop.type === 'Property') { addUsedStateField(prop.key); } else if ( prop.type === 'ExperimentalRestProperty' && classInfo.aliases ) { - classInfo.aliases.push(getName(prop.argument)); + classInfo.aliases.add(getName(prop.argument)); } - }); + } } // Used to record used state fields and new aliases for both @@ -128,54 +128,54 @@ module.exports = { switch (left.type) { case 'Identifier': if (isStateReference(right) && classInfo.aliases) { - classInfo.aliases.push(left.name); + classInfo.aliases.add(left.name); } break; case 'ObjectPattern': if (isStateReference(right)) { handleStateDestructuring(left); } else if (isThisExpression(right) && classInfo.aliases) { - left.properties.forEach(function(prop) { + for (const prop of left.properties) { if (prop.type === 'Property' && getName(prop.key) === 'state') { - var name = getName(prop.value); + const name = getName(prop.value); if (name) { - classInfo.aliases.push(name); + classInfo.aliases.add(name); } else if (prop.value.type === 'ObjectPattern') { handleStateDestructuring(prop.value); } } - }); + } } break; default: - // pass + // pass } } function reportUnusedFields() { // Report all unused state fields. - classInfo.stateFields.forEach(function(node) { - var name = getName(node.key); - if (classInfo.usedStateFields.indexOf(name) < 0) { - context.report(node, 'Unused state field: \'' + name + '\''); + for (const node of classInfo.stateFields) { + const name = getName(node.key); + if (!classInfo.usedStateFields.has(name)) { + context.report(node, `Unused state field: '${name}'`); } - }); + } } return { - ClassDeclaration: function(node) { + ClassDeclaration(node) { if (utils.isES6Component(node)) { classInfo = getInitialClassInfo(); } }, - ObjectExpression: function(node) { + ObjectExpression(node) { if (utils.isES5Component(node)) { classInfo = getInitialClassInfo(); } }, - 'ObjectExpression:exit': function(node) { + 'ObjectExpression:exit'(node) { if (!classInfo) { return; } @@ -186,7 +186,7 @@ module.exports = { } }, - 'ClassDeclaration:exit': function() { + 'ClassDeclaration:exit'() { if (!classInfo) { return; } @@ -194,7 +194,7 @@ module.exports = { classInfo = null; }, - CallExpression: function(node) { + CallExpression(node) { if (!classInfo) { return; } @@ -211,7 +211,7 @@ module.exports = { } }, - ClassProperty: function(node) { + ClassProperty(node) { if (!classInfo) { return; } @@ -227,15 +227,15 @@ module.exports = { } }, - MethodDefinition: function() { + MethodDefinition() { if (!classInfo) { return; } // Create a new set for this.state aliases local to this method. - classInfo.aliases = []; + classInfo.aliases = new Set(); }, - 'MethodDefinition:exit': function() { + 'MethodDefinition:exit'() { if (!classInfo) { return; } @@ -243,19 +243,19 @@ module.exports = { classInfo.aliases = null; }, - FunctionExpression: function(node) { + FunctionExpression(node) { if (!classInfo) { return; } - var parent = node.parent; + const parent = node.parent; if (!utils.isES5Component(parent.parent)) { return; } if (parent.key.name === 'getInitialState') { - var body = node.body.body; - var lastBodyNode = body[body.length - 1]; + const body = node.body.body; + const lastBodyNode = body[body.length - 1]; if ( lastBodyNode.type === 'ReturnStatement' && @@ -265,11 +265,11 @@ module.exports = { } } else { // Create a new set for this.state aliases local to this method. - classInfo.aliases = []; + classInfo.aliases = new Set(); } }, - AssignmentExpression: function(node) { + AssignmentExpression(node) { if (!classInfo) { return; } @@ -281,7 +281,7 @@ module.exports = { node.right.type === 'ObjectExpression' ) { // Find the nearest function expression containing this assignment. - var fn = node; + let fn = node; while (fn.type !== 'FunctionExpression' && fn.parent) { fn = fn.parent; } @@ -300,14 +300,14 @@ module.exports = { } }, - VariableDeclarator: function(node) { + VariableDeclarator(node) { if (!classInfo || !node.init) { return; } handleAssignment(node.id, node.init); }, - MemberExpression: function(node) { + MemberExpression(node) { if (!classInfo) { return; } @@ -322,13 +322,13 @@ module.exports = { } }, - JSXSpreadAttribute: function(node) { + JSXSpreadAttribute(node) { if (classInfo && isStateReference(node.argument)) { classInfo = null; } }, - ExperimentalSpreadProperty: function(node) { + ExperimentalSpreadProperty(node) { if (classInfo && isStateReference(node.argument)) { classInfo = null; } diff --git a/tests/lib/rules/no-unused-state.js b/tests/lib/rules/no-unused-state.js index d0b9c40640..6465950c12 100644 --- a/tests/lib/rules/no-unused-state.js +++ b/tests/lib/rules/no-unused-state.js @@ -4,17 +4,17 @@ 'use strict'; -var rule = require('../../../lib/rules/no-unused-state'); -var RuleTester = require('eslint').RuleTester; +const rule = require('../../../lib/rules/no-unused-state'); +const RuleTester = require('eslint').RuleTester; -var parserOptions = { +const parserOptions = { ecmaVersion: 6, ecmaFeatures: { jsx: true } }; -var eslintTester = new RuleTester({ +const eslintTester = new RuleTester({ parserOptions: parserOptions, parser: 'babel-eslint' }); @@ -22,498 +22,416 @@ var eslintTester = new RuleTester({ function getErrorMessages(unusedFields) { return unusedFields.map(function(field) { return { - message: 'Unused state field: \'' + field + '\'' + message: `Unused state field: '${field}'` }; }); } eslintTester.run('no-unused-state', rule, { valid: [ - [ - 'function StatelessFnUnaffectedTest(props) {', - ' return ;', - '};' - ].join('\n'), - [ - 'var NoStateTest = React.createClass({', - ' render: function() {', - ' return ;', - ' }', - '});' - ].join('\n'), - [ - 'var NoStateMethodTest = React.createClass({', - ' render() {', - ' return ;', - ' }', - '});' - ].join('\n'), - [ - 'var GetInitialStateTest = React.createClass({', - ' getInitialState: function() {', - ' return { foo: 0 };', - ' },', - ' render: function() {', - ' return ;', - ' }', - '});' - ].join('\n'), - [ - 'var GetInitialStateMethodTest = React.createClass({', - ' getInitialState() {', - ' return { foo: 0 };', - ' },', - ' render() {', - ' return ;', - ' }', - '});' - ].join('\n'), - [ - 'var SetStateTest = React.createClass({', - ' onFooChange(newFoo) {', - ' this.setState({ foo: newFoo });', - ' },', - ' render() {', - ' return ;', - ' }', - '});' - ].join('\n'), - [ - 'var MultipleSetState = React.createClass({', - ' getInitialState() {', - ' return { foo: 0 };', - ' },', - ' update() {', - ' this.setState({foo: 1});', - ' },', - ' render() {', - ' return ;', - ' }', - '});' - ].join('\n'), - [ - 'class NoStateTest extends React.Component {', - ' render() {', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class CtorStateTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' render() {', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class SetStateTest extends React.Component {', - ' onFooChange(newFoo) {', - ' this.setState({ foo: newFoo });', - ' }', - ' render() {', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class ClassPropertyStateTest extends React.Component {', - ' state = { foo: 0 };', - ' render() {', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class VariableDeclarationTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' render() {', - ' const foo = this.state.foo;', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class DestructuringTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' render() {', - ' const {foo: myFoo} = this.state;', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class ShorthandDestructuringTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' render() {', - ' const {foo} = this.state;', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class AliasDeclarationTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' render() {', - ' const state = this.state;', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class AliasAssignmentTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' render() {', - ' let state;', - ' state = this.state;', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class DestructuringAliasTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' render() {', - ' const {state: myState} = this;', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class ShorthandDestructuringAliasTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' render() {', - ' const {state} = this;', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class RestPropertyTest extends React.Component {', - ' constructor() {', - ' this.state = {', - ' foo: 0,', - ' bar: 1,', - ' };', - ' }', - ' render() {', - ' const {foo, ...others} = this.state;', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class DeepDestructuringTest extends React.Component {', - ' state = { foo: 0, bar: 0 };', - ' render() {', - ' const {state: {foo, ...others}} = this;', - ' return ;', - ' }', - '}' - ].join('\n'), + `function StatelessFnUnaffectedTest(props) { + return ; + };`, + `var NoStateTest = createReactClass({ + render: function() { + return ; + } + });`, + `var NoStateMethodTest = createReactClass({ + render() { + return ; + } + });`, + `var GetInitialStateTest = createReactClass({ + getInitialState: function() { + return { foo: 0 }; + }, + render: function() { + return ; + } + });`, + `var GetInitialStateMethodTest = createReactClass({ + getInitialState() { + return { foo: 0 }; + }, + render() { + return ; + } + });`, + `var SetStateTest = createReactClass({ + onFooChange(newFoo) { + this.setState({ foo: newFoo }); + }, + render() { + return ; + } + });`, + `var MultipleSetState = createReactClass({ + getInitialState() { + return { foo: 0 }; + }, + update() { + this.setState({foo: 1}); + }, + render() { + return ; + } + });`, + `class NoStateTest extends React.Component { + render() { + return ; + } + }`, + `class CtorStateTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + render() { + return ; + } + }`, + `class SetStateTest extends React.Component { + onFooChange(newFoo) { + this.setState({ foo: newFoo }); + } + render() { + return ; + } + }`, + `class ClassPropertyStateTest extends React.Component { + state = { foo: 0 }; + render() { + return ; + } + }`, + `class VariableDeclarationTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + render() { + const foo = this.state.foo; + return ; + } + }`, + `class DestructuringTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + render() { + const {foo: myFoo} = this.state; + return ; + } + }`, + `class ShorthandDestructuringTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + render() { + const {foo} = this.state; + return ; + } + }`, + `class AliasDeclarationTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + render() { + const state = this.state; + return ; + } + }`, + `class AliasAssignmentTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + render() { + let state; + state = this.state; + return ; + } + }`, + `class DestructuringAliasTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + render() { + const {state: myState} = this; + return ; + } + }`, + `class ShorthandDestructuringAliasTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + render() { + const {state} = this; + return ; + } + }`, + `class RestPropertyTest extends React.Component { + constructor() { + this.state = { + foo: 0, + bar: 1, + }; + } + render() { + const {foo, ...others} = this.state; + return ; + } + }`, + `class DeepDestructuringTest extends React.Component { + state = { foo: 0, bar: 0 }; + render() { + const {state: {foo, ...others}} = this; + return ; + } + }`, // A cleverer analysis might recognize that the following should be errors, // but they're out of scope for this lint rule. - [ - 'class MethodArgFalseNegativeTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' consumeFoo(foo) {}', - ' render() {', - ' this.consumeFoo(this.state.foo)', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class AssignedToObjectFalseNegativeTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' render() {', - ' const obj = { foo: this.state.foo, bar: 0 };', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class ComputedAccessFalseNegativeTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0, bar: 1 };', - ' }', - ' render() {', - ' const bar = \'bar\';', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class JsxSpreadFalseNegativeTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' render() {', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class AliasedJsxSpreadFalseNegativeTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' render() {', - ' const state = this.state;', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class ObjectSpreadFalseNegativeTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' render() {', - ' const attrs = { ...this.state, foo: 1 };', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class ShadowingFalseNegativeTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' render() {', - ' const state = this.state;', - ' let foo;', - ' {', - ' const state = { foo: 5 };', - ' foo = state.foo;', - ' }', - ' return ;', - ' }', - '}' - ].join('\n'), - [ - 'class TypeCastExpressionSpreadFalseNegativeTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' render() {', - ' return ;', - ' }', - '}' - ].join('\n') + `class MethodArgFalseNegativeTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + consumeFoo(foo) {} + render() { + this.consumeFoo(this.state.foo); + return ; + } + }`, + `class AssignedToObjectFalseNegativeTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + render() { + const obj = { foo: this.state.foo, bar: 0 }; + return ; + } + }`, + `class ComputedAccessFalseNegativeTest extends React.Component { + constructor() { + this.state = { foo: 0, bar: 1 }; + } + render() { + const bar = \'bar\'; + return ; + } + }`, + `class JsxSpreadFalseNegativeTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + render() { + return ; + } + }`, + `class AliasedJsxSpreadFalseNegativeTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + render() { + const state = this.state; + return ; + } + }`, + `class ObjectSpreadFalseNegativeTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + render() { + const attrs = { ...this.state, foo: 1 }; + return ; + } + }`, + `class ShadowingFalseNegativeTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + render() { + const state = this.state; + let foo; + { + const state = { foo: 5 }; + foo = state.foo; + } + return ; + } + }`, + `class TypeCastExpressionSpreadFalseNegativeTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + render() { + return ; + } + }` ], invalid: [ { - code: [ - 'var UnusedGetInitialStateTest = React.createClass({', - ' getInitialState: function() {', - ' return { foo: 0 };', - ' },', - ' render: function() {', - ' return ;', - ' }', - '})' - ].join('\n'), + code: `var UnusedGetInitialStateTest = createReactClass({ + getInitialState: function() { + return { foo: 0 }; + }, + render: function() { + return ; + } + })`, errors: getErrorMessages(['foo']) }, { - code: [ - 'var UnusedGetInitialStateMethodTest = React.createClass({', - ' getInitialState() {', - ' return { foo: 0 };', - ' },', - ' render() {', - ' return ;', - ' }', - '})' - ].join('\n'), + code: `var UnusedGetInitialStateMethodTest = createReactClass({ + getInitialState() { + return { foo: 0 }; + }, + render() { + return ; + } + })`, errors: getErrorMessages(['foo']) }, { - code: [ - 'var UnusedSetStateTest = React.createClass({', - ' onFooChange(newFoo) {', - ' this.setState({ foo: newFoo });', - ' },', - ' render() {', - ' return ;', - ' }', - '});' - ].join('\n'), + code: `var UnusedSetStateTest = createReactClass({ + onFooChange(newFoo) { + this.setState({ foo: newFoo }); + }, + render() { + return ; + } + });`, errors: getErrorMessages(['foo']) }, { - code: [ - 'class UnusedCtorStateTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' render() {', - ' return ;', - ' }', - '}' - ].join('\n'), + code: `class UnusedCtorStateTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + render() { + return ; + } + }`, errors: getErrorMessages(['foo']) }, { - code: [ - 'class UnusedSetStateTest extends React.Component {', - ' onFooChange(newFoo) {', - ' this.setState({ foo: newFoo });', - ' }', - ' render() {', - ' return ;', - ' }', - '}' - ].join('\n'), + code: `class UnusedSetStateTest extends React.Component { + onFooChange(newFoo) { + this.setState({ foo: newFoo }); + } + render() { + return ; + } + }`, errors: getErrorMessages(['foo']) }, { - code: [ - 'class UnusedClassPropertyStateTest extends React.Component {', - ' state = { foo: 0 };', - ' render() {', - ' return ;', - ' }', - '}' - ].join('\n'), + code: `class UnusedClassPropertyStateTest extends React.Component { + state = { foo: 0 }; + render() { + return ; + } + }`, errors: getErrorMessages(['foo']) }, { - code: [ - 'class UnusedStateWhenPropsAreSpreadTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' render() {', - ' return ;', - ' }', - '}' - ].join('\n'), + code: `class UnusedStateWhenPropsAreSpreadTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + render() { + return ; + } + }`, errors: getErrorMessages(['foo']) }, { - code: [ - 'class AliasOutOfScopeTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' render() {', - ' const state = this.state;', - ' return ;', - ' }', - ' someMethod() {', - ' const outOfScope = state.foo;', - ' }', - '}' - ].join('\n'), + code: `class AliasOutOfScopeTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + render() { + const state = this.state; + return ; + } + someMethod() { + const outOfScope = state.foo; + } + }`, errors: getErrorMessages(['foo']) }, { - code: [ - 'class MultipleErrorsTest extends React.Component {', - ' constructor() {', - ' this.state = {', - ' foo: 0,', - ' bar: 1,', - ' baz: 2,', - ' qux: 3,', - ' };', - ' }', - ' render() {', - ' let {state} = this;', - ' return ;', - ' }', - '}' - ].join('\n'), + code: `class MultipleErrorsTest extends React.Component { + constructor() { + this.state = { + foo: 0, + bar: 1, + baz: 2, + qux: 3, + }; + } + render() { + let {state} = this; + return ; + } + }`, errors: getErrorMessages(['foo', 'bar']) }, { - code: [ - 'class MultipleErrorsForSameKeyTest extends React.Component {', - ' constructor() {', - ' this.state = { foo: 0 };', - ' }', - ' onFooChange(newFoo) {', - ' this.setState({ foo: newFoo });', - ' }', - ' render() {', - ' return ;', - ' }', - '}' - ].join('\n'), + code: `class MultipleErrorsForSameKeyTest extends React.Component { + constructor() { + this.state = { foo: 0 }; + } + onFooChange(newFoo) { + this.setState({ foo: newFoo }); + } + render() { + return ; + } + }`, errors: getErrorMessages(['foo', 'foo']) }, { - code: [ - 'class UnusedRestPropertyFieldTest extends React.Component {', - ' constructor() {', - ' this.state = {', - ' foo: 0,', - ' bar: 1,', - ' };', - ' }', - ' render() {', - ' const {bar, ...others} = this.state;', - ' return ;', - ' }', - '}' - ].join('\n'), + code: `class UnusedRestPropertyFieldTest extends React.Component { + constructor() { + this.state = { + foo: 0, + bar: 1, + }; + } + render() { + const {bar, ...others} = this.state; + return ; + } + }`, errors: getErrorMessages(['foo']) }, { - code: [ - 'class TypeCastExpressionTest extends React.Component {', - ' constructor() {', - ' this.state = {', - ' foo: 0,', - ' bar: 1,', - ' baz: 2,', - ' qux: 3,', - ' };', - ' }', - ' render() {', - ' const foo = ((this: any).state: any).foo;', - ' const {bar, ...others} = (this.state: any);', - ' let baz;', - ' baz = (others: any)[\'baz\'];', - ' return ;', - ' }', - '}' - ].join('\n'), + code: `class TypeCastExpressionTest extends React.Component { + constructor() { + this.state = { + foo: 0, + bar: 1, + baz: 2, + qux: 3, + }; + } + render() { + const foo = ((this: any).state: any).foo; + const {bar, ...others} = (this.state: any); + let baz; + baz = (others: any)[\'baz\']; + return ; + } + }`, errors: getErrorMessages(['qux']) }, { - code: [ - 'class UnusedDeepDestructuringTest extends React.Component {', - ' state = { foo: 0, bar: 0 };', - ' render() {', - ' const {state: {foo}} = this;', - ' return ;', - ' }', - '}' - ].join('\n'), + code: `class UnusedDeepDestructuringTest extends React.Component { + state = { foo: 0, bar: 0 }; + render() { + const {state: {foo}} = this; + return ; + } + }`, errors: getErrorMessages(['bar']) } ]