@likec4/language-server 1.41.0 → 1.42.1
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/browser/package.json +4 -0
- package/browser-worker/package.json +4 -0
- package/dist/LikeC4LanguageServices.d.ts +1 -1
- package/dist/LikeC4LanguageServices.mjs +3 -2
- package/dist/Rpc.mjs +30 -24
- package/dist/ast.d.ts +1 -7
- package/dist/ast.mjs +0 -10
- package/dist/bundled.mjs +4125 -3660
- package/dist/documentation/documentation-provider.mjs +1 -1
- package/dist/filesystem/FileSystemWatcher.d.ts +2 -2
- package/dist/filesystem/LikeC4FileSystem.mjs +10 -4
- package/dist/filesystem/index.d.ts +1 -1
- package/dist/formatting/LikeC4Formatter.mjs +41 -10
- package/dist/formatting/utils.d.ts +3 -3
- package/dist/formatting/utils.mjs +1 -1
- package/dist/generated/ast.d.ts +35 -16
- package/dist/generated/ast.mjs +69 -26
- package/dist/generated/grammar.mjs +1 -1
- package/dist/lsp/CompletionProvider.mjs +1 -1
- package/dist/lsp/DocumentLinkProvider.d.ts +1 -1
- package/dist/lsp/DocumentLinkProvider.mjs +1 -1
- package/dist/lsp/DocumentSymbolProvider.mjs +1 -1
- package/dist/mcp/NoopLikeC4MCPServer.d.ts +1 -1
- package/dist/mcp/NoopLikeC4MCPServer.mjs +1 -1
- package/dist/mcp/server/StdioLikeC4MCPServer.mjs +4 -1
- package/dist/mcp/server/StreamableLikeC4MCPServer.mjs +3 -3
- package/dist/mcp/server/WithMCPServer.mjs +2 -2
- package/dist/mcp/tools/_common.mjs +2 -2
- package/dist/model/builder/MergedSpecification.d.ts +3 -3
- package/dist/model/builder/MergedSpecification.mjs +13 -39
- package/dist/model/builder/buildModel.mjs +14 -17
- package/dist/model/model-builder.d.ts +1 -1
- package/dist/model/model-builder.mjs +12 -9
- package/dist/model/model-locator.d.ts +5 -0
- package/dist/model/model-locator.mjs +40 -3
- package/dist/model/model-parser-where.mjs +1 -2
- package/dist/model/model-parser.d.ts +19 -2
- package/dist/model/parser/Base.mjs +8 -8
- package/dist/model/parser/DeploymentModelParser.d.ts +1 -0
- package/dist/model/parser/DeploymentModelParser.mjs +7 -7
- package/dist/model/parser/DeploymentViewParser.d.ts +1 -0
- package/dist/model/parser/FqnRefParser.d.ts +2 -0
- package/dist/model/parser/FqnRefParser.mjs +16 -11
- package/dist/model/parser/GlobalsParser.d.ts +8 -2
- package/dist/model/parser/ModelParser.d.ts +1 -0
- package/dist/model/parser/ModelParser.mjs +16 -11
- package/dist/model/parser/PredicatesParser.d.ts +1 -0
- package/dist/model/parser/SpecificationParser.mjs +4 -4
- package/dist/model/parser/ViewsParser.d.ts +12 -2
- package/dist/model/parser/ViewsParser.mjs +123 -31
- package/dist/model-change/ModelChanges.d.ts +1 -1
- package/dist/module.mjs +3 -2
- package/dist/protocol.d.ts +28 -4
- package/dist/references/scope-computation.mjs +2 -3
- package/dist/references/scope-provider.d.ts +2 -2
- package/dist/references/scope-provider.mjs +8 -15
- package/dist/test/testServices.d.ts +2 -0
- package/dist/test/testServices.mjs +10 -11
- package/dist/utils/disposable.mjs +2 -2
- package/dist/utils/index.mjs +1 -1
- package/dist/validation/_shared.d.ts +1 -1
- package/dist/validation/deployment-checks.d.ts +1 -1
- package/dist/validation/deployment-checks.mjs +4 -1
- package/dist/validation/dynamic-view.d.ts +3 -2
- package/dist/validation/dynamic-view.mjs +21 -2
- package/dist/validation/element-ref.d.ts +2 -2
- package/dist/validation/element-ref.mjs +1 -1
- package/dist/validation/imports.d.ts +0 -1
- package/dist/validation/imports.mjs +0 -5
- package/dist/validation/index.d.ts +1 -1
- package/dist/validation/index.mjs +19 -13
- package/dist/validation/view-predicates/relation-with.d.ts +1 -1
- package/dist/validation/view.d.ts +1 -1
- package/dist/view-utils/index.d.ts +0 -1
- package/dist/view-utils/index.mjs +0 -1
- package/dist/views/likec4-views.d.ts +6 -0
- package/dist/views/likec4-views.mjs +31 -18
- package/dist/workspace/ProjectsManager.d.ts +23 -31
- package/dist/workspace/ProjectsManager.mjs +78 -89
- package/dist/workspace/WorkspaceManager.mjs +1 -1
- package/likec4lib/package.json +4 -0
- package/package.json +24 -28
- package/protocol/package.json +4 -0
- package/dist/view-utils/resolve-relative-paths.d.ts +0 -2
- package/dist/view-utils/resolve-relative-paths.mjs +0 -78
|
@@ -27,8 +27,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
27
27
|
views,
|
|
28
28
|
globals,
|
|
29
29
|
likec4lib,
|
|
30
|
-
deployments
|
|
31
|
-
imports
|
|
30
|
+
deployments
|
|
32
31
|
} = document.parseResult.value;
|
|
33
32
|
this.exportLibrary(likec4lib, docExports, document);
|
|
34
33
|
this.exportSpecification(specifications, docExports, document);
|
|
@@ -205,7 +204,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
|
|
|
205
204
|
let imported = imports;
|
|
206
205
|
while (imported) {
|
|
207
206
|
descendants.push(
|
|
208
|
-
this.descriptions.createDescription(imported, imported.imported.$refText
|
|
207
|
+
this.descriptions.createDescription(imported, imported.imported.$refText)
|
|
209
208
|
);
|
|
210
209
|
imported = imported.prev;
|
|
211
210
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type ProjectId } from '@likec4/core';
|
|
2
2
|
import { type AstNodeDescription, type ReferenceInfo, type Scope, type Stream, DefaultScopeProvider } from 'langium';
|
|
3
|
-
import {
|
|
3
|
+
import { ast } from '../ast';
|
|
4
4
|
import type { DeploymentsIndex, FqnIndex } from '../model';
|
|
5
5
|
import type { LikeC4Services } from '../module';
|
|
6
6
|
import type { IndexManager } from '../workspace';
|
|
@@ -10,7 +10,7 @@ export declare class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
10
10
|
protected readonly indexManager: IndexManager;
|
|
11
11
|
constructor(services: LikeC4Services);
|
|
12
12
|
getScope(context: ReferenceInfo): Scope;
|
|
13
|
-
protected genUniqueDescedants(of: () => ast.Element | ast.DeploymentNode | undefined): Generator<Stream<AstNodeDescriptionWithFqn>, void, any>;
|
|
13
|
+
protected genUniqueDescedants(of: () => ast.Element | ast.DeploymentNode | undefined): Generator<Stream<import("../ast").AstNodeDescriptionWithFqn>, void, any>;
|
|
14
14
|
protected genScopeExtendElement({ element }: ast.ExtendElement): Generator<AstNodeDescription>;
|
|
15
15
|
protected genScopeElementView({ viewOf, extends: ext }: ast.ElementView): Generator<AstNodeDescription>;
|
|
16
16
|
protected getScopeForStrictFqnRef(projectId: ProjectId, container: ast.StrictFqnRef, context: ReferenceInfo): any;
|
|
@@ -2,12 +2,10 @@ import { nonexhaustive } from "@likec4/core";
|
|
|
2
2
|
import {
|
|
3
3
|
AstUtils,
|
|
4
4
|
DefaultScopeProvider,
|
|
5
|
-
DONE_RESULT,
|
|
6
5
|
EMPTY_SCOPE,
|
|
7
6
|
EMPTY_STREAM,
|
|
8
7
|
MapScope,
|
|
9
8
|
stream,
|
|
10
|
-
StreamImpl,
|
|
11
9
|
StreamScope
|
|
12
10
|
} from "langium";
|
|
13
11
|
import { ast, isFqnRefInsideGlobals, isFqnRefInsideModel } from "../ast.mjs";
|
|
@@ -81,6 +79,14 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
81
79
|
*genScopeExtendElement({ element }) {
|
|
82
80
|
if (element.el.$nodeDescription) {
|
|
83
81
|
yield element.el.$nodeDescription;
|
|
82
|
+
yield {
|
|
83
|
+
...element.el.$nodeDescription,
|
|
84
|
+
name: "this"
|
|
85
|
+
};
|
|
86
|
+
yield {
|
|
87
|
+
...element.el.$nodeDescription,
|
|
88
|
+
name: "it"
|
|
89
|
+
};
|
|
84
90
|
}
|
|
85
91
|
yield* this.genUniqueDescedants(() => elementRef(element));
|
|
86
92
|
}
|
|
@@ -231,16 +237,3 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
|
|
|
231
237
|
return this.getProjectScope(projectId, referenceType, context);
|
|
232
238
|
}
|
|
233
239
|
}
|
|
234
|
-
function lazyStream(fn) {
|
|
235
|
-
return new StreamImpl(
|
|
236
|
-
() => {
|
|
237
|
-
return fn().iterator();
|
|
238
|
-
},
|
|
239
|
-
(iterator) => {
|
|
240
|
-
if (iterator) {
|
|
241
|
-
return iterator.next();
|
|
242
|
-
}
|
|
243
|
-
return DONE_RESULT;
|
|
244
|
-
}
|
|
245
|
-
);
|
|
246
|
-
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { LikeC4ProjectJsonConfig } from '@likec4/config';
|
|
2
2
|
import type { ComputedLikeC4ModelData } from '@likec4/core';
|
|
3
|
+
import { type LangiumDocument } from 'langium';
|
|
3
4
|
import type { LiteralUnion } from 'type-fest';
|
|
4
5
|
import { URI } from 'vscode-uri';
|
|
5
6
|
import type { LikeC4LangiumDocument } from '../ast';
|
|
@@ -9,6 +10,7 @@ export declare function createTestServices(options?: {
|
|
|
9
10
|
}): {
|
|
10
11
|
services: any;
|
|
11
12
|
addDocument: (input: string, uri?: string) => Promise<LikeC4LangiumDocument>;
|
|
13
|
+
removeDocument: (doc: LangiumDocument | URI) => Promise<void>;
|
|
12
14
|
parse: (input: string, uri?: string) => Promise<LikeC4LangiumDocument>;
|
|
13
15
|
validate: (input: string | LikeC4LangiumDocument, uri?: string) => Promise<{
|
|
14
16
|
document: LikeC4LangiumDocument;
|
|
@@ -63,18 +63,18 @@ export function createTestServices(options) {
|
|
|
63
63
|
langiumDocuments.addDocument(document);
|
|
64
64
|
return document;
|
|
65
65
|
};
|
|
66
|
+
const removeDocument = async (doc) => {
|
|
67
|
+
const uri = doc instanceof URI ? doc : doc.uri;
|
|
68
|
+
await documentBuilder.update([], [uri]);
|
|
69
|
+
};
|
|
66
70
|
const parse = async (input, uri) => {
|
|
67
71
|
const document = await addDocument(input, uri);
|
|
68
|
-
await
|
|
69
|
-
await documentBuilder.build([document], { validation: false });
|
|
70
|
-
});
|
|
72
|
+
await documentBuilder.build([document], { validation: false });
|
|
71
73
|
return document;
|
|
72
74
|
};
|
|
73
75
|
const validate = async (input, uri) => {
|
|
74
76
|
const document = typeof input === "string" ? await addDocument(input, uri) : input;
|
|
75
|
-
await
|
|
76
|
-
await documentBuilder.build([document], { validation: true });
|
|
77
|
-
});
|
|
77
|
+
await documentBuilder.build([document], { validation: true });
|
|
78
78
|
const diagnostics = document.diagnostics ?? [];
|
|
79
79
|
const warnings = diagnostics.flatMap((d) => d.severity === DiagnosticSeverity.Warning ? d.message : []);
|
|
80
80
|
const errors = diagnostics.flatMap((d) => d.severity === DiagnosticSeverity.Error ? d.message : []);
|
|
@@ -86,10 +86,8 @@ export function createTestServices(options) {
|
|
|
86
86
|
};
|
|
87
87
|
};
|
|
88
88
|
const format = async (input, uri) => {
|
|
89
|
-
const document = typeof input === "string" ? await parse(input, uri) : input;
|
|
90
|
-
await
|
|
91
|
-
await documentBuilder.build([document], { validation: true });
|
|
92
|
-
});
|
|
89
|
+
const document = typeof input === "string" ? await parse(stripIndent(input), uri) : input;
|
|
90
|
+
await documentBuilder.build([document], { validation: true });
|
|
93
91
|
const edits = await formatter?.formatDocument(
|
|
94
92
|
document,
|
|
95
93
|
{
|
|
@@ -137,6 +135,7 @@ export function createTestServices(options) {
|
|
|
137
135
|
return {
|
|
138
136
|
services,
|
|
139
137
|
addDocument,
|
|
138
|
+
removeDocument,
|
|
140
139
|
parse,
|
|
141
140
|
validate,
|
|
142
141
|
validateAll,
|
|
@@ -156,7 +155,7 @@ export async function createMultiProjectTestServices(data) {
|
|
|
156
155
|
const projects = {};
|
|
157
156
|
for (const [name, files] of entries(data)) {
|
|
158
157
|
const folderUri = UriUtils.joinPath(URI.parse(workspace), "src", name);
|
|
159
|
-
services.shared.workspace.ProjectsManager.registerProject({
|
|
158
|
+
await services.shared.workspace.ProjectsManager.registerProject({
|
|
160
159
|
config: {
|
|
161
160
|
name,
|
|
162
161
|
exclude: ["node_modules"]
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { logWarnError } from "../logger.mjs";
|
|
2
2
|
export class ADisposable {
|
|
3
3
|
toDispose = [];
|
|
4
4
|
isDisposed = false;
|
|
@@ -13,7 +13,7 @@ export class ADisposable {
|
|
|
13
13
|
try {
|
|
14
14
|
item.dispose();
|
|
15
15
|
} catch (e) {
|
|
16
|
-
|
|
16
|
+
logWarnError(e);
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
}
|
package/dist/utils/index.mjs
CHANGED
|
@@ -4,4 +4,4 @@ import type { LikeC4Services } from '../module';
|
|
|
4
4
|
export declare const deploymentNodeChecks: (services: LikeC4Services) => ValidationCheck<ast.DeploymentNode>;
|
|
5
5
|
export declare const deployedInstanceChecks: (services: LikeC4Services) => ValidationCheck<ast.DeployedInstance>;
|
|
6
6
|
export declare const deploymentRelationChecks: (services: LikeC4Services) => ValidationCheck<ast.DeploymentRelation>;
|
|
7
|
-
export declare const extendDeploymentChecks: (
|
|
7
|
+
export declare const extendDeploymentChecks: (_services: LikeC4Services) => ValidationCheck<ast.ExtendDeployment>;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { FqnRef, isSameHierarchy, nonNullable } from "@likec4/core";
|
|
2
|
+
import { loggable } from "@likec4/log";
|
|
2
3
|
import { AstUtils } from "langium";
|
|
3
4
|
import { ast } from "../ast.mjs";
|
|
5
|
+
import { logger } from "../logger.mjs";
|
|
4
6
|
import { projectIdFrom } from "../utils/index.mjs";
|
|
5
7
|
import { RESERVED_WORDS, tryOrLog } from "./_shared.mjs";
|
|
6
8
|
const { getDocument } = AstUtils;
|
|
@@ -88,6 +90,7 @@ export const deploymentRelationChecks = (services) => {
|
|
|
88
90
|
try {
|
|
89
91
|
sourceFqnRef = parser._resolveDeploymentRelationSource(el);
|
|
90
92
|
} catch (e) {
|
|
93
|
+
logger.warn(loggable(e));
|
|
91
94
|
accept("error", "DeploymentRelation source not resolved", {
|
|
92
95
|
node: el,
|
|
93
96
|
property: "source"
|
|
@@ -130,7 +133,7 @@ export const deploymentRelationChecks = (services) => {
|
|
|
130
133
|
}
|
|
131
134
|
});
|
|
132
135
|
};
|
|
133
|
-
export const extendDeploymentChecks = (
|
|
136
|
+
export const extendDeploymentChecks = (_services) => {
|
|
134
137
|
return tryOrLog((el, accept) => {
|
|
135
138
|
const target = el.deploymentNode.value.ref;
|
|
136
139
|
if (!target || !ast.isDeploymentNode(target)) {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ValidationCheck } from 'langium';
|
|
2
2
|
import { ast } from '../ast';
|
|
3
3
|
import type { LikeC4Services } from '../module';
|
|
4
|
-
export declare const
|
|
5
|
-
export declare const
|
|
4
|
+
export declare const dynamicViewStepSingle: (services: LikeC4Services) => ValidationCheck<ast.DynamicStepSingle>;
|
|
5
|
+
export declare const dynamicViewStepChain: (services: LikeC4Services) => ValidationCheck<ast.DynamicStepChain>;
|
|
6
|
+
export declare const dynamicViewDisplayVariant: (_services: LikeC4Services) => ValidationCheck<ast.DynamicViewDisplayVariantProperty>;
|
|
@@ -4,7 +4,7 @@ import { isEmpty } from "remeda";
|
|
|
4
4
|
import { ast } from "../ast.mjs";
|
|
5
5
|
import { elementRef } from "../utils/elementRef.mjs";
|
|
6
6
|
import { tryOrLog } from "./_shared.mjs";
|
|
7
|
-
export const
|
|
7
|
+
export const dynamicViewStepSingle = (services) => {
|
|
8
8
|
const fqnIndex = services.likec4.FqnIndex;
|
|
9
9
|
return tryOrLog((el, accept) => {
|
|
10
10
|
const sourceEl = elementRef(el.source);
|
|
@@ -30,7 +30,26 @@ export const dynamicViewStep = (services) => {
|
|
|
30
30
|
}
|
|
31
31
|
});
|
|
32
32
|
};
|
|
33
|
-
export const
|
|
33
|
+
export const dynamicViewStepChain = (services) => {
|
|
34
|
+
const fqnIndex = services.likec4.FqnIndex;
|
|
35
|
+
return tryOrLog((el, accept) => {
|
|
36
|
+
const source = el.source;
|
|
37
|
+
if (ast.isDynamicStepSingle(source) && source.isBackward) {
|
|
38
|
+
accept("error", "Invalid chain after backward step", {
|
|
39
|
+
node: el
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
const targetEl = elementRef(el.target);
|
|
43
|
+
const target = targetEl && fqnIndex.getFqn(targetEl);
|
|
44
|
+
if (!target) {
|
|
45
|
+
accept("error", "Target not found (not parsed/indexed yet)", {
|
|
46
|
+
node: el,
|
|
47
|
+
property: "target"
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
});
|
|
51
|
+
};
|
|
52
|
+
export const dynamicViewDisplayVariant = (_services) => {
|
|
34
53
|
return tryOrLog((prop, accept) => {
|
|
35
54
|
if (isEmpty(prop.value) || prop.value !== "diagram" && prop.value !== "sequence") {
|
|
36
55
|
accept("error", 'Invalid display variant: "diagram" or "sequence" are allowed', {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ValidationCheck } from 'langium';
|
|
2
2
|
import type { ast } from '../ast';
|
|
3
3
|
import type { LikeC4Services } from '../module';
|
|
4
|
-
export declare const checkElementRef: (
|
|
4
|
+
export declare const checkElementRef: (_services: LikeC4Services) => ValidationCheck<ast.ElementRef>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { isReferenceToDeploymentModel } from "../utils/index.mjs";
|
|
2
2
|
import { tryOrLog } from "./_shared.mjs";
|
|
3
|
-
export const checkElementRef = (
|
|
3
|
+
export const checkElementRef = (_services) => {
|
|
4
4
|
return tryOrLog((el, accept) => {
|
|
5
5
|
if (isReferenceToDeploymentModel(el.modelElement)) {
|
|
6
6
|
accept("error", "Only model elements allowed here", {
|
|
@@ -2,4 +2,3 @@ import { type ValidationCheck } from 'langium';
|
|
|
2
2
|
import type { ast } from '../ast';
|
|
3
3
|
import type { LikeC4Services } from '../module';
|
|
4
4
|
export declare const checkImportsFromPoject: (services: LikeC4Services) => ValidationCheck<ast.ImportsFromPoject>;
|
|
5
|
-
export declare const checkImported: (services: LikeC4Services) => ValidationCheck<ast.Imported>;
|
|
@@ -4,7 +4,7 @@ import type { LikeC4Services } from '../module';
|
|
|
4
4
|
export { LikeC4DocumentValidator } from './DocumentValidator';
|
|
5
5
|
type Guard<N extends AstNode> = (n: AstNode) => n is N;
|
|
6
6
|
type Guarded<G> = G extends Guard<infer N> ? N : never;
|
|
7
|
-
declare const isValidatableAstNode: (n: AstNode) => n is ast.HexColor | ast.RGBAColor | ast.DeployedInstance | ast.DeploymentNode | ast.DeploymentViewRulePredicate | ast.DeploymentViewRuleStyle | ast.ViewRuleAutoLayout | ast.DynamicViewDisplayVariantProperty | ast.LinkProperty | ast.ViewStringProperty | ast.DynamicViewGlobalPredicateRef | ast.DynamicViewIncludePredicate | ast.ViewRuleGlobalStyle | ast.ViewRuleStyle | ast.ElementStringProperty | ast.ElementStyleProperty | ast.IconProperty | 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.BorderProperty | ast.MultipleProperty | ast.OpacityProperty | ast.ShapeProperty | ast.ViewRuleGlobalPredicateRef | ast.ViewRuleGroup | ast.ViewRulePredicate | ast.
|
|
7
|
+
declare const isValidatableAstNode: (n: AstNode) => n is ast.HexColor | ast.RGBAColor | ast.DeployedInstance | ast.DeploymentNode | ast.DeploymentViewRulePredicate | ast.DeploymentViewRuleStyle | ast.ViewRuleAutoLayout | ast.DynamicViewDisplayVariantProperty | ast.LinkProperty | ast.ViewStringProperty | ast.DynamicViewGlobalPredicateRef | ast.DynamicViewIncludePredicate | ast.ViewRuleGlobalStyle | ast.ViewRuleStyle | ast.DynamicStepChain | ast.DynamicStepSingle | ast.ElementStringProperty | ast.ElementStyleProperty | ast.IconProperty | 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.BorderProperty | ast.MultipleProperty | ast.OpacityProperty | ast.ShapeProperty | ast.ViewRuleGlobalPredicateRef | ast.ViewRuleGroup | ast.ViewRulePredicate | ast.DynamicViewParallelSteps | ast.ElementRef | ast.SpecificationRelationshipKind | ast.GlobalStyle | ast.SpecificationColor | ast.NavigateToProperty | ast.DeploymentRelation | ast.Tags | ast.SpecificationDeploymentNodeKind | ast.GlobalDynamicPredicateGroup | ast.Relation | ast.SpecificationElementKind | ast.Globals | ast.GlobalPredicateGroup | ast.GlobalStyleGroup | ast.SpecificationTag | ast.ImportsFromPoject | ast.SpecificationRule;
|
|
8
8
|
type ValidatableAstNode = Guarded<typeof isValidatableAstNode>;
|
|
9
9
|
export declare function checksFromDiagnostics(doc: LikeC4LangiumDocument): {
|
|
10
10
|
isValid: (n: ValidatableAstNode) => boolean;
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { onNextTick } from "@likec4/core/utils";
|
|
2
|
+
import { loggable } from "@likec4/log";
|
|
1
3
|
import { DocumentState } from "langium";
|
|
2
4
|
import { isNullish } from "remeda";
|
|
3
5
|
import { DiagnosticSeverity } from "vscode-languageserver-types";
|
|
@@ -9,10 +11,10 @@ import {
|
|
|
9
11
|
deploymentRelationChecks,
|
|
10
12
|
extendDeploymentChecks
|
|
11
13
|
} from "./deployment-checks.mjs";
|
|
12
|
-
import { dynamicViewDisplayVariant,
|
|
14
|
+
import { dynamicViewDisplayVariant, dynamicViewStepChain, dynamicViewStepSingle } from "./dynamic-view.mjs";
|
|
13
15
|
import { checkElement } from "./element.mjs";
|
|
14
16
|
import { checkElementRef } from "./element-ref.mjs";
|
|
15
|
-
import {
|
|
17
|
+
import { checkImportsFromPoject } from "./imports.mjs";
|
|
16
18
|
import {
|
|
17
19
|
colorLiteralRuleChecks,
|
|
18
20
|
iconPropertyRuleChecks,
|
|
@@ -57,7 +59,8 @@ const isValidatableAstNode = validatableAstNodeGuards([
|
|
|
57
59
|
ast.isFqnExpr,
|
|
58
60
|
ast.isRelationExpr,
|
|
59
61
|
ast.isDynamicViewParallelSteps,
|
|
60
|
-
ast.
|
|
62
|
+
ast.isDynamicStepChain,
|
|
63
|
+
ast.isDynamicStepSingle,
|
|
61
64
|
ast.isDeploymentViewRule,
|
|
62
65
|
ast.isDeploymentViewRulePredicate,
|
|
63
66
|
ast.isExpressionV2,
|
|
@@ -141,7 +144,8 @@ export function registerValidationChecks(services) {
|
|
|
141
144
|
GlobalPredicateGroup: checkGlobalPredicate(services),
|
|
142
145
|
GlobalDynamicPredicateGroup: checkGlobalPredicate(services),
|
|
143
146
|
GlobalStyleId: checkGlobalStyleId(services),
|
|
144
|
-
|
|
147
|
+
DynamicStepSingle: dynamicViewStepSingle(services),
|
|
148
|
+
DynamicStepChain: dynamicViewStepChain(services),
|
|
145
149
|
LikeC4View: viewChecks(services),
|
|
146
150
|
Element: checkElement(services),
|
|
147
151
|
ElementRef: checkElementRef(services),
|
|
@@ -155,20 +159,22 @@ export function registerValidationChecks(services) {
|
|
|
155
159
|
IncomingRelationExpr: checkIncomingRelationExpr(services),
|
|
156
160
|
OutgoingRelationExpr: checkOutgoingRelationExpr(services),
|
|
157
161
|
ImportsFromPoject: checkImportsFromPoject(services),
|
|
158
|
-
Imported: checkImported(services),
|
|
162
|
+
// Imported: checkImported(services),
|
|
159
163
|
ColorLiteral: colorLiteralRuleChecks(services),
|
|
160
164
|
DynamicViewDisplayVariantProperty: dynamicViewDisplayVariant(services)
|
|
161
165
|
});
|
|
162
166
|
const connection = services.shared.lsp.Connection;
|
|
163
167
|
if (connection) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
168
|
+
onNextTick(() => {
|
|
169
|
+
services.shared.workspace.DocumentBuilder.onUpdate((_, deleted) => {
|
|
170
|
+
for (const uri of deleted) {
|
|
171
|
+
logger.debug(`clear diagnostics for deleted ${uri.path}`);
|
|
172
|
+
connection.sendDiagnostics({
|
|
173
|
+
uri: uri.toString(),
|
|
174
|
+
diagnostics: []
|
|
175
|
+
}).catch((e) => logger.error(loggable(e)));
|
|
176
|
+
}
|
|
177
|
+
});
|
|
172
178
|
});
|
|
173
179
|
}
|
|
174
180
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ValidationCheck } from 'langium';
|
|
2
2
|
import { ast } from '../../ast';
|
|
3
3
|
import type { LikeC4Services } from '../../module';
|
|
4
4
|
export declare const checkRelationExprWith: (_services: LikeC4Services) => ValidationCheck<ast.RelationExprWith>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { ValidationCheck } from 'langium';
|
|
2
2
|
import { ast } from '../ast';
|
|
3
3
|
import type { LikeC4Services } from '../module';
|
|
4
4
|
export declare const viewChecks: (services: LikeC4Services) => ValidationCheck<ast.LikeC4View>;
|
|
@@ -44,6 +44,10 @@ export interface LikeC4Views {
|
|
|
44
44
|
export declare class DefaultLikeC4Views implements LikeC4Views {
|
|
45
45
|
private services;
|
|
46
46
|
private cache;
|
|
47
|
+
/**
|
|
48
|
+
* Set of viewIds with reported errors
|
|
49
|
+
* value is `${projectId}-${viewId}`
|
|
50
|
+
*/
|
|
47
51
|
private viewsWithReportedErrors;
|
|
48
52
|
private ModelBuilder;
|
|
49
53
|
constructor(services: LikeC4Services);
|
|
@@ -57,5 +61,7 @@ export declare class DefaultLikeC4Views implements LikeC4Views {
|
|
|
57
61
|
* Open a view in the preview panel.
|
|
58
62
|
*/
|
|
59
63
|
openView(viewId: ViewId, projectId: ProjectId): Promise<void>;
|
|
64
|
+
private reportViewError;
|
|
65
|
+
private viewSucceed;
|
|
60
66
|
}
|
|
61
67
|
export {};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { loggable } from "@likec4/log";
|
|
2
2
|
import { values } from "remeda";
|
|
3
|
-
import {
|
|
3
|
+
import { logger as rootLogger, logWarnError } from "../logger.mjs";
|
|
4
4
|
import { performanceMark } from "../utils/index.mjs";
|
|
5
5
|
const viewsLogger = rootLogger.getChild("views");
|
|
6
6
|
export class DefaultLikeC4Views {
|
|
@@ -9,6 +9,10 @@ export class DefaultLikeC4Views {
|
|
|
9
9
|
this.ModelBuilder = services.likec4.ModelBuilder;
|
|
10
10
|
}
|
|
11
11
|
cache = /* @__PURE__ */ new WeakMap();
|
|
12
|
+
/**
|
|
13
|
+
* Set of viewIds with reported errors
|
|
14
|
+
* value is `${projectId}-${viewId}`
|
|
15
|
+
*/
|
|
12
16
|
viewsWithReportedErrors = /* @__PURE__ */ new Set();
|
|
13
17
|
ModelBuilder;
|
|
14
18
|
get layouter() {
|
|
@@ -25,10 +29,11 @@ export class DefaultLikeC4Views {
|
|
|
25
29
|
return [];
|
|
26
30
|
}
|
|
27
31
|
const m0 = performanceMark();
|
|
28
|
-
|
|
32
|
+
projectId ??= likeC4Model.project.id;
|
|
33
|
+
const logger = viewsLogger.getChild(projectId);
|
|
29
34
|
logger.debug`layoutAll: ${views.length} views`;
|
|
30
35
|
const tasks = [];
|
|
31
|
-
const
|
|
36
|
+
const styles = likeC4Model.$styles;
|
|
32
37
|
const results = [];
|
|
33
38
|
for (const view of views) {
|
|
34
39
|
let cached = this.cache.get(view);
|
|
@@ -39,15 +44,14 @@ export class DefaultLikeC4Views {
|
|
|
39
44
|
}
|
|
40
45
|
tasks.push({
|
|
41
46
|
view,
|
|
42
|
-
|
|
47
|
+
styles
|
|
43
48
|
});
|
|
44
49
|
}
|
|
45
50
|
if (tasks.length > 0) {
|
|
46
51
|
await this.layouter.batchLayout({
|
|
47
52
|
batch: tasks,
|
|
48
53
|
onSuccess: (task, result) => {
|
|
49
|
-
this.
|
|
50
|
-
this.cache.set(task.view, result);
|
|
54
|
+
this.viewSucceed(task.view, projectId, result);
|
|
51
55
|
results.push(result);
|
|
52
56
|
},
|
|
53
57
|
onError: (task, error) => {
|
|
@@ -65,7 +69,8 @@ export class DefaultLikeC4Views {
|
|
|
65
69
|
async layoutView(viewId, projectId, cancelToken) {
|
|
66
70
|
const model = await this.ModelBuilder.buildLikeC4Model(projectId, cancelToken);
|
|
67
71
|
const view = model.findView(viewId)?.$view;
|
|
68
|
-
|
|
72
|
+
projectId ??= model.project.id;
|
|
73
|
+
const logger = viewsLogger.getChild(projectId);
|
|
69
74
|
if (!view) {
|
|
70
75
|
logger.warn`layoutView ${viewId} not found`;
|
|
71
76
|
return null;
|
|
@@ -73,25 +78,21 @@ export class DefaultLikeC4Views {
|
|
|
73
78
|
let cached = this.cache.get(view);
|
|
74
79
|
if (cached) {
|
|
75
80
|
logger.debug`layout ${viewId} from cache`;
|
|
76
|
-
return await Promise.resolve(cached);
|
|
81
|
+
return await Promise.resolve().then(() => cached);
|
|
77
82
|
}
|
|
78
83
|
try {
|
|
79
84
|
const m0 = performanceMark();
|
|
80
85
|
const result = await this.layouter.layout({
|
|
81
86
|
view,
|
|
82
|
-
|
|
87
|
+
styles: model.$styles
|
|
83
88
|
});
|
|
84
|
-
this.
|
|
85
|
-
this.cache.set(view, result);
|
|
89
|
+
this.viewSucceed(view, projectId, result);
|
|
86
90
|
logger.debug(`layout {viewId} ready in ${m0.pretty}`, { viewId });
|
|
87
91
|
return result;
|
|
88
92
|
} catch (e) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
this.viewsWithReportedErrors.add(viewId);
|
|
93
|
-
logError(e);
|
|
94
|
-
}
|
|
93
|
+
const errMessage = loggable(e);
|
|
94
|
+
logger.warn(errMessage);
|
|
95
|
+
this.reportViewError(view, projectId, errMessage);
|
|
95
96
|
return Promise.reject(e);
|
|
96
97
|
}
|
|
97
98
|
}
|
|
@@ -113,7 +114,7 @@ export class DefaultLikeC4Views {
|
|
|
113
114
|
const tasks = views.map(async (view) => {
|
|
114
115
|
const { dot, svg } = await this.layouter.svg({
|
|
115
116
|
view,
|
|
116
|
-
|
|
117
|
+
styles: likeC4Model.$styles
|
|
117
118
|
});
|
|
118
119
|
return {
|
|
119
120
|
id: view.id,
|
|
@@ -139,6 +140,18 @@ export class DefaultLikeC4Views {
|
|
|
139
140
|
async openView(viewId, projectId) {
|
|
140
141
|
await this.services.Rpc.openView({ viewId, projectId });
|
|
141
142
|
}
|
|
143
|
+
reportViewError(view, projectId, error) {
|
|
144
|
+
const key = `${projectId}-${view.id}`;
|
|
145
|
+
if (!this.viewsWithReportedErrors.has(key)) {
|
|
146
|
+
this.services.shared.lsp.Connection?.window.showErrorMessage(`LikeC4: ${error}`);
|
|
147
|
+
this.viewsWithReportedErrors.add(key);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
viewSucceed(view, projectId, result) {
|
|
151
|
+
const key = `${projectId}-${view.id}`;
|
|
152
|
+
this.viewsWithReportedErrors.delete(key);
|
|
153
|
+
this.cache.set(view, result);
|
|
154
|
+
}
|
|
142
155
|
// async overviewGraph(): Promise<OverviewGraph> {
|
|
143
156
|
// const KEY = 'OverviewGraph'
|
|
144
157
|
// const cache = this.services.ValidatedWorkspaceCache as WorkspaceCache<string, OverviewGraph>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { type LikeC4ProjectConfig } from '@likec4/config';
|
|
2
|
-
import type { NonEmptyReadonlyArray
|
|
3
|
-
import
|
|
1
|
+
import { type LikeC4ProjectConfig, type LikeC4ProjectConfigInput } from '@likec4/config';
|
|
2
|
+
import type { NonEmptyReadonlyArray } from '@likec4/core';
|
|
3
|
+
import type { scalar } from '@likec4/core/types';
|
|
4
|
+
import { type Cancellation, type LangiumDocument, URI, WorkspaceCache } from 'langium';
|
|
4
5
|
import type { Tagged } from 'type-fest';
|
|
5
6
|
import type { LikeC4SharedServices } from '../module';
|
|
6
7
|
/**
|
|
@@ -10,14 +11,14 @@ import type { LikeC4SharedServices } from '../module';
|
|
|
10
11
|
export type ProjectFolder = Tagged<string, 'ProjectFolder'>;
|
|
11
12
|
export declare function ProjectFolder(folder: URI | string): ProjectFolder;
|
|
12
13
|
interface ProjectData {
|
|
13
|
-
id: ProjectId;
|
|
14
|
+
id: scalar.ProjectId;
|
|
14
15
|
config: LikeC4ProjectConfig;
|
|
15
16
|
folder: ProjectFolder;
|
|
16
17
|
folderUri: URI;
|
|
17
18
|
exclude?: (path: string) => boolean;
|
|
18
19
|
}
|
|
19
20
|
export interface Project {
|
|
20
|
-
id: ProjectId;
|
|
21
|
+
id: scalar.ProjectId;
|
|
21
22
|
folderUri: URI;
|
|
22
23
|
config: LikeC4ProjectConfig;
|
|
23
24
|
}
|
|
@@ -28,21 +29,7 @@ export declare class ProjectsManager {
|
|
|
28
29
|
* The global project ID used for all documents
|
|
29
30
|
* that are not part of a specific project.
|
|
30
31
|
*/
|
|
31
|
-
static readonly DefaultProjectId: ProjectId;
|
|
32
|
-
private static DefaultProject;
|
|
33
|
-
/**
|
|
34
|
-
* The mapping between project config files and project IDs.
|
|
35
|
-
*/
|
|
36
|
-
private projectIdToFolder;
|
|
37
|
-
/**
|
|
38
|
-
* Registered projects.
|
|
39
|
-
* Sorted descending by the number of segments in the folder path.
|
|
40
|
-
* This ensures that the most specific project is used for a document.
|
|
41
|
-
*/
|
|
42
|
-
private _projects;
|
|
43
|
-
private excludedDocuments;
|
|
44
|
-
private get defaultGlobalProject();
|
|
45
|
-
private reloadProjectsLimiter;
|
|
32
|
+
static readonly DefaultProjectId: scalar.ProjectId;
|
|
46
33
|
constructor(services: LikeC4SharedServices);
|
|
47
34
|
/**
|
|
48
35
|
* Returns:
|
|
@@ -51,16 +38,16 @@ export declare class ProjectsManager {
|
|
|
51
38
|
* - the ID of the only project
|
|
52
39
|
* - undefined if there are multiple projects.
|
|
53
40
|
*/
|
|
54
|
-
get defaultProjectId(): ProjectId | undefined;
|
|
55
|
-
set defaultProjectId(id: ProjectId | undefined);
|
|
56
|
-
get all(): NonEmptyReadonlyArray<ProjectId>;
|
|
57
|
-
getProject(arg: ProjectId | LangiumDocument): Project;
|
|
41
|
+
get defaultProjectId(): scalar.ProjectId | undefined;
|
|
42
|
+
set defaultProjectId(id: string | scalar.ProjectId | undefined);
|
|
43
|
+
get all(): NonEmptyReadonlyArray<scalar.ProjectId>;
|
|
44
|
+
getProject(arg: scalar.ProjectId | LangiumDocument): Project;
|
|
58
45
|
/**
|
|
59
46
|
* Validates and ensures the project ID.
|
|
60
47
|
* If no project ID is specified, returns default project ID
|
|
61
48
|
* If there are multiple projects and default project is not set, throws an error
|
|
62
49
|
*/
|
|
63
|
-
ensureProjectId(projectId?: ProjectId | undefined): ProjectId;
|
|
50
|
+
ensureProjectId(projectId?: scalar.ProjectId | undefined): scalar.ProjectId;
|
|
64
51
|
hasMultipleProjects(): boolean;
|
|
65
52
|
/**
|
|
66
53
|
* Checks if the specified document should be excluded from processing.
|
|
@@ -77,20 +64,25 @@ export declare class ProjectsManager {
|
|
|
77
64
|
*
|
|
78
65
|
* @param entry The file system entry to check
|
|
79
66
|
*/
|
|
80
|
-
|
|
67
|
+
registerConfigFile(configFile: URI): Promise<ProjectData | undefined>;
|
|
81
68
|
/**
|
|
82
69
|
* Registers (or reloads) likec4 project by config file or config object.
|
|
83
70
|
* If there is some project registered at same folder, it will be reloaded.
|
|
84
71
|
*/
|
|
85
72
|
registerProject(opts: URI | {
|
|
86
|
-
config:
|
|
73
|
+
config: LikeC4ProjectConfigInput;
|
|
87
74
|
folderUri: URI | string;
|
|
88
75
|
}): Promise<ProjectData>;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
76
|
+
/**
|
|
77
|
+
* Registers (or reloads) likec4 project by config file or config object.
|
|
78
|
+
* If there is some project registered at same folder, it will be reloaded.
|
|
79
|
+
*/
|
|
80
|
+
private _registerProject;
|
|
81
|
+
belongsTo(document: LangiumDocument | URI | string): scalar.ProjectId;
|
|
82
|
+
reloadProjects(): Promise<void>;
|
|
83
|
+
protected uniqueProjectId(name: string): scalar.ProjectId;
|
|
92
84
|
protected resetProjectIds(): void;
|
|
93
|
-
protected rebuidDocuments(): Promise<void>;
|
|
85
|
+
protected rebuidDocuments(cancelToken?: Cancellation.CancellationToken): Promise<void>;
|
|
94
86
|
protected findProjectForDocument(documentUri: string): any;
|
|
95
87
|
protected get mappingsToProject(): WorkspaceCache<string, Pick<ProjectData, 'id' | 'config' | 'exclude'>>;
|
|
96
88
|
}
|