Fix line numbers in error messages

This commit is contained in:
Pieter Vander Vennet 2022-04-08 17:56:56 +02:00
parent 09dfb13a07
commit 8da4c9a969
4 changed files with 35 additions and 19 deletions

View file

@ -13,6 +13,11 @@ export default class SomeClass {
* SomeClass.get() + 1 // => 43
*
* new OtherClass().doSomething(new SomeClass()) // => 5
*
* const abc = 42
* SomeClass.get() // => abc
* SomeClass.get() + 1 // => abc + 1
*
*/
private static get() : number{
// a comment

View file

@ -26,7 +26,7 @@ export default class ExtractComments {
}
/**
* Gets the actual comments
* Gets the actual comments and their context.
*/
public getComments(): { comment: string, context: Context }[] {
return this.results

View file

@ -25,15 +25,24 @@ export class ScriptExtraction {
return docstring.split("\n").filter(s => s.startsWith("import "));
}
public static extractScripts(docstring: string): { script: Script, name?: string, line: number }[] {
const out = [] as { script: Script, name?: string, line: number }[]
/**
* Extracts the scripts from a comment
*
* // should have correct line numbers
* const extr = ScriptExtraction.extractScripts("some actual comment\n\n42 // => 42\n\n43 // => 43\n44 // => 44\n\n // should be named\n45 // => 45\n")
* extr[0] // => {script: [{lhs: "42", rhs: "42", tag: '==', line: 2}]}
* extr[1] // => {script: [{lhs: "43", rhs: "43", tag: '==', line: 4},{lhs: "44", rhs: "44", tag: '==', line: 5}]}
* extr[2] // => {name: "should be named", script: [{lhs: "45", rhs: "45", tag: '==', line: 8}]}
*/
public static extractScripts(docstring: string): { script: Script, name?: string }[] {
const out = [] as { script: Script, name?: string }[]
function lineIndexOf(part: string): number {
const index = docstring.indexOf(part)
const before = docstring.slice(0, index)
return before.split(/\r\n|\r|\n/).length - 1
}
for (const s of docstring.split(/\n\n+/m)) {
if (!ScriptExtraction.is_doctest(s)) {
@ -42,12 +51,13 @@ export class ScriptExtraction {
const line = lineIndexOf(s)
const script = ScriptExtraction.extractScript(s, line)
let name = undefined
const match = s.match(/^[ \t]*\/\/([^\n]*)/)
if (match !== null) {
name = match[1].trim()
const name = match[1].trim()
out.push({script, name})
} else {
out.push({script})
}
out.push({script, name, line})
}
return out
}
@ -55,25 +65,25 @@ export class ScriptExtraction {
/**
* ScriptExtraction.extractScript('s', 0) // => [{tag: 'Statement', stmt: 's;'}]
* ScriptExtraction.extractScript('e // => 1', 0) // => [{tag: '==', lhs: 'e', rhs: '1', line: 0}]
* ScriptExtraction.extractScript('s; e // => 1', 0) // => [{tag: 'Statement', stmt: 's;'}, {tag: '==', lhs: 'e', rhs: '1', line: 1}]
* ScriptExtraction.extractScript('s;\n e // => 1', 0) // => [{tag: 'Statement', stmt: 's;'}, {tag: '==', lhs: 'e', rhs: '1', line: 1}]
* ScriptExtraction.extractScript('s0\n e0 // => 0 \n e // => 1', 42) // => [{tag: 'Statement', stmt: 's0;'}, {tag: '==', lhs: 'e0', rhs: '0', line: 43}, {tag: '==', lhs: 'e', rhs: '1', line: 44}]
*/
private static extractScript(s: string, linestart: number): Script {
function getLineNumber(pos: number) {
let line = 0;
for (let i = 0; i < pos; i++) {
if (s === "\n") {
for (let i = 0; i <= pos; i++) {
if (s[i] === "\n") {
line++
}
}
return line;
}
const pwoc = ts.createPrinter({removeComments: true})
const ast = ts.createSourceFile('_.ts', s, ts.ScriptTarget.Latest)
return ast.statements.map((stmt, i): Statement | Equality => {
if (ts.isExpressionStatement(stmt)) {
const next = ast.statements[i + 1] // zip with next
const [a, z] = next ? [next.pos, next.end] : [stmt.end, ast.end]
@ -83,8 +93,8 @@ export class ScriptExtraction {
const lhs = pwoc.printNode(ts.EmitHint.Expression, stmt.expression, ast)
const rhs = m[1].trim()
return {tag: '==', lhs, rhs, line: linestart + getLineNumber(stmt.pos)}
return {tag: '==', lhs, rhs, line: linestart + getLineNumber(a)}
}
}

View file

@ -33,7 +33,8 @@ export default class UnitTest {
public static FromComment(comment: string, context: Context): UnitTest[] {
const imports = ScriptExtraction.extractImports(comment)
return ScriptExtraction.extractScripts(comment).map(({script, line, name}, i) =>
return ScriptExtraction.extractScripts(comment).map(
({script, name}, i) =>
new UnitTest(script, {
...context,
linenumber: (context.linenumber ?? 0) ,
@ -63,7 +64,7 @@ export default class UnitTest {
if (s.tag == 'Statement') {
return s.stmt
} else {
return `__expect(${s.lhs}, "failed at ${this.context.functionname} (${this.context.filepath}:${s.line + (this.context.linenumber ?? 0)}:1)").to.deep.equal(${s.rhs})`
return `__expect(${s.lhs}, "failed at ${this.context.functionname} (${this.context.filepath}:${1 + s.line + (this.context.linenumber ?? 0)}:1)").to.deep.equal(${s.rhs})`
}
})
.map(x => '\n ' + x)