Skip to content

Commit c712808

Browse files
authored
Add support for eslint v8 (#152)
* Add test for eslint v8 * add hasSuggestions
1 parent 0a175f0 commit c712808

File tree

8 files changed

+173
-132
lines changed

8 files changed

+173
-132
lines changed

.eslintrc.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ module.exports = {
5454
},
5555
],
5656
"eslint-plugin/require-meta-docs-url": "off",
57+
"eslint-plugin/require-meta-has-suggestions": "off", // false positive
5758

5859
"@typescript-eslint/naming-convention": [
5960
"error",

.github/workflows/NodeCI.yml

Lines changed: 75 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,80 @@
11
name: CI
22

33
on:
4-
push:
5-
branches: [master]
6-
pull_request:
7-
branches: [master]
4+
push:
5+
branches: [master]
6+
pull_request:
7+
branches: [master]
88

99
jobs:
10-
lint:
11-
runs-on: ubuntu-latest
12-
steps:
13-
- uses: actions/checkout@v2
14-
- uses: actions/setup-node@v2
15-
with:
16-
node-version: 14
17-
- name: Install Packages
18-
run: npm install
19-
- name: Lint
20-
run: npm run lint
21-
test:
22-
runs-on: ubuntu-latest
23-
strategy:
24-
matrix:
25-
node-version: [10.13.x, 12.x, 13.x, 14.x]
26-
steps:
27-
- uses: actions/checkout@v2
28-
- name: Use Node.js ${{ matrix.node-version }}
29-
uses: actions/setup-node@v2
30-
with:
31-
node-version: ${{ matrix.node-version }}
32-
- name: Install Packages
33-
run: npm install
34-
- name: build
35-
run: npm run build
36-
- name: Test
37-
run: npm test
38-
test-with-eslint6:
39-
runs-on: ubuntu-latest
40-
steps:
41-
- uses: actions/checkout@v2
42-
- uses: actions/setup-node@v2
43-
with:
44-
node-version: 8.10.x
45-
- name: Install Target Packages
46-
run: |+
47-
npm i -D [email protected] mocha@7
48-
npx rimraf node_modules
49-
npm install
50-
- name: Test
51-
run: npm test
52-
test-and-coverage:
53-
runs-on: ubuntu-latest
54-
steps:
55-
- uses: actions/checkout@v2
56-
- uses: actions/setup-node@v2
57-
- name: Install Packages
58-
run: npm install
59-
- name: Test
60-
run: npm run test:nyc
61-
- name: Install Coveralls
62-
run: npm i -D coveralls
63-
- name: Coveralls GitHub Action
64-
uses: coverallsapp/[email protected]
65-
with:
66-
github-token: ${{ secrets.GITHUB_TOKEN }}
10+
lint:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v2
14+
- uses: actions/setup-node@v2
15+
with:
16+
node-version: 14
17+
- name: Install Packages
18+
run: npm install
19+
- name: Lint
20+
run: npm run lint
21+
test:
22+
runs-on: ubuntu-latest
23+
strategy:
24+
matrix:
25+
node-version: [10.13.x, 12.x, 13.x, 14.x, 16.x]
26+
steps:
27+
- uses: actions/checkout@v2
28+
- name: Use Node.js ${{ matrix.node-version }}
29+
uses: actions/setup-node@v2
30+
with:
31+
node-version: ${{ matrix.node-version }}
32+
- name: Install Packages
33+
run: npm install
34+
- name: build
35+
run: npm run build
36+
- name: Test
37+
run: npm test
38+
test-with-eslint6:
39+
runs-on: ubuntu-latest
40+
steps:
41+
- uses: actions/checkout@v2
42+
- uses: actions/setup-node@v2
43+
with:
44+
node-version: 8.10.x
45+
- name: Install Target Packages
46+
run: |+
47+
npm i -D [email protected] mocha@7
48+
npx rimraf node_modules
49+
npm install
50+
- name: Test
51+
run: npm test
52+
test-with-eslint8:
53+
runs-on: ubuntu-latest
54+
steps:
55+
- uses: actions/checkout@v2
56+
- uses: actions/setup-node@v2
57+
with:
58+
node-version: 14
59+
- name: Install Target Packages
60+
run: |+
61+
npm i -D eslint@^8.0.0-0
62+
npx rimraf node_modules
63+
npm install
64+
- name: Test
65+
run: npm test
66+
test-and-coverage:
67+
runs-on: ubuntu-latest
68+
steps:
69+
- uses: actions/checkout@v2
70+
- uses: actions/setup-node@v2
71+
- name: Install Packages
72+
run: npm install
73+
- name: Test
74+
run: npm run test:nyc
75+
- name: Install Coveralls
76+
run: npm i -D coveralls
77+
- name: Coveralls GitHub Action
78+
uses: coverallsapp/[email protected]
79+
with:
80+
github-token: ${{ secrets.GITHUB_TOKEN }}

eslint-internal-rules/require-meta-docs-url.js

Lines changed: 75 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
/**
2+
* @author Toru Nagashima <https://github.com/mysticatea>
3+
*/
4+
15
"use strict"
26

37
// -----------------------------------------------------------------------------
@@ -7,19 +11,22 @@
711
const path = require("path")
812
// eslint-disable-next-line node/no-extraneous-require -- ignore
913
const util = require("eslint-plugin-eslint-plugin/lib/utils")
14+
// eslint-disable-next-line node/no-extraneous-require -- ignore
15+
const { getStaticValue } = require("eslint-utils")
1016

1117
// -----------------------------------------------------------------------------
1218
// Rule Definition
1319
// -----------------------------------------------------------------------------
1420

1521
module.exports = {
1622
meta: {
23+
type: "suggestion",
1724
docs: {
18-
description: "require rules to implement a meta.docs.url property",
25+
description:
26+
"require rules to implement a `meta.docs.url` property",
1927
category: "Rules",
2028
recommended: false,
2129
},
22-
type: "suggestion",
2330
fixable: "code",
2431
schema: [
2532
{
@@ -30,6 +37,11 @@ module.exports = {
3037
additionalProperties: false,
3138
},
3239
],
40+
messages: {
41+
mismatch: "`meta.docs.url` property must be `{{expectedUrl}}`.",
42+
missing: "`meta.docs.url` property is missing.",
43+
wrongType: "`meta.docs.url` property must be a string.",
44+
},
3345
},
3446

3547
/**
@@ -46,44 +58,24 @@ module.exports = {
4658
const expectedUrl =
4759
!options.pattern || !ruleName
4860
? undefined
49-
: options.pattern.replace(/\{\{\s*name\s*\}\}/gu, ruleName)
61+
: options.pattern.replace(/\{\{\s*name\s*\}\}/g, ruleName)
5062

5163
/**
52-
* Check whether a given node is the expected URL.
53-
* @param {Node} node The node of property value to check.
64+
* Check whether a given URL is the expected URL.
65+
* @param {string} url The URL to check.
5466
* @returns {boolean} `true` if the node is the expected URL.
5567
*/
56-
function isExpectedUrl(node) {
68+
function isExpectedUrl(url) {
5769
return Boolean(
58-
node &&
59-
node.type === "Literal" &&
60-
typeof node.value === "string" &&
61-
(expectedUrl === undefined || node.value === expectedUrl),
62-
)
63-
}
64-
65-
/**
66-
* Insert a given property into a given object literal.
67-
* @param {SourceCodeFixer} fixer The fixer.
68-
* @param {Node} node The ObjectExpression node to insert a property.
69-
* @param {string} propertyText The property code to insert.
70-
* @returns {void}
71-
*/
72-
function insertProperty(fixer, node, propertyText) {
73-
if (node.properties.length === 0) {
74-
return fixer.replaceText(node, `{\n${propertyText}\n}`)
75-
}
76-
return fixer.insertTextAfter(
77-
sourceCode.getLastToken(
78-
node.properties[node.properties.length - 1],
79-
),
80-
`,\n${propertyText}`,
70+
typeof url === "string" &&
71+
(expectedUrl === undefined || url === expectedUrl),
8172
)
8273
}
8374

8475
return {
85-
Program(node) {
86-
const info = util.getRuleInfo(node)
76+
// eslint-disable-next-line complexity -- ignore
77+
Program() {
78+
const info = util.getRuleInfo(sourceCode)
8779
if (info === null) {
8880
return
8981
}
@@ -106,58 +98,75 @@ module.exports = {
10698
util.getKeyName(p) === "url",
10799
)
108100

109-
if (isExpectedUrl(urlPropNode && urlPropNode.value)) {
101+
const staticValue = urlPropNode
102+
? getStaticValue(urlPropNode.value, context.getScope())
103+
: undefined
104+
if (urlPropNode && !staticValue) {
105+
// Ignore non-static values since we can't determine what they look like.
106+
return
107+
}
108+
109+
if (isExpectedUrl(staticValue && staticValue.value)) {
110110
return
111111
}
112112

113113
context.report({
114-
loc:
115-
(urlPropNode && urlPropNode.value.loc) ||
116-
(docsPropNode && docsPropNode.value.loc) ||
117-
(metaNode && metaNode.loc) ||
118-
node.loc.start,
119-
120-
message: !urlPropNode
121-
? "Rules should export a `meta.docs.url` property."
114+
node:
115+
(urlPropNode && urlPropNode.value) ||
116+
(docsPropNode && docsPropNode.value) ||
117+
metaNode ||
118+
info.create,
119+
120+
messageId: !urlPropNode
121+
? "missing"
122122
: !expectedUrl
123-
? "`meta.docs.url` property must be a string."
124-
: /* otherwise */ "`meta.docs.url` property must be `{{expectedUrl}}`.",
123+
? "wrongType"
124+
: /* otherwise */ "mismatch",
125125

126126
data: {
127127
expectedUrl,
128128
},
129129

130130
fix(fixer) {
131-
if (expectedUrl) {
132-
const urlString = JSON.stringify(expectedUrl)
133-
if (urlPropNode) {
131+
if (!expectedUrl) {
132+
return null
133+
}
134+
135+
const urlString = JSON.stringify(expectedUrl)
136+
if (urlPropNode) {
137+
if (
138+
urlPropNode.value.type === "Literal" ||
139+
(urlPropNode.value.type === "Identifier" &&
140+
urlPropNode.value.name === "undefined")
141+
) {
134142
return fixer.replaceText(
135143
urlPropNode.value,
136144
urlString,
137145
)
138146
}
139-
if (
140-
docsPropNode &&
141-
docsPropNode.value.type === "ObjectExpression"
142-
) {
143-
return insertProperty(
144-
fixer,
145-
docsPropNode.value,
146-
`url: ${urlString}`,
147-
)
148-
}
149-
if (
150-
!docsPropNode &&
151-
metaNode &&
152-
metaNode.type === "ObjectExpression"
153-
) {
154-
return insertProperty(
155-
fixer,
156-
metaNode,
157-
`docs: {\nurl: ${urlString}\n}`,
158-
)
159-
}
147+
} else if (
148+
docsPropNode &&
149+
docsPropNode.value.type === "ObjectExpression"
150+
) {
151+
return util.insertProperty(
152+
fixer,
153+
docsPropNode.value,
154+
`url: ${urlString}`,
155+
sourceCode,
156+
)
157+
} else if (
158+
!docsPropNode &&
159+
metaNode &&
160+
metaNode.type === "ObjectExpression"
161+
) {
162+
return util.insertProperty(
163+
fixer,
164+
metaNode,
165+
`docs: {\nurl: ${urlString}\n}`,
166+
sourceCode,
167+
)
160168
}
169+
161170
return null
162171
},
163172
})

lib/rules/enforce-style-type.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ module.exports = {
5757
},
5858
],
5959
type: "suggestion",
60+
hasSuggestions: true,
6061
},
6162
create(context: RuleContext) {
6263
const styles = getStyleContexts(context).filter(isValidStyleContext)

lib/rules/require-scoped.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ module.exports = {
3131
},
3232
schema: [{ enum: ["always", "never"] }],
3333
type: "suggestion",
34+
hasSuggestions: true,
3435
},
3536
create(context: RuleContext) {
3637
const always = context.options[0] !== "never"

lib/types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export type Rule = {
2626
}
2727
deprecated?: boolean
2828
fixable?: "code" | "whitespace" | null
29+
hasSuggestions?: boolean
2930
schema: unknown[]
3031
messages: { [key: string]: string }
3132
type: "suggestion" | "problem"

0 commit comments

Comments
 (0)