cha-core 1.14.0

Core analysis engine for Cha — pluggable code smell detection
Documentation
package cha:plugin@0.2.0;

/// Data types shared between host and guest.
interface types {
    /// Severity level.
    enum severity {
        hint,
        warning,
        error,
    }

    /// Smell category.
    enum smell-category {
        bloaters,
        oo-abusers,
        change-preventers,
        dispensables,
        couplers,
        security,
    }

    /// Source location.
    record location {
        path: string,
        start-line: u32,
        start-col: u32,
        end-line: u32,
        end-col: u32,
        name: option<string>,
    }

    /// Where a referenced type is declared.
    variant type-origin {
        /// Declared inside the project.
        project-local,
        /// Imported from external module / crate / package (name if known).
        external(string),
        /// Built-in primitive / standard library scalar.
        primitive,
        /// Could not be resolved.
        unknown,
    }

    /// A function parameter or return type, with resolved origin.
    record type-ref {
        /// Innermost type identifier after stripping refs/generics/containers.
        name: string,
        /// Original source text as written.
        raw: string,
        /// Where the type is declared.
        origin: type-origin,
    }

    /// A single finding.
    record finding {
        smell-name: string,
        category: smell-category,
        severity: severity,
        location: location,
        message: string,
        suggested-refactorings: list<string>,
        actual-value: option<f64>,
        threshold: option<f64>,
    }

    /// Switch/match arm value type.
    variant arm-value {
        str-lit(string),
        int-lit(s64),
        char-lit(u32),
        other,
    }

    /// Function info from parsed source.
    record function-info {
        name: string,
        start-line: u32,
        end-line: u32,
        name-col: u32,
        name-end-col: u32,
        line-count: u32,
        complexity: u32,
        parameter-count: u32,
        parameter-types: list<type-ref>,
        parameter-names: list<string>,
        chain-depth: u32,
        switch-arms: u32,
        switch-arm-values: list<arm-value>,
        external-refs: list<string>,
        is-delegating: bool,
        is-exported: bool,
        comment-lines: u32,
        referenced-fields: list<string>,
        null-check-fields: list<string>,
        switch-dispatch-target: option<string>,
        optional-param-count: u32,
        called-functions: list<string>,
        cognitive-complexity: u32,
        body-hash: option<string>,
        return-type: option<type-ref>,
    }

    /// Class info from parsed source.
    record class-info {
        name: string,
        start-line: u32,
        end-line: u32,
        name-col: u32,
        name-end-col: u32,
        method-count: u32,
        line-count: u32,
        delegating-method-count: u32,
        field-count: u32,
        field-names: list<string>,
        field-types: list<string>,
        is-exported: bool,
        has-behavior: bool,
        is-interface: bool,
        parent-name: option<string>,
        override-count: u32,
        self-call-count: u32,
        has-listener-field: bool,
        has-notify-method: bool,
    }

    /// Import info.
    record import-info {
        source: string,
        line: u32,
        col: u32,
        is-module-decl: bool,
    }

    /// File role inferred by the host from path patterns.
    enum file-role {
        source,
        test,
        doc,
        config,
        generated,
    }

    /// Comment info from parsed source.
    record comment-info {
        text: string,
        line: u32,
    }

    /// Typed option value for plugin configuration.
    variant option-value {
        str(string),
        int(s64),
        float(f64),
        boolean(bool),
        list-str(list<string>),
    }

    /// Full analysis context passed to the plugin.
    record analysis-input {
        path: string,
        content: string,
        language: string,
        total-lines: u32,
        role: file-role,
        functions: list<function-info>,
        classes: list<class-info>,
        imports: list<import-info>,
        comments: list<comment-info>,
        type-aliases: list<tuple<string, string>>,
        options: list<tuple<string, option-value>>,
    }
}

/// AST query interface provided by the host.
/// Plugins can import this to execute tree-sitter queries against the current file's AST.
interface tree-query {
    /// A single capture from a query match.
    record query-match {
        capture-name: string,
        node-kind: string,
        text: string,
        start-line: u32,
        start-col: u32,
        end-line: u32,
        end-col: u32,
    }

    /// Execute a tree-sitter query pattern against the current file's AST.
    /// Returns list of matches; each match is a list of captures.
    run-query: func(pattern: string) -> list<list<query-match>>;

    /// Execute multiple query patterns in one call, reducing cross-boundary overhead.
    /// Returns results in the same order as the input patterns.
    run-queries: func(patterns: list<string>) -> list<list<list<query-match>>>;

    /// Get the AST node at a specific position.
    node-at: func(line: u32, col: u32) -> option<query-match>;

    /// Get all named top-level child nodes within a line range.
    nodes-in-range: func(start-line: u32, end-line: u32) -> list<query-match>;
}

/// The world that WASM plugins must implement.
world analyzer {
    use types.{analysis-input, finding};

    import tree-query;

    /// Return the plugin name (matches [plugins.<name>] in .cha.toml).
    export name: func() -> string;

    /// Return the plugin version (e.g. "1.0.0").
    export version: func() -> string;

    /// Return a short description of what the plugin detects.
    export description: func() -> string;

    /// Return the list of authors.
    export authors: func() -> list<string>;

    /// Return the smell names this plugin can produce. Used by the host for
    /// smell-level filtering, `cha plugin list`, and docs. May be empty.
    export smells: func() -> list<string>;

    /// Run analysis and return findings.
    export analyze: func(input: analysis-input) -> list<finding>;
}