@likec4/language-server 1.1.1 → 1.2.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 +4 -4
- package/contrib/likec4.tmLanguage.json +1 -1
- package/dist/ast.d.ts +27 -11
- package/dist/ast.js +11 -7
- package/dist/generated/ast.d.ts +75 -19
- package/dist/generated/ast.js +96 -7
- package/dist/generated/grammar.js +1 -1
- package/dist/lsp/CodeLensProvider.js +5 -2
- package/dist/lsp/DocumentSymbolProvider.d.ts +1 -1
- package/dist/lsp/DocumentSymbolProvider.js +14 -9
- package/dist/lsp/SemanticTokenProvider.js +1 -1
- package/dist/model/model-builder.js +28 -15
- package/dist/model/model-locator.d.ts +2 -2
- package/dist/model/model-locator.js +12 -16
- package/dist/model/model-parser.d.ts +2 -0
- package/dist/model/model-parser.js +143 -33
- package/dist/model-change/ModelChanges.d.ts +2 -1
- package/dist/model-change/ModelChanges.js +26 -20
- package/dist/model-change/changeElementStyle.d.ts +8 -5
- package/dist/model-change/changeElementStyle.js +23 -23
- package/dist/model-change/changeViewLayout.d.ts +4 -4
- package/dist/model-change/changeViewLayout.js +4 -5
- package/dist/references/scope-computation.js +31 -28
- package/dist/shared/NodeKindProvider.js +4 -2
- package/dist/validation/dynamic-view-rule.d.ts +5 -0
- package/dist/validation/dynamic-view-rule.js +32 -0
- package/dist/validation/dynamic-view-step.d.ts +5 -0
- package/dist/validation/dynamic-view-step.js +33 -0
- package/dist/validation/index.js +5 -1
- package/dist/validation/view-predicates/expanded-element.js +1 -0
- package/dist/validation/view-predicates/outgoing.js +2 -2
- package/dist/validation/view.d.ts +1 -1
- package/dist/validation/view.js +1 -3
- package/dist/view-utils/assignNavigateTo.d.ts +1 -1
- package/dist/view-utils/assignNavigateTo.js +2 -1
- package/dist/view-utils/resolve-extended-views.d.ts +2 -2
- package/dist/view-utils/resolve-relative-paths.d.ts +2 -2
- package/dist/view-utils/resolve-relative-paths.js +2 -3
- package/package.json +6 -6
|
@@ -6,52 +6,55 @@ import { isTruthy } from "remeda";
|
|
|
6
6
|
import { ast } from "../ast.js";
|
|
7
7
|
import { logError } from "../logger.js";
|
|
8
8
|
export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
9
|
-
computeExports(document, _cancelToken) {
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
async computeExports(document, _cancelToken) {
|
|
10
|
+
const docExports = [];
|
|
11
|
+
try {
|
|
12
12
|
const { specifications, models, views } = document.parseResult.value;
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
for (const spec of specifications.flatMap((s) => [
|
|
14
|
+
...s.elements,
|
|
15
|
+
...s.relationships,
|
|
16
|
+
...s.tags
|
|
17
|
+
])) {
|
|
18
|
+
try {
|
|
19
|
+
if (ast.isSpecificationTag(spec)) {
|
|
20
|
+
if (spec.tag && isTruthy(spec.tag.name)) {
|
|
21
|
+
docExports.push(
|
|
22
|
+
this.descriptions.createDescription(spec.tag, "#" + spec.tag.name, document)
|
|
23
|
+
);
|
|
24
|
+
}
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
15
27
|
if (spec.kind && isTruthy(spec.kind.name)) {
|
|
16
28
|
docExports.push(
|
|
17
29
|
this.descriptions.createDescription(spec.kind, spec.kind.name, document)
|
|
18
30
|
);
|
|
19
31
|
}
|
|
32
|
+
} catch (e) {
|
|
33
|
+
logError(e);
|
|
20
34
|
}
|
|
21
|
-
} catch (e) {
|
|
22
|
-
logError(e);
|
|
23
|
-
}
|
|
24
|
-
try {
|
|
25
|
-
for (const spec of specifications.flatMap((s) => s.tags)) {
|
|
26
|
-
if (spec.tag && isTruthy(spec.tag.name)) {
|
|
27
|
-
docExports.push(
|
|
28
|
-
this.descriptions.createDescription(spec.tag, "#" + spec.tag.name, document)
|
|
29
|
-
);
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
} catch (e) {
|
|
33
|
-
logError(e);
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
-
|
|
36
|
+
for (const elAst of models.flatMap((m) => m.elements)) {
|
|
37
|
+
try {
|
|
37
38
|
if (ast.isElement(elAst) && isTruthy(elAst.name)) {
|
|
38
39
|
docExports.push(this.descriptions.createDescription(elAst, elAst.name, document));
|
|
39
40
|
}
|
|
41
|
+
} catch (e) {
|
|
42
|
+
logError(e);
|
|
40
43
|
}
|
|
41
|
-
} catch (e) {
|
|
42
|
-
logError(e);
|
|
43
44
|
}
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
for (const viewAst of views.flatMap((v) => v.views)) {
|
|
46
|
+
try {
|
|
46
47
|
if (isTruthy(viewAst.name)) {
|
|
47
48
|
docExports.push(this.descriptions.createDescription(viewAst, viewAst.name, document));
|
|
48
49
|
}
|
|
50
|
+
} catch (e) {
|
|
51
|
+
logError(e);
|
|
49
52
|
}
|
|
50
|
-
} catch (e) {
|
|
51
|
-
logError(e);
|
|
52
53
|
}
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
} catch (e) {
|
|
55
|
+
logError(e);
|
|
56
|
+
}
|
|
57
|
+
return docExports;
|
|
55
58
|
}
|
|
56
59
|
computeLocalScopes(document, _cancelToken) {
|
|
57
60
|
return new Promise((resolve) => {
|
|
@@ -17,7 +17,7 @@ export class NodeKindProvider {
|
|
|
17
17
|
case (ast.isModel(node) || ast.isModelViews(node) || ast.isSpecificationRule(node) || hasType(ast.Model) || hasType(ast.ModelViews) || hasType(ast.SpecificationRule)): {
|
|
18
18
|
return SymbolKind.Namespace;
|
|
19
19
|
}
|
|
20
|
-
case (ast.
|
|
20
|
+
case (ast.isLikeC4View(node) || hasType(ast.LikeC4View)): {
|
|
21
21
|
return SymbolKind.Class;
|
|
22
22
|
}
|
|
23
23
|
case (ast.isTag(node) || hasType(ast.Tag) || (ast.isSpecificationTag(node) || hasType(ast.SpecificationTag))): {
|
|
@@ -43,6 +43,8 @@ export class NodeKindProvider {
|
|
|
43
43
|
return CompletionItemKind.Module;
|
|
44
44
|
case SymbolKind.Class:
|
|
45
45
|
return CompletionItemKind.Class;
|
|
46
|
+
case SymbolKind.Enum:
|
|
47
|
+
return CompletionItemKind.Enum;
|
|
46
48
|
case SymbolKind.EnumMember:
|
|
47
49
|
return CompletionItemKind.EnumMember;
|
|
48
50
|
case SymbolKind.TypeParameter:
|
|
@@ -52,7 +54,7 @@ export class NodeKindProvider {
|
|
|
52
54
|
case SymbolKind.Event:
|
|
53
55
|
return CompletionItemKind.Event;
|
|
54
56
|
default:
|
|
55
|
-
return CompletionItemKind.
|
|
57
|
+
return CompletionItemKind.Reference;
|
|
56
58
|
}
|
|
57
59
|
}
|
|
58
60
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ValidationCheck } from 'langium';
|
|
2
|
+
import { ast } from '../ast';
|
|
3
|
+
import type { LikeC4Services } from '../module';
|
|
4
|
+
export declare const dynamicViewRulePredicate: (_services: LikeC4Services) => ValidationCheck<ast.DynamicViewRulePredicate>;
|
|
5
|
+
//# sourceMappingURL=dynamic-view-rule.d.ts.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { nonexhaustive } from "@likec4/core";
|
|
2
|
+
import { ast } from "../ast.js";
|
|
3
|
+
import { logError } from "../logger.js";
|
|
4
|
+
export const dynamicViewRulePredicate = (_services) => {
|
|
5
|
+
return (el, accept) => {
|
|
6
|
+
try {
|
|
7
|
+
for (const expr of el.expressions) {
|
|
8
|
+
switch (true) {
|
|
9
|
+
case ast.isElementRef(expr):
|
|
10
|
+
case ast.isDescedantsExpr(expr):
|
|
11
|
+
case ast.isCustomElementExpr(expr):
|
|
12
|
+
case ast.isExpandElementExpr(expr):
|
|
13
|
+
return;
|
|
14
|
+
case ast.isRelationExpr(expr):
|
|
15
|
+
case ast.isInOutExpr(expr):
|
|
16
|
+
case ast.isIncomingExpr(expr):
|
|
17
|
+
case ast.isOutgoingExpr(expr):
|
|
18
|
+
case ast.isElementKindExpr(expr):
|
|
19
|
+
case ast.isElementTagExpr(expr):
|
|
20
|
+
case ast.isWildcardExpr(expr):
|
|
21
|
+
return accept("warning", `Expression is not supported by dynamic views`, {
|
|
22
|
+
node: expr
|
|
23
|
+
});
|
|
24
|
+
default:
|
|
25
|
+
nonexhaustive(expr);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
} catch (e) {
|
|
29
|
+
logError(e);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ValidationCheck } from 'langium';
|
|
2
|
+
import { ast } from '../ast';
|
|
3
|
+
import type { LikeC4Services } from '../module';
|
|
4
|
+
export declare const dynamicViewStep: (services: LikeC4Services) => ValidationCheck<ast.DynamicViewStep>;
|
|
5
|
+
//# sourceMappingURL=dynamic-view-step.d.ts.map
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { isAncestor } from "@likec4/core";
|
|
2
|
+
import { elementRef } from "../elementRef.js";
|
|
3
|
+
import { logError } from "../logger.js";
|
|
4
|
+
export const dynamicViewStep = (services) => {
|
|
5
|
+
const fqnIndex = services.likec4.FqnIndex;
|
|
6
|
+
return (el, accept) => {
|
|
7
|
+
try {
|
|
8
|
+
const sourceEl = elementRef(el.source);
|
|
9
|
+
const source = sourceEl && fqnIndex.getFqn(sourceEl);
|
|
10
|
+
if (!source) {
|
|
11
|
+
accept("error", "Source not found (not parsed/indexed yet)", {
|
|
12
|
+
node: el,
|
|
13
|
+
property: "source"
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
const targetEl = elementRef(el.target);
|
|
17
|
+
const target = targetEl && fqnIndex.getFqn(targetEl);
|
|
18
|
+
if (!target) {
|
|
19
|
+
accept("error", "Target not found (not parsed/indexed yet)", {
|
|
20
|
+
node: el,
|
|
21
|
+
property: "target"
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
if (source && target && (isAncestor(source, target) || isAncestor(target, source))) {
|
|
25
|
+
accept("error", "Invalid parent-child relationship", {
|
|
26
|
+
node: el
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
} catch (e) {
|
|
30
|
+
logError(e);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
};
|
package/dist/validation/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { logger } from "../logger.js";
|
|
2
|
+
import { dynamicViewRulePredicate } from "./dynamic-view-rule.js";
|
|
3
|
+
import { dynamicViewStep } from "./dynamic-view-step.js";
|
|
2
4
|
import { elementChecks } from "./element.js";
|
|
3
5
|
import { opacityPropertyRuleChecks } from "./property-checks.js";
|
|
4
6
|
import { relationChecks } from "./relation.js";
|
|
@@ -25,11 +27,13 @@ export function registerValidationChecks(services) {
|
|
|
25
27
|
SpecificationRule: specificationRuleChecks(services),
|
|
26
28
|
Model: modelRuleChecks(services),
|
|
27
29
|
ModelViews: modelViewsChecks(services),
|
|
28
|
-
|
|
30
|
+
DynamicViewStep: dynamicViewStep(services),
|
|
31
|
+
LikeC4View: viewChecks(services),
|
|
29
32
|
Element: elementChecks(services),
|
|
30
33
|
ElementKind: elementKindChecks(services),
|
|
31
34
|
Relation: relationChecks(services),
|
|
32
35
|
Tag: tagChecks(services),
|
|
36
|
+
DynamicViewRulePredicate: dynamicViewRulePredicate(services),
|
|
33
37
|
CustomElementExpr: customElementExprChecks(services),
|
|
34
38
|
ExpandElementExpr: expandElementExprChecks(services),
|
|
35
39
|
RelationshipKind: relationshipChecks(services),
|
|
@@ -4,6 +4,7 @@ export const expandElementExprChecks = (_services) => {
|
|
|
4
4
|
return (el, accept) => {
|
|
5
5
|
switch (true) {
|
|
6
6
|
case ast.isIncludePredicate(el.$container):
|
|
7
|
+
case ast.isDynamicViewRulePredicate(el.$container):
|
|
7
8
|
case ast.isViewRuleStyle(el.$container):
|
|
8
9
|
return;
|
|
9
10
|
case ast.isCustomElementExpr(el.$container):
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { isNullish } from "remeda";
|
|
2
2
|
import { ast } from "../../ast.js";
|
|
3
3
|
export const outgoingExpressionChecks = (_services) => {
|
|
4
4
|
return (el, accept) => {
|
|
5
5
|
if (ast.isWildcardExpr(el.from)) {
|
|
6
6
|
const view = el.$container.$container.$container;
|
|
7
|
-
if (
|
|
7
|
+
if (view.$type === "ElementView" && isNullish(view.viewOf)) {
|
|
8
8
|
accept("warning", "Predicate is ignored as it concerns all relationships", {
|
|
9
9
|
node: el
|
|
10
10
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ValidationCheck } from 'langium';
|
|
2
2
|
import { ast } from '../ast';
|
|
3
3
|
import type { LikeC4Services } from '../module';
|
|
4
|
-
export declare const viewChecks: (services: LikeC4Services) => ValidationCheck<ast.
|
|
4
|
+
export declare const viewChecks: (services: LikeC4Services) => ValidationCheck<ast.LikeC4View>;
|
|
5
5
|
//# sourceMappingURL=view.d.ts.map
|
package/dist/validation/view.js
CHANGED
|
@@ -2,12 +2,10 @@ import { ast } from "../ast.js";
|
|
|
2
2
|
export const viewChecks = (services) => {
|
|
3
3
|
const index = services.shared.workspace.IndexManager;
|
|
4
4
|
return (el, accept) => {
|
|
5
|
-
if (el.extends) {
|
|
6
|
-
}
|
|
7
5
|
if (!el.name) {
|
|
8
6
|
return;
|
|
9
7
|
}
|
|
10
|
-
const anotherViews = index.allElements(ast.
|
|
8
|
+
const anotherViews = index.allElements(ast.LikeC4View).filter((n) => n.name === el.name).limit(2).count();
|
|
11
9
|
if (anotherViews > 1) {
|
|
12
10
|
accept("error", `Duplicate view '${el.name}'`, {
|
|
13
11
|
node: el,
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
+
import { isComputedElementView } from "@likec4/core";
|
|
1
2
|
import { find } from "remeda";
|
|
2
3
|
export function assignNavigateTo(views) {
|
|
3
4
|
const allElementViews = /* @__PURE__ */ new Map();
|
|
4
5
|
for (const v of views) {
|
|
5
|
-
if (v.viewOf && !v.extends) {
|
|
6
|
+
if (isComputedElementView(v) && v.viewOf && !v.extends) {
|
|
6
7
|
const viewsOf = allElementViews.get(v.viewOf) ?? [];
|
|
7
8
|
viewsOf.push(v.id);
|
|
8
9
|
allElementViews.set(v.viewOf, viewsOf);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type View } from '@likec4/core';
|
|
2
2
|
/**
|
|
3
3
|
* Resolve rules of extended views
|
|
4
4
|
* (Removes invalid views)
|
|
5
5
|
*/
|
|
6
|
-
export declare function resolveRulesExtendedViews<V extends Record<any,
|
|
6
|
+
export declare function resolveRulesExtendedViews<V extends Record<any, View>>(unresolvedViews: V): V;
|
|
7
7
|
//# sourceMappingURL=resolve-extended-views.d.ts.map
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export declare function resolveRelativePaths(views:
|
|
1
|
+
import type { View } from '@likec4/core';
|
|
2
|
+
export declare function resolveRelativePaths(views: View[]): View[];
|
|
3
3
|
//# sourceMappingURL=resolve-relative-paths.d.ts.map
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { invariant } from "@likec4/core";
|
|
2
|
-
import {
|
|
3
|
-
import { hasAtLeast } from "remeda";
|
|
2
|
+
import { hasAtLeast, unique, zip } from "remeda";
|
|
4
3
|
function commonAncestorPath(views, sep = "/") {
|
|
5
4
|
if (views.length <= 1)
|
|
6
5
|
return "";
|
|
7
|
-
const uniqURIs =
|
|
6
|
+
const uniqURIs = unique(views.flatMap(({ docUri }) => docUri ? [docUri] : []));
|
|
8
7
|
if (uniqURIs.length === 0)
|
|
9
8
|
return "";
|
|
10
9
|
if (uniqURIs.length === 1) {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@likec4/language-server",
|
|
3
3
|
"description": "LikeC4 Language Server",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.2.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bugs": "https://github.com/likec4/likec4/issues",
|
|
7
7
|
"homepage": "https://likec4.dev",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
}
|
|
62
62
|
},
|
|
63
63
|
"scripts": {
|
|
64
|
-
"typecheck": "tsc
|
|
64
|
+
"typecheck": "tsc -b",
|
|
65
65
|
"watch:langium": "langium generate --watch",
|
|
66
66
|
"watch:ts": "tsc --watch",
|
|
67
67
|
"generate": "langium generate",
|
|
@@ -74,8 +74,8 @@
|
|
|
74
74
|
"test": "vitest run"
|
|
75
75
|
},
|
|
76
76
|
"dependencies": {
|
|
77
|
-
"@likec4/core": "1.
|
|
78
|
-
"@likec4/graph": "1.
|
|
77
|
+
"@likec4/core": "1.2.0",
|
|
78
|
+
"@likec4/graph": "1.2.0",
|
|
79
79
|
"@total-typescript/ts-reset": "^0.5.1",
|
|
80
80
|
"fast-equals": "^5.0.1",
|
|
81
81
|
"langium": "^3.0.0",
|
|
@@ -92,7 +92,7 @@
|
|
|
92
92
|
"vscode-uri": "3.0.8"
|
|
93
93
|
},
|
|
94
94
|
"devDependencies": {
|
|
95
|
-
"@types/node": "^20.
|
|
95
|
+
"@types/node": "^20.13.0",
|
|
96
96
|
"@types/object-hash": "^3.0.6",
|
|
97
97
|
"@types/string-hash": "^1",
|
|
98
98
|
"execa": "^9.1.0",
|
|
@@ -102,5 +102,5 @@
|
|
|
102
102
|
"unbuild": "^2.0.0",
|
|
103
103
|
"vitest": "~1.5.2"
|
|
104
104
|
},
|
|
105
|
-
"packageManager": "yarn@4.
|
|
105
|
+
"packageManager": "yarn@4.3.0"
|
|
106
106
|
}
|