@likec4/language-server 1.4.0 → 1.6.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/README.md +1 -1
- package/contrib/likec4.tmLanguage.json +1 -1
- package/package.json +26 -14
- package/src/Rpc.ts +25 -2
- package/src/ast.ts +19 -15
- package/src/generated/ast.ts +390 -203
- package/src/generated/grammar.ts +1 -1
- package/src/generated-lib/icons.ts +952 -0
- package/src/like-c4.langium +120 -64
- package/src/likec4lib.ts +7 -0
- package/src/lsp/DocumentSymbolProvider.ts +28 -1
- package/src/lsp/SemanticTokenProvider.ts +41 -22
- package/src/model/fqn-computation.ts +29 -7
- package/src/model/fqn-index.ts +18 -31
- package/src/model/model-builder.ts +13 -9
- package/src/model/model-locator.ts +7 -7
- package/src/model/model-parser.ts +166 -69
- package/src/model-change/changeElementStyle.ts +6 -6
- package/src/model-graph/compute-view/__test__/fixture.ts +52 -24
- package/src/model-graph/compute-view/compute.ts +51 -20
- package/src/model-graph/compute-view/predicates.ts +6 -1
- package/src/model-graph/dynamic-view/__test__/fixture.ts +2 -2
- package/src/model-graph/dynamic-view/compute.ts +2 -2
- package/src/model-graph/utils/{applyElementCustomProperties.ts → applyCustomElementProperties.ts} +5 -3
- package/src/model-graph/utils/applyCustomRelationProperties.ts +50 -0
- package/src/model-graph/utils/applyViewRuleStyles.ts +11 -34
- package/src/model-graph/utils/elementExpressionToPredicate.ts +32 -0
- package/src/references/scope-computation.ts +113 -60
- package/src/references/scope-provider.ts +3 -23
- package/src/shared/NodeKindProvider.ts +1 -0
- package/src/shared/WorkspaceManager.ts +15 -6
- package/src/validation/dynamic-view-rule.ts +19 -26
- package/src/validation/element.ts +8 -4
- package/src/validation/index.ts +9 -6
- package/src/validation/property-checks.ts +23 -1
- package/src/validation/view-predicates/custom-element-expr.ts +21 -8
- package/src/validation/view-predicates/custom-relation-expr.ts +16 -0
- package/src/validation/view-predicates/expanded-element.ts +13 -24
- package/src/validation/view-predicates/incoming.ts +5 -5
- package/src/validation/view-predicates/index.ts +1 -0
- package/src/validation/view-predicates/outgoing.ts +5 -5
- package/src/view-utils/assignNavigateTo.ts +2 -2
- package/src/view-utils/manual-layout.ts +4 -2
- package/src/view-utils/resolve-extended-views.ts +2 -2
- package/src/view-utils/resolve-relative-paths.ts +3 -3
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
# `@likec4/language-server`
|
|
2
2
|
|
|
3
|
-
[docs](https://
|
|
3
|
+
[docs](https://likec4.dev/) | [playground](https://playground.likec4.dev/) | [demo](https://template.likec4.dev/view/cloud)
|
|
4
4
|
|
|
5
5
|
Language Server Protocol (LSP) based on [languim](https://github.com/languim/languim) library.
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
14
|
"name": "keyword.control.likec4",
|
|
15
|
-
"match": "\\b(BottomTop|LeftRight|RightLeft|TopBottom|amber|autoLayout|blue|border|browser|color|crow|cylinder|dashed|description|diamond|dotted|dynamic|element|exclude|extend|extends|gray|green|head|icon|include|indigo|it|
|
|
15
|
+
"match": "\\b(BottomTop|LeftRight|RightLeft|TopBottom|amber|autoLayout|blue|border|browser|color|crow|cylinder|dashed|description|diamond|dot|dotted|dynamic|element|element\\.kind|element\\.tag|exclude|extend|extends|gray|green|head|icon|icons|include|indigo|it|likec4lib|line|link|mobile|model|muted|navigateTo|none|normal|odiamond|odot|of|onormal|opacity|open|person|primary|queue|rectangle|red|relationship|secondary|shape|sky|slate|solid|specification|storage|style|tag|tail|technology|this|title|vee|view|views|with)\\b"
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
"name": "string.quoted.double.likec4",
|
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.
|
|
4
|
+
"version": "1.6.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bugs": "https://github.com/likec4/likec4/issues",
|
|
7
7
|
"homepage": "https://likec4.dev",
|
|
@@ -26,6 +26,10 @@
|
|
|
26
26
|
"types": "./dist/index.d.ts",
|
|
27
27
|
"default": "./dist/index.js"
|
|
28
28
|
},
|
|
29
|
+
"./likec4lib": {
|
|
30
|
+
"types": "./dist/likec4lib.d.ts",
|
|
31
|
+
"default": "./dist/likec4lib.js"
|
|
32
|
+
},
|
|
29
33
|
"./browser": {
|
|
30
34
|
"types": "./dist/browser/index.d.ts",
|
|
31
35
|
"default": "./dist/browser/index.js"
|
|
@@ -51,6 +55,10 @@
|
|
|
51
55
|
"types": "./dist/index.d.ts",
|
|
52
56
|
"default": "./dist/index.js"
|
|
53
57
|
},
|
|
58
|
+
"./likec4lib": {
|
|
59
|
+
"types": "./dist/likec4lib.d.ts",
|
|
60
|
+
"default": "./dist/likec4lib.js"
|
|
61
|
+
},
|
|
54
62
|
"./browser": {
|
|
55
63
|
"types": "./dist/browser/index.d.ts",
|
|
56
64
|
"default": "./dist/browser/index.js"
|
|
@@ -71,45 +79,49 @@
|
|
|
71
79
|
},
|
|
72
80
|
"scripts": {
|
|
73
81
|
"typecheck": "tsc --noEmit",
|
|
82
|
+
"pregenerate": "rm -f src/generated/*",
|
|
74
83
|
"watch:langium": "langium generate --watch",
|
|
75
84
|
"watch:ts": "tsc --watch",
|
|
76
|
-
"generate": "langium generate",
|
|
85
|
+
"generate": "langium generate && tsx scripts/generate-icons.ts",
|
|
77
86
|
"dev": "run-p 'watch:*'",
|
|
78
87
|
"lint": "run -T eslint src/ --fix",
|
|
79
88
|
"clean": "run -T rimraf dist contrib",
|
|
80
89
|
"test": "vitest run --no-isolate",
|
|
90
|
+
"vitest:ui": "vitest --no-isolate --ui",
|
|
81
91
|
"test:watch": "vitest"
|
|
82
92
|
},
|
|
83
93
|
"dependencies": {
|
|
84
94
|
"@dagrejs/graphlib": "^2.2.2",
|
|
85
|
-
"@likec4/core": "1.
|
|
95
|
+
"@likec4/core": "1.6.0",
|
|
86
96
|
"@total-typescript/ts-reset": "^0.5.1",
|
|
87
97
|
"fast-equals": "^5.0.1",
|
|
88
98
|
"indent-string": "^5.0.0",
|
|
89
99
|
"json5": "^2.2.3",
|
|
90
|
-
"langium": "3.1.
|
|
100
|
+
"langium": "3.1.2",
|
|
91
101
|
"object-hash": "^3.0.0",
|
|
92
102
|
"p-debounce": "^4.0.0",
|
|
93
|
-
"
|
|
94
|
-
"remeda": "^1.61.0",
|
|
103
|
+
"remeda": "^2.3.0",
|
|
95
104
|
"string-hash": "^1.1.3",
|
|
96
105
|
"strip-indent": "^4.0.0",
|
|
97
|
-
"type-fest": "^4.
|
|
106
|
+
"type-fest": "^4.21.0",
|
|
98
107
|
"ufo": "^1.5.3",
|
|
99
108
|
"vscode-languageserver": "9.0.1",
|
|
100
109
|
"vscode-languageserver-protocol": "3.17.5",
|
|
101
110
|
"vscode-uri": "3.0.8"
|
|
102
111
|
},
|
|
103
112
|
"devDependencies": {
|
|
104
|
-
"@likec4/
|
|
105
|
-
"@
|
|
113
|
+
"@likec4/icons": "1.6.0",
|
|
114
|
+
"@likec4/tsconfig": "1.6.0",
|
|
115
|
+
"@types/node": "^20.14.10",
|
|
106
116
|
"@types/object-hash": "^3.0.6",
|
|
107
117
|
"@types/string-hash": "^1.1.3",
|
|
108
|
-
"execa": "^9.
|
|
118
|
+
"execa": "^9.3.0",
|
|
119
|
+
"glob": "^11.0.0",
|
|
109
120
|
"langium-cli": "3.1.0",
|
|
110
|
-
"npm-run-all2": "^6.
|
|
111
|
-
"
|
|
112
|
-
"
|
|
121
|
+
"npm-run-all2": "^6.2.2",
|
|
122
|
+
"tsx": "~4.9.3",
|
|
123
|
+
"typescript": "^5.5.3",
|
|
124
|
+
"vitest": "~2.0.3"
|
|
113
125
|
},
|
|
114
|
-
"packageManager": "yarn@4.3.
|
|
126
|
+
"packageManager": "yarn@4.3.1"
|
|
115
127
|
}
|
package/src/Rpc.ts
CHANGED
|
@@ -3,8 +3,9 @@ import { logError, logger } from './logger'
|
|
|
3
3
|
import type { LikeC4Services } from './module'
|
|
4
4
|
|
|
5
5
|
import { nonexhaustive } from '@likec4/core'
|
|
6
|
-
import { Disposable, URI, UriUtils } from 'langium'
|
|
6
|
+
import { Disposable, interruptAndCheck, URI, UriUtils } from 'langium'
|
|
7
7
|
import { isLikeC4LangiumDocument } from './ast'
|
|
8
|
+
import { Scheme } from './likec4lib'
|
|
8
9
|
import {
|
|
9
10
|
buildDocuments,
|
|
10
11
|
changeView,
|
|
@@ -46,6 +47,8 @@ export class Rpc implements Disposable {
|
|
|
46
47
|
}
|
|
47
48
|
)
|
|
48
49
|
|
|
50
|
+
let isFirstBuild = true
|
|
51
|
+
|
|
49
52
|
this.disposables.push(
|
|
50
53
|
Disposable.create(() => {
|
|
51
54
|
notifyModelParsed.cancel()
|
|
@@ -67,7 +70,7 @@ export class Rpc implements Disposable {
|
|
|
67
70
|
const changed = docs.map(d => URI.parse(d))
|
|
68
71
|
const notChanged = (uri: URI) => changed.every(c => !UriUtils.equals(c, uri))
|
|
69
72
|
const deleted = LangiumDocuments.all
|
|
70
|
-
.filter(d => isLikeC4LangiumDocument(d) && notChanged(d.uri))
|
|
73
|
+
.filter(d => isLikeC4LangiumDocument(d) && notChanged(d.uri) && d.uri.scheme !== Scheme)
|
|
71
74
|
.map(d => d.uri)
|
|
72
75
|
.toArray()
|
|
73
76
|
logger.debug(
|
|
@@ -75,6 +78,26 @@ export class Rpc implements Disposable {
|
|
|
75
78
|
changed (total ${changed.length}):${docs.map(d => '\n - ' + d).join('')}
|
|
76
79
|
deleted (total ${deleted.length}):${deleted.map(d => '\n - ' + d.toString()).join('\n')}`
|
|
77
80
|
)
|
|
81
|
+
|
|
82
|
+
if (!isFirstBuild && (changed.length + deleted.length) > 0) {
|
|
83
|
+
await Promise.allSettled(
|
|
84
|
+
[...changed, ...deleted].map(async d => {
|
|
85
|
+
const uri = d.toString()
|
|
86
|
+
logger.debug(`clear diagnostics for ${uri}`)
|
|
87
|
+
try {
|
|
88
|
+
await connection.sendDiagnostics({
|
|
89
|
+
uri,
|
|
90
|
+
diagnostics: []
|
|
91
|
+
})
|
|
92
|
+
} catch (e) {
|
|
93
|
+
// Ignore
|
|
94
|
+
logger.warn(`error clearing diagnostics for ${uri}: ${e}`)
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
)
|
|
98
|
+
await interruptAndCheck(cancelToken)
|
|
99
|
+
}
|
|
100
|
+
isFirstBuild = false
|
|
78
101
|
await DocumentBuilder.update(changed, deleted, cancelToken)
|
|
79
102
|
}),
|
|
80
103
|
connection.onRequest(locate, params => {
|
package/src/ast.ts
CHANGED
|
@@ -6,9 +6,9 @@ import {
|
|
|
6
6
|
nonexhaustive,
|
|
7
7
|
RelationRefError
|
|
8
8
|
} from '@likec4/core'
|
|
9
|
-
import type { AstNode, DiagnosticInfo, LangiumDocument, MultiMap } from 'langium'
|
|
9
|
+
import type { AstNode, AstNodeDescription, DiagnosticInfo, LangiumDocument, MultiMap } from 'langium'
|
|
10
10
|
import { AstUtils, DocumentState } from 'langium'
|
|
11
|
-
import { clamp, isNullish } from 'remeda'
|
|
11
|
+
import { clamp, isNullish, isTruthy } from 'remeda'
|
|
12
12
|
import type { ConditionalPick, SetRequired, ValueOf } from 'type-fest'
|
|
13
13
|
import type { Diagnostic } from 'vscode-languageserver-protocol'
|
|
14
14
|
import { DiagnosticSeverity } from 'vscode-languageserver-protocol'
|
|
@@ -133,10 +133,8 @@ export const ElementOps = {
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
export interface
|
|
137
|
-
|
|
138
|
-
el: WeakRef<ast.Element>
|
|
139
|
-
path: string
|
|
136
|
+
export interface DocFqnIndexAstNodeDescription extends AstNodeDescription {
|
|
137
|
+
fqn: c4.Fqn
|
|
140
138
|
}
|
|
141
139
|
|
|
142
140
|
// export type LikeC4AstNode = ast.LikeC4AstType[keyof ast.LikeC4AstType]
|
|
@@ -150,14 +148,14 @@ export interface LikeC4DocumentProps {
|
|
|
150
148
|
c4Relations?: ParsedAstRelation[]
|
|
151
149
|
c4Views?: ParsedAstView[]
|
|
152
150
|
// Fqn -> Element
|
|
153
|
-
|
|
151
|
+
c4fqnIndex?: MultiMap<c4.Fqn, DocFqnIndexAstNodeDescription>
|
|
154
152
|
}
|
|
155
153
|
|
|
156
154
|
export interface LikeC4LangiumDocument
|
|
157
155
|
extends Omit<LangiumDocument<LikeC4Grammar>, 'diagnostics'>, LikeC4DocumentProps
|
|
158
156
|
{}
|
|
159
157
|
export interface FqnIndexedDocument
|
|
160
|
-
extends Omit<LangiumDocument<LikeC4Grammar>, 'diagnostics'>, SetRequired<LikeC4DocumentProps, '
|
|
158
|
+
extends Omit<LangiumDocument<LikeC4Grammar>, 'diagnostics'>, SetRequired<LikeC4DocumentProps, 'c4fqnIndex'>
|
|
161
159
|
{}
|
|
162
160
|
|
|
163
161
|
// export type ParsedLikeC4LangiumDocument = SetRequired<FqnIndexedDocument, keyof LikeC4DocumentProps>
|
|
@@ -166,7 +164,7 @@ export interface ParsedLikeC4LangiumDocument
|
|
|
166
164
|
{}
|
|
167
165
|
|
|
168
166
|
export function cleanParsedModel(doc: LikeC4LangiumDocument) {
|
|
169
|
-
const props: Required<Omit<LikeC4DocumentProps, '
|
|
167
|
+
const props: Required<Omit<LikeC4DocumentProps, 'c4fqnIndex' | 'diagnostics'>> = {
|
|
170
168
|
c4Specification: {
|
|
171
169
|
kinds: {},
|
|
172
170
|
relationships: {}
|
|
@@ -179,7 +177,7 @@ export function cleanParsedModel(doc: LikeC4LangiumDocument) {
|
|
|
179
177
|
}
|
|
180
178
|
|
|
181
179
|
export function isFqnIndexedDocument(doc: LangiumDocument): doc is FqnIndexedDocument {
|
|
182
|
-
return isLikeC4LangiumDocument(doc) && doc.state >= DocumentState.IndexedContent && !!doc.
|
|
180
|
+
return isLikeC4LangiumDocument(doc) && doc.state >= DocumentState.IndexedContent && !!doc.c4fqnIndex
|
|
183
181
|
}
|
|
184
182
|
|
|
185
183
|
export function isLikeC4LangiumDocument(doc: LangiumDocument): doc is LikeC4LangiumDocument {
|
|
@@ -196,7 +194,7 @@ export function isParsedLikeC4LangiumDocument(
|
|
|
196
194
|
&& !!doc.c4Elements
|
|
197
195
|
&& !!doc.c4Relations
|
|
198
196
|
&& !!doc.c4Views
|
|
199
|
-
&& !!doc.
|
|
197
|
+
&& !!doc.c4fqnIndex
|
|
200
198
|
)
|
|
201
199
|
}
|
|
202
200
|
|
|
@@ -209,15 +207,18 @@ function validatableAstNodeGuards<const Predicates extends Guard<AstNode>[]>(
|
|
|
209
207
|
return (n: AstNode): n is Guarded<Predicates[number]> => predicates.some(p => p(n))
|
|
210
208
|
}
|
|
211
209
|
const isValidatableAstNode = validatableAstNodeGuards([
|
|
212
|
-
ast.
|
|
213
|
-
ast.
|
|
210
|
+
ast.isDynamicViewRulePredicateIterator,
|
|
211
|
+
ast.isCustomElementExpression,
|
|
212
|
+
ast.isCustomRelationExpression,
|
|
213
|
+
ast.isElementExpression,
|
|
214
|
+
ast.isRelationExpression,
|
|
214
215
|
ast.isDynamicViewRulePredicate,
|
|
216
|
+
ast.isDynamicViewStep,
|
|
215
217
|
ast.isViewProperty,
|
|
216
218
|
ast.isStyleProperty,
|
|
217
219
|
ast.isTags,
|
|
218
220
|
ast.isViewRule,
|
|
219
221
|
ast.isDynamicViewRule,
|
|
220
|
-
ast.isDynamicViewStep,
|
|
221
222
|
ast.isElementViewBody,
|
|
222
223
|
ast.isDynamicViewBody,
|
|
223
224
|
ast.isLikeC4View,
|
|
@@ -337,7 +338,10 @@ export function toElementStyle(props?: Array<ast.StyleProperty>) {
|
|
|
337
338
|
break
|
|
338
339
|
}
|
|
339
340
|
case ast.isIconProperty(prop): {
|
|
340
|
-
|
|
341
|
+
const icon = prop.libicon?.ref?.name ?? prop.value
|
|
342
|
+
if (isTruthy(icon)) {
|
|
343
|
+
result.icon = icon as c4.IconUrl
|
|
344
|
+
}
|
|
341
345
|
break
|
|
342
346
|
}
|
|
343
347
|
case ast.isOpacityProperty(prop): {
|