Skip to content

Commit b829e90

Browse files
committed
Add jsx-uses-vars rule
1 parent 4ecb8d2 commit b829e90

File tree

4 files changed

+249
-27
lines changed

4 files changed

+249
-27
lines changed

README.md

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -38,11 +38,40 @@ Write `.eslintrc.*` file to configure rules. See also: http://eslint.org/docs/us
3838

3939
<!--RULES_TABLE_START-->
4040

41-
### Possible Errors
41+
### Best Practices
4242

43-
| | Rule ID | Description |
44-
|:---|:--------|:------------|
45-
| ⭐️ | [no-invalid-template-root](./docs/rules/no-invalid-template-root.md) | disallow invalid template root. |
43+
| | Rule ID | Description |
44+
|:---|:--------|:------------|
45+
| ⭐️✒️ | [html-end-tags](./docs/rules/html-end-tags.md) | enforce end tag style. |
46+
| ⭐️✒️ | [html-no-self-closing](./docs/rules/html-no-self-closing.md) | disallow self-closing elements. |
47+
| ⭐️ | [no-confusing-v-for-v-if](./docs/rules/no-confusing-v-for-v-if.md) | disallow confusing `v-for` and `v-if` on the same element. |
48+
| ⭐️ | [no-duplicate-attributes](./docs/rules/no-duplicate-attributes.md) | disallow duplicate arguments. |
49+
| ⭐️ | [no-textarea-mustache](./docs/rules/no-textarea-mustache.md) | disallow mustaches in `<textarea>`. |
50+
| ⭐️ | [require-component-is](./docs/rules/require-component-is.md) | require `v-bind:is` of `<component>` elements. |
51+
| ⭐️ | [require-v-for-key](./docs/rules/require-v-for-key.md) | require `v-bind:key` with `v-for` directives. |
52+
53+
54+
### Stylistic Issues
55+
56+
| | Rule ID | Description |
57+
|:---|:--------|:------------|
58+
| | [html-quotes](./docs/rules/html-quotes.md) | enforce quotes style of HTML attributes. |
59+
| ✒️ | [v-bind-style](./docs/rules/v-bind-style.md) | enforce v-bind directive style. |
60+
| ✒️ | [v-on-style](./docs/rules/v-on-style.md) | enforce v-on directive style. |
61+
62+
63+
### Variables
64+
65+
| | Rule ID | Description |
66+
|:---|:--------|:------------|
67+
| ⭐️ | [jsx-uses-vars](./docs/rules/jsx-uses-vars.md) | Prevent variables used in JSX to be marked as unused |
68+
69+
70+
### Possible Errors
71+
72+
| | Rule ID | Description |
73+
|:---|:--------|:------------|
74+
| ⭐️ | [no-invalid-template-root](./docs/rules/no-invalid-template-root.md) | disallow invalid template root. |
4675
| ⭐️ | [no-invalid-v-bind](./docs/rules/no-invalid-v-bind.md) | disallow invalid v-bind directives. |
4776
| ⭐️ | [no-invalid-v-cloak](./docs/rules/no-invalid-v-cloak.md) | disallow invalid v-cloak directives. |
4877
| ⭐️ | [no-invalid-v-else-if](./docs/rules/no-invalid-v-else-if.md) | disallow invalid v-else-if directives. |
@@ -58,29 +87,6 @@ Write `.eslintrc.*` file to configure rules. See also: http://eslint.org/docs/us
5887
| ⭐️ | [no-invalid-v-text](./docs/rules/no-invalid-v-text.md) | disallow invalid v-text directives. |
5988
| ⭐️ | [no-parsing-error](./docs/rules/no-parsing-error.md) | disallow parsing errors in `<template>`. |
6089

61-
62-
### Best Practices
63-
64-
| | Rule ID | Description |
65-
|:---|:--------|:------------|
66-
| ⭐️✒️ | [html-end-tags](./docs/rules/html-end-tags.md) | enforce end tag style. |
67-
| ⭐️✒️ | [html-no-self-closing](./docs/rules/html-no-self-closing.md) | disallow self-closing elements. |
68-
| ⭐️ | [jsx-uses-vars](./docs/rules/jsx-uses-vars.md) | Prevent variables used in JSX to be marked as unused |
69-
| ⭐️ | [no-confusing-v-for-v-if](./docs/rules/no-confusing-v-for-v-if.md) | disallow confusing `v-for` and `v-if` on the same element. |
70-
| ⭐️ | [no-duplicate-attributes](./docs/rules/no-duplicate-attributes.md) | disallow duplicate arguments. |
71-
| ⭐️ | [no-textarea-mustache](./docs/rules/no-textarea-mustache.md) | disallow mustaches in `<textarea>`. |
72-
| ⭐️ | [require-component-is](./docs/rules/require-component-is.md) | require `v-bind:is` of `<component>` elements. |
73-
| ⭐️ | [require-v-for-key](./docs/rules/require-v-for-key.md) | require `v-bind:key` with `v-for` directives. |
74-
75-
76-
### Stylistic Issues
77-
78-
| | Rule ID | Description |
79-
|:---|:--------|:------------|
80-
| | [html-quotes](./docs/rules/html-quotes.md) | enforce quotes style of HTML attributes. |
81-
| ✒️ | [v-bind-style](./docs/rules/v-bind-style.md) | enforce v-bind directive style. |
82-
| ✒️ | [v-on-style](./docs/rules/v-on-style.md) | enforce v-on directive style. |
83-
8490
<!--RULES_TABLE_END-->
8591

8692
## ⚙ Configs

docs/rules/jsx-uses-vars.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# Prevent variables used in JSX to be marked as unused (jsx-uses-vars)
2+
3+
Since 0.17.0 the ESLint `no-unused-vars` rule does not detect variables used in JSX ([see details](http://eslint.org/blog/2015/03/eslint-0.17.0-released#changes-to-jsxreact-handling)).
4+
This rule will find variables used in JSX and mark them as used.
5+
6+
This rule only has an effect when the `no-unused-vars` rule is enabled.
7+
8+
## Rule Details
9+
10+
Without this rule this code triggers warning:
11+
12+
```js
13+
import Hello from './Hello';
14+
15+
export default {
16+
render () {
17+
return (
18+
<Hello msg="world"></Hello>
19+
)
20+
},
21+
};
22+
```
23+
24+
After turning on, `Hello` is being marked as used and `no-unused-vars` rule doesn't report an issue.
25+
26+
## When Not To Use It
27+
28+
If you are not using JSX or if you do not use the `no-unused-vars` rule then you can disable this rule.

lib/rules/jsx-uses-vars.js

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// the following rule is based on yannickcr/eslint-plugin-react
2+
3+
/**
4+
The MIT License (MIT)
5+
6+
Copyright (c) 2014 Yannick Croissant
7+
8+
Permission is hereby granted, free of charge, to any person obtaining a copy
9+
of this software and associated documentation files (the "Software"), to deal
10+
in the Software without restriction, including without limitation the rights
11+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
copies of the Software, and to permit persons to whom the Software is
13+
furnished to do so, subject to the following conditions:
14+
15+
The above copyright notice and this permission notice shall be included in all
16+
copies or substantial portions of the Software.
17+
18+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24+
SOFTWARE.
25+
*/
26+
27+
/**
28+
* @fileoverview Prevent variables used in JSX to be marked as unused
29+
* @author Yannick Croissant
30+
*/
31+
'use strict';
32+
33+
// ------------------------------------------------------------------------------
34+
// Rule Definition
35+
// ------------------------------------------------------------------------------
36+
37+
module.exports = {
38+
meta: {
39+
docs: {
40+
description: 'Prevent variables used in JSX to be marked as unused',
41+
category: 'Variables',
42+
recommended: true
43+
},
44+
schema: []
45+
},
46+
47+
create(context) {
48+
return {
49+
JSXOpeningElement(node) {
50+
let name;
51+
if (node.name.name) {
52+
// <Foo>
53+
name = node.name.name;
54+
} else if (node.name.object) {
55+
// <Foo...Bar>
56+
let parent = node.name.object;
57+
while (parent.object) {
58+
parent = parent.object;
59+
}
60+
name = parent.name;
61+
} else {
62+
return;
63+
}
64+
65+
context.markVariableAsUsed(name);
66+
}
67+
};
68+
}
69+
};

tests/lib/rules/jsx-uses-vars.js

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/**
2+
* @fileoverview Prevent variables used in JSX to be marked as unused
3+
* @author Michał Sajnóg
4+
*/
5+
"use strict";
6+
7+
//------------------------------------------------------------------------------
8+
// Requirements
9+
//------------------------------------------------------------------------------
10+
11+
var eslint = require('eslint');
12+
var rule = require("../../../lib/rules/jsx-uses-vars");
13+
var ruleNoUnusedVars = require('eslint/lib/rules/no-unused-vars');
14+
15+
var RuleTester = eslint.RuleTester;
16+
var ruleTester = new RuleTester({
17+
parserOptions: {
18+
ecmaVersion: 6,
19+
sourceType: 'module',
20+
ecmaFeatures: {
21+
jsx: true,
22+
},
23+
},
24+
});
25+
26+
var linter = ruleTester.linter || eslint.linter;
27+
linter.defineRule('jsx-uses-vars', rule);
28+
29+
//------------------------------------------------------------------------------
30+
// Tests
31+
//------------------------------------------------------------------------------
32+
33+
ruleTester.run('no-unused-vars', ruleNoUnusedVars, {
34+
35+
valid: [
36+
{
37+
code: `
38+
/* eslint jsx-uses-vars: 1 */
39+
import SomeComponent from './SomeComponent.jsx';
40+
export default {
41+
render () {
42+
return (
43+
<SomeComponent msg="Hello world"></SomeComponent>
44+
)
45+
},
46+
};
47+
`
48+
}, {
49+
code: `
50+
/* eslint jsx-uses-vars: 1 */
51+
import SomeComponent from './SomeComponent.vue';
52+
import OtherComponent from './OtherComponent.vue';
53+
54+
const wrapper = {
55+
testComponent: SomeComponent,
56+
group: {
57+
otherComponent: OtherComponent,
58+
},
59+
};
60+
61+
export default {
62+
render () {
63+
return (
64+
<div>
65+
<wrapper.testComponent msg="asdasdasdasdas"></wrapper.testComponent>
66+
<wrapper.group.otherComponent></wrapper.group.otherComponent>
67+
</div>
68+
)
69+
}
70+
}
71+
`
72+
}, {
73+
code: `
74+
/* eslint jsx-uses-vars: 1 */
75+
export default {
76+
render () {
77+
return (
78+
<div>Lorem ipsum</div>
79+
)
80+
}
81+
}
82+
`
83+
}
84+
],
85+
86+
invalid: [
87+
{
88+
code: `
89+
/* eslint jsx-uses-vars: 1 */
90+
import SomeComponent from './SomeComponent.jsx';
91+
export default {
92+
render () {
93+
return <div></div>;
94+
},
95+
};
96+
`,
97+
errors: [{
98+
message: "'SomeComponent' is defined but never used.",
99+
}]
100+
}, {
101+
code: `
102+
/* eslint jsx-uses-vars: 1 */
103+
import SomeComponent from './SomeComponent.jsx';
104+
const wrapper = {
105+
something: SomeComponent,
106+
};
107+
108+
export default {
109+
render () {
110+
return <div></div>;
111+
},
112+
};
113+
`,
114+
errors: [{
115+
message: "'wrapper' is assigned a value but never used.",
116+
}]
117+
}
118+
]
119+
});

0 commit comments

Comments
 (0)