From 7231815b34eea3b5ec23345338f2d62502948bb2 Mon Sep 17 00:00:00 2001 From: Sindre Gulseth Date: Thu, 22 Aug 2024 20:11:19 +0200 Subject: [PATCH] chore(typeEvaluator): rename mapConcrete to mapNode --- src/typeEvaluator/functions.ts | 58 +++++++++++++++---------------- src/typeEvaluator/typeEvaluate.ts | 34 +++++++++--------- src/typeEvaluator/typeHelpers.ts | 10 +++--- 3 files changed, 50 insertions(+), 52 deletions(-) diff --git a/src/typeEvaluator/functions.ts b/src/typeEvaluator/functions.ts index b24eaef..27b28b6 100644 --- a/src/typeEvaluator/functions.ts +++ b/src/typeEvaluator/functions.ts @@ -2,7 +2,7 @@ import type {FuncCallNode} from '../nodeTypes' import {Scope} from './scope' import {walk} from './typeEvaluate' -import {mapConcrete, nullUnion} from './typeHelpers' +import {mapNode, nullUnion} from './typeHelpers' import type {NullTypeNode, TypeNode} from './types' function unionWithoutNull(unionTypeNode: TypeNode): TypeNode { @@ -20,7 +20,7 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { case 'array.compact': { const arg = walk({node: node.args[0], scope}) - return mapConcrete(arg, scope, (arg) => { + return mapNode(arg, scope, (arg) => { if (arg.type === 'unknown') { return nullUnion({type: 'array', of: {type: 'unknown'}}) } @@ -28,7 +28,7 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { return {type: 'null'} } - const of = mapConcrete(arg.of, scope, (of) => of) + const of = mapNode(arg.of, scope, (of) => of) return { type: 'array', of: unionWithoutNull(of), @@ -40,8 +40,8 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { const arrayArg = walk({node: node.args[0], scope}) const sepArg = walk({node: node.args[1], scope}) - return mapConcrete(arrayArg, scope, (arrayArg) => - mapConcrete(sepArg, scope, (sepArg) => { + return mapNode(arrayArg, scope, (arrayArg) => + mapNode(sepArg, scope, (sepArg) => { if (arrayArg.type === 'unknown' || sepArg.type === 'unknown') { return nullUnion({type: 'string'}) } @@ -49,7 +49,7 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { return {type: 'null'} } - return mapConcrete(arrayArg.of, scope, (of) => { + return mapNode(arrayArg.of, scope, (of) => { // we can only join strings, numbers, and booleans if (of.type !== 'string' && of.type !== 'number' && of.type !== 'boolean') { return {type: 'unknown'} @@ -64,7 +64,7 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { case 'array.unique': { const arg = walk({node: node.args[0], scope}) - return mapConcrete(arg, scope, (arg) => { + return mapNode(arg, scope, (arg) => { if (arg.type === 'unknown') { return nullUnion({type: 'array', of: {type: 'unknown'}}) } @@ -79,7 +79,7 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { case 'global.lower': { const arg = walk({node: node.args[0], scope}) - return mapConcrete(arg, scope, (arg) => { + return mapNode(arg, scope, (arg) => { if (arg.type === 'unknown') { return nullUnion({type: 'string'}) } @@ -99,7 +99,7 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { case 'global.upper': { const arg = walk({node: node.args[0], scope}) - return mapConcrete(arg, scope, (arg) => { + return mapNode(arg, scope, (arg) => { if (arg.type === 'unknown') { return nullUnion({type: 'string'}) } @@ -126,7 +126,7 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { } case 'global.path': { const arg = walk({node: node.args[0], scope}) - return mapConcrete(arg, scope, (arg) => { + return mapNode(arg, scope, (arg) => { if (arg.type === 'unknown') { return nullUnion({type: 'string'}) } @@ -164,7 +164,7 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { case 'global.count': { const arg = walk({node: node.args[0], scope}) - return mapConcrete(arg, scope, (arg) => { + return mapNode(arg, scope, (arg) => { if (arg.type === 'unknown') { return nullUnion({type: 'string'}) } @@ -180,7 +180,7 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { case 'global.dateTime': { const arg = walk({node: node.args[0], scope}) - return mapConcrete(arg, scope, (arg) => { + return mapNode(arg, scope, (arg) => { if (arg.type === 'unknown') { return nullUnion({type: 'string'}) } @@ -200,7 +200,7 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { case 'global.round': { const numNode = walk({node: node.args[0], scope}) - return mapConcrete(numNode, scope, (num) => { + return mapNode(numNode, scope, (num) => { if (num.type === 'unknown') { return nullUnion({type: 'number'}) } @@ -210,7 +210,7 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { } if (node.args.length === 2) { const precisionNode = walk({node: node.args[1], scope}) - return mapConcrete(precisionNode, scope, (precision) => { + return mapNode(precisionNode, scope, (precision) => { if (precision.type === 'unknown') { return nullUnion({type: 'number'}) } @@ -229,7 +229,7 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { case 'global.string': { const arg = walk({node: node.args[0], scope}) - return mapConcrete(arg, scope, (node) => { + return mapNode(arg, scope, (node) => { if (node.type === 'unknown') { return nullUnion({type: 'string'}) } @@ -253,8 +253,8 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { case 'math.sum': { const values = walk({node: node.args[0], scope}) - // use mapConcrete to get concrete resolved value, it will also handle cases where the value is a union - return mapConcrete(values, scope, (node) => { + // use mapNode to get concrete resolved value, it will also handle cases where the value is a union + return mapNode(values, scope, (node) => { if (node.type === 'unknown') { return nullUnion({type: 'number'}) } @@ -265,7 +265,7 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { } // Resolve the concrete type of the array elements - return mapConcrete(node.of, scope, (node) => { + return mapNode(node.of, scope, (node) => { if (node.type === 'unknown') { return nullUnion({type: 'number'}) } @@ -281,8 +281,8 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { case 'math.avg': { const values = walk({node: node.args[0], scope}) - // use mapConcrete to get concrete resolved value, it will also handle cases where the value is a union - return mapConcrete(values, scope, (node) => { + // use mapNode to get concrete resolved value, it will also handle cases where the value is a union + return mapNode(values, scope, (node) => { if (node.type === 'unknown') { return nullUnion({type: 'number'}) } @@ -292,7 +292,7 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { return {type: 'null'} } // Resolve the concrete type of the array elements - return mapConcrete(node.of, scope, (node) => { + return mapNode(node.of, scope, (node) => { if (node.type === 'unknown') { return nullUnion({type: 'number'}) } @@ -309,8 +309,8 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { case 'math.max': case 'math.min': { const values = walk({node: node.args[0], scope}) - // use mapConcrete to get concrete resolved value, it will also handle cases where the value is a union - return mapConcrete(values, scope, (node) => { + // use mapNode to get concrete resolved value, it will also handle cases where the value is a union + return mapNode(values, scope, (node) => { if (node.type === 'unknown') { return nullUnion({type: 'number'}) } @@ -321,7 +321,7 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { } // Resolve the concrete type of the array elements - return mapConcrete(node.of, scope, (node) => { + return mapNode(node.of, scope, (node) => { if (node.type === 'unknown') { return nullUnion({type: 'number'}) } @@ -347,8 +347,8 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { case 'string.startsWith': { const strTypeNode = walk({node: node.args[0], scope}) const prefixTypeNode = walk({node: node.args[1], scope}) - return mapConcrete(strTypeNode, scope, (strNode) => { - return mapConcrete(prefixTypeNode, scope, (prefixNode) => { + return mapNode(strTypeNode, scope, (strNode) => { + return mapNode(prefixTypeNode, scope, (prefixNode) => { if (strNode.type === 'unknown' || prefixNode.type === 'unknown') { return nullUnion({type: 'boolean'}) } @@ -364,8 +364,8 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { case 'string.split': { const strTypeNode = walk({node: node.args[0], scope}) const sepTypeNode = walk({node: node.args[1], scope}) - return mapConcrete(strTypeNode, scope, (strNode) => { - return mapConcrete(sepTypeNode, scope, (sepNode) => { + return mapNode(strTypeNode, scope, (strNode) => { + return mapNode(sepTypeNode, scope, (sepNode) => { if (strNode.type === 'unknown' || sepNode.type === 'unknown') { return nullUnion({type: 'array', of: {type: 'string'}}) } @@ -380,7 +380,7 @@ export function handleFuncCallNode(node: FuncCallNode, scope: Scope): TypeNode { } case 'sanity.versionOf': { const typeNode = walk({node: node.args[0], scope}) - return mapConcrete(typeNode, scope, (typeNode) => { + return mapNode(typeNode, scope, (typeNode) => { if (typeNode.type === 'unknown') { return nullUnion({type: 'array', of: {type: 'string'}}) } diff --git a/src/typeEvaluator/typeEvaluate.ts b/src/typeEvaluator/typeEvaluate.ts index 21598cf..27e032a 100644 --- a/src/typeEvaluator/typeEvaluate.ts +++ b/src/typeEvaluator/typeEvaluate.ts @@ -32,7 +32,7 @@ import {handleFuncCallNode} from './functions' import {match} from './matching' import {optimizeUnions} from './optimizations' import {Context, Scope} from './scope' -import {isFuncCall, mapConcrete, nullUnion, resolveInline} from './typeHelpers' +import {isFuncCall, mapNode, nullUnion, resolveInline} from './typeHelpers' import type { ArrayTypeNode, BooleanTypeNode, @@ -123,7 +123,7 @@ function handleObjectSplatNode( ): TypeNode { const value = walk({node: attr.value, scope}) $trace('object.splat.value %O', value) - return mapConcrete(value, scope, (node) => { + return mapNode(value, scope, (node) => { // splatting over unknown is unknown, we can't know what the attributes are if (node.type === 'unknown') { return {type: 'unknown'} @@ -258,7 +258,7 @@ function handleObjectNode(node: ObjectNode, scope: Scope): TypeNode { } } - const variant = mapConcrete(attributeNode, scope, (attributeNode) => { + const variant = mapNode(attributeNode, scope, (attributeNode) => { $trace('object.conditional.splat.result.concrete %O', attributeNode) if (attributeNode.type !== 'object') { return {type: 'unknown'} @@ -462,9 +462,9 @@ function handleOpCallNode(node: OpCallNode, scope: Scope): TypeNode { $trace('opcall.node %O', node) const lhs = walk({node: node.left, scope}) const rhs = walk({node: node.right, scope}) - return mapConcrete(lhs, scope, (left) => + return mapNode(lhs, scope, (left) => // eslint-disable-next-line complexity, max-statements - mapConcrete(rhs, scope, (right) => { + mapNode(rhs, scope, (right) => { $trace('opcall.node.concrete "%s" %O', node.op, {left, right}) switch (node.op) { @@ -562,7 +562,7 @@ function handleOpCallNode(node: OpCallNode, scope: Scope): TypeNode { value: false, } satisfies BooleanTypeNode } - return mapConcrete(right.of, scope, (arrayTypeNode) => { + return mapNode(right.of, scope, (arrayTypeNode) => { if (arrayTypeNode.type === 'unknown') { return nullUnion({type: 'boolean'}) } @@ -773,7 +773,7 @@ function handleFlatMap(node: FlatMapNode, scope: Scope): TypeNode { return mapArray(base, scope, (base) => { const inner = walk({node: node.expr, scope: scope.createHidden([base.of])}) - return mapConcrete( + return mapNode( inner, scope, (inner) => { @@ -835,7 +835,7 @@ function handleFilterNode(node: FilterNode, scope: Scope): TypeNode { const base = walk({node: node.base, scope}) $trace('filter.base %O', base) - return mapConcrete(base, scope, (base) => { + return mapNode(base, scope, (base) => { $trace('filter.resolving %O', base) if (base.type === 'null') { return base @@ -988,7 +988,7 @@ function handleParentNode({n}: ParentNode, scope: Scope): TypeNode { function handleNotNode(node: NotNode, scope: Scope): TypeNode { const base = walk({node: node.base, scope}) - return mapConcrete(base, scope, (base) => { + return mapNode(base, scope, (base) => { if (base.type === 'unknown') { return nullUnion({type: 'boolean'}) } @@ -1006,7 +1006,7 @@ function handleNotNode(node: NotNode, scope: Scope): TypeNode { function handleNegNode(node: NegNode, scope: Scope): TypeNode { const base = walk({node: node.base, scope}) - return mapConcrete(base, scope, (base) => { + return mapNode(base, scope, (base) => { if (base.type === 'unknown') { return nullUnion({type: 'number'}) } @@ -1022,7 +1022,7 @@ function handleNegNode(node: NegNode, scope: Scope): TypeNode { } function handlePosNode(node: PosNode, scope: Scope): TypeNode { const base = walk({node: node.base, scope}) - return mapConcrete(base, scope, (base) => { + return mapNode(base, scope, (base) => { if (base.type === 'unknown') { return nullUnion({type: 'number'}) } @@ -1051,8 +1051,8 @@ function handleEverythingNode(_: EverythingNode, scope: Scope): TypeNode { function handleAndNode(node: AndNode, scope: Scope): TypeNode { const left = walk({node: node.left, scope}) const right = walk({node: node.right, scope}) - return mapConcrete(left, scope, (lhs) => - mapConcrete(right, scope, (rhs) => { + return mapNode(left, scope, (lhs) => + mapNode(right, scope, (rhs) => { const value = booleanAnd(booleanValue(lhs, scope), booleanValue(rhs, scope)) return booleanInterpretationToTypeNode(value) @@ -1063,8 +1063,8 @@ function handleAndNode(node: AndNode, scope: Scope): TypeNode { function handleOrNode(node: OrNode, scope: Scope): TypeNode { const left = walk({node: node.left, scope}) const right = walk({node: node.right, scope}) - return mapConcrete(left, scope, (lhs) => - mapConcrete(right, scope, (rhs) => { + return mapNode(left, scope, (lhs) => + mapNode(right, scope, (rhs) => { const value = booleanOr(booleanValue(lhs, scope), booleanValue(rhs, scope)) return booleanInterpretationToTypeNode(value) @@ -1266,7 +1266,7 @@ function mapArray( scope: Scope, mapper: (node: ArrayTypeNode) => TypeNode, ): TypeNode { - return mapConcrete(node, scope, (base) => { + return mapNode(node, scope, (base) => { if (base.type === 'unknown') { return base } @@ -1282,7 +1282,7 @@ function mapObject( scope: Scope, mapper: (node: ObjectTypeNode) => TypeNode, ): TypeNode { - return mapConcrete(node, scope, (base) => { + return mapNode(node, scope, (base) => { if (base.type === 'unknown') { return base } diff --git a/src/typeEvaluator/typeHelpers.ts b/src/typeEvaluator/typeHelpers.ts index 6192dec..b35a0c2 100644 --- a/src/typeEvaluator/typeHelpers.ts +++ b/src/typeEvaluator/typeHelpers.ts @@ -96,14 +96,12 @@ export function resolveInline(node: TypeNode, scope: Scope): Exclude( +export function mapNode( node: TypeNode, scope: Scope, mapper: (node: ConcreteTypeNode | UnknownTypeNode) => T, @@ -120,10 +118,10 @@ export function mapConcrete( case 'unknown': return mapper(node) case 'union': - return mergeUnions(node.of.map((inner) => mapConcrete(inner, scope, mapper), mergeUnions)) + return mergeUnions(node.of.map((inner) => mapNode(inner, scope, mapper), mergeUnions)) case 'inline': { const resolvedInline = resolveInline(node, scope) - return mapConcrete(resolvedInline, scope, mapper, mergeUnions) + return mapNode(resolvedInline, scope, mapper, mergeUnions) } default: // @ts-expect-error - all types should be handled