Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package edu.hm.hafner.analysis.parser.violations;

Check warning on line 1 in src/main/java/edu/hm/hafner/analysis/parser/violations/RoslynAnalyzersAdapter.java

View workflow job for this annotation

GitHub Actions / Quality Monitor

Revapi: java.class.added

Class was added.

import java.io.Serial;

/**
* A parser for Roslyn Analyzers SARIF reports.
*
* @author Akash Manna
* @see <a href="https://github.com/dotnet/roslyn-analyzers">Roslyn Analyzers</a>
* @see <a href="https://github.com/dotnet/roslyn">Roslyn</a>
*/
public class RoslynAnalyzersAdapter extends SarifAdapter {
@Serial
private static final long serialVersionUID = 4334638378275050852L;
}
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ public class ParserRegistry {
new ReviveDescriptor(),
new RfLintDescriptor(),
new RoboCopyDescriptor(),
new RoslynAnalyzersDescriptor(),
new RuboCopDescriptor(),
new RuffDescriptor(),
new RustAnalyzerDescriptor(),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package edu.hm.hafner.analysis.registry;

import edu.hm.hafner.analysis.IssueParser;
import edu.hm.hafner.analysis.parser.violations.RoslynAnalyzersAdapter;

/**
* A descriptor for Roslyn Analyzers SARIF reports.
*
* @author Akash Manna
*/
class RoslynAnalyzersDescriptor extends ParserDescriptor {
private static final String ID = "roslyn-analyzers";
private static final String NAME = "Roslyn Analyzers";

RoslynAnalyzersDescriptor() {
super(ID, NAME);
}

@Override
public IssueParser create(final Option... options) {
return new RoslynAnalyzersAdapter();
}

@Override
public String getPattern() {
return "**/roslyn-analyzers-report.sarif";
}

@Override
public String getHelp() {
return "Use command line option <code>/errorlog:roslyn-analyzers-report.sarif</code> "
+ "with <code>dotnet build</code> to generate a Roslyn analyzer SARIF report.";
}

@Override
public String getUrl() {
return "https://learn.microsoft.com/dotnet/csharp/language-reference/compiler-options/errors-warnings#errorlog";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package edu.hm.hafner.analysis.parser.violations;

import org.junit.jupiter.api.Test;

import edu.hm.hafner.analysis.Issue;
import edu.hm.hafner.analysis.IssueParser;
import edu.hm.hafner.analysis.Report;
import edu.hm.hafner.analysis.Severity;
import edu.hm.hafner.analysis.assertions.SoftAssertions;
import edu.hm.hafner.analysis.registry.AbstractParserTest;
import edu.hm.hafner.analysis.registry.ParserRegistry;

import static edu.hm.hafner.analysis.assertions.Assertions.*;

/**
* Tests the class {@link RoslynAnalyzersAdapter}.
*
* @author Akash Manna
*/
class RoslynAnalyzersAdapterTest extends AbstractParserTest {
RoslynAnalyzersAdapterTest() {
super("../roslyn-analyzers-report.sarif");
}

@Override
protected void assertThatIssuesArePresent(final Report report, final SoftAssertions softly) {
softly.assertThat(report).hasSize(3);

softly.assertThat(report.filter(Issue.byType("CA1822")).get(0))
.hasFileName("src/Program.cs")
.hasLineStart(12)
.hasLineEnd(12)
.hasType("CA1822")
.hasSeverity(Severity.WARNING_NORMAL)
.hasMessage("Mark members as static");

softly.assertThat(report.filter(Issue.byType("CA2000")).get(0))
.hasFileName("C:/work/analysis-model/src/Helpers.cs")
.hasLineStart(7)
.hasLineEnd(7)
.hasType("CA2000")
.hasSeverity(Severity.WARNING_HIGH)
.hasMessage("Dispose objects before losing scope");

softly.assertThat(report.filter(Issue.byType("IDE0051")).get(0))
.hasFileName("src/Utilities/Formatting.cs")
.hasLineStart(25)
.hasLineEnd(25)
.hasType("IDE0051")
.hasSeverity(Severity.WARNING_LOW)
.hasMessage("Remove unused private members");
}

@Test
void shouldProvideDescriptorMetadata() {
var descriptor = new ParserRegistry().get("roslyn-analyzers");

assertThat(descriptor.getPattern()).isEqualTo("**/roslyn-analyzers-report.sarif");
assertThat(descriptor.getHelp()).contains("/errorlog:roslyn-analyzers-report.sarif");
assertThat(descriptor.getUrl())
.isEqualTo("https://learn.microsoft.com/dotnet/csharp/language-reference/compiler-options/errors-warnings#errorlog");
assertThat(descriptor.hasHelp()).isTrue();
assertThat(descriptor.hasUrl()).isTrue();
}

@Override
protected IssueParser createParser() {
return new RoslynAnalyzersAdapter();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
class ParserRegistryTest extends ResourceTest {
// Note for parser developers: if you add a new parser,
// please check if you are using the correct type and increment the corresponding count
private static final long WARNING_PARSERS_COUNT = 153L;
private static final long WARNING_PARSERS_COUNT = 154L;
private static final long BUG_PARSERS_COUNT = 3L;
private static final long VULNERABILITY_PARSERS_COUNT = 17L;
private static final long DUPLICATION_PARSERS_COUNT = 3L;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ void shouldFindAllSarifIssues() {
findIssuesOfTool(2, "sarif", "sarif.json");
}

/** Runs the Roslyn Analyzers parser on an output file that contains 3 issues. */
@Test
void shouldFindAllRoslynAnalyzersIssues() {
findIssuesOfTool(3, "roslyn-analyzers", "roslyn-analyzers-report.sarif");
}

/** Runs the Cmake parser on an output file that contains 8 issues. */
@Test
void shouldFindAllCmakeIssues() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
{
"$schema": "https://json.schemastore.org/sarif-2.1.0.json",
"version": "2.1.0",
"runs": [
{
"tool": {
"driver": {
"name": "Microsoft.NetCore.Analyzers"
}
},
"results": [
{
"ruleId": "CA1822",
"level": "warning",
"message": {
"text": "Mark members as static"
},
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "src/Program.cs"
},
"region": {
"startLine": 12,
"endLine": 12,
"startColumn": 9,
"endColumn": 18
}
}
}
]
},
{
"ruleId": "CA2000",
"level": "error",
"message": {
"text": "Dispose objects before losing scope"
},
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "file:///C:/work/analysis-model/src/Helpers.cs"
},
"region": {
"startLine": 7,
"endLine": 7,
"startColumn": 13,
"endColumn": 20
}
}
}
]
},
{
"ruleId": "CA1303",
"level": "warning",
"message": {
"text": "Do not pass literals as localized parameters"
},
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "src/Localization.cs"
},
"region": {
"startLine": 18,
"endLine": 18,
"startColumn": 17,
"endColumn": 29
}
}
}
],
"suppressions": [
{
"state": "accepted",
"justification": "Covered by legacy suppression"
}
]
},
{
"ruleId": "IDE0051",
"level": "note",
"message": {
"text": "Remove unused private members"
},
"locations": [
{
"physicalLocation": {
"artifactLocation": {
"uri": "src/Utilities/Formatting.cs"
},
"region": {
"startLine": 25,
"endLine": 25,
"startColumn": 5,
"endColumn": 15
}
}
}
]
}
]
}
]
}
Loading