Skip to content
This repository was archived by the owner on Mar 23, 2024. It is now read-only.

Commit ad82a43

Browse files
stefania11hzoo
authored andcommitted
New Rule: requireSpacesInGenerator
Fixes #1879 Closes gh-1922
1 parent 3d0ae58 commit ad82a43

4 files changed

Lines changed: 185 additions & 1 deletion

File tree

grouping.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@
156156
"requireShorthandArrowFunctions",
157157
"requireNumericLiterals",
158158
"requireSpread",
159-
"requireTemplateStrings"
159+
"requireTemplateStrings",
160+
"requireSpacesInGenerator"
160161
],
161162
"Everything else": [
162163
"requireParenthesesAroundIIFE",

lib/config/configuration.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -939,6 +939,8 @@ Configuration.prototype.registerDefaultRules = function() {
939939
this.registerRule(require('../rules/require-shorthand-arrow-functions'));
940940
this.registerRule(require('../rules/disallow-shorthand-arrow-functions'));
941941
this.registerRule(require('../rules/disallow-identical-destructuring-names'));
942+
this.registerRule(require('../rules/require-spaces-around-generators'));
943+
942944
/* ES6 only (end) */
943945

944946
this.registerRule(require('../rules/require-curly-braces'));
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
/**
2+
* Requires space before and after `*` in generator functions
3+
*
4+
* Types: `Object`
5+
*
6+
* - `Object` (at least one of properties must be present and it must be set to true):
7+
* - `'beforeStar'`
8+
* - `true` validates that there is a space before `*`
9+
* - `'afterStar'`
10+
* - `true` validates that there is a space after `*`
11+
*
12+
* #### Example
13+
*
14+
* ```js
15+
* "requireSpacesInGenerator": {
16+
* "beforeStar": true,
17+
* "afterStar": true
18+
* }
19+
* ```
20+
* ##### Valid for mode `{ "beforeStar": true, "afterStar": true }`
21+
*
22+
* ```js
23+
* var x = function * () {};
24+
* function * a() {};
25+
* var x = async function * () {};
26+
* var x = async function * a () {};
27+
* async function * a() {}
28+
* var x = async function * (){};
29+
* ```
30+
*
31+
*/
32+
33+
var assert = require('assert');
34+
35+
module.exports = function() {};
36+
37+
module.exports.prototype = {
38+
configure: function(options) {
39+
assert(
40+
typeof options === 'object',
41+
this.getOptionName() + ' option must be an object'
42+
);
43+
44+
if ('beforeStar' in options) {
45+
assert(
46+
options.beforeStar === true,
47+
this.getOptionName() + '.beforeStar ' +
48+
'property requires true value or should be removed'
49+
);
50+
}
51+
if ('afterStar' in options) {
52+
assert(
53+
options.afterStar === true,
54+
this.getOptionName() + '.afterStar ' +
55+
'property requires true value or should be removed'
56+
);
57+
}
58+
59+
assert(
60+
options.beforeStar || options.afterStar,
61+
this.getOptionName() + ' must have beforeStar or afterStar property'
62+
);
63+
64+
this._beforeStar = options.beforeStar;
65+
this._afterStar = options.afterStar;
66+
},
67+
68+
getOptionName: function() {
69+
return 'requireSpacesInGenerator';
70+
},
71+
72+
check: function(file, errors) {
73+
var beforeStar = this._beforeStar;
74+
var afterStar = this._afterStar;
75+
76+
file.iterateNodesByType(['FunctionDeclaration', 'FunctionExpression'], function(node) {
77+
// for a named function, use node.id
78+
var functionNode = node.id || node;
79+
var parent = node.parentNode;
80+
81+
// Ignore syntactic sugar for getters and setters.
82+
if (parent.type === 'Property' && (parent.kind === 'get' || parent.kind === 'set')) {
83+
return;
84+
}
85+
86+
// shorthand or constructor methods
87+
if (parent.method || parent.type === 'MethodDefinition') {
88+
functionNode = parent.key;
89+
}
90+
91+
var currentToken = file.getFirstNodeToken(functionNode);
92+
93+
if (!node.generator) {
94+
return;
95+
}
96+
97+
if (node.async && currentToken.value === 'async') {
98+
currentToken = file.getNextToken(currentToken);
99+
}
100+
101+
if (beforeStar) {
102+
// currentToken assigned outside of function
103+
errors.assert.whitespaceBetween({
104+
token: currentToken,
105+
nextToken: file.getNextToken(currentToken),
106+
message: 'Missing space before star'
107+
});
108+
}
109+
110+
if (afterStar) {
111+
// currentToken reassigned for star token
112+
currentToken = file.getNextToken(currentToken);
113+
errors.assert.whitespaceBetween({
114+
token: currentToken,
115+
nextToken: file.getNextToken(currentToken),
116+
message: 'Missing space after star'
117+
});
118+
}
119+
});
120+
}
121+
};
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
var Checker = require('../../../lib/checker');
2+
var expect = require('chai').expect;
3+
var reportAndFix = require('../../lib/assertHelpers').reportAndFix;
4+
5+
describe('rules/require-spaces-around-generators', function() {
6+
var checker;
7+
beforeEach(function() {
8+
checker = new Checker();
9+
checker.registerDefaultRules();
10+
});
11+
12+
describe('both true', function() {
13+
var rules = {
14+
requireSpacesInGenerator: { beforeStar: true, afterStar: true },
15+
esnext: true
16+
};
17+
18+
beforeEach(function() {
19+
checker.configure(rules);
20+
});
21+
22+
reportAndFix({
23+
name: 'should report missing space before and after the star',
24+
rules: rules,
25+
errors: 2,
26+
input: 'var x = function*(){}',
27+
output: 'var x = function * (){}'
28+
});
29+
30+
reportAndFix({
31+
name: 'should report missing space after the star',
32+
rules: rules,
33+
errors: 1,
34+
input: 'var x = function *(){}',
35+
output: 'var x = function * (){}'
36+
});
37+
38+
reportAndFix({
39+
name: 'should report missing space before the star',
40+
rules: rules,
41+
errors: 1,
42+
input: 'var x = function* (){}',
43+
output: 'var x = function * (){}'
44+
});
45+
46+
it('should not report missing spaces error', function() {
47+
expect(checker.checkString('var x = function * (){}')).to.have.no.errors();
48+
});
49+
50+
it('should skip async functions', function() {
51+
expect(checker.checkString('var x = async function * (){}')).to.have.no.errors();
52+
});
53+
54+
it('should skip async functions', function() {
55+
var testExp = checker.checkString('var x = async function *(){}');
56+
var reqTest = 'requireSpacesInGenerator';
57+
expect(testExp).to.have.one.validation.error.from(reqTest);
58+
});
59+
});
60+
});

0 commit comments

Comments
 (0)