From d9a1d4c41a59b96d90e6407d92c27d834a8d3414 Mon Sep 17 00:00:00 2001 From: Misode Date: Thu, 24 Oct 2024 01:21:53 +0200 Subject: [PATCH] Implement enums and unions --- .../components/generator/McdocRenderer.tsx | 132 +++++++++++++++--- 1 file changed, 112 insertions(+), 20 deletions(-) diff --git a/src/app/components/generator/McdocRenderer.tsx b/src/app/components/generator/McdocRenderer.tsx index 4f9d2ee5..a1787746 100644 --- a/src/app/components/generator/McdocRenderer.tsx +++ b/src/app/components/generator/McdocRenderer.tsx @@ -2,9 +2,9 @@ import * as core from '@spyglassmc/core' import type { JsonNode } from '@spyglassmc/json' import * as json from '@spyglassmc/json' import { JsonArrayNode, JsonBooleanNode, JsonNumberNode, JsonObjectNode, JsonStringNode } from '@spyglassmc/json' -import type { ListType, LiteralType, McdocType, NumericType, PrimitiveArrayType } from '@spyglassmc/mcdoc' +import type { ListType, LiteralType, McdocType, NumericType, PrimitiveArrayType, UnionType } from '@spyglassmc/mcdoc' import { TypeDefSymbolData } from '@spyglassmc/mcdoc/lib/binder/index.js' -import type { McdocCheckerContext, SimplifiedMcdocType, SimplifiedStructType, SimplifyValueNode } from '@spyglassmc/mcdoc/lib/runtime/checker/index.js' +import type { McdocCheckerContext, SimplifiedEnum, SimplifiedMcdocType, SimplifiedMcdocTypeNoUnion, SimplifiedStructType, SimplifyValueNode } from '@spyglassmc/mcdoc/lib/runtime/checker/index.js' import { simplify } from '@spyglassmc/mcdoc/lib/runtime/checker/index.js' import { useCallback } from 'preact/hooks' import { useLocale } from '../../contexts/Locale.jsx' @@ -44,13 +44,7 @@ function Head({ type, optional, node, makeEdit, ctx }: HeadProps) { return } if (type.kind === 'enum') { - const value = JsonStringNode.is(node) ? node.value : undefined - return + return } if (type.kind === 'byte' || type.kind === 'short' || type.kind === 'int' || type.kind === 'long' || type.kind === 'float' || type.kind === 'double') { return @@ -59,11 +53,7 @@ function Head({ type, optional, node, makeEdit, ctx }: HeadProps) { return } if (type.kind === 'union') { - return + return } if (type.kind === 'struct' && optional) { if (node && JsonObjectNode.is(node)) { @@ -86,16 +76,19 @@ function Head({ type, optional, node, makeEdit, ctx }: HeadProps) { function StringHead({ node, makeEdit }: Props) { const value = JsonStringNode.is(node) ? node.value : undefined - const onChangeValue = useCallback((value: string) => { + const onChangeValue = useCallback((newValue: string) => { + if (value === newValue) { + return + } makeEdit((range) => { - if (value.length === 0) { + if (newValue.length === 0) { return undefined } return { type: 'json:string', range, options: json.parser.JsonStringOptions, - value: value, + value: newValue, valueMap: [{ inner: core.Range.create(0), outer: core.Range.create(range.start) }], } }) @@ -104,6 +97,53 @@ function StringHead({ node, makeEdit }: Props) { return onChangeValue((e.target as HTMLInputElement).value)} /> } +interface EnumHeadProps extends HeadProps { + type: SimplifiedEnum, +} +function EnumHead({ type, optional, node, makeEdit }: EnumHeadProps) { + const value = JsonStringNode.is(node) ? node.value : undefined + + const onChangeValue = useCallback((newValue: string) => { + if (value === newValue) { + return + } + makeEdit((range) => { + if (newValue === '__unset__') { + return undefined + } + if (type.enumKind === 'string') { + return { + type: 'json:string', + range, + options: json.parser.JsonStringOptions, + value: newValue, + valueMap: [{ inner: core.Range.create(0), outer: core.Range.create(range.start) }], + } + } + const number: core.FloatNode = { + type: 'float', + range, + value: parseFloat(newValue), + } + const result: JsonNumberNode = { + type: 'json:number', + range, + children: [number], + value: number, + } + number.parent = result + return result + }) + }, [type.enumKind, value, makeEdit]) + + return +} + interface NumericHeadProps extends Props { type: NumericType, } @@ -160,6 +200,35 @@ function BooleanHead({ node, makeEdit }: Props) { } +interface UnionHeadProps extends HeadProps { + type: UnionType +} +function UnionHead({ type, optional, node, makeEdit, ctx }: UnionHeadProps) { + const selectedType = node?.typeDef + + const onSelect = useCallback((newValue: string) => { + makeEdit((range) => { + if (newValue === '__unset__') { + return undefined + } + const newSelected = type.members[parseInt(newValue)] + return getDefault(newSelected, range, ctx) + }) + }, [type, makeEdit, ctx]) + + const memberIndex = selectedType ? type.members.findIndex(m => quickEqualTypes(m, selectedType)) : -1 + + return <> + + {(selectedType || !optional) && } + +} + interface ListHeadProps extends Props { type: ListType | PrimitiveArrayType, } @@ -199,7 +268,7 @@ function ListHead({ type, node, makeEdit, ctx }: ListHeadProps) { return newArray }) } - }, [type, node, makeEdit, canAdd]) + }, [type, node, makeEdit, ctx, canAdd]) return