Class CoverageProbePlacer
Coverage probes are inserted at:
- Function/method entry (FUNCTION_ENTRY)
- If-then branch taken (BRANCH_TRUE)
- Else/else-if branch taken (BRANCH_FALSE)
- Switch case entry (SWITCH_CASE)
- Catch block entry (CATCH_BLOCK)
- Loop body entry (LOOP_BODY)
Each probe has a globally unique ID (GUID) generated from a deterministic FNV-1a 64-bit hash of its context (module, file, line, type, function). This ensures uniqueness across all source files without requiring coordination during parallel compilation.
Note: BLOCK and FUNCTION_EXIT probes are intentionally omitted as they are redundant in EK9 - explicit branch tracking already identifies paths taken, and EK9 functions have exactly one exit point (no return statement).
-
Constructor Summary
ConstructorsConstructorDescriptionCoverageProbePlacer(CompilerFlags compilerFlags, long moduleId, String moduleName, boolean isDevSource) Create a coverage probe placer for a module. -
Method Summary
Modifier and TypeMethodDescriptionvoidaddFieldInjections(int count) Accumulate field-level injection count from a component.voidaddRegistrations(int count) Accumulate registration count from an application.createBranchFalseProbe(DebugInfo debugInfo) Create a branch-false (else) probe instruction.createBranchTrueProbe(DebugInfo debugInfo) Create a branch-true (if/then) probe instruction.createCatchBlockProbe(String exceptionType, DebugInfo debugInfo) Create a catch block probe instruction.createCoverageFinalization(DebugInfo debugInfo) Create a coverage finalization instruction.createFinallyBlockProbe(DebugInfo debugInfo) Create a finally block probe instruction.createFunctionEntryProbe(DebugInfo debugInfo) Create a function entry probe instruction.createInputClassProbe(ISymbol operationSymbol, DebugInfo debugInfo, String scopeId, IRGenerationContext stackContext) Create an input-class probe for a public construct's entry (the dynamic numerator, §5).createLoopBodyProbe(DebugInfo debugInfo) Create a loop body probe instruction.createModuleRegistration(DebugInfo debugInfo) Create a module registration instruction.createProfilingEntryProbe(DebugInfo debugInfo) Create a profiling entry probe instruction.createProfilingExitProbe(DebugInfo debugInfo) Create a profiling exit probe instruction.createStatementProbe(DebugInfo debugInfo) Create a statement probe instruction.createSwitchCaseProbe(String caseLabel, DebugInfo debugInfo) Create a switch case probe instruction.voidenterFunction(String functionName, String simpleName, String sourceFile, int startLine) Enter a function/method context for probe tracking.voidenterFunction(String functionName, String simpleName, String sourceFile, int startLine, FunctionMetrics metrics) Enter a function/method context for probe tracking with metrics.voidexitFunction(int endLine) Exit the current function/method context.Get all probe details for this source file (for testing/verification).Get function details for this source file (for testing/verification).longGet the module ID (hash of module name).intGet the current probe count for this source file.booleanCheck if the §5.3 assert-window markers should be emitted — and note this deliberately does not defer toisInputVarietyEnabled().booleanCheck if coverage instrumentation is enabled.booleanCheck if input-variety numerator instrumentation is enabled.booleanCheck if profiling instrumentation is enabled.voidregisterFileReadability(String sourceFile, String readabilityScore) Register a file's readability score.voidsetSignatureEndLine(int signatureEndLine) Set the end line of the function signature.Serialize probe and function metadata to JSON for runtime coverage computation.
-
Constructor Details
-
CoverageProbePlacer
public CoverageProbePlacer(CompilerFlags compilerFlags, long moduleId, String moduleName, boolean isDevSource) Create a coverage probe placer for a module.- Parameters:
compilerFlags- Compiler flags to check if coverage is enabledmoduleId- Unique identifier for this module (unused, kept for API compatibility)moduleName- Human-readable module nameisDevSource- True if this is dev/test source code (excluded from coverage)
-
-
Method Details
-
isCoverageEnabled
public boolean isCoverageEnabled()Check if coverage instrumentation is enabled. Returns false for dev/test sources - like JaCoCo, we only measure coverage of production code, not the test harness code itself. -
isProfilingEnabled
public boolean isProfilingEnabled()Check if profiling instrumentation is enabled. Returns false for dev/test sources (same exclusion as coverage). -
isInputVarietyEnabled
public boolean isInputVarietyEnabled()Check if input-variety numerator instrumentation is enabled.The dynamic numerator (design §5) rides the coverage-instrumented
-trun, so it is enabled exactly when coverage is (and, like coverage, excludes dev/test sources — the probe instruments the production construct being tested, not the test harness). This keeps every-trun producing the measurement with no extra flag; a dedicated flag / packaging gate is a later concern (§8). -
isAssertWindowEnabled
public boolean isAssertWindowEnabled()Check if the §5.3 assert-window markers should be emitted — and note this deliberately does not defer toisInputVarietyEnabled().The entry probe measures the production construct, so it is (correctly) suppressed in dev/test sources. The assert window is the exact inverse: an
assertstatement lives only in a dev/test source (a production assertion is E81012), so gating the markers on the probe's predicate would emit them nowhere and pinassertedat zero forever. The window is therefore enabled whenever the build is coverage-instrumented, dev source or not. -
registerFileReadability
Register a file's readability score.ARI (Automated Readability Index) is calculated during parsing and provides a grade-level indicator of code readability. This is unique to EK9 - no competitor offers source code readability analysis.
- Parameters:
sourceFile- Source file pathreadabilityScore- ARI score string (e.g., "10-11 Fifth Grade")
-
addFieldInjections
public void addFieldInjections(int count) Accumulate field-level injection count from a component. Field injections are declared as properties with '!' (e.g., logger as Logger!).- Parameters:
count- Number of field-level injections in this component
-
addRegistrations
public void addRegistrations(int count) Accumulate registration count from an application. Registrations are 'register' statements that offer components for injection.- Parameters:
count- Number of register statements in this application
-
enterFunction
Enter a function/method context for probe tracking. Call this when starting to generate IR for a function/method.- Parameters:
functionName- Fully qualified function/method namesimpleName- Simple function/method name (e.g., "_add")sourceFile- Source file containing this functionstartLine- Starting line number of the function
-
enterFunction
public void enterFunction(String functionName, String simpleName, String sourceFile, int startLine, FunctionMetrics metrics) Enter a function/method context for probe tracking with metrics. Call this when starting to generate IR for a function/method.- Parameters:
functionName- Fully qualified function/method namesimpleName- Simple function/method name (e.g., "_add")sourceFile- Source file containing this functionstartLine- Starting line number of the functionmetrics- Code quality metrics from Phase 5
-
setSignatureEndLine
public void setSignatureEndLine(int signatureEndLine) Set the end line of the function signature.The signature includes the function name, parameters (->), and return declaration (<-). This allows HTML coverage reports to color all signature lines consistently based on the FUNCTION_ENTRY coverage status.
- Parameters:
signatureEndLine- Last line of the function signature (after return declaration)
-
exitFunction
public void exitFunction(int endLine) Exit the current function/method context. Records function-level coverage metadata.- Parameters:
endLine- Ending line number of the function body
-
createFunctionEntryProbe
-
createBranchTrueProbe
-
createBranchFalseProbe
-
createSwitchCaseProbe
Create a switch case probe instruction.- Parameters:
caseLabel- Label or description of the case (for logging purposes)debugInfo- Source location information- Returns:
- Coverage probe instruction, or null if coverage disabled
-
createCatchBlockProbe
Create a catch block probe instruction.- Parameters:
exceptionType- Type of exception being caught (for logging purposes)debugInfo- Source location information- Returns:
- Coverage probe instruction, or null if coverage disabled
-
createLoopBodyProbe
-
createFinallyBlockProbe
Create a finally block probe instruction. Tracks execution of explicit finally blocks only.Note: Synthetic finally blocks (from try-with-resources without explicit finally) should NOT be probed because the close() method's FUNCTION_ENTRY already proves cleanup happened.
- Parameters:
debugInfo- Source location information- Returns:
- Coverage probe instruction, or null if coverage disabled
-
createStatementProbe
Create a statement probe instruction. Tracks execution of individual statements for fine-grained coverage.Unlike edge-based tools that infer coverage, EK9 directly measures each statement execution. This ensures accurate coverage even when exceptions are thrown mid-block, and requires zero coverage logic in backends.
- Parameters:
debugInfo- Source location information- Returns:
- Coverage probe instruction, or null if coverage disabled
-
createModuleRegistration
-
createCoverageFinalization
-
createProfilingEntryProbe
Create a profiling entry probe instruction. Uses the current function's ID and name (already tracked by enterFunction).- Parameters:
debugInfo- Source location information- Returns:
- Profiling entry instruction, or null if profiling disabled
-
createProfilingExitProbe
-
createInputClassProbe
public List<IRInstr> createInputClassProbe(ISymbol operationSymbol, DebugInfo debugInfo, String scopeId, IRGenerationContext stackContext) Create an input-class probe for a public construct's entry (the dynamic numerator, §5).In scope exactly when the phase-5
InputVarietyDenominatorRecordersquirrelled anINPUT_VARIETY_FLOORon this callable — reusing that scoping decision rather than re-deriving genus/visibility rules (built-ins, entry shims and no-denominator constructs are thereby excluded, §7). When the recorder also counted the receiver as the implicitp0(§4.5, marked byCommonValues.INPUT_VARIETY_RECEIVER) the probe emits a receiver cell at index 0 with the arguments following — so a stateful no-arg instance method (e.g.pop()) is still probed. The §5.3 result-into-assertion commit rule is a later iteration.- Parameters:
operationSymbol- the callable's symbol (carries the squirrelled scope signal + parameters)debugInfo- source location information- Returns:
- the input-class probe, or
nullwhen disabled / out of scope / no dimensions
-
getProbeCount
public int getProbeCount()Get the current probe count for this source file. -
getModuleId
public long getModuleId()Get the module ID (hash of module name). -
getAllProbes
Get all probe details for this source file (for testing/verification). -
getFunctionDetails
Get function details for this source file (for testing/verification). -
toMetadataJson
Serialize probe and function metadata to JSON for runtime coverage computation.The JSON format is:
{ "probes": [ {"id": "0x1234...", "type": "FUNCTION_ENTRY", "line": 10, "functionId": "0xABCD..."}, {"id": "0x5678...", "type": "BRANCH_TRUE", "line": 15, "functionId": "0xABCD..."} ], "functions": [ {"id": "0xABCD...", "name": "myFunction", "startLine": 10, "endLine": 20, "entryProbeId": "0x1234..."} ] }- Returns:
- JSON string with coverage metadata, or null if no probes and no functions
-