Class CoverageDisplayName

java.lang.Object
org.ek9lang.compiler.phase7.generator.CoverageDisplayName

public final class CoverageDisplayName extends Object
Resolves the user-facing display name for a function/method symbol used in coverage and quality reports.

Three cases are handled:

  • Synthetic methods (_main, _call, i_init, c_init, etc.) — show the enclosing scope name. This makes a program's _main render as the program name, a dynamic function's _call render as the dynamic function's name, and so on.
  • Regular methods/operators on an aggregate (class, trait, component, record, service) — prefix the method name with the aggregate name. Renders as Newt.move, ASimpleClass.aCheck, Walker.?. This distinguishes methods from module-level free functions in coverage report listings.
  • Module-level free functions — show the bare function name with no prefix.

Used by every IR generator that registers function entries with CoverageProbePlacer: OperationDfnGenerator, AggregateDfnGenerator, ServiceDfnGenerator, TextDfnGenerator.

  • Method Details

    • forSymbol

      public static String forSymbol(ISymbol operationSymbol)
      Resolve the display name for a function/method symbol.
      Parameters:
      operationSymbol - the symbol whose display name is needed; must not be null
      Returns:
      user-facing display name suitable for HTML coverage reports
    • identityForSymbol

      public static String identityForSymbol(ISymbol operationSymbol)
      THE join key for a construct — the display name minus its one cosmetic exception.

      Use this whenever a construct must be MATCHED against data gathered elsewhere (input variety, complexity, any per-construct report); use forSymbol(ISymbol) only to show a human a name. They differ for exactly one shape: a constructor renders bare as Counter for readability, but every other producer names it Counter.Counter, so joining on the display form made every constructor silently miss its row.

      Deliberately NOT ISymbol.getFullyQualifiedName(), which is a different thing again: for a method it yields module::classify, dropping the enclosing type, and for a free function it yields the synthetic module::_call. Neither can be joined on.

      Parameters:
      operationSymbol - the symbol whose identity is needed; must not be null
      Returns:
      Aggregate.member for aggregate members (constructors included), else the bare name
    • sourceQualifiedName

      public static String sourceQualifiedName(ISymbol operationSymbol)
      THE fully-qualified name to use as a coverage/profiling IDENTITY for a callable — stable across every parameterisation of a generic.

      Why this exists (defect D11). EK9 monomorphises, so Holder of String and Holder of Integer are separate aggregates with mangled names. A METHOD's getFullyQualifiedName() does not carry its owning type, so two parameterisations already agree — but a CONSTRUCTOR's name IS its type's name, which is the mangled one, so the two disagree and one source constructor acquires an identity per parameterisation. Probe and function ids hash this name, so the effect is a denominator counting the same source constructor N times.

      Coverage is deliberately TYPE-BLIND: it answers "did this source line ever execute", and EK9 has no instanceof or casts, so a generic body cannot branch on its type argument. Type breadth is the separate input-variety axis's job. Hence the generic's own name, NOT getFriendlyName(), which would append the type arguments and split the identity again.

      🔑 Resolved from the SYMBOL (PossibleGenericSymbol.getGenericType()), never by un-mangling the string. FriendlyInternalName is the display-only transform and says so: it reduces every dynamic class and function to cls/fn, which would make two dynamic constructs in one module collide as one identity.

      Parameters:
      operationSymbol - the symbol whose identity is needed; must not be null
      Returns:
      the fully-qualified name, with a parameterised type's constructor named for its generic