Skip to content

Commit 76e1e97

Browse files
committed
feat(require-returns): move settings to options
BREAKING CHANGE: The following settings has been removed and became options under relevant rules. * `settings.jsdoc.allowEmptyNamepaths` -> option in `valid-types` * `settings.jsdoc.checkSeesForNamepaths` -> option in `valid-types` * `settings.jsdoc.exemptEmptyFunctions` -> option in `require-jsdoc` * `settings.jsdoc.forceRequireReturn` -> option in `require-returns` * `settings.jsdoc.avoidExampleOnConstructors` -> option in `require-example`
1 parent ed56935 commit 76e1e97

File tree

4 files changed

+176
-62
lines changed

4 files changed

+176
-62
lines changed

src/iterateJsdoc.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -281,9 +281,6 @@ const getSettings = (context) => {
281281
settings.allowEmptyNamepaths = _.get(context, 'settings.jsdoc.allowEmptyNamepaths') !== false;
282282
settings.checkSeesForNamepaths = Boolean(_.get(context, 'settings.jsdoc.checkSeesForNamepaths'));
283283

284-
// `require-returns` only
285-
settings.forceRequireReturn = Boolean(_.get(context, 'settings.jsdoc.forceRequireReturn'));
286-
287284
// `require-example` only
288285
settings.avoidExampleOnConstructors = Boolean(_.get(context, 'settings.jsdoc.avoidExampleOnConstructors'));
289286

src/rules/requireReturns.js

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import iterateJsdoc from '../iterateJsdoc';
2+
import warnRemovedSettings from '../warnRemovedSettings';
23

34
/**
45
* We can skip checking for a return value, in case the documentation is inherited
@@ -43,16 +44,20 @@ const canSkip = (utils) => {
4344
export default iterateJsdoc(({
4445
report,
4546
utils,
46-
context,
47-
settings
47+
context
4848
}) => {
49+
warnRemovedSettings(context, 'require-returns');
50+
4951
// A preflight check. We do not need to run a deep check
5052
// in case the @returns comment is optional or undefined.
5153
if (canSkip(utils)) {
5254
return;
5355
}
5456

55-
const options = context.options[0] || {};
57+
const options = context.options[0] || {
58+
forceRequireReturn: false,
59+
forceReturnsWithAsync: false
60+
};
5661

5762
const tagName = utils.getPreferredTagName('returns');
5863
if (!tagName) {
@@ -68,7 +73,7 @@ export default iterateJsdoc(({
6873
const [tag] = tags;
6974
const missingReturnTag = typeof tag === 'undefined' || tag === null;
7075
if (missingReturnTag &&
71-
((utils.isAsync() && !utils.hasReturnValue(true) ? options.forceReturnsWithAsync : utils.hasReturnValue()) || settings.forceRequireReturn)
76+
((utils.isAsync() && !utils.hasReturnValue(true) ? options.forceReturnsWithAsync : utils.hasReturnValue()) || options.forceRequireReturn)
7277
) {
7378
report(`Missing JSDoc @${tagName} declaration.`);
7479
}
@@ -84,6 +89,10 @@ export default iterateJsdoc(({
8489
},
8590
type: 'array'
8691
},
92+
forceRequireReturn: {
93+
default: false,
94+
type: 'boolean'
95+
},
8796
forceReturnsWithAsync: {
8897
default: false,
8998
type: 'boolean'

src/warnRemovedSettings.js

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/**
2+
* @typedef {(
3+
* | "require-jsdoc"
4+
* | "require-returns"
5+
* | "valid-types"
6+
* | "require-example"
7+
* | "check-examples"
8+
* )} RulesWithMovedSettings
9+
*/
10+
11+
/** @type {WeakMap<Object, Set<string>>} */
12+
const warnedSettings = new WeakMap();
13+
14+
/**
15+
* Warn only once for each context and setting
16+
*
17+
* @param {Object} context
18+
* @param {string} setting
19+
*/
20+
const hasBeenWarned = (context, setting) => {
21+
return warnedSettings.has(context) && warnedSettings.get(context).has(setting);
22+
};
23+
24+
const markSettingAsWarned = (context, setting) => {
25+
if (!warnedSettings.has(context)) {
26+
warnedSettings.set(context, new Set());
27+
}
28+
29+
warnedSettings.get(context).add(setting);
30+
};
31+
32+
/**
33+
* @param {Object} obj
34+
* @param {string} property
35+
* @returns {boolean}
36+
*/
37+
const has = (obj, property) => {
38+
return Object.prototype.hasOwnProperty.call(obj, property);
39+
};
40+
41+
/**
42+
*
43+
* @param {RulesWithMovedSettings} ruleName
44+
* @returns {string[]}
45+
*/
46+
const getMovedSettings = (ruleName) => {
47+
switch (ruleName) {
48+
case 'require-jsdoc':
49+
return ['exemptEmptyFunctions'];
50+
case 'require-returns':
51+
return ['forceRequireReturn'];
52+
case 'valid-types':
53+
return ['allowEmptyNamepaths', 'checkSeesForNamepaths'];
54+
case 'require-example':
55+
return ['avoidExampleOnConstructors'];
56+
57+
// TODO: move settings of check-examples to options
58+
/* istanbul ignore next */
59+
case 'check-examples':
60+
return [
61+
'captionRequired',
62+
'exampleCodeRegex',
63+
'rejectExampleCodeRegex',
64+
'allowInlineConfig',
65+
'noDefaultExampleRules',
66+
'matchingFileName',
67+
'configFile',
68+
'eslintrcForExamples',
69+
'baseConfig',
70+
'reportUnusedDisableDirectives'
71+
];
72+
}
73+
74+
/* istanbul ignore next */
75+
return [];
76+
};
77+
78+
/**
79+
* @param {Object} context
80+
* @param {RulesWithMovedSettings} ruleName
81+
*/
82+
export default function warnRemovedSettings (context, ruleName) {
83+
const movedSettings = getMovedSettings(ruleName);
84+
85+
if (!context.settings || !context.settings.jsdoc) {
86+
return;
87+
}
88+
89+
for (const setting of movedSettings) {
90+
if (
91+
has(context.settings.jsdoc, setting) &&
92+
!hasBeenWarned(context, setting)
93+
) {
94+
context.report({
95+
loc: {
96+
start: {
97+
column: 1,
98+
line: 1
99+
}
100+
},
101+
message: `\`settings.jsdoc.${setting}\` has been removed, ` +
102+
`use options in the rule \`${ruleName}\` instead.`
103+
});
104+
markSettingAsWarned(context, setting);
105+
}
106+
}
107+
}

test/rules/assertions/requireReturns.js

Lines changed: 56 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,29 @@ export default {
8585
}
8686
}
8787
},
88+
{
89+
code: `
90+
/**
91+
*
92+
*/
93+
function foo() {}
94+
95+
/**
96+
*
97+
*/
98+
function bar() {}
99+
`,
100+
errors: [
101+
{
102+
message: '`settings.jsdoc.forceRequireReturn` has been removed, use options in the rule `require-returns` instead.'
103+
}
104+
],
105+
settings: {
106+
jsdoc: {
107+
forceRequireReturn: true
108+
}
109+
}
110+
},
88111
{
89112
code: `
90113
/**
@@ -99,13 +122,11 @@ export default {
99122
message: 'Missing JSDoc @returns declaration.'
100123
}
101124
],
125+
options: [{
126+
forceRequireReturn: true
127+
}],
102128
parserOptions: {
103129
ecmaVersion: 8
104-
},
105-
settings: {
106-
jsdoc: {
107-
forceRequireReturn: true
108-
}
109130
}
110131
},
111132
{
@@ -121,13 +142,11 @@ export default {
121142
message: 'Missing JSDoc @returns declaration.'
122143
}
123144
],
145+
options: [{
146+
forceRequireReturn: true
147+
}],
124148
parserOptions: {
125149
ecmaVersion: 8
126-
},
127-
settings: {
128-
jsdoc: {
129-
forceRequireReturn: true
130-
}
131150
}
132151
},
133152
{
@@ -143,13 +162,11 @@ export default {
143162
message: 'Missing JSDoc @returns declaration.'
144163
}
145164
],
165+
options: [{
166+
forceRequireReturn: true
167+
}],
146168
parserOptions: {
147169
ecmaVersion: 8
148-
},
149-
settings: {
150-
jsdoc: {
151-
forceRequireReturn: true
152-
}
153170
}
154171
},
155172
{
@@ -165,13 +182,11 @@ export default {
165182
message: 'Missing JSDoc @returns declaration.'
166183
}
167184
],
185+
options: [{
186+
forceRequireReturn: true
187+
}],
168188
parserOptions: {
169189
ecmaVersion: 8
170-
},
171-
settings: {
172-
jsdoc: {
173-
forceRequireReturn: true
174-
}
175190
}
176191
},
177192
{
@@ -188,11 +203,9 @@ export default {
188203
message: 'Missing JSDoc @returns declaration.'
189204
}
190205
],
191-
settings: {
192-
jsdoc: {
193-
forceRequireReturn: true
194-
}
195-
}
206+
options: [{
207+
forceRequireReturn: true
208+
}]
196209
},
197210
{
198211
code: `
@@ -490,11 +503,9 @@ export default {
490503
}
491504
}
492505
`,
493-
settings: {
494-
jsdoc: {
495-
forceRequireReturn: true
496-
}
497-
}
506+
options: [{
507+
forceRequireReturn: true
508+
}]
498509
},
499510
{
500511
code: `
@@ -516,11 +527,9 @@ export default {
516527
function quux () {
517528
}
518529
`,
519-
settings: {
520-
jsdoc: {
521-
forceRequireReturn: true
522-
}
523-
}
530+
options: [{
531+
forceRequireReturn: true
532+
}]
524533
},
525534
{
526535
code: `
@@ -541,11 +550,9 @@ export default {
541550
return undefined;
542551
}
543552
`,
544-
settings: {
545-
jsdoc: {
546-
forceRequireReturn: true
547-
}
548-
}
553+
options: [{
554+
forceRequireReturn: true
555+
}]
549556
},
550557
{
551558
code: `
@@ -565,11 +572,9 @@ export default {
565572
function quux () {
566573
}
567574
`,
568-
settings: {
569-
jsdoc: {
570-
forceRequireReturn: true
571-
}
572-
}
575+
options: [{
576+
forceRequireReturn: true
577+
}]
573578
},
574579
{
575580
code: `
@@ -580,11 +585,9 @@ export default {
580585
return;
581586
}
582587
`,
583-
settings: {
584-
jsdoc: {
585-
forceRequireReturn: true
586-
}
587-
}
588+
options: [{
589+
forceRequireReturn: true
590+
}]
588591
},
589592
{
590593
code: `
@@ -602,13 +605,11 @@ export default {
602605
async function quux () {
603606
}
604607
`,
608+
options: [{
609+
forceRequireReturn: true
610+
}],
605611
parserOptions: {
606612
ecmaVersion: 8
607-
},
608-
settings: {
609-
jsdoc: {
610-
forceRequireReturn: true
611-
}
612613
}
613614
},
614615
{

0 commit comments

Comments
 (0)