@likec4/language-server 1.21.0 → 1.22.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/README.md +4 -1
- package/bin/likec4-language-server.mjs +5 -2
- package/dist/LikeC4FileSystem.js +2 -2
- package/dist/browser.d.ts +3 -3
- package/dist/browser.js +17 -2
- package/dist/bundled.d.ts +8 -0
- package/dist/bundled.js +25 -0
- package/dist/bundled.mjs +2587 -4306
- package/dist/generated-lib/icons.js +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +23 -2
- package/dist/logger.d.ts +9 -3
- package/dist/logger.js +35 -55
- package/dist/model/fqn-computation.js +2 -2
- package/dist/model/model-builder.js +13 -14
- package/dist/model-change/ModelChanges.js +2 -2
- package/dist/module.js +1 -4
- package/dist/references/scope-provider.js +3 -3
- package/dist/view-utils/manual-layout.js +2 -2
- package/dist/views/configurable-layouter.js +4 -4
- package/dist/views/likec4-views.d.ts +2 -1
- package/dist/views/likec4-views.js +2 -2
- package/package.json +14 -14
- package/dist/test/setup.d.ts +0 -1
- package/dist/test/setup.js +0 -7
- package/src/LikeC4FileSystem.ts +0 -38
- package/src/Rpc.ts +0 -134
- package/src/ast.ts +0 -556
- package/src/browser.ts +0 -35
- package/src/documentation/documentation-provider.ts +0 -52
- package/src/documentation/index.ts +0 -1
- package/src/formatting/LikeC4Formatter.ts +0 -639
- package/src/formatting/utils.ts +0 -26
- package/src/generated/ast.ts +0 -3735
- package/src/generated/grammar.ts +0 -10
- package/src/generated/module.ts +0 -33
- package/src/generated-lib/icons.ts +0 -1537
- package/src/index.ts +0 -30
- package/src/like-c4.langium +0 -901
- package/src/likec4lib.ts +0 -6
- package/src/logger.ts +0 -80
- package/src/lsp/CodeLensProvider.ts +0 -50
- package/src/lsp/CompletionProvider.ts +0 -147
- package/src/lsp/DocumentHighlightProvider.ts +0 -12
- package/src/lsp/DocumentLinkProvider.ts +0 -65
- package/src/lsp/DocumentSymbolProvider.ts +0 -313
- package/src/lsp/HoverProvider.ts +0 -92
- package/src/lsp/RenameProvider.ts +0 -8
- package/src/lsp/SemanticTokenProvider.ts +0 -383
- package/src/lsp/index.ts +0 -8
- package/src/model/deployments-index.ts +0 -209
- package/src/model/fqn-computation.ts +0 -83
- package/src/model/fqn-index.ts +0 -138
- package/src/model/index.ts +0 -6
- package/src/model/model-builder.ts +0 -724
- package/src/model/model-locator.ts +0 -146
- package/src/model/model-parser-where.ts +0 -84
- package/src/model/model-parser.ts +0 -86
- package/src/model/parser/Base.ts +0 -113
- package/src/model/parser/DeploymentModelParser.ts +0 -192
- package/src/model/parser/DeploymentViewParser.ts +0 -122
- package/src/model/parser/FqnRefParser.ts +0 -143
- package/src/model/parser/GlobalsParser.ts +0 -96
- package/src/model/parser/ModelParser.ts +0 -170
- package/src/model/parser/PredicatesParser.ts +0 -315
- package/src/model/parser/SpecificationParser.ts +0 -133
- package/src/model/parser/ViewsParser.ts +0 -428
- package/src/model-change/ModelChanges.ts +0 -101
- package/src/model-change/changeElementStyle.ts +0 -172
- package/src/model-change/changeViewLayout.ts +0 -47
- package/src/model-change/saveManualLayout.ts +0 -41
- package/src/module.ts +0 -255
- package/src/protocol.ts +0 -93
- package/src/references/index.ts +0 -3
- package/src/references/name-provider.ts +0 -37
- package/src/references/scope-computation.ts +0 -364
- package/src/references/scope-provider.ts +0 -201
- package/src/shared/NodeKindProvider.ts +0 -121
- package/src/shared/WorkspaceManager.ts +0 -48
- package/src/shared/WorkspaceSymbolProvider.ts +0 -3
- package/src/shared/index.ts +0 -3
- package/src/test/index.ts +0 -1
- package/src/test/setup.ts +0 -8
- package/src/test/testServices.ts +0 -152
- package/src/utils/disposable.ts +0 -30
- package/src/utils/elementRef.ts +0 -26
- package/src/utils/fqnRef.ts +0 -56
- package/src/utils/index.ts +0 -2
- package/src/utils/printDocs.ts +0 -3
- package/src/utils/stringHash.ts +0 -6
- package/src/validation/_shared.ts +0 -29
- package/src/validation/deployment-checks.ts +0 -131
- package/src/validation/dynamic-view-rule.ts +0 -23
- package/src/validation/dynamic-view-step.ts +0 -36
- package/src/validation/element.ts +0 -56
- package/src/validation/index.ts +0 -171
- package/src/validation/property-checks.ts +0 -52
- package/src/validation/relation.ts +0 -63
- package/src/validation/specification.ts +0 -205
- package/src/validation/view-predicates/element-with.ts +0 -36
- package/src/validation/view-predicates/expanded-element.ts +0 -16
- package/src/validation/view-predicates/expression-v2.ts +0 -101
- package/src/validation/view-predicates/incoming.ts +0 -20
- package/src/validation/view-predicates/index.ts +0 -6
- package/src/validation/view-predicates/outgoing.ts +0 -20
- package/src/validation/view-predicates/relation-with.ts +0 -17
- package/src/validation/view.ts +0 -37
- package/src/view-utils/assignNavigateTo.ts +0 -31
- package/src/view-utils/index.ts +0 -2
- package/src/view-utils/manual-layout.ts +0 -116
- package/src/view-utils/resolve-relative-paths.ts +0 -90
- package/src/views/configurable-layouter.ts +0 -65
- package/src/views/index.ts +0 -1
- package/src/views/likec4-views.ts +0 -139
|
@@ -1,364 +0,0 @@
|
|
|
1
|
-
import { nonexhaustive } from '@likec4/core'
|
|
2
|
-
import {
|
|
3
|
-
type AstNode,
|
|
4
|
-
type AstNodeDescription,
|
|
5
|
-
type PrecomputedScopes,
|
|
6
|
-
DefaultScopeComputation,
|
|
7
|
-
MultiMap,
|
|
8
|
-
} from 'langium'
|
|
9
|
-
import { entries, filter, flatMap, forEachObj, groupBy, isNullish, isTruthy, pipe } from 'remeda'
|
|
10
|
-
import type { CancellationToken } from 'vscode-languageserver'
|
|
11
|
-
import { type LikeC4LangiumDocument, ast } from '../ast'
|
|
12
|
-
import { logWarnError } from '../logger'
|
|
13
|
-
import type { LikeC4Services } from '../module'
|
|
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
|
-
}
|
|
28
|
-
|
|
29
|
-
export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
30
|
-
constructor(services: LikeC4Services) {
|
|
31
|
-
super(services)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
override async computeExports(
|
|
35
|
-
document: LikeC4LangiumDocument,
|
|
36
|
-
_cancelToken?: CancellationToken,
|
|
37
|
-
): Promise<AstNodeDescription[]> {
|
|
38
|
-
const docExports: AstNodeDescription[] = []
|
|
39
|
-
try {
|
|
40
|
-
const { specifications, models, views, globals, likec4lib, deployments } = document.parseResult.value
|
|
41
|
-
|
|
42
|
-
// Process library
|
|
43
|
-
this.exportLibrary(likec4lib, docExports, document)
|
|
44
|
-
|
|
45
|
-
// Process specification
|
|
46
|
-
this.exportSpecification(specifications, docExports, document)
|
|
47
|
-
|
|
48
|
-
// Process models
|
|
49
|
-
this.exportModel(models, docExports, document)
|
|
50
|
-
|
|
51
|
-
// Process views
|
|
52
|
-
this.exportViews(views, docExports, document)
|
|
53
|
-
|
|
54
|
-
// Process global
|
|
55
|
-
this.exportGlobals(globals, docExports, document)
|
|
56
|
-
|
|
57
|
-
this.exportDeployments(deployments, docExports, document)
|
|
58
|
-
} catch (e) {
|
|
59
|
-
logWarnError(e)
|
|
60
|
-
}
|
|
61
|
-
return docExports
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
private exportViews(
|
|
65
|
-
modelViews: ast.ModelViews[] | undefined,
|
|
66
|
-
docExports: AstNodeDescription[],
|
|
67
|
-
document: LikeC4LangiumDocument,
|
|
68
|
-
) {
|
|
69
|
-
const views = modelViews?.flatMap(m => m.views)
|
|
70
|
-
if (isNullish(views) || views.length === 0) {
|
|
71
|
-
return
|
|
72
|
-
}
|
|
73
|
-
for (const viewAst of views) {
|
|
74
|
-
try {
|
|
75
|
-
if (isTruthy(viewAst.name)) {
|
|
76
|
-
docExports.push(this.descriptions.createDescription(viewAst, viewAst.name, document))
|
|
77
|
-
}
|
|
78
|
-
} catch (e) {
|
|
79
|
-
logWarnError(e)
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
private exportGlobals(
|
|
85
|
-
globals: ast.Globals[] | undefined,
|
|
86
|
-
docExports: AstNodeDescription[],
|
|
87
|
-
document: LikeC4LangiumDocument,
|
|
88
|
-
) {
|
|
89
|
-
if (isNullish(globals) || globals.length === 0) {
|
|
90
|
-
return
|
|
91
|
-
}
|
|
92
|
-
for (const globalPredicateAst of globals.flatMap(g => g.predicates)) {
|
|
93
|
-
try {
|
|
94
|
-
const id = globalPredicateAst
|
|
95
|
-
if (isTruthy(id.name)) {
|
|
96
|
-
docExports.push(this.descriptions.createDescription(id, id.name, document))
|
|
97
|
-
}
|
|
98
|
-
} catch (e) {
|
|
99
|
-
logWarnError(e)
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
for (const globalStyleAst of globals.flatMap(g => g.styles)) {
|
|
103
|
-
try {
|
|
104
|
-
const id = globalStyleAst.id
|
|
105
|
-
if (isTruthy(id.name)) {
|
|
106
|
-
docExports.push(this.descriptions.createDescription(id, id.name, document))
|
|
107
|
-
}
|
|
108
|
-
} catch (e) {
|
|
109
|
-
logWarnError(e)
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
private exportModel(
|
|
115
|
-
models: ast.Model[] | undefined,
|
|
116
|
-
docExports: AstNodeDescription[],
|
|
117
|
-
document: LikeC4LangiumDocument,
|
|
118
|
-
) {
|
|
119
|
-
if (isNullish(models) || models.length === 0) {
|
|
120
|
-
return
|
|
121
|
-
}
|
|
122
|
-
for (const elAst of models.flatMap(m => m.elements)) {
|
|
123
|
-
try {
|
|
124
|
-
if (ast.isElement(elAst) && isTruthy(elAst.name)) {
|
|
125
|
-
docExports.push(this.descriptions.createDescription(elAst, elAst.name, document))
|
|
126
|
-
}
|
|
127
|
-
} catch (e) {
|
|
128
|
-
logWarnError(e)
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
private exportLibrary(
|
|
134
|
-
likec4lib: ast.LikeC4Lib[] | undefined,
|
|
135
|
-
docExports: AstNodeDescription[],
|
|
136
|
-
document: LikeC4LangiumDocument,
|
|
137
|
-
) {
|
|
138
|
-
if (isNullish(likec4lib)) {
|
|
139
|
-
return
|
|
140
|
-
}
|
|
141
|
-
try {
|
|
142
|
-
for (const iconAst of likec4lib.flatMap(l => l.icons)) {
|
|
143
|
-
docExports.push(this.descriptions.createDescription(iconAst, iconAst.name, document))
|
|
144
|
-
}
|
|
145
|
-
} catch (e) {
|
|
146
|
-
logWarnError(e)
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
private exportSpecification(
|
|
151
|
-
specifications: ast.SpecificationRule[] | undefined,
|
|
152
|
-
docExports: AstNodeDescription[],
|
|
153
|
-
document: LikeC4LangiumDocument,
|
|
154
|
-
) {
|
|
155
|
-
if (isNullish(specifications) || specifications.length === 0) {
|
|
156
|
-
return
|
|
157
|
-
}
|
|
158
|
-
for (
|
|
159
|
-
const spec of specifications.flatMap(s => [
|
|
160
|
-
...s.elements,
|
|
161
|
-
...s.relationships,
|
|
162
|
-
...s.deploymentNodes,
|
|
163
|
-
...s.tags,
|
|
164
|
-
...s.colors,
|
|
165
|
-
])
|
|
166
|
-
) {
|
|
167
|
-
try {
|
|
168
|
-
switch (true) {
|
|
169
|
-
case ast.isSpecificationDeploymentNodeKind(spec):
|
|
170
|
-
case ast.isSpecificationElementKind(spec): {
|
|
171
|
-
if (isTruthy(spec.kind.name)) {
|
|
172
|
-
docExports.push(
|
|
173
|
-
this.descriptions.createDescription(spec.kind, spec.kind.name, document),
|
|
174
|
-
)
|
|
175
|
-
}
|
|
176
|
-
continue
|
|
177
|
-
}
|
|
178
|
-
case ast.isSpecificationTag(spec): {
|
|
179
|
-
if (isTruthy(spec.tag.name)) {
|
|
180
|
-
docExports.push(
|
|
181
|
-
this.descriptions.createDescription(spec.tag, '#' + spec.tag.name, document),
|
|
182
|
-
)
|
|
183
|
-
}
|
|
184
|
-
continue
|
|
185
|
-
}
|
|
186
|
-
case ast.isSpecificationRelationshipKind(spec): {
|
|
187
|
-
if (isTruthy(spec.kind.name)) {
|
|
188
|
-
docExports.push(
|
|
189
|
-
this.descriptions.createDescription(spec.kind, spec.kind.name, document),
|
|
190
|
-
this.descriptions.createDescription(spec.kind, '.' + spec.kind.name, document),
|
|
191
|
-
)
|
|
192
|
-
}
|
|
193
|
-
continue
|
|
194
|
-
}
|
|
195
|
-
case ast.isSpecificationColor(spec): {
|
|
196
|
-
if (isTruthy(spec.name.name)) {
|
|
197
|
-
docExports.push(
|
|
198
|
-
this.descriptions.createDescription(spec.name, spec.name.name, document),
|
|
199
|
-
)
|
|
200
|
-
}
|
|
201
|
-
continue
|
|
202
|
-
}
|
|
203
|
-
// Thow error if not exhaustive
|
|
204
|
-
default:
|
|
205
|
-
nonexhaustive(spec)
|
|
206
|
-
}
|
|
207
|
-
} catch (e) {
|
|
208
|
-
logWarnError(e)
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
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
|
-
|
|
233
|
-
override computeLocalScopes(
|
|
234
|
-
document: LikeC4LangiumDocument,
|
|
235
|
-
_cancelToken?: CancellationToken,
|
|
236
|
-
): Promise<PrecomputedScopes> {
|
|
237
|
-
return new Promise(resolve => {
|
|
238
|
-
const root = document.parseResult.value
|
|
239
|
-
const descendants = [] as AstNodeDescription[]
|
|
240
|
-
const scopes = new MultiMap<AstNode, AstNodeDescription>()
|
|
241
|
-
|
|
242
|
-
for (const model of root.models) {
|
|
243
|
-
try {
|
|
244
|
-
descendants.push(
|
|
245
|
-
...this.processContainer(model, scopes, document),
|
|
246
|
-
)
|
|
247
|
-
} catch (e) {
|
|
248
|
-
logWarnError(e)
|
|
249
|
-
}
|
|
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
|
-
|
|
265
|
-
resolve(scopes)
|
|
266
|
-
})
|
|
267
|
-
}
|
|
268
|
-
|
|
269
|
-
protected processContainer(
|
|
270
|
-
container: ElementsContainer,
|
|
271
|
-
scopes: PrecomputedScopes,
|
|
272
|
-
document: LikeC4LangiumDocument,
|
|
273
|
-
): AstNodeDescription[] {
|
|
274
|
-
const localScope = new MultiMap<string, AstNodeDescription>()
|
|
275
|
-
const descedants = [] as AstNodeDescription[]
|
|
276
|
-
|
|
277
|
-
for (const el of container.elements) {
|
|
278
|
-
if (ast.isRelation(el)) {
|
|
279
|
-
continue
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
let subcontainer
|
|
283
|
-
if (ast.isElement(el)) {
|
|
284
|
-
if (isTruthy(el.name)) {
|
|
285
|
-
localScope.add(el.name, this.descriptions.createDescription(el, el.name, document))
|
|
286
|
-
}
|
|
287
|
-
subcontainer = el.body
|
|
288
|
-
} else if (ast.isExtendElement(el)) {
|
|
289
|
-
subcontainer = el.body
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
if (subcontainer && subcontainer.elements.length > 0) {
|
|
293
|
-
try {
|
|
294
|
-
descedants.push(
|
|
295
|
-
...this.processContainer(subcontainer, scopes, document),
|
|
296
|
-
)
|
|
297
|
-
} catch (e) {
|
|
298
|
-
logWarnError(e)
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
|
|
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)
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
}
|
|
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()]
|
|
363
|
-
}
|
|
364
|
-
}
|
|
@@ -1,201 +0,0 @@
|
|
|
1
|
-
import type * as c4 from '@likec4/core'
|
|
2
|
-
import { nonexhaustive } from '@likec4/core'
|
|
3
|
-
import type { AstNode } from 'langium'
|
|
4
|
-
import {
|
|
5
|
-
type AstNodeDescription,
|
|
6
|
-
type ReferenceInfo,
|
|
7
|
-
type Scope,
|
|
8
|
-
type Stream,
|
|
9
|
-
AstUtils,
|
|
10
|
-
DefaultScopeProvider,
|
|
11
|
-
DONE_RESULT,
|
|
12
|
-
EMPTY_SCOPE,
|
|
13
|
-
EMPTY_STREAM,
|
|
14
|
-
MapScope,
|
|
15
|
-
stream,
|
|
16
|
-
StreamImpl,
|
|
17
|
-
StreamScope,
|
|
18
|
-
} from 'langium'
|
|
19
|
-
import { ast } from '../ast'
|
|
20
|
-
import { logger } from '../logger'
|
|
21
|
-
import type { DeploymentsIndex, FqnIndex } from '../model'
|
|
22
|
-
import type { LikeC4Services } from '../module'
|
|
23
|
-
import { elementRef, getFqnElementRef } from '../utils/elementRef'
|
|
24
|
-
|
|
25
|
-
const { getDocument } = AstUtils
|
|
26
|
-
|
|
27
|
-
export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
28
|
-
private deploymentsIndex: DeploymentsIndex
|
|
29
|
-
private fqnIndex: FqnIndex
|
|
30
|
-
|
|
31
|
-
constructor(services: LikeC4Services) {
|
|
32
|
-
super(services)
|
|
33
|
-
this.fqnIndex = services.likec4.FqnIndex
|
|
34
|
-
this.deploymentsIndex = services.likec4.DeploymentsIndex
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
private directChildrenOf(parent: c4.Fqn): Stream<AstNodeDescription> {
|
|
38
|
-
return this.fqnIndex.directChildrenOf(parent)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// we need lazy resolving here
|
|
42
|
-
private uniqueDescedants(of: () => ast.Element | undefined): Stream<AstNodeDescription> {
|
|
43
|
-
return new StreamImpl(
|
|
44
|
-
() => {
|
|
45
|
-
const element = of()
|
|
46
|
-
const fqn = element && this.fqnIndex.getFqn(element)
|
|
47
|
-
if (fqn) {
|
|
48
|
-
return this.fqnIndex.uniqueDescedants(fqn).iterator()
|
|
49
|
-
}
|
|
50
|
-
return null
|
|
51
|
-
},
|
|
52
|
-
iterator => {
|
|
53
|
-
if (iterator) {
|
|
54
|
-
return iterator.next()
|
|
55
|
-
}
|
|
56
|
-
return DONE_RESULT
|
|
57
|
-
},
|
|
58
|
-
)
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
private scopeElementRef(ref: ast.ElementRef): Stream<AstNodeDescription> {
|
|
62
|
-
return this.uniqueDescedants(() => ref.el.ref)
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
private scopeExtendElement({ element }: ast.ExtendElement): Stream<AstNodeDescription> {
|
|
66
|
-
// we make extended element resolvable inside ExtendElementBody
|
|
67
|
-
return stream([element.el.$nodeDescription])
|
|
68
|
-
.nonNullable()
|
|
69
|
-
.concat(this.uniqueDescedants(() => elementRef(element)))
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
private scopeElementView({ viewOf, extends: ext }: ast.ElementView): Stream<AstNodeDescription> {
|
|
73
|
-
if (viewOf) {
|
|
74
|
-
// If we have "view of parent.target"
|
|
75
|
-
// we make "target" resolvable inside ElementView
|
|
76
|
-
return stream([viewOf.el.$nodeDescription])
|
|
77
|
-
.nonNullable()
|
|
78
|
-
.concat(this.uniqueDescedants(() => elementRef(viewOf)))
|
|
79
|
-
}
|
|
80
|
-
if (ext) {
|
|
81
|
-
return stream([ext]).flatMap(v => {
|
|
82
|
-
const view = v.view.ref
|
|
83
|
-
return view ? this.scopeElementView(view) : EMPTY_STREAM
|
|
84
|
-
})
|
|
85
|
-
}
|
|
86
|
-
return EMPTY_STREAM
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
override getScope(context: ReferenceInfo): Scope {
|
|
90
|
-
try {
|
|
91
|
-
const referenceType = this.reflection.getReferenceType(context)
|
|
92
|
-
try {
|
|
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
|
-
|
|
102
|
-
if (ast.isStrictFqnElementRef(container) && context.property === 'el') {
|
|
103
|
-
const parent = container.parent
|
|
104
|
-
if (!parent) {
|
|
105
|
-
return this.getGlobalScope(referenceType, context)
|
|
106
|
-
}
|
|
107
|
-
return new StreamScope(this.directChildrenOf(getFqnElementRef(parent)))
|
|
108
|
-
}
|
|
109
|
-
if (ast.isElementRef(container) && context.property === 'el') {
|
|
110
|
-
const parent = container.parent
|
|
111
|
-
if (parent) {
|
|
112
|
-
return new StreamScope(this.scopeElementRef(parent))
|
|
113
|
-
}
|
|
114
|
-
// if we have elementRef "this" or "it" we resolve it to the closest element
|
|
115
|
-
if (context.reference.$refText === 'this' || context.reference.$refText === 'it') {
|
|
116
|
-
const closestElement = AstUtils.getContainerOfType(container, ast.isElement)
|
|
117
|
-
if (closestElement) {
|
|
118
|
-
return new MapScope([
|
|
119
|
-
this.descriptions.createDescription(closestElement, context.reference.$refText),
|
|
120
|
-
])
|
|
121
|
-
} else {
|
|
122
|
-
return EMPTY_SCOPE
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
return this.computeScope(context)
|
|
127
|
-
} catch (e) {
|
|
128
|
-
logger.warn(e)
|
|
129
|
-
return this.getGlobalScope(referenceType, context)
|
|
130
|
-
}
|
|
131
|
-
} catch (e) {
|
|
132
|
-
logger.warn(e)
|
|
133
|
-
return EMPTY_SCOPE
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
|
|
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
|
-
|
|
172
|
-
const scopes: Stream<AstNodeDescription>[] = []
|
|
173
|
-
const doc = getDocument(context.container)
|
|
174
|
-
const precomputed = doc.precomputedScopes
|
|
175
|
-
|
|
176
|
-
if (!precomputed) {
|
|
177
|
-
return this.getGlobalScope(referenceType, context)
|
|
178
|
-
}
|
|
179
|
-
|
|
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))
|
|
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
|
|
195
|
-
}
|
|
196
|
-
|
|
197
|
-
return scopes.reduceRight((outerScope, elements) => {
|
|
198
|
-
return this.createScope(elements, outerScope)
|
|
199
|
-
}, this.getGlobalScope(referenceType, context))
|
|
200
|
-
}
|
|
201
|
-
}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import { type AstNode, type AstNodeDescription, isAstNode } from 'langium'
|
|
2
|
-
import type { LangiumSharedServices, NodeKindProvider as LspNodeKindProvider } from 'langium/lsp'
|
|
3
|
-
import { CompletionItemKind, SymbolKind } from 'vscode-languageserver-types'
|
|
4
|
-
import { ast } from '../ast'
|
|
5
|
-
|
|
6
|
-
export class NodeKindProvider implements LspNodeKindProvider {
|
|
7
|
-
constructor(private services: LangiumSharedServices) {}
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Returns a `SymbolKind` as used by `WorkspaceSymbolProvider` or `DocumentSymbolProvider`.
|
|
11
|
-
*/
|
|
12
|
-
// prettier-ignore
|
|
13
|
-
getSymbolKind(node: AstNode | AstNodeDescription): SymbolKind {
|
|
14
|
-
const nodeType = isAstNode(node) ? node.$type : node.type
|
|
15
|
-
const hasType = (...types: string[]) => types.some(t => this.services.AstReflection.isSubtype(nodeType, t))
|
|
16
|
-
switch (true) {
|
|
17
|
-
case hasType(
|
|
18
|
-
ast.Element,
|
|
19
|
-
ast.ExtendElement,
|
|
20
|
-
ast.DeploymentNode,
|
|
21
|
-
ast.DeployedInstance
|
|
22
|
-
):
|
|
23
|
-
return SymbolKind.Constructor
|
|
24
|
-
|
|
25
|
-
case hasType(
|
|
26
|
-
ast.Model,
|
|
27
|
-
ast.ModelViews,
|
|
28
|
-
ast.ModelDeployments,
|
|
29
|
-
ast.Globals,
|
|
30
|
-
ast.SpecificationRule
|
|
31
|
-
):
|
|
32
|
-
return SymbolKind.Namespace
|
|
33
|
-
|
|
34
|
-
case hasType(ast.LikeC4View):
|
|
35
|
-
return SymbolKind.Class
|
|
36
|
-
|
|
37
|
-
case hasType(
|
|
38
|
-
ast.Tag,
|
|
39
|
-
ast.LibIcon,
|
|
40
|
-
ast.CustomColor,
|
|
41
|
-
ast.SpecificationTag
|
|
42
|
-
):
|
|
43
|
-
return SymbolKind.EnumMember
|
|
44
|
-
|
|
45
|
-
case hasType(
|
|
46
|
-
ast.RelationshipKind,
|
|
47
|
-
ast.SpecificationRelationshipKind
|
|
48
|
-
):
|
|
49
|
-
return SymbolKind.Event
|
|
50
|
-
|
|
51
|
-
case hasType(
|
|
52
|
-
ast.ElementKind,
|
|
53
|
-
ast.DeploymentNodeKind,
|
|
54
|
-
ast.SpecificationElementKind,
|
|
55
|
-
ast.SpecificationDeploymentNodeKind
|
|
56
|
-
):
|
|
57
|
-
return SymbolKind.TypeParameter
|
|
58
|
-
}
|
|
59
|
-
return SymbolKind.Field
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Returns a `CompletionItemKind` as used by the `CompletionProvider`.
|
|
63
|
-
*/
|
|
64
|
-
getCompletionItemKind(node: AstNode | AstNodeDescription): CompletionItemKind {
|
|
65
|
-
const nodeType = isAstNode(node) ? node.$type : node.type
|
|
66
|
-
const hasType = (...types: string[]) => types.some(t => this.services.AstReflection.isSubtype(nodeType, t))
|
|
67
|
-
switch (true) {
|
|
68
|
-
case hasType(
|
|
69
|
-
ast.CustomColor
|
|
70
|
-
):
|
|
71
|
-
return CompletionItemKind.Color
|
|
72
|
-
|
|
73
|
-
case hasType(
|
|
74
|
-
ast.Element,
|
|
75
|
-
ast.DeploymentNode,
|
|
76
|
-
ast.DeployedInstance,
|
|
77
|
-
ast.ExtendElement
|
|
78
|
-
):
|
|
79
|
-
return CompletionItemKind.Constructor
|
|
80
|
-
|
|
81
|
-
case hasType(
|
|
82
|
-
ast.Model,
|
|
83
|
-
ast.ModelViews,
|
|
84
|
-
ast.ModelDeployments,
|
|
85
|
-
ast.Globals,
|
|
86
|
-
ast.SpecificationRule
|
|
87
|
-
):
|
|
88
|
-
return CompletionItemKind.Module
|
|
89
|
-
|
|
90
|
-
case hasType(
|
|
91
|
-
ast.LikeC4View
|
|
92
|
-
):
|
|
93
|
-
return CompletionItemKind.Class
|
|
94
|
-
|
|
95
|
-
case hasType(
|
|
96
|
-
ast.Tag,
|
|
97
|
-
ast.LibIcon,
|
|
98
|
-
ast.CustomColor,
|
|
99
|
-
ast.SpecificationTag
|
|
100
|
-
):
|
|
101
|
-
return CompletionItemKind.EnumMember
|
|
102
|
-
|
|
103
|
-
case hasType(
|
|
104
|
-
ast.RelationshipKind,
|
|
105
|
-
ast.SpecificationRelationshipKind
|
|
106
|
-
):
|
|
107
|
-
return CompletionItemKind.Event
|
|
108
|
-
|
|
109
|
-
case hasType(
|
|
110
|
-
ast.ElementKind,
|
|
111
|
-
ast.SpecificationElementKind,
|
|
112
|
-
ast.DeploymentNodeKind,
|
|
113
|
-
ast.SpecificationDeploymentNodeKind
|
|
114
|
-
):
|
|
115
|
-
return CompletionItemKind.TypeParameter
|
|
116
|
-
|
|
117
|
-
default:
|
|
118
|
-
return CompletionItemKind.Reference
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|