@fornari-lanza/domain-design-language-language 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -0
- package/out/domain-design-language-formatter.d.ts +5 -0
- package/out/domain-design-language-formatter.js +197 -0
- package/out/domain-design-language-formatter.js.map +1 -0
- package/out/domain-design-language-module.d.ts +41 -0
- package/out/domain-design-language-module.js +50 -0
- package/out/domain-design-language-module.js.map +1 -0
- package/out/domain-design-language-scope.d.ts +8 -0
- package/out/domain-design-language-scope.js +79 -0
- package/out/domain-design-language-scope.js.map +1 -0
- package/out/domain-design-language-validator.d.ts +39 -0
- package/out/domain-design-language-validator.js +468 -0
- package/out/domain-design-language-validator.js.map +1 -0
- package/out/generated/ast.d.ts +1393 -0
- package/out/generated/ast.js +1147 -0
- package/out/generated/ast.js.map +1 -0
- package/out/generated/grammar.d.ts +6 -0
- package/out/generated/grammar.js +3430 -0
- package/out/generated/grammar.js.map +1 -0
- package/out/generated/module.d.ts +13 -0
- package/out/generated/module.js +21 -0
- package/out/generated/module.js.map +1 -0
- package/out/index.d.ts +5 -0
- package/out/index.js +6 -0
- package/out/index.js.map +1 -0
- package/package.json +49 -0
- package/src/domain-design-language-formatter.ts +186 -0
- package/src/domain-design-language-module.ts +96 -0
- package/src/domain-design-language-scope.ts +132 -0
- package/src/domain-design-language-validator.ts +699 -0
- package/src/domain-design-language.langium +299 -0
- package/src/generated/ast.ts +1737 -0
- package/src/generated/grammar.ts +3432 -0
- package/src/generated/module.ts +25 -0
- package/src/index.ts +5 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"grammar.js","sourceRoot":"","sources":["../../src/generated/grammar.ts"],"names":[],"mappings":"AAAA;;;gFAGgF;AAGhF,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAE9C,IAAI,iCAAsD,CAAC;AAC3D,MAAM,CAAC,MAAM,2BAA2B,GAAG,GAAY,EAAE,CAAC,iCAAiC,IAAI,CAAC,iCAAiC,GAAG,mBAAmB,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA81GtJ,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/******************************************************************************
|
|
2
|
+
* This file was generated by langium-cli 4.0.0.
|
|
3
|
+
* DO NOT EDIT MANUALLY!
|
|
4
|
+
******************************************************************************/
|
|
5
|
+
import type { LangiumSharedCoreServices, LangiumCoreServices, LangiumGeneratedCoreServices, LangiumGeneratedSharedCoreServices, Module } from 'langium';
|
|
6
|
+
export declare const DomainDesignLanguageLanguageMetaData: {
|
|
7
|
+
readonly languageId: "domain-design-language";
|
|
8
|
+
readonly fileExtensions: readonly [".ddd"];
|
|
9
|
+
readonly caseInsensitive: false;
|
|
10
|
+
readonly mode: "development";
|
|
11
|
+
};
|
|
12
|
+
export declare const DomainDesignLanguageGeneratedSharedModule: Module<LangiumSharedCoreServices, LangiumGeneratedSharedCoreServices>;
|
|
13
|
+
export declare const DomainDesignLanguageGeneratedModule: Module<LangiumCoreServices, LangiumGeneratedCoreServices>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/******************************************************************************
|
|
2
|
+
* This file was generated by langium-cli 4.0.0.
|
|
3
|
+
* DO NOT EDIT MANUALLY!
|
|
4
|
+
******************************************************************************/
|
|
5
|
+
import { DomainDesignLanguageAstReflection } from './ast.js';
|
|
6
|
+
import { DomainDesignLanguageGrammar } from './grammar.js';
|
|
7
|
+
export const DomainDesignLanguageLanguageMetaData = {
|
|
8
|
+
languageId: 'domain-design-language',
|
|
9
|
+
fileExtensions: ['.ddd'],
|
|
10
|
+
caseInsensitive: false,
|
|
11
|
+
mode: 'development'
|
|
12
|
+
};
|
|
13
|
+
export const DomainDesignLanguageGeneratedSharedModule = {
|
|
14
|
+
AstReflection: () => new DomainDesignLanguageAstReflection()
|
|
15
|
+
};
|
|
16
|
+
export const DomainDesignLanguageGeneratedModule = {
|
|
17
|
+
Grammar: () => DomainDesignLanguageGrammar(),
|
|
18
|
+
LanguageMetaData: () => DomainDesignLanguageLanguageMetaData,
|
|
19
|
+
parser: {}
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=module.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module.js","sourceRoot":"","sources":["../../src/generated/module.ts"],"names":[],"mappings":"AAAA;;;gFAGgF;AAGhF,OAAO,EAAE,iCAAiC,EAAE,MAAM,UAAU,CAAC;AAC7D,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AAE3D,MAAM,CAAC,MAAM,oCAAoC,GAAG;IAChD,UAAU,EAAE,wBAAwB;IACpC,cAAc,EAAE,CAAC,MAAM,CAAC;IACxB,eAAe,EAAE,KAAK;IACtB,IAAI,EAAE,aAAa;CACc,CAAC;AAEtC,MAAM,CAAC,MAAM,yCAAyC,GAA0E;IAC5H,aAAa,EAAE,GAAG,EAAE,CAAC,IAAI,iCAAiC,EAAE;CAC/D,CAAC;AAEF,MAAM,CAAC,MAAM,mCAAmC,GAA8D;IAC1G,OAAO,EAAE,GAAG,EAAE,CAAC,2BAA2B,EAAE;IAC5C,gBAAgB,EAAE,GAAG,EAAE,CAAC,oCAAoC;IAC5D,MAAM,EAAE,EAAE;CACb,CAAC"}
|
package/out/index.d.ts
ADDED
package/out/index.js
ADDED
package/out/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,oCAAoC,CAAC;AACnD,cAAc,uCAAuC,CAAC;AACtD,cAAc,oBAAoB,CAAC;AACnC,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@fornari-lanza/domain-design-language-language",
|
|
3
|
+
"description": "The language specific package",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"engines": {
|
|
7
|
+
"node": ">=20.10.0",
|
|
8
|
+
"npm": ">=10.2.3"
|
|
9
|
+
},
|
|
10
|
+
"publishConfig": {
|
|
11
|
+
"access": "public"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"out",
|
|
15
|
+
"src"
|
|
16
|
+
],
|
|
17
|
+
"main": "./out/index.js",
|
|
18
|
+
"module": "./out/index.js",
|
|
19
|
+
"exports": {
|
|
20
|
+
".": {
|
|
21
|
+
"types": "./out/index.d.ts",
|
|
22
|
+
"default": "./out/index.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"typesVersions": {
|
|
26
|
+
"*": {
|
|
27
|
+
".": [
|
|
28
|
+
"out/index"
|
|
29
|
+
]
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"scripts": {
|
|
33
|
+
"clean": "shx rm -fr *.tsbuildinfo out",
|
|
34
|
+
"build": "echo 'No build step'",
|
|
35
|
+
"build:clean": "npm run clean && npm run build",
|
|
36
|
+
"langium:generate": "langium generate",
|
|
37
|
+
"langium:watch": "langium generate --watch"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"langium": "~4.0.0"
|
|
41
|
+
},
|
|
42
|
+
"devDependencies": {
|
|
43
|
+
"langium-cli": "~4.0.0"
|
|
44
|
+
},
|
|
45
|
+
"volta": {
|
|
46
|
+
"node": "20.19.2",
|
|
47
|
+
"npm": "10.8.2"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import type { AstNode } from 'langium';
|
|
2
|
+
import { AbstractFormatter, Formatting } from 'langium/lsp';
|
|
3
|
+
import * as ast from './generated/ast.js';
|
|
4
|
+
|
|
5
|
+
export class DomainDesignLanguageFormatter extends AbstractFormatter {
|
|
6
|
+
protected format(node: AstNode): void {
|
|
7
|
+
const formatter = this.getNodeFormatter(node);
|
|
8
|
+
const bracesOpen = formatter.keyword('{');
|
|
9
|
+
const bracesClose = formatter.keyword('}');
|
|
10
|
+
const bracketsOpen = formatter.keyword('[');
|
|
11
|
+
const bracketsClose = formatter.keyword(']');
|
|
12
|
+
const parenthesisOpen = formatter.keyword('(');
|
|
13
|
+
const parenthesisClose = formatter.keyword(')');
|
|
14
|
+
const comma = formatter.keyword(',');
|
|
15
|
+
bracesOpen.append(Formatting.newLine()).prepend(Formatting.oneSpace());
|
|
16
|
+
bracesClose.surround(Formatting.newLine());
|
|
17
|
+
bracketsOpen.append(Formatting.noSpace());
|
|
18
|
+
bracketsClose.prepend(Formatting.noSpace());
|
|
19
|
+
parenthesisOpen.append(Formatting.noSpace());
|
|
20
|
+
parenthesisClose.prepend(Formatting.noSpace());
|
|
21
|
+
comma.append(Formatting.oneSpace()).prepend(Formatting.noSpace());
|
|
22
|
+
if (ast.isDomainModel(node)) {
|
|
23
|
+
const nodes = formatter.nodes(
|
|
24
|
+
...(node.boundedContext ? [node.boundedContext] : []),
|
|
25
|
+
...(node.contextMap ? [node.contextMap] : []),
|
|
26
|
+
);
|
|
27
|
+
nodes.append(Formatting.noIndent());
|
|
28
|
+
} else if (ast.isBoundedContext(node)) {
|
|
29
|
+
formatter
|
|
30
|
+
.properties(
|
|
31
|
+
'ubiquitousLanguage',
|
|
32
|
+
'aggregates',
|
|
33
|
+
'domainServices',
|
|
34
|
+
'ports',
|
|
35
|
+
'commands',
|
|
36
|
+
'eventStorming',
|
|
37
|
+
)
|
|
38
|
+
.prepend(Formatting.indent());
|
|
39
|
+
formatter.property('description').prepend(Formatting.indent());
|
|
40
|
+
} else if (ast.isUbiquitousLanguageDeclaration(node)) {
|
|
41
|
+
formatter.properties('terms').prepend(Formatting.indent());
|
|
42
|
+
} else if (ast.isTerm(node)) {
|
|
43
|
+
formatter
|
|
44
|
+
.keywords('definition:', 'aliases:')
|
|
45
|
+
.prepend(Formatting.indent())
|
|
46
|
+
.append(Formatting.oneSpace());
|
|
47
|
+
} else if (ast.isContextMap(node)) {
|
|
48
|
+
formatter.keyword('ContextMap').append(Formatting.oneSpace());
|
|
49
|
+
formatter.properties('relationships').prepend(Formatting.indent());
|
|
50
|
+
} else if (ast.isAsymmetricRelationship(node)) {
|
|
51
|
+
formatter
|
|
52
|
+
.keywords('upstream:', 'downstream:')
|
|
53
|
+
.prepend(Formatting.indent())
|
|
54
|
+
.append(Formatting.oneSpace());
|
|
55
|
+
formatter
|
|
56
|
+
.properties('customerSupplier', 'description')
|
|
57
|
+
.prepend(Formatting.indent());
|
|
58
|
+
} else if (ast.isSymmetricRelationship(node)) {
|
|
59
|
+
formatter.keyword('Relationship').append(Formatting.oneSpace());
|
|
60
|
+
formatter
|
|
61
|
+
.keywords('between')
|
|
62
|
+
.prepend(Formatting.indent())
|
|
63
|
+
.append(Formatting.oneSpace());
|
|
64
|
+
formatter.keyword('and').surround(Formatting.oneSpace());
|
|
65
|
+
formatter.properties('type', 'description').prepend(Formatting.indent());
|
|
66
|
+
} else if (ast.isAggregateRoot(node)) {
|
|
67
|
+
formatter.keyword('AggregateRoot').append(Formatting.oneSpace());
|
|
68
|
+
formatter
|
|
69
|
+
.keywords('enforcedInvariants:', 'correctivePolicies:')
|
|
70
|
+
.prepend(Formatting.indent())
|
|
71
|
+
.append(Formatting.oneSpace());
|
|
72
|
+
formatter
|
|
73
|
+
.properties(
|
|
74
|
+
'id',
|
|
75
|
+
'attributes',
|
|
76
|
+
'events',
|
|
77
|
+
'description',
|
|
78
|
+
'methods',
|
|
79
|
+
'exceptions',
|
|
80
|
+
)
|
|
81
|
+
.prepend(Formatting.indent());
|
|
82
|
+
} else if (ast.isUID(node)) {
|
|
83
|
+
formatter
|
|
84
|
+
.keywords('type:', 'enforcedInvariants:')
|
|
85
|
+
.prepend(Formatting.indent())
|
|
86
|
+
.append(Formatting.oneSpace());
|
|
87
|
+
} else if (ast.isValueObject(node)) {
|
|
88
|
+
formatter.keyword('ValueObject').append(Formatting.oneSpace());
|
|
89
|
+
formatter
|
|
90
|
+
.properties('attributes', 'description')
|
|
91
|
+
.prepend(Formatting.indent());
|
|
92
|
+
formatter
|
|
93
|
+
.keywords('enforcedInvariants:')
|
|
94
|
+
.prepend(Formatting.indent())
|
|
95
|
+
.append(Formatting.oneSpace());
|
|
96
|
+
} else if (ast.isPrimitiveAttribute(node) || ast.isDomainAttribute(node)) {
|
|
97
|
+
formatter
|
|
98
|
+
.keyword(':')
|
|
99
|
+
.append(Formatting.oneSpace())
|
|
100
|
+
.prepend(Formatting.noSpace());
|
|
101
|
+
formatter.properties('many', 'optional').append(Formatting.oneSpace());
|
|
102
|
+
} else if (ast.isAggregateAttribute(node) || ast.isEntityAttribute(node)) {
|
|
103
|
+
formatter.properties('many', 'optional').append(Formatting.oneSpace());
|
|
104
|
+
} else if (ast.isEntity(node)) {
|
|
105
|
+
formatter.keyword('Entity').append(Formatting.oneSpace());
|
|
106
|
+
formatter.properties('id', 'attributes').prepend(Formatting.indent());
|
|
107
|
+
formatter.property('description').prepend(Formatting.indent());
|
|
108
|
+
} else if (ast.isDomainEventsDeclaration(node)) {
|
|
109
|
+
formatter.properties('events').prepend(Formatting.indent());
|
|
110
|
+
formatter.keyword('DomainEvents').append(Formatting.oneSpace());
|
|
111
|
+
} else if (ast.isDomainEvent(node)) {
|
|
112
|
+
formatter.property('name').append(Formatting.oneSpace());
|
|
113
|
+
formatter.property('description').prepend(Formatting.indent());
|
|
114
|
+
formatter.property('payload').prepend(Formatting.indent());
|
|
115
|
+
} else if (ast.isPayload(node)) {
|
|
116
|
+
formatter.properties('attributes').prepend(Formatting.indent());
|
|
117
|
+
} else if (ast.isDomainService(node) || ast.isCommand(node)) {
|
|
118
|
+
formatter.property('name').prepend(Formatting.oneSpace());
|
|
119
|
+
formatter.property('description').prepend(Formatting.indent());
|
|
120
|
+
formatter
|
|
121
|
+
.keywords('type:', 'uses', 'emits', 'dependencies:')
|
|
122
|
+
.prepend(Formatting.indent())
|
|
123
|
+
.append(Formatting.oneSpace());
|
|
124
|
+
formatter.properties('input', 'response').prepend(Formatting.indent());
|
|
125
|
+
} else if (
|
|
126
|
+
ast.isDomainServiceInput(node) ||
|
|
127
|
+
ast.isDomainServiceResponse(node) ||
|
|
128
|
+
ast.isInputDTO(node) ||
|
|
129
|
+
ast.isResponseDTO(node)
|
|
130
|
+
) {
|
|
131
|
+
formatter.properties('attributes').prepend(Formatting.indent());
|
|
132
|
+
} else if (ast.isPort(node)) {
|
|
133
|
+
formatter.keyword('Port').append(Formatting.oneSpace());
|
|
134
|
+
formatter.property('description').prepend(Formatting.indent());
|
|
135
|
+
} else if (ast.isEventStormingDeclaration(node)) {
|
|
136
|
+
formatter.keyword('EventStorming').append(Formatting.oneSpace());
|
|
137
|
+
formatter.properties('elements', 'flows').prepend(Formatting.indent());
|
|
138
|
+
} else if (ast.isEventStormingElement(node)) {
|
|
139
|
+
formatter.property('name').surround(Formatting.oneSpace());
|
|
140
|
+
formatter.property('description').prepend(Formatting.indent());
|
|
141
|
+
} else if (ast.isProcessFlow(node)) {
|
|
142
|
+
formatter.keyword('ProcessFlow').append(Formatting.oneSpace());
|
|
143
|
+
formatter.property('description').prepend(Formatting.indent());
|
|
144
|
+
formatter
|
|
145
|
+
.properties('given', 'command', 'reactions')
|
|
146
|
+
.prepend(Formatting.indent());
|
|
147
|
+
} else if (ast.isGivenStep(node)) {
|
|
148
|
+
formatter.keyword('given').append(Formatting.oneSpace());
|
|
149
|
+
formatter.keyword('views').surround(Formatting.oneSpace());
|
|
150
|
+
} else if (ast.isActorCommandStep(node)) {
|
|
151
|
+
formatter.keyword('issues').surround(Formatting.oneSpace());
|
|
152
|
+
} else if (ast.isReactionStep(node)) {
|
|
153
|
+
formatter.keywords('on').append(Formatting.oneSpace());
|
|
154
|
+
formatter.keyword('then').surround(Formatting.oneSpace());
|
|
155
|
+
formatter.properties('outcomes').prepend(Formatting.indent());
|
|
156
|
+
} else if (ast.isProjection(node)) {
|
|
157
|
+
formatter.keyword('projects').append(Formatting.oneSpace());
|
|
158
|
+
formatter.keywords('to', 'hotspot').surround(Formatting.oneSpace());
|
|
159
|
+
} else if (ast.isPolicyTrigger(node)) {
|
|
160
|
+
formatter.keyword('triggers').append(Formatting.oneSpace());
|
|
161
|
+
formatter.keyword('hotspot').prepend(Formatting.indent());
|
|
162
|
+
} else if (ast.isPolicy(node)) {
|
|
163
|
+
formatter.keyword('Policy').append(Formatting.oneSpace());
|
|
164
|
+
formatter.property('description').prepend(Formatting.indent());
|
|
165
|
+
formatter
|
|
166
|
+
.keywords('invokes')
|
|
167
|
+
.prepend(Formatting.indent())
|
|
168
|
+
.append(Formatting.oneSpace());
|
|
169
|
+
formatter.keywords('on').surround(Formatting.oneSpace());
|
|
170
|
+
} else if (ast.isMethod(node)) {
|
|
171
|
+
formatter.property('name').append(Formatting.noSpace());
|
|
172
|
+
formatter.keywords('(', ')').surround(Formatting.noSpace());
|
|
173
|
+
formatter
|
|
174
|
+
.properties('description')
|
|
175
|
+
.prepend(Formatting.indent());
|
|
176
|
+
} else if (ast.isMethodsDeclaration(node)) {
|
|
177
|
+
formatter.properties('methods').prepend(Formatting.indent());
|
|
178
|
+
formatter.keyword('Methods').append(Formatting.oneSpace());
|
|
179
|
+
} else if (ast.isExceptionsDeclaration(node)) {
|
|
180
|
+
formatter.properties('exceptions').prepend(Formatting.indent());
|
|
181
|
+
formatter.keyword('DomainExceptions').append(Formatting.oneSpace());
|
|
182
|
+
} else if (ast.isDomainException(node)) {
|
|
183
|
+
formatter.property('name').append(Formatting.oneSpace());
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { type Module, inject } from 'langium';
|
|
2
|
+
import {
|
|
3
|
+
createDefaultModule,
|
|
4
|
+
createDefaultSharedModule,
|
|
5
|
+
type DefaultSharedModuleContext,
|
|
6
|
+
type LangiumServices,
|
|
7
|
+
type LangiumSharedServices,
|
|
8
|
+
type PartialLangiumServices,
|
|
9
|
+
} from 'langium/lsp';
|
|
10
|
+
import {
|
|
11
|
+
DomainDesignLanguageGeneratedModule,
|
|
12
|
+
DomainDesignLanguageGeneratedSharedModule,
|
|
13
|
+
} from './generated/module.js';
|
|
14
|
+
import {
|
|
15
|
+
DomainDesignLanguageValidator,
|
|
16
|
+
registerValidationChecks,
|
|
17
|
+
} from './domain-design-language-validator.js';
|
|
18
|
+
import { DomainDesignLanguageFormatter } from './domain-design-language-formatter.js';
|
|
19
|
+
import { DomainDesignLanguageScopeProvider } from './domain-design-language-scope.js';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Declaration of custom services - add your own service classes here.
|
|
23
|
+
*/
|
|
24
|
+
export type DomainDesignLanguageAddedServices = {
|
|
25
|
+
validation: {
|
|
26
|
+
DomainDesignLanguageValidator: DomainDesignLanguageValidator;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Union of Langium default services and your custom services - use this as constructor parameter
|
|
32
|
+
* of custom service classes.
|
|
33
|
+
*/
|
|
34
|
+
export type DomainDesignLanguageServices = LangiumServices &
|
|
35
|
+
DomainDesignLanguageAddedServices;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Dependency injection module that overrides Langium default services and contributes the
|
|
39
|
+
* declared custom services. The Langium defaults can be partially specified to override only
|
|
40
|
+
* selected services, while the custom services must be fully specified.
|
|
41
|
+
*/
|
|
42
|
+
export const DomainDesignLanguageModule: Module<
|
|
43
|
+
DomainDesignLanguageServices,
|
|
44
|
+
PartialLangiumServices & DomainDesignLanguageAddedServices
|
|
45
|
+
> = {
|
|
46
|
+
validation: {
|
|
47
|
+
DomainDesignLanguageValidator: () => new DomainDesignLanguageValidator(),
|
|
48
|
+
},
|
|
49
|
+
lsp: {
|
|
50
|
+
Formatter: () => new DomainDesignLanguageFormatter(),
|
|
51
|
+
},
|
|
52
|
+
references: {
|
|
53
|
+
ScopeProvider: (services) =>
|
|
54
|
+
new DomainDesignLanguageScopeProvider(services),
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Create the full set of services required by Langium.
|
|
60
|
+
*
|
|
61
|
+
* First inject the shared services by merging two modules:
|
|
62
|
+
* - Langium default shared services
|
|
63
|
+
* - Services generated by langium-cli
|
|
64
|
+
*
|
|
65
|
+
* Then inject the language-specific services by merging three modules:
|
|
66
|
+
* - Langium default language-specific services
|
|
67
|
+
* - Services generated by langium-cli
|
|
68
|
+
* - Services specified in this file
|
|
69
|
+
*
|
|
70
|
+
* @param context Optional module context with the LSP connection
|
|
71
|
+
* @returns An object wrapping the shared services and the language-specific services
|
|
72
|
+
*/
|
|
73
|
+
export function createDomainDesignLanguageServices(
|
|
74
|
+
context: DefaultSharedModuleContext,
|
|
75
|
+
): {
|
|
76
|
+
shared: LangiumSharedServices;
|
|
77
|
+
DomainDesignLanguage: DomainDesignLanguageServices;
|
|
78
|
+
} {
|
|
79
|
+
const shared = inject(
|
|
80
|
+
createDefaultSharedModule(context),
|
|
81
|
+
DomainDesignLanguageGeneratedSharedModule,
|
|
82
|
+
);
|
|
83
|
+
const DomainDesignLanguage = inject(
|
|
84
|
+
createDefaultModule({ shared }),
|
|
85
|
+
DomainDesignLanguageGeneratedModule,
|
|
86
|
+
DomainDesignLanguageModule,
|
|
87
|
+
);
|
|
88
|
+
shared.ServiceRegistry.register(DomainDesignLanguage);
|
|
89
|
+
registerValidationChecks(DomainDesignLanguage);
|
|
90
|
+
if (!context.connection) {
|
|
91
|
+
// We don't run inside a language server
|
|
92
|
+
// Therefore, initialize the configuration provider instantly
|
|
93
|
+
shared.workspace.ConfigurationProvider.initialized({});
|
|
94
|
+
}
|
|
95
|
+
return { shared, DomainDesignLanguage };
|
|
96
|
+
}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import {
|
|
2
|
+
AstNode,
|
|
3
|
+
AstNodeDescription,
|
|
4
|
+
DefaultScopeProvider,
|
|
5
|
+
ReferenceInfo,
|
|
6
|
+
Scope,
|
|
7
|
+
URI,
|
|
8
|
+
} from 'langium';
|
|
9
|
+
import {
|
|
10
|
+
BoundedContext,
|
|
11
|
+
DomainEvent,
|
|
12
|
+
isCommand,
|
|
13
|
+
isAsymmetricRelationship,
|
|
14
|
+
isBoundedContext,
|
|
15
|
+
isDomainAttribute,
|
|
16
|
+
isEntity,
|
|
17
|
+
isPolicyTrigger,
|
|
18
|
+
isProcessFlow,
|
|
19
|
+
isReactionStep,
|
|
20
|
+
isSymmetricRelationship,
|
|
21
|
+
isValueObject,
|
|
22
|
+
ProcessFlow,
|
|
23
|
+
} from './generated/ast.js';
|
|
24
|
+
import { glob } from 'glob';
|
|
25
|
+
|
|
26
|
+
export class DomainDesignLanguageScopeProvider extends DefaultScopeProvider {
|
|
27
|
+
override getScope(context: ReferenceInfo): Scope {
|
|
28
|
+
if (isDomainAttribute(context.container) && context.property === 'type')
|
|
29
|
+
return this.getScopeForDomainAttribute(context);
|
|
30
|
+
if (
|
|
31
|
+
(isCommand(context.container) && context.property === 'events') ||
|
|
32
|
+
(isReactionStep(context.container) && context.property === 'trigger')
|
|
33
|
+
)
|
|
34
|
+
return this.getScopeForDomainEvents(context);
|
|
35
|
+
if (
|
|
36
|
+
isAsymmetricRelationship(context.container) &&
|
|
37
|
+
(context.property === 'upstream' || context.property === 'downstream')
|
|
38
|
+
)
|
|
39
|
+
return this.getBoundedContextsFromGlobalScope();
|
|
40
|
+
if (
|
|
41
|
+
isSymmetricRelationship(context.container) &&
|
|
42
|
+
(context.property === 'participant1' ||
|
|
43
|
+
context.property === 'participant2')
|
|
44
|
+
)
|
|
45
|
+
return this.getBoundedContextsFromGlobalScope();
|
|
46
|
+
return super.getScope(context);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
private searchParent<T extends AstNode>(
|
|
50
|
+
context: ReferenceInfo,
|
|
51
|
+
predicate: (node: AstNode) => boolean,
|
|
52
|
+
): T | undefined {
|
|
53
|
+
let node = context.container;
|
|
54
|
+
while (node.$container && !predicate(node)) node = node.$container;
|
|
55
|
+
return predicate(node) ? (node as T) : undefined;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
private getBoundedContextsFromGlobalScope(): Scope {
|
|
59
|
+
const files = glob.sync('./boundedContexts/*.ddd', { absolute: true });
|
|
60
|
+
const uris = new Set<string>();
|
|
61
|
+
for (const filePath of files) uris.add(URI.file(filePath).toString());
|
|
62
|
+
const astNodeDescriptions = this.indexManager
|
|
63
|
+
.allElements('BoundedContext', uris)
|
|
64
|
+
.toArray();
|
|
65
|
+
return this.createScope(astNodeDescriptions);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private getScopeForDomainAttribute(context: ReferenceInfo): Scope {
|
|
69
|
+
const boundedContext = this.searchParent<BoundedContext>(
|
|
70
|
+
context,
|
|
71
|
+
isBoundedContext,
|
|
72
|
+
);
|
|
73
|
+
const validReferences = new Set<AstNodeDescription>();
|
|
74
|
+
if (boundedContext) {
|
|
75
|
+
boundedContext.aggregates.forEach((aggregate) => {
|
|
76
|
+
validReferences.add(
|
|
77
|
+
this.descriptions.createDescription(aggregate, aggregate.name),
|
|
78
|
+
);
|
|
79
|
+
aggregate.attributes.forEach((attr) => {
|
|
80
|
+
if (isValueObject(attr.type) || isEntity(attr.type))
|
|
81
|
+
validReferences.add(
|
|
82
|
+
this.descriptions.createDescription(
|
|
83
|
+
attr.type,
|
|
84
|
+
`${aggregate.name}.${attr.type.name}`,
|
|
85
|
+
),
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
return this.createScope(validReferences);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
private getScopeForDomainEvents(context: ReferenceInfo): Scope {
|
|
94
|
+
const validReferences = new Set<AstNodeDescription>();
|
|
95
|
+
if (isReactionStep(context.container)) {
|
|
96
|
+
const isFirstReactionStep = context.container.$containerIndex === 0;
|
|
97
|
+
const flow = this.searchParent<ProcessFlow>(context, isProcessFlow);
|
|
98
|
+
const events: DomainEvent[] = [];
|
|
99
|
+
if (isFirstReactionStep) {
|
|
100
|
+
events.push(
|
|
101
|
+
...(flow?.command.command.ref?.events.map((e) => e.ref) ?? []).filter(
|
|
102
|
+
(e): e is DomainEvent => !!e,
|
|
103
|
+
),
|
|
104
|
+
);
|
|
105
|
+
} else {
|
|
106
|
+
const policyEvents =
|
|
107
|
+
flow?.reactions[
|
|
108
|
+
(context.container.$containerIndex ?? 1) - 1
|
|
109
|
+
].outcomes.flatMap((o) =>
|
|
110
|
+
isPolicyTrigger(o) && o.policy.command.ref?.events
|
|
111
|
+
? o.policy.command.ref?.events
|
|
112
|
+
.map((e) => e.ref)
|
|
113
|
+
.filter((e): e is DomainEvent => !!e)
|
|
114
|
+
: [],
|
|
115
|
+
) ?? [];
|
|
116
|
+
events.push(...policyEvents);
|
|
117
|
+
}
|
|
118
|
+
events.forEach((event) => {
|
|
119
|
+
validReferences.add(
|
|
120
|
+
this.descriptions.createDescription(event, event.name),
|
|
121
|
+
);
|
|
122
|
+
});
|
|
123
|
+
} else if (isCommand(context.container)) {
|
|
124
|
+
context.container.aggregate.ref?.events?.events.forEach((event) => {
|
|
125
|
+
validReferences.add(
|
|
126
|
+
this.descriptions.createDescription(event, event.name),
|
|
127
|
+
);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
return this.createScope(validReferences);
|
|
131
|
+
}
|
|
132
|
+
}
|