From b3e72bf67d6ec8c9f5ef1dc117b85287c4054aef Mon Sep 17 00:00:00 2001 From: Alec Larson <1925840+aleclarson@users.noreply.github.com> Date: Mon, 11 Nov 2024 11:45:16 -0500 Subject: [PATCH] refactor: move nodeFields.json into ./scripts/data/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit …and map the field data from tuples into objects. --- .../data/fieldMetadata.json | 0 scripts/data/fieldMetadata.ts | 28 +++++++++++++++++++ scripts/generateTypes.ts | 22 ++++++--------- scripts/inferFieldMetadata.ts | 12 +++++--- 4 files changed, 45 insertions(+), 17 deletions(-) rename nodeFields.json => scripts/data/fieldMetadata.json (100%) create mode 100644 scripts/data/fieldMetadata.ts diff --git a/nodeFields.json b/scripts/data/fieldMetadata.json similarity index 100% rename from nodeFields.json rename to scripts/data/fieldMetadata.json diff --git a/scripts/data/fieldMetadata.ts b/scripts/data/fieldMetadata.ts new file mode 100644 index 0000000..579c03e --- /dev/null +++ b/scripts/data/fieldMetadata.ts @@ -0,0 +1,28 @@ +import fs from 'node:fs' +import path from 'node:path' +import { mapValues } from 'radashi' +import type { NodeFieldMetadataByTag } from '../inferFieldMetadata' + +const dataDir = new URL('.', import.meta.url).pathname +const data = mapValues( + JSON.parse( + fs.readFileSync(path.join(dataDir, 'fieldMetadata.json'), 'utf8'), + ) as NodeFieldMetadataByTag, + fieldMap => + mapValues(fieldMap!, ([nullable, tags, listTags]) => ({ + nullable, + tags, + listTags, + })), +) + +/** + * Field metadata is inferred from test cases sourced from the libpg_query + * repository. Check out the {@link ../inferFieldMetadata.ts inferFieldMetadata} + * module for more details. + */ +export const fieldMetadataMap = data as { + [typeName: string]: { + [fieldName: string]: typeof data[string][string] | undefined + } | undefined +} diff --git a/scripts/generateTypes.ts b/scripts/generateTypes.ts index 88be6ea..2c138aa 100644 --- a/scripts/generateTypes.ts +++ b/scripts/generateTypes.ts @@ -3,15 +3,10 @@ import path from 'node:path' import { bitMasks } from './data/bitMasks' import { expressionFields } from './data/expressionFields' import { expressionTypes } from './data/expressionTypes' +import { fieldMetadataMap } from './data/fieldMetadata' import { nullableFields } from './data/nullableFields' import { skippedEntities } from './data/skippedEntities' import { typeMappings } from './data/typeMappings' -import type { NodeFieldMetadataByTag } from './inferFieldMetadata' - -/** A record of node tag -> field name -> nullability */ -const nodeFieldsByTag: NodeFieldMetadataByTag = JSON.parse( - fs.readFileSync('nodeFields.json', 'utf8'), -) type StructsByModule = Record> type EnumsByModule = Record> @@ -63,8 +58,9 @@ function formatComment( } function readSrcData(fileName: string): T { - const filePath = path.join(__dirname, '../libpg_query/srcdata', fileName) - const content = fs.readFileSync(filePath, 'utf-8') + const scriptDir = new URL('.', import.meta.url).pathname + const dataPath = path.join(scriptDir, '../libpg_query/srcdata', fileName) + const content = fs.readFileSync(dataPath, 'utf-8') return JSON.parse(content) as T } @@ -246,7 +242,7 @@ async function main() { constTypes.push(`{ ${namedFields[0].name}: ${typeName} }`) } - const fieldMetadata = nodeFieldsByTag[typeName] + const fieldMetadata = fieldMetadataMap[typeName] if (!fieldMetadata) { // If field metadata could not be inferred from libpg_query's test // suite, then it's likely not a node type. @@ -295,7 +291,7 @@ async function main() { const debugTags = false if (fieldType === 'any' || fieldType === 'Node') { - const inferredTags = fieldMetadata?.[fieldName]?.[1] + const inferredTags = fieldMetadata?.[fieldName]?.tags if (inferredTags) { if (debugTags) { console.log('Inferred tags for %s:', fieldPath, inferredTags) @@ -303,7 +299,7 @@ async function main() { fieldType = renderTagTypes(inferredTags, fieldPath) } } else if (fieldType === 'any[]') { - const inferredListTags = fieldMetadata?.[fieldName]?.[2] + const inferredListTags = fieldMetadata?.[fieldName]?.listTags if (inferredListTags) { if (debugTags) { console.log( @@ -321,7 +317,7 @@ async function main() { } } if (fieldType === 'any[]' && field.c_type === 'List*') { - const inferredTags = fieldMetadata?.[fieldName]?.[1] + const inferredTags = fieldMetadata?.[fieldName]?.tags if (inferredTags) { if (debugTags) { console.log('Inferred tags for %s:', fieldPath, inferredTags) @@ -343,7 +339,7 @@ async function main() { const nullable = (fieldMetadata - ? fieldMetadata[fieldName]?.[0] ?? true + ? fieldMetadata[fieldName]?.nullable ?? true : /\b(NULL|NIL|if any)\b/.test(field.comment ?? '')) || nullableFields.has(fieldPath) diff --git a/scripts/inferFieldMetadata.ts b/scripts/inferFieldMetadata.ts index 9bd7733..0ecb35a 100644 --- a/scripts/inferFieldMetadata.ts +++ b/scripts/inferFieldMetadata.ts @@ -17,9 +17,9 @@ export type NodeFieldMetadata = [ ] export type NodeFieldMetadataByTag = { - [typeName: string]: - | { [fieldName: string]: NodeFieldMetadata | undefined } - | undefined + [typeName: string]: { + [fieldName: string]: NodeFieldMetadata + } } const fieldsByNodeTag: NodeFieldMetadataByTag = {} @@ -93,4 +93,8 @@ for (const testFile of testFiles) { } catch {} } -fs.writeFileSync('nodeFields.json', JSON.stringify(fieldsByNodeTag, null, 2)) +const scriptDir = new URL('.', import.meta.url).pathname +fs.writeFileSync( + path.join(scriptDir, 'data/fieldMetadata.json'), + JSON.stringify(fieldsByNodeTag, null, 2), +)