IDE Extensions
Inlay hint extensions for VSCode and Rider/ReSharper. Both show TIn -> TOut types inline for each chain call.
What They Show
Given a train chain:
protected override async Task<Either<Exception, OrderReceipt>> RunInternal(OrderRequest input)
=> Activate(input)
.Chain<CheckInventoryJunction>()
.Chain<ChargePaymentJunction>()
.Chain<CreateShipmentJunction>()
.Resolve();The extensions annotate each junction with its resolved types:
.Chain<CheckInventoryJunction>() // OrderRequest -> InventoryResult
.Chain<ChargePaymentJunction>() // InventoryResult -> PaymentConfirmation
.Chain<CreateShipmentJunction>() // PaymentConfirmation -> OrderReceipt
Supported Methods
.Chain<TJunction>().ShortCircuit<TJunction>()
Type Resolution
Types are resolved by walking the junction's type hierarchy to find IJunction<TIn, TOut>. This handles:
- Direct inheritance:
class MyJunction : Junction<string, int> - Primary constructors:
class MyJunction(ILogger logger) : EffectJunction<string, int> - Nested generics:
EffectJunction<Unit, List<Manifest>> - Tuple types:
EffectJunction<(List<A>, List<B>), List<C>>
VSCode
Source: plugins/vscode/trax-hints/
Installation
Install from the VSCode Marketplace
Internals
Activates on C# files. Uses regex to find chain calls, then calls VSCode's definition provider to jump to each junction's source file and extract the generic arguments from the class definition.
Resolved types are cached per junction class. The cache clears when any .cs file is modified.
Rider / ReSharper
Source: plugins/rider-resharper/
Installation
Search for Trax.Core Chain Hints in JetBrains Marketplace.
Or build from source:
cd plugins/rider-resharper
./gradlew buildPluginOutput is in build/distributions/.
Internals
Uses JetBrains' PSI (Program Structure Interface) for type resolution. A daemon analyzer (ElementProblemAnalyzer<IInvocationExpression>) fires on each invocation expression and:
- Checks if the method name is
ChainorShortCircuit - Extracts the type argument from the generic call
- Walks the junction's super-type hierarchy to find
IJunction<TIn, TOut> - Places a
TIn -> TOuthint after the closing parenthesis
PSI resolution is fully semantic — generics, inheritance chains, and type substitution are handled correctly without regex.
Architecture
Dual-targeting project:
- ReSharper (.NET 4.7.2): Standalone extension
- Rider (Kotlin + .NET): .NET analysis runs in Rider's backend; Kotlin handles IDE integration
Both targets share the C# analysis code in src/dotnet/ReSharperPlugin.Trax.Core/.