import { Diagnostic, DiagnosticSeverity } from 'vscode-languageserver' import { TextDocument, Position } from 'vscode-languageserver-textdocument' import * as fs from 'fs'; import * as readline from 'readline' /** * Reads the error file, casts the errors to a readable form, sorts them by origin * @param errorPath the path to the file where the ndjson errors are stored */ export async function readErrors(errorPath: string): Promise<Map<string, Set<NDJSON>>> { let result: Map<string, Set<NDJSON>> = new Map() var stream = fs.createReadStream(errorPath) const rl = readline.createInterface({ input: stream, crlfDelay: Infinity }); let i : number = 1 for await (const line of rl) { let obj: NDJSON try{ console.log(line) obj = JSON.parse(line) }catch(e){ throw Error(e.message + " at line " + line) } i++ let path: string = obj.details.file if (!result.has(path)) { result.set(path, new Set()) } result.get(path)!.add(obj) } return result } /** * Builds diagnostics for a given Set of infos * @param infos the set of infos to build diagnostics with */ export function matchErrors(infos: Set<NDJSON>, file?: TextDocument | undefined): Array<Diagnostic> { let result: Array<Diagnostic> = new Array() for (var info of infos) { let serveity: DiagnosticSeverity = DiagnosticSeverity.Error if (info.type == "error") { serveity = DiagnosticSeverity.Error } if (info.type == "warning") { serveity = DiagnosticSeverity.Warning } if (info.type == "information") { serveity = DiagnosticSeverity.Information } let content: JBody = info.details // Managing case we get conent with no error massage if (content.start.line == -1 && content.start.col == -1 && content.end.line == -1 && content.end.col == -1) { if (file != undefined) { //Due to server architecture we only have the most actual document let targetLine = getFirstOccurence(file).line content.start = { line: targetLine, col: 0 } content.end = { line: targetLine, col: Number.MAX_VALUE } } else { //Fallback if an error occurs on differnt document content.start = { line: 1, col: 0 } content.end = { line: 1, col: Number.MAX_VALUE } } } let diagnostic = { severity: serveity, range: { start: { character: content.start.col, line: content.start.line - 1 }, end: { character: content.end.col, line: content.end.line - 1 } }, message: content.message, source: 'prob_prolog', }; result.push(diagnostic) } return result } ////////////// Representation of the NDJSON File export interface NDJSON { type: string details: JBody } export interface JBody { message: string; type: string; file: string; start: StartOrEnd; end: StartOrEnd; } export interface StartOrEnd { line: number; col: number; } /////////////////// /** * Returns the exakt positiion of the first occurence of an non whitespace token * @param textdocument the Textdocument to analzie */ function getFirstOccurence(textdocument: TextDocument): Position { let counter: number = textdocument.getText().search(/\S|$/) let pos: Position = textdocument.positionAt(counter) pos.line = pos.line + 1 return pos }