Skip to content

Commit 677ff0d

Browse files
authored
Refactor (#306)
1 parent 5441a14 commit 677ff0d

File tree

17 files changed

+76
-179
lines changed

17 files changed

+76
-179
lines changed

src/parse.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,36 +8,32 @@ import { removeFakeNodes } from "./utils/remove-fake-nodes.js";
88
import { updatePositions } from "./utils/update-positions.js";
99

1010
export function parse(text: string, options?: ParseOptions): Root {
11-
const parser = new YAML.Parser();
11+
const lineCounter = new YAML.LineCounter();
12+
const parser = new YAML.Parser(lineCounter.addNewLine);
1213
const composer = new YAML.Composer({
1314
keepSourceTokens: true,
1415
// Intentionally to not cast to boolean, so user can pass a function (undocumented)
1516
// https://eemeli.org/yaml/#options
1617
uniqueKeys: options?.uniqueKeys,
18+
lineCounter,
1719
});
1820
const documentNodes: YAML.Document.Parsed[] = [];
1921
const cstTokens: YAML.CST.Token[] = [];
20-
const context = new Context(text);
22+
const context = new Context(text, lineCounter);
2123

2224
for (const cst of parser.parse(text)) {
2325
cstTokens.push(cst);
2426
for (const doc of composer.next(cst)) {
25-
documentNodes.push(doc);
27+
documentNodes.push(throwParseError(doc, context));
2628
}
2729
}
2830

2931
for (const doc of composer.end()) {
30-
documentNodes.push(doc);
31-
}
32-
33-
for (const doc of documentNodes) {
34-
for (const error of doc.errors) {
35-
throw transformError(error, context);
36-
}
32+
documentNodes.push(throwParseError(doc, context));
3733
}
3834

3935
const root = createRoot(
40-
context.transformRange({ origStart: 0, origEnd: text.length }),
36+
context.transformRange([0, text.length]),
4137
context.transformDocuments(documentNodes, cstTokens),
4238
context.comments,
4339
);
@@ -48,3 +44,11 @@ export function parse(text: string, options?: ParseOptions): Root {
4844

4945
return root;
5046
}
47+
48+
function throwParseError(document: YAML.Document.Parsed, context: Context) {
49+
const { errors } = document;
50+
if (errors.length > 0) {
51+
throw transformError(errors[0], context);
52+
}
53+
return document;
54+
}

src/transforms/alias.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@ export function transformAlias(
1717
}
1818

1919
return createAlias(
20-
context.transformRange({
21-
origStart: alias.range[0],
22-
origEnd: alias.range[1],
23-
}),
20+
context.transformRange(alias.range),
2421
context.transformContentProperties(alias, props.tokens),
2522
alias.source,
2623
);

src/transforms/block-value.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,7 @@ export function transformAstBlockValue(
3434

3535
const headerInfo = parseHeader(blockScalarHeaderToken.source);
3636

37-
const position = context.transformRange({
38-
origStart: blockValue.range[0],
39-
origEnd: blockValue.range[1],
40-
});
37+
const position = context.transformRange(blockValue.range);
4138

4239
return createBlockValue(
4340
position,

src/transforms/comment.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@ export function transformComment(
88
context: Context,
99
): Comment {
1010
return createComment(
11-
context.transformRange({
12-
origStart: comment.offset,
13-
origEnd: comment.offset + comment.source.length,
14-
}),
11+
context.transformRange([
12+
comment.offset,
13+
comment.offset + comment.source.length,
14+
]),
1515
comment.source.slice(1),
1616
);
1717
}

src/transforms/content.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,14 @@ export function transformContentProperties(
2323
let anchor: Anchor | null = null;
2424

2525
for (const token of tokens) {
26-
const tokenRange: Range = {
27-
origStart: token.offset,
28-
origEnd: token.offset + token.source.length,
29-
};
26+
const tokenRange: Range = [
27+
token.offset,
28+
token.offset + token.source.length,
29+
];
3030
switch (token.type) {
3131
case "tag":
3232
{
33-
firstTagOrAnchorRange = firstTagOrAnchorRange || tokenRange;
33+
firstTagOrAnchorRange ??= tokenRange;
3434
let resolvedTag =
3535
node.tag ??
3636
token.source.slice(token.source.startsWith("!!") ? 2 : 1);
@@ -41,15 +41,15 @@ export function transformContentProperties(
4141
}
4242
break;
4343
case "anchor":
44-
firstTagOrAnchorRange = firstTagOrAnchorRange || tokenRange;
44+
firstTagOrAnchorRange ??= tokenRange;
4545
anchor = createAnchor(context.transformRange(tokenRange), node.anchor!);
4646
break;
4747
case "comment": {
4848
const comment = context.transformComment(token);
4949
if (
5050
firstTagOrAnchorRange &&
51-
firstTagOrAnchorRange.origEnd <= tokenRange.origStart &&
52-
tokenRange.origEnd <= node.range[0]
51+
firstTagOrAnchorRange[0] <= tokenRange[0] &&
52+
tokenRange[1] <= node.range[0]
5353
) {
5454
middleComments.push(comment);
5555
}

src/transforms/context.ts

Lines changed: 6 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -22,33 +22,20 @@ import {
2222
class Context {
2323
text;
2424
comments: Comment[] = [];
25-
#linesAndColumns: LinesAndColumns;
25+
#lineCounter: YAML.LineCounter;
2626

27-
constructor(text: string) {
27+
constructor(text: string, lineCounter: YAML.LineCounter) {
2828
this.text = text;
29-
this.#linesAndColumns = new LinesAndColumns(text);
30-
}
31-
32-
#getRangePosition(range: Range): { start: Point; end: Point } {
33-
if (this.text === "" && range.origStart === 0 && range.origEnd === 0) {
34-
return {
35-
start: { offset: 0, line: 1, column: 1 },
36-
end: { offset: 0, line: 1, column: 1 },
37-
};
38-
}
39-
40-
return {
41-
start: this.#linesAndColumns.getPoint(range.origStart),
42-
end: this.#linesAndColumns.getPoint(range.origEnd),
43-
};
29+
this.#lineCounter = lineCounter;
4430
}
4531

4632
transformOffset(offset: number): Point {
47-
return this.#linesAndColumns.getPoint(offset);
33+
const { line, col } = this.#lineCounter.linePos(offset);
34+
return { line, column: col, offset };
4835
}
4936

5037
transformRange(range: Range): Position {
51-
const { start, end } = this.#getRangePosition(range);
38+
const [start, end] = range.map(position => this.transformOffset(position));
5239
return createPosition(start, end);
5340
}
5441

@@ -85,58 +72,3 @@ class Context {
8572
}
8673

8774
export default Context;
88-
89-
class LinesAndColumns {
90-
private lineBreakIndices: number[];
91-
92-
constructor(text: string) {
93-
this.lineBreakIndices = [];
94-
for (let i = 0; i < text.length; i++) {
95-
const ch = text[i];
96-
if (ch === "\n") {
97-
this.lineBreakIndices.push(i);
98-
} else if (ch === "\r") {
99-
if (i + 1 < text.length && text[i + 1] === "\n") {
100-
this.lineBreakIndices.push(i + 1);
101-
i++;
102-
} else {
103-
this.lineBreakIndices.push(i);
104-
}
105-
}
106-
}
107-
}
108-
109-
/**
110-
* Get line and column for the given offset.
111-
* @param offset 0-based offset
112-
* @returns 1-based line and 1-based column
113-
*/
114-
getPoint(offset: number): Point {
115-
let low = 0;
116-
let high = this.lineBreakIndices.length - 1;
117-
118-
while (low <= high) {
119-
const mid = Math.floor((low + high) / 2);
120-
const lineBreakIndex = this.lineBreakIndices[mid];
121-
122-
if (lineBreakIndex < offset) {
123-
low = mid + 1;
124-
} else if (lineBreakIndex > offset) {
125-
high = mid - 1;
126-
} else {
127-
return {
128-
line: mid + 1,
129-
column:
130-
mid === 0 ? offset + 1 : offset - this.lineBreakIndices[mid - 1],
131-
offset,
132-
};
133-
}
134-
}
135-
136-
const line = low + 1;
137-
const lineStartIndex = low === 0 ? 0 : this.lineBreakIndices[low - 1] + 1;
138-
const column = offset - lineStartIndex + 1;
139-
140-
return { line, column, offset };
141-
}
142-
}

src/transforms/directive.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ export function transformDirective(
1010
const parts = directive.source.trim().split(/[\t ]+/);
1111
const name = parts.shift()!.replace(/^%/, "");
1212
return createDirective(
13-
context.transformRange({
14-
origStart: directive.offset,
15-
origEnd: directive.offset + directive.source.length,
16-
}),
13+
context.transformRange([
14+
directive.offset,
15+
directive.offset + directive.source.length,
16+
]),
1717
name,
1818
parts,
1919
);

src/transforms/document-body.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,7 @@ function getPosition(
147147
}
148148
}
149149

150-
const position = context.transformRange({
151-
origStart,
152-
origEnd,
153-
});
150+
const position = context.transformRange([origStart, origEnd]);
154151

155152
const documentEndPoint = docEnd
156153
? context.transformOffset(docEnd.offset + docEnd.source.length)

src/transforms/document-head.ts

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -104,22 +104,13 @@ function getPosition(
104104
context: Context,
105105
) {
106106
const range: Range = docStart
107-
? {
108-
origStart: docStart.offset,
109-
origEnd: docStart.offset + docStart.source.length,
110-
}
107+
? [docStart.offset, docStart.offset + docStart.source.length]
111108
: document.contents
112-
? {
113-
origStart: document.contents.range[0],
114-
origEnd: document.contents.range[0],
115-
}
116-
: {
117-
origStart: document.range[0],
118-
origEnd: document.range[0],
119-
};
109+
? [document.contents.range[0], document.contents.range[0]]
110+
: [document.range[0], document.range[0]];
120111

121112
if (directives.length !== 0) {
122-
range.origStart = directives[0].position.start.offset;
113+
range[0] = directives[0].position.start.offset;
123114
}
124115

125116
return context.transformRange(range);

src/transforms/error.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,6 @@ export function transformError(
1111
return createError(
1212
error.message,
1313
context.text,
14-
context.transformRange({
15-
origStart: range[0],
16-
origEnd: range[1],
17-
}),
14+
context.transformRange(range),
1815
);
1916
}

0 commit comments

Comments
 (0)