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 */
@@ -57,6 +58,42 @@ let prettierFormat;
5758// Rule Definition
5859// ------------------------------------------------------------------------------
5960
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+
6097/**
6198 * Reports a difference.
6299 *
@@ -71,9 +108,9 @@ function reportDifference(context, difference) {
71108 // `context.getSourceCode()` was deprecated in ESLint v8.40.0 and replaced
72109 // with the `sourceCode` property.
73110 // 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 ) ) ;
77114
78115 context . report ( {
79116 messageId : operation ,
@@ -168,7 +205,8 @@ const eslintPluginPrettier = {
168205 const source = sourceCode . text ;
169206
170207 return {
171- Program ( node ) {
208+ /** @param {unknown } node */
209+ [ sourceCode . ast . type ] ( node ) {
172210 if ( ! prettierFormat ) {
173211 // Prettier is expensive to load, so only load it if needed.
174212 prettierFormat = /** @type {PrettierFormat } */ (
0 commit comments