review

package
v0.35.0 Latest Latest
Warning

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

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

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ApplyFix

func ApplyFix(proposal FixProposal) error

ApplyFix applies a fix proposal to the file.

func BuildPatchSkeleton

func BuildPatchSkeleton(path string, note string) string

BuildPatchSkeleton produces a minimal patch skeleton. Not applied. This helper is currently unused but kept for future extension.

func CanRunParallel

func CanRunParallel(a, b FixProposal) bool

CanRunParallel は2つの修正提案が並列実行可能か判定

func ExtractCodeAroundLine

func ExtractCodeAroundLine(code string, line, contextLines int) string

ExtractCodeAroundLine extracts code context around a specific line.

func ParseLineNumberFromSnippet

func ParseLineNumberFromSnippet(snippet string) int

ParseLineNumberFromSnippet tries to extract line number from diff snippet.

func PreviewMultiFileChange

func PreviewMultiFileChange(change *MultiFileChange)

PreviewMultiFileChange displays detailed preview of all changes.

Types

type AIAnalysisResult

type AIAnalysisResult struct {
	Insights []AIInsight `json:"insights"`
}

AIAnalysisResult represents the full AI analysis response.

type AIAnalyzer

type AIAnalyzer struct {
	LLM LLMClient
}

AIAnalyzer performs AI-based code analysis.

func NewAIAnalyzer

func NewAIAnalyzer(llm LLMClient) *AIAnalyzer

NewAIAnalyzer creates a new AI analyzer.

func (*AIAnalyzer) AnalyzeWithAI

func (a *AIAnalyzer) AnalyzeWithAI(code string, filePath string) ([]AIInsight, error)

AnalyzeWithAI analyzes code using LLM and returns insights.

func (*AIAnalyzer) GenerateAIFix

func (a *AIAnalyzer) GenerateAIFix(issue Issue, code string) (*FixProposal, error)

GenerateAIFix generates a fix proposal using LLM.

type AIFixResult

type AIFixResult struct {
	OldCode string `json:"old_code"`
	NewCode string `json:"new_code"`
}

AIFixResult represents an AI-generated fix.

type AIFixer

type AIFixer struct {
	*Fixer
	AIAnalyzer *AIAnalyzer
}

AIFixer extends Fixer with AI-powered fix generation.

func NewAIFixer

func NewAIFixer(llm LLMClient) *AIFixer

NewAIFixer creates a new AI-powered fixer.

func (*AIFixer) ProposeWithAI

func (f *AIFixer) ProposeWithAI(issues []Issue, fileContents map[string]string, opt FixOptions) ([]FixProposal, error)

ProposeWithAI generates fix proposals, using AI for issues that don't have static rule-based fixes.

type AIInsight

type AIInsight struct {
	Severity    string  `json:"severity"`    // critical, warning, info
	Category    string  `json:"category"`    // security, performance, bug, readability
	Line        int     `json:"line"`        // 1-indexed line number
	Description string  `json:"description"` // Problem description
	Suggestion  string  `json:"suggestion"`  // Fix suggestion
	Confidence  float64 `json:"confidence"`  // 0.0-1.0
}

AIInsight represents an insight from AI analysis.

func FilterHighConfidenceInsights

func FilterHighConfidenceInsights(insights []AIInsight, threshold float64) []AIInsight

FilterHighConfidenceInsights filters insights by confidence threshold.

type Analyzer

type Analyzer struct {
	Now func() time.Time
}

func NewAnalyzer

func NewAnalyzer() *Analyzer

func (*Analyzer) Analyze

func (a *Analyzer) Analyze(targets []Target, opt AnalyzerOptions) ([]Issue, error)

type AnalyzerOptions

type AnalyzerOptions struct {
	Focus           ReviewFocus
	MaxIssues       int
	MaxSnippetLines int
}

type ApplyFunc

type ApplyFunc func(ctx context.Context, proposal FixProposal) error

ApplyFunc は修正を適用する関数の型

type FileChange

type FileChange struct {
	FilePath   string
	Patches    []Patch
	BackupPath string // Set after backup is created
}

FileChange represents changes to a single file.

type FixChoice

type FixChoice string

FixChoice represents a user's choice for fixing an issue.

const (
	FixChoiceYes  FixChoice = "y" // Apply this fix
	FixChoiceNo   FixChoice = "n" // Skip this fix
	FixChoiceAll  FixChoice = "a" // Apply all remaining fixes
	FixChoiceQuit FixChoice = "q" // Stop fixing
)

type FixGroup

type FixGroup struct {
	FilePath  string
	Proposals []FixProposal
}

FixGroup はファイル単位でグループ化された修正提案

func GroupByFile

func GroupByFile(proposals []FixProposal) []FixGroup

GroupByFile は修正提案をファイル単位でグループ化 同じファイルへの修正は順番に適用する必要がある

type FixOptions

type FixOptions struct {
	// MaxFixes caps proposals.
	// 0 means default (50).
	MaxFixes int
}

type FixProposal

type FixProposal struct {
	IssueID   string
	Title     string
	Rationale string

	// Example is a code snippet (not necessarily a patch).
	Example string

	// Patch is a best-effort unified diff proposal. It may be empty.
	Patch string

	// Safety notes and constraints.
	Notes []string

	// Actionable indicates whether this fix can be automatically applied.
	// If false, this is a suggestion-only proposal.
	Actionable bool

	// FilePath is the target file for actionable fixes.
	FilePath string

	// OldCode is the code to be replaced (for str_replace style fixes).
	OldCode string

	// NewCode is the replacement code.
	NewCode string
}

type FixResult

type FixResult struct {
	Applied int
	Skipped int
	Failed  int
	Quit    bool
}

FixResult represents the result of an interactive fix session.

func RunInteractiveFixes

func RunInteractiveFixes(issues []Issue, proposals []FixProposal, autoApprove bool) FixResult

RunInteractiveFixes runs the interactive fix session for all actionable proposals.

func RunParallelFixes

func RunParallelFixes(issues []Issue, proposals []FixProposal, autoApprove bool, workers int) FixResult

RunParallelFixes runs fixes in parallel for faster execution. autoApprove: if true, skip all prompts and apply all fixes workers: number of parallel workers (0 = default 4)

type Fixer

type Fixer struct {
	Now func() time.Time
}

func NewFixer

func NewFixer() *Fixer

func (*Fixer) Propose

func (f *Fixer) Propose(issues []Issue, opt FixOptions) ([]FixProposal, error)

type IndependentGroup

type IndependentGroup struct {
	Groups []FixGroup
}

IndependentGroup は独立して実行可能なグループ

func GroupIndependent

func GroupIndependent(groups []FixGroup) []IndependentGroup

GroupIndependent は独立して実行可能なグループに分類 異なるファイルへの修正は並列実行可能

type InteractiveFixer

type InteractiveFixer struct {
	Reader   *bufio.Reader
	AutoAll  bool // Skip prompts and apply all
	Parallel bool // Enable parallel execution
	Workers  int  // Number of parallel workers (default 4)
}

InteractiveFixer handles interactive fix confirmation and application.

func NewInteractiveFixer

func NewInteractiveFixer() *InteractiveFixer

NewInteractiveFixer creates a new interactive fixer.

func NewParallelInteractiveFixer

func NewParallelInteractiveFixer(workers int) *InteractiveFixer

NewParallelInteractiveFixer creates an interactive fixer with parallel execution enabled.

func (*InteractiveFixer) PromptFixConfirm

func (f *InteractiveFixer) PromptFixConfirm(issue Issue, proposal FixProposal) FixChoice

PromptFixConfirm displays fix information and prompts for user choice.

func (*InteractiveFixer) PromptMultiFileConfirm

func (f *InteractiveFixer) PromptMultiFileConfirm(change *MultiFileChange) MultiFixChoice

PromptMultiFileConfirm displays multi-file change information and prompts for user choice.

type Issue

type Issue struct {
	ID          string
	Title       string
	Description string
	Severity    Severity
	Path        string
	LineStart   int
	LineEnd     int
	Snippet     string
	Suggestions []string
	Tags        []string
}

func ConvertInsightsToIssues

func ConvertInsightsToIssues(insights []AIInsight, filePath string) []Issue

ConvertInsightsToIssues converts AI insights to Issue structs.

type LLMClient

type LLMClient interface {
	Chat(prompt string) (string, error)
}

LLMClient is an interface for LLM interactions. This allows decoupling from the agent package.

type MultiFileApplier

type MultiFileApplier struct {
	BackupDir string
}

MultiFileApplier handles applying and rolling back multi-file changes.

func NewMultiFileApplier

func NewMultiFileApplier() *MultiFileApplier

NewMultiFileApplier creates a new applier with a backup directory.

func (*MultiFileApplier) ApplyMultiFileChange

func (a *MultiFileApplier) ApplyMultiFileChange(change *MultiFileChange) error

ApplyMultiFileChange applies all changes with automatic rollback on failure.

func (*MultiFileApplier) CleanupBackups

func (a *MultiFileApplier) CleanupBackups(change *MultiFileChange)

CleanupBackups removes backup files for a change.

func (*MultiFileApplier) RollbackMultiFileChange

func (a *MultiFileApplier) RollbackMultiFileChange(change *MultiFileChange) error

RollbackMultiFileChange rolls back a previously applied change.

func (*MultiFileApplier) ValidateMultiFileChange

func (a *MultiFileApplier) ValidateMultiFileChange(change *MultiFileChange) error

ValidateMultiFileChange validates that all changes can be applied.

type MultiFileChange

type MultiFileChange struct {
	ID          string
	Description string
	Changes     []FileChange
}

MultiFileChange represents a coordinated change across multiple files.

func ConvertFixProposalsToMultiFileChange

func ConvertFixProposalsToMultiFileChange(proposals []FixProposal, description string) *MultiFileChange

ConvertFixProposalsToMultiFileChange converts FixProposals to a MultiFileChange.

type MultiFixChoice

type MultiFixChoice string

MultiFixChoice represents a user's choice for multi-file fixes.

const (
	MultiFixChoiceApply    MultiFixChoice = "a" // Apply all changes
	MultiFixChoicePreview  MultiFixChoice = "p" // Preview changes
	MultiFixChoiceSkip     MultiFixChoice = "s" // Skip this batch
	MultiFixChoiceQuit     MultiFixChoice = "q" // Quit
	MultiFixChoiceRollback MultiFixChoice = "r" // Rollback after apply
)

type MultiFixResult

type MultiFixResult struct {
	Applied    int
	Skipped    int
	Failed     int
	RolledBack bool
	Quit       bool
}

MultiFixResult represents the result of a multi-file fix session.

func RunInteractiveMultiFixes

func RunInteractiveMultiFixes(changes []*MultiFileChange, autoApprove bool) MultiFixResult

RunInteractiveMultiFixes runs an interactive session for multi-file changes.

type Options

type Options struct {
	All   bool
	Paths []string

	Focus ReviewFocus
	Fix   bool

	Mode     string // "changes" or "diff" (best-effort label)
	Provider string
	Model    string

	OutputDir string

	MaxIssues       int
	MaxSnippetLines int

	// AI analysis options
	UseAI     bool      // Enable AI-powered analysis
	LLMClient LLMClient // LLM client for AI analysis (optional)
}

type Orchestrator

type Orchestrator struct {
	Scanner    *Scanner
	Analyzer   *Analyzer
	Fixer      *Fixer
	AIAnalyzer *AIAnalyzer
	Reporter   *Reporter

	Now func() time.Time
}

func NewOrchestrator

func NewOrchestrator() *Orchestrator

func (*Orchestrator) Run

func (o *Orchestrator) Run(ctx context.Context, changeStack []tools.FileChange, opt Options) (Report, string, error)

Run executes the review pipeline.

changeStack is optional but required when opt.All is false.

type ParallelExecutor

type ParallelExecutor struct {
	MaxWorkers int // デフォルト4
	Results    []ParallelFixResult
	// contains filtered or unexported fields
}

ParallelExecutor は修正を並列適用するエグゼキューター

func NewParallelExecutor

func NewParallelExecutor(maxWorkers int) *ParallelExecutor

NewParallelExecutor は新しいParallelExecutorを作成

func (*ParallelExecutor) Execute

func (pe *ParallelExecutor) Execute(ctx context.Context, groups []FixGroup, applyFn ApplyFunc) []ParallelFixResult

Execute は修正を並列に適用

func (*ParallelExecutor) Summary

func (pe *ParallelExecutor) Summary() (total, success, failed int)

Summary は実行結果のサマリーを返す

func (*ParallelExecutor) TotalDuration

func (pe *ParallelExecutor) TotalDuration() time.Duration

TotalDuration は全体の実行時間を返す

type ParallelFixResult

type ParallelFixResult struct {
	ProposalID string
	FilePath   string
	Success    bool
	Error      error
	Duration   time.Duration
}

ParallelFixResult は個々の修正適用結果(並列実行用)

type Patch

type Patch struct {
	// StartLine is 1-indexed inclusive start line (0 means use OldCode matching).
	StartLine int
	// EndLine is 1-indexed inclusive end line (0 means use OldCode matching).
	EndLine int
	// OldCode is the code to be replaced (used when StartLine/EndLine are 0).
	OldCode string
	// NewCode is the replacement code.
	NewCode string
}

Patch represents a single code replacement within a file.

type Report

type Report struct {
	GeneratedAt time.Time
	Mode        string
	Provider    string
	Model       string

	Targets []Target
	Issues  []Issue
	Fixes   []FixProposal

	Summary string
}

type Reporter

type Reporter struct {
	Now func() time.Time
}

func NewReporter

func NewReporter() *Reporter

func (*Reporter) WriteMarkdown

func (r *Reporter) WriteMarkdown(rep Report, opt ReporterOptions) (string, error)

type ReporterOptions

type ReporterOptions struct {
	OutputDir string
	// FileName can be specified for tests; when empty, auto-generated.
	FileName string

	// Permissions
	DirPerm  os.FileMode
	FilePerm os.FileMode

	// IncludeDiff controls whether diff content is embedded into report.
	// Default true, but some callers may want to omit for safety.
	IncludeDiff bool
}

type ReviewFocus

type ReviewFocus struct {
	Security bool
	Test     bool
}

type ScanOptions

type ScanOptions struct {
	All bool
	// Paths filters targets when All==true (git diff). If empty, all changed files.
	Paths []string

	// GitArgs allows customizing the git diff command (mainly for tests or future extension).
	// Example: []string{"diff", "--cached"}
	GitArgs []string

	// MaxSnippetLines limits diff snippet lines for changeStack-based scanning.
	// 0 means default (200).
	MaxSnippetLines int
}

type Scanner

type Scanner struct {
	// If provided, used for timestamps in outputs and testability.
	Now func() time.Time
}

func NewScanner

func NewScanner() *Scanner

func (*Scanner) ScanAllFromGitDiff

func (s *Scanner) ScanAllFromGitDiff(ctx context.Context, opt ScanOptions) ([]Target, error)

ScanAllFromGitDiff uses git diff to obtain patch and extract targets.

Implementation notes: - Uses `git diff --name-only` to list files when available (fast). - Uses `git diff` to obtain patch; then slices per-file patch by "diff --git" headers. - If parsing fails, returns a single Target with Diff containing the entire patch.

func (*Scanner) ScanFromChanges

func (s *Scanner) ScanFromChanges(ctx context.Context, changeStack []tools.FileChange, opt ScanOptions) ([]Target, error)

ScanFromChanges derives target file paths from changeStack and tries to gather per-file diff snippets.

Behavior: - Targets are unique by path. - For each file, tries: `git diff -- <file>`. - If that is empty, tries: `git diff HEAD -- <file>` (covers newly created but unstaged states in some cases). - If still empty, Diff is left empty (caller can decide how to handle).

func (*Scanner) ScanFromPaths

func (s *Scanner) ScanFromPaths(ctx context.Context, paths []string, opt ScanOptions) ([]Target, error)

ScanFromPaths scans files from specified paths (files, directories, or glob patterns).

Behavior: - Supports file paths, directory paths (recursive), and glob patterns (e.g., **/*.go) - Respects .gitignore via `git ls-files` when possible - For each file, tries to get diff from git - Returns error if no valid paths found

type Severity

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

type Target

type Target struct {
	Path       string
	OldPath    string
	ChangeType string // "A","M","D","R" etc. Best-effort.
	Diff       string // unified diff (best-effort)
}

Jump to

Keyboard shortcuts

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