Skip to content

Commit

Permalink
CHANGE: @W-17272495@: Remove use of rule type from output formats and… (
Browse files Browse the repository at this point in the history
  • Loading branch information
stephen-carter-at-sf authored Nov 19, 2024
1 parent d0b84d5 commit 13a61d6
Show file tree
Hide file tree
Showing 18 changed files with 282 additions and 184 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -76,25 +76,33 @@
}
processViolations(data2) {
return (Array.isArray(data2) ? data2 : data2.violations || []).map(
(violation) => ({
file: this.sanitize(violation, "file", ""),
severity: this.sanitize(violation, "severity", ""),
rule: this.sanitize(violation, "rule", ""),
engine: this.sanitize(violation, "engine", ""),
message: this.sanitize(violation, "message", ""),
tags: Array.isArray(violation.tags) ? violation.tags : [],
line: this.sanitize(violation, "line", ""),
column: this.sanitize(violation, "column", ""),
endLine: this.sanitize(violation, "endLine", ""),
endColumn: this.sanitize(violation, "endColumn", ""),
resources: Array.isArray(violation.resources)
? violation.resources
: [],
type: this.sanitize(violation, "type", ""),
locations: Array.isArray(violation.locations)
? violation.locations
: [],
}),
(violation) => {
const primaryLocationIndex = violation.primaryLocationIndex || 0,
primaryLocation =
Array.isArray(violation.locations) &&
violation.locations.length > 0
? violation.locations[primaryLocationIndex]
: {};
return {
file: this.sanitize(primaryLocation, "file", ""),
severity: this.sanitize(violation, "severity", ""),
rule: this.sanitize(violation, "rule", ""),
engine: this.sanitize(violation, "engine", ""),
message: this.sanitize(violation, "message", ""),
tags: Array.isArray(violation.tags) ? violation.tags : [],
line: this.sanitize(primaryLocation, "line", ""),
column: this.sanitize(primaryLocation, "column", ""),
endLine: this.sanitize(primaryLocation, "endLine", ""),
endColumn: this.sanitize(primaryLocation, "endColumn", ""),
resources: Array.isArray(violation.resources)
? violation.resources
: [],
primaryLocationIndex,
locations: Array.isArray(violation.locations)
? violation.locations
: [],
};
},
);
}
filterViolations(severityFilter, engineFilter, searchTerm) {
Expand All @@ -108,8 +116,7 @@
searchRegex.test(violation.file) ||
searchRegex.test(violation.rule) ||
searchRegex.test(violation.tags.join(", ")) ||
searchRegex.test(violation.message) ||
searchRegex.test(violation.type)),
searchRegex.test(violation.message)),
);
}
sortViolations(data2, sortColumn, sortDirection) {
Expand Down Expand Up @@ -229,23 +236,16 @@
if (!((_a = violation.locations) == null ? void 0 : _a.length))
return "";
return `<ul>${violation.locations
.map((location) => {
.map((location, index) => {
const position = this.getPosition(location);
return `<li>
${this.isMainLocation(violation, location) ? "<strong>Main</strong> " : ""}
${index == violation.primaryLocationIndex ? "<strong>Main</strong> " : ""}
<span class="file">${location.file} (${position})</span>
${location.comment ? `<span class="comment">${location.comment}</span>` : ""}
</li>`;
})
.join("")}</ul>`;
}
isMainLocation(violation, location) {
return (
location.file === violation.file &&
location.line === violation.line &&
location.column === violation.column
);
}
updateSummary(data2) {
const uniqueFiles = new Set(data2.map((v) => v.file));
(this.summary.textContent = `Found ${data2.length} violation${1 !== data2.length ? "s" : ""} across ${uniqueFiles.size} file${1 !== uniqueFiles.size ? "s" : ""}`),
Expand Down Expand Up @@ -398,9 +398,9 @@
{ label: "Message", content: violation.message },
{
label:
0 === violation.locations.length ? "Location" : "Locations",
violation.locations.length <= 1 ? "Location" : "Locations",
content:
0 === violation.locations.length
violation.locations.length <= 1
? this.getLocation(violation)
: this.getLocationsList(violation),
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@ import {Options as CsvOptions} from "csv-stringify";
import {OutputFormatter} from "../output-format";
import {JsonViolationOutput, toJsonViolationOutputArray} from "./json-output-format";

// Note that CSV format is limited and doesn't support showing certain information, like multiple code
// locations. CSV format will be a lot like our table view or the main table in the html format.
// We will make users aware of this through our public documentation.

export class CsvOutputFormatter implements OutputFormatter {
format(results: RunResults): string {
// Leveraging the JsonViolationOutput data structure for now. This may change in the near future.
const violationOutputs: JsonViolationOutput[] = toJsonViolationOutputArray(results.getViolations(), results.getRunDirectory());
const options: CsvOptions = {
header: true,
quoted_string: true,
columns: ['rule', 'engine', 'severity', 'type', 'tags', 'file', 'line', 'column',
'endLine', 'endColumn', 'locations', 'message', 'resources'],
columns: ['rule', 'engine', 'severity', 'tags', 'file', 'line', 'column',
'endLine', 'endColumn', 'message', 'resources'],
cast: {
object: value => {
if (Array.isArray(value)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
toJsonViolationOutputArray
} from "./json-output-format";

const HTML_TEMPLATE_VERSION: string = '0.0.1';
const HTML_TEMPLATE_VERSION: string = '0.0.2';
const HTML_TEMPLATE_FILE: string = path.resolve(__dirname, '..', '..', 'output-templates', `html-template-${HTML_TEMPLATE_VERSION}.txt`);
export class HtmlOutputFormatter implements OutputFormatter {
private static readonly TIMESTAMP_HOLE: string = '{{###TIMESTAMP###}}';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {CodeLocation, RunResults, Violation} from "../results";
import {OutputFormatter} from "../output-format";
import {Rule, RuleType, SeverityLevel} from "../rules";
import {Rule, SeverityLevel} from "../rules";

export type JsonResultsOutput = {
runDir: string
Expand All @@ -19,7 +19,6 @@ export type JsonViolationOutput = {
rule: string
engine: string
severity: number
type: string
tags: string[]
file?: string
line?: number
Expand Down Expand Up @@ -133,24 +132,19 @@ function toJsonViolationOutput(violation: Violation, runDir: string, sanitizeFcn
rule: sanitizeFcn(rule.getName()),
engine: sanitizeFcn(rule.getEngineName()),
severity: rule.getSeverityLevel(),
type: rule.getType(),
tags: rule.getTags().map(sanitizeFcn),
file: primaryLocation.getFile() ? makeRelativeIfPossible(primaryLocation.getFile() as string, runDir) : undefined,
line: primaryLocation.getStartLine(),
column: primaryLocation.getStartColumn(),
endLine: primaryLocation.getEndLine(),
endColumn: primaryLocation.getEndColumn(),
primaryLocationIndex: typeSupportsMultipleLocations(rule.getType()) ? violation.getPrimaryLocationIndex() : undefined,
locations: typeSupportsMultipleLocations(rule.getType()) ? toJsonCodeLocationOutputArray(codeLocations, runDir) : undefined,
primaryLocationIndex: violation.getPrimaryLocationIndex(),
locations: toJsonCodeLocationOutputArray(codeLocations, runDir),
message: sanitizeFcn(violation.getMessage()),
resources: violation.getResourceUrls()
};
}

function typeSupportsMultipleLocations(ruleType: RuleType) {
return [RuleType.DataFlow, RuleType.Flow, RuleType.MultiLocation].includes(ruleType);
}

function toJsonCodeLocationOutputArray(codeLocations: CodeLocation[], runDir: string): JsonCodeLocationOutput[] {
return codeLocations.map(loc => {
return new JsonCodeLocationOutput(loc, runDir);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {CodeLocation, EngineRunResults, RunResults, Violation} from "../results";
import * as sarif from "sarif";
import {Rule, RuleType, SeverityLevel} from "../rules";
import {Rule, SeverityLevel} from "../rules";
import {OutputFormatter} from "../output-format";

export class SarifOutputFormatter implements OutputFormatter {
Expand Down Expand Up @@ -51,17 +51,19 @@ function toSarifRun(engineRunResults: EngineRunResults, runDir: string): sarif.R

function toSarifResult(violation: Violation, ruleIndex: number) : sarif.Result {
const primaryCodeLocation = violation.getCodeLocations()[violation.getPrimaryLocationIndex()];
const result: sarif.Result = {
return {
ruleId: violation.getRule().getName(),
ruleIndex: ruleIndex,
level: toSarifNotificationLevel(violation.getRule().getSeverityLevel()),
message: { text: violation.getMessage() },

// Note that sarif format has a limit of 10 elements in the locations array, so we only store
// the primary location (which is what most utilities expect) here
locations: [toSarifLocation(primaryCodeLocation)],

// And then we store the full locations array in the relatedLocations field if users want to see all of them
relatedLocations: violation.getCodeLocations().map(toSarifLocation)
};
if(typeSupportsMultipleLocations(violation.getRule().getType())) {
result.relatedLocations = violation.getCodeLocations().map(toSarifLocation);
}
result.level = toSarifNotificationLevel(violation.getRule().getSeverityLevel());
return result;
}

function toSarifLocation(codeLocation: CodeLocation): sarif.Location {
Expand Down Expand Up @@ -92,9 +94,5 @@ function toSarifReportingDescriptor(rule: Rule): sarif.ReportingDescriptor {
}

function toSarifNotificationLevel(severity: SeverityLevel): sarif.Notification.level {
return severity < 3 ? 'error' : 'warning'; // IF satif.Notification.level is an enum then please return the num instead of the string.
}

function typeSupportsMultipleLocations(ruleType: RuleType) {
return [RuleType.DataFlow, RuleType.Flow, RuleType.MultiLocation].includes(ruleType);
return severity < 3 ? 'error' : 'warning'; // IF sarif.Notification.level is an enum then please return the num instead of the string.
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ export class XmlOutputFormatter implements OutputFormatter {
violationNode.node('rule').text(violationOutput.rule);
violationNode.node('engine').text(violationOutput.engine);
violationNode.node('severity').text(`${violationOutput.severity}`);
violationNode.node('type').text(violationOutput.type);
const tagsNode: xmlbuilder.XMLElement = violationNode.node('tags');
for (const tag of violationOutput.tags) {
tagsNode.node('tag').text(tag);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"rule","engine","severity","type","tags","file","line","column","endLine","endColumn","locations","message","resources"
"stub1RuleA","stubEngine1",4,"Standard","Recommended,CodeStyle","test{{PATHSEP}}config.test.ts",3,6,11,8,,"SomeViolationMessage1","https://example.com/stub1RuleA"
"stub1RuleC","stubEngine1",3,"Standard","Recommended,Performance,Custom","test{{PATHSEP}}run.test.ts",21,7,25,4,,"SomeViolationMessage2","https://example.com/stub1RuleC,https://example.com/aViolationSpecificUrl1,https://example.com/violationSpecificUrl2"
"stub1RuleE","stubEngine1",3,"Standard","Performance","test{{PATHSEP}}run.test.ts",56,4,,,,"Some Violation that contains
"rule","engine","severity","tags","file","line","column","endLine","endColumn","message","resources"
"stub1RuleA","stubEngine1",4,"Recommended,CodeStyle","test{{PATHSEP}}config.test.ts",3,6,11,8,"SomeViolationMessage1","https://example.com/stub1RuleA"
"stub1RuleC","stubEngine1",3,"Recommended,Performance,Custom","test{{PATHSEP}}run.test.ts",21,7,25,4,"SomeViolationMessage2","https://example.com/stub1RuleC,https://example.com/aViolationSpecificUrl1,https://example.com/violationSpecificUrl2"
"stub1RuleE","stubEngine1",3,"Performance","test{{PATHSEP}}run.test.ts",56,4,,,"Some Violation that contains
a new line in `it` and ""various"" 'quotes'. Also it has <brackets> that may need to be {escaped}.","https://example.com/stub1RuleE,https://example.com/stub1RuleE_2"
"stub2RuleC","stubEngine2",2,"DataFlow","Recommended,BestPractice","test{{PATHSEP}}stubs.ts",76,8,,,"test{{PATHSEP}}stubs.ts:4:13,test{{PATHSEP}}test-helpers.ts:9:1,test{{PATHSEP}}stubs.ts:76:8","SomeViolationMessage3",
"stub3RuleA","stubEngine3",3,"Flow","Recommended,ErrorProne","test{{PATHSEP}}stubs.ts",90,1,95,10,"test{{PATHSEP}}stubs.ts:20:10 (Comment at location 1),test{{PATHSEP}}test-helpers.ts:5:10 (Comment at location 2),test{{PATHSEP}}stubs.ts:90:1","SomeViolationMessage4",
"stub2RuleC","stubEngine2",2,"Recommended,BestPractice","test{{PATHSEP}}stubs.ts",76,8,,,"SomeViolationMessage3",
"stub3RuleA","stubEngine3",3,"Recommended,ErrorProne","test{{PATHSEP}}stubs.ts",90,1,95,10,"SomeViolationMessage4",
Loading

0 comments on commit 13a61d6

Please sign in to comment.