/
githubmirror
/
babel
Обзор
Документация
Войти
/
githubmirror
/
babel
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
packages/babel-code-frame/test/index.js
517 строк
13 KB
Nehemiya Wickramasinghe
breaking(code-frame): use 0-based columns to match Babel AST locations (#1… (#17849)
11 май 2026, 16:38
Не верифицирован
11 май 2026, 16:38
e77fa07
Код
Авторство
О чём код?
import { stripVTControlCharacters } from "node:util"; import { codeFrameColumns, highlight } from "../lib/index.js"; describe("@babel/code-frame", function () { test("basic usage", function () { const rawLines = ["class Foo {", " constructor()", "};"].join("\n"); expect( codeFrameColumns(rawLines, { start: { line: 2, column: 15 } }), ).toEqual( [ " 1 | class Foo {", "> 2 | constructor()", " | ^", " 3 | };", ].join("\n"), ); }); test("optional column number", function () { const rawLines = ["class Foo {", " constructor()", "};"].join("\n"); expect( codeFrameColumns(rawLines, { start: { line: 2, column: null } }), ).toEqual( [" 1 | class Foo {", "> 2 | constructor()", " 3 | };"].join("\n"), ); }); test("maximum context lines and padding", function () { const rawLines = [ "/**", " * Sums two numbers.", " *", " * @param a Number", " * @param b Number", " * @returns Number", " */", "", "function sum(a, b) {", " return a + b", "}", ].join("\n"); expect( codeFrameColumns(rawLines, { start: { line: 7, column: 1 } }), ).toEqual( [ " 5 | * @param b Number", " 6 | * @returns Number", "> 7 | */", " | ^", " 8 |", " 9 | function sum(a, b) {", " 10 | return a + b", ].join("\n"), ); }); test("no unnecessary padding due to one-off errors", function () { const rawLines = [ "/**", " * Sums two numbers.", " *", " * @param a Number", " * @param b Number", " * @returns Number", " */", "", "function sum(a, b) {", " return a + b", "}", ].join("\n"); expect( codeFrameColumns(rawLines, { start: { line: 6, column: 1 } }), ).toEqual( [ " 4 | * @param a Number", " 5 | * @param b Number", "> 6 | * @returns Number", " | ^", " 7 | */", " 8 |", " 9 | function sum(a, b) {", ].join("\n"), ); }); test("tabs", function () { const rawLines = [ "\tclass Foo {", "\t \t\t constructor\t(\t)", "\t};", ].join("\n"); expect( codeFrameColumns(rawLines, { start: { line: 2, column: 24 } }), ).toEqual( [ " 1 | \tclass Foo {", "> 2 | \t \t\t constructor\t(\t)", " | \t \t\t \t \t ^", " 3 | \t};", ].join("\n"), ); }); test("opts.linesAbove", function () { const rawLines = [ "/**", " * Sums two numbers.", " *", " * @param a Number", " * @param b Number", " * @returns Number", " */", "", "function sum(a, b) {", " return a + b", "}", ].join("\n"); expect( codeFrameColumns( rawLines, { start: { line: 7, column: 1 } }, { linesAbove: 1 }, ), ).toEqual( [ " 6 | * @returns Number", "> 7 | */", " | ^", " 8 |", " 9 | function sum(a, b) {", " 10 | return a + b", ].join("\n"), ); }); test("opts.linesBelow", function () { const rawLines = [ "/**", " * Sums two numbers.", " *", " * @param a Number", " * @param b Number", " * @returns Number", " */", "", "function sum(a, b) {", " return a + b", "}", ].join("\n"); expect( codeFrameColumns( rawLines, { start: { line: 7, column: 1 } }, { linesBelow: 1 }, ), ).toEqual( [ " 5 | * @param b Number", " 6 | * @returns Number", "> 7 | */", " | ^", " 8 |", ].join("\n"), ); }); test("opts.linesAbove and opts.linesBelow", function () { const rawLines = [ "/**", " * Sums two numbers.", " *", " * @param a Number", " * @param b Number", " * @returns Number", " */", "", "function sum(a, b) {", " return a + b", "}", ].join("\n"); expect( codeFrameColumns( rawLines, { start: { line: 7, column: 1 } }, { linesAbove: 1, linesBelow: 1 }, ), ).toEqual( [" 6 | * @returns Number", "> 7 | */", " | ^", " 8 |"].join("\n"), ); }); test("opts.linesAbove no lines above", function () { const rawLines = [ "class Foo {", " constructor() {", " console.log(arguments);", " }", "};", ].join("\n"); expect( codeFrameColumns(rawLines, { start: { line: 2 } }, { linesAbove: 0 }), ).toEqual( [ "> 2 | constructor() {", " 3 | console.log(arguments);", " 4 | }", " 5 | };", ].join("\n"), ); }); test("opts.linesBelow no lines below", function () { const rawLines = [ "class Foo {", " constructor() {", " console.log(arguments);", " }", "};", ].join("\n"); expect( codeFrameColumns(rawLines, { start: { line: 2 } }, { linesBelow: 0 }), ).toEqual([" 1 | class Foo {", "> 2 | constructor() {"].join("\n")); }); test("opts.linesBelow single line", function () { const rawLines = [ "class Foo {", " constructor() {", " console.log(arguments);", " }", "};", ].join("\n"); expect( codeFrameColumns( rawLines, { start: { line: 2 } }, { linesAbove: 0, linesBelow: 0 }, ), ).toEqual(["> 2 | constructor() {"].join("\n")); }); test("basic usage, new API", function () { const rawLines = ["class Foo {", " constructor()", "};"].join("\n"); expect( codeFrameColumns(rawLines, { start: { line: 2, column: 15 } }), ).toEqual( [ " 1 | class Foo {", "> 2 | constructor()", " | ^", " 3 | };", ].join("\n"), ); }); test("mark multiple columns", function () { const rawLines = ["class Foo {", " constructor()", "};"].join("\n"); expect( codeFrameColumns(rawLines, { start: { line: 2, column: 2 }, end: { line: 2, column: 15 }, }), ).toEqual( [ " 1 | class Foo {", "> 2 | constructor()", " | ^^^^^^^^^^^^^", " 3 | };", ].join("\n"), ); }); test("mark multiple columns across lines", function () { const rawLines = ["class Foo {", " constructor() {", " }", "};"].join( "\n", ); expect( codeFrameColumns(rawLines, { start: { line: 2, column: 16 }, end: { line: 3, column: 3 }, }), ).toEqual( [ " 1 | class Foo {", "> 2 | constructor() {", " | ^", "> 3 | }", " | ^^^", " 4 | };", ].join("\n"), ); }); test("mark multiple columns across multiple lines", function () { const rawLines = [ "class Foo {", " constructor() {", " console.log(arguments);", " }", "};", ].join("\n"); expect( codeFrameColumns(rawLines, { start: { line: 2, column: 16 }, end: { line: 4, column: 3 }, }), ).toEqual( [ " 1 | class Foo {", "> 2 | constructor() {", " | ^", "> 3 | console.log(arguments);", " | ^^^^^^^^^^^^^^^^^^^^^^^^^^^", "> 4 | }", " | ^^^", " 5 | };", ].join("\n"), ); }); test("mark across multiple lines without columns", function () { const rawLines = [ "class Foo {", " constructor() {", " console.log(arguments);", " }", "};", ].join("\n"); expect( codeFrameColumns(rawLines, { start: { line: 2 }, end: { line: 4 } }), ).toEqual( [ " 1 | class Foo {", "> 2 | constructor() {", "> 3 | console.log(arguments);", "> 4 | }", " 5 | };", ].join("\n"), ); }); test("opts.message", function () { const rawLines = ["class Foo {", " constructor()", "};"].join("\n"); expect( codeFrameColumns( rawLines, { start: { line: 2, column: 15 } }, { message: "Missing {", }, ), ).toEqual( [ " 1 | class Foo {", "> 2 | constructor()", " | ^ Missing {", " 3 | };", ].join("\n"), ); }); test("opts.message without column", function () { const rawLines = ["class Foo {", " constructor()", "};"].join("\n"); expect( codeFrameColumns( rawLines, { start: { line: 2 } }, { message: "Missing {", }, ), ).toEqual( [ " Missing {", " 1 | class Foo {", "> 2 | constructor()", " 3 | };", ].join("\n"), ); }); test("opts.message with multiple lines", function () { const rawLines = [ "class Foo {", " constructor() {", " console.log(arguments);", " }", "};", ].join("\n"); expect( codeFrameColumns( rawLines, { start: { line: 2, column: 16 }, end: { line: 4, column: 3 }, }, { message: "something about the constructor body", }, ), ).toEqual( [ " 1 | class Foo {", "> 2 | constructor() {", " | ^", "> 3 | console.log(arguments);", " | ^^^^^^^^^^^^^^^^^^^^^^^^^^^", "> 4 | }", " | ^^^ something about the constructor body", " 5 | };", ].join("\n"), ); }); test("opts.message with multiple lines without columns", function () { const rawLines = [ "class Foo {", " constructor() {", " console.log(arguments);", " }", "};", ].join("\n"); expect( codeFrameColumns( rawLines, { start: { line: 2 }, end: { line: 4 } }, { message: "something about the constructor body", }, ), ).toEqual( [ " something about the constructor body", " 1 | class Foo {", "> 2 | constructor() {", "> 3 | console.log(arguments);", "> 4 | }", " 5 | };", ].join("\n"), ); }); test("highlight works", function () { const raw = "const a = 1"; const highlighted = highlight(raw); expect(stripVTControlCharacters(highlighted)).toBe(raw); expect(highlighted.length).toBeGreaterThan(raw.length); }); test("opts.startLine", function () { const rawLines = "const a = 1;\nconst b = 1"; expect( codeFrameColumns(rawLines, { start: { line: 102 } }, { startLine: 101 }), ).toMatchInlineSnapshot(` " 101 | const a = 1; > 102 | const b = 1" `); }); test("should handle 0-based columns from Babel AST locations", function () { const code = 'x = "foobar";'; // "foobar" (with quotes) starts at column 4 (0-based), ends at column 12 (0-based exclusive) const loc = { start: { line: 1, column: 4 }, end: { line: 1, column: 12 }, }; const result = codeFrameColumns(code, loc); // The underline should cover "foobar" (with quotes) starting at the correct position expect(result).toEqual( ['> 1 | x = "foobar";', " | ^^^^^^^^"].join("\n"), ); }); test("should handle 0-based column 0", function () { const code = '"foobar";'; const loc = { start: { line: 1, column: 0 }, end: { line: 1, column: 8 }, }; const result = codeFrameColumns(code, loc); expect(result).toEqual(['> 1 | "foobar";', " | ^^^^^^^^"].join("\n")); }); test("middle lines in a 4+ line range use each line's own length", function () { const rawLines = [ "class Foo {", " constructor() {", " short", " a much longer middle line here", " end", " }", "};", ].join("\n"); expect( codeFrameColumns(rawLines, { start: { line: 2, column: 16 }, end: { line: 6, column: 3 }, }), ).toEqual( [ " 1 | class Foo {", "> 2 | constructor() {", " | ^", "> 3 | short", " | ^^^^^^^^^", "> 4 | a much longer middle line here", " | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^", "> 5 | end", " | ^^^^^^^", "> 6 | }", " | ^^^", " 7 | };", ].join("\n"), ); }); });