7
7
8
8
/**
9
9
* @import {AST, ESLint, Linter, Rule, SourceCode} from 'eslint'
10
+ * @import {Position} from 'estree'
10
11
* @import {FileInfoOptions, Options as PrettierOptions} from 'prettier'
11
12
* @import {Difference} from 'prettier-linter-helpers'
12
13
*/
@@ -57,6 +58,42 @@ let prettierFormat;
57
58
// Rule Definition
58
59
// ------------------------------------------------------------------------------
59
60
61
+ /** @type {WeakMap<SourceCode, number[]> } */
62
+ const lineIndexesCache = new WeakMap ( ) ;
63
+
64
+ /**
65
+ * Ponyfill `sourceCode.getLocFromIndex` when it's unavailable.
66
+ *
67
+ * See also `getLocFromIndex` in `@eslint/js`.
68
+ *
69
+ * @param {SourceCode } sourceCode
70
+ * @param {number } index
71
+ * @returns {Position }
72
+ */
73
+ function getLocFromIndex ( sourceCode , index ) {
74
+ if ( typeof sourceCode . getLocFromIndex === 'function' ) {
75
+ return sourceCode . getLocFromIndex ( index ) ;
76
+ }
77
+
78
+ let lineIndexes = lineIndexesCache . get ( sourceCode ) ;
79
+ if ( ! lineIndexes ) {
80
+ lineIndexes = [ ...sourceCode . text . matchAll ( / \r ? \n / g) ] . map (
81
+ match => match . index ,
82
+ ) ;
83
+ // first line in the file starts at byte offset 0
84
+ lineIndexes . unshift ( 0 ) ;
85
+ lineIndexesCache . set ( sourceCode , lineIndexes ) ;
86
+ }
87
+
88
+ let line = 0 ;
89
+ while ( line + 1 < lineIndexes . length && lineIndexes [ line + 1 ] < index ) {
90
+ line += 1 ;
91
+ }
92
+ const column = index - lineIndexes [ line ] ;
93
+
94
+ return { line : line + 1 , column } ;
95
+ }
96
+
60
97
/**
61
98
* Reports a difference.
62
99
*
@@ -71,9 +108,9 @@ function reportDifference(context, difference) {
71
108
// `context.getSourceCode()` was deprecated in ESLint v8.40.0 and replaced
72
109
// with the `sourceCode` property.
73
110
// TODO: Only use property when our eslint peerDependency is >=8.40.0.
74
- const [ start , end ] = range . map ( index =>
75
- ( context . sourceCode ?? context . getSourceCode ( ) ) . getLocFromIndex ( index ) ,
76
- ) ;
111
+ const sourceCode = context . sourceCode ?? context . getSourceCode ( ) ;
112
+
113
+ const [ start , end ] = range . map ( index => getLocFromIndex ( sourceCode , index ) ) ;
77
114
78
115
context . report ( {
79
116
messageId : operation ,
@@ -168,7 +205,8 @@ const eslintPluginPrettier = {
168
205
const source = sourceCode . text ;
169
206
170
207
return {
171
- Program ( node ) {
208
+ /** @param {unknown } node */
209
+ [ sourceCode . ast . type ] ( node ) {
172
210
if ( ! prettierFormat ) {
173
211
// Prettier is expensive to load, so only load it if needed.
174
212
prettierFormat = /** @type {PrettierFormat } */ (
0 commit comments