@likec4/language-server 1.19.0 → 1.19.2
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/dist/Rpc.js +6 -0
- package/dist/browser.d.ts +1 -0
- package/dist/documentation/documentation-provider.d.ts +8 -0
- package/dist/documentation/documentation-provider.js +46 -0
- package/dist/documentation/index.d.ts +1 -0
- package/dist/documentation/index.js +1 -0
- package/dist/generated/ast.d.ts +22 -9
- package/dist/generated/ast.js +23 -2
- package/dist/generated/grammar.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -2
- package/dist/like-c4.langium +4 -1
- package/dist/lsp/DocumentSymbolProvider.d.ts +11 -2
- package/dist/lsp/DocumentSymbolProvider.js +78 -6
- package/dist/model/fqn-computation.js +2 -2
- package/dist/model/model-builder.js +3 -3
- package/dist/model/model-parser.d.ts +5 -0
- package/dist/model/parser/DeploymentModelParser.d.ts +1 -0
- package/dist/model/parser/DeploymentViewParser.d.ts +2 -1
- package/dist/model/parser/DeploymentViewParser.js +3 -0
- package/dist/model/parser/FqnRefParser.d.ts +1 -0
- package/dist/model/parser/FqnRefParser.js +13 -0
- package/dist/model/parser/GlobalsParser.d.ts +1 -0
- package/dist/model/parser/ViewsParser.d.ts +1 -0
- package/dist/module.d.ts +9 -1
- package/dist/module.js +47 -8
- package/dist/protocol.d.ts +19 -1
- package/dist/protocol.js +1 -0
- package/dist/references/scope-computation.d.ts +2 -2
- package/dist/references/scope-computation.js +9 -9
- package/dist/validation/dynamic-view-rule.js +3 -2
- package/dist/validation/dynamic-view-step.js +23 -27
- package/dist/validation/index.d.ts +1 -1
- package/dist/validation/property-checks.js +3 -2
- package/dist/validation/specification.js +14 -14
- package/dist/validation/view-predicates/element-with.js +3 -2
- package/dist/validation/view-predicates/expanded-element.js +3 -2
- package/dist/validation/view-predicates/incoming.js +3 -2
- package/dist/validation/view-predicates/outgoing.js +3 -2
- package/dist/validation/view-predicates/relation-with.js +3 -2
- package/dist/validation/view.js +3 -3
- package/dist/views/configurable-layouter.d.ts +7 -0
- package/dist/views/configurable-layouter.js +55 -0
- package/dist/views/index.d.ts +1 -0
- package/dist/views/index.js +1 -0
- package/dist/views/likec4-views.d.ts +26 -0
- package/dist/views/likec4-views.js +113 -0
- package/package.json +14 -11
- package/src/Rpc.ts +13 -7
- package/src/browser.ts +1 -0
- package/src/documentation/documentation-provider.ts +52 -0
- package/src/documentation/index.ts +1 -0
- package/src/generated/ast.ts +47 -11
- package/src/generated/grammar.ts +1 -1
- package/src/index.ts +4 -2
- package/src/like-c4.langium +4 -1
- package/src/lsp/DocumentSymbolProvider.ts +110 -28
- package/src/model/fqn-computation.ts +8 -8
- package/src/model/model-builder.ts +52 -52
- package/src/model/parser/DeploymentViewParser.ts +10 -7
- package/src/model/parser/FqnRefParser.ts +14 -0
- package/src/module.ts +56 -9
- package/src/protocol.ts +29 -4
- package/src/references/scope-computation.ts +35 -35
- package/src/validation/dynamic-view-rule.ts +5 -4
- package/src/validation/dynamic-view-step.ts +23 -26
- package/src/validation/property-checks.ts +11 -10
- package/src/validation/specification.ts +38 -38
- package/src/validation/view-predicates/element-with.ts +6 -5
- package/src/validation/view-predicates/expanded-element.ts +6 -5
- package/src/validation/view-predicates/incoming.ts +6 -5
- package/src/validation/view-predicates/outgoing.ts +6 -5
- package/src/validation/view-predicates/relation-with.ts +6 -5
- package/src/validation/view.ts +5 -5
- package/src/views/configurable-layouter.ts +65 -0
- package/src/views/index.ts +1 -0
- package/src/views/likec4-views.ts +139 -0
|
@@ -2,27 +2,27 @@ import { nonexhaustive } from '@likec4/core'
|
|
|
2
2
|
import {
|
|
3
3
|
type AstNode,
|
|
4
4
|
type AstNodeDescription,
|
|
5
|
+
type PrecomputedScopes,
|
|
5
6
|
DefaultScopeComputation,
|
|
6
7
|
MultiMap,
|
|
7
|
-
type PrecomputedScopes
|
|
8
8
|
} from 'langium'
|
|
9
|
-
import { entries, filter, flatMap,
|
|
9
|
+
import { entries, filter, flatMap, forEachObj, groupBy, isNullish, isTruthy, pipe } from 'remeda'
|
|
10
10
|
import type { CancellationToken } from 'vscode-languageserver'
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
11
|
+
import { type LikeC4LangiumDocument, ast } from '../ast'
|
|
12
|
+
import { logWarnError } from '../logger'
|
|
13
13
|
import type { LikeC4Services } from '../module'
|
|
14
14
|
|
|
15
15
|
type ElementsContainer = ast.Model | ast.ElementBody | ast.ExtendElementBody
|
|
16
16
|
type DeploymentsContainer = ast.ModelDeployments | ast.DeploymentNodeBody
|
|
17
17
|
|
|
18
18
|
function uniqueDescriptions(
|
|
19
|
-
descs: AstNodeDescription[]
|
|
19
|
+
descs: AstNodeDescription[],
|
|
20
20
|
): AstNodeDescription[] {
|
|
21
21
|
return pipe(
|
|
22
22
|
descs,
|
|
23
23
|
groupBy(desc => `${desc.type}.${desc.name}`),
|
|
24
24
|
entries(),
|
|
25
|
-
flatMap(([_, descs]) => descs.length === 1 ? descs : [])
|
|
25
|
+
flatMap(([_, descs]) => descs.length === 1 ? descs : []),
|
|
26
26
|
)
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -33,7 +33,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
33
33
|
|
|
34
34
|
override async computeExports(
|
|
35
35
|
document: LikeC4LangiumDocument,
|
|
36
|
-
_cancelToken?: CancellationToken
|
|
36
|
+
_cancelToken?: CancellationToken,
|
|
37
37
|
): Promise<AstNodeDescription[]> {
|
|
38
38
|
const docExports: AstNodeDescription[] = []
|
|
39
39
|
try {
|
|
@@ -56,7 +56,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
56
56
|
|
|
57
57
|
this.exportDeployments(deployments, docExports, document)
|
|
58
58
|
} catch (e) {
|
|
59
|
-
|
|
59
|
+
logWarnError(e)
|
|
60
60
|
}
|
|
61
61
|
return docExports
|
|
62
62
|
}
|
|
@@ -64,7 +64,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
64
64
|
private exportViews(
|
|
65
65
|
modelViews: ast.ModelViews[] | undefined,
|
|
66
66
|
docExports: AstNodeDescription[],
|
|
67
|
-
document: LikeC4LangiumDocument
|
|
67
|
+
document: LikeC4LangiumDocument,
|
|
68
68
|
) {
|
|
69
69
|
const views = modelViews?.flatMap(m => m.views)
|
|
70
70
|
if (isNullish(views) || views.length === 0) {
|
|
@@ -76,7 +76,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
76
76
|
docExports.push(this.descriptions.createDescription(viewAst, viewAst.name, document))
|
|
77
77
|
}
|
|
78
78
|
} catch (e) {
|
|
79
|
-
|
|
79
|
+
logWarnError(e)
|
|
80
80
|
}
|
|
81
81
|
}
|
|
82
82
|
}
|
|
@@ -84,7 +84,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
84
84
|
private exportGlobals(
|
|
85
85
|
globals: ast.Globals[] | undefined,
|
|
86
86
|
docExports: AstNodeDescription[],
|
|
87
|
-
document: LikeC4LangiumDocument
|
|
87
|
+
document: LikeC4LangiumDocument,
|
|
88
88
|
) {
|
|
89
89
|
if (isNullish(globals) || globals.length === 0) {
|
|
90
90
|
return
|
|
@@ -96,7 +96,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
96
96
|
docExports.push(this.descriptions.createDescription(id, id.name, document))
|
|
97
97
|
}
|
|
98
98
|
} catch (e) {
|
|
99
|
-
|
|
99
|
+
logWarnError(e)
|
|
100
100
|
}
|
|
101
101
|
}
|
|
102
102
|
for (const globalStyleAst of globals.flatMap(g => g.styles)) {
|
|
@@ -106,7 +106,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
106
106
|
docExports.push(this.descriptions.createDescription(id, id.name, document))
|
|
107
107
|
}
|
|
108
108
|
} catch (e) {
|
|
109
|
-
|
|
109
|
+
logWarnError(e)
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
}
|
|
@@ -114,7 +114,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
114
114
|
private exportModel(
|
|
115
115
|
models: ast.Model[] | undefined,
|
|
116
116
|
docExports: AstNodeDescription[],
|
|
117
|
-
document: LikeC4LangiumDocument
|
|
117
|
+
document: LikeC4LangiumDocument,
|
|
118
118
|
) {
|
|
119
119
|
if (isNullish(models) || models.length === 0) {
|
|
120
120
|
return
|
|
@@ -125,7 +125,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
125
125
|
docExports.push(this.descriptions.createDescription(elAst, elAst.name, document))
|
|
126
126
|
}
|
|
127
127
|
} catch (e) {
|
|
128
|
-
|
|
128
|
+
logWarnError(e)
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
131
|
}
|
|
@@ -133,7 +133,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
133
133
|
private exportLibrary(
|
|
134
134
|
likec4lib: ast.LikeC4Lib[] | undefined,
|
|
135
135
|
docExports: AstNodeDescription[],
|
|
136
|
-
document: LikeC4LangiumDocument
|
|
136
|
+
document: LikeC4LangiumDocument,
|
|
137
137
|
) {
|
|
138
138
|
if (isNullish(likec4lib)) {
|
|
139
139
|
return
|
|
@@ -143,14 +143,14 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
143
143
|
docExports.push(this.descriptions.createDescription(iconAst, iconAst.name, document))
|
|
144
144
|
}
|
|
145
145
|
} catch (e) {
|
|
146
|
-
|
|
146
|
+
logWarnError(e)
|
|
147
147
|
}
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
private exportSpecification(
|
|
151
151
|
specifications: ast.SpecificationRule[] | undefined,
|
|
152
152
|
docExports: AstNodeDescription[],
|
|
153
|
-
document: LikeC4LangiumDocument
|
|
153
|
+
document: LikeC4LangiumDocument,
|
|
154
154
|
) {
|
|
155
155
|
if (isNullish(specifications) || specifications.length === 0) {
|
|
156
156
|
return
|
|
@@ -161,7 +161,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
161
161
|
...s.relationships,
|
|
162
162
|
...s.deploymentNodes,
|
|
163
163
|
...s.tags,
|
|
164
|
-
...s.colors
|
|
164
|
+
...s.colors,
|
|
165
165
|
])
|
|
166
166
|
) {
|
|
167
167
|
try {
|
|
@@ -170,7 +170,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
170
170
|
case ast.isSpecificationElementKind(spec): {
|
|
171
171
|
if (isTruthy(spec.kind.name)) {
|
|
172
172
|
docExports.push(
|
|
173
|
-
this.descriptions.createDescription(spec.kind, spec.kind.name, document)
|
|
173
|
+
this.descriptions.createDescription(spec.kind, spec.kind.name, document),
|
|
174
174
|
)
|
|
175
175
|
}
|
|
176
176
|
continue
|
|
@@ -178,7 +178,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
178
178
|
case ast.isSpecificationTag(spec): {
|
|
179
179
|
if (isTruthy(spec.tag.name)) {
|
|
180
180
|
docExports.push(
|
|
181
|
-
this.descriptions.createDescription(spec.tag, '#' + spec.tag.name, document)
|
|
181
|
+
this.descriptions.createDescription(spec.tag, '#' + spec.tag.name, document),
|
|
182
182
|
)
|
|
183
183
|
}
|
|
184
184
|
continue
|
|
@@ -187,7 +187,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
187
187
|
if (isTruthy(spec.kind.name)) {
|
|
188
188
|
docExports.push(
|
|
189
189
|
this.descriptions.createDescription(spec.kind, spec.kind.name, document),
|
|
190
|
-
this.descriptions.createDescription(spec.kind, '.' + spec.kind.name, document)
|
|
190
|
+
this.descriptions.createDescription(spec.kind, '.' + spec.kind.name, document),
|
|
191
191
|
)
|
|
192
192
|
}
|
|
193
193
|
continue
|
|
@@ -195,7 +195,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
195
195
|
case ast.isSpecificationColor(spec): {
|
|
196
196
|
if (isTruthy(spec.name.name)) {
|
|
197
197
|
docExports.push(
|
|
198
|
-
this.descriptions.createDescription(spec.name, spec.name.name, document)
|
|
198
|
+
this.descriptions.createDescription(spec.name, spec.name.name, document),
|
|
199
199
|
)
|
|
200
200
|
}
|
|
201
201
|
continue
|
|
@@ -205,7 +205,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
205
205
|
nonexhaustive(spec)
|
|
206
206
|
}
|
|
207
207
|
} catch (e) {
|
|
208
|
-
|
|
208
|
+
logWarnError(e)
|
|
209
209
|
}
|
|
210
210
|
}
|
|
211
211
|
}
|
|
@@ -213,7 +213,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
213
213
|
private exportDeployments(
|
|
214
214
|
modelDeployments: ast.ModelDeployments[] | undefined,
|
|
215
215
|
docExports: AstNodeDescription[],
|
|
216
|
-
document: LikeC4LangiumDocument
|
|
216
|
+
document: LikeC4LangiumDocument,
|
|
217
217
|
) {
|
|
218
218
|
const nodes = modelDeployments?.flatMap(m => m.elements)
|
|
219
219
|
if (isNullish(nodes) || nodes.length === 0) {
|
|
@@ -232,7 +232,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
232
232
|
|
|
233
233
|
override computeLocalScopes(
|
|
234
234
|
document: LikeC4LangiumDocument,
|
|
235
|
-
_cancelToken?: CancellationToken
|
|
235
|
+
_cancelToken?: CancellationToken,
|
|
236
236
|
): Promise<PrecomputedScopes> {
|
|
237
237
|
return new Promise(resolve => {
|
|
238
238
|
const root = document.parseResult.value
|
|
@@ -242,16 +242,16 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
242
242
|
for (const model of root.models) {
|
|
243
243
|
try {
|
|
244
244
|
descendants.push(
|
|
245
|
-
...this.processContainer(model, scopes, document)
|
|
245
|
+
...this.processContainer(model, scopes, document),
|
|
246
246
|
)
|
|
247
247
|
} catch (e) {
|
|
248
|
-
|
|
248
|
+
logWarnError(e)
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
251
|
for (const deployment of root.deployments) {
|
|
252
252
|
try {
|
|
253
253
|
descendants.push(
|
|
254
|
-
...this.processDeployments(deployment, scopes, document)
|
|
254
|
+
...this.processDeployments(deployment, scopes, document),
|
|
255
255
|
)
|
|
256
256
|
} catch (e) {
|
|
257
257
|
logWarnError(e)
|
|
@@ -269,7 +269,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
269
269
|
protected processContainer(
|
|
270
270
|
container: ElementsContainer,
|
|
271
271
|
scopes: PrecomputedScopes,
|
|
272
|
-
document: LikeC4LangiumDocument
|
|
272
|
+
document: LikeC4LangiumDocument,
|
|
273
273
|
): AstNodeDescription[] {
|
|
274
274
|
const localScope = new MultiMap<string, AstNodeDescription>()
|
|
275
275
|
const descedants = [] as AstNodeDescription[]
|
|
@@ -292,7 +292,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
292
292
|
if (subcontainer && subcontainer.elements.length > 0) {
|
|
293
293
|
try {
|
|
294
294
|
descedants.push(
|
|
295
|
-
...this.processContainer(subcontainer, scopes, document)
|
|
295
|
+
...this.processContainer(subcontainer, scopes, document),
|
|
296
296
|
)
|
|
297
297
|
} catch (e) {
|
|
298
298
|
logWarnError(e)
|
|
@@ -309,7 +309,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
309
309
|
if (descs.length === 1) {
|
|
310
310
|
localScope.add(name, descs[0])
|
|
311
311
|
}
|
|
312
|
-
})
|
|
312
|
+
}),
|
|
313
313
|
)
|
|
314
314
|
}
|
|
315
315
|
const local = [...localScope.values()]
|
|
@@ -320,7 +320,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
320
320
|
protected processDeployments(
|
|
321
321
|
container: DeploymentsContainer,
|
|
322
322
|
scopes: PrecomputedScopes,
|
|
323
|
-
document: LikeC4LangiumDocument
|
|
323
|
+
document: LikeC4LangiumDocument,
|
|
324
324
|
): AstNodeDescription[] {
|
|
325
325
|
const localnames = new Set<string>()
|
|
326
326
|
const descedants = [] as AstNodeDescription[]
|
|
@@ -340,7 +340,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
340
340
|
if (ast.isDeploymentNode(el) && el.body) {
|
|
341
341
|
try {
|
|
342
342
|
descedants.push(
|
|
343
|
-
...this.processDeployments(el.body, scopes, document)
|
|
343
|
+
...this.processDeployments(el.body, scopes, document),
|
|
344
344
|
)
|
|
345
345
|
} catch (e) {
|
|
346
346
|
logWarnError(e)
|
|
@@ -356,7 +356,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
356
356
|
if (descs.length === 1) {
|
|
357
357
|
scopes.add(container, descs[0])
|
|
358
358
|
}
|
|
359
|
-
})
|
|
359
|
+
}),
|
|
360
360
|
)
|
|
361
361
|
}
|
|
362
362
|
return [...scopes.get(container).values()]
|
|
@@ -2,21 +2,22 @@ import { nonexhaustive } from '@likec4/core'
|
|
|
2
2
|
import type { ValidationCheck } from 'langium'
|
|
3
3
|
import { ast, elementExpressionFromPredicate } from '../ast'
|
|
4
4
|
import type { LikeC4Services } from '../module'
|
|
5
|
+
import { tryOrLog } from './_shared'
|
|
5
6
|
|
|
6
7
|
export const dynamicViewRulePredicate = (
|
|
7
|
-
_services: LikeC4Services
|
|
8
|
+
_services: LikeC4Services,
|
|
8
9
|
): ValidationCheck<ast.DynamicViewPredicateIterator> => {
|
|
9
|
-
return (predicate, accept) => {
|
|
10
|
+
return tryOrLog((predicate, accept) => {
|
|
10
11
|
const expr = elementExpressionFromPredicate(predicate.value)
|
|
11
12
|
switch (true) {
|
|
12
13
|
case ast.isElementKindExpression(expr):
|
|
13
14
|
case ast.isElementTagExpression(expr):
|
|
14
15
|
case ast.isWildcardExpression(expr): {
|
|
15
16
|
accept('warning', `Predicate is ignored, as not supported in dynamic views`, {
|
|
16
|
-
node: predicate
|
|
17
|
+
node: predicate,
|
|
17
18
|
})
|
|
18
19
|
return
|
|
19
20
|
}
|
|
20
21
|
}
|
|
21
|
-
}
|
|
22
|
+
})
|
|
22
23
|
}
|
|
@@ -4,36 +4,33 @@ import { ast } from '../ast'
|
|
|
4
4
|
import { logError } from '../logger'
|
|
5
5
|
import type { LikeC4Services } from '../module'
|
|
6
6
|
import { elementRef } from '../utils/elementRef'
|
|
7
|
+
import { tryOrLog } from './_shared'
|
|
7
8
|
|
|
8
9
|
export const dynamicViewStep = (services: LikeC4Services): ValidationCheck<ast.DynamicViewStep> => {
|
|
9
10
|
const fqnIndex = services.likec4.FqnIndex
|
|
10
|
-
return (el, accept) => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
11
|
+
return tryOrLog((el, accept) => {
|
|
12
|
+
const sourceEl: ast.Element | undefined = elementRef(el.source)
|
|
13
|
+
const source = sourceEl && fqnIndex.getFqn(sourceEl)
|
|
14
|
+
if (!source) {
|
|
15
|
+
accept('error', 'Source not found (not parsed/indexed yet)', {
|
|
16
|
+
node: el,
|
|
17
|
+
property: 'source',
|
|
18
|
+
})
|
|
19
|
+
}
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
const targetEl: ast.Element | undefined = elementRef(el.target)
|
|
22
|
+
const target = targetEl && fqnIndex.getFqn(targetEl)
|
|
23
|
+
if (!target) {
|
|
24
|
+
accept('error', 'Target not found (not parsed/indexed yet)', {
|
|
25
|
+
node: el,
|
|
26
|
+
property: 'target',
|
|
27
|
+
})
|
|
28
|
+
}
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
} catch (e) {
|
|
36
|
-
logError(e)
|
|
30
|
+
if (source && target && (isAncestor(source, target) || isAncestor(target, source))) {
|
|
31
|
+
accept('error', 'Invalid parent-child relationship', {
|
|
32
|
+
node: el,
|
|
33
|
+
})
|
|
37
34
|
}
|
|
38
|
-
}
|
|
35
|
+
})
|
|
39
36
|
}
|
|
@@ -1,30 +1,31 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type ValidationCheck, AstUtils } from 'langium'
|
|
2
2
|
import { ast } from '../ast'
|
|
3
3
|
import type { LikeC4Services } from '../module'
|
|
4
|
+
import { tryOrLog } from './_shared'
|
|
4
5
|
|
|
5
6
|
export const opacityPropertyRuleChecks = (
|
|
6
|
-
_: LikeC4Services
|
|
7
|
+
_: LikeC4Services,
|
|
7
8
|
): ValidationCheck<ast.OpacityProperty> => {
|
|
8
|
-
return (node, accept) => {
|
|
9
|
+
return tryOrLog((node, accept) => {
|
|
9
10
|
const opacity = parseFloat(node.value)
|
|
10
11
|
if (isNaN(opacity) || opacity < 0 || opacity > 100) {
|
|
11
12
|
accept('warning', `Value ignored, must be between 0% and 100%`, {
|
|
12
13
|
node,
|
|
13
|
-
property: 'value'
|
|
14
|
+
property: 'value',
|
|
14
15
|
})
|
|
15
16
|
}
|
|
16
|
-
}
|
|
17
|
+
})
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
export const iconPropertyRuleChecks = (
|
|
20
|
-
_: LikeC4Services
|
|
21
|
+
_: LikeC4Services,
|
|
21
22
|
): ValidationCheck<ast.IconProperty> => {
|
|
22
23
|
return (node, accept) => {
|
|
23
24
|
const container = node.$container
|
|
24
25
|
const anotherIcon = container.props.some(p => ast.isIconProperty(p) && p !== node)
|
|
25
26
|
if (anotherIcon) {
|
|
26
27
|
accept('error', `Icon must be defined once`, {
|
|
27
|
-
node
|
|
28
|
+
node,
|
|
28
29
|
})
|
|
29
30
|
}
|
|
30
31
|
if (
|
|
@@ -32,19 +33,19 @@ export const iconPropertyRuleChecks = (
|
|
|
32
33
|
&& container.$container.props.some(p => ast.isIconProperty(p))
|
|
33
34
|
) {
|
|
34
35
|
accept('warning', `Redundant as icon defined on element`, {
|
|
35
|
-
node
|
|
36
|
+
node,
|
|
36
37
|
})
|
|
37
38
|
}
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
|
|
41
42
|
export const notesPropertyRuleChecks = (
|
|
42
|
-
_: LikeC4Services
|
|
43
|
+
_: LikeC4Services,
|
|
43
44
|
): ValidationCheck<ast.NotesProperty> => {
|
|
44
45
|
return (node, accept) => {
|
|
45
46
|
if (!AstUtils.hasContainerOfType(node, ast.isDynamicViewStep)) {
|
|
46
47
|
accept('error', `Notes can be defined only inside dynamic view`, {
|
|
47
|
-
node
|
|
48
|
+
node,
|
|
48
49
|
})
|
|
49
50
|
}
|
|
50
51
|
}
|
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type ValidationCheck, AstUtils } from 'langium'
|
|
2
2
|
import { ast } from '../ast'
|
|
3
3
|
import type { LikeC4Services } from '../module'
|
|
4
4
|
import { RESERVED_WORDS, tryOrLog } from './_shared'
|
|
5
5
|
|
|
6
6
|
export const specificationRuleChecks = (
|
|
7
|
-
_: LikeC4Services
|
|
7
|
+
_: LikeC4Services,
|
|
8
8
|
): ValidationCheck<ast.SpecificationRule> => {
|
|
9
|
-
return (node, accept) => {
|
|
9
|
+
return tryOrLog((node, accept) => {
|
|
10
10
|
if (node.$containerIndex && node.$containerIndex > 0) {
|
|
11
11
|
accept('warning', `Prefer one specification per document`, {
|
|
12
12
|
node: node,
|
|
13
|
-
property: 'name'
|
|
13
|
+
property: 'name',
|
|
14
14
|
})
|
|
15
15
|
}
|
|
16
|
-
}
|
|
16
|
+
})
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export const modelRuleChecks = (_: LikeC4Services): ValidationCheck<ast.Model> => {
|
|
20
|
-
return (node, accept) => {
|
|
20
|
+
return tryOrLog((node, accept) => {
|
|
21
21
|
if (node.$containerIndex && node.$containerIndex > 0) {
|
|
22
22
|
accept('warning', `Prefer one model per document`, {
|
|
23
23
|
node: node,
|
|
24
|
-
property: 'name'
|
|
24
|
+
property: 'name',
|
|
25
25
|
})
|
|
26
26
|
}
|
|
27
|
-
}
|
|
27
|
+
})
|
|
28
28
|
}
|
|
29
29
|
|
|
30
30
|
export const globalsChecks = (_: LikeC4Services): ValidationCheck<ast.Globals> => {
|
|
31
|
-
return (node, accept) => {
|
|
31
|
+
return tryOrLog((node, accept) => {
|
|
32
32
|
if (node.$containerIndex && node.$containerIndex > 0) {
|
|
33
33
|
accept('warning', `Prefer one global block per document`, {
|
|
34
34
|
node: node,
|
|
35
|
-
property: 'name'
|
|
35
|
+
property: 'name',
|
|
36
36
|
})
|
|
37
37
|
}
|
|
38
|
-
}
|
|
38
|
+
})
|
|
39
39
|
}
|
|
40
40
|
|
|
41
41
|
export const elementKindChecks = (services: LikeC4Services): ValidationCheck<ast.ElementKind> => {
|
|
@@ -44,7 +44,7 @@ export const elementKindChecks = (services: LikeC4Services): ValidationCheck<ast
|
|
|
44
44
|
if (RESERVED_WORDS.includes(node.name)) {
|
|
45
45
|
accept('error', `Reserved word: ${node.name}`, {
|
|
46
46
|
node: node,
|
|
47
|
-
property: 'name'
|
|
47
|
+
property: 'name',
|
|
48
48
|
})
|
|
49
49
|
}
|
|
50
50
|
const sameKind = index
|
|
@@ -61,12 +61,12 @@ export const elementKindChecks = (services: LikeC4Services): ValidationCheck<ast
|
|
|
61
61
|
{
|
|
62
62
|
location: {
|
|
63
63
|
range: sameKind.nameSegment!.range,
|
|
64
|
-
uri: sameKind.documentUri.toString()
|
|
64
|
+
uri: sameKind.documentUri.toString(),
|
|
65
65
|
},
|
|
66
|
-
message: `conflicting definition
|
|
67
|
-
}
|
|
68
|
-
]
|
|
69
|
-
}
|
|
66
|
+
message: `conflicting definition`,
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
70
|
})
|
|
71
71
|
}
|
|
72
72
|
})
|
|
@@ -74,7 +74,7 @@ export const elementKindChecks = (services: LikeC4Services): ValidationCheck<ast
|
|
|
74
74
|
|
|
75
75
|
export const tagChecks = (services: LikeC4Services): ValidationCheck<ast.Tag> => {
|
|
76
76
|
const index = services.shared.workspace.IndexManager
|
|
77
|
-
return (node, accept) => {
|
|
77
|
+
return tryOrLog((node, accept) => {
|
|
78
78
|
const tagname = '#' + node.name
|
|
79
79
|
const sameTag = index
|
|
80
80
|
.allElements(ast.Tag)
|
|
@@ -93,27 +93,27 @@ export const tagChecks = (services: LikeC4Services): ValidationCheck<ast.Tag> =>
|
|
|
93
93
|
{
|
|
94
94
|
location: {
|
|
95
95
|
range: sameTag.nameSegment!.range,
|
|
96
|
-
uri: sameTag.documentUri.toString()
|
|
96
|
+
uri: sameTag.documentUri.toString(),
|
|
97
97
|
},
|
|
98
|
-
message: `conflicting definition
|
|
99
|
-
}
|
|
100
|
-
]
|
|
101
|
-
}
|
|
102
|
-
}
|
|
98
|
+
message: `conflicting definition`,
|
|
99
|
+
},
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
103
|
)
|
|
104
104
|
}
|
|
105
|
-
}
|
|
105
|
+
})
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
export const relationshipChecks = (
|
|
109
|
-
services: LikeC4Services
|
|
109
|
+
services: LikeC4Services,
|
|
110
110
|
): ValidationCheck<ast.RelationshipKind> => {
|
|
111
111
|
const index = services.shared.workspace.IndexManager
|
|
112
|
-
return (node, accept) => {
|
|
112
|
+
return tryOrLog((node, accept) => {
|
|
113
113
|
if (RESERVED_WORDS.includes(node.name)) {
|
|
114
114
|
accept('error', `Reserved word: ${node.name}`, {
|
|
115
115
|
node: node,
|
|
116
|
-
property: 'name'
|
|
116
|
+
property: 'name',
|
|
117
117
|
})
|
|
118
118
|
}
|
|
119
119
|
const sameKinds = index
|
|
@@ -124,17 +124,17 @@ export const relationshipChecks = (
|
|
|
124
124
|
if (sameKinds > 1) {
|
|
125
125
|
accept('error', `Duplicate RelationshipKind '${node.name}'`, {
|
|
126
126
|
node: node,
|
|
127
|
-
property: 'name'
|
|
127
|
+
property: 'name',
|
|
128
128
|
})
|
|
129
129
|
}
|
|
130
|
-
}
|
|
130
|
+
})
|
|
131
131
|
}
|
|
132
132
|
|
|
133
133
|
export const globalPredicateChecks = (
|
|
134
|
-
services: LikeC4Services
|
|
134
|
+
services: LikeC4Services,
|
|
135
135
|
): ValidationCheck<ast.GlobalPredicateGroup | ast.GlobalDynamicPredicateGroup> => {
|
|
136
136
|
const index = services.shared.workspace.IndexManager
|
|
137
|
-
return (node, accept) => {
|
|
137
|
+
return tryOrLog((node, accept) => {
|
|
138
138
|
const predicateGroups = index.allElements(ast.GlobalPredicateGroup)
|
|
139
139
|
const dynamicPredicateGroups = index.allElements(ast.GlobalDynamicPredicateGroup)
|
|
140
140
|
const sameName = predicateGroups
|
|
@@ -145,17 +145,17 @@ export const globalPredicateChecks = (
|
|
|
145
145
|
if (sameName > 1) {
|
|
146
146
|
accept('error', `Duplicate GlobalPredicateGroup or GlobalDynamicPredicateGroup name '${node.name}'`, {
|
|
147
147
|
node: node,
|
|
148
|
-
property: 'name'
|
|
148
|
+
property: 'name',
|
|
149
149
|
})
|
|
150
150
|
}
|
|
151
|
-
}
|
|
151
|
+
})
|
|
152
152
|
}
|
|
153
153
|
|
|
154
154
|
export const globalStyleIdChecks = (
|
|
155
|
-
services: LikeC4Services
|
|
155
|
+
services: LikeC4Services,
|
|
156
156
|
): ValidationCheck<ast.GlobalStyleId> => {
|
|
157
157
|
const index = services.shared.workspace.IndexManager
|
|
158
|
-
return (node, accept) => {
|
|
158
|
+
return tryOrLog((node, accept) => {
|
|
159
159
|
const sameName = index
|
|
160
160
|
.allElements(ast.GlobalStyleId)
|
|
161
161
|
.filter(s => s.name === node.name)
|
|
@@ -164,8 +164,8 @@ export const globalStyleIdChecks = (
|
|
|
164
164
|
if (sameName > 1) {
|
|
165
165
|
accept('error', `Duplicate GlobalStyleId name '${node.name}'`, {
|
|
166
166
|
node: node,
|
|
167
|
-
property: 'name'
|
|
167
|
+
property: 'name',
|
|
168
168
|
})
|
|
169
169
|
}
|
|
170
|
-
}
|
|
170
|
+
})
|
|
171
171
|
}
|
|
@@ -3,15 +3,16 @@ import type { ValidationCheck } from 'langium'
|
|
|
3
3
|
import { AstUtils } from 'langium'
|
|
4
4
|
import { ast } from '../../ast'
|
|
5
5
|
import type { LikeC4Services } from '../../module'
|
|
6
|
+
import { tryOrLog } from '../_shared'
|
|
6
7
|
|
|
7
8
|
export const elementPredicateWithChecks = (
|
|
8
|
-
_services: LikeC4Services
|
|
9
|
+
_services: LikeC4Services,
|
|
9
10
|
): ValidationCheck<ast.ElementPredicateWith> => {
|
|
10
|
-
return (el, accept) => {
|
|
11
|
+
return tryOrLog((el, accept) => {
|
|
11
12
|
const container = AstUtils.getContainerOfType(el, ast.isViewRulePredicate)
|
|
12
13
|
if (ast.isExcludePredicate(container)) {
|
|
13
14
|
accept('error', 'Invalid usage inside "exclude"', {
|
|
14
|
-
node: el
|
|
15
|
+
node: el,
|
|
15
16
|
})
|
|
16
17
|
}
|
|
17
18
|
const subject = ast.isElementPredicateWhere(el.subject) ? el.subject.subject : el.subject
|
|
@@ -25,11 +26,11 @@ export const elementPredicateWithChecks = (
|
|
|
25
26
|
case ast.isElementTagExpression(subject):
|
|
26
27
|
accept('error', 'Invalid target (expect reference to specific element)', {
|
|
27
28
|
node: el,
|
|
28
|
-
property: 'subject'
|
|
29
|
+
property: 'subject',
|
|
29
30
|
})
|
|
30
31
|
return
|
|
31
32
|
default:
|
|
32
33
|
nonexhaustive(subject)
|
|
33
34
|
}
|
|
34
|
-
}
|
|
35
|
+
})
|
|
35
36
|
}
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type ValidationCheck, AstUtils } from 'langium'
|
|
2
2
|
import { ast } from '../../ast'
|
|
3
3
|
import type { LikeC4Services } from '../../module'
|
|
4
|
+
import { tryOrLog } from '../_shared'
|
|
4
5
|
|
|
5
6
|
export const expandElementExprChecks = (
|
|
6
|
-
_services: LikeC4Services
|
|
7
|
+
_services: LikeC4Services,
|
|
7
8
|
): ValidationCheck<ast.ExpandElementExpression> => {
|
|
8
|
-
return (el, accept) => {
|
|
9
|
+
return tryOrLog((el, accept) => {
|
|
9
10
|
if (AstUtils.hasContainerOfType(el, ast.isRelationExpression)) {
|
|
10
11
|
accept('warning', `Redundant usage, expand predicate resolves parent element only when used in relations`, {
|
|
11
|
-
node: el
|
|
12
|
+
node: el,
|
|
12
13
|
})
|
|
13
14
|
}
|
|
14
|
-
}
|
|
15
|
+
})
|
|
15
16
|
}
|