@likec4/language-server 1.10.0 → 1.11.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 (55) hide show
  1. package/dist/browser.cjs +5 -1
  2. package/dist/browser.d.cts +9 -8
  3. package/dist/browser.d.mts +9 -8
  4. package/dist/browser.d.ts +9 -8
  5. package/dist/browser.mjs +3 -2
  6. package/dist/index.cjs +15 -2
  7. package/dist/index.d.cts +14 -11
  8. package/dist/index.d.mts +14 -11
  9. package/dist/index.d.ts +14 -11
  10. package/dist/index.mjs +17 -1
  11. package/dist/likec4lib.cjs +949 -952
  12. package/dist/likec4lib.d.cts +1 -1
  13. package/dist/likec4lib.d.mts +1 -1
  14. package/dist/likec4lib.d.ts +1 -1
  15. package/dist/likec4lib.mjs +949 -952
  16. package/dist/model-graph/index.cjs +1 -1
  17. package/dist/model-graph/index.mjs +1 -1
  18. package/dist/protocol.cjs +1 -1
  19. package/dist/protocol.d.cts +3 -1
  20. package/dist/protocol.d.mts +3 -1
  21. package/dist/protocol.d.ts +3 -1
  22. package/dist/protocol.mjs +1 -1
  23. package/dist/shared/{language-server.JWkqVjGv.cjs → language-server.C8lV6gDw.cjs} +120 -118
  24. package/dist/shared/{language-server.DBJJUUgF.mjs → language-server.CCOotWDz.mjs} +120 -119
  25. package/dist/shared/{language-server.DtBRb9os.mjs → language-server.CbqwHp7Q.mjs} +23 -9
  26. package/dist/shared/{language-server.CtKHXJDD.d.ts → language-server.Cyw-bCtc.d.ts} +145 -138
  27. package/dist/shared/{language-server.D-84I33F.d.mts → language-server.DGjTE7xL.d.mts} +145 -138
  28. package/dist/shared/{language-server.DwyCJvXm.cjs → language-server.DJhoJBWh.cjs} +17 -3
  29. package/dist/shared/{language-server.CjFzaJwI.d.cts → language-server.Ol32Kygo.d.cts} +145 -138
  30. package/package.json +34 -29
  31. package/src/Rpc.ts +10 -6
  32. package/src/ast.ts +1 -1
  33. package/src/browser.ts +5 -0
  34. package/src/formatting/LikeC4Formatter.ts +4 -2
  35. package/src/generated/ast.ts +99 -1
  36. package/src/generated/grammar.ts +1 -1
  37. package/src/generated/module.ts +1 -1
  38. package/src/generated-lib/icons.ts +949 -952
  39. package/src/index.ts +23 -2
  40. package/src/likec4lib.ts +1 -1
  41. package/src/logger.ts +16 -16
  42. package/src/lsp/CompletionProvider.ts +1 -1
  43. package/src/model/model-builder.ts +12 -12
  44. package/src/model-graph/compute-view/compute.ts +9 -4
  45. package/src/model-graph/utils/applyCustomRelationProperties.ts +1 -1
  46. package/src/model-graph/utils/uniqueTags.test.ts +42 -0
  47. package/src/model-graph/utils/uniqueTags.ts +19 -0
  48. package/src/protocol.ts +5 -1
  49. package/src/shared/WorkspaceManager.ts +1 -1
  50. package/dist/node.cjs +0 -18
  51. package/dist/node.d.cts +0 -20
  52. package/dist/node.d.mts +0 -20
  53. package/dist/node.d.ts +0 -20
  54. package/dist/node.mjs +0 -16
  55. package/src/node.ts +0 -20
package/src/index.ts CHANGED
@@ -1,4 +1,25 @@
1
- export { setLogLevel } from './logger'
1
+ import { startLanguageServer as startLanguim } from 'langium/lsp'
2
+ import { NodeFileSystem } from 'langium/node'
3
+ import { createConnection, ProposedFeatures } from 'vscode-languageserver/node'
4
+ import { createLanguageServices } from './module'
5
+
6
+ export { logger as lspLogger, setLogLevel } from './logger'
2
7
  export type * from './model'
3
- export { createCustomLanguageServices, createLanguageServices, LikeC4Module } from './module'
4
8
  export type * from './module'
9
+ export { createCustomLanguageServices, createLanguageServices, LikeC4Module } from './module'
10
+
11
+ export function startLanguageServer() {
12
+ /* browser specific setup code */
13
+ const connection = createConnection(ProposedFeatures.all)
14
+
15
+ // Inject the shared services and language-specific services
16
+ const services = createLanguageServices({ connection, ...NodeFileSystem })
17
+
18
+ // Start the language server with the shared services
19
+ startLanguim(services.shared)
20
+
21
+ return {
22
+ ...services,
23
+ connection
24
+ }
25
+ }
package/src/likec4lib.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { LibIcons } from './generated-lib/icons'
2
2
 
3
3
  export const Scheme = 'likec4builtin'
4
- export const Uri = `${Scheme}:///likec4/lib/icons.c4`
4
+ export const Uri = `${Scheme}:///likec4/lib/icons.c4` as const
5
5
 
6
6
  export { LibIcons as Content }
package/src/logger.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  /* eslint-disable @typescript-eslint/no-explicit-any */
2
2
  import { type ConsolaReporter, LogLevels, rootLogger as root } from '@likec4/log'
3
+ import { isError } from 'remeda'
3
4
  import type { Connection } from 'vscode-languageserver'
4
5
 
5
6
  export const logger = root.withTag('lsp')
@@ -28,13 +29,13 @@ export function logErrorToTelemetry(connection: Connection): void {
28
29
  }
29
30
  const tag = logObj.tag || ''
30
31
  const parts = logObj.args.map((arg) => {
31
- if (arg && typeof arg.stack === 'string') {
32
- return arg.message + '\n' + arg.stack
32
+ if (isError(arg)) {
33
+ return arg.stack ?? arg.message
33
34
  }
34
35
  if (typeof arg === 'string') {
35
36
  return arg
36
37
  }
37
- return String(arg)
38
+ return '' + arg
38
39
  })
39
40
  if (tag) {
40
41
  parts.unshift(`[${tag}]`)
@@ -52,33 +53,29 @@ export function logToLspConnection(connection: Connection): void {
52
53
  log: ({ level, ...logObj }, ctx) => {
53
54
  const tag = logObj.tag || ''
54
55
  const parts = logObj.args.map((arg) => {
55
- if (arg && typeof arg.stack === 'string') {
56
- return arg.message + '\n' + arg.stack
56
+ if (isError(arg)) {
57
+ return arg.stack ?? arg.message
57
58
  }
58
59
  if (typeof arg === 'string') {
59
60
  return arg
60
61
  }
61
- return String(arg)
62
+ return '' + arg
62
63
  })
63
64
  if (tag) {
64
65
  parts.unshift(`[${tag}]`)
65
66
  }
66
67
  const message = parts.join(' ')
67
68
  switch (true) {
68
- case level >= LogLevels.trace: {
69
- connection.tracer.log(message)
70
- break
71
- }
72
69
  case level >= LogLevels.debug: {
73
70
  connection.console.debug(message)
74
71
  break
75
72
  }
76
- case level >= LogLevels.info: {
77
- connection.console.info(message)
78
- break
79
- }
73
+ // case level >= LogLevels.info: {
74
+ // connection.console.info(message)
75
+ // break
76
+ // }
80
77
  case level >= LogLevels.log: {
81
- connection.console.log(message)
78
+ connection.console.info(message)
82
79
  break
83
80
  }
84
81
  case level >= LogLevels.warn: {
@@ -89,9 +86,12 @@ export function logToLspConnection(connection: Connection): void {
89
86
  connection.console.error(message)
90
87
  break
91
88
  }
89
+ default: {
90
+ connection.console.log(message)
91
+ }
92
92
  }
93
93
  }
94
94
  }
95
- root.addReporter(reporter)
95
+ root.setReporters([reporter])
96
96
  logger.setReporters(root.options.reporters)
97
97
  }
@@ -1,7 +1,7 @@
1
1
  import { type CompletionProviderOptions, DefaultCompletionProvider } from 'langium/lsp'
2
2
 
3
3
  export class LikeC4CompletionProvider extends DefaultCompletionProvider {
4
- readonly completionOptions = {
4
+ override readonly completionOptions = {
5
5
  triggerCharacters: ['.']
6
6
  } satisfies CompletionProviderOptions
7
7
  }
@@ -315,7 +315,7 @@ export class LikeC4ModelBuilder {
315
315
  async (docs, _cancelToken) => {
316
316
  let parsed = [] as URI[]
317
317
  try {
318
- logger.debug(`[ModelBuilder] onValidated (${docs.length} docs)\n${printDocs(docs)}`)
318
+ logger.debug(`[ModelBuilder] onValidated (${docs.length} docs)`)
319
319
  for (const doc of parser.parse(docs)) {
320
320
  parsed.push(doc.uri)
321
321
  }
@@ -344,7 +344,7 @@ export class LikeC4ModelBuilder {
344
344
  logger.debug('[ModelBuilder] No documents to build model from')
345
345
  return null
346
346
  }
347
- logger.debug(`[ModelBuilder] buildModel from ${docs.length} docs:\n${printDocs(docs)}`)
347
+ logger.debug(`[ModelBuilder] onValidated (${docs.length} docs)`)
348
348
  return buildModel(this.services, docs)
349
349
  })
350
350
  }
@@ -408,14 +408,14 @@ export class LikeC4ModelBuilder {
408
408
  if (cache.has(CACHE_KEY_COMPUTED_MODEL)) {
409
409
  return cache.get(CACHE_KEY_COMPUTED_MODEL)!
410
410
  }
411
- const model = await this.buildModel(cancelToken)
412
- if (!model) {
413
- return null
414
- }
415
411
  return await this.services.shared.workspace.WorkspaceLock.read(async () => {
416
412
  if (cancelToken) {
417
413
  await interruptAndCheck(cancelToken)
418
414
  }
415
+ const model = this.unsafeSyncBuildModel()
416
+ if (!model) {
417
+ return null
418
+ }
419
419
  return this.unsafeSyncBuildComputedModel(model)
420
420
  })
421
421
  }
@@ -429,17 +429,17 @@ export class LikeC4ModelBuilder {
429
429
  if (cache.has(cacheKey)) {
430
430
  return cache.get(cacheKey)!
431
431
  }
432
- const model = await this.buildModel(cancelToken)
433
- const view = model?.views[viewId]
434
- if (!view) {
435
- logger.warn(`[ModelBuilder] Cannot find view ${viewId}`)
436
- return null
437
- }
438
432
  return await this.services.shared.workspace.WorkspaceLock.read(async () => {
439
433
  if (cancelToken) {
440
434
  await interruptAndCheck(cancelToken)
441
435
  }
442
436
  return cache.get(cacheKey, () => {
437
+ const model = this.unsafeSyncBuildModel()
438
+ const view = model?.views[viewId]
439
+ if (!view) {
440
+ logger.warn(`[ModelBuilder] Cannot find view ${viewId}`)
441
+ return null
442
+ }
443
443
  const index = new LikeC4ModelGraph(model)
444
444
  const result = isElementView(view) ? computeView(view, index) : computeDynamicView(view, index)
445
445
  if (!result.isSuccess) {
@@ -30,7 +30,7 @@ import {
30
30
  parentFqn,
31
31
  whereOperatorAsPredicate
32
32
  } from '@likec4/core'
33
- import { filter, flatMap, hasAtLeast, isNonNull, isTruthy, map, omit, only, pipe, reduce, sort, unique } from 'remeda'
33
+ import { filter, hasAtLeast, isNonNull, isTruthy, map, omit, only, pipe, reduce, sort, unique } from 'remeda'
34
34
  import { calcViewLayoutHash } from '../../view-utils/view-hash'
35
35
  import type { LikeC4ModelGraph } from '../LikeC4ModelGraph'
36
36
  import { applyCustomElementProperties } from '../utils/applyCustomElementProperties'
@@ -39,6 +39,7 @@ import { applyViewRuleStyles } from '../utils/applyViewRuleStyles'
39
39
  import { buildComputeNodes } from '../utils/buildComputeNodes'
40
40
  import { buildElementNotations } from '../utils/buildElementNotations'
41
41
  import { sortNodes } from '../utils/sortNodes'
42
+ import { uniqueTags } from '../utils/uniqueTags'
42
43
  import {
43
44
  type ElementPredicateFn,
44
45
  excludeElementKindOrTag,
@@ -218,7 +219,11 @@ export class ComputeCtx {
218
219
  tags?: NonEmptyArray<Tag>
219
220
  navigateTo?: ViewID | undefined
220
221
  } | undefined
221
- relation = relations.length === 1 ? relations[0] : relations.find(r => r.source === source && r.target === target)
222
+ relation = only(relations) ?? pipe(
223
+ relations,
224
+ filter(r => r.source === source && r.target === target),
225
+ only()
226
+ )
222
227
 
223
228
  // This edge represents mutliple relations
224
229
  // We use label if only it is the same for all relations
@@ -279,7 +284,7 @@ export class ComputeCtx {
279
284
  }
280
285
  }
281
286
 
282
- const tags = unique(flatMap(relations, r => r.tags ?? []))
287
+ const tags = uniqueTags(relations)
283
288
 
284
289
  return Object.assign(
285
290
  edge,
@@ -292,7 +297,7 @@ export class ComputeCtx {
292
297
  relation.head && { head: relation.head },
293
298
  relation.tail && { tail: relation.tail },
294
299
  relation.navigateTo && { navigateTo: relation.navigateTo },
295
- hasAtLeast(tags, 1) && { tags }
300
+ tags && { tags }
296
301
  )
297
302
  })
298
303
  }
@@ -1,6 +1,6 @@
1
1
  import type { ComputedEdge, ComputedNode, Element, ViewRule } from '@likec4/core'
2
2
  import { Expr, nonexhaustive } from '@likec4/core'
3
- import { isEmpty, isNullish, omitBy } from 'remeda'
3
+ import { isNullish, omitBy } from 'remeda'
4
4
  import { elementExprToPredicate } from './elementExpressionToPredicate'
5
5
 
6
6
  function relationExpressionToPredicates(
@@ -0,0 +1,42 @@
1
+ import { compareNatural } from '@likec4/core'
2
+ import { describe, expect, it } from 'vitest'
3
+ import { uniqueTags } from './uniqueTags'
4
+
5
+ describe('uniqueTags function', () => {
6
+ it('returns unique tags from an array of elements', () => {
7
+ const input = [
8
+ { tags: ['tag1', 'tag2', 'tag3'] },
9
+ { tags: ['tag2', 'tag3', 'tag4'] },
10
+ { tags: ['tag3', 'tag4', 'tag5'] }
11
+ ] as const
12
+ const result = uniqueTags(input)
13
+ expect(result).toEqual(['tag1', 'tag2', 'tag3', 'tag4', 'tag5'])
14
+ })
15
+
16
+ it('should return unique tags naturally sorted', () => {
17
+ const input = [
18
+ { tags: ['tag1', 'tag20', 'tag30'] },
19
+ { tags: ['tag2', 'tag23', 'tag34'] },
20
+ { tags: ['tag3'] }
21
+ ] as const
22
+ const result = uniqueTags(input)
23
+ expect(result).toEqual([
24
+ 'tag1',
25
+ 'tag2',
26
+ 'tag3',
27
+ 'tag20',
28
+ 'tag23',
29
+ 'tag30',
30
+ 'tag34'
31
+ ].sort(compareNatural))
32
+ })
33
+
34
+ it('returns null if the tags array is null', () => {
35
+ const input = [
36
+ { tags: null },
37
+ {}
38
+ ]
39
+ const result = uniqueTags(input)
40
+ expect(result).toBeNull()
41
+ })
42
+ })
@@ -0,0 +1,19 @@
1
+ import { compareNatural, hasAtLeast, type NonEmptyReadonlyArray, type Tag } from '@likec4/core'
2
+ import { flatMap, pipe, sort, unique } from 'remeda'
3
+ import type { LiteralUnion } from 'type-fest'
4
+
5
+ /**
6
+ * Extracts unique tags from an array of elements.
7
+ * and sort in natural order; returns null if no tags are present.
8
+ */
9
+ export function uniqueTags<T extends { tags?: NonEmptyReadonlyArray<LiteralUnion<Tag, string>> | null }>(
10
+ elements: ReadonlyArray<T>
11
+ ) {
12
+ const tags = pipe(
13
+ elements,
14
+ flatMap(e => e.tags ?? []),
15
+ unique(),
16
+ sort(compareNatural)
17
+ )
18
+ return hasAtLeast(tags, 1) ? tags : null
19
+ }
package/src/protocol.ts CHANGED
@@ -21,7 +21,11 @@ export const fetchModel = new RequestType0<{ model: ParsedLikeC4Model | null },
21
21
  )
22
22
  export type FetchModelRequest = typeof fetchModel
23
23
 
24
- export const fetchComputedModel = new RequestType0<{ model: ComputedLikeC4Model | null }, void>(
24
+ export const fetchComputedModel = new RequestType<
25
+ { cleanCaches?: boolean | undefined },
26
+ { model: ComputedLikeC4Model | null },
27
+ void
28
+ >(
25
29
  'likec4/fetchComputedModel'
26
30
  )
27
31
  export type FetchComputedModelRequest = typeof fetchComputedModel
@@ -23,8 +23,8 @@ export class LikeC4WorkspaceManager extends DefaultWorkspaceManager {
23
23
  folders: WorkspaceFolder[],
24
24
  collector: (document: LangiumDocument) => void
25
25
  ): Promise<void> {
26
- await super.loadAdditionalDocuments(folders, collector)
27
26
  collector(this.documentFactory.fromString(BuiltIn.Content, URI.parse(BuiltIn.Uri)))
27
+ await super.loadAdditionalDocuments(folders, collector)
28
28
  }
29
29
 
30
30
  public workspace() {
package/dist/node.cjs DELETED
@@ -1,18 +0,0 @@
1
- 'use strict';
2
-
3
- const lsp = require('langium/lsp');
4
- const node$1 = require('langium/node');
5
- const node = require('vscode-languageserver/node');
6
- const module$1 = require('./shared/language-server.JWkqVjGv.cjs');
7
-
8
- function startLanguageServer() {
9
- const connection = node.createConnection(node.ProposedFeatures.all);
10
- const services = module$1.createLanguageServices({ connection, ...node$1.NodeFileSystem });
11
- lsp.startLanguageServer(services.shared);
12
- return {
13
- ...services,
14
- connection
15
- };
16
- }
17
-
18
- exports.startLanguageServer = startLanguageServer;
package/dist/node.d.cts DELETED
@@ -1,20 +0,0 @@
1
- import { i as LikeC4SharedServices, a as LikeC4Services } from './shared/language-server.CjFzaJwI.cjs';
2
- import * as vscode_languageserver_lib_common_inlineCompletion_proposed from 'vscode-languageserver/lib/common/inlineCompletion.proposed';
3
- import * as vscode_languageserver_node from 'vscode-languageserver/node';
4
- import '@likec4/core';
5
- import 'langium';
6
- import 'type-fest';
7
- import 'vscode-languageserver-types';
8
- import 'langium/lsp';
9
- import 'vscode-languageserver';
10
- import './protocol.cjs';
11
- import 'vscode-jsonrpc';
12
- import 'vscode-uri';
13
-
14
- declare function startLanguageServer(): {
15
- connection: vscode_languageserver_node._Connection<vscode_languageserver_node._, vscode_languageserver_node._, vscode_languageserver_node._, vscode_languageserver_node._, vscode_languageserver_node._, vscode_languageserver_node._, vscode_languageserver_lib_common_inlineCompletion_proposed.InlineCompletionFeatureShape, vscode_languageserver_node._>;
16
- shared: LikeC4SharedServices;
17
- likec4: LikeC4Services;
18
- };
19
-
20
- export { startLanguageServer };
package/dist/node.d.mts DELETED
@@ -1,20 +0,0 @@
1
- import { i as LikeC4SharedServices, a as LikeC4Services } from './shared/language-server.D-84I33F.mjs';
2
- import * as vscode_languageserver_lib_common_inlineCompletion_proposed from 'vscode-languageserver/lib/common/inlineCompletion.proposed';
3
- import * as vscode_languageserver_node from 'vscode-languageserver/node';
4
- import '@likec4/core';
5
- import 'langium';
6
- import 'type-fest';
7
- import 'vscode-languageserver-types';
8
- import 'langium/lsp';
9
- import 'vscode-languageserver';
10
- import './protocol.mjs';
11
- import 'vscode-jsonrpc';
12
- import 'vscode-uri';
13
-
14
- declare function startLanguageServer(): {
15
- connection: vscode_languageserver_node._Connection<vscode_languageserver_node._, vscode_languageserver_node._, vscode_languageserver_node._, vscode_languageserver_node._, vscode_languageserver_node._, vscode_languageserver_node._, vscode_languageserver_lib_common_inlineCompletion_proposed.InlineCompletionFeatureShape, vscode_languageserver_node._>;
16
- shared: LikeC4SharedServices;
17
- likec4: LikeC4Services;
18
- };
19
-
20
- export { startLanguageServer };
package/dist/node.d.ts DELETED
@@ -1,20 +0,0 @@
1
- import { i as LikeC4SharedServices, a as LikeC4Services } from './shared/language-server.CtKHXJDD.js';
2
- import * as vscode_languageserver_lib_common_inlineCompletion_proposed from 'vscode-languageserver/lib/common/inlineCompletion.proposed';
3
- import * as vscode_languageserver_node from 'vscode-languageserver/node';
4
- import '@likec4/core';
5
- import 'langium';
6
- import 'type-fest';
7
- import 'vscode-languageserver-types';
8
- import 'langium/lsp';
9
- import 'vscode-languageserver';
10
- import './protocol.js';
11
- import 'vscode-jsonrpc';
12
- import 'vscode-uri';
13
-
14
- declare function startLanguageServer(): {
15
- connection: vscode_languageserver_node._Connection<vscode_languageserver_node._, vscode_languageserver_node._, vscode_languageserver_node._, vscode_languageserver_node._, vscode_languageserver_node._, vscode_languageserver_node._, vscode_languageserver_lib_common_inlineCompletion_proposed.InlineCompletionFeatureShape, vscode_languageserver_node._>;
16
- shared: LikeC4SharedServices;
17
- likec4: LikeC4Services;
18
- };
19
-
20
- export { startLanguageServer };
package/dist/node.mjs DELETED
@@ -1,16 +0,0 @@
1
- import { startLanguageServer as startLanguageServer$1 } from 'langium/lsp';
2
- import { NodeFileSystem } from 'langium/node';
3
- import { createConnection, ProposedFeatures } from 'vscode-languageserver/node';
4
- import { a as createLanguageServices } from './shared/language-server.DBJJUUgF.mjs';
5
-
6
- function startLanguageServer() {
7
- const connection = createConnection(ProposedFeatures.all);
8
- const services = createLanguageServices({ connection, ...NodeFileSystem });
9
- startLanguageServer$1(services.shared);
10
- return {
11
- ...services,
12
- connection
13
- };
14
- }
15
-
16
- export { startLanguageServer };
package/src/node.ts DELETED
@@ -1,20 +0,0 @@
1
- import { startLanguageServer as startLanguim } from 'langium/lsp'
2
- import { NodeFileSystem } from 'langium/node'
3
- import { createConnection, ProposedFeatures } from 'vscode-languageserver/node'
4
- import { createLanguageServices } from './module'
5
-
6
- export function startLanguageServer() {
7
- /* browser specific setup code */
8
- const connection = createConnection(ProposedFeatures.all)
9
-
10
- // Inject the shared services and language-specific services
11
- const services = createLanguageServices({ connection, ...NodeFileSystem })
12
-
13
- // Start the language server with the shared services
14
- startLanguim(services.shared)
15
-
16
- return {
17
- ...services,
18
- connection
19
- }
20
- }