Skip to content

chore(csharp): reconcile is_call with abc.branches, and primary-constructor space attribution #1456

Description

@dekobon

Summary

Two small divergences noticed while fixing
#1406, neither
introduced by it, both worth a decision rather than being left implicit.

1. Checker::is_call disagrees with abc.branches

C#'s Checker::is_call matches only the invocation aliases. abc.branches
counts those plus ObjectCreationExpression, ConstructorInitializer, and
since #1406 the primary-constructor base call
(PrimaryConstructorBaseType / a base_list-gated ArgumentList).

So bca find --filter call and abc.branches now disagree by one more
construct than they used to. .claude/rules/grammar-dispatch.md §7 asks for
exactly this cross-walk: two predicates classifying the same nodes through
parallel matches!() drift silently, and each reads as internally
consistent from its own side.

Decide which is intended — is_call is arguably answering a narrower
question ("is this a call site a reader navigates to") than ABC's
Fitzpatrick branch rule ("function invocation or object construction"). If
the divergence is deliberate, say so in a comment at both sites; if not,
widen is_call.

2. A primary constructor opens no FuncSpace

class Sub(int x) : Base(x) has no constructor body, so no function space
is opened and the base call lands on the class space. The classic
: base(x) spelling lands on a function space.

File-level sums agree, so nothing is wrong at the aggregate. But
per-function branches_max / branches_average, and a per-function
bca check --threshold abc=N, see the two spellings differently — the
primary-constructor form contributes to the class row and never to any
function row.

That may well be correct (there is no function there to attribute it to),
but it means a codebase that migrates to primary constructors will see its
per-function ABC distribution shift without any behaviour change. Worth
recording the decision either way.

Related


Resolution

Status: Fixed (pending merge)
Commit: 2463287c on branch fix/issue-1456
Root cause: Neither divergence is a defect. Both are deliberate and
both were undocumented. (1) is_call answers "where is this called" and
ABC's branches applies Fitzpatrick's wider "function invocation or
object creation" rule; the split is the workspace convention across 13
languages, stated only in a Groovy test since #430. (2) A primary
constructor's superclass call sits in the class header — a sibling of
its parameter list, not a child — so no function space encloses it and
the branch is the class's. Fixed as documentation (trait doc, both C#
sites, the Kotlin sibling, two book sections) plus
csharp_is_call_excludes_constructors and per-space assertions on the
Kotlin primary-constructor test. No metric or predicate behaviour
changed.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions