@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
@@ -1,8 +1,7 @@
1
1
  import { type DiagramView, type NonEmptyArray, type ProjectId } from '@likec4/core';
2
2
  import { LikeC4Model } from '@likec4/core/model';
3
- import { URI } from 'langium';
3
+ import { type LangiumDocument, URI } from 'langium';
4
4
  import { type Range } from 'vscode-languageserver-types';
5
- import type { ProjectConfig } from './config';
6
5
  import type { LikeC4ModelBuilder } from './model';
7
6
  import type { LikeC4Services } from './module';
8
7
  import type { Locate } from './protocol';
@@ -13,13 +12,28 @@ export interface LikeC4LanguageServices {
13
12
  readonly builder: LikeC4ModelBuilder;
14
13
  readonly workspaceUri: URI;
15
14
  readonly projectsManager: ProjectsManager;
15
+ /**
16
+ * Returns all projects with relevant documents
17
+ */
16
18
  projects(): NonEmptyArray<{
17
19
  id: ProjectId;
18
20
  folder: URI;
19
- config: ProjectConfig;
21
+ title: string;
20
22
  documents: NonEmptyArray<URI> | null;
21
23
  }>;
22
- diagrams(): Promise<DiagramView[]>;
24
+ /**
25
+ * Returns project by ID
26
+ */
27
+ project(projectId: ProjectId): {
28
+ id: ProjectId;
29
+ folder: URI;
30
+ title: string;
31
+ };
32
+ /**
33
+ * Returns diagrams (i.e. views with layout computed) for the specified project
34
+ * If no project is specified, returns diagrams for default project
35
+ */
36
+ diagrams(project?: ProjectId | undefined): Promise<DiagramView[]>;
23
37
  computedModel(project?: ProjectId | undefined): Promise<LikeC4Model.Computed>;
24
38
  layoutedModel(project?: ProjectId | undefined): Promise<LikeC4Model.Layouted>;
25
39
  getErrors(): Array<{
@@ -28,11 +42,21 @@ export interface LikeC4LanguageServices {
28
42
  range: Range;
29
43
  sourceFsPath: string;
30
44
  }>;
45
+ /**
46
+ * Notifies the language server about changes in the workspace
47
+ */
31
48
  notifyUpdate(update: {
32
49
  changed?: string;
33
50
  removed?: string;
34
51
  }): Promise<boolean>;
52
+ /**
53
+ * Returns the location of the specified element, relation, view or deployment element
54
+ */
35
55
  locate(params: Locate.Params): Locate.Res;
56
+ /**
57
+ * Checks if the specified document should be excluded from processing.
58
+ */
59
+ isExcluded(doc: LangiumDocument): boolean;
36
60
  }
37
61
  /**
38
62
  * Public Language Services
@@ -47,9 +71,14 @@ export declare class DefaultLikeC4LanguageServices implements LikeC4LanguageServ
47
71
  projects(): NonEmptyArray<{
48
72
  id: ProjectId;
49
73
  folder: URI;
50
- config: ProjectConfig;
74
+ title: string;
51
75
  documents: NonEmptyArray<URI> | null;
52
76
  }>;
77
+ project(projectId: ProjectId): {
78
+ id: ProjectId;
79
+ folder: URI;
80
+ title: string;
81
+ };
53
82
  /**
54
83
  * Diagram is a computed view, layouted using Graphviz
55
84
  * Used in React components
@@ -80,4 +109,8 @@ export declare class DefaultLikeC4LanguageServices implements LikeC4LanguageServ
80
109
  removed?: string;
81
110
  }): Promise<boolean>;
82
111
  locate(params: Locate.Params): Locate.Res;
112
+ /**
113
+ * Checks if the specified document should be excluded from processing.
114
+ */
115
+ isExcluded(doc: LangiumDocument): boolean;
83
116
  }
@@ -1,10 +1,13 @@
1
- import { nonexhaustive } from "@likec4/core";
1
+ import {
2
+ nonexhaustive
3
+ } from "@likec4/core";
2
4
  import { LikeC4Model } from "@likec4/core/model";
3
5
  import { loggable } from "@likec4/log";
4
6
  import { URI } from "langium";
5
7
  import { entries, hasAtLeast, indexBy, map, pipe, prop } from "remeda";
6
8
  import { DiagnosticSeverity } from "vscode-languageserver-types";
7
- import { logger as mainLogger } from "./logger.js";
9
+ import { isLikeC4LangiumDocument } from "./ast.js";
10
+ import { logger as mainLogger, logWarnError } from "./logger.js";
8
11
  import { ProjectsManager } from "./workspace/index.js";
9
12
  const logger = mainLogger.getChild("LikeC4LanguageServices");
10
13
  export class DefaultLikeC4LanguageServices {
@@ -27,11 +30,11 @@ export class DefaultLikeC4LanguageServices {
27
30
  entries(),
28
31
  map(([projectId, docs]) => {
29
32
  const id = projectId;
30
- const { folder: folder2, config: config2 } = projectsManager.getProject(id);
33
+ const { folderUri: folderUri2, config: config2 } = projectsManager.getProject(id);
31
34
  return {
32
35
  id,
33
- folder: folder2,
34
- config: config2,
36
+ folder: folderUri2,
37
+ title: config2.title ?? config2.name,
35
38
  documents: map(docs, prop("uri"))
36
39
  };
37
40
  })
@@ -39,14 +42,23 @@ export class DefaultLikeC4LanguageServices {
39
42
  if (hasAtLeast(projectsWithDocs, 1)) {
40
43
  return projectsWithDocs;
41
44
  }
42
- const { folder, config } = projectsManager.getProject(ProjectsManager.DefaultProjectId);
45
+ const { folderUri, config } = projectsManager.getProject(ProjectsManager.DefaultProjectId);
43
46
  return [{
44
47
  id: ProjectsManager.DefaultProjectId,
45
- folder,
46
- config,
48
+ folder: folderUri,
49
+ title: config.title ?? config.name,
47
50
  documents: null
48
51
  }];
49
52
  }
53
+ project(projectId) {
54
+ const projectsManager = this.services.shared.workspace.ProjectsManager;
55
+ const { folderUri, config } = projectsManager.getProject(projectId);
56
+ return {
57
+ id: projectId,
58
+ folder: folderUri,
59
+ title: config.title ?? config.name
60
+ };
61
+ }
50
62
  /**
51
63
  * Diagram is a computed view, layouted using Graphviz
52
64
  * Used in React components
@@ -98,13 +110,20 @@ export class DefaultLikeC4LanguageServices {
98
110
  if (!changed && !removed) {
99
111
  return false;
100
112
  }
113
+ const _changed = changed ? URI.file(changed) : void 0;
114
+ const _removed = removed ? URI.file(removed) : void 0;
115
+ const pm = this.services.shared.workspace.ProjectsManager;
116
+ if (_changed && pm.isConfigFile(_changed) || _removed && pm.isConfigFile(_removed)) {
117
+ await pm.reloadProjects();
118
+ return true;
119
+ }
101
120
  const mutex = this.services.shared.workspace.WorkspaceLock;
102
121
  try {
103
122
  let completed = false;
104
123
  await mutex.write(async (token) => {
105
124
  await this.services.shared.workspace.DocumentBuilder.update(
106
- changed ? [URI.file(changed)] : [],
107
- removed ? [URI.file(removed)] : [],
125
+ _changed ? [_changed] : [],
126
+ _removed ? [_removed] : [],
108
127
  token
109
128
  );
110
129
  completed = !token.isCancellationRequested;
@@ -132,4 +151,15 @@ export class DefaultLikeC4LanguageServices {
132
151
  nonexhaustive(params);
133
152
  }
134
153
  }
154
+ /**
155
+ * Checks if the specified document should be excluded from processing.
156
+ */
157
+ isExcluded(doc) {
158
+ try {
159
+ return !isLikeC4LangiumDocument(doc) || this.services.shared.workspace.ProjectsManager.checkIfExcluded(doc);
160
+ } catch (e) {
161
+ logWarnError(e);
162
+ return false;
163
+ }
164
+ }
135
165
  }
package/dist/Rpc.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  } from "@likec4/core";
6
6
  import { LikeC4Model } from "@likec4/core/model";
7
7
  import { Disposable, interruptAndCheck, URI, UriUtils } from "langium";
8
- import { DiagnosticSeverity } from "vscode-languageserver";
8
+ import { DiagnosticSeverity } from "vscode-languageserver-protocol";
9
9
  import {
10
10
  BuildDocuments,
11
11
  ChangeView,
@@ -20,6 +20,7 @@ import {
20
20
  GetDocumentTags,
21
21
  LayoutView,
22
22
  Locate,
23
+ ReloadProjects,
23
24
  ValidateLayout
24
25
  } from "./protocol.js";
25
26
  import { ADisposable } from "./utils/index.js";
@@ -46,14 +47,14 @@ export class Rpc extends ADisposable {
46
47
  const notifyModelParsed = funnel(
47
48
  () => {
48
49
  logger.debug`sendNotification ${"onDidChangeModel"}`;
49
- connection.sendNotification(DidChangeModelNotification.type, "").catch((e) => {
50
- logger.warn(`[ServerRpc] error sending onDidChangeModel: ${e}`);
51
- return Promise.resolve();
50
+ connection.sendNotification(DidChangeModelNotification.type, "").catch((error) => {
51
+ logger.warn(`[ServerRpc] error sending onDidChangeModel:`, { error });
52
+ return;
52
53
  });
53
54
  },
54
55
  {
55
56
  triggerAt: "end",
56
- minQuietPeriodMs: 100,
57
+ minQuietPeriodMs: 150,
57
58
  maxBurstDurationMs: 500,
58
59
  minGapMs: 300
59
60
  }
@@ -106,9 +107,24 @@ export class Rpc extends ADisposable {
106
107
  logger.debug`received request ${"FetchProjects"}`;
107
108
  const docsByProject = LangiumDocuments.groupedByProject();
108
109
  return {
109
- projects: mapValues(docsByProject, (docs) => map(docs, (d) => d.uri.toString()))
110
+ projects: mapValues(docsByProject, (docs, projectId) => {
111
+ const {
112
+ folderUri,
113
+ config
114
+ } = projects.getProject(projectId);
115
+ return {
116
+ folder: folderUri.toString(),
117
+ config,
118
+ docs: map(docs, (d) => d.uri.toString())
119
+ };
120
+ })
110
121
  };
111
122
  }),
123
+ connection.onRequest(ReloadProjects.req, async (cancelToken) => {
124
+ logger.debug`received request ${"ReloadProjects"}`;
125
+ await projects.reloadProjects(cancelToken);
126
+ return;
127
+ }),
112
128
  connection.onRequest(FetchViewsFromAllProjects.req, async (cancelToken) => {
113
129
  logger.debug`received request ${"FetchViewsFromAllProjects"}`;
114
130
  const promises = projects.all.map(async (projectId) => {