@@ -146,7 +146,10 @@ static void walk_throws(CBMExtractCtx *ctx, TSNode root, const CBMLangSpec *spec
146146// - field/member/selector access (`self.total = ...`, `obj.Field = ...` →
147147// write the trailing field name `total`/`Field`)
148148// Returns NULL if no simple write target can be determined.
149- static char * resolve_lhs_write_name (CBMExtractCtx * ctx , TSNode left ) {
149+ // Sets *is_member_out when the written name is the field half of a
150+ // member/selector LHS — the receiver is stripped from the returned name, so
151+ // this out-param is the only surviving record of the selector shape (#1962).
152+ static char * resolve_lhs_write_name (CBMExtractCtx * ctx , TSNode left , bool * is_member_out ) {
150153 // Unwrap a single-element expression_list (Go).
151154 if (strcmp (ts_node_type (left ), "expression_list" ) == 0 ) {
152155 if (ts_node_named_child_count (left ) != 1 ) {
@@ -184,6 +187,9 @@ static char *resolve_lhs_write_name(CBMExtractCtx *ctx, TSNode left) {
184187 fld = ts_node_child_by_field_name (left , TS_FIELD ("name" ));
185188 }
186189 if (!ts_node_is_null (fld )) {
190+ if (is_member_out ) {
191+ * is_member_out = true;
192+ }
187193 return cbm_node_text (ctx -> arena , fld , ctx -> source );
188194 }
189195 return NULL ;
@@ -251,12 +257,14 @@ static void try_emit_assignment_write(CBMExtractCtx *ctx, TSNode node, const cha
251257 if (ts_node_is_null (left )) {
252258 return ;
253259 }
254- char * name = resolve_lhs_write_name (ctx , left );
260+ bool is_member = false;
261+ char * name = resolve_lhs_write_name (ctx , left , & is_member );
255262 if (name && name [0 ] && !cbm_is_keyword (name , ctx -> language )) {
256263 CBMReadWrite rw ;
257264 rw .var_name = name ;
258265 rw .is_write = true;
259266 rw .enclosing_func_qn = func_qn ;
267+ rw .is_member_access = is_member ;
260268 cbm_rw_push (& ctx -> result -> rw , ctx -> arena , rw );
261269 }
262270}
@@ -329,12 +337,14 @@ void handle_readwrites(CBMExtractCtx *ctx, TSNode node, const CBMLangSpec *spec,
329337 TSNode left = resolve_write_lhs_node (node );
330338
331339 if (!ts_node_is_null (left )) {
332- char * name = resolve_lhs_write_name (ctx , left );
340+ bool is_member = false;
341+ char * name = resolve_lhs_write_name (ctx , left , & is_member );
333342 if (name && name [0 ] && !cbm_is_keyword (name , ctx -> language )) {
334343 CBMReadWrite rw ;
335344 rw .var_name = name ;
336345 rw .is_write = true;
337346 rw .enclosing_func_qn = state -> enclosing_func_qn ;
347+ rw .is_member_access = is_member ;
338348 cbm_rw_push (& ctx -> result -> rw , ctx -> arena , rw );
339349 }
340350 }
0 commit comments