/**
 * Cross-File Call Resolution
 *
 * Resolves method calls to their definitions across file boundaries,
 * enabling cross-file taint tracking.
 */
import type { CallInfo, CircleIR } from '../types/index.js';
import { SymbolTable } from './symbol-table.js';
import { TypeHierarchyResolver } from './type-hierarchy.js';
/**
 * Resolved call with target information
 */
export interface ResolvedCall {
    call: CallInfo;
    sourceFile: string;
    targetFile: string;
    targetMethod: string;
    targetClass: string;
    resolution: 'exact' | 'polymorphic' | 'inferred';
    candidates?: string[];
}
/**
 * Taint propagation information for a method
 */
export interface MethodTaintInfo {
    methodFqn: string;
    file: string;
    taintedParams: number[];
    returnsSource: boolean;
    sourceType?: string;
    sanitizes: boolean;
    sanitizedTypes?: string[];
}
/**
 * Cross-file taint flow
 */
export interface CrossFileTaintFlow {
    sourceFile: string;
    sourceLine: number;
    sourceType: string;
    targetFile: string;
    targetLine: number;
    targetMethod: string;
    flowType: 'call_arg' | 'return_value' | 'field_access';
    taintedArgPositions?: number[];
}
/**
 * Inter-procedural taint chain that spans multiple files / call sites.
 *
 * Shape: SOURCE in file A → caller's wrapper-return site → caller's sink-call
 * site → SINK in file B.  Used when no per-file source/sink is co-located in
 * a single caller frame, so `findCrossFileTaintFlows()` cannot fire.
 */
export interface InterproceduralTaintPath {
    source: {
        file: string;
        line: number;
        type: string;
    };
    sink: {
        file: string;
        line: number;
        type: string;
        cwe: string;
    };
    hops: Array<{
        file: string;
        line: number;
        method: string;
        kind: 'source' | 'wrapper_return' | 'field_write' | 'field_read' | 'sink_call' | 'sink';
    }>;
    confidence: number;
}
/**
 * Per-type field-binding taint summary.
 *
 * Records which fields on a class hold tainted data because a method in the
 * class wrote a tainted parameter into the field (`this.field = param`).
 * Used to surface cross-instance flows of the canonical Jenkins shape:
 *   `@DataBoundConstructor C(p)` writes `this.f = p` → another class holds a
 *   `C` instance and reads `instance.f` → that read flows to a sink.
 */
export interface FieldTaintInfo {
    typeFqn: string;
    fieldName: string;
    fieldType: string | null;
    file: string;
    /** Methods that write tainted data into this field. */
    writers: Array<{
        methodFqn: string;
        methodName: string;
        writeLine: number;
        /** Source type carried into the field (`http_param`, `autowired`, etc.). */
        sourceType: string;
        /** Original source line in the writer's method body. */
        sourceLine: number;
    }>;
}
/**
 * CrossFileResolver - Resolves calls and tracks taint across files
 */
export declare class CrossFileResolver {
    private symbolTable;
    private typeHierarchy;
    private fileIRs;
    private methodTaintInfo;
    private fieldTaintInfo;
    private resolvedCalls;
    constructor(symbolTable: SymbolTable, typeHierarchy: TypeHierarchyResolver);
    /**
     * Add a file's IR for analysis
     */
    addFile(filePath: string, ir: CircleIR): void;
    /**
     * Resolve a call to its target method(s)
     */
    resolveCall(call: CallInfo, fromFile: string): ResolvedCall | undefined;
    /**
     * Resolve call with a receiver (instance method call)
     */
    private resolveWithReceiver;
    /**
     * Resolve static or local method call
     */
    private resolveStaticOrLocal;
    /**
     * Resolve by searching all known methods
     */
    private resolveByMethodName;
    /**
     * Infer the type of a receiver variable
     */
    private inferReceiverType;
    /**
     * Find polymorphic candidates (implementations/subclasses)
     */
    private findPolymorphicCandidates;
    /**
     * Analyze methods for taint propagation characteristics
     */
    private analyzeMethodTaint;
    /**
     * Per-file analysis of cross-instance field bindings.
     *
     * Records `FieldTaintInfo` entries for fields written by:
     *   1. `@DataBoundConstructor`-style constructors  — surfaced as
     *      `constructor_field` sources by `LanguageSourcesPass`.
     *   2. Setter methods `set<Field>(<param>)` — assume the canonical
     *      `this.<field> = <param>` body shape, so the setter PARAMETER acts
     *      as the taint conduit at call sites.
     *   3. `@Autowired` field annotations — the field itself is a framework
     *      injection point; the writer is synthetic (line = field decl).
     *
     * The entries are keyed `${typeFqn}.${fieldName}` and consumed by
     * `findFieldBindingTaintPaths()` to surface flows of the canonical Jenkins
     * shape: ctor writes field → another class reads instance.field → sink.
     */
    private analyzeFieldTaint;
    /**
     * Check if method is a taint source.
     *
     * Excludes synthetic `interprocedural_param` sources — those are per-file
     * meta-analysis signals saying "this method's parameter MIGHT be tainted
     * when called with tainted data", not confirmed external inputs.  Treating
     * them as sources for cross-file `returnsSource` would propagate ghost
     * taint into every callee with typed parameters.
     */
    private isMethodTaintSource;
    /**
     * Get source type for a method (excluding synthetic interprocedural_param)
     */
    private getSourceType;
    /**
     * Find which parameters propagate taint to a sink within this method.
     *
     * Two heuristics, combined:
     *   1. Annotation-based: params with @RequestParam/@RequestBody/@PathVariable.
     *   2. Sink-arg matching: if a known sink call in the method body references
     *      a param by name in its arguments, that param propagates taint to a
     *      sink — this is the summary that cross-file chaining needs to link
     *      a caller's tainted argument to a downstream dangerous operation.
     */
    private findTaintedParams;
    /**
     * Check if method name suggests sanitization
     */
    private isSanitizerMethod;
    /**
     * Get types sanitized by a method
     */
    private getSanitizedTypes;
    /**
     * Find all callers of a method across the project
     */
    findCallers(methodFqn: string): ResolvedCall[];
    /**
     * Find cross-file taint flows
     */
    findCrossFileTaintFlows(): CrossFileTaintFlow[];
    /**
     * Find inter-procedural taint chains spanning multiple files / call sites.
     *
     * Bridges the gap that `findCrossFileTaintFlows()` cannot cover: a real
     * source lives in callee A, its return value bubbles up to caller C as a
     * tainted local, and C then passes that local to callee B which contains
     * the actual dangerous sink.  Neither A nor C alone has a co-located
     * source-and-sink, but the chain A → C → B is a real vulnerability.
     *
     * Algorithm (per caller method M):
     *   1. Seed `tainted` with real (non-`interprocedural_param`) sources in M.
     *   2. Walk calls in M in line order:
     *      a. If callee has `returnsSource = true` and is not a sanitizer,
     *         mark every `local` DFG def at this line as tainted, anchored to
     *         the callee's source.
     *      b. For each tainted arg in this call, if the callee's
     *         `taintedParams` covers that position, emit one
     *         `InterproceduralTaintPath` per sink inside the callee body.
     */
    findInterproceduralTaintPaths(): InterproceduralTaintPath[];
    /**
     * Find cross-instance field-binding taint paths.
     *
     * Closes the canonical Jenkins / framework-DI shape that
     * `findInterproceduralTaintPaths()` cannot cover because the "source" lives
     * on an aliased object's field, not in a callee return:
     *
     *   File A:  class C { @DataBoundConstructor C(p) { this.f = p; } }
     *   File B:  class E { final C step; E(C step){ this.step = step; }
     *                      m() { String x = step.f; sink(x); } }
     *
     * Algorithm (per caller method M in file B):
     *   1. Seed `tainted` with sources inside M (mirrors findInterproc step 1).
     *   2. Scan M's local-def DFG entries for expressions of shape
     *      `<receiver>.<field>` where receiver's declared type owns `<field>`
     *      in the FieldTaintInfo cache. Mark the LHS local as tainted, anchor
     *      its origin to the field-binding writer (e.g. the ctor in file A).
     *   3. After seeding, walk caller-body sinks the same way
     *      `findInterproceduralTaintPaths()` step 2c does, and also forward
     *      tainted locals into cross-file callees whose `taintedParams` mark
     *      the arg position as sink-propagating.
     */
    findFieldBindingTaintPaths(): InterproceduralTaintPath[];
    /**
     * Check whether any loaded type with name `typeName` (simple or FQN suffix)
     * declares a field named `fieldName`.
     */
    private typeHasField;
    /**
     * Resolve a receiver type-name + field-name to the cache key used by
     * `fieldTaintInfo`. Handles simple-name receivers (e.g. `ReadTrustedStep`)
     * by looking up matching FQN keys across loaded files.
     */
    private resolveFieldTaintKey;
    /**
     * Find which method a tainted arg expression references.
     */
    private matchTaintedArg;
    /**
     * Index methods by FQN for quick lookup during chain construction.
     */
    private buildMethodIndex;
    /** Return the first local-def variable name at a given line, if any. */
    private getLocalDefVarAt;
    private findRealSourceLineInMethod;
    /**
     * Get taint info for a method
     */
    getMethodTaintInfo(methodFqn: string): MethodTaintInfo | undefined;
    /**
     * Get all resolved calls from a file
     */
    getResolvedCallsFromFile(filePath: string): ResolvedCall[];
    /**
     * Get statistics
     */
    getStats(): {
        totalFiles: number;
        totalCalls: number;
        resolvedCalls: number;
        crossFileCalls: number;
        methodsWithTaintInfo: number;
    };
    /**
     * Clear all caches
     */
    clear(): void;
    /** Expose field-taint summary (for tests + diagnostics). */
    getFieldTaintInfo(typeFqn: string, fieldName: string): FieldTaintInfo | undefined;
}
/**
 * Build a cross-file resolver from multiple IR results
 */
export declare function buildCrossFileResolver(files: Array<{
    ir: CircleIR;
    path: string;
}>, symbolTable?: SymbolTable, typeHierarchy?: TypeHierarchyResolver): CrossFileResolver;
//# sourceMappingURL=cross-file.d.ts.map