Class CallableIdentity

java.lang.Object
org.ek9lang.compiler.support.CallableIdentity

public final class CallableIdentity extends Object
THE identity of a callable in the phase-5 call graph — module::Aggregate.member for a member of an aggregate, and the plain fully-qualified name for everything else. Use this for any call-graph node key or call-edge target; do NOT key on ISymbol.getFullyQualifiedName().

Why this exists. getFullyQualifiedName() composes the module scope with the symbol's own name only (Symbol.getFullyQualifiedName), so for a method it yields module::check — dropping the enclosing type. That is not a display wart: it made the node key non-unique, so two same-named members on UNRELATED types collapsed into a single graph node. The surviving node took one type's symbol and the other type's callers, and everything downstream inherited it — dead-code detection silently missed the second member (it looked reachable because its namesake was), and reachability, DI ordering and interprocedural lock analysis all read the merged node. A module with five ? operators had one node for all five.

Deliberately NOT CoverageDisplayName.identityForSymbol, which is the join key for coverage/variety/HEX reports and looks almost identical. It additionally maps any name beginning _ (plus i_init/c_init) to its enclosing scope name, which is right for the synthetic _call/_main it was written for but wrong here: a dynamic function is named _Function_<hash>, and rewriting it to its enclosing scope's name would collide it with the real callable declared there — trading one merge bug for another. Dynamic functions are already unique by hash, so they pass through untouched.

The two schemes still AGREE on the shape that matters for joining reports to the graph — an aggregate member is Aggregate.member in both — so a Ca row and a HEX row can finally be matched on identity rather than on a name produced for humans.

  • Method Details

    • forSymbol

      public static String forSymbol(ISymbol symbol)
      The call-graph identity for a callable symbol.
      Parameters:
      symbol - the callable's resolved symbol; must not be null
      Returns:
      module::Aggregate.member for an aggregate member, else the symbol's own FQN
    • declaringConstructOf

      public static String declaringConstructOf(String callableIdentity)
      THE inverse of forSymbol(ISymbol): the declaring construct of a call-graph identity. module::Aggregate.member yields module::Aggregate; a module-level function or program module::name yields itself. Use this to lift a callable-granular call-graph answer to construct granularity; do NOT hand-roll the split.

      It lives here, beside the code that mints the format, on purpose. Two byte-identical private copies had already appeared in compiler-services extractors, and a parser sitting in a different module from the minter is precisely the drifting shortcut that breaks silently the day the format changes — nothing would fail to compile, the split would just quietly return the wrong construct.

      Parameters:
      callableIdentity - an identity as produced by forSymbol(ISymbol), or null
      Returns:
      the declaring construct's fully-qualified name, or null when given null