diff --git a/.github/workflows/gentool-schema.yml b/.github/workflows/gentool-schema.yml new file mode 100644 index 00000000..0371454d --- /dev/null +++ b/.github/workflows/gentool-schema.yml @@ -0,0 +1,33 @@ +name: GenTool JSON schema validation + +permissions: + contents: read + +on: + pull_request: + branches: + - main + workflow_dispatch: + +jobs: + validate_gentool_schema: + runs-on: ubuntu-latest + defaults: + run: + working-directory: sdk/gentool + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: 'lts/*' + + - name: Install dependencies + run: npm ci + + - name: Validate GenTool enum/interface JSON against schema + run: npm run validate:schemas + diff --git a/.vscode/settings.json b/.vscode/settings.json index 25771eb7..949978ae 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -24,5 +24,14 @@ "**/sdk/platform/Web/src/**/*.hpp": "cpp", "**/sdk/platform/Web/src/**/*.c": "c", "**/sdk/platform/Web/src/**/*.cpp": "cpp" - } + }, + "json.schemas": [ + { + "fileMatch": [ + "**/enum/*.json", + "**/interface/*.json" + ], + "url": "./sdk/gentool/gentool.schema.json" + } + ] } diff --git a/sdk/gentool/README.md b/sdk/gentool/README.md index 292e74be..35025c33 100644 --- a/sdk/gentool/README.md +++ b/sdk/gentool/README.md @@ -1,5 +1,40 @@ # GenTool +GenTool generates C, C++, Objective-C, Swift, and JavaScript bindings from `enum/*.json` and `interface/*.json` definitions. + +## Quick reference + +### Scripts + +| Command | Description | +|---------|-------------| +| `npm run generate` | Generate code from enum/interface JSON and update `gentool.schema.generated.json` | +| `npm run validate:schemas` | Validate all enum/interface JSON files against the schema | + +### Workflow: adding a new interface or enum + +1. Create `interface/MyClass.json` or `enum/MyEnum.json` +2. Run `npm run generate` +3. Commit the generated code and `gentool.schema.generated.json` + +### Schema & IDE support + +- **`gentool.schema.json`** — JSON Schema for enum/interface definitions. Editors (e.g. VS Code) use it for validation and autocomplete. +- **`gentool.schema.generated.json`** — Generated list of valid parameterized types (`CLASS_MIX:Vector3`, `ENUM:SolvePnPMethod`, etc.). Regenerated by `npm run generate`. +- **Validation** — CI runs `validate:schemas` on PRs. Run it locally before committing. + +### Common property patterns + +| Pattern | Example | +|---------|---------| +| Simple property | `{ "name": "X", "type": "float" }` | +| Read-only computed | `{ "name": "Length", "type": "float", "getterCustom": true, "hasSetter": false, "hasMemberVar": false }` | +| Class reference | `{ "name": "Position", "type": "CLASS_MIX:Vector3" }` | +| Enum | `{ "name": "Format", "type": "ENUM:ArucoMarkerFormat" }` | +| Array | `{ "name": "Points", "type": "ARRAY_REF:Vector2" }` | + +--- + ## JSON documentation ### Root JSON options diff --git a/sdk/gentool/generate-schema-fragment.js b/sdk/gentool/generate-schema-fragment.js new file mode 100644 index 00000000..4c0a42c8 --- /dev/null +++ b/sdk/gentool/generate-schema-fragment.js @@ -0,0 +1,102 @@ +/** + * Generates gentool.schema.generated.json with enum values for parameterized types + * (CLASS_MIX:Vector3, ENUM:SolvePnPMethod, etc.) so editors can autocomplete them. + * + * Run as part of `npm run generate`. + */ +const fs = require('fs'); +const path = require('path'); +const shared = require('./shared'); + +const PRIMITIVES = [ + 'int8', 'int16', 'int32', 'int64', + 'uint8', 'uint16', 'uint32', 'uint64', + 'float', 'double', 'boolean', 'string' +]; + +const CLASS_PREFIXES = ['CLASS', 'CLASS_REF', 'CLASS_MIX', 'CLASS_PTR', 'CLASS_PTR_REF', 'CLASS_PTR_MIX']; +const ARRAY_PREFIXES = ['ARRAY', 'ARRAY_REF', 'ARRAY_MIX', 'ARRAY_PTR', 'ARRAY_PTR_REF', 'ARRAY_PTR_MIX']; + +const PARAM_CLASS_PREFIXES = ['CLASS', 'CLASS_REF', 'CLASS_PTR', 'CLASS_PTR_REF']; +const PARAM_ARRAY_PREFIXES = ['ARRAY', 'ARRAY_REF', 'ARRAY_PTR', 'ARRAY_PTR_REF']; + +function collectNames(dir, subdir = '') { + const dirPath = path.resolve(__dirname, '..', dir, subdir); + if (!fs.existsSync(dirPath)) return []; + return fs.readdirSync(dirPath, 'utf8') + .filter((f) => f.toLowerCase().endsWith('.json')) + .map((f) => path.basename(f, '.json')); +} + +function main() { + const enumNames = collectNames('enum'); + if (!shared.ignoreCompileTests && fs.existsSync(path.resolve(__dirname, '..', 'enum', 'CompileTests'))) { + enumNames.push(...collectNames('enum', 'CompileTests')); + } + + const interfaceNames = collectNames('interface'); + if (!shared.ignoreCompileTests && fs.existsSync(path.resolve(__dirname, '..', 'interface', 'CompileTests'))) { + interfaceNames.push(...collectNames('interface', 'CompileTests')); + } + + const allTypeNames = [...new Set([...interfaceNames, ...enumNames])]; + + const typeKeyEnum = []; + for (const prefix of CLASS_PREFIXES) { + for (const name of interfaceNames) { + typeKeyEnum.push(`${prefix}:${name}`); + } + } + for (const name of enumNames) { + typeKeyEnum.push(`ENUM:${name}`); + } + for (const prefix of ARRAY_PREFIXES) { + for (const p of PRIMITIVES) { + typeKeyEnum.push(`${prefix}:${p}`); + } + for (const name of allTypeNames) { + typeKeyEnum.push(`${prefix}:${name}`); + } + } + + const paramTypeKeyEnum = []; + for (const prefix of PARAM_CLASS_PREFIXES) { + for (const name of interfaceNames) { + paramTypeKeyEnum.push(`${prefix}:${name}`); + } + } + for (const name of enumNames) { + paramTypeKeyEnum.push(`ENUM:${name}`); + } + for (const prefix of PARAM_ARRAY_PREFIXES) { + for (const p of PRIMITIVES) { + paramTypeKeyEnum.push(`${prefix}:${p}`); + } + for (const name of allTypeNames) { + paramTypeKeyEnum.push(`${prefix}:${name}`); + } + } + + const generated = { + '$schema': 'https://json-schema.org/draft/2020-12/schema', + '$id': 'https://posemesh.auki.dev/schemas/gentool.schema.generated.json', + 'title': 'Generated type enums for GenTool schema', + '$defs': { + 'ParameterizedTypeKey': { + 'type': 'string', + 'enum': typeKeyEnum.sort() + }, + 'ParameterizedParamTypeKey': { + 'type': 'string', + 'enum': paramTypeKeyEnum.sort() + } + } + }; + + const outPath = path.resolve(__dirname, 'gentool.schema.generated.json'); + const content = JSON.stringify(generated, null, 2) + '\n'; + fs.writeFileSync(outPath, content, 'utf8'); + console.log('Generated gentool.schema.generated.json'); +} + +main(); diff --git a/sdk/gentool/gentool.schema.generated.json b/sdk/gentool/gentool.schema.generated.json new file mode 100644 index 00000000..7488186a --- /dev/null +++ b/sdk/gentool/gentool.schema.generated.json @@ -0,0 +1,497 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://posemesh.auki.dev/schemas/gentool.schema.generated.json", + "title": "Generated type enums for GenTool schema", + "$defs": { + "ParameterizedTypeKey": { + "type": "string", + "enum": [ + "ARRAY:ArucoMarkerFormat", + "ARRAY:CompileTestClassShowcaseAllMemberPropTypes", + "ARRAY:CompileTestClassShowcaseAllStaticPropTypes", + "ARRAY:CompileTestDummyClass", + "ARRAY:CompileTestExampleEnum", + "ARRAY:CompileTestExampleFlags", + "ARRAY:CompileTestExampleFlags2", + "ARRAY:CompileTestFunctions", + "ARRAY:CompileTestMethods", + "ARRAY:Landmark", + "ARRAY:LandmarkObservation", + "ARRAY:Matrix2x2", + "ARRAY:Matrix3x3", + "ARRAY:Matrix4x4", + "ARRAY:Pose", + "ARRAY:Quaternion", + "ARRAY:SolvePnPMethod", + "ARRAY:Vector2", + "ARRAY:Vector3", + "ARRAY:Vector4", + "ARRAY:boolean", + "ARRAY:double", + "ARRAY:float", + "ARRAY:int16", + "ARRAY:int32", + "ARRAY:int64", + "ARRAY:int8", + "ARRAY:string", + "ARRAY:uint16", + "ARRAY:uint32", + "ARRAY:uint64", + "ARRAY:uint8", + "ARRAY_MIX:ArucoMarkerFormat", + "ARRAY_MIX:CompileTestClassShowcaseAllMemberPropTypes", + "ARRAY_MIX:CompileTestClassShowcaseAllStaticPropTypes", + "ARRAY_MIX:CompileTestDummyClass", + "ARRAY_MIX:CompileTestExampleEnum", + "ARRAY_MIX:CompileTestExampleFlags", + "ARRAY_MIX:CompileTestExampleFlags2", + "ARRAY_MIX:CompileTestFunctions", + "ARRAY_MIX:CompileTestMethods", + "ARRAY_MIX:Landmark", + "ARRAY_MIX:LandmarkObservation", + "ARRAY_MIX:Matrix2x2", + "ARRAY_MIX:Matrix3x3", + "ARRAY_MIX:Matrix4x4", + "ARRAY_MIX:Pose", + "ARRAY_MIX:Quaternion", + "ARRAY_MIX:SolvePnPMethod", + "ARRAY_MIX:Vector2", + "ARRAY_MIX:Vector3", + "ARRAY_MIX:Vector4", + "ARRAY_MIX:boolean", + "ARRAY_MIX:double", + "ARRAY_MIX:float", + "ARRAY_MIX:int16", + "ARRAY_MIX:int32", + "ARRAY_MIX:int64", + "ARRAY_MIX:int8", + "ARRAY_MIX:string", + "ARRAY_MIX:uint16", + "ARRAY_MIX:uint32", + "ARRAY_MIX:uint64", + "ARRAY_MIX:uint8", + "ARRAY_PTR:ArucoMarkerFormat", + "ARRAY_PTR:CompileTestClassShowcaseAllMemberPropTypes", + "ARRAY_PTR:CompileTestClassShowcaseAllStaticPropTypes", + "ARRAY_PTR:CompileTestDummyClass", + "ARRAY_PTR:CompileTestExampleEnum", + "ARRAY_PTR:CompileTestExampleFlags", + "ARRAY_PTR:CompileTestExampleFlags2", + "ARRAY_PTR:CompileTestFunctions", + "ARRAY_PTR:CompileTestMethods", + "ARRAY_PTR:Landmark", + "ARRAY_PTR:LandmarkObservation", + "ARRAY_PTR:Matrix2x2", + "ARRAY_PTR:Matrix3x3", + "ARRAY_PTR:Matrix4x4", + "ARRAY_PTR:Pose", + "ARRAY_PTR:Quaternion", + "ARRAY_PTR:SolvePnPMethod", + "ARRAY_PTR:Vector2", + "ARRAY_PTR:Vector3", + "ARRAY_PTR:Vector4", + "ARRAY_PTR:boolean", + "ARRAY_PTR:double", + "ARRAY_PTR:float", + "ARRAY_PTR:int16", + "ARRAY_PTR:int32", + "ARRAY_PTR:int64", + "ARRAY_PTR:int8", + "ARRAY_PTR:string", + "ARRAY_PTR:uint16", + "ARRAY_PTR:uint32", + "ARRAY_PTR:uint64", + "ARRAY_PTR:uint8", + "ARRAY_PTR_MIX:ArucoMarkerFormat", + "ARRAY_PTR_MIX:CompileTestClassShowcaseAllMemberPropTypes", + "ARRAY_PTR_MIX:CompileTestClassShowcaseAllStaticPropTypes", + "ARRAY_PTR_MIX:CompileTestDummyClass", + "ARRAY_PTR_MIX:CompileTestExampleEnum", + "ARRAY_PTR_MIX:CompileTestExampleFlags", + "ARRAY_PTR_MIX:CompileTestExampleFlags2", + "ARRAY_PTR_MIX:CompileTestFunctions", + "ARRAY_PTR_MIX:CompileTestMethods", + "ARRAY_PTR_MIX:Landmark", + "ARRAY_PTR_MIX:LandmarkObservation", + "ARRAY_PTR_MIX:Matrix2x2", + "ARRAY_PTR_MIX:Matrix3x3", + "ARRAY_PTR_MIX:Matrix4x4", + "ARRAY_PTR_MIX:Pose", + "ARRAY_PTR_MIX:Quaternion", + "ARRAY_PTR_MIX:SolvePnPMethod", + "ARRAY_PTR_MIX:Vector2", + "ARRAY_PTR_MIX:Vector3", + "ARRAY_PTR_MIX:Vector4", + "ARRAY_PTR_MIX:boolean", + "ARRAY_PTR_MIX:double", + "ARRAY_PTR_MIX:float", + "ARRAY_PTR_MIX:int16", + "ARRAY_PTR_MIX:int32", + "ARRAY_PTR_MIX:int64", + "ARRAY_PTR_MIX:int8", + "ARRAY_PTR_MIX:string", + "ARRAY_PTR_MIX:uint16", + "ARRAY_PTR_MIX:uint32", + "ARRAY_PTR_MIX:uint64", + "ARRAY_PTR_MIX:uint8", + "ARRAY_PTR_REF:ArucoMarkerFormat", + "ARRAY_PTR_REF:CompileTestClassShowcaseAllMemberPropTypes", + "ARRAY_PTR_REF:CompileTestClassShowcaseAllStaticPropTypes", + "ARRAY_PTR_REF:CompileTestDummyClass", + "ARRAY_PTR_REF:CompileTestExampleEnum", + "ARRAY_PTR_REF:CompileTestExampleFlags", + "ARRAY_PTR_REF:CompileTestExampleFlags2", + "ARRAY_PTR_REF:CompileTestFunctions", + "ARRAY_PTR_REF:CompileTestMethods", + "ARRAY_PTR_REF:Landmark", + "ARRAY_PTR_REF:LandmarkObservation", + "ARRAY_PTR_REF:Matrix2x2", + "ARRAY_PTR_REF:Matrix3x3", + "ARRAY_PTR_REF:Matrix4x4", + "ARRAY_PTR_REF:Pose", + "ARRAY_PTR_REF:Quaternion", + "ARRAY_PTR_REF:SolvePnPMethod", + "ARRAY_PTR_REF:Vector2", + "ARRAY_PTR_REF:Vector3", + "ARRAY_PTR_REF:Vector4", + "ARRAY_PTR_REF:boolean", + "ARRAY_PTR_REF:double", + "ARRAY_PTR_REF:float", + "ARRAY_PTR_REF:int16", + "ARRAY_PTR_REF:int32", + "ARRAY_PTR_REF:int64", + "ARRAY_PTR_REF:int8", + "ARRAY_PTR_REF:string", + "ARRAY_PTR_REF:uint16", + "ARRAY_PTR_REF:uint32", + "ARRAY_PTR_REF:uint64", + "ARRAY_PTR_REF:uint8", + "ARRAY_REF:ArucoMarkerFormat", + "ARRAY_REF:CompileTestClassShowcaseAllMemberPropTypes", + "ARRAY_REF:CompileTestClassShowcaseAllStaticPropTypes", + "ARRAY_REF:CompileTestDummyClass", + "ARRAY_REF:CompileTestExampleEnum", + "ARRAY_REF:CompileTestExampleFlags", + "ARRAY_REF:CompileTestExampleFlags2", + "ARRAY_REF:CompileTestFunctions", + "ARRAY_REF:CompileTestMethods", + "ARRAY_REF:Landmark", + "ARRAY_REF:LandmarkObservation", + "ARRAY_REF:Matrix2x2", + "ARRAY_REF:Matrix3x3", + "ARRAY_REF:Matrix4x4", + "ARRAY_REF:Pose", + "ARRAY_REF:Quaternion", + "ARRAY_REF:SolvePnPMethod", + "ARRAY_REF:Vector2", + "ARRAY_REF:Vector3", + "ARRAY_REF:Vector4", + "ARRAY_REF:boolean", + "ARRAY_REF:double", + "ARRAY_REF:float", + "ARRAY_REF:int16", + "ARRAY_REF:int32", + "ARRAY_REF:int64", + "ARRAY_REF:int8", + "ARRAY_REF:string", + "ARRAY_REF:uint16", + "ARRAY_REF:uint32", + "ARRAY_REF:uint64", + "ARRAY_REF:uint8", + "CLASS:CompileTestClassShowcaseAllMemberPropTypes", + "CLASS:CompileTestClassShowcaseAllStaticPropTypes", + "CLASS:CompileTestDummyClass", + "CLASS:CompileTestFunctions", + "CLASS:CompileTestMethods", + "CLASS:Landmark", + "CLASS:LandmarkObservation", + "CLASS:Matrix2x2", + "CLASS:Matrix3x3", + "CLASS:Matrix4x4", + "CLASS:Pose", + "CLASS:Quaternion", + "CLASS:Vector2", + "CLASS:Vector3", + "CLASS:Vector4", + "CLASS_MIX:CompileTestClassShowcaseAllMemberPropTypes", + "CLASS_MIX:CompileTestClassShowcaseAllStaticPropTypes", + "CLASS_MIX:CompileTestDummyClass", + "CLASS_MIX:CompileTestFunctions", + "CLASS_MIX:CompileTestMethods", + "CLASS_MIX:Landmark", + "CLASS_MIX:LandmarkObservation", + "CLASS_MIX:Matrix2x2", + "CLASS_MIX:Matrix3x3", + "CLASS_MIX:Matrix4x4", + "CLASS_MIX:Pose", + "CLASS_MIX:Quaternion", + "CLASS_MIX:Vector2", + "CLASS_MIX:Vector3", + "CLASS_MIX:Vector4", + "CLASS_PTR:CompileTestClassShowcaseAllMemberPropTypes", + "CLASS_PTR:CompileTestClassShowcaseAllStaticPropTypes", + "CLASS_PTR:CompileTestDummyClass", + "CLASS_PTR:CompileTestFunctions", + "CLASS_PTR:CompileTestMethods", + "CLASS_PTR:Landmark", + "CLASS_PTR:LandmarkObservation", + "CLASS_PTR:Matrix2x2", + "CLASS_PTR:Matrix3x3", + "CLASS_PTR:Matrix4x4", + "CLASS_PTR:Pose", + "CLASS_PTR:Quaternion", + "CLASS_PTR:Vector2", + "CLASS_PTR:Vector3", + "CLASS_PTR:Vector4", + "CLASS_PTR_MIX:CompileTestClassShowcaseAllMemberPropTypes", + "CLASS_PTR_MIX:CompileTestClassShowcaseAllStaticPropTypes", + "CLASS_PTR_MIX:CompileTestDummyClass", + "CLASS_PTR_MIX:CompileTestFunctions", + "CLASS_PTR_MIX:CompileTestMethods", + "CLASS_PTR_MIX:Landmark", + "CLASS_PTR_MIX:LandmarkObservation", + "CLASS_PTR_MIX:Matrix2x2", + "CLASS_PTR_MIX:Matrix3x3", + "CLASS_PTR_MIX:Matrix4x4", + "CLASS_PTR_MIX:Pose", + "CLASS_PTR_MIX:Quaternion", + "CLASS_PTR_MIX:Vector2", + "CLASS_PTR_MIX:Vector3", + "CLASS_PTR_MIX:Vector4", + "CLASS_PTR_REF:CompileTestClassShowcaseAllMemberPropTypes", + "CLASS_PTR_REF:CompileTestClassShowcaseAllStaticPropTypes", + "CLASS_PTR_REF:CompileTestDummyClass", + "CLASS_PTR_REF:CompileTestFunctions", + "CLASS_PTR_REF:CompileTestMethods", + "CLASS_PTR_REF:Landmark", + "CLASS_PTR_REF:LandmarkObservation", + "CLASS_PTR_REF:Matrix2x2", + "CLASS_PTR_REF:Matrix3x3", + "CLASS_PTR_REF:Matrix4x4", + "CLASS_PTR_REF:Pose", + "CLASS_PTR_REF:Quaternion", + "CLASS_PTR_REF:Vector2", + "CLASS_PTR_REF:Vector3", + "CLASS_PTR_REF:Vector4", + "CLASS_REF:CompileTestClassShowcaseAllMemberPropTypes", + "CLASS_REF:CompileTestClassShowcaseAllStaticPropTypes", + "CLASS_REF:CompileTestDummyClass", + "CLASS_REF:CompileTestFunctions", + "CLASS_REF:CompileTestMethods", + "CLASS_REF:Landmark", + "CLASS_REF:LandmarkObservation", + "CLASS_REF:Matrix2x2", + "CLASS_REF:Matrix3x3", + "CLASS_REF:Matrix4x4", + "CLASS_REF:Pose", + "CLASS_REF:Quaternion", + "CLASS_REF:Vector2", + "CLASS_REF:Vector3", + "CLASS_REF:Vector4", + "ENUM:ArucoMarkerFormat", + "ENUM:CompileTestExampleEnum", + "ENUM:CompileTestExampleFlags", + "ENUM:CompileTestExampleFlags2", + "ENUM:SolvePnPMethod" + ] + }, + "ParameterizedParamTypeKey": { + "type": "string", + "enum": [ + "ARRAY:ArucoMarkerFormat", + "ARRAY:CompileTestClassShowcaseAllMemberPropTypes", + "ARRAY:CompileTestClassShowcaseAllStaticPropTypes", + "ARRAY:CompileTestDummyClass", + "ARRAY:CompileTestExampleEnum", + "ARRAY:CompileTestExampleFlags", + "ARRAY:CompileTestExampleFlags2", + "ARRAY:CompileTestFunctions", + "ARRAY:CompileTestMethods", + "ARRAY:Landmark", + "ARRAY:LandmarkObservation", + "ARRAY:Matrix2x2", + "ARRAY:Matrix3x3", + "ARRAY:Matrix4x4", + "ARRAY:Pose", + "ARRAY:Quaternion", + "ARRAY:SolvePnPMethod", + "ARRAY:Vector2", + "ARRAY:Vector3", + "ARRAY:Vector4", + "ARRAY:boolean", + "ARRAY:double", + "ARRAY:float", + "ARRAY:int16", + "ARRAY:int32", + "ARRAY:int64", + "ARRAY:int8", + "ARRAY:string", + "ARRAY:uint16", + "ARRAY:uint32", + "ARRAY:uint64", + "ARRAY:uint8", + "ARRAY_PTR:ArucoMarkerFormat", + "ARRAY_PTR:CompileTestClassShowcaseAllMemberPropTypes", + "ARRAY_PTR:CompileTestClassShowcaseAllStaticPropTypes", + "ARRAY_PTR:CompileTestDummyClass", + "ARRAY_PTR:CompileTestExampleEnum", + "ARRAY_PTR:CompileTestExampleFlags", + "ARRAY_PTR:CompileTestExampleFlags2", + "ARRAY_PTR:CompileTestFunctions", + "ARRAY_PTR:CompileTestMethods", + "ARRAY_PTR:Landmark", + "ARRAY_PTR:LandmarkObservation", + "ARRAY_PTR:Matrix2x2", + "ARRAY_PTR:Matrix3x3", + "ARRAY_PTR:Matrix4x4", + "ARRAY_PTR:Pose", + "ARRAY_PTR:Quaternion", + "ARRAY_PTR:SolvePnPMethod", + "ARRAY_PTR:Vector2", + "ARRAY_PTR:Vector3", + "ARRAY_PTR:Vector4", + "ARRAY_PTR:boolean", + "ARRAY_PTR:double", + "ARRAY_PTR:float", + "ARRAY_PTR:int16", + "ARRAY_PTR:int32", + "ARRAY_PTR:int64", + "ARRAY_PTR:int8", + "ARRAY_PTR:string", + "ARRAY_PTR:uint16", + "ARRAY_PTR:uint32", + "ARRAY_PTR:uint64", + "ARRAY_PTR:uint8", + "ARRAY_PTR_REF:ArucoMarkerFormat", + "ARRAY_PTR_REF:CompileTestClassShowcaseAllMemberPropTypes", + "ARRAY_PTR_REF:CompileTestClassShowcaseAllStaticPropTypes", + "ARRAY_PTR_REF:CompileTestDummyClass", + "ARRAY_PTR_REF:CompileTestExampleEnum", + "ARRAY_PTR_REF:CompileTestExampleFlags", + "ARRAY_PTR_REF:CompileTestExampleFlags2", + "ARRAY_PTR_REF:CompileTestFunctions", + "ARRAY_PTR_REF:CompileTestMethods", + "ARRAY_PTR_REF:Landmark", + "ARRAY_PTR_REF:LandmarkObservation", + "ARRAY_PTR_REF:Matrix2x2", + "ARRAY_PTR_REF:Matrix3x3", + "ARRAY_PTR_REF:Matrix4x4", + "ARRAY_PTR_REF:Pose", + "ARRAY_PTR_REF:Quaternion", + "ARRAY_PTR_REF:SolvePnPMethod", + "ARRAY_PTR_REF:Vector2", + "ARRAY_PTR_REF:Vector3", + "ARRAY_PTR_REF:Vector4", + "ARRAY_PTR_REF:boolean", + "ARRAY_PTR_REF:double", + "ARRAY_PTR_REF:float", + "ARRAY_PTR_REF:int16", + "ARRAY_PTR_REF:int32", + "ARRAY_PTR_REF:int64", + "ARRAY_PTR_REF:int8", + "ARRAY_PTR_REF:string", + "ARRAY_PTR_REF:uint16", + "ARRAY_PTR_REF:uint32", + "ARRAY_PTR_REF:uint64", + "ARRAY_PTR_REF:uint8", + "ARRAY_REF:ArucoMarkerFormat", + "ARRAY_REF:CompileTestClassShowcaseAllMemberPropTypes", + "ARRAY_REF:CompileTestClassShowcaseAllStaticPropTypes", + "ARRAY_REF:CompileTestDummyClass", + "ARRAY_REF:CompileTestExampleEnum", + "ARRAY_REF:CompileTestExampleFlags", + "ARRAY_REF:CompileTestExampleFlags2", + "ARRAY_REF:CompileTestFunctions", + "ARRAY_REF:CompileTestMethods", + "ARRAY_REF:Landmark", + "ARRAY_REF:LandmarkObservation", + "ARRAY_REF:Matrix2x2", + "ARRAY_REF:Matrix3x3", + "ARRAY_REF:Matrix4x4", + "ARRAY_REF:Pose", + "ARRAY_REF:Quaternion", + "ARRAY_REF:SolvePnPMethod", + "ARRAY_REF:Vector2", + "ARRAY_REF:Vector3", + "ARRAY_REF:Vector4", + "ARRAY_REF:boolean", + "ARRAY_REF:double", + "ARRAY_REF:float", + "ARRAY_REF:int16", + "ARRAY_REF:int32", + "ARRAY_REF:int64", + "ARRAY_REF:int8", + "ARRAY_REF:string", + "ARRAY_REF:uint16", + "ARRAY_REF:uint32", + "ARRAY_REF:uint64", + "ARRAY_REF:uint8", + "CLASS:CompileTestClassShowcaseAllMemberPropTypes", + "CLASS:CompileTestClassShowcaseAllStaticPropTypes", + "CLASS:CompileTestDummyClass", + "CLASS:CompileTestFunctions", + "CLASS:CompileTestMethods", + "CLASS:Landmark", + "CLASS:LandmarkObservation", + "CLASS:Matrix2x2", + "CLASS:Matrix3x3", + "CLASS:Matrix4x4", + "CLASS:Pose", + "CLASS:Quaternion", + "CLASS:Vector2", + "CLASS:Vector3", + "CLASS:Vector4", + "CLASS_PTR:CompileTestClassShowcaseAllMemberPropTypes", + "CLASS_PTR:CompileTestClassShowcaseAllStaticPropTypes", + "CLASS_PTR:CompileTestDummyClass", + "CLASS_PTR:CompileTestFunctions", + "CLASS_PTR:CompileTestMethods", + "CLASS_PTR:Landmark", + "CLASS_PTR:LandmarkObservation", + "CLASS_PTR:Matrix2x2", + "CLASS_PTR:Matrix3x3", + "CLASS_PTR:Matrix4x4", + "CLASS_PTR:Pose", + "CLASS_PTR:Quaternion", + "CLASS_PTR:Vector2", + "CLASS_PTR:Vector3", + "CLASS_PTR:Vector4", + "CLASS_PTR_REF:CompileTestClassShowcaseAllMemberPropTypes", + "CLASS_PTR_REF:CompileTestClassShowcaseAllStaticPropTypes", + "CLASS_PTR_REF:CompileTestDummyClass", + "CLASS_PTR_REF:CompileTestFunctions", + "CLASS_PTR_REF:CompileTestMethods", + "CLASS_PTR_REF:Landmark", + "CLASS_PTR_REF:LandmarkObservation", + "CLASS_PTR_REF:Matrix2x2", + "CLASS_PTR_REF:Matrix3x3", + "CLASS_PTR_REF:Matrix4x4", + "CLASS_PTR_REF:Pose", + "CLASS_PTR_REF:Quaternion", + "CLASS_PTR_REF:Vector2", + "CLASS_PTR_REF:Vector3", + "CLASS_PTR_REF:Vector4", + "CLASS_REF:CompileTestClassShowcaseAllMemberPropTypes", + "CLASS_REF:CompileTestClassShowcaseAllStaticPropTypes", + "CLASS_REF:CompileTestDummyClass", + "CLASS_REF:CompileTestFunctions", + "CLASS_REF:CompileTestMethods", + "CLASS_REF:Landmark", + "CLASS_REF:LandmarkObservation", + "CLASS_REF:Matrix2x2", + "CLASS_REF:Matrix3x3", + "CLASS_REF:Matrix4x4", + "CLASS_REF:Pose", + "CLASS_REF:Quaternion", + "CLASS_REF:Vector2", + "CLASS_REF:Vector3", + "CLASS_REF:Vector4", + "ENUM:ArucoMarkerFormat", + "ENUM:CompileTestExampleEnum", + "ENUM:CompileTestExampleFlags", + "ENUM:CompileTestExampleFlags2", + "ENUM:SolvePnPMethod" + ] + } + } +} diff --git a/sdk/gentool/gentool.schema.json b/sdk/gentool/gentool.schema.json new file mode 100644 index 00000000..a3eb9c72 --- /dev/null +++ b/sdk/gentool/gentool.schema.json @@ -0,0 +1,434 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://posemesh.auki.dev/schemas/gentool.schema.json", + "title": "Posemesh GenTool enum/interface schema", + "type": "object", + "description": "Schema for Posemesh GenTool enum and interface JSON definitions.", + "markdownDescription": "Schema for Posemesh GenTool enum and interface JSON definitions.", + "oneOf": [ + { "$ref": "#/$defs/EnumDef" }, + { "$ref": "#/$defs/InterfaceDef" } + ], + "$defs": { + "StringWithGen": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + } + }, + "TypeKey": { + "description": "Valid type key for properties (see GenTool README valid types).", + "markdownDescription": "Valid type key for properties. **Primitives:** `int8`, `float`, `string`, etc. **Parameterized:** `CLASS_MIX:Vector3`, `ENUM:SolvePnPMethod`, `ARRAY_REF:float`.", + "oneOf": [ + { + "type": "string", + "enum": ["int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "double", "boolean", "string", "string_ref", "string_mix", "data"] + }, + { "$ref": "gentool.schema.generated.json#/$defs/ParameterizedTypeKey" } + ] + }, + "ParamTypeKey": { + "description": "Valid type key for method/constructor parameters and return types (excludes string_mix, CLASS_MIX, ARRAY_MIX).", + "markdownDescription": "Valid type for parameters/return. Excludes `string_mix`, `CLASS_MIX`, `ARRAY_MIX`.", + "oneOf": [ + { + "type": "string", + "enum": ["int8", "int16", "int32", "int64", "uint8", "uint16", "uint32", "uint64", "float", "double", "boolean", "string", "string_ref", "data"] + }, + { "$ref": "gentool.schema.generated.json#/$defs/ParameterizedParamTypeKey" } + ] + }, + "Alias": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "name": { "type": "string" } + }, + "required": ["name"] + }, + "Property": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "name": { "type": "string", "description": "Property name", "markdownDescription": "**Property name** (e.g. `X`, `Position`)" }, + "type": { "$ref": "#/$defs/TypeKey", "description": "Property type", "markdownDescription": "**Property type** — primitive or `CLASS_MIX:Name`, `ENUM:Name`, `ARRAY_REF:type`" }, + "static": { "type": "boolean", "description": "Static property", "markdownDescription": "**Static** — class-level property" }, + "hasGetter": { "type": "boolean", "description": "Generate getter", "markdownDescription": "**Generate getter** — default `true`" }, + "getterConst": { "type": "boolean", "description": "Getter is const", "markdownDescription": "**Getter is const**" }, + "getterNoexcept": { "type": "boolean", "description": "Getter is noexcept", "markdownDescription": "**Getter is noexcept**" }, + "getterName": { "type": "string", "description": "Custom getter name", "markdownDescription": "**Custom getter name** — override default" }, + "getterMode": { "$ref": "#/$defs/MethodMode", "description": "Getter mode", "markdownDescription": "**Getter mode** — `regular`, `virtual`, `pureVirtual`, `override`" }, + "getterCustom": { "type": "boolean", "description": "Custom getter implementation", "markdownDescription": "**Custom getter** — you implement; use with `hasMemberVar: false` for computed props" }, + "getterVisibility": { "$ref": "#/$defs/Visibility", "description": "Getter visibility", "markdownDescription": "**Getter visibility** — `public`, `protected`, `private`" }, + "hasSetter": { "type": "boolean", "description": "Generate setter", "markdownDescription": "**Generate setter** — default `true`; set `false` for read-only" }, + "setterConst": { "type": "boolean", "description": "Setter is const", "markdownDescription": "**Setter is const**" }, + "setterNoexcept": { "type": "boolean", "description": "Setter is noexcept", "markdownDescription": "**Setter is noexcept**" }, + "setterName": { "type": "string", "description": "Custom setter name", "markdownDescription": "**Custom setter name**" }, + "setterArgName": { "type": "string", "description": "Setter argument name", "markdownDescription": "**Setter argument name**" }, + "setterMode": { "$ref": "#/$defs/MethodMode", "description": "Setter mode", "markdownDescription": "**Setter mode**" }, + "setterCustom": { "type": "boolean", "description": "Custom setter implementation", "markdownDescription": "**Custom setter** — you implement" }, + "setterVisibility": { "$ref": "#/$defs/Visibility", "description": "Setter visibility", "markdownDescription": "**Setter visibility**" }, + "hasMemberVar": { "type": "boolean", "description": "Has backing member variable", "markdownDescription": "**Has member var** — `false` for computed-only (e.g. `Length` from X,Y,Z)" }, + "defaultValue": { "type": "string", "description": "Default value", "markdownDescription": "**Default value** — for constructors" }, + "partOfIdentity": { "type": "boolean", "description": "Include in equality/hash", "markdownDescription": "**Part of identity** — include in `==` and `hash`; default `true`" } + }, + "required": ["name", "type"] + }, + "InitializedProperty": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "name": { "type": "string" }, + "value": { "type": "string" }, + "valuePlaceholder": { "type": "string" }, + "initializeInBody": { "type": "boolean" } + }, + "required": ["name"] + }, + "ParameterlessConstructor": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "initializedProperties": { + "type": "array", + "items": { "$ref": "#/$defs/InitializedProperty" } + }, + "codeFront": { + "type": "array", + "items": { "type": "string" } + }, + "codeBack": { + "type": "array", + "items": { "type": "string" } + }, + "definition": { "$ref": "#/$defs/ConstructorDefinition" }, + "visibility": { "$ref": "#/$defs/Visibility" }, + "noexcept": { "type": "boolean" }, + "custom": { "type": "boolean" } + } + }, + "CopyConstructor": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "mainArgName": { "type": "string" }, + "initializedProperties": { + "type": "array", + "items": { "$ref": "#/$defs/InitializedProperty" } + }, + "codeFront": { + "type": "array", + "items": { "type": "string" } + }, + "codeBack": { + "type": "array", + "items": { "type": "string" } + }, + "operatorCodeFront": { + "type": "array", + "items": { "type": "string" } + }, + "operatorCodeBack": { + "type": "array", + "items": { "type": "string" } + }, + "definition": { "$ref": "#/$defs/ConstructorDefinition" }, + "visibility": { "$ref": "#/$defs/Visibility" }, + "noexcept": { "type": "boolean" }, + "custom": { "type": "boolean" }, + "customOperator": { "type": "boolean" } + } + }, + "MoveConstructor": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "mainArgName": { "type": "string" }, + "initializedProperties": { + "type": "array", + "items": { "$ref": "#/$defs/InitializedProperty" } + }, + "codeFront": { + "type": "array", + "items": { "type": "string" } + }, + "codeBack": { + "type": "array", + "items": { "type": "string" } + }, + "operatorCodeFront": { + "type": "array", + "items": { "type": "string" } + }, + "operatorCodeBack": { + "type": "array", + "items": { "type": "string" } + }, + "definition": { "$ref": "#/$defs/ConstructorDefinition" }, + "visibility": { "$ref": "#/$defs/Visibility" }, + "noexcept": { "type": "boolean" }, + "custom": { "type": "boolean" }, + "customOperator": { "type": "boolean" } + } + }, + "Destructor": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "virtual": { "type": "boolean" }, + "code": { + "type": "array", + "items": { "type": "string" } + }, + "definition": { "$ref": "#/$defs/DestructorDefinition" }, + "visibility": { "$ref": "#/$defs/Visibility" }, + "custom": { "type": "boolean" } + } + }, + "ComparedProperty": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "name": { "type": "string" }, + "useGetter": { "type": "boolean" }, + "comparator": { "type": "string" }, + "comparatorClassInstancePlaceholder": { "type": "string" }, + "comparatorPropertyPlaceholder": { "type": "string" } + }, + "required": ["name"] + }, + "EqualityOperator": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "defined": { "type": "boolean" }, + "comparePointers": { "type": "boolean" }, + "comparedProperties": { + "type": "array", + "items": { "$ref": "#/$defs/ComparedProperty" } + }, + "custom": { "type": "boolean" }, + "customInequality": { "type": "boolean" } + } + }, + "HashedProperty": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "name": { "type": "string" }, + "useGetter": { "type": "boolean" }, + "hasher": { "type": "string" }, + "hasherPlaceholder": { "type": "string" } + }, + "required": ["name"] + }, + "HashOperator": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "defined": { "type": "boolean" }, + "usePointerAsHash": { "type": "boolean" }, + "hashedProperties": { + "type": "array", + "items": { "$ref": "#/$defs/HashedProperty" } + }, + "custom": { "type": "boolean" } + } + }, + "ToStringOperator": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "defined": { "type": "boolean" }, + "custom": { "type": "boolean" } + } + }, + "ConstructorParameter": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "name": { "type": "string" }, + "type": { "$ref": "#/$defs/ParamTypeKey" }, + "objectiveC.namePrefix": { "type": "string" }, + "swift.namePrefix": { "type": "string" } + }, + "required": ["name", "type"] + }, + "Constructor": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "parameters": { + "type": "array", + "items": { "$ref": "#/$defs/ConstructorParameter" }, + "minItems": 1 + }, + "mode": { "$ref": "#/$defs/MethodMode" }, + "visibility": { "$ref": "#/$defs/Visibility" }, + "noexcept": { "type": "boolean" } + }, + "required": ["parameters"] + }, + "MethodParameter": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "name": { "type": "string" }, + "type": { "$ref": "#/$defs/ParamTypeKey" }, + "objectiveC.namePrefix": { "type": "string" }, + "swift.namePrefix": { "type": "string" } + }, + "required": ["name", "type"] + }, + "Method": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "name": { "type": "string" }, + "returnType": { "$ref": "#/$defs/ParamTypeKey" }, + "parameters": { + "type": "array", + "items": { "$ref": "#/$defs/MethodParameter" } + }, + "static": { "type": "boolean" }, + "mode": { "$ref": "#/$defs/MethodMode" }, + "visibility": { "$ref": "#/$defs/Visibility" }, + "noexcept": { "type": "boolean" } + }, + "required": ["name"] + }, + "Visibility": { + "type": "string", + "enum": ["public", "protected", "private"] + }, + "MethodMode": { + "type": "string", + "enum": ["regular", "virtual", "pureVirtual", "override"] + }, + "ConstructorDefinition": { + "type": "string", + "enum": ["defined", "default", "deleted", "omitted"] + }, + "DestructorDefinition": { + "type": "string", + "enum": ["defined", "default", "omitted"] + }, + "EnumConstant": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "name": { "type": "string" } + }, + "required": ["name"] + }, + "EnumDef": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "name": { "type": "string" }, + "constants": { + "type": "array", + "items": { "$ref": "#/$defs/EnumConstant" }, + "minItems": 1 + } + }, + "required": ["name", "constants"] + }, + "InterfaceDef": { + "type": "object", + "additionalProperties": false, + "patternProperties": { + ".*\\.gen$": { "type": "boolean" } + }, + "properties": { + "name": { "type": "string" }, + "static": { "type": "boolean" }, + "final": { "type": "boolean" }, + "aliases": { + "type": "array", + "items": { "$ref": "#/$defs/Alias" } + }, + "headerGuardName": { "type": "string" }, + "properties": { + "type": "array", + "items": { "$ref": "#/$defs/Property" } + }, + "copyable": { "type": "boolean" }, + "movable": { "type": "boolean" }, + "parameterlessConstructor": { "$ref": "#/$defs/ParameterlessConstructor" }, + "copyConstructor": { "$ref": "#/$defs/CopyConstructor" }, + "moveConstructor": { "$ref": "#/$defs/MoveConstructor" }, + "destructor": { "$ref": "#/$defs/Destructor" }, + "equalityOperator": { "$ref": "#/$defs/EqualityOperator" }, + "hashOperator": { "$ref": "#/$defs/HashOperator" }, + "toStringOperator": { "$ref": "#/$defs/ToStringOperator" }, + "c.generateFuncAliasDefines": { "type": "boolean" }, + "constructors": { + "type": "array", + "items": { "$ref": "#/$defs/Constructor" } + }, + "methods": { + "type": "array", + "items": { "$ref": "#/$defs/Method" } + } + }, + "required": ["name"] + } + } +} + diff --git a/sdk/gentool/package.json b/sdk/gentool/package.json index f7fdd214..b6890acb 100644 --- a/sdk/gentool/package.json +++ b/sdk/gentool/package.json @@ -3,9 +3,14 @@ "version": "0.1.0", "main": "generator.js", "scripts": { - "generate": "node generator.js" + "generate": "node generator.js && node generate-schema-fragment.js", + "validate:schemas": "node validate-schemas.js" }, "author": "aukilabs", "license": "UNLICENSED", - "description": "Generator Tool" + "description": "Generator Tool", + "devDependencies": { + "ajv": "^8.18.0", + "ajv-cli": "^5.0.0" + } } diff --git a/sdk/gentool/validate-schemas.js b/sdk/gentool/validate-schemas.js new file mode 100644 index 00000000..8dd774f4 --- /dev/null +++ b/sdk/gentool/validate-schemas.js @@ -0,0 +1,68 @@ +const path = require('path'); +const fs = require('fs'); +const glob = require('glob'); +const Ajv2020 = require('ajv/dist/2020').default; + +const schemaPath = path.resolve(__dirname, 'gentool.schema.json'); + +/** Strip IDE-only keywords (e.g. markdownDescription) so Ajv strict mode accepts the schema. */ +function stripIdeKeywords(obj) { + if (obj === null || typeof obj !== 'object') return obj; + if (Array.isArray(obj)) return obj.map(stripIdeKeywords); + const result = {}; + for (const [key, value] of Object.entries(obj)) { + if (key === 'markdownDescription') continue; + result[key] = stripIdeKeywords(value); + } + return result; +} + +function runAjvOnFile(validate, filePath) { + const data = JSON.parse(fs.readFileSync(filePath, 'utf8')); + const valid = validate(data); + if (!valid) { + console.error(`${filePath} invalid`); + console.error(validate.errors); + return 1; + } + console.log(`${filePath} valid`); + return 0; +} + +function main() { + const enumFiles = glob.sync(path.resolve(__dirname, '..', 'enum', '*.json')); + const interfaceFiles = glob.sync(path.resolve(__dirname, '..', 'interface', '*.json')); + + const allFiles = [...enumFiles, ...interfaceFiles]; + if (allFiles.length === 0) { + console.log('No enum/interface JSON files found to validate.'); + return; + } + + const rawSchema = JSON.parse(fs.readFileSync(schemaPath, 'utf8')); + const schemaForAjv = stripIdeKeywords(rawSchema); + + const generatedPath = path.resolve(__dirname, 'gentool.schema.generated.json'); + if (!fs.existsSync(generatedPath)) { + console.error('gentool.schema.generated.json not found. Run generate-schema-fragment.js or npm run generate.'); + process.exit(1); + } + const generatedSchema = JSON.parse(fs.readFileSync(generatedPath, 'utf8')); + + const ajv = new Ajv2020({ allErrors: true }); + ajv.addSchema(stripIdeKeywords(generatedSchema)); + const validate = ajv.compile(schemaForAjv); + + let exitCode = 0; + for (const file of allFiles) { + const status = runAjvOnFile(validate, file); + if (status !== 0) { + exitCode = status; + } + } + + process.exit(exitCode); +} + +main(); +