Skip to content

Commit 4e3d6f6

Browse files
committed
Add lint rule to ensure that only variables and functions are assigned to module.exports
1 parent 04d4c20 commit 4e3d6f6

9 files changed

Lines changed: 721 additions & 0 deletions

File tree

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
<!--
2+
3+
@license Apache-2.0
4+
5+
Copyright (c) 2018 The Stdlib Authors.
6+
7+
Licensed under the Apache License, Version 2.0 (the "License");
8+
you may not use this file except in compliance with the License.
9+
You may obtain a copy of the License at
10+
11+
http://www.apache.org/licenses/LICENSE-2.0
12+
13+
Unless required by applicable law or agreed to in writing, software
14+
distributed under the License is distributed on an "AS IS" BASIS,
15+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16+
See the License for the specific language governing permissions and
17+
limitations under the License.
18+
19+
-->
20+
21+
# module-exports-assignments
22+
23+
> [ESLint rule][eslint-rules] enforcing that only variables and functions are assigned to `module.exports`.
24+
25+
<section class="intro">
26+
27+
</section>
28+
29+
<!-- /.intro -->
30+
31+
<section class="usage">
32+
33+
## Usage
34+
35+
```javascript
36+
var rule = require( '@stdlib/_tools/eslint/rules/module-exports-assignments' );
37+
```
38+
39+
#### rule
40+
41+
[ESLint rule][eslint-rules] enforcing that only variables and functions are assigned to `module.exports`.
42+
43+
**Bad**:
44+
45+
<!-- eslint-disable stdlib/module-exports-assignments -->
46+
47+
```javascript
48+
var normal = require( '@stdlib/random/base/normal' );
49+
var beta = require( '@stdlib/random/base/beta' );
50+
51+
52+
// EXPORTS //
53+
54+
module.exports = {
55+
'normal': normal,
56+
'beta': beta
57+
};
58+
```
59+
60+
**Good**:
61+
62+
```javascript
63+
var normal = require( '@stdlib/random/base/normal' );
64+
var beta = require( '@stdlib/random/base/beta' );
65+
66+
67+
// VARIABLES //
68+
69+
var ns = {
70+
'normal': normal,
71+
'beta': beta
72+
};
73+
74+
75+
// EXPORTS //
76+
77+
module.exports = ns;
78+
```
79+
80+
</section>
81+
82+
<!-- /.usage -->
83+
84+
<section class="examples">
85+
86+
## Examples
87+
88+
<!-- eslint no-undef: "error" -->
89+
90+
```javascript
91+
var Linter = require( 'eslint' ).Linter;
92+
var rule = require( '@stdlib/_tools/eslint/rules/module-exports-assignments' );
93+
94+
var linter = new Linter();
95+
var result;
96+
var code;
97+
98+
code = [
99+
'module.exports = fun();',
100+
'',
101+
'function fun() {',
102+
' return 3.14;',
103+
'}'
104+
].join( '\n' );
105+
106+
linter.defineRule( 'module-exports-assignments', rule );
107+
108+
result = linter.verify( code, {
109+
'rules': {
110+
'module-exports-assignments': 'error'
111+
}
112+
});
113+
/* returns
114+
[
115+
{
116+
'ruleId': 'module-exports-assignments',
117+
'severity': 2,
118+
'message': 'Only variables and functions should be assigned to `module.exports`',
119+
'line': 1,
120+
'column': 1,
121+
'nodeType': 'AssignmentExpression',
122+
'source': 'module.exports = fun();',
123+
'endLine': 1,
124+
'endColumn': 23
125+
}
126+
]
127+
*/
128+
```
129+
130+
</section>
131+
132+
<!-- /.examples -->
133+
134+
<section class="links">
135+
136+
[eslint-rules]: https://eslint.org/docs/developer-guide/working-with-rules
137+
138+
</section>
139+
140+
<!-- /.links -->
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2018 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
var Linter = require( 'eslint' ).Linter;
22+
var rule = require( './../lib' );
23+
24+
var linter = new Linter();
25+
var result;
26+
var code;
27+
28+
code = [
29+
'module.exports = fun();',
30+
'',
31+
'function fun() {',
32+
' return 3.14;',
33+
'}'
34+
].join( '\n' );
35+
36+
linter.defineRule( 'module-exports-assignments', rule );
37+
38+
result = linter.verify( code, {
39+
'rules': {
40+
'module-exports-assignments': 'error'
41+
}
42+
});
43+
console.log( result );
44+
/* =>
45+
[
46+
{
47+
'ruleId': 'module-exports-assignments',
48+
'severity': 2,
49+
'message': 'Only variables and functions should be assigned to `module.exports`',
50+
'line': 1,
51+
'column': 1,
52+
'nodeType': 'AssignmentExpression',
53+
'source': 'module.exports = fun();',
54+
'endLine': 1,
55+
'endColumn': 23
56+
}
57+
]
58+
*/
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2018 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
/**
22+
* ESLint rule enforcing that only variables and functions are assigned to `module.exports`.
23+
*
24+
* @module @stdlib/_tools/eslint/rules/module-exports-assignments
25+
*
26+
* @example
27+
* var rule = require( '@stdlib/_tools/eslint/rules/module-exports-assignments' );
28+
*
29+
* console.log( rule );
30+
*/
31+
32+
// MODULES //
33+
34+
var main = require( './main.js' );
35+
36+
37+
// EXPORTS //
38+
39+
module.exports = main;
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/**
2+
* @license Apache-2.0
3+
*
4+
* Copyright (c) 2018 The Stdlib Authors.
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
19+
'use strict';
20+
21+
// VARIABLES //
22+
23+
var rule;
24+
25+
26+
// FUNCTIONS //
27+
28+
/**
29+
* Checks whether a node is a variable or function expression.
30+
*
31+
* @private
32+
* @param {ASTNode} node - node to examine
33+
* @returns {boolean} boolean indicating whether node represents a variable or function expression
34+
*/
35+
function isVariableOrFunction( node ) {
36+
if ( !node ) {
37+
return false;
38+
}
39+
return node.type === 'Identifier' || node.type === 'FunctionExpression';
40+
}
41+
42+
/**
43+
* Checks whether a node represents an assignment to `module.exports`.
44+
*
45+
* @private
46+
* @param {ASTNode} node - node to examine
47+
* @returns {boolean} boolean indicating whether node represents a `module.exports` assignment
48+
*/
49+
function isExportStatement( node ) {
50+
if (
51+
node.left.type === 'MemberExpression'
52+
) {
53+
if (
54+
node.left.object.name === 'module' &&
55+
node.left.property.name === 'exports'
56+
) {
57+
return true;
58+
}
59+
if ( node.left.object.name === 'exports' ) {
60+
return true;
61+
}
62+
}
63+
return false;
64+
}
65+
66+
/**
67+
* Rule for validating that only variables and functions are assigned to `module.exports`.
68+
*
69+
* @param {Object} context - ESLint context
70+
* @returns {Object} validators
71+
*/
72+
function main( context ) {
73+
/**
74+
* Reports the error message.
75+
*
76+
* @private
77+
* @param {ASTNode} node - node to report
78+
*/
79+
function report( node ) {
80+
context.report({
81+
'node': node,
82+
'message': 'Only variables and functions should be assigned to `module.exports`'
83+
});
84+
}
85+
86+
/**
87+
* Checks whether only variables and functions are assigned to `module.exports`.
88+
*
89+
* @private
90+
* @param {ASTNode} node - node to examine
91+
*/
92+
function validate( node ) {
93+
if ( isExportStatement( node ) ) {
94+
if ( !isVariableOrFunction( node.right ) ) {
95+
report( node );
96+
}
97+
}
98+
}
99+
100+
return {
101+
'AssignmentExpression': validate
102+
};
103+
}
104+
105+
106+
// MAIN //
107+
108+
rule = {
109+
'meta': {
110+
'docs': {
111+
'description': 'enforce that only variables and functions are assigned to `module.exports`'
112+
},
113+
'schema': []
114+
},
115+
'create': main
116+
};
117+
118+
119+
// EXPORTS //
120+
121+
module.exports = rule;

0 commit comments

Comments
 (0)