Skip to content

Commit

Permalink
update implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
jonaslagoni committed Apr 29, 2024
1 parent 7f3cf53 commit feac4af
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 58 deletions.
7 changes: 0 additions & 7 deletions docs/migrations/version-3-to-4.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,6 @@

This document contain all the breaking changes and migrations guidelines for adapting your code to the new version.

## Rewrite of how types are determined

In v3 and below, there was a edge case where a type could not be determined IF it was a cyclic model that was NOT split out into separate models. This change affects all generators to various degrees.

For example


## Deprecation of `processor.interpreter`

Since the early days we had the option to set `processorOptions.interpreter` options to change how JSON Schema is interpreted to Meta models. However, these options are more accurately part of the `processorOptions.jsonSchema` options.
Expand Down
2 changes: 1 addition & 1 deletion modelina-cli/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

91 changes: 41 additions & 50 deletions src/helpers/ConstrainedTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
ConstrainedUnionModel
} from '../models/ConstrainedMetaModel';
import { Constraints } from './MetaModelToConstrained';

import { TypeMapping, getTypeFromMapping } from './TypeHelpers';

export interface ApplyingTypesOptions<
Expand All @@ -35,6 +34,42 @@ export interface ApplyingTypesOptions<
constrainRules: Constraints<GeneratorOptions>;
}

/**
* Apply const and type to models from the constraint rules
*/
function applyTypeAndConst<
GeneratorOptions,
DependencyManager extends AbstractDependencyManager
>(context: ApplyingTypesOptions<GeneratorOptions, DependencyManager>) {
const {
constrainedModel,
typeMapping,
partOfProperty,
dependencyManager,
generatorOptions,
alreadySeenModels,
constrainRules
} = context;
if (constrainedModel.type !== '') {
return;
}
constrainedModel.type = getTypeFromMapping(typeMapping, {
constrainedModel,
options: generatorOptions,
partOfProperty,
dependencyManager
});

if (constrainedModel.options.const) {
const constrainedConstant = constrainRules.constant({
constrainedMetaModel: constrainedModel,
options: generatorOptions
});
constrainedModel.options.const.value = constrainedConstant;
}
alreadySeenModels.set(constrainedModel, constrainedModel.type);
}

/**
* Applying types and const through cyclic analysis (https://en.wikipedia.org/wiki/Cycle_(graph_theory))
* to detect and adapt unmanageable cyclic models where we cant determine types as normal.
Expand All @@ -56,37 +91,11 @@ export function applyTypesAndConst<
>(
context: ApplyingTypesOptions<GeneratorOptions, DependencyManager>
): ConstrainedMetaModel | undefined {
const {
constrainedModel,
safeTypes,
typeMapping,
partOfProperty,
dependencyManager,
generatorOptions,
alreadySeenModels,
constrainRules
} = context;
const { constrainedModel, safeTypes, alreadySeenModels } = context;
const isCyclicModel =
alreadySeenModels.has(constrainedModel) &&
alreadySeenModels.get(constrainedModel) === undefined;
const hasBeenSolved = alreadySeenModels.has(constrainedModel);
const applyTypeAndConst = (model: ConstrainedMetaModel) => {
model.type = getTypeFromMapping(typeMapping, {
constrainedModel: model,
options: generatorOptions,
partOfProperty,
dependencyManager
});

if (model.options.const) {
const constrainedConstant = constrainRules.constant({
constrainedMetaModel: model,
options: generatorOptions
});
model.options.const.value = constrainedConstant;
}
alreadySeenModels.set(model, model.type);
};

if (isCyclicModel) {
//Cyclic models detected, having to make the edge (right before cyclic occur) to use AnyModel (most open type we have)
Expand All @@ -101,7 +110,7 @@ export function applyTypesAndConst<
constrainedModel.options,
''
);
applyTypeAndConst(anyModel);
applyTypeAndConst({ ...context, constrainedModel: anyModel });
return anyModel;
} else if (hasBeenSolved) {
return undefined;
Expand All @@ -113,7 +122,7 @@ export function applyTypesAndConst<
//Walk over all safe models that can determine it's type right away
for (const safeType of safeTypes) {
if (constrainedModel instanceof safeType) {
applyTypeAndConst(constrainedModel);
applyTypeAndConst({ ...context, constrainedModel });
break;
}
}
Expand All @@ -131,7 +140,7 @@ function walkNode<
GeneratorOptions,
DependencyManager extends AbstractDependencyManager
>(context: ApplyingTypesOptions<GeneratorOptions, DependencyManager>) {
const { constrainedModel, constrainRules, generatorOptions } = context;
const { constrainedModel } = context;

if (constrainedModel instanceof ConstrainedObjectModel) {
walkObjectNode(context);
Expand All @@ -146,26 +155,8 @@ function walkNode<
} else if (constrainedModel instanceof ConstrainedReferenceModel) {
walkReferenceNode(context);
}
if (constrainedModel.type === '') {
constrainedModel.type = getTypeFromMapping(context.typeMapping, {
constrainedModel,
options: context.generatorOptions,
partOfProperty: context.partOfProperty,
dependencyManager: context.dependencyManager
});
context.alreadySeenModels.set(constrainedModel, constrainedModel.type);
}

if (
constrainedModel instanceof ConstrainedReferenceModel &&
constrainedModel.options.const
) {
const constrainedConstant = constrainRules.constant({
constrainedMetaModel: constrainedModel,
options: generatorOptions
});
constrainedModel.options.const.value = constrainedConstant;
}
applyTypeAndConst({ ...context, constrainedModel });

if (constrainedModel instanceof ConstrainedUnionModel) {
addDiscriminatorTypeToUnionModel(constrainedModel);
Expand Down

0 comments on commit feac4af

Please sign in to comment.