Skip to content

Commit

Permalink
feat: [destructuring-assignment] setting up never for sfc and class
Browse files Browse the repository at this point in the history
  • Loading branch information
DianaSuvorova committed Oct 13, 2017
1 parent a25003c commit c967000
Show file tree
Hide file tree
Showing 3 changed files with 117 additions and 30 deletions.
39 changes: 34 additions & 5 deletions docs/rules/destructuring-assignment.md
@@ -1,7 +1,6 @@
# Enforce consostent usage of destructuring assignment of props, state and context (react/destructuring-assignment)

Rule can be set to either of `always`, `never`, `ignore` for SFC and to `always` or `ignore` for class components.

Rule can be set to either of `always`, `never`, `ignore` for `class` and `SFC` components.
```js
"react/destructuring-assignment": [<enabled>, { "SFC": "always", "class": "always"}]
```
Expand Down Expand Up @@ -32,27 +31,57 @@ const MyComponent = ({id}) => {
};
```

```js
const MyComponent = (props, context) => {
const { id } = props;
return (<div id={id} />)
};
```

```js
const Foo = class extends React.PureComponent {
render() {
const { foo } = this.props;
return <div>{foo}</div>;
const { title } = this.context;
return <div>{title}</div>;
}
};
```

If rule option is set to `never` for SFC, the following pattern is considered warning:
If rule option is set to `never`, the following patterns are considered warning:

```js
const MyComponent = ({id}) => {
return (<div id={id} />)
};
```

```js
const MyComponent = (props) => {
const { id } = props;
return (<div id={id} />)
};
```

```js
const Foo = class extends React.PureComponent {
render() {
const { title } = this.state;
return <div>{title}</div>;
}
};
```

and below pattern is correct:

```js
const MyComponent = (props) => {
return (<div id={props.id} />)
};
```

```js
const Foo = class extends React.PureComponent {
render() {
return <div>{this.state.title}</div>;
}
};
39 changes: 30 additions & 9 deletions lib/rules/destructuring-assignment.js
Expand Up @@ -19,24 +19,18 @@ module.exports = {
},
schema: [{
definitions: {
valueSFC: {
value: {
enum: [
'always',
'never',
'ignore'
]
},
valueClass: {
enum: [
'always',
'ignore'
]
}
},
type: 'object',
properties: {
SFC: {$ref: '#/definitions/valueSFC'},
class: {$ref: '#/definitions/valueClass'}
SFC: {$ref: '#/definitions/value'},
class: {$ref: '#/definitions/value'}
},
additionalProperties: false
}]
Expand Down Expand Up @@ -127,6 +121,33 @@ module.exports = {
if (classComponent) {
handleClassUsage(node, classComponent);
}
},

VariableDeclarator: function(node) {
const classComponent = utils.getParentComponent(node);
const SFCComponent = components.get(context.getScope(node).block);

const destructuring = (node.init && node.id && node.id.type === 'ObjectPattern');
// let {foo} = props;
const destructuringSFC = destructuring && (node.init.name === 'props' || node.init.name === 'context');
// let {foo} = this.props;
const destructuringClass = destructuring && node.init.object && node.init.object.type === 'ThisExpression' && (
node.init.property.name === 'props' || node.init.property.name === 'context' || node.init.property.name === 'state'
);

if (SFCComponent && destructuringSFC && options.SFC === 'never') {
context.report({
node: node,
message: `Must never use destructuring ${node.init.name} assignment`
});
}

if (classComponent && destructuringClass && options.class === 'never') {
context.report({
node: node,
message: `Must never use destructuring ${node.init.property.name} assignment`
});
}
}
};
})
Expand Down
69 changes: 53 additions & 16 deletions tests/lib/rules/destructuring-assignment.js
Expand Up @@ -20,24 +20,24 @@ const parserOptions = {
const ruleTester = new RuleTester({parserOptions});
ruleTester.run('destructuring-assignment', rule, {
valid: [{
code: `const Foo = class extends React.PureComponent {
render() {
const { foo } = this.props;
return <div>{foo}</div>;
}
};`
}, {
code: `const Foo = class extends React.PureComponent {
render() {
const { foo } = this.props;
return <div>{foo}</div>;
}
};`,
options: [{SFC: 'always', class: 'always'}]
options: [{SFC: 'always', class: 'always'}],
parser: 'babel-eslint'
}, {
code: `const MyComponent = ({ id, className }) => (
<div id={id} className={className} />
);`
}, {
code: `const MyComponent = (props) => {
const { id, className } = props;
return <div id={id} className={className} />
};`,
parser: 'babel-eslint'
}, {
code: `const MyComponent = ({ id, className }) => (
<div id={id} className={className} />
Expand Down Expand Up @@ -72,12 +72,6 @@ ruleTester.run('destructuring-assignment', rule, {
<div id={id} props={props} color={color} />
);`,
options: [{SFC: 'always', class: 'always'}]
}, {
code: `const MyComponent = (props) => {
const { id, className } = props;
return <div id={id} className={className} />
};`,
options: [{SFC: 'never'}]
}, {
code: `const Foo = class extends React.PureComponent {
render() {
Expand Down Expand Up @@ -107,7 +101,8 @@ ruleTester.run('destructuring-assignment', rule, {
return <div>{foo}</div>;
}
};`,
options: [{SFC: 'always', class: 'always'}]
options: [{SFC: 'always', class: 'always'}],
parser: 'babel-eslint'
}, {
code: `const Foo = class extends React.PureComponent {
render() {
Expand All @@ -122,7 +117,15 @@ ruleTester.run('destructuring-assignment', rule, {
return <div>{foo}</div>;
}
};`,
options: [{SFC: 'always', class: 'always'}]
options: [{SFC: 'always', class: 'always'}],
parser: 'babel-eslint'
}, {
code: `const MyComponent = (props) => {
const { h, i } = hi;
return <div id={props.id} className={props.className} />
};`,
options: [{SFC: 'never'}],
parser: 'babel-eslint'
}],
invalid: [{
code: `const MyComponent = (props) => {
Expand Down Expand Up @@ -203,5 +206,39 @@ ruleTester.run('destructuring-assignment', rule, {
errors: [
{message: 'Must use destructuring props assignment'}
]
}, {
code: `const Foo = class extends React.PureComponent {
render() {
const { foo } = this.props;
return <div>{foo}</div>;
}
};`,
options: [{SFC: 'always', class: 'never'}],
parser: 'babel-eslint',
errors: [
{message: 'Must never use destructuring props assignment'}
]
}, {
code: `const MyComponent = (props) => {
const { id, className } = props;
return <div id={id} className={className} />
};`,
options: [{SFC: 'never'}],
parser: 'babel-eslint',
errors: [
{message: 'Must never use destructuring props assignment'}
]
}, {
code: `const Foo = class extends React.PureComponent {
render() {
const { foo } = this.state;
return <div>{foo}</div>;
}
};`,
options: [{SFC: 'always', class: 'never'}],
parser: 'babel-eslint',
errors: [
{message: 'Must never use destructuring state assignment'}
]
}]
});

0 comments on commit c967000

Please sign in to comment.