Skip to content

Commit f104b16

Browse files
authored
Support for ESLint v8 (#49)
* Support for ESLint v8 * fix ci
1 parent 6b2dfe1 commit f104b16

File tree

4 files changed

+202
-9
lines changed

4 files changed

+202
-9
lines changed

.github/workflows/NodeCI.yml

+37-5
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,50 @@ jobs:
1818
run: npm install
1919
- name: Lint
2020
run: npm run lint
21-
test:
22-
runs-on: ubuntu-latest
21+
test-for-eslint7:
22+
name: "Test for ESLint ${{ matrix.eslint }} on ${{ matrix.node }} OS: ${{matrix.os}}"
23+
runs-on: ${{ matrix.os }}
2324
strategy:
2425
matrix:
25-
node-version: [10.x, 12.x, 13.x, 14.x, 15.x]
26+
os: [ubuntu-latest]
27+
node: [10, 12, 14, 16]
28+
eslint: [7]
2629
steps:
2730
- uses: actions/checkout@v2
28-
- name: Use Node.js ${{ matrix.node-version }}
31+
- name: Use Node.js ${{ matrix.node }}
2932
uses: actions/setup-node@v2
3033
with:
31-
node-version: ${{ matrix.node-version }}
34+
node-version: ${{ matrix.node }}
35+
- name: Install ESLint ${{ matrix.eslint }}
36+
run: |+
37+
npm i -D eslint@${{ matrix.eslint }} --legacy-peer-deps
38+
npx rimraf node_modules
39+
if: matrix.eslint != 7
3240
- name: Install Packages
3341
run: npm install --legacy-peer-deps
3442
- name: Test
3543
run: npm test
44+
test-for-eslint8:
45+
name: "Test for ESLint ${{ matrix.eslint }} on ${{ matrix.node }} OS: ${{matrix.os}}"
46+
runs-on: ${{ matrix.os }}
47+
strategy:
48+
matrix:
49+
os: [ubuntu-latest]
50+
eslint: [^8.0.0-0]
51+
node: [14, 16]
52+
steps:
53+
- name: Checkout
54+
uses: actions/checkout@v2
55+
- name: Setup Node.js ${{ matrix.node }}
56+
uses: actions/setup-node@v2
57+
with:
58+
node-version: ${{ matrix.node }}
59+
- name: Install ESLint ${{ matrix.eslint }}
60+
run: |+
61+
npm i -D eslint@${{ matrix.eslint }} --legacy-peer-deps
62+
npx rimraf node_modules
63+
if: matrix.eslint != 7
64+
- name: Install Packages
65+
run: npm install --legacy-peer-deps
66+
- name: Test
67+
run: yarn test

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
"svelte-eslint-parser": "^0.4.3"
5353
},
5454
"peerDependencies": {
55-
"eslint": "^7.0.0",
55+
"eslint": "^7.0.0 || ^8.0.0-0",
5656
"svelte": "^3.37.0"
5757
},
5858
"peerDependenciesMeta": {

tests/utils/source-code-fixer.ts

+162
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
/**
2+
* Copy from https://github.com/eslint/eslint/blob/master/lib/linter/source-code-fixer.js
3+
* @see https://github.com/eslint/eslint/issues/14936
4+
*/
5+
/**
6+
* @fileoverview An object that caches and applies source code fixes.
7+
* @author Nicholas C. Zakas
8+
*/
9+
10+
import type { Linter } from "eslint"
11+
12+
// ------------------------------------------------------------------------------
13+
// Requirements
14+
// ------------------------------------------------------------------------------
15+
16+
// const debug = require("debug")("eslint:source-code-fixer");
17+
type Message = {
18+
fix?: Linter.LintMessage["fix"]
19+
}
20+
21+
type HasFixMessage = Message & {
22+
fix: NonNullable<Message["fix"]>
23+
}
24+
25+
function hasFixMessage(m: Message): m is HasFixMessage {
26+
return Boolean(m.fix)
27+
}
28+
// ------------------------------------------------------------------------------
29+
// Helpers
30+
// ------------------------------------------------------------------------------
31+
32+
const BOM = "\uFEFF"
33+
34+
/**
35+
* Compares items in a messages array by range.
36+
* @param {Message} a The first message.
37+
* @param {Message} b The second message.
38+
* @returns {int} -1 if a comes before b, 1 if a comes after b, 0 if equal.
39+
* @private
40+
*/
41+
function compareMessagesByFixRange(a: HasFixMessage, b: HasFixMessage) {
42+
return a.fix.range[0] - b.fix.range[0] || a.fix.range[1] - b.fix.range[1]
43+
}
44+
45+
/**
46+
* Compares items in a messages array by line and column.
47+
* @param {Message} a The first message.
48+
* @param {Message} b The second message.
49+
* @returns {int} -1 if a comes before b, 1 if a comes after b, 0 if equal.
50+
* @private
51+
*/
52+
function compareMessagesByLocation(a: any, b: any) {
53+
return a.line - b.line || a.column - b.column
54+
}
55+
56+
// ------------------------------------------------------------------------------
57+
// Public Interface
58+
// ------------------------------------------------------------------------------
59+
60+
/**
61+
* Applies the fixes specified by the messages to the given text. Tries to be
62+
* smart about the fixes and won't apply fixes over the same area in the text.
63+
* @param {string} sourceText The text to apply the changes to.
64+
* @param {Message[]} messages The array of messages reported by ESLint.
65+
* @param {boolean|Function} [shouldFix=true] Determines whether each message should be fixed
66+
* @returns {Object} An object containing the fixed text and any unfixed messages.
67+
*/
68+
export function applyFixes<M extends Message>(
69+
sourceText: string,
70+
messages: M[],
71+
shouldFix: boolean | ((m: M) => boolean) = true,
72+
): {
73+
fixed: boolean
74+
messages: M[]
75+
output: string
76+
} {
77+
// debug("Applying fixes");
78+
79+
if (shouldFix === false) {
80+
// debug("shouldFix parameter was false, not attempting fixes");
81+
return {
82+
fixed: false,
83+
messages,
84+
output: sourceText,
85+
}
86+
}
87+
88+
// clone the array
89+
const remainingMessages = []
90+
const fixes: (HasFixMessage & M)[] = []
91+
const bom = sourceText.startsWith(BOM) ? BOM : ""
92+
const text = bom ? sourceText.slice(1) : sourceText
93+
let lastPos = Number.NEGATIVE_INFINITY
94+
let output = bom
95+
96+
/**
97+
* Try to use the 'fix' from a problem.
98+
* @param {Message} problem The message object to apply fixes from
99+
* @returns {boolean} Whether fix was successfully applied
100+
*/
101+
function attemptFix(problem: HasFixMessage) {
102+
const fix = problem.fix
103+
const start = fix.range[0]
104+
const end = fix.range[1]
105+
106+
// Remain it as a problem if it's overlapped or it's a negative range
107+
if (lastPos >= start || start > end) {
108+
remainingMessages.push(problem)
109+
return false
110+
}
111+
112+
// Remove BOM.
113+
if ((start < 0 && end >= 0) || (start === 0 && fix.text.startsWith(BOM))) {
114+
output = ""
115+
}
116+
117+
// Make output to this fix.
118+
output += text.slice(Math.max(0, lastPos), Math.max(0, start))
119+
output += fix.text
120+
lastPos = end
121+
return true
122+
}
123+
124+
messages.forEach((problem) => {
125+
if (hasFixMessage(problem)) {
126+
fixes.push(problem)
127+
} else {
128+
remainingMessages.push(problem)
129+
}
130+
})
131+
132+
if (fixes.length) {
133+
// debug("Found fixes to apply");
134+
let fixesWereApplied = false
135+
136+
for (const problem of fixes.sort(compareMessagesByFixRange)) {
137+
if (typeof shouldFix !== "function" || shouldFix(problem)) {
138+
attemptFix(problem)
139+
140+
// The only time attemptFix will fail is if a previous fix was
141+
// applied which conflicts with it. So we can mark this as true.
142+
fixesWereApplied = true
143+
} else {
144+
remainingMessages.push(problem)
145+
}
146+
}
147+
output += text.slice(Math.max(0, lastPos))
148+
149+
return {
150+
fixed: fixesWereApplied,
151+
messages: remainingMessages.sort(compareMessagesByLocation),
152+
output,
153+
}
154+
}
155+
156+
// debug("No fixes to apply");
157+
return {
158+
fixed: false,
159+
messages,
160+
output: bom + text,
161+
}
162+
}

tests/utils/utils.ts

+2-3
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,10 @@ import fs from "fs"
22
import path from "path"
33
import type { RuleTester } from "eslint"
44
import { Linter } from "eslint"
5-
// @ts-expect-error for test
6-
import { SourceCodeFixer } from "eslint/lib/linter"
75
import * as svelteESLintParser from "svelte-eslint-parser"
86
// eslint-disable-next-line @typescript-eslint/no-require-imports -- tests
97
import plugin = require("../../src/index")
8+
import { applyFixes } from "./source-code-fixer"
109

1110
/**
1211
* Prevents leading spaces in a multiline template literal from appearing in the resulting string
@@ -208,7 +207,7 @@ function writeFixtures(
208207
}
209208

210209
if (force || !exists(outputFile)) {
211-
const output = SourceCodeFixer.applyFixes(config.code, result).output
210+
const output = applyFixes(config.code, result).output
212211

213212
if (plugin.rules[ruleName].meta.fixable != null) {
214213
fs.writeFileSync(outputFile, output, "utf8")

0 commit comments

Comments
 (0)