-
Notifications
You must be signed in to change notification settings - Fork 295
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Development
: Add SARIF parser
#9609
Conversation
|
WalkthroughThe pull request introduces significant modifications across various classes related to static code analysis report processing. Key changes include enhancements to file handling in Changes
Possibly related PRs
Suggested labels
Suggested reviewers
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 15
🧹 Outside diff range and nitpick comments (22)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/ParserStrategy.java (1)
15-19
: Documentation could be more specific about supported formats.The documentation change from "XML string" to "serialized string" appropriately makes the interface more generic. However, consider documenting the supported serialization formats (e.g., XML, SARIF) to help implementers.
- * Parse a static code analysis report from a serialized string into a common Java representation. + * Parse a static code analysis report from a serialized string (e.g., XML, SARIF) into a common Java representation.src/test/java/de/tum/cit/aet/artemis/programming/StaticCodeAnalysisParserUnitTest.java (4)
29-29
: Consider marking ObjectMapper as finalSince this field is initialized at declaration and never modified, marking it as final would better express its immutability.
- private final ObjectMapper mapper = new ObjectMapper(); + private static final ObjectMapper MAPPER = new ObjectMapper();
49-54
: Add JavaDoc for testParserWithContent methodThe method would benefit from documentation explaining its parameters and purpose, similar to testParserWithFileNamed.
/** * Tests the parsing of report content by comparing it with an expected JSON report * * @param actualReportContent The content of the report to be parsed * @param actualReportFilename The filename to be used for tool detection * @param expectedJSONReportFile The file containing the expected parsed report * @throws IOException If there's an error reading the expected report file */
78-85
: Consider more descriptive test method namesWhile the current names are clear, they could be more specific about the expected behavior. Consider renaming to better reflect the expected outcomes:
- void testParseInvalidXML() + void shouldThrowRuntimeException_whenParsingInvalidXML() - void testInvalidName() + void shouldThrowUnsupportedToolException_whenFileNameDoesNotMatchKnownTools()
SARIF test coverage needs to be integrated into main test suite
The SARIF functionality has dedicated unit tests in
SarifParserTest.java
that thoroughly cover various scenarios including:
- Empty SARIF reports
- Metadata parsing
- Message lookup mechanisms
- Hierarchical rule ID lookup
- Rule index lookup
- Invalid JSON handling
However, this functionality is not integrated into the main
StaticCodeAnalysisParserUnitTest
class alongside other tools like Spotbugs, Checkstyle, and PMD. To maintain consistency:
- Add SARIF to the
StaticCodeAnalysisTool
enum- Add corresponding test resources under
src/test/resources/test-data/static-code-analysis/
- Add a
testSarifParser()
method inStaticCodeAnalysisParserUnitTest
🔗 Analysis chain
Line range hint
1-86
: Verify SARIF parsing test coverageGiven that this PR introduces SARIF parsing functionality (as mentioned in the PR objectives), we should ensure there are corresponding test cases for SARIF report parsing.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Search for SARIF-related test files and test methods echo "Searching for SARIF test files..." fd -e java -e xml "Sarif.*Test" echo "Searching for SARIF test resources..." fd -e json -e xml "sarif" "src/test/resources" echo "Searching for SARIF test methods..." rg -l "test.*Sarif" "src/test"Length of output: 463
Script:
#!/bin/bash # Let's examine the content of the SARIF test file and its test methods echo "=== Content of SARIF Parser Test ===" cat "src/test/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParserTest.java" echo -e "\n=== Searching for SARIF test resources in static-code-analysis folder ===" fd sarif "src/test/resources/test-data/static-code-analysis" echo -e "\n=== Checking if SARIF is integrated in StaticCodeAnalysisParserUnitTest ===" rg "SARIF|sarif" "src/test/java/de/tum/cit/aet/artemis/programming/StaticCodeAnalysisParserUnitTest.java"Length of output: 13937
Script:
#!/bin/bash # Let's check for SARIF test resources and expected files echo "=== Checking for SARIF test resources ===" fd -e json -e xml -e txt sarif "src/test/resources/test-data/static-code-analysis" echo -e "\n=== Checking ReportParser for SARIF support ===" rg -A 5 "getReport|parse.*SARIF" "src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/" echo -e "\n=== Checking StaticCodeAnalysisTool enum for SARIF ===" rg -A 5 "enum StaticCodeAnalysisTool" "src/main/java/de/tum/cit/aet/artemis/programming/"Length of output: 2115
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/SpotbugsParser.java (1)
Line range hint
71-73
: Add null check before accessing first element.The
getFirst()
call onsrcDirs()
could throw NPE if the list is null. Consider using Optional or explicit null checking.-String sourceDirectory = bugCollection.project().srcDirs().isEmpty() ? "" : bugCollection.project().srcDirs().getFirst(); +List<String> srcDirs = bugCollection.project().srcDirs(); +String sourceDirectory = (srcDirs == null || srcDirs.isEmpty()) ? "" : srcDirs.getFirst();src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/PMDCPDParser.java (1)
Line range hint
1-93
: Consider architectural improvements for better maintainability.The class follows good practices but could benefit from these improvements:
- Inject XmlMapper for better testability
- Make constants for magic strings
- Make methods final where possible
class PMDCPDParser implements ParserStrategy { - private static final String CPD_CATEGORY = "Copy/Paste Detection"; + private static final String CPD_CATEGORY = "Copy/Paste Detection"; + private static final String LINES_SUFFIX = " lines"; + private static final String FILE_PREFIX = " - "; + private static final String LINES_RANGE = ": Lines "; - private final XmlMapper xmlMapper = new XmlMapper(); + private final XmlMapper xmlMapper; + + public PMDCPDParser(XmlMapper xmlMapper) { + this.xmlMapper = xmlMapper; + } @Override - public StaticCodeAnalysisReportDTO parse(String reportContent) { + public final StaticCodeAnalysisReportDTO parse(String reportContent) {src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/CheckstyleParser.java (1)
43-43
: Add documentation to clarify expected input format.While the parameter rename makes the method more format-agnostic, the implementation still expects XML content. Consider adding a JavaDoc comment to explicitly document this requirement.
+ /** + * Parses a Checkstyle XML report into a StaticCodeAnalysisReportDTO. + * + * @param reportContent The Checkstyle report content in XML format + * @return A StaticCodeAnalysisReportDTO containing the parsed issues + * @throws RuntimeException if parsing fails + */ public StaticCodeAnalysisReportDTO parse(String reportContent) {src/test/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParserTest.java (5)
16-22
: Consider adding a descriptive error message for orElseThrow()While the implementation is correct, adding a descriptive message to
orElseThrow()
would make debugging easier when the full description is missing.- return rule.getFullDescription().orElseThrow().getText(); + return rule.getFullDescription() + .orElseThrow(() -> new IllegalStateException("Full description is required for rule categorization")) + .getText();
24-45
: Consider adding edge cases to empty report testWhile the test covers the basic empty case, consider adding tests for:
- Empty runs array
- Null runs array
- Missing tool section
47-100
: Enhance assertion specificity in metadata testInstead of using
isEqualTo()
on the entire object, consider using AssertJ's field-by-field assertions for better error messages:assertThat(parsedReport.issues()) .singleElement() .satisfies(issue -> { assertThat(issue.filePath()).isEqualTo("/path/to/file.txt"); assertThat(issue.startLine()).isEqualTo(10); assertThat(issue.endLine()).isEqualTo(30); assertThat(issue.startColumn()).isEqualTo(20); assertThat(issue.endColumn()).isEqualTo(40); assertThat(issue.rule()).isEqualTo("RULE_ID"); assertThat(issue.category()).isEqualTo("CATEGORY"); assertThat(issue.message()).isEqualTo("MESSAGE"); assertThat(issue.severity()).isEqualTo("error"); });🧰 Tools
🪛 ast-grep
[warning] 93-93: Detected a cookie where the
HttpOnly
flag is either missing or disabled. TheHttpOnly
cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set theHttpOnly
flag to true` in all other cases.
Context: StaticCodeAnalysisIssue expected = new StaticCodeAnalysisIssue("/path/to/file.txt", 10, 30, 20, 40, "RULE_ID", "CATEGORY", "MESSAGE", "error", null);
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration
102-184
: Make test method names more descriptiveConsider renaming test methods to better describe the scenario being tested:
- void testMessageLookup() + void shouldResolveMessageFromBothLocalAndGlobalMessageStrings()Also, consider splitting this test into two separate tests for better clarity:
shouldResolveMessageFromLocalMessageStrings()
shouldFallbackToGlobalMessageStrings()
292-304
: Add more invalid JSON test casesConsider adding more test cases for invalid JSON scenarios:
- Malformed JSON with invalid field types
- Missing required fields
- Invalid enum values for severity levels
- Invalid URI format in artifactLocation
Example:
@Test void shouldThrowExceptionForInvalidSeverityLevel() { String report = """ { "runs": [{ "results": [{ "level": "invalid_level", ... }] }] } """; // Test implementation }src/test/java/de/tum/cit/aet/artemis/programming/util/ProgrammingExerciseFactory.java (2)
344-344
: LGTM! Consider adding documentation for the "Other" category.The addition of the
OTHER
case is correct and follows the existing pattern. Consider adding a comment to document the purpose and usage of the "Other" category, especially in the context of SARIF parsing.case GCC -> "Memory"; - case OTHER -> "Other"; + // Used for generic or tool-specific categories in SARIF reports that don't map to standard categories + case OTHER -> "Other";
SwiftLint categories need to be properly defined and implemented
Based on the search results, I found that SwiftLint categories are currently not well defined in the codebase:
- The default categories are marked as inactive with "n/a" mappings in
StaticCodeAnalysisConfigurer.java
:
- Idiomatic
- Code Metrics
- Lint
- Performance
- Miscellaneous
- Only "Code Style" category is active with a generic "swiftLint" mapping
- The TODO comment appears in multiple places indicating this is a known issue
To properly implement SwiftLint categories:
- Review SwiftLint's official rule categories
- Update the category mappings in
StaticCodeAnalysisConfigurer.java
- Update the category value in
ProgrammingExerciseFactory.java
- Configure appropriate weights and states for each category
🔗 Analysis chain
Line range hint
339-339
: Follow up on the SwiftLint TODO comment.There's a TODO comment about better defining SwiftLint categories. Since we're working on static code analysis tooling, this might be a good time to address this.
Would you like help defining better SwiftLint categories or should I create a GitHub issue to track this task?
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check for other SwiftLint related TODOs or configurations rg -i "swiftlint.*category" -A 3 -B 3Length of output: 39
Script:
#!/bin/bash # Let's first check for any SwiftLint related TODOs in the codebase rg -i "todo.*swiftlint" -A 3 -B 3 # Also search for SwiftLint configurations or mentions rg -i "swiftlint" -A 3 -B 3Length of output: 15397
src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobExecutionService.java (2)
381-394
: Enhance error handling and logging messages.While the error handling is good, consider these improvements:
- Add the specific parsing exception type to the warning message
- Include file size in the empty file warning
- Consider logging the first few characters of the file content for debugging
- String msg = "The file " + fileName + " does not contain any testcases."; + String msg = String.format("The file '%s' is empty or contains no testcases (size: %d bytes)", + fileName, testResultFileString.length());
447-452
: Enhance method documentation and error handling.The method would benefit from:
- Documentation about supported report formats
- More detailed error messages including the tool type
/** * Processes a static code analysis report file and adds the report to the corresponding list. * * @param fileName the file name of the static code analysis report file * @param reportContent the content of the static code analysis report file * @param staticCodeAnalysisReports the list of static code analysis reports + * @throws IllegalStateException if the report format is not supported or parsing fails + * @see StaticCodeAnalysisTool for supported report formats */ private void processStaticCodeAnalysisReportFile(String fileName, String reportContent, List<StaticCodeAnalysisReportDTO> staticCodeAnalysisReports, String buildJobId) { try { staticCodeAnalysisReports.add(ReportParser.getReport(reportContent, fileName)); } catch (UnsupportedToolException e) { - String msg = "Failed to parse static code analysis report for " + fileName; + String msg = String.format("Failed to parse static code analysis report '%s'. Tool type: %s", + fileName, StaticCodeAnalysisTool.getToolByFilePattern(fileName) + .map(Object::toString).orElse("unknown")); buildLogsMap.appendBuildLogEntry(buildJobId, msg); throw new IllegalStateException("Failed to parse static code analysis report for " + fileName, e); } }src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/ReportParser.java (2)
14-14
: Update the JavaDoc to accurately describe the method's functionalityThe current description "Builds the document using the provided string and parses it to a Report object." may be misleading. Consider rephrasing it to more precisely reflect the method's operation.
Apply this diff to update the JavaDoc:
- * Builds the document using the provided string and parses it to a Report object. + * Parses the provided static code analysis report content and returns a report DTO.
16-17
: Clarify the purpose of the 'fileName' parameterThe parameter
fileName
is used to configure the parser based on the report's format. To enhance clarity, consider renaming the parameter or updating the documentation to better reflect its role.Apply this diff to update the JavaDoc:
- * @param fileName filename of the report used for configuring a parser + * @param fileName Name of the report file used to determine the appropriate parser based on its formatAlternatively, consider renaming the parameter:
- public static StaticCodeAnalysisReportDTO getReport(String reportContent, String fileName) { + public static StaticCodeAnalysisReportDTO getReport(String reportContent, String reportFileName) {src/main/java/de/tum/cit/aet/artemis/programming/domain/StaticCodeAnalysisTool.java (2)
14-23
: Minimize the use of@formatter:off
and@formatter:on
annotationsExcessive use of
@formatter:off
and@formatter:on
can hinder code readability and consistency. Consider adhering to the project's formatting guidelines to maintain uniformity across the codebase without disabling the formatter.
Line range hint
52-60
: Rename method and update documentation for consistencyThe method
getToolByFilePattern
usesfileName
for exact matching, not patterns. Renaming the method togetToolByFileName
and updating the documentation will enhance clarity and accurately reflect its functionality.Apply this diff to update the method name and documentation:
/** - * Finds a tool by its file pattern (the xml file generated by the tool). + * Finds a tool by its file name (the report file generated by the tool). * - * @param fileName the name of the xml file generated by the tool + * @param fileName the name of the report file generated by the tool * @return Optional with the corresponding tool or empty optional if no appropriate tool was found */ -public static Optional<StaticCodeAnalysisTool> getToolByFilePattern(String fileName) { +public static Optional<StaticCodeAnalysisTool> getToolByFileName(String fileName) { for (StaticCodeAnalysisTool tool : StaticCodeAnalysisTool.values()) { if (Objects.equals(fileName, tool.fileName)) { return Optional.of(tool); } } return Optional.empty(); }src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java (1)
106-110
: Correct the typo in variable namehierarchySeperatorIndex
.The variable name
hierarchySeperatorIndex
contains a typo. It should behierarchySeparatorIndex
for proper spelling and readability.Apply this diff to fix the typo:
- int hierarchySeperatorIndex = ruleId.lastIndexOf('/'); + int hierarchySeparatorIndex = ruleId.lastIndexOf('/'); - if (hierarchySeperatorIndex == -1) { + if (hierarchySeparatorIndex == -1) { return Optional.empty(); } - String baseRuleId = ruleId.substring(0, hierarchySeperatorIndex); + String baseRuleId = ruleId.substring(0, hierarchySeparatorIndex);
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (18)
- build.gradle (3 hunks)
- src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobExecutionService.java (3 hunks)
- src/main/java/de/tum/cit/aet/artemis/programming/domain/StaticCodeAnalysisTool.java (4 hunks)
- src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/ReportParser.java (1 hunks)
- src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/exception/ParserException.java (0 hunks)
- src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/CheckstyleParser.java (1 hunks)
- src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/PMDCPDParser.java (1 hunks)
- src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/PMDParser.java (1 hunks)
- src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/ParserStrategy.java (1 hunks)
- src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/SpotbugsParser.java (1 hunks)
- src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/IdCategorizer.java (1 hunks)
- src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/RuleCategorizer.java (1 hunks)
- src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java (1 hunks)
- src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/utils/ReportUtils.java (0 hunks)
- src/test/java/de/tum/cit/aet/artemis/programming/StaticCodeAnalysisParserUnitTest.java (2 hunks)
- src/test/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParserTest.java (1 hunks)
- src/test/java/de/tum/cit/aet/artemis/programming/util/ProgrammingExerciseFactory.java (1 hunks)
- src/test/resources/test-data/static-code-analysis/reports/cpd_invalid.txt (0 hunks)
💤 Files with no reviewable changes (3)
- src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/exception/ParserException.java
- src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/utils/ReportUtils.java
- src/test/resources/test-data/static-code-analysis/reports/cpd_invalid.txt
✅ Files skipped from review due to trivial changes (1)
- src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/RuleCategorizer.java
🧰 Additional context used
📓 Path-based instructions (13)
src/main/java/de/tum/cit/aet/artemis/buildagent/service/BuildJobExecutionService.java (1)
Pattern
src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_importssrc/main/java/de/tum/cit/aet/artemis/programming/domain/StaticCodeAnalysisTool.java (1)
Pattern
src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_importssrc/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/ReportParser.java (1)
Pattern
src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_importssrc/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/CheckstyleParser.java (1)
Pattern
src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_importssrc/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/PMDCPDParser.java (1)
Pattern
src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_importssrc/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/PMDParser.java (1)
Pattern
src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_importssrc/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/ParserStrategy.java (1)
Pattern
src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_importssrc/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/SpotbugsParser.java (1)
Pattern
src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_importssrc/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/IdCategorizer.java (1)
Pattern
src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_importssrc/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java (1)
Pattern
src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_importssrc/test/java/de/tum/cit/aet/artemis/programming/StaticCodeAnalysisParserUnitTest.java (1)
Pattern
src/test/java/**/*.java
: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: truesrc/test/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParserTest.java (1)
Pattern
src/test/java/**/*.java
: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: truesrc/test/java/de/tum/cit/aet/artemis/programming/util/ProgrammingExerciseFactory.java (1)
Pattern
src/test/java/**/*.java
: test_naming: descriptive; test_size: small_specific; fixed_data: true; junit5_features: true; assert_use: assertThat; assert_specificity: true; archunit_use: enforce_package_rules; db_query_count_tests: track_performance; util_service_factory_pattern: true; avoid_db_access: true; mock_strategy: static_mocks; context_restart_minimize: true
🪛 ast-grep
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/CheckstyleParser.java
[warning] 44-45: Detected a cookie where the
HttpOnly
flag is either missing or disabled. TheHttpOnly
cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set theHttpOnly
flag to true` in all other cases.
Context: (reportContent, new com.fasterxml.jackson.core.type.TypeReference<List>() {
})
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration
[warning] 44-45: Detected a cookie where the
Secure
flag is either missing or disabled. TheSecure
cookie flag instructs the browser to forbid sending the cookie over an insecure HTTP request. Set theSecure
flag totrue
so the cookie will only be sent over HTTPS.
Context: (reportContent, new com.fasterxml.jackson.core.type.TypeReference<List>() {
})
Note: [CWE-614]: Sensitive Cookie in HTTPS Session Without 'Secure' Attribute [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfigurationsrc/test/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParserTest.java
[warning] 93-93: Detected a cookie where the
HttpOnly
flag is either missing or disabled. TheHttpOnly
cookie flag instructs the browser to forbid client-side JavaScript to read the cookie. If JavaScript interaction is required, you can ignore this finding. However, set theHttpOnly
flag to true` in all other cases.
Context: StaticCodeAnalysisIssue expected = new StaticCodeAnalysisIssue("/path/to/file.txt", 10, 30, 20, 40, "RULE_ID", "CATEGORY", "MESSAGE", "error", null);
Note: [CWE-1004]: Sensitive Cookie Without 'HttpOnly' Flag [OWASP A05:2021]: Security Misconfiguration [REFERENCES]
- https://owasp.org/Top10/A05_2021-Security_Misconfiguration
🔇 Additional comments (9)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/ParserStrategy.java (1)
20-20
: LGTM! Parameter rename improves clarity.The parameter rename from
xmlContent
toreportContent
better reflects the generic nature of the input, following the single responsibility principle and preparing the interface for multiple format support.src/test/java/de/tum/cit/aet/artemis/programming/StaticCodeAnalysisParserUnitTest.java (1)
58-75
: LGTM! Well-structured tool-specific testsThe test methods are well-organized, following good testing practices:
- Descriptive naming that clearly indicates what's being tested
- Focused on specific functionality
- Consistent structure across all tool tests
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/SpotbugsParser.java (2)
Line range hint
1-89
: LGTM for the overall implementation.The implementation follows good practices:
- Uses records appropriately for DTOs
- Handles OS-independent paths correctly
- Maintains single responsibility
- Has clear error handling
52-54
: 🛠️ Refactor suggestionConsider validating input format before parsing.
While the parameter rename from
xmlContent
toreportContent
suggests format-agnostic handling, the implementation still assumes XML format. Consider adding format validation to prevent runtime errors with non-XML content.public StaticCodeAnalysisReportDTO parse(String reportContent) { try { + if (!isValidXml(reportContent)) { + throw new IllegalArgumentException("Invalid XML format"); + } BugCollection bugCollection = xmlMapper.readValue(reportContent, BugCollection.class);src/test/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParserTest.java (1)
1-13
: LGTM! Well-organized imports and package structure.The imports are properly organized and use static imports for AssertJ assertions, following best practices.
build.gradle (3)
25-25
: LGTM: Plugin version is appropriate.The jsonschema2pojo plugin version 1.2.2 is the latest stable version, which is suitable for generating Java classes from JSON Schema.
653-658
: LGTM: Proper exclusion of generated sources from Checkstyle.The configuration correctly excludes the generated sources from Checkstyle analysis, which is essential as generated code shouldn't be subject to style checks.
Line range hint
198-658
: Verify SARIF schema location configuration.The configuration for jsonschema2pojo is present, but the SARIF schema source location isn't specified. This is needed for generating the POJO classes.
Let me help verify the schema configuration:
Would you like me to provide a configuration example for the SARIF schema source?
src/main/java/de/tum/cit/aet/artemis/programming/domain/StaticCodeAnalysisTool.java (1)
26-31
: Verify the initialization ofTOOLS_OF_PROGRAMMING_LANGUAGE
While initializing
EnumMap
withMap.of(...)
works in later Java versions, ensure compatibility with all environments where the code will run. Mixing immutable maps with mutable ones could lead to unexpected behavior.Please confirm that this initialization is compatible with the project's supported Java versions.
.../tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/IdCategorizer.java
Outdated
Show resolved
Hide resolved
.../tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/IdCategorizer.java
Outdated
Show resolved
Hide resolved
...in/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/PMDParser.java
Show resolved
Hide resolved
...in/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/PMDParser.java
Show resolved
Hide resolved
...java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/PMDCPDParser.java
Show resolved
Hide resolved
src/main/java/de/tum/cit/aet/artemis/programming/domain/StaticCodeAnalysisTool.java
Show resolved
Hide resolved
...de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java
Outdated
Show resolved
Hide resolved
...de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java
Outdated
Show resolved
Hide resolved
...de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java
Show resolved
Hide resolved
...de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (3)
build.gradle
(4 hunks)src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java
(1 hunks)src/test/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParserTest.java
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- build.gradle
- src/test/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParserTest.java
🧰 Additional context used
📓 Path-based instructions (1)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
📓 Learnings (1)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java (2)
Learnt from: magaupp
PR: ls1intum/Artemis#9609
File: src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java:25-26
Timestamp: 2024-10-28T19:39:06.330Z
Learning: In the `SarifParser` class, tests do not require injecting a different `ObjectMapper`, so it's acceptable to instantiate `ObjectMapper` within the class rather than injecting it via constructor.
Learnt from: magaupp
PR: ls1intum/Artemis#9609
File: src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java:55-55
Timestamp: 2024-10-27T12:51:29.409Z
Learning: The project targets Java 21.
🔇 Additional comments (3)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java (3)
1-33
: LGTM! Clean imports and package structure.
The imports are well-organized, specific (no star imports), and follow the Java coding guidelines.
69-76
:
Improve error handling in parse method.
The current error handling wraps JsonProcessingException
in a generic RuntimeException
, which hides the original error context. This makes it harder for clients to handle specific error cases.
- public StaticCodeAnalysisReportDTO parse(String reportContent) {
+ public StaticCodeAnalysisReportDTO parse(String reportContent) throws SarifFormatException {
SarifLog sarifLog;
try {
sarifLog = objectMapper.readValue(reportContent, SarifLog.class);
}
catch (JsonProcessingException e) {
- throw new RuntimeException(e);
+ throw new SarifFormatException("Failed to parse SARIF report: " + e.getMessage(), e);
}
Likely invalid or redundant comment.
147-161
: Consider graceful handling of missing messages.
Currently, the parser fails when a message is missing. Consider if skipping these results would be more appropriate, allowing other valid results to be processed.
...de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java
Show resolved
Hide resolved
...de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java
Outdated
Show resolved
Hide resolved
All exceptions of SCA parsers are caught in I added local error handling for issue specific problems. Now only they will be skipped instead of the entire file. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (3)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java (3)
109-129
: Consider breaking down processResult method.The method is handling multiple responsibilities: location extraction, rule lookup, category determination, and message handling. Breaking it down would improve readability and maintainability.
+ private record ProcessedRule(String id, String category, Optional<ReportingDescriptor> descriptor) {} + + private ProcessedRule processRule(Result result, ToolComponent driver, Map<String, ReportingDescriptor> ruleOfId) { + String ruleId = getRuleId(result); + Optional<Integer> ruleIndex = getRuleIndex(result); + Optional<ReportingDescriptor> ruleByIndex = driver.getRules().flatMap(rules -> ruleIndex.map(rules::get)); + Optional<ReportingDescriptor> rule = ruleByIndex.or(() -> lookupRuleById(ruleId, ruleOfId)); + String category = rule.map(ruleCategorizer::categorizeRule).orElse(ruleId); + return new ProcessedRule(ruleId, category, rule); + } + private StaticCodeAnalysisIssue processResult(Result result, ToolComponent driver, Map<String, ReportingDescriptor> ruleOfId) throws SarifFormatException { FileLocation fileLocation = result.getLocations() .flatMap(locations -> locations.stream().findFirst()) .flatMap(Location::getPhysicalLocation) .map(this::extractLocation) .orElseThrow(() -> new InformationMissingException("Location needed")); - String ruleId = getRuleId(result); - Optional<Integer> ruleIndex = getRuleIndex(result); - Optional<ReportingDescriptor> ruleByIndex = driver.getRules().flatMap(rules -> ruleIndex.map(rules::get)); - Optional<ReportingDescriptor> rule = ruleByIndex.or(() -> lookupRuleById(ruleId, ruleOfId)); - String category = rule.map(ruleCategorizer::categorizeRule).orElse(ruleId); + ProcessedRule processedRule = processRule(result, driver, ruleOfId); Result.Level level = result.getLevel().orElse(Result.Level.WARNING); - String message = findMessage(result, driver, rule); + String message = findMessage(result, driver, processedRule.descriptor()); return new StaticCodeAnalysisIssue( fileLocation.path(), fileLocation.startLine(), fileLocation.endLine(), fileLocation.startColumn(), fileLocation.endColumn(), - ruleId, category, message, level.toString(), null); + processedRule.id(), processedRule.category(), message, level.toString(), null); }
175-182
: Improve clarity of getBaseRuleId method.The method could be more explicit about its purpose and handle edge cases better.
private static Optional<String> getBaseRuleId(String ruleId) { + if (ruleId == null || ruleId.isEmpty()) { + return Optional.empty(); + } int hierarchySeperatorIndex = ruleId.lastIndexOf('/'); - if (hierarchySeperatorIndex == -1) { + if (hierarchySeperatorIndex <= 0) { // Ensure we have a valid base ID return Optional.empty(); } String baseRuleId = ruleId.substring(0, hierarchySeperatorIndex); return Optional.of(baseRuleId); }
95-107
: Consider implementing partial error recovery.Currently, any malformed result is completely skipped. Consider implementing partial error recovery where possible, such as using default values for missing non-critical information.
For example:
- Missing column information could default to 1
- Missing end line could default to start line
- Missing category could default to a generic category
This would make the parser more resilient while still maintaining data quality.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (1)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java
(1 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
📓 Learnings (1)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java (3)
Learnt from: magaupp
PR: ls1intum/Artemis#9609
File: src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java:43-55
Timestamp: 2024-11-10T02:10:43.536Z
Learning: In `src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java`, exception classes (`SarifFormatException` and `InformationMissingException`) that are only used within the class should remain private.
Learnt from: magaupp
PR: ls1intum/Artemis#9609
File: src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java:25-26
Timestamp: 2024-10-28T19:39:06.330Z
Learning: In the `SarifParser` class, tests do not require injecting a different `ObjectMapper`, so it's acceptable to instantiate `ObjectMapper` within the class rather than injecting it via constructor.
Learnt from: magaupp
PR: ls1intum/Artemis#9609
File: src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java:55-55
Timestamp: 2024-10-27T12:51:29.409Z
Learning: The project targets Java 21.
...de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java
Show resolved
Hide resolved
...de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code looks good now.
I got feedback, that we'd rather not use code generation as a build step. I'll add the required data types as records. |
47c2671
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Outside diff range and nitpick comments (28)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Tool.java (1)
5-10
: Consider enhancing the JavaDoc documentation.While the current documentation is clear, consider adding:
@since
tag for version tracking- Example usage of the record
- Link to the SARIF specification for the Tool object
Example enhancement:
/** * The analysis tool that was run. * * @param driver A component, such as a plug-in or the driver, of the analysis tool that was run. * (Required) + * @since 1.0.0 + * @see <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html#_Toc34317668">SARIF Tool Object</a> + * Example: + * <pre> + * Tool tool = new Tool(new ToolComponent("SpotBugs", "1.0")); + * </pre> */src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/MultiformatMessageString.java (2)
5-10
: Enhance JavaDoc documentation for better clarity.While the basic documentation is present, consider adding:
- Description of supported formats (plain text vs. others)
- Example usage
- Documentation about the JSON deserialization behavior
Example enhancement:
/** * A message string or message format string rendered in multiple formats. + * This record is used in SARIF parsing to handle messages that can be represented + * in both plain text and other formats (e.g., Markdown). * * @param text A plain text message string or format string. * (Required) + * @see com.fasterxml.jackson.annotation.JsonIgnoreProperties + * + * Example: + * <pre> + * var message = new MultiformatMessageString("Error: {0} at line {1}"); + * </pre> */
11-13
: Consider adding parameter validation.While the record implementation is clean and immutable, consider adding validation for the required text parameter to prevent null values.
Example enhancement:
@JsonIgnoreProperties(ignoreUnknown = true) public record MultiformatMessageString(String text) { + public MultiformatMessageString { + if (text == null) { + throw new IllegalArgumentException("text parameter is required"); + } + } }src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/PropertyBag.java (2)
8-10
: Enhance JavaDoc documentation for better clarity.While the basic purpose is documented, consider adding:
- Description of the
additionalProperties
field- Usage examples
- Reference to the SARIF specification section this implements
Consider this documentation enhancement:
/** * Key/value pairs that provide additional information about the object. + * + * This class implements the SARIF PropertyBag as defined in section 3.8.1 of the SARIF spec. + * It allows for flexible storage of additional metadata that may be present in SARIF reports. + * + * @see <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html#_Toc34317498">SARIF PropertyBag</a> */
11-14
: Consider adding type safety and null handling.The current implementation uses
Object
as the value type in the Map, which might be too generic and could lead to runtime type issues.Consider these improvements:
@JsonIgnoreProperties(ignoreUnknown = true) -public record PropertyBag(@JsonAnySetter Map<String, Object> additionalProperties) { +public record PropertyBag(@JsonAnySetter Map<String, Object> additionalProperties) { + public PropertyBag { + // Defensive copy and null check + additionalProperties = additionalProperties != null + ? Map.copyOf(additionalProperties) + : Map.of(); + } }This change:
- Ensures immutability through defensive copying
- Handles null input gracefully
- Maintains the flexibility needed for SARIF parsing while adding safety
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/SarifLog.java (2)
7-14
: Consider enhancing documentation with additional details.While the current documentation is good, it could be more helpful with:
- A link to the SARIF 2.1.0 specification
- Example JSON structure
- Clarification on handling empty or null
runs
listConsider updating the JavaDoc like this:
/** * Static Analysis Results Format (SARIF) Version 2.1.0 JSON Schema * <p> * Static Analysis Results Format (SARIF) Version 2.1.0 JSON Schema: a standard format for the output of static analysis tools. + * @see <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html">SARIF 2.1.0 Specification</a> + * <p> + * Example JSON structure: + * <pre> + * { + * "runs": [ + * { + * "tool": { ... }, + * "results": [ ... ] + * } + * ] + * } + * </pre> * * @param runs The set of runs contained in this log file. - * (Required) + * Must not be null. Empty list indicates no analysis runs. */
15-18
: Consider adding null safety checks for the runs parameter.The record implementation is clean and follows DTO guidelines. However, consider adding runtime validation for the
runs
parameter to prevent null pointer exceptions.Consider adding a compact constructor for validation:
@JsonIgnoreProperties(ignoreUnknown = true) public record SarifLog(List<Run> runs) { - + public SarifLog { + runs = runs != null ? runs : List.of(); + } }src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/ArtifactLocation.java (1)
7-13
: Consider enhancing URI validation and documentationThe record structure and JSON handling are well-implemented. However, consider these improvements:
- Add URI validation to ensure the string is a valid URI
- Enhance documentation to specify:
- Expected URI format (absolute vs. relative)
- Any path restrictions or requirements
- Examples of valid URIs
Consider adding validation in the canonical constructor:
@JsonIgnoreProperties(ignoreUnknown = true) public record ArtifactLocation(String uri) { + public ArtifactLocation { + if (uri != null) { + try { + new java.net.URI(uri); + } catch (java.net.URISyntaxException e) { + throw new IllegalArgumentException("Invalid URI format: " + uri, e); + } + } + }src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/MessageStrings.java (1)
7-10
: Enhance JavaDoc with examples and parameter documentationWhile the documentation is informative, consider adding:
- Example usage of placeholders
- Reference to the SARIF specification section
@param
documentation foradditionalProperties
Example enhancement:
/** * A set of name/value pairs with arbitrary names. Each value is a multiformatMessageString object, which holds message strings in plain text and (optionally) Markdown format. The * strings can include placeholders, which can be used to construct a message in combination with an arbitrary number of additional string arguments. + * + * Example placeholder usage: + * "text": "The {0} contains {1} violations" + * + * @see <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html#_Toc34317468">SARIF spec: Message Strings</a> + * @param additionalProperties Map of message identifiers to their corresponding MultiformatMessageString objects */src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Message.java (2)
7-14
: Consider enhancing documentation with usage examples.The record declaration and documentation are well-structured. The use of
@JsonIgnoreProperties
provides good forward compatibility for the SARIF format.Consider adding:
- Example JSON representation
- Common usage patterns
- Null value handling scenarios
16-28
: Consider caching Optional instances for better performance.The Optional wrapper methods provide good null safety, but creating new Optional instances for each call might impact performance if these methods are called frequently.
Consider caching the Optional instances:
public record Message(String text, String id) { + private volatile Optional<String> cachedOptionalText; + private volatile Optional<String> cachedOptionalId; public Optional<String> getOptionalText() { - return Optional.ofNullable(text); + if (cachedOptionalText == null) { + cachedOptionalText = Optional.ofNullable(text); + } + return cachedOptionalText; } public Optional<String> getOptionalId() { - return Optional.ofNullable(id); + if (cachedOptionalId == null) { + cachedOptionalId = Optional.ofNullable(id); + } + return cachedOptionalId; } }Note: Only apply this optimization if profiling shows these methods are frequently called and creating performance bottlenecks.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Location.java (2)
7-13
: Consider enhancing documentation with examples and spec reference.While the documentation is clear, it would be more helpful with:
- An example of a typical SARIF location structure
- A reference to the relevant section of the SARIF specification
Example enhancement:
/** * A location within a programming artifact. * + * According to the SARIF specification (https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html#_Toc34317670), + * this represents a location where an analysis result was detected. + * + * Example: + * { + * "physicalLocation": { + * "artifactLocation": { "uri": "src/main.js" }, + * "region": { "startLine": 42 } + * } + * } * * @param physicalLocation A physical location relevant to a result. Specifies a reference to a programming artifact together with a range of bytes or characters within that * artifact. */
16-21
: Enhance method documentation with return value and rationale.While the implementation is good, the documentation could be more comprehensive.
Consider enhancing the documentation:
/** * A physical location relevant to a result. Specifies a reference to a programming artifact together with a range of bytes or characters within that artifact. + * + * @return An Optional containing the physical location if present, or empty if the location is null. + * Using Optional promotes null-safety when handling potentially missing location information in SARIF reports. */src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/PhysicalLocation.java (1)
19-21
: Consider adding validation in the Optional wrapper methods.While the Optional wrapper methods provide null-safety, consider adding validation logic for the wrapped objects. For example,
ArtifactLocation
might need URI validation, andRegion
might need range validation.Example enhancement:
public Optional<ArtifactLocation> getOptionalArtifactLocation() { - return Optional.ofNullable(artifactLocation); + return Optional.ofNullable(artifactLocation) + .filter(loc -> loc.uri() != null && !loc.uri().isBlank()); } public Optional<Region> getOptionalRegion() { - return Optional.ofNullable(region); + return Optional.ofNullable(region) + .filter(r -> r.startLine() > 0 && (r.endLine() == null || r.endLine() >= r.startLine())); }Also applies to: 26-28
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Run.java (2)
8-15
: Consider enhancing JavaDoc with specification references.While the documentation is clear, consider adding:
@see
reference to the SARIF specification- Version information of the SARIF format supported
- More concise parameter descriptions
Example enhancement:
/** * Describes a single run of an analysis tool, and contains the reported output of that run. + * @see <a href="https://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html">SARIF v2.1.0 Specification</a> * * @param tool The analysis tool that was run. - * (Required) + * Required. The tool that performed the analysis. * @param results The set of results contained in an SARIF log. The results array can be omitted when a run is solely exporting rules metadata. It must be present (but may be - * empty) if a log file represents an actual scan. + * Optional. The analysis results (required but may be empty for actual scans). */
19-25
: Consider removing redundant JavaDoc.The method documentation duplicates the record parameter documentation. Consider either:
- Removing the redundant documentation, or
- Providing implementation-specific details instead
Example improvement:
- /** - * The set of results contained in an SARIF log. The results array can be omitted when a run is solely exporting rules metadata. It must be present (but may be empty) if a log - * file represents an actual scan. - */ + /** + * Provides a null-safe way to access the analysis results. + * @return an Optional containing the results list, or empty if no results are available + */ public Optional<List<Result>> getOptionalResults() { return Optional.ofNullable(results); }src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/ReportingDescriptorReference.java (1)
16-21
: Consider adding validation for the id parameter.While the constructor handles null
index
appropriately, consider adding validation for theid
parameter to ensure consistent behavior. This is especially important since this class represents a reference used for locating descriptors.public ReportingDescriptorReference(String id, Integer index) { + this.id = Objects.requireNonNullElse(id, ""); this.index = Objects.requireNonNullElse(index, -1); }
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Region.java (2)
7-16
: Consider adding validation for line and column numbers.While the implementation is correct, consider adding validation to ensure that when present, line and column numbers are positive values. This could be done by adding a compact constructor to the record.
Here's a suggested implementation:
@JsonIgnoreProperties(ignoreUnknown = true) public record Region(Integer startLine, Integer startColumn, Integer endLine, Integer endColumn) { + public Region { + if (startLine != null && startLine <= 0) { + throw new IllegalArgumentException("startLine must be positive"); + } + if (startColumn != null && startColumn <= 0) { + throw new IllegalArgumentException("startColumn must be positive"); + } + if (endLine != null && endLine <= 0) { + throw new IllegalArgumentException("endLine must be positive"); + } + if (endColumn != null && endColumn <= 0) { + throw new IllegalArgumentException("endColumn must be positive"); + } + }
18-44
: Consider reducing duplication in Optional wrapper methods.While the implementation is correct, there's repetition in the pattern of wrapping nullable values in Optional. Consider extracting this to a private utility method.
Here's a suggested implementation:
public record Region(Integer startLine, Integer startColumn, Integer endLine, Integer endColumn) { + private static Optional<Integer> toOptional(Integer value) { + return Optional.ofNullable(value); + } + public Optional<Integer> getOptionalStartLine() { - return Optional.ofNullable(startLine); + return toOptional(startLine); } public Optional<Integer> getOptionalStartColumn() { - return Optional.ofNullable(startColumn); + return toOptional(startColumn); } public Optional<Integer> getOptionalEndLine() { - return Optional.ofNullable(endLine); + return toOptional(endLine); } public Optional<Integer> getOptionalEndColumn() { - return Optional.ofNullable(endColumn); + return toOptional(endColumn); }src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/ToolComponent.java (2)
8-19
: Consider adding validation for the required 'name' field.The record is well-documented and follows the single responsibility principle. However, since 'name' is marked as required in the JavaDoc, consider adding validation:
@JsonIgnoreProperties(ignoreUnknown = true) -public record ToolComponent(String name, GlobalMessageStrings globalMessageStrings, List<ReportingDescriptor> rules) { +public record ToolComponent(@NotNull String name, GlobalMessageStrings globalMessageStrings, List<ReportingDescriptor> rules) { + public ToolComponent { + Objects.requireNonNull(name, "Tool component name is required"); + }This ensures that the required field is properly validated at construction time.
21-35
: Consider enhancing JavaDoc for Optional methods.The Optional wrapper methods are well-implemented, but their JavaDoc could be more specific:
/** - * A dictionary, each of whose keys is a resource identifier and each of whose values is a multiformatMessageString object, which holds message strings in plain text and - * (optionally) Markdown format. The strings can include placeholders, which can be used to construct a message in combination with an arbitrary number of additional string - * arguments. + * Returns an Optional wrapper for the globalMessageStrings field. + * + * @return Optional containing the GlobalMessageStrings if present, or empty Optional if null */ /** - * An array of reportingDescriptor objects relevant to the analysis performed by the tool component. + * Returns an Optional wrapper for the rules field. + * + * @return Optional containing the List of ReportingDescriptor if present, or empty Optional if null */src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/ReportingDescriptor.java (3)
9-32
: Consider adding validation for required fields.The JavaDoc indicates that
id
is a required field, but there's no runtime validation to enforce this requirement. Consider adding validation in the compact constructor.@JsonIgnoreProperties(ignoreUnknown = true) public record ReportingDescriptor(String id, Set<String> deprecatedIds, String guid, Set<String> deprecatedGuids, String name, Set<String> deprecatedNames, MultiformatMessageString shortDescription, MultiformatMessageString fullDescription, MessageStrings messageStrings, URI helpUri, MultiformatMessageString help, PropertyBag properties) { + public ReportingDescriptor { + if (id == null || id.isBlank()) { + throw new IllegalArgumentException("id is required and cannot be blank"); + } + }
30-32
: Improve record declaration readability.Consider restructuring the record declaration for better readability by aligning parameters vertically.
-public record ReportingDescriptor(String id, Set<String> deprecatedIds, String guid, Set<String> deprecatedGuids, String name, Set<String> deprecatedNames, - MultiformatMessageString shortDescription, MultiformatMessageString fullDescription, MessageStrings messageStrings, URI helpUri, MultiformatMessageString help, - PropertyBag properties) { +public record ReportingDescriptor( + String id, + Set<String> deprecatedIds, + String guid, + Set<String> deprecatedGuids, + String name, + Set<String> deprecatedNames, + MultiformatMessageString shortDescription, + MultiformatMessageString fullDescription, + MessageStrings messageStrings, + URI helpUri, + MultiformatMessageString help, + PropertyBag properties) {
34-110
: Consider improving documentation and method organization.While the implementation is solid, there are a few suggestions for improvement:
- Some JavaDoc comments are duplicated (e.g., "A message string or message format string rendered in multiple formats" appears multiple times). Consider creating a reference to a common description.
- Consider grouping related methods together (e.g., all deprecated-related methods, all description-related methods) for better organization.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java (1)
172-174
: Consider adding documentation for the rule ID lookup logic.The rule ID lookup implementation includes hierarchy handling, but the logic could be clearer with JavaDoc explaining:
- The format of hierarchical rule IDs
- When and why base rule IDs are used
- Examples of valid rule ID formats
Also applies to: 176-183
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Result.java (3)
30-37
: Consider using primitive types for fields with default valuesThe fields
ruleIndex
,kind
, andlevel
are of boxed types (Integer
,Kind
, andLevel
). Since default values are provided in the constructor, and to adhere to the coding guideline of preferring primitives, consider changing these to primitive types (int
,Kind
, andLevel
cannot be primitives but can be handled appropriately).Apply this diff to modify the field types:
-public record Result(String ruleId, Integer ruleIndex, ReportingDescriptorReference rule, +public record Result(String ruleId, int ruleIndex, ReportingDescriptorReference rule,And update the constructor accordingly:
-public Result(String ruleId, Integer ruleIndex, ReportingDescriptorReference rule, Kind kind, Level level, Message message, List<Location> locations) { +public Result(String ruleId, int ruleIndex, ReportingDescriptorReference rule, Kind kind, Level level, Message message, List<Location> locations) {
86-124
: Reduce code duplication in enum implementationsThe
Kind
andLevel
enums have nearly identical implementations, including thevalue
,CONSTANTS
map, and thefromValue
method. Consider abstracting the common code to a shared utility or base class to adhere to the DRY (Don't Repeat Yourself) principle.Also applies to: 130-169
86-86
: Restrict access modifiers for enums if not publicly requiredBoth
Kind
andLevel
enums are declared as public within theResult
record. If these enums are only used internally or within the same package, consider reducing their access level to package-private to follow the principle of least access.Also applies to: 130-130
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
📒 Files selected for processing (19)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/ArtifactLocation.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/GlobalMessageStrings.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Location.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Message.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/MessageStrings.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/MultiformatMessageString.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/PhysicalLocation.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/PropertyBag.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Region.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/ReportingDescriptor.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/ReportingDescriptorReference.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Result.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Run.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/SarifLog.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Tool.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/ToolComponent.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/IdCategorizer.java
(1 hunks)src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java
(1 hunks)src/test/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParserTest.java
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/IdCategorizer.java
- src/test/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParserTest.java
🧰 Additional context used
📓 Path-based instructions (17)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/ArtifactLocation.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/GlobalMessageStrings.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Location.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Message.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/MessageStrings.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/MultiformatMessageString.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/PhysicalLocation.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/PropertyBag.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Region.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/ReportingDescriptor.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/ReportingDescriptorReference.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Result.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Run.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/SarifLog.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Tool.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/ToolComponent.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java (1)
Pattern src/main/java/**/*.java
: naming:CamelCase; principles:{single_responsibility,small_methods,no_duplication}; db:{perf_queries,datetime_not_timestamp}; rest:{stateless,singleton,delegate_logic,http_only,minimal_dtos}; dtos:{java_records,no_entities,min_data,single_resp}; di:constructor_injection; kiss:simple_code; file_handling:os_indep_paths; practices:{least_access,avoid_transactions,code_reuse,static_member_ref,prefer_primitives}; sql:{param_annotation,uppercase,avoid_subqueries};java:avoid_star_imports
📓 Learnings (1)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java (5)
Learnt from: magaupp
PR: ls1intum/Artemis#9609
File: src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java:57-58
Timestamp: 2024-11-12T12:51:58.050Z
Learning: In the `SarifParser` class, when processing `FileLocation` records, we can expect that the tools used provide sensible line and column numbers, so additional validation is unnecessary.
Learnt from: magaupp
PR: ls1intum/Artemis#9609
File: src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java:77-79
Timestamp: 2024-11-12T12:51:40.391Z
Learning: In the codebase, parsers like `SarifParser` should rethrow exceptions as `RuntimeException` to align with other parsers, and introducing new exception types that have no meaning outside the class is not preferred.
Learnt from: magaupp
PR: ls1intum/Artemis#9609
File: src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java:43-55
Timestamp: 2024-11-12T12:51:58.050Z
Learning: In `src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java`, exception classes (`SarifFormatException` and `InformationMissingException`) that are only used within the class should remain private.
Learnt from: magaupp
PR: ls1intum/Artemis#9609
File: src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java:25-26
Timestamp: 2024-11-12T12:51:40.391Z
Learning: In the `SarifParser` class, tests do not require injecting a different `ObjectMapper`, so it's acceptable to instantiate `ObjectMapper` within the class rather than injecting it via constructor.
Learnt from: magaupp
PR: ls1intum/Artemis#9609
File: src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java:55-55
Timestamp: 2024-11-12T12:51:40.391Z
Learning: The project targets Java 21.
🔇 Additional comments (30)
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Tool.java (2)
1-4
: LGTM! Clean package structure and imports.
The package naming and import statement follow best practices. Good use of specific imports instead of wildcards.
11-13
: Implementation looks good! Let's verify integration points.
The record implementation is clean and follows best practices:
- Uses Java records for immutable DTO
- Properly handles JSON deserialization
- Maintains single responsibility
Let's verify the integration with other SARIF components:
✅ Verification successful
Let me gather more information about the SARIF schema integration by checking the ToolComponent
and related classes.
Implementation is correctly integrated with SARIF schema
The Tool record implementation is properly integrated within the SARIF schema hierarchy:
- Correctly used as a required field in the Run record
- Properly references ToolComponent which follows the same pattern with @JsonIgnoreProperties
- Aligns with the SARIF 2.1.0 JSON schema structure (SarifLog -> Run -> Tool -> ToolComponent)
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify Tool record usage and integration
# Check for references to ensure proper integration
echo "Checking Tool record usage..."
rg -t java "Tool\(" src/main/java
# Verify ToolComponent definition exists
echo "Verifying ToolComponent existence..."
fd -e java -t f "ToolComponent.java" src/main/java
# Check if there are any other SARIF-related classes that might need similar unknown property handling
echo "Checking other SARIF classes..."
fd -e java -t f . src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif
Length of output: 2504
Script:
#!/bin/bash
# Check ToolComponent implementation and its usage
echo "Checking ToolComponent implementation..."
cat src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/ToolComponent.java
# Check SarifLog to understand the overall structure
echo -e "\nChecking SarifLog implementation..."
cat src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/SarifLog.java
# Check Run class to see how Tool is used
echo -e "\nChecking Run implementation..."
cat src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Run.java
Length of output: 4127
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/MultiformatMessageString.java (1)
1-4
: LGTM! Package and imports are well-structured.
The package naming and explicit import follow best practices.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/PropertyBag.java (1)
1-7
: LGTM! Clean package structure and imports.
Package structure and imports follow best practices with specific imports and proper organization.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/SarifLog.java (2)
1-6
: LGTM! Clean and well-organized imports.
The package structure follows conventions, and imports are explicitly declared without using wildcards.
1-18
: Verify integration with SCA tool-specific components.
The SARIF log structure looks good, but let's verify its integration with tool-specific categorizers mentioned in the PR objectives.
✅ Verification successful
Integration with SCA components is properly implemented
The verification shows that SarifLog
is well-integrated within the static code analysis framework:
SarifParser
correctly usesSarifLog
for SARIF format deserialization- The parser is properly connected with
RuleCategorizer
through dependency injection IdCategorizer
implements theRuleCategorizer
interface for SARIF rule categorization
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the integration between SarifLog and RuleCategorizer implementations
# Find all RuleCategorizer implementations that might process SarifLog
ast-grep --pattern 'class $_ implements RuleCategorizer {
$$$
}'
# Find usage patterns of SarifLog with categorizers
rg -l "SarifLog.*RuleCategorizer"
Length of output: 1166
Script:
#!/bin/bash
# Let's verify the integration by checking:
# 1. How SarifLog is used in the codebase
# 2. The relationship between SARIF components and categorizers
# Find direct usages of SarifLog
rg "SarifLog" -A 5
# Find files that connect SARIF components with categorizers
rg "RuleCategorizer.*Sarif|Sarif.*RuleCategorizer" -A 5
# Look for SARIF parser/converter implementations
ast-grep --pattern 'class $_ {
$$$
SarifLog $$$
$$$
}'
Length of output: 3516
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/ArtifactLocation.java (3)
1-6
: LGTM: Clean package structure and imports
The package naming and import statements follow Java conventions and coding guidelines. No unnecessary imports are present.
15-20
: LGTM: Well-implemented null-safe accessor
The getOptionalUri
method follows best practices:
- Provides null-safe access using Optional
- Clear and concise implementation
- Well-documented purpose
1-22
: Verify consistent implementation across SARIF parser
Let's ensure consistent error handling and usage patterns across the SARIF parser implementation.
✅ Verification successful
Based on the results, I can now generate the final response:
Implementation is consistent with SARIF parser patterns
The verification shows consistent implementation across the SARIF parser:
Optional
usage is uniform across all SARIF-related classes for nullable fields- Error handling follows a consistent pattern using
IllegalArgumentException
for invalid values ArtifactLocation
is properly integrated withPhysicalLocation
andSarifParser
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for consistent implementation patterns across SARIF parser
# Check for other classes using ArtifactLocation
echo "Checking ArtifactLocation usage patterns:"
rg -l "ArtifactLocation" --type java
# Check for consistent error handling patterns
echo "\nChecking error handling patterns in SARIF parser:"
rg "throw new" --type java -A 2 -B 2 src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/
# Check for similar Optional usage patterns
echo "\nChecking Optional usage patterns:"
ast-grep --pattern 'return Optional.ofNullable($_)'
Length of output: 9103
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/MessageStrings.java (2)
1-6
: LGTM: Clean package structure and imports
Package naming and import organization follow best practices. Good use of specific imports rather than wildcard imports.
11-13
: Verify MultiformatMessageString implementation
The record implementation follows best practices for DTOs. However, let's verify the referenced MultiformatMessageString
class exists and is properly implemented.
✅ Verification successful
Implementation verified and follows consistent patterns
The MultiformatMessageString
record exists and is properly implemented at src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/MultiformatMessageString.java
. It follows the same immutable record pattern and is consistently used across the SARIF format classes for message handling.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify MultiformatMessageString class exists and follows similar patterns
# Search for MultiformatMessageString class definition
echo "Searching for MultiformatMessageString class definition:"
ast-grep --pattern 'record MultiformatMessageString' || \
ast-grep --pattern 'class MultiformatMessageString'
# Check if it's used consistently across the codebase
echo -e "\nChecking usage patterns:"
rg "MultiformatMessageString" -A 2
Length of output: 3548
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/GlobalMessageStrings.java (2)
1-6
: LGTM! Clean imports and appropriate package structure.
The imports are specific and avoid using wildcards, following the coding guidelines.
7-11
: LGTM! Well-documented with clear purpose.
The JavaDoc clearly explains the record's purpose, structure, and functionality.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Message.java (1)
1-6
: LGTM! Clean and well-organized imports.
The package structure and imports follow best practices with specific imports and clear organization.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Location.java (3)
1-6
: LGTM! Clean and well-organized imports.
Package structure and imports follow best practices with specific imports and clear organization.
14-14
: LGTM! Well-designed record declaration.
The record follows best practices:
- Uses Java records for DTOs
- Maintains single responsibility
- Has clear and descriptive naming
1-23
: Verify SARIF location schema coverage.
Let's ensure this implementation covers all possible location scenarios in the SARIF specification.
✅ Verification successful
Based on the analysis of the SARIF implementation, I can now provide the final response:
The Location implementation adequately covers SARIF specification requirements
The current implementation correctly handles the essential SARIF location components:
- Supports physical locations with artifact references and regions
- Properly handles optional fields through Optional wrappers
- Correctly implements the location hierarchy (Location -> PhysicalLocation -> ArtifactLocation/Region)
- The SarifParser demonstrates proper extraction and validation of all location components
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check if our Location implementation covers all required fields from the SARIF spec
# Search for any additional location-related fields in SARIF examples
rg -i "\"location\".*:.*{" --type json
# Look for other Location-related implementations to ensure consistency
fd -e java -x grep -l "Location" {} \;
Length of output: 9371
Script:
#!/bin/bash
# Let's check the SARIF-related implementations to understand the location handling
# Check the Location class and related classes
rg -A 10 "class.*Location" --type java
# Look for SARIF test files to understand location usage
fd -e json -e sarif -x grep -l "location" {} \;
# Check test cases for SARIF parsing
ast-grep --pattern 'class $_ {
$$$
@Test
$$$
sarif$_($$$) {
$$$
}
$$$
}'
Length of output: 5825
Script:
#!/bin/bash
# Let's check SARIF parser test cases and implementation details
# Check the SARIF parser test class
rg -A 20 "class SarifParserTest" --type java
# Look for SARIF-related classes and their fields
ast-grep --pattern 'class $_ {
$$$
@JsonIgnoreProperties
$$$
record $_($$_) {
$$$
}
}'
# Check for any logical references to Location in SARIF parser
rg -A 5 "Location" src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/
Length of output: 17915
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/PhysicalLocation.java (2)
1-6
: LGTM! Clean imports and package structure.
The imports are specific and well-organized, avoiding wildcard imports as per guidelines.
7-14
: LGTM! Well-documented record with proper JSON handling.
The class is thoroughly documented with JavaDoc, including parameter descriptions. The @JsonIgnoreProperties
annotation ensures robust JSON deserialization.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Run.java (2)
1-7
: LGTM! Clean package structure and imports.
The package naming and import statements follow the coding guidelines, with specific imports and proper organization.
16-17
: LGTM! Well-structured record declaration.
The record follows best practices:
- Uses records for DTOs as per guidelines
- Ensures forward compatibility with
@JsonIgnoreProperties
- Promotes immutability through record usage
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/ReportingDescriptorReference.java (2)
1-15
: LGTM! Well-structured package, imports, and documentation.
The code follows Java naming conventions, uses specific imports, and includes clear JavaDoc documentation. The @JsonIgnoreProperties
annotation is appropriately used for flexible JSON parsing.
23-35
: LGTM! Well-implemented Optional accessors.
The Optional accessor methods are well-designed:
- Clear and descriptive method names following Java conventions
- Proper use of Optional for null-safe access
- Comprehensive JavaDoc documentation
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Region.java (1)
1-6
: LGTM! Clean package structure and imports.
The package naming and import statements follow Java conventions and coding guidelines.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/ToolComponent.java (1)
1-7
: LGTM! Package and imports are well-organized.
The package structure follows Java conventions, and imports are specific without wildcards.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/ReportingDescriptor.java (1)
1-112
: Overall implementation aligns well with PR objectives.
The implementation successfully:
- Uses Java records as suggested in PR comments
- Provides proper error handling through Optional returns
- Follows Java best practices and coding guidelines
- Is well-documented and maintainable
The class serves its purpose well as a POJO for SARIF report deserialization.
src/main/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParser.java (4)
34-38
: LGTM! Well-documented class with clear reference to the SARIF specification.
The class documentation clearly states the SARIF version and includes a link to the specification, which is excellent for maintainability.
86-88
: LGTM! Good handling of non-unique rule IDs.
The code correctly handles potential duplicate rule IDs by using the first occurrence, and the approach is well-documented with a clear comment.
95-107
: LGTM! Robust error handling with appropriate logging levels.
The error handling strategy allows processing to continue even when individual results are problematic:
- Critical format issues are logged as errors
- Missing information is logged as warnings
- Null results are filtered out, allowing partial success
137-141
: LGTM! Good handling of optional region fields with sensible defaults.
The code provides appropriate defaults for optional fields:
- startColumn defaults to 1
- endLine defaults to startLine
- endColumn defaults to startColumn + 1
...cit/aet/artemis/programming/service/localci/scaparser/format/sarif/GlobalMessageStrings.java
Show resolved
Hide resolved
...n/java/de/tum/cit/aet/artemis/programming/service/localci/scaparser/format/sarif/Result.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code re-approve
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code lgtm
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Approve code
I think that there are some redundant javadoc comments within the format/sarif folder that do not add value, in the future we might think about leaving those comments and descriptions out
things like
/**
* The identifier for this message.
*/
public Optional<String> getOptionalId() {
return Optional.ofNullable(id);
}
...um/cit/aet/artemis/programming/service/localci/scaparser/strategy/sarif/SarifParserTest.java
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code looks good to me
Checklist
General
Server
Changes affecting Programming Exercises
Motivation and Context
SARIF is a widely supported exchange format for static code analysis tools. Adding support for this standardized format will be the basis for future additions of SCA tools.
Description
The POJO classes used for deserialization are generated from the JSON schema provided by the standard.
The parser implementation should cover all relevant cases a compliant report could create.
The category of an issue is determined by a tool specific RuleCategorizer.
See #9573 for an example on how the parser is used.
In addition some parts of the ReportParser are removed which were only used in tests.
This simplifies the testing of SCA tools.
This introduces deviations from the code copied from the static-code-analysis-parser repository. But considering #9055 I suggest to move all report parsing, including reports collected by the Jenkins plugin, into this repository.
Testserver States
Note
These badges show the state of the test servers.
Green = Currently available, Red = Currently locked
Click on the badges to get to the test servers.
Review Progress
Code Review
Test Coverage
Server
Screenshots
Summary by CodeRabbit
Release Notes
New Features
Run
,Result
,Tool
, andReportingDescriptor
, improving data structure for analysis results.IdCategorizer
class for categorizing rules in SARIF reports.Improvements
.sarif
.Bug Fixes
Tests