From 0280ac8a04f51e6cb0c87742fc0dc5a11636656c Mon Sep 17 00:00:00 2001 From: HaseenaSainul Date: Thu, 11 May 2023 00:15:41 -0700 Subject: [PATCH 1/9] Enum fixes : 1. missing description added 2. alignment fixes 3. implementation added for enum inside properties 4. Enum to String value Conversion logic added for C --- languages/c/src/types/JSONHelpers.mjs | 12 +-- languages/c/templates/declarations/default.c | 9 +- .../declarations/polymorphic-reducer.c | 11 ++- .../templates/modules/include/Common/Module.h | 10 +- .../c/templates/modules/include/Module.h | 15 ++- languages/c/templates/modules/src/Module.cpp | 17 +++- languages/c/templates/schemas/default.c | 7 +- .../templates/schemas/include/Common/Module.h | 10 +- .../c/templates/schemas/src/JsonData_Module.h | 6 +- .../c/templates/schemas/src/Module_Common.cpp | 6 +- .../c/templates/sections/enum_conversion.c | 1 + languages/c/templates/sections/schemas.c | 2 - languages/c/templates/sections/types.c | 2 - languages/c/templates/types/enum.c | 1 + languages/c/templates/types/enum_conversion.c | 4 + src/macrofier/engine.mjs | 91 +++++++++++++++---- 16 files changed, 142 insertions(+), 62 deletions(-) create mode 100644 languages/c/templates/sections/enum_conversion.c create mode 100644 languages/c/templates/types/enum_conversion.c diff --git a/languages/c/src/types/JSONHelpers.mjs b/languages/c/src/types/JSONHelpers.mjs index 25d1ad3b..0d2d6a08 100644 --- a/languages/c/src/types/JSONHelpers.mjs +++ b/languages/c/src/types/JSONHelpers.mjs @@ -42,15 +42,15 @@ ENUM_CONVERSION_END(Advertising_SkipRestriction) // TODO - this should be a global function in the main /src/ directory... not part of a language pack const keyName = val => val.split(':').pop().replace(/[\.\-]/g, '_').replace(/\+/g, '_plus').replace(/([a-z])([A-Z0-9])/g, '$1_$2').toUpperCase() -function getJsonEnumConversion(schema, module, { name }) { - name = capitalize(schema.title || name) - let e = `ENUM_CONVERSION_BEGIN(${module.info.title}_${name})\n` - +function getJsonEnumConversion(schema, { name }) { + name = (schema.title || name) + let e = schema.description ? ('\n/* ${info.title} - ' + `${schema.description} */`) : '' + e += '\nENUM_CONVERSION_BEGIN(${info.title}_' + `${name})\n` schema.enum.forEach(value => { - e += `{ ${module.info.title.toUpperCase()}_${name.toUpperCase()}_${keyName(value)}, _T("${value}") },` + e += ' { ${info.TITLE}_' + `${name.toUpperCase()}_${keyName(value)}, _T("${value}") },\n` }) - e += `ENUM_CONVERSION_END(${module.info.title}_${name})` + e += 'ENUM_CONVERSION_END(${info.title}_' + `${name})` return e } diff --git a/languages/c/templates/declarations/default.c b/languages/c/templates/declarations/default.c index 72fbf14f..be0b1e14 100644 --- a/languages/c/templates/declarations/default.c +++ b/languages/c/templates/declarations/default.c @@ -1,4 +1,5 @@ - /** - * ${method.summary} - ${method.params} */ - ${method.signature}; +/* + * ${method.summary} + * ${method.params} + */ +${method.signature}; diff --git a/languages/c/templates/declarations/polymorphic-reducer.c b/languages/c/templates/declarations/polymorphic-reducer.c index 979832b2..cf974e1a 100644 --- a/languages/c/templates/declarations/polymorphic-reducer.c +++ b/languages/c/templates/declarations/polymorphic-reducer.c @@ -1,6 +1,7 @@ - /** - * ${method.summary} - ${method.params} */ - ${method.signature} +/* + * ${method.summary} + * ${method.params} + */ +${method.signature} -// TODO: generate reducer signature \ No newline at end of file +// TODO: generate reducer signature diff --git a/languages/c/templates/modules/include/Common/Module.h b/languages/c/templates/modules/include/Common/Module.h index 2834b997..809418a2 100644 --- a/languages/c/templates/modules/include/Common/Module.h +++ b/languages/c/templates/modules/include/Common/Module.h @@ -25,16 +25,16 @@ extern "C" { #endif - // Enums +// Enums - /* ${ENUMS}} */ +/* ${ENUMS} */ - // Schemas +// Schemas - /* ${SCHEMAS} */ +/* ${SCHEMAS} */ #ifdef __cplusplus } #endif -#endif // Header Include Guard \ No newline at end of file +#endif // Header Include Guard diff --git a/languages/c/templates/modules/include/Module.h b/languages/c/templates/modules/include/Module.h index e24c869f..ee034605 100644 --- a/languages/c/templates/modules/include/Module.h +++ b/languages/c/templates/modules/include/Module.h @@ -26,13 +26,20 @@ extern "C" { #endif - /* ${SCHEMAS} */ +// Enums - /* ${ACCESSORS} */ - /* ${DECLARATIONS} */ +/* ${ENUMS} */ + +// Types + +/* ${TYPES} */ + +/* ${ACCESSORS} */ + +/* ${DECLARATIONS} */ #ifdef __cplusplus } #endif -#endif // Header Include Guard \ No newline at end of file +#endif // Header Include Guard diff --git a/languages/c/templates/modules/src/Module.cpp b/languages/c/templates/modules/src/Module.cpp index 0783b416..3f2bb32c 100644 --- a/languages/c/templates/modules/src/Module.cpp +++ b/languages/c/templates/modules/src/Module.cpp @@ -22,16 +22,27 @@ /* ${IMPORTS} */ +namespace FireboltSDK { + namespace ${info.title} { + // Types + + /* ${TYPES} */ + } +} + +namespace WPEFramework { + /* ${ENUMS_CONVERSION} */ +} #ifdef __cplusplus extern "C" { #endif -/* ${TYPES} */ +/* ${ACCESSORS} */ +/* ${METHODS} */ #ifdef __cplusplus } #endif -/* ${ACCESSORS} */ -/* ${METHODS} */ + diff --git a/languages/c/templates/schemas/default.c b/languages/c/templates/schemas/default.c index bc9ab873..a2058da5 100644 --- a/languages/c/templates/schemas/default.c +++ b/languages/c/templates/schemas/default.c @@ -1,5 +1,4 @@ - /** - * ${schema.description} - */ - +/* + * ${schema.description} + */ ${schema.shape} diff --git a/languages/c/templates/schemas/include/Common/Module.h b/languages/c/templates/schemas/include/Common/Module.h index 50ef1fd9..0326c220 100644 --- a/languages/c/templates/schemas/include/Common/Module.h +++ b/languages/c/templates/schemas/include/Common/Module.h @@ -25,16 +25,14 @@ extern "C" { #endif - // Enums +// Enums - /* ${ENUMS} */ +/* ${ENUMS} */ - // Types - - /* ${TYPES} */ +/* ${TYPES} */ #ifdef __cplusplus } #endif -#endif // Header Include Guard \ No newline at end of file +#endif // Header Include Guard diff --git a/languages/c/templates/schemas/src/JsonData_Module.h b/languages/c/templates/schemas/src/JsonData_Module.h index 4cee1781..9ba90428 100644 --- a/languages/c/templates/schemas/src/JsonData_Module.h +++ b/languages/c/templates/schemas/src/JsonData_Module.h @@ -17,7 +17,9 @@ */ namespace FireboltSDK { + namespace ${info.title} { + // Types - /* ${DECLARATIONS} */ - + /* ${SCHEMAS}*/ + } } diff --git a/languages/c/templates/schemas/src/Module_Common.cpp b/languages/c/templates/schemas/src/Module_Common.cpp index 632f38d6..40d1f362 100644 --- a/languages/c/templates/schemas/src/Module_Common.cpp +++ b/languages/c/templates/schemas/src/Module_Common.cpp @@ -21,11 +21,15 @@ #include "Common/${info.title}.h" #include "JsonData_${info.title}.h" +namespace WPEFramework { + + /* ${ENUMS_CONVERSION} */ +} + #ifdef __cplusplus extern "C" { #endif - /* ${TYPES} */ /* ${ACCESSORS} */ /* ${METHODS} */ diff --git a/languages/c/templates/sections/enum_conversion.c b/languages/c/templates/sections/enum_conversion.c new file mode 100644 index 00000000..9295133c --- /dev/null +++ b/languages/c/templates/sections/enum_conversion.c @@ -0,0 +1 @@ +${schema.list} diff --git a/languages/c/templates/sections/schemas.c b/languages/c/templates/sections/schemas.c index a1847009..9295133c 100644 --- a/languages/c/templates/sections/schemas.c +++ b/languages/c/templates/sections/schemas.c @@ -1,3 +1 @@ -// Types & Enums - ${schema.list} diff --git a/languages/c/templates/sections/types.c b/languages/c/templates/sections/types.c index a2d20dbb..9295133c 100644 --- a/languages/c/templates/sections/types.c +++ b/languages/c/templates/sections/types.c @@ -1,3 +1 @@ -// Types - ${schema.list} diff --git a/languages/c/templates/types/enum.c b/languages/c/templates/types/enum.c index 2a8e94d7..6926fa77 100644 --- a/languages/c/templates/types/enum.c +++ b/languages/c/templates/types/enum.c @@ -1,3 +1,4 @@ +/* ${title} ${description} */ typedef enum { ${info.TITLE}_${NAME}_${key}, } ${info.title}_${name}; diff --git a/languages/c/templates/types/enum_conversion.c b/languages/c/templates/types/enum_conversion.c new file mode 100644 index 00000000..646567a0 --- /dev/null +++ b/languages/c/templates/types/enum_conversion.c @@ -0,0 +1,4 @@ +/* ${title} ${description} */ +ENUM_CONVERSION_BEGIN(${info.title}_${name}) + { ${info.TITLE}_${NAME}_${key}, _T("${value}") }, +ENUM_CONVERSION_END(${info.title}_${name}) diff --git a/src/macrofier/engine.mjs b/src/macrofier/engine.mjs index db0304e4..8719db88 100644 --- a/src/macrofier/engine.mjs +++ b/src/macrofier/engine.mjs @@ -64,6 +64,8 @@ const state = { section: undefined } +const capitalize = str => str[0].toUpperCase() + str.substr(1) + const setTyper = (t) => { types = t } @@ -335,6 +337,7 @@ const generateMacros = (obj, templates, languages, options = {}) => { const methods = methodsArray.length ? getTemplate('/sections/methods', templates).replace(/\$\{method.list\}/g, methodsArray.map(m => m.body).join('\n')) : '' const methodList = methodsArray.filter(m => m.body).map(m => m.name) const providerInterfaces = generateProviderInterfaces(obj, templates) + const enumsConversion = generateEnumsConversion(obj, templates) const events = eventsArray.length ? getTemplate('/sections/events', templates).replace(/\$\{event.list\}/g, eventsArray.map(m => m.body).join('\n')) : '' const eventList = eventsArray.map(m => makeEventName(m)) const defaults = generateDefaults(obj, templates) @@ -350,6 +353,7 @@ const generateMacros = (obj, templates, languages, options = {}) => { imports, initialization, enums, + enumsConversion, events, eventList, eventsEnum, @@ -402,6 +406,7 @@ const insertMacros = (fContents = '', macros = {}) => { fContents = fContents.replace(/[ \t]*\/\* \$\{TYPES\} \*\/[ \t]*\n/, macros.types) fContents = fContents.replace(/[ \t]*\/\* \$\{PROVIDERS\} \*\/[ \t]*\n/, macros.providerInterfaces) fContents = fContents.replace(/[ \t]*\/\* \$\{ENUMS\} \*\/[ \t]*\n/, macros.enums) + fContents = fContents.replace(/[ \t]*\/\* \$\{ENUMS_CONVERSION\} \*\/[ \t]*\n/, macros.enumsConversion) fContents = fContents.replace(/[ \t]*\/\* \$\{IMPORTS\} \*\/[ \t]*\n/, macros.imports) fContents = fContents.replace(/[ \t]*\/\* \$\{INITIALIZATION\} \*\/[ \t]*\n/, macros.initialization) fContents = fContents.replace(/[ \t]*\/\* \$\{DEFAULTS\} \*\/[ \t]*\n/, macros.defaults) @@ -486,8 +491,62 @@ function insertTableofContents(content) { return content } +const isEnumType = x => x.type === 'string' && Array.isArray(x.enum) + +const getProperties = x => { + return Array.isArray(x.properties) ? x.properties[0] : x.properties +} + +const isEnumProperties = schema => compose( + getProperties, + filter(enm => enm), + map(enm => (enm.length > 0)), + map(filter(isEnumType)), + map(props => props.map(([k, v]) => v)), + map(Object.entries), + filter(schema => isObject(schema)) +)(schema) + +const getEnumProperties = schema => compose( + getProperties, + filter(enm => enm), + map(filter(isEnumType)), + map(props => props.map(([k, v]) => { + if (isEnumType(v) == true) { + let type = Object.assign({}, v) + type.title = k + return type + } else { + return v + } + })), + map(Object.entries), + filter(schema => isObject(schema)) +)(schema) + + +const convertEnumTemplate = (sch, templateName, templates) => { + const template = getTemplate(templateName, templates).split('\n') + let schema = isEnumType(sch) ? sch : getEnumProperties(sch) + for (var i = 0; i < template.length; i++) { + if (template[i].indexOf('${key}') >= 0) { + template[i] = schema.enum.map(value => { + const safeName = value.split(':').pop().replace(/[\.\-]/g, '_').replace(/\+/g, '_plus').replace(/([a-z])([A-Z0-9])/g, '$1_$2').toUpperCase() + return template[i].replace(/\$\{key\}/g, safeName) + .replace(/\$\{value\}/g, value) + }).join('\n') + template[i] = template[i].replace(/,*$/, ''); + } + } + return template.join('\n') + .replace(/\$\{title\}/g, capitalize(schema.title)) + .replace(/\$\{description\}/g, schema.description ? ('- ' + schema.description) : '') + .replace(/\$\{name\}/g, schema.title) + .replace(/\$\{NAME\}/g, schema.title.toUpperCase()) +} + const enumFinder = compose( - filter(x => x.type === 'string' && Array.isArray(x.enum) && x.title), + filter(x => ((isEnumType(x) && x.title) || isEnumProperties(x))), map(([_, val]) => val), filter(([_key, val]) => isObject(val)) ) @@ -496,24 +555,23 @@ const generateEnums = (json, templates) => { return compose( option(''), map(reduce((acc, val) => acc.concat(val).concat('\n'), '')), - map(map((schema) => { - const template = getTemplate('/types/enum', templates).split('\n') - for (var i = 0; i < template.length; i++) { - if (template[i].indexOf('${key}') >= 0) { - template[i] = schema.enum.map(value => { - const safeName = value.split(':').pop().replace(/[\.\-]/g, '_').replace(/\+/g, '_plus').replace(/([a-z])([A-Z0-9])/g, '$1_$2').toUpperCase() - return template[i].replace(/\$\{key\}/g, safeName) - .replace(/\$\{value\}/g, value) - }).join('\n') - } - } - return template.join('\n').replace(/\$\{name\}/g, schema.title).replace(/\$\{NAME\}/g, schema.title.toUpperCase()) - })), + map(map((schema) => convertEnumTemplate(schema, '/types/enum', templates))), map(enumFinder), getSchemas )(json) } +const generateEnumsConversion = (json, templates) => { + return compose( + option(''), + map(reduce((acc, val) => acc.concat(val).concat('\n'), '')), + map(map((schema) => convertEnumTemplate(schema, '/types/enum_conversion', templates))), + map(enumFinder), + getSchemas + )(json) +} + + const generateEvents = (json, templates) => { const eventNames = eventsOrEmptyArray(json).map(makeEventName) @@ -694,8 +752,6 @@ const generateImports = (json, templates) => { imports += getTemplate('/imports/x-method', templates) } - - if (json['x-schemas'] && Object.keys(json['x-schemas']).length > 0) { imports += Object.keys(json['x-schemas']).map(shared => getTemplate('/imports/default', templates).replace(/\$\{info.title\}/g, shared)).join('\n') } @@ -1235,7 +1291,6 @@ function generateProviderInterfaces(json, templates) { function insertProviderInterfaceMacros(template, capability, moduleJson = {}, templates) { const iface = getProviderInterface(capability, moduleJson, { destination: state.destination, section: state.section })//.map(method => { method.name = method.name.charAt(9).toLowerCase() + method.name.substr(10); return method } ) - const capitalize = str => str[0].toUpperCase() + str.substr(1) const uglyName = capability.split(":").slice(-2).map(capitalize).reverse().join('') + "Provider" let name = iface.length === 1 ? iface[0].name.charAt(0).toUpperCase() + iface[0].name.substr(1) + "Provider" : uglyName @@ -1389,4 +1444,4 @@ export default { insertAggregateMacros, setTyper, setConfig -} \ No newline at end of file +} From 8687ed88c431e0459098377859ba3bf08f326167 Mon Sep 17 00:00:00 2001 From: HaseenaSainul Date: Fri, 19 May 2023 06:38:06 -0400 Subject: [PATCH 2/9] Enum conversion: tempatalize section part also --- languages/c/templates/modules/src/Module.cpp | 4 +--- languages/c/templates/schemas/src/Module_Common.cpp | 5 +---- languages/c/templates/sections/enum_conversion.c | 4 ++++ languages/c/templates/types/enum_conversion.c | 8 ++++---- src/macrofier/engine.mjs | 4 ++-- 5 files changed, 12 insertions(+), 13 deletions(-) diff --git a/languages/c/templates/modules/src/Module.cpp b/languages/c/templates/modules/src/Module.cpp index 3f2bb32c..6d374ff7 100644 --- a/languages/c/templates/modules/src/Module.cpp +++ b/languages/c/templates/modules/src/Module.cpp @@ -30,9 +30,7 @@ namespace FireboltSDK { } } -namespace WPEFramework { - /* ${ENUMS_CONVERSION} */ -} +/* ${ENUMS_CONVERSION} */ #ifdef __cplusplus extern "C" { diff --git a/languages/c/templates/schemas/src/Module_Common.cpp b/languages/c/templates/schemas/src/Module_Common.cpp index 40d1f362..452d34c3 100644 --- a/languages/c/templates/schemas/src/Module_Common.cpp +++ b/languages/c/templates/schemas/src/Module_Common.cpp @@ -21,10 +21,7 @@ #include "Common/${info.title}.h" #include "JsonData_${info.title}.h" -namespace WPEFramework { - - /* ${ENUMS_CONVERSION} */ -} +/* ${ENUMS_CONVERSION} */ #ifdef __cplusplus extern "C" { diff --git a/languages/c/templates/sections/enum_conversion.c b/languages/c/templates/sections/enum_conversion.c index 9295133c..e5165c61 100644 --- a/languages/c/templates/sections/enum_conversion.c +++ b/languages/c/templates/sections/enum_conversion.c @@ -1 +1,5 @@ +namespace WPEFramework { + ${schema.list} + +} diff --git a/languages/c/templates/types/enum_conversion.c b/languages/c/templates/types/enum_conversion.c index 646567a0..ddda2ae9 100644 --- a/languages/c/templates/types/enum_conversion.c +++ b/languages/c/templates/types/enum_conversion.c @@ -1,4 +1,4 @@ -/* ${title} ${description} */ -ENUM_CONVERSION_BEGIN(${info.title}_${name}) - { ${info.TITLE}_${NAME}_${key}, _T("${value}") }, -ENUM_CONVERSION_END(${info.title}_${name}) + /* ${title} ${description} */ + ENUM_CONVERSION_BEGIN(${info.title}_${name}) + { ${info.TITLE}_${NAME}_${key}, _T("${value}") }, + ENUM_CONVERSION_END(${info.title}_${name}) diff --git a/src/macrofier/engine.mjs b/src/macrofier/engine.mjs index 8719db88..2f4d3292 100644 --- a/src/macrofier/engine.mjs +++ b/src/macrofier/engine.mjs @@ -325,6 +325,7 @@ const generateMacros = (obj, templates, languages, options = {}) => { const imports = generateImports(obj, templates) const initialization = generateInitialization(obj, templates) const enums = generateEnums(obj, templates) + const enumsConversion = generateEnumsConversion(obj, templates) const eventsEnum = generateEvents(obj, templates) const examples = generateExamples(obj, templates, languages) @@ -337,7 +338,6 @@ const generateMacros = (obj, templates, languages, options = {}) => { const methods = methodsArray.length ? getTemplate('/sections/methods', templates).replace(/\$\{method.list\}/g, methodsArray.map(m => m.body).join('\n')) : '' const methodList = methodsArray.filter(m => m.body).map(m => m.name) const providerInterfaces = generateProviderInterfaces(obj, templates) - const enumsConversion = generateEnumsConversion(obj, templates) const events = eventsArray.length ? getTemplate('/sections/events', templates).replace(/\$\{event.list\}/g, eventsArray.map(m => m.body).join('\n')) : '' const eventList = eventsArray.map(m => makeEventName(m)) const defaults = generateDefaults(obj, templates) @@ -564,6 +564,7 @@ const generateEnums = (json, templates) => { const generateEnumsConversion = (json, templates) => { return compose( option(''), + map(val => val ? getTemplate('/sections/enum_conversion', templates).replace(/\$\{schema.list\}/g, val.trimEnd()): ''), map(reduce((acc, val) => acc.concat(val).concat('\n'), '')), map(map((schema) => convertEnumTemplate(schema, '/types/enum_conversion', templates))), map(enumFinder), @@ -571,7 +572,6 @@ const generateEnumsConversion = (json, templates) => { )(json) } - const generateEvents = (json, templates) => { const eventNames = eventsOrEmptyArray(json).map(makeEventName) From 45c6f9d6cbd3277e8e02f014891bed14a71b6a39 Mon Sep 17 00:00:00 2001 From: HaseenaSainul Date: Mon, 15 May 2023 10:45:45 -0400 Subject: [PATCH 3/9] Types and Accessor related fixes: 1. Accessor creation 2. JsonContainer creation 3. Types order placed based on depenedencies 4. filtered redundant new lines 5. UnamedSchema issue fixes --- languages/c/Types.mjs | 790 +++++++++++------- languages/c/src/types/ImplHelpers.mjs | 295 +++---- languages/c/src/types/JSONHelpers.mjs | 70 +- languages/c/src/types/NativeHelpers.mjs | 103 ++- languages/c/templates/methods/property.c | 16 +- .../c/templates/modules/include/Module.h | 4 - languages/c/templates/schemas/default.c | 3 - .../c/templates/schemas/src/JsonData_Module.h | 2 +- languages/c/templates/sections/methods.c | 3 +- package-lock.json | 4 +- src/macrofier/engine.mjs | 46 +- 11 files changed, 757 insertions(+), 579 deletions(-) diff --git a/languages/c/Types.mjs b/languages/c/Types.mjs index e44b4a78..8522c112 100644 --- a/languages/c/Types.mjs +++ b/languages/c/Types.mjs @@ -19,364 +19,518 @@ import deepmerge from 'deepmerge' import { getPath } from '../../src/shared/json-schema.mjs' import { getTypeName, getModuleName, description, getObjectHandleManagement, getNativeType, getPropertyAccessors, capitalize, isOptional, generateEnum, getMapAccessors, getArrayAccessors } from './src/types/NativeHelpers.mjs' -import { getObjectHandleManagementImpl, getPropertyAccessorsImpl } from './src/types/ImplHelpers.mjs' -import { getJsonContainerDefinition } from './src/types/JSONHelpers.mjs' +import { getArrayAccessorsImpl, getMapAccessorsImpl, getObjectHandleManagementImpl, getPropertyAccessorsImpl } from './src/types/ImplHelpers.mjs' +import { getJsonContainerDefinition, getJsonDataStructName } from './src/types/JSONHelpers.mjs' + +const getSdkNameSpace = () => 'FireboltSDK' +const getJsonNativeTypeForOpaqueString = () => getSdkNameSpace() + '::JSON::String' +const getEnumName = (name, prefix) => ((prefix.length > 0) ? (prefix + '_' + name) : name) + +const hasProperties = (prop) => { + let hasProperty = false + if (prop.properties) { + hasProperty = true + } else if (prop.additionalProperties && ( prop.additionalProperties.type && (((prop.additionalProperties.type === 'object') && prop.additionalProperties.properties) || (prop.additionalProperties.type !== 'object')))) { + hasProperty = true + } + return hasProperty +} + +function validJsonObjectProperties(json = {}) { + + let valid = true + if (json.type === 'object' || (json.additonalProperties && typeof json.additonalProperties.type === 'object')) { + if (json.properties || json.additonalProperties) { + Object.entries(json.properties || json.additonalProperties).every(([pname, prop]) => { + if (!prop['$ref'] && (pname !== 'additionalProperties') && + ((!prop.type && !prop.const && (prop.schema && !prop.schema.type)) || (Array.isArray(prop.type) && (prop.type.find(t => t === 'null'))))) { + valid = false + } + return valid + }) + } + } + return valid +} + +const deepMergeAll = (module, name, schema, schemas, options) => { + let nonRefsProperty = [...schema.allOf.map(x => x['$ref'] ? '' : x)].filter(elm => elm) + let refsProperty = [...schema.allOf.map(x => x['$ref'] ? getPath(x['$ref'], module, schemas) : '')].filter(elm => elm) + let mergedProperty = [] + let mergedParamSchema = { + type: "object", + properties: {} + } + + nonRefsProperty.forEach(p => { + if (p.properties) { + Object.entries(p.properties).every(([pname, prop]) => { + let present = false + refsProperty.forEach(refP => { + if (refP.properties) { + Object.entries(refP.properties).every(([refname, refprop]) => { + if (refname == pname) { + present = true + } + return !present + }) + } + }) + let prefixedName = (present == false) ? (name + capitalize(pname)) : pname + mergedParamSchema.properties[prefixedName] = prop + return true + }) + mergedProperty.push(mergedParamSchema) + } + }) + refsProperty.forEach(ref => mergedProperty.push(ref)) + let union = deepmerge.all(mergedProperty) + + return union +} function getMethodSignature(method, module, { destination, isInterface = false }) { - const extraParam = '${method.result.type}* ${method.result.name}' + const extraParam = '${method.result.type}* ${method.result.name}' - const prefix = method.tags.find(t => t.name.split(":")[0] === "property") ? "Get" : "" + const prefix = method.tags.find(t => t.name.split(":")[0] === "property") ? "Get" : "" - return 'uint32_t ${info.title}_' + prefix + '${method.Name}(' + extraParam + ')' + return 'uint32_t ${info.title}_' + prefix + '${method.Name}(' + extraParam + ')' } function getMethodSignatureParams(method, module, { destination }) { - return method.params.map(param => param.name + (!param.required ? '?' : '') + ': ' + getSchemaType(param.schema, module, { title: true, destination })).join(', ') + return method.params.map(param => param.name + (!param.required ? '?' : '') + ': ' + getSchemaType(param.schema, module, { name: method.result.name, title: true, destination })).join(', ') } const safeName = prop => prop.match(/[.+]/) ? '"' + prop + '"' : prop function getSchemaType(schema, module, { name, destination, link = false, title = false, code = false, asPath = false, event = false, expandEnums = true, baseUrl = '' } = {}) { - let type = '' - let theTitle = schema.title || name || ('UnamedSchema' + (Math.floor(Math.random() * 100))) - - if (schema['x-method']) { - console.log(`WARNING UNHANDLED: x-method in ${theTitle}`) - //throw "x-methods not supported yet" - } + let info = getSchemaTypeInfo(module, schema, name, module['x-schemas'], { title: title }) + return info.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) - let tName = definition.title || schema['$ref'].split('/').pop() - return getSchemaType(definition, module, { name: tName, destination, link, title, code, asPath, event, expandEnums, baseUrl }) - } - } - else if (schema.const) { - type = getNativeType(schema) - return type - } - else if (schema.type === 'string' && schema.enum) { - //Enum - let typeName = getTypeName(getModuleName(module), theTitle) - return typeName - } - else if (Array.isArray(schema.type)) { - let type = schema.type.find(t => t !== 'null') - console.log(`WARNING UNHANDLED: type is an array containing ${schema.type}`) - } - else if (schema.type === 'array' && schema.items) { - let res - if (Array.isArray(schema.items)) { +function getSchemaTypeInfo(module = {}, json = {}, name = '', schemas = {}, prefixName = '', options = {level: 0, descriptions: true, title: false}) { + + if (json.schema) { + json = json.schema + } + + let structure = {} + structure["type"] = '' + structure["json"] = [] + structure["name"] = {} + structure["namespace"] = {} + + if (json['$ref']) { + if (json['$ref'][0] === '#') { + //Ref points to local schema + //Get Path to ref in this module and getSchemaType + let definition = getPath(json['$ref'], module, schemas) + let tName = definition.title || json['$ref'].split('/').pop() + const res = getSchemaTypeInfo(module, definition, tName, schemas, '', options) + structure.type = res.type + structure.json = res.json + structure.name = res.name + structure.namespace = res.namespace + return structure + } + } + else if (json.const) { + structure.type = getNativeType(json) + structure.json = json + return structure + } + else if (json['x-method']) { + console.log(`WARNING UNHANDLED: x-method in ${name}`) + return structure + //throw "x-methods not supported yet" + } + else if (json.type === 'string' && json.enum) { + //Enum + structure.name = capitalize(name || json.title) + let typeName = getTypeName(getModuleName(module), name || json.title, prefixName, false, false) + let res = description(capitalize(name || json.title), json.description) + '\n' + generateEnum(json, typeName) + structure.json = json + structure.type = typeName + structure.namespace = getModuleName(module) + return structure + } + else if (Array.isArray(json.type)) { + let type = json.type.find(t => t !== 'null') + console.log(`WARNING UNHANDLED: type is an array containing ${json.type}`) + } + else if (json.type === 'array' && json.items && (validJsonObjectProperties(json) === true)) { + let res + if (Array.isArray(json.items)) { //TODO - const IsHomogenous = arr => new Set(arr.map(item => item.type ? item.type : typeof item)).size === 1 - if (!IsHomogenous(schema.items)) { - throw 'Heterogenous Arrays not supported yet' - } - res = getSchemaType(schema.items[0], module, { destination, link, title, code, asPath, event, expandEnums, baseUrl }) - } - else { - // grab the type for the non-array schema - res = getSchemaType(schema.items, module, { destination, link, title, code, asPath, event, expandEnums, baseUrl }) - } - - if (!schema.title && !name) { - console.log(`WARNING: generated name for ${module.info.title} schema w/ no title: ${theTitle}`) - console.dir(schema) - } - - let n = getTypeName(getModuleName(module), theTitle) - return n + 'ArrayHandle' - } - else if (schema.allOf) { - let union = deepmerge.all([...schema.allOf.map(x => x['$ref'] ? getPath(x['$ref'], module) || x : x)]) - if (theTitle) { - union['title'] = theTitle - } - delete union['$ref'] - return getSchemaType(union, module, { destination, link, title, code, asPath, event, expandEnums, baseUrl }) + const IsHomogenous = arr => new Set(arr.map( item => item.type ? item.type : typeof item)).size === 1 + if (!IsHomogenous(json.items)) { + throw 'Heterogenous Arrays not supported yet' + } + res = getSchemaTypeInfo(module, json.items[0], json.items[0].name || name, schemas, prefixName) } - else if (schema.oneOf || schema.anyOf) { - return type - //TODO + else { + // grab the type for the non-array schema + res = getSchemaTypeInfo(module, json.items, json.items.name || name, schemas, prefixName) + } + + let arrayName = capitalize(res.name) + capitalize(res.json.type) + let n = getTypeName(getModuleName(module), arrayName, prefixName) + let def = description(arrayName, json.description) + '\n' + if (options.level === 0) { + def += getObjectHandleManagement(n + 'Array') + '\n' + } + + def += getArrayAccessors(getModuleName(module), arrayName, (n + 'Array'), res.type) + structure.name = res.name || name && (capitalize(name)) + structure.type = n + 'ArrayHandle' + structure.json = json + structure.namespace = getModuleName(module) + return structure + } + else if (json.allOf) { + let title = json.title ? json.title : name + let union = deepMergeAll(module, title, json, schemas, options) + union['title'] = title + + delete union['$ref'] + return getSchemaTypeInfo(module, union, '', schemas, '', options) + } + else if (json.oneOf) { + structure.type = 'char*' + structure.json.type = 'string' + return structure + } + else if (json.anyOf) { + //let mergedSchema = getMergedSchema(module, json, name, schemas) + //let prefix = ((prefixName.length > 0) && (name != prefixName)) ? prefixName : capitalize(name) + //return getSchemaTypeInfo(module, mergedSchema, '', schemas, prefix, options) + } + else if (json.type === 'object') { + structure.json = json + if (hasProperties(json)) { + structure.type = getTypeName(getModuleName(module), json.title || name, prefixName) + 'Handle' + structure.name = (json.name ? json.name : (json.title ? json.title : name)) + structure.namespace = (json.namespace ? json.namespace : getModuleName(module)) } - else if (schema.type === 'object') { - if (!schema.title && !name) { - console.log(`WARNING: generated name for ${module.info.title} schema w/ no title: ${theTitle}`) - console.dir(schema) - } - return getTypeName(getModuleName(module), theTitle) + 'Handle' - //TODO + else { + structure.type = 'char*' } - else if (schema.type) { - type = getNativeType(schema) - return type + if (name) { + structure.name = capitalize(name) } - // TODO: deal with dependencies - return type -} - -//function getSchemaShape(schema = {}, module = {}, { name = '', level = 0, title, summary, descriptions = true, destination, enums = true } = {}) -// function getSchemaType() -function getSchemaShape(schema, module, { name = '', level = 0, title, summary, descriptions = true, destination = '', section = '', enums = true } = {}) { - const isHeader = destination.endsWith(".h") - const isCPP = (destination.endsWith(".cpp") && section !== 'accessors') - - schema = JSON.parse(JSON.stringify(schema)) - - let shape = '' - - name = schema.title || name - - if (!name) { - console.log(`WARNING: schema without a name in ${module.info.title}`) - return shape + return structure + } + else if (json.type) { + structure.type = getNativeType(json) + structure.json = json + if (name || json.title) { + structure.name = capitalize(name || json.title) } + structure.namespace = getModuleName(module) - if (schema['$ref']) { - if (schema['$ref'][0] === '#') { - //Ref points to local schema - //Get Path to ref in this module and getSchemaType - - const schema = getPath(schema['$ref'], module) - const tname = name || schema['$ref'].split('/').pop() - return getSchemaShape(schema, module, { name: tname, descriptions: descriptions, level: level }) - } - } - //If the schema is a const, - else if (schema.hasOwnProperty('const') && !isCPP) { - if (level > 0) { + return structure + } + return structure +} - let t = description(name, schema.description) - typeName = getTypeName(getModuleName(module), name) - t += (isHeader ? getPropertyAccessors(typeName, capitalize(name), typeof schema.const, { level: level, readonly: true, optional: false }) : getPropertyAccessorsImpl(typeName, capitalize(name), getJsonType(schema, module, { level, name }), typeof schema.const, { level: level, readonly: true, optional: false })) +function getSchemaShape(json, module, { name = '', level = 0, title, summary, descriptions = true, destination = '', section = '', enums = true } = {}) { + return getSchemaShapeInfo(json, module, module['x-schemas'], '', { name, level, title, summary, descriptions, destination, section, enums }) +} +function getSchemaShapeInfo(json, module, schemas = {}, prefixName = '', { name = '', level = 0, title, summary, descriptions = true, destination = '', section = '', enums = true } = {}) { + const isHeader = (destination.includes("JsonData_") !== true) && destination.endsWith(".h") + const isCPP = ((destination.endsWith(".cpp") || destination.includes("JsonData_")) && section !== 'accessors') + json = JSON.parse(JSON.stringify(json)) + + name = json.title || name + let shape = '' + + if (json['$ref']) { + if (json['$ref'][0] === '#') { + //Ref points to local schema + //Get Path to ref in this module and getSchemaType + const schema = getPath(json['$ref'], module, schemas) + const tname = schema.title || json['$ref'].split('/').pop() + shape = getSchemaShapeInfo(schema, module, schemas, prefixName, { name, level, title, summary, descriptions, destination, section, enums }) + } + } + //If the schema is a const, + else if (json.hasOwnProperty('const') && !isCPP) { + if (level > 0) { + + let t = description(name, json.description) + typeName = getTypeName(getModuleName(module), name, prefixName) + t += (isHeader ? getPropertyAccessors(typeName, capitalize(name), typeof schema.const, { level: level, readonly: true, optional: false }) : getPropertyAccessorsImpl(typeName, getJsonType(schema, module, { level, name }), typeof schema.const, { level: level, readonly: true, optional: false })) shape += '\n' + t - } } - else if (schema.type === 'object') { - if (!name) { - console.log(`WARNING: unnamed schema in ${module.info.title}.`) - console.dir(schema) - shape = '' - } - else if (schema.properties) { - let tName = getTypeName(getModuleName(module), name) - let c_shape = description(name, schema.description) - let cpp_shape = '' - c_shape += '\n' + (isHeader ? getObjectHandleManagement(tName) : getObjectHandleManagementImpl(tName, getJsonType(schema, module, { name }))) - Object.entries(schema.properties).forEach(([pname, prop]) => { - c_shape += '\n' + description(pname, prop.description) - let res - if (prop.type === 'array') { - if (Array.isArray(prop.items)) { - //TODO - const IsHomogenous = arr => new Set(arr.map(item => item.type ? item.type : typeof item)).size === 1 - if (!IsHomogenous(prop.items)) { - throw 'Heterogenous Arrays not supported yet' - } - res = getSchemaType(prop.items[0], module, { name: pname, level: level, descriptions: descriptions, title: true }) - } - else { - // grab the type for the non-array schema - res = getSchemaType(prop.items, module, { name: pname, level: level, descriptions: descriptions, title: true }) - } - if (res && res.length > 0) { - let n = tName + '_' + capitalize(pname || prop.title) - let def = getArrayAccessors(n + 'Array', res) - c_shape += '\n' + def - } - else { - console.log(`a. WARNING: Type undetermined for ${name}:${pname}`) - } - } else { - res = getSchemaType(prop, module, { name: pname, descriptions: descriptions, level: level + 1, title: true }) - if (res && res.length > 0) { - c_shape += '\n' + (isHeader ? getPropertyAccessors(tName, capitalize(pname), res, { level: level, readonly: false, optional: isOptional(pname, schema) }) : getPropertyAccessorsImpl(tName, capitalize(pname), getJsonType(prop, module, { level, name }), res, { level: level, readonly: false, optional: isOptional(pname, schema) })) - } - else { - console.log(`b. WARNING: Type undetermined for ${name}:${pname}`) - } - } - }) - cpp_shape += getJsonContainerDefinition(tName, Object.entries(schema.properties).map(([name, prop]) => ({ name, type: getJsonType(prop, module) }))) - - if (isCPP) { - shape += '\n' + cpp_shape - } - else { - shape += '\n' + c_shape - } - } - else if (schema.propertyNames && schema.propertyNames.enum) { - //propertyNames in object not handled yet - } - else if (schema.additionalProperties && (typeof schema.additionalProperties === 'object') && !isCPP) { - //This is a map of string to type in schema - //Get the Type - let type = getSchemaType(schema.additionalProperties, module, { name: name }) - if (type && type.length > 0) { - let tName = getTypeName(getModuleName(module), name) - // type.deps.forEach(dep => structure.deps.add(dep)) - let t = description(name, schema.description) - t += '\n' + (isHeader ? getObjectHandleManagement(tName) : getObjectHandleManagementImpl(tName, getJsonType(schema, module, { name }))) - t += getMapAccessors(getTypeName(getModuleName(module), name), type, { descriptions: descriptions, level: level }) - shape += '\n' + t - } - else { - console.log(`c. WARNING: Type undetermined for ${name}`) + } + else if (json.type === 'object') { + if (!name) { + console.log(`WARNING: unnamed schema in ${module.info.title}.`) + console.dir(json) + shape = '' + } + else if (json.properties && (validJsonObjectProperties(json) === true)) { + let c_shape = description(name, json.description) + let cpp_shape = '' + let tName = getTypeName(getModuleName(module), name, prefixName) + c_shape += '\n' + (isHeader ? getObjectHandleManagement(tName) : getObjectHandleManagementImpl(tName, getJsonType(json, module, { name }))) + Object.entries(json.properties).forEach(([pname, prop]) => { + let res + var desc = '\n' + description(pname, prop.description) + if (prop.type === 'array') { + if (Array.isArray(prop.items)) { + //TODO + const IsHomogenous = arr => new Set(arr.map( item => item.type ? item.type : typeof item)).size === 1 + if (!IsHomogenous(prop.items)) { + throw 'Heterogenous Arrays not supported yet' } + res = getSchemaTypeInfo(module, prop.items[0], pname, schemas, prefixName, options) + } + else { + // grab the type for the non-array schema + res = getSchemaTypeInfo(module, prop.items, pname, schemas, prefixName, {level : level, descriptions: descriptions, title: true}) + } + if (res.type && res.type.length > 0) { + let n = tName + '_' + (pname || prop.title) + let def = (isHeader ? getArrayAccessors(n + 'Array', res) : getArrayAccessorsImpl(tName, pname, res, { readonly: true, optional: false })) + c_shape += '\n' + def + } + else { + console.log(`a. WARNING: Type undetermined for ${name}:${pname}`) + } + } else { + let info = getSchemaTypeInfo(module, prop, pname, module['x-schemas'], prefixName, {descriptions: descriptions, level: level + 1, title: true}) + if (info.type && info.type.length > 0) { + let subPropertyName = ((pname.length !== 0) ? capitalize(pname) : info.name) + let moduleProperty = getJsonTypeInfo(module, json, name, schemas, prefixName) + let subProperty = getJsonTypeInfo(module, prop, pname, schemas, prefixName) + c_shape += '\n' + description(pname, info.json.description) + c_shape += '\n' + (isHeader ? getPropertyAccessors(tName, capitalize(pname), info.type, { level: level, readonly: false, optional: isOptional(pname, json) }) : getPropertyAccessorsImpl(tName, moduleProperty.type, subProperty.type, subPropertyName, info.type, info.json, {readonly:false, optional:isOptional(pname, json)})) + } + else { + console.log(`b. WARNING: Type undetermined for ${name}:${pname}`) + } } - else if (schema.patternProperties) { - console.log(`WARNING: patternProperties not supported yet...`) - // throw "patternProperties are not supported by Firebolt" - } - } - else if (schema.anyOf) { - - } - else if (schema.oneOf) { - - } - else if (schema.allOf) { - let union = deepmerge.all([...schema.allOf.map(x => x['$ref'] ? getPath(x['$ref'], module) || x : x)]) - if (name) { - union['title'] = name - } - delete union['$ref'] - return getSchemaShape(union, module, { name, level, title, summary, descriptions, destination, section, enums }) - - } - else if (schema.type === 'array') { - let res = getSchemaType(schema, module, { name, level: 0, descriptions: descriptions }) - // res.deps.forEach(dep => structure.deps.add(dep)) - } - else { - let res = getSchemaType(schema, module, { name, level: level, descriptions: descriptions }) - // res.deps.forEach(dep => structure.deps.add(dep)) - } - // console.dir(structure.deps) - return shape + }) + cpp_shape += getJsonContainerDefinition(json, name, Object.entries(json.properties).map(([name, prop]) => ({ name, type: getJsonType(prop, module, { name }) }))) + + if (isCPP) { + shape += '\n' + cpp_shape + } + else { + shape += '\n' + c_shape + } + } + else if (json.propertyNames && json.propertyNames.enum) { + //propertyNames in object not handled yet + } + else if (json.additionalProperties && (typeof json.additionalProperties === 'object') && (validJsonObjectProperties(json) === true) && !isCPP) { + let info = getSchemaTypeInfo(module, json.additionalProperties, name, module['x-schemas']) + if (!info.type || (info.type.length === 0)) { + info.type = 'char*' + info.json = schema.additionalProperties + info.json.type = 'string' + } + let tName = getTypeName(getModuleName(module), name) + let t = description(name, json.description) + '\n' + let containerType = 'WPEFramework::Core::JSON::VariantContainer' + + let subModuleProperty = getJsonTypeInfo(module, info.json, info.name, module['x-schemas']) + if (isCPP && ((info.json.type === 'object' && info.json.properties) || info.json.type === 'array')) { + // Handle Container generation here + } + t += '\n' + (isHeader ? getObjectHandleManagement(tName) : getObjectHandleManagementImpl(tName, containerType)) + t += (isHeader ? getMapAccessors(tName, info.type, { descriptions: descriptions, level: level }) : getMapAccessorsImpl(tName, containerType, subModuleProperty.type, info.type, info.json, { readonly: true, optional: false })) + shape += '\n' + t + } + else if (json.patternProperties) { + console.log(`WARNING: patternProperties are not supported by Firebolt(inside getModuleName(moduleJson):${name})`) + } + } + else if (json.anyOf) { + //let mergedSchema = getMergedSchema(module, json, name, schemas) + //let prefix = ((prefixName.length > 0) && (name != prefixName)) ? prefixName : capitalize(name) + //return getSchemaShapeInfo(moduleJson, mergedSchema, schemas, name, prefix, { name, level, title, summary, descriptions, destination, section, enums }) + } + else if (json.oneOf) { + //Just ignore schema shape, since this has to be treated as string + } + else if (json.allOf) { + let title = (json.title ? json.title : name) + let union = deepMergeAll(module, title, json, schemas) + union.title = title + + delete union['$ref'] + return getSchemaShapeInfo(union, module, schemas, prefixName, { name, level, title, summary, descriptions, destination, section, enums }) + } + else if (json.type === 'array') { + shape += '\n' + getSchemaType(module, json, name, schemas, prefixName, {level: 0, descriptions: descriptions}) + } + else { + shape += '\n' + getSchemaType(module, json, name, schemas, prefixName, {level: level, descriptions: descriptions}) + } + + return shape } -// function getJsonType(schema, module, { destination, link = false, title = false, code = false, asPath = false, event = false, expandEnums = true, baseUrl = '' } = {}) { - -const getJsonDataStructName = (modName, name) => `${capitalize(modName)}::${capitalize(name)}` - const getJsonNativeType = json => { - let type - let jsonType = json.const ? typeof json.const : json.type - - if (jsonType === 'string') { - type = 'WPEFramework::Core::JSON::String' - } - else if (jsonType === 'number' || json.type === 'integer') { //Lets keep it simple for now - type = 'WPEFramework::Core::JSON::Number' - } - else if (jsonType === 'boolean') { - type = 'WPEFramework::Core::JSON::Boolean' - } - else { - throw 'Unknown JSON Native Type !!!' - } - return type + let type + let jsonType = json.const ? typeof json.const : json.type + + if (jsonType === 'string') { + type = getSdkNameSpace() + '::JSON::String' + } + else if (jsonType === 'number') { + type = 'WPEFramework::Core::JSON::Float' + } + else if (json.type === 'integer') { + type = 'WPEFramework::Core::JSON::DecSInt32' + } + else if (jsonType === 'boolean') { + type = 'WPEFramework::Core::JSON::Boolean' + } + else { + throw 'Unknown JSON Native Type !!!' + } + return type } function getJsonType(schema = {}, module = {}, { name = '', descriptions = false, level = 0 } = {}) { + let info = getJsonTypeInfo(module, schema, name, module['x-schemas'], '', { descriptions: descriptions, level: level }) + return info.type +} - 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) - let tName = definition.title || schema['$ref'].split('/').pop() - return getJsonType(definition, module, { name: tName, descriptions: descriptions, level: level }) - } - } - else if (schema.const) { - return getJsonNativeType(schema) - } - else if (schema['x-method']) { - console.log(`WARNING: x-methods are not supported yet...`) - return type - //throw "x-methods not supported yet" - } - else if (schema.type === 'string' && schema.enum) { - //Enum - let t = getSchemaType(schema, module, { name }) - return 'WPEFramework::Core::JSON::EnumType<::' + t + '>' - } - else if (Array.isArray(schema.type)) { - let type = schema.type.find(t => t !== 'null') - console.log(`WARNING UNHANDLED: type is an array containing ${schema.type}`) - } - else if (schema.type === 'array' && schema.items) { - let res - if (Array.isArray(schema.items)) { - //TODO - const IsHomogenous = arr => new Set(arr.map(item => item.type ? item.type : typeof item)).size === 1 - if (!IsHomogenous(schema.items)) { - throw 'Heterogenous Arrays not supported yet' - } - res = getJsonType(schema.items[0], module, { name: '' }) - } - else { - // grab the type for the non-array schema - res = getJsonType(schema.items, module, { name: '' }) - } - - return `WPEFramework::Core::JSON::ArrayType<${res}>` +function getJsonTypeInfo(module = {}, json = {}, name = '', schemas, prefixName = '', {descriptions = false, level = 0} = {}) { + + if (json.schema) { + json = json.schema + } + + let structure = {} + structure["deps"] = new Set() //To avoid duplication of local ref definitions + structure["type"] = [] + + if (json['$ref']) { + if (json['$ref'][0] === '#') { + //Ref points to local schema + //Get Path to ref in this module and getSchemaType + let definition = getPath(json['$ref'], module, schemas) + let tName = definition.title || json['$ref'].split('/').pop() + + const res = getJsonTypeInfo(module, definition, tName, schemas, '', {descriptions: descriptions, level: level}) + structure.deps = res.deps + structure.type = res.type + return structure + } + } + else if (json.const) { + structure.type = getJsonNativeType(json) + return structure + } + else if (json['x-method']) { + return structure + //throw "x-methods not supported yet" + } + else if (json.additionalProperties && (typeof json.additionalProperties === 'object')) { + //This is a map of string to type in schema + //Get the Type + let type = getJsonTypeInfo(module, json.additionalProperties, name, schemas, prefixName) + if (type.type && type.type.length > 0) { + structure.type = 'WPEFramework::Core::JSON::VariantContainer'; + return structure + } + else { + console.log(`WARNING: Type undetermined for ${name}`) + } + } + else if (json.type === 'string' && json.enum) { + //Enum + let t = 'WPEFramework::Core::JSON::EnumType<' + (json.namespace ? json.namespace : getModuleName(module)) + '_' + (getEnumName(name, prefixName)) + '>' + structure.type.push(t) + return structure + } + else if (Array.isArray(json.type)) { + let type = json.type.find(t => t !== 'null') + console.log(`WARNING UNHANDLED: type is an array containing ${json.type}`) + } + else if (json.type === 'array' && json.items) { + let res + let items + if (Array.isArray(json.items)) { + //TODO + const IsHomogenous = arr => new Set(arr.map( item => item.type ? item.type : typeof item)).size === 1 + if (!IsHomogenous(json.items)) { + throw 'Heterogenous Arrays not supported yet' + } + items = json.items[0] } - else if (schema.allOf) { - let union = deepmerge.all([...schema.allOf.map(x => x['$ref'] ? getPath(x['$ref'], module, schemas) || x : x)]) - if (schema.title) { - union['title'] = schema.title - } - else { - union['title'] = name - } - delete union['$ref'] - return getJsonType(union, module, { name: '', level, descriptions }) - } - else if (schema.oneOf || schema.anyOf) { - return type - //TODO - } - else if (schema.type === 'object') { - if (!schema.title && !name) { - console.log(`WARNING: schema with no name`) - console.dir(schema) - return 'Unknown' - } - return getJsonDataStructName(getModuleName(module), schema.title || name) - //TODO - } - else if (schema.type) { - return getJsonNativeType(schema) + else { + items = json.items + // grab the type for the non-array schema + } + res = getJsonTypeInfo(module, items, items.name || name, schemas, prefixName) + structure.deps = res.deps + let n = capitalize(name || json.title) + structure.type.push(`WPEFramework::Core::JSON::ArrayType<${res.type}>`) + + return structure + } + else if (json.allOf) { + let title = json.title ? json.title : name + let union = deepMergeAll(module, title, json, schemas) + union['title'] = title + + delete union['$ref'] + return getJsonTypeInfo(module, union, '', schemas, '', options) + } + else if (json.oneOf) { + structure.type = getJsonNativeTypeForOpaqueString() + return structure + } + else if (json.patternProperties) { + structure.type = getJsonNativeTypeForOpaqueString() + return structure + } + else if (json.anyOf) { + /*let mergedSchema = getMergedSchema(module, json, name, schemas) + return getJsonTypeInfo(module, mergedSchema, name, schemas, prefixName, options)*/ + } + else if (json.type === 'object') { + if (hasProperties(json) !== true) { + structure.type = getJsonNativeTypeForOpaqueString() } - return type + else { + let schema = getSchemaTypeInfo(module, json, name) + if (schema.namespace && schema.namespace.length > 0) { + structure.type.push(getJsonDataStructName(schema.namespace, json.title || name, prefixName)) + } + } + return structure + } + else if (json.type) { + structure.type = getJsonNativeType(json) + return structure + } + return structure } function getTypeScriptType(jsonType) { - if (jsonType === 'integer') { - return 'number' - } - else { - return jsonType - } + if (jsonType === 'integer') { + return 'number' + } + else { + return jsonType + } } const enumReducer = (acc, val, i, arr) => { - const keyName = val.split(':').pop().replace(/[\.\-]/g, '_').replace(/\+/g, '_plus').replace(/([a-z])([A-Z0-9])/g, '$1_$2').toUpperCase() - acc = acc + ` ${keyName} = '${val}'` - if (i < arr.length - 1) { - acc = acc.concat(',\n') - } - return acc + const keyName = val.split(':').pop().replace(/[\.\-]/g, '_').replace(/\+/g, '_plus').replace(/([a-z])([A-Z0-9])/g, '$1_$2').toUpperCase() + acc = acc + ` ${keyName} = '${val}'` + if (i < arr.length - 1) { + acc = acc.concat(',\n') + } + return acc } export default { @@ -385,4 +539,4 @@ export default { getSchemaShape, getSchemaType, getJsonType -} \ No newline at end of file +} diff --git a/languages/c/src/types/ImplHelpers.mjs b/languages/c/src/types/ImplHelpers.mjs index f3b39cbf..33e97c53 100644 --- a/languages/c/src/types/ImplHelpers.mjs +++ b/languages/c/src/types/ImplHelpers.mjs @@ -1,28 +1,35 @@ const Indent = '\t' +const getSdkNameSpace = () => 'FireboltSDK' +const wpeJsonNameSpace = () => 'WPEFramework::Core::JSON' +const getFireboltStringType = () => 'FireboltTypes_StringHandle' + const getObjectHandleManagementImpl = (varName, jsonDataName) => { - let result = ` -${varName}Handle ${varName}Handle_Create(void) { + let result = `${varName}Handle ${varName}Handle_Create(void) +{ WPEFramework::Core::ProxyType<${jsonDataName}>* type = new WPEFramework::Core::ProxyType<${jsonDataName}>(); *type = WPEFramework::Core::ProxyType<${jsonDataName}>::Create(); return (static_cast<${varName}Handle>(type)); } -void ${varName}Handle_Addref(${varName}Handle handle) { +void ${varName}Handle_Addref(${varName}Handle handle) +{ ASSERT(handle != NULL); WPEFramework::Core::ProxyType<${jsonDataName}>* var = static_cast*>(handle); ASSERT(var->IsValid()); var->AddRef(); } -void ${varName}Handle_Release(${varName}Handle handle) { +void ${varName}Handle_Release(${varName}Handle handle) +{ ASSERT(handle != NULL); WPEFramework::Core::ProxyType<${jsonDataName}>* var = static_cast*>(handle); var->Release(); - if(var->IsValid() != true) { + if (var->IsValid() != true) { delete var; } } -bool ${varName}Handle_IsValid(${varName}Handle handle) { +bool ${varName}Handle_IsValid(${varName}Handle handle) +{ ASSERT(handle != NULL); WPEFramework::Core::ProxyType<${jsonDataName}>* var = static_cast*>(handle); ASSERT(var->IsValid()); @@ -32,105 +39,68 @@ bool ${varName}Handle_IsValid(${varName}Handle handle) { return result } -const getPropertyAccessorsImpl = (objName, propertyName, jsonDataName, propertyType, json = {}, options = {readonly:false, optional:false}) => { - - let result - if (json.type === 'object') { - result += `${objName}_${propertyName}Handle ${objName}_Get_${propertyName}(${objName}Handle handle) { +const getPropertyAccessorsImpl = (objName, modulePropertyType, subPropertyType, subPropertyName, accessorPropertyType, json = {}, options = {readonly:false, optional:false}) => { + let result = '' + result += `${accessorPropertyType} ${objName}_Get_${subPropertyName}(${objName}Handle handle) +{ ASSERT(handle != NULL); - WPEFramework::Core::ProxyType<${jsonDataName}>* var = static_cast*>(handle); + WPEFramework::Core::ProxyType<${modulePropertyType}>* var = static_cast*>(handle); ASSERT(var->IsValid()); - - WPEFramework::Core::ProxyType<${objName}::${propertyName}>* object = new WPEFramework::Core::ProxyType<${objName}::${propertyName}>(); - *object = WPEFramework::Core::ProxyType<${objName}::${propertyName}>::Create(); - *(*object) = (*var)->${propertyName}; - return (static_cast<${objName}_${propertyType}Handle>(object));` + '\n' - } else if (json.type === 'array') { - result += `${objName}_${propertyName}ArrayHandle ${objName}_Get_${propertyName}(${objName}Handle handle) { - ASSERT(handle != NULL); - WPEFramework::Core::ProxyType<${jsonDataName}>* var = static_cast*>(handle); - ASSERT(var->IsValid()); - - WPEFramework::Core::ProxyType>* object = new WPEFramework::Core::ProxyType>(); - *object = WPEFramework::Core::ProxyType>::Create(); - *(*object) = (*var)->${propertyName}.Element(); - return (static_cast<${objName}_${propertyType}ArrayHandle>(object));` + '\n' - } else if (json.enum) { - result += `${objName}_${propertyName} ${objName}_Get_${propertyName}(${objName}Handle handle) { - ASSERT(handle != NULL); - WPEFramework::Core::ProxyType<${jsonDataName}>* var = static_cast*>(handle); - ASSERT(var->IsValid()); - - return static_cast<${propertyType}>((*var)->${propertyName}.Value());` + '\n' - } else { - result += `${propertyType} ${objName}_Get_${propertyName}(${objName}Handle handle) { - ASSERT(handle != NULL); - WPEFramework::Core::ProxyType<${jsonDataName}>* var = static_cast*>(handle); - ASSERT(var->IsValid());` + '\n' - if (json.type === 'string') { - result += ` - return static_cast<${propertyType}>((*var)->${propertyName}.Value().c_str());` + '\n' - } else { - result += ` - return static_cast<${propertyType}>((*var)->${propertyName}.Value());` + '\n' +` + '\n' + if ((json.type === 'object') && (accessorPropertyType !== 'char*')) { + result += ` WPEFramework::Core::ProxyType<${subPropertyType}>* element = new WPEFramework::Core::ProxyType<${subPropertyType}>(); + *element = WPEFramework::Core::ProxyType<${subPropertyType}>::Create(); + *(*element) = (*var)->${subPropertyName}; + return (static_cast<${accessorPropertyType}>(element));` + '\n' + } + else { + if ((typeof json.const === 'string') || (json.type === 'string' && !json.enum) || (accessorPropertyType === 'char*')) { + result += ` return (const_cast<${accessorPropertyType}>((*var)->${subPropertyName}.Value().c_str()));` + '\n' + } + else { + result += ` return (static_cast<${accessorPropertyType}>((*var)->${subPropertyName}.Value()));` + '\n' } } - result += ` -}` + '\n' - if (!options.readonly) { - if (json.type === 'object') { - result += `${Indent.repeat(options.level)}void ${objName}_Set_${propertyName}(${objName}Handle handle, ${objName}_${propertyName}Handle ${propertyName.toLowerCase()}) { - ASSERT(handle != NULL); - WPEFramework::Core::ProxyType<${jsonDataName}>* var = static_cast*>(handle); - ASSERT(var->IsValid()); + result += `}` + '\n' - WPEFramework::Core::ProxyType<${objName}::${propertyName}>* object = static_cast*>(${propertyName.toLowerCase()}); - (*var)->${propertyName} = *(*object);` + '\n' - } - if (json.type === 'array') { - result += `${Indent.repeat(options.level)}void ${objName}_Set_${propertyName}(${objName}Handle handle, ${objName}_${propertyName}ArrayHandle ${propertyName.toLowerCase()}) { - ASSERT(handle != NULL); - WPEFramework::Core::ProxyType<${jsonDataName}>* var = static_cast*>(handle); - ASSERT(var->IsValid()); - WPEFramework::Core::ProxyType>* object = static_cast>*>(${propertyName.toLowerCase()}).Element(); - (*var)->${propertyName} = *(*object);` + '\n' - } if (json.enum) { - result += `${Indent.repeat(options.level)}void ${objName}_Set_${propertyName}(${objName}Handle handle, ${objName}_${propertyName} ${propertyName.toLowerCase()}) { + if (!options.readonly) { + let type = (accessorPropertyType === getFireboltStringType()) ? 'char*' : accessorPropertyType + result += `void ${objName}_Set_${subPropertyName}(${objName}Handle handle, ${type} value)\n{ ASSERT(handle != NULL); - WPEFramework::Core::ProxyType<${jsonDataName}>* var = static_cast*>(handle); + WPEFramework::Core::ProxyType<${modulePropertyType}>* var = static_cast*>(handle); ASSERT(var->IsValid()); +` + '\n' - (*var)->${propertyName} = static_cast<${propertyType}>(${propertyName.toLowerCase()});` + '\n' + if (json.type === 'object' && (accessorPropertyType !== 'char*')) { + result += ` WPEFramework::Core::ProxyType<${subPropertyType}>* object = static_cast*>(value); + (*var)->${subPropertyName} = *(*object);` + '\n' } else { - result += `${Indent.repeat(options.level)}void ${objName}_Set_${propertyName}(${objName}Handle handle, ${propertyType} ${propertyName.toLowerCase()}) { - ASSERT(handle != NULL); - WPEFramework::Core::ProxyType<${jsonDataName}>* var = static_cast*>(handle); - ASSERT(var->IsValid()); - - (*var)->${propertyName} = static_cast<${propertyType}>(${propertyName.toLowerCase()});` + '\n' + result += ` (*var)->${subPropertyName} = value;` + '\n' } -result += `}` + '\n' + result += `}` + '\n' } if (options.optional === true) { - result += `${Indent.repeat(options.level)}bool ${objName}_has_${propertyName}(${objName}Handle handle) { + result += `bool ${objName}_Has_${subPropertyName}(${objName}Handle handle)\n{ ASSERT(handle != NULL); - WPEFramework::Core::ProxyType<${jsonDataName}>* var = static_cast*>(handle); + WPEFramework::Core::ProxyType<${modulePropertyType}>* var = static_cast*>(handle); ASSERT(var->IsValid()); - return ((*var)->${propertyName}.IsSet()); + + return ((*var)->${subPropertyName}.IsSet()); }` + '\n' - result += `${Indent.repeat(options.level)}void ${objName}_clear_${propertyName}(${objName}Handle handle) { + result += `void ${objName}_Clear_${subPropertyName}(${objName}Handle handle)\n{ ASSERT(handle != NULL); - WPEFramework::Core::ProxyType<${jsonDataName}>* var = static_cast*>(handle); + WPEFramework::Core::ProxyType<${modulePropertyType}>* var = static_cast*>(handle); ASSERT(var->IsValid()); - ((*var)->${propertyName}.Clear()); + ((*var)->${subPropertyName}.Clear()); }` + '\n' } + return result } -const getArrayAccessors = (objName, propertyName, propertyType, json = {}, options = {readonly:false, optional:false}) => { +const getArrayAccessorsImpl = (objName, propertyName, propertyType, json = {}, options = {readonly:false, optional:false}) => { let result = ` uint32_t ${objName}_${propertyName}Array_Size(${objName}::${propertyName}ArrayHandle handle) { ASSERT(handle != NULL); @@ -205,90 +175,127 @@ result += `${objName}_${propertyType}Handle ${objName}_${propertyName}Array_Get( return result } -const getMapAccessors = (objName, propertyName, propertyType, json = {}, options = {readonly:false, optional:false}) => { - let result = `uint32_t ${objName}_${propertyName}_KeysCount(${objName}_${propertyName}Handle handle) { +const getMapAccessorsImpl = (objName, containerType, subPropertyType, accessorPropertyType, json = {}, options = {readonly:false, optional:false}) => { + let result = `uint32_t ${objName}_KeysCount(${objName}Handle handle) +{ ASSERT(handle != NULL); - WPEFramework::Core::ProxyType<${objName}::${propertyName}>* var = static_cast*>(handle); + WPEFramework::Core::ProxyType<${containerType}>* var = static_cast*>(handle); ASSERT(var->IsValid()); - return (*var)->Size()); - - }` + '\n' - result += `void ${objName}_${propertyName}_AddKey(${objName}_${propertyName}Handle handle, char* key, ${propertyType} value) { - ASSERT(handle != NULL); - WPEFramework::Core::ProxyType<${objName}::${propertyName}>* var = static_cast*>(handle); - ASSERT(var->IsValid());` + '\n' - - if (json.type === 'object') { - result += ` - (*var)->Add(key, value);` + '\n' - } else if (json.type === 'boolean') { - result += ` - WPEFramework::Core::JSON::Boolean element(value);` - } else if (json.type === 'string') { - result += ` - WPEFramework::Core::JSON::String element(value);` - } else if (json.type === 'number') { - result += ` - WPEFramework::Core::JSON::Number element(value);` - } else if (json.type === 'array') { - result += ` - WPEFramework::Core::JSON::ArrayType element(value);` - } else if (json.enum) { - result += ` - WPEFramework::Core::JSON::EnumType element(value); - (*var)->Add(key, element);` + '\n' + ${containerType}::Iterator elements = (*var)->Variants(); + uint32_t count = 0; + while (elements.Next()) { + count++; } - result += ` - }` + '\n' - result += `void ${objName}_${propertyName}_RemoveKey(${objName}_${propertyName}Handle handle, char* key) { + return (count); +}` + '\n' + result += `void ${objName}_AddKey(${objName}Handle handle, char* key, ${accessorPropertyType} value) +{ ASSERT(handle != NULL); - WPEFramework::Core::ProxyType<${objName}::${propertyName}>* var = static_cast*>(handle); + WPEFramework::Core::ProxyType<${containerType}>* var = static_cast*>(handle); ASSERT(var->IsValid()); - - (*var)->Remove(key); - }` + '\n' +` + '\n' + let elementContainer = subPropertyType + if (containerType.includes('VariantContainer')) { + elementContainer = 'WPEFramework::Core::JSON::Variant' + } + if ((json.type === 'object') || (json.type === 'array' && json.items)) { + if (containerType.includes('VariantContainer')) { + result += ` ${subPropertyType}& container = *(*(static_cast*>(value)));` + '\n' + result += ` string containerStr;` + '\n' + result += ` element.ToString(containerStr);` + '\n' + result += ` WPEFramework::Core::JSON::VariantContainer containerVariant(containerStr);` + '\n' + result += ` WPEFramework::Core::JSON::Variant element = containerVariant;` + '\n' + } + else { + result += ` ${subPropertyType}& element = *(*(static_cast*>(value)));` + '\n' + } + } else { + result += ` ${elementContainer} element(value);` + '\n' + } + result += ` (*var)->Set(const_cast(key), element); +}` + '\n' - if (json.type === 'object') { - result += `${objName}_${propertyType}Handle ${objName}_${propertyName}_FindKey(${objName}_${propertyName}Handle handle, char* key) { + result += `void ${objName}_RemoveKey(${objName}Handle handle, char* key) +{ ASSERT(handle != NULL); - WPEFramework::Core::ProxyType<${objName}::${propertyName}>* var = static_cast*>(handle); + WPEFramework::Core::ProxyType<${containerType}>* var = static_cast*>(handle); ASSERT(var->IsValid()); - WPEFramework::Core::ProxyType<${objName}::${propertyType}>* object = new WPEFramework::Core::ProxyType<${objName}::${propertyType}>(); - *object = WPEFramework::Core::ProxyType<${objName}::${propertyName}>::Create(); - *(*object) = (*var)->Find(key); - return (static_cast<${objName}_${propertyType}Handle>(object));` + '\n' - } else if (json.type === 'array') { - result += `${objName}_${propertyType}ArrayHandle ${objName}_${propertyName}_FindKey(${objName}_${propertyName}Handle handle, char* key) { - ASSERT(handle != NULL); - WPEFramework::Core::ProxyType<${objName}::${propertyName}>* var = static_cast*>(handle); - ASSERT(var->IsValid()); - WPEFramework::Core::ProxyType>* object = new WPEFramework::Core::ProxyType>(); - *object = WPEFramework::Core::ProxyType>::Create(); - *(*object) = (*var)->Find(key); - return (static_cast<${objName}_${propertyType}ArrayHandle>(object));` + '\n' + (*var)->Remove(key); +}` + '\n' - } else { - result += `${propertyType} ${objName}_${propertyName}_FindKey(${objName}_${propertyName}Handle handle, char* key) { + result += `${accessorPropertyType} ${objName}_FindKey(${objName}Handle handle, char* key) +{ ASSERT(handle != NULL); - WPEFramework::Core::ProxyType<${objName}::${propertyName}>* var = static_cast*>(handle); + WPEFramework::Core::ProxyType<${containerType}>* var = static_cast*>(handle); ASSERT(var->IsValid());` + '\n' - - if (json.type === 'string') { + if ((json.type === 'object') || (json.type === 'array') || + ((json.type === 'string' || (typeof json.const === 'string')) && !json.enum)) { + result += ` ${accessorPropertyType} status = nullptr;` + '\n' + } + else if (json.type === 'boolean') { + result += ` ${accessorPropertyType} status = false;` + '\n' + } + else { + result += ` ${accessorPropertyType} status = 0;` + '\n' + } + + result += ` + if ((*var)->HasLabel(key) == true) {` + if (json.type === 'object') { + result += ` + string objectStr; + (*var)->Get(key).Object().ToString(objectStr); + ${subPropertyType} objectMap; + objectMap.FromString(objectStr); + + WPEFramework::Core::ProxyType<${subPropertyType}>* element = new WPEFramework::Core::ProxyType<${subPropertyType}>(); + *element = WPEFramework::Core::ProxyType<${subPropertyType}>::Create(); + *(*element) = objectMap; + + status = (static_cast<${accessorPropertyType}>(element));` + '\n' + } + else if (json.type === 'array' && json.items) { + result += ` + WPEFramework::Core::ProxyType<${subPropertyType}>* element = new WPEFramework::Core::ProxyType<${subPropertyType}>(); + *element = WPEFramework::Core::ProxyType<${subPropertyType}>::Create(); + *(*element) = (*var)->Get(key).Array(); + status = (static_cast<${accessorPropertyType}>(element));` + '\n' + } + else { + if (json.type === 'string' || (typeof json.const === 'string')) { + if (json.enum) { + result += ` + status = (const_cast<${accessorPropertyType}>((*var)->Get(key).));` + '\n' + } + else { + result += ` + status = (const_cast<${accessorPropertyType}>((*var)->Get(key).String().c_str()));` + '\n' + } + } + else if (json.type === 'boolean') { result += ` - return (static_cast<${propertyType}>((*var)->(Find(key).Value().c_str())));` + '\n' - } else { + status = (static_cast<${accessorPropertyType}>((*var)->Get(key).Boolean()));` + '\n' + } + else if (json.type === 'number') { result += ` - return (static_cast<${propertyType}>((*var)->(Find(key).Value())));` + '\n' + status = (static_cast<${accessorPropertyType}>((*var)->Get(key).Float()));` + '\n' + } + else if (json.type === 'integer') { + result += ` + status = (static_cast<${accessorPropertyType}>((*var)->Get(key).Number()));` + '\n' } } - result += ` -}` + '\n' + result += ` } + return status; +}` return result } export { + getArrayAccessorsImpl, + getMapAccessorsImpl, getObjectHandleManagementImpl, getPropertyAccessorsImpl } diff --git a/languages/c/src/types/JSONHelpers.mjs b/languages/c/src/types/JSONHelpers.mjs index 0d2d6a08..2a787c97 100644 --- a/languages/c/src/types/JSONHelpers.mjs +++ b/languages/c/src/types/JSONHelpers.mjs @@ -1,31 +1,54 @@ const capitalize = str => str[0].toUpperCase() + str.substr(1) +const getSdkNameSpace = () => 'FireboltSDK' +const getJsonDataPrefix = () => 'JsonData_' +const wpeJsonNameSpace = () => 'WPEFramework::Core::JSON' -function getJsonContainerDefinition (name, props) { - name = capitalize(name) - let c = ` class ${name}: public Core::JSON::Container { - public: - ${name}(const ${name}&) = delete; - ${name}& operator=(const ${name}&) = delete; - ~${name}() override = default; - - public: - ${name}() - : Core::JSON::Container() - {` +const getJsonDataStructName = (modName, name, prefixName = '') => { + let result =((prefixName.length > 0) && (prefixName != name)) ? `${capitalize(modName)}::${getJsonDataPrefix()}${capitalize(prefixName)}${capitalize(name)}` : `${capitalize(modName)}::${getJsonDataPrefix()}${capitalize(name)}` + + return ((result.includes(wpeJsonNameSpace()) === true) ? result : `${getSdkNameSpace()}::${result}`) +} + +function getJsonContainerDefinition (schema, name, props) { + let c = schema.description ? (' /*\n * ${info.title} - ' + `${schema.description}\n */\n`) : '' + name = getJsonDataPrefix() + capitalize(name) + c += ` class ${name}: public WPEFramework::Core::JSON::Container { + public: + ~${name}() override = default; - props.forEach(prop => { - c += `\n Add(_T("${prop.name}"), &${capitalize(prop.name)});` - }) + public: + ${name}() + : WPEFramework::Core::JSON::Container() + {` - c += `\n }\n\n public:` + props.forEach(prop => { + c += `\n Add(_T("${prop.name}"), &${capitalize(prop.name)});` + }) + c += `\n }\n` + c += `\n ${name}(const ${name}& copy) + {` + props.forEach(prop => { + c += `\n Add(_T("${prop.name}"), &${capitalize(prop.name)});` + c += `\n ${capitalize(prop.name)} = copy.${capitalize(prop.name)};` + }) + c += ` + }\n + ${name}& operator=(const ${name}& rhs) + {` + props.forEach(prop => { + c += `\n ${capitalize(prop.name)} = rhs.${capitalize(prop.name)};` + }) + c += `\n return (*this); + }\n + public:` - props.forEach(prop => { - c += `\n ${prop.type} ${capitalize(prop.name)};` - }) + props.forEach(prop => { + c += `\n ${prop.type} ${capitalize(prop.name)};` + }) - c += '\n };' - return c - } + c += '\n };' + return c +} /* @@ -57,5 +80,6 @@ function getJsonEnumConversion(schema, { name }) { export { getJsonContainerDefinition, - getJsonEnumConversion + getJsonEnumConversion, + getJsonDataStructName } diff --git a/languages/c/src/types/NativeHelpers.mjs b/languages/c/src/types/NativeHelpers.mjs index 79242d1f..56e45ac8 100644 --- a/languages/c/src/types/NativeHelpers.mjs +++ b/languages/c/src/types/NativeHelpers.mjs @@ -29,6 +29,7 @@ const { isObject, isArray, propEq, pathSatisfies, hasProp, propSatisfies } = pre const getModuleName = json => getPathOr(null, ['info', 'title'], json) || json.title || 'missing' +const getFireboltStringType = () => 'FireboltTypes_StringHandle' const getHeaderText = () => { return `/* @@ -84,34 +85,21 @@ const SdkTypesPrefix = 'Firebolt' const Indent = ' ' const getNativeType = json => { - let type - - if (json.const) { - if (typeof json.const === 'string') { - type = 'char*' - } - else if (typeof json.const === 'number') { - type = 'uint32_t' - if (json.const < 0) - type = 'int32_t' - } else if (typeof json.const === 'boolean'){ - type = 'bool' - } - } - else if (json.type === 'string') { - type = 'char*' - } - else if (json.type === 'number' || json.type === 'integer') { //Lets keep it simple for now - type = 'uint32_t' - if ((json.minimum && json.minimum < 0) - || (json.exclusiveMinimum && json.exclusiveMinimum < 0)) { - type = 'int32_t' - } - } - else if (json.type === 'boolean') { - type = 'bool' - } - return type + let type + let jsonType = json.const ? typeof json.const : json.type + if (jsonType === 'string') { + type = 'char*' + } + else if (jsonType === 'number') { + type = 'float' + } + else if (jsonType === 'integer') { + type = 'int32_t' + } + else if (jsonType === 'boolean') { + type = 'bool' + } + return type } const getObjectHandleManagement = varName => { @@ -126,38 +114,43 @@ bool ${varName}Handle_IsValid(${varName}Handle handle); } const getPropertyAccessors = (objName, propertyName, propertyType, options = {level:0, readonly:false, optional:false}) => { - let result = `${Indent.repeat(options.level)}${propertyType} ${objName}_Get_${propertyName}(${objName}Handle handle);` + '\n' if (!options.readonly) { - result += `${Indent.repeat(options.level)}void ${objName}_Set_${propertyName}(${objName}Handle handle, ${propertyType} ${propertyName.toLowerCase()});` + '\n' + let type = (propertyType === getFireboltStringType()) ? 'char*' : propertyType + result += `${Indent.repeat(options.level)}void ${objName}_Set_${propertyName}(${objName}Handle handle, ${type} ${propertyName.toLowerCase()});` + '\n' } if (options.optional === true) { - result += `${Indent.repeat(options.level)}bool ${objName}_has_${propertyName}(${objName}Handle handle);` + '\n' - result += `${Indent.repeat(options.level)}void ${objName}_clear_${propertyName}(${objName}Handle handle);` + '\n' + result += `${Indent.repeat(options.level)}bool ${objName}_Has_${propertyName}(${objName}Handle handle);` + '\n' + result += `${Indent.repeat(options.level)}void ${objName}_Clear_${propertyName}(${objName}Handle handle);` + '\n' } return result } -const getMapAccessors = (typeName, nativeType, level=0) => { +const getMapAccessors = (typeName, accessorPropertyType, level = 0) => { let res res = `${Indent.repeat(level)}uint32_t ${typeName}_KeysCount(${typeName}Handle handle);` + '\n' - res += `${Indent.repeat(level)}void ${typeName}_AddKey(${typeName}Handle handle, char* key, ${nativeType} value);` + '\n' + res += `${Indent.repeat(level)}void ${typeName}_AddKey(${typeName}Handle handle, char* key, ${accessorPropertyType} value);` + '\n' res += `${Indent.repeat(level)}void ${typeName}_RemoveKey(${typeName}Handle handle, char* key);` + '\n' - res += `${Indent.repeat(level)}${nativeType} ${typeName}_FindKey(${typeName}Handle handle, char* key);` + '\n' + res += `${Indent.repeat(level)}${accessorPropertyType} ${typeName}_FindKey(${typeName}Handle handle, char* key);` + '\n' return res } -const getTypeName = (moduleName, varName, upperCase = false) => { - let mName = upperCase ? moduleName.toUpperCase() : capitalize(moduleName) - let vName = upperCase ? varName.toUpperCase() : capitalize(varName) +const getTypeName = (moduleName, varName, prefixName = '', upperCase = false, capitalCase = true) => { - return `${mName}_${vName}` + let mName = upperCase ? moduleName.toUpperCase() : capitalize(moduleName) + let vName = upperCase ? varName.toUpperCase() : capitalCase ? capitalize(varName) : varName + if (prefixName.length > 0) { + prefixName = (prefixName !== varName) ? (upperCase ? prefixName.toUpperCase() : capitalize(prefixName)) : '' + } + prefixName = (prefixName.length > 0) ?(upperCase ? prefixName.toUpperCase() : capitalize(prefixName)) : prefixName + let name = (prefixName.length > 0) ? `${mName}_${prefixName}_${vName}` : `${mName}_${vName}` + return name } const getArrayAccessors = (arrayName, valueType) => { @@ -201,25 +194,25 @@ const getIncludeDefinitions = (json = {}, jsonData = false) => { .concat([`#include "Firebolt/Types.h"`]) } - function getPropertyGetterSignature(method, module, paramType) { - let m = `${capitalize(getModuleName(module))}_Get${capitalize(method.name)}` - return `${description(method.name, method.summary)}\nuint32 ${m}( ${paramType === 'char*' ? 'FireboltTypes_StringHandle' : paramType}* ${method.result.name || method.name} )` - } +function getPropertyGetterSignature(method, module, paramType) { + let m = `${capitalize(getModuleName(module))}_Get${capitalize(method.name)}` + return `${description(method.name, method.summary)}\nuint32 ${m}( ${paramType === 'char*' ? 'FireboltTypes_StringHandle' : paramType}* ${method.result.name || method.name} )` +} - function getPropertySetterSignature(method, module, paramType) { - let m = `${capitalize(getModuleName(module))}_Set${capitalize(method.name)}` - return `${description(method.name, method.summary)}\nuint32 ${m}( ${paramType} ${method.result.name || method.name} )` - } +function getPropertySetterSignature(method, module, paramType) { + let m = `${capitalize(getModuleName(module))}_Set${capitalize(method.name)}` + return `${description(method.name, method.summary)}\nuint32 ${m}( ${paramType} ${method.result.name || method.name} )` +} - function getPropertyEventCallbackSignature(method, module, paramType) { - return `typedef void (*On${capitalize(method.name)}Changed)(${paramType === 'char*' ? 'FireboltTypes_StringHandle' : paramType})` - } +function getPropertyEventCallbackSignature(method, module, paramType) { + return `typedef void (*On${capitalize(method.name)}Changed)(${paramType === 'char*' ? 'FireboltTypes_StringHandle' : paramType})` +} - function getPropertyEventSignature(method, module) { - return `${description(method.name, 'Listen to updates')}\n` + `uint32_t ${capitalize(getModuleName(module))}_Listen${capitalize(method.name)}Update(On${capitalize(method.name)}Changed notification, uint16_t* listenerId)` - } +function getPropertyEventSignature(method, module) { + return `${description(method.name, 'Listen to updates')}\n` + `uint32_t ${capitalize(getModuleName(module))}_Listen${capitalize(method.name)}Update(On${capitalize(method.name)}Changed notification, uint16_t* listenerId)` +} - export { +export { getHeaderText, getIncludeGuardOpen, getStyleGuardOpen, @@ -241,4 +234,4 @@ const getIncludeDefinitions = (json = {}, jsonData = false) => { getPropertyAccessors, isOptional, generateEnum - } +} diff --git a/languages/c/templates/methods/property.c b/languages/c/templates/methods/property.c index 8f301bea..1c70ba29 100644 --- a/languages/c/templates/methods/property.c +++ b/languages/c/templates/methods/property.c @@ -1,12 +1,12 @@ /* ${method.name} - ${method.description} */ uint32_t ${info.title}_Get${method.Name}(${method.params}${if.params}, ${end.if.params}${method.result.type}* ${method.result.name}) { - const string method = _T("${info.title}.${method.name}"); - FireboltSDK::${info.title}::${method.result.type} jsonResult; + const string method = _T("${info.title}.${method.name}"); + FireboltSDK::${info.title}::${method.result.type} jsonResult; - uint32_t status = FireboltSDK::Properties::Get(method, jsonResult); - if (status == FireboltSDKErrorNone) { - WPEFramework::Core::ProxyType* resultPtr = new WPEFramework::Core::ProxyType(); - *${method.result.name} = static_cast<${info.title}_${method.result.type}Handle>(resultPtr); - } - return status; + uint32_t status = FireboltSDK::Properties::Get(method, jsonResult); + if (status == FireboltSDKErrorNone) { + WPEFramework::Core::ProxyType* resultPtr = new WPEFramework::Core::ProxyType(); + *${method.result.name} = static_cast<${info.title}_${method.result.type}Handle>(resultPtr); + } + return status; } diff --git a/languages/c/templates/modules/include/Module.h b/languages/c/templates/modules/include/Module.h index ee034605..a202f643 100644 --- a/languages/c/templates/modules/include/Module.h +++ b/languages/c/templates/modules/include/Module.h @@ -30,10 +30,6 @@ extern "C" { /* ${ENUMS} */ -// Types - -/* ${TYPES} */ - /* ${ACCESSORS} */ /* ${DECLARATIONS} */ diff --git a/languages/c/templates/schemas/default.c b/languages/c/templates/schemas/default.c index a2058da5..9a52cff7 100644 --- a/languages/c/templates/schemas/default.c +++ b/languages/c/templates/schemas/default.c @@ -1,4 +1 @@ -/* - * ${schema.description} - */ ${schema.shape} diff --git a/languages/c/templates/schemas/src/JsonData_Module.h b/languages/c/templates/schemas/src/JsonData_Module.h index 9ba90428..7fa2b6f4 100644 --- a/languages/c/templates/schemas/src/JsonData_Module.h +++ b/languages/c/templates/schemas/src/JsonData_Module.h @@ -20,6 +20,6 @@ namespace FireboltSDK { namespace ${info.title} { // Types - /* ${SCHEMAS}*/ + /* ${SCHEMAS} */ } } diff --git a/languages/c/templates/sections/methods.c b/languages/c/templates/sections/methods.c index 3f382a63..3ab606c0 100644 --- a/languages/c/templates/sections/methods.c +++ b/languages/c/templates/sections/methods.c @@ -1,3 +1,4 @@ - // Methods +// Methods + ${method.list} diff --git a/package-lock.json b/package-lock.json index 8382cf29..0186c79b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@firebolt-js/openrpc", - "version": "1.8.0-next.2", + "version": "2.0.0-next.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@firebolt-js/openrpc", - "version": "1.8.0-next.2", + "version": "2.0.0-next.0", "license": "Apache-2.0", "dependencies": { "ajv": "^8.3.0", diff --git a/src/macrofier/engine.mjs b/src/macrofier/engine.mjs index 962dbb16..070fbc42 100644 --- a/src/macrofier/engine.mjs +++ b/src/macrofier/engine.mjs @@ -105,11 +105,12 @@ const getLinkForSchema = (schema, json) => { const dirs = config.createModuleDirectories const copySchemasIntoModules = config.copySchemasIntoModules + let name = schema.title || schema.name if (schema.schema) { schema = schema.schema } - const type = types.getSchemaType(schema, json, { destination: state.destination, section: state.section }) + const type = types.getSchemaType(schema, json, { name: name, destination: state.destination, section: state.section }) // local - insert a bogus link, that we'll udpate later based on final table-of-contents if (json.components.schemas[type]) { @@ -341,12 +342,12 @@ const generateMacros = (obj, templates, languages, options = {}) => { const events = eventsArray.length ? getTemplate('/sections/events', templates).replace(/\$\{event.list\}/g, eventsArray.map(m => m.body).join('\n')) : '' const eventList = eventsArray.map(m => makeEventName(m)) const defaults = generateDefaults(obj, templates) - const schemasArray = generateSchemas(obj, templates, { baseUrl: '', section: 'schemas' }).filter(s => (options.copySchemasIntoModules || !s.uri)) + const schemasArray = generateSchemas(obj, templates, { baseUrl: '', section: 'schemas' }).filter(s => (options.copySchemasIntoModules || !s.uri)).reverse() const accessorsArray = generateSchemas(obj, templates, { baseUrl: '', section: 'accessors' }).filter(s => (options.copySchemasIntoModules || !s.uri)) - const schemas = schemasArray.length ? getTemplate('/sections/schemas', templates).replace(/\$\{schema.list\}/g, schemasArray.map(s => s.body).join('\n')) : '' + const schemas = schemasArray.length ? getTemplate('/sections/schemas', templates).replace(/\$\{schema.list\}/g, schemasArray.map(s => s.body).filter(body => body).join('\n')) : '' const typesArray = schemasArray.filter(x => !x.enum) - const types = typesArray.length ? getTemplate('/sections/types', templates).replace(/\$\{schema.list\}/g, typesArray.map(s => s.body).join('\n')) : '' - const accessors = accessorsArray.length ? getTemplate('/sections/accessors', templates).replace(/\$\{schema.list\}/g, accessorsArray.map(s => s.body).join('\n')) : '' + const types = typesArray.length ? getTemplate('/sections/types', templates).replace(/\$\{schema.list\}/g, typesArray.map(s => s.body).filter(body => body).join('\n')) : '' + const accessors = accessorsArray.length ? getTemplate('/sections/accessors', templates).replace(/\$\{schema.list\}/g, accessorsArray.map(s => s.body).filter(body => body).join('\n')) : '' const module = getTemplate('/codeblocks/module', templates) const macros = { @@ -636,6 +637,7 @@ function generateSchemas(json, templates, options) { } let content = getTemplate('/schemas/default', templates) + content = content.trim() if (!schema.examples || schema.examples.length === 0) { content = content.replace(/\$\{if\.examples\}.*?\{end\.if\.examples\}/gms, '') @@ -1066,9 +1068,9 @@ function insertMethodMacros(template, methodObj, json, templates, examples={}) { .replace(/\$\{method\.result\.name\}/g, result.name) .replace(/\$\{method\.result\.summary\}/g, result.summary) .replace(/\$\{method\.result\.link\}/g, getLinkForSchema(result, json)) //, baseUrl: options.baseUrl - .replace(/\$\{method\.result\.type\}/g, types.getSchemaType(result.schema, json, {title: true, asPath: false, destination: state.destination })) //, baseUrl: options.baseUrl - .replace(/\$\{event\.result\.type\}/, isEventMethod(methodObj) ? types.getSchemaType(result.schema, json, { destination: state.destination, event: true, description: methodObj.result.summary, asPath: false }): '') //, baseUrl: options.baseUrl - .replace(/\$\{method\.result\}/g, generateResult(result.schema, json, templates)) + .replace(/\$\{method\.result\.type\}/g, types.getSchemaType(result.schema, json, {name: result.title || result.name, title: true, asPath: false, destination: state.destination })) //, baseUrl: options.baseUrl + .replace(/\$\{event\.result\.type\}/, isEventMethod(methodObj) ? types.getSchemaType(result.schema, json, { name: result.title || result.name, destination: state.destination, event: true, description: methodObj.result.summary, asPath: false }): '') //, baseUrl: options.baseUrl + .replace(/\$\{method\.result\}/g, generateResult(result, json, templates)) .replace(/\$\{method\.example\.value\}/g, JSON.stringify(methodObj.examples[0].result.value)) .replace(/\$\{method\.alternative\}/g, method.alternative) .replace(/\$\{method\.alternative.link\}/g, '#'+(method.alternative || "").toLowerCase()) @@ -1196,25 +1198,29 @@ function insertExampleMacros(template, examples, method, json, templates) { return template.replace(/\$\{method\.examples\}/g, content) } -function generateResult(result, json, templates) { - const type = types.getSchemaType(result, json, { destination: state.destination, section: state.section }) +function generateResult(schema, json, templates) { + + let name = schema.name || schema.title + let result = schema.schema ? schema.schema : schema + + const type = types.getSchemaType(result, json, { name: name, destination: state.destination, section: state.section }) if (result.type === 'object' && result.properties) { let content = getTemplate('/types/object', templates).split('\n') for (var i=0; i= 0) { - content[i] = Object.entries(result.properties).map(([title, property]) => insertSchemaMacros(content[i], title, property, json)).join('\n') + content[i] = Object.entries(result.properties).map(([title, property]) => insertSchemaMacros(content[i], title || name, property, json)).join('\n') } } - return insertSchemaMacros(content.join('\n'), result.title, result, json) + return insertSchemaMacros(content.join('\n'), name, schema, json) } else if (type === 'string' && Array.isArray(result.enum)) { - return insertSchemaMacros(getTemplate('/types/enum', templates), result, json) + return insertSchemaMacros(getTemplate('/types/enum', templates), name, schema, json) } else if (result.$ref) { - const link = getLinkForSchema(result, json) + const link = getLinkForSchema(schema, json) // if we get a real link use it if (link !== '#') { @@ -1222,19 +1228,19 @@ function generateResult(result, json, templates) { } // otherwise this was a schema with no title, and we'll just copy it here else { - const schema = localizeDependencies(result, json) + const sch = localizeDependencies(result, json) return getTemplate('/types/default', templates) - .replace(/\$\{type\}/, types.getSchemaShape(schema, json, { name: result.$ref.split("/").pop()})) + .replace(/\$\{type\}/, types.getSchemaShape(sch, json, { name: result.$ref.split("/").pop()})) } } else { - return insertSchemaMacros(getTemplate('/types/default', templates), result.title, result, json) + return insertSchemaMacros(getTemplate('/types/default', templates), name, schema, json) } } function insertSchemaMacros(template, title, schema, module) { return template.replace(/\$\{property\}/g, title) - .replace(/\$\{type\}/g, types.getSchemaType(schema, module, { destination: state.destination, section: state.section, code: false })) + .replace(/\$\{type\}/g, types.getSchemaType(schema.schema ? schema.schema : schema, module, { name: title, destination: state.destination, section: state.section, code: false })) .replace(/\$\{type.link\}/g, getLinkForSchema(schema, module)) .replace(/\$\{description\}/g, schema.description || '') .replace(/\$\{name\}/g, title || '') @@ -1245,9 +1251,9 @@ function insertParameterMacros(template, param, method, module) { //| `${method.param.name}` | ${method.param.type} | ${method.param.required} | ${method.param.summary} ${method.param.constraints} | let constraints = getSchemaConstraints(param, module) - let type = types.getSchemaType(param.schema, module, { destination: state.destination, section: state.section, code: false, link: false, title: true, asPath: false, expandEnums: false }) //baseUrl: options.baseUrl + let type = types.getSchemaType(param.schema, module, { name: param.name, destination: state.destination, section: state.section, code: false, link: false, title: true, asPath: false, expandEnums: false }) //baseUrl: options.baseUrl let typeLink = getLinkForSchema(param, module) - let jsonType = types.getJsonType(param.schema, module, { destination: state.destination, section: state.section, code: false, link: false, title: true, asPath: false, expandEnums: false }) + let jsonType = types.getJsonType(param.schema, module, { name: param.name, destination: state.destination, section: state.section, code: false, link: false, title: true, asPath: false, expandEnums: false }) if (constraints && type) { constraints = '
' + constraints From 13b1e6c4e02da06e9fae44d12c864b67de0d0a97 Mon Sep 17 00:00:00 2001 From: HaseenaSainul Date: Tue, 23 May 2023 07:12:41 -0400 Subject: [PATCH 4/9] getLinkForSchema and generateResults: signature updated to pass optional name, and remove name and schema setting logic inside. remove reverse() content.trim: do only if there is no valid content, otherwise trim whitespace after content --- src/macrofier/engine.mjs | 42 +++++++++++++++++----------------------- 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/src/macrofier/engine.mjs b/src/macrofier/engine.mjs index 070fbc42..6e4fa117 100644 --- a/src/macrofier/engine.mjs +++ b/src/macrofier/engine.mjs @@ -101,15 +101,10 @@ const getTemplateForExampleResult = (method, templates) => { return template || JSON.stringify(method.examples[0].result.value, null, '\t') } -const getLinkForSchema = (schema, json) => { +const getLinkForSchema = (schema, json, { name = '' } = {}) => { const dirs = config.createModuleDirectories const copySchemasIntoModules = config.copySchemasIntoModules - let name = schema.title || schema.name - if (schema.schema) { - schema = schema.schema - } - const type = types.getSchemaType(schema, json, { name: name, destination: state.destination, section: state.section }) // local - insert a bogus link, that we'll udpate later based on final table-of-contents @@ -342,7 +337,7 @@ const generateMacros = (obj, templates, languages, options = {}) => { const events = eventsArray.length ? getTemplate('/sections/events', templates).replace(/\$\{event.list\}/g, eventsArray.map(m => m.body).join('\n')) : '' const eventList = eventsArray.map(m => makeEventName(m)) const defaults = generateDefaults(obj, templates) - const schemasArray = generateSchemas(obj, templates, { baseUrl: '', section: 'schemas' }).filter(s => (options.copySchemasIntoModules || !s.uri)).reverse() + const schemasArray = generateSchemas(obj, templates, { baseUrl: '', section: 'schemas' }).filter(s => (options.copySchemasIntoModules || !s.uri)) const accessorsArray = generateSchemas(obj, templates, { baseUrl: '', section: 'accessors' }).filter(s => (options.copySchemasIntoModules || !s.uri)) const schemas = schemasArray.length ? getTemplate('/sections/schemas', templates).replace(/\$\{schema.list\}/g, schemasArray.map(s => s.body).filter(body => body).join('\n')) : '' const typesArray = schemasArray.filter(x => !x.enum) @@ -637,7 +632,6 @@ function generateSchemas(json, templates, options) { } let content = getTemplate('/schemas/default', templates) - content = content.trim() if (!schema.examples || schema.examples.length === 0) { content = content.replace(/\$\{if\.examples\}.*?\{end\.if\.examples\}/gms, '') @@ -670,6 +664,9 @@ function generateSchemas(json, templates, options) { else { content = content.replace(/.*\$\{schema.seeAlso\}/, '') } + content = content.trim().length ? content.trimEnd() : content.trim() + + const isEnum = x => x.type === 'string' && Array.isArray(x.enum) && x.title const result = uri ? { uri: uri, @@ -723,7 +720,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, { destination: state.destination, section: state.section }) + '](' + getLinkForSchema(schema, json, true) + ')') // need full module here, not just the schema + .map(schema => '[' + types.getSchemaType(schema, json, { destination: state.destination, section: state.section }) + '](' + getLinkForSchema(schema, json, { name: schema.title }) + ')') // need full module here, not just the schema .filter(link => link) .join('\n') @@ -1067,10 +1064,10 @@ function insertMethodMacros(template, methodObj, json, templates, examples={}) { .replace(/\$\{method\.capabilities\}/g, capabilities) .replace(/\$\{method\.result\.name\}/g, result.name) .replace(/\$\{method\.result\.summary\}/g, result.summary) - .replace(/\$\{method\.result\.link\}/g, getLinkForSchema(result, json)) //, baseUrl: options.baseUrl - .replace(/\$\{method\.result\.type\}/g, types.getSchemaType(result.schema, json, {name: result.title || result.name, title: true, asPath: false, destination: state.destination })) //, baseUrl: options.baseUrl - .replace(/\$\{event\.result\.type\}/, isEventMethod(methodObj) ? types.getSchemaType(result.schema, json, { name: result.title || result.name, destination: state.destination, event: true, description: methodObj.result.summary, asPath: false }): '') //, baseUrl: options.baseUrl - .replace(/\$\{method\.result\}/g, generateResult(result, json, templates)) + .replace(/\$\{method\.result\.link\}/g, getLinkForSchema(result.schema, json, {name : result.name})) //, baseUrl: options.baseUrl + .replace(/\$\{method\.result\.type\}/g, types.getSchemaType(result.schema, json, {name: result.name, title: true, asPath: false, destination: state.destination })) //, baseUrl: options.baseUrl + .replace(/\$\{event\.result\.type\}/, isEventMethod(methodObj) ? types.getSchemaType(result.schema, json, { name: result.name, destination: state.destination, event: true, description: methodObj.result.summary, asPath: false }): '') //, baseUrl: options.baseUrl + .replace(/\$\{method\.result\}/g, generateResult(result.schema, json, templates, { name : result.name })) .replace(/\$\{method\.example\.value\}/g, JSON.stringify(methodObj.examples[0].result.value)) .replace(/\$\{method\.alternative\}/g, method.alternative) .replace(/\$\{method\.alternative.link\}/g, '#'+(method.alternative || "").toLowerCase()) @@ -1198,11 +1195,8 @@ function insertExampleMacros(template, examples, method, json, templates) { return template.replace(/\$\{method\.examples\}/g, content) } -function generateResult(schema, json, templates) { +function generateResult(result, json, templates, { name = '' } = {}) { - let name = schema.name || schema.title - let result = schema.schema ? schema.schema : schema - const type = types.getSchemaType(result, json, { name: name, destination: state.destination, section: state.section }) if (result.type === 'object' && result.properties) { @@ -1214,13 +1208,13 @@ function generateResult(schema, json, templates) { } } - return insertSchemaMacros(content.join('\n'), name, schema, json) + return insertSchemaMacros(content.join('\n'), name, result, json) } else if (type === 'string' && Array.isArray(result.enum)) { - return insertSchemaMacros(getTemplate('/types/enum', templates), name, schema, json) + return insertSchemaMacros(getTemplate('/types/enum', templates), name, result, json) } else if (result.$ref) { - const link = getLinkForSchema(schema, json) + const link = getLinkForSchema(result, json, { name: name}) // if we get a real link use it if (link !== '#') { @@ -1234,14 +1228,14 @@ function generateResult(schema, json, templates) { } } else { - return insertSchemaMacros(getTemplate('/types/default', templates), name, schema, json) + return insertSchemaMacros(getTemplate('/types/default', templates), name, result, json) } } function insertSchemaMacros(template, title, schema, module) { return template.replace(/\$\{property\}/g, title) .replace(/\$\{type\}/g, types.getSchemaType(schema.schema ? schema.schema : schema, module, { name: title, destination: state.destination, section: state.section, code: false })) - .replace(/\$\{type.link\}/g, getLinkForSchema(schema, module)) + .replace(/\$\{type.link\}/g, getLinkForSchema(schema.schema ? schema.schema : schema, module, { name: title })) .replace(/\$\{description\}/g, schema.description || '') .replace(/\$\{name\}/g, title || '') } @@ -1252,7 +1246,7 @@ function insertParameterMacros(template, param, method, module) { let constraints = getSchemaConstraints(param, module) let type = types.getSchemaType(param.schema, module, { name: param.name, destination: state.destination, section: state.section, code: false, link: false, title: true, asPath: false, expandEnums: false }) //baseUrl: options.baseUrl - let typeLink = getLinkForSchema(param, module) + let typeLink = getLinkForSchema(param.schema, module, { name: param.name }) let jsonType = types.getJsonType(param.schema, module, { name: param.name, destination: state.destination, section: state.section, code: false, link: false, title: true, asPath: false, expandEnums: false }) if (constraints && type) { @@ -1266,7 +1260,7 @@ function insertParameterMacros(template, param, method, module) { .replace(/\$\{method.param.required\}/g, param.required || 'false') .replace(/\$\{method.param.type\}/g, type) .replace(/\$\{json.param.type\}/g, jsonType) - .replace(/\$\{method.param.link\}/g, getLinkForSchema(param, module)) //getType(param)) + .replace(/\$\{method.param.link\}/g, getLinkForSchema(param.schema, module, { name: param.name} )) //getType(param)) .replace(/\$\{method.param.constraints\}/g, constraints) //getType(param)) } From da0284b4b613cda7903a2f593f5e2dbc3527ad96 Mon Sep 17 00:00:00 2001 From: HaseenaSainul Date: Thu, 25 May 2023 05:15:27 -0400 Subject: [PATCH 5/9] Types and Accessors: fixes to generate proper format and anyOf support added --- languages/c/Types.mjs | 281 ++++++++++++++----- languages/c/src/types/ImplHelpers.mjs | 99 ++++--- languages/c/src/types/JSONHelpers.mjs | 2 +- languages/c/src/types/NativeHelpers.mjs | 46 ++- languages/c/templates/modules/src/Module.cpp | 1 - languages/c/templates/sections/accessors.c | 1 - src/macrofier/engine.mjs | 2 +- 7 files changed, 301 insertions(+), 131 deletions(-) diff --git a/languages/c/Types.mjs b/languages/c/Types.mjs index 8522c112..6cebc2fc 100644 --- a/languages/c/Types.mjs +++ b/languages/c/Types.mjs @@ -18,7 +18,7 @@ import deepmerge from 'deepmerge' import { getPath } from '../../src/shared/json-schema.mjs' -import { getTypeName, getModuleName, description, getObjectHandleManagement, getNativeType, getPropertyAccessors, capitalize, isOptional, generateEnum, getMapAccessors, getArrayAccessors } from './src/types/NativeHelpers.mjs' +import { getTypeName, getModuleName, description, getObjectHandleManagement, getNativeType, getPropertyAccessors, capitalize, isOptional, generateEnum, getMapAccessors, getArrayAccessors, getArrayElementSchema } from './src/types/NativeHelpers.mjs' import { getArrayAccessorsImpl, getMapAccessorsImpl, getObjectHandleManagementImpl, getPropertyAccessorsImpl } from './src/types/ImplHelpers.mjs' import { getJsonContainerDefinition, getJsonDataStructName } from './src/types/JSONHelpers.mjs' @@ -26,6 +26,15 @@ const getSdkNameSpace = () => 'FireboltSDK' const getJsonNativeTypeForOpaqueString = () => getSdkNameSpace() + '::JSON::String' const getEnumName = (name, prefix) => ((prefix.length > 0) ? (prefix + '_' + name) : name) +const getRefModule = (title) => { + let module = { + info: { + title: `${title}` + } + } + return module +} + const hasProperties = (prop) => { let hasProperty = false if (prop.properties) { @@ -53,6 +62,75 @@ function validJsonObjectProperties(json = {}) { return valid } +function union(schemas, module, commonSchemas) { + + const result = {}; + for (const schema of schemas) { + for (const [key, value] of Object.entries(schema)) { + if (!result.hasOwnProperty(key)) { + // If the key does not already exist in the result schema, add it + if (value && value.anyOf) { + result[key] = union(value.anyOf, module, commonSchemas) + } else if (key === 'title' || key === 'description' || key === 'required') { + //console.warn(`Ignoring "${key}"`) + } else { + result[key] = value; + } + } else if (key === 'type') { + // If the key is 'type', merge the types of the two schemas + if(result[key] === value) { + //console.warn(`Ignoring "${key}" that is already present and same`) + } else { + console.warn(`ERROR "${key}" is not same -${JSON.stringify(result, null, 4)} ${key} ${result[key]} - ${value}`); + throw "ERROR: type is not same" + } + } else { + //If the Key is a const then merge them into an enum + if(value && value.const) { + if(result[key].enum) { + result[key].enum = Array.from(new Set([...result[key].enum, value.const])) + } + else { + result[key].enum = Array.from(new Set([result[key].const, value.const])) + delete result[key].const + } + } + // If the key exists in both schemas and is not 'type', merge the values + else if (Array.isArray(result[key])) { + // If the value is an array, concatenate the arrays and remove duplicates + result[key] = Array.from(new Set([...result[key], ...value])) + } else if (result[key] && result[key].enum && value && value.enum) { + //If the value is an enum, merge the enums together and remove duplicates + result[key].enum = Array.from(new Set([...result[key].enum, ...value.enum])) + } else if (typeof result[key] === 'object' && typeof value === 'object') { + // If the value is an object, recursively merge the objects + result[key] = union([result[key], value], module, commonSchemas); + } else if (result[key] !== value) { + // If the value is a primitive and is not the same in both schemas, ignore it + //console.warn(`Ignoring conflicting value for key "${key}"`) + } + } + } + } + return result; +} + +function getMergedSchema(module, json, name, schemas) { + let refsResolved = [...json.anyOf.map(x => x['$ref'] ? getPath(x['$ref'], module, schemas) || x : x)] + let allOfsResolved = refsResolved.map(sch => sch.allOf ? deepmerge.all([...sch.allOf.map(x => x['$ref'] ? getPath(x['$ref'], module, schemas) || x : x)]) : sch) + + let mergedSchema = union(allOfsResolved, module, schemas) + if (json.title) { + mergedSchema['title'] = json.title + } + else { + mergedSchema['title'] = name + } + + delete mergedSchema['$ref'] + return mergedSchema +} + const deepMergeAll = (module, name, schema, schemas, options) => { let nonRefsProperty = [...schema.allOf.map(x => x['$ref'] ? '' : x)].filter(elm => elm) let refsProperty = [...schema.allOf.map(x => x['$ref'] ? getPath(x['$ref'], module, schemas) : '')].filter(elm => elm) @@ -98,17 +176,18 @@ function getMethodSignature(method, module, { destination, isInterface = false } } function getMethodSignatureParams(method, module, { destination }) { - return method.params.map(param => param.name + (!param.required ? '?' : '') + ': ' + getSchemaType(param.schema, module, { name: method.result.name, title: true, destination })).join(', ') + + return method.params.map(param => param.name + (!param.required ? '?' : '') + ': ' + getSchemaType(param.schema, module, { name: param.name, title: true, destination })).join(', ') } const safeName = prop => prop.match(/[.+]/) ? '"' + prop + '"' : prop -function getSchemaType(schema, module, { name, destination, link = false, title = false, code = false, asPath = false, event = false, expandEnums = true, baseUrl = '' } = {}) { - let info = getSchemaTypeInfo(module, schema, name, module['x-schemas'], { title: title }) +function getSchemaType(schema, module, { name, prefix = '', destination, link = false, title = false, code = false, asPath = false, event = false, expandEnums = true, baseUrl = '' } = {}) { + let info = getSchemaTypeInfo(module, schema, name, module['x-schemas'], prefix, { title: title }) return info.type } -function getSchemaTypeInfo(module = {}, json = {}, name = '', schemas = {}, prefixName = '', options = {level: 0, descriptions: true, title: false}) { +function getSchemaTypeInfo(module = {}, json = {}, name = '', schemas = {}, prefix = '', options = {level: 0, descriptions: true, title: false}) { if (json.schema) { json = json.schema @@ -126,7 +205,12 @@ function getSchemaTypeInfo(module = {}, json = {}, name = '', schemas = {}, pref //Get Path to ref in this module and getSchemaType let definition = getPath(json['$ref'], module, schemas) let tName = definition.title || json['$ref'].split('/').pop() - const res = getSchemaTypeInfo(module, definition, tName, schemas, '', options) + let schema = module + if (json['$ref'].includes('x-schemas')) { + schema = (getRefModule(json['$ref'].split('/')[2])) + } + + const res = getSchemaTypeInfo(schema, definition, tName, schemas, '', options) structure.type = res.type structure.json = res.json structure.name = res.name @@ -147,7 +231,7 @@ function getSchemaTypeInfo(module = {}, json = {}, name = '', schemas = {}, pref else if (json.type === 'string' && json.enum) { //Enum structure.name = capitalize(name || json.title) - let typeName = getTypeName(getModuleName(module), name || json.title, prefixName, false, false) + let typeName = getTypeName(getModuleName(module), name || json.title, prefix, false, false) let res = description(capitalize(name || json.title), json.description) + '\n' + generateEnum(json, typeName) structure.json = json structure.type = typeName @@ -159,28 +243,22 @@ function getSchemaTypeInfo(module = {}, json = {}, name = '', schemas = {}, pref console.log(`WARNING UNHANDLED: type is an array containing ${json.type}`) } else if (json.type === 'array' && json.items && (validJsonObjectProperties(json) === true)) { - let res + let res = '' if (Array.isArray(json.items)) { //TODO const IsHomogenous = arr => new Set(arr.map( item => item.type ? item.type : typeof item)).size === 1 if (!IsHomogenous(json.items)) { throw 'Heterogenous Arrays not supported yet' } - res = getSchemaTypeInfo(module, json.items[0], json.items[0].name || name, schemas, prefixName) + res = getSchemaTypeInfo(module, json.items[0], json.items[0].name || name, schemas, prefix) } else { // grab the type for the non-array schema - res = getSchemaTypeInfo(module, json.items, json.items.name || name, schemas, prefixName) + res = getSchemaTypeInfo(module, json.items, json.items.name || name, schemas, prefix) } let arrayName = capitalize(res.name) + capitalize(res.json.type) - let n = getTypeName(getModuleName(module), arrayName, prefixName) - let def = description(arrayName, json.description) + '\n' - if (options.level === 0) { - def += getObjectHandleManagement(n + 'Array') + '\n' - } - - def += getArrayAccessors(getModuleName(module), arrayName, (n + 'Array'), res.type) + let n = getTypeName(getModuleName(module), arrayName, prefix) structure.name = res.name || name && (capitalize(name)) structure.type = n + 'ArrayHandle' structure.json = json @@ -201,14 +279,17 @@ function getSchemaTypeInfo(module = {}, json = {}, name = '', schemas = {}, pref return structure } else if (json.anyOf) { - //let mergedSchema = getMergedSchema(module, json, name, schemas) - //let prefix = ((prefixName.length > 0) && (name != prefixName)) ? prefixName : capitalize(name) - //return getSchemaTypeInfo(module, mergedSchema, '', schemas, prefix, options) + console.log("json.anyOf ---" + name) + console.log(json) + console.log(module) + let mergedSchema = getMergedSchema(module, json, name, schemas) + let prefixName = ((prefix.length > 0) && (name != prefix)) ? prefix : capitalize(name) + return getSchemaTypeInfo(module, mergedSchema, '', schemas, prefixName, options) } else if (json.type === 'object') { structure.json = json if (hasProperties(json)) { - structure.type = getTypeName(getModuleName(module), json.title || name, prefixName) + 'Handle' + structure.type = getTypeName(getModuleName(module), json.title || name, prefix) + 'Handle' structure.name = (json.name ? json.name : (json.title ? json.title : name)) structure.namespace = (json.namespace ? json.namespace : getModuleName(module)) } @@ -234,12 +315,14 @@ function getSchemaTypeInfo(module = {}, json = {}, name = '', schemas = {}, pref return structure } -function getSchemaShape(json, module, { name = '', level = 0, title, summary, descriptions = true, destination = '', section = '', enums = true } = {}) { - return getSchemaShapeInfo(json, module, module['x-schemas'], '', { name, level, title, summary, descriptions, destination, section, enums }) +function getSchemaShape(json, module, { name = '', prefix = '', level = 0, title, summary, descriptions = true, destination = '', section = '', enums = true } = {}) { + + let shape = getSchemaShapeInfo(json, module, module['x-schemas'], { name, prefix, merged: false, level, title, summary, descriptions, destination, section, enums }) + return shape } -function getSchemaShapeInfo(json, module, schemas = {}, prefixName = '', { name = '', level = 0, title, summary, descriptions = true, destination = '', section = '', enums = true } = {}) { +function getSchemaShapeInfo(json, module, schemas = {}, { name = '', prefix = '', merged = false, level = 0, title, summary, descriptions = true, destination = '', section = '', enums = true } = {}) { const isHeader = (destination.includes("JsonData_") !== true) && destination.endsWith(".h") - const isCPP = ((destination.endsWith(".cpp") || destination.includes("JsonData_")) && section !== 'accessors') + const isCPP = ((destination.endsWith(".cpp") || destination.includes("JsonData_")) && (section.includes('accessors') !== true)) json = JSON.parse(JSON.stringify(json)) name = json.title || name @@ -251,15 +334,19 @@ function getSchemaShapeInfo(json, module, schemas = {}, prefixName = '', { name //Get Path to ref in this module and getSchemaType const schema = getPath(json['$ref'], module, schemas) const tname = schema.title || json['$ref'].split('/').pop() - shape = getSchemaShapeInfo(schema, module, schemas, prefixName, { name, level, title, summary, descriptions, destination, section, enums }) + if (json['$ref'].includes('x-schemas')) { + schema = (getRefModule(json['$ref'].split('/')[2])) + } + + shape = getSchemaShapeInfo(schema, module, schemas, { name, prefix, merged, level, title, summary, descriptions, destination, section, enums }) } } //If the schema is a const, else if (json.hasOwnProperty('const') && !isCPP) { if (level > 0) { - let t = description(name, json.description) - typeName = getTypeName(getModuleName(module), name, prefixName) + let t = description(capitalize(name), json.description) + typeName = getTypeName(getModuleName(module), name, prefix) t += (isHeader ? getPropertyAccessors(typeName, capitalize(name), typeof schema.const, { level: level, readonly: true, optional: false }) : getPropertyAccessorsImpl(typeName, getJsonType(schema, module, { level, name }), typeof schema.const, { level: level, readonly: true, optional: false })) shape += '\n' + t } @@ -271,13 +358,15 @@ function getSchemaShapeInfo(json, module, schemas = {}, prefixName = '', { name shape = '' } else if (json.properties && (validJsonObjectProperties(json) === true)) { - let c_shape = description(name, json.description) + let c_shape = description(capitalize(name), json.description) let cpp_shape = '' - let tName = getTypeName(getModuleName(module), name, prefixName) + let tName = getTypeName(getModuleName(module), name, prefix) c_shape += '\n' + (isHeader ? getObjectHandleManagement(tName) : getObjectHandleManagementImpl(tName, getJsonType(json, module, { name }))) + let props = [] + let containerName = ((prefix.length > 0) && (name != prefix)) ? (prefix + capitalize(name)) : capitalize(name) Object.entries(json.properties).forEach(([pname, prop]) => { - let res - var desc = '\n' + description(pname, prop.description) + let items + var desc = '\n' + description(capitalize(pname), prop.description) if (prop.type === 'array') { if (Array.isArray(prop.items)) { //TODO @@ -285,35 +374,50 @@ function getSchemaShapeInfo(json, module, schemas = {}, prefixName = '', { name if (!IsHomogenous(prop.items)) { throw 'Heterogenous Arrays not supported yet' } - res = getSchemaTypeInfo(module, prop.items[0], pname, schemas, prefixName, options) + items = prop.items[0] } else { // grab the type for the non-array schema - res = getSchemaTypeInfo(module, prop.items, pname, schemas, prefixName, {level : level, descriptions: descriptions, title: true}) + items = prop.items } - if (res.type && res.type.length > 0) { - let n = tName + '_' + (pname || prop.title) - let def = (isHeader ? getArrayAccessors(n + 'Array', res) : getArrayAccessorsImpl(tName, pname, res, { readonly: true, optional: false })) - c_shape += '\n' + def + let info = getSchemaTypeInfo(module, items, items.name || pname, schemas, prefix, {level : level, descriptions: descriptions, title: true}) + if (info.type && info.type.length > 0) { + let objName = tName + '_' + capitalize(prop.title || pname) + let moduleName = info.namespace + info.json.namespace = info.namespace + let moduleProperty = getJsonTypeInfo(module, json, json.title || name, schemas, prefix) + let prefixName = ((prefix.length > 0) && items['$ref']) ? '' : prefix + let subModuleProperty = getJsonTypeInfo(module, info.json, info.name, schemas, prefix) + + let t = description(capitalize(info.name), json.description) + '\n' + t += '\n' + (isHeader ? getArrayAccessors(objName, tName, info.type) : getArrayAccessorsImpl(tName, moduleProperty.type, (tName + 'Handle'), subModuleProperty.type, capitalize(pname || prop.title), info.type, info.json)) + c_shape += '\n' + t + props.push({name: `${pname}`, type: `WPEFramework::Core::JSON::ArrayType<${subModuleProperty.type}>`}) } else { console.log(`a. WARNING: Type undetermined for ${name}:${pname}`) } } else { - let info = getSchemaTypeInfo(module, prop, pname, module['x-schemas'], prefixName, {descriptions: descriptions, level: level + 1, title: true}) + if (((merged === false) || ((merged === true) && (pname.includes(name)))) && (prop.type === 'object' || prop.anyOf || prop.allOf)) { + shape += getSchemaShapeInfo(prop, module, schemas, { name : pname, prefix, merged: false, level: 1, title, summary, descriptions, destination, section, enums }) + } + let info = getSchemaTypeInfo(module, prop, pname, module['x-schemas'], prefix, {descriptions: descriptions, level: level + 1, title: true}) if (info.type && info.type.length > 0) { let subPropertyName = ((pname.length !== 0) ? capitalize(pname) : info.name) - let moduleProperty = getJsonTypeInfo(module, json, name, schemas, prefixName) - let subProperty = getJsonTypeInfo(module, prop, pname, schemas, prefixName) - c_shape += '\n' + description(pname, info.json.description) - c_shape += '\n' + (isHeader ? getPropertyAccessors(tName, capitalize(pname), info.type, { level: level, readonly: false, optional: isOptional(pname, json) }) : getPropertyAccessorsImpl(tName, moduleProperty.type, subProperty.type, subPropertyName, info.type, info.json, {readonly:false, optional:isOptional(pname, json)})) + let moduleProperty = getJsonTypeInfo(module, json, name, schemas, prefix) + let subProperty = getJsonTypeInfo(module, prop, pname, schemas, prefix) + c_shape += '\n' + description(capitalize(pname), info.json.description) + c_shape += '\n' + (isHeader ? getPropertyAccessors(tName, capitalize(pname), info.type, { level: 0, readonly: false, optional: isOptional(pname, json) }) : getPropertyAccessorsImpl(tName, moduleProperty.type, subProperty.type, subPropertyName, info.type, info.json, {readonly:false, optional:isOptional(pname, json)})) + let property = getJsonType(prop, module, { name : pname, prefix }) + props.push({name: `${pname}`, type: `${property}`}) } else { console.log(`b. WARNING: Type undetermined for ${name}:${pname}`) } } }) - cpp_shape += getJsonContainerDefinition(json, name, Object.entries(json.properties).map(([name, prop]) => ({ name, type: getJsonType(prop, module, { name }) }))) + + cpp_shape += getJsonContainerDefinition(json, containerName, props) if (isCPP) { shape += '\n' + cpp_shape @@ -326,32 +430,36 @@ function getSchemaShapeInfo(json, module, schemas = {}, prefixName = '', { name //propertyNames in object not handled yet } else if (json.additionalProperties && (typeof json.additionalProperties === 'object') && (validJsonObjectProperties(json) === true) && !isCPP) { - let info = getSchemaTypeInfo(module, json.additionalProperties, name, module['x-schemas']) + let info = getSchemaTypeInfo(module, json.additionalProperties, name, module['x-schemas'], prefix) if (!info.type || (info.type.length === 0)) { info.type = 'char*' - info.json = schema.additionalProperties + info.json = json.additionalProperties info.json.type = 'string' } - let tName = getTypeName(getModuleName(module), name) - let t = description(name, json.description) + '\n' + + let tName = getTypeName(getModuleName(module), name, prefix) + let t = description(capitalize(name), json.description) + '\n' let containerType = 'WPEFramework::Core::JSON::VariantContainer' let subModuleProperty = getJsonTypeInfo(module, info.json, info.name, module['x-schemas']) if (isCPP && ((info.json.type === 'object' && info.json.properties) || info.json.type === 'array')) { // Handle Container generation here } + t += '\n' + (isHeader ? getObjectHandleManagement(tName) : getObjectHandleManagementImpl(tName, containerType)) t += (isHeader ? getMapAccessors(tName, info.type, { descriptions: descriptions, level: level }) : getMapAccessorsImpl(tName, containerType, subModuleProperty.type, info.type, info.json, { readonly: true, optional: false })) shape += '\n' + t } else if (json.patternProperties) { - console.log(`WARNING: patternProperties are not supported by Firebolt(inside getModuleName(moduleJson):${name})`) + console.log(`WARNING: patternProperties are not supported by Firebolt(inside getModuleName(module):${name})`) } } else if (json.anyOf) { - //let mergedSchema = getMergedSchema(module, json, name, schemas) - //let prefix = ((prefixName.length > 0) && (name != prefixName)) ? prefixName : capitalize(name) - //return getSchemaShapeInfo(moduleJson, mergedSchema, schemas, name, prefix, { name, level, title, summary, descriptions, destination, section, enums }) + if (level > 0) { + let mergedSchema = getMergedSchema(module, json, name, schemas) + let prefixName = ((prefix.length > 0) && (name != prefix)) ? prefix : capitalize(name) + shape += getSchemaShapeInfo(mergedSchema, module, schemas, { name, prefix: prefixName, merged, level, title, summary, descriptions, destination, section, enums }) + } } else if (json.oneOf) { //Just ignore schema shape, since this has to be treated as string @@ -362,13 +470,44 @@ function getSchemaShapeInfo(json, module, schemas = {}, prefixName = '', { name union.title = title delete union['$ref'] - return getSchemaShapeInfo(union, module, schemas, prefixName, { name, level, title, summary, descriptions, destination, section, enums }) + + return getSchemaShapeInfo(union, module, schemas, { name, prefix, merged: true, level, title, summary, descriptions, destination, section, enums }) } - else if (json.type === 'array') { - shape += '\n' + getSchemaType(module, json, name, schemas, prefixName, {level: 0, descriptions: descriptions}) + else if (json.type === 'array' && !isCPP) { + let j + if (Array.isArray(json.items)) { + //TODO + const IsHomogenous = arr => new Set(arr.map( item => item.type ? item.type : typeof item)).size === 1 + if (!IsHomogenous(json.items)) { + throw 'Heterogenous Arrays not supported yet' + } + j = json.items[0] + } + else { + j = json.items + } + + let info = getSchemaTypeInfo(module, j, j.name || name, schemas, prefix, {level : level, descriptions: descriptions, title: true}) + + if (info.type && info.type.length > 0) { + let type = getArrayElementSchema(json, module, schemas, info.name) + let arrayName = capitalize(info.name) + capitalize(type.type) + let objName = getTypeName(info.namespace, arrayName, prefix) + let tName = objName + 'Array' + let moduleName = info.namespace + info.json.namespace = info.namespace + let moduleProperty = getJsonTypeInfo(module, json, json.title || name, schemas, prefix) + let t = '' + if (level === 0) { + t += description(capitalize(info.name), json.description) + '\n' + t += '\n' + (isHeader ? getObjectHandleManagement(tName) : getObjectHandleManagementImpl(tName, moduleProperty.type)) + } + t += '\n' + (isHeader ? getArrayAccessors(objName, tName, info.type) : getArrayAccessorsImpl(objName, moduleProperty.type, (tName + 'Handle'), getJsonNativeType(type), '', info.type, info.json)) + shape += '\n' + t + } } else { - shape += '\n' + getSchemaType(module, json, name, schemas, prefixName, {level: level, descriptions: descriptions}) + shape += '\n' + getSchemaType(module, json, name, schemas, prefix, {level: level, descriptions: descriptions}) } return shape @@ -396,12 +535,12 @@ const getJsonNativeType = json => { return type } -function getJsonType(schema = {}, module = {}, { name = '', descriptions = false, level = 0 } = {}) { - let info = getJsonTypeInfo(module, schema, name, module['x-schemas'], '', { descriptions: descriptions, level: level }) +function getJsonType(schema = {}, module = {}, { name = '', prefix = '', descriptions = false, level = 0 } = {}) { + let info = getJsonTypeInfo(module, schema, name, module['x-schemas'], prefix, { descriptions: descriptions, level: level }) return info.type } -function getJsonTypeInfo(module = {}, json = {}, name = '', schemas, prefixName = '', {descriptions = false, level = 0} = {}) { +function getJsonTypeInfo(module = {}, json = {}, name = '', schemas, prefix = '', {descriptions = false, level = 0} = {}) { if (json.schema) { json = json.schema @@ -418,7 +557,12 @@ function getJsonTypeInfo(module = {}, json = {}, name = '', schemas, prefixName let definition = getPath(json['$ref'], module, schemas) let tName = definition.title || json['$ref'].split('/').pop() - const res = getJsonTypeInfo(module, definition, tName, schemas, '', {descriptions: descriptions, level: level}) + let schema = module + if (json['$ref'].includes('x-schemas')) { + schema = (getRefModule(json['$ref'].split('/')[2])) + } + + const res = getJsonTypeInfo(schema, definition, tName, schemas, '', {descriptions, level}) structure.deps = res.deps structure.type = res.type return structure @@ -435,7 +579,7 @@ function getJsonTypeInfo(module = {}, json = {}, name = '', schemas, prefixName else if (json.additionalProperties && (typeof json.additionalProperties === 'object')) { //This is a map of string to type in schema //Get the Type - let type = getJsonTypeInfo(module, json.additionalProperties, name, schemas, prefixName) + let type = getJsonTypeInfo(module, json.additionalProperties, name, schemas, prefix) if (type.type && type.type.length > 0) { structure.type = 'WPEFramework::Core::JSON::VariantContainer'; return structure @@ -446,7 +590,7 @@ function getJsonTypeInfo(module = {}, json = {}, name = '', schemas, prefixName } else if (json.type === 'string' && json.enum) { //Enum - let t = 'WPEFramework::Core::JSON::EnumType<' + (json.namespace ? json.namespace : getModuleName(module)) + '_' + (getEnumName(name, prefixName)) + '>' + let t = 'WPEFramework::Core::JSON::EnumType<' + (json.namespace ? json.namespace : getModuleName(module)) + '_' + (getEnumName(name, prefix)) + '>' structure.type.push(t) return structure } @@ -469,7 +613,7 @@ function getJsonTypeInfo(module = {}, json = {}, name = '', schemas, prefixName items = json.items // grab the type for the non-array schema } - res = getJsonTypeInfo(module, items, items.name || name, schemas, prefixName) + res = getJsonTypeInfo(module, items, items.name || name, schemas, prefix) structure.deps = res.deps let n = capitalize(name || json.title) structure.type.push(`WPEFramework::Core::JSON::ArrayType<${res.type}>`) @@ -482,7 +626,7 @@ function getJsonTypeInfo(module = {}, json = {}, name = '', schemas, prefixName union['title'] = title delete union['$ref'] - return getJsonTypeInfo(module, union, '', schemas, '', options) + return getJsonTypeInfo(module, union, '', schemas, '', {descriptions, level}) } else if (json.oneOf) { structure.type = getJsonNativeTypeForOpaqueString() @@ -493,17 +637,18 @@ function getJsonTypeInfo(module = {}, json = {}, name = '', schemas, prefixName return structure } else if (json.anyOf) { - /*let mergedSchema = getMergedSchema(module, json, name, schemas) - return getJsonTypeInfo(module, mergedSchema, name, schemas, prefixName, options)*/ + let mergedSchema = getMergedSchema(module, json, name, schemas) + let prefixName = ((prefix.length > 0) && (name != prefix)) ? prefix : capitalize(name) + structure = getJsonTypeInfo(module, mergedSchema, name, schemas, prefixName, {descriptions, level}) } else if (json.type === 'object') { if (hasProperties(json) !== true) { structure.type = getJsonNativeTypeForOpaqueString() } else { - let schema = getSchemaTypeInfo(module, json, name) + let schema = getSchemaTypeInfo(module, json, name, module['x-schemas'], prefix) if (schema.namespace && schema.namespace.length > 0) { - structure.type.push(getJsonDataStructName(schema.namespace, json.title || name, prefixName)) + structure.type.push(getJsonDataStructName(schema.namespace, json.title || name, prefix)) } } return structure diff --git a/languages/c/src/types/ImplHelpers.mjs b/languages/c/src/types/ImplHelpers.mjs index 33e97c53..47852c9e 100644 --- a/languages/c/src/types/ImplHelpers.mjs +++ b/languages/c/src/types/ImplHelpers.mjs @@ -99,77 +99,72 @@ const getPropertyAccessorsImpl = (objName, modulePropertyType, subPropertyType, return result } +const getArrayAccessorsImpl = (objName, modulePropertyType, objHandleType, subPropertyType, subPropertyName, accessorPropertyType, json = {}) => { -const getArrayAccessorsImpl = (objName, propertyName, propertyType, json = {}, options = {readonly:false, optional:false}) => { - let result = ` -uint32_t ${objName}_${propertyName}Array_Size(${objName}::${propertyName}ArrayHandle handle) { + let propertyName + if (subPropertyName) { + propertyName = '(*var)->' + `${subPropertyName}` + objName = objName + '_' + subPropertyName + } + else { + propertyName = '(*(*var))' + } + + let result = `uint32_t ${objName}Array_Size(${objHandleType} handle) { ASSERT(handle != NULL); - WPEFramework::Core::ProxyType<${objName}::${propertyName}>* var = static_cast*>(handle); + WPEFramework::Core::ProxyType<${modulePropertyType}>* var = static_cast*>(handle); ASSERT(var->IsValid()); - return ((*var)->Length()); + return (${propertyName}.Length()); }` + '\n' - if (json.type === 'object') { -result += `${objName}_${propertyType}Handle ${objName}_${propertyName}Array_Get(${objName}_${propertyName}ArrayHandle handle, uint32_t index) { - ASSERT(handle != NULL); - WPEFramework::Core::ProxyType>* var = static_cast>*>(handle); - ASSERT(var->IsValid()); - WPEFramework::Core::ProxyType<${objName}::${propertyType}>* object = new WPEFramework::Core::ProxyType<${objName}::${propertyType}>(); - *object = WPEFramework::Core::ProxyType<${objName}::${propertyName}>::Create(); - *(*object) = (*var)->Get(index); - return (static_cast<${objName}_${propertyType}Handle>(object));` + '\n' - } else if (json.enum) { - result += `${objName}_${propertyType} ${objName}_${propertyName}Array_Get(${objName}_${propertyName}ArrayHandle handle, uint32_t index) { - ASSERT(handle != NULL); - WPEFramework::Core::ProxyType>* var = static_cast>*>(handle); - ASSERT(var->IsValid()); - - return (static_cast<${propertyType}>((*var)->Get(index)));` + '\n' - } else { - result += `${propertyType} ${objName}_${propertyName}Array_Get(${objName}_${propertyName}ArrayHandle handle, uint32_t index) { + result += `${accessorPropertyType} ${objName}Array_Get(${objHandleType} handle, uint32_t index) +{ ASSERT(handle != NULL); - WPEFramework::Core::ProxyType>* var = static_cast>*>(handle); + WPEFramework::Core::ProxyType<${modulePropertyType}>* var = static_cast*>(handle); ASSERT(var->IsValid());` + '\n' - if (json.type === 'string') { - result += `return (static_cast<${propertyType}>((*var)->Get(index).Value().c_str()));` + '\n' - } else { - result += `return (static_cast<${propertyType}>((*var)->Get(index)));` + '\n' - } + if ((json.type === 'object') || (json.type === 'array')) { + result += `WPEFramework::Core::ProxyType<${subPropertyType}>* object = new WPEFramework::Core::ProxyType<${subPropertyType}>(); + *object = WPEFramework::Core::ProxyType<${subPropertyType}>::Create(); + *(*object) = ${propertyName}.Get(index); + return (static_cast<${accessorPropertyType}>(object));` + '\n' + } + else { + if ((typeof json.const === 'string') || (json.type === 'string' && !json.enum)) { + result += ` return (const_cast<${accessorPropertyType}>(${propertyName}.Get(index).Value().c_str()));` + '\n' + } + else { + result += ` return (static_cast<${accessorPropertyType}>(${propertyName}.Get(index)));` + '\n' + } } result += `}` + '\n' - if (json.type === 'object') { - result += `void ${objName}_${propertyName}Array_Add(${objName}_${propertyName}ArrayHandle handle, ${objName}_${propertyType}Handle value) { - ASSERT(handle != NULL); - WPEFramework::Core::ProxyType>* var = static_cast>*>(handle); - ASSERT(var->IsValid()); - WPEFramework::Core::ProxyType<${objName}::${propertyType}>* object = static_cast*>(value); - - (*var)->Add(*(*object));` + '\n' - } else { - result += `void ${objName}_${propertyName}Array_Add(${objName}_${propertyName}ArrayHandle handle, ${propertyType} value) { + let type = (accessorPropertyType === getFireboltStringType()) ? 'char*' : accessorPropertyType + result += `void ${objName}Array_Add(${objHandleType} handle, ${type} value) +{ ASSERT(handle != NULL); - WPEFramework::Core::ProxyType>* var = static_cast>*>(handle); + WPEFramework::Core::ProxyType<${modulePropertyType}>* var = static_cast*>(handle); ASSERT(var->IsValid());` + '\n' - if (json.type === 'string') { - result += `WPEFramework::Core::JSON::String element(value);` + '\n' - } else if (json.type === 'number') { - result += `WPEFramework::Core::JSON::Number element(value);` + '\n' - } else if (json.enum) { - result += `WPEFramework::Core::JSON::EnumType<${propertyType}> element(value);` + '\n' - } - result += `(*var)->Add(element);` + '\n' + + if ((json.type === 'object') || (json.type === 'array')) { + result += ` ${subPropertyType}& element = *(*(static_cast*>(value)));` + '\n' } - result += `}` + '\n' + else { + result += ` ${subPropertyType} element(value);` + '\n' + } + result += ` + ${propertyName}.Add(element); +}` + '\n' - result += `void ${objName}_${propertyName}Array_Clear(${objName}_${propertyName}ArrayHandle handle) { + result += `void ${objName}Array_Clear(${objHandleType} handle) +{ ASSERT(handle != NULL); - WPEFramework::Core::ProxyType>* var = static_cast>*>(handle); + WPEFramework::Core::ProxyType<${modulePropertyType}>* var = static_cast*>(handle); ASSERT(var->IsValid()); - (*var)->Clear(); + + ${propertyName}.Clear(); }` + '\n' return result diff --git a/languages/c/src/types/JSONHelpers.mjs b/languages/c/src/types/JSONHelpers.mjs index 2a787c97..0d0c4179 100644 --- a/languages/c/src/types/JSONHelpers.mjs +++ b/languages/c/src/types/JSONHelpers.mjs @@ -4,7 +4,7 @@ const getJsonDataPrefix = () => 'JsonData_' const wpeJsonNameSpace = () => 'WPEFramework::Core::JSON' const getJsonDataStructName = (modName, name, prefixName = '') => { - let result =((prefixName.length > 0) && (prefixName != name)) ? `${capitalize(modName)}::${getJsonDataPrefix()}${capitalize(prefixName)}${capitalize(name)}` : `${capitalize(modName)}::${getJsonDataPrefix()}${capitalize(name)}` + let result =((prefixName.length > 0) && (capitalize(prefixName) != capitalize(name))) ? `${capitalize(modName)}::${getJsonDataPrefix()}${capitalize(prefixName)}${capitalize(name)}` : `${capitalize(modName)}::${getJsonDataPrefix()}${capitalize(name)}` return ((result.includes(wpeJsonNameSpace()) === true) ? result : `${getSdkNameSpace()}::${result}`) } diff --git a/languages/c/src/types/NativeHelpers.mjs b/languages/c/src/types/NativeHelpers.mjs index 56e45ac8..b0a4ebb4 100644 --- a/languages/c/src/types/NativeHelpers.mjs +++ b/languages/c/src/types/NativeHelpers.mjs @@ -84,8 +84,39 @@ const SdkTypesPrefix = 'Firebolt' const Indent = ' ' +const getArrayElementSchema = (json, module, schemas = {}, name) => { + let result = '' + if (json.type === 'array' && json.items) { + if (Array.isArray(json.items)) { + result = json.items[0] + } + else { + // grab the type for the non-array schema + result = json.items + } + if (result['$ref']) { + result = getPath(result['$ref'], module, schemas) + } + } + else if (json.type == 'object') { + if (json.properties) { + Object.entries(json.properties).every(([pname, prop]) => { + if (prop.type === 'array') { + result = getArrayElementSchema(prop, module, schemas) + if (name === capitalize(pname)) { + return false + } + } + return true + }) + } + } + + return result +} + const getNativeType = json => { - let type + let type = '' let jsonType = json.const ? typeof json.const : json.type if (jsonType === 'string') { type = 'char*' @@ -153,12 +184,12 @@ const getTypeName = (moduleName, varName, prefixName = '', upperCase = false, ca return name } -const getArrayAccessors = (arrayName, valueType) => { +const getArrayAccessors = (arrayName, propertyType, valueType) => { - let res = `uint32_t ${arrayName}_Size(${arrayName}Handle handle);` + '\n' - res += `${valueType} ${arrayName}_Get(${arrayName}Handle handle, uint32_t index);` + '\n' - res += `void ${arrayName}_Add(${arrayName}Handle handle, ${valueType} value);` + '\n' - res += `void ${arrayName}_Clear(${arrayName}Handle handle);` + '\n' + let res = `uint32_t ${arrayName}Array_Size(${propertyType}Handle handle);` + '\n' + res += `${valueType} ${arrayName}Array_Get(${propertyType}Handle handle, uint32_t index);` + '\n' + res += `void ${arrayName}Array_Add(${propertyType}Handle handle, ${valueType} value);` + '\n' + res += `void ${arrayName}Array_Clear(${propertyType}Handle handle);` + '\n' return res } @@ -233,5 +264,6 @@ export { getObjectHandleManagement, getPropertyAccessors, isOptional, - generateEnum + generateEnum, + getArrayElementSchema } diff --git a/languages/c/templates/modules/src/Module.cpp b/languages/c/templates/modules/src/Module.cpp index 6d374ff7..c69d176f 100644 --- a/languages/c/templates/modules/src/Module.cpp +++ b/languages/c/templates/modules/src/Module.cpp @@ -25,7 +25,6 @@ namespace FireboltSDK { namespace ${info.title} { // Types - /* ${TYPES} */ } } diff --git a/languages/c/templates/sections/accessors.c b/languages/c/templates/sections/accessors.c index 0586b2a5..1c790810 100644 --- a/languages/c/templates/sections/accessors.c +++ b/languages/c/templates/sections/accessors.c @@ -1,3 +1,2 @@ // Accessors - ${schema.list} diff --git a/src/macrofier/engine.mjs b/src/macrofier/engine.mjs index 6e4fa117..84059279 100644 --- a/src/macrofier/engine.mjs +++ b/src/macrofier/engine.mjs @@ -720,7 +720,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, { 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, { name: schema.title, destination: state.destination, section: state.section }) + '](' + getLinkForSchema(schema, json, { name: schema.title }) + ')') // need full module here, not just the schema .filter(link => link) .join('\n') From e7684548acd8d59c13a99d350426c9e842d71399 Mon Sep 17 00:00:00 2001 From: HaseenaSainul Date: Thu, 25 May 2023 05:32:04 -0400 Subject: [PATCH 6/9] Types and Accessors generation added for objects inside methods result/params --- languages/c/Types.mjs | 3 -- .../c/templates/sections/methods_accessors.c | 1 + .../c/templates/sections/methods_types.c | 1 + src/macrofier/engine.mjs | 31 +++++++++++++++---- src/macrofier/index.mjs | 3 +- 5 files changed, 28 insertions(+), 11 deletions(-) create mode 100644 languages/c/templates/sections/methods_accessors.c create mode 100644 languages/c/templates/sections/methods_types.c diff --git a/languages/c/Types.mjs b/languages/c/Types.mjs index 6cebc2fc..90e71ca4 100644 --- a/languages/c/Types.mjs +++ b/languages/c/Types.mjs @@ -279,9 +279,6 @@ function getSchemaTypeInfo(module = {}, json = {}, name = '', schemas = {}, pref return structure } else if (json.anyOf) { - console.log("json.anyOf ---" + name) - console.log(json) - console.log(module) let mergedSchema = getMergedSchema(module, json, name, schemas) let prefixName = ((prefix.length > 0) && (name != prefix)) ? prefix : capitalize(name) return getSchemaTypeInfo(module, mergedSchema, '', schemas, prefixName, options) diff --git a/languages/c/templates/sections/methods_accessors.c b/languages/c/templates/sections/methods_accessors.c new file mode 100644 index 00000000..9295133c --- /dev/null +++ b/languages/c/templates/sections/methods_accessors.c @@ -0,0 +1 @@ +${schema.list} diff --git a/languages/c/templates/sections/methods_types.c b/languages/c/templates/sections/methods_types.c new file mode 100644 index 00000000..9295133c --- /dev/null +++ b/languages/c/templates/sections/methods_types.c @@ -0,0 +1 @@ +${schema.list} diff --git a/src/macrofier/engine.mjs b/src/macrofier/engine.mjs index 84059279..9559300e 100644 --- a/src/macrofier/engine.mjs +++ b/src/macrofier/engine.mjs @@ -65,6 +65,7 @@ const state = { } const capitalize = str => str[0].toUpperCase() + str.substr(1) +const hasMethodsSchema = (json, options) => json.methods && json.methods.length const setTyper = (t) => { types = t @@ -333,6 +334,11 @@ const generateMacros = (obj, templates, languages, options = {}) => { const declarations = declarationsArray.length ? getTemplate('/sections/declarations', templates).replace(/\$\{declaration\.list\}/g, declarationsArray.map(m => m.declaration).join('\n')) : '' const methods = methodsArray.length ? getTemplate('/sections/methods', templates).replace(/\$\{method.list\}/g, methodsArray.map(m => m.body).join('\n')) : '' const methodList = methodsArray.filter(m => m.body).map(m => m.name) + const methodTypesArray = generateSchemas(obj, templates, { baseUrl: '', section: 'methods_schemas' }).filter(s => (options.copySchemasIntoModules || !s.uri)) + const methodTypes = methodTypesArray.length ? getTemplate('/sections/methods_types', templates).replace(/\$\{schema.list\}/g, methodTypesArray.map(s => s.body).filter(body => body).join('\n')) : '' + const methodAccessorsArray = generateSchemas(obj, templates, { baseUrl: '', section: 'methods_accessors' }).filter(s => (options.copySchemasIntoModules || !s.uri)) + const methodAccessors = methodAccessorsArray.length ? getTemplate('/sections/methods_accessors', templates).replace(/\$\{schema.list\}/g, methodAccessorsArray.map(s => s.body).filter(body => body).join('\n')) : '' + const providerInterfaces = generateProviderInterfaces(obj, templates) const events = eventsArray.length ? getTemplate('/sections/events', templates).replace(/\$\{event.list\}/g, eventsArray.map(m => m.body).join('\n')) : '' const eventList = eventsArray.map(m => makeEventName(m)) @@ -341,8 +347,9 @@ const generateMacros = (obj, templates, languages, options = {}) => { const accessorsArray = generateSchemas(obj, templates, { baseUrl: '', section: 'accessors' }).filter(s => (options.copySchemasIntoModules || !s.uri)) const schemas = schemasArray.length ? getTemplate('/sections/schemas', templates).replace(/\$\{schema.list\}/g, schemasArray.map(s => s.body).filter(body => body).join('\n')) : '' const typesArray = schemasArray.filter(x => !x.enum) - const types = typesArray.length ? getTemplate('/sections/types', templates).replace(/\$\{schema.list\}/g, typesArray.map(s => s.body).filter(body => body).join('\n')) : '' - const accessors = accessorsArray.length ? getTemplate('/sections/accessors', templates).replace(/\$\{schema.list\}/g, accessorsArray.map(s => s.body).filter(body => body).join('\n')) : '' + const types = (typesArray.length ? getTemplate('/sections/types', templates).replace(/\$\{schema.list\}/g, typesArray.map(s => s.body).filter(body => body).join('\n')) : '') + methodTypes + + const accessors = (accessorsArray.length ? getTemplate('/sections/accessors', templates).replace(/\$\{schema.list\}/g, accessorsArray.map(s => s.body).filter(body => body).join('\n')) : '') + methodAccessors const module = getTemplate('/codeblocks/module', templates) const macros = { @@ -623,9 +630,9 @@ const isEnum = x => x.type && x.type === 'string' && Array.isArray(x.enum) && x. function generateSchemas(json, templates, options) { let results = [] - const schemas = json.definitions || (json.components && json.components.schemas) || {} + const schemas = (options.section.includes('methods') ? (hasMethodsSchema(json) ? json.methods : '') : (json.definitions || (json.components && json.components.schemas) || {})) - const generate = (name, schema, uri) => { + const generate = (name, schema, uri, { prefix = '' } = {}) => { // these are internal schemas used by the firebolt-openrpc tooling, and not meant to be used in code/doc generation if (['ListenResponse', 'ProviderRequest', 'ProviderResponse', 'FederatedResponse', 'FederatedRequest'].includes(name)) { return @@ -646,7 +653,7 @@ function generateSchemas(json, templates, options) { else { content = content.replace(/\$\{if\.description\}(.*?)\{end\.if\.description\}/gms, '$1') } - const schemaShape = types.getSchemaShape(schema, json, { name, destination: state.destination, section: options.section }) + const schemaShape = types.getSchemaShape(schema, json, { name, prefix, destination: state.destination, section: options.section }) content = content .replace(/\$\{schema.title\}/, (schema.title || name)) @@ -689,6 +696,18 @@ function generateSchemas(json, templates, options) { if (isSchema(schema)) { list.push([name, schema]) } + else if (schema.tags) { + if (!isDeprecatedMethod(schema)) { + schema.params.forEach(param => { + if (param.schema && (param.schema.type === 'object')) { + list.push([param.name, param.schema, '', { prefix : schema.name}]) + } + }) + if (schema.result.schema && (schema.result.schema.type === 'object')) { + list.push([schema.result.name, schema.result.schema, '', { prefix : schema.name}]) + } + } + } }) list.sort((a, b) => { @@ -1224,7 +1243,7 @@ function generateResult(result, json, templates, { name = '' } = {}) { else { const sch = localizeDependencies(result, json) return getTemplate('/types/default', templates) - .replace(/\$\{type\}/, types.getSchemaShape(sch, json, { name: result.$ref.split("/").pop()})) + .replace(/\$\{type\}/, types.getSchemaShape(sch, json, { name: result.$ref.split("/").pop() })) } } else { diff --git a/src/macrofier/index.mjs b/src/macrofier/index.mjs index 89c194e2..fd270b6e 100644 --- a/src/macrofier/index.mjs +++ b/src/macrofier/index.mjs @@ -200,7 +200,6 @@ const macrofy = async ( } }) - console.log() } // Grab all schema groups w/ a URI string. These came from some external json-schema that was bundled into the OpenRPC @@ -271,4 +270,4 @@ const macrofy = async ( }) } -export default macrofy \ No newline at end of file +export default macrofy From 72a6e81614a0a7f308b22d0fd63bdc36b448b5ad Mon Sep 17 00:00:00 2001 From: HaseenaSainul Date: Thu, 25 May 2023 09:23:06 -0400 Subject: [PATCH 7/9] Types/Accessorts: native ganeration - prefixing logic updates --- languages/c/Types.mjs | 11 +++++------ languages/c/src/types/JSONHelpers.mjs | 4 ++-- languages/c/src/types/NativeHelpers.mjs | 10 +++++----- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/languages/c/Types.mjs b/languages/c/Types.mjs index 90e71ca4..0bb6cc59 100644 --- a/languages/c/Types.mjs +++ b/languages/c/Types.mjs @@ -230,7 +230,7 @@ function getSchemaTypeInfo(module = {}, json = {}, name = '', schemas = {}, pref } else if (json.type === 'string' && json.enum) { //Enum - structure.name = capitalize(name || json.title) + structure.name = name || json.title let typeName = getTypeName(getModuleName(module), name || json.title, prefix, false, false) let res = description(capitalize(name || json.title), json.description) + '\n' + generateEnum(json, typeName) structure.json = json @@ -280,7 +280,7 @@ function getSchemaTypeInfo(module = {}, json = {}, name = '', schemas = {}, pref } else if (json.anyOf) { let mergedSchema = getMergedSchema(module, json, name, schemas) - let prefixName = ((prefix.length > 0) && (name != prefix)) ? prefix : capitalize(name) + let prefixName = ((prefix.length > 0) && (!name.startsWith(prefix))) ? prefix : capitalize(name) return getSchemaTypeInfo(module, mergedSchema, '', schemas, prefixName, options) } else if (json.type === 'object') { @@ -360,7 +360,7 @@ function getSchemaShapeInfo(json, module, schemas = {}, { name = '', prefix = '' let tName = getTypeName(getModuleName(module), name, prefix) c_shape += '\n' + (isHeader ? getObjectHandleManagement(tName) : getObjectHandleManagementImpl(tName, getJsonType(json, module, { name }))) let props = [] - let containerName = ((prefix.length > 0) && (name != prefix)) ? (prefix + capitalize(name)) : capitalize(name) + let containerName = ((prefix.length > 0) && (!name.startsWith(prefix))) ? (prefix + '_' + capitalize(name)) : capitalize(name) Object.entries(json.properties).forEach(([pname, prop]) => { let items var desc = '\n' + description(capitalize(pname), prop.description) @@ -454,7 +454,7 @@ function getSchemaShapeInfo(json, module, schemas = {}, { name = '', prefix = '' else if (json.anyOf) { if (level > 0) { let mergedSchema = getMergedSchema(module, json, name, schemas) - let prefixName = ((prefix.length > 0) && (name != prefix)) ? prefix : capitalize(name) + let prefixName = ((prefix.length > 0) && (!name.startsWith(prefix))) ? prefix : capitalize(name) shape += getSchemaShapeInfo(mergedSchema, module, schemas, { name, prefix: prefixName, merged, level, title, summary, descriptions, destination, section, enums }) } } @@ -612,7 +612,6 @@ function getJsonTypeInfo(module = {}, json = {}, name = '', schemas, prefix = '' } res = getJsonTypeInfo(module, items, items.name || name, schemas, prefix) structure.deps = res.deps - let n = capitalize(name || json.title) structure.type.push(`WPEFramework::Core::JSON::ArrayType<${res.type}>`) return structure @@ -635,7 +634,7 @@ function getJsonTypeInfo(module = {}, json = {}, name = '', schemas, prefix = '' } else if (json.anyOf) { let mergedSchema = getMergedSchema(module, json, name, schemas) - let prefixName = ((prefix.length > 0) && (name != prefix)) ? prefix : capitalize(name) + let prefixName = ((prefix.length > 0) && (!name.startsWith(prefix))) ? prefix : capitalize(name) structure = getJsonTypeInfo(module, mergedSchema, name, schemas, prefixName, {descriptions, level}) } else if (json.type === 'object') { diff --git a/languages/c/src/types/JSONHelpers.mjs b/languages/c/src/types/JSONHelpers.mjs index 0d0c4179..5050f260 100644 --- a/languages/c/src/types/JSONHelpers.mjs +++ b/languages/c/src/types/JSONHelpers.mjs @@ -3,8 +3,8 @@ const getSdkNameSpace = () => 'FireboltSDK' const getJsonDataPrefix = () => 'JsonData_' const wpeJsonNameSpace = () => 'WPEFramework::Core::JSON' -const getJsonDataStructName = (modName, name, prefixName = '') => { - let result =((prefixName.length > 0) && (capitalize(prefixName) != capitalize(name))) ? `${capitalize(modName)}::${getJsonDataPrefix()}${capitalize(prefixName)}${capitalize(name)}` : `${capitalize(modName)}::${getJsonDataPrefix()}${capitalize(name)}` +const getJsonDataStructName = (modName, name, prefix = '') => { + let result =((prefix.length > 0) && (!name.startsWith(prefix))) ? `${capitalize(modName)}::${getJsonDataPrefix()}${capitalize(prefix)}_${capitalize(name)}` : `${capitalize(modName)}::${getJsonDataPrefix()}${capitalize(name)}` return ((result.includes(wpeJsonNameSpace()) === true) ? result : `${getSdkNameSpace()}::${result}`) } diff --git a/languages/c/src/types/NativeHelpers.mjs b/languages/c/src/types/NativeHelpers.mjs index b0a4ebb4..eac20c16 100644 --- a/languages/c/src/types/NativeHelpers.mjs +++ b/languages/c/src/types/NativeHelpers.mjs @@ -172,15 +172,15 @@ const getMapAccessors = (typeName, accessorPropertyType, level = 0) => { return res } -const getTypeName = (moduleName, varName, prefixName = '', upperCase = false, capitalCase = true) => { +const getTypeName = (moduleName, varName, prefix = '', upperCase = false, capitalCase = true) => { let mName = upperCase ? moduleName.toUpperCase() : capitalize(moduleName) let vName = upperCase ? varName.toUpperCase() : capitalCase ? capitalize(varName) : varName - if (prefixName.length > 0) { - prefixName = (prefixName !== varName) ? (upperCase ? prefixName.toUpperCase() : capitalize(prefixName)) : '' + if (prefix.length > 0) { + prefix = (!varName.startsWith(prefix)) ? (upperCase ? prefix.toUpperCase() : capitalize(prefix)) : '' } - prefixName = (prefixName.length > 0) ?(upperCase ? prefixName.toUpperCase() : capitalize(prefixName)) : prefixName - let name = (prefixName.length > 0) ? `${mName}_${prefixName}_${vName}` : `${mName}_${vName}` + prefix = (prefix.length > 0) ?(upperCase ? prefix.toUpperCase() : capitalize(prefix)) : prefix + let name = (prefix.length > 0) ? `${mName}_${prefix}_${vName}` : `${mName}_${vName}` return name } From f8eaa49961d958aac736dcd828e9adb2fb248eaa Mon Sep 17 00:00:00 2001 From: HaseenaSainul Date: Wed, 31 May 2023 00:12:57 -0400 Subject: [PATCH 8/9] Review comment updates --- src/macrofier/engine.mjs | 10 +++++----- src/macrofier/index.mjs | 1 - 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/macrofier/engine.mjs b/src/macrofier/engine.mjs index 9559300e..20fb8d4b 100644 --- a/src/macrofier/engine.mjs +++ b/src/macrofier/engine.mjs @@ -1223,7 +1223,7 @@ function generateResult(result, json, templates, { name = '' } = {}) { for (var i=0; i= 0) { - content[i] = Object.entries(result.properties).map(([title, property]) => insertSchemaMacros(content[i], title || name, property, json)).join('\n') + content[i] = Object.entries(result.properties).map(([title, property]) => insertSchemaMacros(content[i], title, property, json)).join('\n') } } @@ -1241,9 +1241,9 @@ function generateResult(result, json, templates, { name = '' } = {}) { } // otherwise this was a schema with no title, and we'll just copy it here else { - const sch = localizeDependencies(result, json) + const schema = localizeDependencies(result, json) return getTemplate('/types/default', templates) - .replace(/\$\{type\}/, types.getSchemaShape(sch, json, { name: result.$ref.split("/").pop() })) + .replace(/\$\{type\}/, types.getSchemaShape(schema, json, { name: result.$ref.split("/").pop() })) } } else { @@ -1253,8 +1253,8 @@ function generateResult(result, json, templates, { name = '' } = {}) { function insertSchemaMacros(template, title, schema, module) { return template.replace(/\$\{property\}/g, title) - .replace(/\$\{type\}/g, types.getSchemaType(schema.schema ? schema.schema : schema, module, { name: title, destination: state.destination, section: state.section, code: false })) - .replace(/\$\{type.link\}/g, getLinkForSchema(schema.schema ? schema.schema : schema, module, { name: title })) + .replace(/\$\{type\}/g, types.getSchemaType(schema, module, { name: title, destination: state.destination, section: state.section, code: false })) + .replace(/\$\{type.link\}/g, getLinkForSchema(schema, module, { name: title })) .replace(/\$\{description\}/g, schema.description || '') .replace(/\$\{name\}/g, title || '') } diff --git a/src/macrofier/index.mjs b/src/macrofier/index.mjs index fd270b6e..f8acada8 100644 --- a/src/macrofier/index.mjs +++ b/src/macrofier/index.mjs @@ -199,7 +199,6 @@ const macrofy = async ( delete outputFiles[file] } }) - } // Grab all schema groups w/ a URI string. These came from some external json-schema that was bundled into the OpenRPC From c30e13d5ef3ce32036284052d52968af0b041652 Mon Sep 17 00:00:00 2001 From: HaseenaSainul Date: Thu, 1 Jun 2023 11:20:33 -0400 Subject: [PATCH 9/9] Remove redundant macro enum-conversion --- src/macrofier/engine.mjs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/macrofier/engine.mjs b/src/macrofier/engine.mjs index 0ab665fd..2883fce1 100644 --- a/src/macrofier/engine.mjs +++ b/src/macrofier/engine.mjs @@ -355,7 +355,6 @@ const generateMacros = (obj, templates, languages, options = {}) => { imports, initialization, enums, - enumsConversion, events, eventList, eventsEnum, @@ -408,7 +407,6 @@ const insertMacros = (fContents = '', macros = {}) => { fContents = fContents.replace(/[ \t]*\/\* \$\{TYPES\} \*\/[ \t]*\n/, macros.types) fContents = fContents.replace(/[ \t]*\/\* \$\{PROVIDERS\} \*\/[ \t]*\n/, macros.providerInterfaces) fContents = fContents.replace(/[ \t]*\/\* \$\{ENUMS\} \*\/[ \t]*\n/, macros.enums) - fContents = fContents.replace(/[ \t]*\/\* \$\{ENUMS_CONVERSION\} \*\/[ \t]*\n/, macros.enumsConversion) fContents = fContents.replace(/[ \t]*\/\* \$\{IMPORTS\} \*\/[ \t]*\n/, macros.imports) fContents = fContents.replace(/[ \t]*\/\* \$\{INITIALIZATION\} \*\/[ \t]*\n/, macros.initialization) fContents = fContents.replace(/[ \t]*\/\* \$\{DEFAULTS\} \*\/[ \t]*\n/, macros.defaults)