Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support ESLint 8.x #792

Merged
merged 13 commits into from Oct 23, 2021
3 changes: 3 additions & 0 deletions .README/rules/check-examples.md
@@ -1,5 +1,8 @@
### `check-examples`

> **NOTE**: This rule currently does not work in ESLint 8 (we are waiting for
> [issue 14745](https://github.com/eslint/eslint/issues/14745)).

Ensures that (JavaScript) examples within JSDoc adhere to ESLint rules. Also
has options to lint the default values of optional `@param`/`@arg`/`@argument`
and `@property`/`@prop` tags or the values of `@default`/`@defaultvalue` tags.
Expand Down
23 changes: 6 additions & 17 deletions .travis.yml
Expand Up @@ -9,37 +9,26 @@ node_js:

before_install:
- npm config set depth 0
install:
- echo "Avoid Travis's npm auto-install"
before_script: >
node_version=$(node -v);
if [ ${node_version:3:1} = "." ]; then
echo "Node 10+"
if [ ${ESLINT} = "6" ]; then
npm install --legacy-peer-deps --no-save "eslint@${ESLINT}" eslint-config-canonical@24.4.4
else
npm install --legacy-peer-deps --no-save "eslint@${ESLINT}"
fi
else
echo "Node 8+"
npm install --legacy-peer-deps --no-save "eslint@${ESLINT}" husky@3.1.0 semantic-release@15.14.0 eslint-config-canonical@18.1.1
fi
npm install --legacy-peer-deps --no-save "eslint@${ESLINT}"
notifications:
email: false
script:
- npm run test
- 'if [ -n "${LINT-}" ]; then npm run lint; fi'
# Disable until eslint-config-canonical fixed
# - 'if [ -n "${LINT-}" ]; then npm run lint; fi'
- npm run build
env:
jobs:
- ESLINT=8
- ESLINT=7
- ESLINT=6
jobs:
fast_finish: true
include:
- node_js: 'lts/*'
env: LINT=true
exclude:
- node_js: 8
env: ESLINT=7
after_success:
- export NODE_ENV=production
- npm run build
Expand Down
17 changes: 13 additions & 4 deletions README.md
Expand Up @@ -945,6 +945,9 @@ function quux (foo) {
<a name="eslint-plugin-jsdoc-rules-check-examples"></a>
### <code>check-examples</code>

> **NOTE**: This rule currently does not work in ESLint 8 (we are waiting for
> [issue 14745](https://github.com/eslint/eslint/issues/14745)).

Ensures that (JavaScript) examples within JSDoc adhere to ESLint rules. Also
has options to lint the default values of optional `@param`/`@arg`/`@argument`
and `@property`/`@prop` tags or the values of `@default`/`@defaultvalue` tags.
Expand Down Expand Up @@ -6914,7 +6917,7 @@ class MyClass {
*/
myClassField = 1
}
// "jsdoc/match-description": ["error"|"warn", {"contexts":["ClassProperty"]}]
// "jsdoc/match-description": ["error"|"warn", {"contexts":["PropertyDefinition"]}]
// Message: JSDoc description does not satisfy the regex pattern.

/**
Expand Down Expand Up @@ -7182,7 +7185,7 @@ class MyClass {
*/
myClassField = 1
}
// "jsdoc/match-description": ["error"|"warn", {"contexts":["ClassProperty"]}]
// "jsdoc/match-description": ["error"|"warn", {"contexts":["PropertyDefinition"]}]

/**
* Foo.
Expand Down Expand Up @@ -12813,7 +12816,7 @@ class Animal {
@SomeAnnotation('optionalParameter')
tail: boolean;
}
// "jsdoc/require-jsdoc": ["error"|"warn", {"contexts":["ClassProperty"]}]
// "jsdoc/require-jsdoc": ["error"|"warn", {"contexts":["PropertyDefinition"]}]
// Message: Missing JSDoc comment.

@Entity('users')
Expand Down Expand Up @@ -12907,7 +12910,7 @@ export class MyComponentComponent {
@Input()
public value = new EventEmitter();
}
// "jsdoc/require-jsdoc": ["error"|"warn", {"contexts":["ClassProperty:has(Decorator[expression.callee.name=\"Input\"])"]}]
// "jsdoc/require-jsdoc": ["error"|"warn", {"contexts":["PropertyDefinition > Decorator[expression.callee.name=\"Input\"]"]}]
// Message: Missing JSDoc comment.

requestAnimationFrame(draw)
Expand Down Expand Up @@ -12951,6 +12954,12 @@ function comment () {
}
// "jsdoc/require-jsdoc": ["error"|"warn", {"enableFixer":false,"fixerMessage":" TODO: add comment"}]
// Message: Missing JSDoc comment.

export class InovaAutoCompleteComponent {
public disabled = false;
}
// "jsdoc/require-jsdoc": ["error"|"warn", {"contexts":["PropertyDefinition"],"publicOnly":true}]
// Message: Missing JSDoc comment.
````

The following patterns are not considered problems:
Expand Down
19 changes: 11 additions & 8 deletions package.json
Expand Up @@ -5,7 +5,7 @@
"url": "http://gajus.com"
},
"dependencies": {
"@es-joy/jsdoccomment": "0.10.8",
"@es-joy/jsdoccomment": "0.11.0",
"comment-parser": "1.2.4",
"debug": "^4.3.2",
"esquery": "^1.4.0",
Expand All @@ -26,12 +26,12 @@
"@babel/preset-env": "^7.15.8",
"@babel/register": "^7.15.3",
"@hkdobrev/run-if-changed": "^0.3.1",
"@typescript-eslint/parser": "^4.33.0",
"@typescript-eslint/parser": "^5.0.0",
"babel-plugin-add-module-exports": "^1.0.4",
"babel-plugin-istanbul": "^6.0.0",
"chai": "^4.3.4",
"cross-env": "^7.0.3",
"eslint": "7.32.0",
"eslint": "^8.0.0",
"eslint-config-canonical": "^28.0.0",
"gitdown": "^3.1.4",
"glob": "^7.2.0",
Expand All @@ -48,10 +48,10 @@
"node": "^12 || ^14 || ^16"
},
"lint-staged": {
".eslintignore": "npm run lint",
"./*.js": "npm run lint-arg --",
"src/**/*.js": "npm run lint-arg --",
"test/**/*.js": "npm run lint-arg --"
"DISABLE.eslintignore": "npm run lint",
"DISABLE./*.js": "npm run lint-arg --",
"DISABLEsrc/**/*.js": "npm run lint-arg --",
"DISABLEtest/**/*.js": "npm run lint-arg --"
},
"run-if-changed": {
"package-lock.json": "npm run install-offline"
Expand All @@ -65,7 +65,7 @@
"main": "./dist/index.js",
"name": "eslint-plugin-jsdoc",
"peerDependencies": {
"eslint": "^6.0.0 || ^7.0.0"
"eslint": "^7.0.0 || ^8.0.0"
},
"repository": {
"type": "git",
Expand Down Expand Up @@ -95,6 +95,9 @@
"include": [
"src/"
],
"exclude": [
"src/rules/checkExamples.js"
],
"check-coverage": true,
"branches": 100,
"lines": 100,
Expand Down
2 changes: 2 additions & 0 deletions src/iterateJsdoc.js
Expand Up @@ -708,6 +708,8 @@ const makeReport = (context, commentNode) => {
end: {line: lineNumber},
start: {line: lineNumber},
};
// Todo: Remove once `check-examples` can be restored for ESLint 8+
// istanbul ignore if
if (jsdocLoc.column) {
const colNumber = commentNode.loc.start.column + jsdocLoc.column;

Expand Down
6 changes: 6 additions & 0 deletions src/jsdocUtils.js
Expand Up @@ -718,6 +718,9 @@ const hasNonEmptyResolverCall = (node, resolverName) => {
case 'ObjectProperty':
/* eslint-disable no-fallthrough */
// istanbul ignore next -- In Babel?
case 'PropertyDefinition':
/* eslint-disable no-fallthrough */
// istanbul ignore next -- In Babel?
case 'ClassProperty':
/* eslint-enable no-fallthrough */
case 'Property':
Expand Down Expand Up @@ -907,6 +910,9 @@ const hasNonFunctionYield = (node, checkYieldReturnValue) => {
return hasNonFunctionYield(property, checkYieldReturnValue);
});

// istanbul ignore next -- In Babel?
case 'PropertyDefinition':
/* eslint-disable no-fallthrough */
// istanbul ignore next -- In Babel?
case 'ObjectProperty':
/* eslint-disable no-fallthrough */
Expand Down
16 changes: 11 additions & 5 deletions src/rules/checkExamples.js
@@ -1,9 +1,9 @@
// Todo: When peerDeps bump to ESLint 7, see about replacing `CLIEngine`
// with non-deprecated `ESLint` class:
// Todo: When replace `CLIEngine` with `ESLint` when feature set complete per https://github.com/eslint/eslint/issues/14745
// https://github.com/eslint/eslint/blob/master/docs/user-guide/migrating-to-7.0.0.md#-the-cliengine-class-has-been-deprecated
import {
CLIEngine,
CLIEngine, ESLint,
} from 'eslint';
import semver from 'semver'
import iterateJsdoc from '../iterateJsdoc';

const zeroBasedLineIndexAdjust = -1;
Expand Down Expand Up @@ -85,6 +85,13 @@ export default iterateJsdoc(({
context,
globalState,
}) => {
if (semver.gte(ESLint.version, '8.0.0')) {
return report({
loc: { start: { column: 1, line: 1 } },
message: `This rule cannot yet be supported for ESLint 8; you should either downgrade to ESLint 7 or disable this rule. The possibility for ESLint 8 support is being tracked at https://github.com/eslint/eslint/issues/14745`,
});
}

if (!globalState.has('checkExamples-matchingFileName')) {
globalState.set('checkExamples-matchingFileName', new Map());
}
Expand Down Expand Up @@ -196,8 +203,7 @@ export default iterateJsdoc(({
matchingFileNameMap.set(fileNameMapKey, cliFile);
}

const {results: [{messages}]} =
cliFile.executeOnText(src);
const {results: [{messages}]} = cliFile.executeOnText(src);

if (!('line' in tag)) {
tag.line = tag.source[0].number;
Expand Down
4 changes: 2 additions & 2 deletions src/rules/requireJsdoc.js
Expand Up @@ -308,7 +308,7 @@ export default {

if (
['VariableDeclarator', 'AssignmentExpression', 'ExportDefaultDeclaration'].includes(node.parent.type) ||
['Property', 'ObjectProperty', 'ClassProperty'].includes(node.parent.type) && node === node.parent.value
['Property', 'ObjectProperty', 'ClassProperty', 'PropertyDefinition'].includes(node.parent.type) && node === node.parent.value
) {
checkJsDoc({isFunctionContext: true}, null, node);
}
Expand Down Expand Up @@ -351,7 +351,7 @@ export default {

if (
['VariableDeclarator', 'AssignmentExpression', 'ExportDefaultDeclaration'].includes(node.parent.type) ||
['Property', 'ObjectProperty', 'ClassProperty'].includes(node.parent.type) && node === node.parent.value
['Property', 'ObjectProperty', 'ClassProperty', 'PropertyDefinition'].includes(node.parent.type) && node === node.parent.value
) {
checkJsDoc({isFunctionContext: true}, null, node);
}
Expand Down
4 changes: 2 additions & 2 deletions test/rules/assertions/matchDescription.js
Expand Up @@ -794,7 +794,7 @@ export default {
options: [
{
contexts: [
'ClassProperty',
'PropertyDefinition',
],
},
],
Expand Down Expand Up @@ -1269,7 +1269,7 @@ export default {
options: [
{
contexts: [
'ClassProperty',
'PropertyDefinition',
],
},
],
Expand Down
47 changes: 33 additions & 14 deletions test/rules/assertions/requireJsdoc.js
Expand Up @@ -2,10 +2,6 @@
* @see https://github.com/eslint/eslint/blob/master/tests/lib/rules/require-jsdoc.js
*/

import {
CLIEngine,
} from 'eslint';

export default {
invalid: [
{
Expand Down Expand Up @@ -2591,7 +2587,7 @@ function quux (foo) {
],
options: [
{
contexts: ['ClassProperty'],
contexts: ['PropertyDefinition'],
},
],
output: `
Expand Down Expand Up @@ -3016,15 +3012,7 @@ function quux (foo) {
},
],
options: [{
contexts: [
// Only fixed to support `:has()` with TS later in ESLint 7, but
// for our testing of ESLint 6, we use `>` which is equivalent in
// this case; after having peerDeps. to ESLint 7+, we can remove
// this check and use of `CLIEngine`
CLIEngine.version.startsWith('6') ?
'ClassProperty > Decorator[expression.callee.name="Input"]' :
'ClassProperty:has(Decorator[expression.callee.name="Input"])',
],
contexts: ['PropertyDefinition > Decorator[expression.callee.name="Input"]'],
}],
output: `
export class MyComponentComponent {
Expand Down Expand Up @@ -3262,6 +3250,37 @@ function quux (foo) {
}
`,
},
{
code: `
export class InovaAutoCompleteComponent {
public disabled = false;
}
`,
errors: [
{
line: 3,
message: 'Missing JSDoc comment.',
}
],
options: [
{
contexts: ['PropertyDefinition'],
publicOnly: true,
},
],
output: `
export class InovaAutoCompleteComponent {
/**
*
*/
public disabled = false;
}
`,
parser: require.resolve('@typescript-eslint/parser'),
parserOptions: {
sourceType: 'module',
},
},
],
valid: [{
code: `
Expand Down
11 changes: 8 additions & 3 deletions test/rules/index.js
@@ -1,13 +1,18 @@
import {
RuleTester,
} from 'eslint';
import { ESLint, RuleTester } from 'eslint';
import _ from 'lodash';
import semver from 'semver'
import config from '../../src';
import ruleNames from './ruleNames.json';

const ruleTester = new RuleTester();

(process.env.npm_config_rule ? process.env.npm_config_rule.split(',') : ruleNames).forEach(async (ruleName) => {
if (semver.gte(ESLint.version, '8.0.0') && ruleName === 'check-examples') {
// This rule cannot yet be supported for ESLint 8;
// The possibility for ESLint 8 support is being tracked at https://github.com/eslint/eslint/issues/14745
return;
}

const rule = config.rules[ruleName];

const parserOptions = {
Expand Down