Skip to content

Commit

Permalink
fix: caret position was incorrect (#14984)
Browse files Browse the repository at this point in the history
  • Loading branch information
sapphi-red authored Nov 15, 2023
1 parent c61c376 commit 2b4e793
Show file tree
Hide file tree
Showing 7 changed files with 184 additions and 31 deletions.
93 changes: 93 additions & 0 deletions packages/vite/src/node/__tests__/__snapshots__/utils.spec.ts.snap
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html

exports[`generateCodeFrames > end 1`] = `
"
1 | import foo from './foo'
| ^
2 | foo()
"
`;

exports[`generateCodeFrames > end 2`] = `
"
1 | import foo from './foo'
| ^^^^^^^^^^^^^^^^^^^^^^^
2 | foo()
"
`;

exports[`generateCodeFrames > end 3`] = `
"
1 | import foo from './foo'
| ^^^^^^^^^^^^^^^^^^^^^^^
2 | foo()
| ^^^^^
"
`;

exports[`generateCodeFrames > range 1`] = `
"
1 |
2 | import foo from './foo'
3 |
| ^
4 | foo()
5 |
"
`;

exports[`generateCodeFrames > start with number 1`] = `
"
1 | import foo from './foo'
| ^
2 | foo()
"
`;

exports[`generateCodeFrames > start with number 2`] = `
"
1 | import foo from './foo'
| ^
2 | foo()
"
`;

exports[`generateCodeFrames > start with number 3`] = `
"
1 | import foo from './foo'
2 | foo()
| ^
"
`;

exports[`generateCodeFrames > start with postion 1`] = `
"
1 | import foo from './foo'
| ^
2 | foo()
"
`;

exports[`generateCodeFrames > start with postion 2`] = `
"
1 | import foo from './foo'
| ^
2 | foo()
"
`;

exports[`generateCodeFrames > start with postion 3`] = `
"
1 | import foo from './foo'
2 | foo()
| ^
"
`;

exports[`generateCodeFrames > works with CRLF 1`] = `
"
1 | import foo from './foo'
2 | foo()
| ^
"
`;
54 changes: 54 additions & 0 deletions packages/vite/src/node/__tests__/utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
asyncFlatten,
bareImportRE,
flattenId,
generateCodeFrame,
getHash,
getLocalhostAddressIfDiffersFromDNS,
injectQuery,
Expand Down Expand Up @@ -176,6 +177,59 @@ describe('posToNumber', () => {
})
})

describe('generateCodeFrames', () => {
const source = `
import foo from './foo'
foo()
`.trim()
const sourceCrLf = source.replace(/\n/, '\r\n')
const longSource = `
import foo from './foo'
foo()
// bar
// baz
`

const expectSnapshot = (value: string) => {
try {
// add new line to make snapshot easier to read
expect('\n' + value + '\n').toMatchSnapshot()
} catch (e) {
// don't include this function in stacktrace
Error.captureStackTrace(e, expectSnapshot)
throw e
}
}

test('start with number', () => {
expectSnapshot(generateCodeFrame(source, 0))
expectSnapshot(generateCodeFrame(source, 1))
expectSnapshot(generateCodeFrame(source, 24))
})

test('start with postion', () => {
expectSnapshot(generateCodeFrame(source, { line: 1, column: 0 }))
expectSnapshot(generateCodeFrame(source, { line: 1, column: 1 }))
expectSnapshot(generateCodeFrame(source, { line: 2, column: 0 }))
})

test('works with CRLF', () => {
expectSnapshot(generateCodeFrame(sourceCrLf, { line: 2, column: 0 }))
})

test('end', () => {
expectSnapshot(generateCodeFrame(source, 0, 0))
expectSnapshot(generateCodeFrame(source, 0, 23))
expectSnapshot(generateCodeFrame(source, 0, 29))
})

test('range', () => {
expectSnapshot(generateCodeFrame(longSource, { line: 3, column: 0 }))
})
})

describe('getHash', () => {
test('8-digit hex', () => {
const hash = getHash(Buffer.alloc(0))
Expand Down
22 changes: 15 additions & 7 deletions packages/vite/src/node/plugins/css.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1185,13 +1185,21 @@ async function compileCSS(
deps.add(files[i])
}
} else if (message.type === 'warning') {
let msg = `[vite:css] ${message.text}`
if (message.line && message.column) {
msg += `\n${generateCodeFrame(code, {
line: message.line,
column: message.column,
})}`
}
const warning = message as PostCSS.Warning
let msg = `[vite:css] ${warning.text}`
msg += `\n${generateCodeFrame(
code,
{
line: warning.line,
column: warning.column,
},
warning.endLine !== undefined && warning.endColumn !== undefined
? {
line: warning.endLine,
column: warning.endColumn,
}
: undefined,
)}`
config.logger.warn(colors.yellow(msg))
}
}
Expand Down
10 changes: 1 addition & 9 deletions packages/vite/src/node/plugins/esbuild.ts
Original file line number Diff line number Diff line change
Expand Up @@ -433,15 +433,7 @@ export function resolveEsbuildTranspileOptions(
function prettifyMessage(m: Message, code: string): string {
let res = colors.yellow(m.text)
if (m.location) {
const lines = code.split(/\r?\n/g)
const line = Number(m.location.line)
const column = Number(m.location.column)
const offset =
lines
.slice(0, line - 1)
.map((l) => l.length)
.reduce((total, l) => total + l + 1, 0) + column
res += `\n` + generateCodeFrame(code, offset, offset + 1)
res += `\n` + generateCodeFrame(code, m.location)
}
return res + `\n`
}
Expand Down
6 changes: 5 additions & 1 deletion packages/vite/src/node/plugins/html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,11 @@ function formatParseError(parserError: ParserError, id: string, html: string) {
const formattedError = {
code: parserError.code,
message: `parse5 error code ${parserError.code}`,
frame: generateCodeFrame(html, parserError.startOffset),
frame: generateCodeFrame(
html,
parserError.startOffset,
parserError.endOffset,
),
loc: {
file: id,
line: parserError.startLine,
Expand Down
2 changes: 1 addition & 1 deletion packages/vite/src/node/plugins/importAnalysis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ export function importAnalysisPlugin(config: ResolvedConfig): Plugin {
`\n` +
colors.cyan(importerModule.file) +
`\n` +
colors.reset(generateCodeFrame(source, start)) +
colors.reset(generateCodeFrame(source, start, end)) +
colors.yellow(
`\nThe above dynamic import cannot be analyzed by Vite.\n` +
`See ${colors.blue(
Expand Down
28 changes: 15 additions & 13 deletions packages/vite/src/node/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -460,10 +460,14 @@ export function pad(source: string, n = 2): string {
return lines.map((l) => ` `.repeat(n) + l).join(`\n`)
}

export function posToNumber(
source: string,
pos: number | { line: number; column: number },
): number {
type Pos = {
/** 1-based */
line: number
/** 0-based */
column: number
}

export function posToNumber(source: string, pos: number | Pos): number {
if (typeof pos === 'number') return pos
const lines = source.split(splitRE)
const { line, column } = pos
Expand All @@ -474,10 +478,7 @@ export function posToNumber(
return start + column
}

export function numberToPos(
source: string,
offset: number | { line: number; column: number },
): { line: number; column: number } {
export function numberToPos(source: string, offset: number | Pos): Pos {
if (typeof offset !== 'number') return offset
if (offset > source.length) {
throw new Error(
Expand All @@ -501,16 +502,16 @@ export function numberToPos(

export function generateCodeFrame(
source: string,
start: number | { line: number; column: number } = 0,
end?: number,
start: number | Pos = 0,
end?: number | Pos,
): string {
start = posToNumber(source, start)
end = end || start
end = end !== undefined ? posToNumber(source, end) : start
const lines = source.split(splitRE)
let count = 0
const res: string[] = []
for (let i = 0; i < lines.length; i++) {
count += lines[i].length + 1
count += lines[i].length
if (count >= start) {
for (let j = i - range; j <= i + range || end > count; j++) {
if (j < 0 || j >= lines.length) continue
Expand All @@ -523,7 +524,7 @@ export function generateCodeFrame(
const lineLength = lines[j].length
if (j === i) {
// push underline
const pad = Math.max(start - (count - lineLength) + 1, 0)
const pad = Math.max(start - (count - lineLength), 0)
const length = Math.max(
1,
end > count ? lineLength - pad : end - start,
Expand All @@ -539,6 +540,7 @@ export function generateCodeFrame(
}
break
}
count++
}
return res.join('\n')
}
Expand Down

0 comments on commit 2b4e793

Please sign in to comment.