@likec4/language-server 1.16.0 → 1.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/dist/browser.cjs +1 -1
  2. package/dist/browser.d.cts +2 -2
  3. package/dist/browser.d.mts +2 -2
  4. package/dist/browser.d.ts +2 -2
  5. package/dist/browser.mjs +2 -2
  6. package/dist/index.cjs +35 -5
  7. package/dist/index.d.cts +17 -4
  8. package/dist/index.d.mts +17 -4
  9. package/dist/index.d.ts +17 -4
  10. package/dist/index.mjs +34 -5
  11. package/dist/model-graph/index.cjs +1 -1
  12. package/dist/model-graph/index.mjs +1 -1
  13. package/dist/shared/{language-server.D_13fWJQ.mjs → language-server.BIbAD1T-.mjs} +43 -16
  14. package/dist/shared/{language-server.CnkCWVtf.d.cts → language-server.BQRvVmE0.d.cts} +3 -38
  15. package/dist/shared/{language-server.7iILaJYc.d.ts → language-server.BysPcTxr.d.ts} +3 -38
  16. package/dist/shared/{language-server.Bd3NZ8uH.cjs → language-server.D2QdbOJO.cjs} +54 -14
  17. package/dist/shared/{language-server.C5gxpVUH.mjs → language-server.DGrBGmsd.mjs} +55 -15
  18. package/dist/shared/{language-server.Dym6GL4P.cjs → language-server.DKV_FdPN.cjs} +43 -16
  19. package/dist/shared/{language-server.DIaiY0-C.d.mts → language-server._wkyPgso.d.mts} +3 -38
  20. package/package.json +16 -16
  21. package/src/LikeC4FileSystem.ts +36 -0
  22. package/src/Rpc.ts +2 -2
  23. package/src/formatting/LikeC4Formatter.ts +9 -4
  24. package/src/generated/ast.ts +2 -2
  25. package/src/generated/grammar.ts +2 -2
  26. package/src/generated/module.ts +3 -2
  27. package/src/index.ts +3 -3
  28. package/src/like-c4.langium +1 -1
  29. package/src/lsp/SemanticTokenProvider.ts +26 -8
  30. package/src/model/fqn-computation.ts +6 -2
  31. package/src/model-graph/compute-view/__test__/fixture.ts +6 -0
  32. package/src/model-graph/compute-view/compute.ts +9 -2
  33. package/src/model-graph/dynamic-view/compute.ts +55 -16
  34. package/src/model-graph/utils/applyCustomElementProperties.ts +1 -3
  35. package/dist/shared/language-server.CmBZHwSl.d.cts +0 -1338
  36. package/dist/shared/language-server.DViE1Zxi.d.mts +0 -1338
  37. package/dist/shared/language-server.DwyQ1FtY.d.ts +0 -1338
@@ -1,5 +1,5 @@
1
1
  /******************************************************************************
2
- * This file was generated by langium-cli 3.2.0.
2
+ * This file was generated by langium-cli 3.3.0.
3
3
  * DO NOT EDIT MANUALLY!
4
4
  ******************************************************************************/
5
5
 
@@ -10,7 +10,8 @@ import { LikeC4Grammar } from './grammar';
10
10
  export const LikeC4LanguageMetaData = {
11
11
  languageId: 'likec4',
12
12
  fileExtensions: ['.c4', '.likec4', '.like-c4'],
13
- caseInsensitive: false
13
+ caseInsensitive: false,
14
+ mode: 'production'
14
15
  } as const satisfies LanguageMetaData;
15
16
 
16
17
  export const parserConfig: IParserConfig = {
package/src/index.ts CHANGED
@@ -1,19 +1,19 @@
1
1
  import { startLanguageServer as startLanguim } from 'langium/lsp'
2
- import { NodeFileSystem } from 'langium/node'
3
2
  import { createConnection, ProposedFeatures } from 'vscode-languageserver/node'
3
+ import { LikeC4FileSystem } from './LikeC4FileSystem'
4
4
  import { createLanguageServices } from './module'
5
5
 
6
6
  export { logger as lspLogger, setLogLevel } from './logger'
7
7
  export type * from './model'
8
8
  export type * from './module'
9
9
  export { createCustomLanguageServices, createLanguageServices, LikeC4Module } from './module'
10
-
10
+ export { LikeC4FileSystem }
11
11
  export function startLanguageServer() {
12
12
  /* browser specific setup code */
13
13
  const connection = createConnection(ProposedFeatures.all)
14
14
 
15
15
  // Inject the shared services and language-specific services
16
- const services = createLanguageServices({ connection, ...NodeFileSystem })
16
+ const services = createLanguageServices({ connection, ...LikeC4FileSystem })
17
17
 
18
18
  // Start the language server with the shared services
19
19
  startLanguim(services.shared)
@@ -557,7 +557,7 @@ OpacityProperty:
557
557
 
558
558
  // Element properties -------------------------------------
559
559
  IconProperty:
560
- key='icon' ':'? (libicon=[LibIcon:IconId] | value=Uri) ';'?;
560
+ key='icon' ':'? (libicon=[LibIcon:IconId] | value=('none'|Uri)) ';'?;
561
561
 
562
562
  ShapeProperty:
563
563
  key='shape' ':'? value=ElementShape ';'?;
@@ -196,6 +196,32 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
196
196
  property: 'key',
197
197
  type: SemanticTokenTypes.property
198
198
  })
199
+ if (ast.isIconProperty(node)) {
200
+ if (node.libicon) {
201
+ acceptor({
202
+ node,
203
+ property: 'libicon',
204
+ type: SemanticTokenTypes.enum,
205
+ modifier: [SemanticTokenModifiers.defaultLibrary]
206
+ })
207
+ } else {
208
+ if (node.value === 'none') {
209
+ acceptor({
210
+ node,
211
+ property: 'value',
212
+ type: SemanticTokenTypes.enum,
213
+ modifier: [SemanticTokenModifiers.defaultLibrary]
214
+ })
215
+ } else {
216
+ acceptor({
217
+ node,
218
+ property: 'value',
219
+ type: SemanticTokenTypes.string
220
+ })
221
+ }
222
+ }
223
+ return 'prune'
224
+ }
199
225
  if ('value' in node && node.value) {
200
226
  acceptor({
201
227
  node,
@@ -203,14 +229,6 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
203
229
  type: SemanticTokenTypes.string
204
230
  })
205
231
  }
206
- if (ast.isIconProperty(node) && node.libicon) {
207
- acceptor({
208
- node,
209
- property: 'libicon',
210
- type: SemanticTokenTypes.enum,
211
- modifier: [SemanticTokenModifiers.defaultLibrary]
212
- })
213
- }
214
232
  return 'prune'
215
233
  }
216
234
  if (
@@ -52,7 +52,9 @@ export function computeDocumentFqn(document: LikeC4LangiumDocument, services: Li
52
52
  if (isDefined(el.body) && !isEmpty(el.body.elements)) {
53
53
  const fqn = getFqnElementRef(el.element)
54
54
  for (const child of el.body.elements) {
55
- traverseStack.push([child, fqn])
55
+ if (!ast.isRelation(child)) {
56
+ traverseStack.push([child, fqn])
57
+ }
56
58
  }
57
59
  }
58
60
  continue
@@ -66,7 +68,9 @@ export function computeDocumentFqn(document: LikeC4LangiumDocument, services: Li
66
68
  ElementOps.writeId(el, fqn)
67
69
  if (isDefined(el.body) && !isEmpty(el.body.elements)) {
68
70
  for (const child of el.body.elements) {
69
- traverseStack.push([child, fqn])
71
+ if (!ast.isRelation(child)) {
72
+ traverseStack.push([child, fqn])
73
+ }
70
74
  }
71
75
  }
72
76
  continue
@@ -12,6 +12,7 @@ import {
12
12
  type Expression as C4Expression,
13
13
  type Fqn,
14
14
  type GlobalStyleID,
15
+ type IconUrl,
15
16
  type IncomingExpr as C4IncomingExpr,
16
17
  type InOutExpr as C4InOutExpr,
17
18
  isElementRef,
@@ -163,6 +164,7 @@ export const fakeElements = {
163
164
  id: 'cloud',
164
165
  kind: 'system',
165
166
  title: 'cloud',
167
+ icon: 'none',
166
168
  tags: ['next', 'old']
167
169
  }),
168
170
  'cloud.backend': el({
@@ -179,6 +181,7 @@ export const fakeElements = {
179
181
  'cloud.backend.graphql': el({
180
182
  id: 'cloud.backend.graphql',
181
183
  kind: 'component',
184
+ icon: 'tech:graphql' as IconUrl,
182
185
  title: 'graphql'
183
186
  }),
184
187
  'email': el({
@@ -202,12 +205,14 @@ export const fakeElements = {
202
205
  id: 'cloud.frontend.dashboard',
203
206
  kind: 'component',
204
207
  title: 'dashboard',
208
+ icon: 'tech:react' as IconUrl,
205
209
  tags: ['next']
206
210
  }),
207
211
  'amazon': el({
208
212
  id: 'amazon',
209
213
  kind: 'system',
210
214
  title: 'amazon',
215
+ icon: 'tech:aws' as IconUrl,
211
216
  tags: ['aws']
212
217
  }),
213
218
  'amazon.s3': el({
@@ -215,6 +220,7 @@ export const fakeElements = {
215
220
  kind: 'component',
216
221
  title: 's3',
217
222
  shape: 'storage',
223
+ icon: 'aws:s3' as IconUrl,
218
224
  tags: ['aws', 'storage']
219
225
  })
220
226
  } satisfies Record<string, Element>
@@ -181,7 +181,7 @@ export class ComputeCtx {
181
181
 
182
182
  protected get activeGroup() {
183
183
  return this.activeGroupStack[0] ?? this.__rootGroup
184
- }
184
+ }
185
185
 
186
186
  protected get includedElements() {
187
187
  return new Set([
@@ -283,7 +283,14 @@ export class ComputeCtx {
283
283
  ...(autoLayoutRule?.nodeSep && { nodeSep: autoLayoutRule.nodeSep }),
284
284
  ...(autoLayoutRule?.rankSep && { rankSep: autoLayoutRule.rankSep })
285
285
  },
286
- nodes: map(nodes, omit(['notation'])),
286
+ nodes: map(nodes, n => {
287
+ // omit notation
288
+ delete n.notation
289
+ if (n.icon === 'none') {
290
+ delete n.icon
291
+ }
292
+ return n
293
+ }),
287
294
  edges: applyCustomRelationProperties(rules, nodes, sortedEdges),
288
295
  ...(elementNotations.length > 0 && {
289
296
  notation: {
@@ -91,7 +91,12 @@ export class DynamicViewComputeCtx {
91
91
  title,
92
92
  relations,
93
93
  tags,
94
- navigateTo: derivedNavigateTo
94
+ navigateTo: derivedNavigateTo,
95
+ head,
96
+ tail,
97
+ color,
98
+ line,
99
+ notation
95
100
  } = this.findRelations(source, target)
96
101
 
97
102
  const navigateTo = isTruthy(stepNavigateTo) && stepNavigateTo !== this.view.id ? stepNavigateTo : derivedNavigateTo
@@ -105,7 +110,12 @@ export class DynamicViewComputeCtx {
105
110
  relations: relations ?? [],
106
111
  isBackward: isBackward ?? false,
107
112
  ...(navigateTo ? { navigateTo } : {}),
108
- ...(tags ? { tags } : {})
113
+ ...(tags ? { tags } : {}),
114
+ ...(head ? { head } : {}),
115
+ ...(tail ? { tail } : {}),
116
+ ...(color ? { color } : {}),
117
+ ...(line ? { line } : {}),
118
+ ...(notation ? { notation } : {})
109
119
  })
110
120
  }
111
121
 
@@ -208,7 +218,14 @@ export class DynamicViewComputeCtx {
208
218
  ...(autoLayoutRule?.nodeSep && { nodeSep: autoLayoutRule.nodeSep }),
209
219
  ...(autoLayoutRule?.rankSep && { rankSep: autoLayoutRule.rankSep })
210
220
  },
211
- nodes: map(nodes, omit(['notation'])),
221
+ nodes: map(nodes, n => {
222
+ // omit notation
223
+ delete n.notation
224
+ if (n.icon === 'none') {
225
+ delete n.icon
226
+ }
227
+ return n
228
+ }),
212
229
  edges,
213
230
  ...(elementNotations.length > 0 && {
214
231
  notation: {
@@ -223,6 +240,11 @@ export class DynamicViewComputeCtx {
223
240
  tags: NonEmptyArray<Tag> | null
224
241
  relations: NonEmptyArray<RelationID> | null
225
242
  navigateTo: ViewID | null
243
+ tail: RelationshipArrowType | null
244
+ head: RelationshipArrowType | null
245
+ color: Color | null
246
+ line: RelationshipLineType | null
247
+ notation: string | null
226
248
  } {
227
249
  const relationships = unique(this.graph.edgesBetween(source, target).flatMap(e => e.relations))
228
250
  if (relationships.length === 0) {
@@ -230,7 +252,12 @@ export class DynamicViewComputeCtx {
230
252
  title: null,
231
253
  tags: null,
232
254
  relations: null,
233
- navigateTo: null
255
+ navigateTo: null,
256
+ tail: null,
257
+ head: null,
258
+ color: null,
259
+ line: null,
260
+ notation: null
234
261
  }
235
262
  }
236
263
  const alltags = pipe(
@@ -245,16 +272,6 @@ export class DynamicViewComputeCtx {
245
272
  // Most closest relation
246
273
  const relation = only(relationships) || relationships.find(r => r.source === source.id && r.target === target.id)
247
274
 
248
- // This edge represents mutliple relations
249
- // We use label if only it is the same for all relations
250
- const title = isTruthy(relation?.title) ? relation.title : pipe(
251
- relationships,
252
- map(r => r.title),
253
- filter(isTruthy),
254
- unique(),
255
- only()
256
- )
257
-
258
275
  const navigateTo = !!relation?.navigateTo && relation.navigateTo !== this.view.id ? relation.navigateTo : pipe(
259
276
  relationships,
260
277
  map(r => r.navigateTo),
@@ -264,11 +281,33 @@ export class DynamicViewComputeCtx {
264
281
  only()
265
282
  )
266
283
 
284
+ const commonProperties = relationships.reduce((acc, r) => {
285
+ isTruthy(r.title) && acc.title.push(r.title)
286
+ isTruthy(r.tail) && acc.tail.push(r.tail)
287
+ isTruthy(r.head) && acc.head.push(r.head)
288
+ isTruthy(r.color) && acc.color.push(r.color)
289
+ isTruthy(r.line) && acc.line.push(r.line)
290
+
291
+ return acc
292
+ }, {
293
+ title: [] as string[],
294
+ tail: [] as RelationshipArrowType[],
295
+ head: [] as RelationshipArrowType[],
296
+ color: [] as Color[],
297
+ line: [] as RelationshipLineType[],
298
+ notation: [] as string[]
299
+ })
300
+
267
301
  return {
268
- title: title ?? null,
269
302
  tags,
270
303
  relations,
271
- navigateTo: navigateTo ?? null
304
+ navigateTo: navigateTo ?? null,
305
+ title: pipe(commonProperties.title, unique(), only()) ?? null,
306
+ tail: pipe(commonProperties.tail, unique(), only()) ?? null,
307
+ head: pipe(commonProperties.head, unique(), only()) ?? null,
308
+ color: pipe(commonProperties.color, unique(), only()) ?? null,
309
+ line: pipe(commonProperties.line, unique(), only()) ?? null,
310
+ notation: pipe(commonProperties.notation, unique(), only()) ?? null
272
311
  }
273
312
  }
274
313
  }
@@ -1,7 +1,5 @@
1
- import { ComputedNode, type Expression, type ViewRule } from '@likec4/core'
2
- import { Expr, isViewRuleGroup, isViewRulePredicate } from '@likec4/core'
1
+ import { ComputedNode, Expr, type Expression, isViewRuleGroup, isViewRulePredicate, type ViewRule } from '@likec4/core'
3
2
  import { isEmpty, isNullish, omitBy } from 'remeda'
4
- import { NodesGroup } from '../compute-view/compute'
5
3
  import { elementExprToPredicate } from './elementExpressionToPredicate'
6
4
 
7
5
  export function flattenGroupRules<T extends Expression>(guard: (expr: Expression) => expr is T) {