cordis/stack-trace/stack-trace.ts

74 lines
2.3 KiB
TypeScript

import * as path from 'path';
export interface Frame {
functionName?: string;
fileName: string;
line?: number;
column?: number;
}
/** Converts an error into a list of frames based on the error stack */
export function parse(err: Error): Frame[] {
if (!err.stack) {
return [];
}
const lines = err.stack.split('\n').slice(1);
return lines
.map(function(line: string): Frame {
if (line.match(/^\s*[-]{4,}$/)) {
return { fileName: line };
}
let pieces = line.trim().split(' ');
// pieces[0] will always be 'at'
function parseData(fileUri: string, functionName?: string): Frame {
let pieces = fileUri.split(':');
let column: number | undefined = parseInt(pieces[pieces.length - 1]); if (Number.isNaN(column)) column = undefined;
let line: number | undefined = parseInt(pieces[pieces.length - 2]); if (Number.isNaN(line)) line = undefined;
let colLinePieces = (column ? 1 : 0) + (line ? 1 : 0)
let fileName = pieces.slice(0, pieces.length - colLinePieces).join(':');
return { fileName: fileName, line: line, column: column, functionName: functionName };
}
if (pieces.length === 2) {
return parseData(pieces[1]);
} else {
// chop of parenthesis chop off 'at' and file path
return parseData(pieces[pieces.length - 1].slice(1, -1), pieces.slice(1, -1).join(' '));
}
});
}
export function relativizeFilePath(frame: Frame, baseDir: string): Frame {
if (frame.fileName && frame.fileName[0] === '/') {
let relativeFileName = path.relative(baseDir, frame.fileName);
return Object.assign({}, frame, { fileName: relativeFileName });
}
return frame;
}
/** Converts a parsed frame into a line that "could have come from an Error" */
export function getFrameLine(frame: Frame): string {
if (frame.functionName) {
if (frame.line) {
if (frame.column) {
return ` at ${frame.functionName} (${frame.fileName}:${frame.line}:${frame.column})`;
} else {
return ` at ${frame.functionName} (${frame.fileName}:${frame.line})`;
}
} else {
return ` at ${frame.functionName} (${frame.fileName})`;
}
} else {
if (frame.line) {
if (frame.column) {
return ` at ${frame.fileName}:${frame.line}:${frame.column}`;
} else {
return ` at ${frame.fileName}:${frame.line}`;
}
} else {
return ` at ${frame.fileName}`;
}
}
}