UNPKG

@markandrus/effect-derive

Version:

Derive Covariant (Functor), Foldable, and Traversable instances, as well as base functors, for algebraic data types (ADTs)

57 lines (56 loc) 2.67 kB
import { Node, SyntaxKind } from 'ts-morph'; export function createRegistryMatcher(registry) { return function registryMatcher(holeName, tyNode) { switch (tyNode.getKind()) { case SyntaxKind.TypeReference: { const tyRefNode = tyNode.asKindOrThrow(SyntaxKind.TypeReference); const tyRefName = tyRefNode.getTypeName().print(); if (tyRefName === holeName) return []; const holeIndexAndMapFunction = registry.get(tyRefName); if (holeIndexAndMapFunction == null) return undefined; const [holeIndex, mapFunction] = holeIndexAndMapFunction; const tyArg = tyRefNode.getTypeArguments()[holeIndex]; if (tyArg == null) return undefined; const tail = registryMatcher(holeName, tyArg); if (tail == null) return undefined; return [mapFunction].concat(tail); } case SyntaxKind.ArrayType: { const tyArrayNode = tyNode.asKindOrThrow(SyntaxKind.ArrayType); const holeIndexAndMapFunction = registry.get('Array'); if (holeIndexAndMapFunction == null) return undefined; const mapFunction = holeIndexAndMapFunction[1]; const elemTyNode = tyArrayNode.getElementTypeNode(); const tail = registryMatcher(holeName, elemTyNode); if (tail == null) return undefined; return [mapFunction].concat(tail); } case SyntaxKind.TypeOperator: { const tyOpNode = tyNode.asKindOrThrow(SyntaxKind.TypeOperator); if (tyOpNode.getOperator() !== SyntaxKind.ReadonlyKeyword) return undefined; const tyNode2 = tyOpNode.getTypeNode(); if (Node.isArrayTypeNode(tyNode2)) { const holeIndexAndMapFunction = registry.get('ReadonlyArray'); if (holeIndexAndMapFunction == null) return undefined; const mapFunction = holeIndexAndMapFunction[1]; const elemTyNode = tyNode2.getElementTypeNode(); const tail = registryMatcher(holeName, elemTyNode); if (tail == null) return undefined; return [mapFunction].concat(tail); } return undefined; } default: return undefined; } }; }