@likec4/language-server 1.17.1 → 1.19.0
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/contrib/likec4.tmLanguage.json +1 -1
- package/dist/LikeC4FileSystem.d.ts +13 -0
- package/dist/LikeC4FileSystem.js +27 -0
- package/dist/Rpc.d.ts +9 -0
- package/dist/Rpc.js +126 -0
- package/dist/ast.d.ts +200 -0
- package/dist/ast.js +276 -0
- package/dist/browser.d.ts +6 -20
- package/dist/browser.js +13 -0
- package/dist/formatting/LikeC4Formatter.d.ts +27 -0
- package/dist/formatting/LikeC4Formatter.js +261 -0
- package/dist/formatting/utils.d.ts +6 -0
- package/dist/formatting/utils.js +15 -0
- package/dist/generated/ast.d.ts +1242 -0
- package/dist/generated/ast.js +1945 -0
- package/dist/generated/grammar.d.ts +6 -0
- package/dist/generated/grammar.js +3 -0
- package/dist/generated/module.d.ts +9 -0
- package/dist/generated/module.js +23 -0
- package/dist/generated-lib/icons.d.ts +1 -0
- package/dist/{likec4lib.mjs → generated-lib/icons.js} +1 -6
- package/dist/index.d.ts +8 -31
- package/dist/index.js +13 -0
- package/dist/like-c4.langium +845 -0
- package/dist/likec4lib.d.ts +4 -6
- package/dist/likec4lib.js +4 -0
- package/dist/logger.d.ts +7 -0
- package/dist/logger.js +73 -0
- package/dist/lsp/CodeLensProvider.d.ts +9 -0
- package/dist/lsp/CodeLensProvider.js +40 -0
- package/dist/lsp/CompletionProvider.d.ts +6 -0
- package/dist/lsp/CompletionProvider.js +135 -0
- package/dist/lsp/DocumentHighlightProvider.d.ts +9 -0
- package/dist/lsp/DocumentHighlightProvider.js +10 -0
- package/dist/lsp/DocumentLinkProvider.d.ts +11 -0
- package/dist/lsp/DocumentLinkProvider.js +49 -0
- package/dist/lsp/DocumentSymbolProvider.d.ts +23 -0
- package/dist/lsp/DocumentSymbolProvider.js +202 -0
- package/dist/lsp/HoverProvider.d.ts +10 -0
- package/dist/lsp/HoverProvider.js +69 -0
- package/dist/lsp/RenameProvider.d.ts +5 -0
- package/dist/lsp/RenameProvider.js +6 -0
- package/dist/lsp/SemanticTokenProvider.d.ts +7 -0
- package/dist/lsp/SemanticTokenProvider.js +297 -0
- package/dist/lsp/index.d.ts +7 -0
- package/dist/lsp/index.js +7 -0
- package/dist/model/deployments-index.d.ts +60 -0
- package/dist/model/deployments-index.js +181 -0
- package/dist/model/fqn-computation.d.ts +3 -0
- package/dist/model/fqn-computation.js +72 -0
- package/dist/model/fqn-index.d.ts +25 -0
- package/dist/model/fqn-index.js +96 -0
- package/dist/model/index.d.ts +6 -0
- package/dist/model/index.js +6 -0
- package/dist/model/model-builder.d.ts +32 -0
- package/dist/model/model-builder.js +598 -0
- package/dist/model/model-locator.d.ts +23 -0
- package/dist/model/model-locator.js +126 -0
- package/dist/model/model-parser-where.d.ts +3 -0
- package/dist/model/model-parser-where.js +70 -0
- package/dist/model/model-parser.d.ts +292 -0
- package/dist/model/model-parser.js +72 -0
- package/dist/model/parser/Base.d.ts +28 -0
- package/dist/model/parser/Base.js +87 -0
- package/dist/model/parser/DeploymentModelParser.d.ts +33 -0
- package/dist/model/parser/DeploymentModelParser.js +162 -0
- package/dist/model/parser/DeploymentViewParser.d.ts +38 -0
- package/dist/model/parser/DeploymentViewParser.js +98 -0
- package/dist/model/parser/FqnRefParser.d.ts +29 -0
- package/dist/model/parser/FqnRefParser.js +108 -0
- package/dist/model/parser/GlobalsParser.d.ts +66 -0
- package/dist/model/parser/GlobalsParser.js +80 -0
- package/dist/model/parser/ModelParser.d.ts +27 -0
- package/dist/model/parser/ModelParser.js +122 -0
- package/dist/model/parser/PredicatesParser.d.ts +34 -0
- package/dist/model/parser/PredicatesParser.js +272 -0
- package/dist/model/parser/SpecificationParser.d.ts +27 -0
- package/dist/model/parser/SpecificationParser.js +120 -0
- package/dist/model/parser/ViewsParser.d.ts +64 -0
- package/dist/model/parser/ViewsParser.js +377 -0
- package/dist/model-change/ModelChanges.d.ts +15 -0
- package/dist/model-change/ModelChanges.js +89 -0
- package/dist/model-change/changeElementStyle.d.ts +16 -0
- package/dist/model-change/changeElementStyle.js +136 -0
- package/dist/model-change/changeViewLayout.d.ts +12 -0
- package/dist/model-change/changeViewLayout.js +32 -0
- package/dist/model-change/saveManualLayout.d.ts +11 -0
- package/dist/model-change/saveManualLayout.js +27 -0
- package/dist/module.d.ts +62 -0
- package/dist/module.js +123 -0
- package/dist/protocol.d.ts +27 -27
- package/dist/protocol.js +14 -0
- package/dist/references/index.d.ts +3 -0
- package/dist/references/index.js +3 -0
- package/dist/references/name-provider.d.ts +9 -0
- package/dist/references/name-provider.js +33 -0
- package/dist/references/scope-computation.d.ts +20 -0
- package/dist/references/scope-computation.js +281 -0
- package/dist/references/scope-provider.d.ts +16 -0
- package/dist/references/scope-provider.js +165 -0
- package/dist/shared/NodeKindProvider.d.ts +15 -0
- package/dist/shared/NodeKindProvider.js +108 -0
- package/dist/shared/WorkspaceManager.d.ts +18 -0
- package/dist/shared/WorkspaceManager.js +36 -0
- package/dist/shared/WorkspaceSymbolProvider.d.ts +3 -0
- package/dist/shared/WorkspaceSymbolProvider.js +3 -0
- package/dist/shared/index.d.ts +3 -0
- package/dist/shared/index.js +3 -0
- package/dist/test/index.d.ts +1 -0
- package/dist/test/index.js +1 -0
- package/dist/test/setup.d.ts +1 -0
- package/dist/test/setup.js +7 -0
- package/dist/test/testServices.d.ts +22 -0
- package/dist/test/testServices.js +119 -0
- package/dist/utils/elementRef.d.ts +11 -0
- package/dist/utils/elementRef.js +15 -0
- package/dist/utils/fqnRef.d.ts +8 -0
- package/dist/utils/fqnRef.js +46 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/printDocs.d.ts +2 -0
- package/dist/utils/printDocs.js +1 -0
- package/dist/utils/stringHash.d.ts +1 -0
- package/dist/utils/stringHash.js +5 -0
- package/dist/validation/_shared.d.ts +3 -0
- package/dist/validation/_shared.js +22 -0
- package/dist/validation/deployment-checks.d.ts +6 -0
- package/dist/validation/deployment-checks.js +114 -0
- package/dist/validation/dynamic-view-rule.d.ts +4 -0
- package/dist/validation/dynamic-view-rule.js +16 -0
- package/dist/validation/dynamic-view-step.d.ts +4 -0
- package/dist/validation/dynamic-view-step.js +33 -0
- package/dist/validation/element.d.ts +4 -0
- package/dist/validation/element.js +49 -0
- package/dist/validation/index.d.ts +15 -0
- package/dist/validation/index.js +152 -0
- package/dist/validation/property-checks.d.ts +6 -0
- package/dist/validation/property-checks.js +38 -0
- package/dist/validation/relation.d.ts +5 -0
- package/dist/validation/relation.js +56 -0
- package/dist/validation/specification.d.ts +11 -0
- package/dist/validation/specification.js +136 -0
- package/dist/validation/view-predicates/element-with.d.ts +4 -0
- package/dist/validation/view-predicates/element-with.js +30 -0
- package/dist/validation/view-predicates/expanded-element.d.ts +4 -0
- package/dist/validation/view-predicates/expanded-element.js +11 -0
- package/dist/validation/view-predicates/expression-v2.d.ts +5 -0
- package/dist/validation/view-predicates/expression-v2.js +83 -0
- package/dist/validation/view-predicates/incoming.d.ts +4 -0
- package/dist/validation/view-predicates/incoming.js +15 -0
- package/dist/validation/view-predicates/index.d.ts +6 -0
- package/dist/validation/view-predicates/index.js +6 -0
- package/dist/validation/view-predicates/outgoing.d.ts +4 -0
- package/dist/validation/view-predicates/outgoing.js +15 -0
- package/dist/validation/view-predicates/relation-with.d.ts +4 -0
- package/dist/validation/view-predicates/relation-with.js +12 -0
- package/dist/validation/view.d.ts +4 -0
- package/dist/validation/view.js +23 -0
- package/dist/view-utils/assignNavigateTo.d.ts +2 -0
- package/dist/view-utils/assignNavigateTo.js +25 -0
- package/dist/view-utils/index.d.ts +2 -0
- package/dist/view-utils/index.js +2 -0
- package/dist/view-utils/manual-layout.d.ts +7 -0
- package/dist/view-utils/manual-layout.js +99 -0
- package/dist/view-utils/resolve-relative-paths.d.ts +2 -0
- package/dist/view-utils/resolve-relative-paths.js +78 -0
- package/package.json +42 -73
- package/src/LikeC4FileSystem.ts +22 -21
- package/src/Rpc.ts +6 -3
- package/src/ast.ts +136 -172
- package/src/browser.ts +10 -11
- package/src/generated/ast.ts +656 -40
- package/src/generated/grammar.ts +1 -1
- package/src/index.ts +11 -8
- package/src/like-c4.langium +173 -22
- package/src/logger.ts +41 -57
- package/src/lsp/CodeLensProvider.ts +0 -1
- package/src/lsp/CompletionProvider.ts +20 -5
- package/src/lsp/DocumentSymbolProvider.ts +5 -2
- package/src/lsp/HoverProvider.ts +37 -3
- package/src/lsp/SemanticTokenProvider.ts +58 -32
- package/src/model/deployments-index.ts +222 -0
- package/src/model/fqn-computation.ts +1 -1
- package/src/model/fqn-index.ts +0 -1
- package/src/model/index.ts +1 -0
- package/src/model/model-builder.ts +176 -39
- package/src/model/model-locator.ts +36 -7
- package/src/model/model-parser.ts +69 -1119
- package/src/model/parser/Base.ts +107 -0
- package/src/model/parser/DeploymentModelParser.ts +192 -0
- package/src/model/parser/DeploymentViewParser.ts +116 -0
- package/src/model/parser/FqnRefParser.ts +118 -0
- package/src/model/parser/GlobalsParser.ts +96 -0
- package/src/model/parser/ModelParser.ts +141 -0
- package/src/model/parser/PredicatesParser.ts +291 -0
- package/src/model/parser/SpecificationParser.ts +133 -0
- package/src/model/parser/ViewsParser.ts +428 -0
- package/src/model-change/changeViewLayout.ts +2 -2
- package/src/module.ts +26 -21
- package/src/protocol.ts +10 -6
- package/src/references/index.ts +1 -0
- package/src/references/name-provider.ts +37 -0
- package/src/references/scope-computation.ts +130 -21
- package/src/references/scope-provider.ts +68 -35
- package/src/shared/NodeKindProvider.ts +15 -3
- package/src/{elementRef.ts → utils/elementRef.ts} +1 -1
- package/src/utils/fqnRef.ts +56 -0
- package/src/utils/stringHash.ts +2 -2
- package/src/validation/_shared.ts +6 -5
- package/src/validation/deployment-checks.ts +131 -0
- package/src/validation/dynamic-view-step.ts +1 -1
- package/src/validation/index.ts +104 -6
- package/src/validation/relation.ts +1 -1
- package/src/validation/view-predicates/expression-v2.ts +101 -0
- package/src/validation/view-predicates/index.ts +1 -0
- package/src/view-utils/assignNavigateTo.ts +6 -5
- package/src/view-utils/index.ts +0 -1
- package/src/view-utils/manual-layout.ts +25 -0
- package/dist/browser.cjs +0 -25
- package/dist/browser.d.cts +0 -23
- package/dist/browser.d.mts +0 -23
- package/dist/browser.mjs +0 -20
- package/dist/index.cjs +0 -53
- package/dist/index.d.cts +0 -34
- package/dist/index.d.mts +0 -34
- package/dist/index.mjs +0 -46
- package/dist/likec4lib.cjs +0 -1546
- package/dist/likec4lib.d.cts +0 -6
- package/dist/likec4lib.d.mts +0 -6
- package/dist/model-graph/index.cjs +0 -10
- package/dist/model-graph/index.d.cts +0 -81
- package/dist/model-graph/index.d.mts +0 -81
- package/dist/model-graph/index.d.ts +0 -81
- package/dist/model-graph/index.mjs +0 -1
- package/dist/protocol.cjs +0 -25
- package/dist/protocol.d.cts +0 -45
- package/dist/protocol.d.mts +0 -45
- package/dist/protocol.mjs +0 -17
- package/dist/shared/language-server.BIbAD1T-.mjs +0 -6292
- package/dist/shared/language-server.BQRvVmE0.d.cts +0 -1303
- package/dist/shared/language-server.BysPcTxr.d.ts +0 -1303
- package/dist/shared/language-server.D2QdbOJO.cjs +0 -1995
- package/dist/shared/language-server.DGrBGmsd.mjs +0 -1981
- package/dist/shared/language-server.DKV_FdPN.cjs +0 -6304
- package/dist/shared/language-server._wkyPgso.d.mts +0 -1303
- package/src/model-graph/LikeC4ModelGraph.ts +0 -338
- package/src/model-graph/compute-view/__test__/fixture.ts +0 -630
- package/src/model-graph/compute-view/compute.ts +0 -788
- package/src/model-graph/compute-view/index.ts +0 -33
- package/src/model-graph/compute-view/predicates.ts +0 -509
- package/src/model-graph/dynamic-view/__test__/fixture.ts +0 -61
- package/src/model-graph/dynamic-view/compute.ts +0 -313
- package/src/model-graph/dynamic-view/index.ts +0 -29
- package/src/model-graph/index.ts +0 -3
- package/src/model-graph/utils/applyCustomElementProperties.ts +0 -65
- package/src/model-graph/utils/applyCustomRelationProperties.ts +0 -41
- package/src/model-graph/utils/applyViewRuleStyles.ts +0 -49
- package/src/model-graph/utils/buildComputeNodes.ts +0 -113
- package/src/model-graph/utils/buildElementNotations.ts +0 -63
- package/src/model-graph/utils/elementExpressionToPredicate.ts +0 -39
- package/src/model-graph/utils/relationExpressionToPredicates.ts +0 -43
- package/src/model-graph/utils/sortNodes.ts +0 -105
- package/src/model-graph/utils/uniqueTags.test.ts +0 -42
- package/src/model-graph/utils/uniqueTags.ts +0 -19
- package/src/utils/graphlib.ts +0 -9
- package/src/view-utils/resolve-extended-views.ts +0 -66
- package/src/view-utils/resolve-global-rules.ts +0 -88
- package/src/view-utils/view-hash.ts +0 -27
|
@@ -6,21 +6,38 @@ import {
|
|
|
6
6
|
MultiMap,
|
|
7
7
|
type PrecomputedScopes
|
|
8
8
|
} from 'langium'
|
|
9
|
-
import { isNullish, isTruthy } from 'remeda'
|
|
9
|
+
import { entries, filter, flatMap, forEach, forEachObj, groupBy, isNullish, isTruthy, pipe } from 'remeda'
|
|
10
10
|
import type { CancellationToken } from 'vscode-languageserver'
|
|
11
11
|
import { ast, type LikeC4LangiumDocument } from '../ast'
|
|
12
|
-
import { logError } from '../logger'
|
|
12
|
+
import { logError, logWarnError } from '../logger'
|
|
13
|
+
import type { LikeC4Services } from '../module'
|
|
13
14
|
|
|
14
15
|
type ElementsContainer = ast.Model | ast.ElementBody | ast.ExtendElementBody
|
|
16
|
+
type DeploymentsContainer = ast.ModelDeployments | ast.DeploymentNodeBody
|
|
17
|
+
|
|
18
|
+
function uniqueDescriptions(
|
|
19
|
+
descs: AstNodeDescription[]
|
|
20
|
+
): AstNodeDescription[] {
|
|
21
|
+
return pipe(
|
|
22
|
+
descs,
|
|
23
|
+
groupBy(desc => `${desc.type}.${desc.name}`),
|
|
24
|
+
entries(),
|
|
25
|
+
flatMap(([_, descs]) => descs.length === 1 ? descs : [])
|
|
26
|
+
)
|
|
27
|
+
}
|
|
15
28
|
|
|
16
29
|
export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
30
|
+
constructor(services: LikeC4Services) {
|
|
31
|
+
super(services)
|
|
32
|
+
}
|
|
33
|
+
|
|
17
34
|
override async computeExports(
|
|
18
35
|
document: LikeC4LangiumDocument,
|
|
19
36
|
_cancelToken?: CancellationToken
|
|
20
37
|
): Promise<AstNodeDescription[]> {
|
|
21
38
|
const docExports: AstNodeDescription[] = []
|
|
22
39
|
try {
|
|
23
|
-
const { specifications, models, views, globals, likec4lib } = document.parseResult.value
|
|
40
|
+
const { specifications, models, views, globals, likec4lib, deployments } = document.parseResult.value
|
|
24
41
|
|
|
25
42
|
// Process library
|
|
26
43
|
this.exportLibrary(likec4lib, docExports, document)
|
|
@@ -36,6 +53,8 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
36
53
|
|
|
37
54
|
// Process global
|
|
38
55
|
this.exportGlobals(globals, docExports, document)
|
|
56
|
+
|
|
57
|
+
this.exportDeployments(deployments, docExports, document)
|
|
39
58
|
} catch (e) {
|
|
40
59
|
logError(e)
|
|
41
60
|
}
|
|
@@ -43,14 +62,15 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
43
62
|
}
|
|
44
63
|
|
|
45
64
|
private exportViews(
|
|
46
|
-
|
|
65
|
+
modelViews: ast.ModelViews[] | undefined,
|
|
47
66
|
docExports: AstNodeDescription[],
|
|
48
67
|
document: LikeC4LangiumDocument
|
|
49
68
|
) {
|
|
69
|
+
const views = modelViews?.flatMap(m => m.views)
|
|
50
70
|
if (isNullish(views) || views.length === 0) {
|
|
51
71
|
return
|
|
52
72
|
}
|
|
53
|
-
for (const viewAst of views
|
|
73
|
+
for (const viewAst of views) {
|
|
54
74
|
try {
|
|
55
75
|
if (isTruthy(viewAst.name)) {
|
|
56
76
|
docExports.push(this.descriptions.createDescription(viewAst, viewAst.name, document))
|
|
@@ -139,12 +159,14 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
139
159
|
const spec of specifications.flatMap(s => [
|
|
140
160
|
...s.elements,
|
|
141
161
|
...s.relationships,
|
|
162
|
+
...s.deploymentNodes,
|
|
142
163
|
...s.tags,
|
|
143
164
|
...s.colors
|
|
144
165
|
])
|
|
145
166
|
) {
|
|
146
167
|
try {
|
|
147
168
|
switch (true) {
|
|
169
|
+
case ast.isSpecificationDeploymentNodeKind(spec):
|
|
148
170
|
case ast.isSpecificationElementKind(spec): {
|
|
149
171
|
if (isTruthy(spec.kind.name)) {
|
|
150
172
|
docExports.push(
|
|
@@ -188,21 +210,58 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
188
210
|
}
|
|
189
211
|
}
|
|
190
212
|
|
|
213
|
+
private exportDeployments(
|
|
214
|
+
modelDeployments: ast.ModelDeployments[] | undefined,
|
|
215
|
+
docExports: AstNodeDescription[],
|
|
216
|
+
document: LikeC4LangiumDocument
|
|
217
|
+
) {
|
|
218
|
+
const nodes = modelDeployments?.flatMap(m => m.elements)
|
|
219
|
+
if (isNullish(nodes) || nodes.length === 0) {
|
|
220
|
+
return
|
|
221
|
+
}
|
|
222
|
+
for (const node of nodes) {
|
|
223
|
+
try {
|
|
224
|
+
if (ast.isDeploymentNode(node) && isTruthy(node.name)) {
|
|
225
|
+
docExports.push(this.descriptions.createDescription(node, node.name, document))
|
|
226
|
+
}
|
|
227
|
+
} catch (e) {
|
|
228
|
+
logWarnError(e)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
191
233
|
override computeLocalScopes(
|
|
192
234
|
document: LikeC4LangiumDocument,
|
|
193
235
|
_cancelToken?: CancellationToken
|
|
194
236
|
): Promise<PrecomputedScopes> {
|
|
195
237
|
return new Promise(resolve => {
|
|
196
238
|
const root = document.parseResult.value
|
|
239
|
+
const descendants = [] as AstNodeDescription[]
|
|
197
240
|
const scopes = new MultiMap<AstNode, AstNodeDescription>()
|
|
241
|
+
|
|
198
242
|
for (const model of root.models) {
|
|
199
243
|
try {
|
|
200
|
-
|
|
201
|
-
|
|
244
|
+
descendants.push(
|
|
245
|
+
...this.processContainer(model, scopes, document)
|
|
246
|
+
)
|
|
202
247
|
} catch (e) {
|
|
203
248
|
logError(e)
|
|
204
249
|
}
|
|
205
250
|
}
|
|
251
|
+
for (const deployment of root.deployments) {
|
|
252
|
+
try {
|
|
253
|
+
descendants.push(
|
|
254
|
+
...this.processDeployments(deployment, scopes, document)
|
|
255
|
+
)
|
|
256
|
+
} catch (e) {
|
|
257
|
+
logWarnError(e)
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
uniqueDescriptions(descendants).forEach(desc => {
|
|
262
|
+
scopes.add(root, desc)
|
|
263
|
+
})
|
|
264
|
+
|
|
206
265
|
resolve(scopes)
|
|
207
266
|
})
|
|
208
267
|
}
|
|
@@ -211,9 +270,10 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
211
270
|
container: ElementsContainer,
|
|
212
271
|
scopes: PrecomputedScopes,
|
|
213
272
|
document: LikeC4LangiumDocument
|
|
214
|
-
) {
|
|
273
|
+
): AstNodeDescription[] {
|
|
215
274
|
const localScope = new MultiMap<string, AstNodeDescription>()
|
|
216
|
-
const
|
|
275
|
+
const descedants = [] as AstNodeDescription[]
|
|
276
|
+
|
|
217
277
|
for (const el of container.elements) {
|
|
218
278
|
if (ast.isRelation(el)) {
|
|
219
279
|
continue
|
|
@@ -231,25 +291,74 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
231
291
|
|
|
232
292
|
if (subcontainer && subcontainer.elements.length > 0) {
|
|
233
293
|
try {
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
}
|
|
294
|
+
descedants.push(
|
|
295
|
+
...this.processContainer(subcontainer, scopes, document)
|
|
296
|
+
)
|
|
238
297
|
} catch (e) {
|
|
239
|
-
|
|
298
|
+
logWarnError(e)
|
|
240
299
|
}
|
|
241
300
|
}
|
|
242
301
|
}
|
|
243
302
|
|
|
244
|
-
if (
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
303
|
+
if (descedants.length) {
|
|
304
|
+
pipe(
|
|
305
|
+
descedants,
|
|
306
|
+
filter(desc => !localScope.has(desc.name)),
|
|
307
|
+
groupBy(desc => desc.name),
|
|
308
|
+
forEachObj((descs, name) => {
|
|
309
|
+
if (descs.length === 1) {
|
|
310
|
+
localScope.add(name, descs[0])
|
|
311
|
+
}
|
|
312
|
+
})
|
|
313
|
+
)
|
|
314
|
+
}
|
|
315
|
+
const local = [...localScope.values()]
|
|
316
|
+
scopes.addAll(container, local)
|
|
317
|
+
return local
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
protected processDeployments(
|
|
321
|
+
container: DeploymentsContainer,
|
|
322
|
+
scopes: PrecomputedScopes,
|
|
323
|
+
document: LikeC4LangiumDocument
|
|
324
|
+
): AstNodeDescription[] {
|
|
325
|
+
const localnames = new Set<string>()
|
|
326
|
+
const descedants = [] as AstNodeDescription[]
|
|
327
|
+
|
|
328
|
+
for (const el of container.elements) {
|
|
329
|
+
if (ast.isDeploymentRelation(el)) {
|
|
330
|
+
continue
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
let name = this.nameProvider.getName(el)
|
|
334
|
+
if (isTruthy(name)) {
|
|
335
|
+
const desc = this.descriptions.createDescription(el, name, document)
|
|
336
|
+
scopes.add(container, desc)
|
|
337
|
+
localnames.add(desc.name)
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
if (ast.isDeploymentNode(el) && el.body) {
|
|
341
|
+
try {
|
|
342
|
+
descedants.push(
|
|
343
|
+
...this.processDeployments(el.body, scopes, document)
|
|
344
|
+
)
|
|
345
|
+
} catch (e) {
|
|
346
|
+
logWarnError(e)
|
|
249
347
|
}
|
|
250
348
|
}
|
|
251
349
|
}
|
|
252
|
-
|
|
253
|
-
|
|
350
|
+
if (descedants.length > 0) {
|
|
351
|
+
pipe(
|
|
352
|
+
descedants,
|
|
353
|
+
filter(desc => !localnames.has(desc.name)),
|
|
354
|
+
groupBy(desc => desc.name),
|
|
355
|
+
forEachObj((descs, name) => {
|
|
356
|
+
if (descs.length === 1) {
|
|
357
|
+
scopes.add(container, descs[0])
|
|
358
|
+
}
|
|
359
|
+
})
|
|
360
|
+
)
|
|
361
|
+
}
|
|
362
|
+
return [...scopes.get(container).values()]
|
|
254
363
|
}
|
|
255
364
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { invariant } from '@likec4/core'
|
|
2
1
|
import type * as c4 from '@likec4/core'
|
|
2
|
+
import { nonexhaustive } from '@likec4/core'
|
|
3
3
|
import type { AstNode } from 'langium'
|
|
4
4
|
import {
|
|
5
5
|
type AstNodeDescription,
|
|
@@ -17,19 +17,21 @@ import {
|
|
|
17
17
|
StreamScope
|
|
18
18
|
} from 'langium'
|
|
19
19
|
import { ast } from '../ast'
|
|
20
|
-
import { elementRef, getFqnElementRef } from '../elementRef'
|
|
21
20
|
import { logger } from '../logger'
|
|
22
|
-
import type { FqnIndex } from '../model
|
|
21
|
+
import type { DeploymentsIndex, FqnIndex } from '../model'
|
|
23
22
|
import type { LikeC4Services } from '../module'
|
|
23
|
+
import { elementRef, getFqnElementRef } from '../utils/elementRef'
|
|
24
24
|
|
|
25
25
|
const { getDocument } = AstUtils
|
|
26
26
|
|
|
27
27
|
export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
28
|
+
private deploymentsIndex: DeploymentsIndex
|
|
28
29
|
private fqnIndex: FqnIndex
|
|
29
30
|
|
|
30
31
|
constructor(services: LikeC4Services) {
|
|
31
32
|
super(services)
|
|
32
33
|
this.fqnIndex = services.likec4.FqnIndex
|
|
34
|
+
this.deploymentsIndex = services.likec4.DeploymentsIndex
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
private directChildrenOf(parent: c4.Fqn): Stream<AstNodeDescription> {
|
|
@@ -87,15 +89,20 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
87
89
|
override getScope(context: ReferenceInfo): Scope {
|
|
88
90
|
try {
|
|
89
91
|
const referenceType = this.reflection.getReferenceType(context)
|
|
90
|
-
if (referenceType !== ast.Element) {
|
|
91
|
-
return this.getGlobalScope(referenceType)
|
|
92
|
-
}
|
|
93
92
|
try {
|
|
94
93
|
const container = context.container
|
|
94
|
+
if (ast.isFqnRef(container)) {
|
|
95
|
+
return this.getScopeForFqnRef(container, context)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if (referenceType !== ast.Element) {
|
|
99
|
+
return this.getGlobalScope(referenceType, context)
|
|
100
|
+
}
|
|
101
|
+
|
|
95
102
|
if (ast.isFqnElementRef(container) && context.property === 'el') {
|
|
96
103
|
const parent = container.parent
|
|
97
104
|
if (!parent) {
|
|
98
|
-
return this.getGlobalScope(referenceType)
|
|
105
|
+
return this.getGlobalScope(referenceType, context)
|
|
99
106
|
}
|
|
100
107
|
return new StreamScope(this.directChildrenOf(getFqnElementRef(parent)))
|
|
101
108
|
}
|
|
@@ -119,7 +126,7 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
119
126
|
return this.computeScope(context)
|
|
120
127
|
} catch (e) {
|
|
121
128
|
logger.warn(e)
|
|
122
|
-
return this.getGlobalScope(referenceType)
|
|
129
|
+
return this.getGlobalScope(referenceType, context)
|
|
123
130
|
}
|
|
124
131
|
} catch (e) {
|
|
125
132
|
logger.warn(e)
|
|
@@ -127,42 +134,68 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
127
134
|
}
|
|
128
135
|
}
|
|
129
136
|
|
|
130
|
-
protected
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
137
|
+
protected getScopeForFqnRef(container: ast.FqnRef, context: ReferenceInfo) {
|
|
138
|
+
const parent = container.parent
|
|
139
|
+
if (!parent) {
|
|
140
|
+
return this.createScope(
|
|
141
|
+
// First preference for deployment nodes
|
|
142
|
+
this.computeScope(context, ast.DeploymentNode).getAllElements(),
|
|
143
|
+
this.createScope(
|
|
144
|
+
// Second preference for deployed instances
|
|
145
|
+
this.computeScope(context, ast.DeployedInstance).getAllElements(),
|
|
146
|
+
// Third preference for elements if we are in deployment view
|
|
147
|
+
AstUtils.hasContainerOfType(container, ast.isDeploymentView)
|
|
148
|
+
? this.computeScope(context, ast.Element)
|
|
149
|
+
: EMPTY_SCOPE
|
|
150
|
+
)
|
|
151
|
+
)
|
|
152
|
+
}
|
|
153
|
+
const parentRef = parent.value.ref
|
|
154
|
+
if (!parentRef) {
|
|
155
|
+
return EMPTY_SCOPE
|
|
156
|
+
}
|
|
157
|
+
if (ast.isDeploymentNode(parentRef)) {
|
|
158
|
+
return new StreamScope(this.deploymentsIndex.nested(parentRef))
|
|
159
|
+
}
|
|
160
|
+
if (ast.isDeployedInstance(parentRef)) {
|
|
161
|
+
return new StreamScope(this.scopeElementRef(parentRef.element))
|
|
162
|
+
}
|
|
163
|
+
if (ast.isElement(parentRef)) {
|
|
164
|
+
return new StreamScope(this.uniqueDescedants(() => parentRef))
|
|
165
|
+
}
|
|
166
|
+
return nonexhaustive(parentRef)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
protected computeScope(context: ReferenceInfo, referenceType = this.reflection.getReferenceType(context)) {
|
|
170
|
+
const isElementReference = this.reflection.isSubtype(referenceType, ast.Element)
|
|
171
|
+
|
|
134
172
|
const scopes: Stream<AstNodeDescription>[] = []
|
|
135
173
|
const doc = getDocument(context.container)
|
|
136
174
|
const precomputed = doc.precomputedScopes
|
|
137
175
|
|
|
138
|
-
if (precomputed) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
while (container) {
|
|
142
|
-
const elements = precomputed.get(container).filter(byReferenceType)
|
|
143
|
-
if (elements.length > 0) {
|
|
144
|
-
scopes.push(stream(elements))
|
|
145
|
-
}
|
|
176
|
+
if (!precomputed) {
|
|
177
|
+
return this.getGlobalScope(referenceType, context)
|
|
178
|
+
}
|
|
146
179
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
container = container.$container
|
|
180
|
+
const byReferenceType = (desc: AstNodeDescription) => this.reflection.isSubtype(desc.type, referenceType)
|
|
181
|
+
let container: AstNode | undefined = context.container
|
|
182
|
+
while (container) {
|
|
183
|
+
const elements = precomputed.get(container).filter(byReferenceType)
|
|
184
|
+
if (elements.length > 0) {
|
|
185
|
+
scopes.push(stream(elements))
|
|
154
186
|
}
|
|
187
|
+
|
|
188
|
+
if (isElementReference && ast.isExtendElementBody(container)) {
|
|
189
|
+
scopes.push(this.scopeExtendElement(container.$container))
|
|
190
|
+
}
|
|
191
|
+
if (isElementReference && ast.isElementViewBody(container)) {
|
|
192
|
+
scopes.push(this.scopeElementView(container.$container))
|
|
193
|
+
}
|
|
194
|
+
container = container.$container
|
|
155
195
|
}
|
|
156
196
|
|
|
157
197
|
return scopes.reduceRight((outerScope, elements) => {
|
|
158
198
|
return this.createScope(elements, outerScope)
|
|
159
|
-
}, this.getGlobalScope(referenceType))
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
/**
|
|
163
|
-
* Create a global scope filtered for the given reference type.
|
|
164
|
-
*/
|
|
165
|
-
protected override getGlobalScope(referenceType: string): Scope {
|
|
166
|
-
return new StreamScope(this.indexManager.allElements(referenceType))
|
|
199
|
+
}, this.getGlobalScope(referenceType, context))
|
|
167
200
|
}
|
|
168
201
|
}
|
|
@@ -16,13 +16,17 @@ export class NodeKindProvider implements LspNodeKindProvider {
|
|
|
16
16
|
switch (true) {
|
|
17
17
|
case hasType(
|
|
18
18
|
ast.Element,
|
|
19
|
-
ast.ExtendElement
|
|
19
|
+
ast.ExtendElement,
|
|
20
|
+
ast.DeploymentNode,
|
|
21
|
+
ast.DeployedInstance
|
|
20
22
|
):
|
|
21
23
|
return SymbolKind.Constructor
|
|
22
24
|
|
|
23
25
|
case hasType(
|
|
24
26
|
ast.Model,
|
|
25
27
|
ast.ModelViews,
|
|
28
|
+
ast.ModelDeployments,
|
|
29
|
+
ast.Globals,
|
|
26
30
|
ast.SpecificationRule
|
|
27
31
|
):
|
|
28
32
|
return SymbolKind.Namespace
|
|
@@ -46,7 +50,9 @@ export class NodeKindProvider implements LspNodeKindProvider {
|
|
|
46
50
|
|
|
47
51
|
case hasType(
|
|
48
52
|
ast.ElementKind,
|
|
49
|
-
ast.
|
|
53
|
+
ast.DeploymentNodeKind,
|
|
54
|
+
ast.SpecificationElementKind,
|
|
55
|
+
ast.SpecificationDeploymentNodeKind
|
|
50
56
|
):
|
|
51
57
|
return SymbolKind.TypeParameter
|
|
52
58
|
}
|
|
@@ -66,6 +72,8 @@ export class NodeKindProvider implements LspNodeKindProvider {
|
|
|
66
72
|
|
|
67
73
|
case hasType(
|
|
68
74
|
ast.Element,
|
|
75
|
+
ast.DeploymentNode,
|
|
76
|
+
ast.DeployedInstance,
|
|
69
77
|
ast.ExtendElement
|
|
70
78
|
):
|
|
71
79
|
return CompletionItemKind.Constructor
|
|
@@ -73,6 +81,8 @@ export class NodeKindProvider implements LspNodeKindProvider {
|
|
|
73
81
|
case hasType(
|
|
74
82
|
ast.Model,
|
|
75
83
|
ast.ModelViews,
|
|
84
|
+
ast.ModelDeployments,
|
|
85
|
+
ast.Globals,
|
|
76
86
|
ast.SpecificationRule
|
|
77
87
|
):
|
|
78
88
|
return CompletionItemKind.Module
|
|
@@ -98,7 +108,9 @@ export class NodeKindProvider implements LspNodeKindProvider {
|
|
|
98
108
|
|
|
99
109
|
case hasType(
|
|
100
110
|
ast.ElementKind,
|
|
101
|
-
ast.SpecificationElementKind
|
|
111
|
+
ast.SpecificationElementKind,
|
|
112
|
+
ast.DeploymentNodeKind,
|
|
113
|
+
ast.SpecificationDeploymentNodeKind
|
|
102
114
|
):
|
|
103
115
|
return CompletionItemKind.TypeParameter
|
|
104
116
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { AstUtils } from 'langium'
|
|
2
|
+
import { isNullish } from 'remeda'
|
|
3
|
+
import { ast } from '../ast'
|
|
4
|
+
|
|
5
|
+
export function instanceRef(deploymentRef: ast.FqnRef): ast.DeployedInstance | null {
|
|
6
|
+
let referenceable
|
|
7
|
+
while ((referenceable = deploymentRef.value?.ref)) {
|
|
8
|
+
if (ast.isDeploymentNode(referenceable)) {
|
|
9
|
+
return null
|
|
10
|
+
}
|
|
11
|
+
if (ast.isDeployedInstance(referenceable)) {
|
|
12
|
+
return referenceable
|
|
13
|
+
}
|
|
14
|
+
if (isNullish(deploymentRef.parent)) {
|
|
15
|
+
return null
|
|
16
|
+
}
|
|
17
|
+
deploymentRef = deploymentRef.parent
|
|
18
|
+
}
|
|
19
|
+
return null
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function deploymentNodeRef(deploymentRef: ast.FqnRef): ast.DeploymentNode | null {
|
|
23
|
+
let referenceable = deploymentRef.value.ref ?? null
|
|
24
|
+
if (!referenceable || ast.isDeploymentNode(referenceable)) {
|
|
25
|
+
return referenceable
|
|
26
|
+
}
|
|
27
|
+
const artifact = instanceRef(deploymentRef)
|
|
28
|
+
// Because path in deploymentRef may be omitted,
|
|
29
|
+
// we find artifact first and then its container
|
|
30
|
+
return artifact ? AstUtils.getContainerOfType(artifact, ast.isDeploymentNode) ?? null : null
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function isReferenceToLogicalModel(node: ast.FqnRef) {
|
|
34
|
+
// iterate up the root parent
|
|
35
|
+
while (node.parent) {
|
|
36
|
+
node = node.parent
|
|
37
|
+
}
|
|
38
|
+
return ast.isElement(node.value.ref)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Returns true if node references deployment model
|
|
43
|
+
*/
|
|
44
|
+
export function isReferenceToDeploymentModel(node: ast.FqnRef) {
|
|
45
|
+
let referenceable
|
|
46
|
+
while ((referenceable = node.value?.ref)) {
|
|
47
|
+
if (ast.isDeploymentElement(referenceable)) {
|
|
48
|
+
return true
|
|
49
|
+
}
|
|
50
|
+
if (isNullish(node.parent)) {
|
|
51
|
+
return false
|
|
52
|
+
}
|
|
53
|
+
node = node.parent
|
|
54
|
+
}
|
|
55
|
+
return false
|
|
56
|
+
}
|
package/src/utils/stringHash.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type AstNode,
|
|
1
|
+
import { type AstNode, type ValidationAcceptor, type ValidationCheck } from 'langium'
|
|
2
|
+
import { isPromise } from 'remeda'
|
|
2
3
|
import type { CancellationToken } from 'vscode-jsonrpc'
|
|
3
4
|
import { logWarnError } from '../logger'
|
|
4
5
|
|
|
@@ -13,11 +14,11 @@ export const RESERVED_WORDS = [
|
|
|
13
14
|
|
|
14
15
|
export function tryOrLog<T extends AstNode>(fn: ValidationCheck<T>): ValidationCheck<T> {
|
|
15
16
|
return async (node: T, accept: ValidationAcceptor, cancelToken: CancellationToken) => {
|
|
16
|
-
if (cancelToken) {
|
|
17
|
-
await interruptAndCheck(cancelToken)
|
|
18
|
-
}
|
|
19
17
|
try {
|
|
20
|
-
|
|
18
|
+
const result = fn(node, accept, cancelToken)
|
|
19
|
+
if (isPromise(result)) {
|
|
20
|
+
await result
|
|
21
|
+
}
|
|
21
22
|
} catch (e) {
|
|
22
23
|
logWarnError(e)
|
|
23
24
|
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { FqnRef, isSameHierarchy, nonNullable } from '@likec4/core'
|
|
2
|
+
import { type ValidationCheck, AstUtils } from 'langium'
|
|
3
|
+
import { ast } from '../ast'
|
|
4
|
+
import type { LikeC4Services } from '../module'
|
|
5
|
+
import type { LikeC4NameProvider } from '../references'
|
|
6
|
+
import { RESERVED_WORDS, tryOrLog } from './_shared'
|
|
7
|
+
|
|
8
|
+
const { getDocument } = AstUtils
|
|
9
|
+
|
|
10
|
+
export const deploymentNodeChecks = (services: LikeC4Services): ValidationCheck<ast.DeploymentNode> => {
|
|
11
|
+
const DeploymentsIndex = services.likec4.DeploymentsIndex
|
|
12
|
+
const Names = services.references.NameProvider
|
|
13
|
+
return tryOrLog((el, accept) => {
|
|
14
|
+
const nodeName = Names.getName(el)
|
|
15
|
+
if (!nodeName) {
|
|
16
|
+
accept('error', 'DeploymentNode must be named', {
|
|
17
|
+
node: el,
|
|
18
|
+
})
|
|
19
|
+
return
|
|
20
|
+
}
|
|
21
|
+
const range = nonNullable(Names.getNameNode(el), 'name CstNode not found').range
|
|
22
|
+
|
|
23
|
+
if (RESERVED_WORDS.includes(nodeName)) {
|
|
24
|
+
accept('error', `Reserved word: ${nodeName}`, {
|
|
25
|
+
node: el,
|
|
26
|
+
range,
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
|
+
const fqnName = DeploymentsIndex.getFqn(el)
|
|
30
|
+
|
|
31
|
+
const withSameName = DeploymentsIndex.byFqn(fqnName).limit(2).toArray()
|
|
32
|
+
if (withSameName.length > 1) {
|
|
33
|
+
accept(
|
|
34
|
+
'error',
|
|
35
|
+
`Duplicate node name "${fqnName}"`,
|
|
36
|
+
{
|
|
37
|
+
node: el,
|
|
38
|
+
range,
|
|
39
|
+
},
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const deployedInstanceChecks = (services: LikeC4Services): ValidationCheck<ast.DeployedInstance> => {
|
|
46
|
+
const DeploymentsIndex = services.likec4.DeploymentsIndex
|
|
47
|
+
const Names = services.references.NameProvider as LikeC4NameProvider
|
|
48
|
+
// const Locator = services.workspace.AstNodeLocator
|
|
49
|
+
return tryOrLog((el, accept) => {
|
|
50
|
+
const artifactName = Names.getName(el)
|
|
51
|
+
if (!artifactName) {
|
|
52
|
+
accept('error', 'Deployed instance must be named, unique inside node', {
|
|
53
|
+
node: el,
|
|
54
|
+
})
|
|
55
|
+
return
|
|
56
|
+
}
|
|
57
|
+
const range = nonNullable(Names.getNameNode(el), 'name CstNode not found').range
|
|
58
|
+
|
|
59
|
+
if (RESERVED_WORDS.includes(artifactName)) {
|
|
60
|
+
accept('error', `Reserved word: ${artifactName}`, {
|
|
61
|
+
node: el,
|
|
62
|
+
range,
|
|
63
|
+
})
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const fqnName = DeploymentsIndex.getFqn(el)
|
|
67
|
+
|
|
68
|
+
const withSameName = DeploymentsIndex.byFqn(fqnName).limit(2).toArray()
|
|
69
|
+
if (withSameName.length > 1) {
|
|
70
|
+
accept(
|
|
71
|
+
'error',
|
|
72
|
+
`Duplicate instance name "${fqnName}"`,
|
|
73
|
+
{
|
|
74
|
+
node: el,
|
|
75
|
+
range,
|
|
76
|
+
},
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
})
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export const deploymentRelationChecks = (services: LikeC4Services): ValidationCheck<ast.DeploymentRelation> => {
|
|
83
|
+
const ModelParser = services.likec4.ModelParser
|
|
84
|
+
return tryOrLog((el, accept) => {
|
|
85
|
+
const source = el.source?.value?.ref
|
|
86
|
+
if (!source) {
|
|
87
|
+
let sourceCstText = el.source?.$cstNode?.text ?? ''
|
|
88
|
+
accept('error', `DeploymentRelation source '${sourceCstText}' not resolved`, {
|
|
89
|
+
node: el,
|
|
90
|
+
property: 'source',
|
|
91
|
+
})
|
|
92
|
+
return
|
|
93
|
+
}
|
|
94
|
+
const target = el.target?.value?.ref
|
|
95
|
+
if (!target) {
|
|
96
|
+
let targetCstText = el.target?.$cstNode?.text ?? ''
|
|
97
|
+
accept('error', `DeploymentRelation target '${targetCstText}' not resolved`, {
|
|
98
|
+
node: el,
|
|
99
|
+
property: 'target',
|
|
100
|
+
})
|
|
101
|
+
return
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const doc = getDocument(el)
|
|
105
|
+
const parser = ModelParser.forDocument(doc)
|
|
106
|
+
|
|
107
|
+
const sourceFqnRef = parser.parseFqnRef(el.source)
|
|
108
|
+
if (FqnRef.isModelRef(sourceFqnRef)) {
|
|
109
|
+
accept('error', 'DeploymentRelation must refer deployment element', {
|
|
110
|
+
node: el,
|
|
111
|
+
property: 'source',
|
|
112
|
+
})
|
|
113
|
+
return
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const targetFqnRef = parser.parseFqnRef(el.target)
|
|
117
|
+
if (FqnRef.isModelRef(targetFqnRef)) {
|
|
118
|
+
accept('error', 'DeploymentRelation must refer deployment element', {
|
|
119
|
+
node: el,
|
|
120
|
+
property: 'target',
|
|
121
|
+
})
|
|
122
|
+
return
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (isSameHierarchy(sourceFqnRef.deployment, targetFqnRef.deployment)) {
|
|
126
|
+
accept('error', 'Invalid parent-child relationship', {
|
|
127
|
+
node: el,
|
|
128
|
+
})
|
|
129
|
+
}
|
|
130
|
+
})
|
|
131
|
+
}
|