Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CPPSDK: changes to handle enum and x-schema enum without title #138

Merged
merged 4 commits into from
Oct 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading