@likec4/language-server 1.32.0 → 1.32.2
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 -0
- package/dist/ast.js +4 -1
- package/dist/bundled.mjs +2314 -2312
- 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 +30 -6
- package/dist/generated/ast.js +44 -9
- package/dist/generated/grammar.js +1 -1
- package/dist/mcp/LikeC4MCPServerFactory.d.ts +4 -0
- package/dist/mcp/LikeC4MCPServerFactory.js +6 -0
- 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/model-builder.js +20 -19
- package/dist/model/model-parser.d.ts +9 -0
- package/dist/model/parser/Base.d.ts +1 -0
- package/dist/model/parser/Base.js +22 -0
- package/dist/model/parser/DeploymentModelParser.d.ts +1 -0
- package/dist/model/parser/DeploymentModelParser.js +7 -5
- package/dist/model/parser/DeploymentViewParser.d.ts +1 -0
- package/dist/model/parser/FqnRefParser.d.ts +1 -0
- package/dist/model/parser/GlobalsParser.d.ts +1 -0
- package/dist/model/parser/ImportsParser.d.ts +1 -0
- package/dist/model/parser/ModelParser.d.ts +1 -0
- package/dist/model/parser/ModelParser.js +7 -5
- package/dist/model/parser/PredicatesParser.d.ts +1 -0
- package/dist/model/parser/SpecificationParser.d.ts +1 -0
- package/dist/model/parser/SpecificationParser.js +4 -2
- package/dist/model/parser/ViewsParser.d.ts +1 -0
- package/dist/module.d.ts +2 -2
- package/dist/module.js +4 -4
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.js +19 -0
- package/dist/validation/index.d.ts +1 -1
- package/dist/validation/index.js +10 -3
- package/dist/validation/property-checks.d.ts +1 -0
- package/dist/validation/property-checks.js +62 -0
- package/dist/views/configurable-layouter.d.ts +2 -2
- package/dist/views/configurable-layouter.js +4 -2
- package/dist/views/likec4-views.d.ts +2 -3
- package/dist/views/likec4-views.js +29 -50
- package/dist/workspace/ProjectsManager.d.ts +0 -1
- package/dist/workspace/ProjectsManager.js +15 -4
- package/package.json +16 -16
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
|
+
}
|
|
@@ -3,7 +3,7 @@ import { type LikeC4LangiumDocument, ast } from '../ast';
|
|
|
3
3
|
import type { LikeC4Services } from '../module';
|
|
4
4
|
type Guard<N extends AstNode> = (n: AstNode) => n is N;
|
|
5
5
|
type Guarded<G> = G extends Guard<infer N> ? N : never;
|
|
6
|
-
declare const isValidatableAstNode: (n: AstNode) => n is ast.DeployedInstance | ast.DeploymentNode | ast.DeploymentViewRulePredicate | ast.DeploymentViewRuleStyle | ast.ViewRuleAutoLayout | ast.DynamicViewGlobalPredicateRef | ast.DynamicViewIncludePredicate | ast.ViewRuleGlobalStyle | ast.ViewRuleStyle | ast.ElementStringProperty | ast.ElementStyleProperty | ast.IconProperty | ast.LinkProperty | ast.MetadataBody | ast.ElementKindExpression | ast.ElementTagExpression | ast.FqnRefExpr | ast.WildcardExpression | ast.FqnExprWhere | ast.FqnExprWith | ast.DirectedRelationExpr | ast.InOutRelationExpr | ast.IncomingRelationExpr | ast.OutgoingRelationExpr | ast.RelationExprWhere | ast.RelationExprWith | ast.Element | ast.ExtendDeployment | ast.ExtendElement | ast.Imported | ast.DeploymentView | ast.DynamicView | ast.ElementView | ast.RelationStringProperty | ast.ArrowProperty | ast.ColorProperty | ast.LineProperty | ast.PaddingSizeProperty | ast.ShapeSizeProperty | ast.TextSizeProperty | ast.MetadataAttribute | ast.NotationProperty | ast.NotesProperty | ast.SpecificationElementStringProperty | ast.SpecificationRelationshipStringProperty | ast.ViewStringProperty | ast.BorderProperty | ast.MultipleProperty | ast.OpacityProperty | ast.ShapeProperty | ast.ViewRuleGlobalPredicateRef | ast.ViewRuleGroup | ast.ViewRulePredicate | ast.SpecificationRelationshipKind | ast.GlobalStyle | ast.SpecificationColor | ast.NavigateToProperty | ast.DynamicViewStep | ast.ElementRef | ast.DeploymentRelation | ast.Tags | ast.SpecificationDeploymentNodeKind | ast.DynamicViewParallelSteps | ast.GlobalDynamicPredicateGroup | ast.Relation | ast.SpecificationElementKind | ast.Globals | ast.GlobalPredicateGroup | ast.GlobalStyleGroup | ast.
|
|
6
|
+
declare const isValidatableAstNode: (n: AstNode) => n is ast.HexColor | ast.RGBAColor | ast.DeployedInstance | ast.DeploymentNode | ast.DeploymentViewRulePredicate | ast.DeploymentViewRuleStyle | ast.ViewRuleAutoLayout | ast.DynamicViewGlobalPredicateRef | ast.DynamicViewIncludePredicate | ast.ViewRuleGlobalStyle | ast.ViewRuleStyle | ast.ElementStringProperty | ast.ElementStyleProperty | ast.IconProperty | ast.LinkProperty | ast.MetadataBody | ast.ElementKindExpression | ast.ElementTagExpression | ast.FqnRefExpr | ast.WildcardExpression | ast.FqnExprWhere | ast.FqnExprWith | ast.DirectedRelationExpr | ast.InOutRelationExpr | ast.IncomingRelationExpr | ast.OutgoingRelationExpr | ast.RelationExprWhere | ast.RelationExprWith | ast.Element | ast.ExtendDeployment | ast.ExtendElement | ast.Imported | ast.DeploymentView | ast.DynamicView | ast.ElementView | ast.RelationStringProperty | ast.ArrowProperty | ast.ColorProperty | ast.LineProperty | ast.PaddingSizeProperty | ast.ShapeSizeProperty | ast.TextSizeProperty | ast.MetadataAttribute | ast.NotationProperty | ast.NotesProperty | ast.SpecificationElementStringProperty | ast.SpecificationRelationshipStringProperty | ast.ViewStringProperty | ast.BorderProperty | ast.MultipleProperty | ast.OpacityProperty | ast.ShapeProperty | ast.ViewRuleGlobalPredicateRef | ast.ViewRuleGroup | ast.ViewRulePredicate | ast.SpecificationRelationshipKind | ast.GlobalStyle | ast.SpecificationColor | ast.NavigateToProperty | ast.DynamicViewStep | ast.ElementRef | ast.DeploymentRelation | ast.Tags | ast.SpecificationDeploymentNodeKind | ast.DynamicViewParallelSteps | ast.GlobalDynamicPredicateGroup | ast.Relation | ast.SpecificationElementKind | ast.Globals | ast.GlobalPredicateGroup | ast.GlobalStyleGroup | ast.SpecificationTag | ast.ImportsFromPoject | ast.SpecificationRule;
|
|
7
7
|
type ValidatableAstNode = Guarded<typeof isValidatableAstNode>;
|
|
8
8
|
export declare function checksFromDiagnostics(doc: LikeC4LangiumDocument): {
|
|
9
9
|
isValid: (n: ValidatableAstNode) => boolean;
|
package/dist/validation/index.js
CHANGED
|
@@ -13,7 +13,12 @@ import { dynamicViewStep } from "./dynamic-view-step.js";
|
|
|
13
13
|
import { checkElement } from "./element.js";
|
|
14
14
|
import { checkElementRef } from "./element-ref.js";
|
|
15
15
|
import { checkImported, checkImportsFromPoject } from "./imports.js";
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
colorLiteralRuleChecks,
|
|
18
|
+
iconPropertyRuleChecks,
|
|
19
|
+
notesPropertyRuleChecks,
|
|
20
|
+
opacityPropertyRuleChecks
|
|
21
|
+
} from "./property-checks.js";
|
|
17
22
|
import { checkRelationBody, relationChecks } from "./relation.js";
|
|
18
23
|
import {
|
|
19
24
|
checkDeploymentNodeKind,
|
|
@@ -82,7 +87,8 @@ const isValidatableAstNode = validatableAstNodeGuards([
|
|
|
82
87
|
ast.isSpecificationDeploymentNodeKind,
|
|
83
88
|
ast.isSpecificationTag,
|
|
84
89
|
ast.isSpecificationColor,
|
|
85
|
-
ast.isSpecificationRule
|
|
90
|
+
ast.isSpecificationRule,
|
|
91
|
+
ast.isColorLiteral
|
|
86
92
|
]);
|
|
87
93
|
const findInvalidContainer = (node) => {
|
|
88
94
|
let nd = node;
|
|
@@ -147,7 +153,8 @@ export function registerValidationChecks(services) {
|
|
|
147
153
|
IncomingRelationExpr: checkIncomingRelationExpr(services),
|
|
148
154
|
OutgoingRelationExpr: checkOutgoingRelationExpr(services),
|
|
149
155
|
ImportsFromPoject: checkImportsFromPoject(services),
|
|
150
|
-
Imported: checkImported(services)
|
|
156
|
+
Imported: checkImported(services),
|
|
157
|
+
ColorLiteral: colorLiteralRuleChecks(services)
|
|
151
158
|
});
|
|
152
159
|
const connection = services.shared.lsp.Connection;
|
|
153
160
|
if (connection) {
|
|
@@ -4,3 +4,4 @@ import type { LikeC4Services } from '../module';
|
|
|
4
4
|
export declare const opacityPropertyRuleChecks: (_: LikeC4Services) => ValidationCheck<ast.OpacityProperty>;
|
|
5
5
|
export declare const iconPropertyRuleChecks: (_: LikeC4Services) => ValidationCheck<ast.IconProperty>;
|
|
6
6
|
export declare const notesPropertyRuleChecks: (_: LikeC4Services) => ValidationCheck<ast.NotesProperty>;
|
|
7
|
+
export declare const colorLiteralRuleChecks: (_: LikeC4Services) => ValidationCheck<ast.ColorLiteral>;
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { nonexhaustive } from "@likec4/core";
|
|
1
2
|
import { AstUtils } from "langium";
|
|
3
|
+
import { isNumber, isString } from "remeda";
|
|
2
4
|
import { ast } from "../ast.js";
|
|
3
5
|
import { tryOrLog } from "./_shared.js";
|
|
4
6
|
export const opacityPropertyRuleChecks = (_) => {
|
|
@@ -43,3 +45,63 @@ export const notesPropertyRuleChecks = (_) => {
|
|
|
43
45
|
}
|
|
44
46
|
};
|
|
45
47
|
};
|
|
48
|
+
export const colorLiteralRuleChecks = (_) => {
|
|
49
|
+
return (node, accept) => {
|
|
50
|
+
if (node.$type === "HexColor") {
|
|
51
|
+
if (node.hex === void 0) {
|
|
52
|
+
accept("error", `Invalid HEX`, {
|
|
53
|
+
node,
|
|
54
|
+
property: "hex"
|
|
55
|
+
});
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const length = isNumber(node.hex) ? node.hex.toString().length : node.hex.length;
|
|
59
|
+
if (length !== 6 && length !== 3 && length !== 8) {
|
|
60
|
+
accept("error", `Invalid value "${node.$cstNode?.text}", must be 3, 6 or 8 characters long`, {
|
|
61
|
+
node,
|
|
62
|
+
property: "hex"
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (node.$type === "RGBAColor") {
|
|
68
|
+
if (!isNumber(node.red) || node.red < 0 || node.red > 255) {
|
|
69
|
+
accept("error", `Invalid value, must be between 0 and 255`, {
|
|
70
|
+
node,
|
|
71
|
+
property: "red"
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
if (!isNumber(node.green) || node.green < 0 || node.green > 255) {
|
|
75
|
+
accept("error", `Invalid value, must be between 0 and 255`, {
|
|
76
|
+
node,
|
|
77
|
+
property: "green"
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
if (!isNumber(node.blue) || node.blue < 0 || node.blue > 255) {
|
|
81
|
+
accept("error", `Invalid value, must be between 0 and 255`, {
|
|
82
|
+
node,
|
|
83
|
+
property: "blue"
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
if (isNumber(node.alpha)) {
|
|
87
|
+
if (node.alpha < 0 || node.alpha > 1) {
|
|
88
|
+
accept("error", `Invalid value, must be between 0 and 1`, {
|
|
89
|
+
node,
|
|
90
|
+
property: "alpha"
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
if (isString(node.alpha)) {
|
|
95
|
+
const alpha = parseFloat(node.alpha);
|
|
96
|
+
if (alpha < 0 || alpha > 100) {
|
|
97
|
+
accept("error", `Invalid value, must be between 0% and 100%`, {
|
|
98
|
+
node,
|
|
99
|
+
property: "alpha"
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
nonexhaustive(node);
|
|
106
|
+
};
|
|
107
|
+
};
|
|
@@ -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";
|
|
@@ -16,7 +16,9 @@ export const ConfigurableLayouter = {
|
|
|
16
16
|
Layouter(services) {
|
|
17
17
|
logger.debug("Creating ConfigurableLayouter");
|
|
18
18
|
const wasmAdapter = new GraphvizWasmAdapter();
|
|
19
|
-
const layouter = new
|
|
19
|
+
const layouter = new QueueGraphvizLayoter({
|
|
20
|
+
graphviz: wasmAdapter
|
|
21
|
+
});
|
|
20
22
|
const langId = services.LanguageMetaData.languageId;
|
|
21
23
|
services.shared.workspace.ConfigurationProvider.onConfigurationSectionUpdate((update) => {
|
|
22
24
|
logger.debug("Configuration update: {update}", { update });
|
|
@@ -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,36 @@ 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 });
|
|
56
|
+
this.cache.delete(task.view);
|
|
60
57
|
}
|
|
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
58
|
});
|
|
69
59
|
}
|
|
70
|
-
await this.queue.onIdle();
|
|
71
60
|
if (results.length !== views.length) {
|
|
72
|
-
logger.warn`layouted ${results.length} of ${views.length} views`;
|
|
61
|
+
logger.warn`layouted ${results.length} of ${views.length} views in ${m0.pretty}`;
|
|
73
62
|
} else if (results.length > 0) {
|
|
74
|
-
logger.debug`layouted all ${results.length} views`;
|
|
63
|
+
logger.debug`layouted all ${results.length} views in ${m0.pretty}`;
|
|
75
64
|
}
|
|
76
65
|
return results;
|
|
77
66
|
}
|
|
78
67
|
async layoutView(viewId, projectId, cancelToken = CancellationToken.None) {
|
|
79
68
|
const model = await this.ModelBuilder.buildLikeC4Model(projectId, cancelToken);
|
|
80
69
|
const view = model.findView(viewId)?.$view;
|
|
81
|
-
const logger =
|
|
70
|
+
const logger = projectId ? viewsLogger.getChild(projectId) : viewsLogger;
|
|
82
71
|
if (!view) {
|
|
83
72
|
logger.warn`layoutView ${viewId} not found`;
|
|
84
73
|
return null;
|
|
@@ -89,24 +78,14 @@ export class DefaultLikeC4Views {
|
|
|
89
78
|
return await Promise.resolve(cached);
|
|
90
79
|
}
|
|
91
80
|
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
|
-
});
|
|
81
|
+
const m0 = performanceMark();
|
|
82
|
+
const result = await this.layouter.layout({
|
|
83
|
+
view,
|
|
84
|
+
specification: model.$data.specification
|
|
103
85
|
});
|
|
104
|
-
if (!result) {
|
|
105
|
-
throw new Error(`Failed to layout view ${viewId}`);
|
|
106
|
-
}
|
|
107
86
|
this.viewsWithReportedErrors.delete(viewId);
|
|
108
87
|
this.cache.set(view, result);
|
|
109
|
-
logger.debug(`layout {viewId} ready in ${
|
|
88
|
+
logger.debug(`layout {viewId} ready in ${m0.pretty}`, { viewId });
|
|
110
89
|
return result;
|
|
111
90
|
} catch (e) {
|
|
112
91
|
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.32.
|
|
4
|
+
"version": "1.32.2",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"bugs": "https://github.com/likec4/likec4/issues",
|
|
7
7
|
"homepage": "https://likec4.dev",
|
|
@@ -93,11 +93,11 @@
|
|
|
93
93
|
},
|
|
94
94
|
"devDependencies": {
|
|
95
95
|
"@types/chroma-js": "^3.1.1",
|
|
96
|
-
"@modelcontextprotocol/sdk": "^1.
|
|
96
|
+
"@modelcontextprotocol/sdk": "^1.12.1",
|
|
97
97
|
"@msgpack/msgpack": "^3.1.1",
|
|
98
98
|
"@smithy/util-base64": "^4.0.0",
|
|
99
99
|
"@types/express": "^5.0.2",
|
|
100
|
-
"@types/node": "
|
|
100
|
+
"@types/node": "~20.19.0",
|
|
101
101
|
"@types/picomatch": "^4.0.0",
|
|
102
102
|
"@types/which": "^3.0.4",
|
|
103
103
|
"chroma-js": "^3.1.2",
|
|
@@ -117,26 +117,26 @@
|
|
|
117
117
|
"pretty-ms": "^9.2.0",
|
|
118
118
|
"remeda": "^2.23.0",
|
|
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": "
|
|
125
|
+
"unbuild": "3.5.0",
|
|
126
|
+
"valibot": "^1.1.0",
|
|
127
|
+
"vitest": "3.2.3",
|
|
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": "^3.
|
|
135
|
-
"@likec4/
|
|
136
|
-
"@likec4/
|
|
137
|
-
"@likec4/
|
|
138
|
-
"@likec4/
|
|
139
|
-
"@likec4/
|
|
134
|
+
"zod": "^3.25.64",
|
|
135
|
+
"@likec4/icons": "1.32.2",
|
|
136
|
+
"@likec4/core": "1.32.2",
|
|
137
|
+
"@likec4/tsconfig": "1.32.2",
|
|
138
|
+
"@likec4/layouts": "1.32.2",
|
|
139
|
+
"@likec4/log": "1.32.2"
|
|
140
140
|
},
|
|
141
141
|
"scripts": {
|
|
142
142
|
"typecheck": "tsc -b --verbose",
|
|
@@ -148,7 +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
|
-
"clean": "
|
|
151
|
+
"clean": "pnpm rimraf dist contrib lib src/generated src/generated-lib",
|
|
152
152
|
"test": "vitest run --no-isolate",
|
|
153
153
|
"test-dbg": "vitest run --no-isolate -t formating",
|
|
154
154
|
"vitest:ui": "vitest --no-isolate --ui",
|