mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-10-27 06:53:11 +08:00
Merge Java hybrid LSP
Integrates the type-aware Java semantic resolver from
worktree-adding-java-lsp-support (based on 673ac4e): java_lsp.c + generated
java.lang/util stdlib registry, wired into the per-file LSP pass, with 94
java_lsp tests + ~170 java_lsp_coverage tests.
Wiring conflicts (the shared files diverged 146 commits on main) resolved by
keeping main's existing LSP registrations (go/c/php/py/ts/cs) and adding the
Java entries in lsp_all.c, cbm.c (cbm_run_java_lsp dispatch), test_main.c and
Makefile.cbm.
Adapted to the current unity-build: renamed java_lsp.c's static helpers
node_text/return_type_of to java_node_text/java_return_type_of so they no
longer collide with ts_lsp.c inside the shared lsp_all.c translation unit.
4082 tests pass (incl. java_lsp + java_lsp_coverage); ASan/UBSan clean.
This commit is contained in:
+2
-1
@@ -333,6 +333,7 @@ TEST_PY_LSP_STRESS_SRCS = tests/test_py_lsp_stress.c
|
||||
TEST_PY_LSP_SCALE_SRCS = tests/test_py_lsp_scale.c
|
||||
|
||||
TEST_TS_LSP_SRCS = tests/test_ts_lsp.c
|
||||
TEST_JAVA_LSP_SRCS = tests/test_java_lsp.c tests/test_java_lsp_coverage.c
|
||||
|
||||
TEST_INTEGRATION_SRCS = tests/test_integration.c tests/test_incremental.c
|
||||
|
||||
@@ -353,7 +354,7 @@ TEST_SIMHASH_SRCS = tests/test_simhash.c
|
||||
|
||||
TEST_STACK_OVERFLOW_SRCS = tests/test_stack_overflow.c
|
||||
|
||||
ALL_TEST_SRCS = $(TEST_FOUNDATION_SRCS) $(TEST_EXTRACTION_SRCS) $(TEST_STORE_SRCS) $(TEST_CYPHER_SRCS) $(TEST_MCP_SRCS) $(TEST_DISCOVER_SRCS) $(TEST_GRAPH_BUFFER_SRCS) $(TEST_PIPELINE_SRCS) $(TEST_WATCHER_SRCS) $(TEST_LZ4_SRCS) $(TEST_ZSTD_SRCS) $(TEST_ARTIFACT_SRCS) $(TEST_SQLITE_WRITER_SRCS) $(TEST_GO_LSP_SRCS) $(TEST_C_LSP_SRCS) $(TEST_PHP_LSP_SRCS) $(TEST_CS_LSP_SRCS) $(TEST_CS_LSP_BENCH_SRCS) $(TEST_SCOPE_SRCS) $(TEST_TYPE_REP_SRCS) $(TEST_PY_LSP_SRCS) $(TEST_PY_LSP_BENCH_SRCS) $(TEST_PY_LSP_STRESS_SRCS) $(TEST_PY_LSP_SCALE_SRCS) $(TEST_TS_LSP_SRCS) $(TEST_TRACES_SRCS) $(TEST_CLI_SRCS) $(TEST_MEM_SRCS) $(TEST_UI_SRCS) $(TEST_SECURITY_SRCS) $(TEST_YAML_SRCS) $(TEST_SIMHASH_SRCS) $(TEST_STACK_OVERFLOW_SRCS) $(TEST_INTEGRATION_SRCS)
|
||||
ALL_TEST_SRCS = $(TEST_FOUNDATION_SRCS) $(TEST_EXTRACTION_SRCS) $(TEST_STORE_SRCS) $(TEST_CYPHER_SRCS) $(TEST_MCP_SRCS) $(TEST_DISCOVER_SRCS) $(TEST_GRAPH_BUFFER_SRCS) $(TEST_PIPELINE_SRCS) $(TEST_WATCHER_SRCS) $(TEST_LZ4_SRCS) $(TEST_ZSTD_SRCS) $(TEST_ARTIFACT_SRCS) $(TEST_SQLITE_WRITER_SRCS) $(TEST_GO_LSP_SRCS) $(TEST_C_LSP_SRCS) $(TEST_PHP_LSP_SRCS) $(TEST_CS_LSP_SRCS) $(TEST_CS_LSP_BENCH_SRCS) $(TEST_SCOPE_SRCS) $(TEST_TYPE_REP_SRCS) $(TEST_PY_LSP_SRCS) $(TEST_PY_LSP_BENCH_SRCS) $(TEST_PY_LSP_STRESS_SRCS) $(TEST_PY_LSP_SCALE_SRCS) $(TEST_TS_LSP_SRCS) $(TEST_JAVA_LSP_SRCS) $(TEST_TRACES_SRCS) $(TEST_CLI_SRCS) $(TEST_MEM_SRCS) $(TEST_UI_SRCS) $(TEST_SECURITY_SRCS) $(TEST_YAML_SRCS) $(TEST_SIMHASH_SRCS) $(TEST_STACK_OVERFLOW_SRCS) $(TEST_INTEGRATION_SRCS)
|
||||
|
||||
|
||||
# ── Build directories ────────────────────────────────────────────
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "lsp/py_lsp.h"
|
||||
#include "lsp/ts_lsp.h"
|
||||
#include "lsp/cs_lsp.h"
|
||||
#include "lsp/java_lsp.h"
|
||||
#include "preprocessor.h"
|
||||
#include "foundation/compat.h"
|
||||
#include "tree_sitter/api.h" // TSParser, TSNode, TSTree, TSInput, TSLanguage, TSPoint, TSParseOptions, TSParseState
|
||||
@@ -503,6 +504,9 @@ CBMFileResult *cbm_extract_file(const char *source, int source_len, CBMLanguage
|
||||
cbm_run_cs_lsp(a, result, source, source_len, root);
|
||||
}
|
||||
}
|
||||
if (language == CBM_LANG_JAVA) {
|
||||
cbm_run_java_lsp(a, result, source, source_len, root);
|
||||
}
|
||||
atomic_fetch_add(&total_lsp_ns, now_ns() - lsp_start);
|
||||
|
||||
// Calls extracted so far all carry ORIGINAL-source line numbers; the C/C++
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,167 @@
|
||||
#ifndef CBM_LSP_JAVA_LSP_H
|
||||
#define CBM_LSP_JAVA_LSP_H
|
||||
|
||||
/*
|
||||
* java_lsp.h — Pure-C Java semantic resolver.
|
||||
*
|
||||
* Reverse-engineered from JLS §6 (Names) and §15 (Expressions) plus the
|
||||
* algorithm shape used by Eclipse JDT-LS / java-language-server (which both
|
||||
* delegate to javac.com.sun.source). The goal is parity with what JDT-LS
|
||||
* exposes through textDocument/definition + textDocument/references for
|
||||
* call-site resolution, *without* shelling out to javac.
|
||||
*
|
||||
* Mirrors the structure of go_lsp.h / c_lsp.h / php_lsp.h / py_lsp.h.
|
||||
*
|
||||
* Resolution scheme (single file):
|
||||
* 1. Tree-sitter parses Java source into AST.
|
||||
* 2. Build a CBMTypeRegistry from this file's CBMDefinitions + Java
|
||||
* stdlib (java.lang.*, java.util.*, java.io.*, java.util.function.*,
|
||||
* java.util.stream.*).
|
||||
* 3. Walk the AST and for every method_invocation / object_creation /
|
||||
* field_access expression, evaluate the expression's type using
|
||||
* JLS-style scope chains (block → method params → class members →
|
||||
* superclass chain → outer class → import single → import on-demand →
|
||||
* java.lang → same package).
|
||||
* 4. Match the textual call (callee name + arity) against the resolved
|
||||
* receiver type's method set, walking superclasses and interfaces.
|
||||
* Best-overload resolution falls back to argument count match.
|
||||
* 5. Emit CBMResolvedCall entries with confidence ≥ 0.6 (the LSP floor
|
||||
* enforced by lsp_resolve.h).
|
||||
*/
|
||||
|
||||
#include "type_rep.h"
|
||||
#include "scope.h"
|
||||
#include "type_registry.h"
|
||||
#include "../cbm.h"
|
||||
#include "go_lsp.h" /* CBMLSPDef, CBMResolvedCallArray reused across languages */
|
||||
|
||||
/* Java `use`-style import kinds. Mirrors PHP's enum with Java semantics. */
|
||||
enum {
|
||||
CBM_JAVA_IMPORT_TYPE = 0, /* import com.foo.Bar; — type import */
|
||||
CBM_JAVA_IMPORT_STATIC = 1, /* import static com.foo.Bar.method; */
|
||||
CBM_JAVA_IMPORT_ON_DEMAND = 2, /* import com.foo.*; — package on-demand */
|
||||
CBM_JAVA_IMPORT_STATIC_OD = 3, /* import static com.foo.Bar.*; */
|
||||
};
|
||||
|
||||
/* Per-file resolution context. */
|
||||
typedef struct {
|
||||
CBMArena *arena;
|
||||
const char *source;
|
||||
int source_len;
|
||||
const CBMTypeRegistry *registry;
|
||||
CBMScope *current_scope;
|
||||
|
||||
/* Java package — the package declared in the file ("com.example"), or
|
||||
* empty string for the unnamed package. Stored in dotted form. */
|
||||
const char *package_name;
|
||||
|
||||
/* The path-derived module QN for this file (passed in from the caller),
|
||||
* used as the QN prefix for types defined here. */
|
||||
const char *module_qn;
|
||||
|
||||
/* Import map. Each entry is one of CBM_JAVA_IMPORT_*.
|
||||
* - TYPE: local_name="Bar", target_qn="com.foo.Bar"
|
||||
* - STATIC: local_name="sqrt", target_qn="java.lang.Math.sqrt"
|
||||
* - ON_DEMAND: local_name="*", target_qn="com.foo"
|
||||
* - STATIC_OD: local_name="*", target_qn="java.lang.Math"
|
||||
*/
|
||||
const char **import_local_names;
|
||||
const char **import_target_qns;
|
||||
int *import_kinds;
|
||||
int import_count;
|
||||
int import_cap;
|
||||
|
||||
/* Current enclosing context. */
|
||||
const char *enclosing_method_qn; /* QN of the nearest method/ctor */
|
||||
const char *enclosing_class_qn; /* QN of the nearest class/interface/enum */
|
||||
const char *enclosing_super_qn; /* QN of the immediate superclass (NULL ⇒ Object) */
|
||||
const char *enclosing_class_short; /* short name of enclosing class — for "this" + ctor */
|
||||
const char **enclosing_class_stack; /* nested-class stack (enclosing_class_qn at each depth) */
|
||||
int enclosing_class_depth;
|
||||
int enclosing_class_cap;
|
||||
|
||||
/* Output: resolved + diagnostic call edges. */
|
||||
CBMResolvedCallArray *resolved_calls;
|
||||
|
||||
/* Recursion guards. */
|
||||
int eval_depth;
|
||||
int statement_depth;
|
||||
|
||||
/* Debug mode (CBM_LSP_DEBUG env). */
|
||||
bool debug;
|
||||
} JavaLSPContext;
|
||||
|
||||
/* ── Initialization / configuration ───────────────────────────────── */
|
||||
|
||||
void java_lsp_init(JavaLSPContext *ctx, CBMArena *arena, const char *source, int source_len,
|
||||
const CBMTypeRegistry *registry, const char *package_name,
|
||||
const char *module_qn, CBMResolvedCallArray *out);
|
||||
|
||||
void java_lsp_add_import(JavaLSPContext *ctx, const char *local_name, const char *target_qn,
|
||||
int kind);
|
||||
|
||||
/* ── Walking / resolution ─────────────────────────────────────────── */
|
||||
|
||||
void java_lsp_process_file(JavaLSPContext *ctx, TSNode root);
|
||||
|
||||
/* Evaluate the type of an arbitrary Java expression node. May return
|
||||
* cbm_type_unknown(); never returns NULL. */
|
||||
const CBMType *java_eval_expr_type(JavaLSPContext *ctx, TSNode node);
|
||||
|
||||
/* Convert a Java type AST node (type_identifier, generic_type, array_type,
|
||||
* scoped_type_identifier, void_type, integral_type, ...) into a CBMType. */
|
||||
const CBMType *java_parse_type_node(JavaLSPContext *ctx, TSNode node);
|
||||
|
||||
/* Process a Java statement, binding any declared variables/parameters into
|
||||
* the current scope. */
|
||||
void java_process_statement(JavaLSPContext *ctx, TSNode node);
|
||||
|
||||
/* Resolve a Java type name (bare or qualified) against the current scope
|
||||
* (imports + java.lang + same package). Returns the registered FQN or NULL. */
|
||||
const char *java_resolve_type_name(JavaLSPContext *ctx, const char *name);
|
||||
|
||||
/* Lookup a method on a class, walking the super-chain and implemented
|
||||
* interfaces. Returns the matched function or NULL. */
|
||||
const CBMRegisteredFunc *java_lookup_method(JavaLSPContext *ctx, const char *class_qn,
|
||||
const char *method_name, int arg_count);
|
||||
|
||||
/* Lookup a field on a class, walking the super-chain. Returns the field's
|
||||
* type, or cbm_type_unknown() on miss. */
|
||||
const CBMType *java_lookup_field_type(JavaLSPContext *ctx, const char *class_qn,
|
||||
const char *field_name);
|
||||
|
||||
/* ── Top-level entry points ───────────────────────────────────────── */
|
||||
|
||||
/* Single-file LSP: build registry from file defs + stdlib, walk and resolve. */
|
||||
void cbm_run_java_lsp(CBMArena *arena, CBMFileResult *result, const char *source, int source_len,
|
||||
TSNode root);
|
||||
|
||||
/* Cross-file LSP: build registry from defs + stdlib, re-parse if needed,
|
||||
* walk and resolve. defs include both local + cross-file definitions. */
|
||||
void cbm_run_java_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, CBMResolvedCallArray *out);
|
||||
|
||||
/* Register the Java standard library (java.lang/util/io/etc.) into reg.
|
||||
* Implementation lives in generated/java_stdlib_data.c. */
|
||||
void cbm_java_stdlib_register(CBMTypeRegistry *reg, CBMArena *arena);
|
||||
|
||||
/* ── Batch cross-file LSP ─────────────────────────────────────────── */
|
||||
|
||||
typedef struct {
|
||||
const char *source;
|
||||
int source_len;
|
||||
const char *module_qn;
|
||||
TSTree *cached_tree;
|
||||
CBMLSPDef *defs;
|
||||
int def_count;
|
||||
const char **import_names;
|
||||
const char **import_qns;
|
||||
int import_count;
|
||||
} CBMBatchJavaLSPFile;
|
||||
|
||||
void cbm_batch_java_lsp_cross(CBMArena *arena, CBMBatchJavaLSPFile *files, int file_count,
|
||||
CBMResolvedCallArray *out);
|
||||
|
||||
#endif /* CBM_LSP_JAVA_LSP_H */
|
||||
@@ -17,3 +17,5 @@
|
||||
#include "lsp/ts_lsp.c"
|
||||
#include "lsp/cs_lsp.c"
|
||||
#include "lsp/generated/cs_stdlib_data.c"
|
||||
#include "lsp/java_lsp.c"
|
||||
#include "lsp/generated/java_stdlib_data.c"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -52,6 +52,8 @@ extern void suite_py_lsp_bench(void);
|
||||
extern void suite_py_lsp_stress(void);
|
||||
extern void suite_py_lsp_scale(void);
|
||||
extern void suite_ts_lsp(void);
|
||||
extern void suite_java_lsp(void);
|
||||
extern void suite_java_lsp_coverage(void);
|
||||
extern void suite_store_arch(void);
|
||||
extern void suite_store_bulk(void);
|
||||
extern void suite_store_pragmas(void);
|
||||
@@ -141,6 +143,8 @@ int main(void) {
|
||||
RUN_SUITE(py_lsp_stress);
|
||||
RUN_SUITE(py_lsp_scale);
|
||||
RUN_SUITE(ts_lsp);
|
||||
RUN_SUITE(java_lsp);
|
||||
RUN_SUITE(java_lsp_coverage);
|
||||
|
||||
/* Architecture + ADR + Louvain */
|
||||
RUN_SUITE(store_arch);
|
||||
|
||||
Reference in New Issue
Block a user