Skip to content

Inspections

The bus will happily run with a Broadcast that nobody listens to or a ReactTo that no one ever triggers — structurally, those calls are just coroutines that never collect a value. That flexibility is load-bearing most of the time (a producer doesn’t care whether it has zero or ten consumers), but it means a typo, a deleted listener, or a missing provider can silently break a feature without any static error.

Navigator adds one inspection, enabled by default at warning level, that catches half-wired channels at edit time instead of at runtime.

The inspection flags six situations — all of them “one half of a channel with nothing on the other half”:

FlagWhat’s missing
Broadcast<T> with no listenersA ListenFor<T> somewhere.
ListenFor<T> with no sourcesA Broadcast<T> somewhere.
Trigger<A> with no reactorsA ReactTo<A> somewhere.
ReactTo<A> with no sourcesA Trigger<A> somewhere.
Request<I, N> with no providerA @SynapseProvider class for I.
@SynapseProvider with no callersA Request<I, N> somewhere.

Matching follows the same rules as the runtime bus — an interface or abstract type on either side counts as connected if any subtype satisfies the other half. A ReactTo<AnalyticsEvent> marker-interface consumer is considered connected as long as at least one concrete AnalyticsEvent subclass is actually being triggered somewhere, even if no call site uses the marker interface directly.

The warning surfaces in three places:

  • In the editor gutter — the gutter icon at the call site renders in the warning style instead of the normal style.
  • In the tool window — both Type Map and Flow Map sort unconnected entries to the top so they’re the first thing you see.
  • In the Problems panel — alongside other inspections, scoped to the module.

Because the check happens against the project-wide cache rather than just the current file, it catches “producer added, consumer forgotten” and “consumer added, producer forgotten” equally, which the IDE’s built-in reference-following can’t do on its own.

The inspection is configurable under **Settings > Editor > Inspections

Kotlin > Synapse Navigator > Unconnected SynapseLib channel**. You can disable it per-scope (for example, on a scratches module) or downgrade the severity from warning to weak warning if you want the gutter to stay clean and only surface the problem in the Problems panel.

If the inspection is flagging something you know to be correct — usually because a call site uses a domain-specific wrapper function that Navigator isn’t recognizing — the fix is upstream: add the wrapper’s name under Settings > Tools > SynapseLib as an alias for the base function, and both the inspection and the gutter will start picking up the wrapped call.

Every unconnected-channel warning ships with a Generate Counterpart quick fix (Alt+Enter). Invoking it inserts a TODO stub for the missing half of the channel:

  • On an unconnected Broadcast<SessionState>, it inserts a ListenFor<SessionState> { /* TODO */ } stub at an appropriate insertion point.
  • On an unconnected Trigger<AddItem>, it inserts a ReactTo<AddItem> { impulse -> /* TODO */ } stub.
  • On an unconnected Request<FetchFoo, Foo>, it inserts a @SynapseProvider class stub with the right superclass parameters and a produce override whose body is TODO().
  • On a @SynapseProvider with no callers, it inserts a Request<FetchFoo, Foo>() stub at the cursor.

The stub is not meant to be the finished wiring — it’s meant to be the shape of the missing half, placed somewhere the compiler will accept it, so you can immediately start filling in the real body. Navigator picks a reasonable insertion point (the current file for local counterparts, a nearby coordinator for cross-file ones), but the stub always lands as a normal edit you can undo or relocate.

The pragmatic workflow is: type the half you’re thinking about, accept the inspection’s warning as a reminder that the other half doesn’t exist yet, hit Alt+Enter, fill in the TODO, and move on. The inspection clears on the next incremental rescan.

  • Back to Arch — the architecture Navigator navigates.