Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Reviews, improves, and writes SwiftUI code following state management, view composition, performance, and iOS 26+ Liquid Glass best practices.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
scripts/instruments_parser/causes.py
1"""SwiftUI cause-graph lane (`swiftui-causes` schema).23Instruments emits one row per edge in SwiftUI's dependency graph: every time4a source node (a state change, user defaults observer, system event, etc.)5propagates to a destination node (a body evaluation, layout, creation), a6row is written with both endpoints as metadata values.78This lane aggregates those edges two ways:910- **By source node** — which attribute graph nodes are driving the most11updates overall. The canonical "why is my app thrashing?" view; a12`UserDefaultObserver.send()` showing up with 11k outgoing edges is a13feedback storm.14- **By destination node** — which views/modifiers receive the most15invalidations, and from whom. Use this to trace a hot view back to the16source that keeps poking it.1718The analyzer's main lane (`swiftui`) tells you *what* updates are19expensive; this lane tells you *why* they keep happening.20"""21from __future__ import annotations2223from collections import Counter, defaultdict24from pathlib import Path25from typing import Any2627from . import xctrace, xml_utils2829SCHEMA = "swiftui-causes"3031# Metadata nodes render as space-separated field dumps ("A gray icon n/a n/a").32# We aggregate on the full fmt string so callers can spot specific edges like33# "@AppStorage TextStyleModifier.fontOption", but also expose the short head34# ("@AppStorage", "Creation of App", ...) for coarser grouping.353637def analyze(38trace_path: Path,39toc_schemas: frozenset[str],40top_n: int = 10,41top_k_per_node: int = 5,42window: tuple[int, int] | None = None,43run: int = 1,44) -> dict[str, Any]:45if SCHEMA not in toc_schemas:46return {47"lane": "swiftui-causes",48"available": False,49"notes": [50"SwiftUI causes data not present (requires SwiftUI template on a real device).",51],52}5354xml_bytes = xctrace.export_schema(trace_path, SCHEMA, run=run)55stream = xml_utils.RowStream(xml_bytes)5657source_edges: Counter[str] = Counter()58destination_edges: Counter[str] = Counter()59fanout: dict[str, Counter[str]] = defaultdict(Counter)60fanin: dict[str, Counter[str]] = defaultdict(Counter)61label_counts: Counter[str] = Counter()62total_edges = 06364for row in stream:65time_el = xml_utils.first_present(row, "timestamp", "time")66if time_el is not None:67t_ns = xml_utils.int_text(stream.resolve(time_el))68if t_ns is not None and not xml_utils.in_window(t_ns, window):69continue7071src = _fmt(row, stream, "source-node")72dst = _fmt(row, stream, "destination-node")73if not src or not dst:74continue7576source_edges[src] += 177destination_edges[dst] += 178fanout[src][dst] += 179fanin[dst][src] += 18081label = _fmt(row, stream, "label")82if label:83label_counts[label] += 18485total_edges += 18687top_sources = [88{89"source": src,90"edges": count,91"top_destinations": [92{"destination": d, "edges": c}93for d, c in fanout[src].most_common(top_k_per_node)94],95}96for src, count in source_edges.most_common(top_n)97]9899top_destinations = [100{101"destination": dst,102"edges": count,103"top_sources": [104{"source": s, "edges": c}105for s, c in fanin[dst].most_common(top_k_per_node)106],107}108for dst, count in destination_edges.most_common(top_n)109]110111return {112"lane": "swiftui-causes",113"available": True,114"schema_used": SCHEMA,115"metrics": {116"total_edges": total_edges,117"unique_sources": len(source_edges),118"unique_destinations": len(destination_edges),119"top_labels": dict(label_counts.most_common(top_n)),120},121"top_sources": top_sources,122"top_destinations": top_destinations,123"notes": [],124}125126127def fanin_for(128trace_path: Path,129toc_schemas: frozenset[str],130destination_contains: str,131top_k: int = 10,132window: tuple[int, int] | None = None,133run: int = 1,134) -> dict[str, Any]:135"""Return the top source nodes feeding any destination whose fmt string136contains `destination_contains` (case-insensitive substring).137138Used when the agent has a suspect view from the `swiftui` lane and wants139to know *who keeps invalidating it*. Does a full pass over the causes140schema each time — cheap enough at typical trace sizes.141"""142if SCHEMA not in toc_schemas:143return {"available": False, "matches": []}144145needle = destination_contains.lower()146xml_bytes = xctrace.export_schema(trace_path, SCHEMA, run=run)147stream = xml_utils.RowStream(xml_bytes)148149matches: dict[str, Counter[str]] = defaultdict(Counter)150totals: Counter[str] = Counter()151152for row in stream:153time_el = xml_utils.first_present(row, "timestamp", "time")154if time_el is not None:155t_ns = xml_utils.int_text(stream.resolve(time_el))156if t_ns is not None and not xml_utils.in_window(t_ns, window):157continue158159dst = _fmt(row, stream, "destination-node")160if not dst or needle not in dst.lower():161continue162src = _fmt(row, stream, "source-node")163if not src:164continue165166matches[dst][src] += 1167totals[dst] += 1168169out = []170for dst, count in totals.most_common(top_k):171out.append({172"destination": dst,173"total_incoming_edges": count,174"top_sources": [175{"source": s, "edges": c}176for s, c in matches[dst].most_common(top_k)177],178})179return {"available": True, "matches": out}180181182def _fmt(row, stream, key: str) -> str | None:183el = row.get(key)184if el is None:185return None186resolved = stream.resolve(el)187return resolved.get("fmt") or xml_utils.str_text(resolved)188