@likec4/language-server 0.50.0 → 0.52.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 +18 -6
- package/dist/ast.js +39 -5
- package/dist/model/model-builder.js +2 -2
- package/dist/model/model-parser.js +30 -29
- package/dist/module.d.ts +10 -2
- package/dist/references/scope-computation.d.ts +2 -2
- package/dist/references/scope-computation.js +58 -57
- package/dist/references/scope-provider.js +15 -13
- package/dist/shared/NodeKindProvider.js +3 -1
- package/dist/test/testServices.d.ts +1 -1
- package/package.json +7 -7
package/dist/ast.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/// <reference types="react" />
|
|
2
2
|
import { type c4 } from '@likec4/core';
|
|
3
|
-
import type { LangiumDocument, MultiMap } from 'langium';
|
|
4
|
-
import type { SetRequired } from 'type-fest';
|
|
3
|
+
import type { AstNode, DiagnosticInfo, LangiumDocument, MultiMap } from 'langium';
|
|
4
|
+
import type { ConditionalPick, SetRequired, ValueOf } from 'type-fest';
|
|
5
|
+
import type { Diagnostic } from 'vscode-languageserver-protocol';
|
|
5
6
|
import type { LikeC4Grammar } from './generated/ast';
|
|
6
7
|
import * as ast from './generated/ast';
|
|
7
8
|
export { ast };
|
|
@@ -73,23 +74,34 @@ export interface DocFqnIndexEntry {
|
|
|
73
74
|
el: WeakRef<ast.Element>;
|
|
74
75
|
path: string;
|
|
75
76
|
}
|
|
77
|
+
export type LikeC4AstNode = ValueOf<ConditionalPick<ast.LikeC4AstType, AstNode>>;
|
|
78
|
+
type LikeC4DocumentDiagnostic = Diagnostic & DiagnosticInfo<LikeC4AstNode>;
|
|
76
79
|
export interface LikeC4DocumentProps {
|
|
80
|
+
diagnostics?: Array<LikeC4DocumentDiagnostic>;
|
|
77
81
|
c4Specification?: ParsedAstSpecification;
|
|
78
82
|
c4Elements?: ParsedAstElement[];
|
|
79
83
|
c4Relations?: ParsedAstRelation[];
|
|
80
84
|
c4Views?: ParsedAstElementView[];
|
|
81
85
|
c4fqns?: MultiMap<c4.Fqn, DocFqnIndexEntry>;
|
|
82
86
|
}
|
|
83
|
-
export interface LikeC4LangiumDocument extends LangiumDocument<LikeC4Grammar>, LikeC4DocumentProps {
|
|
87
|
+
export interface LikeC4LangiumDocument extends Omit<LangiumDocument<LikeC4Grammar>, 'diagnostics'>, LikeC4DocumentProps {
|
|
84
88
|
}
|
|
85
|
-
export interface FqnIndexedDocument extends LangiumDocument<LikeC4Grammar>, SetRequired<LikeC4DocumentProps, 'c4fqns'> {
|
|
89
|
+
export interface FqnIndexedDocument extends Omit<LangiumDocument<LikeC4Grammar>, 'diagnostics'>, SetRequired<LikeC4DocumentProps, 'c4fqns'> {
|
|
86
90
|
}
|
|
87
|
-
export interface ParsedLikeC4LangiumDocument extends LangiumDocument<LikeC4Grammar>, Required<LikeC4DocumentProps> {
|
|
91
|
+
export interface ParsedLikeC4LangiumDocument extends Omit<LangiumDocument<LikeC4Grammar>, 'diagnostics'>, Required<LikeC4DocumentProps> {
|
|
88
92
|
}
|
|
89
93
|
export declare function cleanParsedModel(doc: LikeC4LangiumDocument): ParsedLikeC4LangiumDocument;
|
|
90
94
|
export declare function isFqnIndexedDocument(doc: LangiumDocument): doc is FqnIndexedDocument;
|
|
91
95
|
export declare function isLikeC4LangiumDocument(doc: LangiumDocument): doc is LikeC4LangiumDocument;
|
|
92
96
|
export declare function isParsedLikeC4LangiumDocument(doc: LangiumDocument): doc is ParsedLikeC4LangiumDocument;
|
|
97
|
+
type Guard<N extends AstNode> = (n: AstNode) => n is N;
|
|
98
|
+
type Guarded<G> = G extends Guard<infer N> ? N : never;
|
|
99
|
+
declare const isValidatableAstNode: (n: AstNode) => n is ast.Relation | ast.SpecificationRelationshipKind | ast.SpecificationRule | ast.SpecificationElementKind | ast.Element | ast.Model | ast.ExtendElement | ast.ElementView | ast.ModelViews | ast.SpecificationTag;
|
|
100
|
+
type ValidatableAstNode = Guarded<typeof isValidatableAstNode>;
|
|
101
|
+
export declare function checksFromDiagnostics(doc: LikeC4LangiumDocument): {
|
|
102
|
+
isValid: (n: ValidatableAstNode) => boolean;
|
|
103
|
+
invalidNodes: WeakSet<ast.ExplicitRelation | ast.ImplicitRelation | ast.SpecificationRelationshipKind | ast.SpecificationRule | ast.SpecificationElementKind | ast.Element | ast.Model | ast.ExtendElement | ast.ElementView | ast.ModelViews | ast.SpecificationTag>;
|
|
104
|
+
};
|
|
93
105
|
export declare const isValidLikeC4LangiumDocument: (doc: LangiumDocument) => doc is ParsedLikeC4LangiumDocument;
|
|
94
106
|
export declare function streamModel(doc: LikeC4LangiumDocument): Generator<ast.Relation | ast.Element, void, unknown>;
|
|
95
107
|
export declare function resolveRelationPoints(node: ast.Relation): {
|
|
@@ -113,7 +125,7 @@ export declare function toRelationshipStyle(props?: ast.SpecificationRelationshi
|
|
|
113
125
|
tail?: c4.RelationshipArrowType;
|
|
114
126
|
};
|
|
115
127
|
export declare function toRelationshipStyleExcludeDefaults(props?: ast.SpecificationRelationshipKind['props']): {
|
|
116
|
-
tail?:
|
|
128
|
+
tail?: c4.RelationshipArrowType;
|
|
117
129
|
head?: "crow" | "diamond" | "none" | "odiamond" | "onormal" | "open" | "vee";
|
|
118
130
|
line?: "dotted" | "solid";
|
|
119
131
|
color?: "amber" | "blue" | "green" | "indigo" | "muted" | "primary" | "red" | "secondary" | "sky" | "slate";
|
package/dist/ast.js
CHANGED
|
@@ -7,12 +7,12 @@ import {
|
|
|
7
7
|
RelationRefError,
|
|
8
8
|
nonexhaustive
|
|
9
9
|
} from "@likec4/core";
|
|
10
|
-
import { DocumentState } from "langium";
|
|
10
|
+
import { DocumentState, getContainerOfType } from "langium";
|
|
11
11
|
import { isNil } from "remeda";
|
|
12
|
+
import { DiagnosticSeverity } from "vscode-languageserver-protocol";
|
|
12
13
|
import { elementRef } from "./elementRef.js";
|
|
13
14
|
import * as ast from "./generated/ast.js";
|
|
14
15
|
import { LikeC4LanguageMetaData } from "./generated/module.js";
|
|
15
|
-
import { DiagnosticSeverity } from "vscode-languageserver-protocol";
|
|
16
16
|
export { ast };
|
|
17
17
|
const idattr = Symbol.for("idattr");
|
|
18
18
|
export const ElementViewOps = {
|
|
@@ -58,18 +58,52 @@ export function isLikeC4LangiumDocument(doc) {
|
|
|
58
58
|
export function isParsedLikeC4LangiumDocument(doc) {
|
|
59
59
|
return isLikeC4LangiumDocument(doc) && doc.state == DocumentState.Validated && !!doc.c4Specification && !!doc.c4Elements && !!doc.c4Relations && !!doc.c4Views && !!doc.c4fqns;
|
|
60
60
|
}
|
|
61
|
+
function validatableAstNodeGuards(predicates) {
|
|
62
|
+
return (n) => predicates.some((p) => p(n));
|
|
63
|
+
}
|
|
64
|
+
const isValidatableAstNode = validatableAstNodeGuards([
|
|
65
|
+
ast.isModel,
|
|
66
|
+
ast.isRelation,
|
|
67
|
+
ast.isElement,
|
|
68
|
+
ast.isExtendElement,
|
|
69
|
+
ast.isSpecificationRule,
|
|
70
|
+
ast.isSpecificationElementKind,
|
|
71
|
+
ast.isSpecificationRelationshipKind,
|
|
72
|
+
ast.isSpecificationTag,
|
|
73
|
+
ast.isElementView,
|
|
74
|
+
ast.isModelViews
|
|
75
|
+
]);
|
|
76
|
+
export function checksFromDiagnostics(doc) {
|
|
77
|
+
const invalidNodes = new WeakSet(
|
|
78
|
+
doc.diagnostics?.flatMap((d) => {
|
|
79
|
+
if (d.severity === DiagnosticSeverity.Error) {
|
|
80
|
+
return getContainerOfType(d.node, isValidatableAstNode) ?? [];
|
|
81
|
+
}
|
|
82
|
+
return [];
|
|
83
|
+
}) ?? []
|
|
84
|
+
);
|
|
85
|
+
const isValid = (n) => !invalidNodes.has(n);
|
|
86
|
+
return {
|
|
87
|
+
isValid,
|
|
88
|
+
invalidNodes
|
|
89
|
+
};
|
|
90
|
+
}
|
|
61
91
|
export const isValidLikeC4LangiumDocument = (doc) => {
|
|
62
92
|
if (!isParsedLikeC4LangiumDocument(doc))
|
|
63
93
|
return false;
|
|
64
94
|
const { parseResult, diagnostics } = doc;
|
|
65
|
-
return parseResult.lexerErrors.length === 0 && (!diagnostics || diagnostics.every((d) => d.severity !== DiagnosticSeverity.Error));
|
|
95
|
+
return parseResult.lexerErrors.length === 0 && parseResult.parserErrors.length === 0 && (!diagnostics || diagnostics.length === 0 || diagnostics.every((d) => d.severity !== DiagnosticSeverity.Error));
|
|
66
96
|
};
|
|
67
97
|
export function* streamModel(doc) {
|
|
68
|
-
const
|
|
98
|
+
const { isValid } = checksFromDiagnostics(doc);
|
|
99
|
+
const elements = doc.parseResult.value.models.flatMap((m) => isValid(m) ? m.elements : []);
|
|
69
100
|
const traverseStack = [...elements];
|
|
70
101
|
const relations = [];
|
|
71
102
|
let el;
|
|
72
103
|
while (el = traverseStack.shift()) {
|
|
104
|
+
if (!isValid(el)) {
|
|
105
|
+
continue;
|
|
106
|
+
}
|
|
73
107
|
if (ast.isRelation(el)) {
|
|
74
108
|
relations.push(el);
|
|
75
109
|
continue;
|
|
@@ -185,7 +219,7 @@ export function toRelationshipStyleExcludeDefaults(props) {
|
|
|
185
219
|
...color && color !== DefaultRelationshipColor ? { color } : {},
|
|
186
220
|
...line && line !== DefaultLineStyle ? { line } : {},
|
|
187
221
|
...head && head !== DefaultArrowType ? { head } : {},
|
|
188
|
-
...tail
|
|
222
|
+
...tail ? { tail } : {}
|
|
189
223
|
};
|
|
190
224
|
}
|
|
191
225
|
export function toAutoLayout(direction) {
|
|
@@ -7,7 +7,7 @@ import { LikeC4ModelGraph, computeView } from "@likec4/graph";
|
|
|
7
7
|
import { DocumentState } from "langium";
|
|
8
8
|
import * as R from "remeda";
|
|
9
9
|
import { Disposable } from "vscode-languageserver";
|
|
10
|
-
import {
|
|
10
|
+
import { isParsedLikeC4LangiumDocument } from "../ast.js";
|
|
11
11
|
import { logError, logWarnError, logger } from "../logger.js";
|
|
12
12
|
import { printDocs } from "../utils.js";
|
|
13
13
|
import { assignNavigateTo, resolveRelativePaths, resolveRulesExtendedViews } from "../view-utils/index.js";
|
|
@@ -255,7 +255,7 @@ ${printDocs(docs)}`);
|
|
|
255
255
|
});
|
|
256
256
|
}
|
|
257
257
|
documents() {
|
|
258
|
-
return this.langiumDocuments.all.filter(
|
|
258
|
+
return this.langiumDocuments.all.filter(isParsedLikeC4LangiumDocument).toArray();
|
|
259
259
|
}
|
|
260
260
|
notifyListeners(docs) {
|
|
261
261
|
for (const listener of this.listeners) {
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
ElementViewOps,
|
|
8
8
|
ast,
|
|
9
9
|
cleanParsedModel,
|
|
10
|
+
checksFromDiagnostics,
|
|
10
11
|
isFqnIndexedDocument,
|
|
11
12
|
resolveRelationPoints,
|
|
12
13
|
streamModel,
|
|
@@ -18,7 +19,7 @@ import {
|
|
|
18
19
|
import { elementRef, getFqnElementRef } from "../elementRef.js";
|
|
19
20
|
import { logError, logWarnError, logger } from "../logger.js";
|
|
20
21
|
function toSingleLine(str) {
|
|
21
|
-
return str
|
|
22
|
+
return str ? removeIndent(str).split("\n").join(" ") : void 0;
|
|
22
23
|
}
|
|
23
24
|
function removeIndent(str) {
|
|
24
25
|
return str ? stripIndent(str).trim() : void 0;
|
|
@@ -53,35 +54,32 @@ export class LikeC4ModelParser {
|
|
|
53
54
|
this.parseViews(doc);
|
|
54
55
|
return doc;
|
|
55
56
|
}
|
|
56
|
-
parseSpecification(
|
|
57
|
-
const
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
c4Specification.kinds[
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
}
|
|
57
|
+
parseSpecification(doc) {
|
|
58
|
+
const { isValid } = checksFromDiagnostics(doc);
|
|
59
|
+
const { parseResult, c4Specification } = doc;
|
|
60
|
+
const specifications = parseResult.value.specifications.filter(isValid);
|
|
61
|
+
const element_specs = specifications.flatMap((s) => s.elements.filter(isValid));
|
|
62
|
+
for (const { kind, style } of element_specs) {
|
|
63
|
+
try {
|
|
64
|
+
const kindName = kind.name;
|
|
65
|
+
c4Specification.kinds[kindName] = {
|
|
66
|
+
...c4Specification.kinds[kindName],
|
|
67
|
+
...toElementStyleExcludeDefaults(style?.props)
|
|
68
|
+
};
|
|
69
|
+
} catch (e) {
|
|
70
|
+
logWarnError(e);
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
|
-
const relations_specs =
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
logWarnError(e);
|
|
84
|
-
}
|
|
73
|
+
const relations_specs = specifications.flatMap((s) => s.relationships.filter(isValid));
|
|
74
|
+
for (const { kind, props } of relations_specs) {
|
|
75
|
+
try {
|
|
76
|
+
const kindName = kind.name;
|
|
77
|
+
c4Specification.relationships[kindName] = {
|
|
78
|
+
...c4Specification.relationships[kindName],
|
|
79
|
+
...toRelationshipStyleExcludeDefaults(props)
|
|
80
|
+
};
|
|
81
|
+
} catch (e) {
|
|
82
|
+
logWarnError(e);
|
|
85
83
|
}
|
|
86
84
|
}
|
|
87
85
|
}
|
|
@@ -155,7 +153,10 @@ export class LikeC4ModelParser {
|
|
|
155
153
|
};
|
|
156
154
|
}
|
|
157
155
|
parseViews(doc) {
|
|
158
|
-
const
|
|
156
|
+
const { isValid } = checksFromDiagnostics(doc);
|
|
157
|
+
const views = doc.parseResult.value.views.flatMap(
|
|
158
|
+
(v) => isValid(v) ? v.views.filter(isValid) : []
|
|
159
|
+
);
|
|
159
160
|
for (const view of views) {
|
|
160
161
|
try {
|
|
161
162
|
const v = this.parseElementView(view);
|
package/dist/module.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { WorkspaceCache, type DefaultSharedModuleContext, type LangiumServices, type LangiumSharedServices, type Module, type PartialLangiumServices } from 'langium';
|
|
2
2
|
import { Rpc } from './Rpc';
|
|
3
|
-
import { LikeC4DocumentLinkProvider, LikeC4DocumentSymbolProvider } from './lsp';
|
|
3
|
+
import { LikeC4CodeLensProvider, LikeC4DocumentLinkProvider, LikeC4DocumentSymbolProvider, LikeC4HoverProvider, LikeC4SemanticTokenProvider } from './lsp';
|
|
4
4
|
import { FqnIndex, LikeC4ModelBuilder, LikeC4ModelLocator, LikeC4ModelParser } from './model';
|
|
5
|
+
import { LikeC4ScopeComputation, LikeC4ScopeProvider } from './references';
|
|
5
6
|
import { LikeC4WorkspaceManager, NodeKindProvider, WorkspaceSymbolProvider } from './shared';
|
|
6
7
|
interface LikeC4AddedSharedServices {
|
|
7
8
|
lsp: {
|
|
@@ -26,8 +27,15 @@ export interface LikeC4AddedServices {
|
|
|
26
27
|
ModelLocator: LikeC4ModelLocator;
|
|
27
28
|
};
|
|
28
29
|
lsp: {
|
|
29
|
-
DocumentLinkProvider: LikeC4DocumentLinkProvider;
|
|
30
30
|
DocumentSymbolProvider: LikeC4DocumentSymbolProvider;
|
|
31
|
+
SemanticTokenProvider: LikeC4SemanticTokenProvider;
|
|
32
|
+
HoverProvider: LikeC4HoverProvider;
|
|
33
|
+
CodeLensProvider: LikeC4CodeLensProvider;
|
|
34
|
+
DocumentLinkProvider: LikeC4DocumentLinkProvider;
|
|
35
|
+
};
|
|
36
|
+
references: {
|
|
37
|
+
ScopeComputation: LikeC4ScopeComputation;
|
|
38
|
+
ScopeProvider: LikeC4ScopeProvider;
|
|
31
39
|
};
|
|
32
40
|
shared?: LikeC4SharedServices;
|
|
33
41
|
}
|
|
@@ -3,8 +3,8 @@ import type { CancellationToken } from 'vscode-languageserver';
|
|
|
3
3
|
import { ast, type LikeC4LangiumDocument } from '../ast';
|
|
4
4
|
type ElementsContainer = ast.Model | ast.ElementBody | ast.ExtendElementBody;
|
|
5
5
|
export declare class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
6
|
-
computeExports(document: LikeC4LangiumDocument, _cancelToken
|
|
7
|
-
computeLocalScopes(document: LikeC4LangiumDocument, _cancelToken
|
|
6
|
+
computeExports(document: LikeC4LangiumDocument, _cancelToken?: CancellationToken): Promise<AstNodeDescription[]>;
|
|
7
|
+
computeLocalScopes(document: LikeC4LangiumDocument, _cancelToken?: CancellationToken): Promise<PrecomputedScopes>;
|
|
8
8
|
protected processContainer(container: ElementsContainer, scopes: PrecomputedScopes, document: LikeC4LangiumDocument): MultiMap<string, AstNodeDescription>;
|
|
9
9
|
}
|
|
10
10
|
export {};
|
|
@@ -2,74 +2,71 @@ import {
|
|
|
2
2
|
DefaultScopeComputation,
|
|
3
3
|
MultiMap
|
|
4
4
|
} from "langium";
|
|
5
|
-
import {
|
|
5
|
+
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
9
|
computeExports(document, _cancelToken) {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
try {
|
|
22
|
-
for (const spec of specifications.flatMap((s) => s.tags)) {
|
|
23
|
-
if (spec.tag && isTruthy(spec.tag.name)) {
|
|
24
|
-
docExports.push(
|
|
25
|
-
this.descriptions.createDescription(spec.tag, "#" + spec.tag.name, document)
|
|
26
|
-
);
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
} catch (e) {
|
|
30
|
-
logError(e);
|
|
31
|
-
}
|
|
32
|
-
try {
|
|
33
|
-
for (const spec of specifications.flatMap((s) => s.relationships)) {
|
|
34
|
-
if (spec.kind && isTruthy(spec.kind.name)) {
|
|
35
|
-
docExports.push(this.descriptions.createDescription(spec.kind, spec.kind.name, document));
|
|
10
|
+
return new Promise((resolve) => {
|
|
11
|
+
const docExports = [];
|
|
12
|
+
const { specifications, models, views } = document.parseResult.value;
|
|
13
|
+
try {
|
|
14
|
+
for (const spec of specifications.flatMap((s) => [...s.elements, ...s.relationships])) {
|
|
15
|
+
if (spec.kind && isTruthy(spec.kind.name)) {
|
|
16
|
+
docExports.push(
|
|
17
|
+
this.descriptions.createDescription(spec.kind, spec.kind.name, document)
|
|
18
|
+
);
|
|
19
|
+
}
|
|
36
20
|
}
|
|
21
|
+
} catch (e) {
|
|
22
|
+
logError(e);
|
|
37
23
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
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
|
+
}
|
|
45
31
|
}
|
|
32
|
+
} catch (e) {
|
|
33
|
+
logError(e);
|
|
46
34
|
}
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
if (isTruthy(viewAst.name)) {
|
|
53
|
-
docExports.push(this.descriptions.createDescription(viewAst, viewAst.name, document));
|
|
35
|
+
try {
|
|
36
|
+
for (const elAst of models.flatMap((m) => m.elements)) {
|
|
37
|
+
if (ast.isElement(elAst) && isTruthy(elAst.name)) {
|
|
38
|
+
docExports.push(this.descriptions.createDescription(elAst, elAst.name, document));
|
|
39
|
+
}
|
|
54
40
|
}
|
|
41
|
+
} catch (e) {
|
|
42
|
+
logError(e);
|
|
55
43
|
}
|
|
56
|
-
} catch (e) {
|
|
57
|
-
logError(e);
|
|
58
|
-
}
|
|
59
|
-
return Promise.resolve(docExports);
|
|
60
|
-
}
|
|
61
|
-
async computeLocalScopes(document, _cancelToken) {
|
|
62
|
-
const root = document.parseResult.value;
|
|
63
|
-
const scopes = new MultiMap();
|
|
64
|
-
for (const model of root.models) {
|
|
65
44
|
try {
|
|
66
|
-
const
|
|
67
|
-
|
|
45
|
+
for (const viewAst of views.flatMap((v) => v.views)) {
|
|
46
|
+
if (isTruthy(viewAst.name)) {
|
|
47
|
+
docExports.push(this.descriptions.createDescription(viewAst, viewAst.name, document));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
68
50
|
} catch (e) {
|
|
69
51
|
logError(e);
|
|
70
52
|
}
|
|
71
|
-
|
|
72
|
-
|
|
53
|
+
resolve(docExports);
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
computeLocalScopes(document, _cancelToken) {
|
|
57
|
+
return new Promise((resolve) => {
|
|
58
|
+
const root = document.parseResult.value;
|
|
59
|
+
const scopes = new MultiMap();
|
|
60
|
+
for (const model of root.models) {
|
|
61
|
+
try {
|
|
62
|
+
const nested = this.processContainer(model, scopes, document);
|
|
63
|
+
scopes.addAll(root, nested.values());
|
|
64
|
+
} catch (e) {
|
|
65
|
+
logError(e);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
resolve(scopes);
|
|
69
|
+
});
|
|
73
70
|
}
|
|
74
71
|
processContainer(container, scopes, document) {
|
|
75
72
|
const localScope = new MultiMap();
|
|
@@ -88,9 +85,13 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
88
85
|
subcontainer = el.body;
|
|
89
86
|
}
|
|
90
87
|
if (subcontainer && subcontainer.elements.length > 0) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
88
|
+
try {
|
|
89
|
+
const nested = this.processContainer(subcontainer, scopes, document);
|
|
90
|
+
for (const [nestedName, desc] of nested) {
|
|
91
|
+
nestedScopes.add(nestedName, desc);
|
|
92
|
+
}
|
|
93
|
+
} catch (e) {
|
|
94
|
+
logError(e);
|
|
94
95
|
}
|
|
95
96
|
}
|
|
96
97
|
}
|
|
@@ -101,22 +101,24 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
101
101
|
const scopes = [];
|
|
102
102
|
const doc = getDocument(context.container);
|
|
103
103
|
const precomputed = doc.precomputedScopes;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if (referenceType === ast.Element) {
|
|
112
|
-
if (ast.isExtendElementBody(container)) {
|
|
113
|
-
scopes.push(this.scopeExtendElement(container.$container));
|
|
104
|
+
if (precomputed) {
|
|
105
|
+
const byReferenceType = (desc) => this.reflection.isSubtype(desc.type, referenceType);
|
|
106
|
+
let container = context.container;
|
|
107
|
+
while (container) {
|
|
108
|
+
const elements = precomputed.get(container).filter(byReferenceType);
|
|
109
|
+
if (elements.length > 0) {
|
|
110
|
+
scopes.push(stream(elements));
|
|
114
111
|
}
|
|
115
|
-
if (ast.
|
|
116
|
-
|
|
112
|
+
if (referenceType === ast.Element) {
|
|
113
|
+
if (ast.isExtendElementBody(container)) {
|
|
114
|
+
scopes.push(this.scopeExtendElement(container.$container));
|
|
115
|
+
}
|
|
116
|
+
if (ast.isElementViewBody(container)) {
|
|
117
|
+
scopes.push(this.scopeElementView(container.$container));
|
|
118
|
+
}
|
|
117
119
|
}
|
|
120
|
+
container = container.$container;
|
|
118
121
|
}
|
|
119
|
-
container = container.$container;
|
|
120
122
|
}
|
|
121
123
|
return scopes.reduceRight((outerScope, elements) => {
|
|
122
124
|
return this.createScope(elements, outerScope);
|
|
@@ -47,10 +47,12 @@ export class NodeKindProvider {
|
|
|
47
47
|
return CompletionItemKind.EnumMember;
|
|
48
48
|
case SymbolKind.TypeParameter:
|
|
49
49
|
return CompletionItemKind.TypeParameter;
|
|
50
|
+
case SymbolKind.Interface:
|
|
51
|
+
return CompletionItemKind.Interface;
|
|
50
52
|
case SymbolKind.Event:
|
|
51
53
|
return CompletionItemKind.Event;
|
|
52
54
|
default:
|
|
53
|
-
return CompletionItemKind.
|
|
55
|
+
return CompletionItemKind.Keyword;
|
|
54
56
|
}
|
|
55
57
|
}
|
|
56
58
|
}
|
|
@@ -4,7 +4,7 @@ export declare function createTestServices(workspace?: string): {
|
|
|
4
4
|
parse: (input: string, uri?: string) => Promise<LikeC4LangiumDocument>;
|
|
5
5
|
validate: (input: string | LikeC4LangiumDocument, uri?: string) => Promise<{
|
|
6
6
|
document: LikeC4LangiumDocument;
|
|
7
|
-
diagnostics: import("vscode-languageserver-types").Diagnostic[];
|
|
7
|
+
diagnostics: (import("vscode-languageserver-types").Diagnostic & import("langium").DiagnosticInfo<import("../ast").LikeC4AstNode>)[];
|
|
8
8
|
warnings: string[];
|
|
9
9
|
errors: string[];
|
|
10
10
|
}>;
|
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.52.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bugs": "https://github.com/likec4/likec4/issues",
|
|
7
7
|
"homepage": "https://likec4.dev",
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"test": "vitest run"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@likec4/core": "0.
|
|
54
|
-
"@likec4/graph": "0.
|
|
53
|
+
"@likec4/core": "0.52.0",
|
|
54
|
+
"@likec4/graph": "0.52.0",
|
|
55
55
|
"langium": "^2.1.3",
|
|
56
56
|
"object-hash": "^3.0.0",
|
|
57
57
|
"p-debounce": "^4.0.0",
|
|
@@ -59,21 +59,21 @@
|
|
|
59
59
|
"rambdax": "^9.1.1",
|
|
60
60
|
"remeda": "^1.29.0",
|
|
61
61
|
"strip-indent": "^4.0.0",
|
|
62
|
-
"type-fest": "^4.8.
|
|
62
|
+
"type-fest": "^4.8.3",
|
|
63
63
|
"ufo": "^1.3.2",
|
|
64
64
|
"vscode-languageserver": "9.0.1",
|
|
65
65
|
"vscode-languageserver-protocol": "3.17.5",
|
|
66
66
|
"vscode-uri": "3.0.8"
|
|
67
67
|
},
|
|
68
68
|
"devDependencies": {
|
|
69
|
-
"@types/node": "^20.10.
|
|
69
|
+
"@types/node": "^20.10.4",
|
|
70
70
|
"@types/object-hash": "^3.0.6",
|
|
71
71
|
"execa": "^8.0.1",
|
|
72
72
|
"langium-cli": "^2.1.0",
|
|
73
73
|
"npm-run-all": "^4.1.5",
|
|
74
|
-
"typescript": "^5.3.
|
|
74
|
+
"typescript": "^5.3.3",
|
|
75
75
|
"unbuild": "^2.0.0",
|
|
76
|
-
"vitest": "^0.
|
|
76
|
+
"vitest": "^1.0.4"
|
|
77
77
|
},
|
|
78
78
|
"packageManager": "yarn@4.0.2",
|
|
79
79
|
"volta": {
|