impactsense-parser 0.1.2

Multi-language static analysis: parse codebases into an in-memory dependency graph for impact analysis
Documentation
use std::fmt;

/// Labels used for nodes in the Neo4j graph.
///
/// This file is the central "schema contract" describing what node types
/// exist and which common properties they are expected to have.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum NodeLabel {
    /// Source file (any language).
    File,
    /// Logical module / grouping of functions.
    /// For Erlang this is one `.erl` file with a `-module(Name).`.
    Module,
    /// A concrete function or method.
    Function,
    /// OTP/custom behaviour contract node.
    Behaviour,
    /// Callback contract declared by a behaviour.
    Callback,
    /// An HTTP or RPC API endpoint exposed by the system.
    ApiEndpoint,
    /// An external API or service that the system calls out to.
    ExternalApi,
}

impl fmt::Display for NodeLabel {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let s = match self {
            NodeLabel::File => "File",
            NodeLabel::Module => "Module",
            NodeLabel::Function => "Function",
            NodeLabel::Behaviour => "Behaviour",
            NodeLabel::Callback => "Callback",
            NodeLabel::ApiEndpoint => "ApiEndpoint",
            NodeLabel::ExternalApi => "ExternalApi",
        };
        f.write_str(s)
    }
}

/// Common property keys shared across node types.
pub mod props {
    /// Filesystem or project‑relative path.
    pub const PATH: &str = "path";
    /// Programming language of the artifact (e.g. "erlang", "java").
    pub const LANGUAGE: &str = "language";
    /// Web / application framework (e.g. "cowboy", "spring").
    pub const FRAMEWORK: &str = "framework";
    /// Logical project or service name (e.g. "omega").
    pub const PROJECT_NAME: &str = "project_name";
    /// Simple name (module name, function name, etc.).
    pub const NAME: &str = "name";
    /// Fully-qualified name for symbols (e.g. module:function/arity or
    /// com.example.Class.method).
    pub const FQN: &str = "fqn";
    /// Arity for languages that care about it (e.g. Erlang).
    pub const ARITY: &str = "arity";
    /// Return type of the function when it is explicitly declared (Java, C#,
    /// Go, Erlang -spec, etc.). This is optional and may be absent for
    /// dynamically-typed or unannotated code.
    pub const RETURN_TYPE: &str = "return_type";
    /// Number of parameters the function takes. For Erlang this should match
    /// `arity`; for other languages it is simply the parameter list length.
    pub const PARAM_COUNT: &str = "param_count";
    /// Parameter types when they are explicitly written in the source (e.g.
    /// Java, C#, Go, TypeScript). Stored as an array of strings.
    pub const PARAM_TYPES: &str = "param_types";
    /// Whether callback is optional for its behaviour contract.
    pub const OPTIONAL: &str = "optional";
    /// HTTP method(s) for an API endpoint, e.g. GET/POST.
    pub const METHOD: &str = "method";
    /// Canonical path for an API endpoint, e.g. "/omega/api/getavroutes".
    pub const PATH_TEMPLATE: &str = "path";
    /// Protocol for the endpoint (e.g. "http", "https", "grpc").
    pub const PROTOCOL: &str = "protocol";
    /// Base URL for an external API, e.g. "https://api.vendorx.com".
    pub const BASE_URL: &str = "base_url";
    /// Logical provider/vendor name for an external API, e.g. "VendorX".
    pub const PROVIDER: &str = "provider";
    /// Logical service domain for an external API, e.g. "payments",
    /// "inventory", "search".
    pub const SERVICE: &str = "service";
    /// Zstd-compressed source snippet (RedCompressor wire format, raw bytes).
    pub const CODE_BYTES: &str = "code_bytes";
}

/// Structured view of the properties we expect on a `File` node.
#[derive(Debug, Clone)]
pub struct FileNode<'a> {
    pub path: &'a str,
    pub language: &'a str,
    pub framework: Option<&'a str>,
    pub project_name: Option<&'a str>,
}

/// Structured view of the properties we expect on a `Module` node.
#[derive(Debug, Clone)]
pub struct ModuleNode<'a> {
    pub name: &'a str,
    pub path: &'a str,
    pub language: &'a str,
    pub framework: Option<&'a str>,
    pub project_name: Option<&'a str>,
}

/// Structured view of the properties we expect on a `Function` node.
///
/// This is intentionally generic and works across languages:
/// - Erlang: `name`, `arity`, `fqn = "module:name/arity"`.
/// - Java / C#: `name`, `arity = None`, `fqn` includes class + method.
#[derive(Debug, Clone)]
pub struct FunctionNode<'a> {
    pub name: &'a str,
    pub fqn: &'a str,
    pub path: &'a str,
    pub language: &'a str,
    pub framework: Option<&'a str>,
    pub project_name: Option<&'a str>,
    /// For Erlang this should be `Some(arity)`, for many other languages it
    /// can remain `None`.
    pub arity: Option<u32>,
    /// Explicit return type, if it can be extracted from the syntax tree or
    /// type annotations.
    pub return_type: Option<&'a str>,
    /// Number of parameters, if it can be extracted. For parameter-less
    /// functions this is typically `Some(0)`, but callers may also choose to
    /// leave it as `None` if they do not compute it.
    pub param_count: Option<u32>,
    /// Parameter type names in declaration order, when available. This allows
    /// richer queries like "which functions take an OrderDetail as input?".
    pub param_types: Option<&'a [&'a str]>,
}

/// Structured view of the properties we expect on a `Behaviour` node.
#[derive(Debug, Clone)]
pub struct BehaviourNode<'a> {
    /// Behaviour name, e.g. `gen_server`, `my_custom_behaviour`.
    pub name: &'a str,
    /// File path where this behaviour is declared (if local/custom).
    pub path: Option<&'a str>,
    pub language: Option<&'a str>,
    pub project_name: Option<&'a str>,
}

/// Structured view of the properties we expect on a `Callback` node.
#[derive(Debug, Clone)]
pub struct CallbackNode<'a> {
    /// Callback simple name, e.g. `handle_call`.
    pub name: &'a str,
    /// Stable callback key, e.g. `gen_server:handle_call/3`.
    pub fqn: &'a str,
    pub arity: u32,
    pub optional: bool,
    pub language: Option<&'a str>,
    pub project_name: Option<&'a str>,
}

/// Structured view of the properties we expect on an `ApiEndpoint` node.
///
/// This shape is intentionally minimal and framework-agnostic so it can be
/// populated from Erlang/Cowboy, Java/Spring, JS/Express, etc.
#[derive(Debug, Clone)]
pub struct ApiEndpointNode<'a> {
    /// HTTP methods for this endpoint (e.g. ["GET"], ["GET","POST"]).
    pub methods: &'a [&'a str],
    /// Canonical path template, e.g. "/omega/api/getavroutes" or
    /// "/orders/{id}".
    pub path: &'a str,
    /// Protocol such as "http" or "https".
    pub protocol: Option<&'a str>,
    /// Framework that exposes this endpoint (e.g. "cowboy", "spring").
    pub framework: Option<&'a str>,
    /// Logical project/service name this endpoint belongs to.
    pub project_name: Option<&'a str>,
}

/// Structured view of the properties we expect on an `ExternalApi` node.
///
/// This represents a remote system or API surface that our code calls into.
/// Multiple internal functions across projects/frameworks can all point to
/// the same `ExternalApi` node via `CALLS_EXTERNAL_API` edges.
#[derive(Debug, Clone)]
pub struct ExternalApiNode<'a> {
    /// Human-friendly logical name, e.g. "VendorX", "Stripe", "GDS-Search".
    pub name: &'a str,
    /// Base URL if it is an HTTP(S) API, e.g. "https://api.vendorx.com".
    pub base_url: Option<&'a str>,
    /// Protocol such as "http", "https", "grpc", "kafka".
    pub protocol: Option<&'a str>,
    /// Provider or organization behind the API, e.g. "VendorX".
    pub provider: Option<&'a str>,
    /// Logical service domain, e.g. "payments", "inventory", "search".
    pub service: Option<&'a str>,
}