@likec4/language-server 1.32.1 → 1.33.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 +6 -5
- package/dist/ast.js +3 -0
- package/dist/bundled.mjs +3347 -2559
- package/dist/config/schema.d.ts +2 -2
- package/dist/config/schema.js +8 -11
- package/dist/formatting/LikeC4Formatter.js +2 -2
- package/dist/generated/ast.d.ts +22 -11
- package/dist/generated/ast.js +19 -5
- package/dist/generated/grammar.js +1 -1
- package/dist/lsp/SemanticTokenProvider.js +1 -1
- package/dist/mcp/LikeC4MCPServerFactory.d.ts +4 -0
- package/dist/mcp/LikeC4MCPServerFactory.js +6 -0
- package/dist/mcp/LikeC4MCPTools.js +5 -2
- package/dist/mcp/sseserver/MCPServer.d.ts +4 -2
- package/dist/mcp/sseserver/MCPServer.js +12 -6
- package/dist/mcp/sseserver/with-mcp-server.js +22 -6
- package/dist/model/builder/MergedSpecification.js +8 -4
- package/dist/model/index.d.ts +1 -0
- package/dist/model/index.js +1 -0
- package/dist/model/model-builder.js +20 -19
- package/dist/model/model-parser.d.ts +126 -0
- package/dist/model/parser/Base.d.ts +30 -2
- package/dist/model/parser/Base.js +54 -3
- package/dist/model/parser/DeploymentModelParser.d.ts +14 -0
- package/dist/model/parser/DeploymentModelParser.js +28 -23
- package/dist/model/parser/DeploymentViewParser.d.ts +14 -0
- package/dist/model/parser/DeploymentViewParser.js +15 -6
- package/dist/model/parser/FqnRefParser.d.ts +14 -0
- package/dist/model/parser/FqnRefParser.js +8 -6
- package/dist/model/parser/GlobalsParser.d.ts +14 -0
- package/dist/model/parser/ImportsParser.d.ts +14 -0
- package/dist/model/parser/ModelParser.d.ts +14 -0
- package/dist/model/parser/ModelParser.js +27 -17
- package/dist/model/parser/PredicatesParser.d.ts +14 -0
- package/dist/model/parser/SpecificationParser.d.ts +14 -0
- package/dist/model/parser/SpecificationParser.js +16 -11
- package/dist/model/parser/ValueConverter.d.ts +4 -0
- package/dist/model/parser/ValueConverter.js +12 -0
- package/dist/model/parser/ViewsParser.d.ts +14 -0
- package/dist/model/parser/ViewsParser.js +21 -7
- package/dist/module.d.ts +6 -3
- package/dist/module.js +9 -5
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.js +19 -0
- package/dist/views/configurable-layouter.d.ts +2 -2
- package/dist/views/configurable-layouter.js +23 -27
- package/dist/views/likec4-views.d.ts +2 -3
- package/dist/views/likec4-views.js +28 -50
- package/dist/workspace/ProjectsManager.d.ts +0 -1
- package/dist/workspace/ProjectsManager.js +15 -4
- package/package.json +24 -23
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { DefaultValueConverter, ValueConverter } from "langium";
|
|
2
|
+
export class LikeC4ValueConverter extends DefaultValueConverter {
|
|
3
|
+
runConverter(rule, input, cstNode) {
|
|
4
|
+
if (rule.name === "MarkdownString") {
|
|
5
|
+
if (input.startsWith('"""') && input.endsWith('"""') || input.startsWith(`'''`) && input.endsWith(`'''`)) {
|
|
6
|
+
input = input.slice(3, -3);
|
|
7
|
+
}
|
|
8
|
+
return ValueConverter.convertString(input);
|
|
9
|
+
}
|
|
10
|
+
return super.runConverter(rule, input, cstNode);
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -58,6 +58,7 @@ export declare function ViewsParser<TBase extends WithPredicates & WithDeploymen
|
|
|
58
58
|
getMetadata(metadataAstNode: ast.MetadataProperty | undefined): {
|
|
59
59
|
[key: string]: string;
|
|
60
60
|
} | undefined;
|
|
61
|
+
parseMarkdownOrString(markdownOrString: ast.MarkdownOrString | undefined): c4.MarkdownOrString | undefined;
|
|
61
62
|
convertTags<E extends {
|
|
62
63
|
tags?: ast.Tags;
|
|
63
64
|
}>(withTags?: E | undefined): any;
|
|
@@ -70,6 +71,19 @@ export declare function ViewsParser<TBase extends WithPredicates & WithDeploymen
|
|
|
70
71
|
parseColorLiteral(astNode: ast.ColorLiteral): c4.ColorLiteral | undefined;
|
|
71
72
|
parseElementStyle(elementProps: Array<ast.ElementProperty> | ast.ElementStyleProperty | undefined): import("../../ast").ParsedElementStyle;
|
|
72
73
|
parseStyleProps(styleProps: Array<ast.StyleProperty> | undefined): import("../../ast").ParsedElementStyle;
|
|
74
|
+
parseTitleDescriptionTechnology(inlineProps: {
|
|
75
|
+
title?: string | undefined;
|
|
76
|
+
description?: string | undefined;
|
|
77
|
+
technology?: string | undefined;
|
|
78
|
+
}, bodyProps: {
|
|
79
|
+
title?: ast.MarkdownOrString | undefined;
|
|
80
|
+
description?: ast.MarkdownOrString | undefined;
|
|
81
|
+
technology?: ast.MarkdownOrString | undefined;
|
|
82
|
+
}): {
|
|
83
|
+
title?: string;
|
|
84
|
+
description?: c4.MarkdownOrString;
|
|
85
|
+
technology?: string;
|
|
86
|
+
};
|
|
73
87
|
parseDeploymentView(astNode: ast.DeploymentView): import("../../ast").ParsedAstDeploymentView;
|
|
74
88
|
parseDeploymentViewRule(astRule: ast.DeploymentViewRule): c4.DeploymentViewRule;
|
|
75
89
|
parseDeploymentViewRulePredicate(astRule: ast.DeploymentViewRulePredicate): c4.DeploymentViewPredicate;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import * as c4 from "@likec4/core";
|
|
2
2
|
import { invariant, isNonEmptyArray, nonexhaustive } from "@likec4/core";
|
|
3
|
-
import { isArray, isDefined, isNonNullish, isTruthy } from "remeda";
|
|
3
|
+
import { filter, isArray, isDefined, isNonNullish, isTruthy, mapToObj, pipe } from "remeda";
|
|
4
4
|
import {
|
|
5
5
|
ast,
|
|
6
|
+
parseMarkdownAsString,
|
|
6
7
|
toAutoLayout,
|
|
7
8
|
toColor,
|
|
8
9
|
ViewOps
|
|
@@ -71,8 +72,15 @@ export function ViewsParser(B) {
|
|
|
71
72
|
viewOf ?? ""
|
|
72
73
|
);
|
|
73
74
|
}
|
|
74
|
-
const title =
|
|
75
|
-
|
|
75
|
+
const { title = null, description = null } = this.parseTitleDescriptionTechnology(
|
|
76
|
+
{},
|
|
77
|
+
pipe(
|
|
78
|
+
body.props,
|
|
79
|
+
filter((p) => this.isValid(p)),
|
|
80
|
+
filter(ast.isViewStringProperty),
|
|
81
|
+
mapToObj((p) => [p.key, p.value])
|
|
82
|
+
)
|
|
83
|
+
);
|
|
76
84
|
const tags = this.convertTags(body);
|
|
77
85
|
const links = this.convertLinks(body);
|
|
78
86
|
const manualLayout = parseViewManualLayout(astNode);
|
|
@@ -191,7 +199,7 @@ export function ViewsParser(B) {
|
|
|
191
199
|
(e) => c4.ModelExpression.isFqnExpr(e)
|
|
192
200
|
);
|
|
193
201
|
const style = this.parseStyleProps(astRule.props.filter(ast.isStyleProperty));
|
|
194
|
-
const notation = removeIndent(astRule.props.find(ast.isNotationProperty)?.value);
|
|
202
|
+
const notation = removeIndent(parseMarkdownAsString(astRule.props.find(ast.isNotationProperty)?.value));
|
|
195
203
|
return {
|
|
196
204
|
targets,
|
|
197
205
|
style,
|
|
@@ -216,8 +224,14 @@ export function ViewsParser(B) {
|
|
|
216
224
|
astPath
|
|
217
225
|
);
|
|
218
226
|
}
|
|
219
|
-
const title =
|
|
220
|
-
|
|
227
|
+
const { title = null, description = null } = this.parseTitleDescriptionTechnology(
|
|
228
|
+
{},
|
|
229
|
+
pipe(
|
|
230
|
+
props,
|
|
231
|
+
filter(ast.isViewStringProperty),
|
|
232
|
+
mapToObj((p) => [p.key, p.value])
|
|
233
|
+
)
|
|
234
|
+
);
|
|
221
235
|
const tags = this.convertTags(body);
|
|
222
236
|
const links = this.convertLinks(body);
|
|
223
237
|
ViewOps.writeId(astNode, id);
|
|
@@ -338,7 +352,7 @@ export function ViewsParser(B) {
|
|
|
338
352
|
case ast.isNotationProperty(prop):
|
|
339
353
|
case ast.isNotesProperty(prop): {
|
|
340
354
|
if (isDefined(prop.value)) {
|
|
341
|
-
step[prop.key] = removeIndent(prop.value) ?? "";
|
|
355
|
+
step[prop.key] = removeIndent(parseMarkdownAsString(prop.value)) ?? "";
|
|
342
356
|
}
|
|
343
357
|
break;
|
|
344
358
|
}
|
package/dist/module.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { QueueGraphvizLayoter } from '@likec4/layouts';
|
|
2
2
|
import { type Module, WorkspaceCache } from 'langium';
|
|
3
3
|
import { type DefaultSharedModuleContext, type LangiumServices, type LangiumSharedServices, type PartialLangiumServices } from 'langium/lsp';
|
|
4
4
|
import { LikeC4DocumentationProvider } from './documentation';
|
|
@@ -6,7 +6,7 @@ import { type LikeC4LanguageServices } from './LikeC4LanguageServices';
|
|
|
6
6
|
import { LikeC4CodeLensProvider, LikeC4CompletionProvider, LikeC4DocumentHighlightProvider, LikeC4DocumentLinkProvider, LikeC4DocumentSymbolProvider, LikeC4HoverProvider, LikeC4SemanticTokenProvider } from './lsp';
|
|
7
7
|
import { type LikeC4MCPServer, type LikeC4MCPServerFactory } from './mcp/LikeC4MCPServerFactory';
|
|
8
8
|
import { type LikeC4MCPTools } from './mcp/LikeC4MCPTools';
|
|
9
|
-
import { type LikeC4ModelBuilder, DeploymentsIndex, FqnIndex, LikeC4ModelLocator, LikeC4ModelParser } from './model';
|
|
9
|
+
import { type LikeC4ModelBuilder, DeploymentsIndex, FqnIndex, LikeC4ModelLocator, LikeC4ModelParser, LikeC4ValueConverter } from './model';
|
|
10
10
|
import { LikeC4ModelChanges } from './model-change/ModelChanges';
|
|
11
11
|
import { LikeC4NameProvider, LikeC4ScopeComputation, LikeC4ScopeProvider } from './references';
|
|
12
12
|
import { Rpc } from './Rpc';
|
|
@@ -43,7 +43,7 @@ export interface LikeC4AddedServices {
|
|
|
43
43
|
likec4: {
|
|
44
44
|
LanguageServices: LikeC4LanguageServices;
|
|
45
45
|
Views: LikeC4Views;
|
|
46
|
-
Layouter:
|
|
46
|
+
Layouter: QueueGraphvizLayoter;
|
|
47
47
|
DeploymentsIndex: DeploymentsIndex;
|
|
48
48
|
FqnIndex: FqnIndex;
|
|
49
49
|
ModelParser: LikeC4ModelParser;
|
|
@@ -66,6 +66,9 @@ export interface LikeC4AddedServices {
|
|
|
66
66
|
ScopeProvider: LikeC4ScopeProvider;
|
|
67
67
|
};
|
|
68
68
|
shared?: LikeC4SharedServices;
|
|
69
|
+
parser: {
|
|
70
|
+
ValueConverter: LikeC4ValueConverter;
|
|
71
|
+
};
|
|
69
72
|
}
|
|
70
73
|
export type LikeC4Services = LangiumServices & LikeC4AddedServices;
|
|
71
74
|
export declare const LikeC4Module: Module<LikeC4Services, PartialLangiumServices & LikeC4AddedServices>;
|
package/dist/module.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GraphvizWasmAdapter, QueueGraphvizLayoter } from "@likec4/layouts";
|
|
2
2
|
import {
|
|
3
3
|
DocumentState,
|
|
4
4
|
EmptyFileSystem,
|
|
@@ -16,7 +16,6 @@ import {
|
|
|
16
16
|
LikeC4GeneratedSharedModule
|
|
17
17
|
} from "./generated/module.js";
|
|
18
18
|
import { DefaultLikeC4LanguageServices } from "./LikeC4LanguageServices.js";
|
|
19
|
-
import { logger } from "./logger.js";
|
|
20
19
|
import {
|
|
21
20
|
LikeC4CodeLensProvider,
|
|
22
21
|
LikeC4CompletionProvider,
|
|
@@ -36,7 +35,8 @@ import {
|
|
|
36
35
|
DeploymentsIndex,
|
|
37
36
|
FqnIndex,
|
|
38
37
|
LikeC4ModelLocator,
|
|
39
|
-
LikeC4ModelParser
|
|
38
|
+
LikeC4ModelParser,
|
|
39
|
+
LikeC4ValueConverter
|
|
40
40
|
} from "./model/index.js";
|
|
41
41
|
import { LikeC4ModelChanges } from "./model-change/ModelChanges.js";
|
|
42
42
|
import {
|
|
@@ -87,8 +87,9 @@ export const LikeC4Module = {
|
|
|
87
87
|
likec4: {
|
|
88
88
|
LanguageServices: bind(DefaultLikeC4LanguageServices),
|
|
89
89
|
Layouter: (_services) => {
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
return new QueueGraphvizLayoter({
|
|
91
|
+
graphviz: new GraphvizWasmAdapter()
|
|
92
|
+
});
|
|
92
93
|
},
|
|
93
94
|
Views: bind(DefaultLikeC4Views),
|
|
94
95
|
DeploymentsIndex: bind(DeploymentsIndex),
|
|
@@ -116,6 +117,9 @@ export const LikeC4Module = {
|
|
|
116
117
|
NameProvider: bind(LikeC4NameProvider),
|
|
117
118
|
ScopeComputation: bind(LikeC4ScopeComputation),
|
|
118
119
|
ScopeProvider: bind(LikeC4ScopeProvider)
|
|
120
|
+
},
|
|
121
|
+
parser: {
|
|
122
|
+
ValueConverter: bind(LikeC4ValueConverter)
|
|
119
123
|
}
|
|
120
124
|
};
|
|
121
125
|
export function createCustomLanguageServices(context, module, module2, module3) {
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -4,3 +4,8 @@ export * from './fqnRef';
|
|
|
4
4
|
export * from './projectId';
|
|
5
5
|
export * from './stringHash';
|
|
6
6
|
export declare function safeCall<T>(fn: () => T): T | undefined;
|
|
7
|
+
export declare function performanceNow(): number;
|
|
8
|
+
export declare function performanceMark(): {
|
|
9
|
+
readonly ms: number;
|
|
10
|
+
readonly pretty: string;
|
|
11
|
+
};
|
package/dist/utils/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import prettyMs from "pretty-ms";
|
|
1
2
|
import { logger } from "../logger.js";
|
|
2
3
|
export * from "./disposable.js";
|
|
3
4
|
export * from "./elementRef.js";
|
|
@@ -12,3 +13,21 @@ export function safeCall(fn) {
|
|
|
12
13
|
return void 0;
|
|
13
14
|
}
|
|
14
15
|
}
|
|
16
|
+
export function performanceNow() {
|
|
17
|
+
try {
|
|
18
|
+
return performance.now();
|
|
19
|
+
} catch (e) {
|
|
20
|
+
return Date.now();
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
export function performanceMark() {
|
|
24
|
+
const t0 = performanceNow();
|
|
25
|
+
return {
|
|
26
|
+
get ms() {
|
|
27
|
+
return performanceNow() - t0;
|
|
28
|
+
},
|
|
29
|
+
get pretty() {
|
|
30
|
+
return prettyMs(performanceNow() - t0);
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { QueueGraphvizLayoter } from '@likec4/layouts';
|
|
2
2
|
import type { LikeC4Services } from '../module';
|
|
3
3
|
export declare const ConfigurableLayouter: {
|
|
4
4
|
likec4: {
|
|
5
|
-
Layouter(services: LikeC4Services):
|
|
5
|
+
Layouter(services: LikeC4Services): QueueGraphvizLayoter;
|
|
6
6
|
};
|
|
7
7
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { GraphvizWasmAdapter, QueueGraphvizLayoter } from "@likec4/layouts";
|
|
2
2
|
import { GraphvizBinaryAdapter } from "@likec4/layouts/graphviz/binary";
|
|
3
3
|
import { isEmpty } from "remeda";
|
|
4
4
|
import which from "which";
|
|
@@ -15,39 +15,35 @@ export const ConfigurableLayouter = {
|
|
|
15
15
|
likec4: {
|
|
16
16
|
Layouter(services) {
|
|
17
17
|
logger.debug("Creating ConfigurableLayouter");
|
|
18
|
-
const
|
|
19
|
-
const layouter = new GraphvizLayouter(wasmAdapter);
|
|
20
|
-
const langId = services.LanguageMetaData.languageId;
|
|
18
|
+
const layouter = new QueueGraphvizLayoter();
|
|
21
19
|
services.shared.workspace.ConfigurationProvider.onConfigurationSectionUpdate((update) => {
|
|
22
20
|
logger.debug("Configuration update: {update}", { update });
|
|
23
|
-
if (update.section
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
21
|
+
if (update.section !== services.LanguageMetaData.languageId) {
|
|
22
|
+
logger.debug(`Ignoring configuration update as it is not for ${services.LanguageMetaData.languageId}`);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
const { mode, path } = update.configuration.graphviz ?? {
|
|
27
|
+
mode: "wasm",
|
|
28
|
+
path: ""
|
|
29
|
+
};
|
|
30
|
+
if (mode !== "wasm") {
|
|
34
31
|
let binaryPath = isEmpty(path) ? graphvizBinPath() : path;
|
|
35
|
-
if (binaryPath
|
|
36
|
-
layouter.changePort(
|
|
37
|
-
logger.
|
|
38
|
-
services.shared.lsp.Connection?.window.showWarningMessage(
|
|
39
|
-
"No Graphviz binaries found on PATH, set path to binaries in settings."
|
|
40
|
-
);
|
|
32
|
+
if (!isEmpty(binaryPath)) {
|
|
33
|
+
layouter.changePort(new GraphvizBinaryAdapter(binaryPath));
|
|
34
|
+
logger.info`use graphviz binary: ${binaryPath}`;
|
|
41
35
|
return;
|
|
42
36
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
37
|
+
logger.warn(`No Graphviz binaries found on PATH, use graphviz wasm`);
|
|
38
|
+
services.shared.lsp.Connection?.window.showWarningMessage(
|
|
39
|
+
"No Graphviz binaries found on PATH, set path to binaries in settings."
|
|
40
|
+
);
|
|
47
41
|
}
|
|
48
|
-
|
|
42
|
+
layouter.changePort(new GraphvizWasmAdapter());
|
|
43
|
+
logger.info("use graphviz wasm");
|
|
44
|
+
} catch (error) {
|
|
45
|
+
logger.error("Failed to update configuration", { error });
|
|
49
46
|
}
|
|
50
|
-
logger.warn("Unexpected configuration update: {update}", { update });
|
|
51
47
|
});
|
|
52
48
|
return layouter;
|
|
53
49
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ComputedView, DiagramView, ProjectId, ViewId } from '@likec4/core';
|
|
2
|
-
import { GraphvizLayouter } from '@likec4/layouts';
|
|
2
|
+
import { type QueueGraphvizLayoter, GraphvizLayouter } from '@likec4/layouts';
|
|
3
3
|
import { CancellationToken } from 'vscode-jsonrpc';
|
|
4
4
|
import type { LikeC4Services } from '../module';
|
|
5
5
|
export type GraphvizOut = {
|
|
@@ -24,9 +24,8 @@ export declare class DefaultLikeC4Views implements LikeC4Views {
|
|
|
24
24
|
private cache;
|
|
25
25
|
private viewsWithReportedErrors;
|
|
26
26
|
private ModelBuilder;
|
|
27
|
-
private queue;
|
|
28
27
|
constructor(services: LikeC4Services);
|
|
29
|
-
get layouter():
|
|
28
|
+
get layouter(): QueueGraphvizLayoter;
|
|
30
29
|
computedViews(projectId?: ProjectId | undefined, cancelToken?: CancellationToken): Promise<ComputedView[]>;
|
|
31
30
|
layoutAllViews(projectId?: ProjectId | undefined, cancelToken?: CancellationToken): Promise<Array<Readonly<GraphvizOut>>>;
|
|
32
31
|
layoutView(viewId: ViewId, projectId?: ProjectId | undefined, cancelToken?: CancellationToken): Promise<GraphvizOut | null>;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { loggable } from "@likec4/log";
|
|
2
|
-
import PQueue from "p-queue";
|
|
3
|
-
import prettyMs from "pretty-ms";
|
|
4
2
|
import { values } from "remeda";
|
|
5
3
|
import { CancellationToken } from "vscode-jsonrpc";
|
|
6
4
|
import { logError, logger as rootLogger, logWarnError } from "../logger.js";
|
|
5
|
+
import { performanceMark } from "../utils/index.js";
|
|
6
|
+
const viewsLogger = rootLogger.getChild("views");
|
|
7
7
|
export class DefaultLikeC4Views {
|
|
8
8
|
constructor(services) {
|
|
9
9
|
this.services = services;
|
|
@@ -12,7 +12,6 @@ export class DefaultLikeC4Views {
|
|
|
12
12
|
cache = /* @__PURE__ */ new WeakMap();
|
|
13
13
|
viewsWithReportedErrors = /* @__PURE__ */ new Set();
|
|
14
14
|
ModelBuilder;
|
|
15
|
-
queue = new PQueue({ concurrency: 2, timeout: 2e4, throwOnTimeout: true });
|
|
16
15
|
get layouter() {
|
|
17
16
|
return this.services.likec4.Layouter;
|
|
18
17
|
}
|
|
@@ -26,16 +25,10 @@ export class DefaultLikeC4Views {
|
|
|
26
25
|
if (views.length === 0) {
|
|
27
26
|
return [];
|
|
28
27
|
}
|
|
29
|
-
const
|
|
28
|
+
const m0 = performanceMark();
|
|
29
|
+
const logger = projectId ? viewsLogger.getChild(projectId) : viewsLogger;
|
|
30
30
|
logger.debug`layoutAll: ${views.length} views`;
|
|
31
|
-
|
|
32
|
-
logger.debug`wait for previous layouts to finish`;
|
|
33
|
-
await this.queue.onIdle();
|
|
34
|
-
}
|
|
35
|
-
if (this.layouter.port.concurrency !== this.queue.concurrency) {
|
|
36
|
-
this.queue.concurrency = this.layouter.port.concurrency;
|
|
37
|
-
logger.debug`set queue concurrency to ${this.layouter.port.concurrency}`;
|
|
38
|
-
}
|
|
31
|
+
const tasks = [];
|
|
39
32
|
const specification = likeC4Model.$data.specification;
|
|
40
33
|
const results = [];
|
|
41
34
|
for (const view of views) {
|
|
@@ -45,40 +38,35 @@ export class DefaultLikeC4Views {
|
|
|
45
38
|
results.push(cached);
|
|
46
39
|
continue;
|
|
47
40
|
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
41
|
+
tasks.push({
|
|
42
|
+
view,
|
|
43
|
+
specification
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
if (tasks.length > 0) {
|
|
47
|
+
await this.layouter.batchLayout({
|
|
48
|
+
batch: tasks,
|
|
49
|
+
onSuccess: (task, result) => {
|
|
50
|
+
this.viewsWithReportedErrors.delete(task.view.id);
|
|
51
|
+
this.cache.set(task.view, result);
|
|
52
|
+
results.push(result);
|
|
53
|
+
},
|
|
54
|
+
onError: (task, error) => {
|
|
55
|
+
logger.warn(`Fail layout view ${task.view.id}`, { error });
|
|
60
56
|
}
|
|
61
|
-
this.viewsWithReportedErrors.delete(view.id);
|
|
62
|
-
logger.debug`done layout view ${view.id}`;
|
|
63
|
-
this.cache.set(view, result);
|
|
64
|
-
results.push(result);
|
|
65
|
-
}).catch((e) => {
|
|
66
|
-
logger.error(`Fail layout view ${view.id}`, { e });
|
|
67
|
-
this.cache.delete(view);
|
|
68
57
|
});
|
|
69
58
|
}
|
|
70
|
-
await this.queue.onIdle();
|
|
71
59
|
if (results.length !== views.length) {
|
|
72
|
-
logger.warn`layouted ${results.length} of ${views.length} views`;
|
|
60
|
+
logger.warn`layouted ${results.length} of ${views.length} views in ${m0.pretty}`;
|
|
73
61
|
} else if (results.length > 0) {
|
|
74
|
-
logger.debug`layouted all ${results.length} views`;
|
|
62
|
+
logger.debug`layouted all ${results.length} views in ${m0.pretty}`;
|
|
75
63
|
}
|
|
76
64
|
return results;
|
|
77
65
|
}
|
|
78
66
|
async layoutView(viewId, projectId, cancelToken = CancellationToken.None) {
|
|
79
67
|
const model = await this.ModelBuilder.buildLikeC4Model(projectId, cancelToken);
|
|
80
68
|
const view = model.findView(viewId)?.$view;
|
|
81
|
-
const logger =
|
|
69
|
+
const logger = projectId ? viewsLogger.getChild(projectId) : viewsLogger;
|
|
82
70
|
if (!view) {
|
|
83
71
|
logger.warn`layoutView ${viewId} not found`;
|
|
84
72
|
return null;
|
|
@@ -89,24 +77,14 @@ export class DefaultLikeC4Views {
|
|
|
89
77
|
return await Promise.resolve(cached);
|
|
90
78
|
}
|
|
91
79
|
try {
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
}
|
|
97
|
-
const result = await this.queue.add(async () => {
|
|
98
|
-
logger.debug`layouting view ${view.id}...`;
|
|
99
|
-
return await this.layouter.layout({
|
|
100
|
-
view,
|
|
101
|
-
specification: model.$data.specification
|
|
102
|
-
});
|
|
80
|
+
const m0 = performanceMark();
|
|
81
|
+
const result = await this.layouter.layout({
|
|
82
|
+
view,
|
|
83
|
+
specification: model.$data.specification
|
|
103
84
|
});
|
|
104
|
-
if (!result) {
|
|
105
|
-
throw new Error(`Failed to layout view ${viewId}`);
|
|
106
|
-
}
|
|
107
85
|
this.viewsWithReportedErrors.delete(viewId);
|
|
108
86
|
this.cache.set(view, result);
|
|
109
|
-
logger.debug(`layout {viewId} ready in ${
|
|
87
|
+
logger.debug(`layout {viewId} ready in ${m0.pretty}`, { viewId });
|
|
110
88
|
return result;
|
|
111
89
|
} catch (e) {
|
|
112
90
|
if (!this.viewsWithReportedErrors.has(viewId)) {
|
|
@@ -50,7 +50,6 @@ export declare class ProjectsManager {
|
|
|
50
50
|
* Checks if the provided file system entry is a valid project config file.
|
|
51
51
|
*
|
|
52
52
|
* @param entry The file system entry to check
|
|
53
|
-
* @returns {boolean} Returns true if the entry is a valid config file, false otherwise.
|
|
54
53
|
*/
|
|
55
54
|
loadConfigFile(entry: FileSystemNode): Promise<Project | undefined>;
|
|
56
55
|
registerProject(configFile: URI): Promise<Project>;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { BiMap, invariant, nonNullable } from "@likec4/core";
|
|
2
|
+
import { loggable } from "@likec4/log";
|
|
2
3
|
import { URI, WorkspaceCache } from "langium";
|
|
3
4
|
import picomatch from "picomatch/posix";
|
|
4
5
|
import { hasAtLeast, isNullish, map, pipe, prop, sortBy } from "remeda";
|
|
@@ -9,7 +10,7 @@ import {
|
|
|
9
10
|
withoutProtocol,
|
|
10
11
|
withProtocol
|
|
11
12
|
} from "ufo";
|
|
12
|
-
import { parseConfigJson } from "../config/index.js";
|
|
13
|
+
import { parseConfigJson, validateConfig } from "../config/index.js";
|
|
13
14
|
import { logger as mainLogger } from "../logger.js";
|
|
14
15
|
const logger = mainLogger.getChild("ProjectsManager");
|
|
15
16
|
export class ProjectsManager {
|
|
@@ -115,14 +116,23 @@ export class ProjectsManager {
|
|
|
115
116
|
* Checks if the provided file system entry is a valid project config file.
|
|
116
117
|
*
|
|
117
118
|
* @param entry The file system entry to check
|
|
118
|
-
* @returns {boolean} Returns true if the entry is a valid config file, false otherwise.
|
|
119
119
|
*/
|
|
120
120
|
async loadConfigFile(entry) {
|
|
121
121
|
if (entry.isDirectory) {
|
|
122
122
|
return void 0;
|
|
123
123
|
}
|
|
124
124
|
if (this.isConfigFile(entry)) {
|
|
125
|
-
|
|
125
|
+
try {
|
|
126
|
+
return await this.registerProject(entry.uri);
|
|
127
|
+
} catch (error) {
|
|
128
|
+
this.services.lsp.Connection?.window.showErrorMessage(
|
|
129
|
+
`LikeC4: Failed to register project at ${entry.uri.toString()}
|
|
130
|
+
|
|
131
|
+
${loggable(error)}`
|
|
132
|
+
);
|
|
133
|
+
logger.error("Failed to register project at {uri}", { uri: entry.uri.toString(), error });
|
|
134
|
+
return void 0;
|
|
135
|
+
}
|
|
126
136
|
}
|
|
127
137
|
return void 0;
|
|
128
138
|
}
|
|
@@ -135,7 +145,8 @@ export class ProjectsManager {
|
|
|
135
145
|
const folderUri2 = configFile.with({ path });
|
|
136
146
|
return this.registerProject({ config: config2, folderUri: folderUri2 });
|
|
137
147
|
}
|
|
138
|
-
const
|
|
148
|
+
const config = validateConfig(opts.config);
|
|
149
|
+
const { folderUri } = opts;
|
|
139
150
|
let id = config.name;
|
|
140
151
|
let i = 1;
|
|
141
152
|
while (this.projectIdToFolder.has(id)) {
|
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.33.0",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bugs": "https://github.com/likec4/likec4/issues",
|
|
7
7
|
"homepage": "https://likec4.dev",
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"directory": "packages/language-server"
|
|
21
21
|
},
|
|
22
22
|
"engines": {
|
|
23
|
-
"node": ">=20.19.
|
|
23
|
+
"node": ">=20.19.3"
|
|
24
24
|
},
|
|
25
25
|
"engineStrict": true,
|
|
26
26
|
"type": "module",
|
|
@@ -93,50 +93,50 @@
|
|
|
93
93
|
},
|
|
94
94
|
"devDependencies": {
|
|
95
95
|
"@types/chroma-js": "^3.1.1",
|
|
96
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
97
|
-
"@msgpack/msgpack": "^3.1.
|
|
96
|
+
"@modelcontextprotocol/sdk": "^1.13.1",
|
|
97
|
+
"@msgpack/msgpack": "^3.1.2",
|
|
98
98
|
"@smithy/util-base64": "^4.0.0",
|
|
99
|
-
"@types/express": "^5.0.
|
|
100
|
-
"@types/node": "~20.19.
|
|
99
|
+
"@types/express": "^5.0.3",
|
|
100
|
+
"@types/node": "~20.19.1",
|
|
101
101
|
"@types/picomatch": "^4.0.0",
|
|
102
102
|
"@types/which": "^3.0.4",
|
|
103
103
|
"chroma-js": "^3.1.2",
|
|
104
104
|
"esm-env": "^1.2.2",
|
|
105
105
|
"express": "^5.1.0",
|
|
106
106
|
"fast-equals": "^5.2.2",
|
|
107
|
-
"fdir": "
|
|
107
|
+
"fdir": "6.4.6",
|
|
108
108
|
"indent-string": "^5.0.0",
|
|
109
109
|
"json5": "^2.2.3",
|
|
110
110
|
"langium": "3.5.0",
|
|
111
111
|
"langium-cli": "3.5.0",
|
|
112
112
|
"natural-compare-lite": "^1.4.0",
|
|
113
|
-
"p-debounce": "
|
|
114
|
-
"p-queue": "
|
|
115
|
-
"p-timeout": "
|
|
113
|
+
"p-debounce": "4.0.0",
|
|
114
|
+
"p-queue": "8.1.0",
|
|
115
|
+
"p-timeout": "6.1.4",
|
|
116
116
|
"picomatch": "^4.0.2",
|
|
117
117
|
"pretty-ms": "^9.2.0",
|
|
118
|
-
"remeda": "^2.23.
|
|
118
|
+
"remeda": "^2.23.1",
|
|
119
119
|
"strip-indent": "^4.0.0",
|
|
120
|
-
"tsx": "
|
|
121
|
-
"turbo": "
|
|
120
|
+
"tsx": "4.19.4",
|
|
121
|
+
"turbo": "2.5.4",
|
|
122
122
|
"type-fest": "^4.41.0",
|
|
123
|
-
"typescript": "
|
|
123
|
+
"typescript": "5.8.3",
|
|
124
124
|
"ufo": "^1.6.1",
|
|
125
|
-
"unbuild": "
|
|
126
|
-
"valibot": "^1.
|
|
127
|
-
"vitest": "3.2.
|
|
125
|
+
"unbuild": "3.5.0",
|
|
126
|
+
"valibot": "^1.1.0",
|
|
127
|
+
"vitest": "3.2.4",
|
|
128
128
|
"vscode-jsonrpc": "8.2.0",
|
|
129
129
|
"vscode-languageserver": "9.0.1",
|
|
130
130
|
"vscode-languageserver-protocol": "3.17.5",
|
|
131
131
|
"vscode-languageserver-types": "3.17.5",
|
|
132
132
|
"vscode-uri": "3.1.0",
|
|
133
133
|
"which": "^5.0.0",
|
|
134
|
-
"zod": "
|
|
135
|
-
"@likec4/core": "1.
|
|
136
|
-
"@likec4/
|
|
137
|
-
"@likec4/
|
|
138
|
-
"@likec4/tsconfig": "1.
|
|
139
|
-
"@likec4/
|
|
134
|
+
"zod": "3.25.67",
|
|
135
|
+
"@likec4/core": "1.33.0",
|
|
136
|
+
"@likec4/layouts": "1.33.0",
|
|
137
|
+
"@likec4/log": "1.33.0",
|
|
138
|
+
"@likec4/tsconfig": "1.33.0",
|
|
139
|
+
"@likec4/icons": "1.33.0"
|
|
140
140
|
},
|
|
141
141
|
"scripts": {
|
|
142
142
|
"typecheck": "tsc -b --verbose",
|
|
@@ -148,6 +148,7 @@
|
|
|
148
148
|
"generate": "langium generate && tsx scripts/generate-icons.ts",
|
|
149
149
|
"dev": "run-p \"watch:*\"",
|
|
150
150
|
"lint": "run -T eslint src/ --fix",
|
|
151
|
+
"lint:package": "pnpx publint ./package.tgz",
|
|
151
152
|
"clean": "pnpm rimraf dist contrib lib src/generated src/generated-lib",
|
|
152
153
|
"test": "vitest run --no-isolate",
|
|
153
154
|
"test-dbg": "vitest run --no-isolate -t formating",
|