@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.
- package/contrib/likec4.tmLanguage.json +1 -1
- package/dist/browser.cjs +21 -0
- package/dist/browser.d.cts +22 -0
- package/dist/browser.d.mts +22 -0
- package/dist/browser.d.ts +22 -0
- package/dist/browser.mjs +19 -0
- package/dist/index.cjs +10 -0
- package/dist/index.d.cts +18 -0
- package/dist/index.d.mts +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.mjs +1 -0
- package/dist/likec4lib.cjs +961 -0
- package/dist/likec4lib.d.cts +6 -0
- package/dist/likec4lib.d.mts +6 -0
- package/dist/likec4lib.d.ts +6 -0
- package/dist/likec4lib.mjs +957 -0
- package/dist/model-graph/index.cjs +10 -0
- package/dist/model-graph/index.d.cts +79 -0
- package/dist/model-graph/index.d.mts +79 -0
- package/dist/model-graph/index.d.ts +79 -0
- package/dist/model-graph/index.mjs +1 -0
- package/dist/node.cjs +18 -0
- package/dist/node.d.cts +20 -0
- package/dist/node.d.mts +20 -0
- package/dist/node.d.ts +20 -0
- package/dist/node.mjs +16 -0
- package/dist/protocol.cjs +25 -0
- package/dist/protocol.d.cts +43 -0
- package/dist/protocol.d.mts +43 -0
- package/dist/protocol.d.ts +43 -0
- package/dist/protocol.mjs +17 -0
- package/dist/shared/language-server.86lmJ8ZN.d.cts +1194 -0
- package/dist/shared/language-server.B1TZgyoH.cjs +5371 -0
- package/dist/shared/language-server.CCB4ESN5.mjs +1606 -0
- package/dist/shared/language-server.CFTY6j4e.d.mts +1194 -0
- package/dist/shared/language-server.D0bOlrCi.cjs +1619 -0
- package/dist/shared/language-server.Q-wtPShM.mjs +5360 -0
- package/dist/shared/language-server.RjhrBZS0.d.ts +1194 -0
- package/package.json +35 -20
- package/src/ast.ts +44 -32
- package/src/browser.ts +0 -3
- package/src/elementRef.ts +1 -1
- package/src/generated/ast.ts +105 -86
- package/src/generated/grammar.ts +1 -1
- package/src/generated-lib/icons.ts +1 -1
- package/src/like-c4.langium +30 -18
- package/src/likec4lib.ts +2 -3
- package/src/logger.ts +9 -1
- package/src/lsp/RenameProvider.ts +8 -0
- package/src/lsp/SemanticTokenProvider.ts +19 -1
- package/src/lsp/index.ts +1 -0
- package/src/model/fqn-computation.ts +33 -23
- package/src/model/fqn-index.ts +5 -20
- package/src/model/model-builder.ts +147 -90
- package/src/model/model-locator.ts +1 -1
- package/src/model/model-parser-where.ts +3 -2
- package/src/model/model-parser.ts +57 -19
- package/src/model-graph/LikeC4ModelGraph.ts +42 -21
- package/src/model-graph/compute-view/__test__/fixture.ts +16 -14
- package/src/model-graph/compute-view/compute.ts +9 -6
- package/src/model-graph/compute-view/predicates.ts +3 -3
- package/src/model-graph/dynamic-view/__test__/fixture.ts +1 -0
- package/src/model-graph/dynamic-view/compute.ts +2 -1
- package/src/model-graph/utils/elementExpressionToPredicate.ts +1 -1
- package/src/model-graph/utils/sortNodes.ts +2 -6
- package/src/module.ts +23 -3
- package/src/protocol.ts +4 -5
- package/src/references/scope-computation.ts +10 -1
- package/src/references/scope-provider.ts +22 -9
- package/src/shared/NodeKindProvider.ts +73 -34
- package/src/test/setup.ts +3 -8
- package/src/utils/graphlib.ts +11 -0
- package/src/validation/_shared.ts +24 -0
- package/src/validation/element.ts +9 -9
- package/src/validation/index.ts +2 -1
- package/src/validation/relation.ts +45 -39
- package/src/validation/specification.ts +15 -2
- package/src/validation/view.ts +7 -0
- package/src/view-utils/manual-layout.ts +1 -1
- package/src/view-utils/resolve-extended-views.ts +19 -10
- package/src/view-utils/resolve-relative-paths.ts +5 -7
- package/src/view-utils/view-hash.ts +1 -1
- package/src/reset.d.ts +0 -2
package/src/like-c4.langium
CHANGED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
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
|
-
|
|
148
|
-
|
|
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' ':'?
|
|
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 = '
|
|
4
|
-
export const
|
|
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.
|
|
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
|
|
@@ -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
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import { AsFqn,
|
|
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 {
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
if (
|
|
63
|
-
|
|
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
|
-
|
|
74
|
+
nonexhaustive(el)
|
|
75
|
+
} catch (e) {
|
|
76
|
+
logError(e)
|
|
66
77
|
}
|
|
67
|
-
nonexhaustive(el)
|
|
68
78
|
}
|
|
69
79
|
}
|
package/src/model/fqn-index.ts
CHANGED
|
@@ -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 {
|
|
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
|
-
|
|
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
|
|
54
|
+
private entries(filterByFqn: (fqn: Fqn) => boolean): Stream<DocFqnIndexAstNodeDescription> {
|
|
55
55
|
return this.documents.flatMap(doc => {
|
|
56
|
-
|
|
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> {
|