Skip to content

Commit 7b39b75

Browse files
committed
refactor: cleanup
1 parent 8ec6cde commit 7b39b75

3 files changed

Lines changed: 65 additions & 51 deletions

File tree

eslint-plugin-prettier.js

Lines changed: 36 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,12 @@
77

88
/**
99
* @import {AST, ESLint, Linter, Rule, SourceCode} from 'eslint'
10+
* @import {Position} from 'estree'
1011
* @import {FileInfoOptions, Options as PrettierOptions} from 'prettier'
1112
* @import {Difference} from 'prettier-linter-helpers'
1213
*/
1314

1415
/**
15-
* @typedef {{ line: number; column: number; offset: number }} Location
16-
*
1716
* @typedef {PrettierOptions & {
1817
* onDiskFilepath: string;
1918
* parserMeta?: ESLint.ObjectMetaProperties['meta'];
@@ -27,11 +26,6 @@
2726
* options: Options,
2827
* fileInfoOptions: FileInfoOptions,
2928
* ) => string} PrettierFormat
30-
*
31-
*
32-
* @typedef {Parameters<
33-
* Exclude<ESLint.Plugin['rules'], undefined>[string]['create']
34-
* >[0]} RuleContext
3529
*/
3630

3731
'use strict';
@@ -64,29 +58,52 @@ let prettierFormat;
6458
// Rule Definition
6559
// ------------------------------------------------------------------------------
6660

61+
/** @type {WeakMap<SourceCode, number[]>} */
62+
const lineIndexesCache = new WeakMap();
63+
6764
/**
68-
* Converts a byte offset to a Location.
65+
* Ponyfill `sourceCode.getLocFromIndex` when it's unavailable.
6966
*
7067
* See also `getLocFromIndex` in `@eslint/js`.
7168
*
72-
* @param {number[]} lineIndexes
73-
* @param {number} offset
74-
* @returns {Location}
69+
* @param {SourceCode} sourceCode
70+
* @param {number} index
71+
* @returns {Position}
7572
*/
76-
function getLocFromOffset(lineIndexes, offset) {
73+
function getLocFromIndex(sourceCode, index) {
74+
if (typeof sourceCode.getLocFromIndex === 'function') {
75+
return sourceCode.getLocFromIndex(index);
76+
}
77+
78+
if (!('text' in sourceCode)) {
79+
throw new Error(
80+
'prettier/prettier: non-textual source code is unsupported',
81+
);
82+
}
83+
84+
let lineIndexes = lineIndexesCache.get(sourceCode);
85+
86+
if (!lineIndexes) {
87+
lineIndexes = [
88+
0,
89+
...sourceCode.text.matchAll(/\n/g).map(match => match.index),
90+
];
91+
lineIndexesCache.set(sourceCode, lineIndexes);
92+
}
93+
7794
let line = 0;
78-
while (line + 1 < lineIndexes.length && lineIndexes[line + 1] < offset) {
95+
while (line + 1 < lineIndexes.length && lineIndexes[line + 1] < index) {
7996
line += 1;
8097
}
8198

82-
const column = offset - lineIndexes[line];
83-
return { line: line + 1, column, offset };
99+
const column = index - lineIndexes[line];
100+
return { line: line + 1, column };
84101
}
85102

86103
/**
87104
* Reports a difference.
88105
*
89-
* @param {RuleContext} context - The ESLint rule context.
106+
* @param {Rule.RuleContext} context - The ESLint rule context.
90107
* @param {Difference} difference - The difference object.
91108
* @returns {void}
92109
*/
@@ -99,38 +116,7 @@ function reportDifference(context, difference) {
99116
// TODO: Only use property when our eslint peerDependency is >=8.40.0.
100117
const sourceCode = context.sourceCode ?? context.getSourceCode();
101118

102-
const lazy = {
103-
/**
104-
* Lazily computes the line indices for `sourceCode`.
105-
*
106-
* @returns {number[]}
107-
*/
108-
get lineIndexes() {
109-
// @ts-ignore
110-
delete this.lineIndexes;
111-
112-
if (!('text' in sourceCode)) {
113-
throw new Error(
114-
'prettier/prettier: non-textual source code is unsupported',
115-
);
116-
}
117-
118-
// @ts-ignore
119-
this.lineIndexes = [...sourceCode.text.matchAll(/\n/g)].map(
120-
match => match.index,
121-
);
122-
// first line in the file starts at byte offset 0
123-
this.lineIndexes.unshift(0);
124-
return this.lineIndexes;
125-
},
126-
};
127-
128-
const [start, end] = range.map(
129-
index =>
130-
// @ts-ignore
131-
sourceCode.getLocFromIndex?.(index) ??
132-
getLocFromOffset(lazy.lineIndexes, index),
133-
);
119+
const [start, end] = range.map(index => getLocFromIndex(sourceCode, index));
134120

135121
context.report({
136122
messageId: operation,
@@ -147,7 +133,7 @@ function reportDifference(context, difference) {
147133
// Module Definition
148134
// ------------------------------------------------------------------------------
149135

150-
/** @satisfies {ESLint.Plugin} */
136+
/** @type {ESLint.Plugin} */
151137
const eslintPluginPrettier = {
152138
meta: { name, version },
153139
configs: {
@@ -225,6 +211,7 @@ const eslintPluginPrettier = {
225211
const source = sourceCode.text;
226212

227213
return {
214+
/** @param {unknown} node */
228215
[sourceCode.ast.type](node) {
229216
if (!prettierFormat) {
230217
// Prettier is expensive to load, so only load it if needed.

test/fixtures/empty.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

test/prettier.mjs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,26 @@ runFixture('invalid-prettierrc/*', [
381381
],
382382
]);
383383

384+
runFixture('*.json', [
385+
[
386+
{
387+
column: 1,
388+
endColumn: 1,
389+
endLine: 2,
390+
fix: {
391+
range: [0, 1],
392+
text: '',
393+
},
394+
line: 1,
395+
message: 'Delete `⏎`',
396+
messageId: 'delete',
397+
nodeType: null,
398+
ruleId: 'prettier/prettier',
399+
severity: 2,
400+
},
401+
],
402+
]);
403+
384404
const jsonRuleTester = new RuleTester({
385405
plugins: {
386406
json: eslintPluginJson,
@@ -462,7 +482,7 @@ function getPrettierRcJsFilename(dir, file = 'dummy.js') {
462482
* @type {ESLint}
463483
* @import {ESLint} from 'eslint'
464484
*/
465-
let eslint;
485+
var eslint; // bad mocha: `ReferenceError: Cannot access 'eslint' before initialization`
466486

467487
/**
468488
* @param {string} pattern
@@ -530,11 +550,17 @@ async function runFixture(pattern, asserts, skip) {
530550
pug: eslintPluginPug,
531551
},
532552
},
553+
{
554+
files: ['**/*.json'],
555+
plugins: {
556+
json: eslintPluginJson,
557+
},
558+
...eslintPluginJson.configs.recommended,
559+
},
533560
],
534561
ignore: false,
535562
});
536563
}
537-
538564
if (skip) {
539565
return;
540566
}

0 commit comments

Comments
 (0)