@likec4/language-server 0.8.0 → 0.18.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 +1 -1
- package/contrib/likec4.tmLanguage.json +1 -1
- package/dist/generated/ast.d.ts +5 -4
- package/dist/generated/ast.js +3 -4
- package/dist/generated/grammar.d.ts +2 -2
- package/dist/generated/grammar.js +37 -1
- package/dist/generated/module.d.ts +2 -2
- package/dist/generated/module.js +1 -2
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/lsp/SemanticTokenProvider.js +7 -43
- package/dist/{references → model}/fqn-computation.js +1 -1
- package/dist/model/fqn-index.d.ts +5 -4
- package/dist/model/fqn-index.js +20 -40
- package/dist/model/index.d.ts +1 -0
- package/dist/model/index.js +1 -0
- package/dist/model/model-builder.js +33 -26
- package/dist/model/model-locator.d.ts +1 -1
- package/dist/module.js +0 -4
- package/dist/protocol.d.ts +5 -6
- package/dist/protocol.js +5 -3
- package/dist/references/scope-computation.js +0 -2
- package/dist/registerProtocolHandlers.js +41 -11
- package/dist/validation/element.js +6 -0
- package/package.json +8 -21
- /package/dist/{references → model}/fqn-computation.d.ts +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// Monarch syntax highlighting for the likec4 language.
|
|
2
2
|
export default {
|
|
3
3
|
keywords: [
|
|
4
|
-
'BottomTop','LeftRight','RightLeft','TopBottom','autoLayout','browser','color','cylinder','description','element','exclude','extend','include','it','model','muted','of','person','primary','queue','rectangle','secondary','shape','specification','storage','style','tag','technology','this','title','view','views'
|
|
4
|
+
'BottomTop','LeftRight','RightLeft','TopBottom','amber','autoLayout','blue','browser','color','cylinder','description','element','exclude','extend','gray','green','include','indigo','it','mobile','model','muted','of','person','primary','queue','rectangle','red','secondary','shape','sky','slate','specification','storage','style','tag','technology','this','title','view','views'
|
|
5
5
|
],
|
|
6
6
|
operators: [
|
|
7
7
|
'*','->','.*'
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
},
|
|
13
13
|
{
|
|
14
14
|
"name": "keyword.control.likec4",
|
|
15
|
-
"match": "\\b(BottomTop|LeftRight|RightLeft|TopBottom|autoLayout|browser|color|cylinder|description|element|exclude|extend|include|it|model|muted|of|person|primary|queue|rectangle|secondary|shape|specification|storage|style|tag|technology|this|title|view|views)\\b"
|
|
15
|
+
"match": "\\b(BottomTop|LeftRight|RightLeft|TopBottom|amber|autoLayout|blue|browser|color|cylinder|description|element|exclude|extend|gray|green|include|indigo|it|mobile|model|muted|of|person|primary|queue|rectangle|red|secondary|shape|sky|slate|specification|storage|style|tag|technology|this|title|view|views)\\b"
|
|
16
16
|
},
|
|
17
17
|
{
|
|
18
18
|
"name": "string.quoted.double.likec4",
|
package/dist/generated/ast.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/******************************************************************************
|
|
2
|
-
* This file was generated by langium-cli 1.2.
|
|
2
|
+
* This file was generated by langium-cli 1.2.1.
|
|
3
3
|
* DO NOT EDIT MANUALLY!
|
|
4
4
|
******************************************************************************/
|
|
5
|
-
import { AstNode,
|
|
5
|
+
import type { AstNode, Reference, ReferenceInfo, TypeMetaData } from 'langium';
|
|
6
|
+
import { AbstractAstReflection } from 'langium';
|
|
6
7
|
export type AnyStringProperty = ElementStringProperty | RelationStringProperty | ViewProperty;
|
|
7
8
|
export declare const AnyStringProperty = "AnyStringProperty";
|
|
8
9
|
export declare function isAnyStringProperty(item: unknown): item is AnyStringProperty;
|
|
@@ -15,14 +16,14 @@ export declare function isElementExpression(item: unknown): item is ElementExpre
|
|
|
15
16
|
export type ElementProperty = ElementStringProperty | ElementStyleProperty;
|
|
16
17
|
export declare const ElementProperty = "ElementProperty";
|
|
17
18
|
export declare function isElementProperty(item: unknown): item is ElementProperty;
|
|
18
|
-
export type ElementShape = 'browser' | 'cylinder' | 'person' | 'queue' | 'rectangle' | 'storage';
|
|
19
|
+
export type ElementShape = 'browser' | 'cylinder' | 'mobile' | 'person' | 'queue' | 'rectangle' | 'storage';
|
|
19
20
|
export declare function isElementShape(item: unknown): item is ElementShape;
|
|
20
21
|
export type Expression = ElementExpression | InOutExpression | IncomingExpression | OutgoingExpression | RelationExpression;
|
|
21
22
|
export declare const Expression = "Expression";
|
|
22
23
|
export declare function isExpression(item: unknown): item is Expression;
|
|
23
24
|
export type Name = 'element' | 'model' | ElementShape | ThemeColor | string;
|
|
24
25
|
export declare function isName(item: unknown): item is Name;
|
|
25
|
-
export type ThemeColor = 'muted' | 'primary' | 'secondary';
|
|
26
|
+
export type ThemeColor = 'amber' | 'blue' | 'gray' | 'green' | 'indigo' | 'muted' | 'primary' | 'red' | 'secondary' | 'sky' | 'slate';
|
|
26
27
|
export declare function isThemeColor(item: unknown): item is ThemeColor;
|
|
27
28
|
export type View = ElementView;
|
|
28
29
|
export declare const View = "View";
|
package/dist/generated/ast.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/******************************************************************************
|
|
2
|
-
* This file was generated by langium-cli 1.2.
|
|
2
|
+
* This file was generated by langium-cli 1.2.1.
|
|
3
3
|
* DO NOT EDIT MANUALLY!
|
|
4
4
|
******************************************************************************/
|
|
5
|
-
/* eslint-disable */
|
|
6
5
|
import { AbstractAstReflection } from 'langium';
|
|
7
6
|
export const AnyStringProperty = 'AnyStringProperty';
|
|
8
7
|
export function isAnyStringProperty(item) {
|
|
@@ -21,7 +20,7 @@ export function isElementProperty(item) {
|
|
|
21
20
|
return reflection.isInstance(item, ElementProperty);
|
|
22
21
|
}
|
|
23
22
|
export function isElementShape(item) {
|
|
24
|
-
return item === 'rectangle' || item === 'person' || item === 'browser' || item === 'cylinder' || item === 'storage' || item === 'queue';
|
|
23
|
+
return item === 'rectangle' || item === 'person' || item === 'browser' || item === 'mobile' || item === 'cylinder' || item === 'storage' || item === 'queue';
|
|
25
24
|
}
|
|
26
25
|
export const Expression = 'Expression';
|
|
27
26
|
export function isExpression(item) {
|
|
@@ -31,7 +30,7 @@ export function isName(item) {
|
|
|
31
30
|
return isElementShape(item) || isThemeColor(item) || item === 'element' || item === 'model' || (typeof item === 'string' && (/((([^\W\d_])|(_))((([^\W\d_])|([0-9]))|(_))*)/.test(item)));
|
|
32
31
|
}
|
|
33
32
|
export function isThemeColor(item) {
|
|
34
|
-
return item === 'primary' || item === 'secondary' || item === 'muted';
|
|
33
|
+
return item === 'primary' || item === 'secondary' || item === 'muted' || item === 'slate' || item === 'blue' || item === 'indigo' || item === 'sky' || item === 'red' || item === 'gray' || item === 'green' || item === 'amber';
|
|
35
34
|
}
|
|
36
35
|
export const View = 'View';
|
|
37
36
|
export function isView(item) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/******************************************************************************
|
|
2
|
-
* This file was generated by langium-cli 1.2.
|
|
2
|
+
* This file was generated by langium-cli 1.2.1.
|
|
3
3
|
* DO NOT EDIT MANUALLY!
|
|
4
4
|
******************************************************************************/
|
|
5
|
-
import { Grammar } from 'langium';
|
|
5
|
+
import type { Grammar } from 'langium';
|
|
6
6
|
export declare const LikeC4Grammar: () => Grammar;
|
|
7
7
|
//# sourceMappingURL=grammar.d.ts.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/******************************************************************************
|
|
2
|
-
* This file was generated by langium-cli 1.2.
|
|
2
|
+
* This file was generated by langium-cli 1.2.1.
|
|
3
3
|
* DO NOT EDIT MANUALLY!
|
|
4
4
|
******************************************************************************/
|
|
5
5
|
import { loadGrammarFromJson } from 'langium';
|
|
@@ -2059,6 +2059,38 @@ export const LikeC4Grammar = () => loadedLikeC4Grammar ?? (loadedLikeC4Grammar =
|
|
|
2059
2059
|
{
|
|
2060
2060
|
"$type": "Keyword",
|
|
2061
2061
|
"value": "muted"
|
|
2062
|
+
},
|
|
2063
|
+
{
|
|
2064
|
+
"$type": "Keyword",
|
|
2065
|
+
"value": "slate"
|
|
2066
|
+
},
|
|
2067
|
+
{
|
|
2068
|
+
"$type": "Keyword",
|
|
2069
|
+
"value": "blue"
|
|
2070
|
+
},
|
|
2071
|
+
{
|
|
2072
|
+
"$type": "Keyword",
|
|
2073
|
+
"value": "indigo"
|
|
2074
|
+
},
|
|
2075
|
+
{
|
|
2076
|
+
"$type": "Keyword",
|
|
2077
|
+
"value": "sky"
|
|
2078
|
+
},
|
|
2079
|
+
{
|
|
2080
|
+
"$type": "Keyword",
|
|
2081
|
+
"value": "red"
|
|
2082
|
+
},
|
|
2083
|
+
{
|
|
2084
|
+
"$type": "Keyword",
|
|
2085
|
+
"value": "gray"
|
|
2086
|
+
},
|
|
2087
|
+
{
|
|
2088
|
+
"$type": "Keyword",
|
|
2089
|
+
"value": "green"
|
|
2090
|
+
},
|
|
2091
|
+
{
|
|
2092
|
+
"$type": "Keyword",
|
|
2093
|
+
"value": "amber"
|
|
2062
2094
|
}
|
|
2063
2095
|
]
|
|
2064
2096
|
},
|
|
@@ -2088,6 +2120,10 @@ export const LikeC4Grammar = () => loadedLikeC4Grammar ?? (loadedLikeC4Grammar =
|
|
|
2088
2120
|
"$type": "Keyword",
|
|
2089
2121
|
"value": "browser"
|
|
2090
2122
|
},
|
|
2123
|
+
{
|
|
2124
|
+
"$type": "Keyword",
|
|
2125
|
+
"value": "mobile"
|
|
2126
|
+
},
|
|
2091
2127
|
{
|
|
2092
2128
|
"$type": "Keyword",
|
|
2093
2129
|
"value": "cylinder"
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/******************************************************************************
|
|
2
|
-
* This file was generated by langium-cli 1.2.
|
|
2
|
+
* This file was generated by langium-cli 1.2.1.
|
|
3
3
|
* DO NOT EDIT MANUALLY!
|
|
4
4
|
******************************************************************************/
|
|
5
|
-
import { LangiumGeneratedServices, LangiumGeneratedSharedServices, LangiumSharedServices, LangiumServices, LanguageMetaData, Module, IParserConfig } from 'langium';
|
|
5
|
+
import type { LangiumGeneratedServices, LangiumGeneratedSharedServices, LangiumSharedServices, LangiumServices, LanguageMetaData, Module, IParserConfig } from 'langium';
|
|
6
6
|
export declare const LikeC4LanguageMetaData: LanguageMetaData;
|
|
7
7
|
export declare const parserConfig: IParserConfig;
|
|
8
8
|
export declare const LikeC4GeneratedSharedModule: Module<LangiumSharedServices, LangiumGeneratedSharedServices>;
|
package/dist/generated/module.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
/******************************************************************************
|
|
2
|
-
* This file was generated by langium-cli 1.2.
|
|
2
|
+
* This file was generated by langium-cli 1.2.1.
|
|
3
3
|
* DO NOT EDIT MANUALLY!
|
|
4
4
|
******************************************************************************/
|
|
5
|
-
import 'langium';
|
|
6
5
|
import { LikeC4AstReflection } from './ast';
|
|
7
6
|
import { LikeC4Grammar } from './grammar';
|
|
8
7
|
export const LikeC4LanguageMetaData = {
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -135,46 +135,9 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
135
135
|
if (ast.isElement(node)) {
|
|
136
136
|
return this.highlightAstElement(node, acceptor);
|
|
137
137
|
}
|
|
138
|
-
// if (ast.isExtendElement(node)) {
|
|
139
|
-
// keyword('extend')
|
|
140
|
-
// return
|
|
141
|
-
// }
|
|
142
|
-
// if (ast.isElementProperty(node) || ast.isRelationProperty(node) || ast.isViewProperty(node)) {
|
|
143
|
-
// acceptor({
|
|
144
|
-
// node,
|
|
145
|
-
// property: 'key',
|
|
146
|
-
// type: SemanticTokenTypes.property,
|
|
147
|
-
// modifier: [SemanticTokenModifiers.definition]
|
|
148
|
-
// })
|
|
149
|
-
// if ('value' in node) {
|
|
150
|
-
// acceptor({
|
|
151
|
-
// node,
|
|
152
|
-
// property: 'value',
|
|
153
|
-
// type: SemanticTokenTypes.string
|
|
154
|
-
// })
|
|
155
|
-
// }
|
|
156
|
-
// return
|
|
157
|
-
// }
|
|
158
138
|
if (ast.isView(node)) {
|
|
159
139
|
return this.highlightView(node, acceptor);
|
|
160
140
|
}
|
|
161
|
-
// if (ast.isDynamicViewSteps(node)) {
|
|
162
|
-
// keyword('steps')
|
|
163
|
-
// return
|
|
164
|
-
// }
|
|
165
|
-
// if (ast.isViewRuleAutoLayout(node)) {
|
|
166
|
-
// keyword('autoLayout')
|
|
167
|
-
// return
|
|
168
|
-
// }
|
|
169
|
-
// if (ast.isViewRuleStyle(node)) {
|
|
170
|
-
// keyword('style')
|
|
171
|
-
// return
|
|
172
|
-
// }
|
|
173
|
-
// if (ast.isViewRuleExpression(node)) {
|
|
174
|
-
// keyword(node.isInclude ? 'include' : 'exclude')
|
|
175
|
-
// return
|
|
176
|
-
// }
|
|
177
|
-
// //
|
|
178
141
|
}
|
|
179
142
|
highlightAstElement(node, acceptor) {
|
|
180
143
|
acceptor({
|
|
@@ -198,11 +161,17 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
198
161
|
}
|
|
199
162
|
}
|
|
200
163
|
highlightView(node, acceptor) {
|
|
164
|
+
acceptor({
|
|
165
|
+
node,
|
|
166
|
+
keyword: 'view',
|
|
167
|
+
type: SemanticTokenTypes.keyword
|
|
168
|
+
});
|
|
201
169
|
if (node.name) {
|
|
202
170
|
acceptor({
|
|
203
171
|
node,
|
|
204
172
|
property: 'name',
|
|
205
|
-
type: SemanticTokenTypes.variable
|
|
173
|
+
type: SemanticTokenTypes.variable,
|
|
174
|
+
modifier: [SemanticTokenModifiers.declaration]
|
|
206
175
|
});
|
|
207
176
|
}
|
|
208
177
|
if (node.viewOf) {
|
|
@@ -212,11 +181,6 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
|
|
|
212
181
|
type: SemanticTokenTypes.keyword
|
|
213
182
|
});
|
|
214
183
|
}
|
|
215
|
-
acceptor({
|
|
216
|
-
node,
|
|
217
|
-
keyword: 'view',
|
|
218
|
-
type: SemanticTokenTypes.keyword
|
|
219
|
-
});
|
|
220
184
|
}
|
|
221
185
|
}
|
|
222
186
|
//# sourceMappingURL=SemanticTokenProvider.js.map
|
|
@@ -5,11 +5,11 @@ import { isEmpty, isNil } from 'rambdax';
|
|
|
5
5
|
import { ElementOps, ast } from '../ast';
|
|
6
6
|
import { strictElementRefFqn } from '../elementRef';
|
|
7
7
|
export function computeDocumentFqn(document, services) {
|
|
8
|
+
const c4fqns = document.c4fqns = new MultiMap();
|
|
8
9
|
const { model } = document.parseResult.value;
|
|
9
10
|
if (!model?.elements) {
|
|
10
11
|
return;
|
|
11
12
|
}
|
|
12
|
-
const c4fqns = document.c4fqns = new MultiMap();
|
|
13
13
|
const locator = services.workspace.AstNodeLocator;
|
|
14
14
|
const traverseStack = model.elements.map(el => [el, null]);
|
|
15
15
|
let pair;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
+
import type { Fqn } from '@likec4/core/types';
|
|
2
|
+
import type { LangiumDocuments } from 'langium';
|
|
1
3
|
import { DocumentState, MultiMap, StreamImpl } from 'langium';
|
|
2
|
-
import type {
|
|
4
|
+
import type { SetNonNullable } from 'type-fest';
|
|
3
5
|
import type { ast } from '../ast';
|
|
4
6
|
import { type LikeC4LangiumDocument } from '../ast';
|
|
5
7
|
import type { LikeC4Services } from '../module';
|
|
6
|
-
import type { Fqn } from '@likec4/core/types';
|
|
7
|
-
import type { SetNonNullable } from 'type-fest';
|
|
8
8
|
export interface FqnIndexEntry {
|
|
9
9
|
fqn: Fqn;
|
|
10
10
|
name: string;
|
|
@@ -13,6 +13,7 @@ export interface FqnIndexEntry {
|
|
|
13
13
|
}
|
|
14
14
|
export declare class FqnIndex {
|
|
15
15
|
private services;
|
|
16
|
+
protected langiumDocuments: LangiumDocuments;
|
|
16
17
|
constructor(services: LikeC4Services);
|
|
17
18
|
private documents;
|
|
18
19
|
private entries;
|
|
@@ -25,7 +26,7 @@ export declare class FqnIndex {
|
|
|
25
26
|
c4Elements: import("../ast").ParsedAstElement[];
|
|
26
27
|
c4Relations: import("../ast").ParsedAstRelation[];
|
|
27
28
|
c4Views: import("../ast").ParsedAstElementView[];
|
|
28
|
-
readonly uri: URI;
|
|
29
|
+
readonly uri: import("vscode-uri").URI;
|
|
29
30
|
readonly textDocument: import("vscode-languageserver-textdocument").TextDocument;
|
|
30
31
|
state: DocumentState;
|
|
31
32
|
parseResult: import("langium").ParseResult<ast.LikeC4Document>;
|
package/dist/model/fqn-index.js
CHANGED
|
@@ -1,59 +1,39 @@
|
|
|
1
|
+
import { nameFromFqn, parentFqn } from '@likec4/core/utils';
|
|
1
2
|
import { DocumentState, DONE_RESULT, getDocument, MultiMap, StreamImpl } from 'langium';
|
|
3
|
+
import { isNil } from 'rambdax';
|
|
2
4
|
import { ElementOps, isLikeC4LangiumDocument } from '../ast';
|
|
3
5
|
import { logger } from '../logger';
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
import { isNil } from 'rambdax';
|
|
7
|
-
import '../generated/ast';
|
|
8
|
-
const isFqnIndexedDocument = (doc) => isLikeC4LangiumDocument(doc) && doc.state >= DocumentState.ComputedScopes && !isNil(doc.c4fqns);
|
|
6
|
+
import { computeDocumentFqn } from './fqn-computation';
|
|
7
|
+
const isFqnIndexedDocument = (doc) => isLikeC4LangiumDocument(doc) && doc.state >= DocumentState.IndexedContent && !isNil(doc.c4fqns);
|
|
9
8
|
export class FqnIndex {
|
|
10
9
|
services;
|
|
11
|
-
|
|
12
|
-
// protected readonly descriptions: AstNodeDescriptionProvider
|
|
10
|
+
langiumDocuments;
|
|
13
11
|
constructor(services) {
|
|
14
12
|
this.services = services;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
// }
|
|
29
|
-
// )
|
|
13
|
+
this.langiumDocuments = services.shared.workspace.LangiumDocuments;
|
|
14
|
+
services.shared.workspace.DocumentBuilder.onBuildPhase(DocumentState.IndexedContent, (docs, _cancelToken) => {
|
|
15
|
+
for (const doc of docs) {
|
|
16
|
+
if (isLikeC4LangiumDocument(doc)) {
|
|
17
|
+
try {
|
|
18
|
+
computeDocumentFqn(doc, services);
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
logger.error(e);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
});
|
|
30
26
|
}
|
|
31
27
|
documents() {
|
|
32
|
-
return this.
|
|
28
|
+
return this.langiumDocuments.all.filter(isFqnIndexedDocument);
|
|
33
29
|
}
|
|
34
30
|
entries() {
|
|
35
31
|
return this.documents().flatMap(doc => doc.c4fqns.entries().map(([fqn, path]) => ({ fqn, path, doc })));
|
|
36
32
|
}
|
|
37
|
-
// private index() {
|
|
38
|
-
// const index = new MultiMap<Fqn, {
|
|
39
|
-
// path: string,
|
|
40
|
-
// doc: LikeC4LangiumDocument
|
|
41
|
-
// }>()
|
|
42
|
-
// this.entries().toMap()
|
|
43
|
-
// this.entries().forEach(({ fqn, path, doc }) => {
|
|
44
|
-
// index.add(fqn, { path, doc })
|
|
45
|
-
// })
|
|
46
|
-
// // for (const doc of this.documents()) {
|
|
47
|
-
// // doc.c4fqns.entries().forEach(([fqn, path]) => {
|
|
48
|
-
// // index.add(fqn, { path, doc })
|
|
49
|
-
// // })
|
|
50
|
-
// // }
|
|
51
|
-
// return index
|
|
52
|
-
// }
|
|
53
33
|
get(el) {
|
|
54
34
|
let fqn = ElementOps.readId(el) ?? null;
|
|
55
|
-
const doc = getDocument(el);
|
|
56
35
|
if (fqn) {
|
|
36
|
+
const doc = getDocument(el);
|
|
57
37
|
if (isFqnIndexedDocument(doc) && doc.c4fqns.has(fqn)) {
|
|
58
38
|
return fqn;
|
|
59
39
|
}
|
package/dist/model/index.d.ts
CHANGED
package/dist/model/index.js
CHANGED
|
@@ -2,12 +2,11 @@ import { computeViews } from '@likec4/core/compute-view';
|
|
|
2
2
|
import { DefaultElementShape, DefaultThemeColor } from '@likec4/core/types';
|
|
3
3
|
import { compareByFqnHierarchically, parentFqn } from '@likec4/core/utils';
|
|
4
4
|
import { A, O, flow, pipe } from '@mobily/ts-belt';
|
|
5
|
-
import { DocumentState, getDocument
|
|
5
|
+
import { DocumentState, getDocument } from 'langium';
|
|
6
6
|
import objectHash from 'object-hash';
|
|
7
|
-
import { clone, isNil, mergeDeepRight,
|
|
7
|
+
import { clone, isNil, mergeDeepRight, reduce } from 'rambdax';
|
|
8
8
|
import invariant from 'tiny-invariant';
|
|
9
|
-
import { toAutoLayout } from '../ast';
|
|
10
|
-
import { ElementViewOps, ast, c4hash, cleanParsedModel, isLikeC4LangiumDocument, isParsedLikeC4LangiumDocument, resolveRelationPoints, streamModel, toElementStyle } from '../ast';
|
|
9
|
+
import { ElementViewOps, ast, c4hash, cleanParsedModel, isLikeC4LangiumDocument, isParsedLikeC4LangiumDocument, resolveRelationPoints, streamModel, toAutoLayout, toElementStyle } from '../ast';
|
|
11
10
|
import { elementRef, strictElementRefFqn } from '../elementRef';
|
|
12
11
|
import { logger } from '../logger';
|
|
13
12
|
import { Rpc } from '../protocol';
|
|
@@ -20,26 +19,24 @@ export class LikeC4ModelBuilder {
|
|
|
20
19
|
this.services = services;
|
|
21
20
|
this.fqnIndex = services.likec4.FqnIndex;
|
|
22
21
|
this.langiumDocuments = services.shared.workspace.LangiumDocuments;
|
|
23
|
-
services.shared.workspace.DocumentBuilder.onBuildPhase(DocumentState.Validated,
|
|
22
|
+
services.shared.workspace.DocumentBuilder.onBuildPhase(DocumentState.Validated, (docs, cancelToken) => {
|
|
24
23
|
let countOfChangedDocs = 0;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
33
|
-
catch (e) {
|
|
34
|
-
logger.warn(`Error parsing document ${doc.uri.toString()}`);
|
|
24
|
+
for (const doc of docs) {
|
|
25
|
+
if (cancelToken.isCancellationRequested) {
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
if (isLikeC4LangiumDocument(doc) && this.parseDocument(doc)) {
|
|
30
|
+
countOfChangedDocs++;
|
|
35
31
|
}
|
|
36
32
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (countOfChangedDocs > 0 && !cancelToken.isCancellationRequested) {
|
|
40
|
-
await this.notifyClient();
|
|
33
|
+
catch (e) {
|
|
34
|
+
logger.warn(`Error parsing document ${doc.uri.toString()}`);
|
|
41
35
|
}
|
|
42
36
|
}
|
|
37
|
+
if (countOfChangedDocs > 0 && !cancelToken.isCancellationRequested) {
|
|
38
|
+
void this.notifyClient();
|
|
39
|
+
}
|
|
43
40
|
});
|
|
44
41
|
}
|
|
45
42
|
get connection() {
|
|
@@ -51,8 +48,10 @@ export class LikeC4ModelBuilder {
|
|
|
51
48
|
buildModel() {
|
|
52
49
|
const docs = this.documents();
|
|
53
50
|
if (docs.length === 0) {
|
|
51
|
+
logger.debug('No documents to build model from');
|
|
54
52
|
return;
|
|
55
53
|
}
|
|
54
|
+
// TODO:
|
|
56
55
|
try {
|
|
57
56
|
const c4Specification = reduce((acc, doc) => mergeDeepRight(acc, doc.c4Specification), {
|
|
58
57
|
kinds: {}
|
|
@@ -65,22 +64,25 @@ export class LikeC4ModelBuilder {
|
|
|
65
64
|
const toModelElement = (el) => {
|
|
66
65
|
const kind = c4Specification.kinds[el.kind];
|
|
67
66
|
if (kind) {
|
|
67
|
+
const { astPath, ...model } = el;
|
|
68
68
|
return {
|
|
69
69
|
...(kind.shape !== DefaultElementShape ? { shape: kind.shape } : {}),
|
|
70
70
|
...(kind.color !== DefaultThemeColor ? { color: kind.color } : {}),
|
|
71
|
-
...
|
|
71
|
+
...model
|
|
72
72
|
};
|
|
73
73
|
}
|
|
74
74
|
return null;
|
|
75
75
|
};
|
|
76
76
|
const toModelRelation = (rel) => {
|
|
77
|
-
|
|
77
|
+
const { astPath, ...model } = rel;
|
|
78
|
+
return model;
|
|
78
79
|
};
|
|
79
80
|
const elements = pipe(docs.flatMap(d => d.c4Elements), A.filterMap(flow(toModelElement, O.fromNullable)), A.sort(compareByFqnHierarchically), A.reduce({}, (acc, el) => {
|
|
80
81
|
const parent = parentFqn(el.id);
|
|
81
82
|
if (!parent || parent in acc) {
|
|
82
83
|
if (el.id in acc) {
|
|
83
84
|
logger.warn(`Duplicate element id: ${el.id}`);
|
|
85
|
+
return acc;
|
|
84
86
|
}
|
|
85
87
|
acc[el.id] = el;
|
|
86
88
|
}
|
|
@@ -89,24 +91,30 @@ export class LikeC4ModelBuilder {
|
|
|
89
91
|
const relations = pipe(docs.flatMap(d => d.c4Relations), A.filterMap(flow(toModelRelation, O.fromPredicate(({ source, target }) => source in elements && target in elements))), A.reduce({}, (acc, el) => {
|
|
90
92
|
if (el.id in acc) {
|
|
91
93
|
logger.warn(`Duplicate relation id: ${el.id}`);
|
|
94
|
+
return acc;
|
|
92
95
|
}
|
|
93
96
|
acc[el.id] = el;
|
|
94
97
|
return acc;
|
|
95
98
|
}));
|
|
96
99
|
const toModelView = (view) => {
|
|
97
|
-
|
|
100
|
+
// eslint-disable-next-line prefer-const
|
|
101
|
+
let { astPath, rules, title, ...model } = view;
|
|
98
102
|
if (!title && view.viewOf) {
|
|
99
103
|
title = elements[view.viewOf]?.title;
|
|
100
104
|
}
|
|
105
|
+
if (!title && view.id === 'index') {
|
|
106
|
+
title = 'Landscape view';
|
|
107
|
+
}
|
|
101
108
|
return {
|
|
102
|
-
...
|
|
103
|
-
...(
|
|
104
|
-
rules: clone(
|
|
109
|
+
...model,
|
|
110
|
+
...(title && { title }),
|
|
111
|
+
rules: clone(rules)
|
|
105
112
|
};
|
|
106
113
|
};
|
|
107
114
|
const views = pipe(docs.flatMap(d => d.c4Views), A.filterMap(flow(toModelView, O.fromPredicate(v => isNil(v.viewOf) || v.viewOf in elements))), A.reduce({}, (acc, v) => {
|
|
108
115
|
if (v.id in acc) {
|
|
109
116
|
logger.warn(`Duplicate view id: ${v.id}`);
|
|
117
|
+
return acc;
|
|
110
118
|
}
|
|
111
119
|
acc[v.id] = v;
|
|
112
120
|
return acc;
|
|
@@ -332,7 +340,6 @@ export class LikeC4ModelBuilder {
|
|
|
332
340
|
if (!connection) {
|
|
333
341
|
return;
|
|
334
342
|
}
|
|
335
|
-
logger.debug('Send onDidChangeModel');
|
|
336
343
|
await connection.sendNotification(Rpc.onDidChangeModel);
|
|
337
344
|
}
|
|
338
345
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type * as c4 from '@likec4/core/types';
|
|
2
|
-
import type { Location } from 'vscode-languageserver';
|
|
2
|
+
import type { Location } from 'vscode-languageserver-protocol';
|
|
3
3
|
import type { ParsedAstElement } from '../ast';
|
|
4
4
|
import { ast } from '../ast';
|
|
5
5
|
import type { LikeC4Services } from '../module';
|
package/dist/module.js
CHANGED
|
@@ -14,10 +14,6 @@ export const LikeC4Module = {
|
|
|
14
14
|
FqnIndex: bind(FqnIndex),
|
|
15
15
|
ModelBuilder: bind(LikeC4ModelBuilder),
|
|
16
16
|
ModelLocator: bind(LikeC4ModelLocator)
|
|
17
|
-
// Model: bind(LikeC4Model),
|
|
18
|
-
// Model: bind(LikeC4Model),
|
|
19
|
-
// SpecIndex: bind(LikeC4SpecIndex),
|
|
20
|
-
// Validator: bind(LikeC4Validator)
|
|
21
17
|
},
|
|
22
18
|
lsp: {
|
|
23
19
|
DocumentSymbolProvider: bind(LikeC4DocumentSymbolProvider),
|
package/dist/protocol.d.ts
CHANGED
|
@@ -1,14 +1,9 @@
|
|
|
1
1
|
import type { Fqn, LikeC4Model, RelationID, ViewID } from '@likec4/core';
|
|
2
2
|
import type { DocumentUri, Location } from 'vscode-languageserver-protocol';
|
|
3
3
|
import { NotificationType0, RequestType0, RequestType } from 'vscode-languageserver-protocol';
|
|
4
|
-
|
|
5
|
-
export declare const fetchModel: RequestType0<{
|
|
6
|
-
model: LikeC4Model | null;
|
|
7
|
-
}, void>;
|
|
8
|
-
export interface BuildDocumentsParams {
|
|
4
|
+
interface BuildDocumentsParams {
|
|
9
5
|
docs: DocumentUri[];
|
|
10
6
|
}
|
|
11
|
-
export declare const buildDocuments: RequestType<BuildDocumentsParams, void, void>;
|
|
12
7
|
export interface LocateElementParams {
|
|
13
8
|
element: Fqn;
|
|
14
9
|
property?: string;
|
|
@@ -25,6 +20,9 @@ export declare const Rpc: {
|
|
|
25
20
|
readonly fetchModel: RequestType0<{
|
|
26
21
|
model: LikeC4Model | null;
|
|
27
22
|
}, void>;
|
|
23
|
+
readonly rebuild: RequestType0<{
|
|
24
|
+
docs: DocumentUri[];
|
|
25
|
+
}, void>;
|
|
28
26
|
readonly buildDocuments: RequestType<BuildDocumentsParams, void, void>;
|
|
29
27
|
readonly locateElement: RequestType<LocateElementParams, Location | null, void>;
|
|
30
28
|
readonly locateRelation: RequestType<{
|
|
@@ -34,4 +32,5 @@ export declare const Rpc: {
|
|
|
34
32
|
id: ViewID;
|
|
35
33
|
}, Location | null, void>;
|
|
36
34
|
};
|
|
35
|
+
export {};
|
|
37
36
|
//# sourceMappingURL=protocol.d.ts.map
|
package/dist/protocol.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { NotificationType0, RequestType0, RequestType } from 'vscode-languageserver-protocol';
|
|
2
2
|
//#region From server
|
|
3
|
-
|
|
3
|
+
const onDidChangeModel = new NotificationType0('likec4/onDidChangeModel');
|
|
4
4
|
//#endregion
|
|
5
5
|
//#region To server
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const fetchModel = new RequestType0('likec4/fetchModel');
|
|
7
|
+
const rebuild = new RequestType0('likec4/rebuildModel');
|
|
8
|
+
const buildDocuments = new RequestType('likec4/buildDocuments');
|
|
8
9
|
export const locateElement = new RequestType('likec4/locateElement');
|
|
9
10
|
export const locateRelation = new RequestType('likec4/locateRelation');
|
|
10
11
|
export const locateView = new RequestType('likec4/locateView');
|
|
@@ -12,6 +13,7 @@ export const locateView = new RequestType('likec4/locateView');
|
|
|
12
13
|
export const Rpc = {
|
|
13
14
|
onDidChangeModel,
|
|
14
15
|
fetchModel,
|
|
16
|
+
rebuild,
|
|
15
17
|
buildDocuments,
|
|
16
18
|
locateElement,
|
|
17
19
|
locateRelation,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { DefaultScopeComputation, MultiMap } from 'langium';
|
|
2
2
|
import { ast } from '../ast';
|
|
3
|
-
import { computeDocumentFqn } from './fqn-computation';
|
|
4
3
|
export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
5
4
|
services;
|
|
6
5
|
constructor(services) {
|
|
@@ -26,7 +25,6 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
26
25
|
docExports.push(this.descriptions.createDescription(elAst, elAst.name, document));
|
|
27
26
|
}
|
|
28
27
|
}
|
|
29
|
-
computeDocumentFqn(document, this.services);
|
|
30
28
|
}
|
|
31
29
|
// const c4fqns = document.c4fqns
|
|
32
30
|
// logger.debug(`doc ${document.uri.path}:
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { URI } from 'vscode-uri';
|
|
1
2
|
import { logger } from './logger';
|
|
2
3
|
import { Rpc } from './protocol';
|
|
3
4
|
export function registerProtocolHandlers(services) {
|
|
@@ -17,24 +18,53 @@ export function registerProtocolHandlers(services) {
|
|
|
17
18
|
model = null;
|
|
18
19
|
logger.error(e);
|
|
19
20
|
}
|
|
20
|
-
return Promise.resolve({
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
return Promise.resolve({ model });
|
|
22
|
+
});
|
|
23
|
+
connection.onRequest(Rpc.rebuild, async (cancelToken) => {
|
|
24
|
+
const changed = LangiumDocuments.all.map(d => d.uri).toArray();
|
|
25
|
+
logger.debug(`Rebuild all documents: [
|
|
26
|
+
${changed.map(d => d.toString()).join('\n ')}
|
|
27
|
+
]`);
|
|
28
|
+
await services.shared.workspace.DocumentBuilder.update(changed, [], cancelToken);
|
|
29
|
+
return {
|
|
30
|
+
docs: changed.map(d => d.toString())
|
|
31
|
+
};
|
|
23
32
|
});
|
|
24
33
|
connection.onRequest(Rpc.buildDocuments, async ({ docs }, cancelToken) => {
|
|
34
|
+
if (docs.length === 0) {
|
|
35
|
+
logger.debug(`Received empty request to rebuild`);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
logger.debug(`Received request to rebuild: [
|
|
39
|
+
${docs.join('\n ')}
|
|
40
|
+
]`);
|
|
25
41
|
const changed = [];
|
|
26
42
|
for (const d of docs) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
43
|
+
try {
|
|
44
|
+
const uri = URI.parse(d);
|
|
45
|
+
if (LangiumDocuments.hasDocument(uri)) {
|
|
46
|
+
changed.push(uri);
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
logger.warn(`LangiumDocuments does not have document: ${d}`);
|
|
50
|
+
LangiumDocuments.getOrCreateDocument(uri);
|
|
51
|
+
}
|
|
30
52
|
}
|
|
31
|
-
|
|
32
|
-
logger.error(
|
|
53
|
+
catch (e) {
|
|
54
|
+
logger.error(e);
|
|
33
55
|
}
|
|
34
56
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
57
|
+
if (changed.length !== docs.length) {
|
|
58
|
+
const all = LangiumDocuments.all.map(d => d.uri.toString()).toArray();
|
|
59
|
+
logger.warn(`
|
|
60
|
+
We have in LangiumDocuments: [
|
|
61
|
+
${all.join('\n ')}
|
|
62
|
+
]
|
|
63
|
+
We rebuild: [
|
|
64
|
+
${changed.join('\n ')}
|
|
65
|
+
]
|
|
66
|
+
`.trim());
|
|
67
|
+
}
|
|
38
68
|
await services.shared.workspace.DocumentBuilder.update(changed, [], cancelToken);
|
|
39
69
|
});
|
|
40
70
|
connection.onRequest(Rpc.locateElement, async ({ element, property }, _cancelToken) => {
|
|
@@ -11,6 +11,12 @@ export const elementChecks = (services) => {
|
|
|
11
11
|
}
|
|
12
12
|
const withSameFqn = fqnIndex.byFqn(fqn).limit(2).count();
|
|
13
13
|
if (withSameFqn > 1) {
|
|
14
|
+
// console.error(withSameFqn.map(e => ({
|
|
15
|
+
// fqn,
|
|
16
|
+
// name: el.name,
|
|
17
|
+
// path: e.path,
|
|
18
|
+
// doc: e.doc.uri.toString()
|
|
19
|
+
// })))
|
|
14
20
|
accept('error', `Duplicate element name ${el.name !== fqn ? el.name + ' (' + fqn + ')' : el.name}`, {
|
|
15
21
|
node: el,
|
|
16
22
|
property: 'name'
|
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.18.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bugs": "https://github.com/likec4/likec4/issues",
|
|
7
7
|
"homepage": "https://likec4.dev",
|
|
@@ -11,8 +11,7 @@
|
|
|
11
11
|
"contrib",
|
|
12
12
|
"!**/__mocks__/",
|
|
13
13
|
"!**/__test__/",
|
|
14
|
-
"!**/*.spec
|
|
15
|
-
"!**/*.spec.d.ts",
|
|
14
|
+
"!**/*.spec.*",
|
|
16
15
|
"!**/*.map"
|
|
17
16
|
],
|
|
18
17
|
"repository": {
|
|
@@ -29,11 +28,6 @@
|
|
|
29
28
|
"types": "./dist/index.d.ts",
|
|
30
29
|
"import": "./dist/index.js",
|
|
31
30
|
"require": "./dist/index.js"
|
|
32
|
-
},
|
|
33
|
-
"./builtin": {
|
|
34
|
-
"types": "./dist/builtin.d.ts",
|
|
35
|
-
"import": "./dist/builtin.js",
|
|
36
|
-
"require": "./dist/builtin.js"
|
|
37
31
|
}
|
|
38
32
|
},
|
|
39
33
|
"publishConfig": {
|
|
@@ -47,11 +41,6 @@
|
|
|
47
41
|
"types": "./dist/index.d.ts",
|
|
48
42
|
"import": "./dist/index.js",
|
|
49
43
|
"require": "./dist/index.js"
|
|
50
|
-
},
|
|
51
|
-
"./builtin": {
|
|
52
|
-
"types": "./dist/builtin.d.ts",
|
|
53
|
-
"import": "./dist/builtin.js",
|
|
54
|
-
"require": "./dist/builtin.js"
|
|
55
44
|
}
|
|
56
45
|
}
|
|
57
46
|
},
|
|
@@ -65,11 +54,11 @@
|
|
|
65
54
|
"dev": "run-p 'watch:*'",
|
|
66
55
|
"lint": "run -T eslint src/ --fix",
|
|
67
56
|
"clean": "run -T rimraf dist contrib",
|
|
68
|
-
"test": "vitest run",
|
|
69
|
-
"test:watch": "vitest"
|
|
57
|
+
"test": "run -T vitest run",
|
|
58
|
+
"test:watch": "run -T vitest"
|
|
70
59
|
},
|
|
71
60
|
"dependencies": {
|
|
72
|
-
"@likec4/core": "0.
|
|
61
|
+
"@likec4/core": "0.18.0",
|
|
73
62
|
"@mobily/ts-belt": "^3.13.1",
|
|
74
63
|
"langium": "^1.2.0",
|
|
75
64
|
"nanoid": "^4.0.2",
|
|
@@ -77,17 +66,15 @@
|
|
|
77
66
|
"rambdax": "^9.1.1",
|
|
78
67
|
"strip-indent": "^4.0.0",
|
|
79
68
|
"tiny-invariant": "^1.3.1",
|
|
80
|
-
"type-fest": "^3.
|
|
69
|
+
"type-fest": "^3.11.1",
|
|
81
70
|
"vscode-languageserver": "~8.1.0",
|
|
82
71
|
"vscode-languageserver-protocol": "~3.17.3"
|
|
83
72
|
},
|
|
84
73
|
"devDependencies": {
|
|
85
74
|
"@types/node": "^18.15.11",
|
|
86
75
|
"@types/object-hash": "^3.0.2",
|
|
87
|
-
"langium-cli": "^1.2.
|
|
76
|
+
"langium-cli": "^1.2.1",
|
|
88
77
|
"npm-run-all": "^4.1.5",
|
|
89
|
-
"typescript": "^5.
|
|
90
|
-
"vite": "^4.3.3",
|
|
91
|
-
"vitest": "^0.31.0"
|
|
78
|
+
"typescript": "^5.1.3"
|
|
92
79
|
}
|
|
93
80
|
}
|
|
File without changes
|