161 lines
6.7 KiB
C
161 lines
6.7 KiB
C
#ifndef CBM_LSP_GO_LSP_H
|
|
#define CBM_LSP_GO_LSP_H
|
|
|
|
#include "type_rep.h"
|
|
#include "scope.h"
|
|
#include "type_registry.h"
|
|
#include "../cbm.h"
|
|
|
|
// GoLSPContext holds state for Go expression type evaluation within a file.
|
|
typedef struct {
|
|
CBMArena* arena;
|
|
const char* source;
|
|
int source_len;
|
|
const CBMTypeRegistry* registry;
|
|
CBMScope* current_scope;
|
|
|
|
// Import map: local_name -> package QN (arena-allocated)
|
|
const char** import_local_names; // NULL-terminated
|
|
const char** import_package_qns; // NULL-terminated
|
|
int import_count;
|
|
|
|
// Current function context
|
|
const char* enclosing_func_qn;
|
|
const char* package_qn; // module QN for this file
|
|
|
|
// Output: resolved calls accumulate here
|
|
CBMResolvedCallArray* resolved_calls;
|
|
|
|
// AST-walk recursion depth for resolve_calls_in_node (guards stack overflow
|
|
// on deeply-nested/cyclic files; see cbm_lsp_max_walk_depth). Zero via memset.
|
|
int walk_depth;
|
|
|
|
// Debug mode (CBM_LSP_DEBUG env)
|
|
bool debug;
|
|
} GoLSPContext;
|
|
|
|
// Initialize a GoLSPContext for processing one file.
|
|
void go_lsp_init(GoLSPContext* ctx, CBMArena* arena, const char* source, int source_len,
|
|
const CBMTypeRegistry* registry, const char* package_qn, CBMResolvedCallArray* out);
|
|
|
|
// Add an import mapping.
|
|
void go_lsp_add_import(GoLSPContext* ctx, const char* local_name, const char* package_qn);
|
|
|
|
// Process all functions in a file's AST, evaluating types and resolving calls.
|
|
// root is the tree-sitter root node of the file.
|
|
void go_lsp_process_file(GoLSPContext* ctx, TSNode root);
|
|
|
|
// Evaluate the type of a Go expression node.
|
|
const CBMType* go_eval_expr_type(GoLSPContext* ctx, TSNode node);
|
|
|
|
// Parse a Go type AST node into a CBMType.
|
|
const CBMType* go_parse_type_node(GoLSPContext* ctx, TSNode node);
|
|
|
|
// Process a Go statement, binding variables into the current scope.
|
|
void go_process_statement(GoLSPContext* ctx, TSNode node);
|
|
|
|
// Evaluate a builtin call (make, new, append, len, cap, delete).
|
|
const CBMType* go_eval_builtin_call(GoLSPContext* ctx, const char* name, TSNode args);
|
|
|
|
// Look up a field or method on a type, traversing embedded types.
|
|
const CBMRegisteredFunc* go_lookup_field_or_method(GoLSPContext* ctx,
|
|
const char* type_qn, const char* member_name);
|
|
|
|
// Entry point: build registry from file's own defs + run LSP resolution.
|
|
// Called from cbm_extract_file() after definitions and imports are extracted.
|
|
void cbm_run_go_lsp(CBMArena* arena, CBMFileResult* result,
|
|
const char* source, int source_len, TSNode root);
|
|
|
|
// Register Go stdlib types and functions into a registry.
|
|
// Auto-generated by scripts/gen-go-stdlib.go.
|
|
void cbm_go_stdlib_register(CBMTypeRegistry* reg, CBMArena* arena);
|
|
|
|
// --- Cross-file LSP resolution ---
|
|
|
|
// Simplified definition for cross-file type/function registration.
|
|
// String fields are borrowed (caller owns memory until cbm_run_go_lsp_cross returns).
|
|
typedef struct {
|
|
const char* qualified_name;
|
|
const char* short_name;
|
|
const char* label; // "Function", "Method", "Type", "Interface"
|
|
const char* receiver_type; // for methods: receiver type QN (NULL for functions)
|
|
const char* def_module_qn; // module QN where this def lives (for type text qualification)
|
|
const char* return_types; // "|"-separated return type texts, e.g. "*File|error"
|
|
const char* embedded_types; // "|"-separated embedded type QNs (for struct embedding)
|
|
const char* field_defs; // "|"-separated "name:type" pairs (for struct fields, e.g. "Binder:Binder|Name:string")
|
|
const char* method_names_str; // "|"-separated method names for interfaces (e.g. "Get|Put|Delete")
|
|
bool is_interface;
|
|
CBMLanguage lang; // language of the file that defined this — used by Tier 2 per-language registry build to filter all_defs
|
|
const char* namespace_name; // declared namespace/package for source-root-independent JVM filtering
|
|
} CBMLSPDef;
|
|
|
|
// Parse source, build registry from defs + stdlib, run LSP.
|
|
// Re-parses source with tree-sitter internally.
|
|
// defs includes both file-local and cross-file definitions.
|
|
// import_names/import_qns are parallel arrays of length import_count.
|
|
// Results written to out (arena-allocated).
|
|
void cbm_run_go_lsp_cross(
|
|
CBMArena* arena,
|
|
const char* source, int source_len,
|
|
const char* module_qn,
|
|
CBMLSPDef* defs, int def_count,
|
|
const char** import_names, const char** import_qns, int import_count,
|
|
TSTree* cached_tree, // NULL = parse internally
|
|
CBMResolvedCallArray* out);
|
|
|
|
/* Tier 2 (gopls package-summary pattern):
|
|
* Build a project-wide, finalized CBMTypeRegistry from all Go defs ONCE.
|
|
* Run cross-file LSP per file using that shared registry — no per-file
|
|
* registry build, O(1) lookups, no Phase 1b/1c mutations. Reg is borrowed
|
|
* from arena (arena owns the storage); reg pointer is valid for arena
|
|
* lifetime. */
|
|
CBMTypeRegistry* cbm_go_build_cross_registry(
|
|
CBMArena* arena, CBMLSPDef* defs, int def_count);
|
|
|
|
void cbm_run_go_lsp_cross_with_registry(
|
|
CBMArena* arena,
|
|
const char* source, int source_len,
|
|
const char* module_qn,
|
|
CBMTypeRegistry* reg, // pre-built, finalized, READ-ONLY
|
|
const char** import_names, const char** import_qns, int import_count,
|
|
TSTree* cached_tree, // NULL = parse internally
|
|
CBMResolvedCallArray* out);
|
|
|
|
/* Tier 3: AST-walk-free fast resolver. Iterates result->calls and
|
|
* resolves fully-qualified calls (pkg.Func) directly from the
|
|
* pre-built registry — no tree-sitter parse, no AST walk. Returns
|
|
* the count of calls that STILL need the slow path (methods on
|
|
* locals + qualified calls we couldn't resolve). When the return
|
|
* value is 0, the caller can skip the cbm_run_go_lsp_cross_with_
|
|
* registry parse+walk entirely. Resolved entries are appended to
|
|
* result->resolved_calls in result->arena. */
|
|
int cbm_go_fast_resolve_qualified_calls(
|
|
CBMFileResult* result,
|
|
CBMTypeRegistry* reg,
|
|
const char** import_names, const char** import_qns, int import_count);
|
|
|
|
// --- Batch cross-file LSP ---
|
|
|
|
// Per-file input for batch Go LSP processing.
|
|
typedef struct {
|
|
const char* source;
|
|
int source_len;
|
|
const char* module_qn;
|
|
TSTree* cached_tree; // from TSTree caching (NULL = parse internally)
|
|
CBMLSPDef* defs; // combined file-local + cross-file defs
|
|
int def_count;
|
|
const char** import_names; // parallel arrays, import_count long
|
|
const char** import_qns;
|
|
int import_count;
|
|
} CBMBatchGoLSPFile;
|
|
|
|
// Process multiple Go files' cross-file LSP in one CGo call.
|
|
// out must point to file_count pre-zeroed CBMResolvedCallArray structs.
|
|
// Uses per-file arenas internally; results are copied to the output arena.
|
|
void cbm_batch_go_lsp_cross(
|
|
CBMArena* arena,
|
|
CBMBatchGoLSPFile* files, int file_count,
|
|
CBMResolvedCallArray* out);
|
|
|
|
#endif // CBM_LSP_GO_LSP_H
|