@likec4/language-server 1.23.1 → 1.24.1
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/dist/LikeC4FileSystem.d.ts +1 -0
- package/dist/LikeC4FileSystem.js +7 -0
- package/dist/Rpc.js +13 -11
- package/dist/ast.d.ts +13 -29
- package/dist/ast.js +3 -70
- package/dist/bundled.mjs +2441 -2610
- package/dist/generated/ast.d.ts +36 -8
- package/dist/generated/ast.js +44 -2
- package/dist/generated/grammar.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/likec4lib.d.ts +2 -0
- package/dist/likec4lib.js +3 -0
- package/dist/lsp/CodeLensProvider.js +10 -6
- package/dist/lsp/CompletionProvider.js +20 -2
- package/dist/lsp/DocumentLinkProvider.d.ts +3 -3
- package/dist/lsp/DocumentLinkProvider.js +5 -5
- package/dist/lsp/DocumentSymbolProvider.d.ts +1 -1
- package/dist/lsp/DocumentSymbolProvider.js +5 -2
- package/dist/lsp/HoverProvider.js +20 -7
- package/dist/lsp/SemanticTokenProvider.js +18 -1
- package/dist/model/builder/MergedExtends.d.ts +12 -0
- package/dist/model/builder/MergedExtends.js +67 -0
- package/dist/model/builder/MergedSpecification.d.ts +29 -0
- package/dist/model/builder/MergedSpecification.js +203 -0
- package/dist/model/builder/buildModel.d.ts +3 -0
- package/dist/model/builder/buildModel.js +194 -0
- package/dist/model/deployments-index.d.ts +5 -56
- package/dist/model/deployments-index.js +61 -137
- package/dist/model/fqn-index.d.ts +50 -19
- package/dist/model/fqn-index.js +176 -69
- package/dist/model/index.d.ts +0 -1
- package/dist/model/index.js +0 -1
- package/dist/model/model-builder.d.ts +10 -9
- package/dist/model/model-builder.js +102 -547
- package/dist/model/model-locator.d.ts +2 -1
- package/dist/model/model-locator.js +7 -9
- package/dist/model/model-parser.d.ts +156 -150
- package/dist/model/model-parser.js +68 -38
- package/dist/model/parser/Base.d.ts +3 -3
- package/dist/model/parser/Base.js +15 -9
- package/dist/model/parser/DeploymentModelParser.d.ts +4 -3
- package/dist/model/parser/DeploymentModelParser.js +54 -3
- package/dist/model/parser/DeploymentViewParser.d.ts +3 -2
- package/dist/model/parser/FqnRefParser.d.ts +2 -2
- package/dist/model/parser/GlobalsParser.d.ts +3 -2
- package/dist/model/parser/ModelParser.d.ts +4 -4
- package/dist/model/parser/ModelParser.js +45 -4
- package/dist/model/parser/PredicatesParser.d.ts +2 -2
- package/dist/model/parser/SpecificationParser.d.ts +2 -2
- package/dist/model/parser/ViewsParser.d.ts +3 -2
- package/dist/module.d.ts +2 -3
- package/dist/module.js +2 -3
- package/dist/references/scope-computation.d.ts +1 -1
- package/dist/references/scope-computation.js +14 -11
- package/dist/references/scope-provider.d.ts +16 -4
- package/dist/references/scope-provider.js +64 -30
- package/dist/test/testServices.d.ts +2 -1
- package/dist/test/testServices.js +23 -20
- package/dist/utils/elementRef.d.ts +1 -1
- package/dist/utils/elementRef.js +3 -3
- package/dist/validation/deployment-checks.d.ts +1 -0
- package/dist/validation/deployment-checks.js +12 -0
- package/dist/validation/index.d.ts +1 -1
- package/dist/validation/index.js +8 -1
- package/dist/views/configurable-layouter.js +3 -3
- package/dist/views/likec4-views.d.ts +1 -0
- package/dist/views/likec4-views.js +11 -11
- package/package.json +12 -13
- package/dist/bundled.d.ts +0 -8
- package/dist/bundled.js +0 -25
- package/dist/model/fqn-computation.d.ts +0 -3
- package/dist/model/fqn-computation.js +0 -72
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
} from "langium";
|
|
13
13
|
import { ast } from "../ast.js";
|
|
14
14
|
import { logWarnError } from "../logger.js";
|
|
15
|
-
import { elementRef,
|
|
15
|
+
import { elementRef, readStrictFqn } from "../utils/elementRef.js";
|
|
16
16
|
const { getDocument } = AstUtils;
|
|
17
17
|
export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
18
18
|
deploymentsIndex;
|
|
@@ -22,18 +22,19 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
22
22
|
this.fqnIndex = services.likec4.FqnIndex;
|
|
23
23
|
this.deploymentsIndex = services.likec4.DeploymentsIndex;
|
|
24
24
|
}
|
|
25
|
-
directChildrenOf(parent) {
|
|
26
|
-
return this.fqnIndex.directChildrenOf(parent);
|
|
27
|
-
}
|
|
28
25
|
// we need lazy resolving here
|
|
29
26
|
uniqueDescedants(of) {
|
|
30
27
|
return new StreamImpl(
|
|
31
28
|
() => {
|
|
32
29
|
const element = of();
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
if (element && ast.isElement(element)) {
|
|
31
|
+
const fqn = this.fqnIndex.getFqn(element);
|
|
35
32
|
return this.fqnIndex.uniqueDescedants(fqn).iterator();
|
|
36
33
|
}
|
|
34
|
+
if (element && ast.isDeploymentNode(element)) {
|
|
35
|
+
const fqn = this.deploymentsIndex.getFqn(element);
|
|
36
|
+
return this.deploymentsIndex.uniqueDescedants(fqn).iterator();
|
|
37
|
+
}
|
|
37
38
|
return null;
|
|
38
39
|
},
|
|
39
40
|
(iterator) => {
|
|
@@ -44,24 +45,6 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
44
45
|
}
|
|
45
46
|
);
|
|
46
47
|
}
|
|
47
|
-
scopeElementRef(ref) {
|
|
48
|
-
return this.uniqueDescedants(() => ref.el.ref);
|
|
49
|
-
}
|
|
50
|
-
scopeExtendElement({ element }) {
|
|
51
|
-
return stream([element.el.$nodeDescription]).nonNullable().concat(this.uniqueDescedants(() => elementRef(element)));
|
|
52
|
-
}
|
|
53
|
-
scopeElementView({ viewOf, extends: ext }) {
|
|
54
|
-
if (viewOf) {
|
|
55
|
-
return stream([viewOf.el.$nodeDescription]).nonNullable().concat(this.uniqueDescedants(() => elementRef(viewOf)));
|
|
56
|
-
}
|
|
57
|
-
if (ext) {
|
|
58
|
-
return stream([ext]).flatMap((v) => {
|
|
59
|
-
const view = v.view.ref;
|
|
60
|
-
return view ? this.scopeElementView(view) : EMPTY_STREAM;
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
return EMPTY_STREAM;
|
|
64
|
-
}
|
|
65
48
|
getScope(context) {
|
|
66
49
|
try {
|
|
67
50
|
const referenceType = this.reflection.getReferenceType(context);
|
|
@@ -70,6 +53,9 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
70
53
|
if (ast.isFqnRef(container)) {
|
|
71
54
|
return this.getScopeForFqnRef(container, context);
|
|
72
55
|
}
|
|
56
|
+
if (ast.isStrictFqnRef(container)) {
|
|
57
|
+
return this.getScopeForStrictFqnRef(container, context);
|
|
58
|
+
}
|
|
73
59
|
if (referenceType !== ast.Element) {
|
|
74
60
|
return this.getGlobalScope(referenceType, context);
|
|
75
61
|
}
|
|
@@ -78,12 +64,12 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
78
64
|
if (!parent) {
|
|
79
65
|
return this.getGlobalScope(referenceType, context);
|
|
80
66
|
}
|
|
81
|
-
return new StreamScope(this.directChildrenOf(
|
|
67
|
+
return new StreamScope(this.fqnIndex.directChildrenOf(readStrictFqn(parent)));
|
|
82
68
|
}
|
|
83
69
|
if (ast.isElementRef(container) && context.property === "el") {
|
|
84
70
|
const parent = container.parent;
|
|
85
71
|
if (parent) {
|
|
86
|
-
return new StreamScope(this.
|
|
72
|
+
return new StreamScope(this.getScopeElementRef(parent));
|
|
87
73
|
}
|
|
88
74
|
if (context.reference.$refText === "this" || context.reference.$refText === "it") {
|
|
89
75
|
const closestElement = AstUtils.getContainerOfType(container, ast.isElement);
|
|
@@ -106,6 +92,39 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
106
92
|
return EMPTY_SCOPE;
|
|
107
93
|
}
|
|
108
94
|
}
|
|
95
|
+
getScopeElementRef(ref) {
|
|
96
|
+
return this.uniqueDescedants(() => ref.el.ref);
|
|
97
|
+
}
|
|
98
|
+
getScopeExtendElement({ element }) {
|
|
99
|
+
return stream([element.el.$nodeDescription]).nonNullable().concat(this.uniqueDescedants(() => elementRef(element)));
|
|
100
|
+
}
|
|
101
|
+
getScopeElementView({ viewOf, extends: ext }) {
|
|
102
|
+
if (viewOf) {
|
|
103
|
+
return stream([viewOf.el.$nodeDescription]).nonNullable().concat(this.uniqueDescedants(() => elementRef(viewOf)));
|
|
104
|
+
}
|
|
105
|
+
if (ext) {
|
|
106
|
+
return stream([ext]).flatMap((v) => {
|
|
107
|
+
const view = v.view.ref;
|
|
108
|
+
return view ? this.getScopeElementView(view) : EMPTY_STREAM;
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
return EMPTY_STREAM;
|
|
112
|
+
}
|
|
113
|
+
getScopeForStrictFqnRef(container, context) {
|
|
114
|
+
const parent = container.parent;
|
|
115
|
+
if (!parent) {
|
|
116
|
+
return this.getGlobalScope(ast.DeploymentNode, context);
|
|
117
|
+
}
|
|
118
|
+
return new StreamScope(
|
|
119
|
+
this.deploymentsIndex.directChildrenOf(readStrictFqn(parent)).filter((desc) => this.reflection.isSubtype(desc.type, ast.DeploymentNode))
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
getScopeExtendDeployment({ deploymentNode }) {
|
|
123
|
+
return stream([deploymentNode.value.$nodeDescription]).nonNullable().concat(this.uniqueDescedants(() => {
|
|
124
|
+
const target = deploymentNode.value.ref;
|
|
125
|
+
return target && ast.isDeploymentNode(target) ? target : void 0;
|
|
126
|
+
}));
|
|
127
|
+
}
|
|
109
128
|
getScopeForFqnRef(container, context) {
|
|
110
129
|
const parent = container.parent;
|
|
111
130
|
if (!parent) {
|
|
@@ -125,18 +144,30 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
125
144
|
return EMPTY_SCOPE;
|
|
126
145
|
}
|
|
127
146
|
if (ast.isDeploymentNode(parentRef)) {
|
|
128
|
-
return new StreamScope(this.
|
|
147
|
+
return new StreamScope(this.uniqueDescedants(() => parentRef));
|
|
129
148
|
}
|
|
130
149
|
if (ast.isDeployedInstance(parentRef)) {
|
|
131
|
-
return new StreamScope(this.
|
|
150
|
+
return new StreamScope(this.getScopeElementRef(parentRef.element));
|
|
132
151
|
}
|
|
133
152
|
if (ast.isElement(parentRef)) {
|
|
134
153
|
return new StreamScope(this.uniqueDescedants(() => parentRef));
|
|
135
154
|
}
|
|
136
155
|
return nonexhaustive(parentRef);
|
|
137
156
|
}
|
|
157
|
+
/**
|
|
158
|
+
* Computes the scope for a given reference context.
|
|
159
|
+
*
|
|
160
|
+
* @param context - The reference information containing the context for which the scope is being computed.
|
|
161
|
+
* @param referenceType - The type of reference being resolved. Defaults to the reference type derived from the context.
|
|
162
|
+
* @returns A scope containing the relevant AST node descriptions for the given reference context.
|
|
163
|
+
*
|
|
164
|
+
* This method first checks if there are precomputed scopes available in the document. If not, it falls back to the global scope.
|
|
165
|
+
* It then iterates through the container hierarchy, collecting relevant scopes based on the reference type and container type.
|
|
166
|
+
* Finally, it combines the collected scopes with the global scope to produce the final scope.
|
|
167
|
+
*/
|
|
138
168
|
computeScope(context, referenceType = this.reflection.getReferenceType(context)) {
|
|
139
169
|
const isElementReference = this.reflection.isSubtype(referenceType, ast.Element);
|
|
170
|
+
const isDeploymentReference = this.reflection.isSubtype(referenceType, ast.DeploymentElement);
|
|
140
171
|
const scopes = [];
|
|
141
172
|
const doc = getDocument(context.container);
|
|
142
173
|
const precomputed = doc.precomputedScopes;
|
|
@@ -150,11 +181,14 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
150
181
|
if (elements.length > 0) {
|
|
151
182
|
scopes.push(stream(elements));
|
|
152
183
|
}
|
|
184
|
+
if (isDeploymentReference && ast.isExtendDeploymentBody(container)) {
|
|
185
|
+
scopes.push(this.getScopeExtendDeployment(container.$container));
|
|
186
|
+
}
|
|
153
187
|
if (isElementReference && ast.isExtendElementBody(container)) {
|
|
154
|
-
scopes.push(this.
|
|
188
|
+
scopes.push(this.getScopeExtendElement(container.$container));
|
|
155
189
|
}
|
|
156
190
|
if (isElementReference && ast.isElementViewBody(container)) {
|
|
157
|
-
scopes.push(this.
|
|
191
|
+
scopes.push(this.getScopeElementView(container.$container));
|
|
158
192
|
}
|
|
159
193
|
container = container.$container;
|
|
160
194
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { LikeC4LangiumDocument } from '../ast';
|
|
2
2
|
export declare function createTestServices(workspace?: string): {
|
|
3
3
|
services: any;
|
|
4
|
+
addDocument: (input: string, uri?: string) => Promise<LikeC4LangiumDocument>;
|
|
4
5
|
parse: (input: string, uri?: string) => Promise<LikeC4LangiumDocument>;
|
|
5
6
|
validate: (input: string | LikeC4LangiumDocument, uri?: string) => Promise<{
|
|
6
7
|
document: LikeC4LangiumDocument;
|
|
@@ -13,7 +14,7 @@ export declare function createTestServices(workspace?: string): {
|
|
|
13
14
|
errors: any;
|
|
14
15
|
warnings: any;
|
|
15
16
|
}>;
|
|
16
|
-
buildModel: () => Promise<
|
|
17
|
+
buildModel: () => Promise<ComputedLikeC4Model>;
|
|
17
18
|
buildLikeC4Model: () => Promise<any>;
|
|
18
19
|
resetState: () => Promise<void>;
|
|
19
20
|
format: (input: string | LikeC4LangiumDocument, uri?: string) => Promise<any>;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { LikeC4Model } from "@likec4/core";
|
|
2
1
|
import { DocumentState, EmptyFileSystem, TextDocument } from "langium";
|
|
3
2
|
import * as assert from "node:assert";
|
|
4
3
|
import stripIndent from "strip-indent";
|
|
@@ -19,13 +18,10 @@ export function createTestServices(workspace = "file:///test/workspace") {
|
|
|
19
18
|
};
|
|
20
19
|
let isInitialized = false;
|
|
21
20
|
let documentIndex = 1;
|
|
22
|
-
const
|
|
21
|
+
const addDocument = async (input, uri) => {
|
|
23
22
|
if (!isInitialized) {
|
|
23
|
+
isInitialized = true;
|
|
24
24
|
await services.shared.workspace.WorkspaceLock.write(async (_cancelToken) => {
|
|
25
|
-
if (isInitialized) {
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
isInitialized = true;
|
|
29
25
|
services.shared.workspace.WorkspaceManager.initialize({
|
|
30
26
|
capabilities: {},
|
|
31
27
|
processId: null,
|
|
@@ -45,13 +41,17 @@ export function createTestServices(workspace = "file:///test/workspace") {
|
|
|
45
41
|
docUri
|
|
46
42
|
);
|
|
47
43
|
langiumDocuments.addDocument(document);
|
|
44
|
+
return document;
|
|
45
|
+
};
|
|
46
|
+
const parse = async (input, uri) => {
|
|
47
|
+
const document = await addDocument(input, uri);
|
|
48
48
|
await services.shared.workspace.WorkspaceLock.write(async (_cancelToken) => {
|
|
49
49
|
await documentBuilder.build([document], { validation: false });
|
|
50
50
|
});
|
|
51
51
|
return document;
|
|
52
52
|
};
|
|
53
53
|
const validate = async (input, uri) => {
|
|
54
|
-
const document = typeof input === "string" ? await
|
|
54
|
+
const document = typeof input === "string" ? await addDocument(input, uri) : input;
|
|
55
55
|
await services.shared.workspace.WorkspaceLock.write(async (_cancelToken) => {
|
|
56
56
|
await documentBuilder.build([document], { validation: true });
|
|
57
57
|
});
|
|
@@ -80,13 +80,11 @@ export function createTestServices(workspace = "file:///test/workspace") {
|
|
|
80
80
|
return TextDocument.applyEdits(document.textDocument, edits ?? []);
|
|
81
81
|
};
|
|
82
82
|
const validateAll = async () => {
|
|
83
|
-
await services.shared.workspace.WorkspaceLock.write(async (_cancelToken) => {
|
|
84
|
-
const docs2 = langiumDocuments.all.toArray();
|
|
85
|
-
await documentBuilder.build(docs2, { validation: true });
|
|
86
|
-
});
|
|
87
|
-
await documentBuilder.waitUntil(DocumentState.Validated);
|
|
88
83
|
const docs = langiumDocuments.all.toArray();
|
|
89
84
|
assert.ok(docs.length > 0, "no documents to validate");
|
|
85
|
+
await services.shared.workspace.WorkspaceLock.write(async (cancelToken) => {
|
|
86
|
+
await documentBuilder.build(docs, { validation: true }, cancelToken);
|
|
87
|
+
});
|
|
90
88
|
const diagnostics = docs.flatMap((doc) => doc.diagnostics ?? []);
|
|
91
89
|
const warnings = diagnostics.flatMap((d) => d.severity === DiagnosticSeverity.Warning ? d.message : []);
|
|
92
90
|
const errors = diagnostics.flatMap((d) => d.severity === DiagnosticSeverity.Error ? d.message : []);
|
|
@@ -97,16 +95,20 @@ export function createTestServices(workspace = "file:///test/workspace") {
|
|
|
97
95
|
};
|
|
98
96
|
};
|
|
99
97
|
const buildModel = async () => {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
98
|
+
if (langiumDocuments.all.some((doc) => doc.state < DocumentState.Validated)) {
|
|
99
|
+
await validateAll();
|
|
100
|
+
}
|
|
101
|
+
const likec4model = await modelBuilder.buildLikeC4Model();
|
|
102
|
+
if (!likec4model) throw new Error("No model found");
|
|
103
|
+
return likec4model.$model;
|
|
104
104
|
};
|
|
105
105
|
const buildLikeC4Model = async () => {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
106
|
+
if (langiumDocuments.all.some((doc) => doc.state < DocumentState.Validated)) {
|
|
107
|
+
await validateAll();
|
|
108
|
+
}
|
|
109
|
+
const likec4model = await modelBuilder.buildLikeC4Model();
|
|
110
|
+
if (!likec4model) throw new Error("No model found");
|
|
111
|
+
return likec4model;
|
|
110
112
|
};
|
|
111
113
|
const resetState = async () => {
|
|
112
114
|
await services.shared.workspace.WorkspaceLock.write(async (cancelToken) => {
|
|
@@ -116,6 +118,7 @@ export function createTestServices(workspace = "file:///test/workspace") {
|
|
|
116
118
|
};
|
|
117
119
|
return {
|
|
118
120
|
services,
|
|
121
|
+
addDocument,
|
|
119
122
|
parse,
|
|
120
123
|
validate,
|
|
121
124
|
validateAll,
|
|
@@ -8,4 +8,4 @@ export declare function elementRef(node: ast.ElementRef | ast.StrictFqnElementRe
|
|
|
8
8
|
* Returns FQN of StrictFqnElementRef
|
|
9
9
|
* a.b.c.d - for c node returns a.b.c
|
|
10
10
|
*/
|
|
11
|
-
export declare function
|
|
11
|
+
export declare function readStrictFqn(node: ast.StrictFqnElementRef | ast.StrictFqnRef): c4.Fqn;
|
package/dist/utils/elementRef.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export function elementRef(node) {
|
|
2
2
|
return node.el.ref;
|
|
3
3
|
}
|
|
4
|
-
export function
|
|
5
|
-
const name = [node.el.$refText];
|
|
4
|
+
export function readStrictFqn(node) {
|
|
5
|
+
const name = [node.$type === "StrictFqnRef" ? node.value.$refText : node.el.$refText];
|
|
6
6
|
let parent = node.parent;
|
|
7
7
|
while (parent) {
|
|
8
|
-
name.push(parent.el.$refText);
|
|
8
|
+
name.push(parent.$type === "StrictFqnRef" ? parent.value.$refText : parent.el.$refText);
|
|
9
9
|
parent = parent.parent;
|
|
10
10
|
}
|
|
11
11
|
if (name.length === 1) {
|
|
@@ -4,3 +4,4 @@ import type { LikeC4Services } from '../module';
|
|
|
4
4
|
export declare const deploymentNodeChecks: (services: LikeC4Services) => ValidationCheck<ast.DeploymentNode>;
|
|
5
5
|
export declare const deployedInstanceChecks: (services: LikeC4Services) => ValidationCheck<ast.DeployedInstance>;
|
|
6
6
|
export declare const deploymentRelationChecks: (services: LikeC4Services) => ValidationCheck<ast.DeploymentRelation>;
|
|
7
|
+
export declare const extendDeploymentChecks: (services: LikeC4Services) => ValidationCheck<ast.ExtendDeployment>;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { FqnRef, isSameHierarchy, nonNullable } from "@likec4/core";
|
|
2
2
|
import { AstUtils } from "langium";
|
|
3
|
+
import { ast } from "../ast.js";
|
|
3
4
|
import { RESERVED_WORDS, tryOrLog } from "./_shared.js";
|
|
4
5
|
const { getDocument } = AstUtils;
|
|
5
6
|
export const deploymentNodeChecks = (services) => {
|
|
@@ -112,3 +113,14 @@ export const deploymentRelationChecks = (services) => {
|
|
|
112
113
|
}
|
|
113
114
|
});
|
|
114
115
|
};
|
|
116
|
+
export const extendDeploymentChecks = (services) => {
|
|
117
|
+
return tryOrLog((el, accept) => {
|
|
118
|
+
const target = el.deploymentNode.value.ref;
|
|
119
|
+
if (!target || !ast.isDeploymentNode(target)) {
|
|
120
|
+
accept("error", "ExtendDeployment allows only DeploymentNode", {
|
|
121
|
+
node: el,
|
|
122
|
+
property: "deploymentNode"
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
});
|
|
126
|
+
};
|
|
@@ -3,7 +3,7 @@ import { type LikeC4LangiumDocument, ast } from '../ast';
|
|
|
3
3
|
import type { LikeC4Services } from '../module';
|
|
4
4
|
type Guard<N extends AstNode> = (n: AstNode) => n is N;
|
|
5
5
|
type Guarded<G> = G extends Guard<infer N> ? N : never;
|
|
6
|
-
declare const isValidatableAstNode: (n: AstNode) => n is ast.DeployedInstance | ast.DeploymentNode | ast.DeploymentViewRulePredicate | ast.DeploymentViewRuleStyle | ast.ViewRuleAutoLayout | ast.DynamicViewGlobalPredicateRef | ast.DynamicViewIncludePredicate | ast.ViewRuleGlobalStyle | ast.ViewRuleStyle | ast.ElementDescedantsExpression | ast.ElementKindExpression | ast.ElementRef | ast.ElementTagExpression | ast.ExpandElementExpression | ast.WildcardExpression | ast.ElementPredicateWhere | ast.ElementPredicateWith | ast.ElementPredicateWhereV2 | ast.FqnRefExpr | ast.ElementStringProperty | ast.ElementStyleProperty | ast.IconProperty | ast.LinkProperty | ast.MetadataBody | ast.DirectedRelationExpr | ast.InOutRelationExpr | ast.IncomingRelationExpr | ast.OutgoingRelationExpr | ast.RelationPredicateWhereV2 | ast.Element | ast.ExtendElement | ast.DeploymentView | ast.DynamicView | ast.ElementView | ast.DirectedRelationExpression | ast.InOutRelationExpression | ast.IncomingRelationExpression | ast.OutgoingRelationExpression | ast.RelationPredicateWhere | ast.RelationPredicateWith | ast.RelationStringProperty | ast.ArrowProperty | ast.ColorProperty | ast.LineProperty | ast.PaddingSizeProperty | ast.ShapeSizeProperty | ast.TextSizeProperty | ast.MetadataAttribute | ast.NotationProperty | ast.NotesProperty | ast.SpecificationElementStringProperty | ast.SpecificationRelationshipStringProperty | ast.ViewStringProperty | ast.BorderProperty | ast.MultipleProperty | ast.OpacityProperty | ast.ShapeProperty | ast.ViewRuleGlobalPredicateRef | ast.ViewRuleGroup | ast.ExcludePredicate | ast.IncludePredicate | ast.SpecificationRelationshipKind | ast.GlobalStyle | ast.SpecificationColor | ast.NavigateToProperty | ast.DynamicViewStep | ast.Tags | ast.DeploymentRelation | ast.SpecificationDeploymentNodeKind | ast.DynamicViewParallelSteps | ast.GlobalDynamicPredicateGroup | ast.DynamicViewPredicateIterator | ast.Relation | ast.SpecificationElementKind | ast.GlobalPredicateGroup | ast.Globals | ast.GlobalStyleGroup | ast.SpecificationRule | ast.SpecificationTag;
|
|
6
|
+
declare const isValidatableAstNode: (n: AstNode) => n is ast.DeployedInstance | ast.DeploymentNode | ast.DeploymentViewRulePredicate | ast.DeploymentViewRuleStyle | ast.ViewRuleAutoLayout | ast.DynamicViewGlobalPredicateRef | ast.DynamicViewIncludePredicate | ast.ViewRuleGlobalStyle | ast.ViewRuleStyle | ast.ElementDescedantsExpression | ast.ElementKindExpression | ast.ElementRef | ast.ElementTagExpression | ast.ExpandElementExpression | ast.WildcardExpression | ast.ElementPredicateWhere | ast.ElementPredicateWith | ast.ElementPredicateWhereV2 | ast.FqnRefExpr | ast.ElementStringProperty | ast.ElementStyleProperty | ast.IconProperty | ast.LinkProperty | ast.MetadataBody | ast.DirectedRelationExpr | ast.InOutRelationExpr | ast.IncomingRelationExpr | ast.OutgoingRelationExpr | ast.RelationPredicateWhereV2 | ast.Element | ast.ExtendDeployment | ast.ExtendElement | ast.DeploymentView | ast.DynamicView | ast.ElementView | ast.DirectedRelationExpression | ast.InOutRelationExpression | ast.IncomingRelationExpression | ast.OutgoingRelationExpression | ast.RelationPredicateWhere | ast.RelationPredicateWith | ast.RelationStringProperty | ast.ArrowProperty | ast.ColorProperty | ast.LineProperty | ast.PaddingSizeProperty | ast.ShapeSizeProperty | ast.TextSizeProperty | ast.MetadataAttribute | ast.NotationProperty | ast.NotesProperty | ast.SpecificationElementStringProperty | ast.SpecificationRelationshipStringProperty | ast.ViewStringProperty | ast.BorderProperty | ast.MultipleProperty | ast.OpacityProperty | ast.ShapeProperty | ast.ViewRuleGlobalPredicateRef | ast.ViewRuleGroup | ast.ExcludePredicate | ast.IncludePredicate | ast.SpecificationRelationshipKind | ast.GlobalStyle | ast.SpecificationColor | ast.NavigateToProperty | ast.DynamicViewStep | ast.Tags | ast.DeploymentRelation | ast.SpecificationDeploymentNodeKind | ast.DynamicViewParallelSteps | ast.GlobalDynamicPredicateGroup | ast.DynamicViewPredicateIterator | ast.Relation | ast.SpecificationElementKind | ast.GlobalPredicateGroup | ast.Globals | ast.GlobalStyleGroup | ast.SpecificationRule | ast.SpecificationTag;
|
|
7
7
|
type ValidatableAstNode = Guarded<typeof isValidatableAstNode>;
|
|
8
8
|
export declare function checksFromDiagnostics(doc: LikeC4LangiumDocument): {
|
|
9
9
|
isValid: (n: ValidatableAstNode) => boolean;
|
package/dist/validation/index.js
CHANGED
|
@@ -3,7 +3,12 @@ import { isNullish } from "remeda";
|
|
|
3
3
|
import { DiagnosticSeverity } from "vscode-languageserver-types";
|
|
4
4
|
import { ast } from "../ast.js";
|
|
5
5
|
import { logger } from "../logger.js";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
deployedInstanceChecks,
|
|
8
|
+
deploymentNodeChecks,
|
|
9
|
+
deploymentRelationChecks,
|
|
10
|
+
extendDeploymentChecks
|
|
11
|
+
} from "./deployment-checks.js";
|
|
7
12
|
import { dynamicViewRulePredicate } from "./dynamic-view-rule.js";
|
|
8
13
|
import { dynamicViewStep } from "./dynamic-view-step.js";
|
|
9
14
|
import { elementChecks } from "./element.js";
|
|
@@ -70,6 +75,7 @@ const isValidatableAstNode = validatableAstNodeGuards([
|
|
|
70
75
|
ast.isNavigateToProperty,
|
|
71
76
|
ast.isElement,
|
|
72
77
|
ast.isExtendElement,
|
|
78
|
+
ast.isExtendDeployment,
|
|
73
79
|
ast.isSpecificationElementKind,
|
|
74
80
|
ast.isSpecificationRelationshipKind,
|
|
75
81
|
ast.isSpecificationDeploymentNodeKind,
|
|
@@ -114,6 +120,7 @@ export function registerValidationChecks(services) {
|
|
|
114
120
|
DeploymentNodeKind: deploymentNodeKindChecks(services),
|
|
115
121
|
DeploymentNode: deploymentNodeChecks(services),
|
|
116
122
|
DeploymentRelation: deploymentRelationChecks(services),
|
|
123
|
+
ExtendDeployment: extendDeploymentChecks(services),
|
|
117
124
|
FqnRefExpr: fqnRefExprChecks(services),
|
|
118
125
|
RelationExpr: relationExprChecks(services),
|
|
119
126
|
NotesProperty: notesPropertyRuleChecks(services),
|
|
@@ -19,7 +19,7 @@ export const ConfigurableLayouter = {
|
|
|
19
19
|
const layouter = new GraphvizLayouter(wasmAdapter);
|
|
20
20
|
const langId = services.LanguageMetaData.languageId;
|
|
21
21
|
services.shared.workspace.ConfigurationProvider.onConfigurationSectionUpdate((update) => {
|
|
22
|
-
logger.debug("Configuration update", { update });
|
|
22
|
+
logger.debug("Configuration update: {update}", { update });
|
|
23
23
|
if (update.section === langId) {
|
|
24
24
|
try {
|
|
25
25
|
const { mode, path } = update.configuration.graphviz ?? {
|
|
@@ -41,13 +41,13 @@ export const ConfigurableLayouter = {
|
|
|
41
41
|
return;
|
|
42
42
|
}
|
|
43
43
|
layouter.changePort(new GraphvizBinaryAdapter(binaryPath));
|
|
44
|
-
logger.info
|
|
44
|
+
logger.info`use graphviz binary: ${binaryPath}`;
|
|
45
45
|
} catch (error) {
|
|
46
46
|
logger.error("Failed to update configuration", { error });
|
|
47
47
|
}
|
|
48
48
|
return;
|
|
49
49
|
}
|
|
50
|
-
logger.warn("Unexpected configuration update", { update });
|
|
50
|
+
logger.warn("Unexpected configuration update: {update}", { update });
|
|
51
51
|
});
|
|
52
52
|
return layouter;
|
|
53
53
|
}
|
|
@@ -15,6 +15,7 @@ export declare class LikeC4Views {
|
|
|
15
15
|
private services;
|
|
16
16
|
private cache;
|
|
17
17
|
private viewsWithReportedErrors;
|
|
18
|
+
private ModelBuilder;
|
|
18
19
|
constructor(services: LikeC4Services);
|
|
19
20
|
get layouter(): GraphvizLayouter;
|
|
20
21
|
computedViews(cancelToken?: Cancellation.CancellationToken): Promise<ComputedView[]>;
|
|
@@ -3,15 +3,17 @@ import { logError, logWarnError } from "../logger.js";
|
|
|
3
3
|
export class LikeC4Views {
|
|
4
4
|
constructor(services) {
|
|
5
5
|
this.services = services;
|
|
6
|
+
this.ModelBuilder = services.likec4.ModelBuilder;
|
|
6
7
|
}
|
|
7
8
|
cache = /* @__PURE__ */ new WeakMap();
|
|
8
9
|
viewsWithReportedErrors = /* @__PURE__ */ new Set();
|
|
10
|
+
ModelBuilder;
|
|
9
11
|
get layouter() {
|
|
10
12
|
return this.services.likec4.Layouter;
|
|
11
13
|
}
|
|
12
14
|
async computedViews(cancelToken) {
|
|
13
|
-
const
|
|
14
|
-
return
|
|
15
|
+
const likeC4Model = await this.ModelBuilder.buildLikeC4Model(cancelToken);
|
|
16
|
+
return values(likeC4Model.$model.views);
|
|
15
17
|
}
|
|
16
18
|
async layoutAllViews(cancelToken) {
|
|
17
19
|
const views = await this.computedViews(cancelToken);
|
|
@@ -24,6 +26,7 @@ export class LikeC4Views {
|
|
|
24
26
|
this.viewsWithReportedErrors.delete(view.id);
|
|
25
27
|
tasks.push(
|
|
26
28
|
this.layouter.layout(view).then((result) => {
|
|
29
|
+
this.viewsWithReportedErrors.delete(view.id);
|
|
27
30
|
this.cache.set(view, result);
|
|
28
31
|
return result;
|
|
29
32
|
}).catch((e) => {
|
|
@@ -41,17 +44,14 @@ export class LikeC4Views {
|
|
|
41
44
|
return results;
|
|
42
45
|
}
|
|
43
46
|
async layoutView(viewId, cancelToken) {
|
|
44
|
-
const model = await this.
|
|
45
|
-
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
const view = model.views[viewId];
|
|
47
|
+
const model = await this.ModelBuilder.buildLikeC4Model(cancelToken);
|
|
48
|
+
const view = model.findView(viewId)?.$view;
|
|
49
49
|
if (!view) {
|
|
50
50
|
return null;
|
|
51
51
|
}
|
|
52
52
|
let cached = this.cache.get(view);
|
|
53
53
|
if (cached) {
|
|
54
|
-
return cached;
|
|
54
|
+
return await Promise.resolve(cached);
|
|
55
55
|
}
|
|
56
56
|
try {
|
|
57
57
|
const result = await this.layouter.layout(view);
|
|
@@ -63,8 +63,8 @@ export class LikeC4Views {
|
|
|
63
63
|
const errMessage = e instanceof Error ? e.message : "" + e;
|
|
64
64
|
this.services.shared.lsp.Connection?.window.showErrorMessage(`LikeC4: ${errMessage}`);
|
|
65
65
|
this.viewsWithReportedErrors.add(viewId);
|
|
66
|
+
logError(e);
|
|
66
67
|
}
|
|
67
|
-
logError(e);
|
|
68
68
|
return Promise.reject(e);
|
|
69
69
|
}
|
|
70
70
|
}
|
|
@@ -74,7 +74,7 @@ export class LikeC4Views {
|
|
|
74
74
|
}
|
|
75
75
|
async viewsAsGraphvizOut() {
|
|
76
76
|
const KEY = "All-LayoutedViews-DotWithSvg";
|
|
77
|
-
const cache = this.services.
|
|
77
|
+
const cache = this.services.ValidatedWorkspaceCache;
|
|
78
78
|
if (cache.has(KEY)) {
|
|
79
79
|
return await Promise.resolve(cache.get(KEY));
|
|
80
80
|
}
|
|
@@ -101,7 +101,7 @@ export class LikeC4Views {
|
|
|
101
101
|
}
|
|
102
102
|
async overviewGraph() {
|
|
103
103
|
const KEY = "OverviewGraph";
|
|
104
|
-
const cache = this.services.
|
|
104
|
+
const cache = this.services.ValidatedWorkspaceCache;
|
|
105
105
|
if (cache.has(KEY)) {
|
|
106
106
|
return await Promise.resolve(cache.get(KEY));
|
|
107
107
|
}
|
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.24.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bugs": "https://github.com/likec4/likec4/issues",
|
|
7
7
|
"homepage": "https://likec4.dev",
|
|
@@ -84,11 +84,11 @@
|
|
|
84
84
|
"@hpcc-js/wasm-graphviz": "1.7.0"
|
|
85
85
|
},
|
|
86
86
|
"devDependencies": {
|
|
87
|
-
"@msgpack/msgpack": "^3.
|
|
87
|
+
"@msgpack/msgpack": "^3.1.0",
|
|
88
88
|
"@smithy/util-base64": "^4.0.0",
|
|
89
89
|
"@types/node": "^20.17.17",
|
|
90
90
|
"@types/which": "^3.0.4",
|
|
91
|
-
"@vitest/coverage-v8": "^3.0.
|
|
91
|
+
"@vitest/coverage-v8": "^3.0.6",
|
|
92
92
|
"esm-env": "^1.2.2",
|
|
93
93
|
"fast-equals": "^5.2.2",
|
|
94
94
|
"fdir": "^6.4.3",
|
|
@@ -96,28 +96,27 @@
|
|
|
96
96
|
"json5": "^2.2.3",
|
|
97
97
|
"langium": "3.3.1",
|
|
98
98
|
"langium-cli": "3.3.0",
|
|
99
|
-
"mnemonist": "^0.40.2",
|
|
100
99
|
"natural-compare-lite": "^1.4.0",
|
|
101
100
|
"p-debounce": "^4.0.0",
|
|
102
|
-
"remeda": "^2.20.
|
|
101
|
+
"remeda": "^2.20.2",
|
|
103
102
|
"strip-indent": "^4.0.0",
|
|
104
|
-
"tsx": "~4.19.
|
|
103
|
+
"tsx": "~4.19.3",
|
|
105
104
|
"turbo": "^2.4.2",
|
|
106
105
|
"type-fest": "4.34.1",
|
|
107
106
|
"typescript": "5.7.3",
|
|
108
107
|
"ufo": "^1.5.4",
|
|
109
108
|
"unbuild": "^3.3.1",
|
|
110
|
-
"vitest": "^3.0.
|
|
109
|
+
"vitest": "^3.0.6",
|
|
111
110
|
"vscode-jsonrpc": "8.2.0",
|
|
112
111
|
"vscode-languageserver": "9.0.1",
|
|
113
112
|
"vscode-languageserver-types": "3.17.5",
|
|
114
113
|
"vscode-uri": "3.1.0",
|
|
115
114
|
"which": "^5.0.0",
|
|
116
|
-
"@likec4/
|
|
117
|
-
"@likec4/
|
|
118
|
-
"@likec4/
|
|
119
|
-
"@likec4/log": "1.
|
|
120
|
-
"@likec4/
|
|
115
|
+
"@likec4/core": "1.24.1",
|
|
116
|
+
"@likec4/icons": "1.24.1",
|
|
117
|
+
"@likec4/layouts": "1.24.1",
|
|
118
|
+
"@likec4/log": "1.24.1",
|
|
119
|
+
"@likec4/tsconfig": "1.24.1"
|
|
121
120
|
},
|
|
122
121
|
"scripts": {
|
|
123
122
|
"typecheck": "tsc --noEmit",
|
|
@@ -126,7 +125,7 @@
|
|
|
126
125
|
"watch:langium": "langium generate --watch",
|
|
127
126
|
"watch:ts": "tsc --watch",
|
|
128
127
|
"generate": "langium generate && tsx scripts/generate-icons.ts",
|
|
129
|
-
"dev": "run-p
|
|
128
|
+
"dev": "run-p \"watch:*\"",
|
|
130
129
|
"lint": "run -T eslint src/ --fix",
|
|
131
130
|
"clean": "rm -r -f dist contrib",
|
|
132
131
|
"test": "vitest run --no-isolate",
|
package/dist/bundled.d.ts
DELETED
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import { type LikeC4Services, type LikeC4SharedServices } from './module';
|
|
2
|
-
/**
|
|
3
|
-
* This is used as `bin` entry point to start the language server.
|
|
4
|
-
*/
|
|
5
|
-
export declare function startLanguageServer(): Promise<{
|
|
6
|
-
shared: LikeC4SharedServices;
|
|
7
|
-
likec4: LikeC4Services;
|
|
8
|
-
}>;
|
package/dist/bundled.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { configureLogger, getConsoleSink } from "@likec4/log";
|
|
2
|
-
import { startLanguageServer as startLanguim } from "langium/lsp";
|
|
3
|
-
import { createConnection, ProposedFeatures } from "vscode-languageserver/node";
|
|
4
|
-
import { LikeC4FileSystem } from "./LikeC4FileSystem.js";
|
|
5
|
-
import { logger } from "./logger.js";
|
|
6
|
-
import { createCustomLanguageServices } from "./module.js";
|
|
7
|
-
import { ConfigurableLayouter } from "./views/configurable-layouter.js";
|
|
8
|
-
export async function startLanguageServer() {
|
|
9
|
-
const connection = createConnection(ProposedFeatures.all);
|
|
10
|
-
await configureLogger({
|
|
11
|
-
sinks: {
|
|
12
|
-
console: getConsoleSink()
|
|
13
|
-
},
|
|
14
|
-
loggers: [
|
|
15
|
-
{
|
|
16
|
-
category: ["likec4"],
|
|
17
|
-
sinks: ["console"]
|
|
18
|
-
}
|
|
19
|
-
]
|
|
20
|
-
});
|
|
21
|
-
logger.info("Starting LikeC4 language server");
|
|
22
|
-
const services = createCustomLanguageServices({ connection, ...LikeC4FileSystem }, ConfigurableLayouter);
|
|
23
|
-
startLanguim(services.shared);
|
|
24
|
-
return services;
|
|
25
|
-
}
|