-
-
Notifications
You must be signed in to change notification settings - Fork 29
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add
require-meta-schema-description
rule (#490)
* feat: add require-meta-schema-description rule * Update lib/rules/require-meta-schema-description.js Co-authored-by: Brad Zacher <[email protected]> * Added tests too * recommended: false * Fill in test coverage * npm run update:eslint-docs --------- Co-authored-by: Brad Zacher <[email protected]>
- Loading branch information
1 parent
a3b3c05
commit 875200b
Showing
12 changed files
with
665 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
# Require rules `meta.schema` properties to include descriptions (`eslint-plugin/require-meta-schema-description`) | ||
|
||
<!-- end auto-generated rule header --> | ||
|
||
Defining a description in the schema for each rule option helps explain that option to users. | ||
It also allows documentation generators such as [`eslint-doc-generator`](https://github.com/bmish/eslint-doc-generator) to generate more informative documentation for users. | ||
|
||
## Rule Details | ||
|
||
This rule requires that if a rule option has a property in the rule's `meta.schema`, it should have a `description`. | ||
|
||
Examples of **incorrect** code for this rule: | ||
|
||
```js | ||
/* eslint eslint-plugin/require-meta-schema-description: error */ | ||
|
||
module.exports = { | ||
meta: { | ||
schema: [ | ||
{ | ||
elements: { type: 'string' }, | ||
type: 'array', | ||
}, | ||
], | ||
}, | ||
create() {}, | ||
}; | ||
|
||
module.exports = { | ||
meta: { | ||
schema: [ | ||
{ | ||
properties: { | ||
something: { | ||
type: 'string', | ||
}, | ||
}, | ||
type: 'object', | ||
}, | ||
], | ||
}, | ||
create() {}, | ||
}; | ||
``` | ||
|
||
Examples of **correct** code for this rule: | ||
|
||
```js | ||
/* eslint eslint-plugin/require-meta-schema-description: error */ | ||
|
||
module.exports = { | ||
meta: { | ||
schema: [ | ||
{ | ||
description: 'Elements to allow.', | ||
elements: { type: 'string' }, | ||
type: 'array', | ||
}, | ||
], | ||
}, | ||
create() {}, | ||
}; | ||
|
||
module.exports = { | ||
meta: { | ||
schema: [ | ||
{ | ||
oneOf: [ | ||
{ | ||
description: 'Elements to allow.', | ||
elements: { type: 'string' }, | ||
type: 'array', | ||
}, | ||
], | ||
}, | ||
], | ||
}, | ||
create() {}, | ||
}; | ||
``` | ||
|
||
## When Not To Use It | ||
|
||
If your rule options are very simple and well-named, and your rule isn't used by developers outside of your immediate team, you may not need this rule. | ||
|
||
## Further Reading | ||
|
||
- [working-with-rules#options-schemas](https://eslint.org/docs/developer-guide/working-with-rules#options-schemas) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
'use strict'; | ||
|
||
const { getStaticValue } = require('@eslint-community/eslint-utils'); | ||
const utils = require('../utils'); | ||
|
||
// ------------------------------------------------------------------------------ | ||
// Rule Definition | ||
// ------------------------------------------------------------------------------ | ||
|
||
/** @type {import('eslint').Rule.RuleModule} */ | ||
module.exports = { | ||
meta: { | ||
type: 'suggestion', | ||
docs: { | ||
description: | ||
'require rules `meta.schema` properties to include descriptions', | ||
category: 'Rules', | ||
recommended: false, | ||
url: 'https://github.com/eslint-community/eslint-plugin-eslint-plugin/tree/HEAD/docs/rules/require-meta-schema-description.md', | ||
}, | ||
schema: [], | ||
messages: { | ||
missingDescription: 'Schema option is missing an ajv description.', | ||
}, | ||
}, | ||
|
||
create(context) { | ||
const sourceCode = context.sourceCode || context.getSourceCode(); // TODO: just use context.sourceCode when dropping eslint < v9 | ||
const { scopeManager } = sourceCode; | ||
const ruleInfo = utils.getRuleInfo(sourceCode); | ||
if (!ruleInfo) { | ||
return {}; | ||
} | ||
|
||
const schemaNode = utils.getMetaSchemaNode(ruleInfo.meta, scopeManager); | ||
if (!schemaNode) { | ||
return {}; | ||
} | ||
|
||
const schemaProperty = utils.getMetaSchemaNodeProperty( | ||
schemaNode, | ||
scopeManager, | ||
); | ||
if (schemaProperty?.type !== 'ArrayExpression') { | ||
return {}; | ||
} | ||
|
||
for (const element of schemaProperty.elements) { | ||
checkSchemaElement(element, true); | ||
} | ||
|
||
return {}; | ||
|
||
function checkSchemaElement(node, isRoot) { | ||
if (node.type !== 'ObjectExpression') { | ||
return; | ||
} | ||
|
||
let hadChildren = false; | ||
let hadDescription = false; | ||
|
||
for (const { key, value } of node.properties) { | ||
const staticKey = | ||
key.type === 'Identifier' ? { value: key.name } : getStaticValue(key); | ||
if (!staticKey?.value) { | ||
continue; | ||
} | ||
|
||
switch (key.name ?? key.value) { | ||
case 'description': { | ||
hadDescription = true; | ||
break; | ||
} | ||
|
||
case 'oneOf': { | ||
hadChildren = true; | ||
|
||
if (value.type === 'ArrayExpression') { | ||
for (const element of value.elements) { | ||
checkSchemaElement(element, isRoot); | ||
} | ||
} | ||
|
||
break; | ||
} | ||
|
||
case 'properties': { | ||
hadChildren = true; | ||
|
||
for (const property of value.properties) { | ||
if (property.value?.type === 'ObjectExpression') { | ||
checkSchemaElement(property.value); | ||
} | ||
} | ||
|
||
break; | ||
} | ||
} | ||
} | ||
|
||
if (!hadDescription && !(hadChildren && isRoot)) { | ||
context.report({ | ||
messageId: 'missingDescription', | ||
node, | ||
}); | ||
} | ||
} | ||
}, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.