Skip to content

Commit

Permalink
CPPSDK: changes to handle enum and x-schema enum without title (#138)
Browse files Browse the repository at this point in the history
  • Loading branch information
HaseenaSainul authored Oct 25, 2023
1 parent 7031fc2 commit 6d1339b
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 28 deletions.
2 changes: 1 addition & 1 deletion languages/cpp/templates/types/enum.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* ${title} ${description} */
enum class ${name} {
${key},
${key}${delimiter},${end.delimiter}
};
50 changes: 31 additions & 19 deletions src/macrofier/engine.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,10 @@ const promoteSchema = (location, property, title, document, destinationPath) =>
}

// only consider sub-objects and sub enums to be sub-schemas
const isSubSchema = (schema) => schema.type === 'object' || (schema.type === 'string' && schema.enum) // || (schema.type === 'array' && schema.items)
const isSubSchema = (schema) => schema.type === 'object' || (schema.type === 'string' && schema.enum)

// check schema is sub enum of array
const isSubEnumOfArraySchema = (schema) => (schema.type === 'array' && schema.items.enum)

const promoteAndNameSubSchemas = (obj) => {
// make a copy so we don't polute our inputs
Expand All @@ -402,19 +405,30 @@ const promoteAndNameSubSchemas = (obj) => {
while (more) {
more = false
Object.entries(obj.components.schemas).forEach(([key, schema]) => {
if ((schema.type === "object") && schema.properties) {
Object.entries(schema.properties).forEach(([name, propSchema]) => {
if (isSubSchema(propSchema)) {
more = true
const descriptor = {
name: name,
schema: propSchema
let componentSchemaProperties = schema.allOf ? schema.allOf : [schema]
componentSchemaProperties.forEach((componentSchema) => {
if ((componentSchema.type === "object") && componentSchema.properties) {
Object.entries(componentSchema.properties).forEach(([name, propSchema]) => {
if (isSubSchema(propSchema)) {
more = true
const descriptor = {
name: name,
schema: propSchema
}
addContentDescriptorSubSchema(descriptor, key, obj)
componentSchema.properties[name] = descriptor.schema
}
addContentDescriptorSubSchema(descriptor, key, obj)
schema.properties[name] = descriptor.schema
}
})
}
if (isSubEnumOfArraySchema(propSchema)) {
const descriptor = {
name: name,
schema: propSchema.items
}
addContentDescriptorSubSchema(descriptor, key, obj)
componentSchema.properties[name].items = descriptor.schema
}
})
}
})

if (!schema.title) {
schema.title = capitalize(key)
Expand Down Expand Up @@ -727,14 +741,12 @@ const convertEnumTemplate = (schema, templateName, templates) => {
const template = getTemplate(templateName, templates).split('\n')
for (var i = 0; i < template.length; i++) {
if (template[i].indexOf('${key}') >= 0) {
template[i] = enumSchema.enum.map(value => {
template[i] = enumSchema.enum.map((value, id) => {
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)
.replace(/\$\{delimiter\}(.*?)\$\{end.delimiter\}/g, id === enumSchema.enum.length - 1 ? '' : '$1')
}).join('\n')
if (!templateName.includes(".cpp")) {
template[i] = template[i].replace(/,*$/, '');
}
}
}
return template.join('\n')
Expand Down Expand Up @@ -867,7 +879,7 @@ function generateSchemas(json, templates, options) {
else {
content = content.replace(/\$\{if\.description\}(.*?)\{end\.if\.description\}/gms, '$1')
}
const schemaShape = types.getSchemaShape(schema, json, { templateDir: state.typeTemplateDir, destination: state.destination, section: options.section })
const schemaShape = types.getSchemaShape(schema, json, { templateDir: state.typeTemplateDir, destination: state.destination, section: options.section})

content = content
.replace(/\$\{schema.title\}/, (schema.title || name))
Expand All @@ -887,7 +899,7 @@ function generateSchemas(json, templates, options) {
}
content = content.trim().length ? content : content.trim()

const isEnum = x => x.type === 'string' && Array.isArray(x.enum) && x.title
const isEnum = x => x.type && Array.isArray(x.enum) && x.title && ((x.type === 'string') || (x.type[0] === 'string'))

const result = uri ? {
uri: uri,
Expand Down
24 changes: 16 additions & 8 deletions src/macrofier/types.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -157,14 +157,21 @@ const insertConstMacros = (content, schema, module, name) => {
return content
}

const insertEnumMacros = (content, schema, module, name) => {
const insertEnumMacros = (content, schema, module, name, suffix, templateDir = "types") => {
const template = content.split('\n')

for (var i = 0; i < template.length; i++) {
if (template[i].indexOf('${key}') >= 0) {
template[i] = schema.enum.map(value => {
return template[i].replace(/\$\{key\}/g, safeName(value))
.replace(/\$\{value\}/g, value)
let values = []
schema.enum.map(value => {
if (!value) {
value = getTemplate(path.join(templateDir, 'unset' + suffix))
}
value ? values.push(template[i].replace(/\$\{key\}/g, safeName(value))
.replace(/\$\{value\}/g, value)) : ''
})
template[i] = values.map((value, id) => {
return value.replace(/\$\{delimiter\}(.*?)\$\{end.delimiter\}/g, id === values.length - 1 ? '' : '$1')
}).join('\n')
}
}
Expand Down Expand Up @@ -377,15 +384,15 @@ function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', name

let result = level === 0 ? getTemplate(path.join(templateDir, 'default' + suffix)) : '${shape}'

if (enums && level === 0 && schema.type === "string" && Array.isArray(schema.enum)) {
if (enums && level === 0 && Array.isArray(schema.enum) && ((schema.type === "string") || (schema.type[0] === "string"))) {
result = getTemplate(path.join(templateDir, 'enum' + suffix))
return insertSchemaMacros(insertEnumMacros(result, schema, module, theTitle), schema, module, theTitle, parent, property)
return insertSchemaMacros(insertEnumMacros(result, schema, module, theTitle, suffix, templateDir), schema, module, theTitle, parent, property)
}

if (schema['$ref']) {
const someJson = getPath(schema['$ref'], module)
if (someJson) {
return getSchemaShape(someJson, module, { templateDir, name, parent, property, level, summary, descriptions, destination, enums: false })
return getSchemaShape(someJson, module, { templateDir, name, parent, property, level, summary, descriptions, destination, enums })
}
throw "Unresolvable $ref: " + schema['ref'] + ", in " + module.info.title
}
Expand All @@ -395,8 +402,9 @@ function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', name
return result
}
else if (!skipTitleOnce && (level > 0) && schema.title) {
let enumType = (schema.type === 'string' && Array.isArray(schema.enum))
// TODO: allow the 'ref' template to actually insert the shape using getSchemaShape
const innerShape = getSchemaShape(schema, module, { skipTitleOnce: true, templateDir, name, parent, property, level, summary, descriptions, destination, enums: false })
const innerShape = getSchemaShape(schema, module, { skipTitleOnce: true, templateDir, name, parent, property, level, summary, descriptions, destination, enums: enumType })

const shape = getTemplate(path.join(templateDir, 'ref' + suffix))
.replace(/\$\{shape\}/g, innerShape)
Expand Down
5 changes: 5 additions & 0 deletions src/shared/modules.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -1224,6 +1224,11 @@ const getModule = (name, json, copySchemas) => {
...(openrpc[destination[0]][destination[1]][destination[2]] || {})
}
}
const capitalize = str => str[0].toUpperCase() + str.substr(1)
if (!schema.title) {
schema.title = capitalize(parts.pop())
}

openrpc = setPath(destination, schema, openrpc)
}
})
Expand Down

0 comments on commit 6d1339b

Please sign in to comment.