@likec4/language-server 0.23.0 → 0.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/contrib/likec4.monarch.ts +3 -3
- package/dist/ast.d.ts +1 -2
- package/dist/ast.js +6 -6
- package/dist/elementRef.js +1 -0
- package/dist/generated/ast.d.ts +8 -0
- package/dist/generated/ast.js +3 -0
- package/dist/generated/grammar.js +223 -144
- package/dist/lsp/DocumentSymbolProvider.d.ts +1 -1
- package/dist/lsp/DocumentSymbolProvider.js +1 -1
- package/dist/lsp/HoverProvider.d.ts +1 -1
- package/dist/lsp/SemanticTokenProvider.js +23 -24
- package/dist/model/model-builder.d.ts +2 -1
- package/dist/model/model-builder.js +26 -13
- package/dist/module.js +24 -9
- package/dist/protocol.d.ts +2 -2
- package/dist/protocol.js +2 -2
- package/dist/references/scope-computation.js +4 -6
- package/dist/registerProtocolHandlers.js +6 -21
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/package.json +4 -4
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
******************************************************************************/
|
|
6
6
|
/// <reference types="react" />
|
|
7
7
|
import { type DocumentSymbolProvider, type MaybePromise } from 'langium';
|
|
8
|
-
import { type DocumentSymbol } from 'vscode-languageserver';
|
|
8
|
+
import { type DocumentSymbol } from 'vscode-languageserver-protocol';
|
|
9
9
|
import { type LikeC4LangiumDocument, ast } from '../ast';
|
|
10
10
|
import type { LikeC4Services } from '../module';
|
|
11
11
|
export declare class LikeC4DocumentSymbolProvider implements DocumentSymbolProvider {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
******************************************************************************/
|
|
6
6
|
import invariant from 'tiny-invariant';
|
|
7
7
|
import { findNodeForProperty } from 'langium';
|
|
8
|
-
import { SymbolKind } from 'vscode-languageserver';
|
|
8
|
+
import { SymbolKind } from 'vscode-languageserver-protocol';
|
|
9
9
|
import { ast } from '../ast';
|
|
10
10
|
import { logger } from '../logger';
|
|
11
11
|
export class LikeC4DocumentSymbolProvider {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type AstNode, AstNodeHoverProvider, type MaybePromise } from 'langium';
|
|
2
|
-
import type { Hover } from 'vscode-languageserver';
|
|
2
|
+
import type { Hover } from 'vscode-languageserver-protocol';
|
|
3
3
|
import type { LikeC4Services } from '../module';
|
|
4
4
|
export declare class LikeC4HoverProvider extends AstNodeHoverProvider {
|
|
5
5
|
private locator;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AbstractSemanticTokenProvider } from 'langium';
|
|
2
|
-
import { SemanticTokenModifiers, SemanticTokenTypes } from 'vscode-languageserver';
|
|
2
|
+
import { SemanticTokenModifiers, SemanticTokenTypes } from 'vscode-languageserver-protocol';
|
|
3
3
|
import { ast } from '../ast';
|
|
4
4
|
import { isElementRefHead } from '../elementRef';
|
|
5
5
|
export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
@@ -7,7 +7,8 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
7
7
|
const keyword = (keyword, _index) => acceptor({
|
|
8
8
|
node,
|
|
9
9
|
keyword,
|
|
10
|
-
type: SemanticTokenTypes.keyword
|
|
10
|
+
type: SemanticTokenTypes.keyword,
|
|
11
|
+
modifier: [SemanticTokenModifiers.defaultLibrary]
|
|
11
12
|
});
|
|
12
13
|
if (ast.isElementRef(node) || ast.isStrictElementRef(node)) {
|
|
13
14
|
acceptor({
|
|
@@ -25,11 +26,17 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
25
26
|
});
|
|
26
27
|
return;
|
|
27
28
|
}
|
|
28
|
-
if (ast.
|
|
29
|
+
if (ast.isRelation(node) ||
|
|
30
|
+
ast.isRelationExpression(node) ||
|
|
29
31
|
ast.isIncomingExpression(node) ||
|
|
32
|
+
ast.isInOutExpression(node) ||
|
|
30
33
|
ast.isOutgoingExpression(node)) {
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
acceptor({
|
|
35
|
+
node,
|
|
36
|
+
property: 'arr',
|
|
37
|
+
type: SemanticTokenTypes.keyword,
|
|
38
|
+
modifier: [SemanticTokenModifiers.defaultLibrary]
|
|
39
|
+
});
|
|
33
40
|
}
|
|
34
41
|
if (ast.isElementKindExpression(node) || ast.isElementTagExpression(node)) {
|
|
35
42
|
keyword('element');
|
|
@@ -54,13 +61,7 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
54
61
|
return;
|
|
55
62
|
}
|
|
56
63
|
}
|
|
57
|
-
if (ast.isInOutExpression(node)) {
|
|
58
|
-
keyword('->', 0);
|
|
59
|
-
keyword('->', 1);
|
|
60
|
-
return;
|
|
61
|
-
}
|
|
62
64
|
if (ast.isRelation(node)) {
|
|
63
|
-
keyword('->');
|
|
64
65
|
if ('title' in node) {
|
|
65
66
|
acceptor({
|
|
66
67
|
node,
|
|
@@ -102,11 +103,16 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
102
103
|
node,
|
|
103
104
|
property: 'key',
|
|
104
105
|
type: SemanticTokenTypes.keyword
|
|
106
|
+
// type: SemanticTokenTypes.property,
|
|
107
|
+
// modifier: [
|
|
108
|
+
// SemanticTokenModifiers.readonly,
|
|
109
|
+
// SemanticTokenModifiers.declaration
|
|
110
|
+
// ]
|
|
105
111
|
});
|
|
106
112
|
acceptor({
|
|
107
113
|
node,
|
|
108
114
|
property: 'value',
|
|
109
|
-
type: SemanticTokenTypes.
|
|
115
|
+
type: SemanticTokenTypes.enum
|
|
110
116
|
});
|
|
111
117
|
return;
|
|
112
118
|
}
|
|
@@ -115,6 +121,11 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
115
121
|
node,
|
|
116
122
|
property: 'key',
|
|
117
123
|
type: SemanticTokenTypes.keyword
|
|
124
|
+
// type: SemanticTokenTypes.property,
|
|
125
|
+
// modifier: [
|
|
126
|
+
// SemanticTokenModifiers.readonly,
|
|
127
|
+
// SemanticTokenModifiers.declaration
|
|
128
|
+
// ]
|
|
118
129
|
});
|
|
119
130
|
acceptor({
|
|
120
131
|
node,
|
|
@@ -151,20 +162,8 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
151
162
|
type: SemanticTokenTypes.keyword,
|
|
152
163
|
modifier: []
|
|
153
164
|
});
|
|
154
|
-
if ('title' in node) {
|
|
155
|
-
acceptor({
|
|
156
|
-
node,
|
|
157
|
-
property: 'title',
|
|
158
|
-
type: SemanticTokenTypes.string
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
165
|
}
|
|
162
166
|
highlightView(node, acceptor) {
|
|
163
|
-
acceptor({
|
|
164
|
-
node,
|
|
165
|
-
keyword: 'view',
|
|
166
|
-
type: SemanticTokenTypes.keyword
|
|
167
|
-
});
|
|
168
167
|
if (node.name) {
|
|
169
168
|
acceptor({
|
|
170
169
|
node,
|
|
@@ -12,7 +12,7 @@ export declare class LikeC4ModelBuilder {
|
|
|
12
12
|
/**
|
|
13
13
|
* @returns if the document was changed
|
|
14
14
|
*/
|
|
15
|
-
protected parseDocument(doc: LikeC4LangiumDocument):
|
|
15
|
+
protected parseDocument(doc: LikeC4LangiumDocument): void;
|
|
16
16
|
private parseElement;
|
|
17
17
|
private parseRelation;
|
|
18
18
|
private parseElementExpression;
|
|
@@ -22,6 +22,7 @@ export declare class LikeC4ModelBuilder {
|
|
|
22
22
|
protected resolveFqn(node: ast.Element | ast.ExtendElement): c4.Fqn;
|
|
23
23
|
private getAstNodePath;
|
|
24
24
|
private convertTags;
|
|
25
|
+
private scheduledCb;
|
|
25
26
|
private notifyClient;
|
|
26
27
|
}
|
|
27
28
|
//# sourceMappingURL=model-builder.d.ts.map
|
|
@@ -6,11 +6,12 @@ import objectHash from 'object-hash';
|
|
|
6
6
|
import { clone, isNil } from 'rambdax';
|
|
7
7
|
import * as R from 'remeda';
|
|
8
8
|
import invariant from 'tiny-invariant';
|
|
9
|
-
import { ElementViewOps, ast,
|
|
9
|
+
import { ElementViewOps, ast, cleanParsedModel, isLikeC4LangiumDocument, isValidLikeC4LangiumDocument, resolveRelationPoints, streamModel, toAutoLayout, toElementStyle } from '../ast';
|
|
10
10
|
import { elementRef, strictElementRefFqn } from '../elementRef';
|
|
11
11
|
import { logger } from '../logger';
|
|
12
12
|
import { Rpc } from '../protocol';
|
|
13
13
|
import { failExpectedNever } from '../utils';
|
|
14
|
+
import stripIndent from 'strip-indent';
|
|
14
15
|
export class LikeC4ModelBuilder {
|
|
15
16
|
services;
|
|
16
17
|
fqnIndex;
|
|
@@ -25,17 +26,20 @@ export class LikeC4ModelBuilder {
|
|
|
25
26
|
if (cancelToken.isCancellationRequested) {
|
|
26
27
|
break;
|
|
27
28
|
}
|
|
29
|
+
if (!isLikeC4LangiumDocument(doc)) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
countOfChangedDocs++;
|
|
28
33
|
try {
|
|
29
|
-
|
|
30
|
-
countOfChangedDocs++;
|
|
31
|
-
}
|
|
34
|
+
this.parseDocument(doc);
|
|
32
35
|
}
|
|
33
36
|
catch (e) {
|
|
34
37
|
logger.error(`Error parsing document ${doc.uri.toString()}`);
|
|
38
|
+
logger.error(e);
|
|
35
39
|
}
|
|
36
40
|
}
|
|
37
41
|
if (countOfChangedDocs > 0 && !cancelToken.isCancellationRequested) {
|
|
38
|
-
|
|
42
|
+
this.notifyClient();
|
|
39
43
|
}
|
|
40
44
|
});
|
|
41
45
|
}
|
|
@@ -43,7 +47,7 @@ export class LikeC4ModelBuilder {
|
|
|
43
47
|
return this.services.shared.lsp.Connection;
|
|
44
48
|
}
|
|
45
49
|
documents() {
|
|
46
|
-
return this.langiumDocuments.all.toArray().filter(
|
|
50
|
+
return this.langiumDocuments.all.toArray().filter(isValidLikeC4LangiumDocument);
|
|
47
51
|
}
|
|
48
52
|
buildModel() {
|
|
49
53
|
const docs = this.documents();
|
|
@@ -56,7 +60,7 @@ export class LikeC4ModelBuilder {
|
|
|
56
60
|
const c4Specification = {
|
|
57
61
|
kinds: {}
|
|
58
62
|
};
|
|
59
|
-
R.
|
|
63
|
+
R.forEach(R.map(docs, R.prop('c4Specification')), spec => Object.assign(c4Specification.kinds, spec.kinds));
|
|
60
64
|
const toModelElement = (el) => {
|
|
61
65
|
const kind = c4Specification.kinds[el.kind];
|
|
62
66
|
if (kind) {
|
|
@@ -166,9 +170,9 @@ export class LikeC4ModelBuilder {
|
|
|
166
170
|
}
|
|
167
171
|
}
|
|
168
172
|
}
|
|
169
|
-
const prevHash = doc.c4hash ?? ''
|
|
170
|
-
doc.c4hash = c4hash(doc)
|
|
171
|
-
return prevHash !== doc.c4hash
|
|
173
|
+
// const prevHash = doc.c4hash ?? ''
|
|
174
|
+
// doc.c4hash = c4hash(doc)
|
|
175
|
+
// return prevHash !== doc.c4hash
|
|
172
176
|
}
|
|
173
177
|
parseElement(astNode) {
|
|
174
178
|
const id = this.resolveFqn(astNode);
|
|
@@ -189,7 +193,7 @@ export class LikeC4ModelBuilder {
|
|
|
189
193
|
astPath,
|
|
190
194
|
title: title ?? astNode.name,
|
|
191
195
|
...(technology && { technology }),
|
|
192
|
-
...(description && { description }),
|
|
196
|
+
...(description && { description: stripIndent(description).trim() }),
|
|
193
197
|
...(tags.length > 0 ? { tags } : {}),
|
|
194
198
|
...(shape && shape !== DefaultElementShape ? { shape } : {}),
|
|
195
199
|
...(color && color !== DefaultThemeColor ? { color } : {})
|
|
@@ -331,12 +335,21 @@ export class LikeC4ModelBuilder {
|
|
|
331
335
|
convertTags(el) {
|
|
332
336
|
return el.tags?.value.map(tagRef => tagRef.ref?.name) ?? [];
|
|
333
337
|
}
|
|
334
|
-
|
|
338
|
+
scheduledCb = null;
|
|
339
|
+
notifyClient() {
|
|
335
340
|
const connection = this.connection;
|
|
336
341
|
if (!connection) {
|
|
337
342
|
return;
|
|
338
343
|
}
|
|
339
|
-
|
|
344
|
+
if (this.scheduledCb) {
|
|
345
|
+
logger.debug('debounce scheduled onDidChangeModel');
|
|
346
|
+
clearTimeout(this.scheduledCb);
|
|
347
|
+
}
|
|
348
|
+
this.scheduledCb = setTimeout(() => {
|
|
349
|
+
logger.debug('send onDidChangeModel');
|
|
350
|
+
this.scheduledCb = null;
|
|
351
|
+
void connection.sendNotification(Rpc.onDidChangeModel, '');
|
|
352
|
+
}, 350);
|
|
340
353
|
}
|
|
341
354
|
}
|
|
342
355
|
//# sourceMappingURL=model-builder.js.map
|
package/dist/module.js
CHANGED
|
@@ -6,6 +6,7 @@ import { LikeC4ScopeComputation, LikeC4ScopeProvider } from './references';
|
|
|
6
6
|
import { registerProtocolHandlers } from './registerProtocolHandlers';
|
|
7
7
|
import { LikeC4CodeLensProvider, LikeC4WorkspaceManager } from './shared';
|
|
8
8
|
import { registerValidationChecks } from './validation';
|
|
9
|
+
import { logger } from './logger';
|
|
9
10
|
function bind(Type) {
|
|
10
11
|
return (services) => new Type(services);
|
|
11
12
|
}
|
|
@@ -39,15 +40,29 @@ const LikeC4SharedModule = {
|
|
|
39
40
|
}
|
|
40
41
|
};
|
|
41
42
|
export function createLanguageServices(context) {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
43
|
+
const connection = context?.connection;
|
|
44
|
+
if (connection) {
|
|
45
|
+
const log = (method) => (message) => {
|
|
46
|
+
try {
|
|
47
|
+
console[method](message);
|
|
48
|
+
connection.console[method](String(message));
|
|
49
|
+
if (method === 'error') {
|
|
50
|
+
connection.telemetry.logEvent({ eventName: 'error', message });
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
console.error(error);
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
logger.log = log('log');
|
|
58
|
+
logger.info = log('info');
|
|
59
|
+
logger.warn = log('warn');
|
|
60
|
+
logger.error = log('error');
|
|
61
|
+
logger.trace = logger.debug = (message) => {
|
|
62
|
+
console.debug(message);
|
|
63
|
+
connection.tracer.log(message);
|
|
64
|
+
};
|
|
65
|
+
}
|
|
51
66
|
const moduleContext = {
|
|
52
67
|
...EmptyFileSystem,
|
|
53
68
|
...context
|
package/dist/protocol.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Fqn, LikeC4Model, RelationID, ViewID } from '@likec4/core';
|
|
2
2
|
import type { DocumentUri, Location } from 'vscode-languageserver-protocol';
|
|
3
|
-
import {
|
|
3
|
+
import { NotificationType, RequestType0, RequestType } from 'vscode-languageserver-protocol';
|
|
4
4
|
interface BuildDocumentsParams {
|
|
5
5
|
docs: DocumentUri[];
|
|
6
6
|
}
|
|
@@ -16,7 +16,7 @@ export declare const locateView: RequestType<{
|
|
|
16
16
|
id: ViewID;
|
|
17
17
|
}, Location | null, void>;
|
|
18
18
|
export declare const Rpc: {
|
|
19
|
-
readonly onDidChangeModel:
|
|
19
|
+
readonly onDidChangeModel: NotificationType<string>;
|
|
20
20
|
readonly fetchModel: RequestType0<{
|
|
21
21
|
model: LikeC4Model | null;
|
|
22
22
|
}, void>;
|
package/dist/protocol.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { NotificationType, RequestType0, RequestType } from 'vscode-languageserver-protocol';
|
|
2
2
|
//#region From server
|
|
3
|
-
const onDidChangeModel = new
|
|
3
|
+
const onDidChangeModel = new NotificationType('likec4/onDidChangeModel');
|
|
4
4
|
//#endregion
|
|
5
5
|
//#region To server
|
|
6
6
|
const fetchModel = new RequestType0('likec4/fetchModel');
|
|
@@ -18,19 +18,17 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
18
18
|
docExports.push(this.descriptions.createDescription(tag, '#' + tag.name, document));
|
|
19
19
|
}
|
|
20
20
|
}
|
|
21
|
+
// Filled later by FqnIndex (on IndexedContent phase)
|
|
21
22
|
document.c4fqns = undefined;
|
|
22
|
-
|
|
23
|
+
// Only root model elements are exported
|
|
24
|
+
if (model && model.elements.length > 0) {
|
|
23
25
|
for (const elAst of model.elements) {
|
|
24
26
|
if (ast.isElement(elAst)) {
|
|
25
27
|
docExports.push(this.descriptions.createDescription(elAst, elAst.name, document));
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
30
|
}
|
|
29
|
-
|
|
30
|
-
// logger.debug(`doc ${document.uri.path}:
|
|
31
|
-
// fqns: ${c4fqns ? Array.from(c4fqns.keys()).join(', ') : '--'}
|
|
32
|
-
// `)
|
|
33
|
-
if (views) {
|
|
31
|
+
if (views && views.views.length > 0) {
|
|
34
32
|
for (const viewAst of views.views) {
|
|
35
33
|
if ('name' in viewAst) {
|
|
36
34
|
docExports.push(this.descriptions.createDescription(viewAst, viewAst.name, document));
|
|
@@ -67,29 +67,14 @@ We rebuild: [
|
|
|
67
67
|
}
|
|
68
68
|
await services.shared.workspace.DocumentBuilder.update(changed, [], cancelToken);
|
|
69
69
|
});
|
|
70
|
-
connection.onRequest(Rpc.locateElement,
|
|
71
|
-
|
|
72
|
-
return Promise.resolve(modelLocator.locateElement(element, property ?? 'name'));
|
|
73
|
-
}
|
|
74
|
-
catch (e) {
|
|
75
|
-
return Promise.reject(e);
|
|
76
|
-
}
|
|
70
|
+
connection.onRequest(Rpc.locateElement, ({ element, property }) => {
|
|
71
|
+
return modelLocator.locateElement(element, property ?? 'name');
|
|
77
72
|
});
|
|
78
|
-
connection.onRequest(Rpc.locateRelation, ({ id }
|
|
79
|
-
|
|
80
|
-
return Promise.resolve(modelLocator.locateRelation(id));
|
|
81
|
-
}
|
|
82
|
-
catch (e) {
|
|
83
|
-
return Promise.reject(e);
|
|
84
|
-
}
|
|
73
|
+
connection.onRequest(Rpc.locateRelation, ({ id }) => {
|
|
74
|
+
return modelLocator.locateRelation(id);
|
|
85
75
|
});
|
|
86
|
-
connection.onRequest(Rpc.locateView, ({ id }
|
|
87
|
-
|
|
88
|
-
return Promise.resolve(modelLocator.locateView(id));
|
|
89
|
-
}
|
|
90
|
-
catch (e) {
|
|
91
|
-
return Promise.reject(e);
|
|
92
|
-
}
|
|
76
|
+
connection.onRequest(Rpc.locateView, ({ id }) => {
|
|
77
|
+
return modelLocator.locateView(id);
|
|
93
78
|
});
|
|
94
79
|
}
|
|
95
80
|
//# sourceMappingURL=registerProtocolHandlers.js.map
|