Skip to content

Commit 6010114

Browse files
fix: change logic for displaying structural and semantic parser errors
Signed-off-by: Fredrik Nordlander <fredrik.nordlander@digg.se>
1 parent 019c24d commit 6010114

File tree

3 files changed

+56
-17
lines changed

3 files changed

+56
-17
lines changed

src/app.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import { SpecParseError } from './util/RapLPSpecParseError.js';
2828
import type { IParser } from '@stoplight/spectral-parsers';
2929
import { Document as SpectralDocument } from '@stoplight/spectral-core';
3030
import { Issue } from './util/RapLPIssueHelpers.js';
31+
import * as IssueHelper from './util/RapLPIssueHelpers.js';
3132

3233
declare var AggregateError: {
3334
prototype: AggregateError;
@@ -97,25 +98,24 @@ async function main(): Promise<void> {
9798
let apiSpecDocument: SpectralDocument;
9899
let parseResult: any;
99100
try {
100-
// NOTE: use filePath (camelCase)
101101
const prefer = detectSpecFormatPreference(apiSpecFileName,undefined,'auto');
102102
parseResult = await parseApiSpecInput(
103103
{filePath: apiSpecFileName},{
104104
strict: strict,
105105
preferJsonError: prefer
106106
}
107107
);
108+
// Issue handling ----------
108109
if (parseResult.strictIssues && parseResult.strictIssues.length > 0) {
109110
console.error('Strict validation reported issues:');
110111
parseResult.strictIssues.forEach((iss: Issue) =>
111112
console.error(chalk.yellow(`- ${iss.type} at ${iss.path} : ${iss.message} ${iss.line ? `(line ${iss.line})` : ''}`)),
112-
//console.error(`- ${iss.type} at ${iss.path} : ${iss.message} ${iss.line ? `(line ${iss.line})` : ''}`),
113113
);
114114
process.exitCode = 2;
115115
return;
116116
}
117117
} catch (err: any) {
118-
// Hantering av parse-fel (behåll din logik men använd return; nu innanför main())
118+
// Parse handling
119119
if (err instanceof SpecParseError) {
120120
const formattedDate = new Date().toISOString();
121121
const logData = {

src/util/RapLPIssueHelpers.ts

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -306,31 +306,70 @@ export function consolidateIssues(issues: Issue[]): Issue[] {
306306
return merged;
307307
}
308308
/**
309-
* Format single issue into editor-like lines (array of strings)
309+
* Format a single Issue into editor-like lines (no duplicates).
310310
*/
311311
export function formatIssueAsEditorLines(issue: Issue): string[] {
312312
const lines: string[] = [];
313-
const typ = issue.type ? `${issue.type}` : 'Error';
314-
lines.push(`${typ} error at ${issue.path || issue.location || '<unknown>'}`);
315-
lines.push(issue.message || '(no message)');
316-
if (issue.details && issue.details.length) {
317-
for (const d of issue.details) lines.push(d);
313+
314+
const typ = (issue.type ?? 'Error').toString();
315+
const target = issue.path || issue.location || '<unknown>';
316+
const header = `${typ} error at ${target}`;
317+
318+
// header
319+
lines.push(header);
320+
321+
// message
322+
const msg = (issue.message ?? '').toString().trim();
323+
if (msg) lines.push(msg);
324+
325+
// details (only ones that are not identical to message)
326+
if (Array.isArray(issue.details) && issue.details.length) {
327+
for (const d of issue.details) {
328+
const dd = (d ?? '').toString().trim();
329+
if (!dd) continue;
330+
if (dd === msg) continue; // skip duplicate
331+
lines.push(dd);
332+
}
318333
}
319-
if (issue.raw && Array.isArray(issue.raw)) {
334+
335+
// If raw is present, include only lines from raw that are not duplicates of already included lines
336+
if (Array.isArray(issue.raw) && issue.raw.length) {
320337
for (const r of issue.raw) {
321-
const t = String(r).trim();
322-
if (t && !lines.includes(t)) lines.push(t);
338+
const rr = (r ?? '').toString().trim();
339+
if (!rr) continue;
340+
// skip if it's identical to header, msg, any details or "Jump to line ..." (we will add jump ourselves)
341+
if (rr === header) continue;
342+
if (rr === msg) continue;
343+
if ((issue.details || []).some(d => (d ?? '').toString().trim() === rr)) continue;
344+
if (/^Jump to line\s+\d+/i.test(rr)) continue;
345+
lines.push(rr);
323346
}
324347
}
325-
if (typeof issue.line === 'number') lines.push(`Jump to line ${issue.line}`);
348+
349+
// Jump to line (prefer issue.line if present)
350+
const l = normalizeLine(issue.line);
351+
if (l) lines.push(`Jump to line ${l}`);
352+
326353
return lines;
327354
}
355+
function normalizeLine(line?: number | null): number | undefined {
356+
if (typeof line === 'number' && Number.isFinite(line) && line > 0) return line;
357+
return undefined;
358+
}
328359
/**
329-
* Format array of issues to single editor-like string (for snippet)
360+
* Format entire Issue[] as a single editor-like text block.
361+
* Ensures issues are separated by a blank line.
330362
*/
331363
export function formatIssuesAsEditorText(issues: Issue[]): string {
332-
if (!issues || !issues.length) return '';
333-
return issues.map(i => formatIssueAsEditorLines(i).join('\n')).join('\n\n');
364+
if (!Array.isArray(issues) || issues.length === 0) return '';
365+
366+
// We'll assume caller has already consolidated & sorted issues.
367+
const blocks: string[] = [];
368+
for (const issue of issues) {
369+
const lines = formatIssueAsEditorLines(issue);
370+
if (lines.length) blocks.push(lines.join('\n'));
371+
}
372+
return blocks.join('\n\n');
334373
}
335374
export function parsePrettyLinesToIssues(prettyLines: string[]): Issue[] {
336375
const issues: Issue[] = [];

src/util/validateUtil.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@ export async function parseApiSpecInput(input: SpecInput,
206206
console.error('Spectral semantic validation failed (non-fatal):', e?.message ?? String(e));
207207
spectralDiagnostics = [];
208208
}
209-
const finalIssues = IssueHelper.buildIssuesFromPrettyAndSpectral(prettyLines ?? [], spectralDiagnostics, false /* addOneToLine */);
209+
const finalIssues = IssueHelper.buildIssuesFromPrettyAndSpectral(prettyLines ?? [], spectralDiagnostics, true /* addOneToLine */);
210210
//console.log('Merged issues length:', Array.isArray(finalIssues) ? finalIssues.length : 0);
211211
issues = Array.isArray(finalIssues) && finalIssues.length ? finalIssues : undefined;
212212
issues = finalIssues && finalIssues.length ? finalIssues : undefined;

0 commit comments

Comments
 (0)