From 5695efe54635faf910e719c46d2969afd4ae0976 Mon Sep 17 00:00:00 2001 From: HaseenaSainul <41037131+HaseenaSainul@users.noreply.github.com> Date: Wed, 18 Oct 2023 09:09:23 +0530 Subject: [PATCH] CPP SDK : changes to handle additional Properties (#134) CPP SDK : changes to handle additional Properties --- .../templates/types/additionalProperties.h | 2 +- .../templates/types/additionalPropertiesKey.h | 1 + src/macrofier/types.mjs | 101 ++++++++++++------ 3 files changed, 72 insertions(+), 32 deletions(-) create mode 100644 languages/cpp/templates/types/additionalPropertiesKey.h diff --git a/languages/cpp/templates/types/additionalProperties.h b/languages/cpp/templates/types/additionalProperties.h index baa50800..05581106 100644 --- a/languages/cpp/templates/types/additionalProperties.h +++ b/languages/cpp/templates/types/additionalProperties.h @@ -1 +1 @@ -${title} value; \ No newline at end of file +std::unordered_map<${key}, ${type}> ${title}; diff --git a/languages/cpp/templates/types/additionalPropertiesKey.h b/languages/cpp/templates/types/additionalPropertiesKey.h new file mode 100644 index 00000000..9c1a95b6 --- /dev/null +++ b/languages/cpp/templates/types/additionalPropertiesKey.h @@ -0,0 +1 @@ +std::string diff --git a/src/macrofier/types.mjs b/src/macrofier/types.mjs index d6e53788..7c627fce 100644 --- a/src/macrofier/types.mjs +++ b/src/macrofier/types.mjs @@ -30,6 +30,7 @@ const primitives = { "string": "string" } +const isPrimitiveType = type => primitives[type] ? true : false const allocatedPrimitiveProxies = {} function setTemplates(t) { @@ -109,7 +110,7 @@ function insertSchemaMacros(content, schema, module, name, parent, property, rec .replace(/\$\{info.TITLE\}/g, moduleTitle.toUpperCase()) if (recursive) { - content = content.replace(/\$\{type\}/g, getSchemaType(schema, module, { name: title, destination: state.destination, section: state.section, code: false, namespace: true })) + content = content.replace(/\$\{type\}/g, getSchemaType(schema, module, { destination: state.destination, section: state.section, code: false, namespace: true })) } return content } @@ -137,13 +138,40 @@ const insertEnumMacros = (content, schema, module, name) => { return template.join('\n') } -const insertObjectMacros = (content, schema, module, title, property, options) => { - options = options ? JSON.parse(JSON.stringify(options)) : {} +const insertObjectAdditionalPropertiesMacros = (content, schema, module, title, options) => { + const options2 = options ? JSON.parse(JSON.stringify(options)) : {} + options2.parent = title + options2.level = options.level + 1 + + const shape = getSchemaShape(schema.additionalProperties, module, options2) + let type = getSchemaType(schema.additionalProperties, module, options2).trimEnd() + const propertyNames = localizeDependencies(schema, module).propertyNames + + let jsonType = getJsonType(schema.additionalProperties, module) + if (!isPrimitiveType(jsonType)) { + jsonType = 'string' + } + + const additionalType = getPrimitiveType(jsonType, 'additional-types') + let key = (propertyNames && propertyNames.title) ? propertyNames.title : getTemplate(path.join(options.templateDir, 'additionalPropertiesKey')).trimEnd() + + content = content + .replace(/\$\{shape\}/g, shape) + .replace(/\$\{parent\.title\}/g, title) + .replace(/\$\{title\}/g, title) + .replace(/\$\{type\}/g, type) + .replace(/\$\{additional\.type\}/g, additionalType) + .replace(/\$\{key\}/g, key) + .replace(/\$\{delimiter\}(.*?)\$\{end.delimiter\}/g, '') + .replace(/\$\{if\.optional\}(.*?)\$\{end\.if\.optional\}/g, '') - const options2 = JSON.parse(JSON.stringify(options)) + return content +} + +const insertObjectMacros = (content, schema, module, title, property, options) => { + const options2 = options ? JSON.parse(JSON.stringify(options)) : {} options2.parent = title options2.level = options.level + 1 - options2.name = '' ;(['properties', 'properties.register', 'properties.assign']).forEach(macro => { const indent = (content.split('\n').find(line => line.includes("${" + macro + "}")) || '').match(/^\s+/) || [''][0] @@ -151,21 +179,7 @@ const insertObjectMacros = (content, schema, module, title, property, options) = const template = getTemplate(path.join(options.templateDir, 'property' + (templateType ? `-${templateType}` : ''))).replace(/\n/gms, indent + '\n') const properties = [] - - if (schema.additionalProperties && (typeof schema.additionalProperties === 'object')) { - const template = getTemplate(path.join(options.templateDir, 'additionalProperties')) - let type = getSchemaType(schema.additionalProperties, module, options2) - const shape = getSchemaShape(schema.additionalProperties, module, options2) - properties.push(template - .replace(/\$\{property\}/g, '') - .replace(/\$\{Property\}/g, '') - .replace(/\$\{shape\}/g, shape) - .replace(/\$\{parent\.title\}/g, title) - .replace(/\$\{title\}/g, type) - .replace(/\$\{delimiter\}(.*?)\$\{end.delimiter\}/g, '') - .replace(/\$\{if\.optional\}(.*?)\$\{end\.if\.optional\}/g, '')) - } - + if (schema.properties) { Object.entries(schema.properties).forEach(([name, prop], i) => { options2.property = name @@ -319,7 +333,7 @@ function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', name if (level === 0 && !schema.title) { return '' } - + const suffix = destination && ('.' + destination.split('.').pop()) || '' const theTitle = insertSchemaMacros(getTemplate(path.join(templateDir, 'title' + suffix)), schema, module, schema.title || name, parent, property, false) @@ -353,8 +367,14 @@ function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', name return insertSchemaMacros(result, schema, module, theTitle, parent, property) } else if (schema.type === 'object') { - const shape = insertObjectMacros(getTemplate(path.join(templateDir, 'object' + suffix)), schema, module, theTitle, property, { level, parent, property, templateDir, descriptions, destination, section, enums }) - + 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 }) + } + else { + shape = insertObjectMacros(getTemplate(path.join(templateDir, 'object' + suffix)), schema, module, theTitle, property, { level, parent, property, templateDir, descriptions, destination, section, enums, namespace: true }) + } result = result.replace(/\$\{shape\}/g, shape) return insertSchemaMacros(result, schema, module, theTitle, parent, property) } @@ -614,11 +634,17 @@ function getSchemaType(schema, module, { destination, templateDir = 'types', lin // } } else if (schema.type) { - // TODO: this assumes that when type is an array of types, that it's one other primative & 'null', which isn't necessarily true. - const schemaType = !Array.isArray(schema.type) ? schema.type : schema.type.find(t => t !== 'null') - const primitive = getPrimitiveType(schemaType, templateDir) - const type = allocatedProxy ? allocatedPrimitiveProxies[schemaType] || primitive : primitive - return wrap(type, code ? '`' : '') + const template = getTemplate(path.join(templateDir, 'additionalProperties')) + if (schema.additionalProperties && template ) { + return insertSchemaMacros(getTemplate(path.join(templateDir, 'Title')), schema, module, theTitle, '', '', 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. + const schemaType = !Array.isArray(schema.type) ? schema.type : schema.type.find(t => t !== 'null') + const primitive = getPrimitiveType(schemaType, templateDir) + const type = allocatedProxy ? allocatedPrimitiveProxies[schemaType] || primitive : primitive + return wrap(type, code ? '`' : '') + } } else { // TODO this is TypeScript specific @@ -627,7 +653,21 @@ function getSchemaType(schema, module, { destination, templateDir = 'types', lin } function getJsonType(schema, module, { destination, link = false, title = false, code = false, asPath = false, event = false, expandEnums = true, baseUrl = '' } = {}) { - return '' + + schema = sanitize(schema) + let type + if (schema['$ref']) { + if (schema['$ref'][0] === '#') { + //Ref points to local schema + //Get Path to ref in this module and getSchemaType + let definition = getPath(schema['$ref'], module) + type = getJsonType(definition, schema, {destination}) + } + } + else { + type = !Array.isArray(schema.type) ? schema.type : schema.type.find(t => t !== 'null') + } + return type } function getSchemaInstantiation(schema, module, { instantiationType }) { @@ -642,6 +682,5 @@ export default { getMethodSignatureParams, getSchemaShape, getSchemaType, - getJsonType, getSchemaInstantiation -} \ No newline at end of file +}