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

Support titles and deeper parsing of schemas #16

Closed
KitsuneRal opened this issue Dec 3, 2017 · 1 comment
Closed

Support titles and deeper parsing of schemas #16

KitsuneRal opened this issue Dec 3, 2017 · 1 comment
Assignees

Comments

@KitsuneRal
Copy link
Member

So far anything more complex than a flat list of properties is converted to an opaque object (matching QJsonObject in Qt), both for parameters and for response properties. Also, schema title attribute is completely skipped though it could serve as a type name.

@KitsuneRal KitsuneRal self-assigned this Dec 6, 2017
@KitsuneRal
Copy link
Member Author

Turned out to be quite a rabbit hole. Enriched the data structures immensely though.

KitsuneRal added a commit that referenced this issue Dec 6, 2017
 #16)

- Model:
  - ObjectSchema can have a name now, taken from the "title" attribute in the schema definition.
  - TypeUsage can be created from an ObjectSchema (with an obvious meaning - usage of type defined by that schema).
  - TypeUsage stores a base name in the API description for which it was created. This is used to map compound types (such as "array") more intelligently, enabling, e.g., a case for mapping an array of strings to Qt's QStringList.
  - TypeUsage::operator() has been renamed to instantiate(), to reflect what it does for parametrised types.
  - ObjectSchema and TypeUsage structs have an additional "scope" field that is either empty (for "global" definitions/usages) or has the operationId in which the data type has been defined.
  - Call is made a standard-layout structure, with former reference *Params fields replaced by accessor functions. Its move constructor missed on some fields so didn't really work; now it's replaced with the default one.
  - ObjectSchema structs are now stored in a vector instead of an unordered_map - we need them to be printed in the order of arrival so that name resolution for schemas works in C++ and other languages. Model::addSchema() is an entry point to add a new schema with uniqueness control (and register its imports).
  - camelCase(): _ (underscore) is left intact in the beginning and the end of identifiers, enabling things like `_camelCase` and `camelCase_`.
  - Instead of having many CallClass structs, with a single Call in each, it's now a single CallClass (until we make a better use of it) with all Calls collected under it. This simplifies traversal in Printer and better reflects the idea of an API as a group of calls.
- Analyzer:
  - Responsibilities are clearly distinguished between analyzeSchema (enumerates on whatever comes in the schema; delegates identifying the types for those whatevers to analyzeType, and reference resolution to tryResolveRefs), analyzeType (that never enumerates on the contents, only checking "type" and "format" attributes; delegates to analyzeSchema if it detects a non-primitive type) and tryResolveParentTypes (now tryResolveRefs, resolves references for analyzeSchema). tryResolveRefs in theory can be inlined into analyzeSchema now but it's better to keep them separate as we may get reference resolution requirements in other places than schemas.
  - analyzeSchema and analyzeType now receive an additional "scope" parameter to work with types defined inside operations.
  - tryResolveRefs: multiple inheritance (aka "more than one entry in "allOf") support. All those should be "$ref" for now; some more refactoring should be done to support an arbitrary combination of $refs and schemas.
  - analyzeType and addParamsFromSchema: in-depth analysis of array element types and schemas (via analyzeSchema), which means that arrays and schemas are no more treated as opaque objects; instead, arrays can be referred to as parametrised types and schemas are referred to by their names. To parametrise arrays, the "format" level in the types mapping is reused, matching it against "baseName" (either "format", or "type" if "format" is empty) of the element type.
- Translator::mapType is unified to deal with type mapping both for arrays and simple types (by moving out the parametrised type logic to that single place in Analyzer::analyzeType() where it is needed); depending on its arguments it fills the produced TypeUsage instances with the best found "baseName".
- Printer:
  - Picks the type renderer from `gtad.yaml` and uses it to properly render qualified types. This is necessary now that we can have data structures inside operation classes and at the same time parametrised classes for arrays. There's no way this can be defined in the output file template because array type parameters are completely invisible from there; so instead we specify how a parametrised type looks like in the types mapping and then provide a separate renderer that will make either a qualified or an unqualified name depending on whether the scope part is passed to it.
  - Because of the above changes {{datatype}} variables are now just compatibility shortcuts to {{dataType.name}}, and to have a qualified name {{dataType.qualifiedName}} can be used.
  - setList: {{last?}} is replaced with {{@join}} (which is always defined as true or false, unlike {{last?}} that was only defined for true cases) as it causes surprises when not defined if {{last?}} is already defined in the upper iterative layer (case in point: `{{#section1}}{{#last?}}yet good {{/last?}}{{#section2}}{{#last?}}surprise!{{/last?}}{{/section2}}{{/section1}} - the second {{#last?}}, being undefined, is subverted by the defined higher-level {{#last?}}).
  - setList: To unify between exporting lists of strings and lists of objects (to support the hasMore/@join flag in lists of strings, in particular) strings are now stored into {{_}} (Mustache uses {{.}} to get to a string in a list of strings). Next to {{_}}, {{hasMore}} and {{@join}} are defined. For objects, {{_}} is not introduced - just use your fields as usual.
  - renderType now makes both a qualified and an unqualified version for the passed TypeUsage.
  - prepareField (now Printer::dumpField): paramNameCamelCase is now nameCamelCase.
  - Making Mustache context for data structures is refactored from print() to dumpTypes and dumpAllTypes, now that we have to do it in several places. Available variables for data structures are: name, baseName, trivial?, parent (only for trivial structures), parents (for all structures), vars (a list of structure fields).
  - print(): "allModels" introduced that includes both global and local data structures. "models" only has global structures on the global level, and only local ones on inner levels.
KitsuneRal added a commit that referenced this issue Dec 7, 2017
 #16)

- Model:
  - ObjectSchema can have a name now, taken from the "title" attribute in the schema definition.
  - TypeUsage can be created from an ObjectSchema (with an obvious meaning - usage of type defined by that schema).
  - TypeUsage stores a base name in the API description for which it was created. This is used to map compound types (such as "array") more intelligently, enabling, e.g., a case for mapping an array of strings to Qt's QStringList.
  - TypeUsage::operator() has been renamed to instantiate(), to reflect what it does for parametrised types.
  - ObjectSchema and TypeUsage structs have an additional "scope" field that is either empty (for "global" definitions/usages) or has the operationId in which the data type has been defined.
  - Call is made a standard-layout structure, with former reference *Params fields replaced by accessor functions. Its move constructor missed on some fields so didn't really work; now it's replaced with the default one.
  - ObjectSchema structs are now stored in a vector instead of an unordered_map - we need them to be printed in the order of arrival so that name resolution for schemas works in C++ and other languages. Model::addSchema() is an entry point to add a new schema with uniqueness control (and register its imports).
  - camelCase(): _ (underscore) is left intact in the beginning and the end of identifiers, enabling things like `_camelCase` and `camelCase_`.
  - Instead of having many CallClass structs, with a single Call in each, it's now a single CallClass (until we make a better use of it) with all Calls collected under it. This simplifies traversal in Printer and better reflects the idea of an API as a group of calls.
- Analyzer:
  - Responsibilities are clearly distinguished between analyzeSchema (enumerates on whatever comes in the schema; delegates identifying the types for those whatevers to analyzeType, and reference resolution to tryResolveRefs), analyzeType (that never enumerates on the contents, only checking "type" and "format" attributes; delegates to analyzeSchema if it detects a non-primitive type) and tryResolveParentTypes (now tryResolveRefs, resolves references for analyzeSchema). tryResolveRefs in theory can be inlined into analyzeSchema now but it's better to keep them separate as we may get reference resolution requirements in other places than schemas.
  - analyzeSchema and analyzeType now receive an additional "scope" parameter to work with types defined inside operations.
  - tryResolveRefs: multiple inheritance (aka "more than one entry in "allOf") support. All those should be "$ref" for now; some more refactoring should be done to support an arbitrary combination of $refs and schemas.
  - analyzeType and addParamsFromSchema: in-depth analysis of array element types and schemas (via analyzeSchema), which means that arrays and schemas are no more treated as opaque objects; instead, arrays can be referred to as parametrised types and schemas are referred to by their names. To parametrise arrays, the "format" level in the types mapping is reused, matching it against "baseName" (either "format", or "type" if "format" is empty) of the element type.
- Translator::mapType is unified to deal with type mapping both for arrays and simple types (by moving out the parametrised type logic to that single place in Analyzer::analyzeType() where it is needed); depending on its arguments it fills the produced TypeUsage instances with the best found "baseName".
- Printer:
  - Picks the type renderer from `gtad.yaml` and uses it to properly render qualified types. This is necessary now that we can have data structures inside operation classes and at the same time parametrised classes for arrays. There's no way this can be defined in the output file template because array type parameters are completely invisible from there; so instead we specify how a parametrised type looks like in the types mapping and then provide a separate renderer that will make either a qualified or an unqualified name depending on whether the scope part is passed to it.
  - Because of the above changes {{datatype}} variables are now just compatibility shortcuts to {{dataType.name}}, and to have a qualified name {{dataType.qualifiedName}} can be used.
  - setList: {{last?}} is replaced with {{@join}} (which is always defined as true or false, unlike {{last?}} that was only defined for true cases) as it causes surprises when not defined if {{last?}} is already defined in the upper iterative layer (case in point: `{{#section1}}{{#last?}}yet good {{/last?}}{{#section2}}{{#last?}}surprise!{{/last?}}{{/section2}}{{/section1}} - the second {{#last?}}, being undefined, is subverted by the defined higher-level {{#last?}}).
  - setList: To unify between exporting lists of strings and lists of objects (to support the hasMore/@join flag in lists of strings, in particular) strings are now stored into {{_}} (Mustache uses {{.}} to get to a string in a list of strings). Next to {{_}}, {{hasMore}} and {{@join}} are defined. For objects, {{_}} is not introduced - just use your fields as usual.
  - renderType now makes both a qualified and an unqualified version for the passed TypeUsage.
  - prepareField (now Printer::dumpField): paramNameCamelCase is now nameCamelCase.
  - Making Mustache context for data structures is refactored from print() to dumpTypes and dumpAllTypes, now that we have to do it in several places. Available variables for data structures are: name, baseName, trivial?, parent (only for trivial structures), parents (for all structures), vars (a list of structure fields).
  - print(): "allModels" introduced that includes both global and local data structures. "models" only has global structures on the global level, and only local ones on inner levels.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Version 0.4 - Done
Development

No branches or pull requests

1 participant