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

CPP SDK : changes to handle additional Properties #134

Merged
merged 4 commits into from
Oct 18, 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/additionalProperties.h
Original file line number Diff line number Diff line change
@@ -1 +1 @@
${title} value;
std::unordered_map<${key}, ${type}> ${title};
1 change: 1 addition & 0 deletions languages/cpp/templates/types/additionalPropertiesKey.h
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
std::string
101 changes: 70 additions & 31 deletions src/macrofier/types.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const primitives = {
"string": "string"
}

const isPrimitiveType = type => primitives[type] ? true : false
const allocatedPrimitiveProxies = {}

function setTemplates(t) {
Expand Down Expand Up @@ -109,7 +110,7 @@ function insertSchemaMacros(content, schema, module, name, parent, property, rec
.replace(/\$\{info.TITLE\}/g, moduleTitle.toUpperCase())

if (recursive) {
content = content.replace(/\$\{type\}/g, getSchemaType(schema, module, { name: title, destination: state.destination, section: state.section, code: false, namespace: true }))
content = content.replace(/\$\{type\}/g, getSchemaType(schema, module, { destination: state.destination, section: state.section, code: false, namespace: true }))
}
return content
}
Expand Down Expand Up @@ -137,35 +138,48 @@ const insertEnumMacros = (content, schema, module, name) => {
return template.join('\n')
}

const insertObjectMacros = (content, schema, module, title, property, options) => {
options = options ? JSON.parse(JSON.stringify(options)) : {}
const insertObjectAdditionalPropertiesMacros = (content, schema, module, title, options) => {
const options2 = options ? JSON.parse(JSON.stringify(options)) : {}
options2.parent = title
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've already made a copy on line 143. Why do you need a second copy?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ha, looks like I did that :)

I think the extra copy can go away, though.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I can't find where this new insertObjectAdditionalProperitesMacros method is called.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry missed to updated calling place. corrected now

options2.level = options.level + 1

const shape = getSchemaShape(schema.additionalProperties, module, options2)
let type = getSchemaType(schema.additionalProperties, module, options2).trimEnd()
const propertyNames = localizeDependencies(schema, module).propertyNames

let jsonType = getJsonType(schema.additionalProperties, module)
if (!isPrimitiveType(jsonType)) {
jsonType = 'string'
}

const additionalType = getPrimitiveType(jsonType, 'additional-types')
let key = (propertyNames && propertyNames.title) ? propertyNames.title : getTemplate(path.join(options.templateDir, 'additionalPropertiesKey')).trimEnd()

content = content
.replace(/\$\{shape\}/g, shape)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you confirm that none of the JS templates were using ${property} or ${Property} here?

I forget why I had those two lines in there, but there must have been some reason.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have not seen any use case from javascript. javascript generation not showed any issue

.replace(/\$\{parent\.title\}/g, title)
.replace(/\$\{title\}/g, title)
.replace(/\$\{type\}/g, type)
.replace(/\$\{additional\.type\}/g, additionalType)
.replace(/\$\{key\}/g, key)
.replace(/\$\{delimiter\}(.*?)\$\{end.delimiter\}/g, '')
.replace(/\$\{if\.optional\}(.*?)\$\{end\.if\.optional\}/g, '')

const options2 = JSON.parse(JSON.stringify(options))
return content
}

const insertObjectMacros = (content, schema, module, title, property, options) => {
const options2 = options ? JSON.parse(JSON.stringify(options)) : {}
options2.parent = title
options2.level = options.level + 1
options2.name = ''

;(['properties', 'properties.register', 'properties.assign']).forEach(macro => {
const indent = (content.split('\n').find(line => line.includes("${" + macro + "}")) || '').match(/^\s+/) || [''][0]
const templateType = macro.split('.').slice(1).join('')
const template = getTemplate(path.join(options.templateDir, 'property' + (templateType ? `-${templateType}` : ''))).replace(/\n/gms, indent + '\n')

const properties = []

if (schema.additionalProperties && (typeof schema.additionalProperties === 'object')) {
const template = getTemplate(path.join(options.templateDir, 'additionalProperties'))
let type = getSchemaType(schema.additionalProperties, module, options2)
const shape = getSchemaShape(schema.additionalProperties, module, options2)
properties.push(template
.replace(/\$\{property\}/g, '')
.replace(/\$\{Property\}/g, '')
.replace(/\$\{shape\}/g, shape)
.replace(/\$\{parent\.title\}/g, title)
.replace(/\$\{title\}/g, type)
.replace(/\$\{delimiter\}(.*?)\$\{end.delimiter\}/g, '')
.replace(/\$\{if\.optional\}(.*?)\$\{end\.if\.optional\}/g, ''))
}


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't we be calling insertObjectAdditionalProperitesMacros here, with the same if (schema.additionalProperties... block?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I updated code now to call insertObjectAdditionalProperitesMacros now

if (schema.properties) {
Object.entries(schema.properties).forEach(([name, prop], i) => {
options2.property = name
Expand Down Expand Up @@ -319,7 +333,7 @@ function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', name
if (level === 0 && !schema.title) {
return ''
}

const suffix = destination && ('.' + destination.split('.').pop()) || ''
const theTitle = insertSchemaMacros(getTemplate(path.join(templateDir, 'title' + suffix)), schema, module, schema.title || name, parent, property, false)

Expand Down Expand Up @@ -353,8 +367,14 @@ function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', name
return insertSchemaMacros(result, schema, module, theTitle, parent, property)
}
else if (schema.type === 'object') {
const shape = insertObjectMacros(getTemplate(path.join(templateDir, 'object' + suffix)), schema, module, theTitle, property, { level, parent, property, templateDir, descriptions, destination, section, enums })

let shape
const additionalPropertiesTemplate = getTemplate(path.join(templateDir, 'additionalProperties'))
if (additionalPropertiesTemplate && schema.additionalProperties && (typeof schema.additionalProperties === 'object')) {
shape = insertObjectAdditionalPropertiesMacros(additionalPropertiesTemplate, schema, module, theTitle, { level, parent, templateDir, namespace: true })
}
else {
shape = insertObjectMacros(getTemplate(path.join(templateDir, 'object' + suffix)), schema, module, theTitle, property, { level, parent, property, templateDir, descriptions, destination, section, enums, namespace: true })
}
result = result.replace(/\$\{shape\}/g, shape)
return insertSchemaMacros(result, schema, module, theTitle, parent, property)
}
Expand Down Expand Up @@ -614,11 +634,17 @@ function getSchemaType(schema, module, { destination, templateDir = 'types', lin
// }
}
else if (schema.type) {
// TODO: this assumes that when type is an array of types, that it's one other primative & 'null', which isn't necessarily true.
const schemaType = !Array.isArray(schema.type) ? schema.type : schema.type.find(t => t !== 'null')
const primitive = getPrimitiveType(schemaType, templateDir)
const type = allocatedProxy ? allocatedPrimitiveProxies[schemaType] || primitive : primitive
return wrap(type, code ? '`' : '')
const template = getTemplate(path.join(templateDir, 'additionalProperties'))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current method (getSchemaType) doesn't recurse into each property...

It looks like you're inserting the Title template if there happens to be a template for additionalProperties

I'm not sure I follow that. Could you explain?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

additionalPorperties always seening like a map. FlatMap is additional property and it is map. Here we have to get only its title. FlatMap. hence added logic to get Title.

if (schema.additionalProperties && template ) {
return insertSchemaMacros(getTemplate(path.join(templateDir, 'Title')), schema, module, theTitle, '', '', false)
}
else {
// TODO: this assumes that when type is an array of types, that it's one other primative & 'null', which isn't necessarily true.
const schemaType = !Array.isArray(schema.type) ? schema.type : schema.type.find(t => t !== 'null')
const primitive = getPrimitiveType(schemaType, templateDir)
const type = allocatedProxy ? allocatedPrimitiveProxies[schemaType] || primitive : primitive
return wrap(type, code ? '`' : '')
}
}
else {
// TODO this is TypeScript specific
Expand All @@ -627,7 +653,21 @@ function getSchemaType(schema, module, { destination, templateDir = 'types', lin
}

function getJsonType(schema, module, { destination, link = false, title = false, code = false, asPath = false, event = false, expandEnums = true, baseUrl = '' } = {}) {
return ''

schema = sanitize(schema)
let type
if (schema['$ref']) {
if (schema['$ref'][0] === '#') {
//Ref points to local schema
//Get Path to ref in this module and getSchemaType
let definition = getPath(schema['$ref'], module)
type = getJsonType(definition, schema, {destination})
}
}
else {
type = !Array.isArray(schema.type) ? schema.type : schema.type.find(t => t !== 'null')
}
return type
}

function getSchemaInstantiation(schema, module, { instantiationType }) {
Expand All @@ -642,6 +682,5 @@ export default {
getMethodSignatureParams,
getSchemaShape,
getSchemaType,
getJsonType,
getSchemaInstantiation
}
}
Loading