@likec4/language-server 1.36.0 → 1.37.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.
Files changed (45) hide show
  1. package/dist/LikeC4LanguageServices.d.ts +38 -5
  2. package/dist/LikeC4LanguageServices.js +40 -10
  3. package/dist/Rpc.js +22 -6
  4. package/dist/bundled.mjs +2480 -2464
  5. package/dist/config/schema.d.ts +1 -1
  6. package/dist/config/schema.js +1 -1
  7. package/dist/likec4lib.d.ts +1 -1
  8. package/dist/lsp/DocumentLinkProvider.js +3 -3
  9. package/dist/lsp/DocumentSymbolProvider.js +1 -1
  10. package/dist/mcp/tools/list-projects.js +2 -2
  11. package/dist/mcp/tools/read-project-summary.js +2 -2
  12. package/dist/model/builder/buildModel.d.ts +1 -1
  13. package/dist/model/builder/buildModel.js +4 -6
  14. package/dist/model/model-parser.d.ts +9 -9
  15. package/dist/model/model-parser.js +3 -0
  16. package/dist/model/parser/Base.d.ts +1 -1
  17. package/dist/model/parser/Base.js +1 -1
  18. package/dist/model/parser/DeploymentModelParser.d.ts +1 -1
  19. package/dist/model/parser/DeploymentViewParser.d.ts +1 -1
  20. package/dist/model/parser/DeploymentViewParser.js +2 -2
  21. package/dist/model/parser/FqnRefParser.d.ts +1 -1
  22. package/dist/model/parser/FqnRefParser.js +8 -1
  23. package/dist/model/parser/GlobalsParser.d.ts +1 -1
  24. package/dist/model/parser/ImportsParser.d.ts +1 -1
  25. package/dist/model/parser/ModelParser.d.ts +1 -1
  26. package/dist/model/parser/PredicatesParser.d.ts +1 -1
  27. package/dist/model/parser/SpecificationParser.d.ts +1 -1
  28. package/dist/model/parser/ViewsParser.d.ts +1 -1
  29. package/dist/model/parser/ViewsParser.js +3 -3
  30. package/dist/module.d.ts +4 -0
  31. package/dist/module.js +4 -1
  32. package/dist/protocol.d.ts +18 -4
  33. package/dist/protocol.js +5 -1
  34. package/dist/test/testServices.d.ts +5 -2
  35. package/dist/test/testServices.js +4 -1
  36. package/dist/validation/DocumentValidator.d.ts +11 -0
  37. package/dist/validation/DocumentValidator.js +16 -0
  38. package/dist/validation/index.d.ts +1 -1
  39. package/dist/validation/index.js +1 -0
  40. package/dist/workspace/LangiumDocuments.d.ts +1 -0
  41. package/dist/workspace/LangiumDocuments.js +11 -2
  42. package/dist/workspace/ProjectsManager.d.ts +35 -17
  43. package/dist/workspace/ProjectsManager.js +169 -47
  44. package/dist/workspace/WorkspaceManager.js +1 -1
  45. package/package.json +6 -6
@@ -3,7 +3,7 @@ export declare const ProjectConfig: v.ObjectSchema<{
3
3
  readonly name: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.NonEmptyAction<string, "Project name cannot be empty">, v.ExcludesAction<string, "default", "Project name cannot be \"default\"">, v.ExcludesAction<string, ".", "Project name cannot contain \".\", try to use A-z, 0-9, _ and -">, v.ExcludesAction<string, "@", "Project name cannot contain \"@\", try to use A-z, 0-9, _ and -">, v.ExcludesAction<string, "#", "Project name cannot contain \"#\", try to use A-z, 0-9, _ and -">, v.DescriptionAction<string, "Project name, must be unique in the workspace">]>;
4
4
  readonly title: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.NonEmptyAction<string, "Project title cannot be empty if specified">, v.DescriptionAction<string, "A human readable title for the project">]>, undefined>;
5
5
  readonly contactPerson: v.OptionalSchema<v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.NonEmptyAction<string, "Contact person cannot be empty if specified">, v.DescriptionAction<string, "A person who has been involved in creating or maintaining this project">]>, undefined>;
6
- readonly exclude: v.OptionalSchema<v.SchemaWithPipe<readonly [v.ArraySchema<v.StringSchema<undefined>, undefined>, v.DescriptionAction<string[], "List of file patterns to exclude from the project, default is [\"**/node_modules/**/*\"]">]>, undefined>;
6
+ readonly exclude: v.OptionalSchema<v.SchemaWithPipe<readonly [v.ArraySchema<v.StringSchema<undefined>, undefined>, v.DescriptionAction<string[], "List of file patterns to exclude from the project, default is [\"**/node_modules/**\"]">]>, undefined>;
7
7
  }, undefined>;
8
8
  export type ProjectConfig = v.InferOutput<typeof ProjectConfig>;
9
9
  export declare function parseConfigJson(config: string): ProjectConfig;
@@ -27,7 +27,7 @@ export const ProjectConfig = v.object({
27
27
  exclude: v.optional(
28
28
  v.pipe(
29
29
  v.array(v.string()),
30
- v.description('List of file patterns to exclude from the project, default is ["**/node_modules/**/*"]')
30
+ v.description('List of file patterns to exclude from the project, default is ["**/node_modules/**"]')
31
31
  )
32
32
  )
33
33
  });
@@ -1,4 +1,4 @@
1
- import { type URI } from 'langium';
1
+ import type { URI } from 'vscode-uri';
2
2
  import { LibIcons } from './generated-lib/icons';
3
3
  export declare const Scheme = "likec4builtin";
4
4
  export declare const Uri: "likec4builtin:///likec4/lib/icons.c4";
@@ -7,7 +7,7 @@ export class LikeC4DocumentLinkProvider {
7
7
  this.services = services;
8
8
  }
9
9
  async getDocumentLinks(doc, _params, cancelToken) {
10
- if (!isLikeC4LangiumDocument(doc)) {
10
+ if (!isLikeC4LangiumDocument(doc) || this.services.likec4.LanguageServices.isExcluded(doc)) {
11
11
  return [];
12
12
  }
13
13
  return AstUtils.streamAllContents(doc.parseResult.value).filter(ast.isLinkProperty).map((n) => {
@@ -33,7 +33,7 @@ export class LikeC4DocumentLinkProvider {
33
33
  if (isRelative(link)) {
34
34
  return joinRelativeURL(doc.uri.toString(), "../", link);
35
35
  }
36
- const base = this.services.shared.workspace.ProjectsManager.getProject(doc).folder;
36
+ const base = this.services.shared.workspace.ProjectsManager.getProject(doc).folderUri;
37
37
  return joinRelativeURL(base.toString(), link);
38
38
  }
39
39
  relativeLink(doc, link) {
@@ -41,7 +41,7 @@ export class LikeC4DocumentLinkProvider {
41
41
  return withoutLeadingSlash(link);
42
42
  }
43
43
  if (isRelative(link)) {
44
- const base = this.services.shared.workspace.ProjectsManager.getProject(doc).folder.toString();
44
+ const base = this.services.shared.workspace.ProjectsManager.getProject(doc).folderUri.toString();
45
45
  const docURL = new URL(doc.uri.toString());
46
46
  const linkURL = new URL(link, docURL).toString();
47
47
  return withoutLeadingSlash(
@@ -19,7 +19,7 @@ export class LikeC4DocumentSymbolProvider {
19
19
  parser;
20
20
  locator;
21
21
  async getSymbols(doc, _params, cancelToken) {
22
- if (!isLikeC4LangiumDocument(doc)) {
22
+ if (!isLikeC4LangiumDocument(doc) || this.services.likec4.LanguageServices.isExcluded(doc)) {
23
23
  return [];
24
24
  }
25
25
  if (doc.state <= DocumentState.Linked) {
@@ -16,7 +16,7 @@ Returns array of projects with:
16
16
  outputSchema: {
17
17
  projects: z.array(z.object({
18
18
  name: z.string(),
19
- title: z.string().optional(),
19
+ title: z.string(),
20
20
  folder: z.string(),
21
21
  sources: z.array(z.string())
22
22
  }))
@@ -26,7 +26,7 @@ Returns array of projects with:
26
26
  return {
27
27
  projects: projects.map((p) => ({
28
28
  name: p.id,
29
- title: p.config?.title,
29
+ title: p.title,
30
30
  folder: p.folder.toString(),
31
31
  sources: p.documents?.map((d) => d.toString()) ?? []
32
32
  }))
@@ -29,7 +29,7 @@ Searches for LikeC4 project by name in workspace and returns its summary:
29
29
  project: z.string().optional().describe('Project name (optional, will use "default" if not specified)')
30
30
  },
31
31
  outputSchema: {
32
- title: z.string().optional(),
32
+ title: z.string(),
33
33
  folder: z.string(),
34
34
  sources: z.array(z.string()),
35
35
  specification: z.object({
@@ -52,7 +52,7 @@ Searches for LikeC4 project by name in workspace and returns its summary:
52
52
  invariant(project, `Project "${projectId}" not found`);
53
53
  const model = await languageServices.computedModel(project.id);
54
54
  return {
55
- title: project.config?.title,
55
+ title: project.title,
56
56
  folder: project.folder.toString(),
57
57
  sources: project.documents?.map((d) => d.toString()) ?? [],
58
58
  specification: {
@@ -16,6 +16,6 @@ export type BuildModelData = {
16
16
  */
17
17
  export declare function buildModelData(project: {
18
18
  id: c4.ProjectId;
19
- folder: URI;
19
+ folderUri: URI;
20
20
  config: Readonly<ProjectConfig>;
21
21
  }, docs: ParsedLikeC4LangiumDocument[]): BuildModelData;
@@ -190,16 +190,14 @@ export function buildModelData(project, docs) {
190
190
  indexBy(prop("id")),
191
191
  resolveRulesExtendedViews
192
192
  );
193
- const projectInfo = {
194
- id: project.id,
195
- name: project.config.name,
196
- ...project.config.title && { title: project.config.title }
197
- };
198
193
  return {
199
194
  data: {
200
195
  [c4._stage]: "parsed",
201
196
  projectId: project.id,
202
- project: projectInfo,
197
+ project: {
198
+ id: project.id,
199
+ title: project.config.title ?? project.config.name
200
+ },
203
201
  specification: {
204
202
  tags: c4Specification.tags,
205
203
  elements: c4Specification.specs.elements,
@@ -57,7 +57,7 @@ declare const DocumentParserFromMixins: {
57
57
  readonly doc: ParsedLikeC4LangiumDocument;
58
58
  get project(): {
59
59
  id: ProjectId;
60
- folder: ProjectId;
60
+ folderUri: ProjectId;
61
61
  config: Readonly<import("../config").ProjectConfig>;
62
62
  };
63
63
  resolveFqn(node: import("../generated/ast").FqnReferenceable): ProjectId;
@@ -150,7 +150,7 @@ declare const DocumentParserFromMixins: {
150
150
  readonly doc: ParsedLikeC4LangiumDocument;
151
151
  get project(): {
152
152
  id: ProjectId;
153
- folder: ProjectId;
153
+ folderUri: ProjectId;
154
154
  config: Readonly<import("../config").ProjectConfig>;
155
155
  };
156
156
  resolveFqn(node: import("../generated/ast").FqnReferenceable): ProjectId;
@@ -205,7 +205,7 @@ declare const DocumentParserFromMixins: {
205
205
  readonly doc: ParsedLikeC4LangiumDocument;
206
206
  get project(): {
207
207
  id: ProjectId;
208
- folder: ProjectId;
208
+ folderUri: ProjectId;
209
209
  config: Readonly<import("../config").ProjectConfig>;
210
210
  };
211
211
  resolveFqn(node: import("../generated/ast").FqnReferenceable): ProjectId;
@@ -274,7 +274,7 @@ declare const DocumentParserFromMixins: {
274
274
  readonly doc: ParsedLikeC4LangiumDocument;
275
275
  get project(): {
276
276
  id: ProjectId;
277
- folder: ProjectId;
277
+ folderUri: ProjectId;
278
278
  config: Readonly<import("../config").ProjectConfig>;
279
279
  };
280
280
  resolveFqn(node: import("../generated/ast").FqnReferenceable): ProjectId;
@@ -336,7 +336,7 @@ declare const DocumentParserFromMixins: {
336
336
  readonly doc: ParsedLikeC4LangiumDocument;
337
337
  get project(): {
338
338
  id: ProjectId;
339
- folder: ProjectId;
339
+ folderUri: ProjectId;
340
340
  config: Readonly<import("../config").ProjectConfig>;
341
341
  };
342
342
  resolveFqn(node: import("../generated/ast").FqnReferenceable): ProjectId;
@@ -406,7 +406,7 @@ declare const DocumentParserFromMixins: {
406
406
  readonly doc: ParsedLikeC4LangiumDocument;
407
407
  get project(): {
408
408
  id: ProjectId;
409
- folder: ProjectId;
409
+ folderUri: ProjectId;
410
410
  config: Readonly<import("../config").ProjectConfig>;
411
411
  };
412
412
  resolveFqn(node: import("../generated/ast").FqnReferenceable): ProjectId;
@@ -469,7 +469,7 @@ declare const DocumentParserFromMixins: {
469
469
  readonly doc: ParsedLikeC4LangiumDocument;
470
470
  get project(): {
471
471
  id: ProjectId;
472
- folder: ProjectId;
472
+ folderUri: ProjectId;
473
473
  config: Readonly<import("../config").ProjectConfig>;
474
474
  };
475
475
  resolveFqn(node: import("../generated/ast").FqnReferenceable): ProjectId;
@@ -512,7 +512,7 @@ declare const DocumentParserFromMixins: {
512
512
  readonly doc: ParsedLikeC4LangiumDocument;
513
513
  get project(): {
514
514
  id: ProjectId;
515
- folder: ProjectId;
515
+ folderUri: ProjectId;
516
516
  config: Readonly<import("../config").ProjectConfig>;
517
517
  };
518
518
  resolveFqn(node: import("../generated/ast").FqnReferenceable): ProjectId;
@@ -570,7 +570,7 @@ declare const DocumentParserFromMixins: {
570
570
  readonly doc: ParsedLikeC4LangiumDocument;
571
571
  get project(): {
572
572
  id: ProjectId;
573
- folder: ProjectId;
573
+ folderUri: ProjectId;
574
574
  config: Readonly<import("../config").ProjectConfig>;
575
575
  };
576
576
  resolveFqn(node: import("../generated/ast").FqnReferenceable): ProjectId;
@@ -37,6 +37,9 @@ export class LikeC4ModelParser {
37
37
  DocumentState.Linked,
38
38
  (doc) => {
39
39
  try {
40
+ if (services.shared.workspace.ProjectsManager.checkIfExcluded(doc)) {
41
+ return;
42
+ }
40
43
  if (!isLikeC4Builtin(doc.uri)) {
41
44
  this.cachedParsers.set(doc, this.createParser(doc));
42
45
  }
@@ -25,7 +25,7 @@ export declare class BaseParser {
25
25
  constructor(services: LikeC4Services, doc: ParsedLikeC4LangiumDocument);
26
26
  get project(): {
27
27
  id: c4.ProjectId;
28
- folder: URI;
28
+ folderUri: URI;
29
29
  config: Readonly<ProjectConfig>;
30
30
  };
31
31
  resolveFqn(node: ast.FqnReferenceable): c4.Fqn;
@@ -187,7 +187,7 @@ export class BaseParser {
187
187
  return joinRelativeURL(this.doc.uri.toString(), "../", value);
188
188
  }
189
189
  case (value && hasLeadingSlash(value)): {
190
- return joinURL(this.project.folder.toString(), value);
190
+ return joinURL(this.project.folderUri.toString(), value);
191
191
  }
192
192
  default: {
193
193
  return void 0;
@@ -32,7 +32,7 @@ export declare function DeploymentModelParser<TBase extends WithExpressionV2>(B:
32
32
  readonly doc: import("../../ast").ParsedLikeC4LangiumDocument;
33
33
  get project(): {
34
34
  id: c4.ProjectId;
35
- folder: c4;
35
+ folderUri: c4;
36
36
  config: Readonly<import("../../config").ProjectConfig>;
37
37
  };
38
38
  resolveFqn(node: ast.FqnReferenceable): c4.Fqn;
@@ -30,7 +30,7 @@ export declare function DeploymentViewParser<TBase extends WithExpressionV2 & Wi
30
30
  readonly doc: import("../../ast").ParsedLikeC4LangiumDocument;
31
31
  get project(): {
32
32
  id: c4.ProjectId;
33
- folder: c4;
33
+ folderUri: c4;
34
34
  config: Readonly<import("../../config").ProjectConfig>;
35
35
  };
36
36
  resolveFqn(node: ast.FqnReferenceable): c4.Fqn;
@@ -5,7 +5,7 @@ import { ast, parseMarkdownAsString, toAutoLayout, ViewOps } from "../../ast.js"
5
5
  import { logWarnError } from "../../logger.js";
6
6
  import { stringHash } from "../../utils/index.js";
7
7
  import { parseViewManualLayout } from "../../view-utils/manual-layout.js";
8
- import { removeIndent } from "./Base.js";
8
+ import { removeIndent, toSingleLine } from "./Base.js";
9
9
  export function DeploymentViewParser(B) {
10
10
  return class DeploymentViewParser extends B {
11
11
  parseDeploymentView(astNode) {
@@ -39,7 +39,7 @@ export function DeploymentViewParser(B) {
39
39
  [c4._type]: "deployment",
40
40
  id,
41
41
  astPath,
42
- title,
42
+ title: toSingleLine(title) ?? null,
43
43
  description,
44
44
  tags,
45
45
  links: isNonEmptyArray(links) ? links : null,
@@ -25,7 +25,7 @@ export declare function ExpressionV2Parser<TBase extends Base>(B: TBase): {
25
25
  readonly doc: import("../../ast").ParsedLikeC4LangiumDocument;
26
26
  get project(): {
27
27
  id: c4.ProjectId;
28
- folder: c4;
28
+ folderUri: c4;
29
29
  config: Readonly<import("../../config").ProjectConfig>;
30
30
  };
31
31
  resolveFqn(node: ast.FqnReferenceable): c4.Fqn;
@@ -88,7 +88,14 @@ export function ExpressionV2Parser(B) {
88
88
  }
89
89
  if (ast.isElementStringProperty(prop)) {
90
90
  if (isDefined(prop.value)) {
91
- acc.custom[prop.key] = removeIndent(parseMarkdownAsString(prop.value)) || "";
91
+ if (prop.key === "description") {
92
+ const parsed = this.parseMarkdownOrString(prop.value);
93
+ if (parsed) {
94
+ acc.custom["description"] = parsed;
95
+ }
96
+ } else {
97
+ acc.custom[prop.key] = removeIndent(parseMarkdownAsString(prop.value)) || "";
98
+ }
92
99
  }
93
100
  return acc;
94
101
  }
@@ -54,7 +54,7 @@ export declare function GlobalsParser<TBase extends WithViewsParser>(B: TBase):
54
54
  readonly doc: import("../../ast").ParsedLikeC4LangiumDocument;
55
55
  get project(): {
56
56
  id: c4.ProjectId;
57
- folder: c4;
57
+ folderUri: c4;
58
58
  config: Readonly<import("../../config").ProjectConfig>;
59
59
  };
60
60
  resolveFqn(node: ast.FqnReferenceable): c4.Fqn;
@@ -9,7 +9,7 @@ export declare function ImportsParser<TBase extends Base>(B: TBase): {
9
9
  readonly doc: import("../../ast").ParsedLikeC4LangiumDocument;
10
10
  get project(): {
11
11
  id: ProjectId;
12
- folder: ProjectId;
12
+ folderUri: ProjectId;
13
13
  config: Readonly<import("../../config").ProjectConfig>;
14
14
  };
15
15
  resolveFqn(node: ast.FqnReferenceable): ProjectId;
@@ -31,7 +31,7 @@ export declare function ModelParser<TBase extends WithExpressionV2>(B: TBase): {
31
31
  readonly doc: import("../../ast").ParsedLikeC4LangiumDocument;
32
32
  get project(): {
33
33
  id: c4.ProjectId;
34
- folder: c4;
34
+ folderUri: c4;
35
35
  config: Readonly<import("../../config").ProjectConfig>;
36
36
  };
37
37
  resolveFqn(node: ast.FqnReferenceable): c4.Fqn;
@@ -36,7 +36,7 @@ export declare function PredicatesParser<TBase extends WithExpressionV2>(B: TBas
36
36
  readonly doc: import("../../ast").ParsedLikeC4LangiumDocument;
37
37
  get project(): {
38
38
  id: c4.ProjectId;
39
- folder: c4;
39
+ folderUri: c4;
40
40
  config: Readonly<import("../../config").ProjectConfig>;
41
41
  };
42
42
  resolveFqn(node: ast.FqnReferenceable): c4.Fqn;
@@ -15,7 +15,7 @@ export declare function SpecificationParser<TBase extends Base>(B: TBase): {
15
15
  readonly doc: import("../../ast").ParsedLikeC4LangiumDocument;
16
16
  get project(): {
17
17
  id: c4.ProjectId;
18
- folder: c4;
18
+ folderUri: c4;
19
19
  config: Readonly<import("../../config").ProjectConfig>;
20
20
  };
21
21
  resolveFqn(node: ast.FqnReferenceable): c4.Fqn;
@@ -52,7 +52,7 @@ export declare function ViewsParser<TBase extends WithPredicates & WithDeploymen
52
52
  readonly doc: import("../../ast").ParsedLikeC4LangiumDocument;
53
53
  get project(): {
54
54
  id: c4.ProjectId;
55
- folder: c4;
55
+ folderUri: c4;
56
56
  config: Readonly<import("../../config").ProjectConfig>;
57
57
  };
58
58
  resolveFqn(node: ast.FqnReferenceable): c4.Fqn;
@@ -26,7 +26,7 @@ export function ViewsParser(B) {
26
26
  return [];
27
27
  }
28
28
  });
29
- const folder = viewBlock.folder && !isEmpty(viewBlock.folder.trim()) ? viewBlock.folder : null;
29
+ const folder = viewBlock.folder && !isEmpty(viewBlock.folder.trim()) ? toSingleLine(viewBlock.folder) : null;
30
30
  for (const view of viewBlock.views) {
31
31
  try {
32
32
  if (!isValid(view)) {
@@ -93,7 +93,7 @@ export function ViewsParser(B) {
93
93
  [c4._type]: "element",
94
94
  id,
95
95
  astPath,
96
- title,
96
+ title: toSingleLine(title) ?? null,
97
97
  description,
98
98
  tags,
99
99
  links: isNonEmptyArray(links) ? links : null,
@@ -245,7 +245,7 @@ export function ViewsParser(B) {
245
245
  [c4._type]: "dynamic",
246
246
  id,
247
247
  astPath,
248
- title,
248
+ title: toSingleLine(title) ?? null,
249
249
  description,
250
250
  tags,
251
251
  links: isNonEmptyArray(links) ? links : null,
package/dist/module.d.ts CHANGED
@@ -10,6 +10,7 @@ import { LikeC4ModelChanges } from './model-change/ModelChanges';
10
10
  import { LikeC4NameProvider, LikeC4ScopeComputation, LikeC4ScopeProvider } from './references';
11
11
  import { Rpc } from './Rpc';
12
12
  import { NodeKindProvider, WorkspaceSymbolProvider } from './shared';
13
+ import { LikeC4DocumentValidator } from './validation';
13
14
  import { type LikeC4Views } from './views';
14
15
  import { IndexManager, LangiumDocuments, LikeC4WorkspaceManager, ProjectsManager } from './workspace';
15
16
  interface LikeC4AddedSharedServices {
@@ -33,6 +34,9 @@ export interface LikeC4AddedServices {
33
34
  DocumentationProvider: LikeC4DocumentationProvider;
34
35
  };
35
36
  ValidatedWorkspaceCache: WorkspaceCache<string, any>;
37
+ validation: {
38
+ DocumentValidator: LikeC4DocumentValidator;
39
+ };
36
40
  Rpc: Rpc;
37
41
  mcp: {
38
42
  Server: LikeC4MCPServer;
package/dist/module.js CHANGED
@@ -45,7 +45,7 @@ import {
45
45
  NodeKindProvider,
46
46
  WorkspaceSymbolProvider
47
47
  } from "./shared/index.js";
48
- import { registerValidationChecks } from "./validation/index.js";
48
+ import { LikeC4DocumentValidator, registerValidationChecks } from "./validation/index.js";
49
49
  import { DefaultLikeC4Views } from "./views/index.js";
50
50
  import {
51
51
  AstNodeDescriptionProvider,
@@ -73,6 +73,9 @@ export const LikeC4Module = {
73
73
  documentation: {
74
74
  DocumentationProvider: bind(LikeC4DocumentationProvider)
75
75
  },
76
+ validation: {
77
+ DocumentValidator: bind(LikeC4DocumentValidator)
78
+ },
76
79
  ValidatedWorkspaceCache: (services) => new WorkspaceCache(services.shared, DocumentState.Validated),
77
80
  Rpc: bind(Rpc),
78
81
  mcp: {
@@ -1,6 +1,7 @@
1
1
  import type { ComputedLikeC4ModelData, ComputedView, DeploymentFqn, DiagramView, Fqn, LayoutedLikeC4ModelData, NonEmptyArray, ProjectId, RelationId, ViewChange, ViewId } from '@likec4/core';
2
- import { NotificationType, RequestType, RequestType0 } from 'vscode-languageserver';
3
- import type { DiagnosticSeverity, DocumentUri, Location, Position, Range } from 'vscode-languageserver-types';
2
+ import { NotificationType, RequestType, RequestType0 } from 'vscode-languageserver-protocol';
3
+ import type { DiagnosticSeverity, DocumentUri, Location, Position, Range, URI } from 'vscode-languageserver-types';
4
+ import type { ProjectConfig } from './config';
4
5
  export declare namespace DidChangeModelNotification {
5
6
  const type: NotificationType<string>;
6
7
  type Type = typeof type;
@@ -121,13 +122,26 @@ export declare namespace ValidateLayout {
121
122
  type Req = typeof Req;
122
123
  }
123
124
  /**
124
- * Request to build documents.
125
+ * Request to reload projects.
126
+ */
127
+ export declare namespace ReloadProjects {
128
+ type Params = never;
129
+ type Res = void;
130
+ const req: RequestType0<void, void>;
131
+ type Req = typeof req;
132
+ }
133
+ /**
134
+ * Fetch all non-empty projects.
125
135
  */
126
136
  export declare namespace FetchProjects {
127
137
  type Params = never;
128
138
  type Res = {
129
139
  projects: {
130
- [projectId: ProjectId]: NonEmptyArray<DocumentUri>;
140
+ [projectId: ProjectId]: {
141
+ folder: URI;
142
+ config: ProjectConfig;
143
+ docs: NonEmptyArray<DocumentUri>;
144
+ };
131
145
  };
132
146
  };
133
147
  const req: RequestType0<Res, void>;
package/dist/protocol.js CHANGED
@@ -1,4 +1,4 @@
1
- import { NotificationType, RequestType, RequestType0 } from "vscode-languageserver";
1
+ import { NotificationType, RequestType, RequestType0 } from "vscode-languageserver-protocol";
2
2
  export var DidChangeModelNotification;
3
3
  ((DidChangeModelNotification2) => {
4
4
  DidChangeModelNotification2.type = new NotificationType("likec4/onDidChangeModel");
@@ -31,6 +31,10 @@ export var ValidateLayout;
31
31
  ((ValidateLayout2) => {
32
32
  ValidateLayout2.Req = new RequestType("likec4/validate-layout");
33
33
  })(ValidateLayout || (ValidateLayout = {}));
34
+ export var ReloadProjects;
35
+ ((ReloadProjects2) => {
36
+ ReloadProjects2.req = new RequestType0("likec4/reload-projects");
37
+ })(ReloadProjects || (ReloadProjects = {}));
34
38
  export var FetchProjects;
35
39
  ((FetchProjects2) => {
36
40
  FetchProjects2.req = new RequestType0("likec4/fetch-projects");
@@ -1,4 +1,6 @@
1
1
  import type { ComputedLikeC4ModelData } from '@likec4/core';
2
+ import type { LiteralUnion } from 'type-fest';
3
+ import { URI } from 'vscode-uri';
2
4
  import type { LikeC4LangiumDocument } from '../ast';
3
5
  export declare function createTestServices(workspace?: string): {
4
6
  services: any;
@@ -38,6 +40,7 @@ export declare function createMultiProjectTestServices<const Projects extends Re
38
40
  services: any;
39
41
  projects: { readonly [K in keyof Projects]: { readonly [L in keyof Projects[K]]: LikeC4LangiumDocument; }; };
40
42
  projectsManager: any;
43
+ addDocument: (uri: string | URI, input: string) => Promise<LikeC4LangiumDocument>;
41
44
  /**
42
45
  * Add document outside of projects
43
46
  */
@@ -47,8 +50,8 @@ export declare function createMultiProjectTestServices<const Projects extends Re
47
50
  errors: any;
48
51
  warnings: any;
49
52
  }>;
50
- buildModel: (projectId: keyof Projects) => Promise<ComputedLikeC4ModelData>;
51
- buildLikeC4Model: (projectId: keyof Projects) => Promise<any>;
53
+ buildModel: (projectId: LiteralUnion<keyof Projects, string>) => Promise<ComputedLikeC4ModelData>;
54
+ buildLikeC4Model: (projectId: LiteralUnion<keyof Projects, string>) => Promise<any>;
52
55
  }>;
53
56
  export type TestServices = ReturnType<typeof createTestServices>;
54
57
  export type TestParseFn = TestServices['validate'];
@@ -165,12 +165,15 @@ export async function createMultiProjectTestServices(data) {
165
165
  }
166
166
  async function buildModel(projectId) {
167
167
  const model = await buildLikeC4Model(projectId);
168
- return model.$model;
168
+ return model.$data;
169
169
  }
170
170
  return {
171
171
  services,
172
172
  projects,
173
173
  projectsManager: services.shared.workspace.ProjectsManager,
174
+ addDocument: async (uri, input) => {
175
+ return await addDocument(input, uri.toString());
176
+ },
174
177
  /**
175
178
  * Add document outside of projects
176
179
  */
@@ -0,0 +1,11 @@
1
+ import { type LangiumDocument, type ValidationOptions, Cancellation, DefaultDocumentValidator } from 'langium';
2
+ import type { Diagnostic } from 'vscode-languageserver-types';
3
+ import type { LikeC4Services } from '../module';
4
+ export declare class LikeC4DocumentValidator extends DefaultDocumentValidator {
5
+ protected services: LikeC4Services;
6
+ constructor(services: LikeC4Services);
7
+ /**
8
+ * If the document is excluded, then we skip validation and return an empty array of diagnostics.
9
+ */
10
+ validateDocument(document: LangiumDocument, options?: ValidationOptions, cancelToken?: Cancellation.CancellationToken): Promise<Diagnostic[]>;
11
+ }
@@ -0,0 +1,16 @@
1
+ import { DefaultDocumentValidator } from "langium";
2
+ export class LikeC4DocumentValidator extends DefaultDocumentValidator {
3
+ constructor(services) {
4
+ super(services);
5
+ this.services = services;
6
+ }
7
+ /**
8
+ * If the document is excluded, then we skip validation and return an empty array of diagnostics.
9
+ */
10
+ async validateDocument(document, options, cancelToken) {
11
+ if (this.services.shared.workspace.ProjectsManager.checkIfExcluded(document)) {
12
+ return [];
13
+ }
14
+ return await super.validateDocument(document, options, cancelToken);
15
+ }
16
+ }
@@ -1,6 +1,7 @@
1
1
  import { type AstNode } from 'langium';
2
2
  import { type LikeC4LangiumDocument, ast } from '../ast';
3
3
  import type { LikeC4Services } from '../module';
4
+ export { LikeC4DocumentValidator } from './DocumentValidator';
4
5
  type Guard<N extends AstNode> = (n: AstNode) => n is N;
5
6
  type Guarded<G> = G extends Guard<infer N> ? N : never;
6
7
  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;
@@ -12,4 +13,3 @@ export declare function checksFromDiagnostics(doc: LikeC4LangiumDocument): {
12
13
  export type ChecksFromDiagnostics = ReturnType<typeof checksFromDiagnostics>;
13
14
  export type IsValidFn = ChecksFromDiagnostics['isValid'];
14
15
  export declare function registerValidationChecks(services: LikeC4Services): void;
15
- export {};
@@ -40,6 +40,7 @@ import {
40
40
  checkRelationExpr,
41
41
  checkRelationExprWith
42
42
  } from "./view-predicates/index.js";
43
+ export { LikeC4DocumentValidator } from "./DocumentValidator.js";
43
44
  function validatableAstNodeGuards(predicates) {
44
45
  return (n) => predicates.some((p) => p(n));
45
46
  }
@@ -11,4 +11,5 @@ export declare class LangiumDocuments extends DefaultLangiumDocuments {
11
11
  get allExcludingBuiltin(): Stream<LikeC4LangiumDocument>;
12
12
  projectDocuments(projectId: ProjectId): Stream<LikeC4LangiumDocument>;
13
13
  groupedByProject(): Record<ProjectId, NonEmptyArray<LikeC4LangiumDocument>>;
14
+ resetProjectIds(): void;
14
15
  }
@@ -13,10 +13,10 @@ export class LangiumDocuments extends DefaultLangiumDocuments {
13
13
  get allExcludingBuiltin() {
14
14
  const projects = this.services.workspace.ProjectsManager;
15
15
  return super.all.filter((doc) => {
16
- if (!isLikeC4LangiumDocument(doc) || isLikeC4Builtin(doc.uri)) {
16
+ if (!isLikeC4LangiumDocument(doc) || isLikeC4Builtin(doc.uri) || projects.checkIfExcluded(doc)) {
17
17
  return false;
18
18
  }
19
- doc.likec4ProjectId ??= projects.belongsTo(doc.uri);
19
+ doc.likec4ProjectId = projects.belongsTo(doc.uri);
20
20
  return true;
21
21
  });
22
22
  }
@@ -26,4 +26,13 @@ export class LangiumDocuments extends DefaultLangiumDocuments {
26
26
  groupedByProject() {
27
27
  return groupBy(this.allExcludingBuiltin.toArray(), prop("likec4ProjectId"));
28
28
  }
29
+ resetProjectIds() {
30
+ const projects = this.services.workspace.ProjectsManager;
31
+ this.all.forEach((doc) => {
32
+ if (!isLikeC4LangiumDocument(doc) || isLikeC4Builtin(doc.uri)) {
33
+ return;
34
+ }
35
+ doc.likec4ProjectId = projects.belongsTo(doc);
36
+ });
37
+ }
29
38
  }