@likec4/language-server 1.8.0 → 1.9.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 (83) 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.86lmJ8ZN.d.cts +1194 -0
  33. package/dist/shared/language-server.B1TZgyoH.cjs +5371 -0
  34. package/dist/shared/language-server.CCB4ESN5.mjs +1606 -0
  35. package/dist/shared/language-server.CFTY6j4e.d.mts +1194 -0
  36. package/dist/shared/language-server.D0bOlrCi.cjs +1619 -0
  37. package/dist/shared/language-server.Q-wtPShM.mjs +5360 -0
  38. package/dist/shared/language-server.RjhrBZS0.d.ts +1194 -0
  39. package/package.json +35 -20
  40. package/src/ast.ts +44 -32
  41. package/src/browser.ts +0 -3
  42. package/src/elementRef.ts +1 -1
  43. package/src/generated/ast.ts +105 -86
  44. package/src/generated/grammar.ts +1 -1
  45. package/src/generated-lib/icons.ts +1 -1
  46. package/src/like-c4.langium +30 -18
  47. package/src/likec4lib.ts +2 -3
  48. package/src/logger.ts +9 -1
  49. package/src/lsp/RenameProvider.ts +8 -0
  50. package/src/lsp/SemanticTokenProvider.ts +19 -1
  51. package/src/lsp/index.ts +1 -0
  52. package/src/model/fqn-computation.ts +33 -23
  53. package/src/model/fqn-index.ts +5 -20
  54. package/src/model/model-builder.ts +147 -90
  55. package/src/model/model-locator.ts +1 -1
  56. package/src/model/model-parser-where.ts +3 -2
  57. package/src/model/model-parser.ts +57 -19
  58. package/src/model-graph/LikeC4ModelGraph.ts +42 -21
  59. package/src/model-graph/compute-view/__test__/fixture.ts +16 -14
  60. package/src/model-graph/compute-view/compute.ts +9 -6
  61. package/src/model-graph/compute-view/predicates.ts +3 -3
  62. package/src/model-graph/dynamic-view/__test__/fixture.ts +1 -0
  63. package/src/model-graph/dynamic-view/compute.ts +2 -1
  64. package/src/model-graph/utils/elementExpressionToPredicate.ts +1 -1
  65. package/src/model-graph/utils/sortNodes.ts +2 -6
  66. package/src/module.ts +23 -3
  67. package/src/protocol.ts +4 -5
  68. package/src/references/scope-computation.ts +10 -1
  69. package/src/references/scope-provider.ts +22 -9
  70. package/src/shared/NodeKindProvider.ts +73 -34
  71. package/src/test/setup.ts +3 -8
  72. package/src/utils/graphlib.ts +11 -0
  73. package/src/validation/_shared.ts +24 -0
  74. package/src/validation/element.ts +9 -9
  75. package/src/validation/index.ts +2 -1
  76. package/src/validation/relation.ts +45 -39
  77. package/src/validation/specification.ts +15 -2
  78. package/src/validation/view.ts +7 -0
  79. package/src/view-utils/manual-layout.ts +1 -1
  80. package/src/view-utils/resolve-extended-views.ts +19 -10
  81. package/src/view-utils/resolve-relative-paths.ts +5 -7
  82. package/src/view-utils/view-hash.ts +1 -1
  83. package/src/reset.d.ts +0 -2
@@ -1,4 +1,4 @@
1
- export const LibIcons = `likec4lib {
1
+ export const LibIcons: string = `likec4lib {
2
2
  icons {
3
3
  aws:activate
4
4
  aws:alexa-for-business
@@ -31,12 +31,16 @@ Tag:
31
31
  RelationshipKind:
32
32
  name=Id;
33
33
 
34
+ CustomColor:
35
+ name=CustomColorId;
36
+
34
37
  SpecificationRule:
35
38
  name='specification' '{'
36
39
  (
37
40
  elements+=SpecificationElementKind |
38
41
  tags+=SpecificationTag |
39
- relationships+=SpecificationRelationshipKind
42
+ relationships+=SpecificationRelationshipKind |
43
+ colors+=SpecificationColor
40
44
  )*
41
45
  '}';
42
46
 
@@ -54,6 +58,9 @@ SpecificationElementStringProperty:
54
58
  SpecificationTag:
55
59
  'tag' tag=Tag;
56
60
 
61
+ SpecificationColor:
62
+ 'color' name=CustomColor color=CustomColorValue;
63
+
57
64
  SpecificationRelationshipKind:
58
65
  'relationship' kind=RelationshipKind ('{'
59
66
  props+=(
@@ -72,7 +79,7 @@ Model:
72
79
  name='model' '{'
73
80
  elements+=(
74
81
  ExtendElement |
75
- ExplicitRelation |
82
+ Relation<true> |
76
83
  Element
77
84
  )*
78
85
  '}'
@@ -97,7 +104,7 @@ ElementBody: '{'
97
104
  tags=Tags?
98
105
  props+=ElementProperty*
99
106
  elements+=(
100
- Relation |
107
+ Relation<false> |
101
108
  Element
102
109
  )*
103
110
  '}'
@@ -115,7 +122,7 @@ ExtendElement:
115
122
 
116
123
  ExtendElementBody: '{'
117
124
  elements+=(
118
- ExplicitRelation |
125
+ Relation<true> |
119
126
  Element
120
127
  )*
121
128
  '}'
@@ -132,20 +139,18 @@ Tags:
132
139
  (values+=[Tag:TagId])+ ({infer Tags.prev=current} ',' (values+=[Tag:TagId])*)* ';'?
133
140
  ;
134
141
 
135
- Relation:
136
- ExplicitRelation | ImplicitRelation;
137
-
138
- ExplicitRelation:
139
- source=ElementRef RelationFragment;
140
-
141
- ImplicitRelation:
142
- ('this' | 'it')? RelationFragment;
143
-
144
- fragment RelationFragment:
145
- ('->' | '-[' kind=[RelationshipKind] ']->' | kind=[RelationshipKind:DotId] )
142
+ Relation<isExplicit>:
143
+ (<isExplicit> source=ElementRef | <!isExplicit> source=ElementRef?)
144
+ (
145
+ kind=[RelationshipKind:DotId] |
146
+ '-[' kind=[RelationshipKind] ']->' |
147
+ '->'
148
+ )
146
149
  target=ElementRef
147
- title=String?
148
- technology=String?
150
+ (
151
+ title=String
152
+ technology=String?
153
+ )?
149
154
  tags=Tags?
150
155
  body=RelationBody?
151
156
  ;
@@ -449,7 +454,7 @@ NavigateToProperty:
449
454
  LinkProperty:
450
455
  key='link' ':'? value=Uri title=String? ';'?;
451
456
  ColorProperty:
452
- key='color' ':'? value=ThemeColor ';'?;
457
+ key='color' ':'? (themeColor=ThemeColor | customColor=[CustomColor:CustomColorId]) ';'?;
453
458
 
454
459
  OpacityProperty:
455
460
  key='opacity' ':'? value=Percent ';'?;
@@ -515,6 +520,9 @@ ThemeColor returns string:
515
520
  ElementShape returns string:
516
521
  'rectangle' | 'person' | 'browser' | 'mobile' | 'cylinder' | 'storage' | 'queue';
517
522
 
523
+ CustomColorValue returns string:
524
+ Hash (Id | Hex);
525
+
518
526
  IconId returns string:
519
527
  LIB_ICON;
520
528
 
@@ -527,6 +535,9 @@ TagId returns string:
527
535
  DotId returns string:
528
536
  Dot Id;
529
537
 
538
+ CustomColorId returns string:
539
+ IdTerminal | ElementShape | ArrowType | LineOptions | 'element' | 'model';
540
+
530
541
  Id returns string:
531
542
  IdTerminal | ElementShape | ThemeColor | ArrowType | LineOptions | 'element' | 'model';
532
543
 
@@ -582,3 +593,4 @@ terminal String: /"[^"]*"|'[^']*'/;
582
593
  // terminal TagId: HASH LETTER (LETTER | DIGIT | UNDERSCORE | DASH)*;
583
594
  // terminal IdTerminal: (LETTER | UNDERSCORE+ (LETTER | DIGIT)) (LETTER | DIGIT | UNDERSCORE | DASH)*;
584
595
  terminal IdTerminal: /[_]*[a-zA-Z][-\w]*/;
596
+ terminal Hex: /[a-zA-Z0-9]+/;
package/src/likec4lib.ts CHANGED
@@ -1,7 +1,6 @@
1
1
  import { LibIcons } from './generated-lib/icons'
2
2
 
3
- export const Scheme = 'likec4-lib'
4
- export const Path = `/icons.c4`
5
- export const Uri = `${Scheme}://${Path}`
3
+ export const Scheme = 'likec4builtin'
4
+ export const Uri = `${Scheme}:///likec4/lib/icons.c4`
6
5
 
7
6
  export { LibIcons as Content }
package/src/logger.ts CHANGED
@@ -65,14 +65,22 @@ export function logToLspConnection(connection: Connection): void {
65
65
  }
66
66
  const message = parts.join(' ')
67
67
  switch (true) {
68
+ case level >= LogLevels.trace: {
69
+ connection.tracer.log(message)
70
+ break
71
+ }
68
72
  case level >= LogLevels.debug: {
69
73
  connection.console.debug(message)
70
74
  break
71
75
  }
72
- case level >= LogLevels.log: {
76
+ case level >= LogLevels.info: {
73
77
  connection.console.info(message)
74
78
  break
75
79
  }
80
+ case level >= LogLevels.log: {
81
+ connection.console.log(message)
82
+ break
83
+ }
76
84
  case level >= LogLevels.warn: {
77
85
  connection.console.warn(message)
78
86
  break
@@ -0,0 +1,8 @@
1
+ import { DefaultRenameProvider } from 'langium/lsp'
2
+ import type { LikeC4Services } from '../module'
3
+
4
+ export class LikeC4RenameProvider extends DefaultRenameProvider {
5
+ constructor(services: LikeC4Services) {
6
+ super(services)
7
+ }
8
+ }
@@ -118,6 +118,23 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
118
118
  })
119
119
  return !node.parent ? 'prune' : undefined
120
120
  }
121
+ if (ast.isSpecificationColor(node)) {
122
+ acceptor({
123
+ node,
124
+ keyword: 'color',
125
+ type: SemanticTokenTypes.keyword
126
+ })
127
+ acceptor({
128
+ node,
129
+ property: 'name',
130
+ type: SemanticTokenTypes.type,
131
+ modifier: [
132
+ SemanticTokenModifiers.declaration,
133
+ SemanticTokenModifiers.readonly
134
+ ]
135
+ })
136
+ return
137
+ }
121
138
  if (ast.isSpecificationElementKind(node) || ast.isSpecificationRelationshipKind(node)) {
122
139
  acceptor({
123
140
  node,
@@ -188,7 +205,8 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
188
205
  acceptor({
189
206
  node,
190
207
  property: 'libicon',
191
- type: SemanticTokenTypes.enum
208
+ type: SemanticTokenTypes.enum,
209
+ modifier: [SemanticTokenModifiers.defaultLibrary]
192
210
  })
193
211
  }
194
212
  return 'prune'
package/src/lsp/index.ts CHANGED
@@ -4,4 +4,5 @@ export * from './DocumentHighlightProvider'
4
4
  export * from './DocumentLinkProvider'
5
5
  export * from './DocumentSymbolProvider'
6
6
  export * from './HoverProvider'
7
+ export * from './RenameProvider'
7
8
  export * from './SemanticTokenProvider'
@@ -1,8 +1,10 @@
1
- import { AsFqn, type c4, nonexhaustive } from '@likec4/core'
1
+ import { AsFqn, nonexhaustive } from '@likec4/core'
2
+ import type * as c4 from '@likec4/core'
2
3
  import { type AstNodeDescription, type AstNodeLocator, AstUtils, CstUtils, GrammarUtils, MultiMap } from 'langium'
3
- import { isEmpty, isNullish as isNil } from 'remeda'
4
+ import { isDefined, isEmpty } from 'remeda'
4
5
  import { ast, ElementOps, type LikeC4LangiumDocument } from '../ast'
5
6
  import { getFqnElementRef } from '../elementRef'
7
+ import { logError } from '../logger'
6
8
  import type { LikeC4Services } from '../module'
7
9
 
8
10
  const { findNodeForProperty } = GrammarUtils
@@ -41,29 +43,37 @@ export function computeDocumentFqn(document: LikeC4LangiumDocument, services: Li
41
43
  const traverseStack: TraversePair[] = elements.map(el => [el, null])
42
44
  let pair
43
45
  while ((pair = traverseStack.shift())) {
44
- const [el, parent] = pair
45
- if (ast.isRelation(el)) {
46
- continue
47
- }
48
- if (ast.isExtendElement(el)) {
49
- if (!isNil(el.body) && !isEmpty(el.body.elements)) {
50
- const fqn = getFqnElementRef(el.element)
51
- el.body.elements.forEach(child => traverseStack.push([child, fqn]))
46
+ try {
47
+ const [el, parent] = pair
48
+ if (ast.isRelation(el)) {
49
+ continue
52
50
  }
53
- continue
54
- }
55
- if (ast.isElement(el)) {
56
- const fqn = AsFqn(el.name, parent)
57
- c4fqnIndex.add(fqn, {
58
- ...toAstNodeDescription(locator, el, document),
59
- fqn
60
- })
61
- ElementOps.writeId(el, fqn)
62
- if (!isNil(el.body) && !isEmpty(el.body.elements)) {
63
- el.body.elements.forEach(child => traverseStack.push([child, fqn]))
51
+ if (ast.isExtendElement(el)) {
52
+ if (isDefined(el.body) && !isEmpty(el.body.elements)) {
53
+ const fqn = getFqnElementRef(el.element)
54
+ for (const child of el.body.elements) {
55
+ traverseStack.push([child, fqn])
56
+ }
57
+ }
58
+ continue
59
+ }
60
+ if (ast.isElement(el)) {
61
+ const fqn = AsFqn(el.name, parent)
62
+ c4fqnIndex.add(fqn, {
63
+ ...toAstNodeDescription(locator, el, document),
64
+ fqn
65
+ })
66
+ ElementOps.writeId(el, fqn)
67
+ if (isDefined(el.body) && !isEmpty(el.body.elements)) {
68
+ for (const child of el.body.elements) {
69
+ traverseStack.push([child, fqn])
70
+ }
71
+ }
72
+ continue
64
73
  }
65
- continue
74
+ nonexhaustive(el)
75
+ } catch (e) {
76
+ logError(e)
66
77
  }
67
- nonexhaustive(el)
68
78
  }
69
79
  }
@@ -4,7 +4,7 @@ import type { AstNodeDescription, LangiumDocuments, Stream } from 'langium'
4
4
  import { DocumentState, DONE_RESULT, MultiMap, stream, StreamImpl } from 'langium'
5
5
  import type { ast, DocFqnIndexAstNodeDescription, FqnIndexedDocument } from '../ast'
6
6
  import { ElementOps, isFqnIndexedDocument, isLikeC4LangiumDocument } from '../ast'
7
- import { logError, logger } from '../logger'
7
+ import { logger, logWarnError } from '../logger'
8
8
  import type { LikeC4Services } from '../module'
9
9
  import { printDocs } from '../utils/printDocs'
10
10
  import { computeDocumentFqn } from './fqn-computation'
@@ -37,11 +37,11 @@ export class FqnIndex {
37
37
  try {
38
38
  computeDocumentFqn(doc, services)
39
39
  } catch (e) {
40
- logError(e)
40
+ logWarnError(e)
41
41
  }
42
42
  }
43
43
  }
44
- return Promise.resolve()
44
+ return await Promise.resolve()
45
45
  }
46
46
  )
47
47
  logger.debug(`[FqnIndex] Created`)
@@ -51,29 +51,14 @@ export class FqnIndex {
51
51
  return this.langiumDocuments.all.filter(isFqnIndexedDocument)
52
52
  }
53
53
 
54
- private entries(filterByFqn?: (fqn: Fqn) => boolean): Stream<DocFqnIndexAstNodeDescription> {
54
+ private entries(filterByFqn: (fqn: Fqn) => boolean): Stream<DocFqnIndexAstNodeDescription> {
55
55
  return this.documents.flatMap(doc => {
56
- if (filterByFqn) {
57
- return doc.c4fqnIndex.keys().filter(filterByFqn).flatMap(fqn => doc.c4fqnIndex.get(fqn))
58
- }
59
- return doc.c4fqnIndex.values()
56
+ return doc.c4fqnIndex.keys().filter(filterByFqn).flatMap(fqn => doc.c4fqnIndex.get(fqn))
60
57
  })
61
58
  }
62
59
 
63
60
  public getFqn(el: ast.Element): Fqn | null {
64
61
  return ElementOps.readId(el) ?? null
65
- // let fqn = ElementOps.readId(el) ?? null
66
- // if (fqn) {
67
- // const doc = getDocument(el)
68
- // if (isFqnIndexedDocument(doc) && doc.c4fqns.has(fqn)) {
69
- // return fqn
70
- // }
71
- // const path = this.services.workspace.AstNodeLocator.getAstNodePath(el)
72
- // logError(`Clean cached FQN ${fqn} at ${path}`)
73
- // ElementOps.writeId(el, null)
74
- // fqn = null
75
- // }
76
- // return fqn
77
62
  }
78
63
 
79
64
  public byFqn(fqn: Fqn): Stream<AstNodeDescription> {