Skip to content

Commit

Permalink
Added Value Object constructor evaluation (#464)
Browse files Browse the repository at this point in the history
  • Loading branch information
giorgosnty authored May 29, 2023
1 parent a042a65 commit 03f3ea8
Show file tree
Hide file tree
Showing 17 changed files with 309 additions and 3 deletions.
18 changes: 18 additions & 0 deletions transpiler/__tests__/ast/core/builders/evaluationDirector.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,24 @@ export class EvaluationBuilderDirector {
};
}

buildValueObjectonstructorEvaluation(
valueObjectIdentifier: string,
propsParam: PropsParam,
): TEvaluation {
const { fields, expression } = propsParam;
const props: TDomainEvaluationExpression = fields ? { fields } : { ...expression };
return {
evaluation: {
valueObjectConstructor: {
domainEvaluation: {
valueObjectIdentifier,
props,
},
},
},
};
}

buildDomainServiceEvaluation(domainServiceIdentifier: string, args?: TArgumentList): TEvaluation {
return {
evaluation: {
Expand Down
10 changes: 10 additions & 0 deletions transpiler/__tests__/ast/core/mocks/evaluation/evaluation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,16 @@ export const validEvaluationTestCases: Array<TestCase> = [
],
}),
},
{
description: 'Valid value object constructor evaluation',
fileId: 'testFile.bl',
inputBLString: "JestTestEvaluation { NameVO({ message: 'Hello, World!' })}",
evaluation: new EvaluationBuilderDirector().buildValueObjectonstructorEvaluation('NameVO', {
fields: [
new EvaluationFieldBuilderDirector().buildStringEvaluationField('message', 'Hello, World!'),
],
}),
},
{
description: 'valid Domain Event Evaluation',
fileId: 'testFile.bl',
Expand Down
20 changes: 20 additions & 0 deletions transpiler/__tests__/target/typescript/core/builders/evaluation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import { DomainEventEvaluationNodeBuilder } from '../../../../../src/ast/core/in
import { IdentifierNodeBuilder } from '../../../../../src/ast/core/intermediate-ast/builders/identifier/IdentifierBuilder.js';
import { PackageMethodNameBuilder } from '../../../../../src/ast/core/intermediate-ast/builders/expressions/evaluation/PackageMethodNameBuilder.js';
import { PackageEvaluationNodeBuilder } from '../../../../../src/ast/core/intermediate-ast/builders/expressions/evaluation/PackageEvaluationNodeBuilder.js';
import { ValueObjectIdentifierNodeBuilder } from '../../../../../src/ast/core/intermediate-ast/builders/valueObject/ValueObjectIdentifierNodeBuilder.js';
import { ValueObjectConstructorEvaluationNodeBuilder } from '../../../../../src/ast/core/intermediate-ast/builders/expressions/evaluation/ValueObjectConstructorEvaluationNodeBuilder.js';

export class EvaluationBuilderDirector {
buildStructEvaluation(identifier: string, evalFields: EvaluationFieldNode[]): EvaluationNode {
Expand Down Expand Up @@ -122,6 +124,24 @@ export class EvaluationBuilderDirector {
return evaluationNode;
}

buildValueObjectConstructorEvaluationWithExpression(
valueObjectName: string,
expressionNode: ExpressionNode,
): EvaluationNode {
const domainEvaluation =
new DomainEvaluationBuilderDirector().buildDomainEvaluationWithExpressionProps(
new ValueObjectIdentifierNodeBuilder().withName(valueObjectName).build(),
expressionNode,
);
const valueObjectEvaluationNode = new ValueObjectConstructorEvaluationNodeBuilder()
.withEvaluation(domainEvaluation)
.build();
const evaluationNode = new EvaluationBuilder()
.withEvaluation(valueObjectEvaluationNode)
.build();
return evaluationNode;
}

buildErrorEvaluation(
identifier: string,
argumentDependencies?: ArgumentListNode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,14 @@ export const VALID_EVALUATION_TEST_CASES = [
),
output: 'new TodoEntity(todoProps)',
},
{
description: 'Value object constructor evaluation with identifier expression',
evaluation: new EvaluationBuilderDirector().buildValueObjectConstructorEvaluationWithExpression(
'TitleVO',
new ExpressionBuilderDirector().buildIdentifierExpression('titleProps'),
),
output: 'new TitleVO(titleProps)',
},
{
description: 'Read model evaluation',
evaluation: new EvaluationBuilderDirector().buildReadModelEvaluation(
Expand Down
7 changes: 7 additions & 0 deletions transpiler/src/ast/core/BitloopsVisitor/BitloopsVisitor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,7 @@ import { domainServiceEvaluationVisitor } from './helpers/expression/evaluation/
import { IntegrationEventHandlerHandleMethodNode } from '../intermediate-ast/nodes/integration-event/IntegrationEventHandlerHandleMethodNode.js';
import { anonymousFunctionVisitor } from './helpers/anonymousFunctionVisitor.js';
import { arrowFunctionBodyVisitor } from './helpers/arrowFunctionBodyVisitor.js';
import { valueObjectConstructorEvaluationVisitor } from './helpers/expression/evaluation/valueObejctConstructorEvaluation.js';

export type TContextInfo = {
boundedContextName: string;
Expand Down Expand Up @@ -693,6 +694,12 @@ export default class BitloopsVisitor extends BitloopsParserVisitor {
return entityConstructorEvaluationVisitor(this, ctx);
}

visitValueObjectConstructorEvaluation(
ctx: BitloopsParser.ValueObjectConstructorEvaluationContext,
): any {
return valueObjectConstructorEvaluationVisitor(this, ctx);
}

visitDomainEvaluationInputFieldList(ctx: BitloopsParser.DomainEvaluationInputFieldListContext) {
return domainEvaluationInputFieldListVisitor(this, ctx);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/**
* Bitloops Language CLI
* Copyright (C) 2022 Bitloops S.A.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* For further information you can contact legal(at)bitloops.com.
*/

import BitloopsVisitor from '../../../BitloopsVisitor.js';
import BitloopsParser from '../../../../../../parser/core/grammar/BitloopsParser.js';
import { produceMetadata } from '../../../metadata.js';
import { DomainEvaluationNodeBuilder } from '../../../../intermediate-ast/builders/expressions/evaluation/DomainEvaluation/DomainEvaluationNodeBuilder.js';
import { ValueObjectConstructorEvaluationNode } from '../../../../intermediate-ast/nodes/Expression/Evaluation/ValueObjectConstructorEvaluationNode.js';
import { ValueObjectConstructorEvaluationNodeBuilder } from '../../../../intermediate-ast/builders/expressions/evaluation/ValueObjectConstructorEvaluationNodeBuilder.js';

export const valueObjectConstructorEvaluationVisitor = (
thisVisitor: BitloopsVisitor,
ctx: BitloopsParser.ValueObjectConstructorEvaluationContext,
): ValueObjectConstructorEvaluationNode => {
const props = thisVisitor.visit(ctx.domainEvaluationInput());
const valueObjectIdentifier = thisVisitor.visit(ctx.valueObjectIdentifier());

const metadata = produceMetadata(ctx, thisVisitor);
const domainEvaluation = new DomainEvaluationNodeBuilder(metadata)
.withIdentifier(valueObjectIdentifier)
.withProps(props)
.build();

const node = new ValueObjectConstructorEvaluationNodeBuilder(metadata)
.withEvaluation(domainEvaluation)
.build();
return node;
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* Bitloops Language CLI
* Copyright (C) 2022 Bitloops S.A.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* For further information you can contact legal(at)bitloops.com.
*/
import { DomainEvaluationNode } from '../../../nodes/Expression/Evaluation/DomainEvaluation/DomainEvaluation.js';
import { ValueObjectConstructorEvaluationNode } from '../../../nodes/Expression/Evaluation/ValueObjectConstructorEvaluationNode.js';
import { TNodeMetadata } from '../../../nodes/IntermediateASTNode.js';
import { IBuilder } from '../../IBuilder.js';

export class ValueObjectConstructorEvaluationNodeBuilder
implements IBuilder<ValueObjectConstructorEvaluationNode>
{
private valueObjectConstructorEvaluationNode: ValueObjectConstructorEvaluationNode;
private evaluation: DomainEvaluationNode;

constructor(metadata?: TNodeMetadata) {
this.valueObjectConstructorEvaluationNode = new ValueObjectConstructorEvaluationNode(metadata);
}

public withEvaluation(
evaluation: DomainEvaluationNode,
): ValueObjectConstructorEvaluationNodeBuilder {
this.evaluation = evaluation;
return this;
}

public build(): ValueObjectConstructorEvaluationNode {
this.valueObjectConstructorEvaluationNode.addChild(this.evaluation);

this.valueObjectConstructorEvaluationNode.buildObjectValue();

return this.valueObjectConstructorEvaluationNode;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ export class EntityConstructorEvaluationNode extends EvaluationNode {
this.nodeType = BitloopsTypesMapping.TEntityConstructorEvaluation;
this.classNodeName = EntityConstructorEvaluationNode.nodeName;
}

public override getIdentifierNode(): EntityIdentifierNode {
const domainEvaluationNode = this.getChildNodeByType<DomainEvaluationNode>(
BitloopsTypesMapping.TDomainEvaluation,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* Bitloops Language CLI
* Copyright (C) 2022 Bitloops S.A.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* For further information you can contact legal(at)bitloops.com.
*/
import { BitloopsTypesMapping } from '../../../../../../helpers/mappings.js';
import { TNodeMetadata } from '../../IntermediateASTNode.js';
import { ValueObjectIdentifierNode } from '../../valueObject/ValueObjectIdentifierNode.js';
import { DomainEvaluationNode } from './DomainEvaluation/DomainEvaluation.js';
import { EvaluationNode } from './EvaluationNode.js';

export class ValueObjectConstructorEvaluationNode extends EvaluationNode {
private static nodeName = 'valueObjectConstructor';

constructor(metadata?: TNodeMetadata) {
super(metadata);
this.nodeType = BitloopsTypesMapping.TValueObjectConstructorEvaluation;
this.classNodeName = ValueObjectConstructorEvaluationNode.nodeName;
}
public override getIdentifierNode(): ValueObjectIdentifierNode {
const domainEvaluationNode = this.getChildNodeByType<DomainEvaluationNode>(
BitloopsTypesMapping.TDomainEvaluation,
);
const identifier = domainEvaluationNode.getChildren().find((child) => {
return child.getNodeType() === BitloopsTypesMapping.TValueObjectIdentifier;
}) as ValueObjectIdentifierNode;
return identifier;
}

public getInferredType(): string {
const valueObjectEvaluationIdentifier =
this.getIdentifierNode().getValue().valueObjectIdentifier;
return valueObjectEvaluationIdentifier;
}
}
1 change: 1 addition & 0 deletions transpiler/src/helpers/mappings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ const BitloopsTypesMapping = {
TIfErrorExpression: 'TIfErrorExpression',
TAnonymousFunction: 'TAnonymousFunction',
TArrowFunctionBody: 'TArrowFunctionBody',
TValueObjectConstructorEvaluation: 'TValueObjectConstructorEvaluation',
} as const;

type TBitloopsTypesKeys = keyof typeof BitloopsTypesMapping;
Expand Down
5 changes: 5 additions & 0 deletions transpiler/src/parser/core/grammar/BitloopsParser.g4
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,7 @@ evaluation
| valueObjectEvaluation
| entityEvaluation
| entityConstructorEvaluation
| valueObjectConstructorEvaluation
| propsEvaluation
| structEvaluation
| commandEvaluation
Expand Down Expand Up @@ -619,6 +620,10 @@ entityConstructorEvaluation
: entityIdentifier domainEvaluationInput
;

valueObjectConstructorEvaluation
: valueObjectIdentifier domainEvaluationInput
;

commandEvaluation
: commandIdentifier Dot Create OpenParen (OpenBrace evaluationFieldList CloseBrace)? CloseParen
;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,13 @@ export const domainEvaluationToTargetLanguage = (
};
};

const getDomainName = (evaluation: TDomainEvaluation): string => {
export const getDomainName = (evaluation: TDomainEvaluation): string => {
const domainEvaluation = evaluation.domainEvaluation;
let domainName;
if ('entityIdentifier' in domainEvaluation) domainName = domainEvaluation.entityIdentifier;
if ('valueObjectIdentifier' in domainEvaluation)
else if ('valueObjectIdentifier' in domainEvaluation)
domainName = domainEvaluation.valueObjectIdentifier;
else if ('readModelIdentifier' in domainEvaluation)
domainName = domainEvaluation.readModelIdentifier;
return domainName;
};
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@ const evaluationToTargetLanguage = (variable: TEvaluation): TTargetDependenciesT
});
}

if (EvaluationTypeIdentifiers.iValueObjectConstructorEvaluation(evaluation)) {
return modelToTargetLanguage({
type: BitloopsTypesMapping.TValueObjectConstructorEvaluation,
value: evaluation,
});
}

if (EvaluationTypeIdentifiers.isDomainServiceEvaluation(evaluation)) {
return modelToTargetLanguage({
type: BitloopsTypesMapping.TDomainServiceEvaluation,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* Bitloops Language
* Copyright (C) 2022 Bitloops S.A.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* For further information you can contact legal(at)bitloops.com.
*/

import {
TDomainEvaluation,
TValueObjectConstructorEvaluation,
TTargetDependenciesTypeScript,
} from '../../../../../../../types.js';
import { BitloopsTypesMapping } from '../../../../../../../helpers/mappings.js';
import { modelToTargetLanguage } from '../../../../modelToTargetLanguage.js';
import { DomainEvaluationPropsTypeIdentifiers } from '../../../../type-identifiers/domainEvaluationProps.js';
import { getDomainName } from './entityConstructorEvaluation.js';

export const valueObjectConstructorEvaluationToTargetLanguage = (
evaluation: TValueObjectConstructorEvaluation,
): TTargetDependenciesTypeScript => {
const valueObjectEvaluation = evaluation.valueObjectConstructor;

const result = domainEvaluationToTargetLanguage(valueObjectEvaluation);

return result;
};

export const domainEvaluationToTargetLanguage = (
evaluation: TDomainEvaluation,
): TTargetDependenciesTypeScript => {
const domainProperties = evaluation.domainEvaluation.props;

let resultDomainProps: TTargetDependenciesTypeScript;
if (DomainEvaluationPropsTypeIdentifiers.isExpression(domainProperties)) {
resultDomainProps = modelToTargetLanguage({
type: BitloopsTypesMapping.TExpression,
value: domainProperties,
});
} else {
resultDomainProps = modelToTargetLanguage({
type: BitloopsTypesMapping.TEvaluationFields,
value: domainProperties.fields,
});
}

const dependencies = [...resultDomainProps.dependencies];
const domainName = getDomainName(evaluation);

return {
output: `new ${domainName}(${resultDomainProps.output})`,
dependencies,
};
};
Loading

0 comments on commit 03f3ea8

Please sign in to comment.