Skip to content

Commit e9e78d3

Browse files
committed
refactor(iterateJsdoc): avoid building/passing in checkJsdoc when contexts is an object returned from returns
refactor(iterateJsdoc): throw if provided a bad iterator rule testing(iterateJsdoc): add testing file, checking basic arguments testing(require-param): add missing coverage (`augmentsExtendsReplacesDocs`)
1 parent 93dc649 commit e9e78d3

File tree

3 files changed

+186
-19
lines changed

3 files changed

+186
-19
lines changed

src/iterateJsdoc.js

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -277,9 +277,13 @@ export {
277277
* @param {{meta: any, returns?: any}} opts
278278
*/
279279
export default function iterateJsdoc (iterator, opts) {
280-
if (!opts.meta || !opts.meta.type || !['problem', 'suggestion', 'layout'].includes(opts.meta.type)) {
280+
const metaType = _.get(opts, 'meta.type');
281+
if (!metaType || !['problem', 'suggestion', 'layout'].includes(metaType)) {
281282
throw new TypeError('Rule must include `meta.type` option (with value "problem", "suggestion", or "layout")');
282283
}
284+
if (typeof iterator !== 'function' && (!opts || typeof opts.returns !== 'function')) {
285+
throw new TypeError('The iterator argument must be a function or an object with a `returns` method.');
286+
}
283287

284288
return {
285289
/**
@@ -296,6 +300,14 @@ export default function iterateJsdoc (iterator, opts) {
296300

297301
const settings = getSettings(context);
298302

303+
let contexts = opts.returns;
304+
if (typeof opts.returns === 'function') {
305+
contexts = opts.returns(context, sourceCode);
306+
}
307+
308+
if (!Array.isArray(contexts) && contexts) {
309+
return contexts;
310+
}
299311
const checkJsdoc = (node) => {
300312
const jsdocNode = getJSDocComment(sourceCode, node);
301313

@@ -364,27 +376,19 @@ export default function iterateJsdoc (iterator, opts) {
364376
utils
365377
});
366378
};
367-
368-
let contexts = opts.returns;
369-
if (typeof opts.returns === 'function') {
370-
contexts = opts.returns(context, sourceCode, checkJsdoc);
379+
if (!contexts) {
380+
return {
381+
ArrowFunctionExpression: checkJsdoc,
382+
FunctionDeclaration: checkJsdoc,
383+
FunctionExpression: checkJsdoc
384+
};
371385
}
372386

373-
if (Array.isArray(contexts)) {
374-
return contexts.reduce((obj, prop) => {
375-
obj[prop] = checkJsdoc;
387+
return contexts.reduce((obj, prop) => {
388+
obj[prop] = checkJsdoc;
376389

377-
return obj;
378-
}, {});
379-
} else if (contexts) {
380-
return contexts;
381-
}
382-
383-
return {
384-
ArrowFunctionExpression: checkJsdoc,
385-
FunctionDeclaration: checkJsdoc,
386-
FunctionExpression: checkJsdoc
387-
};
390+
return obj;
391+
}, {});
388392
},
389393
meta: opts.meta
390394
};

test/iterateJsdoc.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/* eslint-disable max-nested-callbacks */
2+
3+
import {
4+
expect
5+
} from 'chai';
6+
// eslint-disable-next-line import/no-named-default
7+
import {parseComment, default as iterateJsdoc} from '../src/iterateJsdoc';
8+
9+
describe('iterateJsdoc', () => {
10+
describe('constructor', () => {
11+
context('options', () => {
12+
it('throws with missing options', () => {
13+
expect(() => {
14+
iterateJsdoc(() => {});
15+
}).to.throw(TypeError);
16+
});
17+
});
18+
context('meta', () => {
19+
context('Invalid arguments', () => {
20+
context('Invalid iterator', () => {
21+
it('throws with missing function', () => {
22+
expect(() => {
23+
iterateJsdoc(undefined, {meta: {type: 'suggestion'}});
24+
}).to.throw(TypeError);
25+
});
26+
it('throws with object missing `returns` method', () => {
27+
expect(() => {
28+
iterateJsdoc({}, {meta: {type: 'suggestion'}});
29+
}).to.throw(TypeError);
30+
});
31+
});
32+
context('Invalid options', () => {
33+
it('throws with missing meta', () => {
34+
expect(() => {
35+
iterateJsdoc(() => {}, {});
36+
}).to.throw(TypeError);
37+
});
38+
it('throws with empty meta', () => {
39+
expect(() => {
40+
iterateJsdoc(() => {}, {meta: {}});
41+
}).to.throw(TypeError);
42+
});
43+
it('throws with bad type', () => {
44+
expect(() => {
45+
iterateJsdoc(() => {}, {meta: {type: 'bad'}});
46+
}).to.throw(TypeError);
47+
});
48+
});
49+
});
50+
context('Valid arguments', () => {
51+
it('Does not throw with function and options', () => {
52+
expect(() => {
53+
iterateJsdoc(() => {}, {meta: {type: 'suggestion'}});
54+
}).to.not.throw();
55+
});
56+
it('Does not throw with object and options', () => {
57+
expect(() => {
58+
iterateJsdoc(undefined, {
59+
meta: {type: 'suggestion'},
60+
returns () {
61+
return {};
62+
}
63+
});
64+
}).to.not.throw();
65+
});
66+
});
67+
});
68+
});
69+
describe('parseComment', () => {
70+
context('Parses comments', () => {
71+
it('', () => {
72+
expect(parseComment({value: `* SomeDescription
73+
@param {MyType} name desc
74+
`}, '')).to.deep.equal({
75+
description: 'SomeDescription',
76+
line: 0,
77+
source: 'SomeDescription\n@param {MyType} name desc',
78+
tags: [
79+
{
80+
description: 'desc',
81+
line: 1,
82+
name: 'name',
83+
optional: false,
84+
source: '@param {MyType} name desc',
85+
tag: 'param',
86+
type: 'MyType'
87+
}
88+
]
89+
});
90+
});
91+
});
92+
});
93+
});

test/rules/assertions/requireParam.js

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,36 @@ export default {
405405
}
406406
`
407407
},
408+
{
409+
code: `
410+
/**
411+
* @augments
412+
*/
413+
function quux (foo) {
414+
415+
}
416+
`,
417+
settings: {
418+
jsdoc: {
419+
augmentsExtendsReplacesDocs: true
420+
}
421+
}
422+
},
423+
{
424+
code: `
425+
/**
426+
* @extends
427+
*/
428+
function quux (foo) {
429+
430+
}
431+
`,
432+
settings: {
433+
jsdoc: {
434+
augmentsExtendsReplacesDocs: true
435+
}
436+
}
437+
},
408438
{
409439
code: `
410440
/**
@@ -545,6 +575,46 @@ export default {
545575
}
546576
`
547577
},
578+
{
579+
code: `
580+
/**
581+
* @augments
582+
*/
583+
class A {
584+
/**
585+
*
586+
*/
587+
quux (foo) {
588+
589+
}
590+
}
591+
`,
592+
settings: {
593+
jsdoc: {
594+
augmentsExtendsReplacesDocs: true
595+
}
596+
}
597+
},
598+
{
599+
code: `
600+
/**
601+
* @extends
602+
*/
603+
class A {
604+
/**
605+
*
606+
*/
607+
quux (foo) {
608+
609+
}
610+
}
611+
`,
612+
settings: {
613+
jsdoc: {
614+
augmentsExtendsReplacesDocs: true
615+
}
616+
}
617+
},
548618
{
549619
code: `
550620
/**

0 commit comments

Comments
 (0)