@likec4/language-server 1.8.1 → 1.10.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.
Files changed (85) hide show
  1. package/contrib/likec4.tmLanguage.json +1 -1
  2. package/dist/browser.cjs +21 -0
  3. package/dist/browser.d.cts +22 -0
  4. package/dist/browser.d.mts +22 -0
  5. package/dist/browser.d.ts +22 -0
  6. package/dist/browser.mjs +19 -0
  7. package/dist/index.cjs +10 -0
  8. package/dist/index.d.cts +18 -0
  9. package/dist/index.d.mts +18 -0
  10. package/dist/index.d.ts +18 -0
  11. package/dist/index.mjs +1 -0
  12. package/dist/likec4lib.cjs +961 -0
  13. package/dist/likec4lib.d.cts +6 -0
  14. package/dist/likec4lib.d.mts +6 -0
  15. package/dist/likec4lib.d.ts +6 -0
  16. package/dist/likec4lib.mjs +957 -0
  17. package/dist/model-graph/index.cjs +10 -0
  18. package/dist/model-graph/index.d.cts +79 -0
  19. package/dist/model-graph/index.d.mts +79 -0
  20. package/dist/model-graph/index.d.ts +79 -0
  21. package/dist/model-graph/index.mjs +1 -0
  22. package/dist/node.cjs +18 -0
  23. package/dist/node.d.cts +20 -0
  24. package/dist/node.d.mts +20 -0
  25. package/dist/node.d.ts +20 -0
  26. package/dist/node.mjs +16 -0
  27. package/dist/protocol.cjs +25 -0
  28. package/dist/protocol.d.cts +43 -0
  29. package/dist/protocol.d.mts +43 -0
  30. package/dist/protocol.d.ts +43 -0
  31. package/dist/protocol.mjs +17 -0
  32. package/dist/shared/language-server.CjFzaJwI.d.cts +1223 -0
  33. package/dist/shared/language-server.CtKHXJDD.d.ts +1223 -0
  34. package/dist/shared/language-server.D-84I33F.d.mts +1223 -0
  35. package/dist/shared/language-server.DBJJUUgF.mjs +5737 -0
  36. package/dist/shared/language-server.DtBRb9os.mjs +1656 -0
  37. package/dist/shared/language-server.DwyCJvXm.cjs +1669 -0
  38. package/dist/shared/language-server.JWkqVjGv.cjs +5748 -0
  39. package/package.json +36 -20
  40. package/src/ast.ts +48 -36
  41. package/src/browser.ts +0 -3
  42. package/src/elementRef.ts +1 -1
  43. package/src/formatting/LikeC4Formatter.ts +388 -0
  44. package/src/formatting/utils.ts +26 -0
  45. package/src/generated/ast.ts +170 -12
  46. package/src/generated/grammar.ts +1 -1
  47. package/src/generated-lib/icons.ts +1 -1
  48. package/src/like-c4.langium +49 -8
  49. package/src/likec4lib.ts +2 -3
  50. package/src/logger.ts +9 -1
  51. package/src/lsp/DocumentLinkProvider.ts +27 -15
  52. package/src/lsp/RenameProvider.ts +8 -0
  53. package/src/lsp/SemanticTokenProvider.ts +20 -2
  54. package/src/lsp/index.ts +1 -0
  55. package/src/model/fqn-computation.ts +33 -23
  56. package/src/model/fqn-index.ts +5 -21
  57. package/src/model/model-builder.ts +180 -112
  58. package/src/model/model-locator.ts +1 -1
  59. package/src/model/model-parser-where.ts +3 -2
  60. package/src/model/model-parser.ts +99 -39
  61. package/src/model-graph/LikeC4ModelGraph.ts +42 -21
  62. package/src/model-graph/compute-view/__test__/fixture.ts +16 -14
  63. package/src/model-graph/compute-view/compute.ts +110 -81
  64. package/src/model-graph/compute-view/predicates.ts +6 -8
  65. package/src/model-graph/dynamic-view/__test__/fixture.ts +1 -0
  66. package/src/model-graph/dynamic-view/compute.ts +98 -61
  67. package/src/model-graph/utils/buildElementNotations.ts +1 -1
  68. package/src/model-graph/utils/elementExpressionToPredicate.ts +1 -1
  69. package/src/model-graph/utils/sortNodes.ts +2 -6
  70. package/src/module.ts +21 -4
  71. package/src/protocol.ts +4 -5
  72. package/src/references/scope-computation.ts +10 -1
  73. package/src/references/scope-provider.ts +2 -1
  74. package/src/shared/NodeKindProvider.ts +73 -34
  75. package/src/test/setup.ts +3 -8
  76. package/src/test/testServices.ts +27 -7
  77. package/src/utils/graphlib.ts +11 -0
  78. package/src/validation/index.ts +2 -1
  79. package/src/validation/property-checks.ts +13 -1
  80. package/src/validation/specification.ts +3 -3
  81. package/src/view-utils/manual-layout.ts +1 -1
  82. package/src/view-utils/resolve-extended-views.ts +19 -10
  83. package/src/view-utils/resolve-relative-paths.ts +19 -24
  84. package/src/view-utils/view-hash.ts +1 -1
  85. package/src/reset.d.ts +0 -2
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@likec4/language-server",
3
3
  "description": "LikeC4 Language Server",
4
- "version": "1.8.1",
4
+ "version": "1.10.0",
5
5
  "license": "MIT",
6
6
  "bugs": "https://github.com/likec4/likec4/issues",
7
7
  "homepage": "https://likec4.dev",
@@ -21,30 +21,37 @@
21
21
  "directory": "packages/language-server"
22
22
  },
23
23
  "type": "module",
24
+ "sideEffects": false,
24
25
  "exports": {
25
26
  ".": {
26
27
  "types": "./dist/index.d.ts",
27
- "default": "./dist/index.js"
28
+ "import": "./dist/index.mjs",
29
+ "require": "./dist/index.cjs"
28
30
  },
29
31
  "./likec4lib": {
30
32
  "types": "./dist/likec4lib.d.ts",
31
- "default": "./dist/likec4lib.js"
33
+ "import": "./dist/likec4lib.mjs",
34
+ "require": "./dist/likec4lib.cjs"
32
35
  },
33
36
  "./browser": {
34
37
  "types": "./dist/browser.d.ts",
35
- "default": "./dist/browser.js"
38
+ "import": "./dist/browser.mjs",
39
+ "require": "./dist/browser.cjs"
36
40
  },
37
41
  "./protocol": {
38
42
  "types": "./dist/protocol.d.ts",
39
- "default": "./dist/protocol.js"
43
+ "import": "./dist/protocol.mjs",
44
+ "require": "./dist/protocol.cjs"
40
45
  },
41
46
  "./node": {
42
47
  "types": "./dist/node.d.ts",
43
- "default": "./dist/node.js"
48
+ "import": "./dist/node.mjs",
49
+ "require": "./dist/node.cjs"
44
50
  },
45
51
  "./model-graph": {
46
52
  "types": "./dist/model-graph/index.d.ts",
47
- "default": "./dist/model-graph/index.js"
53
+ "import": "./dist/model-graph/index.mjs",
54
+ "require": "./dist/model-graph/index.cjs"
48
55
  }
49
56
  },
50
57
  "publishConfig": {
@@ -53,32 +60,40 @@
53
60
  "exports": {
54
61
  ".": {
55
62
  "types": "./dist/index.d.ts",
56
- "default": "./dist/index.js"
63
+ "import": "./dist/index.mjs",
64
+ "require": "./dist/index.cjs"
57
65
  },
58
66
  "./likec4lib": {
59
67
  "types": "./dist/likec4lib.d.ts",
60
- "default": "./dist/likec4lib.js"
68
+ "import": "./dist/likec4lib.mjs",
69
+ "require": "./dist/likec4lib.cjs"
61
70
  },
62
71
  "./browser": {
63
72
  "types": "./dist/browser.d.ts",
64
- "default": "./dist/browser.js"
73
+ "import": "./dist/browser.mjs",
74
+ "require": "./dist/browser.cjs"
65
75
  },
66
76
  "./protocol": {
67
77
  "types": "./dist/protocol.d.ts",
68
- "default": "./dist/protocol.js"
78
+ "import": "./dist/protocol.mjs",
79
+ "require": "./dist/protocol.cjs"
69
80
  },
70
81
  "./node": {
71
82
  "types": "./dist/node.d.ts",
72
- "default": "./dist/node.js"
83
+ "import": "./dist/node.mjs",
84
+ "require": "./dist/node.cjs"
73
85
  },
74
86
  "./model-graph": {
75
87
  "types": "./dist/model-graph/index.d.ts",
76
- "default": "./dist/model-graph/index.js"
88
+ "import": "./dist/model-graph/index.mjs",
89
+ "require": "./dist/model-graph/index.cjs"
77
90
  }
78
91
  }
79
92
  },
80
93
  "scripts": {
81
94
  "typecheck": "tsc --noEmit",
95
+ "prepack": "turbo run build",
96
+ "build": "unbuild",
82
97
  "pregenerate": "rm -f src/generated/*",
83
98
  "watch:langium": "langium generate --watch",
84
99
  "watch:ts": "tsc --watch",
@@ -87,16 +102,16 @@
87
102
  "lint": "run -T eslint src/ --fix",
88
103
  "clean": "run -T rimraf dist contrib",
89
104
  "test": "vitest run --no-isolate",
105
+ "test-dbg": "vitest run --no-isolate -t formating",
90
106
  "vitest:ui": "vitest --no-isolate --ui",
91
107
  "test:watch": "vitest"
92
108
  },
93
109
  "dependencies": {
94
110
  "@dagrejs/graphlib": "^2.2.4",
95
- "@likec4/core": "1.8.1",
96
- "@likec4/log": "1.8.1",
111
+ "@likec4/core": "1.10.0",
112
+ "@likec4/log": "1.10.0",
97
113
  "@msgpack/msgpack": "^3.0.0-beta2",
98
114
  "@smithy/util-base64": "^3.0.0",
99
- "@total-typescript/ts-reset": "^0.5.1",
100
115
  "fast-equals": "^5.0.1",
101
116
  "indent-string": "^5.0.0",
102
117
  "json5": "^2.2.3",
@@ -106,7 +121,7 @@
106
121
  "remeda": "^2.11.0",
107
122
  "string-hash": "^1.1.3",
108
123
  "strip-indent": "^4.0.0",
109
- "type-fest": "^4.21.0",
124
+ "type-fest": "^4.26.0",
110
125
  "ufo": "^1.5.4",
111
126
  "vscode-jsonrpc": "8.2.0",
112
127
  "vscode-languageserver": "9.0.1",
@@ -114,17 +129,18 @@
114
129
  "vscode-uri": "3.0.8"
115
130
  },
116
131
  "devDependencies": {
117
- "@likec4/icons": "1.8.1",
118
- "@likec4/tsconfig": "1.8.1",
132
+ "@likec4/icons": "1.10.0",
133
+ "@likec4/tsconfig": "1.10.0",
119
134
  "@types/node": "^20.16.1",
120
135
  "@types/object-hash": "^3.0.6",
121
136
  "@types/string-hash": "^1.1.3",
122
137
  "execa": "^9.3.1",
123
- "glob": "^11.0.0",
124
138
  "langium-cli": "3.1.1",
125
139
  "npm-run-all2": "^6.2.2",
126
140
  "tsx": "~4.9.3",
141
+ "turbo": "^2.1.1",
127
142
  "typescript": "^5.5.4",
143
+ "unbuild": "^3.0.0-rc.7",
128
144
  "vitest": "~2.0.5"
129
145
  },
130
146
  "packageManager": "yarn@4.3.1"
package/src/ast.ts CHANGED
@@ -1,11 +1,5 @@
1
- import {
2
- type c4,
3
- DefaultArrowType,
4
- DefaultLineStyle,
5
- DefaultRelationshipColor,
6
- nonexhaustive,
7
- RelationRefError
8
- } from '@likec4/core'
1
+ import { DefaultArrowType, DefaultLineStyle, DefaultRelationshipColor, nonexhaustive } from '@likec4/core'
2
+ import type * as c4 from '@likec4/core'
9
3
  import type { AstNode, AstNodeDescription, DiagnosticInfo, LangiumDocument, MultiMap } from 'langium'
10
4
  import { DocumentState } from 'langium'
11
5
  import { clamp, isDefined, isNullish, isTruthy } from 'remeda'
@@ -36,13 +30,14 @@ declare module './generated/ast' {
36
30
  type ParsedElementStyle = {
37
31
  shape?: c4.ElementShape
38
32
  icon?: c4.IconUrl
39
- color?: c4.ThemeColor
33
+ color?: c4.Color
40
34
  border?: c4.BorderStyle
41
35
  opacity?: number
42
36
  }
43
37
 
44
38
  export interface ParsedAstSpecification {
45
- kinds: Record<c4.ElementKind, {
39
+ tags: Set<c4.Tag>
40
+ elements: Record<c4.ElementKind, {
46
41
  technology?: string
47
42
  notation?: string
48
43
  style: ParsedElementStyle
@@ -52,12 +47,18 @@ export interface ParsedAstSpecification {
52
47
  {
53
48
  technology?: string
54
49
  notation?: string
55
- color?: c4.ThemeColor
50
+ color?: c4.Color
56
51
  line?: c4.RelationshipLineType
57
52
  head?: c4.RelationshipArrowType
58
53
  tail?: c4.RelationshipArrowType
59
54
  }
60
55
  >
56
+ colors: Record<
57
+ c4.CustomColor,
58
+ {
59
+ color: c4.HexColorLiteral
60
+ }
61
+ >
61
62
  }
62
63
 
63
64
  export interface ParsedAstElement {
@@ -83,11 +84,12 @@ export interface ParsedAstRelation {
83
84
  title: string
84
85
  description?: string
85
86
  technology?: string
86
- color?: c4.ThemeColor
87
+ color?: c4.Color
87
88
  line?: c4.RelationshipLineType
88
89
  head?: c4.RelationshipArrowType
89
90
  tail?: c4.RelationshipArrowType
90
91
  links?: c4.NonEmptyArray<ParsedLink>
92
+ navigateTo?: c4.ViewID
91
93
  metadata?: { [key: string]: string }
92
94
  }
93
95
 
@@ -113,7 +115,7 @@ export interface ParsedAstDynamicView {
113
115
  description: string | null
114
116
  tags: c4.NonEmptyArray<c4.Tag> | null
115
117
  links: c4.NonEmptyArray<ParsedLink> | null
116
- steps: c4.DynamicViewStep[]
118
+ steps: c4.DynamicViewStepOrParallel[]
117
119
  rules: Array<c4.DynamicViewRule>
118
120
  manualLayout?: c4.ViewManualLayout
119
121
  }
@@ -181,8 +183,10 @@ export interface ParsedLikeC4LangiumDocument
181
183
  export function cleanParsedModel(doc: LikeC4LangiumDocument) {
182
184
  const props: Required<Omit<LikeC4DocumentProps, 'c4fqnIndex' | 'diagnostics'>> = {
183
185
  c4Specification: {
184
- kinds: {},
185
- relationships: {}
186
+ tags: new Set(),
187
+ elements: {},
188
+ relationships: {},
189
+ colors: {}
186
190
  },
187
191
  c4Elements: [],
188
192
  c4Relations: [],
@@ -191,14 +195,14 @@ export function cleanParsedModel(doc: LikeC4LangiumDocument) {
191
195
  return Object.assign(doc, props) as ParsedLikeC4LangiumDocument
192
196
  }
193
197
 
194
- export function isFqnIndexedDocument(doc: LangiumDocument): doc is FqnIndexedDocument {
195
- return isLikeC4LangiumDocument(doc) && doc.state >= DocumentState.IndexedContent && !!doc.c4fqnIndex
196
- }
197
-
198
198
  export function isLikeC4LangiumDocument(doc: LangiumDocument): doc is LikeC4LangiumDocument {
199
199
  return doc.textDocument.languageId === LikeC4LanguageMetaData.languageId
200
200
  }
201
201
 
202
+ export function isFqnIndexedDocument(doc: LangiumDocument): doc is FqnIndexedDocument {
203
+ return isLikeC4LangiumDocument(doc) && doc.state >= DocumentState.IndexedContent && !!doc.c4fqnIndex
204
+ }
205
+
202
206
  export function isParsedLikeC4LangiumDocument(
203
207
  doc: LangiumDocument
204
208
  ): doc is ParsedLikeC4LangiumDocument {
@@ -227,6 +231,7 @@ const isValidatableAstNode = validatableAstNodeGuards([
227
231
  ast.isRelationPredicateWith,
228
232
  ast.isElementExpression,
229
233
  ast.isRelationExpression,
234
+ ast.isDynamicViewParallelSteps,
230
235
  ast.isDynamicViewStep,
231
236
  ast.isViewProperty,
232
237
  ast.isStyleProperty,
@@ -247,6 +252,7 @@ const isValidatableAstNode = validatableAstNodeGuards([
247
252
  ast.isSpecificationElementKind,
248
253
  ast.isSpecificationRelationshipKind,
249
254
  ast.isSpecificationTag,
255
+ ast.isSpecificationColor,
250
256
  ast.isSpecificationRule,
251
257
  ast.isModelViews,
252
258
  ast.isModel
@@ -261,7 +267,7 @@ const findInvalidContainer = (node: LikeC4AstNode): ValidatableAstNode | undefin
261
267
  }
262
268
  nd = nd.$container
263
269
  }
264
- return
270
+ return undefined
265
271
  }
266
272
 
267
273
  export function checksFromDiagnostics(doc: LikeC4LangiumDocument) {
@@ -279,8 +285,9 @@ export function checksFromDiagnostics(doc: LikeC4LangiumDocument) {
279
285
  }
280
286
  }
281
287
  export type ChecksFromDiagnostics = ReturnType<typeof checksFromDiagnostics>
288
+ export type IsValidFn = ChecksFromDiagnostics['isValid']
282
289
 
283
- export function* streamModel(doc: LikeC4LangiumDocument, isValid: ChecksFromDiagnostics['isValid']) {
290
+ export function* streamModel(doc: LikeC4LangiumDocument, isValid: IsValidFn) {
284
291
  const traverseStack = doc.parseResult.value.models.flatMap(m => (isValid(m) ? m.elements : []))
285
292
  const relations = [] as ast.Relation[]
286
293
  let el
@@ -299,13 +306,7 @@ export function* streamModel(doc: LikeC4LangiumDocument, isValid: ChecksFromDiag
299
306
  continue
300
307
  }
301
308
  if (el.body && el.body.elements.length > 0) {
302
- for (const nested of el.body.elements) {
303
- if (ast.isRelation(nested)) {
304
- relations.push(nested)
305
- } else {
306
- traverseStack.push(nested)
307
- }
308
- }
309
+ traverseStack.push(...el.body.elements)
309
310
  }
310
311
  yield el
311
312
  }
@@ -320,12 +321,12 @@ export function resolveRelationPoints(node: ast.Relation): {
320
321
  } {
321
322
  const target = elementRef(node.target)
322
323
  if (!target) {
323
- throw new RelationRefError('Invalid reference to target')
324
+ throw new Error('RelationRefError: Invalid reference to target')
324
325
  }
325
326
  if (isDefined(node.source)) {
326
327
  const source = elementRef(node.source)
327
328
  if (!source) {
328
- throw new RelationRefError('Invalid reference to source')
329
+ throw new Error('RelationRefError: Invalid reference to source')
329
330
  }
330
331
  return {
331
332
  source,
@@ -333,7 +334,7 @@ export function resolveRelationPoints(node: ast.Relation): {
333
334
  }
334
335
  }
335
336
  if (!ast.isElementBody(node.$container)) {
336
- throw new RelationRefError('Invalid container for sourceless relation')
337
+ throw new Error('RelationRefError: Invalid container for sourceless relation')
337
338
  }
338
339
  return {
339
340
  source: node.$container.$container,
@@ -346,12 +347,15 @@ export function parseAstOpacityProperty({ value }: ast.OpacityProperty): number
346
347
  return isNaN(opacity) ? 100 : clamp(opacity, { min: 0, max: 100 })
347
348
  }
348
349
 
349
- export function toElementStyle(props?: Array<ast.StyleProperty>) {
350
+ export function toElementStyle(props: Array<ast.StyleProperty> | undefined, isValid: IsValidFn) {
350
351
  const result = {} as ParsedElementStyle
351
352
  if (!props || props.length === 0) {
352
353
  return result
353
354
  }
354
355
  for (const prop of props) {
356
+ if (!isValid(prop)) {
357
+ continue
358
+ }
355
359
  switch (true) {
356
360
  case ast.isBorderProperty(prop): {
357
361
  if (isTruthy(prop.value)) {
@@ -360,8 +364,9 @@ export function toElementStyle(props?: Array<ast.StyleProperty>) {
360
364
  break
361
365
  }
362
366
  case ast.isColorProperty(prop): {
363
- if (isTruthy(prop.value)) {
364
- result.color = prop.value
367
+ const color = toColor(prop)
368
+ if (isTruthy(color)) {
369
+ result.color = color
365
370
  }
366
371
  break
367
372
  }
@@ -392,7 +397,7 @@ export function toElementStyle(props?: Array<ast.StyleProperty>) {
392
397
 
393
398
  export function toRelationshipStyle(props?: ast.RelationshipStyleProperty[]) {
394
399
  const result = {} as {
395
- color?: c4.ThemeColor
400
+ color?: c4.Color
396
401
  line?: c4.RelationshipLineType
397
402
  head?: c4.RelationshipArrowType
398
403
  tail?: c4.RelationshipArrowType
@@ -402,7 +407,10 @@ export function toRelationshipStyle(props?: ast.RelationshipStyleProperty[]) {
402
407
  }
403
408
  for (const prop of props) {
404
409
  if (ast.isColorProperty(prop)) {
405
- result.color = prop.value
410
+ const color = toColor(prop)
411
+ if (isTruthy(color)) {
412
+ result.color = color
413
+ }
406
414
  continue
407
415
  }
408
416
  if (ast.isLineProperty(prop)) {
@@ -442,6 +450,10 @@ export function toRelationshipStyleExcludeDefaults(
442
450
  }
443
451
  }
444
452
 
453
+ export function toColor(astNode: ast.ColorProperty): c4.Color | undefined {
454
+ return astNode?.themeColor ?? (astNode?.customColor?.$refText as (c4.HexColorLiteral | undefined))
455
+ }
456
+
445
457
  export function toAutoLayout(
446
458
  direction: ast.ViewLayoutDirection
447
459
  ): c4.ViewRuleAutoLayout['autoLayout'] {
package/src/browser.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { startLanguageServer as startLanguim } from 'langium/lsp'
2
2
  import { BrowserMessageReader, BrowserMessageWriter, createConnection } from 'vscode-languageserver/browser'
3
- import { logToLspConnection } from './logger'
4
3
  import { createLanguageServices } from './module'
5
4
 
6
5
  // This is an example copied as is from here:
@@ -22,8 +21,6 @@ export function startLanguageServer() {
22
21
  // Start the language server with the shared services
23
22
  startLanguim(services.shared)
24
23
 
25
- logToLspConnection(connection)
26
-
27
24
  return {
28
25
  ...services,
29
26
  connection,
package/src/elementRef.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { type c4 } from '@likec4/core'
1
+ import type * as c4 from '@likec4/core'
2
2
  import type { ast } from './ast'
3
3
  /**
4
4
  * Returns referenced AST Element