impactsense-parser 0.1.0

Multi-language static analysis: parse codebases into an in-memory dependency graph for impact analysis
Documentation
//! Pure extraction from parsed files into [`ProjectIr`] (no Neo4j).

use std::path::Path;

use thiserror::Error;

use crate::graph::{build_project_ir, GraphPersistenceOptions};
use crate::ir::ProjectIr;
use crate::pipeline::ScanOptions;
use crate::scanner::{scan_and_parse, FileScanConfig, ScannerError};

pub use crate::graph::ExtractOptions;

impl From<&ScanOptions> for crate::graph::ExtractOptions {
    fn from(opts: &ScanOptions) -> Self {
        Self {
            verbose_imports: opts.graph.verbose_imports,
            max_parse_warnings_per_file: opts.graph.max_parse_warnings_per_file,
        }
    }
}

impl From<&GraphPersistenceOptions> for crate::graph::ExtractOptions {
    fn from(opts: &GraphPersistenceOptions) -> Self {
        Self {
            verbose_imports: opts.verbose_imports,
            max_parse_warnings_per_file: opts.max_parse_warnings_per_file,
        }
    }
}

#[derive(Debug, Error)]
pub enum ExtractError {
    #[error("scan/parse failed: {0}")]
    Scanner(#[from] ScannerError),
}

/// Build a full project IR from an already-parsed file batch.
pub fn build_project_ir_from_files(
    root: &Path,
    files: &[crate::scanner::ParsedFile],
    options: &ExtractOptions,
) -> ProjectIr {
    build_project_ir(root, files, options)
}

/// Scan a repository root and build project IR.
pub fn scan_and_build_ir(
    root: &Path,
    options: &ExtractOptions,
    scan: &ScanOptions,
) -> Result<ProjectIr, ExtractError> {
    let mut config = FileScanConfig::new(root);
    config.follow_symlinks = scan.follow_symlinks;
    config.max_file_size = scan.max_file_size;
    let files = scan_and_parse(&config)?;
    Ok(build_project_ir_from_files(root, &files, options))
}

/// Parse specific targets and build IR delta (incremental).
pub fn parse_files_to_ir(
    root: &Path,
    parse_targets: &[String],
    options: &ExtractOptions,
    scan: &ScanOptions,
) -> Result<ProjectIr, ExtractError> {
    let mut config = FileScanConfig::new(root);
    config.follow_symlinks = scan.follow_symlinks;
    config.max_file_size = scan.max_file_size;
    let paths: Vec<_> = parse_targets.iter().map(std::path::PathBuf::from).collect();
    let files = crate::scanner_incremental::scan_and_parse_incremental_vector(&config, &paths)?;
    Ok(build_project_ir_from_files(root, &files, options))
}