diff --git a/src/Parser/SarifParser.spec.ts b/src/Parser/SarifParser.spec.ts index cd3f735..d821eb7 100644 --- a/src/Parser/SarifParser.spec.ts +++ b/src/Parser/SarifParser.spec.ts @@ -17,36 +17,36 @@ describe('SarifParser tests', () => { { id: 'TEST001', shortDescription: { - text: 'Test rule description' - } - } - ] - } + text: 'Test rule description', + }, + }, + ], + }, }, results: [ { ruleId: 'TEST001', level: 'warning', message: { - text: 'This is a test warning' + text: 'This is a test warning', }, locations: [ { physicalLocation: { artifactLocation: { - uri: 'C:\\source\\Test.cs' + uri: 'C:\\source\\Test.cs', }, region: { startLine: 42, - startColumn: 13 - } - } - } - ] - } - ] - } - ] + startColumn: 13, + }, + }, + }, + ], + }, + ], + }, + ], }; const sarifLogNoLocation = { @@ -55,20 +55,20 @@ describe('SarifParser tests', () => { { tool: { driver: { - name: 'TestAnalyzer' - } + name: 'TestAnalyzer', + }, }, results: [ { ruleId: 'TEST002', level: 'error', message: { - text: 'Error without location' - } - } - ] - } - ] + text: 'Error without location', + }, + }, + ], + }, + ], }; const sarifLogMultipleResults = { @@ -77,53 +77,53 @@ describe('SarifParser tests', () => { { tool: { driver: { - name: 'TestAnalyzer' - } + name: 'TestAnalyzer', + }, }, results: [ { ruleId: 'TEST003', level: 'warning', message: { - text: 'First warning' + text: 'First warning', }, locations: [ { physicalLocation: { artifactLocation: { - uri: 'C:\\source\\Test1.cs' + uri: 'C:\\source\\Test1.cs', }, region: { startLine: 10, - startColumn: 5 - } - } - } - ] + startColumn: 5, + }, + }, + }, + ], }, { ruleId: 'TEST004', level: 'error', message: { - text: 'Second error' + text: 'Second error', }, locations: [ { physicalLocation: { artifactLocation: { - uri: 'C:\\source\\Test2.cs' + uri: 'C:\\source\\Test2.cs', }, region: { startLine: 20, - startColumn: 8 - } - } - } - ] - } - ] - } - ] + startColumn: 8, + }, + }, + }, + ], + }, + ], + }, + ], }; const sarifLogUnrelatedPath = { @@ -132,33 +132,33 @@ describe('SarifParser tests', () => { { tool: { driver: { - name: 'TestAnalyzer' - } + name: 'TestAnalyzer', + }, }, results: [ { ruleId: 'TEST005', level: 'warning', message: { - text: 'Warning with unrelated path' + text: 'Warning with unrelated path', }, locations: [ { physicalLocation: { artifactLocation: { - uri: '/usr/share/test/Unrelated.cs' + uri: '/usr/share/test/Unrelated.cs', }, region: { startLine: 15, - startColumn: 3 - } - } - } - ] - } - ] - } - ] + startColumn: 3, + }, + }, + }, + ], + }, + ], + }, + ], }; it('Should parse basic SARIF log correctly', () => { @@ -214,12 +214,12 @@ describe('SarifParser tests', () => { { tool: { driver: { - name: 'TestAnalyzer' - } + name: 'TestAnalyzer', + }, }, - results: [] - } - ] + results: [], + }, + ], }; const result = new SarifParser(cwdWin).parse(JSON.stringify(emptyLog)); expect(result).toHaveLength(0); @@ -234,7 +234,9 @@ describe('SarifParser tests', () => { version: '2.1.0', // missing runs array }; - expect(() => new SarifParser(cwdWin).parse(JSON.stringify(invalidLog))).toThrowError(); + expect(() => + new SarifParser(cwdWin).parse(JSON.stringify(invalidLog)), + ).toThrowError(); }); it('Should handle missing severity level and default to warning', () => { @@ -244,35 +246,35 @@ describe('SarifParser tests', () => { { tool: { driver: { - name: 'TestAnalyzer' - } + name: 'TestAnalyzer', + }, }, results: [ { ruleId: 'TEST006', message: { - text: 'Message with no severity level' + text: 'Message with no severity level', }, locations: [ { physicalLocation: { artifactLocation: { - uri: 'C:\\source\\Test.cs' + uri: 'C:\\source\\Test.cs', }, region: { startLine: 1, - startColumn: 1 - } - } - } - ] - } - ] - } - ] + startColumn: 1, + }, + }, + }, + ], + }, + ], + }, + ], }; const result = new SarifParser(cwdWin).parse(JSON.stringify(logWithNoLevel)); expect(result).toHaveLength(1); expect(result[0].severity).toBe(LintSeverity.warning); }); -}); \ No newline at end of file +}); diff --git a/src/Parser/SarifParser.ts b/src/Parser/SarifParser.ts index 6e6f723..3e69e34 100644 --- a/src/Parser/SarifParser.ts +++ b/src/Parser/SarifParser.ts @@ -7,6 +7,7 @@ import { Parser } from './@interfaces/parser.interface'; import { LintItem } from './@types'; import { mapSeverity } from './utils/dotnetSeverityMap'; import { ProjectType } from '../Config/@enums'; +import { LintSeverity } from './@enums/LintSeverity'; import { NoNaN } from './utils/number.util'; interface SarifLog { @@ -53,34 +54,47 @@ interface SarifResult { export class SarifParser extends Parser { parse(content: string): LintItem[] { try { - const sarifLog: SarifLog = JSON.parse(content); - - if (!this.isValidSarifLog(sarifLog)) { - const message = "SarifParser Error: Invalid SARIF format"; - Log.error(message, { content }); - throw new Error(message); - } - - const lintItems: LintItem[] = []; - - for (const run of sarifLog.runs) { - const results = run.results || []; - for (const result of results) { - const lintItem = this.toLintItem(result, run); - if (lintItem) { - lintItems.push(lintItem); - } - } - } - - return lintItems; + const sarifLog = this.parseSarifContent(content); + return this.processRuns(sarifLog.runs); } catch (error) { - const message = "SarifParser Error: Failed to parse SARIF content"; + const message = 'SarifParser Error: Failed to parse SARIF content'; Log.error(message, { error, content }); throw new Error(message); } } + private parseSarifContent(content: string): SarifLog { + const sarifLog: SarifLog = JSON.parse(content); + + if (!this.isValidSarifLog(sarifLog)) { + const message = 'SarifParser Error: Invalid SARIF format'; + Log.error(message, { content }); + throw new Error(message); + } + + return sarifLog; + } + + private processRuns(runs: SarifRun[]): LintItem[] { + const lintItems: LintItem[] = []; + + for (const run of runs) { + this.processResults(run, lintItems); + } + + return lintItems; + } + + private processResults(run: SarifRun, lintItems: LintItem[]): void { + const results = run.results || []; + for (const result of results) { + const lintItem = this.toLintItem(result, run); + if (lintItem) { + lintItems.push(lintItem); + } + } + } + private isValidSarifLog(log: any): log is SarifLog { return ( log && @@ -104,29 +118,31 @@ export class SarifParser extends Parser { Log.warn(`SarifParser Warning: source path is not relative to root`, { uri }); } - // Map SARIF severity levels to your existing severity system - const severityMap: Record = { - 'error': 'error', - 'warning': 'warning', - 'note': 'info', - 'none': 'info' - }; - return { ruleId: result.ruleId, - log: JSON.stringify(result), // Store the original result for reference - line: NoNaN(location.region?.startLine), - lineOffset: NoNaN(location.region?.startColumn), + log: JSON.stringify(result), + line: NoNaN(String(location.region?.startLine || '')), + lineOffset: NoNaN(String(location.region?.startColumn || '')), msg: `${result.ruleId}: ${result.message.text}`, source: relativeSrcPath ?? basename(slash(uri)), - severity: mapSeverity(severityMap[result.level ?? 'warning']), + severity: this.getSeverity(result.level), valid: !!relativeSrcPath, type: ProjectType.sarif, }; } - // Helper method to find rule details if needed + private getSeverity(level?: string): LintSeverity { + const severityMap: Record = { + error: 'error', + warning: 'warning', + note: 'info', + none: 'info', + }; + + return mapSeverity(severityMap[level ?? 'warning']); + } + private findRuleDetails(ruleId: string, run: SarifRun): SarifRule | undefined { - return run.tool.driver.rules?.find(rule => rule.id === ruleId); + return run.tool.driver.rules?.find((rule) => rule.id === ruleId); } -} \ No newline at end of file +}