-
-
Notifications
You must be signed in to change notification settings - Fork 0
Output Formats
Every SPM command emits JSON Lines (JSONL): one self-contained JSON object per line. This page
documents the schemas produced by analyze (static) and the instrumented app
under run (runtime). Field names and types here are taken directly from the
toJson methods in lib/src/features/*/data/models/. For the meaning of each analysis metric, see
Extracted Features.
One JSON object per line, one line per State class. The analyze output contains exactly these
17 fields (AnalysisResultModel.toJson):
{
"instanceId": "42",
"filePath": "lib/screens/shopping_cart_screen.dart",
"stateClassName": "_ShoppingCartScreenState",
"treeNonConstWidgetCount": 24,
"treeMaxWidgetNestingDepth": 7,
"treeListRenderingStrategy": 2,
"rootBuildReturnsConstWidget": 0,
"treeConstWidgetCount": 2,
"helperReferenceCount": 2,
"usesLayoutDependentBuilder": 1,
"treeCyclomaticComplexity": 5,
"treeIterationCount": 1,
"treeMaxIterationNestingDepth": 1,
"iterationWidgetCount": 3,
"valueObjectAllocCount": 4,
"helperWidgetCount": 3,
"helperMaxWidgetNestingDepth": 2
}| Field | Type | Description |
|---|---|---|
instanceId |
string | ID for this State class: hash of the root-relative path + class name. Used to join with runtime profiler data. It is not unique across transplanted targets that share one file/class, so the benchmark pipeline keys by sample_id instead. |
filePath |
string | Source path relative to the analyzed project root. |
stateClassName |
string | Name of the State subclass. |
treeNonConstWidgetCount |
int | Non-const widget instantiations across reachable build bodies; excludes const boundaries and helper-body widgets. |
treeMaxWidgetNestingDepth |
int | Maximum widget depth composed across reachable custom-widget build bodies. |
treeListRenderingStrategy |
0/1/2 | Worst list-rendering form across builds and helpers: 0 none, 1 lazy (.builder/.separated/.custom, slivers), 2 eager O(N) (concrete children: on a scroll list, or runtime-length Column/Row/Wrap/Flex children). (Replaced the buildUsesListViewBuilder boolean on 2026-07-20.)
|
rootBuildReturnsConstWidget |
0/1 | Whether the root State.build directly returns a const widget. |
treeConstWidgetCount |
int | Const widget boundaries across reachable build bodies; helper-body const widgets belong to helperWidgetCount. (Named constConstructorRatio in JSONL produced before 2026-07-18.)
|
helperReferenceCount |
int | Widget-returning helper reference sites in reachable build bodies: invocations, tear-offs, and explicit getters. |
usesLayoutDependentBuilder |
0/1 | Whether builds or helpers use LayoutBuilder, CustomMultiChildLayout, or Flow. |
treeCyclomaticComplexity |
int | Complexity summed across reachable build bodies, plus helper-body decision points without extra helper base points. |
treeIterationCount |
int | Loops, collection-for elements, and linear collection operations across build and helper bodies. |
treeMaxIterationNestingDepth |
int | Maximum lexical iteration nesting within any analyzed build or helper body. |
iterationWidgetCount |
int | Non-const widgets built in per-element scopes across builds and helpers: loops, collection-op callbacks, and lazy builders. |
valueObjectAllocCount |
int | All non-const, non-widget constructor allocations across build and helper bodies. |
helperWidgetCount |
int | Widget instantiations in reachable helper bodies, including const widgets. |
helperMaxWidgetNestingDepth |
int | Maximum widget nesting within any individual reachable helper body. |
0/1fields are Dartbools serialized as1/0bytoJson. See Extracted Features for the precise definition of each metric.
Feature keys were renamed so every name states its scope: tree* = aggregated over the whole
static call tree, root* = root build() only, helper* = helper bodies only. Older JSONL
files can be normalized with this map:
| Old key (pre-2026-07-20) | Current key |
|---|---|
buildWidgetInstanceCount |
treeNonConstWidgetCount |
buildMaxWidgetNestingDepth |
treeMaxWidgetNestingDepth |
buildUsesListViewBuilder (bool, pre-07-20) / buildListRenderingStrategy
|
treeListRenderingStrategy |
buildReturnsConstWidget |
rootBuildReturnsConstWidget |
constConstructorRatio (pre-07-18) / constWidgetCount
|
treeConstWidgetCount |
buildHelperMethodCount |
helperReferenceCount |
buildCyclomaticComplexity |
treeCyclomaticComplexity |
buildIterationCount |
treeIterationCount |
buildMaxIterationNestingDepth |
treeMaxIterationNestingDepth |
helperMethodWidgetCount |
helperWidgetCount |
helperMethodMaxNestingDepth |
helperMaxWidgetNestingDepth |
usesLayoutDependentBuilder, iterationWidgetCount, valueObjectAllocCount, and the identity
keys (instanceId, filePath, stateClassName) are unchanged. The legacy boolean
buildUsesListViewBuilder maps onto the none/lazy levels of the ordinal only; it cannot
express eager (2).
Two event types are emitted, distinguished by the event field. Which one you get depends on the
Flutter build mode (see inject): --profile → performance_metric,
--debug → dataflow-metric. Every event carries a timestamp (ISO-8601) and the instanceId
that joins back to the static-analysis record.
Performance event, emitted under --profile (PerformanceMetricsModel.toJson):
{
"timestamp": "2026-02-20T10:15:30.123Z",
"event": "performance_metric",
"instanceId": "42",
"buildSpan": 4123
}| Field | Type | Description |
|---|---|---|
timestamp |
string | ISO-8601 timestamp of the event. |
event |
string | Always "performance_metric". |
instanceId |
string | The instrumented State instance. |
buildSpan |
int | Build duration of the matched rebuild frame, in microseconds (0 on the 5-second timeout fallback). |
Dataflow event, emitted under --debug (DataflowMetricsModel.toJson):
{
"timestamp": "2026-02-20T10:15:30.456Z",
"event": "dataflow-metric",
"instanceId": "42",
"taintedRebuildCount": 5,
"totalWidgetCount": 42,
"maxNestingDepth": 7,
"taintedRatio": 0.119,
"opacityRebuildCount": 0,
"shaderMaskRebuildCount": 0,
"clipRRectRebuildCount": 1,
"clipOvalRebuildCount": 0,
"clipPathRebuildCount": 0,
"backdropFilterRebuildCount": 0
}| Field | Type | Description |
|---|---|---|
timestamp |
string | ISO-8601 timestamp of the event. |
event |
string | Always "dataflow-metric". |
instanceId |
string | The instrumented State instance. |
taintedRebuildCount |
int | Widgets that actually rebuilt as a result of the setState. |
totalWidgetCount |
int | Total widgets in the analyzed subtree. |
maxNestingDepth |
int | Maximum nesting depth of the analyzed subtree. |
taintedRatio |
double |
taintedRebuildCount / totalWidgetCount. |
opacityRebuildCount |
int | Rebuilt Opacity widgets. |
shaderMaskRebuildCount |
int | Rebuilt ShaderMask widgets. |
clipRRectRebuildCount |
int | Rebuilt ClipRRect widgets. |
clipOvalRebuildCount |
int | Rebuilt ClipOval widgets. |
clipPathRebuildCount |
int | Rebuilt ClipPath widgets. |
backdropFilterRebuildCount |
int | Rebuilt BackdropFilter widgets. |
Commands
Reference
Internals
Contributing