Documentation
¶
Overview ¶
Package finding provides a unified data model and pipeline for static analysis tools.
The finding package solves the fragmentation problem in Go's static analysis ecosystem where each tool invents its own types for findings. It provides:
- A common Finding type that all tools can use
- Standard severity levels (info, warning, error, critical)
- Fix strategies (none, suggest, direct, ai)
- Position tracking with range support
- SARIF 2.1.0 output generation
- LSP Diagnostic conversion
- go/analysis integration
- Report merging and filtering
Quick Start ¶
Create a finding:
f := finding.Finding{
ID: finding.GenerateID("my-tool", "unused-var", finding.Position{File: "main.go", Line: 5}),
Rule: "unused-var",
ToolName: "my-tool",
Message: "variable x is unused",
Severity: finding.SeverityWarning,
Position: finding.Position{File: "main.go", Line: 5, Column: 2},
}
Create a report:
report := finding.NewReport(finding.ToolInfo{Name: "my-tool"})
report.AddFinding(f)
report.ComputeSummary()
Output as SARIF:
sarifJSON, err := report.ToSARIF()
Core Types ¶
The main types are Finding, Report, and the supporting types:
- Finding: A single issue detected by a tool
- Report: Container for all findings from a tool run
- Severity: info, warning, error, critical
- FixStrategy: none, suggest, direct, ai
- Position: File, line, column location
- Range: Start and end positions
Filtering ¶
Filter findings using predicates:
errors := finding.Filter(findings, finding.BySeverity(finding.SeverityError)) autoFixable := finding.Filter(findings, finding.ByFixStrategy(finding.FixStrategyDirect)) byFile := finding.GroupByFile(findings)
Converting from go/analysis ¶
Convert from the standard Go analysis framework:
finding := finding.FromDiagnostic(diag, pass.Fset, "my-analyzer", "RULE001")
Pipeline ¶
The package includes a pipeline for automated fixing:
- Detect: Run tools and collect findings
- Triage: Route by fix strategy
- Fix: Apply direct fixes, route AI fixes
- Verify: Re-run and validate
See the pipeline subpackage for details.
Cross-Tool Correlation ¶
Correlate finds related findings across different tools using simple heuristics (same file, nearby lines). It is a standalone utility, not wired into the pipeline:
correlations := finding.Correlate(allFindings)
for _, c := range correlations {
fmt.Printf("%v are related: %s (%.1f)\n", c.FindingIDs, c.Reason, c.Confidence)
}
Known Limitations ¶
SeverityCritical maps to SARIF level "error" (SARIF 2.1.0 has no "critical" level). The original severity is preserved in Properties["go-finding/severity"] for round-trip fidelity.
Related Projects ¶
- go/analysis: The standard Go analysis framework
- SARIF 2.1.0: Static Analysis Results Interchange Format
- LSP: Language Server Protocol
Example (Basic) ¶
package main
import (
"fmt"
"github.com/larsartmann/go-finding"
)
func main() {
// Create a finding
f := finding.Finding{
ID: finding.GenerateID(
"my-linter",
"unused-import",
finding.Position{File: "main.go", Line: 5},
),
Rule: "unused-import",
ToolName: "my-linter",
Message: "import \"fmt\" is unused",
Severity: finding.SeverityWarning,
Position: finding.Pos("main.go", 5, 2),
Category: finding.CategoryStyle,
FixStrategy: finding.FixStrategyDirect,
BeforeCode: `import "fmt"`,
AfterCode: "",
}
// Create a report
report := finding.NewReport(finding.ToolInfo{Name: "my-linter", Version: "1.0.0"})
report.AddFinding(f)
report.ComputeSummary()
// Print summary
fmt.Printf("Tool: %s\n", report.Tool.Name)
fmt.Printf("Total findings: %d\n", report.Summary.Total)
fmt.Printf("Warnings: %d\n", report.Summary.BySeverity[finding.SeverityWarning])
}
Output: Tool: my-linter Total findings: 1 Warnings: 1
Example (Filter) ¶
package main
import (
"fmt"
"github.com/larsartmann/go-finding"
)
func main() {
findings := []finding.Finding{
{ID: "1", Severity: finding.SeverityError, Rule: "nil-pointer", ToolName: "analyzer"},
{ID: "2", Severity: finding.SeverityWarning, Rule: "unused-var", ToolName: "analyzer"},
{ID: "3", Severity: finding.SeverityInfo, Rule: "comment-style", ToolName: "analyzer"},
}
// Filter for errors only
errors := finding.Filter(findings, finding.BySeverity(finding.SeverityError))
fmt.Printf("Errors: %d\n", len(errors))
// Filter for severity >= warning
warningsAndErrors := finding.Filter(
findings,
finding.BySeverityAtLeast(finding.SeverityWarning),
)
fmt.Printf("Warnings and Errors: %d\n", len(warningsAndErrors))
}
Output: Errors: 1 Warnings and Errors: 2
Example (Merge) ¶
package main
import (
"fmt"
"github.com/larsartmann/go-finding"
)
func main() {
// Reports from different tools
r1 := finding.NewReport(finding.ToolInfo{Name: "linter-a"})
r1.AddFinding(finding.Finding{
ID: "a:rule1:file.go:10:5",
Severity: finding.SeverityError,
Position: finding.Position{File: "file.go", Line: 10},
})
r2 := finding.NewReport(finding.ToolInfo{Name: "linter-b"})
r2.AddFinding(finding.Finding{
ID: "b:rule2:file.go:20:3",
Severity: finding.SeverityWarning,
Position: finding.Position{File: "file.go", Line: 20},
})
// Merge reports
merged := finding.Merge([]*finding.Report{r1, r2})
merged.ComputeSummary()
fmt.Printf("Total: %d\n", merged.Summary.Total)
fmt.Printf("Files: %d\n", merged.Summary.FilesAffected)
}
Output: Total: 2 Files: 1
Example (Merging) ¶
Example_mergingShows unified report from multiple tools.
package main
import (
"fmt"
"github.com/larsartmann/go-finding"
)
func main() {
// Tool A: Linter
toolA := finding.NewReport(finding.ToolInfo{Name: "linter", Version: "1.0"})
toolA.AddFinding(finding.Finding{
ID: "linter:unused:main.go:10",
Rule: "unused",
ToolName: "linter",
Message: "unused variable",
Severity: finding.SeverityWarning,
Position: finding.Position{File: "main.go", Line: 10},
})
// Tool B: Security Scanner
toolB := finding.NewReport(finding.ToolInfo{Name: "security", Version: "2.0"})
toolB.AddFinding(finding.Finding{
ID: "security:sql-inject:db.go:45",
Rule: "sql-inject",
ToolName: "security",
Message: "SQL injection vulnerability",
Severity: finding.SeverityCritical,
Position: finding.Position{File: "db.go", Line: 45},
})
// Merge into unified report
merged := finding.Merge([]*finding.Report{toolA, toolB})
merged.ComputeSummary()
fmt.Printf("Unified Report:\n")
fmt.Printf("Total: %d findings from %d tools\n", merged.Summary.Total, 2)
fmt.Printf("By severity: critical=%d, warning=%d\n",
merged.Summary.BySeverity[finding.SeverityCritical],
merged.Summary.BySeverity[finding.SeverityWarning])
}
Output: Unified Report: Total: 2 findings from 2 tools By severity: critical=1, warning=1
Example (SimpleCLI) ¶
Example_simpleCLI demonstrates a simple CLI tool using the finding library.
package main
import (
"fmt"
"log"
"github.com/larsartmann/go-finding"
)
func main() {
// Simulate findings from a tool
findings := []finding.Finding{
{
ID: "linter:unused-import:main.go:3:2",
Rule: "unused-import",
ToolName: "my-linter",
Message: "import \"fmt\" is unused",
Severity: finding.SeverityWarning,
Position: finding.Pos("main.go", 3, 2),
Category: finding.CategoryStyle,
FixStrategy: finding.FixStrategyDirect,
BeforeCode: `import "fmt"`,
AfterCode: "",
},
{
ID: "linter:unused-var:main.go:10:5",
Rule: "unused-var",
ToolName: "my-linter",
Message: "variable x is unused",
Severity: finding.SeverityWarning,
Position: finding.Pos("main.go", 10, 5),
Category: finding.CategoryStyle,
FixStrategy: finding.FixStrategySuggest,
Suggestion: "Remove the variable or use it",
},
{
ID: "linter:nil-pointer:auth.go:45:12",
Rule: "nil-pointer",
ToolName: "my-linter",
Message: "potential nil pointer dereference",
Severity: finding.SeverityError,
Position: finding.Position{File: "auth.go", Line: 45, Column: 12},
Category: finding.CategorySecurity,
FixStrategy: finding.FixStrategyNone,
},
}
// Create report
report := finding.NewReport(finding.ToolInfo{Name: "my-linter", Version: "1.0.0"})
report.AddFindings(findings)
report.ComputeSummary()
// Filter for actionable items
autoFixable := finding.Filter(findings, finding.ByFixStrategy(finding.FixStrategyDirect))
suggestions := finding.Filter(findings, finding.ByFixStrategy(finding.FixStrategySuggest))
// Output summary
fmt.Printf("=== Analysis Summary ===\n")
fmt.Printf("Total findings: %d\n", report.Summary.Total)
fmt.Printf("Auto-fixable: %d\n", len(autoFixable))
fmt.Printf("Need manual review: %d\n", len(suggestions))
fmt.Printf("Errors: %d\n", report.Summary.BySeverity[finding.SeverityError])
fmt.Printf("Warnings: %d\n", report.Summary.BySeverity[finding.SeverityWarning])
// Output SARIF for CI integration
sarif, err := report.ToSARIF()
if err != nil {
log.Fatal(err)
}
_ = sarif // In real tool, write to file
}
Output: === Analysis Summary === Total findings: 3 Auto-fixable: 1 Need manual review: 1 Errors: 1 Warnings: 2
Index ¶
- Constants
- Variables
- func FilterInvalid(f Finding) bool
- func FormatDiagnostic(d *analysis.Diagnostic, fset *token.FileSet, analyzerName string) string
- func GenerateID(toolName, rule string, pos Position) string
- func GroupBy(findings []Finding, keyFn func(Finding) string) map[string][]Finding
- func GroupByCategory(findings []Finding) map[Category][]Finding
- func GroupByFile(findings []Finding) map[string][]Finding
- func GroupBySeverity(findings []Finding) map[Severity][]Finding
- func HasFix(f Finding) bool
- func HasSuggestion(f Finding) bool
- func IsCategory(err error, cat ErrorCategory) bool
- func IsFindingError(err error) bool
- func IsHashID(id string) bool
- func NotSuppressed(f Finding) bool
- func RangeLinesEq(a, b Range) bool
- func SortByPosition(findings []Finding)
- func SortBySeverity(findings []Finding)
- type Builder
- func (b *Builder) Build() Finding
- func (b *Builder) WithAfterCode(code string) *Builder
- func (b *Builder) WithBeforeCode(code string) *Builder
- func (b *Builder) WithCategory(cat Category) *Builder
- func (b *Builder) WithConfidence(c float64) *Builder
- func (b *Builder) WithFixStrategy(fs FixStrategy) *Builder
- func (b *Builder) WithID(id string) *Builder
- func (b *Builder) WithMetadata(m map[string]string) *Builder
- func (b *Builder) WithRange(r Range) *Builder
- func (b *Builder) WithRelated(refs ...RelatedRef) *Builder
- func (b *Builder) WithSnippet(s string) *Builder
- func (b *Builder) WithSuggestion(s string) *Builder
- func (b *Builder) WithSuppression(s Suppression) *Builder
- func (b *Builder) WithTag(tag string) *Builder
- type Category
- type Correlation
- type DeduplicateBy
- type ErrorCategory
- type FilterFunc
- type Finding
- func Filter(findings []Finding, predicates ...FilterFunc) []Finding
- func FindingsFromJSON(data []byte) ([]Finding, int, error)
- func FindingsFromSARIF(data []byte) ([]Finding, error)
- func FromDiagnostic(d *analysis.Diagnostic, fset *token.FileSet, toolName, ruleCode string) Finding
- func FromJSON(data []byte) (*Finding, error)
- func FromLSP(fileURI string, diag LSPDiagnostic) Finding
- func NewFinding(rule, toolName, message string, severity Severity, pos Position) Finding
- func (f Finding) Clone() Finding
- func (f Finding) Equal(other Finding) bool
- func (f Finding) HasFix() bool
- func (f Finding) HasSuggestion() bool
- func (f Finding) IsSuppressed() bool
- func (f Finding) IsSuppressedAt(now time.Time) bool
- func (f Finding) IsValid() bool
- func (f Finding) LineJSON() (string, error)
- func (f Finding) NormalizedConfidence() float64
- func (f Finding) String() string
- func (f Finding) ToLSP() LSPDiagnostic
- type FindingError
- func NewConflictError(message string, cause error) *FindingError
- func NewIOError(message string, cause error) *FindingError
- func NewInternalError(message string, cause error) *FindingError
- func NewParseError(message string, cause error) *FindingError
- func NewValidationError(message string, cause error) *FindingError
- type FixStrategy
- type LSPDiagnostic
- type LSPLocation
- type LSPPosition
- type LSPRange
- type LSPRelatedInfo
- type MergeOption
- type MergeOptions
- type ParsedID
- type Position
- type Range
- func (r Range) Adjacent(other Range) bool
- func (r Range) Compare(other Range) int
- func (r Range) Contains(p Position) bool
- func (r Range) Equal(other Range) bool
- func (r Range) HasEnd() bool
- func (r Range) Intersection(other Range) *Range
- func (r Range) IsValid() bool
- func (r Range) Length() int
- func (r Range) LineCount() int
- func (r Range) Overlaps(other Range) bool
- type RelatedRef
- type Report
- func (r *Report) ActiveFindings() []Finding
- func (r *Report) AddFinding(f Finding)
- func (r *Report) AddFindings(findings []Finding)
- func (r *Report) All() iter.Seq[Finding]
- func (r *Report) ByCategory(cat Category) []Finding
- func (r *Report) ByFixStrategy(fs FixStrategy) []Finding
- func (r *Report) BySeverity(sev Severity) []Finding
- func (r *Report) ComputeSummary()
- func (r *Report) FindByID(id string) *Finding
- func (r *Report) FindByRule(rule string) []Finding
- func (r *Report) Len() int
- func (r *Report) PrettyJSON() (string, error)
- func (r *Report) ToSARIF() ([]byte, error)
- func (r *Report) ToSARIFFiltered(minSeverity Severity) ([]byte, error)
- type SarifArtifactChange
- type SarifArtifactLocation
- type SarifDriver
- type SarifFix
- type SarifLocation
- type SarifLog
- type SarifMessage
- type SarifPhysicalLocation
- type SarifRegion
- type SarifRelatedLoc
- type SarifReplacement
- type SarifResult
- type SarifRun
- type SarifTool
- type Severity
- func (s Severity) Compare(other Severity) int
- func (s Severity) GreaterThan(other Severity) bool
- func (s Severity) GreaterThanOrEqual(other Severity) bool
- func (s Severity) IsValid() bool
- func (s Severity) LessThan(other Severity) bool
- func (s Severity) LessThanOrEqual(other Severity) bool
- func (s Severity) String() string
- type Summary
- type Suppression
- type SuppressionKind
- type ToolInfo
Examples ¶
Constants ¶
const ( LSPSeverityError = 1 // Error LSPSeverityWarning = 2 // Warning LSPSeverityInfo = 3 // Information LSPSeverityHint = 4 // Hint )
LSP severity level constants per the LSP specification.
const ( VersionMajor = 0 VersionMinor = 1 VersionPatch = 3 Version = "0.1.3" )
Version constants for programmatic version checking.
Variables ¶
var ( ErrValidation = errors.New("finding: validation error") ErrIO = errors.New("finding: I/O error") ErrParse = errors.New("finding: parse error") ErrConflict = errors.New("finding: conflict error") ErrInternal = errors.New("finding: internal error") )
Sentinel errors for use with errors.Is.
var ( ErrInvalidFinding = errors.New("invalid finding: missing required fields") ErrInvalidReport = errors.New("invalid report: missing tool name") )
Sentinel errors for JSON validation.
Functions ¶
func FilterInvalid ¶ added in v0.2.0
FilterInvalid returns true if the finding is invalid (has missing required fields).
func FormatDiagnostic ¶
FormatDiagnostic returns a formatted string for a go/analysis diagnostic. Similar to how go vet formats output.
func GenerateID ¶
GenerateID creates a stable, unique identifier for a finding. Format: "tool:rule:file:line:col" (human-readable) If line is 0, uses hash-based ID for stability.
Example ¶
package main
import (
"fmt"
"github.com/larsartmann/go-finding"
)
func main() {
pos := finding.Position{File: "main.go", Line: 42, Column: 5}
id := finding.GenerateID("govet", "printf", pos)
fmt.Println(id)
// Hash-based ID when line is 0
posNoLine := finding.Position{File: "main.go"}
hashID := finding.GenerateID("govet", "printf", posNoLine)
fmt.Println(finding.IsHashID(hashID))
}
Output: govet:printf:main.go:42:5 true
func GroupByCategory ¶
GroupByCategory groups findings by category.
func GroupByFile ¶
GroupByFile groups findings by file path.
Example ¶
package main
import (
"fmt"
"github.com/larsartmann/go-finding"
)
func main() {
findings := []finding.Finding{
{ID: "1", Position: finding.Position{File: "a.go"}},
{ID: "2", Position: finding.Position{File: "b.go"}},
{ID: "3", Position: finding.Position{File: "a.go"}},
}
byFile := finding.GroupByFile(findings)
fmt.Println("a.go:", len(byFile["a.go"]))
fmt.Println("b.go:", len(byFile["b.go"]))
}
Output: a.go: 2 b.go: 1
func GroupBySeverity ¶
GroupBySeverity groups findings by severity.
func HasSuggestion ¶
HasSuggestion returns a filter for findings with suggestions.
func IsCategory ¶
func IsCategory(err error, cat ErrorCategory) bool
IsCategory returns true if err is a FindingError with the given category.
func IsFindingError ¶
IsFindingError returns true if err is a *FindingError.
func NotSuppressed ¶
NotSuppressed returns a filter for non-suppressed findings.
func RangeLinesEq ¶
RangeLinesEq checks if two ranges have equal start/end lines (ignoring columns/files).
func SortByPosition ¶
func SortByPosition(findings []Finding)
SortByPosition sorts findings by file path, then line, then column.
func SortBySeverity ¶
func SortBySeverity(findings []Finding)
SortBySeverity sorts findings by severity (most severe first).
Types ¶
type Builder ¶ added in v0.2.0
type Builder struct {
// contains filtered or unexported fields
}
Builder provides a fluent API for constructing Finding values. Use NewBuilder with the required fields, then chain With* methods for optional fields, and call Build to obtain the result.
Example:
f := NewBuilder("nilcheck", "govet", "possible nil deref", SeverityError, Pos("main.go", 42, 5)).
WithFixStrategy(FixStrategyDirect).
WithBeforeCode("x.foo").
WithAfterCode("x.foo()").
Build()
func NewBuilder ¶ added in v0.2.0
NewBuilder creates a builder seeded with the required fields. The ID is auto-generated from the provided arguments.
func (*Builder) WithAfterCode ¶ added in v0.2.0
WithAfterCode sets the code after the fix.
func (*Builder) WithBeforeCode ¶ added in v0.2.0
WithBeforeCode sets the code before the fix.
func (*Builder) WithCategory ¶ added in v0.2.0
WithCategory sets the category.
func (*Builder) WithConfidence ¶ added in v0.2.0
WithConfidence sets the confidence level (clamped to [0.0, 1.0]).
func (*Builder) WithFixStrategy ¶ added in v0.2.0
func (b *Builder) WithFixStrategy(fs FixStrategy) *Builder
WithFixStrategy sets the fix strategy.
func (*Builder) WithMetadata ¶ added in v0.2.0
WithMetadata copies the given metadata into the finding.
func (*Builder) WithRelated ¶ added in v0.2.0
func (b *Builder) WithRelated(refs ...RelatedRef) *Builder
WithRelated appends related references.
func (*Builder) WithSnippet ¶ added in v0.2.0
WithSnippet sets the surrounding code context.
func (*Builder) WithSuggestion ¶ added in v0.2.0
WithSuggestion sets the human-readable fix suggestion.
func (*Builder) WithSuppression ¶ added in v0.2.0
func (b *Builder) WithSuppression(s Suppression) *Builder
WithSuppression sets the suppression info.
type Category ¶
type Category string
Category classifies the domain of a finding.
const ( CategorySecurity Category = "security" CategoryStyle Category = "style" CategoryPerformance Category = "performance" CategoryCorrectness Category = "correctness" CategoryComplexity Category = "complexity" CategoryDuplication Category = "duplication" CategoryErrorHandling Category = "error-handling" CategoryMigration Category = "migration" CategoryTypeSafety Category = "type-safety" CategoryStructure Category = "structure" CategoryConfiguration Category = "configuration" CategoryDocumentation Category = "documentation" CategoryTesting Category = "testing" CategoryUnused Category = "unused" )
Standard category constants for findings.
func (Category) IsStandard ¶
IsStandard returns true if the category is one of the predefined standard constants.
type Correlation ¶
type Correlation struct {
FindingIDs []string `json:"findingIds"`
Reason string `json:"reason"` // Why they're correlated
Confidence float64 `json:"confidence"` // 0.0-1.0
}
Correlation links related findings from different tools.
func Correlate ¶
func Correlate(findings []Finding) []Correlation
Correlate finds potentially related findings across tools. Currently uses simple heuristics: same file + nearby lines.
This can be used standalone or enabled in Pipeline via Config.CorrelateFindings. When enabled, the pipeline populates PipelineResult.Correlations automatically.
Example ¶
package main
import (
"fmt"
"github.com/larsartmann/go-finding"
)
func main() {
findings := []finding.Finding{
{
ID: "govet:printf:main.go:10:3", Rule: "printf",
ToolName: "govet", Message: "format error",
Severity: finding.SeverityWarning,
Position: finding.Pos("main.go", 10, 3),
},
{
ID: "staticcheck:SA1000:main.go:12:1", Rule: "SA1000",
ToolName: "staticcheck", Message: "invalid regex",
Severity: finding.SeverityError,
Position: finding.Pos("main.go", 12, 1),
},
}
correlations := finding.Correlate(findings)
fmt.Println("Correlations:", len(correlations))
for _, c := range correlations {
fmt.Printf("%.1f: %s\n", c.Confidence, c.Reason)
}
}
Output: Correlations: 1 0.6: same file, nearby lines
type DeduplicateBy ¶
type DeduplicateBy int
DeduplicateBy specifies what fields to use for deduplication.
const ( DeduplicateByID DeduplicateBy = iota // Exact ID matches. DeduplicateByPosition // File:line:column matching. DeduplicateByRule // Rule + position matching. )
Deduplication strategies control how findings are matched during merge.
type ErrorCategory ¶
type ErrorCategory string
ErrorCategory categorizes errors for programmatic handling.
const ( // ErrCategoryValidation indicates validation errors. ErrCategoryValidation ErrorCategory = "validation" // ErrCategoryIO indicates file system or network errors. ErrCategoryIO ErrorCategory = "io" // ErrCategoryParse indicates parsing errors. ErrCategoryParse ErrorCategory = "parse" // ErrCategoryConflict indicates conflicting operations. ErrCategoryConflict ErrorCategory = "conflict" // ErrCategoryInternal indicates internal logic errors. ErrCategoryInternal ErrorCategory = "internal" )
func GetCategory ¶
func GetCategory(err error) ErrorCategory
GetCategory returns the category of the error, or empty string if not a FindingError.
func (ErrorCategory) IsValid ¶
func (c ErrorCategory) IsValid() bool
IsValid returns true if the error category is a non-empty string. Custom categories are valid. Use specific constants for predefined values.
type FilterFunc ¶
FilterFunc is a predicate for filtering findings.
func ByCategory ¶
func ByCategory(cat Category) FilterFunc
ByCategory returns a filter for the given category.
func ByFile ¶
func ByFile(file string) FilterFunc
ByFile returns a filter for findings in the given file.
func ByFixStrategy ¶
func ByFixStrategy(fs FixStrategy) FilterFunc
ByFixStrategy returns a filter for the given fix strategy.
func BySeverity ¶
func BySeverity(sev Severity) FilterFunc
BySeverity returns a filter for the given severity.
func BySeverityAtLeast ¶
func BySeverityAtLeast(sev Severity) FilterFunc
BySeverityAtLeast returns a filter for severity >= the given level. Findings with invalid severity are excluded (return false).
type Finding ¶
type Finding struct {
// Identity
ID string `json:"id"` // Stable unique identifier (e.g., "tool:rule:file:42:5")
Rule string `json:"rule"` // Rule/check name (e.g., "STRONG_ID", "clone-detected")
ToolName string `json:"toolName"` // Source tool name (e.g., "branching-flow", "art-dupl")
// Core
Message string `json:"message"` // Human-readable description
Severity Severity `json:"severity"` // info, warning, error, critical
Position Position `json:"position"` // Where the issue is
// Classification
Category Category `json:"category,omitempty"` // Domain: "security", "style", "duplication", etc.
Tag string `json:"tag,omitempty"` // Sub-classification: "phantom-type", "clone", etc.
// Fix
FixStrategy FixStrategy `json:"fixStrategy"` // none, suggest, direct, ai
Suggestion string `json:"suggestion,omitempty"` // Human-readable fix description
BeforeCode string `json:"beforeCode,omitempty"` // Code before the fix
AfterCode string `json:"afterCode,omitempty"` // Code after the fix
// Context
Range *Range `json:"range,omitempty"` // For span-based findings
Snippet string `json:"snippet,omitempty"` // Surrounding code context
Confidence float64 `json:"confidence,omitempty"` // 0.0-1.0
Related []RelatedRef `json:"related,omitempty"` // Related findings
Suppression *Suppression `json:"suppression,omitempty"` // If suppressed
// Extensibility
Metadata map[string]string `json:"metadata,omitempty"` // Tool-specific key-value pairs
}
Finding represents a single issue detected by a static analysis tool.
func Filter ¶
func Filter(findings []Finding, predicates ...FilterFunc) []Finding
Filter returns findings that match all predicates.
Example ¶
package main
import (
"fmt"
"github.com/larsartmann/go-finding"
)
func main() {
findings := []finding.Finding{
{
ID: "1",
Rule: "R1",
Severity: finding.SeverityInfo,
Position: finding.Position{File: "a.go"},
},
{
ID: "2",
Rule: "R2",
Severity: finding.SeverityError,
Position: finding.Position{File: "b.go"},
},
{
ID: "3",
Rule: "R1",
Severity: finding.SeverityWarning,
Position: finding.Position{File: "a.go"},
},
}
errors := finding.Filter(findings, finding.BySeverityAtLeast(finding.SeverityError))
fmt.Println("Errors:", len(errors))
fromA := finding.Filter(findings, finding.ByFile("a.go"))
fmt.Println("In a.go:", len(fromA))
combined := finding.Filter(findings,
finding.ByRule("R1"),
finding.ByFile("a.go"),
)
fmt.Println("R1 in a.go:", len(combined))
}
Output: Errors: 1 In a.go: 2 R1 in a.go: 2
func FindingsFromJSON ¶
FindingsFromJSON parses a slice of Findings from JSON and validates each one. Invalid findings are silently dropped. Use the returned count to detect data loss.
func FindingsFromSARIF ¶
FindingsFromSARIF parses SARIF JSON and returns Findings. It extracts go-finding-specific properties for round-trip fidelity (severity, ID, tool name, etc.) and falls back to SARIF fields otherwise.
func FromDiagnostic ¶
func FromDiagnostic( d *analysis.Diagnostic, fset *token.FileSet, toolName, ruleCode string, ) Finding
FromDiagnostic converts a go/analysis.Diagnostic to a Finding. The toolName parameter identifies which analyzer produced this. The ruleCode parameter provides a rule identifier (since go/analysis.Diagnostic doesn't have Code).
func FromLSP ¶
func FromLSP(fileURI string, diag LSPDiagnostic) Finding
FromLSP creates a Finding from an LSP Diagnostic at the given file URI. Preserves end position in Range and related information when present. The raw LSP severity integer is stored in Metadata under "go-finding/lsp-severity".
func NewFinding ¶
NewFinding creates a Finding with an auto-generated ID and default fix strategy.
func (Finding) Equal ¶
Equal reports whether two findings are identical, including all nested fields.
func (Finding) HasSuggestion ¶
HasSuggestion returns true if this finding has a human-readable suggestion.
func (Finding) IsSuppressed ¶
IsSuppressed returns true if this finding is suppressed at the current time.
func (Finding) IsSuppressedAt ¶ added in v0.2.0
IsSuppressedAt returns true if this finding is suppressed at the given time. Use this in tests for deterministic suppression checks.
func (Finding) NormalizedConfidence ¶ added in v0.2.0
NormalizedConfidence returns the confidence clamped to [0.0, 1.0].
func (Finding) ToLSP ¶
func (f Finding) ToLSP() LSPDiagnostic
ToLSP converts a Finding to LSP Diagnostic format. Note: This is a lossy conversion - some fields (FixStrategy, Confidence, etc.) are lost.
type FindingError ¶
type FindingError struct {
Category ErrorCategory // Category of error
Finding *Finding // Associated finding (may be nil)
Message string // Human-readable message
Cause error // Underlying cause (may be nil)
File string // File path (if applicable)
Position *Position // Position in file (if applicable)
}
FindingError provides structured error information with context.
Example ¶
package main
import (
"errors"
"fmt"
"github.com/larsartmann/go-finding"
)
func main() {
err := finding.NewValidationError("invalid input", nil)
fmt.Println(finding.IsFindingError(err))
fmt.Println(finding.GetCategory(err))
ioErr := finding.NewIOError("read file", errors.New("permission denied"))
fmt.Println(ioErr.Error())
}
Output: true validation [io] read file: permission denied
func NewConflictError ¶
func NewConflictError(message string, cause error) *FindingError
NewConflictError creates a conflict error.
func NewIOError ¶
func NewIOError(message string, cause error) *FindingError
NewIOError creates an IO error.
func NewInternalError ¶
func NewInternalError(message string, cause error) *FindingError
NewInternalError creates an internal error.
func NewParseError ¶
func NewParseError(message string, cause error) *FindingError
NewParseError creates a parse error.
func NewValidationError ¶
func NewValidationError(message string, cause error) *FindingError
NewValidationError creates a validation error.
func (*FindingError) Error ¶
func (e *FindingError) Error() string
Error implements the error interface.
func (*FindingError) Is ¶
func (e *FindingError) Is(target error) bool
Is supports errors.Is by matching sentinel errors.
func (*FindingError) Unwrap ¶
func (e *FindingError) Unwrap() error
Unwrap returns the underlying cause for error inspection.
func (*FindingError) WithFinding ¶
func (e *FindingError) WithFinding(f Finding) *FindingError
WithFinding sets the finding on a copy of the FindingError and returns it.
func (*FindingError) WithPosition ¶
func (e *FindingError) WithPosition(pos Position) *FindingError
WithPosition sets the position on a copy of the FindingError and returns it.
type FixStrategy ¶
type FixStrategy string
FixStrategy indicates how a finding can be remediated.
const ( // FixStrategyNone indicates no fix is available. FixStrategyNone FixStrategy = "none" // FixStrategySuggest provides a human-readable suggestion. FixStrategySuggest FixStrategy = "suggest" // FixStrategyDirect can be automatically applied. FixStrategyDirect FixStrategy = "direct" // FixStrategyAI requires AI assistance. // Pipeline triage groups this with FixStrategySuggest (no auto-apply). // NeedsAI() is defined but no AI backend exists yet. Reserve this value // for future AI-powered remediation — do not remove. FixStrategyAI FixStrategy = "ai" )
func (FixStrategy) CanAutoApply ¶
func (f FixStrategy) CanAutoApply() bool
CanAutoApply returns true if this fix strategy can be automatically applied.
func (FixStrategy) IsValid ¶
func (f FixStrategy) IsValid() bool
IsValid returns true if the fix strategy is a valid value.
func (FixStrategy) NeedsAI ¶
func (f FixStrategy) NeedsAI() bool
NeedsAI returns true if this fix strategy requires AI assistance.
func (FixStrategy) String ¶
func (f FixStrategy) String() string
String returns the string representation of the fix strategy.
type LSPDiagnostic ¶
type LSPDiagnostic struct {
Range LSPRange `json:"range"`
Severity int `json:"severity,omitempty"` // 1=Error, 2=Warning, 3=Info, 4=Hint
Code string `json:"code,omitempty"`
Source string `json:"source,omitempty"`
Message string `json:"message"`
Related []LSPRelatedInfo `json:"relatedInformation,omitempty"`
}
LSPDiagnostic represents an LSP (Language Server Protocol) diagnostic. Used for converting Finding objects to LSP diagnostic format.
type LSPLocation ¶
LSPLocation represents the location of a diagnostic.
type LSPPosition ¶
type LSPPosition struct {
Line int `json:"line"` // 0-based
Character int `json:"character"` // 0-based
}
LSPPosition represents a 0-based position in a text document.
type LSPRange ¶
type LSPRange struct {
Start LSPPosition `json:"start"`
End LSPPosition `json:"end"`
}
LSPRange represents a 0-based character range in a text document.
type LSPRelatedInfo ¶
type LSPRelatedInfo struct {
Location LSPLocation `json:"location"`
Message string `json:"message"`
}
LSPRelatedInfo provides related information for a diagnostic.
type MergeOption ¶
type MergeOption func(*MergeOptions)
MergeOption is a functional option for configuring merge behavior.
func WithDeduplicateBy ¶
func WithDeduplicateBy(by DeduplicateBy) MergeOption
WithDeduplicateBy sets the deduplication strategy.
func WithDeduplication ¶
func WithDeduplication(enabled bool) MergeOption
WithDeduplication enables/disables deduplication.
type MergeOptions ¶
type MergeOptions struct {
Deduplicate bool
DeduplicateBy DeduplicateBy
}
MergeOptions controls how reports are merged.
type ParsedID ¶
ParsedID holds the components of a parsed finding ID.
func ParseID ¶
ParseID parses a finding ID and extracts its components.
Example ¶
package main
import (
"fmt"
"github.com/larsartmann/go-finding"
)
func main() {
p := finding.ParseID("govet:printf:main.go:42:5")
if !p.OK() {
fmt.Println("invalid ID")
return
}
fmt.Printf("tool=%s rule=%s file=%s line=%d col=%d\n", p.Tool, p.Rule, p.File, p.Line, p.Column)
}
Output: tool=govet rule=printf file=main.go line=42 col=5
type Position ¶
type Position struct {
File string `json:"file"` // Required: file path
Line int `json:"line,omitempty"` // 1-based line number; 0 = not set
Column int `json:"column,omitempty"` // 1-based column number; 0 = not set
Offset int `json:"offset,omitempty"` // 0-based byte offset; -1 = not set
}
Position represents a location in source code. Line and Column are 1-based; 0 means not set. Offset is 0-based; -1 means not set (offset 0 = start of file is valid).
func FromTokenPosition ¶
FromTokenPosition creates a Position from a token.Position.
func NodePosition ¶
NodePosition returns a Position from an AST node.
func Pos ¶
Pos is a convenience constructor for Position. It creates a Position with the given file, line, and column.
func (Position) Compare ¶
Compare returns -1, 0, or 1 depending on whether p is less than, equal to, or greater than other. Positions are ordered by file, then line, then column, then offset. This is consistent with Equal: Compare returns 0 iff Equal returns true.
type Range ¶
type Range struct {
Start Position `json:"start"` // Required: start position
End Position `json:"end"` // Optional: end position
}
Range represents a span in source code from Start to End.
Example ¶
package main
import (
"fmt"
"github.com/larsartmann/go-finding"
)
func main() {
r := finding.NewRange("main.go", 10, 1, 15, 20)
p := finding.Position{File: "main.go", Line: 12, Column: 5}
fmt.Println("Contains:", r.Contains(p))
fmt.Println("Valid:", r.IsValid())
fmt.Println("HasEnd:", r.HasEnd())
}
Output: Contains: true Valid: true HasEnd: true
func NewRangePtr ¶
NewRangePtr creates a pointer to a Range with the given file, start/end lines, and columns.
func (Range) Adjacent ¶
Adjacent reports whether this range is immediately adjacent to another range. Adjacent means one range ends exactly where the other begins.
func (Range) Compare ¶
Compare returns -1, 0, or 1 depending on whether r is less than, equal to, or greater than other. Ranges are ordered by start position, then end position.
func (Range) Contains ¶
Contains reports whether the position is within the range. Checks same file, line range, and offset when line ranges aren't available.
func (Range) Intersection ¶
Intersection returns the overlapping region of two ranges, or nil if they don't overlap.
func (Range) Length ¶
Length returns the byte length of the range (End.Offset - Start.Offset). Returns 0 if either offset is not set. Returns 0 if End < Start.
type RelatedRef ¶
type RelatedRef struct {
FindingID string `json:"findingId"` // ID of the related finding
Relation string `json:"relation"` // e.g., "clone-of", "wraps", "causes"
Position Position `json:"position"` // Quick access to related location
}
RelatedRef links to another finding.
func (RelatedRef) IsValid ¶
func (r RelatedRef) IsValid() bool
IsValid returns true if the reference has a non-empty FindingID.
type Report ¶
type Report struct {
Tool ToolInfo `json:"tool"` // Tool metadata
Findings []Finding `json:"findings"` // All findings from this run
Summary Summary `json:"summary"` // Aggregated statistics
// contains filtered or unexported fields
}
Report is the top-level container for a tool run. Use NewReport to create a thread-safe instance.
func Merge ¶
func Merge(reports []*Report, opts ...MergeOption) *Report
Merge combines multiple reports into one. The merged report has: - Tool.Name = "merged" (unless there's only one report) - Findings from all reports - Summary computed from all findings Options control deduplication and conflict resolution.
Example ¶
package main
import (
"fmt"
"github.com/larsartmann/go-finding"
)
func main() {
r1 := finding.NewReport(finding.ToolInfo{Name: "tool-a"})
r1.AddFinding(finding.Finding{
ID: "govet:printf:main.go:10:3",
Rule: "printf",
ToolName: "govet",
Message: "fmt.Printf format error",
Severity: finding.SeverityWarning,
Position: finding.Pos("main.go", 10, 3),
})
r2 := finding.NewReport(finding.ToolInfo{Name: "tool-b"})
r2.AddFinding(finding.Finding{
ID: "staticcheck:SA1000:main.go:20:1",
Rule: "SA1000",
ToolName: "staticcheck",
Message: "invalid regular expression",
Severity: finding.SeverityError,
Position: finding.Pos("main.go", 20, 1),
})
merged := finding.Merge([]*finding.Report{r1, r2})
fmt.Println("Total:", merged.Summary.Total)
}
Output: Total: 2
Example (Deduplication) ¶
package main
import (
"fmt"
"github.com/larsartmann/go-finding"
)
func main() {
duplicate := finding.Finding{
ID: "same-id",
Rule: "R1",
Position: finding.Position{File: "a.go"},
}
r1 := finding.NewReport(finding.ToolInfo{Name: "tool-a"})
r1.AddFinding(duplicate)
r2 := finding.NewReport(finding.ToolInfo{Name: "tool-b"})
r2.AddFinding(duplicate)
merged := finding.Merge([]*finding.Report{r1, r2})
fmt.Println("After dedup:", merged.Summary.Total)
}
Output: After dedup: 1
func NewReport ¶
NewReport creates a new report with the given tool info.
Example ¶
package main
import (
"fmt"
"github.com/larsartmann/go-finding"
)
func main() {
report := finding.NewReport(finding.ToolInfo{Name: "mytool", Version: "1.0.0"})
report.AddFinding(finding.Finding{
ID: "mytool:RULE001:main.go:5:1",
Rule: "RULE001",
ToolName: "mytool",
Message: "unused variable",
Severity: finding.SeverityWarning,
Category: finding.CategoryCorrectness,
FixStrategy: finding.FixStrategySuggest,
Suggestion: "Remove the unused variable",
Position: finding.Pos("main.go", 5, 1),
})
report.ComputeSummary()
fmt.Println("Total:", report.Summary.Total)
fmt.Println("Files:", report.Summary.FilesAffected)
}
Output: Total: 1 Files: 1
func ReportFromJSON ¶
ReportFromJSON parses a Report from JSON and validates required fields. Invalid findings are silently dropped. Use the returned count to detect data loss.
func (*Report) ActiveFindings ¶
ActiveFindings returns all non-suppressed findings.
Example ¶
package main
import (
"fmt"
"github.com/larsartmann/go-finding"
)
func main() {
report := finding.NewReport(finding.ToolInfo{Name: "tool"})
report.AddFinding(finding.Finding{
ID: "1", Rule: "R1", Position: finding.Position{File: "a.go"},
})
report.AddFinding(finding.Finding{
ID: "2", Rule: "R2", Position: finding.Position{File: "b.go"},
Suppression: &finding.Suppression{Kind: finding.SuppressionInSource, Rule: "R2"},
})
active := report.ActiveFindings()
fmt.Println("Active:", len(active))
}
Output: Active: 1
func (*Report) AddFinding ¶
AddFinding adds a finding to the report. Safe for concurrent use.
func (*Report) AddFindings ¶
AddFindings adds multiple findings to the report. Safe for concurrent use.
func (*Report) All ¶ added in v0.2.0
All returns an iterator over all findings in the report. Supports break via yield returning false. All returns all findings in the report (including suppressed). The yielded Finding values are copies; modifications do not affect the report.
func (*Report) ByCategory ¶
ByCategory returns findings filtered by category, excluding suppressed. For composable filtering, use filter.ByCategory with filter.NotSuppressed instead.
func (*Report) ByFixStrategy ¶
func (r *Report) ByFixStrategy(fs FixStrategy) []Finding
ByFixStrategy returns findings filtered by fix strategy, excluding suppressed. For composable filtering, use filter.ByFixStrategy with filter.NotSuppressed instead.
func (*Report) BySeverity ¶
BySeverity returns findings filtered by severity, excluding suppressed. For composable filtering, use filter.BySeverity with filter.NotSuppressed instead.
func (*Report) ComputeSummary ¶
func (r *Report) ComputeSummary()
ComputeSummary recalculates the summary from the current findings.
func (*Report) FindByID ¶
FindByID returns a finding by its ID, or nil if not found. FindByID returns the finding with the given ID, or nil if not found. The returned Finding is a copy; modifications do not affect the report.
func (*Report) FindByRule ¶
FindByRule returns all non-suppressed findings matching the given rule name.
func (*Report) PrettyJSON ¶
PrettyJSON returns a formatted JSON representation of the report.
func (*Report) ToSARIF ¶
ToSARIF converts a Report to SARIF 2.1.0 format.
Example ¶
package main
import (
"encoding/json"
"fmt"
"github.com/larsartmann/go-finding"
)
func main() {
report := finding.NewReport(finding.ToolInfo{Name: "mytool", Version: "1.0.0"})
pos := finding.Pos("main.go", 1, 1)
f := finding.Finding{
Severity: finding.SeverityWarning,
ID: "mytool:R1:main.go:1:1",
Rule: "R1",
ToolName: "mytool",
Message: "test finding",
Position: pos,
}
report.AddFinding(f)
data, err := report.ToSARIF()
if err != nil {
fmt.Println("error:", err)
return
}
var log struct {
Version string `json:"version"`
}
_ = json.Unmarshal(data, &log)
fmt.Println("SARIF version:", log.Version)
}
Output: SARIF version: 2.1.0
type SarifArtifactChange ¶
type SarifArtifactChange struct {
ArtifactLocation SarifArtifactLocation `json:"artifactLocation"`
Replacements []SarifReplacement `json:"replacements"`
}
SarifArtifactChange represents a change to an artifact.
type SarifArtifactLocation ¶
type SarifArtifactLocation struct {
URI string `json:"uri"`
}
SarifArtifactLocation represents the artifact URI.
type SarifDriver ¶
SarifDriver represents the main driver tool with version information.
type SarifFix ¶
type SarifFix struct {
Description SarifMessage `json:"description"`
Changes []SarifArtifactChange `json:"artifactChanges"`
}
SarifFix represents a fix to be applied to the artifact.
type SarifLocation ¶
type SarifLocation struct {
PhysicalLocation SarifPhysicalLocation `json:"physicalLocation"`
}
SarifLocation represents a location in SARIF format.
type SarifLog ¶
type SarifLog struct {
Version string `json:"version"`
Schema string `json:"$schema"`
Runs []SarifRun `json:"runs"`
}
SarifLog represents a SARIF log file containing run results.
type SarifMessage ¶
type SarifMessage struct {
Text string `json:"text"`
}
SarifMessage represents a message in SARIF format.
type SarifPhysicalLocation ¶
type SarifPhysicalLocation struct {
ArtifactLocation SarifArtifactLocation `json:"artifactLocation"`
Region *SarifRegion `json:"region,omitempty"`
}
SarifPhysicalLocation represents physical details of a location.
type SarifRegion ¶
type SarifRegion struct {
StartLine int `json:"startLine,omitempty"`
StartColumn int `json:"startColumn,omitempty"`
EndLine int `json:"endLine,omitempty"`
EndColumn int `json:"endColumn,omitempty"`
}
SarifRegion represents a code region in a text document.
type SarifRelatedLoc ¶
type SarifRelatedLoc struct {
PhysicalLocation SarifPhysicalLocation `json:"physicalLocation"`
Message SarifMessage `json:"message"`
}
SarifRelatedLoc represents a related location in SARIF.
type SarifReplacement ¶
type SarifReplacement struct {
DeletedRegion SarifRegion `json:"deletedRegion"`
InsertedText SarifMessage `json:"insertedText"`
}
SarifReplacement represents a replacement of text in an artifact.
type SarifResult ¶
type SarifResult struct {
RuleID string `json:"ruleId"`
Level string `json:"level"`
Message SarifMessage `json:"message"`
Locations []SarifLocation `json:"locations"`
Fixes []SarifFix `json:"fixes,omitempty"`
Related []SarifRelatedLoc `json:"relatedLocations,omitempty"`
Rank float64 `json:"rank,omitempty"`
Properties map[string]any `json:"properties,omitempty"`
}
SarifResult represents a single finding in SARIF format.
type SarifRun ¶
type SarifRun struct {
Tool SarifTool `json:"tool"`
Results []SarifResult `json:"results"`
}
SarifRun represents a single analysis run in a SARIF log.
type SarifTool ¶
type SarifTool struct {
Driver SarifDriver `json:"driver"`
}
SarifTool defines the static analysis tool that generated the results.
type Severity ¶
type Severity string
Severity represents the severity level of a finding.
Example ¶
package main
import (
"fmt"
"github.com/larsartmann/go-finding"
)
func main() {
fmt.Println(finding.SeverityInfo)
fmt.Println(finding.SeverityWarning)
fmt.Println(finding.SeverityError)
fmt.Println(finding.SeverityCritical)
fmt.Println(finding.SeverityError.GreaterThan(finding.SeverityWarning))
fmt.Println(finding.SeverityInfo.LessThan(finding.SeverityCritical))
}
Output: info warning error critical true true
const ( SeverityInfo Severity = "info" SeverityWarning Severity = "warning" SeverityError Severity = "error" SeverityCritical Severity = "critical" )
Severity levels for findings, ordered by urgency.
func FromSARIFLevel ¶
FromSARIFLevel converts a SARIF level back to Severity. Lossy: both SeverityCritical and SeverityError map to SARIF "error", so FromSARIFLevel("error") returns SeverityError. For full fidelity, read the "go-finding/severity" property from the result instead.
func (Severity) Compare ¶ added in v0.1.3
Compare returns -1, 0, or 1 depending on whether s is less than, equal to, or greater than other. Invalid severities rank below all valid ones. Two different invalid severities are ordered lexicographically to ensure a total ordering.
func (Severity) GreaterThan ¶
GreaterThan returns true if this severity is greater than the other. Order: info < warning < error < critical.
func (Severity) GreaterThanOrEqual ¶
GreaterThanOrEqual returns true if this severity is greater than or equal to the other.
func (Severity) LessThanOrEqual ¶
LessThanOrEqual returns true if this severity is less than or equal to the other.
type Summary ¶
type Summary struct {
Total int `json:"total"` // Total findings
BySeverity map[Severity]int `json:"bySeverity"` // Count by severity
ByCategory map[Category]int `json:"byCategory,omitempty"` // Count by category
ByFixStrategy map[FixStrategy]int `json:"byFixStrategy,omitempty"` // Count by fix strategy
FilesAffected int `json:"filesAffected,omitempty"` // Unique files with findings
DurationMs int64 `json:"durationMs,omitempty"` // Execution time
Suppressed int `json:"suppressed,omitempty"` // Count of suppressed findings
}
Summary contains aggregated statistics for a report.
type Suppression ¶
type Suppression struct {
Kind SuppressionKind `json:"kind"` // Where the suppression is defined
Rule string `json:"rule"` // Which rule is suppressed
Reason string `json:"reason"` // Why it's suppressed
ExpiresAt *time.Time `json:"expiresAt,omitempty"` // Optional expiry
}
Suppression represents a suppressed finding.
func (*Suppression) IsExpired ¶
func (s *Suppression) IsExpired(now time.Time) bool
IsExpired returns true if the suppression has expired relative to now.
func (*Suppression) IsValid ¶
func (s *Suppression) IsValid() bool
IsValid returns true if the suppression has a kind and rule.
type SuppressionKind ¶
type SuppressionKind string
SuppressionKind indicates where a suppression was defined.
const ( SuppressionInSource SuppressionKind = "in-source" // e.g., //nolint, //lint:ignore SuppressionInConfig SuppressionKind = "in-config" // Config file rules SuppressionInReview SuppressionKind = "in-review" // Accepted as false positive )
Suppression kinds indicate where a suppression was defined.
func (SuppressionKind) IsValid ¶
func (k SuppressionKind) IsValid() bool
IsValid returns true if the suppression kind is a recognized value.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
analysis
module
|
|
|
cmd
|
|
|
go-finding
command
Package main implements the go-finding CLI tool.
|
Package main implements the go-finding CLI tool. |
|
examples
|
|
|
basic
command
basic demonstrates creating a Finding and Report from scratch.
|
basic demonstrates creating a Finding and Report from scratch. |
|
builder
command
builder demonstrates the fluent Finding builder API.
|
builder demonstrates the fluent Finding builder API. |
|
pipeline
command
pipeline demonstrates running the detection-fix-verify loop.
|
pipeline demonstrates running the detection-fix-verify loop. |
|
internal
|
|
|
detectors
Package detectors provides built-in detector implementations that wrap external static analysis tools.
|
Package detectors provides built-in detector implementations that wrap external static analysis tools. |
|
Package pipeline provides a detect → triage → fix → verify workflow for automated code remediation.
|
Package pipeline provides a detect → triage → fix → verify workflow for automated code remediation. |
|
toolsdk
module
|