Files
wehub-resource-sync 41cb1c0170
OpenSSF Scorecard / scorecard (push) Failing after 0s
DCO / dco (push) Failing after 0s
CodeQL SAST / analyze (push) Failing after 1s
Deploy Pages / deploy (push) Failing after 1s
chore: import upstream snapshot with attribution
2026-07-13 12:28:05 +08:00

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