From 0263ff17abb0d1c7a26dc46c01a556025dcdc220 Mon Sep 17 00:00:00 2001 From: HaseenaSainul Date: Wed, 25 Oct 2023 05:20:36 -0400 Subject: [PATCH 1/4] CPPSDK: 1. add overrideRule to handle template generation for object/primitives based on language requiredment 2. remove enum level checking inside getSchemaShape, to generate enums shape for all levels --- languages/cpp/language.config.json | 3 ++- src/macrofier/engine.mjs | 9 +++++---- src/macrofier/index.mjs | 2 ++ src/macrofier/types.mjs | 23 +++++++++++++++-------- src/sdk/index.mjs | 1 + 5 files changed, 25 insertions(+), 13 deletions(-) diff --git a/languages/cpp/language.config.json b/languages/cpp/language.config.json index debc539d..ef6d63b1 100644 --- a/languages/cpp/language.config.json +++ b/languages/cpp/language.config.json @@ -5,7 +5,8 @@ "extractSubSchemas": true, "unwrapResultObjects": false, "createPolymorphicMethods": true, - "excludeDeclarations":true, + "excludeDeclarations": true, + "overrideRule": true, "aggregateFiles": [ "/include/firebolt.h", "/src/firebolt.cpp" diff --git a/src/macrofier/engine.mjs b/src/macrofier/engine.mjs index 4def4f6e..4e856c61 100644 --- a/src/macrofier/engine.mjs +++ b/src/macrofier/engine.mjs @@ -879,7 +879,7 @@ function generateSchemas(json, templates, options) { else { content = content.replace(/\$\{if\.description\}(.*?)\{end\.if\.description\}/gms, '$1') } - const schemaShape = types.getSchemaShape(schema, json, { templateDir: state.typeTemplateDir, destination: state.destination, section: options.section}) + const schemaShape = types.getSchemaShape(schema, json, { templateDir: state.typeTemplateDir, destination: state.destination, section: options.section }) content = content .replace(/\$\{schema.title\}/, (schema.title || name)) @@ -943,7 +943,7 @@ function getRelatedSchemaLinks(schema = {}, json = {}, templates = {}, options = .map(path => path.substring(2).split('/')) .map(path => getPathOr(null, path, json)) .filter(schema => schema.title) - .map(schema => '[' + types.getSchemaType(schema, json, { templateDir: state.typeTemplateDir, destination: state.destination, section: state.section }) + '](' + getLinkForSchema(schema, json, { name: schema.title }) + ')') // need full module here, not just the schema + .map(schema => '[' + types.getSchemaType(schema, json, { templateDir: state.typeTemplateDir, destination: state.destination, section: state.section }) + '](' + getLinkForSchema(schema, json) + ')') // need full module here, not just the schema .filter(link => link) .join('\n') @@ -1349,7 +1349,7 @@ function insertMethodMacros(template, methodObj, json, templates, examples = {}) .replace(/\$\{method\.result\.summary\}/g, result.summary) .replace(/\$\{method\.result\.link\}/g, getLinkForSchema(result.schema, json)) //, baseUrl: options.baseUrl .replace(/\$\{method\.result\.type\}/g, types.getSchemaType(result.schema, json, { templateDir: state.typeTemplateDir, title: true, asPath: false, destination: state.destination, result: true })) //, baseUrl: options.baseUrl - .replace(/\$\{method\.result\.json\}/, types.getSchemaType(result.schema, json, { templateDir: 'json-types', destination: state.destination, section: state.section, title: true, code: false, link: false, asPath: false, expandEnums: false, namespace: true })) + .replace(/\$\{method\.result\.json\}/g, types.getSchemaType(result.schema, json, { templateDir: 'json-types', destination: state.destination, section: state.section, title: true, code: false, link: false, asPath: false, expandEnums: false, namespace: true })) // todo: what does prefix do? .replace(/\$\{event\.result\.type\}/g, isEventMethod(methodObj) ? types.getMethodSignatureResult(event, json, { destination: state.destination, section: state.section, callback: true }) : '') .replace(/\$\{event\.result\.json\.type\}/g, resultJsonType) @@ -1358,6 +1358,7 @@ function insertMethodMacros(template, methodObj, json, templates, examples = {}) .replace(/\$\{method\.result\}/g, generateResult(result.schema, json, templates, { name: result.name })) .replace(/\$\{method\.result\.json\.type\}/g, resultJsonType) .replace(/\$\{method\.result\.instantiation\}/g, resultInst) + .replace(/\$\{method\.result\.initialization\}/g, resultInit) .replace(/\$\{method\.result\.properties\}/g, resultParams) .replace(/\$\{method\.result\.instantiation\.with\.indent\}/g, indent(resultInst, ' ')) .replace(/\$\{method\.example\.value\}/g, JSON.stringify(methodObj.examples[0].result.value)) @@ -1603,7 +1604,7 @@ function insertParameterMacros(template, param, method, module) { .replace(/\$\{method.param.type\}/g, type) .replace(/\$\{json.param.type\}/g, jsonType) .replace(/\$\{method.param.link\}/g, getLinkForSchema(param.schema, module)) //getType(param)) - .replace(/\$\{method.param.constraints\}/g, constraints) //getType(param)) + .replace(/\$\{method.param.constraints\}/g, constraints) //getType(param)) } function insertCapabilityMacros(template, capabilities, method, module) { diff --git a/src/macrofier/index.mjs b/src/macrofier/index.mjs index 04cdd9fb..6f2a6c4b 100644 --- a/src/macrofier/index.mjs +++ b/src/macrofier/index.mjs @@ -54,6 +54,7 @@ const macrofy = async ( additionalSchemaTemplates, additionalMethodTemplates, excludeDeclarations, + overrideRule, aggregateFiles, operators, primitives, @@ -110,6 +111,7 @@ const macrofy = async ( typer.setPrimitives(primitives) typer.setAllocatedPrimitiveProxies(allocatedPrimitiveProxies) typer.setConvertTuples(convertTuplesToArraysOrObjects) + typer.setOverrideRule(overrideRule) let templatesPermission = {} if (persistPermission) { diff --git a/src/macrofier/types.mjs b/src/macrofier/types.mjs index e7bd5e71..d5ce60e4 100644 --- a/src/macrofier/types.mjs +++ b/src/macrofier/types.mjs @@ -21,6 +21,7 @@ import { getPath, localizeDependencies } from '../shared/json-schema.mjs' import path from "path" let convertTuplesToArraysOrObjects = false +let overrideRule = false const templates = {} const state = {} const primitives = { @@ -50,6 +51,10 @@ function setAllocatedPrimitiveProxies(m) { Object.assign(allocatedPrimitiveProxies, m) } +function setOverrideRule(rule) { + overrideRule = rule +} + const capitalize = str => str ? str[0].toUpperCase() + str.substr(1) : str const indent = (str, padding) => { let first = true @@ -339,6 +344,7 @@ const insertObjectMacros = (content, schema, module, title, property, options) = content = content.replace(regex, properties.join('\n')) .replace(/\$\{level}/g, options.parentLevel > 0 ? options.parentLevel : '') + content = overrideRule ? (properties.length ? content : '') : content }) return content @@ -386,7 +392,7 @@ const insertTupleMacros = (content, schema, module, title, options) => { const getPrimitiveType = (type, templateDir = 'types') => { const template = getTemplate(path.join(templateDir, type)) || getTemplate(path.join(templateDir, 'generic')) - return primitives[type] || template + return overrideRule === true ? (template || primitives[type]) : (primitives[type] || template) } const pickBestType = types => Array.isArray(types) ? types.find(t => t !== 'null') : types @@ -435,12 +441,12 @@ function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', paren } const suffix = destination && ('.' + destination.split('.').pop()) || '' - const theTitle = insertSchemaMacros(getTemplate(path.join(templateDir, 'title' + suffix)), schema, module, { name: schema.title, parent, property, required, recursive: false}) + const theTitle = insertSchemaMacros(getTemplate(path.join(templateDir, 'title' + suffix)), schema, module, { name: schema.title, parent, property, required, recursive: false }) let result = level === 0 ? getTemplate(path.join(templateDir, 'default' + suffix)) : '${shape}' let genericTemplate = getTemplate(path.join(templateDir, 'generic' + suffix)) - if (enums && level === 0 && Array.isArray(schema.enum) && ((schema.type === "string") || (schema.type[0] === "string"))) { + if (enums && Array.isArray(schema.enum) && ((schema.type === "string") || (schema.type[0] === "string"))) { result = getTemplate(path.join(templateDir, 'enum' + suffix)) || genericTemplate return insertSchemaMacros(insertEnumMacros(result, schema, module, theTitle, suffix, templateDir), schema, module, { name: theTitle, parent, property, required }) } @@ -534,7 +540,7 @@ function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', paren } else if (schema.type === "array" && schema.items && !Array.isArray(schema.items)) { // array - const items = getSchemaShape(schema.items, module, { templateDir, parent, property, required, parentLevel: parentLevel + 1, level, summary, descriptions, destination, enums: false , array: true}) + const items = getSchemaShape(schema.items, module, { templateDir, parent, property, required, parentLevel: parentLevel + 1, level, summary, descriptions, destination, enums: false, array: true }) const shape = insertArrayMacros(getTemplate(path.join(templateDir, 'array' + suffix)) || genericTemplate, schema, module, level, items) result = result.replace(/\$\{shape\}/g, shape) .replace(/\$\{if\.object\}(.*?)\$\{end\.if\.object\}/gms, (schema.items.type === 'object') ? '$1' : '') @@ -545,7 +551,7 @@ function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', paren const shape = insertPrimitiveMacros(getTemplate(path.join(templateDir, 'primitive' + suffix) || genericTemplate), schema, module, theTitle, templateDir) result = result.replace(/\$\{shape\}/g, shape) if (level > 0) { - return insertSchemaMacros(result, schema, module, { name: theTitle, parent, property, required, templateDir}) + return insertSchemaMacros(result, schema, module, { name: theTitle, parent, property, required, templateDir }) } } @@ -607,7 +613,7 @@ function getSchemaType(schema, module, { destination, templateDir = 'types', lin const suffix = destination && ('.' + destination.split('.').pop()) || '' const namespaceStr = namespace ? getTemplate(path.join(templateDir, 'namespace' + suffix)) : '' - const theTitle = insertSchemaMacros(namespaceStr + getTemplate(path.join(templateDir, 'title' + suffix)), schema, module, { name: schema.title, parent: getXSchemaGroup(schema, module), recursive: false}) + const theTitle = insertSchemaMacros(namespaceStr + getTemplate(path.join(templateDir, 'title' + suffix)), schema, module, { name: schema.title, parent: getXSchemaGroup(schema, module), recursive: false }) const allocatedProxy = event || result const title = schema.type === "object" || schema.enum ? true : false @@ -710,7 +716,7 @@ function getSchemaType(schema, module, { destination, templateDir = 'types', lin else if (!isTuple(schema)) { const baseDir = (templateDir !== 'json-types' ? 'types': templateDir) template = insertArrayMacros(getTemplate(path.join(baseDir, 'array')), schema, module) - template = insertSchemaMacros(template, schema.items, module, { name: getSchemaType(schema.items, module, {destination, templateDir, link, title, code, asPath, event, result, expandEnums, baseUrl, namespace }) }) + template = insertSchemaMacros(template, schema.items, module, { name: getSchemaType(schema.items, module, {destination, templateDir, link, title, code, asPath, event, result, expandEnums, baseUrl, namespace })}) } else { template = insertTupleMacros(getTemplate(path.join(templateDir, 'tuple')), schema, module, '', { templateDir }) @@ -753,7 +759,7 @@ function getSchemaType(schema, module, { destination, templateDir = 'types', lin else if (schema.type) { const template = getTemplate(path.join(templateDir, 'additionalProperties')) if (schema.additionalProperties && template ) { - return insertSchemaMacros(getTemplate(path.join(templateDir, 'Title')), schema, module, { name: theTitle, recursive: false}) + return insertSchemaMacros(getTemplate(path.join(templateDir, 'Title')), schema, module, { name: theTitle, recursive: false }) } else { // TODO: this assumes that when type is an array of types, that it's one other primative & 'null', which isn't necessarily true. @@ -798,6 +804,7 @@ export default { setPrimitives, setConvertTuples, setAllocatedPrimitiveProxies, + setOverrideRule, getMethodSignatureParams, getMethodSignatureResult, getSchemaShape, diff --git a/src/sdk/index.mjs b/src/sdk/index.mjs index 763b6c9e..a465f84c 100755 --- a/src/sdk/index.mjs +++ b/src/sdk/index.mjs @@ -70,6 +70,7 @@ const run = async ({ additionalSchemaTemplates: config.additionalSchemaTemplates, additionalMethodTemplates: config.additionalMethodTemplates, excludeDeclarations: config.excludeDeclarations, + overrideRule: config.overrideRule, staticModuleNames: staticModuleNames, hideExcluded: true, aggregateFiles: config.aggregateFiles, From 0d0820170577d24d5b712f6eae582bb5054b66b4 Mon Sep 17 00:00:00 2001 From: HaseenaSainul Date: Fri, 27 Oct 2023 10:15:59 -0400 Subject: [PATCH 2/4] CPPSDK: handle primitive type with level 0 using primitive flag & remove override rule for properties insertion to object template --- .../json-types/object-empty-property.h | 1 + .../templates/types/object-empty-property.h | 2 + src/macrofier/engine.mjs | 14 +++--- src/macrofier/types.mjs | 47 +++++++++---------- 4 files changed, 31 insertions(+), 33 deletions(-) create mode 100644 languages/cpp/templates/json-types/object-empty-property.h create mode 100644 languages/cpp/templates/types/object-empty-property.h diff --git a/languages/cpp/templates/json-types/object-empty-property.h b/languages/cpp/templates/json-types/object-empty-property.h new file mode 100644 index 00000000..94be02b1 --- /dev/null +++ b/languages/cpp/templates/json-types/object-empty-property.h @@ -0,0 +1 @@ + using ${title} = WPEFramework::Core::JSON::VariantContainer; diff --git a/languages/cpp/templates/types/object-empty-property.h b/languages/cpp/templates/types/object-empty-property.h new file mode 100644 index 00000000..a5aae7f4 --- /dev/null +++ b/languages/cpp/templates/types/object-empty-property.h @@ -0,0 +1,2 @@ +/* ${title} */ +using ${title} = std::string; \ No newline at end of file diff --git a/src/macrofier/engine.mjs b/src/macrofier/engine.mjs index 4e856c61..2e8f6704 100644 --- a/src/macrofier/engine.mjs +++ b/src/macrofier/engine.mjs @@ -1252,16 +1252,16 @@ function insertMethodMacros(template, methodObj, json, templates, examples = {}) const pullsResultType = pullsResult && types.getSchemaShape(pullsResult, json, { destination: state.destination, templateDir: state.typeTemplateDir, section: state.section }) const pullsForType = pullsResult && types.getSchemaType(pullsResult, json, { destination: state.destination, templateDir: state.typeTemplateDir, section: state.section }) const pullsParamsType = pullsParams ? types.getSchemaShape(pullsParams, json, { destination: state.destination, templateDir: state.typeTemplateDir, section: state.section }) : '' - const serializedParams = flattenedMethod.params.map(param => types.getSchemaShape(param.schema, json, { templateDir: 'parameter-serialization', property: param.name, required: param.required || false, destination: state.destination, section: state.section, level: 1, skipTitleOnce: true })).join('\n') - const resultInst = types.getSchemaShape(flattenedMethod.result.schema, json, { templateDir: 'result-instantiation', property: flattenedMethod.result.name, destination: state.destination, section: state.section, level: 1, skipTitleOnce: true }) // w/out level: 1, getSchemaShape skips anonymous types, like primitives - const resultInit = types.getSchemaShape(flattenedMethod.result.schema, json, { templateDir: 'result-initialization', property: flattenedMethod.result.name, destination: state.destination, section: state.section, level: 1, skipTitleOnce: true }) // w/out level: 1, getSchemaShape skips anonymous types, like primitives - const serializedEventParams = event ? flattenedMethod.params.filter(p => p.name !== 'listen').map(param => types.getSchemaShape(param.schema, json, {templateDir: 'parameter-serialization', property: param.name, required: param.required || false, destination: state.destination, section: state.section, level: 1, skipTitleOnce: true })).join('\n') : '' + const serializedParams = flattenedMethod.params.map(param => types.getSchemaShape(param.schema, json, { templateDir: 'parameter-serialization', property: param.name, required: param.required || false, destination: state.destination, section: state.section, primitive: true, skipTitleOnce: true })).join('\n') + const resultInst = types.getSchemaShape(flattenedMethod.result.schema, json, { templateDir: 'result-instantiation', property: flattenedMethod.result.name, destination: state.destination, section: state.section, primitive: true, skipTitleOnce: true }) // w/out primitive: true, getSchemaShape skips anonymous types, like primitives + const resultInit = types.getSchemaShape(flattenedMethod.result.schema, json, { templateDir: 'result-initialization', property: flattenedMethod.result.name, destination: state.destination, section: state.section, primitive: true, skipTitleOnce: true }) // w/out primitive: true, getSchemaShape skips anonymous types, like primitives + const serializedEventParams = event ? flattenedMethod.params.filter(p => p.name !== 'listen').map(param => types.getSchemaShape(param.schema, json, {templateDir: 'parameter-serialization', property: param.name, required: param.required || false, destination: state.destination, section: state.section, primitive: true, skipTitleOnce: true })).join('\n') : '' // this was wrong... check when we merge if it was fixed - const callbackSerializedParams = event ? types.getSchemaShape(event.result.schema, json, { templateDir: 'callback-parameter-serialization', property: result.name, destination: state.destination, section: state.section, level: 1, skipTitleOnce: true }) : '' + const callbackSerializedParams = event ? types.getSchemaShape(event.result.schema, json, { templateDir: 'callback-parameter-serialization', property: result.name, required: event.result.schema.required || false, destination: state.destination, section: state.section, primitive: true, skipTitleOnce: true }) : '' - const callbackResultInst = event ? types.getSchemaShape(event.result.schema, json, { templateDir: 'callback-result-instantiation', property: result.name, destination: state.destination, section: state.section, level: 1, skipTitleOnce: true }) : '' + const callbackResultInst = event ? types.getSchemaShape(event.result.schema, json, { templateDir: 'callback-result-instantiation', property: result.name, destination: state.destination, section: state.section, primitive: true, skipTitleOnce: true }) : '' // hmm... how is this different from callbackSerializedParams? i guess they get merged? - const callbackResponseInst = event ? types.getSchemaShape(event.result.schema, json, { templateDir: 'callback-response-instantiation', property: result.name, destination: state.destination, section: state.section, level: 1, skipTitleOnce: true }) : '' + const callbackResponseInst = event ? types.getSchemaShape(event.result.schema, json, { templateDir: 'callback-response-instantiation', property: result.name, destination: state.destination, section: state.section, primitive: true, skipTitleOnce: true }) : '' const resultType = result.schema ? types.getSchemaType(result.schema, json, { templateDir: state.typeTemplateDir }) : '' const resultJsonType = result.schema ? types.getSchemaType(result.schema, json, { templateDir: 'json-types' }) : '' const resultParams = generateResultParams(result.schema, json, templates, { name: result.name}) diff --git a/src/macrofier/types.mjs b/src/macrofier/types.mjs index d5ce60e4..4dfede00 100644 --- a/src/macrofier/types.mjs +++ b/src/macrofier/types.mjs @@ -155,8 +155,8 @@ function insertSchemaMacros(content, schema, module, { name = '', parent = '', p .replace(/\$\{property\}/g, property) .replace(/\$\{Property\}/g, capitalize(property)) .replace(/\$\{if\.namespace\.notsame}(.*?)\$\{end\.if\.namespace\.notsame\}/g, (module.info.title !== (parent || moduleTitle)) ? '$1' : '') - .replace(/\$\{parent\.title\}/g, parent) - .replace(/\$\{parent\.Title\}/g, capitalize(parent)) + .replace(/\$\{parent\.title\}/g, parent || moduleTitle) + .replace(/\$\{parent\.Title\}/g, capitalize(parent || moduleTitle)) .replace(/\$\{if\.optional\}(.*?)\$\{end\.if\.optional\}/gms, required ? '' : '$1') .replace(/\$\{if\.impl.optional\}(.*?)\$\{end\.if\.impl.optional\}/gms, required ? '' : '$1') .replace(/\$\{description\}/g, schema.description ? schema.description : '') @@ -205,7 +205,7 @@ const insertObjectAdditionalPropertiesMacros = (content, schema, module, title, const options2 = options ? JSON.parse(JSON.stringify(options)) : {} options2.parent = title options2.level = options.level + 1 - + options2.required = options.required const shape = getSchemaShape(schema.additionalProperties, module, options2) let type = getSchemaType(schema.additionalProperties, module, options2).trimEnd() const propertyNames = localizeDependencies(schema, module).propertyNames @@ -238,14 +238,11 @@ const insertObjectMacros = (content, schema, module, title, property, options) = options2.parentLevel = options.parentLevel options2.level = options.level + 1 options2.templateDir = options.templateDir - ;(['properties', 'properties.register', 'properties.assign']).forEach(macro => { const indent = (content.split('\n').find(line => line.includes("${" + macro + "}")) || '').match(/^\s+/) || [''][0] const templateType = macro.split('.').slice(1).join('') const template = getTemplate(path.join(options.templateDir, 'property' + (templateType ? `-${templateType}` : ''))).replace(/\n/gms, indent + '\n') - const properties = [] - if (schema.properties) { Object.entries(schema.properties).forEach(([name, prop], i) => { let localizedProp = localizeDependencies(prop, module) @@ -257,7 +254,6 @@ const insertObjectMacros = (content, schema, module, title, property, options) = const schemaShape = getSchemaShape(prop, module, options2) const type = getSchemaType(prop, module, options2) - // don't push properties w/ unsupported types if (type) { let replacedTemplate = template @@ -297,7 +293,7 @@ const insertObjectMacros = (content, schema, module, title, property, options) = } }) } - + if (schema.propertyNames) { const { propertyNames } = localizeDependencies(schema, module) if (propertyNames.enum) { @@ -339,14 +335,15 @@ const insertObjectMacros = (content, schema, module, title, property, options) = }) } } - - const regex = new RegExp("\\$\\{" + macro + "\\}", "g") + const regex = new RegExp("\\$\\{" + macro + "\\}", "g") content = content.replace(regex, properties.join('\n')) .replace(/\$\{level}/g, options.parentLevel > 0 ? options.parentLevel : '') - content = overrideRule ? (properties.length ? content : '') : content - }) + if (!schema.properties && ! schema.propertyNames) { + content = !schema.additionalProperties ? getTemplate(path.join(options.templateDir, 'object-empty-property')) : '' + } + }) return content } @@ -430,23 +427,21 @@ const sanitize = (schema) => { return result } -function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', parent = '', property = '', required = true, parentLevel = 0, level = 0, summary, descriptions = true, destination, section, enums = true, skipTitleOnce = false, array = false } = {}) { +function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', parent = '', property = '', required = true, parentLevel = 0, level = 0, summary, descriptions = true, destination, section, enums = true, skipTitleOnce = false, array = false, primitive = false } = {}) { schema = sanitize(schema) - state.destination = destination state.section = section - - if (level === 0 && !schema.title) { + if (level === 0 && !schema.title && !primitive) { return '' } const suffix = destination && ('.' + destination.split('.').pop()) || '' const theTitle = insertSchemaMacros(getTemplate(path.join(templateDir, 'title' + suffix)), schema, module, { name: schema.title, parent, property, required, recursive: false }) - let result = level === 0 ? getTemplate(path.join(templateDir, 'default' + suffix)) : '${shape}' + let result = level === 0 && !primitive ? getTemplate(path.join(templateDir, 'default' + suffix)) : '${shape}' let genericTemplate = getTemplate(path.join(templateDir, 'generic' + suffix)) - if (enums && Array.isArray(schema.enum) && ((schema.type === "string") || (schema.type[0] === "string"))) { + if (enums && level === 0 && Array.isArray(schema.enum) && ((schema.type === "string") || (schema.type[0] === "string"))) { result = getTemplate(path.join(templateDir, 'enum' + suffix)) || genericTemplate return insertSchemaMacros(insertEnumMacros(result, schema, module, theTitle, suffix, templateDir), schema, module, { name: theTitle, parent, property, required }) } @@ -454,7 +449,7 @@ function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', paren if (schema['$ref']) { const someJson = getPath(schema['$ref'], module) if (someJson) { - return getSchemaShape(someJson, module, { templateDir, parent, property, required, parentLevel, level, summary, descriptions, destination, enums, array }) + return getSchemaShape(someJson, module, { templateDir, parent, property, required, parentLevel, level, summary, descriptions, destination, enums, array, primitive }) } throw "Unresolvable $ref: " + schema['ref'] + ", in " + module.info.title } @@ -466,7 +461,7 @@ function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', paren else if (!skipTitleOnce && (level > 0) && schema.title) { let enumType = (schema.type === 'string' && Array.isArray(schema.enum)) // TODO: allow the 'ref' template to actually insert the shape using getSchemaShape - const innerShape = getSchemaShape(schema, module, { skipTitleOnce: true, templateDir, parent, property, required, parentLevel, level, summary, descriptions, destination, enums: enumType, array }) + const innerShape = getSchemaShape(schema, module, { skipTitleOnce: true, templateDir, parent, property, required, parentLevel, level, summary, descriptions, destination, enums: enumType, array, primitive }) const shape = getTemplate(path.join(templateDir, 'ref' + suffix)) .replace(/\$\{shape\}/g, innerShape) @@ -478,11 +473,11 @@ function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', paren let shape const additionalPropertiesTemplate = getTemplate(path.join(templateDir, 'additionalProperties')) if (additionalPropertiesTemplate && schema.additionalProperties && (typeof schema.additionalProperties === 'object')) { - shape = insertObjectAdditionalPropertiesMacros(additionalPropertiesTemplate, schema, module, theTitle, { level, parent, templateDir, namespace: true }) + shape = insertObjectAdditionalPropertiesMacros(additionalPropertiesTemplate, schema, module, theTitle, { level, parent, templateDir, namespace: true, required }) } else { let objectLevel = array ? 0 : level - shape = insertObjectMacros(getTemplate(path.join(templateDir, 'object' + (array ? '-array' : '') + suffix)) || genericTemplate, schema, module, theTitle, property, { parentLevel, level: objectLevel, parent, property, required, templateDir, descriptions, destination, section, enums, namespace: true }) + shape = insertObjectMacros(getTemplate(path.join(templateDir, 'object' + (array ? '-array' : '') + suffix)) || genericTemplate, schema, module, theTitle, property, { parentLevel, level: objectLevel, parent, property, required, templateDir, descriptions, destination, section, enums, namespace: true, primitive }) } result = result.replace(/\$\{shape\}/g, shape) return insertSchemaMacros(result, schema, module, { name: theTitle, parent, property, required, templateDir }) @@ -530,7 +525,7 @@ function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', paren } delete union['$ref'] - return getSchemaShape(union, module, { templateDir, parent, property, required, parentLevel, level, summary, descriptions, destination, enums: false, array }) + return getSchemaShape(union, module, { templateDir, parent, property, required, parentLevel, level, summary, descriptions, destination, enums: false, array, primitive }) } else if (schema.type === "array" && schema.items && isSupportedTuple(schema)) { // tuple @@ -540,8 +535,8 @@ function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', paren } else if (schema.type === "array" && schema.items && !Array.isArray(schema.items)) { // array - const items = getSchemaShape(schema.items, module, { templateDir, parent, property, required, parentLevel: parentLevel + 1, level, summary, descriptions, destination, enums: false, array: true }) - const shape = insertArrayMacros(getTemplate(path.join(templateDir, 'array' + suffix)) || genericTemplate, schema, module, level, items) + const items = getSchemaShape(schema.items, module, { templateDir, parent, property, required, parentLevel: parentLevel + 1, level, summary, descriptions, destination, enums: false, array: true, primitive }) + const shape = insertArrayMacros(getTemplate(path.join(templateDir, 'array' + suffix)) || genericTemplate, schema, module, level, items, schema.required) result = result.replace(/\$\{shape\}/g, shape) .replace(/\$\{if\.object\}(.*?)\$\{end\.if\.object\}/gms, (schema.items.type === 'object') ? '$1' : '') .replace(/\$\{if\.non\.object\}(.*?)\$\{end\.if\.non\.object\}/gms, (schema.items.type !== 'object') ? '$1' : '') @@ -550,7 +545,7 @@ function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', paren else if (schema.type) { const shape = insertPrimitiveMacros(getTemplate(path.join(templateDir, 'primitive' + suffix) || genericTemplate), schema, module, theTitle, templateDir) result = result.replace(/\$\{shape\}/g, shape) - if (level > 0) { + if (level > 0 || primitive) { return insertSchemaMacros(result, schema, module, { name: theTitle, parent, property, required, templateDir }) } } From d22a2129025c995ce02383200c44306259c3ed17 Mon Sep 17 00:00:00 2001 From: HaseenaSainul Date: Fri, 27 Oct 2023 11:47:59 -0400 Subject: [PATCH 3/4] cppsdK: use primitive types from templates, instead defined variable --- languages/cpp/language.config.json | 8 +------- languages/cpp/templates/types/boolean.h | 1 + languages/cpp/templates/types/integer.h | 1 + languages/cpp/templates/types/number.h | 1 + languages/cpp/templates/types/string.h | 1 + src/macrofier/engine.mjs | 8 ++++---- src/macrofier/index.mjs | 2 -- src/macrofier/types.mjs | 23 ++++++++++------------- src/sdk/index.mjs | 1 - 9 files changed, 19 insertions(+), 27 deletions(-) create mode 100644 languages/cpp/templates/types/boolean.h create mode 100644 languages/cpp/templates/types/integer.h create mode 100644 languages/cpp/templates/types/number.h create mode 100644 languages/cpp/templates/types/string.h diff --git a/languages/cpp/language.config.json b/languages/cpp/language.config.json index ef6d63b1..db9b7ddc 100644 --- a/languages/cpp/language.config.json +++ b/languages/cpp/language.config.json @@ -6,7 +6,6 @@ "unwrapResultObjects": false, "createPolymorphicMethods": true, "excludeDeclarations": true, - "overrideRule": true, "aggregateFiles": [ "/include/firebolt.h", "/src/firebolt.cpp" @@ -22,12 +21,7 @@ "/src/jsondata_module.h" ], "persistPermission": true, - "primitives": { - "boolean": "bool", - "integer": "int32_t", - "number": "float", - "string": "std::string" - }, + "primitives": {}, "langVersion" : "c++17", "additionalSchemaTemplates": [ "json-types" ], "additionalMethodTemplates": [ "declarations", "declarations-override" ] diff --git a/languages/cpp/templates/types/boolean.h b/languages/cpp/templates/types/boolean.h new file mode 100644 index 00000000..fc75f206 --- /dev/null +++ b/languages/cpp/templates/types/boolean.h @@ -0,0 +1 @@ +bool \ No newline at end of file diff --git a/languages/cpp/templates/types/integer.h b/languages/cpp/templates/types/integer.h new file mode 100644 index 00000000..33028e0f --- /dev/null +++ b/languages/cpp/templates/types/integer.h @@ -0,0 +1 @@ +int32_t \ No newline at end of file diff --git a/languages/cpp/templates/types/number.h b/languages/cpp/templates/types/number.h new file mode 100644 index 00000000..05eeb48f --- /dev/null +++ b/languages/cpp/templates/types/number.h @@ -0,0 +1 @@ +float \ No newline at end of file diff --git a/languages/cpp/templates/types/string.h b/languages/cpp/templates/types/string.h new file mode 100644 index 00000000..c6d1c815 --- /dev/null +++ b/languages/cpp/templates/types/string.h @@ -0,0 +1 @@ +std::string \ No newline at end of file diff --git a/src/macrofier/engine.mjs b/src/macrofier/engine.mjs index 2e8f6704..031e61ea 100644 --- a/src/macrofier/engine.mjs +++ b/src/macrofier/engine.mjs @@ -1252,12 +1252,12 @@ function insertMethodMacros(template, methodObj, json, templates, examples = {}) const pullsResultType = pullsResult && types.getSchemaShape(pullsResult, json, { destination: state.destination, templateDir: state.typeTemplateDir, section: state.section }) const pullsForType = pullsResult && types.getSchemaType(pullsResult, json, { destination: state.destination, templateDir: state.typeTemplateDir, section: state.section }) const pullsParamsType = pullsParams ? types.getSchemaShape(pullsParams, json, { destination: state.destination, templateDir: state.typeTemplateDir, section: state.section }) : '' - const serializedParams = flattenedMethod.params.map(param => types.getSchemaShape(param.schema, json, { templateDir: 'parameter-serialization', property: param.name, required: param.required || false, destination: state.destination, section: state.section, primitive: true, skipTitleOnce: true })).join('\n') - const resultInst = types.getSchemaShape(flattenedMethod.result.schema, json, { templateDir: 'result-instantiation', property: flattenedMethod.result.name, destination: state.destination, section: state.section, primitive: true, skipTitleOnce: true }) // w/out primitive: true, getSchemaShape skips anonymous types, like primitives + const serializedParams = flattenedMethod.params.map(param => types.getSchemaShape(param.schema, json, { templateDir: 'parameter-serialization', property: param.name, required: param.required, destination: state.destination, section: state.section, primitive: true, skipTitleOnce: true })).join('\n') + const resultInst = types.getSchemaShape(flattenedMethod.result.schema, json, { templateDir: 'result-instantiation', property: flattenedMethod.result.name, required: flattenedMethod.result.required, destination: state.destination, section: state.section, primitive: true, skipTitleOnce: true }) // w/out primitive: true, getSchemaShape skips anonymous types, like primitives const resultInit = types.getSchemaShape(flattenedMethod.result.schema, json, { templateDir: 'result-initialization', property: flattenedMethod.result.name, destination: state.destination, section: state.section, primitive: true, skipTitleOnce: true }) // w/out primitive: true, getSchemaShape skips anonymous types, like primitives - const serializedEventParams = event ? flattenedMethod.params.filter(p => p.name !== 'listen').map(param => types.getSchemaShape(param.schema, json, {templateDir: 'parameter-serialization', property: param.name, required: param.required || false, destination: state.destination, section: state.section, primitive: true, skipTitleOnce: true })).join('\n') : '' + const serializedEventParams = event ? flattenedMethod.params.filter(p => p.name !== 'listen').map(param => types.getSchemaShape(param.schema, json, {templateDir: 'parameter-serialization', property: param.name, required: param.required, destination: state.destination, section: state.section, primitive: true, skipTitleOnce: true })).join('\n') : '' // this was wrong... check when we merge if it was fixed - const callbackSerializedParams = event ? types.getSchemaShape(event.result.schema, json, { templateDir: 'callback-parameter-serialization', property: result.name, required: event.result.schema.required || false, destination: state.destination, section: state.section, primitive: true, skipTitleOnce: true }) : '' + const callbackSerializedParams = event ? types.getSchemaShape(event.result.schema, json, { templateDir: 'callback-parameter-serialization', property: result.name, required: event.result.schema.required, destination: state.destination, section: state.section, primitive: true, skipTitleOnce: true }) : '' const callbackResultInst = event ? types.getSchemaShape(event.result.schema, json, { templateDir: 'callback-result-instantiation', property: result.name, destination: state.destination, section: state.section, primitive: true, skipTitleOnce: true }) : '' // hmm... how is this different from callbackSerializedParams? i guess they get merged? diff --git a/src/macrofier/index.mjs b/src/macrofier/index.mjs index 6f2a6c4b..04cdd9fb 100644 --- a/src/macrofier/index.mjs +++ b/src/macrofier/index.mjs @@ -54,7 +54,6 @@ const macrofy = async ( additionalSchemaTemplates, additionalMethodTemplates, excludeDeclarations, - overrideRule, aggregateFiles, operators, primitives, @@ -111,7 +110,6 @@ const macrofy = async ( typer.setPrimitives(primitives) typer.setAllocatedPrimitiveProxies(allocatedPrimitiveProxies) typer.setConvertTuples(convertTuplesToArraysOrObjects) - typer.setOverrideRule(overrideRule) let templatesPermission = {} if (persistPermission) { diff --git a/src/macrofier/types.mjs b/src/macrofier/types.mjs index 4dfede00..4ef38043 100644 --- a/src/macrofier/types.mjs +++ b/src/macrofier/types.mjs @@ -21,18 +21,18 @@ import { getPath, localizeDependencies } from '../shared/json-schema.mjs' import path from "path" let convertTuplesToArraysOrObjects = false -let overrideRule = false const templates = {} const state = {} -const primitives = { +let primitives = { "integer": "number", "number": "number", "boolean": "boolean", "string": "string" } +const stdPrimitives = [ "integer", "number", "boolean", "string" ] const isVoid = type => (type === 'void') ? true : false -const isPrimitiveType = type => primitives[type] ? true : false +const isPrimitiveType = type => stdPrimitives.includes(type) ? true : false const allocatedPrimitiveProxies = {} function setTemplates(t) { @@ -40,7 +40,9 @@ function setTemplates(t) { } function setPrimitives(p) { - Object.assign(primitives, p) + if (p) { + primitives = p + } } function setConvertTuples(t) { @@ -51,10 +53,6 @@ function setAllocatedPrimitiveProxies(m) { Object.assign(allocatedPrimitiveProxies, m) } -function setOverrideRule(rule) { - overrideRule = rule -} - const capitalize = str => str ? str[0].toUpperCase() + str.substr(1) : str const indent = (str, padding) => { let first = true @@ -144,7 +142,7 @@ const getXSchemaGroup = (schema, module) => { return group } -function insertSchemaMacros(content, schema, module, { name = '', parent = '', property = '', required = true, recursive = true, templateDir = 'types'}) { +function insertSchemaMacros(content, schema, module, { name = '', parent = '', property = '', required = false, recursive = true, templateDir = 'types'}) { const title = name || schema.title || '' let moduleTitle = getXSchemaGroup(schema, module) @@ -250,7 +248,7 @@ const insertObjectMacros = (content, schema, module, title, property, options) = options2.templateDir += subProperty ? '/sub-property' : '' const objSeparator = getTemplate(path.join(options2.templateDir, 'object-separator')) - options2.required = prop.required ? prop.required : false + options2.required = schema.required && schema.required.includes(name) const schemaShape = getSchemaShape(prop, module, options2) const type = getSchemaType(prop, module, options2) @@ -389,7 +387,7 @@ const insertTupleMacros = (content, schema, module, title, options) => { const getPrimitiveType = (type, templateDir = 'types') => { const template = getTemplate(path.join(templateDir, type)) || getTemplate(path.join(templateDir, 'generic')) - return overrideRule === true ? (template || primitives[type]) : (primitives[type] || template) + return (primitives[type] || template) } const pickBestType = types => Array.isArray(types) ? types.find(t => t !== 'null') : types @@ -427,7 +425,7 @@ const sanitize = (schema) => { return result } -function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', parent = '', property = '', required = true, parentLevel = 0, level = 0, summary, descriptions = true, destination, section, enums = true, skipTitleOnce = false, array = false, primitive = false } = {}) { +function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', parent = '', property = '', required = false, parentLevel = 0, level = 0, summary, descriptions = true, destination, section, enums = true, skipTitleOnce = false, array = false, primitive = false } = {}) { schema = sanitize(schema) state.destination = destination state.section = section @@ -799,7 +797,6 @@ export default { setPrimitives, setConvertTuples, setAllocatedPrimitiveProxies, - setOverrideRule, getMethodSignatureParams, getMethodSignatureResult, getSchemaShape, diff --git a/src/sdk/index.mjs b/src/sdk/index.mjs index a465f84c..763b6c9e 100755 --- a/src/sdk/index.mjs +++ b/src/sdk/index.mjs @@ -70,7 +70,6 @@ const run = async ({ additionalSchemaTemplates: config.additionalSchemaTemplates, additionalMethodTemplates: config.additionalMethodTemplates, excludeDeclarations: config.excludeDeclarations, - overrideRule: config.overrideRule, staticModuleNames: staticModuleNames, hideExcluded: true, aggregateFiles: config.aggregateFiles, From 8266d8f6d7bcb866de34141e95f79773eef7a941 Mon Sep 17 00:00:00 2001 From: HaseenaSainul Date: Fri, 3 Nov 2023 06:02:11 -0400 Subject: [PATCH 4/4] CPPSDK: check additionalProperties case well before excluding content --- src/macrofier/types.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/macrofier/types.mjs b/src/macrofier/types.mjs index 4ef38043..280b7192 100644 --- a/src/macrofier/types.mjs +++ b/src/macrofier/types.mjs @@ -338,7 +338,7 @@ const insertObjectMacros = (content, schema, module, title, property, options) = content = content.replace(regex, properties.join('\n')) .replace(/\$\{level}/g, options.parentLevel > 0 ? options.parentLevel : '') - if (!schema.properties && ! schema.propertyNames) { + if (!schema.properties && !schema.propertyNames && !schema.additionalProperties) { content = !schema.additionalProperties ? getTemplate(path.join(options.templateDir, 'object-empty-property')) : '' } })