@likec4/language-server 1.9.0 → 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 (48) hide show
  1. package/contrib/likec4.tmLanguage.json +1 -1
  2. package/dist/browser.cjs +1 -1
  3. package/dist/browser.d.cts +1 -1
  4. package/dist/browser.d.mts +1 -1
  5. package/dist/browser.d.ts +1 -1
  6. package/dist/browser.mjs +1 -1
  7. package/dist/index.cjs +1 -1
  8. package/dist/index.d.cts +2 -2
  9. package/dist/index.d.mts +2 -2
  10. package/dist/index.d.ts +2 -2
  11. package/dist/index.mjs +1 -1
  12. package/dist/model-graph/index.cjs +1 -1
  13. package/dist/model-graph/index.mjs +1 -1
  14. package/dist/node.cjs +1 -1
  15. package/dist/node.d.cts +1 -1
  16. package/dist/node.d.mts +1 -1
  17. package/dist/node.d.ts +1 -1
  18. package/dist/node.mjs +1 -1
  19. package/dist/shared/{language-server.86lmJ8ZN.d.cts → language-server.CjFzaJwI.d.cts} +42 -13
  20. package/dist/shared/{language-server.RjhrBZS0.d.ts → language-server.CtKHXJDD.d.ts} +42 -13
  21. package/dist/shared/{language-server.CFTY6j4e.d.mts → language-server.D-84I33F.d.mts} +42 -13
  22. package/dist/shared/{language-server.Q-wtPShM.mjs → language-server.DBJJUUgF.mjs} +485 -108
  23. package/dist/shared/{language-server.CCB4ESN5.mjs → language-server.DtBRb9os.mjs} +166 -116
  24. package/dist/shared/{language-server.D0bOlrCi.cjs → language-server.DwyCJvXm.cjs} +164 -114
  25. package/dist/shared/{language-server.B1TZgyoH.cjs → language-server.JWkqVjGv.cjs} +481 -104
  26. package/package.json +6 -5
  27. package/src/ast.ts +8 -6
  28. package/src/formatting/LikeC4Formatter.ts +388 -0
  29. package/src/formatting/utils.ts +26 -0
  30. package/src/generated/ast.ts +104 -10
  31. package/src/generated/grammar.ts +1 -1
  32. package/src/like-c4.langium +34 -7
  33. package/src/lsp/DocumentLinkProvider.ts +27 -15
  34. package/src/lsp/SemanticTokenProvider.ts +1 -1
  35. package/src/lsp/index.ts +1 -1
  36. package/src/model/fqn-index.ts +0 -1
  37. package/src/model/model-builder.ts +43 -32
  38. package/src/model/model-parser.ts +43 -21
  39. package/src/model-graph/compute-view/compute.ts +104 -78
  40. package/src/model-graph/compute-view/predicates.ts +3 -5
  41. package/src/model-graph/dynamic-view/compute.ts +96 -60
  42. package/src/model-graph/utils/buildElementNotations.ts +1 -1
  43. package/src/module.ts +6 -9
  44. package/src/test/testServices.ts +27 -7
  45. package/src/validation/index.ts +2 -1
  46. package/src/validation/property-checks.ts +13 -1
  47. package/src/validation/specification.ts +3 -3
  48. package/src/view-utils/resolve-relative-paths.ts +14 -17
@@ -1,4 +1,4 @@
1
- import type { ValidationCheck } from 'langium'
1
+ import { AstUtils, type ValidationCheck } from 'langium'
2
2
  import { ast } from '../ast'
3
3
  import type { LikeC4Services } from '../module'
4
4
 
@@ -37,3 +37,15 @@ export const iconPropertyRuleChecks = (
37
37
  }
38
38
  }
39
39
  }
40
+
41
+ export const notesPropertyRuleChecks = (
42
+ _: LikeC4Services
43
+ ): ValidationCheck<ast.NotesProperty> => {
44
+ return (node, accept) => {
45
+ if (!AstUtils.hasContainerOfType(node, ast.isDynamicViewStep)) {
46
+ accept('error', `Notes can be defined only inside dynamic view`, {
47
+ node
48
+ })
49
+ }
50
+ }
51
+ }
@@ -8,7 +8,7 @@ export const specificationRuleChecks = (
8
8
  ): ValidationCheck<ast.SpecificationRule> => {
9
9
  return (node, accept) => {
10
10
  if (node.$containerIndex && node.$containerIndex > 0) {
11
- accept('error', `Only one specification per document is allowed`, {
11
+ accept('warning', `Prefer one specification per document`, {
12
12
  node: node,
13
13
  property: 'name'
14
14
  })
@@ -19,7 +19,7 @@ export const specificationRuleChecks = (
19
19
  export const modelRuleChecks = (_: LikeC4Services): ValidationCheck<ast.Model> => {
20
20
  return (node, accept) => {
21
21
  if (node.$containerIndex && node.$containerIndex > 0) {
22
- accept('error', `Only one model per document is allowed`, {
22
+ accept('warning', `Prefer one model per document`, {
23
23
  node: node,
24
24
  property: 'name'
25
25
  })
@@ -30,7 +30,7 @@ export const modelRuleChecks = (_: LikeC4Services): ValidationCheck<ast.Model> =
30
30
  export const modelViewsChecks = (_: LikeC4Services): ValidationCheck<ast.ModelViews> => {
31
31
  return (node, accept) => {
32
32
  if (node.$containerIndex && node.$containerIndex > 0) {
33
- accept('error', `Only one views block per document is allowed`, {
33
+ accept('warning', `Prefer one views block per document`, {
34
34
  node: node,
35
35
  property: 'name'
36
36
  })
@@ -1,6 +1,6 @@
1
1
  import type { LikeC4View } from '@likec4/core'
2
- import { invariant } from '@likec4/core'
3
- import { filter, hasAtLeast, isTruthy, map, pipe, unique, zip } from 'remeda'
2
+ import { compareNatural, invariant } from '@likec4/core'
3
+ import { filter, hasAtLeast, isTruthy, map, pipe, unique } from 'remeda'
4
4
  import { parsePath } from 'ufo'
5
5
 
6
6
  function commonAncestorPath(views: LikeC4View[], sep = '/') {
@@ -11,7 +11,7 @@ function commonAncestorPath(views: LikeC4View[], sep = '/') {
11
11
  unique()
12
12
  )
13
13
  if (uniqURIs.length === 0) return ''
14
- if (hasAtLeast(uniqURIs, 1) && uniqURIs.length === 1) {
14
+ if (uniqURIs.length === 1) {
15
15
  const parts = parsePath(uniqURIs[0]).pathname.split(sep)
16
16
  if (parts.length <= 1) return sep
17
17
  parts.pop() // remove filename
@@ -47,7 +47,7 @@ export function resolveRelativePaths(views: LikeC4View[]): LikeC4View[] {
47
47
  .map(view => {
48
48
  if (!view.docUri) {
49
49
  return {
50
- ...view,
50
+ view,
51
51
  parts: []
52
52
  }
53
53
  }
@@ -62,28 +62,25 @@ export function resolveRelativePaths(views: LikeC4View[]): LikeC4View[] {
62
62
  path = path.includes(sep) ? path.slice(path.lastIndexOf(sep) + 1) : path
63
63
  }
64
64
  return {
65
- ...view,
65
+ view,
66
66
  parts: path.split(sep)
67
67
  }
68
68
  })
69
69
  // Sort views by path segments
70
70
  .sort((a, b) => {
71
- if (a.parts.length === b.parts.length) {
72
- if (a.parts.length === 0) {
73
- return 0
74
- }
75
- for (const [_a, _b] of zip(a.parts, b.parts)) {
76
- const compare = _a.localeCompare(_b)
77
- if (compare !== 0) {
78
- return compare
79
- }
71
+ if (a.parts.length !== b.parts.length) {
72
+ return a.parts.length - b.parts.length
73
+ }
74
+ for (let i = 0; i < a.parts.length; i++) {
75
+ const compare = compareNatural(a.parts[i], b.parts[i])
76
+ if (compare !== 0) {
77
+ return compare
80
78
  }
81
- return 0
82
79
  }
83
- return a.parts.length - b.parts.length
80
+ return compareNatural(a.view.title ?? a.view.id, b.view.title ?? b.view.id)
84
81
  })
85
82
  // Build relativePath from path segments
86
- .map(({ parts, ...view }) => {
83
+ .map(({ parts, view }) => {
87
84
  return {
88
85
  ...view,
89
86
  relativePath: parts.join(sep)