@likec4/language-server 0.34.0 → 0.36.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/ast.d.ts +1 -1
- package/dist/ast.js +1 -1
- package/dist/generated/ast.d.ts +3 -2
- package/dist/generated/ast.js +3 -2
- package/dist/generated/grammar.d.ts +1 -1
- package/dist/generated/grammar.js +17 -12
- package/dist/generated/module.d.ts +1 -1
- package/dist/generated/module.js +1 -1
- package/dist/logger.js +3 -2
- package/dist/lsp/DocumentSymbolProvider.js +2 -2
- package/dist/model/fqn-computation.js +1 -1
- package/dist/model/fqn-index.d.ts +1 -1
- package/dist/model/fqn-index.js +17 -2
- package/dist/model/model-locator.js +19 -20
- package/dist/model/model-parser.js +14 -2
- package/dist/references/scope-computation.d.ts +0 -3
- package/dist/references/scope-computation.js +7 -12
- package/dist/references/scope-provider.js +8 -1
- package/dist/registerProtocolHandlers.js +14 -1
- package/dist/validation/element.js +7 -0
- package/dist/validation/relation.d.ts +1 -1
- package/dist/validation/relation.js +29 -16
- package/package.json +8 -7
package/dist/ast.d.ts
CHANGED
package/dist/ast.js
CHANGED
|
@@ -119,7 +119,7 @@ export function resolveRelationPoints(node) {
|
|
|
119
119
|
};
|
|
120
120
|
}
|
|
121
121
|
if (!ast.isElementBody(node.$container)) {
|
|
122
|
-
throw new RelationRefError('Invalid relation parent');
|
|
122
|
+
throw new RelationRefError('Invalid relation parent, expected Element');
|
|
123
123
|
}
|
|
124
124
|
return {
|
|
125
125
|
source: node.$container.$container,
|
package/dist/generated/ast.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/******************************************************************************
|
|
2
|
-
* This file was generated by langium-cli 2.0.
|
|
2
|
+
* This file was generated by langium-cli 2.0.1.
|
|
3
3
|
* DO NOT EDIT MANUALLY!
|
|
4
4
|
******************************************************************************/
|
|
5
5
|
import type { AstNode, Reference, ReferenceInfo, TypeMetaData } from 'langium';
|
|
@@ -269,8 +269,9 @@ export declare function isSpecificationElementKind(item: unknown): item is Speci
|
|
|
269
269
|
export interface SpecificationRule extends AstNode {
|
|
270
270
|
readonly $container: LikeC4Document;
|
|
271
271
|
readonly $type: 'SpecificationRule';
|
|
272
|
+
elements: Array<SpecificationElementKind>;
|
|
272
273
|
name: 'specification';
|
|
273
|
-
|
|
274
|
+
tags: Array<SpecificationTag>;
|
|
274
275
|
}
|
|
275
276
|
export declare const SpecificationRule = "SpecificationRule";
|
|
276
277
|
export declare function isSpecificationRule(item: unknown): item is SpecificationRule;
|
package/dist/generated/ast.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/******************************************************************************
|
|
2
|
-
* This file was generated by langium-cli 2.0.
|
|
2
|
+
* This file was generated by langium-cli 2.0.1.
|
|
3
3
|
* DO NOT EDIT MANUALLY!
|
|
4
4
|
******************************************************************************/
|
|
5
5
|
import { AbstractAstReflection } from 'langium';
|
|
@@ -352,7 +352,8 @@ export class LikeC4AstReflection extends AbstractAstReflection {
|
|
|
352
352
|
return {
|
|
353
353
|
name: 'SpecificationRule',
|
|
354
354
|
mandatory: [
|
|
355
|
-
{ name: '
|
|
355
|
+
{ name: 'elements', type: 'array' },
|
|
356
|
+
{ name: 'tags', type: 'array' }
|
|
356
357
|
]
|
|
357
358
|
};
|
|
358
359
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/******************************************************************************
|
|
2
|
-
* This file was generated by langium-cli 2.0.
|
|
2
|
+
* This file was generated by langium-cli 2.0.1.
|
|
3
3
|
* DO NOT EDIT MANUALLY!
|
|
4
4
|
******************************************************************************/
|
|
5
5
|
import type { Grammar } from 'langium';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/******************************************************************************
|
|
2
|
-
* This file was generated by langium-cli 2.0.
|
|
2
|
+
* This file was generated by langium-cli 2.0.1.
|
|
3
3
|
* DO NOT EDIT MANUALLY!
|
|
4
4
|
******************************************************************************/
|
|
5
5
|
import { loadGrammarFromJson } from 'langium';
|
|
@@ -130,28 +130,33 @@ export const LikeC4Grammar = () => loadedLikeC4Grammar ?? (loadedLikeC4Grammar =
|
|
|
130
130
|
"arguments": []
|
|
131
131
|
},
|
|
132
132
|
{
|
|
133
|
-
"$type": "
|
|
134
|
-
"
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
{
|
|
133
|
+
"$type": "Alternatives",
|
|
134
|
+
"elements": [
|
|
135
|
+
{
|
|
136
|
+
"$type": "Assignment",
|
|
137
|
+
"feature": "elements",
|
|
138
|
+
"operator": "+=",
|
|
139
|
+
"terminal": {
|
|
140
140
|
"$type": "RuleCall",
|
|
141
141
|
"rule": {
|
|
142
142
|
"$ref": "#/rules@4"
|
|
143
143
|
},
|
|
144
144
|
"arguments": []
|
|
145
|
-
}
|
|
146
|
-
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"$type": "Assignment",
|
|
149
|
+
"feature": "tags",
|
|
150
|
+
"operator": "+=",
|
|
151
|
+
"terminal": {
|
|
147
152
|
"$type": "RuleCall",
|
|
148
153
|
"rule": {
|
|
149
154
|
"$ref": "#/rules@5"
|
|
150
155
|
},
|
|
151
156
|
"arguments": []
|
|
152
157
|
}
|
|
153
|
-
|
|
154
|
-
|
|
158
|
+
}
|
|
159
|
+
],
|
|
155
160
|
"cardinality": "*"
|
|
156
161
|
},
|
|
157
162
|
{
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/******************************************************************************
|
|
2
|
-
* This file was generated by langium-cli 2.0.
|
|
2
|
+
* This file was generated by langium-cli 2.0.1.
|
|
3
3
|
* DO NOT EDIT MANUALLY!
|
|
4
4
|
******************************************************************************/
|
|
5
5
|
import type { LangiumGeneratedServices, LangiumGeneratedSharedServices, LangiumSharedServices, LangiumServices, Module, IParserConfig } from 'langium';
|
package/dist/generated/module.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/******************************************************************************
|
|
2
|
-
* This file was generated by langium-cli 2.0.
|
|
2
|
+
* This file was generated by langium-cli 2.0.1.
|
|
3
3
|
* DO NOT EDIT MANUALLY!
|
|
4
4
|
******************************************************************************/
|
|
5
5
|
import { LikeC4AstReflection } from './ast.js';
|
package/dist/logger.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
2
|
-
import { normalizeError
|
|
2
|
+
import { normalizeError } from '@likec4/core';
|
|
3
3
|
/* eslint-disable @typescript-eslint/no-redundant-type-constituents */
|
|
4
4
|
let isSilent = false;
|
|
5
5
|
export const logger = {
|
|
@@ -44,6 +44,7 @@ export function logWarnError(err) {
|
|
|
44
44
|
logger.warn(err);
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
|
-
|
|
47
|
+
const error = normalizeError(err);
|
|
48
|
+
logger.warn(`${error.name}: ${error.message}`);
|
|
48
49
|
}
|
|
49
50
|
//# sourceMappingURL=logger.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { findNodeForProperty } from 'langium';
|
|
2
|
-
import { compact, isEmpty, map, pipe } from 'remeda';
|
|
2
|
+
import { compact, concat, isEmpty, map, pipe } from 'remeda';
|
|
3
3
|
import { SymbolKind } from 'vscode-languageserver-protocol';
|
|
4
4
|
import { ast } from '../ast';
|
|
5
5
|
import { logError } from '../logger';
|
|
@@ -68,7 +68,7 @@ export class LikeC4DocumentSymbolProvider {
|
|
|
68
68
|
const specKeywordNode = findNodeForProperty(cstModel, 'name');
|
|
69
69
|
if (!specKeywordNode)
|
|
70
70
|
return [];
|
|
71
|
-
const specSymbols = pipe(astSpec.
|
|
71
|
+
const specSymbols = pipe(concat(astSpec.elements, astSpec.tags), map(nd => {
|
|
72
72
|
if (ast.isSpecificationElementKind(nd)) {
|
|
73
73
|
return getElementKindSymbol(nd);
|
|
74
74
|
}
|
|
@@ -20,7 +20,7 @@ export declare class FqnIndex {
|
|
|
20
20
|
private documents;
|
|
21
21
|
private entries;
|
|
22
22
|
getFqn(el: ast.Element): Fqn | null;
|
|
23
|
-
byFqn(fqn: Fqn): Stream<
|
|
23
|
+
byFqn(fqn: Fqn): Stream<FqnIndexEntry>;
|
|
24
24
|
directChildrenOf(parent: Fqn): Stream<FqnIndexEntry>;
|
|
25
25
|
/**
|
|
26
26
|
* Returns descedant elements with unique names in the scope
|
package/dist/model/fqn-index.js
CHANGED
|
@@ -52,7 +52,16 @@ export class FqnIndex {
|
|
|
52
52
|
return this.langiumDocuments.all.filter(isFqnIndexedDocument);
|
|
53
53
|
}
|
|
54
54
|
entries() {
|
|
55
|
-
return this.documents().flatMap(doc => doc.c4fqns
|
|
55
|
+
return this.documents().flatMap(doc => doc.c4fqns
|
|
56
|
+
.entries()
|
|
57
|
+
.map(([fqn, entry]) => {
|
|
58
|
+
const el = entry.el.deref();
|
|
59
|
+
if (el) {
|
|
60
|
+
return { ...entry, fqn, el, doc };
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
})
|
|
64
|
+
.nonNullable());
|
|
56
65
|
}
|
|
57
66
|
getFqn(el) {
|
|
58
67
|
return el.fqn ?? ElementOps.readId(el) ?? null;
|
|
@@ -70,7 +79,13 @@ export class FqnIndex {
|
|
|
70
79
|
}
|
|
71
80
|
byFqn(fqn) {
|
|
72
81
|
return this.documents().flatMap(doc => {
|
|
73
|
-
return doc.c4fqns.get(fqn)
|
|
82
|
+
return doc.c4fqns.get(fqn).flatMap(entry => {
|
|
83
|
+
const el = entry.el.deref();
|
|
84
|
+
if (el) {
|
|
85
|
+
return [{ fqn, el, doc, path: entry.path, name: entry.name }];
|
|
86
|
+
}
|
|
87
|
+
return [];
|
|
88
|
+
});
|
|
74
89
|
});
|
|
75
90
|
}
|
|
76
91
|
directChildrenOf(parent) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
+
import { InvalidModelError } from '@likec4/core';
|
|
1
2
|
import { findNodeForProperty, getDocument } from 'langium';
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { nonNullable } from '@likec4/core';
|
|
3
|
+
import { ast, isParsedLikeC4LangiumDocument } from '../ast';
|
|
4
|
+
import {} from './fqn-index';
|
|
5
5
|
export class LikeC4ModelLocator {
|
|
6
6
|
services;
|
|
7
7
|
fqnIndex;
|
|
@@ -15,7 +15,7 @@ export class LikeC4ModelLocator {
|
|
|
15
15
|
return this.langiumDocuments.all.filter(isParsedLikeC4LangiumDocument);
|
|
16
16
|
}
|
|
17
17
|
getParsedElement(astNode) {
|
|
18
|
-
const fqn =
|
|
18
|
+
const fqn = this.fqnIndex.getFqn(astNode);
|
|
19
19
|
if (!fqn)
|
|
20
20
|
return null;
|
|
21
21
|
const doc = getDocument(astNode);
|
|
@@ -25,22 +25,18 @@ export class LikeC4ModelLocator {
|
|
|
25
25
|
return doc.c4Elements.find(e => e.id === fqn) ?? null;
|
|
26
26
|
}
|
|
27
27
|
locateElement(fqn, property = 'name') {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
continue;
|
|
32
|
-
}
|
|
33
|
-
const { el: node } = nonNullable(entries[0]);
|
|
34
|
-
const propertyNode = findNodeForProperty(node.$cstNode, property) ?? node.$cstNode;
|
|
35
|
-
if (!propertyNode) {
|
|
36
|
-
return null;
|
|
37
|
-
}
|
|
38
|
-
return {
|
|
39
|
-
uri: doc.uri.toString(),
|
|
40
|
-
range: propertyNode.range
|
|
41
|
-
};
|
|
28
|
+
const entry = this.fqnIndex.byFqn(fqn).head();
|
|
29
|
+
if (!entry) {
|
|
30
|
+
return null;
|
|
42
31
|
}
|
|
43
|
-
|
|
32
|
+
const propertyNode = findNodeForProperty(entry.el.$cstNode, property) ?? entry.el.$cstNode;
|
|
33
|
+
if (!propertyNode) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
uri: entry.doc.uri.toString(),
|
|
38
|
+
range: propertyNode.range
|
|
39
|
+
};
|
|
44
40
|
}
|
|
45
41
|
locateRelation(relationId) {
|
|
46
42
|
for (const doc of this.documents()) {
|
|
@@ -64,6 +60,9 @@ export class LikeC4ModelLocator {
|
|
|
64
60
|
};
|
|
65
61
|
}
|
|
66
62
|
}
|
|
63
|
+
if (node.arr == null) {
|
|
64
|
+
throw new InvalidModelError('Relation.arr is not defined, but should be');
|
|
65
|
+
}
|
|
67
66
|
const targetNode = findNodeForProperty(node.$cstNode, 'arr');
|
|
68
67
|
if (!targetNode) {
|
|
69
68
|
return null;
|
|
@@ -71,7 +70,7 @@ export class LikeC4ModelLocator {
|
|
|
71
70
|
return {
|
|
72
71
|
uri: doc.uri.toString(),
|
|
73
72
|
range: {
|
|
74
|
-
start: targetNode.range.
|
|
73
|
+
start: targetNode.range.start,
|
|
75
74
|
end: targetNode.range.end
|
|
76
75
|
}
|
|
77
76
|
};
|
|
@@ -46,9 +46,13 @@ export class LikeC4ModelParser {
|
|
|
46
46
|
}
|
|
47
47
|
async parseDocument(doc, cancelToken) {
|
|
48
48
|
const { elements, relations, views, specification } = cleanParsedModel(doc);
|
|
49
|
-
const specs = doc.parseResult.value.specification?.
|
|
49
|
+
const specs = doc.parseResult.value.specification?.elements;
|
|
50
50
|
if (specs) {
|
|
51
51
|
for (const { kind, style } of specs) {
|
|
52
|
+
if (kind.name in specification.kinds) {
|
|
53
|
+
logger.warn(`Duplicate specification for kind ${kind.name}`);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
52
56
|
try {
|
|
53
57
|
specification.kinds[kind.name] = toElementStyleExcludeDefaults(style?.props);
|
|
54
58
|
}
|
|
@@ -246,7 +250,15 @@ export class LikeC4ModelParser {
|
|
|
246
250
|
...(description && { description }),
|
|
247
251
|
...(tags && { tags }),
|
|
248
252
|
...(links && isNonEmptyArray(links) && { links }),
|
|
249
|
-
rules: astNode.rules.
|
|
253
|
+
rules: astNode.rules.flatMap(n => {
|
|
254
|
+
try {
|
|
255
|
+
return this.parseViewRule(n);
|
|
256
|
+
}
|
|
257
|
+
catch (e) {
|
|
258
|
+
logWarnError(e);
|
|
259
|
+
return [];
|
|
260
|
+
}
|
|
261
|
+
})
|
|
250
262
|
};
|
|
251
263
|
}
|
|
252
264
|
resolveFqn(node) {
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import { DefaultScopeComputation, MultiMap, type AstNodeDescription, type PrecomputedScopes } from 'langium';
|
|
2
2
|
import type { CancellationToken } from 'vscode-languageserver';
|
|
3
3
|
import { ast, type LikeC4LangiumDocument } from '../ast';
|
|
4
|
-
import type { LikeC4Services } from '../module';
|
|
5
4
|
type ElementsContainer = ast.Model | ast.ElementBody | ast.ExtendElementBody;
|
|
6
5
|
export declare class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
7
|
-
private services;
|
|
8
|
-
constructor(services: LikeC4Services);
|
|
9
6
|
computeExports(document: LikeC4LangiumDocument, _cancelToken: CancellationToken): Promise<AstNodeDescription[]>;
|
|
10
7
|
computeLocalScopes(document: LikeC4LangiumDocument, _cancelToken: CancellationToken): Promise<PrecomputedScopes>;
|
|
11
8
|
protected processContainer(container: ElementsContainer, scopes: PrecomputedScopes, document: LikeC4LangiumDocument): MultiMap<string, AstNodeDescription>;
|
|
@@ -1,25 +1,20 @@
|
|
|
1
1
|
import { DefaultScopeComputation, MultiMap } from 'langium';
|
|
2
|
-
import { ast } from '../ast';
|
|
3
2
|
import { isEmpty } from 'remeda';
|
|
3
|
+
import { ast } from '../ast';
|
|
4
4
|
export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
5
|
-
services;
|
|
6
|
-
constructor(services) {
|
|
7
|
-
super(services);
|
|
8
|
-
this.services = services;
|
|
9
|
-
}
|
|
10
5
|
computeExports(document, _cancelToken) {
|
|
11
6
|
const { specification, model, views } = document.parseResult.value;
|
|
12
7
|
const docExports = [];
|
|
13
|
-
if (specification
|
|
14
|
-
for (const spec of specification.
|
|
15
|
-
if (
|
|
8
|
+
if (specification) {
|
|
9
|
+
for (const spec of specification.elements) {
|
|
10
|
+
if (spec.kind && !isEmpty(spec.kind.name)) {
|
|
16
11
|
docExports.push(this.descriptions.createDescription(spec.kind, spec.kind.name, document));
|
|
17
|
-
continue;
|
|
18
12
|
}
|
|
19
|
-
|
|
13
|
+
}
|
|
14
|
+
for (const spec of specification.tags) {
|
|
15
|
+
if (spec.tag && !isEmpty(spec.tag.name)) {
|
|
20
16
|
docExports.push(this.descriptions.createDescription(spec.tag, spec.tag.name, document));
|
|
21
17
|
docExports.push(this.descriptions.createDescription(spec.tag, '#' + spec.tag.name, document));
|
|
22
|
-
continue;
|
|
23
18
|
}
|
|
24
19
|
}
|
|
25
20
|
}
|
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
import { DONE_RESULT, DefaultScopeProvider, EMPTY_STREAM, StreamImpl, StreamScope, getDocument, stream } from 'langium';
|
|
1
|
+
import { DONE_RESULT, DefaultScopeProvider, EMPTY_STREAM, StreamImpl, StreamScope, getDocument, stream, findNodeForProperty, toDocumentSegment } from 'langium';
|
|
2
2
|
import { ast } from '../ast';
|
|
3
3
|
import { elementRef, isElementRefHead, parentStrictElementRef } from '../elementRef';
|
|
4
4
|
import { logError } from '../logger';
|
|
5
5
|
function toAstNodeDescription(entry) {
|
|
6
|
+
const $cstNode = findNodeForProperty(entry.el.$cstNode, 'name');
|
|
6
7
|
return {
|
|
7
8
|
documentUri: entry.doc.uri,
|
|
8
9
|
name: entry.name,
|
|
10
|
+
...(entry.el.$cstNode && {
|
|
11
|
+
selectionSegment: toDocumentSegment(entry.el.$cstNode)
|
|
12
|
+
}),
|
|
13
|
+
...($cstNode && {
|
|
14
|
+
nameSegment: toDocumentSegment($cstNode)
|
|
15
|
+
}),
|
|
9
16
|
path: entry.path,
|
|
10
17
|
type: ast.Element
|
|
11
18
|
};
|
|
@@ -2,6 +2,7 @@ import { URI } from 'vscode-uri';
|
|
|
2
2
|
import { logger, logError } from './logger';
|
|
3
3
|
import { Rpc } from './protocol';
|
|
4
4
|
import { nonexhaustive } from '@likec4/core';
|
|
5
|
+
import { isLikeC4LangiumDocument } from './ast';
|
|
5
6
|
export function registerProtocolHandlers(services) {
|
|
6
7
|
const connection = services.shared.lsp.Connection;
|
|
7
8
|
if (!connection) {
|
|
@@ -22,7 +23,19 @@ export function registerProtocolHandlers(services) {
|
|
|
22
23
|
return Promise.resolve({ model });
|
|
23
24
|
});
|
|
24
25
|
connection.onRequest(Rpc.rebuild, async (cancelToken) => {
|
|
25
|
-
const changed = LangiumDocuments.all
|
|
26
|
+
const changed = LangiumDocuments.all
|
|
27
|
+
.map(d => {
|
|
28
|
+
// clean up any computed properties
|
|
29
|
+
if (isLikeC4LangiumDocument(d)) {
|
|
30
|
+
delete d.c4Specification;
|
|
31
|
+
delete d.c4Elements;
|
|
32
|
+
delete d.c4Relations;
|
|
33
|
+
delete d.c4Views;
|
|
34
|
+
delete d.c4fqns;
|
|
35
|
+
}
|
|
36
|
+
return d.uri;
|
|
37
|
+
})
|
|
38
|
+
.toArray();
|
|
26
39
|
logger.debug(`[ProtocolHandlers] rebuild all documents: [
|
|
27
40
|
${changed.map(d => d.toString()).join('\n ')}
|
|
28
41
|
]`);
|
|
@@ -29,6 +29,13 @@ export const elementChecks = (services) => {
|
|
|
29
29
|
]
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
|
+
// for (let i = 3; i < el.props.length; i++) {
|
|
33
|
+
// accept('error', `Too many properties, max 3 allowed`, {
|
|
34
|
+
// node: el,
|
|
35
|
+
// property: 'props',
|
|
36
|
+
// index: i
|
|
37
|
+
// })
|
|
38
|
+
// }
|
|
32
39
|
};
|
|
33
40
|
};
|
|
34
41
|
//# sourceMappingURL=element.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ValidationCheck } from 'langium';
|
|
2
|
-
import
|
|
2
|
+
import { ast } from '../ast';
|
|
3
3
|
import type { LikeC4Services } from '../module';
|
|
4
4
|
export declare const relationChecks: (services: LikeC4Services) => ValidationCheck<ast.Relation>;
|
|
5
5
|
//# sourceMappingURL=relation.d.ts.map
|
|
@@ -1,30 +1,43 @@
|
|
|
1
1
|
import { isSameHierarchy } from '@likec4/core';
|
|
2
|
-
import {
|
|
2
|
+
import { ast } from '../ast';
|
|
3
|
+
import { elementRef } from '../elementRef';
|
|
3
4
|
import { logError } from '../logger';
|
|
4
5
|
export const relationChecks = (services) => {
|
|
5
6
|
const fqnIndex = services.likec4.FqnIndex;
|
|
6
7
|
return (el, accept) => {
|
|
7
8
|
try {
|
|
8
|
-
const
|
|
9
|
-
const target = fqnIndex.getFqn(
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
const targetEl = elementRef(el.target);
|
|
10
|
+
const target = targetEl && fqnIndex.getFqn(targetEl);
|
|
11
|
+
if (!target) {
|
|
12
|
+
accept('error', 'Target not found (not parsed/indexed yet)', {
|
|
13
|
+
node: el,
|
|
14
|
+
property: 'target'
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
let sourceEl;
|
|
18
|
+
if ('source' in el) {
|
|
19
|
+
sourceEl = elementRef(el.source);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
if (!ast.isElementBody(el.$container)) {
|
|
23
|
+
accept('error', 'Invalid relation, expected to have source defined or be inside the element', {
|
|
14
24
|
node: el,
|
|
15
|
-
|
|
25
|
+
keyword: '->'
|
|
16
26
|
});
|
|
17
27
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
node: el,
|
|
21
|
-
property: 'source'
|
|
22
|
-
});
|
|
28
|
+
else {
|
|
29
|
+
sourceEl = el.$container.$container;
|
|
23
30
|
}
|
|
24
|
-
return;
|
|
25
31
|
}
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
const source = sourceEl && fqnIndex.getFqn(sourceEl);
|
|
33
|
+
if (sourceEl && !source) {
|
|
34
|
+
accept('error', 'Source not found (not parsed/indexed yet)', {
|
|
35
|
+
node: el,
|
|
36
|
+
property: 'source'
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
if (source && target && isSameHierarchy(source, target)) {
|
|
40
|
+
return accept('error', 'Invalid parent-child relationship', {
|
|
28
41
|
node: el
|
|
29
42
|
});
|
|
30
43
|
}
|
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.36.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bugs": "https://github.com/likec4/likec4/issues",
|
|
7
7
|
"homepage": "https://likec4.dev",
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"test:watch": "vitest"
|
|
43
43
|
},
|
|
44
44
|
"dependencies": {
|
|
45
|
-
"@likec4/core": "0.
|
|
46
|
-
"langium": "^2.0.
|
|
45
|
+
"@likec4/core": "0.36.0",
|
|
46
|
+
"langium": "^2.0.2",
|
|
47
47
|
"nanoid": "^4.0.2",
|
|
48
48
|
"object-hash": "^3.0.0",
|
|
49
49
|
"rambdax": "^9.1.1",
|
|
@@ -56,9 +56,10 @@
|
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/node": "^18.15.11",
|
|
58
58
|
"@types/object-hash": "^3.0.2",
|
|
59
|
-
"langium-cli": "^2.0.
|
|
59
|
+
"langium-cli": "^2.0.1",
|
|
60
60
|
"npm-run-all": "^4.1.5",
|
|
61
|
-
"typescript": "^5.
|
|
62
|
-
"vitest": "^0.34.
|
|
63
|
-
}
|
|
61
|
+
"typescript": "^5.2.2",
|
|
62
|
+
"vitest": "^0.34.3"
|
|
63
|
+
},
|
|
64
|
+
"packageManager": "yarn@3.6.3"
|
|
64
65
|
}
|