pub trait CodeAnalyzer<D: Doc + Send + Sync>: 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 = ServiceResult<Vec<CodeMatch<'_, D>>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: '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 = ServiceResult<Vec<CodeMatch<'_, D>>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: '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 = ServiceResult<usize>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: '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 = ServiceResult<Vec<CrossFileRelationship>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: '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 = ServiceResult<Vec<CodeMatch<'_, D>>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait { ... }
fn validate_pattern(&self, pattern: &str) -> ServiceResult<()> { ... }
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 = ServiceResult<Vec<Vec<CodeMatch<'_, D>>>>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: '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 = ServiceResult<()>> + Send + 'async_trait>>
where Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: '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§
Sourcefn 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 = ServiceResult<Vec<CodeMatch<'_, D>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
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 = ServiceResult<Vec<CodeMatch<'_, D>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: '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 inpattern- 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
Sourcefn 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 = ServiceResult<Vec<CodeMatch<'_, D>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: '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 = ServiceResult<Vec<CodeMatch<'_, D>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: '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 inpatterns- Slice of AST patterns to matchcontext- Analysis context for execution configuration
§Returns
Vector of CodeMatch instances for all pattern matches
Sourcefn 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 = ServiceResult<usize>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: '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 = ServiceResult<usize>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: '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 replacementreplacement- Replacement template or contentcontext- Analysis context for execution configuration
§Returns
Number of replacements made
Sourcefn analyze_cross_file_relationships<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
documents: &'life1 [ParsedDocument<D>],
context: &'life2 AnalysisContext,
) -> Pin<Box<dyn Future<Output = ServiceResult<Vec<CrossFileRelationship>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: '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 = ServiceResult<Vec<CrossFileRelationship>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: '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 analyzecontext- Analysis context with scope and execution configuration
§Returns
Vector of CrossFileRelationship instances representing codebase-level connections
Sourcefn capabilities(&self) -> AnalyzerCapabilities
fn capabilities(&self) -> AnalyzerCapabilities
Get analyzer capabilities and configuration.
Provided Methods§
Sourcefn 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 = ServiceResult<Vec<CodeMatch<'_, D>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
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 = ServiceResult<Vec<CodeMatch<'_, D>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
Find specific AST node types efficiently.
Default implementation uses pattern matching, but implementations can override for more efficient node type searches.
Sourcefn validate_pattern(&self, pattern: &str) -> ServiceResult<()>
fn validate_pattern(&self, pattern: &str) -> ServiceResult<()>
Validate pattern syntax before analysis.
Default implementation performs basic validation. Implementations can override for language-specific validation.
Sourcefn 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 = ServiceResult<Vec<Vec<CodeMatch<'_, D>>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: '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 = ServiceResult<Vec<Vec<CodeMatch<'_, D>>>>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: 'async_trait,
'life3: 'async_trait,
'life4: 'async_trait,
Perform batch analysis operations efficiently.
Optimizes for analyzing multiple documents with multiple patterns by batching operations and using appropriate execution strategies.
Sourcefn extract_symbols<'life0, 'life1, 'life2, 'async_trait>(
&'life0 self,
_document: &'life1 mut ParsedDocument<D>,
_context: &'life2 AnalysisContext,
) -> Pin<Box<dyn Future<Output = ServiceResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: '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 = ServiceResult<()>> + Send + 'async_trait>>where
Self: 'async_trait,
'life0: 'async_trait,
'life1: 'async_trait,
'life2: '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.