mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-10-28 07:03:20 +08:00
Merge pull request #771 from apappas1129/fix/767-imports-import-targetable-label
fix(pipeline): reject non-file-like IMPORTS targets in fallback strategies
This commit is contained in:
@@ -1328,8 +1328,9 @@ static const cbm_gbuf_node_t *resolve_sibling_file(const cbm_pipeline_ctx_t *ctx
|
||||
}
|
||||
const cbm_gbuf_node_t *n = cbm_gbuf_find_by_qn(ctx->gbuf, qn);
|
||||
free(qn);
|
||||
if (n && (!source_file_qn || !n->qualified_name ||
|
||||
strcmp(n->qualified_name, source_file_qn) != 0)) {
|
||||
if (n && import_targetable_label(n->label) &&
|
||||
(!source_file_qn || !n->qualified_name ||
|
||||
strcmp(n->qualified_name, source_file_qn) != 0)) {
|
||||
found = n;
|
||||
break;
|
||||
}
|
||||
@@ -1347,7 +1348,13 @@ const cbm_gbuf_node_t *cbm_pipeline_resolve_import_node(const cbm_pipeline_ctx_t
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Strategy 1: module-path resolution → existing node (Python/TS/Go). */
|
||||
/* Strategy 1: module-path resolution → existing node (Python/TS/Go).
|
||||
* No label filter here: directory-module languages (Go/Java packages)
|
||||
* legitimately resolve straight to a Folder node -- that's the intended,
|
||||
* correct import target, not a collision. The Folder-collision problem
|
||||
* (#767) only shows up downstream, in Strategy 4's retry-with-truncated-
|
||||
* path loop, which re-enters resolve_module with a DIFFERENT, shortened
|
||||
* string that the original import never named. */
|
||||
char *target_qn = cbm_pipeline_resolve_module(ctx, source_rel, imp->module_path);
|
||||
const cbm_gbuf_node_t *target = target_qn ? cbm_gbuf_find_by_qn(ctx->gbuf, target_qn) : NULL;
|
||||
free(target_qn);
|
||||
@@ -1571,8 +1578,9 @@ const cbm_gbuf_node_t *cbm_pipeline_resolve_import_node(const cbm_pipeline_ctx_t
|
||||
char *rqn = cbm_pipeline_resolve_module(ctx, source_rel, work);
|
||||
const cbm_gbuf_node_t *n = rqn ? cbm_gbuf_find_by_qn(ctx->gbuf, rqn) : NULL;
|
||||
free(rqn);
|
||||
if (n && (!source_file_qn || !n->qualified_name ||
|
||||
strcmp(n->qualified_name, source_file_qn) != 0)) {
|
||||
if (n && import_targetable_label(n->label) &&
|
||||
(!source_file_qn || !n->qualified_name ||
|
||||
strcmp(n->qualified_name, source_file_qn) != 0)) {
|
||||
return n;
|
||||
}
|
||||
char *sl = strrchr(work, '/');
|
||||
|
||||
@@ -1158,6 +1158,50 @@ TEST(contract_edge_workspaces_imports_issue408) {
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* #767: a wildcard tsconfig alias for the "@lib" prefix (mapped to ./src/lib)
|
||||
* shares that prefix with an unrelated scoped npm package ("@lib/external-pkg",
|
||||
* meant to resolve normally from node_modules). The engine has no such file
|
||||
* and must NOT invent an edge to the "src/lib" Folder node via a later
|
||||
* fallback strategy that re-tries the truncated "@lib" prefix against the
|
||||
* tsconfig's other, bare alias entry. Zero IMPORTS edges in the whole project
|
||||
* is the correct outcome: the same as any other unresolved external import. */
|
||||
TEST(contract_edge_imports_alias_no_phantom_folder_edge_issue767) {
|
||||
LangProj lp;
|
||||
static const LangFile f[] = {
|
||||
{"tsconfig.json", "{\n \"compilerOptions\": {\n \"paths\": {\n"
|
||||
" \"@lib\": [\"./src/lib\"],\n"
|
||||
" \"@lib/*\": [\"./src/lib/*\"]\n }\n }\n}\n"},
|
||||
{"src/lib/thing.ts", "export const Thing = {};\n"},
|
||||
{"src/consumer.ts",
|
||||
"import { ClientC } from '@lib/external-pkg';\n\n"
|
||||
"export function useClient() {\n return new ClientC();\n}\n"}};
|
||||
cbm_store_t *store = lang_index_files(&lp, f, 3);
|
||||
int got = store ? cbm_store_count_edges_by_type(store, lp.project, "IMPORTS") : -1;
|
||||
if (got != 0) {
|
||||
fprintf(stderr, " [EDGE] FAIL IMPORTS count=%d expected=0 (phantom Folder edge)\n", got);
|
||||
}
|
||||
ASSERT_EQ(got, 0);
|
||||
lang_cleanup(&lp, store);
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* #767 regression guard: a wildcard tsconfig alias resolving to a REAL,
|
||||
* indexed file must still produce its IMPORTS edge — the import-targetable
|
||||
* label filter must reject Folder/Project/etc. matches without rejecting
|
||||
* legitimate File/Module matches. */
|
||||
TEST(contract_edge_imports_alias_resolves_real_file_issue767) {
|
||||
static const LangFile f[] = {
|
||||
{"tsconfig.json", "{\n \"compilerOptions\": {\n \"paths\": {\n"
|
||||
" \"@lib\": [\"./src/lib\"],\n"
|
||||
" \"@lib/*\": [\"./src/lib/*\"]\n }\n }\n}\n"},
|
||||
{"src/lib/thing.ts", "export const Thing = {};\n"},
|
||||
{"src/consumer.ts",
|
||||
"import { Thing } from '@lib/thing';\n\n"
|
||||
"export function useThing() {\n return Thing;\n}\n"}};
|
||||
ASSERT_TRUE(edge_present(f, 3, "IMPORTS", 1));
|
||||
PASS();
|
||||
}
|
||||
|
||||
/* DEPENDS_ON — Helm Chart.yaml `dependencies:` -> per-dependency Chart node.
|
||||
* Basename must be exactly "Chart.yaml"; pass_k8s runs in both pipeline paths. */
|
||||
TEST(contract_edge_depends_on) {
|
||||
@@ -1365,6 +1409,8 @@ SUITE(lang_contract) {
|
||||
* FILE_CHANGES_WITH (git co-change). Completes 25-edge-type coverage. */
|
||||
RUN_TEST(contract_edge_tests);
|
||||
RUN_TEST(contract_edge_workspaces_imports_issue408);
|
||||
RUN_TEST(contract_edge_imports_alias_no_phantom_folder_edge_issue767);
|
||||
RUN_TEST(contract_edge_imports_alias_resolves_real_file_issue767);
|
||||
RUN_TEST(contract_edge_depends_on);
|
||||
RUN_TEST(contract_edge_parallel_service_edges);
|
||||
RUN_TEST(contract_edge_file_changes_with);
|
||||
|
||||
Reference in New Issue
Block a user