Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 53 additions & 2 deletions internal/cbm/cbm.c
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,47 @@ void cbm_rw_push(CBMRWArray *arr, CBMArena *a, CBMReadWrite rw) {
arr->items[arr->count++] = rw;
}

static bool def_label_is_preprocessed_callable(const char *label) {
return label && (strcmp(label, "Function") == 0 || strcmp(label, "Method") == 0);
}

static bool result_has_same_def_identity(const CBMFileResult *result, const CBMDefinition *def) {
if (!result || !def || !def->label || !def->qualified_name) {
return false;
}
for (int i = 0; i < result->defs.count; i++) {
const CBMDefinition *cur = &result->defs.items[i];
if (!cur->label || !cur->qualified_name) {
continue;
}
if (strcmp(cur->label, def->label) == 0 &&
strcmp(cur->qualified_name, def->qualified_name) == 0) {
return true;
}
}
return false;
}

static void merge_missing_preprocessed_callables(CBMFileResult *dst, const CBMFileResult *src,
CBMArena *arena) {
if (!dst || !src) {
return;
}
for (int i = 0; i < src->defs.count; i++) {
const CBMDefinition *def = &src->defs.items[i];
if (!def->qualified_name || !def->name) {
continue;
}
if (!def_label_is_preprocessed_callable(def->label)) {
continue;
}
if (result_has_same_def_identity(dst, def)) {
continue;
}
cbm_defs_push(&dst->defs, arena, *def);
}
}

void cbm_typerefs_push(CBMTypeRefArray *arr, CBMArena *a, CBMTypeRef tr) {
GROW_ARRAY(arr, a);
arr->items[arr->count++] = tr;
Expand Down Expand Up @@ -879,8 +920,10 @@ static CBMFileResult *cbm_extract_file_impl(const char *source, int source_len,
// metrics. Remember the boundary.
int orig_calls_count = result->calls.count;

// Second pass: preprocess C/C++/CUDA and extract additional macro-hidden calls.
// Defs keep original-source line numbers; only CALLS are extracted from expanded source.
// Second pass: preprocess C/C++/CUDA and extract additional macro-hidden
// callables/calls. Existing defs keep original-source line numbers; only
// callables missing from the raw tree-sitter pass are filled from expanded
// source so #ifdef/#else signature blocks cannot swallow later methods.
if (language == CBM_LANG_C || language == CBM_LANG_CPP || language == CBM_LANG_CUDA) {
uint64_t pp_start = now_ns();
char *expanded = cbm_preprocess(source, source_len, rel_path, extra_defines, include_paths,
Expand Down Expand Up @@ -919,6 +962,14 @@ static CBMFileResult *cbm_extract_file_impl(const char *source, int source_len,
.module_qn = result->module_qn,
.root = pp_root,
};
CBMFileResult pp_defs_result = {0};
pp_defs_result.module_qn = result->module_qn;
pp_defs_result.is_test_file = result->is_test_file;
CBMExtractCtx pp_defs_ctx = pp_ctx;
pp_defs_ctx.result = &pp_defs_result;
cbm_extract_definition_nodes(&pp_defs_ctx);
merge_missing_preprocessed_callables(result, &pp_defs_result, a);

// Re-run unified extraction on expanded source.
// This adds macro-expanded calls; duplicates with original calls are
// harmless (pipeline deduplicates by caller+callee).
Expand Down
2 changes: 2 additions & 0 deletions internal/cbm/cbm.h
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,8 @@ void cbm_channels_push(CBMChannelArray *arr, CBMArena *a, CBMChannel ch);
// --- Sub-extractor entry points ---

void cbm_extract_definitions(CBMExtractCtx *ctx);
// Run only the definition walker: no Module node and no variable extraction.
void cbm_extract_definition_nodes(CBMExtractCtx *ctx);
void cbm_extract_imports(CBMExtractCtx *ctx);
void cbm_extract_usages(CBMExtractCtx *ctx);
void cbm_extract_semantic(CBMExtractCtx *ctx);
Expand Down
8 changes: 8 additions & 0 deletions internal/cbm/extract_defs.c
Original file line number Diff line number Diff line change
Expand Up @@ -6396,3 +6396,11 @@ void cbm_extract_definitions(CBMExtractCtx *ctx) {
// Extract module-level variables
extract_variables(ctx, ctx->root, spec);
}

void cbm_extract_definition_nodes(CBMExtractCtx *ctx) {
const CBMLangSpec *spec = cbm_lang_spec(ctx->language);
if (!spec) {
return;
}
walk_defs(ctx, ctx->root, spec, 0);
}
47 changes: 47 additions & 0 deletions tests/test_extraction.c
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,52 @@ TEST(cpp_out_of_line_method_issue428) {
PASS();
}

/* #946: C++ code commonly gates alternate out-of-line method signatures with
* #ifdef/#else/#endif. Raw tree-sitter can mis-balance the duplicate opening
* braces and lose methods that follow the conditional block; extraction must
* still recover later methods from the translation unit. */
TEST(cpp_preproc_signature_gap_issue946) {
CBMFileResult *r =
extract("struct Rect {};\n"
"struct IBinder {};\n"
"struct IRegionSamplingListener {};\n"
"typedef int status_t;\n"
"\n"
"class SurfaceFlinger {\n"
"public:\n"
" status_t addRegionSamplingListener(const Rect&, const IBinder&,\n"
" const IRegionSamplingListener&, bool);\n"
" status_t addRegionSamplingListener(const Rect&, const IBinder&,\n"
" const IRegionSamplingListener&);\n"
" void commit();\n"
" void composite();\n"
"};\n"
"\n"
"#ifdef FLYME_GRAPHICS_EXTEND_LUMARGB\n"
"status_t SurfaceFlinger::addRegionSamplingListener(const Rect& samplingArea,\n"
" const IBinder& stopLayerHandle,\n"
" const IRegionSamplingListener& listener,\n"
" const bool rgbSample) {\n"
"#else\n"
"status_t SurfaceFlinger::addRegionSamplingListener(const Rect& samplingArea,\n"
" const IBinder& stopLayerHandle,\n"
" const IRegionSamplingListener& listener) {\n"
"#endif\n"
" return 0;\n"
"}\n"
"\n"
"void SurfaceFlinger::commit() {}\n"
"\n"
"void SurfaceFlinger::composite() {}\n",
CBM_LANG_CPP, "t", "SurfaceFlinger.cpp");
ASSERT_NOT_NULL(r);
ASSERT_FALSE(r->has_error);
ASSERT(has_def(r, "Method", "commit"));
ASSERT(has_def(r, "Method", "composite"));
cbm_free_result(r);
PASS();
}

/* --- COBOL paragraph --- */
TEST(cobol_paragraph) {
CBMFileResult *r =
Expand Down Expand Up @@ -3601,6 +3647,7 @@ SUITE(extraction) {
RUN_TEST(zig_struct);
RUN_TEST(cpp_function);
RUN_TEST(cpp_out_of_line_method_issue428);
RUN_TEST(cpp_preproc_signature_gap_issue946);
RUN_TEST(cobol_paragraph);
RUN_TEST(verilog_module);
RUN_TEST(cuda_kernel);
Expand Down
Loading