234 lines
6.4 KiB
JavaScript
234 lines
6.4 KiB
JavaScript
const yargs = require("yargs");
|
|
const path = require("path");
|
|
const fs = require("fs");
|
|
const SchemaCache = require("./SchemaCache");
|
|
const generate = require("./generate");
|
|
const generateCombinedWriter = require("./generateCombinedWriter");
|
|
const generateRegisterExtensions = require("./generateRegisterExtensions");
|
|
const getNameFromTitle = require("./getNameFromTitle");
|
|
|
|
const argv = yargs.options({
|
|
schemas: {
|
|
description: "The paths to the JSON schemas.",
|
|
demandOption: true,
|
|
type: "array",
|
|
},
|
|
output: {
|
|
description: "The output directory for the generated class files.",
|
|
demandOption: true,
|
|
type: "string",
|
|
},
|
|
readerOutput: {
|
|
description: "The output directory for the generated reader files.",
|
|
demandOption: true,
|
|
type: "string",
|
|
},
|
|
writerOutput: {
|
|
description: "The output directory for the generated writer files.",
|
|
demandOption: true,
|
|
type: "string",
|
|
},
|
|
extensions: {
|
|
description: "The extension directories.",
|
|
demandOption: true,
|
|
type: "array",
|
|
},
|
|
config: {
|
|
description:
|
|
"The path to the configuration options controlling code generation, expressed in a JSON file.",
|
|
demandOption: true,
|
|
type: "string",
|
|
},
|
|
namespace: {
|
|
description: "Namespace to put the generated classes in.",
|
|
demandOption: true,
|
|
type: "string",
|
|
},
|
|
readerNamespace: {
|
|
description: "Namespace to put the generated reader files in.",
|
|
demandOption: true,
|
|
type: "string",
|
|
},
|
|
writerNamespace: {
|
|
description: "Namespace to put the generated writer files in.",
|
|
demandOption: true,
|
|
type: "string",
|
|
},
|
|
oneHandlerFile: {
|
|
description:
|
|
"Generate all the JSON handler implementations into a single file, GeneratedJsonHandlers.cpp.",
|
|
type: "bool",
|
|
default: true,
|
|
},
|
|
}).argv;
|
|
|
|
function splitSchemaPath(schemaPath) {
|
|
const schemaNameIndex = schemaPath.lastIndexOf("/") + 1;
|
|
const schemaName = schemaPath.slice(schemaNameIndex);
|
|
const schemaBasePath = schemaPath.slice(0, schemaNameIndex);
|
|
return { schemaName, schemaBasePath };
|
|
}
|
|
|
|
const schemaBasePaths = [];
|
|
for (const schemaPath of argv.schemas) {
|
|
const { _, schemaBasePath } = splitSchemaPath(schemaPath);
|
|
schemaBasePaths.push(schemaBasePath);
|
|
}
|
|
|
|
const schemaCache = new SchemaCache(schemaBasePaths, argv.extensions);
|
|
|
|
let schemas = [];
|
|
for (const schemaPath of argv.schemas) {
|
|
const { schemaName, _ } = splitSchemaPath(schemaPath);
|
|
const schema = schemaCache.load(schemaName);
|
|
schemas.push(schema);
|
|
}
|
|
const rootSchema = schemas[0];
|
|
|
|
const config = JSON.parse(fs.readFileSync(argv.config, "utf-8"));
|
|
|
|
if (argv.oneHandlerFile) {
|
|
// Clear the handler implementation file, and then we'll append to it in `generate`.
|
|
const readerHeaderOutputDir = path.join(
|
|
argv.readerOutput,
|
|
"generated",
|
|
"src"
|
|
);
|
|
fs.mkdirSync(readerHeaderOutputDir, { recursive: true });
|
|
const readerSourceOutputPath = path.join(
|
|
readerHeaderOutputDir,
|
|
"GeneratedJsonHandlers.cpp"
|
|
);
|
|
fs.writeFileSync(readerSourceOutputPath, "", "utf-8");
|
|
}
|
|
|
|
const options = {
|
|
schemaCache,
|
|
oneHandlerFile: argv.oneHandlerFile,
|
|
outputDir: argv.output,
|
|
readerOutputDir: argv.readerOutput,
|
|
config: config,
|
|
namespace: argv.namespace,
|
|
readerNamespace: argv.readerNamespace,
|
|
writerNamespace: argv.writerNamespace,
|
|
// key: Title of the element name that is extended (e.g. "Mesh Primitive")
|
|
// value: Array of extension type names.
|
|
extensions: {},
|
|
};
|
|
|
|
const writers = [];
|
|
|
|
function getObjectToExtend(schema, extensionName) {
|
|
const parts = schema.split("/");
|
|
const last = parts[parts.length - 1];
|
|
const subParts = last.split(".");
|
|
const extensionNameIndex = subParts.indexOf(extensionName);
|
|
if (extensionNameIndex == -1 || extensionNameIndex == 0) {
|
|
return undefined;
|
|
}
|
|
const objectToExtend = subParts.slice(0, extensionNameIndex).join(".");
|
|
return objectToExtend;
|
|
}
|
|
|
|
for (const extension of config.extensions) {
|
|
const extensionSchema = schemaCache.loadExtension(
|
|
extension.schema,
|
|
extension.extensionName
|
|
);
|
|
const extensionClassName = getNameFromTitle(config, extensionSchema.title);
|
|
|
|
if (!extensionSchema) {
|
|
console.warn(
|
|
`Could not load schema ${extension.schema} for extension class ${extensionClassName}.`
|
|
);
|
|
continue;
|
|
}
|
|
|
|
if (!config.classes[extensionSchema.title]) {
|
|
config.classes[extensionSchema.title] = {};
|
|
}
|
|
config.classes[extensionSchema.title].overrideName = extensionClassName;
|
|
config.classes[extensionSchema.title].extensionName = extension.extensionName;
|
|
|
|
schemas.push(...generate(options, extensionSchema, writers));
|
|
|
|
var objectsToExtend = [];
|
|
if (extension.attachTo !== undefined) {
|
|
objectsToExtend = objectsToExtend.concat(extension.attachTo);
|
|
} else {
|
|
const attachTo = getObjectToExtend(
|
|
extension.schema,
|
|
extension.extensionName,
|
|
extensionClassName
|
|
);
|
|
if (attachTo !== undefined) {
|
|
objectsToExtend.push(attachTo);
|
|
}
|
|
}
|
|
if (objectsToExtend.length === 0) {
|
|
console.warn(
|
|
`Could not find object to extend for extension class ${extensionClassName}`
|
|
);
|
|
continue;
|
|
}
|
|
|
|
for (const objectToExtend of objectsToExtend) {
|
|
const objectToExtendSchema = schemaCache.load(
|
|
`${objectToExtend}.schema.json`
|
|
);
|
|
if (!objectToExtendSchema) {
|
|
console.warn(`Could not load schema for ${objectToExtend}.`);
|
|
continue;
|
|
}
|
|
|
|
if (!options.extensions[objectToExtendSchema.title]) {
|
|
options.extensions[objectToExtendSchema.title] = [];
|
|
}
|
|
|
|
options.extensions[objectToExtendSchema.title].push({
|
|
name: extension.extensionName,
|
|
className: extensionClassName,
|
|
});
|
|
}
|
|
}
|
|
|
|
function processSchemas() {
|
|
const processed = {};
|
|
|
|
while (schemas.length > 0) {
|
|
const schema = schemas.pop();
|
|
if (processed[schema.sourcePath]) {
|
|
continue;
|
|
}
|
|
processed[schema.sourcePath] = true;
|
|
|
|
if ((options.config.classes[schema.title] || {}).manuallyDefined) {
|
|
continue;
|
|
}
|
|
schemas.push(...generate(options, schema, writers));
|
|
}
|
|
}
|
|
|
|
processSchemas();
|
|
|
|
generateRegisterExtensions({
|
|
readerOutputDir: argv.readerOutput,
|
|
writerOutputDir: argv.writerOutput,
|
|
config: config,
|
|
namespace: argv.namespace,
|
|
readerNamespace: argv.readerNamespace,
|
|
writerNamespace: argv.writerNamespace,
|
|
rootSchema: rootSchema,
|
|
extensions: options.extensions,
|
|
});
|
|
|
|
generateCombinedWriter({
|
|
writerOutputDir: argv.writerOutput,
|
|
config: config,
|
|
namespace: argv.namespace,
|
|
writerNamespace: argv.writerNamespace,
|
|
rootSchema: rootSchema,
|
|
writers: writers,
|
|
extensions: options.extensions,
|
|
});
|