mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-04 10:48:20 +00:00
fix(csharp): preserve escaped constructors and conditional extension members
Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This commit is contained in:
1 parent
5e6b1bb3f6
commit
7028640495
2 files changed
+62
-7
No files matched your search
@@ -8943,9 +8943,15 @@ static bool csharp_is_extension_block(TSNode node, TSNode class_node, const char
|
||||
}
|
||||
TSNode type_name = ts_node_child_by_field_name(class_node, TS_FIELD("name"));
|
||||
if (!ts_node_is_null(type_name)) {
|
||||
const char *type_text = source + ts_node_start_byte(type_name);
|
||||
uint32_t tlen = ts_node_end_byte(type_name) - ts_node_start_byte(type_name);
|
||||
if (tlen == kw_len &&
|
||||
strncmp(source + ts_node_start_byte(type_name), "extension", kw_len) == 0) {
|
||||
/* A verbatim identifier names the same type: class @extension may
|
||||
* declare a genuine constructor spelled extension(). */
|
||||
if (tlen > 0 && type_text[0] == '@') {
|
||||
type_text++;
|
||||
tlen--;
|
||||
}
|
||||
if (tlen == kw_len && strncmp(type_text, "extension", kw_len) == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -8963,11 +8969,11 @@ static void extract_csharp_extension_members(CBMExtractCtx *ctx, TSNode ext_node
|
||||
if (ts_node_is_null(body)) {
|
||||
return;
|
||||
}
|
||||
uint32_t count = ts_node_child_count(body);
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
TSNode member = ts_node_child(body, i);
|
||||
if (ts_node_is_null(member) ||
|
||||
strcmp(ts_node_type(member), "local_function_statement") != 0) {
|
||||
member_iter_t it;
|
||||
member_iter_init(&it, body, ctx->language, false);
|
||||
TSNode member;
|
||||
while (member_iter_next(&it, &member)) {
|
||||
if (strcmp(ts_node_type(member), "local_function_statement") != 0) {
|
||||
continue;
|
||||
}
|
||||
TSNode name = resolve_method_name(member, ctx->language);
|
||||
@@ -8976,6 +8982,7 @@ static void extract_csharp_extension_members(CBMExtractCtx *ctx, TSNode ext_node
|
||||
}
|
||||
push_method_def(ctx, member, class_node, class_qn, spec, name);
|
||||
}
|
||||
member_iter_done(&it);
|
||||
}
|
||||
|
||||
// Extract methods inside a class body
|
||||
|
||||
@@ -916,6 +916,52 @@ TEST(csharp_constructor_of_type_named_extension) {
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* Escaping a type identifier does not change its constructor's identity. */
|
||||
TEST(csharp_constructor_of_escaped_type_named_extension) {
|
||||
const char *src = "namespace App { public class @extension { "
|
||||
"public extension() { int ConstructorLocal() => 1; } } }";
|
||||
CBMFileResult *r = extract(src, CBM_LANG_CSHARP, "t", "extension.cs");
|
||||
ASSERT_NOT_NULL(r);
|
||||
ASSERT_FALSE(r->has_error);
|
||||
ASSERT(has_def(r, "Method", "extension"));
|
||||
ASSERT_FALSE(has_def(r, "Method", "ConstructorLocal"));
|
||||
cbm_free_result(r);
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* All conditional branches expose extension members, but method-local
|
||||
* functions must never be promoted to members of the enclosing type. */
|
||||
TEST(csharp_extension_block_conditional_members) {
|
||||
const char *src = "public static class TextExtensions\n"
|
||||
"{\n"
|
||||
" extension(string text)\n"
|
||||
" {\n"
|
||||
"#if FIRST\n"
|
||||
" public int First() { int Nested() => 1; return Nested(); }\n"
|
||||
"#elif SECOND\n"
|
||||
" public int Second() => 2;\n"
|
||||
"#else\n"
|
||||
"#if NESTED\n"
|
||||
" public int Third() => 3;\n"
|
||||
"#else\n"
|
||||
" public int Fourth() => 4;\n"
|
||||
"#endif\n"
|
||||
"#endif\n"
|
||||
" }\n"
|
||||
"}\n";
|
||||
CBMFileResult *r = extract(src, CBM_LANG_CSHARP, "t", "TextExtensions.cs");
|
||||
ASSERT_NOT_NULL(r);
|
||||
ASSERT_FALSE(r->has_error);
|
||||
ASSERT(has_def(r, "Method", "First"));
|
||||
ASSERT(has_def(r, "Method", "Second"));
|
||||
ASSERT(has_def(r, "Method", "Third"));
|
||||
ASSERT(has_def(r, "Method", "Fourth"));
|
||||
ASSERT_FALSE(has_def_any(r, "extension"));
|
||||
ASSERT_FALSE(has_def(r, "Method", "Nested"));
|
||||
cbm_free_result(r);
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* --- Swift --- */
|
||||
TEST(swift_class) {
|
||||
CBMFileResult *r = extract("class Vehicle {\n var speed: Int = 0\n func accelerate() { "
|
||||
@@ -13195,6 +13241,8 @@ SUITE(extraction) {
|
||||
RUN_TEST(csharp_interface);
|
||||
RUN_TEST(csharp_extension_block_members);
|
||||
RUN_TEST(csharp_constructor_of_type_named_extension);
|
||||
RUN_TEST(csharp_constructor_of_escaped_type_named_extension);
|
||||
RUN_TEST(csharp_extension_block_conditional_members);
|
||||
RUN_TEST(swift_class);
|
||||
RUN_TEST(swift_protocol);
|
||||
RUN_TEST(kotlin_function);
|
||||
|
||||
Reference in new issue
Block a user