@likec4/language-server 1.25.0 → 1.26.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 (61) hide show
  1. package/bin/likec4-language-server.mjs +1 -1
  2. package/dist/LikeC4FileSystem.js +6 -1
  3. package/dist/LikeC4LanguageServices.d.ts +77 -0
  4. package/dist/LikeC4LanguageServices.js +118 -0
  5. package/dist/Rpc.js +106 -28
  6. package/dist/ast.d.ts +10 -0
  7. package/dist/bundled.mjs +2352 -2278
  8. package/dist/config/index.d.ts +1 -0
  9. package/dist/config/index.js +1 -0
  10. package/dist/config/schema.d.ts +8 -0
  11. package/dist/config/schema.js +19 -0
  12. package/dist/index.d.ts +1 -0
  13. package/dist/lsp/CodeLensProvider.js +3 -1
  14. package/dist/model/builder/buildModel.d.ts +8 -1
  15. package/dist/model/deployments-index.js +1 -1
  16. package/dist/model/fqn-index.d.ts +9 -6
  17. package/dist/model/fqn-index.js +24 -14
  18. package/dist/model/model-builder.d.ts +16 -6
  19. package/dist/model/model-builder.js +64 -50
  20. package/dist/model/model-locator.d.ts +11 -10
  21. package/dist/model/model-locator.js +32 -14
  22. package/dist/model/model-parser.d.ts +148 -148
  23. package/dist/model/model-parser.js +2 -2
  24. package/dist/model/parser/ModelParser.js +14 -2
  25. package/dist/model-change/ModelChanges.d.ts +1 -1
  26. package/dist/model-change/ModelChanges.js +2 -2
  27. package/dist/module.d.ts +9 -3
  28. package/dist/module.js +19 -5
  29. package/dist/protocol.d.ts +98 -16
  30. package/dist/protocol.js +21 -6
  31. package/dist/references/scope-provider.d.ts +24 -11
  32. package/dist/references/scope-provider.js +97 -68
  33. package/dist/shared/index.d.ts +0 -1
  34. package/dist/shared/index.js +0 -1
  35. package/dist/test/testServices.d.ts +15 -1
  36. package/dist/test/testServices.js +65 -17
  37. package/dist/utils/index.d.ts +3 -0
  38. package/dist/utils/index.js +3 -0
  39. package/dist/utils/projectId.d.ts +3 -0
  40. package/dist/utils/projectId.js +6 -0
  41. package/dist/validation/deployment-checks.js +5 -2
  42. package/dist/validation/element.js +2 -1
  43. package/dist/validation/specification.js +14 -7
  44. package/dist/validation/view.js +10 -8
  45. package/dist/views/index.d.ts +1 -1
  46. package/dist/views/index.js +1 -1
  47. package/dist/views/likec4-views.d.ts +17 -8
  48. package/dist/views/likec4-views.js +12 -11
  49. package/dist/workspace/AstNodeDescriptionProvider.d.ts +7 -0
  50. package/dist/workspace/AstNodeDescriptionProvider.js +18 -0
  51. package/dist/workspace/IndexManager.d.ts +10 -0
  52. package/dist/workspace/IndexManager.js +17 -0
  53. package/dist/workspace/LangiumDocuments.d.ts +14 -0
  54. package/dist/workspace/LangiumDocuments.js +31 -0
  55. package/dist/workspace/ProjectsManager.d.ts +48 -0
  56. package/dist/workspace/ProjectsManager.js +150 -0
  57. package/dist/{shared → workspace}/WorkspaceManager.d.ts +8 -2
  58. package/dist/{shared → workspace}/WorkspaceManager.js +22 -0
  59. package/dist/workspace/index.d.ts +5 -0
  60. package/dist/workspace/index.js +5 -0
  61. package/package.json +21 -12
package/dist/module.js CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  LikeC4GeneratedModule,
16
16
  LikeC4GeneratedSharedModule
17
17
  } from "./generated/module.js";
18
+ import { DefaultLikeC4LanguageServices } from "./LikeC4LanguageServices.js";
18
19
  import { logger } from "./logger.js";
19
20
  import {
20
21
  LikeC4CodeLensProvider,
@@ -26,9 +27,9 @@ import {
26
27
  LikeC4SemanticTokenProvider
27
28
  } from "./lsp/index.js";
28
29
  import {
30
+ DefaultLikeC4ModelBuilder,
29
31
  DeploymentsIndex,
30
32
  FqnIndex,
31
- LikeC4ModelBuilder,
32
33
  LikeC4ModelLocator,
33
34
  LikeC4ModelParser
34
35
  } from "./model/index.js";
@@ -40,18 +41,27 @@ import {
40
41
  } from "./references/index.js";
41
42
  import { Rpc } from "./Rpc.js";
42
43
  import {
43
- LikeC4WorkspaceManager,
44
44
  NodeKindProvider,
45
45
  WorkspaceSymbolProvider
46
46
  } from "./shared/index.js";
47
47
  import { registerValidationChecks } from "./validation/index.js";
48
- import { LikeC4Views } from "./views/index.js";
48
+ import { DefaultLikeC4Views } from "./views/index.js";
49
+ import {
50
+ AstNodeDescriptionProvider,
51
+ IndexManager,
52
+ LangiumDocuments,
53
+ LikeC4WorkspaceManager,
54
+ ProjectsManager
55
+ } from "./workspace/index.js";
49
56
  const LikeC4SharedModule = {
50
57
  lsp: {
51
58
  NodeKindProvider: (services) => new NodeKindProvider(services),
52
59
  WorkspaceSymbolProvider: (services) => new WorkspaceSymbolProvider(services)
53
60
  },
54
61
  workspace: {
62
+ IndexManager: (services) => new IndexManager(services),
63
+ LangiumDocuments: (services) => new LangiumDocuments(services),
64
+ ProjectsManager: (services) => new ProjectsManager(services),
55
65
  WorkspaceManager: (services) => new LikeC4WorkspaceManager(services)
56
66
  }
57
67
  };
@@ -65,16 +75,17 @@ export const LikeC4Module = {
65
75
  ValidatedWorkspaceCache: (services) => new WorkspaceCache(services.shared, DocumentState.Validated),
66
76
  Rpc: bind(Rpc),
67
77
  likec4: {
78
+ LanguageServices: bind(DefaultLikeC4LanguageServices),
68
79
  Layouter: (_services) => {
69
80
  logger.debug("Creating GraphvizLayouter with GraphvizWasmAdapter");
70
81
  return new GraphvizLayouter(new GraphvizWasmAdapter());
71
82
  },
72
- Views: bind(LikeC4Views),
83
+ Views: bind(DefaultLikeC4Views),
73
84
  DeploymentsIndex: bind(DeploymentsIndex),
74
85
  ModelChanges: bind(LikeC4ModelChanges),
75
86
  FqnIndex: bind(FqnIndex),
76
87
  ModelParser: bind(LikeC4ModelParser),
77
- ModelBuilder: bind(LikeC4ModelBuilder),
88
+ ModelBuilder: bind(DefaultLikeC4ModelBuilder),
78
89
  ModelLocator: bind(LikeC4ModelLocator)
79
90
  },
80
91
  lsp: {
@@ -88,6 +99,9 @@ export const LikeC4Module = {
88
99
  DocumentLinkProvider: bind(LikeC4DocumentLinkProvider),
89
100
  Formatter: bind(LikeC4Formatter)
90
101
  },
102
+ workspace: {
103
+ AstNodeDescriptionProvider: bind(AstNodeDescriptionProvider)
104
+ },
91
105
  references: {
92
106
  NameProvider: bind(LikeC4NameProvider),
93
107
  ScopeComputation: bind(LikeC4ScopeComputation),
@@ -1,41 +1,79 @@
1
- import type { ComputedLikeC4Model, ComputedView, DiagramView, Fqn, LayoutedLikeC4Model, RelationId, ViewChange, ViewId } from '@likec4/core';
1
+ import type { ComputedLikeC4ModelData, ComputedView, DiagramView, Fqn, LayoutedLikeC4ModelData, NonEmptyArray, ProjectId, RelationId, ViewChange, ViewId } from '@likec4/core';
2
2
  import { NotificationType, RequestType, RequestType0 } from 'vscode-jsonrpc';
3
3
  import type { DiagnosticSeverity, DocumentUri, Location, Position } from 'vscode-languageserver-types';
4
- export declare const onDidChangeModel: NotificationType<string>;
5
- export type OnDidChangeModelNotification = typeof onDidChangeModel;
4
+ export declare namespace DidChangeModelNotification {
5
+ const type: NotificationType<string>;
6
+ type Type = typeof type;
7
+ }
8
+ /**
9
+ * Request to fetch the computed model data
10
+ * If LSP has multiple projects, the projectId is required.
11
+ * otherwise throws an error.
12
+ */
6
13
  export declare namespace FetchComputedModel {
7
14
  type Params = {
15
+ projectId?: string | undefined;
8
16
  cleanCaches?: boolean | undefined;
9
17
  };
10
18
  type Res = {
11
- model: ComputedLikeC4Model | null;
19
+ model: ComputedLikeC4ModelData | null;
12
20
  };
13
- const Req: RequestType<Params, Res, void>;
14
- type Req = typeof Req;
21
+ const req: RequestType<Params, Res, void>;
22
+ type Req = typeof req;
23
+ }
24
+ /**
25
+ * Request to fetch all views of all projects
26
+ */
27
+ export declare namespace FetchViewsFromAllProjects {
28
+ type Res = {
29
+ views: Array<{
30
+ id: ViewId;
31
+ title: string;
32
+ projectId: ProjectId;
33
+ }>;
34
+ };
35
+ const req: RequestType0<Res, void>;
36
+ type Req = typeof req;
15
37
  }
38
+ /**
39
+ * Request to compute a view.
40
+ * If LSP has multiple projects, the projectId is required.
41
+ * otherwise throws an error.
42
+ */
16
43
  export declare namespace ComputeView {
17
44
  type Params = {
18
45
  viewId: ViewId;
46
+ projectId?: string;
19
47
  };
20
48
  type Result = {
21
49
  view: ComputedView | null;
22
50
  };
23
- const Req: RequestType<Params, Result, void>;
24
- type Req = typeof Req;
51
+ const req: RequestType<Params, Result, void>;
52
+ type Req = typeof req;
25
53
  }
54
+ /**
55
+ * Request to fetch the layouted model data
56
+ * If LSP has multiple projects, the projectId is required.
57
+ * otherwise throws an error.
58
+ */
26
59
  export declare namespace FetchLayoutedModel {
60
+ type Params = {
61
+ projectId?: string | undefined;
62
+ };
27
63
  type Res = {
28
- model: LayoutedLikeC4Model | null;
64
+ model: LayoutedLikeC4ModelData | null;
29
65
  };
30
- const Req: RequestType0<Res, void>;
31
- type Req = typeof Req;
66
+ const req: RequestType<Params, Res, void>;
67
+ type Req = typeof req;
32
68
  }
33
69
  /**
34
70
  * Request to layout a view.
71
+ * If LSP has multiple projects, the projectId is required.
35
72
  */
36
73
  export declare namespace LayoutView {
37
74
  type Params = {
38
75
  viewId: ViewId;
76
+ projectId?: string | undefined;
39
77
  };
40
78
  type Res = {
41
79
  result: {
@@ -43,14 +81,17 @@ export declare namespace LayoutView {
43
81
  diagram: DiagramView;
44
82
  } | null;
45
83
  };
46
- const Req: RequestType<Params, Res, void>;
47
- type Req = typeof Req;
84
+ const req: RequestType<Params, Res, void>;
85
+ type Req = typeof req;
48
86
  }
49
87
  /**
50
- * Request to layout all existing views.
88
+ * Request to validate all views
89
+ * If projects ID is provided, it will validate only the views of that project.
51
90
  */
52
91
  export declare namespace ValidateLayout {
53
- type Params = never;
92
+ type Params = {
93
+ projectId?: string;
94
+ };
54
95
  type Res = {
55
96
  result: {
56
97
  uri: string;
@@ -63,9 +104,22 @@ export declare namespace ValidateLayout {
63
104
  };
64
105
  }[] | null;
65
106
  };
66
- const Req: RequestType0<Res, void>;
107
+ const Req: RequestType<Params, Res, void>;
67
108
  type Req = typeof Req;
68
109
  }
110
+ /**
111
+ * Request to build documents.
112
+ */
113
+ export declare namespace FetchProjects {
114
+ type Params = never;
115
+ type Res = {
116
+ projects: {
117
+ [projectId: ProjectId]: NonEmptyArray<DocumentUri>;
118
+ };
119
+ };
120
+ const req: RequestType0<Res, void>;
121
+ type Req = typeof req;
122
+ }
69
123
  /**
70
124
  * Request to build documents.
71
125
  */
@@ -78,29 +132,57 @@ export declare namespace BuildDocuments {
78
132
  }
79
133
  /**
80
134
  * Request to locate an element, relation, deployment or view.
135
+ * If LSP has multiple projects, the projectId is required.
81
136
  */
82
137
  export declare namespace Locate {
83
138
  type Params = {
84
139
  element: Fqn;
140
+ projectId?: string | undefined;
85
141
  property?: string;
86
142
  } | {
143
+ projectId?: string | undefined;
87
144
  relation: RelationId;
88
145
  } | {
89
146
  deployment: Fqn;
147
+ projectId?: string | undefined;
90
148
  property?: string;
91
149
  } | {
92
150
  view: ViewId;
151
+ projectId?: string | undefined;
93
152
  };
94
153
  type Res = Location | null;
95
154
  const Req: RequestType<Params, Res, void>;
96
155
  type Req = typeof Req;
97
156
  }
157
+ /**
158
+ * Request to change the view
159
+ * If LSP has multiple projects, the projectId is required.
160
+ */
98
161
  export declare namespace ChangeView {
99
162
  type Params = {
100
163
  viewId: ViewId;
101
164
  change: ViewChange;
165
+ projectId?: string | undefined;
102
166
  };
103
167
  type Res = Location | null;
104
168
  const Req: RequestType<Params, Res, void>;
105
169
  type Req = typeof Req;
106
170
  }
171
+ /**
172
+ * Request to fetch telemetry metrics
173
+ */
174
+ export declare namespace FetchTelemetryMetrics {
175
+ type Res = {
176
+ metrics: null | {
177
+ elementKinds: number;
178
+ relationshipKinds: number;
179
+ tags: number;
180
+ elements: number;
181
+ relationships: number;
182
+ views: number;
183
+ projects: number;
184
+ };
185
+ };
186
+ const req: RequestType0<Res, void>;
187
+ type Req = typeof req;
188
+ }
package/dist/protocol.js CHANGED
@@ -1,25 +1,36 @@
1
1
  import { NotificationType, RequestType, RequestType0 } from "vscode-jsonrpc";
2
- export const onDidChangeModel = new NotificationType("likec4/onDidChangeModel");
2
+ export var DidChangeModelNotification;
3
+ ((DidChangeModelNotification2) => {
4
+ DidChangeModelNotification2.type = new NotificationType("likec4/onDidChangeModel");
5
+ })(DidChangeModelNotification || (DidChangeModelNotification = {}));
3
6
  export var FetchComputedModel;
4
7
  ((FetchComputedModel2) => {
5
- FetchComputedModel2.Req = new RequestType("likec4/fetchComputedModel");
8
+ FetchComputedModel2.req = new RequestType("likec4/fetchComputedModel");
6
9
  })(FetchComputedModel || (FetchComputedModel = {}));
10
+ export var FetchViewsFromAllProjects;
11
+ ((FetchViewsFromAllProjects2) => {
12
+ FetchViewsFromAllProjects2.req = new RequestType0("likec4/fetchViewsFromAllProjects");
13
+ })(FetchViewsFromAllProjects || (FetchViewsFromAllProjects = {}));
7
14
  export var ComputeView;
8
15
  ((ComputeView2) => {
9
- ComputeView2.Req = new RequestType("likec4/computeView");
16
+ ComputeView2.req = new RequestType("likec4/computeView");
10
17
  })(ComputeView || (ComputeView = {}));
11
18
  export var FetchLayoutedModel;
12
19
  ((FetchLayoutedModel2) => {
13
- FetchLayoutedModel2.Req = new RequestType0("likec4/fetchLayoutedModel");
20
+ FetchLayoutedModel2.req = new RequestType("likec4/fetchLayoutedModel");
14
21
  })(FetchLayoutedModel || (FetchLayoutedModel = {}));
15
22
  export var LayoutView;
16
23
  ((LayoutView2) => {
17
- LayoutView2.Req = new RequestType("likec4/layout-view");
24
+ LayoutView2.req = new RequestType("likec4/layout-view");
18
25
  })(LayoutView || (LayoutView = {}));
19
26
  export var ValidateLayout;
20
27
  ((ValidateLayout2) => {
21
- ValidateLayout2.Req = new RequestType0("likec4/validate-layout");
28
+ ValidateLayout2.Req = new RequestType("likec4/validate-layout");
22
29
  })(ValidateLayout || (ValidateLayout = {}));
30
+ export var FetchProjects;
31
+ ((FetchProjects2) => {
32
+ FetchProjects2.req = new RequestType0("likec4/fetch-projects");
33
+ })(FetchProjects || (FetchProjects = {}));
23
34
  export var BuildDocuments;
24
35
  ((BuildDocuments2) => {
25
36
  BuildDocuments2.Req = new RequestType("likec4/build");
@@ -32,3 +43,7 @@ export var ChangeView;
32
43
  ((ChangeView2) => {
33
44
  ChangeView2.Req = new RequestType("likec4/change-view");
34
45
  })(ChangeView || (ChangeView = {}));
46
+ export var FetchTelemetryMetrics;
47
+ ((FetchTelemetryMetrics2) => {
48
+ FetchTelemetryMetrics2.req = new RequestType0("likec4/metrics");
49
+ })(FetchTelemetryMetrics || (FetchTelemetryMetrics = {}));
@@ -1,18 +1,23 @@
1
- import { type ReferenceInfo, type Scope, DefaultScopeProvider } from 'langium';
1
+ import { type ProjectId } from '@likec4/core';
2
+ import { type AstNodeDescription, type ReferenceInfo, type Scope, type Stream, DefaultScopeProvider } from 'langium';
2
3
  import { ast } from '../ast';
4
+ import type { DeploymentsIndex, FqnIndex } from '../model';
3
5
  import type { LikeC4Services } from '../module';
6
+ import type { IndexManager } from '../workspace';
4
7
  export declare class LikeC4ScopeProvider extends DefaultScopeProvider {
5
- private deploymentsIndex;
6
- private fqnIndex;
8
+ protected deploymentsIndex: DeploymentsIndex;
9
+ protected fqnIndex: FqnIndex;
10
+ protected readonly indexManager: IndexManager;
7
11
  constructor(services: LikeC4Services);
8
- private uniqueDescedants;
9
12
  getScope(context: ReferenceInfo): Scope;
10
- private getScopeElementRef;
11
- private getScopeExtendElement;
12
- private getScopeElementView;
13
- private getScopeForStrictFqnRef;
14
- private getScopeExtendDeployment;
15
- protected getScopeForFqnRef(container: ast.FqnRef, context: ReferenceInfo): any;
13
+ protected genUniqueDescedants(of: () => ast.Element | ast.DeploymentNode | undefined): Generator<Stream<import("../ast").AstNodeDescriptionWithFqn>, void, any>;
14
+ protected streamScopeElementRef(ref: ast.ElementRef): Stream<AstNodeDescription>;
15
+ protected streamScopeExtendElement({ element }: ast.ExtendElement): Stream<AstNodeDescription>;
16
+ protected streamScopeElementView({ viewOf, extends: ext }: ast.ElementView): Stream<AstNodeDescription>;
17
+ protected getScopeForStrictFqnRef(projectId: ProjectId, container: ast.StrictFqnRef, context: ReferenceInfo): any;
18
+ protected streamScopeExtendDeployment({ deploymentNode }: ast.ExtendDeployment): Stream<AstNodeDescription>;
19
+ protected streamForFqnRef(projectId: ProjectId, container: ast.FqnRef, context: ReferenceInfo): Stream<AstNodeDescription>;
20
+ protected genScopeForFqnRef(projectId: ProjectId, container: ast.FqnRef, context: ReferenceInfo): Generator<any, void, any>;
16
21
  /**
17
22
  * Computes the scope for a given reference context.
18
23
  *
@@ -24,5 +29,13 @@ export declare class LikeC4ScopeProvider extends DefaultScopeProvider {
24
29
  * It then iterates through the container hierarchy, collecting relevant scopes based on the reference type and container type.
25
30
  * Finally, it combines the collected scopes with the global scope to produce the final scope.
26
31
  */
27
- protected computeScope(context: ReferenceInfo, referenceType?: any): any;
32
+ protected computeScope(projectId: ProjectId, context: ReferenceInfo, referenceType?: any): Generator<any, void, any>;
33
+ /**
34
+ * Create a global scope filtered for the given reference type.
35
+ */
36
+ protected getProjectScope(projectId: ProjectId, referenceType: string, context: ReferenceInfo): Scope;
37
+ /**
38
+ * Create a global scope filtered for the given reference type.
39
+ */
40
+ protected getGlobalScope(referenceType: string, context: ReferenceInfo): Scope;
28
41
  }
@@ -12,64 +12,45 @@ import {
12
12
  } from "langium";
13
13
  import { ast } from "../ast.js";
14
14
  import { logWarnError } from "../logger.js";
15
+ import { projectIdFrom } from "../utils/index.js";
15
16
  import { elementRef, readStrictFqn } from "../utils/elementRef.js";
16
17
  const { getDocument } = AstUtils;
17
18
  export class LikeC4ScopeProvider extends DefaultScopeProvider {
18
19
  deploymentsIndex;
19
20
  fqnIndex;
21
+ indexManager;
20
22
  constructor(services) {
21
23
  super(services);
24
+ this.indexManager = services.shared.workspace.IndexManager;
22
25
  this.fqnIndex = services.likec4.FqnIndex;
23
26
  this.deploymentsIndex = services.likec4.DeploymentsIndex;
24
27
  }
25
- // we need lazy resolving here
26
- uniqueDescedants(of) {
27
- return new StreamImpl(
28
- () => {
29
- const element = of();
30
- if (element && ast.isElement(element)) {
31
- const fqn = this.fqnIndex.getFqn(element);
32
- return this.fqnIndex.uniqueDescedants(fqn).iterator();
33
- }
34
- if (element && ast.isDeploymentNode(element)) {
35
- const fqn = this.deploymentsIndex.getFqn(element);
36
- return this.deploymentsIndex.uniqueDescedants(fqn).iterator();
37
- }
38
- return null;
39
- },
40
- (iterator) => {
41
- if (iterator) {
42
- return iterator.next();
43
- }
44
- return DONE_RESULT;
45
- }
46
- );
47
- }
48
28
  getScope(context) {
49
29
  try {
30
+ const projectId = projectIdFrom(context.container);
50
31
  const referenceType = this.reflection.getReferenceType(context);
51
32
  try {
52
33
  const container = context.container;
53
34
  if (ast.isFqnRef(container)) {
54
- return this.getScopeForFqnRef(container, context);
35
+ return new StreamScope(this.streamForFqnRef(projectId, container, context));
55
36
  }
56
37
  if (ast.isStrictFqnRef(container)) {
57
- return this.getScopeForStrictFqnRef(container, context);
38
+ return this.getScopeForStrictFqnRef(projectId, container, context);
58
39
  }
59
40
  if (referenceType !== ast.Element) {
60
- return this.getGlobalScope(referenceType, context);
41
+ return this.getProjectScope(projectId, referenceType, context);
61
42
  }
62
43
  if (ast.isStrictFqnElementRef(container) && context.property === "el") {
63
44
  const parent = container.parent;
64
45
  if (!parent) {
65
- return this.getGlobalScope(referenceType, context);
46
+ return this.getProjectScope(projectId, referenceType, context);
66
47
  }
67
- return new StreamScope(this.fqnIndex.directChildrenOf(readStrictFqn(parent)));
48
+ return new StreamScope(this.fqnIndex.directChildrenOf(projectId, readStrictFqn(parent)));
68
49
  }
69
50
  if (ast.isElementRef(container) && context.property === "el") {
70
51
  const parent = container.parent;
71
52
  if (parent) {
72
- return new StreamScope(this.getScopeElementRef(parent));
53
+ return new StreamScope(this.streamScopeElementRef(parent));
73
54
  }
74
55
  if (context.reference.$refText === "this" || context.reference.$refText === "it") {
75
56
  const closestElement = AstUtils.getContainerOfType(container, ast.isElement);
@@ -82,78 +63,93 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
82
63
  }
83
64
  }
84
65
  }
85
- return this.computeScope(context);
66
+ return new StreamScope(stream(this.computeScope(projectId, context)));
86
67
  } catch (e) {
87
68
  logWarnError(e);
88
- return this.getGlobalScope(referenceType, context);
69
+ return this.getProjectScope(projectId, referenceType, context);
89
70
  }
90
71
  } catch (e) {
91
72
  logWarnError(e);
92
73
  return EMPTY_SCOPE;
93
74
  }
94
75
  }
95
- getScopeElementRef(ref) {
96
- return this.uniqueDescedants(() => ref.el.ref);
76
+ // we need lazy resolving here
77
+ *genUniqueDescedants(of) {
78
+ const element = of();
79
+ if (!element) {
80
+ return;
81
+ }
82
+ const projectId = projectIdFrom(element);
83
+ if (ast.isElement(element)) {
84
+ const fqn = this.fqnIndex.getFqn(element);
85
+ yield* this.fqnIndex.uniqueDescedants(projectId, fqn);
86
+ return;
87
+ }
88
+ if (ast.isDeploymentNode(element)) {
89
+ const fqn = this.deploymentsIndex.getFqn(element);
90
+ yield* this.deploymentsIndex.uniqueDescedants(projectId, fqn);
91
+ }
97
92
  }
98
- getScopeExtendElement({ element }) {
99
- return stream([element.el.$nodeDescription]).nonNullable().concat(this.uniqueDescedants(() => elementRef(element)));
93
+ streamScopeElementRef(ref) {
94
+ return stream(this.genUniqueDescedants(() => ref.el.ref));
100
95
  }
101
- getScopeElementView({ viewOf, extends: ext }) {
96
+ streamScopeExtendElement({ element }) {
97
+ return stream([element.el.$nodeDescription]).nonNullable().concat(this.genUniqueDescedants(() => elementRef(element)));
98
+ }
99
+ streamScopeElementView({ viewOf, extends: ext }) {
102
100
  if (viewOf) {
103
- return stream([viewOf.el.$nodeDescription]).nonNullable().concat(this.uniqueDescedants(() => elementRef(viewOf)));
101
+ return stream([viewOf.el.$nodeDescription]).nonNullable().concat(this.genUniqueDescedants(() => elementRef(viewOf)));
104
102
  }
105
103
  if (ext) {
106
104
  return stream([ext]).flatMap((v) => {
107
105
  const view = v.view.ref;
108
- return view ? this.getScopeElementView(view) : EMPTY_STREAM;
106
+ return view ? this.streamScopeElementView(view) : EMPTY_STREAM;
109
107
  });
110
108
  }
111
109
  return EMPTY_STREAM;
112
110
  }
113
- getScopeForStrictFqnRef(container, context) {
111
+ getScopeForStrictFqnRef(projectId, container, context) {
114
112
  const parent = container.parent;
115
113
  if (!parent) {
116
- return this.getGlobalScope(ast.DeploymentNode, context);
114
+ return this.getProjectScope(projectId, ast.DeploymentNode, context);
117
115
  }
118
116
  return new StreamScope(
119
- this.deploymentsIndex.directChildrenOf(readStrictFqn(parent)).filter((desc) => this.reflection.isSubtype(desc.type, ast.DeploymentNode))
117
+ this.deploymentsIndex.directChildrenOf(projectId, readStrictFqn(parent)).filter((desc) => this.reflection.isSubtype(desc.type, ast.DeploymentNode))
120
118
  );
121
119
  }
122
- getScopeExtendDeployment({ deploymentNode }) {
123
- return stream([deploymentNode.value.$nodeDescription]).nonNullable().concat(this.uniqueDescedants(() => {
120
+ streamScopeExtendDeployment({ deploymentNode }) {
121
+ return stream([deploymentNode.value.$nodeDescription]).nonNullable().concat(this.genUniqueDescedants(() => {
124
122
  const target = deploymentNode.value.ref;
125
123
  return target && ast.isDeploymentNode(target) ? target : void 0;
126
124
  }));
127
125
  }
128
- getScopeForFqnRef(container, context) {
126
+ streamForFqnRef(projectId, container, context) {
129
127
  const parent = container.parent;
130
128
  if (!parent) {
131
- return this.createScope(
132
- // First preference for deployment nodes
133
- this.computeScope(context, ast.DeploymentNode).getAllElements(),
134
- this.createScope(
135
- // Second preference for deployed instances
136
- this.computeScope(context, ast.DeployedInstance).getAllElements(),
137
- // Third preference for elements if we are in deployment view
138
- AstUtils.hasContainerOfType(container, ast.isDeploymentView) ? this.computeScope(context, ast.Element) : EMPTY_SCOPE
139
- )
140
- );
129
+ return stream(this.genScopeForFqnRef(projectId, container, context));
141
130
  }
142
131
  const parentRef = parent.value.ref;
143
132
  if (!parentRef) {
144
- return EMPTY_SCOPE;
133
+ return EMPTY_STREAM;
145
134
  }
146
135
  if (ast.isDeploymentNode(parentRef)) {
147
- return new StreamScope(this.uniqueDescedants(() => parentRef));
136
+ return stream(this.genUniqueDescedants(() => parentRef));
148
137
  }
149
138
  if (ast.isDeployedInstance(parentRef)) {
150
- return new StreamScope(this.getScopeElementRef(parentRef.element));
139
+ return stream(this.streamScopeElementRef(parentRef.element));
151
140
  }
152
141
  if (ast.isElement(parentRef)) {
153
- return new StreamScope(this.uniqueDescedants(() => parentRef));
142
+ return stream(this.genUniqueDescedants(() => parentRef));
154
143
  }
155
144
  return nonexhaustive(parentRef);
156
145
  }
146
+ *genScopeForFqnRef(projectId, container, context) {
147
+ yield* this.computeScope(projectId, context, ast.DeploymentNode);
148
+ yield* this.computeScope(projectId, context, ast.DeployedInstance);
149
+ if (AstUtils.hasContainerOfType(container, ast.isDeploymentView)) {
150
+ yield* this.computeScope(projectId, context, ast.Element);
151
+ }
152
+ }
157
153
  /**
158
154
  * Computes the scope for a given reference context.
159
155
  *
@@ -165,35 +161,68 @@ export class LikeC4ScopeProvider extends DefaultScopeProvider {
165
161
  * It then iterates through the container hierarchy, collecting relevant scopes based on the reference type and container type.
166
162
  * Finally, it combines the collected scopes with the global scope to produce the final scope.
167
163
  */
168
- computeScope(context, referenceType = this.reflection.getReferenceType(context)) {
164
+ *computeScope(projectId, context, referenceType = this.reflection.getReferenceType(context)) {
169
165
  const isElementReference = this.reflection.isSubtype(referenceType, ast.Element);
170
166
  const isDeploymentReference = this.reflection.isSubtype(referenceType, ast.DeploymentElement);
171
- const scopes = [];
172
167
  const doc = getDocument(context.container);
173
168
  const precomputed = doc.precomputedScopes;
174
169
  if (!precomputed) {
175
- return this.getGlobalScope(referenceType, context);
170
+ yield* this.getProjectScope(projectId, referenceType, context).getAllElements();
171
+ return;
176
172
  }
177
173
  const byReferenceType = (desc) => this.reflection.isSubtype(desc.type, referenceType);
178
174
  let container = context.container;
179
175
  while (container) {
180
176
  const elements = precomputed.get(container).filter(byReferenceType);
181
177
  if (elements.length > 0) {
182
- scopes.push(stream(elements));
178
+ yield* elements;
183
179
  }
184
180
  if (isDeploymentReference && ast.isExtendDeploymentBody(container)) {
185
- scopes.push(this.getScopeExtendDeployment(container.$container));
181
+ yield* this.streamScopeExtendDeployment(container.$container);
186
182
  }
187
183
  if (isElementReference && ast.isExtendElementBody(container)) {
188
- scopes.push(this.getScopeExtendElement(container.$container));
184
+ yield* this.streamScopeExtendElement(container.$container);
189
185
  }
190
186
  if (isElementReference && ast.isElementViewBody(container)) {
191
- scopes.push(this.getScopeElementView(container.$container));
187
+ yield* this.streamScopeElementView(container.$container);
192
188
  }
193
189
  container = container.$container;
194
190
  }
195
- return scopes.reduceRight((outerScope, elements) => {
196
- return this.createScope(elements, outerScope);
197
- }, this.getGlobalScope(referenceType, context));
191
+ yield* this.getProjectScope(projectId, referenceType, context).getAllElements();
198
192
  }
193
+ /**
194
+ * Create a global scope filtered for the given reference type.
195
+ */
196
+ getProjectScope(projectId, referenceType, context) {
197
+ if (referenceType === ast.LibIcon) {
198
+ return super.getGlobalScope(referenceType, context);
199
+ }
200
+ return this.globalScopeCache.get(
201
+ `${projectId}::${referenceType}`,
202
+ () => new MapScope(this.indexManager.projectElements(projectId, referenceType))
203
+ );
204
+ }
205
+ /**
206
+ * Create a global scope filtered for the given reference type.
207
+ */
208
+ getGlobalScope(referenceType, context) {
209
+ if (referenceType === ast.LibIcon) {
210
+ return super.getGlobalScope(referenceType, context);
211
+ }
212
+ const projectId = projectIdFrom(context.container);
213
+ return this.getProjectScope(projectId, referenceType, context);
214
+ }
215
+ }
216
+ function lazyStream(fn) {
217
+ return new StreamImpl(
218
+ () => {
219
+ return fn().iterator();
220
+ },
221
+ (iterator) => {
222
+ if (iterator) {
223
+ return iterator.next();
224
+ }
225
+ return DONE_RESULT;
226
+ }
227
+ );
199
228
  }
@@ -1,3 +1,2 @@
1
1
  export * from './NodeKindProvider';
2
- export * from './WorkspaceManager';
3
2
  export * from './WorkspaceSymbolProvider';
@@ -1,3 +1,2 @@
1
1
  export * from "./NodeKindProvider.js";
2
- export * from "./WorkspaceManager.js";
3
2
  export * from "./WorkspaceSymbolProvider.js";