mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-03 08:03:38 +08:00
Merge pull request #1940 from ilyabrykau-orca/fix/go-struct-fields
fix(extract): descend into Go struct field_declaration_list
This commit is contained in:
@@ -4780,6 +4780,20 @@ static TSNode find_class_member_body(TSNode class_node, CBMLanguage lang) {
|
|||||||
return ts_node_is_null(declarations) ? body : declarations;
|
return ts_node_is_null(declarations) ? body : declarations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Go structs keep their field_declaration nodes one level below the body that
|
||||||
|
* find_class_body() returns: type_spec's `type` child is a struct_type whose
|
||||||
|
* only named child is a field_declaration_list. Interfaces need no such step --
|
||||||
|
* interface_type holds its method specs directly, which is why interface members
|
||||||
|
* extracted correctly while every struct field was silently skipped. Normalize
|
||||||
|
* here, the same way the Java enum_body_declarations step above does. */
|
||||||
|
static TSNode go_normalize_struct_body(TSNode body) {
|
||||||
|
if (ts_node_is_null(body) || strcmp(ts_node_type(body), "struct_type") != 0) {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
TSNode list = cbm_find_child_by_kind(body, "field_declaration_list");
|
||||||
|
return ts_node_is_null(list) ? body : list;
|
||||||
|
}
|
||||||
|
|
||||||
// Dart: resolve method name from method_signature/function_signature.
|
// Dart: resolve method name from method_signature/function_signature.
|
||||||
static TSNode resolve_dart_method_name(TSNode child, const char *ck) {
|
static TSNode resolve_dart_method_name(TSNode child, const char *ck) {
|
||||||
if (strcmp(ck, "method_signature") == 0) {
|
if (strcmp(ck, "method_signature") == 0) {
|
||||||
@@ -6656,6 +6670,9 @@ static void extract_class_fields(CBMExtractCtx *ctx, TSNode class_node, const ch
|
|||||||
}
|
}
|
||||||
|
|
||||||
TSNode body = find_class_member_body(class_node, ctx->language);
|
TSNode body = find_class_member_body(class_node, ctx->language);
|
||||||
|
if (ctx->language == CBM_LANG_GO) {
|
||||||
|
body = go_normalize_struct_body(body);
|
||||||
|
}
|
||||||
if (ts_node_is_null(body)) {
|
if (ts_node_is_null(body)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -6945,6 +6962,13 @@ static void extract_class_fields(CBMExtractCtx *ctx, TSNode class_node, const ch
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Go: `_` is the blank identifier, used for explicit struct padding in
|
||||||
|
* generated code. It is not a referenceable field, and emitting it gives
|
||||||
|
* every `_` in the repository a same-named node to collide with. */
|
||||||
|
if (ctx->language == CBM_LANG_GO && strcmp(name, "_") == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const char *field_qn = cbm_arena_sprintf(a, "%s.%s", class_qn, name);
|
const char *field_qn = cbm_arena_sprintf(a, "%s.%s", class_qn, name);
|
||||||
|
|
||||||
CBMDefinition def;
|
CBMDefinition def;
|
||||||
|
|||||||
@@ -3015,6 +3015,59 @@ TEST(go_imports) {
|
|||||||
PASS();
|
PASS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* #1935: Go struct fields were never extracted — find_class_body() returns the
|
||||||
|
* struct_type node, whose only named child is a field_declaration_list, so the
|
||||||
|
* member loop matched nothing and every field was silently skipped (0 Field
|
||||||
|
* nodes for ~5055 declarations on the measured repo). Interfaces hold their
|
||||||
|
* method specs directly and always worked. The blank identifier `_` is struct
|
||||||
|
* padding, not a referenceable field, and must stay out (241 collision edges
|
||||||
|
* on two generated structs otherwise). */
|
||||||
|
TEST(extract_go_struct_fields_have_nodes) {
|
||||||
|
CBMFileResult *r = extract("package fxf\n\n"
|
||||||
|
"type Config struct {\n"
|
||||||
|
"\tName string\n"
|
||||||
|
"\tTimeout int\n"
|
||||||
|
"\tNested *Config\n"
|
||||||
|
"\t_ [8]byte\n"
|
||||||
|
"}\n\n"
|
||||||
|
"type Reader interface {\n"
|
||||||
|
"\tRead(p []byte) (int, error)\n"
|
||||||
|
"\tClose() error\n"
|
||||||
|
"}\n",
|
||||||
|
CBM_LANG_GO, "t", "cfg.go");
|
||||||
|
ASSERT_NOT_NULL(r);
|
||||||
|
ASSERT_FALSE(r->has_error);
|
||||||
|
/* RED before the descend fix: count is 0. The blank identifier must not
|
||||||
|
* bring it to 4. */
|
||||||
|
ASSERT_EQ(count_defs_with_label(r, "Field"), 3);
|
||||||
|
ASSERT_TRUE(has_def(r, "Field", "Name"));
|
||||||
|
ASSERT_TRUE(has_def(r, "Field", "Timeout"));
|
||||||
|
ASSERT_TRUE(has_def(r, "Field", "Nested"));
|
||||||
|
ASSERT_FALSE(has_def(r, "Field", "_"));
|
||||||
|
/* Each field carries its declared type in return_type. */
|
||||||
|
for (int i = 0; i < r->defs.count; i++) {
|
||||||
|
const CBMDefinition *d = &r->defs.items[i];
|
||||||
|
if (!d->label || strcmp(d->label, "Field") != 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ASSERT_NOT_NULL(d->return_type);
|
||||||
|
if (strcmp(d->name, "Name") == 0) {
|
||||||
|
ASSERT_TRUE(strcmp(d->return_type, "string") == 0);
|
||||||
|
}
|
||||||
|
if (strcmp(d->name, "Timeout") == 0) {
|
||||||
|
ASSERT_TRUE(strcmp(d->return_type, "int") == 0);
|
||||||
|
}
|
||||||
|
if (strcmp(d->name, "Nested") == 0) {
|
||||||
|
ASSERT_TRUE(strcmp(d->return_type, "*Config") == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Interface members keep extracting exactly as before. */
|
||||||
|
ASSERT_TRUE(has_def(r, "Method", "Read"));
|
||||||
|
ASSERT_TRUE(has_def(r, "Method", "Close"));
|
||||||
|
cbm_free_result(r);
|
||||||
|
PASS();
|
||||||
|
}
|
||||||
|
|
||||||
TEST(java_imports) {
|
TEST(java_imports) {
|
||||||
CBMFileResult *r = extract(
|
CBMFileResult *r = extract(
|
||||||
"import java.util.List;\nimport java.util.ArrayList;\nimport static java.lang.Math.PI;\n"
|
"import java.util.List;\nimport java.util.ArrayList;\nimport static java.lang.Math.PI;\n"
|
||||||
@@ -6699,6 +6752,7 @@ SUITE(extraction) {
|
|||||||
RUN_TEST(python_imports);
|
RUN_TEST(python_imports);
|
||||||
RUN_TEST(js_imports);
|
RUN_TEST(js_imports);
|
||||||
RUN_TEST(go_imports);
|
RUN_TEST(go_imports);
|
||||||
|
RUN_TEST(extract_go_struct_fields_have_nodes);
|
||||||
RUN_TEST(java_imports);
|
RUN_TEST(java_imports);
|
||||||
RUN_TEST(rust_imports);
|
RUN_TEST(rust_imports);
|
||||||
RUN_TEST(c_imports);
|
RUN_TEST(c_imports);
|
||||||
|
|||||||
Reference in New Issue
Block a user