@likec4/language-server 0.36.0 → 0.37.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/contrib/likec4.monarch.ts +1 -1
- package/contrib/likec4.tmLanguage.json +1 -1
- package/dist/ast.d.ts +2 -1
- package/dist/elementRef.d.ts +14 -2
- package/dist/elementRef.js +14 -2
- package/dist/generated/ast.d.ts +26 -9
- package/dist/generated/ast.js +14 -3
- package/dist/generated/grammar.js +235 -143
- package/dist/lsp/SemanticTokenProvider.js +14 -13
- package/dist/model/fqn-computation.js +2 -2
- package/dist/model/fqn-index.js +4 -6
- package/dist/model/model-builder.d.ts +3 -1
- package/dist/model/model-builder.js +76 -33
- package/dist/model/model-locator.js +1 -1
- package/dist/model/model-parser.js +31 -15
- package/dist/protocol.d.ts +10 -2
- package/dist/protocol.js +5 -1
- package/dist/references/scope-provider.js +13 -7
- package/dist/registerProtocolHandlers.js +16 -0
- package/dist/validation/view.js +3 -0
- package/package.json +3 -3
|
@@ -10,6 +10,14 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
10
10
|
type: SemanticTokenTypes.keyword,
|
|
11
11
|
modifier: [SemanticTokenModifiers.defaultLibrary]
|
|
12
12
|
});
|
|
13
|
+
if ('arr' in node) {
|
|
14
|
+
acceptor({
|
|
15
|
+
node,
|
|
16
|
+
property: 'arr',
|
|
17
|
+
type: SemanticTokenTypes.keyword,
|
|
18
|
+
modifier: [SemanticTokenModifiers.defaultLibrary]
|
|
19
|
+
});
|
|
20
|
+
}
|
|
13
21
|
if (ast.isElementRef(node) || ast.isStrictElementRef(node)) {
|
|
14
22
|
acceptor({
|
|
15
23
|
node,
|
|
@@ -18,21 +26,21 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
18
26
|
});
|
|
19
27
|
return;
|
|
20
28
|
}
|
|
21
|
-
if (ast.
|
|
29
|
+
if (ast.isElementViewRef(node)) {
|
|
22
30
|
acceptor({
|
|
23
31
|
node,
|
|
24
|
-
property: '
|
|
32
|
+
property: 'view',
|
|
25
33
|
type: SemanticTokenTypes.variable
|
|
26
34
|
});
|
|
27
35
|
return;
|
|
28
36
|
}
|
|
29
|
-
if (
|
|
37
|
+
if (ast.isWildcardExpression(node)) {
|
|
30
38
|
acceptor({
|
|
31
39
|
node,
|
|
32
|
-
property: '
|
|
33
|
-
type: SemanticTokenTypes.
|
|
34
|
-
modifier: [SemanticTokenModifiers.defaultLibrary]
|
|
40
|
+
property: 'isWildcard',
|
|
41
|
+
type: SemanticTokenTypes.variable
|
|
35
42
|
});
|
|
43
|
+
return;
|
|
36
44
|
}
|
|
37
45
|
// if (
|
|
38
46
|
// ast.isRelation(node) ||
|
|
@@ -197,13 +205,6 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
197
205
|
modifier: [SemanticTokenModifiers.declaration]
|
|
198
206
|
});
|
|
199
207
|
}
|
|
200
|
-
if (node.viewOf) {
|
|
201
|
-
acceptor({
|
|
202
|
-
node,
|
|
203
|
-
keyword: 'of',
|
|
204
|
-
type: SemanticTokenTypes.keyword
|
|
205
|
-
});
|
|
206
|
-
}
|
|
207
208
|
}
|
|
208
209
|
}
|
|
209
210
|
//# sourceMappingURL=SemanticTokenProvider.js.map
|
|
@@ -2,7 +2,7 @@ import { AsFqn, nonexhaustive } from '@likec4/core';
|
|
|
2
2
|
import { MultiMap } from 'langium';
|
|
3
3
|
import { isEmpty, isNil } from 'remeda';
|
|
4
4
|
import { ElementOps, ast } from '../ast';
|
|
5
|
-
import {
|
|
5
|
+
import { fqnElementRef } from '../elementRef';
|
|
6
6
|
export function computeDocumentFqn(document, services) {
|
|
7
7
|
const c4fqns = (document.c4fqns = new MultiMap());
|
|
8
8
|
const { model } = document.parseResult.value;
|
|
@@ -19,7 +19,7 @@ export function computeDocumentFqn(document, services) {
|
|
|
19
19
|
}
|
|
20
20
|
if (ast.isExtendElement(el)) {
|
|
21
21
|
if (!isNil(el.body) && !isEmpty(el.body.elements)) {
|
|
22
|
-
const fqn =
|
|
22
|
+
const fqn = fqnElementRef(el.element);
|
|
23
23
|
el.body.elements.forEach(child => traverseStack.push([child, fqn]));
|
|
24
24
|
}
|
|
25
25
|
continue;
|
package/dist/model/fqn-index.js
CHANGED
|
@@ -51,9 +51,10 @@ export class FqnIndex {
|
|
|
51
51
|
documents() {
|
|
52
52
|
return this.langiumDocuments.all.filter(isFqnIndexedDocument);
|
|
53
53
|
}
|
|
54
|
-
entries() {
|
|
54
|
+
entries(filterByFqn = () => true) {
|
|
55
55
|
return this.documents().flatMap(doc => doc.c4fqns
|
|
56
56
|
.entries()
|
|
57
|
+
.filter(([fqn]) => filterByFqn(fqn))
|
|
57
58
|
.map(([fqn, entry]) => {
|
|
58
59
|
const el = entry.el.deref();
|
|
59
60
|
if (el) {
|
|
@@ -90,8 +91,7 @@ export class FqnIndex {
|
|
|
90
91
|
}
|
|
91
92
|
directChildrenOf(parent) {
|
|
92
93
|
return stream([parent]).flatMap(_parent => {
|
|
93
|
-
const children = this.entries()
|
|
94
|
-
.filter(e => parentFqn(e.fqn) === _parent)
|
|
94
|
+
const children = this.entries(fqn => parentFqn(fqn) === _parent)
|
|
95
95
|
.map((entry) => [entry.name, entry])
|
|
96
96
|
.toArray();
|
|
97
97
|
if (children.length === 0) {
|
|
@@ -112,9 +112,7 @@ export class FqnIndex {
|
|
|
112
112
|
const childrenNames = new Set();
|
|
113
113
|
const descedants = [];
|
|
114
114
|
const nested = new MultiMap();
|
|
115
|
-
this.entries()
|
|
116
|
-
.filter(e => e.fqn.startsWith(prefix))
|
|
117
|
-
.forEach(e => {
|
|
115
|
+
this.entries(f => f.startsWith(prefix)).forEach(e => {
|
|
118
116
|
const name = nameFromFqn(e.fqn);
|
|
119
117
|
const entry = { ...e, name };
|
|
120
118
|
// To keep direct children always
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type c4 } from '@likec4/core';
|
|
1
|
+
import { type ViewID, type c4 } from '@likec4/core';
|
|
2
2
|
import type { LikeC4Services } from '../module';
|
|
3
3
|
export declare class LikeC4ModelBuilder {
|
|
4
4
|
private services;
|
|
@@ -7,7 +7,9 @@ export declare class LikeC4ModelBuilder {
|
|
|
7
7
|
constructor(services: LikeC4Services);
|
|
8
8
|
private cleanCache;
|
|
9
9
|
private documents;
|
|
10
|
+
buildRawModel(): c4.LikeC4RawModel | null;
|
|
10
11
|
buildModel(): c4.LikeC4Model | null;
|
|
12
|
+
computeView(viewId: ViewID): c4.ComputedView | null;
|
|
11
13
|
private scheduledCb;
|
|
12
14
|
private notifyClient;
|
|
13
15
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { ModelIndex,
|
|
2
|
-
import { clone } from 'rambdax';
|
|
1
|
+
import { ModelIndex, compareByFqnHierarchically, parentFqn, resolveRulesExtendedViews, computeView, assignNavigateTo, isStrictElementView } from '@likec4/core';
|
|
3
2
|
import * as R from 'remeda';
|
|
4
3
|
import { isValidLikeC4LangiumDocument } from '../ast';
|
|
5
4
|
import { logError, logWarnError, logger } from '../logger';
|
|
@@ -58,42 +57,49 @@ function buildModel(docs) {
|
|
|
58
57
|
return null;
|
|
59
58
|
};
|
|
60
59
|
const relations = R.pipe(R.flatMap(docs, d => d.c4Relations), R.map(toModelRelation), R.compact, R.mapToObj(r => [r.id, r]));
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
if (!title && view.viewOf) {
|
|
67
|
-
title = elements[view.viewOf]?.title;
|
|
68
|
-
}
|
|
69
|
-
if (!title && view.id === 'index') {
|
|
70
|
-
title = 'Landscape view';
|
|
71
|
-
}
|
|
72
|
-
const computeResult = computeView({
|
|
73
|
-
...model,
|
|
74
|
-
title: title ?? null,
|
|
75
|
-
description: description ?? null,
|
|
76
|
-
tags: tags ?? null,
|
|
77
|
-
links: links ?? null,
|
|
78
|
-
rules: clone(rules)
|
|
79
|
-
}, modelIndex);
|
|
80
|
-
if (!computeResult.isSuccess) {
|
|
81
|
-
logWarnError(computeResult.error);
|
|
82
|
-
return null;
|
|
83
|
-
}
|
|
84
|
-
return computeResult.view;
|
|
60
|
+
const toElementView = (view) => {
|
|
61
|
+
// eslint-disable-next-line prefer-const
|
|
62
|
+
let { astPath, rules, title, description, tags, links, ...model } = view;
|
|
63
|
+
if (!title && 'viewOf' in view) {
|
|
64
|
+
title = elements[view.viewOf]?.title;
|
|
85
65
|
}
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
return null;
|
|
66
|
+
if (!title && view.id === 'index') {
|
|
67
|
+
title = 'Landscape view';
|
|
89
68
|
}
|
|
69
|
+
return {
|
|
70
|
+
...model,
|
|
71
|
+
title: title ?? null,
|
|
72
|
+
description: description ?? null,
|
|
73
|
+
tags: tags ?? null,
|
|
74
|
+
links: links ?? null,
|
|
75
|
+
rules
|
|
76
|
+
};
|
|
90
77
|
};
|
|
91
|
-
const views = R.pipe(R.flatMap(docs, d => d.c4Views), R.map(
|
|
92
|
-
|
|
78
|
+
const views = R.pipe(R.flatMap(docs, d => d.c4Views), R.map(toElementView), R.compact, R.mapToObj(v => [v.id, v]));
|
|
79
|
+
// add index view if not present
|
|
80
|
+
if (!('index' in views)) {
|
|
81
|
+
views['index'] = {
|
|
82
|
+
id: 'index',
|
|
83
|
+
title: 'Landscape',
|
|
84
|
+
description: null,
|
|
85
|
+
tags: null,
|
|
86
|
+
links: null,
|
|
87
|
+
rules: [
|
|
88
|
+
{
|
|
89
|
+
isInclude: true,
|
|
90
|
+
exprs: [
|
|
91
|
+
{
|
|
92
|
+
wildcard: true
|
|
93
|
+
}
|
|
94
|
+
]
|
|
95
|
+
}
|
|
96
|
+
]
|
|
97
|
+
};
|
|
98
|
+
}
|
|
93
99
|
return {
|
|
94
100
|
elements,
|
|
95
101
|
relations,
|
|
96
|
-
views:
|
|
102
|
+
views: resolveRulesExtendedViews(views)
|
|
97
103
|
};
|
|
98
104
|
}
|
|
99
105
|
export class LikeC4ModelBuilder {
|
|
@@ -114,7 +120,7 @@ export class LikeC4ModelBuilder {
|
|
|
114
120
|
documents() {
|
|
115
121
|
return this.langiumDocuments.all.filter(isValidLikeC4LangiumDocument).toArray();
|
|
116
122
|
}
|
|
117
|
-
|
|
123
|
+
buildRawModel() {
|
|
118
124
|
if ('last' in this.cachedModel) {
|
|
119
125
|
logger.debug('[ModelBuilder] returning cached model');
|
|
120
126
|
return this.cachedModel.last;
|
|
@@ -133,6 +139,43 @@ export class LikeC4ModelBuilder {
|
|
|
133
139
|
return null;
|
|
134
140
|
}
|
|
135
141
|
}
|
|
142
|
+
buildModel() {
|
|
143
|
+
const model = this.buildRawModel();
|
|
144
|
+
if (!model) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
const index = ModelIndex.from(model);
|
|
148
|
+
const views = R.pipe(R.values(model.views), R.map(view => computeView(view, index).view), R.compact);
|
|
149
|
+
assignNavigateTo(views);
|
|
150
|
+
return {
|
|
151
|
+
elements: model.elements,
|
|
152
|
+
relations: model.relations,
|
|
153
|
+
views: R.mapToObj(views, v => [v.id, v])
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
computeView(viewId) {
|
|
157
|
+
const model = this.buildRawModel();
|
|
158
|
+
const view = model?.views[viewId];
|
|
159
|
+
if (!view) {
|
|
160
|
+
logger.warn(`[ModelBuilder] Cannot find view ${viewId}`);
|
|
161
|
+
return null;
|
|
162
|
+
}
|
|
163
|
+
const result = computeView(view, ModelIndex.from(model));
|
|
164
|
+
if (!result.isSuccess) {
|
|
165
|
+
logError(result.error);
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
const allElementViews = R.values(model.views).filter((v) => isStrictElementView(v) && v.id !== viewId);
|
|
169
|
+
const computedView = result.view;
|
|
170
|
+
computedView.nodes.forEach(node => {
|
|
171
|
+
// find first element view that is not the current one
|
|
172
|
+
const navigateTo = R.find(allElementViews, v => v.viewOf === node.id);
|
|
173
|
+
if (navigateTo) {
|
|
174
|
+
node.navigateTo = navigateTo.id;
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
return computedView;
|
|
178
|
+
}
|
|
136
179
|
scheduledCb = null;
|
|
137
180
|
notifyClient() {
|
|
138
181
|
const connection = this.services.shared.lsp.Connection;
|
|
@@ -91,7 +91,7 @@ export class LikeC4ModelLocator {
|
|
|
91
91
|
if (node.name) {
|
|
92
92
|
targetNode = findNodeForProperty(node.$cstNode, 'name') ?? targetNode;
|
|
93
93
|
}
|
|
94
|
-
else if (node
|
|
94
|
+
else if ('viewOf' in node) {
|
|
95
95
|
targetNode = findNodeForProperty(node.$cstNode, 'viewOf') ?? targetNode;
|
|
96
96
|
}
|
|
97
97
|
if (!targetNode) {
|
|
@@ -4,7 +4,7 @@ import objectHash from 'object-hash';
|
|
|
4
4
|
import stripIndent from 'strip-indent';
|
|
5
5
|
import { Disposable } from 'vscode-languageserver-protocol';
|
|
6
6
|
import { ElementViewOps, ast, cleanParsedModel, isLikeC4LangiumDocument, resolveRelationPoints, streamModel, toAutoLayout, toElementStyle, toElementStyleExcludeDefaults } from '../ast';
|
|
7
|
-
import { elementRef,
|
|
7
|
+
import { elementRef, fqnElementRef } from '../elementRef';
|
|
8
8
|
import { logError, logWarnError, logger } from '../logger';
|
|
9
9
|
import { printDocs } from '../utils';
|
|
10
10
|
export class LikeC4ModelParser {
|
|
@@ -226,31 +226,29 @@ export class LikeC4ModelParser {
|
|
|
226
226
|
nonexhaustive(astRule);
|
|
227
227
|
}
|
|
228
228
|
parseElementView(astNode) {
|
|
229
|
-
const
|
|
230
|
-
|
|
229
|
+
const body = astNode.body;
|
|
230
|
+
invariant(body, 'ElementView body is not defined');
|
|
231
231
|
const astPath = this.getAstNodePath(astNode);
|
|
232
232
|
let id = astNode.name;
|
|
233
233
|
if (!id) {
|
|
234
234
|
const doc = getDocument(astNode).uri.toString();
|
|
235
235
|
id = objectHash({
|
|
236
236
|
doc,
|
|
237
|
-
astPath
|
|
238
|
-
viewOf: viewOf ?? null
|
|
237
|
+
astPath
|
|
239
238
|
});
|
|
240
239
|
}
|
|
241
|
-
const title =
|
|
242
|
-
const description =
|
|
243
|
-
const tags = this.convertTags(
|
|
244
|
-
const links =
|
|
245
|
-
|
|
246
|
-
id,
|
|
240
|
+
const title = body.props.find(p => p.key === 'title')?.value;
|
|
241
|
+
const description = body.props.find(p => p.key === 'description')?.value;
|
|
242
|
+
const tags = this.convertTags(body);
|
|
243
|
+
const links = body.props.filter(ast.isLinkProperty).map(p => p.value);
|
|
244
|
+
const basic = {
|
|
245
|
+
id: id,
|
|
247
246
|
astPath,
|
|
248
|
-
...(viewOf && { viewOf }),
|
|
249
247
|
...(title && { title }),
|
|
250
248
|
...(description && { description }),
|
|
251
249
|
...(tags && { tags }),
|
|
252
|
-
...(
|
|
253
|
-
rules:
|
|
250
|
+
...(isNonEmptyArray(links) && { links }),
|
|
251
|
+
rules: body.rules.flatMap(n => {
|
|
254
252
|
try {
|
|
255
253
|
return this.parseViewRule(n);
|
|
256
254
|
}
|
|
@@ -260,10 +258,28 @@ export class LikeC4ModelParser {
|
|
|
260
258
|
}
|
|
261
259
|
})
|
|
262
260
|
};
|
|
261
|
+
if ('viewOf' in astNode) {
|
|
262
|
+
const viewOfEl = elementRef(astNode.viewOf);
|
|
263
|
+
const viewOf = viewOfEl && this.resolveFqn(viewOfEl);
|
|
264
|
+
invariant(viewOf, ' viewOf is not resolved: ' + astNode.$cstNode?.text);
|
|
265
|
+
return {
|
|
266
|
+
...basic,
|
|
267
|
+
viewOf
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
if ('extends' in astNode) {
|
|
271
|
+
const extendsView = astNode.extends.view.ref;
|
|
272
|
+
invariant(extendsView?.name, 'view extends is not resolved: ' + astNode.$cstNode?.text);
|
|
273
|
+
return {
|
|
274
|
+
...basic,
|
|
275
|
+
extends: extendsView.name
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
return basic;
|
|
263
279
|
}
|
|
264
280
|
resolveFqn(node) {
|
|
265
281
|
if (ast.isExtendElement(node)) {
|
|
266
|
-
return
|
|
282
|
+
return fqnElementRef(node.element);
|
|
267
283
|
}
|
|
268
284
|
const fqn = this.fqnIndex.getFqn(node);
|
|
269
285
|
invariant(fqn, `Not indexed element: ${this.getAstNodePath(node)}`);
|
package/dist/protocol.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { Fqn, LikeC4Model, RelationID, ViewID } from '@likec4/core';
|
|
1
|
+
import type { ComputedView, Fqn, LikeC4Model, LikeC4RawModel, RelationID, ViewID } from '@likec4/core';
|
|
2
2
|
import type { DocumentUri, Location } from 'vscode-languageserver-protocol';
|
|
3
|
-
import { NotificationType,
|
|
3
|
+
import { NotificationType, RequestType, RequestType0 } from 'vscode-languageserver-protocol';
|
|
4
4
|
interface BuildDocumentsParams {
|
|
5
5
|
docs: DocumentUri[];
|
|
6
6
|
}
|
|
@@ -18,6 +18,14 @@ export declare const Rpc: {
|
|
|
18
18
|
readonly fetchModel: RequestType0<{
|
|
19
19
|
model: LikeC4Model | null;
|
|
20
20
|
}, void>;
|
|
21
|
+
readonly fetchRawModel: RequestType0<{
|
|
22
|
+
rawmodel: LikeC4RawModel | null;
|
|
23
|
+
}, void>;
|
|
24
|
+
readonly computeView: RequestType<{
|
|
25
|
+
viewId: ViewID;
|
|
26
|
+
}, {
|
|
27
|
+
view: ComputedView | null;
|
|
28
|
+
}, void>;
|
|
21
29
|
readonly rebuild: RequestType0<{
|
|
22
30
|
docs: DocumentUri[];
|
|
23
31
|
}, void>;
|
package/dist/protocol.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import { NotificationType,
|
|
1
|
+
import { NotificationType, RequestType, RequestType0 } from 'vscode-languageserver-protocol';
|
|
2
2
|
//#region From server
|
|
3
3
|
const onDidChangeModel = new NotificationType('likec4/onDidChangeModel');
|
|
4
4
|
//#endregion
|
|
5
5
|
//#region To server
|
|
6
|
+
const fetchRawModel = new RequestType0('likec4/fetchRaw');
|
|
6
7
|
const fetchModel = new RequestType0('likec4/fetchModel');
|
|
8
|
+
const computeView = new RequestType('likec4/computeView');
|
|
7
9
|
const rebuild = new RequestType0('likec4/rebuildModel');
|
|
8
10
|
const buildDocuments = new RequestType('likec4/buildDocuments');
|
|
9
11
|
export const locate = new RequestType('likec4/locate');
|
|
@@ -11,6 +13,8 @@ export const locate = new RequestType('likec4/locate');
|
|
|
11
13
|
export const Rpc = {
|
|
12
14
|
onDidChangeModel,
|
|
13
15
|
fetchModel,
|
|
16
|
+
fetchRawModel,
|
|
17
|
+
computeView,
|
|
14
18
|
rebuild,
|
|
15
19
|
buildDocuments,
|
|
16
20
|
locate
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { DONE_RESULT, DefaultScopeProvider, EMPTY_STREAM, StreamImpl, StreamScope, getDocument, stream, findNodeForProperty, toDocumentSegment } from 'langium';
|
|
2
2
|
import { ast } from '../ast';
|
|
3
|
-
import { elementRef, isElementRefHead,
|
|
3
|
+
import { elementRef, isElementRefHead, parentFqnElementRef } from '../elementRef';
|
|
4
4
|
import { logError } from '../logger';
|
|
5
5
|
function toAstNodeDescription(entry) {
|
|
6
6
|
const $cstNode = findNodeForProperty(entry.el.$cstNode, 'name');
|
|
@@ -52,11 +52,17 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
52
52
|
scopeExtendElement(extend) {
|
|
53
53
|
return this.uniqueDescedants(() => elementRef(extend.element));
|
|
54
54
|
}
|
|
55
|
-
scopeElementView({ viewOf }) {
|
|
56
|
-
if (
|
|
57
|
-
return
|
|
55
|
+
scopeElementView({ viewOf, extends: ext }) {
|
|
56
|
+
if (ext) {
|
|
57
|
+
return stream([ext]).flatMap(v => {
|
|
58
|
+
const view = v.view.ref;
|
|
59
|
+
return view ? this.scopeElementView(view) : EMPTY_STREAM;
|
|
60
|
+
});
|
|
58
61
|
}
|
|
59
|
-
|
|
62
|
+
if (viewOf) {
|
|
63
|
+
return this.uniqueDescedants(() => elementRef(viewOf));
|
|
64
|
+
}
|
|
65
|
+
return EMPTY_STREAM;
|
|
60
66
|
}
|
|
61
67
|
getScope(context) {
|
|
62
68
|
const referenceType = this.reflection.getReferenceType(context);
|
|
@@ -68,7 +74,7 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
68
74
|
if (isElementRefHead(container)) {
|
|
69
75
|
return this.getGlobalScope(referenceType);
|
|
70
76
|
}
|
|
71
|
-
const parent =
|
|
77
|
+
const parent = parentFqnElementRef(container);
|
|
72
78
|
return new StreamScope(this.directChildrenOf(parent));
|
|
73
79
|
}
|
|
74
80
|
if (ast.isElementRef(container) && !isElementRefHead(container)) {
|
|
@@ -102,7 +108,7 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
102
108
|
if (ast.isExtendElementBody(container)) {
|
|
103
109
|
scopes.push(this.scopeExtendElement(container.$container));
|
|
104
110
|
}
|
|
105
|
-
if (ast.
|
|
111
|
+
if (ast.isElementViewBody(container)) {
|
|
106
112
|
scopes.push(this.scopeElementView(container.$container));
|
|
107
113
|
}
|
|
108
114
|
}
|
|
@@ -22,6 +22,22 @@ export function registerProtocolHandlers(services) {
|
|
|
22
22
|
}
|
|
23
23
|
return Promise.resolve({ model });
|
|
24
24
|
});
|
|
25
|
+
connection.onRequest(Rpc.fetchRawModel, async (_cancelToken) => {
|
|
26
|
+
let rawmodel;
|
|
27
|
+
try {
|
|
28
|
+
rawmodel = modelBuilder.buildRawModel() ?? null;
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
rawmodel = null;
|
|
32
|
+
logError(e);
|
|
33
|
+
}
|
|
34
|
+
return Promise.resolve({ rawmodel });
|
|
35
|
+
});
|
|
36
|
+
connection.onRequest(Rpc.computeView, ({ viewId }) => {
|
|
37
|
+
return {
|
|
38
|
+
view: modelBuilder.computeView(viewId)
|
|
39
|
+
};
|
|
40
|
+
});
|
|
25
41
|
connection.onRequest(Rpc.rebuild, async (cancelToken) => {
|
|
26
42
|
const changed = LangiumDocuments.all
|
|
27
43
|
.map(d => {
|
package/dist/validation/view.js
CHANGED
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@likec4/language-server",
|
|
3
3
|
"description": "LikeC4 Language Server",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.37.1",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bugs": "https://github.com/likec4/likec4/issues",
|
|
7
7
|
"homepage": "https://likec4.dev",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"test:watch": "vitest"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@likec4/core": "0.
|
|
45
|
+
"@likec4/core": "0.37.1",
|
|
46
46
|
"langium": "^2.0.2",
|
|
47
47
|
"nanoid": "^4.0.2",
|
|
48
48
|
"object-hash": "^3.0.0",
|
|
@@ -59,7 +59,7 @@
|
|
|
59
59
|
"langium-cli": "^2.0.1",
|
|
60
60
|
"npm-run-all": "^4.1.5",
|
|
61
61
|
"typescript": "^5.2.2",
|
|
62
|
-
"vitest": "^0.34.
|
|
62
|
+
"vitest": "^0.34.4"
|
|
63
63
|
},
|
|
64
64
|
"packageManager": "yarn@3.6.3"
|
|
65
65
|
}
|