Skip to content

Commit 13a61d6

Browse files
CHANGE: @W-17272495@: Remove use of rule type from output formats and… (#132)
1 parent d0b84d5 commit 13a61d6

18 files changed

+282
-184
lines changed

packages/code-analyzer-core/output-templates/html-template-0.0.1.txt renamed to packages/code-analyzer-core/output-templates/html-template-0.0.2.txt

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -76,25 +76,33 @@
7676
}
7777
processViolations(data2) {
7878
return (Array.isArray(data2) ? data2 : data2.violations || []).map(
79-
(violation) => ({
80-
file: this.sanitize(violation, "file", ""),
81-
severity: this.sanitize(violation, "severity", ""),
82-
rule: this.sanitize(violation, "rule", ""),
83-
engine: this.sanitize(violation, "engine", ""),
84-
message: this.sanitize(violation, "message", ""),
85-
tags: Array.isArray(violation.tags) ? violation.tags : [],
86-
line: this.sanitize(violation, "line", ""),
87-
column: this.sanitize(violation, "column", ""),
88-
endLine: this.sanitize(violation, "endLine", ""),
89-
endColumn: this.sanitize(violation, "endColumn", ""),
90-
resources: Array.isArray(violation.resources)
91-
? violation.resources
92-
: [],
93-
type: this.sanitize(violation, "type", ""),
94-
locations: Array.isArray(violation.locations)
95-
? violation.locations
96-
: [],
97-
}),
79+
(violation) => {
80+
const primaryLocationIndex = violation.primaryLocationIndex || 0,
81+
primaryLocation =
82+
Array.isArray(violation.locations) &&
83+
violation.locations.length > 0
84+
? violation.locations[primaryLocationIndex]
85+
: {};
86+
return {
87+
file: this.sanitize(primaryLocation, "file", ""),
88+
severity: this.sanitize(violation, "severity", ""),
89+
rule: this.sanitize(violation, "rule", ""),
90+
engine: this.sanitize(violation, "engine", ""),
91+
message: this.sanitize(violation, "message", ""),
92+
tags: Array.isArray(violation.tags) ? violation.tags : [],
93+
line: this.sanitize(primaryLocation, "line", ""),
94+
column: this.sanitize(primaryLocation, "column", ""),
95+
endLine: this.sanitize(primaryLocation, "endLine", ""),
96+
endColumn: this.sanitize(primaryLocation, "endColumn", ""),
97+
resources: Array.isArray(violation.resources)
98+
? violation.resources
99+
: [],
100+
primaryLocationIndex,
101+
locations: Array.isArray(violation.locations)
102+
? violation.locations
103+
: [],
104+
};
105+
},
98106
);
99107
}
100108
filterViolations(severityFilter, engineFilter, searchTerm) {
@@ -108,8 +116,7 @@
108116
searchRegex.test(violation.file) ||
109117
searchRegex.test(violation.rule) ||
110118
searchRegex.test(violation.tags.join(", ")) ||
111-
searchRegex.test(violation.message) ||
112-
searchRegex.test(violation.type)),
119+
searchRegex.test(violation.message)),
113120
);
114121
}
115122
sortViolations(data2, sortColumn, sortDirection) {
@@ -229,23 +236,16 @@
229236
if (!((_a = violation.locations) == null ? void 0 : _a.length))
230237
return "";
231238
return `<ul>${violation.locations
232-
.map((location) => {
239+
.map((location, index) => {
233240
const position = this.getPosition(location);
234241
return `<li>
235-
${this.isMainLocation(violation, location) ? "<strong>Main</strong> " : ""}
242+
${index == violation.primaryLocationIndex ? "<strong>Main</strong> " : ""}
236243
<span class="file">${location.file} (${position})</span>
237244
${location.comment ? `<span class="comment">${location.comment}</span>` : ""}
238245
</li>`;
239246
})
240247
.join("")}</ul>`;
241248
}
242-
isMainLocation(violation, location) {
243-
return (
244-
location.file === violation.file &&
245-
location.line === violation.line &&
246-
location.column === violation.column
247-
);
248-
}
249249
updateSummary(data2) {
250250
const uniqueFiles = new Set(data2.map((v) => v.file));
251251
(this.summary.textContent = `Found ${data2.length} violation${1 !== data2.length ? "s" : ""} across ${uniqueFiles.size} file${1 !== uniqueFiles.size ? "s" : ""}`),
@@ -398,9 +398,9 @@
398398
{ label: "Message", content: violation.message },
399399
{
400400
label:
401-
0 === violation.locations.length ? "Location" : "Locations",
401+
violation.locations.length <= 1 ? "Location" : "Locations",
402402
content:
403-
0 === violation.locations.length
403+
violation.locations.length <= 1
404404
? this.getLocation(violation)
405405
: this.getLocationsList(violation),
406406
},

packages/code-analyzer-core/src/output-formats/csv-output-format.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@ import {Options as CsvOptions} from "csv-stringify";
44
import {OutputFormatter} from "../output-format";
55
import {JsonViolationOutput, toJsonViolationOutputArray} from "./json-output-format";
66

7+
// Note that CSV format is limited and doesn't support showing certain information, like multiple code
8+
// locations. CSV format will be a lot like our table view or the main table in the html format.
9+
// We will make users aware of this through our public documentation.
10+
711
export class CsvOutputFormatter implements OutputFormatter {
812
format(results: RunResults): string {
913
// Leveraging the JsonViolationOutput data structure for now. This may change in the near future.
1014
const violationOutputs: JsonViolationOutput[] = toJsonViolationOutputArray(results.getViolations(), results.getRunDirectory());
1115
const options: CsvOptions = {
1216
header: true,
1317
quoted_string: true,
14-
columns: ['rule', 'engine', 'severity', 'type', 'tags', 'file', 'line', 'column',
15-
'endLine', 'endColumn', 'locations', 'message', 'resources'],
18+
columns: ['rule', 'engine', 'severity', 'tags', 'file', 'line', 'column',
19+
'endLine', 'endColumn', 'message', 'resources'],
1620
cast: {
1721
object: value => {
1822
if (Array.isArray(value)) {

packages/code-analyzer-core/src/output-formats/html-output-format.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
toJsonViolationOutputArray
99
} from "./json-output-format";
1010

11-
const HTML_TEMPLATE_VERSION: string = '0.0.1';
11+
const HTML_TEMPLATE_VERSION: string = '0.0.2';
1212
const HTML_TEMPLATE_FILE: string = path.resolve(__dirname, '..', '..', 'output-templates', `html-template-${HTML_TEMPLATE_VERSION}.txt`);
1313
export class HtmlOutputFormatter implements OutputFormatter {
1414
private static readonly TIMESTAMP_HOLE: string = '{{###TIMESTAMP###}}';

packages/code-analyzer-core/src/output-formats/json-output-format.ts

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {CodeLocation, RunResults, Violation} from "../results";
22
import {OutputFormatter} from "../output-format";
3-
import {Rule, RuleType, SeverityLevel} from "../rules";
3+
import {Rule, SeverityLevel} from "../rules";
44

55
export type JsonResultsOutput = {
66
runDir: string
@@ -19,7 +19,6 @@ export type JsonViolationOutput = {
1919
rule: string
2020
engine: string
2121
severity: number
22-
type: string
2322
tags: string[]
2423
file?: string
2524
line?: number
@@ -133,24 +132,19 @@ function toJsonViolationOutput(violation: Violation, runDir: string, sanitizeFcn
133132
rule: sanitizeFcn(rule.getName()),
134133
engine: sanitizeFcn(rule.getEngineName()),
135134
severity: rule.getSeverityLevel(),
136-
type: rule.getType(),
137135
tags: rule.getTags().map(sanitizeFcn),
138136
file: primaryLocation.getFile() ? makeRelativeIfPossible(primaryLocation.getFile() as string, runDir) : undefined,
139137
line: primaryLocation.getStartLine(),
140138
column: primaryLocation.getStartColumn(),
141139
endLine: primaryLocation.getEndLine(),
142140
endColumn: primaryLocation.getEndColumn(),
143-
primaryLocationIndex: typeSupportsMultipleLocations(rule.getType()) ? violation.getPrimaryLocationIndex() : undefined,
144-
locations: typeSupportsMultipleLocations(rule.getType()) ? toJsonCodeLocationOutputArray(codeLocations, runDir) : undefined,
141+
primaryLocationIndex: violation.getPrimaryLocationIndex(),
142+
locations: toJsonCodeLocationOutputArray(codeLocations, runDir),
145143
message: sanitizeFcn(violation.getMessage()),
146144
resources: violation.getResourceUrls()
147145
};
148146
}
149147

150-
function typeSupportsMultipleLocations(ruleType: RuleType) {
151-
return [RuleType.DataFlow, RuleType.Flow, RuleType.MultiLocation].includes(ruleType);
152-
}
153-
154148
function toJsonCodeLocationOutputArray(codeLocations: CodeLocation[], runDir: string): JsonCodeLocationOutput[] {
155149
return codeLocations.map(loc => {
156150
return new JsonCodeLocationOutput(loc, runDir);

packages/code-analyzer-core/src/output-formats/sarif-output-format.ts

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {CodeLocation, EngineRunResults, RunResults, Violation} from "../results";
22
import * as sarif from "sarif";
3-
import {Rule, RuleType, SeverityLevel} from "../rules";
3+
import {Rule, SeverityLevel} from "../rules";
44
import {OutputFormatter} from "../output-format";
55

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

5252
function toSarifResult(violation: Violation, ruleIndex: number) : sarif.Result {
5353
const primaryCodeLocation = violation.getCodeLocations()[violation.getPrimaryLocationIndex()];
54-
const result: sarif.Result = {
54+
return {
5555
ruleId: violation.getRule().getName(),
5656
ruleIndex: ruleIndex,
57+
level: toSarifNotificationLevel(violation.getRule().getSeverityLevel()),
5758
message: { text: violation.getMessage() },
59+
60+
// Note that sarif format has a limit of 10 elements in the locations array, so we only store
61+
// the primary location (which is what most utilities expect) here
5862
locations: [toSarifLocation(primaryCodeLocation)],
63+
64+
// And then we store the full locations array in the relatedLocations field if users want to see all of them
65+
relatedLocations: violation.getCodeLocations().map(toSarifLocation)
5966
};
60-
if(typeSupportsMultipleLocations(violation.getRule().getType())) {
61-
result.relatedLocations = violation.getCodeLocations().map(toSarifLocation);
62-
}
63-
result.level = toSarifNotificationLevel(violation.getRule().getSeverityLevel());
64-
return result;
6567
}
6668

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

9496
function toSarifNotificationLevel(severity: SeverityLevel): sarif.Notification.level {
95-
return severity < 3 ? 'error' : 'warning'; // IF satif.Notification.level is an enum then please return the num instead of the string.
96-
}
97-
98-
function typeSupportsMultipleLocations(ruleType: RuleType) {
99-
return [RuleType.DataFlow, RuleType.Flow, RuleType.MultiLocation].includes(ruleType);
97+
return severity < 3 ? 'error' : 'warning'; // IF sarif.Notification.level is an enum then please return the num instead of the string.
10098
}

packages/code-analyzer-core/src/output-formats/xml-output-format.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ export class XmlOutputFormatter implements OutputFormatter {
2424
violationNode.node('rule').text(violationOutput.rule);
2525
violationNode.node('engine').text(violationOutput.engine);
2626
violationNode.node('severity').text(`${violationOutput.severity}`);
27-
violationNode.node('type').text(violationOutput.type);
2827
const tagsNode: xmlbuilder.XMLElement = violationNode.node('tags');
2928
for (const tag of violationOutput.tags) {
3029
tagsNode.node('tag').text(tag);
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
"rule","engine","severity","type","tags","file","line","column","endLine","endColumn","locations","message","resources"
2-
"stub1RuleA","stubEngine1",4,"Standard","Recommended,CodeStyle","test{{PATHSEP}}config.test.ts",3,6,11,8,,"SomeViolationMessage1","https://example.com/stub1RuleA"
3-
"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"
4-
"stub1RuleE","stubEngine1",3,"Standard","Performance","test{{PATHSEP}}run.test.ts",56,4,,,,"Some Violation that contains
1+
"rule","engine","severity","tags","file","line","column","endLine","endColumn","message","resources"
2+
"stub1RuleA","stubEngine1",4,"Recommended,CodeStyle","test{{PATHSEP}}config.test.ts",3,6,11,8,"SomeViolationMessage1","https://example.com/stub1RuleA"
3+
"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"
4+
"stub1RuleE","stubEngine1",3,"Performance","test{{PATHSEP}}run.test.ts",56,4,,,"Some Violation that contains
55
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"
6-
"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",
7-
"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",
6+
"stub2RuleC","stubEngine2",2,"Recommended,BestPractice","test{{PATHSEP}}stubs.ts",76,8,,,"SomeViolationMessage3",
7+
"stub3RuleA","stubEngine3",3,"Recommended,ErrorProne","test{{PATHSEP}}stubs.ts",90,1,95,10,"SomeViolationMessage4",

0 commit comments

Comments
 (0)