Skip to main content

CodeAnalyzer

Trait CodeAnalyzer 

Source
pub trait CodeAnalyzer<D>: Send + Sync
where D: Doc + Send + Sync,
{ // Required methods fn find_pattern<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, document: &'life1 ParsedDocument<D>, pattern: &'life2 str, context: &'life3 AnalysisContext, ) -> Pin<Box<dyn Future<Output = Result<Vec<CodeMatch<'life0, D>>, Box<dyn Error + Send + Sync>>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, Self: 'async_trait; fn find_all_patterns<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>( &'life0 self, document: &'life1 ParsedDocument<D>, patterns: &'life2 [&'life3 str], context: &'life4 AnalysisContext, ) -> Pin<Box<dyn Future<Output = Result<Vec<CodeMatch<'life0, D>>, Box<dyn Error + Send + Sync>>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait, Self: 'async_trait; fn replace_pattern<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>( &'life0 self, document: &'life1 mut ParsedDocument<D>, pattern: &'life2 str, replacement: &'life3 str, context: &'life4 AnalysisContext, ) -> Pin<Box<dyn Future<Output = Result<usize, Box<dyn Error + Send + Sync>>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait, Self: 'async_trait; fn analyze_cross_file_relationships<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, documents: &'life1 [ParsedDocument<D>], context: &'life2 AnalysisContext, ) -> Pin<Box<dyn Future<Output = Result<Vec<CrossFileRelationship>, Box<dyn Error + Send + Sync>>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait; fn capabilities(&self) -> AnalyzerCapabilities; // Provided methods fn find_nodes_by_kind<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, document: &'life1 ParsedDocument<D>, node_kind: &'life2 str, context: &'life3 AnalysisContext, ) -> Pin<Box<dyn Future<Output = Result<Vec<CodeMatch<'life0, D>>, Box<dyn Error + Send + Sync>>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, Self: 'async_trait { ... } fn validate_pattern( &self, pattern: &str, ) -> Result<(), Box<dyn Error + Send + Sync>> { ... } fn compile_pattern<'life0, 'life1, 'async_trait>( &'life0 self, pattern: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<CompiledPattern, Box<dyn Error + Send + Sync>>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait { ... } fn batch_analyze<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>( &'life0 self, documents: &'life1 [ParsedDocument<D>], patterns: &'life2 [&'life3 str], context: &'life4 AnalysisContext, ) -> Pin<Box<dyn Future<Output = Result<Vec<Vec<CodeMatch<'life0, D>>>, Box<dyn Error + Send + Sync>>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait, Self: 'async_trait { ... } fn extract_symbols<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _document: &'life1 mut ParsedDocument<D>, _context: &'life2 AnalysisContext, ) -> Pin<Box<dyn Future<Output = Result<(), Box<dyn Error + Send + Sync>>> + Send + 'async_trait>> where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait { ... } }
Expand description

Core analyzer service trait that abstracts ast-grep analysis functionality.

This trait provides both single-file analysis (preserving all ast-grep matching and replacement capabilities) and codebase-level analysis (adding graph intelligence and cross-file relationships).

§Design Philosophy

  • Preserve Power: All ast-grep Matcher and Replacer functionality accessible
  • Bridge Levels: Connect file-level AST operations to codebase-level graph intelligence
  • Enable Intelligence: Add cross-file relationships and codebase-wide analysis
  • Abstract Execution: Support different execution environments and strategies

§Examples

§File-Level Pattern Matching (preserves ast-grep power)

let analyzer = MyAnalyzer;
let context = AnalysisContext::default();

// Find all function declarations - preserves ast-grep pattern power
let matches = analyzer.find_pattern(
    &document,
    "fn $NAME($$$PARAMS) { $$$BODY }",
    &context
).await?;

for match_result in matches {
    // Access ast-grep NodeMatch functionality
    let node_match = match_result.ast_node_match();
    let env = node_match.get_env();

    if let Some(name) = env.get_match("NAME") {
        println!("Function: {}", name.text());
    }

    // Plus codebase-level context
    for relationship in match_result.relationships() {
        println!("Cross-file relationship: {:?}", relationship.kind);
    }
}

§Codebase-Level Analysis

let analyzer = MyAnalyzer;
let mut context = AnalysisContext::default();
context.scope = ExecutionScope::Codebase;

// Analyze relationships across entire codebase
let relationships = analyzer.analyze_cross_file_relationships(
    &documents,
    &context
).await?;

// Build intelligence on top of ast-grep file-level analysis
for rel in relationships {
    match rel.kind {
        thread_services::types::RelationshipKind::Calls => {
            println!("{} calls {} ({}->{})",
                rel.source_symbol, rel.target_symbol,
                rel.source_file.display(), rel.target_file.display());
        },
        thread_services::types::RelationshipKind::Imports => {
            println!("{} imports from {}",
                rel.source_file.display(), rel.target_file.display());
        },
        _ => {}
    }
}

Required Methods§

Source

fn find_pattern<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, document: &'life1 ParsedDocument<D>, pattern: &'life2 str, context: &'life3 AnalysisContext, ) -> Pin<Box<dyn Future<Output = Result<Vec<CodeMatch<'life0, D>>, Box<dyn Error + Send + Sync>>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, Self: 'async_trait,

Find matches for a pattern in a document.

Preserves all ast-grep pattern matching power while adding codebase-level context. Returns CodeMatch instances that wrap NodeMatch and add cross-file relationship information.

§Arguments
  • document - ParsedDocument to search in
  • pattern - AST pattern using ast-grep meta-variable syntax (e.g., “$VAR”)
  • context - Analysis context for execution configuration
§Returns

Vector of CodeMatch instances with both ast-grep functionality and codebase context

Source

fn find_all_patterns<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>( &'life0 self, document: &'life1 ParsedDocument<D>, patterns: &'life2 [&'life3 str], context: &'life4 AnalysisContext, ) -> Pin<Box<dyn Future<Output = Result<Vec<CodeMatch<'life0, D>>, Box<dyn Error + Send + Sync>>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait, Self: 'async_trait,

Find matches for multiple patterns efficiently.

Optimizes for multiple pattern searches by batching operations and reusing AST traversals where possible.

§Arguments
  • document - ParsedDocument to search in
  • patterns - Slice of AST patterns to match
  • context - Analysis context for execution configuration
§Returns

Vector of CodeMatch instances for all pattern matches

Source

fn replace_pattern<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>( &'life0 self, document: &'life1 mut ParsedDocument<D>, pattern: &'life2 str, replacement: &'life3 str, context: &'life4 AnalysisContext, ) -> Pin<Box<dyn Future<Output = Result<usize, Box<dyn Error + Send + Sync>>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait, Self: 'async_trait,

Replace matches for a pattern with replacement content.

Preserves all ast-grep replacement power including template-based replacement with meta-variable substitution and structural replacement.

§Arguments
  • document - ParsedDocument to perform replacements in (modified in-place)
  • pattern - AST pattern to match for replacement
  • replacement - Replacement template or content
  • context - Analysis context for execution configuration
§Returns

Number of replacements made

Source

fn analyze_cross_file_relationships<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, documents: &'life1 [ParsedDocument<D>], context: &'life2 AnalysisContext, ) -> Pin<Box<dyn Future<Output = Result<Vec<CrossFileRelationship>, Box<dyn Error + Send + Sync>>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Analyze relationships across multiple files.

This is where Thread extends ast-grep from file-level to codebase-level. Builds graph intelligence on top of ast-grep’s powerful file-level analysis.

§Arguments
  • documents - Collection of ParsedDocuments to analyze
  • context - Analysis context with scope and execution configuration
§Returns

Vector of CrossFileRelationship instances representing codebase-level connections

Source

fn capabilities(&self) -> AnalyzerCapabilities

Get analyzer capabilities and configuration.

Provided Methods§

Source

fn find_nodes_by_kind<'life0, 'life1, 'life2, 'life3, 'async_trait>( &'life0 self, document: &'life1 ParsedDocument<D>, node_kind: &'life2 str, context: &'life3 AnalysisContext, ) -> Pin<Box<dyn Future<Output = Result<Vec<CodeMatch<'life0, D>>, Box<dyn Error + Send + Sync>>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, Self: 'async_trait,

Find specific AST node types efficiently.

Default implementation uses pattern matching, but implementations can override for more efficient node type searches.

Source

fn validate_pattern( &self, pattern: &str, ) -> Result<(), Box<dyn Error + Send + Sync>>

Validate pattern syntax before analysis.

Default implementation performs basic validation. Implementations can override for language-specific validation.

Source

fn compile_pattern<'life0, 'life1, 'async_trait>( &'life0 self, pattern: &'life1 str, ) -> Pin<Box<dyn Future<Output = Result<CompiledPattern, Box<dyn Error + Send + Sync>>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, Self: 'async_trait,

Compile pattern for efficient reuse.

Default implementation returns the pattern as-is. Implementations can override to pre-compile patterns for better performance.

Source

fn batch_analyze<'life0, 'life1, 'life2, 'life3, 'life4, 'async_trait>( &'life0 self, documents: &'life1 [ParsedDocument<D>], patterns: &'life2 [&'life3 str], context: &'life4 AnalysisContext, ) -> Pin<Box<dyn Future<Output = Result<Vec<Vec<CodeMatch<'life0, D>>>, Box<dyn Error + Send + Sync>>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, 'life3: 'async_trait, 'life4: 'async_trait, Self: 'async_trait,

Perform batch analysis operations efficiently.

Optimizes for analyzing multiple documents with multiple patterns by batching operations and using appropriate execution strategies.

Source

fn extract_symbols<'life0, 'life1, 'life2, 'async_trait>( &'life0 self, _document: &'life1 mut ParsedDocument<D>, _context: &'life2 AnalysisContext, ) -> Pin<Box<dyn Future<Output = Result<(), Box<dyn Error + Send + Sync>>> + Send + 'async_trait>>
where 'life0: 'async_trait, 'life1: 'async_trait, 'life2: 'async_trait, Self: 'async_trait,

Extract symbols and metadata from documents.

Bridges ast-grep file-level analysis to codebase-level intelligence by extracting symbols, imports, exports, and other metadata.

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§

Source§

impl<D> CodeAnalyzer<D> for CocoIndexAnalyzer
where D: Doc + Send + Sync,