@likec4/language-server 1.27.2 → 1.28.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/dist/LikeC4LanguageServices.js +6 -7
- package/dist/ast.d.ts +16 -9
- package/dist/ast.js +58 -79
- package/dist/bundled.mjs +2130 -2127
- package/dist/config/schema.d.ts +3 -3
- package/dist/config/schema.js +12 -5
- package/dist/documentation/documentation-provider.js +3 -1
- package/dist/formatting/LikeC4Formatter.d.ts +0 -2
- package/dist/formatting/LikeC4Formatter.js +24 -53
- package/dist/generated/ast.d.ts +128 -233
- package/dist/generated/ast.js +134 -306
- package/dist/generated/grammar.js +1 -1
- package/dist/lsp/CompletionProvider.d.ts +3 -0
- package/dist/lsp/CompletionProvider.js +128 -113
- package/dist/lsp/DocumentLinkProvider.js +6 -3
- package/dist/lsp/HoverProvider.js +3 -1
- package/dist/lsp/SemanticTokenProvider.js +33 -43
- package/dist/model/builder/MergedSpecification.d.ts +5 -3
- package/dist/model/builder/MergedSpecification.js +21 -7
- package/dist/model/builder/buildModel.d.ts +6 -1
- package/dist/model/builder/buildModel.js +20 -15
- package/dist/model/deployments-index.js +4 -2
- package/dist/model/fqn-index.d.ts +4 -2
- package/dist/model/fqn-index.js +28 -5
- package/dist/model/model-builder.d.ts +2 -2
- package/dist/model/model-builder.js +54 -16
- package/dist/model/model-locator.js +7 -4
- package/dist/model/model-parser.d.ts +215 -52
- package/dist/model/model-parser.js +6 -2
- package/dist/model/parser/Base.d.ts +11 -2
- package/dist/model/parser/Base.js +138 -3
- package/dist/model/parser/DeploymentModelParser.d.ts +19 -2
- package/dist/model/parser/DeploymentModelParser.js +19 -29
- package/dist/model/parser/DeploymentViewParser.d.ts +18 -2
- package/dist/model/parser/DeploymentViewParser.js +6 -24
- package/dist/model/parser/FqnRefParser.d.ts +18 -3
- package/dist/model/parser/FqnRefParser.js +264 -40
- package/dist/model/parser/GlobalsParser.d.ts +35 -18
- package/dist/model/parser/ImportsParser.d.ts +32 -0
- package/dist/model/parser/ImportsParser.js +26 -0
- package/dist/model/parser/ModelParser.d.ts +26 -2
- package/dist/model/parser/ModelParser.js +21 -41
- package/dist/model/parser/PredicatesParser.d.ts +35 -12
- package/dist/model/parser/PredicatesParser.js +20 -271
- package/dist/model/parser/SpecificationParser.d.ts +8 -0
- package/dist/model/parser/SpecificationParser.js +5 -9
- package/dist/model/parser/ViewsParser.d.ts +36 -19
- package/dist/model/parser/ViewsParser.js +15 -11
- package/dist/model-change/changeElementStyle.d.ts +2 -2
- package/dist/model-change/changeElementStyle.js +2 -1
- package/dist/references/name-provider.js +8 -2
- package/dist/references/scope-computation.d.ts +1 -1
- package/dist/references/scope-computation.js +33 -3
- package/dist/references/scope-provider.d.ts +7 -8
- package/dist/references/scope-provider.js +59 -41
- package/dist/shared/NodeKindProvider.js +4 -2
- package/dist/test/testServices.d.ts +2 -0
- package/dist/test/testServices.js +4 -1
- package/dist/utils/elementRef.d.ts +1 -1
- package/dist/utils/elementRef.js +6 -1
- package/dist/utils/fqnRef.d.ts +3 -0
- package/dist/utils/fqnRef.js +15 -4
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +9 -0
- package/dist/utils/projectId.d.ts +2 -1
- package/dist/utils/projectId.js +11 -1
- package/dist/validation/_shared.js +2 -2
- package/dist/validation/deployment-checks.js +24 -10
- package/dist/validation/element-ref.d.ts +4 -0
- package/dist/validation/element-ref.js +12 -0
- package/dist/validation/element.d.ts +1 -1
- package/dist/validation/element.js +1 -1
- package/dist/validation/imports.d.ts +5 -0
- package/dist/validation/imports.js +30 -0
- package/dist/validation/index.d.ts +1 -1
- package/dist/validation/index.js +47 -45
- package/dist/validation/relation.d.ts +2 -2
- package/dist/validation/relation.js +24 -27
- package/dist/validation/specification.d.ts +9 -9
- package/dist/validation/specification.js +9 -9
- package/dist/validation/view-predicates/{element-with.d.ts → fqn-expr-with.d.ts} +1 -1
- package/dist/validation/view-predicates/fqn-expr-with.js +42 -0
- package/dist/validation/view-predicates/fqn-ref-expr.d.ts +4 -0
- package/dist/validation/view-predicates/fqn-ref-expr.js +53 -0
- package/dist/validation/view-predicates/incoming.d.ts +1 -1
- package/dist/validation/view-predicates/incoming.js +2 -2
- package/dist/validation/view-predicates/index.d.ts +6 -6
- package/dist/validation/view-predicates/index.js +6 -6
- package/dist/validation/view-predicates/outgoing.d.ts +1 -1
- package/dist/validation/view-predicates/outgoing.js +8 -4
- package/dist/validation/view-predicates/{expanded-element.d.ts → relation-expr.d.ts} +1 -1
- package/dist/validation/view-predicates/relation-expr.js +39 -0
- package/dist/validation/view-predicates/relation-with.d.ts +1 -1
- package/dist/validation/view-predicates/relation-with.js +8 -5
- package/dist/workspace/AstNodeDescriptionProvider.d.ts +1 -1
- package/dist/workspace/AstNodeDescriptionProvider.js +2 -3
- package/dist/workspace/IndexManager.d.ts +1 -1
- package/dist/workspace/IndexManager.js +5 -4
- package/dist/workspace/LangiumDocuments.d.ts +1 -1
- package/dist/workspace/LangiumDocuments.js +3 -5
- package/dist/workspace/ProjectsManager.d.ts +25 -7
- package/dist/workspace/ProjectsManager.js +76 -32
- package/dist/workspace/WorkspaceManager.d.ts +4 -5
- package/dist/workspace/WorkspaceManager.js +53 -20
- package/package.json +12 -10
- package/dist/validation/dynamic-view-rule.d.ts +0 -4
- package/dist/validation/dynamic-view-rule.js +0 -17
- package/dist/validation/view-predicates/element-with.js +0 -31
- package/dist/validation/view-predicates/expanded-element.js +0 -12
- package/dist/validation/view-predicates/expression-v2.d.ts +0 -5
- package/dist/validation/view-predicates/expression-v2.js +0 -83
|
@@ -16,8 +16,11 @@ export class LikeC4NameProvider extends DefaultNameProvider {
|
|
|
16
16
|
if (isNamed(node)) {
|
|
17
17
|
return node.name;
|
|
18
18
|
}
|
|
19
|
+
if (ast.isImported(node)) {
|
|
20
|
+
return node.imported.$refText;
|
|
21
|
+
}
|
|
19
22
|
if (ast.isDeployedInstance(node)) {
|
|
20
|
-
return node.
|
|
23
|
+
return node.target.modelElement.value.$refText;
|
|
21
24
|
}
|
|
22
25
|
return void 0;
|
|
23
26
|
}
|
|
@@ -25,8 +28,11 @@ export class LikeC4NameProvider extends DefaultNameProvider {
|
|
|
25
28
|
if (isNamed(node)) {
|
|
26
29
|
return super.getNameNode(node);
|
|
27
30
|
}
|
|
31
|
+
if (ast.isImported(node)) {
|
|
32
|
+
return node.imported.$refNode;
|
|
33
|
+
}
|
|
28
34
|
if (ast.isDeployedInstance(node)) {
|
|
29
|
-
return node.
|
|
35
|
+
return node.target.modelElement.value.$refNode;
|
|
30
36
|
}
|
|
31
37
|
return void 0;
|
|
32
38
|
}
|
|
@@ -3,7 +3,7 @@ import type { CancellationToken } from 'vscode-languageserver';
|
|
|
3
3
|
import { type LikeC4LangiumDocument, ast } from '../ast';
|
|
4
4
|
import type { LikeC4Services } from '../module';
|
|
5
5
|
type ElementsContainer = ast.Model | ast.ElementBody | ast.ExtendElementBody;
|
|
6
|
-
type DeploymentsContainer = ast.ModelDeployments | ast.DeploymentNodeBody | ast.ExtendDeploymentBody;
|
|
6
|
+
type DeploymentsContainer = ast.ModelDeployments | ast.DeploymentNodeBody | ast.ExtendDeploymentBody | ast.DeployedInstanceBody;
|
|
7
7
|
export declare class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
8
8
|
constructor(services: LikeC4Services);
|
|
9
9
|
computeExports(document: LikeC4LangiumDocument, _cancelToken?: CancellationToken): Promise<AstNodeDescription[]>;
|
|
@@ -21,7 +21,15 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
21
21
|
async computeExports(document, _cancelToken) {
|
|
22
22
|
const docExports = [];
|
|
23
23
|
try {
|
|
24
|
-
const {
|
|
24
|
+
const {
|
|
25
|
+
specifications,
|
|
26
|
+
models,
|
|
27
|
+
views,
|
|
28
|
+
globals,
|
|
29
|
+
likec4lib,
|
|
30
|
+
deployments,
|
|
31
|
+
imports
|
|
32
|
+
} = document.parseResult.value;
|
|
25
33
|
this.exportLibrary(likec4lib, docExports, document);
|
|
26
34
|
this.exportSpecification(specifications, docExports, document);
|
|
27
35
|
this.exportModel(models, docExports, document);
|
|
@@ -193,6 +201,19 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
193
201
|
logWarnError(e);
|
|
194
202
|
}
|
|
195
203
|
}
|
|
204
|
+
for (const imports of root.imports.flatMap((i) => i.imports)) {
|
|
205
|
+
try {
|
|
206
|
+
let imported = imports;
|
|
207
|
+
while (imported) {
|
|
208
|
+
descendants.push(
|
|
209
|
+
this.descriptions.createDescription(imported, imported.imported.$refText, document)
|
|
210
|
+
);
|
|
211
|
+
imported = imported.prev;
|
|
212
|
+
}
|
|
213
|
+
} catch (e) {
|
|
214
|
+
logWarnError(e);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
196
217
|
uniqueDescriptions(descendants).forEach((desc) => {
|
|
197
218
|
scopes.add(root, desc);
|
|
198
219
|
});
|
|
@@ -212,6 +233,10 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
212
233
|
localScope.add(el.name, this.descriptions.createDescription(el, el.name, document));
|
|
213
234
|
}
|
|
214
235
|
subcontainer = el.body;
|
|
236
|
+
if (subcontainer) {
|
|
237
|
+
scopes.add(subcontainer, this.descriptions.createDescription(el, "this", document));
|
|
238
|
+
scopes.add(subcontainer, this.descriptions.createDescription(el, "it", document));
|
|
239
|
+
}
|
|
215
240
|
} else if (ast.isExtendElement(el)) {
|
|
216
241
|
subcontainer = el.body;
|
|
217
242
|
}
|
|
@@ -248,17 +273,22 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
248
273
|
if (ast.isDeploymentRelation(el)) {
|
|
249
274
|
continue;
|
|
250
275
|
}
|
|
276
|
+
let subcontainer = el.body;
|
|
251
277
|
if (!ast.isExtendDeployment(el)) {
|
|
252
278
|
let name = this.nameProvider.getName(el);
|
|
253
279
|
if (isTruthy(name)) {
|
|
254
280
|
const desc = this.descriptions.createDescription(el, name, document);
|
|
255
281
|
localScope.add(name, desc);
|
|
256
282
|
}
|
|
283
|
+
if (subcontainer) {
|
|
284
|
+
scopes.add(subcontainer, this.descriptions.createDescription(el, "this", document));
|
|
285
|
+
scopes.add(subcontainer, this.descriptions.createDescription(el, "it", document));
|
|
286
|
+
}
|
|
257
287
|
}
|
|
258
|
-
if (
|
|
288
|
+
if (subcontainer) {
|
|
259
289
|
try {
|
|
260
290
|
descedants.push(
|
|
261
|
-
...this.processDeployments(
|
|
291
|
+
...this.processDeployments(subcontainer, scopes, document)
|
|
262
292
|
);
|
|
263
293
|
} catch (e) {
|
|
264
294
|
logWarnError(e);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ProjectId } from '@likec4/core';
|
|
2
2
|
import { type AstNodeDescription, type ReferenceInfo, type Scope, type Stream, DefaultScopeProvider } from 'langium';
|
|
3
|
-
import { ast } from '../ast';
|
|
3
|
+
import { type AstNodeDescriptionWithFqn, ast } from '../ast';
|
|
4
4
|
import type { DeploymentsIndex, FqnIndex } from '../model';
|
|
5
5
|
import type { LikeC4Services } from '../module';
|
|
6
6
|
import type { IndexManager } from '../workspace';
|
|
@@ -10,14 +10,13 @@ export declare class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
10
10
|
protected readonly indexManager: IndexManager;
|
|
11
11
|
constructor(services: LikeC4Services);
|
|
12
12
|
getScope(context: ReferenceInfo): Scope;
|
|
13
|
-
protected genUniqueDescedants(of: () => ast.Element | ast.DeploymentNode | undefined): Generator<Stream<
|
|
14
|
-
protected
|
|
15
|
-
protected
|
|
16
|
-
protected streamScopeElementView({ viewOf, extends: ext }: ast.ElementView): Stream<AstNodeDescription>;
|
|
13
|
+
protected genUniqueDescedants(of: () => ast.Element | ast.DeploymentNode | undefined): Generator<Stream<AstNodeDescriptionWithFqn>, void, any>;
|
|
14
|
+
protected genScopeExtendElement({ element }: ast.ExtendElement): Generator<AstNodeDescription>;
|
|
15
|
+
protected genScopeElementView({ viewOf, extends: ext }: ast.ElementView): Generator<AstNodeDescription>;
|
|
17
16
|
protected getScopeForStrictFqnRef(projectId: ProjectId, container: ast.StrictFqnRef, context: ReferenceInfo): any;
|
|
18
|
-
protected
|
|
17
|
+
protected genScopeExtendDeployment({ deploymentNode }: ast.ExtendDeployment): Generator<AstNodeDescription>;
|
|
19
18
|
protected streamForFqnRef(projectId: ProjectId, container: ast.FqnRef, context: ReferenceInfo): Stream<AstNodeDescription>;
|
|
20
|
-
protected
|
|
19
|
+
protected genScopeForParentlessFqnRef(projectId: ProjectId, container: ast.FqnRef, context: ReferenceInfo): Generator<AstNodeDescription>;
|
|
21
20
|
/**
|
|
22
21
|
* Computes the scope for a given reference context.
|
|
23
22
|
*
|
|
@@ -29,7 +28,7 @@ export declare class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
29
28
|
* It then iterates through the container hierarchy, collecting relevant scopes based on the reference type and container type.
|
|
30
29
|
* Finally, it combines the collected scopes with the global scope to produce the final scope.
|
|
31
30
|
*/
|
|
32
|
-
protected computeScope(projectId: ProjectId, context: ReferenceInfo, referenceType?: any): Generator<
|
|
31
|
+
protected computeScope(projectId: ProjectId, context: ReferenceInfo, referenceType?: any): Generator<AstNodeDescription>;
|
|
33
32
|
/**
|
|
34
33
|
* Create a global scope filtered for the given reference type.
|
|
35
34
|
*/
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
StreamImpl,
|
|
11
11
|
StreamScope
|
|
12
12
|
} from "langium";
|
|
13
|
-
import { ast } from "../ast.js";
|
|
13
|
+
import { ast, isFqnRefInsideGlobals, isFqnRefInsideModel } from "../ast.js";
|
|
14
14
|
import { logWarnError } from "../logger.js";
|
|
15
15
|
import { projectIdFrom } from "../utils/index.js";
|
|
16
16
|
import { elementRef, readStrictFqn } from "../utils/elementRef.js";
|
|
@@ -40,6 +40,10 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
40
40
|
if (referenceType !== ast.Element) {
|
|
41
41
|
return this.getProjectScope(projectId, referenceType, context);
|
|
42
42
|
}
|
|
43
|
+
if (ast.isImported(container)) {
|
|
44
|
+
const projectId2 = projectIdFrom(container);
|
|
45
|
+
return new StreamScope(this.fqnIndex.rootElements(projectId2));
|
|
46
|
+
}
|
|
43
47
|
if (ast.isStrictFqnElementRef(container) && context.property === "el") {
|
|
44
48
|
const parent = container.parent;
|
|
45
49
|
if (!parent) {
|
|
@@ -47,22 +51,6 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
47
51
|
}
|
|
48
52
|
return new StreamScope(this.fqnIndex.directChildrenOf(projectId, readStrictFqn(parent)));
|
|
49
53
|
}
|
|
50
|
-
if (ast.isElementRef(container) && context.property === "el") {
|
|
51
|
-
const parent = container.parent;
|
|
52
|
-
if (parent) {
|
|
53
|
-
return new StreamScope(this.streamScopeElementRef(parent));
|
|
54
|
-
}
|
|
55
|
-
if (context.reference.$refText === "this" || context.reference.$refText === "it") {
|
|
56
|
-
const closestElement = AstUtils.getContainerOfType(container, ast.isElement);
|
|
57
|
-
if (closestElement) {
|
|
58
|
-
return new MapScope([
|
|
59
|
-
this.descriptions.createDescription(closestElement, context.reference.$refText)
|
|
60
|
-
]);
|
|
61
|
-
} else {
|
|
62
|
-
return EMPTY_SCOPE;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
54
|
return new StreamScope(stream(this.computeScope(projectId, context)));
|
|
67
55
|
} catch (e) {
|
|
68
56
|
logWarnError(e);
|
|
@@ -90,23 +78,26 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
90
78
|
yield* this.deploymentsIndex.uniqueDescedants(projectId, fqn);
|
|
91
79
|
}
|
|
92
80
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
81
|
+
*genScopeExtendElement({ element }) {
|
|
82
|
+
if (element.el.$nodeDescription) {
|
|
83
|
+
yield element.el.$nodeDescription;
|
|
84
|
+
}
|
|
85
|
+
yield* this.genUniqueDescedants(() => elementRef(element));
|
|
98
86
|
}
|
|
99
|
-
|
|
87
|
+
*genScopeElementView({ viewOf, extends: ext }) {
|
|
100
88
|
if (viewOf) {
|
|
101
|
-
|
|
89
|
+
if (viewOf.modelElement.value.$nodeDescription) {
|
|
90
|
+
yield viewOf.modelElement.value.$nodeDescription;
|
|
91
|
+
}
|
|
92
|
+
yield* this.genUniqueDescedants(() => elementRef(viewOf));
|
|
93
|
+
return;
|
|
102
94
|
}
|
|
103
95
|
if (ext) {
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
96
|
+
const view = ext.view.ref;
|
|
97
|
+
if (view) {
|
|
98
|
+
yield* this.genScopeElementView(view);
|
|
99
|
+
}
|
|
108
100
|
}
|
|
109
|
-
return EMPTY_STREAM;
|
|
110
101
|
}
|
|
111
102
|
getScopeForStrictFqnRef(projectId, container, context) {
|
|
112
103
|
const parent = container.parent;
|
|
@@ -117,37 +108,64 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
117
108
|
this.deploymentsIndex.directChildrenOf(projectId, readStrictFqn(parent)).filter((desc) => this.reflection.isSubtype(desc.type, ast.DeploymentNode))
|
|
118
109
|
);
|
|
119
110
|
}
|
|
120
|
-
|
|
121
|
-
|
|
111
|
+
*genScopeExtendDeployment({ deploymentNode }) {
|
|
112
|
+
if (deploymentNode.value.$nodeDescription) {
|
|
113
|
+
yield deploymentNode.value.$nodeDescription;
|
|
114
|
+
}
|
|
115
|
+
yield* this.genUniqueDescedants(() => {
|
|
122
116
|
const target = deploymentNode.value.ref;
|
|
123
117
|
return target && ast.isDeploymentNode(target) ? target : void 0;
|
|
124
|
-
})
|
|
118
|
+
});
|
|
125
119
|
}
|
|
126
120
|
streamForFqnRef(projectId, container, context) {
|
|
127
121
|
const parent = container.parent;
|
|
128
122
|
if (!parent) {
|
|
129
|
-
return stream(this.
|
|
123
|
+
return stream(this.genScopeForParentlessFqnRef(projectId, container, context));
|
|
130
124
|
}
|
|
131
125
|
const parentRef = parent.value.ref;
|
|
132
126
|
if (!parentRef) {
|
|
133
127
|
return EMPTY_STREAM;
|
|
134
128
|
}
|
|
129
|
+
if (ast.isImported(parentRef)) {
|
|
130
|
+
return stream(this.genUniqueDescedants(() => {
|
|
131
|
+
return parentRef.imported.ref;
|
|
132
|
+
}));
|
|
133
|
+
}
|
|
135
134
|
if (ast.isDeploymentNode(parentRef)) {
|
|
136
135
|
return stream(this.genUniqueDescedants(() => parentRef));
|
|
137
136
|
}
|
|
138
137
|
if (ast.isDeployedInstance(parentRef)) {
|
|
139
|
-
return stream(this.
|
|
138
|
+
return stream(this.genUniqueDescedants(() => {
|
|
139
|
+
const target = parentRef.target.modelElement.value.ref;
|
|
140
|
+
if (ast.isImported(target)) {
|
|
141
|
+
return target.imported.ref;
|
|
142
|
+
}
|
|
143
|
+
return ast.isElement(target) ? target : void 0;
|
|
144
|
+
}));
|
|
140
145
|
}
|
|
141
146
|
if (ast.isElement(parentRef)) {
|
|
142
147
|
return stream(this.genUniqueDescedants(() => parentRef));
|
|
143
148
|
}
|
|
144
149
|
return nonexhaustive(parentRef);
|
|
145
150
|
}
|
|
146
|
-
*
|
|
147
|
-
|
|
148
|
-
yield* this.computeScope(projectId, context, ast.DeployedInstance);
|
|
149
|
-
if (AstUtils.hasContainerOfType(container, ast.isDeploymentView)) {
|
|
151
|
+
*genScopeForParentlessFqnRef(projectId, container, context) {
|
|
152
|
+
if (AstUtils.hasContainerOfType(container, ast.isElementRef) || isFqnRefInsideModel(container)) {
|
|
150
153
|
yield* this.computeScope(projectId, context, ast.Element);
|
|
154
|
+
} else if (isFqnRefInsideGlobals(container)) {
|
|
155
|
+
yield* this.computeScope(projectId, context, ast.Element);
|
|
156
|
+
yield* this.computeScope(projectId, context, ast.DeploymentNode);
|
|
157
|
+
yield* this.computeScope(projectId, context, ast.DeployedInstance);
|
|
158
|
+
} else {
|
|
159
|
+
yield* this.computeScope(projectId, context, ast.DeploymentNode);
|
|
160
|
+
yield* this.computeScope(projectId, context, ast.DeployedInstance);
|
|
161
|
+
if (AstUtils.hasContainerOfType(container, ast.isDeploymentViewBody)) {
|
|
162
|
+
yield* this.computeScope(projectId, context, ast.Element);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const doc = getDocument(container);
|
|
166
|
+
const precomputed = doc.precomputedScopes;
|
|
167
|
+
if (precomputed) {
|
|
168
|
+
yield* precomputed.values().filter((nd) => this.reflection.isSubtype(nd.type, ast.Imported));
|
|
151
169
|
}
|
|
152
170
|
}
|
|
153
171
|
/**
|
|
@@ -178,13 +196,13 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
178
196
|
yield* elements;
|
|
179
197
|
}
|
|
180
198
|
if (isDeploymentReference && ast.isExtendDeploymentBody(container)) {
|
|
181
|
-
yield* this.
|
|
199
|
+
yield* this.genScopeExtendDeployment(container.$container);
|
|
182
200
|
}
|
|
183
201
|
if (isElementReference && ast.isExtendElementBody(container)) {
|
|
184
|
-
yield* this.
|
|
202
|
+
yield* this.genScopeExtendElement(container.$container);
|
|
185
203
|
}
|
|
186
204
|
if (isElementReference && ast.isElementViewBody(container)) {
|
|
187
|
-
yield* this.
|
|
205
|
+
yield* this.genScopeElementView(container.$container);
|
|
188
206
|
}
|
|
189
207
|
container = container.$container;
|
|
190
208
|
}
|
|
@@ -17,7 +17,8 @@ export class NodeKindProvider {
|
|
|
17
17
|
ast.Element,
|
|
18
18
|
ast.ExtendElement,
|
|
19
19
|
ast.DeploymentNode,
|
|
20
|
-
ast.DeployedInstance
|
|
20
|
+
ast.DeployedInstance,
|
|
21
|
+
ast.Imported
|
|
21
22
|
):
|
|
22
23
|
return SymbolKind.Constructor;
|
|
23
24
|
case hasType(
|
|
@@ -67,7 +68,8 @@ export class NodeKindProvider {
|
|
|
67
68
|
ast.Element,
|
|
68
69
|
ast.DeploymentNode,
|
|
69
70
|
ast.DeployedInstance,
|
|
70
|
-
ast.ExtendElement
|
|
71
|
+
ast.ExtendElement,
|
|
72
|
+
ast.Imported
|
|
71
73
|
):
|
|
72
74
|
return CompletionItemKind.Constructor;
|
|
73
75
|
case hasType(
|
|
@@ -20,7 +20,9 @@ export declare function createTestServices(workspace?: string): {
|
|
|
20
20
|
format: (input: string | LikeC4LangiumDocument, uri?: string) => Promise<any>;
|
|
21
21
|
};
|
|
22
22
|
export declare function createMultiProjectTestServices<const Projects extends Record<string, Record<string, string>>>(data: Projects): Promise<{
|
|
23
|
+
services: any;
|
|
23
24
|
projects: { readonly [K in keyof Projects]: { readonly [L in keyof Projects[K]]: LikeC4LangiumDocument; }; };
|
|
25
|
+
projectsManager: any;
|
|
24
26
|
/**
|
|
25
27
|
* Add document outside of projects
|
|
26
28
|
*/
|
|
@@ -141,7 +141,8 @@ export async function createMultiProjectTestServices(data) {
|
|
|
141
141
|
const folderUri = UriUtils.joinPath(URI.parse(workspace), "src", name);
|
|
142
142
|
services.shared.workspace.ProjectsManager.registerProject({
|
|
143
143
|
config: {
|
|
144
|
-
name
|
|
144
|
+
name,
|
|
145
|
+
exclude: ["node_modules"]
|
|
145
146
|
},
|
|
146
147
|
folderUri
|
|
147
148
|
});
|
|
@@ -164,7 +165,9 @@ export async function createMultiProjectTestServices(data) {
|
|
|
164
165
|
return model.$model;
|
|
165
166
|
}
|
|
166
167
|
return {
|
|
168
|
+
services,
|
|
167
169
|
projects,
|
|
170
|
+
projectsManager: services.shared.workspace.ProjectsManager,
|
|
168
171
|
/**
|
|
169
172
|
* Add document outside of projects
|
|
170
173
|
*/
|
package/dist/utils/elementRef.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
import { ast } from "../ast.js";
|
|
1
2
|
export function elementRef(node) {
|
|
2
|
-
|
|
3
|
+
let el = ast.isStrictFqnElementRef(node) ? node.el.ref : node.modelElement.value.ref;
|
|
4
|
+
if (el?.$type === "Imported") {
|
|
5
|
+
el = el.imported.ref;
|
|
6
|
+
}
|
|
7
|
+
return el?.$type === "Element" ? el : void 0;
|
|
3
8
|
}
|
|
4
9
|
export function readStrictFqn(node) {
|
|
5
10
|
const name = [node.$type === "StrictFqnRef" ? node.value.$refText : node.el.$refText];
|
package/dist/utils/fqnRef.d.ts
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { ast } from '../ast';
|
|
2
|
+
export declare function referenceableParent(node: ast.FqnRef): ast.Referenceable | null;
|
|
2
3
|
export declare function instanceRef(deploymentRef: ast.FqnRef): ast.DeployedInstance | null;
|
|
3
4
|
export declare function deploymentNodeRef(deploymentRef: ast.FqnRef): ast.DeploymentNode | null;
|
|
5
|
+
export declare function importsRef(node: ast.FqnRef): ast.Imported | null;
|
|
6
|
+
export declare function isImportsRef(node: ast.FqnRef): boolean;
|
|
4
7
|
export declare function isReferenceToLogicalModel(node: ast.FqnRef): boolean;
|
|
5
8
|
/**
|
|
6
9
|
* Returns true if node references deployment model
|
package/dist/utils/fqnRef.js
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import { AstUtils } from "langium";
|
|
2
2
|
import { isNullish } from "remeda";
|
|
3
3
|
import { ast } from "../ast.js";
|
|
4
|
+
export function referenceableParent(node) {
|
|
5
|
+
while (node.parent) {
|
|
6
|
+
node = node.parent;
|
|
7
|
+
}
|
|
8
|
+
return node.value.ref ?? null;
|
|
9
|
+
}
|
|
4
10
|
export function instanceRef(deploymentRef) {
|
|
5
11
|
let referenceable;
|
|
6
12
|
while (referenceable = deploymentRef.value?.ref) {
|
|
@@ -25,11 +31,16 @@ export function deploymentNodeRef(deploymentRef) {
|
|
|
25
31
|
const artifact = instanceRef(deploymentRef);
|
|
26
32
|
return artifact ? AstUtils.getContainerOfType(artifact, ast.isDeploymentNode) ?? null : null;
|
|
27
33
|
}
|
|
34
|
+
export function importsRef(node) {
|
|
35
|
+
const referenceable = referenceableParent(node);
|
|
36
|
+
return referenceable?.$type === "Imported" ? referenceable : null;
|
|
37
|
+
}
|
|
38
|
+
export function isImportsRef(node) {
|
|
39
|
+
return !!importsRef(node);
|
|
40
|
+
}
|
|
28
41
|
export function isReferenceToLogicalModel(node) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
return ast.isElement(node.value.ref);
|
|
42
|
+
const referenceable = referenceableParent(node);
|
|
43
|
+
return referenceable?.$type === "Element";
|
|
33
44
|
}
|
|
34
45
|
export function isReferenceToDeploymentModel(node) {
|
|
35
46
|
let referenceable;
|
package/dist/utils/index.d.ts
CHANGED
package/dist/utils/index.js
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
|
+
import { logger } from "../logger.js";
|
|
1
2
|
export * from "./disposable.js";
|
|
2
3
|
export * from "./elementRef.js";
|
|
3
4
|
export * from "./fqnRef.js";
|
|
4
5
|
export * from "./projectId.js";
|
|
5
6
|
export * from "./stringHash.js";
|
|
7
|
+
export function safeCall(fn) {
|
|
8
|
+
try {
|
|
9
|
+
return fn();
|
|
10
|
+
} catch (e) {
|
|
11
|
+
logger.debug(`Safe call failed`, { error: e });
|
|
12
|
+
return void 0;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import { type ProjectId } from '@likec4/core';
|
|
2
2
|
import { type AstNode, type LangiumDocument } from 'langium';
|
|
3
|
-
|
|
3
|
+
import { ast } from '../ast';
|
|
4
|
+
export declare function projectIdFrom(value: AstNode | LangiumDocument | ast.ImportsFromPoject | ast.Imported): ProjectId;
|
package/dist/utils/projectId.js
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
|
-
import { nonNullable } from "@likec4/core";
|
|
1
|
+
import { invariant, nonNullable } from "@likec4/core";
|
|
2
2
|
import { AstUtils, isAstNode } from "langium";
|
|
3
|
+
import { ast } from "../ast.js";
|
|
3
4
|
export function projectIdFrom(value) {
|
|
5
|
+
if (ast.isImported(value)) {
|
|
6
|
+
while (value.$type === "Imported" && value.$container) {
|
|
7
|
+
value = value.$container;
|
|
8
|
+
}
|
|
9
|
+
invariant(ast.isImportsFromPoject(value));
|
|
10
|
+
}
|
|
11
|
+
if (ast.isImportsFromPoject(value)) {
|
|
12
|
+
return value.project;
|
|
13
|
+
}
|
|
4
14
|
const doc = isAstNode(value) ? AstUtils.getDocument(value) : value;
|
|
5
15
|
return nonNullable(doc.likec4ProjectId, () => `Invalid state, document ${doc.uri} has no project ID assigned`);
|
|
6
16
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { isPromise } from "remeda";
|
|
2
|
-
import {
|
|
2
|
+
import { logger } from "../logger.js";
|
|
3
3
|
export const RESERVED_WORDS = [
|
|
4
4
|
"this",
|
|
5
5
|
"it",
|
|
@@ -19,7 +19,7 @@ export function tryOrLog(fn) {
|
|
|
19
19
|
} catch (e) {
|
|
20
20
|
const message = e instanceof Error ? e.message : String(e);
|
|
21
21
|
accept("error", `Validation failed: ${message}`, { node });
|
|
22
|
-
|
|
22
|
+
logger.debug(`Validation failed: ${message}`, { error: e });
|
|
23
23
|
}
|
|
24
24
|
};
|
|
25
25
|
}
|
|
@@ -73,15 +73,6 @@ export const deployedInstanceChecks = (services) => {
|
|
|
73
73
|
export const deploymentRelationChecks = (services) => {
|
|
74
74
|
const ModelParser = services.likec4.ModelParser;
|
|
75
75
|
return tryOrLog((el, accept) => {
|
|
76
|
-
const source = el.source?.value?.ref;
|
|
77
|
-
if (!source) {
|
|
78
|
-
let sourceCstText = el.source?.$cstNode?.text ?? "";
|
|
79
|
-
accept("error", `DeploymentRelation source '${sourceCstText}' not resolved`, {
|
|
80
|
-
node: el,
|
|
81
|
-
property: "source"
|
|
82
|
-
});
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
76
|
const target = el.target?.value?.ref;
|
|
86
77
|
if (!target) {
|
|
87
78
|
let targetCstText = el.target?.$cstNode?.text ?? "";
|
|
@@ -93,7 +84,23 @@ export const deploymentRelationChecks = (services) => {
|
|
|
93
84
|
}
|
|
94
85
|
const doc = getDocument(el);
|
|
95
86
|
const parser = ModelParser.forDocument(doc);
|
|
96
|
-
|
|
87
|
+
let sourceFqnRef;
|
|
88
|
+
try {
|
|
89
|
+
sourceFqnRef = parser._resolveDeploymentRelationSource(el);
|
|
90
|
+
} catch (e) {
|
|
91
|
+
accept("error", "DeploymentRelation source not resolved", {
|
|
92
|
+
node: el,
|
|
93
|
+
property: "source"
|
|
94
|
+
});
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (FqnRef.isImportRef(sourceFqnRef)) {
|
|
98
|
+
accept("error", "DeploymentRelation cannot refer imported model (not implemented yet)", {
|
|
99
|
+
node: el,
|
|
100
|
+
property: "source"
|
|
101
|
+
});
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
97
104
|
if (FqnRef.isModelRef(sourceFqnRef)) {
|
|
98
105
|
accept("error", "DeploymentRelation must refer deployment element", {
|
|
99
106
|
node: el,
|
|
@@ -102,6 +109,13 @@ export const deploymentRelationChecks = (services) => {
|
|
|
102
109
|
return;
|
|
103
110
|
}
|
|
104
111
|
const targetFqnRef = parser.parseFqnRef(el.target);
|
|
112
|
+
if (FqnRef.isImportRef(targetFqnRef)) {
|
|
113
|
+
accept("error", "DeploymentRelation cannot refer imported model (not implemented yet)", {
|
|
114
|
+
node: el,
|
|
115
|
+
property: "target"
|
|
116
|
+
});
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
105
119
|
if (FqnRef.isModelRef(targetFqnRef)) {
|
|
106
120
|
accept("error", "DeploymentRelation must refer deployment element", {
|
|
107
121
|
node: el,
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { isReferenceToDeploymentModel } from "../utils/index.js";
|
|
2
|
+
import { tryOrLog } from "./_shared.js";
|
|
3
|
+
export const checkElementRef = (services) => {
|
|
4
|
+
return tryOrLog((el, accept) => {
|
|
5
|
+
if (isReferenceToDeploymentModel(el.modelElement)) {
|
|
6
|
+
accept("error", "Only model elements allowed here", {
|
|
7
|
+
node: el,
|
|
8
|
+
property: "modelElement"
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { type ValidationCheck } from 'langium';
|
|
2
2
|
import type { ast } from '../ast';
|
|
3
3
|
import type { LikeC4Services } from '../module';
|
|
4
|
-
export declare const
|
|
4
|
+
export declare const checkElement: (services: LikeC4Services) => ValidationCheck<ast.Element>;
|
|
@@ -2,7 +2,7 @@ import { AstUtils } from "langium";
|
|
|
2
2
|
import { projectIdFrom } from "../utils/index.js";
|
|
3
3
|
import { RESERVED_WORDS, tryOrLog } from "./_shared.js";
|
|
4
4
|
const { getDocument } = AstUtils;
|
|
5
|
-
export const
|
|
5
|
+
export const checkElement = (services) => {
|
|
6
6
|
const fqnIndex = services.likec4.FqnIndex;
|
|
7
7
|
const locator = services.workspace.AstNodeLocator;
|
|
8
8
|
return tryOrLog((el, accept) => {
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type ValidationCheck } from 'langium';
|
|
2
|
+
import type { ast } from '../ast';
|
|
3
|
+
import type { LikeC4Services } from '../module';
|
|
4
|
+
export declare const checkImportsFromPoject: (services: LikeC4Services) => ValidationCheck<ast.ImportsFromPoject>;
|
|
5
|
+
export declare const checkImported: (services: LikeC4Services) => ValidationCheck<ast.Imported>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { AstUtils } from "langium";
|
|
2
|
+
import { projectIdFrom } from "../utils/index.js";
|
|
3
|
+
import { tryOrLog } from "./_shared.js";
|
|
4
|
+
const { getDocument } = AstUtils;
|
|
5
|
+
export const checkImportsFromPoject = (services) => {
|
|
6
|
+
const projects = services.shared.workspace.ProjectsManager;
|
|
7
|
+
return tryOrLog((el, accept) => {
|
|
8
|
+
const doc = getDocument(el);
|
|
9
|
+
const projectId = projectIdFrom(doc);
|
|
10
|
+
if (el.project === projectId) {
|
|
11
|
+
accept("error", "Imported project cannot be the same as the current project", {
|
|
12
|
+
node: el,
|
|
13
|
+
property: "project"
|
|
14
|
+
});
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (!projects.all.includes(el.project)) {
|
|
18
|
+
accept("error", "Imported project not found", {
|
|
19
|
+
node: el,
|
|
20
|
+
property: "project"
|
|
21
|
+
});
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
};
|
|
26
|
+
export const checkImported = (services) => {
|
|
27
|
+
const fqnIndex = services.likec4.FqnIndex;
|
|
28
|
+
return tryOrLog((el, accept) => {
|
|
29
|
+
});
|
|
30
|
+
};
|
|
@@ -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.
|
|
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.ElementStringProperty | ast.ElementStyleProperty | ast.IconProperty | ast.LinkProperty | ast.MetadataBody | ast.ElementKindExpression | ast.ElementTagExpression | ast.FqnRefExpr | ast.WildcardExpression | ast.FqnExprWhere | ast.FqnExprWith | ast.DirectedRelationExpr | ast.InOutRelationExpr | ast.IncomingRelationExpr | ast.OutgoingRelationExpr | ast.RelationExprWhere | ast.RelationExprWith | ast.Element | ast.ExtendDeployment | ast.ExtendElement | ast.Imported | ast.DeploymentView | ast.DynamicView | ast.ElementView | 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.ViewRulePredicate | ast.SpecificationRelationshipKind | ast.GlobalStyle | ast.SpecificationColor | ast.NavigateToProperty | ast.DynamicViewStep | ast.ElementRef | ast.DeploymentRelation | ast.Tags | ast.SpecificationDeploymentNodeKind | ast.DynamicViewParallelSteps | ast.GlobalDynamicPredicateGroup | ast.Relation | ast.SpecificationElementKind | ast.Globals | ast.GlobalPredicateGroup | ast.GlobalStyleGroup | ast.ImportsFromPoject | 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;
|