lint

package
v0.2.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 14, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AnalyzeSetupBody

func AnalyzeSetupBody(body *ast.BlockStmt) token.Pos

AnalyzeSetupBody performs control-flow gating analysis on a Setup callback body. It returns the end position of the first statement that introduces gating (i.e., has an early return in one branch but not all branches). Allocations after this position are conditionally gated.

Returns token.NoPos if no gating is detected.

func NodeString

func NodeString(fset *token.FileSet, node ast.Node) string

NodeString returns a best-effort string representation for a node.

func SetDefaultRules

func SetDefaultRules(rs *RuleSet)

SetDefaultRules installs the default ruleset (called by rules package).

func UnaliasNamed

func UnaliasNamed(t types.Type) *types.Named

UnaliasNamed resolves named types through aliases and pointers.

Types

type AnalysisContext

type AnalysisContext struct {
	FileSet     *token.FileSet
	CurrentFile *ast.File
	FilePath    string

	CurrentFunc *ast.FuncDecl
	ScopeStack  []ScopeType

	SetupDepth int
	SetupIndex int

	AllocationCounts map[string]int

	PropsParamName string
	PropsGetCount  int
	PropsCellNames map[string]bool

	Diagnostics []Diagnostic

	TypeInfo         *types.Info
	PackagePath      string
	IgnoreDirectives map[int][]string
	IgnoreHasReason  map[int]bool

	SetupPropsTypes     map[string]bool
	EventHandlerVisited map[*types.Func]bool

	// GatingEndPos is the end position of the first early-return control flow
	// statement in the current Setup callback. Allocations after this position
	// are conditionally gated by the early return.
	// Set to token.NoPos when no gating is detected.
	GatingEndPos token.Pos

	// CurrentSetupFuncLit is the active Setup callback function literal.
	// It is set only while analyzing the body of a vango.Setup callback.
	CurrentSetupFuncLit *ast.FuncLit

	// SSAIndex provides SSA-backed lookups for dataflow analysis.
	// It is optional; when nil, rules must fall back to syntax-only heuristics.
	SSAIndex *flow.SSAIndex

	// SSAUnavailableReason describes why SSA-based analysis is unavailable.
	// When set, persisted initializer rules will fail-closed and emit an error.
	SSAUnavailableReason string

	// PersistedInitSSAUnavailableReported ensures we emit VANGO.LINT.SSA_UNAVAILABLE
	// at most once per persisted initializer call site.
	PersistedInitSSAUnavailableReported map[token.Pos]bool

	// GlobalInitExprs maps "pkgpath.name" to its initializer expression (if any),
	// based on types.Info.InitOrder for the current package.
	GlobalInitExprs map[string]ast.Expr

	// GlobalVarsMutated marks "pkgpath.name" for package-level vars that are assigned
	// outside their initializer (including inside init() functions). This is used to
	// treat reads of such vars as non-deterministic provenance.
	GlobalVarsMutated map[string]bool
}

AnalysisContext tracks the current analysis state during AST traversal.

func NewAnalysisContext

func NewAnalysisContext(fset *token.FileSet, file *ast.File, filePath string, sharedProps map[string]bool) *AnalysisContext

NewAnalysisContext creates a new analysis context.

func (*AnalysisContext) AddDiagnostic

func (ctx *AnalysisContext) AddDiagnostic(diag Diagnostic)

AddDiagnostic adds a diagnostic to the context.

func (*AnalysisContext) CurrentScope

func (ctx *AnalysisContext) CurrentScope() ScopeType

CurrentScope returns the innermost scope.

func (*AnalysisContext) GatingConditionPos

func (ctx *AnalysisContext) GatingConditionPos() token.Pos

GatingConditionPos returns the end position of the gating control flow statement. Returns token.NoPos if no gating is active.

func (*AnalysisContext) GetCurrentFunctionName

func (ctx *AnalysisContext) GetCurrentFunctionName() string

GetCurrentFunctionName returns the name of the current function.

func (*AnalysisContext) InConditional

func (ctx *AnalysisContext) InConditional() bool

InConditional returns true if currently inside a conditional.

func (*AnalysisContext) InEffectCallback

func (ctx *AnalysisContext) InEffectCallback() bool

InEffectCallback returns true if currently inside an Effect callback.

func (*AnalysisContext) InEventHandler

func (ctx *AnalysisContext) InEventHandler() bool

InEventHandler returns true if currently inside an event handler.

func (*AnalysisContext) InLoop

func (ctx *AnalysisContext) InLoop() bool

InLoop returns true if currently inside a loop.

func (*AnalysisContext) InOnChangeCallback

func (ctx *AnalysisContext) InOnChangeCallback() bool

InOnChangeCallback returns true if currently inside an OnChange callback.

func (*AnalysisContext) InOnChangeKeyFn

func (ctx *AnalysisContext) InOnChangeKeyFn() bool

InOnChangeKeyFn returns true if currently inside an OnChange key function.

func (*AnalysisContext) InOnMountCallback

func (ctx *AnalysisContext) InOnMountCallback() bool

InOnMountCallback returns true if currently inside an OnMount callback.

func (*AnalysisContext) InRenderClosure

func (ctx *AnalysisContext) InRenderClosure() bool

InRenderClosure returns true if currently inside a render closure.

func (*AnalysisContext) InScope

func (ctx *AnalysisContext) InScope(scope ScopeType) bool

InScope checks if we're currently in the given scope type.

func (*AnalysisContext) InSetupCallback

func (ctx *AnalysisContext) InSetupCallback() bool

InSetupCallback returns true if currently inside a Setup callback.

func (*AnalysisContext) IncrementAllocation

func (ctx *AnalysisContext) IncrementAllocation(class, kind string) int

IncrementAllocation increments the allocation counter for a class+kind.

func (*AnalysisContext) IsGated

func (ctx *AnalysisContext) IsGated(pos token.Pos) bool

IsGated returns true if the given position is after an early-return gate. This indicates the allocation at that position is conditionally executed due to a preceding control flow statement that may return early.

func (*AnalysisContext) ParseIgnoreDirectives

func (ctx *AnalysisContext) ParseIgnoreDirectives()

ParseIgnoreDirectives extracts //vango:lint-ignore directives from comments.

func (*AnalysisContext) PopScope

func (ctx *AnalysisContext) PopScope()

PopScope exits the current scope.

func (*AnalysisContext) Position

func (ctx *AnalysisContext) Position(pos token.Pos) token.Position

Position returns the file:line:col position for a token.Pos.

func (*AnalysisContext) PushScope

func (ctx *AnalysisContext) PushScope(scope ScopeType)

PushScope enters a new scope.

func (*AnalysisContext) ResetAllocations

func (ctx *AnalysisContext) ResetAllocations()

ResetAllocations resets allocation counters.

type Analyzer

type Analyzer struct {
	Rules        *RuleSet
	StrictMode   StrictModeProfile
	FileSet      *token.FileSet
	Diagnostics  []Diagnostic
	SchemaImpact *SchemaImpact
	Artifacts    *Artifacts
}

Analyzer performs static analysis on Vango source code.

func NewAnalyzer

func NewAnalyzer() *Analyzer

NewAnalyzer creates a new analyzer with default rules.

func (*Analyzer) AnalyzeDir

func (a *Analyzer) AnalyzeDir(dir string) error

AnalyzeDir analyzes all Go packages rooted at a directory.

func (*Analyzer) AnalyzeDirContext

func (a *Analyzer) AnalyzeDirContext(ctx context.Context, dir string) error

AnalyzeDirContext analyzes all Go packages rooted at a directory with cancellation support.

func (*Analyzer) AnalyzeFile

func (a *Analyzer) AnalyzeFile(path string) error

AnalyzeFile analyzes a single Go file.

func (*Analyzer) AnalyzeFileContext

func (a *Analyzer) AnalyzeFileContext(ctx context.Context, path string) error

AnalyzeFileContext analyzes a single Go file with cancellation support.

func (*Analyzer) AnalyzeSource

func (a *Analyzer) AnalyzeSource(filename string, src string) error

AnalyzeSource analyzes a Go source string.

func (*Analyzer) Report

func (a *Analyzer) Report() DiagnosticReport

Report generates a diagnostic report.

func (*Analyzer) WithArtifacts

func (a *Analyzer) WithArtifacts(artifacts *Artifacts) *Analyzer

WithArtifacts sets artifact paths for reporting.

func (*Analyzer) WithSchemaImpact

func (a *Analyzer) WithSchemaImpact(impact *SchemaImpact) *Analyzer

WithSchemaImpact sets the schema impact for reporting.

func (*Analyzer) WithStrictMode

func (a *Analyzer) WithStrictMode(mode StrictModeProfile) *Analyzer

WithStrictMode sets the strictness profile.

type Artifacts

type Artifacts struct {
	Manifest string `json:"manifest,omitempty"`
	Schema   string `json:"schema,omitempty"`
	Bindings string `json:"bindings,omitempty"`
}

Artifacts lists the generated artifact paths.

type CallInfo

type CallInfo struct {
	Obj      *types.Func
	PkgPath  string
	Name     string
	IsMethod bool
	Recv     types.Type
}

CallInfo captures resolved info about a call expression.

func ResolveCall

func ResolveCall(call *ast.CallExpr, info *types.Info) *CallInfo

ResolveCall returns call info using type data when available.

type Diagnostic

type Diagnostic struct {
	// Code is the diagnostic code (e.g., VANGO.SETUP.CONDITIONAL_ALLOC).
	Code string `json:"code"`

	// Severity is error, warning, or info.
	Severity Severity `json:"severity"`

	// Location is where the diagnostic occurred.
	Location DiagnosticLocation `json:"location"`

	// Message is a short description.
	Message string `json:"message"`

	// Detail is a longer explanation for terminal output (not serialized).
	Detail string `json:"-"`

	// Context contains diagnostic-specific context.
	Context *DiagnosticContext `json:"context,omitempty"`

	// Fixes contains suggested fixes.
	Fixes []DiagnosticFix `json:"fixes,omitempty"`

	// DocURL is a link to documentation (not serialized).
	DocURL string `json:"-"`
}

Diagnostic represents a single lint diagnostic.

type DiagnosticBuilder

type DiagnosticBuilder struct {
	// contains filtered or unexported fields
}

DiagnosticBuilder provides a fluent API for creating diagnostics.

func NewDiagnostic

func NewDiagnostic(code string) *DiagnosticBuilder

NewDiagnostic creates a new diagnostic builder.

func (*DiagnosticBuilder) Build

func (b *DiagnosticBuilder) Build() Diagnostic

func (*DiagnosticBuilder) WithContext

func (*DiagnosticBuilder) WithDetail

func (b *DiagnosticBuilder) WithDetail(detail string) *DiagnosticBuilder

func (*DiagnosticBuilder) WithDocURL

func (b *DiagnosticBuilder) WithDocURL(url string) *DiagnosticBuilder

func (*DiagnosticBuilder) WithFix

func (*DiagnosticBuilder) WithFunction

func (b *DiagnosticBuilder) WithFunction(fn string) *DiagnosticBuilder

func (*DiagnosticBuilder) WithLocation

func (b *DiagnosticBuilder) WithLocation(file string, line, col int) *DiagnosticBuilder

func (*DiagnosticBuilder) WithMessage

func (b *DiagnosticBuilder) WithMessage(msg string) *DiagnosticBuilder

func (*DiagnosticBuilder) WithSeverity

func (b *DiagnosticBuilder) WithSeverity(s Severity) *DiagnosticBuilder

type DiagnosticContext

type DiagnosticContext struct {
	// Condition is the conditional expression (for CONDITIONAL_ALLOC).
	Condition string `json:"condition,omitempty"`

	// Allocation is the allocation expression.
	Allocation string `json:"allocation,omitempty"`

	// Persisted indicates if this relates to persisted state.
	Persisted bool `json:"persisted"`
}

DiagnosticContext contains context-specific information about the diagnostic. Only fields defined in the spec are serialized.

type DiagnosticFix

type DiagnosticFix struct {
	// Description explains what the fix does.
	Description string `json:"description"`

	// Auto indicates if this fix can be applied automatically.
	Auto bool `json:"auto"`

	// Command is the CLI command to apply the fix (if any).
	Command *string `json:"command"`

	// Example shows the corrected code.
	Example string `json:"example,omitempty"`
}

DiagnosticFix represents a suggested fix for a diagnostic.

type DiagnosticLocation

type DiagnosticLocation struct {
	File     string `json:"file"`
	Line     int    `json:"line"`
	Column   int    `json:"column"`
	Function string `json:"function,omitempty"`
}

DiagnosticLocation represents where a diagnostic occurred.

type DiagnosticReport

type DiagnosticReport struct {
	// Tool identifier.
	Tool string `json:"tool"`

	// ToolVersion is the vango version.
	ToolVersion string `json:"toolVersion"`

	// Status is "error", "warning", or "ok".
	Status string `json:"status"`

	// Diagnostics contains all diagnostic messages.
	Diagnostics []Diagnostic `json:"diagnostics"`

	// SchemaImpact describes deployment impact (optional).
	SchemaImpact *SchemaImpact `json:"schemaImpact,omitempty"`

	// Artifacts lists generated files.
	Artifacts *Artifacts `json:"artifacts,omitempty"`
}

DiagnosticReport is the complete JSON output structure.

func LintPaths

func LintPaths(paths []string, mode StrictModeProfile) (DiagnosticReport, error)

LintPaths analyzes the provided files or directories and returns a report. When paths is empty, the current working directory is analyzed.

type Formatter

type Formatter struct {
	Format       OutputFormat
	ColorEnabled bool
}

Formatter handles diagnostic output.

func NewFormatter

func NewFormatter(format OutputFormat) *Formatter

NewFormatter creates a new formatter.

func (*Formatter) FormatReport

func (f *Formatter) FormatReport(report DiagnosticReport) string

FormatReport formats a diagnostic report.

func (*Formatter) Print

func (f *Formatter) Print(report DiagnosticReport)

Print writes the report to stdout.

func (*Formatter) PrintToStderr

func (f *Formatter) PrintToStderr(report DiagnosticReport)

PrintToStderr writes the report to stderr.

type OutputFormat

type OutputFormat string

OutputFormat specifies the output format.

const (
	OutputFormatTerminal OutputFormat = "terminal"
	OutputFormatJSON     OutputFormat = "json"
	OutputFormatCompact  OutputFormat = "compact"
)

type Rule

type Rule interface {
	Code() string
	DefaultSeverity() Severity
	CISeverity() Severity
	Description() string
	DocURL() string
	Check(node ast.Node, ctx *AnalysisContext)
}

Rule represents a lint rule.

type RuleSet

type RuleSet struct {
	// contains filtered or unexported fields
}

RuleSet is a collection of rules.

func DefaultRules

func DefaultRules() *RuleSet

DefaultRules returns the default set of all lint rules.

func NewRuleSet

func NewRuleSet() *RuleSet

NewRuleSet creates a new rule set.

func (*RuleSet) Add

func (rs *RuleSet) Add(rule Rule)

Add adds a rule to the set.

func (*RuleSet) Clone

func (rs *RuleSet) Clone() *RuleSet

Clone returns a shallow copy of the rule set.

func (*RuleSet) Rules

func (rs *RuleSet) Rules() []Rule

Rules returns all rules.

type SchemaImpact

type SchemaImpact struct {
	// Classification is warm_deploy, cold_deploy, or schema_neutral.
	Classification string `json:"classification"`

	// Reason explains why (id_removed, id_added, fingerprint_changed, etc.).
	Reason string `json:"reason,omitempty"`

	// AffectedIDs lists the anchor keys of affected primitives.
	AffectedIDs []string `json:"affectedIDs,omitempty"`
}

SchemaImpact represents the deployment impact of changes.

type ScopeType

type ScopeType int

ScopeType represents the current analysis scope.

const (
	ScopeTopLevel ScopeType = iota
	ScopeFunction
	ScopeSetupCallback
	ScopeRenderClosure
	ScopeEventHandler
	ScopeOnMountCallback
	ScopeEffectCallback
	ScopeOnChangeKeyFn
	ScopeOnChangeCallback
	ScopeConditional
	ScopeLoop
)

type Severity

type Severity string

Severity represents the diagnostic severity level.

const (
	SeverityError   Severity = "error"
	SeverityWarning Severity = "warning"
	SeverityInfo    Severity = "info"
)

func EffectiveSeverity

func EffectiveSeverity(rule Rule, profile StrictModeProfile) Severity

EffectiveSeverity returns the effective severity for a rule given the profile.

type StrictModeProfile

type StrictModeProfile string

StrictModeProfile determines lint severity escalation.

const (
	StrictModeDefault StrictModeProfile = "default"
	StrictModeCI      StrictModeProfile = "ci"
)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL