Builder
The Sarif::Builder provides a fluent API for constructing SARIF documents. It handles object wiring (tool, rules, results, ruleIndex linking) so you can focus on your data.
Basic Usage
log = Sarif::Builder.build do |b|
b.run("MyTool", "1.0.0") do |r|
r.result("Issue found", level: Sarif::Level::Warning)
end
end
Adding Rules
Define rules before results. The builder auto-links ruleIndex when a result references a rule_id:
log = Sarif::Builder.build do |b|
b.run("Linter") do |r|
r.rule("R001", name: "NoUnused",
short_description: "No unused variables",
level: Sarif::Level::Warning)
r.rule("R002", name: "NoShadow",
short_description: "No shadowed variables",
level: Sarif::Level::Error)
r.result("Variable 'x' is unused",
rule_id: "R001", level: Sarif::Level::Warning,
uri: "src/app.cr", start_line: 15)
r.result("Variable 'i' shadows outer 'i'",
rule_id: "R002", level: Sarif::Level::Error,
uri: "src/loop.cr", start_line: 22, start_column: 5)
end
end
The resulting JSON will have ruleIndex: 0 for the first result and ruleIndex: 1 for the second.
Result Builder Block
For more control, use the block form:
log = Sarif::Builder.build do |b|
b.run("Tool") do |r|
r.result do |rb|
rb.message("Complex issue", markdown: "**Complex** issue")
rb.rule_id("R1")
rb.level(Sarif::Level::Error)
rb.location(uri: "file.cr", start_line: 5, end_line: 10)
rb.related_location(uri: "other.cr", start_line: 20,
message_text: "Related code", id: 1)
rb.fingerprint("primary", "hash123")
end
end
end
Adding Artifacts
Register analyzed files:
log = Sarif::Builder.build do |b|
b.run("Scanner") do |r|
r.artifact("src/main.cr", mime_type: "text/x-crystal")
r.artifact("src/utils.cr", mime_type: "text/x-crystal")
r.result("Issue in main", uri: "src/main.cr", start_line: 1)
end
end
Adding Invocations
Record how the tool was invoked:
log = Sarif::Builder.build do |b|
b.run("Scanner") do |r|
r.invocation(true, "scanner --check src/")
r.result("Found issue", level: Sarif::Level::Warning)
end
end
Multiple Runs
A single SARIF log can contain results from multiple tools:
log = Sarif::Builder.build do |b|
b.run("Linter", "1.0") do |r|
r.result("Style issue", level: Sarif::Level::Note)
end
b.run("SecurityScanner", "2.0") do |r|
r.result("Vulnerability found", level: Sarif::Level::Error)
end
end
Complete Example
log = Sarif::Builder.build do |b|
b.run("CrystalLint", "2.0.0") do |r|
r.rule("CL001", name: "UnusedVar",
short_description: "Unused variable detected",
help_uri: "https://example.com/rules/CL001")
r.rule("CL002", name: "ShadowVar",
short_description: "Variable shadows outer scope")
r.artifact("src/app.cr", mime_type: "text/x-crystal")
r.artifact("src/loop.cr", mime_type: "text/x-crystal")
r.invocation(true, "crystal-lint src/")
r.result("Variable 'x' is never used",
rule_id: "CL001", level: Sarif::Level::Warning,
uri: "src/app.cr", start_line: 15)
r.result("Variable 'i' shadows outer 'i'",
rule_id: "CL002", level: Sarif::Level::Note,
uri: "src/loop.cr", start_line: 22, start_column: 5)
end
end
puts log.to_pretty_json