Skip to content

Commit

Permalink
Add support for eslint v8 (#152)
Browse files Browse the repository at this point in the history
* Add test for eslint v8

* add hasSuggestions
  • Loading branch information
ota-meshi committed Aug 22, 2021
1 parent 0a175f0 commit c712808
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 132 deletions.
1 change: 1 addition & 0 deletions .eslintrc.js
Expand Up @@ -54,6 +54,7 @@ module.exports = {
},
],
"eslint-plugin/require-meta-docs-url": "off",
"eslint-plugin/require-meta-has-suggestions": "off", // false positive

"@typescript-eslint/naming-convention": [
"error",
Expand Down
136 changes: 75 additions & 61 deletions .github/workflows/NodeCI.yml
@@ -1,66 +1,80 @@
name: CI

on:
push:
branches: [master]
pull_request:
branches: [master]
push:
branches: [master]
pull_request:
branches: [master]

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 14
- name: Install Packages
run: npm install
- name: Lint
run: npm run lint
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.13.x, 12.x, 13.x, 14.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- name: Install Packages
run: npm install
- name: build
run: npm run build
- name: Test
run: npm test
test-with-eslint6:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 8.10.x
- name: Install Target Packages
run: |+
npm i -D eslint@6.0.0 mocha@7
npx rimraf node_modules
npm install
- name: Test
run: npm test
test-and-coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- name: Install Packages
run: npm install
- name: Test
run: npm run test:nyc
- name: Install Coveralls
run: npm i -D coveralls
- name: Coveralls GitHub Action
uses: coverallsapp/github-action@1.1.3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 14
- name: Install Packages
run: npm install
- name: Lint
run: npm run lint
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [10.13.x, 12.x, 13.x, 14.x, 16.x]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
- name: Install Packages
run: npm install
- name: build
run: npm run build
- name: Test
run: npm test
test-with-eslint6:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 8.10.x
- name: Install Target Packages
run: |+
npm i -D eslint@6.0.0 mocha@7
npx rimraf node_modules
npm install
- name: Test
run: npm test
test-with-eslint8:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: 14
- name: Install Target Packages
run: |+
npm i -D eslint@^8.0.0-0
npx rimraf node_modules
npm install
- name: Test
run: npm test
test-and-coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
- name: Install Packages
run: npm install
- name: Test
run: npm run test:nyc
- name: Install Coveralls
run: npm i -D coveralls
- name: Coveralls GitHub Action
uses: coverallsapp/github-action@1.1.3
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
141 changes: 75 additions & 66 deletions eslint-internal-rules/require-meta-docs-url.js
@@ -1,3 +1,7 @@
/**
* @author Toru Nagashima <https://github.com/mysticatea>
*/

"use strict"

// -----------------------------------------------------------------------------
Expand All @@ -7,19 +11,22 @@
const path = require("path")
// eslint-disable-next-line node/no-extraneous-require -- ignore
const util = require("eslint-plugin-eslint-plugin/lib/utils")
// eslint-disable-next-line node/no-extraneous-require -- ignore
const { getStaticValue } = require("eslint-utils")

// -----------------------------------------------------------------------------
// Rule Definition
// -----------------------------------------------------------------------------

module.exports = {
meta: {
type: "suggestion",
docs: {
description: "require rules to implement a meta.docs.url property",
description:
"require rules to implement a `meta.docs.url` property",
category: "Rules",
recommended: false,
},
type: "suggestion",
fixable: "code",
schema: [
{
Expand All @@ -30,6 +37,11 @@ module.exports = {
additionalProperties: false,
},
],
messages: {
mismatch: "`meta.docs.url` property must be `{{expectedUrl}}`.",
missing: "`meta.docs.url` property is missing.",
wrongType: "`meta.docs.url` property must be a string.",
},
},

/**
Expand All @@ -46,44 +58,24 @@ module.exports = {
const expectedUrl =
!options.pattern || !ruleName
? undefined
: options.pattern.replace(/\{\{\s*name\s*\}\}/gu, ruleName)
: options.pattern.replace(/\{\{\s*name\s*\}\}/g, ruleName)

/**
* Check whether a given node is the expected URL.
* @param {Node} node The node of property value to check.
* Check whether a given URL is the expected URL.
* @param {string} url The URL to check.
* @returns {boolean} `true` if the node is the expected URL.
*/
function isExpectedUrl(node) {
function isExpectedUrl(url) {
return Boolean(
node &&
node.type === "Literal" &&
typeof node.value === "string" &&
(expectedUrl === undefined || node.value === expectedUrl),
)
}

/**
* Insert a given property into a given object literal.
* @param {SourceCodeFixer} fixer The fixer.
* @param {Node} node The ObjectExpression node to insert a property.
* @param {string} propertyText The property code to insert.
* @returns {void}
*/
function insertProperty(fixer, node, propertyText) {
if (node.properties.length === 0) {
return fixer.replaceText(node, `{\n${propertyText}\n}`)
}
return fixer.insertTextAfter(
sourceCode.getLastToken(
node.properties[node.properties.length - 1],
),
`,\n${propertyText}`,
typeof url === "string" &&
(expectedUrl === undefined || url === expectedUrl),
)
}

return {
Program(node) {
const info = util.getRuleInfo(node)
// eslint-disable-next-line complexity -- ignore
Program() {
const info = util.getRuleInfo(sourceCode)
if (info === null) {
return
}
Expand All @@ -106,58 +98,75 @@ module.exports = {
util.getKeyName(p) === "url",
)

if (isExpectedUrl(urlPropNode && urlPropNode.value)) {
const staticValue = urlPropNode
? getStaticValue(urlPropNode.value, context.getScope())
: undefined
if (urlPropNode && !staticValue) {
// Ignore non-static values since we can't determine what they look like.
return
}

if (isExpectedUrl(staticValue && staticValue.value)) {
return
}

context.report({
loc:
(urlPropNode && urlPropNode.value.loc) ||
(docsPropNode && docsPropNode.value.loc) ||
(metaNode && metaNode.loc) ||
node.loc.start,

message: !urlPropNode
? "Rules should export a `meta.docs.url` property."
node:
(urlPropNode && urlPropNode.value) ||
(docsPropNode && docsPropNode.value) ||
metaNode ||
info.create,

messageId: !urlPropNode
? "missing"
: !expectedUrl
? "`meta.docs.url` property must be a string."
: /* otherwise */ "`meta.docs.url` property must be `{{expectedUrl}}`.",
? "wrongType"
: /* otherwise */ "mismatch",

data: {
expectedUrl,
},

fix(fixer) {
if (expectedUrl) {
const urlString = JSON.stringify(expectedUrl)
if (urlPropNode) {
if (!expectedUrl) {
return null
}

const urlString = JSON.stringify(expectedUrl)
if (urlPropNode) {
if (
urlPropNode.value.type === "Literal" ||
(urlPropNode.value.type === "Identifier" &&
urlPropNode.value.name === "undefined")
) {
return fixer.replaceText(
urlPropNode.value,
urlString,
)
}
if (
docsPropNode &&
docsPropNode.value.type === "ObjectExpression"
) {
return insertProperty(
fixer,
docsPropNode.value,
`url: ${urlString}`,
)
}
if (
!docsPropNode &&
metaNode &&
metaNode.type === "ObjectExpression"
) {
return insertProperty(
fixer,
metaNode,
`docs: {\nurl: ${urlString}\n}`,
)
}
} else if (
docsPropNode &&
docsPropNode.value.type === "ObjectExpression"
) {
return util.insertProperty(
fixer,
docsPropNode.value,
`url: ${urlString}`,
sourceCode,
)
} else if (
!docsPropNode &&
metaNode &&
metaNode.type === "ObjectExpression"
) {
return util.insertProperty(
fixer,
metaNode,
`docs: {\nurl: ${urlString}\n}`,
sourceCode,
)
}

return null
},
})
Expand Down
1 change: 1 addition & 0 deletions lib/rules/enforce-style-type.ts
Expand Up @@ -57,6 +57,7 @@ module.exports = {
},
],
type: "suggestion",
hasSuggestions: true,
},
create(context: RuleContext) {
const styles = getStyleContexts(context).filter(isValidStyleContext)
Expand Down
1 change: 1 addition & 0 deletions lib/rules/require-scoped.ts
Expand Up @@ -31,6 +31,7 @@ module.exports = {
},
schema: [{ enum: ["always", "never"] }],
type: "suggestion",
hasSuggestions: true,
},
create(context: RuleContext) {
const always = context.options[0] !== "never"
Expand Down
1 change: 1 addition & 0 deletions lib/types.ts
Expand Up @@ -26,6 +26,7 @@ export type Rule = {
}
deprecated?: boolean
fixable?: "code" | "whitespace" | null
hasSuggestions?: boolean
schema: unknown[]
messages: { [key: string]: string }
type: "suggestion" | "problem"
Expand Down

0 comments on commit c712808

Please sign in to comment.