refactor(compiler): add ability to get the context around a `ParseLocation` (#14113)
This commit is contained in:
parent
80b9570dca
commit
5885c52c1f
|
@ -48,6 +48,51 @@ export class ParseLocation {
|
||||||
}
|
}
|
||||||
return new ParseLocation(this.file, offset, line, col);
|
return new ParseLocation(this.file, offset, line, col);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the source around the location
|
||||||
|
// Up to `maxChars` or `maxLines` on each side of the location
|
||||||
|
getContext(maxChars: number, maxLines: number): {before: string, after: string} {
|
||||||
|
const content = this.file.content;
|
||||||
|
let startOffset = this.offset;
|
||||||
|
|
||||||
|
if (isPresent(startOffset)) {
|
||||||
|
if (startOffset > content.length - 1) {
|
||||||
|
startOffset = content.length - 1;
|
||||||
|
}
|
||||||
|
let endOffset = startOffset;
|
||||||
|
let ctxChars = 0;
|
||||||
|
let ctxLines = 0;
|
||||||
|
|
||||||
|
while (ctxChars < maxChars && startOffset > 0) {
|
||||||
|
startOffset--;
|
||||||
|
ctxChars++;
|
||||||
|
if (content[startOffset] == '\n') {
|
||||||
|
if (++ctxLines == maxLines) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ctxChars = 0;
|
||||||
|
ctxLines = 0;
|
||||||
|
while (ctxChars < maxChars && endOffset < content.length - 1) {
|
||||||
|
endOffset++;
|
||||||
|
ctxChars++;
|
||||||
|
if (content[endOffset] == '\n') {
|
||||||
|
if (++ctxLines == maxLines) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
before: content.substring(startOffset, this.offset),
|
||||||
|
after: content.substring(this.offset, endOffset + 1),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ParseSourceFile {
|
export class ParseSourceFile {
|
||||||
|
@ -74,47 +119,9 @@ export class ParseError {
|
||||||
public level: ParseErrorLevel = ParseErrorLevel.FATAL) {}
|
public level: ParseErrorLevel = ParseErrorLevel.FATAL) {}
|
||||||
|
|
||||||
toString(): string {
|
toString(): string {
|
||||||
const source = this.span.start.file.content;
|
const ctx = this.span.start.getContext(100, 3);
|
||||||
let ctxStart = this.span.start.offset;
|
const contextStr = ctx ? ` ("${ctx.before}[ERROR ->]${ctx.after}")` : '';
|
||||||
let contextStr = '';
|
const details = this.span.details ? `, ${this.span.details}` : '';
|
||||||
let details = '';
|
|
||||||
if (isPresent(ctxStart)) {
|
|
||||||
if (ctxStart > source.length - 1) {
|
|
||||||
ctxStart = source.length - 1;
|
|
||||||
}
|
|
||||||
let ctxEnd = ctxStart;
|
|
||||||
let ctxLen = 0;
|
|
||||||
let ctxLines = 0;
|
|
||||||
|
|
||||||
while (ctxLen < 100 && ctxStart > 0) {
|
|
||||||
ctxStart--;
|
|
||||||
ctxLen++;
|
|
||||||
if (source[ctxStart] == '\n') {
|
|
||||||
if (++ctxLines == 3) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ctxLen = 0;
|
|
||||||
ctxLines = 0;
|
|
||||||
while (ctxLen < 100 && ctxEnd < source.length - 1) {
|
|
||||||
ctxEnd++;
|
|
||||||
ctxLen++;
|
|
||||||
if (source[ctxEnd] == '\n') {
|
|
||||||
if (++ctxLines == 3) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const context = source.substring(ctxStart, this.span.start.offset) + '[ERROR ->]' +
|
|
||||||
source.substring(this.span.start.offset, ctxEnd + 1);
|
|
||||||
contextStr = ` ("${context}")`;
|
|
||||||
}
|
|
||||||
if (this.span.details) {
|
|
||||||
details = `, ${this.span.details}`;
|
|
||||||
}
|
|
||||||
return `${this.msg}${contextStr}: ${this.span.start}${details}`;
|
return `${this.msg}${contextStr}: ${this.span.start}${details}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue