Documentation
¶
Overview ¶
Package index provides in-memory indexing for code symbols.
The index package contains SymbolIndex, a concurrent-safe data structure for fast O(1) lookups of symbols by ID, name, file path, and kind.
Ownership Model ¶
The index stores pointers to symbols but does NOT own them:
- Symbols MUST NOT be mutated after being added to the index
- To update symbols: call RemoveByFile() then AddBatch() with new symbols
- The index does NOT copy symbols (for memory efficiency)
Thread Safety ¶
SymbolIndex is safe for concurrent use. Multiple goroutines can call any combination of methods simultaneously. Write operations (Add, AddBatch, RemoveByFile, Clear) use exclusive locks; read operations (GetBy*, Search, Stats) use shared locks.
Index ¶
- Constants
- Variables
- type BatchError
- type IndexStats
- type SymbolIndex
- func (idx *SymbolIndex) Add(symbol *ast.Symbol) error
- func (idx *SymbolIndex) AddBatch(symbols []*ast.Symbol) error
- func (idx *SymbolIndex) Clear()
- func (idx *SymbolIndex) Clone() *SymbolIndex
- func (idx *SymbolIndex) GetByFile(filePath string) []*ast.Symbol
- func (idx *SymbolIndex) GetByID(id string) (*ast.Symbol, bool)
- func (idx *SymbolIndex) GetByKind(kind ast.SymbolKind) []*ast.Symbol
- func (idx *SymbolIndex) GetByName(name string) []*ast.Symbol
- func (idx *SymbolIndex) GetUniqueFilePaths() []string
- func (idx *SymbolIndex) RemoveByFile(filePath string) int
- func (idx *SymbolIndex) Search(ctx context.Context, query string, limit int) ([]*ast.Symbol, error)
- func (idx *SymbolIndex) Stats() IndexStats
- type SymbolIndexOption
- type SymbolIndexOptions
Constants ¶
const (
// DefaultMaxSymbols is the default maximum number of symbols the index can hold.
DefaultMaxSymbols = 1_000_000
)
Default configuration values.
Variables ¶
var ( // ErrDuplicateSymbol is returned when adding a symbol with an ID // that already exists in the index. ErrDuplicateSymbol = errors.New("duplicate symbol ID") // ErrMaxSymbolsExceeded is returned when the index has reached // its configured maximum capacity. ErrMaxSymbolsExceeded = errors.New("maximum symbol count exceeded") // ErrInvalidSymbol is returned when a symbol fails validation. // The underlying error from Symbol.Validate() is wrapped. ErrInvalidSymbol = errors.New("invalid symbol") )
Sentinel errors for symbol index operations.
Functions ¶
This section is empty.
Types ¶
type BatchError ¶
type BatchError struct {
// Errors contains all individual errors encountered during the batch operation.
// Each error includes the index position (e.g., "symbol[0]: duplicate ID").
Errors []error
}
BatchError aggregates multiple errors from batch operations.
When AddBatch encounters validation errors or duplicates, it collects all errors and returns them together rather than failing on the first error. This allows callers to see all problems at once.
BatchError implements the standard errors.Unwrap() interface for Go 1.20+ multi-error unwrapping.
func (*BatchError) Error ¶
func (e *BatchError) Error() string
Error returns a human-readable summary of the batch errors.
Format depends on error count:
- 1 error: returns that error's message directly
- 2+ errors: returns count and first error with "and N more" suffix
func (*BatchError) ErrorList ¶
func (e *BatchError) ErrorList() string
ErrorList returns a formatted string with all errors, one per line.
This is useful for logging or displaying the full list of problems to a user who needs to fix them all.
func (*BatchError) Unwrap ¶
func (e *BatchError) Unwrap() []error
Unwrap returns the underlying errors for use with errors.Is and errors.As.
This implements the Go 1.20+ multi-error unwrapping interface.
type IndexStats ¶
type IndexStats struct {
// TotalSymbols is the total number of symbols in the index.
TotalSymbols int
// ByKind maps each SymbolKind to the count of symbols of that kind.
ByKind map[ast.SymbolKind]int
// FileCount is the number of unique files with symbols in the index.
FileCount int
// MaxSymbols is the configured maximum capacity.
MaxSymbols int
}
IndexStats contains statistics about the symbol index.
type SymbolIndex ¶
type SymbolIndex struct {
// contains filtered or unexported fields
}
SymbolIndex provides fast O(1) lookups of symbols by various keys.
The index maintains multiple maps for efficient access patterns:
- byID: Primary index for unique symbol lookup
- byName: Secondary index for name-based queries (multiple symbols can share a name)
- byFile: Secondary index for file-based queries
- byKind: Secondary index for kind-based queries
Thread Safety:
SymbolIndex is safe for concurrent use. Multiple goroutines can call any combination of methods simultaneously.
Ownership:
The index stores pointers to symbols but does NOT own them. Symbols MUST NOT be mutated after being added to the index.
func NewSymbolIndex ¶
func NewSymbolIndex(opts ...SymbolIndexOption) *SymbolIndex
NewSymbolIndex creates a new empty symbol index with the given options.
Description:
Creates a concurrent-safe index for storing and querying code symbols. The index is empty upon creation.
Example:
// Default options (1M max symbols) idx := NewSymbolIndex() // Custom options idx := NewSymbolIndex(WithMaxSymbols(100_000))
func (*SymbolIndex) Add ¶
func (idx *SymbolIndex) Add(symbol *ast.Symbol) error
Add adds a single symbol to the index.
Description:
Validates the symbol, checks for duplicates and capacity, then adds the symbol to all indexes atomically.
Inputs:
symbol - The symbol to add. Must pass Symbol.Validate().
Outputs:
error - Non-nil if validation fails, symbol ID already exists, or
index is at capacity.
Errors:
ErrInvalidSymbol - Symbol failed validation ErrDuplicateSymbol - Symbol with same ID already exists ErrMaxSymbolsExceeded - Index is at capacity
Thread Safety:
This method is safe for concurrent use.
func (*SymbolIndex) AddBatch ¶
func (idx *SymbolIndex) AddBatch(symbols []*ast.Symbol) error
AddBatch adds multiple symbols to the index atomically.
Description:
Validates all symbols, checks for duplicates (both within the batch and against existing symbols), then adds all symbols atomically. If any validation fails, NO symbols are added.
Inputs:
symbols - The symbols to add. All must pass validation.
Outputs:
error - Non-nil if any validation fails, any duplicates exist, or
adding would exceed capacity.
Errors:
*BatchError - Contains all validation/duplicate errors found ErrMaxSymbolsExceeded - Adding batch would exceed capacity
Thread Safety:
This method is safe for concurrent use.
func (*SymbolIndex) Clear ¶
func (idx *SymbolIndex) Clear()
Clear removes all symbols from the index.
Description:
Resets the index to empty state. All counters are reset to zero.
Thread Safety:
This method is safe for concurrent use.
func (*SymbolIndex) Clone ¶
func (idx *SymbolIndex) Clone() *SymbolIndex
Clone creates a deep copy of the symbol index.
Description:
Creates an independent copy of the index that can be modified without affecting the original. Used for copy-on-write incremental updates.
Outputs:
*SymbolIndex - A deep copy of the index.
Behavior:
- All maps are deep copied
- Symbol pointers are shared (symbols are immutable after add)
- Counters are copied
- Options are copied
Thread Safety:
The returned index is independent and can be modified without synchronization. This method is safe to call concurrently on the source index.
func (*SymbolIndex) GetByFile ¶
func (idx *SymbolIndex) GetByFile(filePath string) []*ast.Symbol
GetByFile retrieves all symbols in the given file.
Description:
Performs O(1) lookup, returns defensive copy of the result slice.
Inputs:
filePath - The file path (relative to project root)
Outputs:
[]*ast.Symbol - Defensive copy of symbols in that file, nil if none found
Thread Safety:
This method is safe for concurrent use. The returned slice is a copy and can be safely modified by the caller.
func (*SymbolIndex) GetByID ¶
func (idx *SymbolIndex) GetByID(id string) (*ast.Symbol, bool)
GetByID retrieves a symbol by its unique ID.
Description:
Performs O(1) lookup in the primary index.
Inputs:
id - The symbol ID (format: "file_path:line:name")
Outputs:
*ast.Symbol - The symbol if found, nil otherwise bool - True if symbol was found
Thread Safety:
This method is safe for concurrent use.
func (*SymbolIndex) GetByKind ¶
func (idx *SymbolIndex) GetByKind(kind ast.SymbolKind) []*ast.Symbol
GetByKind retrieves all symbols of the given kind.
Description:
Performs O(1) lookup, returns defensive copy of the result slice.
Inputs:
kind - The symbol kind (e.g., SymbolKindFunction)
Outputs:
[]*ast.Symbol - Defensive copy of symbols of that kind, nil if none found
Thread Safety:
This method is safe for concurrent use. The returned slice is a copy and can be safely modified by the caller.
func (*SymbolIndex) GetByName ¶
func (idx *SymbolIndex) GetByName(name string) []*ast.Symbol
GetByName retrieves all symbols with the given name.
Description:
Performs O(1) lookup, returns defensive copy of the result slice. Multiple symbols can share the same name (e.g., "Handler" in different packages).
Inputs:
name - The symbol name to search for
Outputs:
[]*ast.Symbol - Defensive copy of matching symbols, nil if none found
Thread Safety:
This method is safe for concurrent use. The returned slice is a copy and can be safely modified by the caller.
func (*SymbolIndex) GetUniqueFilePaths ¶
func (idx *SymbolIndex) GetUniqueFilePaths() []string
GetUniqueFilePaths returns a list of unique file paths that have symbols in the index.
Description:
CRS-26n: Used by computeGraphContentHash to include file identity in the content hash. This prevents hash collisions when two different projects have the same node+edge count.
Outputs:
[]string - Unique file paths (unsorted). Caller should sort if deterministic
ordering is needed.
Thread Safety:
This method is safe for concurrent use.
func (*SymbolIndex) RemoveByFile ¶
func (idx *SymbolIndex) RemoveByFile(filePath string) int
RemoveByFile removes all symbols from the given file.
Description:
Removes symbols from all indexes atomically. Use this before AddBatch when updating symbols for a file.
Inputs:
filePath - The file path whose symbols should be removed
Outputs:
int - Number of symbols removed
Thread Safety:
This method is safe for concurrent use.
func (*SymbolIndex) Search ¶
Search finds symbols matching the query string.
Description:
Performs fuzzy search across all symbol names. Results are sorted by relevance: exact matches first, then prefix matches, then substring matches, then fuzzy matches (Levenshtein distance < 3).
Performance:
O(n) where n is total symbols. For indexes > 50k symbols, consider using GetByName() for exact matches first. The context is checked periodically during search to allow cancellation.
Inputs:
ctx - Context for cancellation query - Search string (case-insensitive) limit - Maximum number of results to return (0 = no limit)
Outputs:
[]*ast.Symbol - Matching symbols sorted by relevance error - Non-nil if context was cancelled
Thread Safety:
This method is safe for concurrent use.
func (*SymbolIndex) Stats ¶
func (idx *SymbolIndex) Stats() IndexStats
Stats returns statistics about the index.
Description:
Returns counts using O(1) maintained counters, not map traversal.
Outputs:
IndexStats - Current index statistics
Thread Safety:
This method is safe for concurrent use.
type SymbolIndexOption ¶
type SymbolIndexOption func(*SymbolIndexOptions)
SymbolIndexOption is a functional option for configuring SymbolIndex.
func WithMaxSymbols ¶
func WithMaxSymbols(max int) SymbolIndexOption
WithMaxSymbols sets the maximum number of symbols the index can hold.
type SymbolIndexOptions ¶
type SymbolIndexOptions struct {
// MaxSymbols is the maximum number of symbols the index can hold.
// Attempting to add more symbols returns ErrMaxSymbolsExceeded.
// Default: 1,000,000
MaxSymbols int
}
SymbolIndexOptions configures SymbolIndex behavior and limits.
func DefaultSymbolIndexOptions ¶
func DefaultSymbolIndexOptions() SymbolIndexOptions
DefaultSymbolIndexOptions returns the default options.