Class CallGraph
This call graph is built during Phase 5 (PRE_IR_CHECKS) using RTA (Rapid Type Analysis). EK9's closed-world semantics (no reflection, no dynamic loading) means the call graph is 100% sound - all possible call targets are known at compile time.
Key Properties
- Bidirectional: Query both callers and callees
- RTA-based: Polymorphic calls filtered by allocated types
- Thread-safe: Uses ConcurrentHashMap for parallel construction
- Entry point aware: Distinguishes programs and @Test programs
Analyses Enabled
- E81007: Empty @Test (no assertions reachable)
- Orphan assertion detection: assert* not reachable from @Test
- Assert in production: assert* reachable from non-@Test program
- Dead code detection: Functions not reachable from any entry point
- Purity validation: Pure calling impure detection
- See Also:
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidAdd a call edge from caller to callee.Get all registered callables.Get all entry points (programs, @Test programs, and service operations).Get all allocated types (used by RTA).Find assertion-containing callables that ARE reachable from production programs.intGet total number of registered callables.getCallableInfo(String name) Get metadata for a callable.Get all callables that directly contain assertions.Get all callables that directly contain injection sites.getCallers(String callee) Get all callers of a callable.intGet total number of edges in the call graph.Find assertion-containing callables that are NOT reachable from any @Test AND are also NOT reachable from production programs.getOutgoingCalls(String caller) Get all outgoing call edges from a callable.getOutgoingCallsInSourceOrder(String caller) THE source-ordered view of a callable's outgoing edges - use it wherever ONE edge must stand for a callee (the representative call site) or edges are listed for a person: earliest site first, so a callee called twice is always shown at its FIRST site and a rendered list reads top-down.Get all production entry points (non-test programs plus service operations).Get all program entry points (excluding @Test programs).getReachableCallables(Set<String> entryPoints) Get all callables reachable from the given entry points.Get all service-operation entry points (HTTP/runtime-dispatched).Get all @Test program entry points.Find @Test programs that have no reachable assertions (E81007 candidates).Get all callables that are NOT reachable from any entry point (dead code).booleanCheck if any @Test entry points have been registered.booleanhasReachableAssertions(String testEntryPoint) Check if assertions are transitively reachable from a @Test program.booleanhasReachableInjections(String programEntryPoint) Check if injections are transitively reachable from a program entry point.booleanisReachableFrom(String target, Set<String> entryPoints) Check if a callable is reachable from any of the given entry points.booleanisReachableFromPrograms(String target) Check if a callable is reachable from any non-test program.booleanisReachableFromTests(String target) Check if a callable is reachable from any @Test entry point.booleanisTypeAllocated(String typeName) Check if a type is allocated (instantiated) in the program.voidrecordAllocatedType(String fullyQualifiedTypeName) Record that a type is allocated (instantiated) in the program.voidregisterCallable(CallableInfo info) Register a callable entity (function, method, program, etc.).toString()
-
Constructor Details
-
CallGraph
public CallGraph()
-
-
Method Details
-
registerCallable
Register a callable entity (function, method, program, etc.). -
addEdge
Add a call edge from caller to callee. -
recordAllocatedType
Record that a type is allocated (instantiated) in the program. Used by RTA to filter polymorphic call targets. -
getOutgoingCalls
Get all outgoing call edges from a callable.This is a hash SET: its iteration order folds in the edge's source token, which folds in the source PATH, so it is stable for one checkout and arbitrary in source terms. Aggregate over it freely; never let it choose WHICH edge represents a callee or the ORDER a list is displayed in - use
getOutgoingCallsInSourceOrder(String)for that. -
getOutgoingCallsInSourceOrder
THE source-ordered view of a callable's outgoing edges - use it wherever ONE edge must stand for a callee (the representative call site) or edges are listed for a person: earliest site first, so a callee called twice is always shown at its FIRST site and a rendered list reads top-down.Ordered by line, then column, then callee. A callable's body lives in one source, so line and column ARE the source order; the callee tie-break only makes the order total should two edges ever share a token. Picking "first" from
getOutgoingCalls(String)instead was a hash-ordered instrument: the same query answered a different site on two runs with no code change, and two callees each called twice were shown at their first and second site respectively. -
getCallers
-
getCallableInfo
Get metadata for a callable. -
getAllCallables
-
getProgramEntryPoints
-
getTestEntryPoints
-
getServiceEntryPoints
-
getProductionEntryPoints
Get all production entry points (non-test programs plus service operations). These are the roots a release artefact can be entered through; a callable reachable from one of these is live in production. Tests are deliberately excluded so that "reachable only from tests" can be distinguished. -
hasAnyTestEntryPoints
public boolean hasAnyTestEntryPoints()Check if any @Test entry points have been registered. Used to auto-enable call graph validation when tests are present, regardless of devBuild flag. -
getAllEntryPoints
-
getAllocatedTypes
-
isTypeAllocated
Check if a type is allocated (instantiated) in the program. -
getCallablesWithAssertions
-
getCallablesWithInjections
-
hasReachableInjections
Check if injections are transitively reachable from a program entry point. Used for DI completeness validation.- Parameters:
programEntryPoint- The program to check- Returns:
- true if any injection is reachable from this program
-
isReachableFrom
Check if a callable is reachable from any of the given entry points. Uses iterative worklist algorithm for transitive reachability.- Parameters:
target- The callable to check reachability forentryPoints- Set of entry points to start from- Returns:
- true if target is transitively reachable from any entry point
-
isReachableFromTests
Check if a callable is reachable from any @Test entry point. -
isReachableFromPrograms
Check if a callable is reachable from any non-test program. -
getReachableCallables
-
getUnreachableCallables
-
hasReachableAssertions
Check if assertions are transitively reachable from a @Test program. Used for E81007 (empty test) detection.- Parameters:
testEntryPoint- The @Test program to check- Returns:
- true if any assertion is reachable from this test
-
getTestsWithoutAssertions
-
getOrphanAssertions
Find assertion-containing callables that are NOT reachable from any @Test AND are also NOT reachable from production programs. These are "orphan assertions" that will never be executed.Note: Assertions reachable from production programs are NOT considered orphans - they have a more specific problem (PRODUCTION_ASSERTION) which is worse because they're actually running in production code using assert instead of require.
-
getAssertionsInProductionCode
-
getEdgeCount
public int getEdgeCount()Get total number of edges in the call graph. -
getCallableCount
public int getCallableCount()Get total number of registered callables. -
toString
-