@likec4/language-server 1.36.1 → 1.38.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 (94) hide show
  1. package/dist/LikeC4LanguageServices.d.ts +43 -7
  2. package/dist/LikeC4LanguageServices.js +51 -11
  3. package/dist/Rpc.js +22 -6
  4. package/dist/browser.d.ts +1 -1
  5. package/dist/browser.js +1 -1
  6. package/dist/bundled.mjs +4258 -3083
  7. package/dist/config/schema.d.ts +1 -1
  8. package/dist/config/schema.js +1 -1
  9. package/dist/empty.d.ts +2 -0
  10. package/dist/empty.js +1 -0
  11. package/dist/filesystem/ChokidarWatcher.d.ts +14 -0
  12. package/dist/filesystem/ChokidarWatcher.js +64 -0
  13. package/dist/filesystem/FileSystemWatcher.d.ts +19 -0
  14. package/dist/filesystem/FileSystemWatcher.js +11 -0
  15. package/dist/filesystem/LikeC4FileSystem.d.ts +5 -0
  16. package/dist/filesystem/LikeC4FileSystem.js +56 -0
  17. package/dist/filesystem/index.d.ts +20 -0
  18. package/dist/filesystem/index.js +16 -0
  19. package/dist/index.d.ts +18 -4
  20. package/dist/index.js +23 -10
  21. package/dist/likec4lib.d.ts +1 -1
  22. package/dist/lsp/DocumentLinkProvider.js +3 -3
  23. package/dist/lsp/DocumentSymbolProvider.js +1 -1
  24. package/dist/mcp/{sseserver/MCPServerFactory.d.ts → MCPServerFactory.d.ts} +1 -1
  25. package/dist/mcp/MCPServerFactory.js +69 -0
  26. package/dist/mcp/NoopLikeC4MCPServer.d.ts +4 -10
  27. package/dist/mcp/NoopLikeC4MCPServer.js +5 -10
  28. package/dist/mcp/interfaces.d.ts +7 -5
  29. package/dist/mcp/interfaces.js +4 -0
  30. package/dist/mcp/server/StdioLikeC4MCPServer.d.ts +16 -0
  31. package/dist/mcp/server/StdioLikeC4MCPServer.js +43 -0
  32. package/dist/mcp/{sseserver/MCPServer.d.ts → server/StreamableLikeC4MCPServer.d.ts} +3 -2
  33. package/dist/mcp/server/StreamableLikeC4MCPServer.js +156 -0
  34. package/dist/mcp/server/WithMCPServer.d.ts +2 -0
  35. package/dist/mcp/server/WithMCPServer.js +57 -0
  36. package/dist/mcp/tools/_common.d.ts +24 -5
  37. package/dist/mcp/tools/_common.js +31 -3
  38. package/dist/mcp/tools/find-relationships.d.ts +13 -0
  39. package/dist/mcp/tools/find-relationships.js +151 -0
  40. package/dist/mcp/tools/list-projects.js +42 -14
  41. package/dist/mcp/tools/open-view.d.ts +4 -3
  42. package/dist/mcp/tools/open-view.js +37 -14
  43. package/dist/mcp/tools/{read-project-elements.d.ts → read-deployment.d.ts} +6 -3
  44. package/dist/mcp/tools/read-deployment.js +130 -0
  45. package/dist/mcp/tools/read-element.d.ts +4 -3
  46. package/dist/mcp/tools/read-element.js +114 -51
  47. package/dist/mcp/tools/read-project-summary.d.ts +3 -2
  48. package/dist/mcp/tools/read-project-summary.js +141 -34
  49. package/dist/mcp/tools/read-view.d.ts +4 -3
  50. package/dist/mcp/tools/read-view.js +146 -105
  51. package/dist/mcp/tools/search-element.js +81 -30
  52. package/dist/mcp/utils.js +7 -4
  53. package/dist/model/builder/buildModel.d.ts +1 -1
  54. package/dist/model/builder/buildModel.js +4 -6
  55. package/dist/model/model-parser.d.ts +9 -9
  56. package/dist/model/model-parser.js +3 -0
  57. package/dist/model/parser/Base.d.ts +1 -1
  58. package/dist/model/parser/Base.js +1 -1
  59. package/dist/model/parser/DeploymentModelParser.d.ts +1 -1
  60. package/dist/model/parser/DeploymentViewParser.d.ts +1 -1
  61. package/dist/model/parser/DeploymentViewParser.js +2 -2
  62. package/dist/model/parser/FqnRefParser.d.ts +1 -1
  63. package/dist/model/parser/FqnRefParser.js +8 -1
  64. package/dist/model/parser/GlobalsParser.d.ts +1 -1
  65. package/dist/model/parser/ImportsParser.d.ts +1 -1
  66. package/dist/model/parser/ModelParser.d.ts +1 -1
  67. package/dist/model/parser/PredicatesParser.d.ts +1 -1
  68. package/dist/model/parser/SpecificationParser.d.ts +1 -1
  69. package/dist/model/parser/ViewsParser.d.ts +1 -1
  70. package/dist/model/parser/ViewsParser.js +3 -3
  71. package/dist/module.d.ts +13 -9
  72. package/dist/module.js +28 -30
  73. package/dist/protocol.d.ts +18 -4
  74. package/dist/protocol.js +5 -1
  75. package/dist/test/testServices.d.ts +5 -2
  76. package/dist/test/testServices.js +7 -3
  77. package/dist/validation/DocumentValidator.d.ts +11 -0
  78. package/dist/validation/DocumentValidator.js +16 -0
  79. package/dist/validation/index.d.ts +1 -1
  80. package/dist/validation/index.js +1 -0
  81. package/dist/workspace/LangiumDocuments.d.ts +1 -0
  82. package/dist/workspace/LangiumDocuments.js +10 -1
  83. package/dist/workspace/ProjectsManager.d.ts +35 -17
  84. package/dist/workspace/ProjectsManager.js +168 -54
  85. package/dist/workspace/WorkspaceManager.d.ts +9 -2
  86. package/dist/workspace/WorkspaceManager.js +31 -40
  87. package/package.json +14 -10
  88. package/dist/LikeC4FileSystem.d.ts +0 -14
  89. package/dist/LikeC4FileSystem.js +0 -39
  90. package/dist/mcp/sseserver/MCPServer.js +0 -80
  91. package/dist/mcp/sseserver/MCPServerFactory.js +0 -50
  92. package/dist/mcp/sseserver/WithMCPServer.d.ts +0 -9
  93. package/dist/mcp/sseserver/WithMCPServer.js +0 -53
  94. package/dist/mcp/tools/read-project-elements.js +0 -93
@@ -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
@@ -2,16 +2,20 @@ 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';
5
+ import { type FileSystemModuleContext, type FileSystemProvider, type FileSystemWatcher } from './filesystem';
5
6
  import { type LikeC4LanguageServices } from './LikeC4LanguageServices';
6
7
  import { LikeC4CodeLensProvider, LikeC4CompletionProvider, LikeC4DocumentHighlightProvider, LikeC4DocumentLinkProvider, LikeC4DocumentSymbolProvider, LikeC4HoverProvider, LikeC4SemanticTokenProvider } from './lsp';
7
- import { type LikeC4MCPServer, type LikeC4MCPServerFactory } from './mcp/interfaces';
8
+ import { type LikeC4MCPServer, type LikeC4MCPServerModuleContext } from './mcp/interfaces';
9
+ import { LikeC4MCPServerFactory } from './mcp/MCPServerFactory';
8
10
  import { type LikeC4ModelBuilder, DeploymentsIndex, FqnIndex, LikeC4ModelLocator, LikeC4ModelParser, LikeC4ValueConverter } from './model';
9
11
  import { LikeC4ModelChanges } from './model-change/ModelChanges';
10
12
  import { LikeC4NameProvider, LikeC4ScopeComputation, LikeC4ScopeProvider } from './references';
11
13
  import { Rpc } from './Rpc';
12
14
  import { NodeKindProvider, WorkspaceSymbolProvider } from './shared';
15
+ import { LikeC4DocumentValidator } from './validation';
13
16
  import { type LikeC4Views } from './views';
14
17
  import { IndexManager, LangiumDocuments, LikeC4WorkspaceManager, ProjectsManager } from './workspace';
18
+ export type LanguageServicesContext = Omit<DefaultSharedModuleContext, 'fileSystemProvider'> & FileSystemModuleContext & LikeC4MCPServerModuleContext;
15
19
  interface LikeC4AddedSharedServices {
16
20
  lsp: {
17
21
  NodeKindProvider: NodeKindProvider;
@@ -22,6 +26,8 @@ interface LikeC4AddedSharedServices {
22
26
  IndexManager: IndexManager;
23
27
  LangiumDocuments: LangiumDocuments;
24
28
  WorkspaceManager: LikeC4WorkspaceManager;
29
+ FileSystemProvider: FileSystemProvider;
30
+ FileSystemWatcher: FileSystemWatcher;
25
31
  };
26
32
  }
27
33
  export type LikeC4SharedServices = LangiumSharedServices & LikeC4AddedSharedServices;
@@ -33,6 +39,9 @@ export interface LikeC4AddedServices {
33
39
  DocumentationProvider: LikeC4DocumentationProvider;
34
40
  };
35
41
  ValidatedWorkspaceCache: WorkspaceCache<string, any>;
42
+ validation: {
43
+ DocumentValidator: LikeC4DocumentValidator;
44
+ };
36
45
  Rpc: Rpc;
37
46
  mcp: {
38
47
  Server: LikeC4MCPServer;
@@ -69,15 +78,10 @@ export interface LikeC4AddedServices {
69
78
  };
70
79
  }
71
80
  export type LikeC4Services = LangiumServices & LikeC4AddedServices;
72
- export declare const LikeC4Module: Module<LikeC4Services, PartialLangiumServices & LikeC4AddedServices>;
73
- export type LanguageServicesContext = Partial<DefaultSharedModuleContext>;
74
- export declare function createCustomLanguageServices<I1, I2, I3, I extends I1 & I2 & I3 & LikeC4Services>(context: LanguageServicesContext, module?: Module<I, I1>, module2?: Module<I, I2>, module3?: Module<I, I3>): {
81
+ export declare const createLikeC4Module: (context: LikeC4MCPServerModuleContext) => Module<LikeC4Services, PartialLangiumServices & LikeC4AddedServices>;
82
+ export declare function createLanguageServices<I1, I2, I3, I extends I1 & I2 & I3 & LikeC4Services>(context: Partial<LanguageServicesContext>, module?: Module<I, I1>, module2?: Module<I, I2>, module3?: Module<I, I3>): {
75
83
  shared: LikeC4SharedServices;
76
84
  likec4: I;
77
85
  };
78
- export declare function createSharedServices(context?: LanguageServicesContext): LikeC4SharedServices;
79
- export declare function createLanguageServices(context?: LanguageServicesContext): {
80
- shared: LikeC4SharedServices;
81
- likec4: LikeC4Services;
82
- };
86
+ export declare function createSharedServices(context?: Partial<LanguageServicesContext>): LikeC4SharedServices;
83
87
  export {};
package/dist/module.js CHANGED
@@ -1,7 +1,6 @@
1
1
  import { GraphvizWasmAdapter, QueueGraphvizLayoter } from "@likec4/layouts";
2
2
  import {
3
3
  DocumentState,
4
- EmptyFileSystem,
5
4
  inject,
6
5
  WorkspaceCache
7
6
  } from "langium";
@@ -10,6 +9,9 @@ import {
10
9
  createDefaultSharedModule
11
10
  } from "langium/lsp";
12
11
  import { LikeC4DocumentationProvider } from "./documentation/index.js";
12
+ import {
13
+ NoopFileSystem
14
+ } from "./filesystem/index.js";
13
15
  import { LikeC4Formatter } from "./formatting/LikeC4Formatter.js";
14
16
  import {
15
17
  LikeC4GeneratedModule,
@@ -25,7 +27,10 @@ import {
25
27
  LikeC4HoverProvider,
26
28
  LikeC4SemanticTokenProvider
27
29
  } from "./lsp/index.js";
28
- import { NoopLikeC4MCPServer, NoopLikeC4MCPServerFactory } from "./mcp/NoopLikeC4MCPServer.js";
30
+ import {
31
+ NoMCPServer
32
+ } from "./mcp/interfaces.js";
33
+ import { LikeC4MCPServerFactory } from "./mcp/MCPServerFactory.js";
29
34
  import {
30
35
  DefaultLikeC4ModelBuilder,
31
36
  DeploymentsIndex,
@@ -45,7 +50,7 @@ import {
45
50
  NodeKindProvider,
46
51
  WorkspaceSymbolProvider
47
52
  } from "./shared/index.js";
48
- import { registerValidationChecks } from "./validation/index.js";
53
+ import { LikeC4DocumentValidator, registerValidationChecks } from "./validation/index.js";
49
54
  import { DefaultLikeC4Views } from "./views/index.js";
50
55
  import {
51
56
  AstNodeDescriptionProvider,
@@ -54,7 +59,7 @@ import {
54
59
  LikeC4WorkspaceManager,
55
60
  ProjectsManager
56
61
  } from "./workspace/index.js";
57
- const LikeC4SharedModule = {
62
+ const createLikeC4SharedModule = (context) => ({
58
63
  lsp: {
59
64
  NodeKindProvider: (services) => new NodeKindProvider(services),
60
65
  WorkspaceSymbolProvider: (services) => new WorkspaceSymbolProvider(services)
@@ -63,21 +68,26 @@ const LikeC4SharedModule = {
63
68
  IndexManager: (services) => new IndexManager(services),
64
69
  LangiumDocuments: (services) => new LangiumDocuments(services),
65
70
  ProjectsManager: (services) => new ProjectsManager(services),
66
- WorkspaceManager: (services) => new LikeC4WorkspaceManager(services)
71
+ WorkspaceManager: (services) => new LikeC4WorkspaceManager(services),
72
+ FileSystemProvider: (services) => context.fileSystemProvider(services),
73
+ FileSystemWatcher: (services) => context.fileSystemWatcher(services)
67
74
  }
68
- };
75
+ });
69
76
  function bind(Type) {
70
77
  return (services) => new Type(services);
71
78
  }
72
- export const LikeC4Module = {
79
+ export const createLikeC4Module = (context) => ({
73
80
  documentation: {
74
81
  DocumentationProvider: bind(LikeC4DocumentationProvider)
75
82
  },
83
+ validation: {
84
+ DocumentValidator: bind(LikeC4DocumentValidator)
85
+ },
76
86
  ValidatedWorkspaceCache: (services) => new WorkspaceCache(services.shared, DocumentState.Validated),
77
87
  Rpc: bind(Rpc),
78
88
  mcp: {
79
- Server: bind(NoopLikeC4MCPServer),
80
- ServerFactory: bind(NoopLikeC4MCPServerFactory)
89
+ Server: (services) => context.mcpServer(services),
90
+ ServerFactory: bind(LikeC4MCPServerFactory)
81
91
  },
82
92
  likec4: {
83
93
  LanguageServices: bind(DefaultLikeC4LanguageServices),
@@ -116,13 +126,16 @@ export const LikeC4Module = {
116
126
  parser: {
117
127
  ValueConverter: bind(LikeC4ValueConverter)
118
128
  }
119
- };
120
- export function createCustomLanguageServices(context, module, module2, module3) {
129
+ });
130
+ export function createLanguageServices(context, module, module2, module3) {
121
131
  const shared = createSharedServices(context);
122
132
  const modules = [
123
133
  createDefaultModule({ shared }),
124
134
  LikeC4GeneratedModule,
125
- LikeC4Module,
135
+ createLikeC4Module({
136
+ ...NoMCPServer,
137
+ ...context
138
+ }),
126
139
  module,
127
140
  module2,
128
141
  module3
@@ -139,30 +152,15 @@ export function createCustomLanguageServices(context, module, module2, module3)
139
152
  }
140
153
  export function createSharedServices(context = {}) {
141
154
  const moduleContext = {
142
- ...EmptyFileSystem,
155
+ ...NoMCPServer,
156
+ ...NoopFileSystem,
143
157
  ...context
144
158
  };
145
159
  return inject(
146
160
  createDefaultSharedModule(moduleContext),
147
161
  LikeC4GeneratedSharedModule,
148
- LikeC4SharedModule
149
- );
150
- }
151
- export function createLanguageServices(context = {}) {
152
- const shared = createSharedServices(context);
153
- const likec4 = inject(
154
- createDefaultModule({ shared }),
155
- LikeC4GeneratedModule,
156
- LikeC4Module
162
+ createLikeC4SharedModule(moduleContext)
157
163
  );
158
- shared.ServiceRegistry.register(likec4);
159
- registerValidationChecks(likec4);
160
- if (!context.connection) {
161
- shared.workspace.ConfigurationProvider.initialized({});
162
- } else {
163
- likec4.Rpc.init();
164
- }
165
- return { shared, likec4 };
166
164
  }
167
165
  function _merge(target, source) {
168
166
  if (source) {
@@ -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-jsonrpc';
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-jsonrpc";
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'];
@@ -1,12 +1,13 @@
1
- import { DocumentState, EmptyFileSystem, TextDocument, UriUtils } from "langium";
1
+ import { DocumentState, TextDocument, UriUtils } from "langium";
2
2
  import * as assert from "node:assert";
3
3
  import { entries } from "remeda";
4
4
  import stripIndent from "strip-indent";
5
5
  import { DiagnosticSeverity } from "vscode-languageserver-types";
6
6
  import { URI, Utils } from "vscode-uri";
7
+ import { NoopFileSystem } from "../filesystem/index.js";
7
8
  import { createLanguageServices } from "../module.js";
8
9
  export function createTestServices(workspace = "file:///test/workspace") {
9
- const services = createLanguageServices(EmptyFileSystem).likec4;
10
+ const services = createLanguageServices(NoopFileSystem).likec4;
10
11
  const metaData = services.LanguageMetaData;
11
12
  const langiumDocuments = services.shared.workspace.LangiumDocuments;
12
13
  const documentBuilder = services.shared.workspace.DocumentBuilder;
@@ -165,12 +166,15 @@ export async function createMultiProjectTestServices(data) {
165
166
  }
166
167
  async function buildModel(projectId) {
167
168
  const model = await buildLikeC4Model(projectId);
168
- return model.$model;
169
+ return model.$data;
169
170
  }
170
171
  return {
171
172
  services,
172
173
  projects,
173
174
  projectsManager: services.shared.workspace.ProjectsManager,
175
+ addDocument: async (uri, input) => {
176
+ return await addDocument(input, uri.toString());
177
+ },
174
178
  /**
175
179
  * Add document outside of projects
176
180
  */
@@ -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,7 +13,7 @@ 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
19
  doc.likec4ProjectId = projects.belongsTo(doc.uri);
@@ -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
  }
@@ -1,14 +1,27 @@
1
1
  import type { NonEmptyReadonlyArray, ProjectId } from '@likec4/core';
2
- import { type FileSystemNode, type LangiumDocument, URI, WorkspaceCache } from 'langium';
3
- import picomatch from 'picomatch/posix';
2
+ import { type Cancellation, type FileSystemNode, type LangiumDocument, URI, WorkspaceCache } from 'langium';
3
+ import picomatch from 'picomatch';
4
+ import type { Tagged } from 'type-fest';
4
5
  import { ProjectConfig } from '../config';
5
6
  import type { LikeC4SharedServices } from '../module';
6
- interface Project {
7
+ /**
8
+ * A tagged string that represents a project folder.
9
+ * Always has trailing slash.
10
+ */
11
+ export type ProjectFolder = Tagged<string, 'ProjectFolder'>;
12
+ export declare function ProjectFolder(folder: URI | string): ProjectFolder;
13
+ interface ProjectData {
7
14
  id: ProjectId;
8
15
  config: ProjectConfig;
9
- folder: string;
16
+ folder: ProjectFolder;
17
+ folderUri: URI;
10
18
  exclude?: picomatch.Matcher;
11
19
  }
20
+ export interface Project {
21
+ id: ProjectId;
22
+ folderUri: URI;
23
+ config: ProjectConfig;
24
+ }
12
25
  export declare class ProjectsManager {
13
26
  protected services: LikeC4SharedServices;
14
27
  /**
@@ -27,7 +40,9 @@ export declare class ProjectsManager {
27
40
  * This ensures that the most specific project is used for a document.
28
41
  */
29
42
  private _projects;
43
+ private excludedDocuments;
30
44
  private defaultGlobalProject;
45
+ private reloadProjectsLimiter;
31
46
  constructor(services: LikeC4SharedServices);
32
47
  /**
33
48
  * Returns:
@@ -37,29 +52,32 @@ export declare class ProjectsManager {
37
52
  */
38
53
  get defaultProjectId(): ProjectId | undefined;
39
54
  get all(): NonEmptyReadonlyArray<ProjectId>;
40
- getProject(arg: ProjectId | LangiumDocument): {
41
- id: ProjectId;
42
- folder: URI;
43
- config: Readonly<ProjectConfig>;
44
- };
55
+ getProject(arg: ProjectId | LangiumDocument): Project;
45
56
  ensureProjectId(projectId?: ProjectId | undefined): ProjectId;
46
57
  hasMultipleProjects(): boolean;
47
- checkIfExcluded(documentUri: URI): boolean;
48
- isConfigFile(entry: FileSystemNode): boolean;
58
+ checkIfExcluded(document: LangiumDocument | URI | string): boolean;
59
+ /**
60
+ * Checks if it is a config file and it is not excluded by default exclude pattern
61
+ *
62
+ * @param entry The file system entry to check
63
+ */
64
+ isConfigFile(entry: URI): boolean;
49
65
  /**
50
66
  * Checks if the provided file system entry is a valid project config file.
51
67
  *
52
68
  * @param entry The file system entry to check
53
69
  */
54
- loadConfigFile(entry: FileSystemNode): Promise<Project | undefined>;
55
- registerProject(configFile: URI): Promise<Project>;
70
+ loadConfigFile(entry: FileSystemNode): Promise<ProjectData | undefined>;
71
+ registerProject(configFile: URI): Promise<ProjectData>;
56
72
  registerProject(opts: {
57
73
  config: ProjectConfig;
58
74
  folderUri: URI | string;
59
- }): Promise<Project>;
75
+ }): Promise<ProjectData>;
60
76
  belongsTo(document: LangiumDocument | URI | string): ProjectId;
61
- protected findProjectForDocument(documentUri: string): Omit<Project, 'folder'>;
62
- private _mappingsToProject;
63
- protected get mappingsToProject(): WorkspaceCache<string, Omit<Project, 'folder'>>;
77
+ reloadProjects(token?: Cancellation.CancellationToken): Promise<void>;
78
+ protected uniqueProjectId(name: string): ProjectId;
79
+ protected resetProjectIds(): void;
80
+ protected findProjectForDocument(documentUri: string): any;
81
+ protected get mappingsToProject(): WorkspaceCache<string, Pick<ProjectData, 'id' | 'config' | 'exclude'>>;
64
82
  }
65
83
  export {};