diff --git a/.README/README.md b/.README/README.md index f29314af7..05ee2ed8f 100644 --- a/.README/README.md +++ b/.README/README.md @@ -462,6 +462,12 @@ values are objects with the following optional properties: name (`@throws Some text`); does not require that both exist but disallows just an empty tag. +### `contexts` + +`settings.jsdoc.contexts` can be used as the default for any rules +with a `contexts` property option. See the "AST and Selectors" section +for more on this format. + ## Advanced ### AST and Selectors diff --git a/README.md b/README.md index 14ec55497..0abc9fe2e 100644 --- a/README.md +++ b/README.md @@ -21,6 +21,7 @@ JSDoc linting rules for ESLint. * [`@override`/`@augments`/`@extends`/`@implements`/`@ignore` Without Accompanying `@param`/`@description`/`@example`/`@returns`/`@throws`/`@yields`](#user-content-eslint-plugin-jsdoc-settings-override-augments-extends-implements-ignore-without-accompanying-param-description-example-returns-throws-yields) * [Settings to Configure `check-types` and `no-undefined-types`](#user-content-eslint-plugin-jsdoc-settings-settings-to-configure-check-types-and-no-undefined-types) * [`structuredTags`](#user-content-eslint-plugin-jsdoc-settings-structuredtags) + * [`contexts`](#user-content-eslint-plugin-jsdoc-settings-contexts) * [Advanced](#user-content-eslint-plugin-jsdoc-advanced) * [AST and Selectors](#user-content-eslint-plugin-jsdoc-advanced-ast-and-selectors) * [Rules](#user-content-eslint-plugin-jsdoc-rules) @@ -553,6 +554,14 @@ values are objects with the following optional properties: name (`@throws Some text`); does not require that both exist but disallows just an empty tag. + + +### contexts + +`settings.jsdoc.contexts` can be used as the default for any rules +with a `contexts` property option. See the "AST and Selectors" section +for more on this format. + ## Advanced @@ -6756,8 +6765,8 @@ function is adhering. #### Options - - + + ##### contexts Set this to an array of strings representing the AST context (or an object with @@ -7091,8 +7100,8 @@ You may also provide an object with `message`: } ``` - - + + ##### contexts Set this to an array of strings representing the AST context (or an object with @@ -8922,8 +8931,8 @@ the presence of ES6 default parameters (bearing in mind that such "defaults" are only applied when the supplied value is missing or `undefined` but not for `null` or other "falsey" values). - - + + ##### contexts Set this to an array of strings representing the AST context (or an object with @@ -9113,8 +9122,8 @@ not report if there were only a function declaration of the name "ignoreMe" #### Options - - + + ##### contexts Set this to an array of strings representing the AST context (or an object with @@ -9159,6 +9168,15 @@ function quux () { */ function quux () { +} +// Settings: {"jsdoc":{"contexts":[{"comment":"JsdocBlock[postDelimiter=\"\"]:has(JsdocTypeUnion > JsdocTypeName[value=\"Foo\"]:nth-child(1))","context":"FunctionDeclaration"}]}} +// Message: Syntax is required: FunctionDeclaration with JsdocBlock[postDelimiter=""]:has(JsdocTypeUnion > JsdocTypeName[value="Foo"]:nth-child(1)) + +/** + * @implements {Bar|Foo} + */ +function quux () { + } // "jsdoc/no-missing-syntax": ["error"|"warn", {"contexts":[{"comment":"JsdocBlock[postDelimiter=\"\"]:has(JsdocTypeUnion > JsdocTypeName[value=\"Bar\"]:nth-child(1))","context":"FunctionDeclaration"},{"comment":"JsdocBlock[postDelimiter=\"\"]:has(JsdocTypeUnion > JsdocTypeName[value=\"Foo\"]:nth-child(1))","context":"FunctionDeclaration"}]}] // Message: Syntax is required: FunctionDeclaration with JsdocBlock[postDelimiter=""]:has(JsdocTypeUnion > JsdocTypeName[value="Foo"]:nth-child(1)) @@ -9206,7 +9224,7 @@ function quux () { function quux () { } -// Message: Rule `no-missing-syntax` is missing a `context` option. +// Message: Rule `no-missing-syntax` is missing a `contexts` option. /** * @implements {Bar|Foo} @@ -9590,8 +9608,8 @@ is designed to do), you can just use ESLint's rule. #### Options - - + + ##### contexts Set this to an array of strings representing the AST context (or an object with @@ -9669,7 +9687,16 @@ function quux () { function quux () { } -// Message: Rule `no-restricted-syntax` is missing a `context` option. +// Message: Rule `no-restricted-syntax` is missing a `contexts` option. + +/** + * @implements {Bar|Foo} + */ +function quux () { + +} +// Settings: {"jsdoc":{"contexts":["FunctionDeclaration"]}} +// Message: Rule `no-restricted-syntax` is missing a `contexts` option. /** * @param opt_a @@ -9911,8 +9938,8 @@ the type information would be redundant with TypeScript. #### Options - - + + ##### contexts Set this to an array of strings representing the AST context (or an object with @@ -11922,6 +11949,16 @@ class quux { // "jsdoc/require-description": ["error"|"warn", {"contexts":["ClassDeclaration"],"descriptionStyle":"tag"}] // Message: Missing JSDoc @description declaration. +/** + * + */ +class quux { + +} +// Settings: {"jsdoc":{"contexts":["ClassDeclaration"]}} +// "jsdoc/require-description": ["error"|"warn", {"descriptionStyle":"tag"}] +// Message: Missing JSDoc @description declaration. + /** * */ @@ -12406,8 +12443,8 @@ exemption of the rule. Boolean to indicate that no-argument functions should not be reported for missing `@example` declarations. - - + + ##### contexts Set this to an array of strings representing the AST context (or an object with @@ -13311,8 +13348,8 @@ An object with the following optional boolean keys which all default to - `FunctionExpression` - `MethodDefinition` - - + + ##### contexts Set this to an array of strings or objects representing the additional AST @@ -13512,6 +13549,13 @@ export const test = () => { export const test = () => { +}; +// Settings: {"jsdoc":{"contexts":["ArrowFunctionExpression"]}} +// "jsdoc/require-jsdoc": ["error"|"warn", {"publicOnly":true}] +// Message: Missing JSDoc comment. + +export const test = () => { + }; // "jsdoc/require-jsdoc": ["error"|"warn", {"contexts":[{"context":"ArrowFunctionExpression"}],"publicOnly":true}] // Message: Missing JSDoc comment. @@ -15091,8 +15135,8 @@ string. Defaults to `false`. The description string to set by default for destructured roots. Defaults to "The root object". - - + + ##### contexts Set this to an array of strings representing the AST context (or an object with @@ -15289,8 +15333,8 @@ Requires that all function parameters have names. #### Options - - + + ##### contexts Set this to an array of strings representing the AST context (or an object with @@ -15449,8 +15493,8 @@ object. Uses `defaultDestructuredRootType` for the type string. Defaults to The type string to set by default for destructured roots. Defaults to "object". - - + + ##### contexts Set this to an array of strings representing the AST context (or an object with @@ -15977,8 +16021,8 @@ You could set this regular expression to a more expansive list, or you could restrict it such that even types matching those strings would not need destructuring. - - + + ##### contexts Set this to an array of strings representing the AST context (or an object with @@ -18746,8 +18790,8 @@ or if it is `Promise` or `Promise`. #### Options - - + + ##### contexts Set this to an array of strings representing the AST context (or an object with @@ -18905,8 +18949,8 @@ Requires that `@returns` tag has `type` value. #### Options - - + + ##### contexts Set this to an array of strings representing the AST context (or an object with diff --git a/src/iterateJsdoc.js b/src/iterateJsdoc.js index 7b3ebcdce..57ffbd343 100644 --- a/src/iterateJsdoc.js +++ b/src/iterateJsdoc.js @@ -873,6 +873,9 @@ const getSettings = (context) => { // Many rules, e.g., `check-tag-names` mode: context.settings.jsdoc?.mode ?? (context.parserPath.includes('@typescript-eslint') ? 'typescript' : 'jsdoc'), + + // Many rules + contexts: context.settings.jsdoc?.contexts, }; /* eslint-enable canonical/sort-keys */ @@ -1176,6 +1179,7 @@ const iterateAllJsdocs = (iterator, ruleConfig, contexts, additiveCommentContext if (lastCall && ruleConfig.exit) { ruleConfig.exit({ context, + settings, state, utils, }); @@ -1323,7 +1327,7 @@ export default function iterateJsdoc (iterator, ruleConfig) { if (ruleConfig.contextDefaults || ruleConfig.contextSelected || ruleConfig.matchContext) { contexts = ruleConfig.matchContext && context.options[0]?.match ? context.options[0].match : - jsdocUtils.enforcedContexts(context, ruleConfig.contextDefaults); + jsdocUtils.enforcedContexts(context, ruleConfig.contextDefaults, ruleConfig.nonGlobalSettings ? {} : settings); if (contexts) { contexts = contexts.map((obj) => { @@ -1410,6 +1414,7 @@ export default function iterateJsdoc (iterator, ruleConfig) { contextObject['Program:exit'] = () => { ruleConfig.exit({ context, + settings, state, }); }; diff --git a/src/jsdocUtils.js b/src/jsdocUtils.js index 3873c89e3..b9e3bc5f7 100644 --- a/src/jsdocUtils.js +++ b/src/jsdocUtils.js @@ -997,17 +997,16 @@ const parseClosureTemplateTag = (tag) => { * * @param {*} context * @param {DefaultContexts} defaultContexts + * @param settings * @returns {string[]} */ -const enforcedContexts = (context, defaultContexts) => { - const { - contexts = defaultContexts === true ? [ - 'ArrowFunctionExpression', - 'FunctionDeclaration', - 'FunctionExpression', - 'TSDeclareFunction', - ] : defaultContexts, - } = context.options[0] || {}; +const enforcedContexts = (context, defaultContexts, settings) => { + const contexts = context.options[0]?.contexts || settings.contexts || (defaultContexts === true ? [ + 'ArrowFunctionExpression', + 'FunctionDeclaration', + 'FunctionExpression', + 'TSDeclareFunction', + ] : defaultContexts); return contexts; }; diff --git a/src/rules/noMissingSyntax.js b/src/rules/noMissingSyntax.js index e217d7877..a889812fe 100644 --- a/src/rules/noMissingSyntax.js +++ b/src/rules/noMissingSyntax.js @@ -59,9 +59,10 @@ export default iterateJsdoc(({ contextSelected: true, exit ({ context, + settings, state, }) { - if (!context.options.length) { + if (!context.options.length && !settings.contexts) { context.report({ loc: { start: { @@ -69,17 +70,16 @@ export default iterateJsdoc(({ line: 1, }, }, - message: 'Rule `no-missing-syntax` is missing a `context` option.', + message: 'Rule `no-missing-syntax` is missing a `contexts` option.', }); return; } setDefaults(state); - const { - contexts, - } = context.options[0]; + contexts = settings?.contexts, + } = context.options[0] || {}; // Report when MISSING contexts.some((cntxt) => { diff --git a/src/rules/noRestrictedSyntax.js b/src/rules/noRestrictedSyntax.js index fedbdffd5..a92358a71 100644 --- a/src/rules/noRestrictedSyntax.js +++ b/src/rules/noRestrictedSyntax.js @@ -11,7 +11,7 @@ export default iterateJsdoc(({ report, }) => { if (!context.options.length) { - report('Rule `no-restricted-syntax` is missing a `context` option.'); + report('Rule `no-restricted-syntax` is missing a `contexts` option.'); return; } @@ -94,4 +94,5 @@ export default iterateJsdoc(({ ], type: 'suggestion', }, + nonGlobalSettings: true, }); diff --git a/src/rules/requireJsdoc.js b/src/rules/requireJsdoc.js index a92e9d201..a60eed55d 100644 --- a/src/rules/requireJsdoc.js +++ b/src/rules/requireJsdoc.js @@ -162,10 +162,10 @@ const getOption = (context, baseObject, option, key) => { return baseObject.properties[key].default; }; -const getOptions = (context) => { +const getOptions = (context, settings) => { const { publicOnly, - contexts = [], + contexts = settings.contexts || [], exemptEmptyConstructors = true, exemptEmptyFunctions = false, enableFixer = true, @@ -222,7 +222,7 @@ export default { enableFixer, fixerMessage, minLineCount, - } = getOptions(context); + } = getOptions(context, settings); const checkJsDoc = (info, handler, node) => { if ( @@ -363,7 +363,7 @@ export default { return { ...jsdocUtils.getContextObject( - jsdocUtils.enforcedContexts(context, []), + jsdocUtils.enforcedContexts(context, [], settings), checkJsDoc, ), ArrowFunctionExpression (node) { diff --git a/test/rules/assertions/noMissingSyntax.js b/test/rules/assertions/noMissingSyntax.js index 2f574192f..7baa30444 100644 --- a/test/rules/assertions/noMissingSyntax.js +++ b/test/rules/assertions/noMissingSyntax.js @@ -34,6 +34,33 @@ export default { */ function quux () { + } + `, + errors: [ + { + line: 1, + message: 'Syntax is required: FunctionDeclaration with ' + + 'JsdocBlock[postDelimiter=""]:has(JsdocTypeUnion > JsdocTypeName[value="Foo"]:nth-child(1))', + }, + ], + settings: { + jsdoc: { + contexts: [ + { + comment: 'JsdocBlock[postDelimiter=""]:has(JsdocTypeUnion > JsdocTypeName[value="Foo"]:nth-child(1))', + context: 'FunctionDeclaration', + }, + ], + }, + }, + }, + { + code: ` + /** + * @implements {Bar|Foo} + */ + function quux () { + } `, errors: [ @@ -186,7 +213,7 @@ export default { errors: [ { line: 1, - message: 'Rule `no-missing-syntax` is missing a `context` option.', + message: 'Rule `no-missing-syntax` is missing a `contexts` option.', }, ], }, diff --git a/test/rules/assertions/noRestrictedSyntax.js b/test/rules/assertions/noRestrictedSyntax.js index 70e8c45f4..157b5510c 100644 --- a/test/rules/assertions/noRestrictedSyntax.js +++ b/test/rules/assertions/noRestrictedSyntax.js @@ -151,10 +151,33 @@ export default { errors: [ { line: 2, - message: 'Rule `no-restricted-syntax` is missing a `context` option.', + message: 'Rule `no-restricted-syntax` is missing a `contexts` option.', }, ], }, + { + code: ` + /** + * @implements {Bar|Foo} + */ + function quux () { + + } + `, + errors: [ + { + line: 2, + message: 'Rule `no-restricted-syntax` is missing a `contexts` option.', + }, + ], + settings: { + jsdoc: { + contexts: [ + 'FunctionDeclaration', + ], + }, + }, + }, { code: ` /** diff --git a/test/rules/assertions/requireDescription.js b/test/rules/assertions/requireDescription.js index f25fd45bb..a1ed81120 100644 --- a/test/rules/assertions/requireDescription.js +++ b/test/rules/assertions/requireDescription.js @@ -129,6 +129,34 @@ export default { }, ], }, + { + code: ` + /** + * + */ + class quux { + + } + `, + errors: [ + { + line: 2, + message: 'Missing JSDoc @description declaration.', + }, + ], + options: [ + { + descriptionStyle: 'tag', + }, + ], + settings: { + jsdoc: { + contexts: [ + 'ClassDeclaration', + ], + }, + }, + }, { code: ` /** diff --git a/test/rules/assertions/requireJsdoc.js b/test/rules/assertions/requireJsdoc.js index f9ebe4445..3d64cf96d 100644 --- a/test/rules/assertions/requireJsdoc.js +++ b/test/rules/assertions/requireJsdoc.js @@ -506,6 +506,43 @@ function quux (foo) { type: 'ArrowFunctionExpression', }, ], + options: [ + { + publicOnly: true, + }, + ], + output: ` + /** + * + */ + export const test = () => { + + }; + `, + parserOptions: { + sourceType: 'module', + }, + settings: { + jsdoc: { + contexts: [ + 'ArrowFunctionExpression', + ], + }, + }, + }, + { + code: ` + export const test = () => { + + }; + `, + errors: [ + { + line: 2, + message: 'Missing JSDoc comment.', + type: 'ArrowFunctionExpression', + }, + ], options: [ { contexts: [