Skip to content

Commit b108c8c

Browse files
committed
added fullDescription to FileIssueNode and SastIssueNode
1 parent 1c8b860 commit b108c8c

File tree

5 files changed

+109
-13
lines changed

5 files changed

+109
-13
lines changed

src/main/java/com/jfrog/ide/common/nodes/FileIssueNode.java

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ public class FileIssueNode extends IssueNode implements SubtitledTreeNode {
2323
@JsonProperty()
2424
private String ruleID;
2525

26+
private String fullDescription;
27+
2628
// Empty constructor for deserialization
2729
@SuppressWarnings("unused")
2830
protected FileIssueNode() {
@@ -36,12 +38,21 @@ public FileIssueNode(String title, String filePath, int rowStart, int colStart,
3638
this.severity = severity;
3739
this.ruleID = ruleID;
3840
}
39-
public FileIssueNode(String title, String reason, SourceCodeScanType reportType, Severity severity, String ruleID){
41+
42+
// Constructor for building FileIssueNode with fullDescription param
43+
public FileIssueNode(String title, String filePath, int rowStart, int colStart, int rowEnd, int colEnd, String reason, String lineSnippet, SourceCodeScanType reportType, Severity severity, String ruleID, String fullDescription) {
44+
this(title, filePath, rowStart, colStart, rowEnd, colEnd, reason, lineSnippet, reportType, severity, ruleID);
45+
this.fullDescription = fullDescription;
46+
}
47+
48+
// Temporary constructor for ScaIssueNode that currently not passing location info
49+
public FileIssueNode(String title, String reason, SourceCodeScanType reportType, Severity severity, String ruleID, String fullDescription){
4050
this.title = title;
4151
this.reason = reason;
4252
this.reporterType = reportType;
4353
this.severity = severity;
4454
this.ruleID = ruleID;
55+
this.fullDescription = fullDescription;
4556
this.findingInfo = new FindingInfo();
4657
}
4758

src/main/java/com/jfrog/ide/common/nodes/SastIssueNode.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,18 @@ public class SastIssueNode extends FileIssueNode {
1818
private SastIssueNode() {
1919
}
2020

21+
@SuppressWarnings("unused")
2122
public SastIssueNode(String name, String filePath, int rowStart, int colStart, int rowEnd, int colEnd, String reason, String lineSnippet, FindingInfo[][] codeFlows, Severity severity, String ruleID) {
2223
super(name, filePath, rowStart, colStart, rowEnd, colEnd, reason, lineSnippet, SourceCodeScanType.SAST, severity, ruleID);
2324
this.codeFlows = codeFlows;
2425
}
2526

27+
// Constructor for building SastIssueNode with fullDescription param
28+
public SastIssueNode(String name, String filePath, int rowStart, int colStart, int rowEnd, int colEnd, String reason, String lineSnippet, FindingInfo[][] codeFlows, Severity severity, String ruleID, String fullDescription) {
29+
super(name, filePath, rowStart, colStart, rowEnd, colEnd, reason, lineSnippet, SourceCodeScanType.SAST, severity, ruleID, fullDescription);
30+
this.codeFlows = codeFlows;
31+
}
32+
2633
@Override
2734
public boolean equals(Object o) {
2835
if (this == o) return true;

src/main/java/com/jfrog/ide/common/nodes/ScaIssueNode.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@ public class ScaIssueNode extends FileIssueNode {
1616
private String fixedVersions;
1717

1818
// Empty constructor for deserialization
19+
@SuppressWarnings("unused")
1920
ScaIssueNode() {
2021
}
2122

22-
public ScaIssueNode(String title, String reason, Severity severity, String ruleID, Applicability applicability, List<List<ImpactPath>> impactPaths, String fixedVersions) {
23-
super(title, reason, SourceCodeScanType.SCA, severity, ruleID);
23+
public ScaIssueNode(String title, String reason, Severity severity, String ruleID, Applicability applicability, List<List<ImpactPath>> impactPaths, String fixedVersions, String fullDescription) {
24+
super(title, reason, SourceCodeScanType.SCA, severity, ruleID, fullDescription);
2425
this.applicability = applicability;
2526
this.impactPaths = impactPaths;
2627
this.isDirectDependency = isDirectDependency(impactPaths, ruleID);

src/main/java/com/jfrog/ide/common/parse/SarifParser.java

Lines changed: 76 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import com.jetbrains.qodana.sarif.model.*;
77
import com.jfrog.ide.common.nodes.FileIssueNode;
88
import com.jfrog.ide.common.nodes.FileTreeNode;
9+
import com.jfrog.ide.common.nodes.SastIssueNode;
910
import com.jfrog.ide.common.nodes.ScaIssueNode;
11+
import com.jfrog.ide.common.nodes.subentities.FindingInfo;
1012
import com.jfrog.ide.common.nodes.subentities.ImpactPath;
1113
import com.jfrog.ide.common.nodes.subentities.Severity;
1214
import com.jfrog.ide.common.nodes.subentities.SourceCodeScanType;
@@ -17,31 +19,46 @@
1719
import java.io.*;
1820
import java.util.*;
1921

22+
/**
23+
* SarifParser is responsible for parsing SARIF reports and converting them into a list of FileTreeNode objects.
24+
*/
2025
public class SarifParser {
2126
private final Log log;
2227

28+
/**
29+
* Constructor for SarifParser.
30+
*
31+
* @param log the logger to be used for logging errors and information.
32+
*/
2333
SarifParser(Log log) {
2434
this.log = log;
2535
}
2636

37+
/**
38+
* Parses the given SARIF report output and returns a list of FileTreeNode objects.
39+
*
40+
* @param output the SARIF report as a string.
41+
* @return a list of FileTreeNode objects representing the parsed findings.
42+
* @throws NoSuchElementException if no runs are found in the SARIF report.
43+
*/
2744
List<FileTreeNode> parse (String output) {
2845
Reader reader = new StringReader(output);
29-
3046
SarifReport report = SarifUtil.readReport(reader);
31-
// extract SCA run object from SARIF
32-
3347
List<Run> runs = report.getRuns();
3448
if (runs.isEmpty()) {
3549
log.error("No runs found in SARIF report");
3650
throw new NoSuchElementException("No runs found in the scan SARIF report");
3751
}
38-
3952
return new ArrayList<>(parseScanFindings(runs));
4053
}
4154

42-
55+
/**
56+
* Parses the scan findings from the given list of runs.
57+
*
58+
* @param runs the list of runs from the SARIF report.
59+
* @return a list of FileTreeNode objects representing the parsed findings.
60+
*/
4361
private List<FileTreeNode> parseScanFindings(List<Run> runs){
44-
// a method for parsing SCA findings and build FileTreeNodes and IssueNodes
4562
List<FileTreeNode> fileTreeNodes = new ArrayList<>();
4663

4764
for (Run run : runs) {
@@ -81,30 +98,79 @@ private List<FileTreeNode> parseScanFindings(List<Run> runs){
8198
return fileTreeNodes;
8299
}
83100

84-
101+
/**
102+
* Generates a ScaIssueNode from the given rule and result.
103+
*
104+
* @param rule the reporting descriptor rule.
105+
* @param result the result from the SARIF report.
106+
* @return a ScaIssueNode representing the issue.
107+
*/
85108
private FileIssueNode generateScaFileIssueNode(ReportingDescriptor rule, Result result){
86109
Applicability applicability = Applicability.fromSarif(Objects.requireNonNull(result.getProperties()).get("applicability").toString());
87110
String fixedVersions = Objects.requireNonNull(result.getProperties()).get("fixedVersion").toString();
88111
List<List<ImpactPath>> impactPaths = new ObjectMapper().convertValue(Objects.requireNonNull(rule.getProperties()).get("impactPaths"), new TypeReference<>() {
89112
});
90113
Severity severity = Severity.fromSarif(result.getLevel().toString());
91114
String fullDescription = rule.getFullDescription().getText();
115+
String reason = result.getMessage().getText();
92116

93-
return new ScaIssueNode(SourceCodeScanType.SCA.getScannerIssueTitle(), fullDescription, severity, rule.getId(), applicability, impactPaths, fixedVersions);
117+
return new ScaIssueNode(SourceCodeScanType.SCA.getScannerIssueTitle(), reason, severity, rule.getId(), applicability, impactPaths, fixedVersions, fullDescription);
94118
}
95119

120+
/**
121+
* Generates a FileIssueNode for JAS from the given rule, result, reporter, and file path.
122+
*
123+
* @param rule the reporting descriptor rule.
124+
* @param result the result from the SARIF report.
125+
* @param reporter the source code scan type.
126+
* @param filePath the file path where the issue was found.
127+
* @return a FileIssueNode representing the issue.
128+
*/
96129
private FileIssueNode generateJasFileIssueNode(ReportingDescriptor rule, Result result, SourceCodeScanType reporter, String filePath){
97130
Severity severity = Severity.fromSarif(result.getLevel().toString());
98-
String fullDescription = rule.getFullDescription().getText(); // TODO: is needed?
131+
String fullDescription = rule.getFullDescription().getText();
99132
int rowStart = result.getLocations().get(0).getPhysicalLocation().getRegion().getStartLine();
100133
int colStart = result.getLocations().get(0).getPhysicalLocation().getRegion().getStartColumn();
101134
int rowEnd = result.getLocations().get(0).getPhysicalLocation().getRegion().getEndLine();
102135
int colEnd = result.getLocations().get(0).getPhysicalLocation().getRegion().getEndColumn();
103136
String lineSnippet = result.getLocations().get(0).getPhysicalLocation().getRegion().getSnippet().getText();
104137
String reason = result.getMessage().getText();
138+
if (reporter.equals(SourceCodeScanType.SAST)) {
139+
FindingInfo[][] codeFlows = convertCodeFlowsToFindingInfo(result.getCodeFlows());
140+
return new SastIssueNode(reporter.getScannerIssueTitle(), filePath, rowStart, colStart, rowEnd, colEnd, reason,
141+
lineSnippet, codeFlows, severity, rule.getId(), fullDescription);
142+
}
105143

106144
return new FileIssueNode(reporter.getScannerIssueTitle(), filePath, rowStart, colStart, rowEnd, colEnd, reason,
107-
lineSnippet, reporter, severity, rule.getId());
145+
lineSnippet, reporter, severity, rule.getId(), fullDescription);
146+
}
147+
148+
private static FindingInfo[][] convertCodeFlowsToFindingInfo(List<CodeFlow> codeFlows) {
149+
if (codeFlows == null || codeFlows.isEmpty()) {
150+
return null;
151+
}
152+
List<ThreadFlow> flows = codeFlows.get(0).getThreadFlows();
153+
if (flows == null || flows.isEmpty()) {
154+
return null;
155+
}
156+
FindingInfo[][] results = new FindingInfo[flows.size()][];
157+
for (int i = 0; i < flows.size(); i++) {
158+
ThreadFlow flow = flows.get(i);
159+
List<ThreadFlowLocation> locations = flow.getLocations();
160+
results[i] = new FindingInfo[locations.size()];
161+
for (int j = 0; j < locations.size(); j++) {
162+
PhysicalLocation location = locations.get(j).getLocation().getPhysicalLocation();
163+
results[i][j] = new FindingInfo(
164+
location.getArtifactLocation().getUri(),
165+
location.getRegion().getStartLine(),
166+
location.getRegion().getStartColumn(),
167+
location.getRegion().getEndLine(),
168+
location.getRegion().getEndColumn(),
169+
location.getRegion().getSnippet().getText()
170+
);
171+
}
172+
}
173+
return results;
108174
}
109175

110176

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package com.jfrog.ide.common.parse;
2+
3+
import org.testng.annotations.Test;
4+
5+
public class SarifParserTest {
6+
7+
@Test
8+
public void setUp() {
9+
10+
}
11+
}

0 commit comments

Comments
 (0)