Skip to content

Commit 03f3ea8

Browse files
authored
Added Value Object constructor evaluation (#464)
1 parent a042a65 commit 03f3ea8

File tree

17 files changed

+309
-3
lines changed

17 files changed

+309
-3
lines changed

transpiler/__tests__/ast/core/builders/evaluationDirector.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,24 @@ export class EvaluationBuilderDirector {
219219
};
220220
}
221221

222+
buildValueObjectonstructorEvaluation(
223+
valueObjectIdentifier: string,
224+
propsParam: PropsParam,
225+
): TEvaluation {
226+
const { fields, expression } = propsParam;
227+
const props: TDomainEvaluationExpression = fields ? { fields } : { ...expression };
228+
return {
229+
evaluation: {
230+
valueObjectConstructor: {
231+
domainEvaluation: {
232+
valueObjectIdentifier,
233+
props,
234+
},
235+
},
236+
},
237+
};
238+
}
239+
222240
buildDomainServiceEvaluation(domainServiceIdentifier: string, args?: TArgumentList): TEvaluation {
223241
return {
224242
evaluation: {

transpiler/__tests__/ast/core/mocks/evaluation/evaluation.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,16 @@ export const validEvaluationTestCases: Array<TestCase> = [
106106
],
107107
}),
108108
},
109+
{
110+
description: 'Valid value object constructor evaluation',
111+
fileId: 'testFile.bl',
112+
inputBLString: "JestTestEvaluation { NameVO({ message: 'Hello, World!' })}",
113+
evaluation: new EvaluationBuilderDirector().buildValueObjectonstructorEvaluation('NameVO', {
114+
fields: [
115+
new EvaluationFieldBuilderDirector().buildStringEvaluationField('message', 'Hello, World!'),
116+
],
117+
}),
118+
},
109119
{
110120
description: 'valid Domain Event Evaluation',
111121
fileId: 'testFile.bl',

transpiler/__tests__/target/typescript/core/builders/evaluation.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ import { DomainEventEvaluationNodeBuilder } from '../../../../../src/ast/core/in
3232
import { IdentifierNodeBuilder } from '../../../../../src/ast/core/intermediate-ast/builders/identifier/IdentifierBuilder.js';
3333
import { PackageMethodNameBuilder } from '../../../../../src/ast/core/intermediate-ast/builders/expressions/evaluation/PackageMethodNameBuilder.js';
3434
import { PackageEvaluationNodeBuilder } from '../../../../../src/ast/core/intermediate-ast/builders/expressions/evaluation/PackageEvaluationNodeBuilder.js';
35+
import { ValueObjectIdentifierNodeBuilder } from '../../../../../src/ast/core/intermediate-ast/builders/valueObject/ValueObjectIdentifierNodeBuilder.js';
36+
import { ValueObjectConstructorEvaluationNodeBuilder } from '../../../../../src/ast/core/intermediate-ast/builders/expressions/evaluation/ValueObjectConstructorEvaluationNodeBuilder.js';
3537

3638
export class EvaluationBuilderDirector {
3739
buildStructEvaluation(identifier: string, evalFields: EvaluationFieldNode[]): EvaluationNode {
@@ -122,6 +124,24 @@ export class EvaluationBuilderDirector {
122124
return evaluationNode;
123125
}
124126

127+
buildValueObjectConstructorEvaluationWithExpression(
128+
valueObjectName: string,
129+
expressionNode: ExpressionNode,
130+
): EvaluationNode {
131+
const domainEvaluation =
132+
new DomainEvaluationBuilderDirector().buildDomainEvaluationWithExpressionProps(
133+
new ValueObjectIdentifierNodeBuilder().withName(valueObjectName).build(),
134+
expressionNode,
135+
);
136+
const valueObjectEvaluationNode = new ValueObjectConstructorEvaluationNodeBuilder()
137+
.withEvaluation(domainEvaluation)
138+
.build();
139+
const evaluationNode = new EvaluationBuilder()
140+
.withEvaluation(valueObjectEvaluationNode)
141+
.build();
142+
return evaluationNode;
143+
}
144+
125145
buildErrorEvaluation(
126146
identifier: string,
127147
argumentDependencies?: ArgumentListNode,

transpiler/__tests__/target/typescript/core/mocks/expression/evaluation.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,14 @@ export const VALID_EVALUATION_TEST_CASES = [
118118
),
119119
output: 'new TodoEntity(todoProps)',
120120
},
121+
{
122+
description: 'Value object constructor evaluation with identifier expression',
123+
evaluation: new EvaluationBuilderDirector().buildValueObjectConstructorEvaluationWithExpression(
124+
'TitleVO',
125+
new ExpressionBuilderDirector().buildIdentifierExpression('titleProps'),
126+
),
127+
output: 'new TitleVO(titleProps)',
128+
},
121129
{
122130
description: 'Read model evaluation',
123131
evaluation: new EvaluationBuilderDirector().buildReadModelEvaluation(

transpiler/src/ast/core/BitloopsVisitor/BitloopsVisitor.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ import { domainServiceEvaluationVisitor } from './helpers/expression/evaluation/
247247
import { IntegrationEventHandlerHandleMethodNode } from '../intermediate-ast/nodes/integration-event/IntegrationEventHandlerHandleMethodNode.js';
248248
import { anonymousFunctionVisitor } from './helpers/anonymousFunctionVisitor.js';
249249
import { arrowFunctionBodyVisitor } from './helpers/arrowFunctionBodyVisitor.js';
250+
import { valueObjectConstructorEvaluationVisitor } from './helpers/expression/evaluation/valueObejctConstructorEvaluation.js';
250251

251252
export type TContextInfo = {
252253
boundedContextName: string;
@@ -693,6 +694,12 @@ export default class BitloopsVisitor extends BitloopsParserVisitor {
693694
return entityConstructorEvaluationVisitor(this, ctx);
694695
}
695696

697+
visitValueObjectConstructorEvaluation(
698+
ctx: BitloopsParser.ValueObjectConstructorEvaluationContext,
699+
): any {
700+
return valueObjectConstructorEvaluationVisitor(this, ctx);
701+
}
702+
696703
visitDomainEvaluationInputFieldList(ctx: BitloopsParser.DomainEvaluationInputFieldListContext) {
697704
return domainEvaluationInputFieldListVisitor(this, ctx);
698705
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/**
2+
* Bitloops Language CLI
3+
* Copyright (C) 2022 Bitloops S.A.
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*
18+
* For further information you can contact legal(at)bitloops.com.
19+
*/
20+
21+
import BitloopsVisitor from '../../../BitloopsVisitor.js';
22+
import BitloopsParser from '../../../../../../parser/core/grammar/BitloopsParser.js';
23+
import { produceMetadata } from '../../../metadata.js';
24+
import { DomainEvaluationNodeBuilder } from '../../../../intermediate-ast/builders/expressions/evaluation/DomainEvaluation/DomainEvaluationNodeBuilder.js';
25+
import { ValueObjectConstructorEvaluationNode } from '../../../../intermediate-ast/nodes/Expression/Evaluation/ValueObjectConstructorEvaluationNode.js';
26+
import { ValueObjectConstructorEvaluationNodeBuilder } from '../../../../intermediate-ast/builders/expressions/evaluation/ValueObjectConstructorEvaluationNodeBuilder.js';
27+
28+
export const valueObjectConstructorEvaluationVisitor = (
29+
thisVisitor: BitloopsVisitor,
30+
ctx: BitloopsParser.ValueObjectConstructorEvaluationContext,
31+
): ValueObjectConstructorEvaluationNode => {
32+
const props = thisVisitor.visit(ctx.domainEvaluationInput());
33+
const valueObjectIdentifier = thisVisitor.visit(ctx.valueObjectIdentifier());
34+
35+
const metadata = produceMetadata(ctx, thisVisitor);
36+
const domainEvaluation = new DomainEvaluationNodeBuilder(metadata)
37+
.withIdentifier(valueObjectIdentifier)
38+
.withProps(props)
39+
.build();
40+
41+
const node = new ValueObjectConstructorEvaluationNodeBuilder(metadata)
42+
.withEvaluation(domainEvaluation)
43+
.build();
44+
return node;
45+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Bitloops Language CLI
3+
* Copyright (C) 2022 Bitloops S.A.
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*
18+
* For further information you can contact legal(at)bitloops.com.
19+
*/
20+
import { DomainEvaluationNode } from '../../../nodes/Expression/Evaluation/DomainEvaluation/DomainEvaluation.js';
21+
import { ValueObjectConstructorEvaluationNode } from '../../../nodes/Expression/Evaluation/ValueObjectConstructorEvaluationNode.js';
22+
import { TNodeMetadata } from '../../../nodes/IntermediateASTNode.js';
23+
import { IBuilder } from '../../IBuilder.js';
24+
25+
export class ValueObjectConstructorEvaluationNodeBuilder
26+
implements IBuilder<ValueObjectConstructorEvaluationNode>
27+
{
28+
private valueObjectConstructorEvaluationNode: ValueObjectConstructorEvaluationNode;
29+
private evaluation: DomainEvaluationNode;
30+
31+
constructor(metadata?: TNodeMetadata) {
32+
this.valueObjectConstructorEvaluationNode = new ValueObjectConstructorEvaluationNode(metadata);
33+
}
34+
35+
public withEvaluation(
36+
evaluation: DomainEvaluationNode,
37+
): ValueObjectConstructorEvaluationNodeBuilder {
38+
this.evaluation = evaluation;
39+
return this;
40+
}
41+
42+
public build(): ValueObjectConstructorEvaluationNode {
43+
this.valueObjectConstructorEvaluationNode.addChild(this.evaluation);
44+
45+
this.valueObjectConstructorEvaluationNode.buildObjectValue();
46+
47+
return this.valueObjectConstructorEvaluationNode;
48+
}
49+
}

transpiler/src/ast/core/intermediate-ast/nodes/Expression/Evaluation/EntityConstructorEvaluationNode.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ export class EntityConstructorEvaluationNode extends EvaluationNode {
3131
this.nodeType = BitloopsTypesMapping.TEntityConstructorEvaluation;
3232
this.classNodeName = EntityConstructorEvaluationNode.nodeName;
3333
}
34-
3534
public override getIdentifierNode(): EntityIdentifierNode {
3635
const domainEvaluationNode = this.getChildNodeByType<DomainEvaluationNode>(
3736
BitloopsTypesMapping.TDomainEvaluation,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Bitloops Language CLI
3+
* Copyright (C) 2022 Bitloops S.A.
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*
18+
* For further information you can contact legal(at)bitloops.com.
19+
*/
20+
import { BitloopsTypesMapping } from '../../../../../../helpers/mappings.js';
21+
import { TNodeMetadata } from '../../IntermediateASTNode.js';
22+
import { ValueObjectIdentifierNode } from '../../valueObject/ValueObjectIdentifierNode.js';
23+
import { DomainEvaluationNode } from './DomainEvaluation/DomainEvaluation.js';
24+
import { EvaluationNode } from './EvaluationNode.js';
25+
26+
export class ValueObjectConstructorEvaluationNode extends EvaluationNode {
27+
private static nodeName = 'valueObjectConstructor';
28+
29+
constructor(metadata?: TNodeMetadata) {
30+
super(metadata);
31+
this.nodeType = BitloopsTypesMapping.TValueObjectConstructorEvaluation;
32+
this.classNodeName = ValueObjectConstructorEvaluationNode.nodeName;
33+
}
34+
public override getIdentifierNode(): ValueObjectIdentifierNode {
35+
const domainEvaluationNode = this.getChildNodeByType<DomainEvaluationNode>(
36+
BitloopsTypesMapping.TDomainEvaluation,
37+
);
38+
const identifier = domainEvaluationNode.getChildren().find((child) => {
39+
return child.getNodeType() === BitloopsTypesMapping.TValueObjectIdentifier;
40+
}) as ValueObjectIdentifierNode;
41+
return identifier;
42+
}
43+
44+
public getInferredType(): string {
45+
const valueObjectEvaluationIdentifier =
46+
this.getIdentifierNode().getValue().valueObjectIdentifier;
47+
return valueObjectEvaluationIdentifier;
48+
}
49+
}

transpiler/src/helpers/mappings.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ const BitloopsTypesMapping = {
222222
TIfErrorExpression: 'TIfErrorExpression',
223223
TAnonymousFunction: 'TAnonymousFunction',
224224
TArrowFunctionBody: 'TArrowFunctionBody',
225+
TValueObjectConstructorEvaluation: 'TValueObjectConstructorEvaluation',
225226
} as const;
226227

227228
type TBitloopsTypesKeys = keyof typeof BitloopsTypesMapping;

transpiler/src/parser/core/grammar/BitloopsParser.g4

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,7 @@ evaluation
265265
| valueObjectEvaluation
266266
| entityEvaluation
267267
| entityConstructorEvaluation
268+
| valueObjectConstructorEvaluation
268269
| propsEvaluation
269270
| structEvaluation
270271
| commandEvaluation
@@ -619,6 +620,10 @@ entityConstructorEvaluation
619620
: entityIdentifier domainEvaluationInput
620621
;
621622

623+
valueObjectConstructorEvaluation
624+
: valueObjectIdentifier domainEvaluationInput
625+
;
626+
622627
commandEvaluation
623628
: commandIdentifier Dot Create OpenParen (OpenBrace evaluationFieldList CloseBrace)? CloseParen
624629
;

transpiler/src/target/typescript-nest/core/components/statements/expression/evaluation/entityConstructorEvaluation.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,11 +64,13 @@ export const domainEvaluationToTargetLanguage = (
6464
};
6565
};
6666

67-
const getDomainName = (evaluation: TDomainEvaluation): string => {
67+
export const getDomainName = (evaluation: TDomainEvaluation): string => {
6868
const domainEvaluation = evaluation.domainEvaluation;
6969
let domainName;
7070
if ('entityIdentifier' in domainEvaluation) domainName = domainEvaluation.entityIdentifier;
71-
if ('valueObjectIdentifier' in domainEvaluation)
71+
else if ('valueObjectIdentifier' in domainEvaluation)
7272
domainName = domainEvaluation.valueObjectIdentifier;
73+
else if ('readModelIdentifier' in domainEvaluation)
74+
domainName = domainEvaluation.readModelIdentifier;
7375
return domainName;
7476
};

transpiler/src/target/typescript-nest/core/components/statements/expression/evaluation/index.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,13 @@ const evaluationToTargetLanguage = (variable: TEvaluation): TTargetDependenciesT
9696
});
9797
}
9898

99+
if (EvaluationTypeIdentifiers.iValueObjectConstructorEvaluation(evaluation)) {
100+
return modelToTargetLanguage({
101+
type: BitloopsTypesMapping.TValueObjectConstructorEvaluation,
102+
value: evaluation,
103+
});
104+
}
105+
99106
if (EvaluationTypeIdentifiers.isDomainServiceEvaluation(evaluation)) {
100107
return modelToTargetLanguage({
101108
type: BitloopsTypesMapping.TDomainServiceEvaluation,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
/**
2+
* Bitloops Language
3+
* Copyright (C) 2022 Bitloops S.A.
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU General Public License as published by
7+
* the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*
18+
* For further information you can contact legal(at)bitloops.com.
19+
*/
20+
21+
import {
22+
TDomainEvaluation,
23+
TValueObjectConstructorEvaluation,
24+
TTargetDependenciesTypeScript,
25+
} from '../../../../../../../types.js';
26+
import { BitloopsTypesMapping } from '../../../../../../../helpers/mappings.js';
27+
import { modelToTargetLanguage } from '../../../../modelToTargetLanguage.js';
28+
import { DomainEvaluationPropsTypeIdentifiers } from '../../../../type-identifiers/domainEvaluationProps.js';
29+
import { getDomainName } from './entityConstructorEvaluation.js';
30+
31+
export const valueObjectConstructorEvaluationToTargetLanguage = (
32+
evaluation: TValueObjectConstructorEvaluation,
33+
): TTargetDependenciesTypeScript => {
34+
const valueObjectEvaluation = evaluation.valueObjectConstructor;
35+
36+
const result = domainEvaluationToTargetLanguage(valueObjectEvaluation);
37+
38+
return result;
39+
};
40+
41+
export const domainEvaluationToTargetLanguage = (
42+
evaluation: TDomainEvaluation,
43+
): TTargetDependenciesTypeScript => {
44+
const domainProperties = evaluation.domainEvaluation.props;
45+
46+
let resultDomainProps: TTargetDependenciesTypeScript;
47+
if (DomainEvaluationPropsTypeIdentifiers.isExpression(domainProperties)) {
48+
resultDomainProps = modelToTargetLanguage({
49+
type: BitloopsTypesMapping.TExpression,
50+
value: domainProperties,
51+
});
52+
} else {
53+
resultDomainProps = modelToTargetLanguage({
54+
type: BitloopsTypesMapping.TEvaluationFields,
55+
value: domainProperties.fields,
56+
});
57+
}
58+
59+
const dependencies = [...resultDomainProps.dependencies];
60+
const domainName = getDomainName(evaluation);
61+
62+
return {
63+
output: `new ${domainName}(${resultDomainProps.output})`,
64+
dependencies,
65+
};
66+
};

0 commit comments

Comments
 (0)