mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-11-04 10:48:20 +00:00
fix(doc-links): the C# scope reads what the parse view hid
The parse view keeps one branch of each #if, which is enough for the graph's nodes. The scope read that same tree, so a namespace or a type another branch names differently looked placed and complete. A reference valid in the other build was then reported as doc rot, where it used to be a graph gap. When the view hid a branch, keep the file's own parse for the scope. A view that only blanked `ref` hides nothing and stays in use. RED: doc_mentions_cs_scope_parse_errors, doc_mentions_resolver_parse_errors. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
This commit is contained in:
1 parent
0774ecde2a
commit
0fc6bdcb84
3 files changed
+40
-11
No files matched your search
+23
-7
@@ -1098,7 +1098,7 @@ static uint64_t parse_error_bytes(TSTree *tree) {
|
||||
* taking every type it declares with it. This view has the same length and the same
|
||||
* lines: conditional directives and the branches after a file's first one are blank,
|
||||
* and so is that `ref`. Only a file the grammar could not otherwise read uses it. */
|
||||
static char *csharp_parse_view(const char *source, uint32_t length) {
|
||||
static char *csharp_parse_view(const char *source, uint32_t length, bool *hid_branch) {
|
||||
enum { MAX_DEPTH = 64 };
|
||||
char *view = cbm_alloc(CBM_MEM_CLASS_EXTRACT, (size_t)length + 1);
|
||||
if (!view)
|
||||
@@ -1122,7 +1122,7 @@ static char *csharp_parse_view(const char *source, uint32_t length) {
|
||||
if (opens && depth < MAX_DEPTH)
|
||||
inactive[depth++] = false;
|
||||
else if (switches && depth > 0)
|
||||
inactive[depth - 1] = true;
|
||||
*hid_branch = inactive[depth - 1] = true;
|
||||
else if (closes && depth > 0)
|
||||
depth--;
|
||||
bool hidden = false;
|
||||
@@ -1153,12 +1153,14 @@ static char *csharp_parse_view(const char *source, uint32_t length) {
|
||||
return view;
|
||||
}
|
||||
|
||||
TSTree *cbm_parse_source_repairing(TSParser *parser, CBMLanguage language, const char *source,
|
||||
uint32_t source_len, TSParseOptions opts) {
|
||||
TSTree *cbm_parse_source_repairing_ex(TSParser *parser, CBMLanguage language, const char *source,
|
||||
uint32_t source_len, TSParseOptions opts,
|
||||
TSTree **unrepaired) {
|
||||
TSTree *tree = cbm_parse_source(parser, source, source_len, opts);
|
||||
if (!tree || language != CBM_LANG_CSHARP || !ts_node_has_error(ts_tree_root_node(tree)))
|
||||
return tree;
|
||||
char *view = csharp_parse_view(source, source_len);
|
||||
bool hid_branch = false;
|
||||
char *view = csharp_parse_view(source, source_len, &hid_branch);
|
||||
if (!view)
|
||||
return tree;
|
||||
ts_parser_reset(parser);
|
||||
@@ -1167,13 +1169,21 @@ TSTree *cbm_parse_source_repairing(TSParser *parser, CBMLanguage language, const
|
||||
if (!repaired)
|
||||
return tree;
|
||||
if (parse_error_bytes(repaired) < parse_error_bytes(tree)) {
|
||||
ts_tree_delete(tree);
|
||||
if (unrepaired && hid_branch)
|
||||
*unrepaired = tree;
|
||||
else
|
||||
ts_tree_delete(tree);
|
||||
return repaired;
|
||||
}
|
||||
ts_tree_delete(repaired);
|
||||
return tree;
|
||||
}
|
||||
|
||||
TSTree *cbm_parse_source_repairing(TSParser *parser, CBMLanguage language, const char *source,
|
||||
uint32_t source_len, TSParseOptions opts) {
|
||||
return cbm_parse_source_repairing_ex(parser, language, source, source_len, opts, NULL);
|
||||
}
|
||||
|
||||
static CBM_TLS TSParser *tl_parser = NULL;
|
||||
static CBM_TLS CBMLanguage tl_parser_lang = CBM_LANG_COUNT; // invalid sentinel
|
||||
|
||||
@@ -4367,10 +4377,12 @@ static CBMFileResult *extract_file_ex_body(const char *source, int source_len, C
|
||||
cbm_sql_values_kept_ranges(source, (uint32_t)source_len, &sql_kept) &&
|
||||
ts_parser_set_included_ranges(parser, sql_kept.items, sql_kept.count);
|
||||
bool c_family = language == CBM_LANG_C || language == CBM_LANG_CPP || language == CBM_LANG_CUDA;
|
||||
TSTree *unrepaired = NULL;
|
||||
TSTree *tree =
|
||||
c_family
|
||||
? cbm_parse_c_source_defined(parser, source, (uint32_t)source_len, opts, extra_defines)
|
||||
: cbm_parse_source_repairing(parser, language, source, (uint32_t)source_len, opts);
|
||||
: cbm_parse_source_repairing_ex(parser, language, source, (uint32_t)source_len, opts,
|
||||
&unrepaired);
|
||||
if (sql_ranged) {
|
||||
(void)ts_parser_set_included_ranges(parser, NULL, 0);
|
||||
}
|
||||
@@ -4444,6 +4456,7 @@ static CBMFileResult *extract_file_ex_body(const char *source, int source_len, C
|
||||
.rel_path = rel_path,
|
||||
.module_qn = result->module_qn,
|
||||
.root = root,
|
||||
.unrepaired_root = unrepaired ? ts_tree_root_node(unrepaired) : (TSNode){0},
|
||||
.macro_table = macro_table,
|
||||
.return_type_table = return_type_table,
|
||||
.walk_budget_nodes = cbm_walk_max_nodes(),
|
||||
@@ -5170,6 +5183,9 @@ static CBMFileResult *extract_file_ex_body(const char *source, int source_len, C
|
||||
/* Doc-comment references of the documented definitions, and the file's
|
||||
* doc-link scope: both read the complete docstrings and the tree. */
|
||||
cbm_doclinks_extract(&ctx);
|
||||
if (unrepaired) {
|
||||
ts_tree_delete(unrepaired);
|
||||
}
|
||||
|
||||
// Accumulate profiling counters
|
||||
atomic_fetch_add(&total_parse_ns, t1 - t0);
|
||||
|
||||
@@ -1165,6 +1165,9 @@ typedef struct {
|
||||
* The core never reads, interprets or frees it. It is the only place for
|
||||
* such state: a static or thread-local cache is not. */
|
||||
void *doclink_state;
|
||||
/* C#: the parse of the file itself when `root` reads it through a view that hid a branch of
|
||||
* a conditional (cbm_parse_source_repairing_ex); null otherwise. Alive for this call only. */
|
||||
TSNode unrepaired_root;
|
||||
} CBMExtractCtx;
|
||||
|
||||
/* Internal configured-definition seams. No declarations pointer enters a result. */
|
||||
@@ -1280,6 +1283,12 @@ TSTree *cbm_parse_source(TSParser *parser, const char *source, uint32_t source_l
|
||||
* same-length view of it. Offsets and lines are the source's own. */
|
||||
TSTree *cbm_parse_source_repairing(TSParser *parser, CBMLanguage language, const char *source,
|
||||
uint32_t source_len, TSParseOptions opts);
|
||||
/* As above. When the view that was used hid a branch of a conditional, *unrepaired receives the
|
||||
* parse of the file itself, for a reader that must see what the view left out; the caller deletes
|
||||
* it. Otherwise *unrepaired is left alone. */
|
||||
TSTree *cbm_parse_source_repairing_ex(TSParser *parser, CBMLanguage language, const char *source,
|
||||
uint32_t source_len, TSParseOptions opts,
|
||||
TSTree **unrepaired);
|
||||
/* As above for C-family source. A word that can only be an attribute macro is left out
|
||||
* of the parse, so `class LLVM_ABI StringRef {` reads as the class. Offsets and positions
|
||||
* stay those of the real file. Every C-family whole-file parse goes through here, so the
|
||||
|
||||
@@ -3036,7 +3036,11 @@ void cbm_doclink_cs_test_spoil_scope(const char *rel_path) {
|
||||
#endif
|
||||
|
||||
const char *cbm_doclink_cs_scan_scope(CBMExtractCtx *ctx) {
|
||||
if (ts_node_is_null(ctx->root)) {
|
||||
/* The parse view reads one branch of each #if, which is enough for the graph's nodes. A scope
|
||||
* read from it would call a namespace or a type complete when another branch of the file
|
||||
* names a different one, and a reference valid there would be reported as doc rot. */
|
||||
TSNode root = ts_node_is_null(ctx->unrepaired_root) ? ctx->root : ctx->unrepaired_root;
|
||||
if (ts_node_is_null(root)) {
|
||||
return NULL;
|
||||
}
|
||||
cs_scan_t s = {.ctx = ctx,
|
||||
@@ -3046,13 +3050,13 @@ const char *cbm_doclink_cs_scan_scope(CBMExtractCtx *ctx) {
|
||||
.untrusted = UINT32_MAX,
|
||||
.next_region = SKIP_ONE};
|
||||
s.root_end_byte = ctx->source_len > 0 ? (uint32_t)ctx->source_len : 0;
|
||||
s.root_end_line = cs_end_line(ctx->root);
|
||||
s.lexical = ts_node_has_error(ctx->root);
|
||||
s.root_end_line = cs_end_line(root);
|
||||
s.lexical = ts_node_has_error(root);
|
||||
if (s.lexical) {
|
||||
cs_scan_tokens(&s);
|
||||
}
|
||||
/* the root itself is an error node when nothing of the file parsed */
|
||||
cs_collect(&s, ctx->root, cs_kind_is(ctx->root, "ERROR") ? CS_OWNER_LEXICAL : CS_OWNER_NONE);
|
||||
cs_collect(&s, root, cs_kind_is(root, "ERROR") ? CS_OWNER_LEXICAL : CS_OWNER_NONE);
|
||||
cs_add_text_items(&s);
|
||||
sb_puts(&s.sb, CBM_DOCLINK_CS_SCOPE_TAG "\n");
|
||||
cs_emit_items(&s);
|
||||
|
||||
Reference in new issue
Block a user