Skip to content
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

refactor(errors): move SARIF logic to sarif.d #17025

Merged
merged 1 commit into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 1 addition & 1 deletion compiler/src/build.d
Original file line number Diff line number Diff line change
Expand Up @@ -1560,7 +1560,7 @@ auto sourceFiles()
s2ir.d tocsym.d toctype.d tocvdebug.d todt.d toir.d toobj.d
"),
driver: fileArray(env["D"], "dinifile.d dmdparams.d gluelayer.d lib/package.d lib/elf.d lib/mach.d lib/mscoff.d
link.d mars.d main.d lib/scanelf.d lib/scanmach.d lib/scanmscoff.d timetrace.d vsoptions.d
link.d mars.d main.d sarif.d lib/scanelf.d lib/scanmach.d lib/scanmscoff.d timetrace.d vsoptions.d
"),
frontend: fileArray(env["D"], "
access.d aggregate.d aliasthis.d argtypes_x86.d argtypes_sysv_x64.d argtypes_aarch64.d arrayop.d
Expand Down
172 changes: 1 addition & 171 deletions compiler/src/dmd/errors.d
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import dmd.root.rmem;
import dmd.root.string;
import dmd.console;
import dmd.root.filename;
import dmd.sarif;

nothrow:

Expand All @@ -36,177 +37,6 @@ enum ErrorKind
message,
}

// Struct for SARIF Tool Information
struct ToolInformation {
string name;
string toolVersion;

string toJson() nothrow {
return `{"name": "` ~ name ~ `", "version": "` ~ toolVersion ~ `"}`;
}
}

// Struct for SARIF Result
struct Result {
string ruleId; // Rule identifier
string message; // Error message
string uri; // File path (URI)
int startLine; // Line number where the error occurs
int startColumn; // Column number where the error occurs

string toJson() nothrow {
return `{"ruleId": "` ~ ruleId ~ `", "message": "` ~ message ~ `", "location": {"artifactLocation": {"uri": "` ~ uri ~ `"}, "region": {"startLine": ` ~ intToString(startLine) ~ `, "startColumn": ` ~ intToString(startColumn) ~ `}}}`;
}
}

// SARIF Report Struct
struct SarifReport {
ToolInformation tool; // Information about the tool
Invocation invocation; // Information about the execution
Result[] results; // List of results (errors, warnings, etc.)

string toJson() nothrow {
string resultsJson = "[" ~ results[0].toJson();
foreach (result; results[1 .. $]) {
resultsJson ~= ", " ~ result.toJson();
}
resultsJson ~= "]";

return `{"tool": ` ~ tool.toJson() ~ `, "invocation": ` ~ invocation.toJson() ~ `, "results": ` ~ resultsJson ~ `}`;
}
}

// Function to convert SourceLoc to JSON string
string sourceLocToJson(const SourceLoc sourceLoc) nothrow {
OutBuffer result;

// Write the JSON for the file URI
result.writestring(`{
"artifactLocation": {
"uri": "file://`);
result.writestring(sourceLoc.filename);
result.writestring(`"
},
"region": {
"startLine": `);
result.print(sourceLoc.line);
result.writestring(`,
"startColumn": `);
result.print(sourceLoc.column);
result.writestring(`
}
}`);

return result.extractSlice();
}

// Struct for Invocation Information
struct Invocation {
bool executionSuccessful;

string toJson() nothrow {
return `{"executionSuccessful": ` ~ (executionSuccessful ? "true" : "false") ~ `}`;
}
}

// Function to replace writeln with fprintf for printing to stdout
void printToStdout(string message) nothrow {
fprintf(stdout, "%.*s\n", cast(int)message.length, message.ptr); // Cast to int
}

void generateSarifReport(const ref Loc loc, const(char)* format, va_list ap, ErrorKind kind) nothrow
{
// Format the error message
string formattedMessage = formatErrorMessage(format, ap);

// Create an OutBuffer to store the SARIF report
OutBuffer ob;
ob.doindent = true;

// Extract and clean the version string
const(char)* rawVersionChars = global.versionChars();

// Remove 'v' prefix if it exists
if (*rawVersionChars == 'v') {
rawVersionChars += 1;
}

// Find the first non-numeric character after the version number
const(char)* nonNumeric = strchr(rawVersionChars, '-');
size_t length = nonNumeric ? cast(size_t)(nonNumeric - rawVersionChars) : strlen(rawVersionChars);

// Build SARIF report
ob.level = 0;
ob.writestringln("{");
ob.level = 1;

ob.writestringln(`"version": "2.1.0",`);
ob.writestringln(`"$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json",`);
ob.writestringln(`"runs": [{`);

// Tool Information
ob.level += 1;
ob.writestringln(`"tool": {`);
ob.writestringln(`"driver": {`);
ob.printf(`"name": "%s",`, global.compileEnv.vendor.ptr);
ob.printf(`"version": "%.*s",`, cast(int)length, rawVersionChars);
ob.writestringln(`"informationUri": "https://dlang.org/dmd.html"`);
ob.writestringln("}");
ob.writestringln("},");

// Invocation Information
ob.writestringln(`"invocations": [{`);
ob.writestringln(`"executionSuccessful": false`);
ob.writestringln("}],");

// Results Array
ob.writestringln(`"results": [{`);
ob.writestringln(`"ruleId": "DMD",`);
ob.printf(`"message": { "text": "%s" },`, formattedMessage.ptr);

// Location Information
ob.writestringln(`"locations": [{`);
ob.writestringln(`"physicalLocation": {`);
ob.writestringln(`"artifactLocation": {`);
ob.printf(`"uri": "%s"`, loc.filename);
ob.writestringln("},");
ob.writestringln(`"region": {`);
ob.printf(`"startLine": %d,`, loc.linnum);
ob.printf(`"startColumn": %d`, loc.charnum);
ob.writestringln("}");
ob.writestringln("}");
ob.writestringln("}]");
ob.writestringln("}]");

// Close the run and SARIF JSON
ob.level -= 1;
ob.writestringln("}]");
ob.level = 0;
ob.writestringln("}");

// Extract the final null-terminated string and print it to stdout
const(char)* sarifOutput = ob.extractChars();
fputs(sarifOutput, stdout);
fflush(stdout);
}

// Helper function to format error messages
string formatErrorMessage(const(char)* format, va_list ap) nothrow
{
char[2048] buffer; // Buffer for the formatted message
import core.stdc.stdio : vsnprintf;
vsnprintf(buffer.ptr, buffer.length, format, ap);
return buffer[0 .. buffer.length].dup;
}

// Function to convert int to string
string intToString(int value) nothrow {
char[32] buffer;
import core.stdc.stdio : sprintf;
sprintf(buffer.ptr, "%d", value);
return buffer[0 .. buffer.length].dup;
}

/***************************
* Error message sink for D compiler.
*/
Expand Down
178 changes: 178 additions & 0 deletions compiler/src/dmd/sarif.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
module dmd.sarif;

import core.stdc.stdarg;
import core.stdc.stdio;
import core.stdc.string;
import dmd.errorsink;
import dmd.globals;
import dmd.location;
import dmd.common.outbuffer;
import dmd.root.rmem;
import dmd.console;
import dmd.errors;

// Struct for SARIF Tool Information
struct ToolInformation {
string name;
string toolVersion;

string toJson() nothrow {
return `{"name": "` ~ name ~ `", "version": "` ~ toolVersion ~ `"}`;

Check warning on line 20 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L20

Added line #L20 was not covered by tests
}
}

// Function to convert int to string
string intToString(int value) nothrow {
char[32] buffer;

Check warning on line 26 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L26

Added line #L26 was not covered by tests
import core.stdc.stdio : sprintf;
sprintf(buffer.ptr, "%d", value);
return buffer[0 .. buffer.length].dup;

Check warning on line 29 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L28-L29

Added lines #L28 - L29 were not covered by tests
}

// Struct for SARIF Result
struct Result {
string ruleId; // Rule identifier
string message; // Error message
string uri; // File path (URI)
int startLine; // Line number where the error occurs
int startColumn; // Column number where the error occurs

string toJson() nothrow {
return `{"ruleId": "` ~ ruleId ~ `", "message": "` ~ message ~ `", "location": {"artifactLocation": {"uri": "` ~ uri ~ `"}, "region": {"startLine": ` ~ intToString(startLine) ~ `, "startColumn": ` ~ intToString(startColumn) ~ `}}}`;

Check warning on line 41 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L41

Added line #L41 was not covered by tests
}
}

// SARIF Report Struct
struct SarifReport {
ToolInformation tool; // Information about the tool
Invocation invocation; // Information about the execution
Result[] results; // List of results (errors, warnings, etc.)

string toJson() nothrow {
string resultsJson = "[" ~ results[0].toJson();
foreach (result; results[1 .. $]) {
resultsJson ~= ", " ~ result.toJson();

Check warning on line 54 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L52-L54

Added lines #L52 - L54 were not covered by tests
}
resultsJson ~= "]";

Check warning on line 56 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L56

Added line #L56 was not covered by tests

return `{"tool": ` ~ tool.toJson() ~ `, "invocation": ` ~ invocation.toJson() ~ `, "results": ` ~ resultsJson ~ `}`;

Check warning on line 58 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L58

Added line #L58 was not covered by tests
}
}

// Function to convert SourceLoc to JSON string
string sourceLocToJson(const SourceLoc sourceLoc) nothrow {
OutBuffer result;

Check warning on line 64 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L64

Added line #L64 was not covered by tests

// Write the JSON for the file URI
result.writestring(`{

Check warning on line 67 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L67

Added line #L67 was not covered by tests
"artifactLocation": {
"uri": "file://`);
result.writestring(sourceLoc.filename);
result.writestring(`"

Check warning on line 71 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L70-L71

Added lines #L70 - L71 were not covered by tests
},
"region": {
"startLine": `);
result.print(sourceLoc.line);
result.writestring(`,

Check warning on line 76 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L75-L76

Added lines #L75 - L76 were not covered by tests
"startColumn": `);
result.print(sourceLoc.column);
result.writestring(`

Check warning on line 79 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L78-L79

Added lines #L78 - L79 were not covered by tests
}
}`);

return result.extractSlice();

Check warning on line 83 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L83

Added line #L83 was not covered by tests
}

// Struct for Invocation Information
struct Invocation {
bool executionSuccessful;

string toJson() nothrow {
return `{"executionSuccessful": ` ~ (executionSuccessful ? "true" : "false") ~ `}`;

Check warning on line 91 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L91

Added line #L91 was not covered by tests
}
}

// Helper function to format error messages
string formatErrorMessage(const(char)* format, va_list ap) nothrow
{
char[2048] buffer; // Buffer for the formatted message

Check warning on line 98 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L98

Added line #L98 was not covered by tests
import core.stdc.stdio : vsnprintf;
vsnprintf(buffer.ptr, buffer.length, format, ap);
return buffer[0 .. buffer.length].dup;

Check warning on line 101 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L100-L101

Added lines #L100 - L101 were not covered by tests
}

void generateSarifReport(const ref Loc loc, const(char)* format, va_list ap, ErrorKind kind) nothrow
{
// Format the error message
string formattedMessage = formatErrorMessage(format, ap);

Check warning on line 107 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L107

Added line #L107 was not covered by tests

// Create an OutBuffer to store the SARIF report
OutBuffer ob;
ob.doindent = true;

Check warning on line 111 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L110-L111

Added lines #L110 - L111 were not covered by tests

// Extract and clean the version string
const(char)* rawVersionChars = global.versionChars();

Check warning on line 114 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L114

Added line #L114 was not covered by tests

// Remove 'v' prefix if it exists
if (*rawVersionChars == 'v') {
rawVersionChars += 1;

Check warning on line 118 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L117-L118

Added lines #L117 - L118 were not covered by tests
}

// Find the first non-numeric character after the version number
const(char)* nonNumeric = strchr(rawVersionChars, '-');
size_t length = nonNumeric ? cast(size_t)(nonNumeric - rawVersionChars) : strlen(rawVersionChars);

Check warning on line 123 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L122-L123

Added lines #L122 - L123 were not covered by tests

// Build SARIF report
ob.level = 0;
ob.writestringln("{");
ob.level = 1;

Check warning on line 128 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L126-L128

Added lines #L126 - L128 were not covered by tests

ob.writestringln(`"version": "2.1.0",`);
ob.writestringln(`"$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0.json",`);
ob.writestringln(`"runs": [{`);

Check warning on line 132 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L130-L132

Added lines #L130 - L132 were not covered by tests

// Tool Information
ob.level += 1;
ob.writestringln(`"tool": {`);
ob.writestringln(`"driver": {`);
ob.printf(`"name": "%s",`, global.compileEnv.vendor.ptr);
ob.printf(`"version": "%.*s",`, cast(int)length, rawVersionChars);
ob.writestringln(`"informationUri": "https://dlang.org/dmd.html"`);
ob.writestringln("}");
ob.writestringln("},");

Check warning on line 142 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L135-L142

Added lines #L135 - L142 were not covered by tests

// Invocation Information
ob.writestringln(`"invocations": [{`);
ob.writestringln(`"executionSuccessful": false`);
ob.writestringln("}],");

Check warning on line 147 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L145-L147

Added lines #L145 - L147 were not covered by tests

// Results Array
ob.writestringln(`"results": [{`);
ob.writestringln(`"ruleId": "DMD",`);
ob.printf(`"message": { "text": "%s" },`, formattedMessage.ptr);

Check warning on line 152 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L150-L152

Added lines #L150 - L152 were not covered by tests

// Location Information
ob.writestringln(`"locations": [{`);
ob.writestringln(`"physicalLocation": {`);
ob.writestringln(`"artifactLocation": {`);
ob.printf(`"uri": "%s"`, loc.filename);
ob.writestringln("},");
ob.writestringln(`"region": {`);
ob.printf(`"startLine": %d,`, loc.linnum);
ob.printf(`"startColumn": %d`, loc.charnum);
ob.writestringln("}");
ob.writestringln("}");
ob.writestringln("}]");
ob.writestringln("}]");

Check warning on line 166 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L155-L166

Added lines #L155 - L166 were not covered by tests

// Close the run and SARIF JSON
ob.level -= 1;
ob.writestringln("}]");
ob.level = 0;
ob.writestringln("}");

Check warning on line 172 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L169-L172

Added lines #L169 - L172 were not covered by tests

// Extract the final null-terminated string and print it to stdout
const(char)* sarifOutput = ob.extractChars();
fputs(sarifOutput, stdout);
fflush(stdout);

Check warning on line 177 in compiler/src/dmd/sarif.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/sarif.d#L175-L177

Added lines #L175 - L177 were not covered by tests
}
Loading