|
1 | 1 | /// <reference path="../typings.d.ts" />
|
2 | 2 |
|
3 | 3 | import type { Linter } from 'eslint'
|
4 |
| -import type { SourceLocation } from 'estree' |
5 |
| -import type { Position } from 'unist' |
| 4 | +import type { Position as ESPosition, SourceLocation } from 'estree' |
| 5 | +import type { Point, Position } from 'unist' |
6 | 6 |
|
7 |
| -import type { Arrayable, JsxNode, ParserFn, ParserOptions } from './types' |
| 7 | +import type { |
| 8 | + Arrayable, |
| 9 | + JsxNode, |
| 10 | + ParserFn, |
| 11 | + ParserOptions, |
| 12 | + ValueOf, |
| 13 | +} from './types' |
8 | 14 |
|
9 | 15 | export const FALLBACK_PARSERS = [
|
10 | 16 | '@typescript-eslint/parser',
|
@@ -90,43 +96,55 @@ export const hasProperties = <T, P extends keyof T = keyof T>(
|
90 | 96 | obj &&
|
91 | 97 | properties.every(property => property in obj)
|
92 | 98 |
|
93 |
| -export const restoreNodeLocation = <T>( |
94 |
| - node: T, |
95 |
| - startLine: number, |
96 |
| - offset: number, |
97 |
| -): T => { |
| 99 | +// fix #292 |
| 100 | +export const getPositionAt = (code: string, offset: number): ESPosition => { |
| 101 | + let currOffset = 0 |
| 102 | + |
| 103 | + for (const [index, { length }] of code.split('\n').entries()) { |
| 104 | + const line = index + 1 |
| 105 | + const nextOffset = currOffset + length |
| 106 | + |
| 107 | + if (nextOffset >= offset) { |
| 108 | + return { |
| 109 | + line, |
| 110 | + column: offset - currOffset, |
| 111 | + } |
| 112 | + } |
| 113 | + |
| 114 | + currOffset = nextOffset + 1 // add a line break `\n` offset |
| 115 | + } |
| 116 | +} |
| 117 | + |
| 118 | +export const restoreNodeLocation = <T>(node: T, point: Point): T => { |
98 | 119 | if (node && typeof node === 'object') {
|
99 |
| - for (const value of Object.values(node)) { |
100 |
| - restoreNodeLocation(value, startLine, offset) |
| 120 | + for (const value of Object.values(node) as Array<ValueOf<T>>) { |
| 121 | + restoreNodeLocation(value, point) |
101 | 122 | }
|
102 | 123 | }
|
103 | 124 |
|
104 | 125 | if (!hasProperties<BaseNode>(node, ['loc', 'range'])) {
|
105 | 126 | return node
|
106 | 127 | }
|
107 | 128 |
|
108 |
| - const { |
| 129 | + let { |
109 | 130 | loc: { start: startLoc, end: endLoc },
|
110 |
| - range, |
| 131 | + range: [start, end], |
111 | 132 | } = node
|
112 |
| - const start = range[0] + offset |
113 |
| - const end = range[1] + offset |
114 | 133 |
|
115 |
| - const restoredStartLine = startLine + startLoc.line |
116 |
| - const restoredEndLine = startLine + endLoc.line |
| 134 | + const range = [(start += point.offset), (end += point.offset)] as const |
117 | 135 |
|
118 | 136 | return Object.assign(node, {
|
119 | 137 | start,
|
120 | 138 | end,
|
121 |
| - range: [start, end], |
| 139 | + range, |
122 | 140 | loc: {
|
123 | 141 | start: {
|
124 |
| - line: restoredStartLine, |
125 |
| - column: startLoc.column + (restoredStartLine === 1 ? offset : 0), |
| 142 | + line: point.line + startLoc.line, |
| 143 | + column: startLoc.column + (startLoc.line === 1 ? point.column : 0), |
126 | 144 | },
|
127 | 145 | end: {
|
128 |
| - line: restoredEndLine, |
129 |
| - column: endLoc.column + (restoredEndLine === 1 ? offset : 0), |
| 146 | + line: point.line + endLoc.line, |
| 147 | + column: endLoc.column + (endLoc.line === 1 ? point.column : 0), |
130 | 148 | },
|
131 | 149 | },
|
132 | 150 | })
|
|
0 commit comments