diff --git a/.README/README.md b/.README/README.md
index d4902aa25..9be098081 100644
--- a/.README/README.md
+++ b/.README/README.md
@@ -199,6 +199,8 @@ Or one may set the targeted tag to an object with a custom `message`, but withou
}
```
+Note that the preferred tags indicated in the `settings.jsdoc.tagNamePreference`
+map will be assumed to be defined by `check-tag-names`.
The defaults in `eslint-plugin-jsdoc` (for tags which offer
aliases) are as follows:
@@ -236,24 +238,6 @@ This setting is utilized by the the rule for tag name checking
- `require-returns-description`
- `require-returns-type`
-### Additional Tag Names
-
-Use `settings.jsdoc.additionalTagNames` to configure additional, allowed JSDoc
-tags in the rule `check-tag-names`. The format of the configuration is as follows:
-
-```json
-{
- "rules": {},
- "settings": {
- "jsdoc": {
- "additionalTagNames": {
- "customTags": ["define", "record"]
- }
- }
- }
-}
-```
-
### `@override`/`@augments`/`@extends`/`@implements` Without Accompanying `@param`/`@description`/`@example`/`@returns`
The following settings allows the element(s) they reference to be omitted
diff --git a/.README/rules/check-tag-names.md b/.README/rules/check-tag-names.md
index 23162ac36..c896ae027 100644
--- a/.README/rules/check-tag-names.md
+++ b/.README/rules/check-tag-names.md
@@ -75,10 +75,26 @@ version
yields
```
+Note that the tags indicated as replacements in `settings.jsdoc.tagNamePreference` will automatically be considered as valid.
+
+#### Options
+
+##### `definedTags`
+
+Use an array of `definedTags` strings to configure additional, allowed JSDoc tags.
+The format is as follows:
+
+```json
+{
+ "definedTags": ["define", "record"]
+}
+```
+
|||
|---|---|
|Context|everywhere|
|Tags|N/A|
-|Settings|`tagNamePreference`, `additionalTagNames`|
+|Options|`definedTags`|
+|Settings|`tagNamePreference`|
diff --git a/README.md b/README.md
index 7d6e8f32b..fb9db051a 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,6 @@ JSDoc linting rules for ESLint.
* [Allow `@private` to disable rules for that comment block](#eslint-plugin-jsdoc-settings-allow-private-to-disable-rules-for-that-comment-block)
* [Exempting empty functions from `require-jsdoc`](#eslint-plugin-jsdoc-settings-exempting-empty-functions-from-require-jsdoc)
* [Alias Preference](#eslint-plugin-jsdoc-settings-alias-preference)
- * [Additional Tag Names](#eslint-plugin-jsdoc-settings-additional-tag-names)
* [`@override`/`@augments`/`@extends`/`@implements` Without Accompanying `@param`/`@description`/`@example`/`@returns`](#eslint-plugin-jsdoc-settings-override-augments-extends-implements-without-accompanying-param-description-example-returns)
* [Settings to Configure `check-types` and `no-undefined-types`](#eslint-plugin-jsdoc-settings-settings-to-configure-check-types-and-no-undefined-types)
* [Settings to Configure `valid-types`](#eslint-plugin-jsdoc-settings-settings-to-configure-valid-types)
@@ -249,6 +248,8 @@ Or one may set the targeted tag to an object with a custom `message`, but withou
}
```
+Note that the preferred tags indicated in the `settings.jsdoc.tagNamePreference`
+map will be assumed to be defined by `check-tag-names`.
The defaults in `eslint-plugin-jsdoc` (for tags which offer
aliases) are as follows:
@@ -286,25 +287,6 @@ This setting is utilized by the the rule for tag name checking
- `require-returns-description`
- `require-returns-type`
-
-### Additional Tag Names
-
-Use `settings.jsdoc.additionalTagNames` to configure additional, allowed JSDoc
-tags in the rule `check-tag-names`. The format of the configuration is as follows:
-
-```json
-{
- "rules": {},
- "settings": {
- "jsdoc": {
- "additionalTagNames": {
- "customTags": ["define", "record"]
- }
- }
- }
-}
-```
-
### @override
/@augments
/@extends
/@implements
Without Accompanying @param
/@description
/@example
/@returns
@@ -1249,11 +1231,29 @@ version
yields
```
+Note that the tags indicated as replacements in `settings.jsdoc.tagNamePreference` will automatically be considered as valid.
+
+
+#### Options
+
+
+##### definedTags
+
+Use an array of `definedTags` strings to configure additional, allowed JSDoc tags.
+The format is as follows:
+
+```json
+{
+ "definedTags": ["define", "record"]
+}
+```
+
|||
|---|---|
|Context|everywhere|
|Tags|N/A|
-|Settings|`tagNamePreference`, `additionalTagNames`|
+|Options|`definedTags`|
+|Settings|`tagNamePreference`|
The following patterns are considered problems:
@@ -1327,7 +1327,7 @@ function quux (foo) {
function quux (foo) {
}
-// Settings: {"jsdoc":{"additionalTagNames":{"customTags":["bar"]}}}
+// Options: [{"definedTags":["bar"]}]
// Message: Invalid JSDoc tag name "baz".
/**
@@ -1337,7 +1337,7 @@ function quux (foo) {
function quux (foo) {
}
-// Settings: {"jsdoc":{"additionalTagNames":{"customTags":["bar"]}}}
+// Options: [{"definedTags":["bar"]}]
// Message: Invalid JSDoc tag name "baz".
/**
@@ -1375,6 +1375,15 @@ function quux () {
}
// Settings: {"jsdoc":{"tagNamePreference":{"todo":{"message":"Please use x-todo instead of todo","replacement":"x-todo"}}}}
// Message: Please use x-todo instead of todo
+
+/**
+ * @todo
+ */
+function quux () {
+
+}
+// Settings: {"jsdoc":{"tagNamePreference":{"todo":55}}}
+// Message: Invalid `settings.jsdoc.tagNamePreference`. Values must be falsy, a string, or an object.
````
The following patterns are not considered problems:
@@ -1408,7 +1417,15 @@ function quux (foo) {
function quux (foo) {
}
-// Settings: {"jsdoc":{"additionalTagNames":{"customTags":["bar"]}}}
+// Options: [{"definedTags":["bar"]}]
+
+/**
+ * @baz @bar foo
+ */
+function quux (foo) {
+
+}
+// Options: [{"definedTags":["baz","bar"]}]
/**
* @baz @bar foo
@@ -1416,7 +1433,7 @@ function quux (foo) {
function quux (foo) {
}
-// Settings: {"jsdoc":{"additionalTagNames":{"customTags":["baz","bar"]}}}
+// Settings: {"jsdoc":{"tagNamePreference":{"param":"baz","returns":{"message":"Prefer `bar`","replacement":"bar"},"todo":false}}}
/**
* @abstract
@@ -1521,7 +1538,7 @@ Date
RegExp
```
-
+
#### Options
`check-types` allows one option:
@@ -2402,10 +2419,10 @@ by our supported Node versions):
``^([A-Z]|[`\\d_])[\\s\\S]*[.?!`]$``
-
+
#### Options
-
+
##### matchDescription
You can supply your own expression to override the default, passing a
@@ -2420,7 +2437,7 @@ You can supply your own expression to override the default, passing a
As with the default, the supplied regular expression will be applied with the
Unicode (`"u"`) flag and is *not* case-insensitive.
-
+
##### tags
If you want different regular expressions to apply to tags, you may use
@@ -2447,7 +2464,7 @@ tag should be linted with the `matchDescription` value (or the default).
}
```
-
+
##### mainDescription
If you wish to override the main function description without changing the
@@ -2469,7 +2486,7 @@ There is no need to add `mainDescription: true`, as by default, the main
function (and only the main function) is linted, though you may disable checking
it by setting it to `false`.
-
+
##### contexts
Set this to an array of strings representing the AST context
@@ -2915,7 +2932,7 @@ const q = {
Enforces a consistent padding of the block description.
-
+
#### Options
This rule allows one optional string argument. If it is `"always"` then a problem is raised when there is a newline after the description. If it is `"never"` then a problem is raised when there is no newline after the description. The default value is `"always"`.
@@ -3075,7 +3092,7 @@ The following types are always considered defined.
- `any`, `*`
- `Array`, `Object`, `RegExp`, `Date`, `Function`
-
+
#### Options
An option object may have the following keys:
@@ -3671,7 +3688,7 @@ Requires that all functions have a description.
* All functions must have a `@description` tag.
* Every description tag must have a non-empty description that explains the purpose of the method.
-
+
#### Options
An options object may have any of the following properties:
@@ -3865,7 +3882,7 @@ Requires that all functions have examples.
* All functions must have one or more `@example` tags.
* Every example tag must have a non-empty description that explains the method's usage.
-
+
#### Options
Has an object option with one optional property:
@@ -3996,7 +4013,7 @@ function quux () {
Requires a hyphen before the `@param` description.
-
+
#### Options
This rule takes one optional string argument. If it is `"always"` then a problem is raised when there is no hyphen before the description. If it is `"never"` then a problem is raised when there is a hyphen before the description. The default value is `"always"`.
@@ -4102,7 +4119,7 @@ function quux () {
Checks for presence of jsdoc comments, on class declarations as well as
functions.
-
+
#### Options
Accepts one optional options object with the following optional keys.
@@ -5138,7 +5155,7 @@ function quux (foo) {
Requires that all function parameters are documented.
-
+
#### Options
An options object accepts one optional property:
@@ -6065,7 +6082,7 @@ function quux () {
Requires returns are documented.
-
+
#### Options
- `exemptedBy` - Array of tags (e.g., `['type']`) whose presence on the document
diff --git a/src/iterateJsdoc.js b/src/iterateJsdoc.js
index 7affb6be9..bc43a4bbb 100644
--- a/src/iterateJsdoc.js
+++ b/src/iterateJsdoc.js
@@ -28,7 +28,6 @@ const getUtils = (
jsdocNode,
{
tagNamePreference,
- additionalTagNames,
allowEmptyNamepaths,
overrideReplacesDocs,
implementsReplacesDocs,
@@ -89,8 +88,8 @@ const getUtils = (
return isObject && !allowObjectReturn ? ret.replacement : ret;
};
- utils.isValidTag = (name) => {
- return jsdocUtils.isValidTag(name, additionalTagNames);
+ utils.isValidTag = (name, definedTags) => {
+ return jsdocUtils.isValidTag(name, definedTags);
};
utils.hasATag = (name) => {
@@ -261,9 +260,6 @@ const getSettings = (context) => {
settings.implementsReplacesDocs = _.get(context, 'settings.jsdoc.implementsReplacesDocs');
settings.augmentsExtendsReplacesDocs = _.get(context, 'settings.jsdoc.augmentsExtendsReplacesDocs');
- // `check-tag-names` only
- settings.additionalTagNames = _.get(context, 'settings.jsdoc.additionalTagNames') || {};
-
// `check-examples` only
settings.exampleCodeRegex = _.get(context, 'settings.jsdoc.exampleCodeRegex') || null;
settings.rejectExampleCodeRegex = _.get(context, 'settings.jsdoc.rejectExampleCodeRegex') || null;
diff --git a/src/jsdocUtils.js b/src/jsdocUtils.js
index b77321912..b421e5d86 100644
--- a/src/jsdocUtils.js
+++ b/src/jsdocUtils.js
@@ -79,9 +79,9 @@ const getPreferredTagName = (name : string, tagPreference : Object = {}) : strin
return name;
};
-const isValidTag = (name : string, additionalTagNames : Object) : boolean => {
+const isValidTag = (name : string, definedTags : Array) : boolean => {
const validTagNames = _.keys(tagNames).concat(_.flatten(_.values(tagNames)));
- const additionalTags = additionalTagNames.customTags || [];
+ const additionalTags = definedTags;
const allTags = validTagNames.concat(additionalTags);
return allTags.includes(name);
diff --git a/src/rules/checkTagNames.js b/src/rules/checkTagNames.js
index c6489504c..e9afdc12d 100644
--- a/src/rules/checkTagNames.js
+++ b/src/rules/checkTagNames.js
@@ -1,3 +1,4 @@
+import _ from 'lodash';
import iterateJsdoc from '../iterateJsdoc';
export default iterateJsdoc(({
@@ -5,14 +6,41 @@ export default iterateJsdoc(({
jsdoc,
report,
utils,
+ context,
jsdocNode
}) => {
if (!jsdoc.tags) {
return;
}
+ const {definedTags = []} = context.options[0] || {};
+
+ let definedPreferredTags = [];
+ const preferredTags = _.get(context, 'settings.jsdoc.tagNamePreference');
+ if (preferredTags) {
+ // Replace `_.values` with `Object.values` when we may start requiring Node 7+
+ definedPreferredTags = _.values(preferredTags).map((preferredTag) => {
+ if (typeof preferredTag === 'string') {
+ // May become an empty string but will be filtered out below
+ return preferredTag;
+ }
+ if (!preferredTag) {
+ return undefined;
+ }
+ if (typeof preferredTag !== 'object') {
+ report(
+ 'Invalid `settings.jsdoc.tagNamePreference`. Values must be falsy, a string, or an object.'
+ );
+ }
+
+ return preferredTag.replacement;
+ }).filter((preferredType) => {
+ return preferredType;
+ });
+ }
+
jsdoc.tags.forEach((jsdocTag) => {
const tagName = jsdocTag.tag;
- if (utils.isValidTag(tagName)) {
+ if (utils.isValidTag(tagName, [...definedTags, ...definedPreferredTags])) {
let preferredTagName = utils.getPreferredTagName(
tagName,
true,
@@ -41,6 +69,20 @@ export default iterateJsdoc(({
iterateAllJsdocs: true,
meta: {
fixable: 'code',
+ schema: [
+ {
+ additionalProperties: false,
+ properties: {
+ definedTags: {
+ items: {
+ type: 'string'
+ },
+ type: 'array'
+ }
+ },
+ type: 'object'
+ }
+ ],
type: 'suggestion'
}
});
diff --git a/test/jsdocUtils.js b/test/jsdocUtils.js
index 6dec68ed9..30119f25c 100644
--- a/test/jsdocUtils.js
+++ b/test/jsdocUtils.js
@@ -26,22 +26,22 @@ describe('jsdocUtils', () => {
describe('isValidTag()', () => {
context('tag is invalid', () => {
it('returns false', () => {
- expect(jsdocUtils.isValidTag('foo', {})).to.equal(false);
+ expect(jsdocUtils.isValidTag('foo', [])).to.equal(false);
});
});
context('tag is valid', () => {
it('returns true', () => {
- expect(jsdocUtils.isValidTag('param', {})).to.equal(true);
+ expect(jsdocUtils.isValidTag('param', [])).to.equal(true);
});
});
context('tag is valid alias', () => {
it('returns true', () => {
- expect(jsdocUtils.isValidTag('arg', {})).to.equal(true);
+ expect(jsdocUtils.isValidTag('arg', [])).to.equal(true);
});
});
context('tag is valid and customized', () => {
it('returns true', () => {
- expect(jsdocUtils.isValidTag('foobar', {customTags: ['foobar']})).to.equal(true);
+ expect(jsdocUtils.isValidTag('foobar', ['foobar'])).to.equal(true);
});
});
});
diff --git a/test/rules/assertions/checkTagNames.js b/test/rules/assertions/checkTagNames.js
index 261d83678..820e8851a 100644
--- a/test/rules/assertions/checkTagNames.js
+++ b/test/rules/assertions/checkTagNames.js
@@ -164,13 +164,9 @@ export default {
message: 'Invalid JSDoc tag name "baz".'
}
],
- settings: {
- jsdoc: {
- additionalTagNames: {
- customTags: ['bar']
- }
- }
- }
+ options: [{
+ definedTags: ['bar']
+ }]
},
{
code: `
@@ -188,13 +184,9 @@ export default {
message: 'Invalid JSDoc tag name "baz".'
}
],
- settings: {
- jsdoc: {
- additionalTagNames: {
- customTags: ['bar']
- }
- }
- }
+ options: [{
+ definedTags: ['bar']
+ }]
},
{
code: `
@@ -291,6 +283,31 @@ export default {
}
}
}
+ },
+ {
+ code: `
+ /**
+ * @todo
+ */
+ function quux () {
+
+ }
+ `,
+ errors: [
+ {
+ message: 'Invalid `settings.jsdoc.tagNamePreference`. Values must be falsy, a string, or an object.'
+ },
+ {
+ message: 'Invalid JSDoc tag (preference). Replace "todo" JSDoc tag with "55".'
+ }
+ ],
+ settings: {
+ jsdoc: {
+ tagNamePreference: {
+ todo: 55
+ }
+ }
+ }
}
],
valid: [
@@ -340,13 +357,22 @@ export default {
}
`,
- settings: {
- jsdoc: {
- additionalTagNames: {
- customTags: ['bar']
+ options: [{
+ definedTags: ['bar']
+ }]
+ },
+ {
+ code: `
+ /**
+ * @baz @bar foo
+ */
+ function quux (foo) {
+
}
- }
- }
+ `,
+ options: [{
+ definedTags: ['baz', 'bar']
+ }]
},
{
code: `
@@ -359,8 +385,13 @@ export default {
`,
settings: {
jsdoc: {
- additionalTagNames: {
- customTags: ['baz', 'bar']
+ tagNamePreference: {
+ param: 'baz',
+ returns: {
+ message: 'Prefer `bar`',
+ replacement: 'bar'
+ },
+ todo: false
}
}
}