@likec4/language-server 1.19.0 → 1.19.2

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 (77) hide show
  1. package/dist/Rpc.js +6 -0
  2. package/dist/browser.d.ts +1 -0
  3. package/dist/documentation/documentation-provider.d.ts +8 -0
  4. package/dist/documentation/documentation-provider.js +46 -0
  5. package/dist/documentation/index.d.ts +1 -0
  6. package/dist/documentation/index.js +1 -0
  7. package/dist/generated/ast.d.ts +22 -9
  8. package/dist/generated/ast.js +23 -2
  9. package/dist/generated/grammar.js +1 -1
  10. package/dist/index.d.ts +1 -0
  11. package/dist/index.js +3 -2
  12. package/dist/like-c4.langium +4 -1
  13. package/dist/lsp/DocumentSymbolProvider.d.ts +11 -2
  14. package/dist/lsp/DocumentSymbolProvider.js +78 -6
  15. package/dist/model/fqn-computation.js +2 -2
  16. package/dist/model/model-builder.js +3 -3
  17. package/dist/model/model-parser.d.ts +5 -0
  18. package/dist/model/parser/DeploymentModelParser.d.ts +1 -0
  19. package/dist/model/parser/DeploymentViewParser.d.ts +2 -1
  20. package/dist/model/parser/DeploymentViewParser.js +3 -0
  21. package/dist/model/parser/FqnRefParser.d.ts +1 -0
  22. package/dist/model/parser/FqnRefParser.js +13 -0
  23. package/dist/model/parser/GlobalsParser.d.ts +1 -0
  24. package/dist/model/parser/ViewsParser.d.ts +1 -0
  25. package/dist/module.d.ts +9 -1
  26. package/dist/module.js +47 -8
  27. package/dist/protocol.d.ts +19 -1
  28. package/dist/protocol.js +1 -0
  29. package/dist/references/scope-computation.d.ts +2 -2
  30. package/dist/references/scope-computation.js +9 -9
  31. package/dist/validation/dynamic-view-rule.js +3 -2
  32. package/dist/validation/dynamic-view-step.js +23 -27
  33. package/dist/validation/index.d.ts +1 -1
  34. package/dist/validation/property-checks.js +3 -2
  35. package/dist/validation/specification.js +14 -14
  36. package/dist/validation/view-predicates/element-with.js +3 -2
  37. package/dist/validation/view-predicates/expanded-element.js +3 -2
  38. package/dist/validation/view-predicates/incoming.js +3 -2
  39. package/dist/validation/view-predicates/outgoing.js +3 -2
  40. package/dist/validation/view-predicates/relation-with.js +3 -2
  41. package/dist/validation/view.js +3 -3
  42. package/dist/views/configurable-layouter.d.ts +7 -0
  43. package/dist/views/configurable-layouter.js +55 -0
  44. package/dist/views/index.d.ts +1 -0
  45. package/dist/views/index.js +1 -0
  46. package/dist/views/likec4-views.d.ts +26 -0
  47. package/dist/views/likec4-views.js +113 -0
  48. package/package.json +14 -11
  49. package/src/Rpc.ts +13 -7
  50. package/src/browser.ts +1 -0
  51. package/src/documentation/documentation-provider.ts +52 -0
  52. package/src/documentation/index.ts +1 -0
  53. package/src/generated/ast.ts +47 -11
  54. package/src/generated/grammar.ts +1 -1
  55. package/src/index.ts +4 -2
  56. package/src/like-c4.langium +4 -1
  57. package/src/lsp/DocumentSymbolProvider.ts +110 -28
  58. package/src/model/fqn-computation.ts +8 -8
  59. package/src/model/model-builder.ts +52 -52
  60. package/src/model/parser/DeploymentViewParser.ts +10 -7
  61. package/src/model/parser/FqnRefParser.ts +14 -0
  62. package/src/module.ts +56 -9
  63. package/src/protocol.ts +29 -4
  64. package/src/references/scope-computation.ts +35 -35
  65. package/src/validation/dynamic-view-rule.ts +5 -4
  66. package/src/validation/dynamic-view-step.ts +23 -26
  67. package/src/validation/property-checks.ts +11 -10
  68. package/src/validation/specification.ts +38 -38
  69. package/src/validation/view-predicates/element-with.ts +6 -5
  70. package/src/validation/view-predicates/expanded-element.ts +6 -5
  71. package/src/validation/view-predicates/incoming.ts +6 -5
  72. package/src/validation/view-predicates/outgoing.ts +6 -5
  73. package/src/validation/view-predicates/relation-with.ts +6 -5
  74. package/src/validation/view.ts +5 -5
  75. package/src/views/configurable-layouter.ts +65 -0
  76. package/src/views/index.ts +1 -0
  77. package/src/views/likec4-views.ts +139 -0
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export { logger as lspLogger, setLogLevel } from './logger';
4
4
  export type { DocumentParser, LikeC4ModelBuilder, LikeC4ModelLocator, LikeC4ModelParser } from './model';
5
5
  export { createCustomLanguageServices, createLanguageServices, LikeC4Module } from './module';
6
6
  export type { LikeC4Services, LikeC4SharedServices } from './module';
7
+ export type { LikeC4Views } from './views';
7
8
  export { LikeC4FileSystem };
8
9
  export declare function startLanguageServer(): {
9
10
  shared: LikeC4SharedServices;
package/dist/index.js CHANGED
@@ -1,13 +1,14 @@
1
1
  import { startLanguageServer as startLanguim } from "langium/lsp";
2
2
  import { createConnection, ProposedFeatures } from "vscode-languageserver/node";
3
3
  import { LikeC4FileSystem } from "./LikeC4FileSystem.js";
4
- import { createLanguageServices } from "./module.js";
4
+ import { createCustomLanguageServices } from "./module.js";
5
+ import { ConfigurableLayouter } from "./views/configurable-layouter.js";
5
6
  export { logger as lspLogger, setLogLevel } from "./logger.js";
6
7
  export { createCustomLanguageServices, createLanguageServices, LikeC4Module } from "./module.js";
7
8
  export { LikeC4FileSystem };
8
9
  export function startLanguageServer() {
9
10
  const connection = createConnection(ProposedFeatures.all);
10
- const services = createLanguageServices({ connection, ...LikeC4FileSystem });
11
+ const services = createCustomLanguageServices({ connection, ...LikeC4FileSystem }, ConfigurableLayouter);
11
12
  startLanguim(services.shared);
12
13
  return services;
13
14
  }
@@ -620,10 +620,13 @@ DeploymentViewRulePredicateExpression:
620
620
  ;
621
621
 
622
622
  ExpressionV2:
623
- RelationExpr |
623
+ RelationPredicateOrWhereV2 |
624
624
  FqnExpr
625
625
  ;
626
626
 
627
+ RelationPredicateOrWhereV2:
628
+ RelationExpr ({infer RelationPredicateWhereV2.subject=current} 'where' where=WhereRelationExpression?)?
629
+ ;
627
630
 
628
631
  FqnExpr:
629
632
  {infer WildcardExpression} isWildcard?='*' |
@@ -1,16 +1,22 @@
1
1
  import { type AstNode, type MaybePromise } from 'langium';
2
2
  import type { DocumentSymbolProvider, NodeKindProvider } from 'langium/lsp';
3
3
  import { type DocumentSymbol, SymbolKind } from 'vscode-languageserver-types';
4
- import { ast, type LikeC4LangiumDocument } from '../ast';
4
+ import { type LikeC4LangiumDocument, ast } from '../ast';
5
+ import type { LikeC4ModelLocator, LikeC4ModelParser } from '../model';
5
6
  import type { LikeC4Services } from '../module';
7
+ import type { LikeC4NameProvider } from '../references';
6
8
  export declare class LikeC4DocumentSymbolProvider implements DocumentSymbolProvider {
7
9
  private services;
8
10
  protected readonly nodeKindProvider: NodeKindProvider;
11
+ protected readonly nameProvider: LikeC4NameProvider;
12
+ protected readonly parser: LikeC4ModelParser;
13
+ protected readonly locator: LikeC4ModelLocator;
9
14
  constructor(services: LikeC4Services);
10
- getSymbols({ parseResult: { value: { specifications, models, views, likec4lib } } }: LikeC4LangiumDocument): MaybePromise<DocumentSymbol[]>;
15
+ getSymbols({ parseResult: { value: { specifications, models, deployments, views, likec4lib }, }, }: LikeC4LangiumDocument): MaybePromise<DocumentSymbol[]>;
11
16
  protected getLikec4LibSymbol(astLib: ast.LikeC4Lib): DocumentSymbol[];
12
17
  protected getSpecSymbol(astSpec: ast.SpecificationRule): DocumentSymbol[];
13
18
  protected getModelSymbol(astModel: ast.Model): DocumentSymbol[];
19
+ protected getDeploymentModelSymbol(astModel: ast.ModelDeployments): DocumentSymbol[];
14
20
  protected getElementsSymbol(el: ast.Element | ast.Relation | ast.ExtendElement): DocumentSymbol[];
15
21
  protected getExtendElementSymbol(astElement: ast.ExtendElement): DocumentSymbol[];
16
22
  protected getElementSymbol(astElement: ast.Element): DocumentSymbol[];
@@ -19,5 +25,8 @@ export declare class LikeC4DocumentSymbolProvider implements DocumentSymbolProvi
19
25
  protected getTagSymbol(astTag: ast.SpecificationTag): DocumentSymbol | null;
20
26
  protected getLibIconSymbol(astTag: ast.LibIcon): DocumentSymbol | null;
21
27
  protected getViewSymbol(astView: ast.LikeC4View): DocumentSymbol[];
28
+ protected getDeploymentElementSymbol(el: ast.DeploymentElement | ast.DeploymentRelation): DocumentSymbol[];
29
+ protected getDeploymentNodeSymbol(astElement: ast.DeploymentNode): DocumentSymbol[];
30
+ protected getDeployedInstanceSymbol(astElement: ast.DeployedInstance): DocumentSymbol[];
22
31
  protected symbolKind(node: AstNode): SymbolKind;
23
32
  }
@@ -1,31 +1,38 @@
1
1
  import { nonexhaustive } from "@likec4/core";
2
- import { GrammarUtils } from "langium";
2
+ import { AstUtils, GrammarUtils } from "langium";
3
3
  import { filter, isEmpty, isTruthy, map, pipe } from "remeda";
4
4
  import { SymbolKind } from "vscode-languageserver-types";
5
5
  import { ast } from "../ast.js";
6
- import { logError } from "../logger.js";
6
+ import { logWarnError } from "../logger.js";
7
7
  import { getFqnElementRef } from "../utils/elementRef.js";
8
8
  export class LikeC4DocumentSymbolProvider {
9
9
  constructor(services) {
10
10
  this.services = services;
11
11
  this.nodeKindProvider = services.shared.lsp.NodeKindProvider;
12
+ this.parser = services.likec4.ModelParser;
13
+ this.locator = services.likec4.ModelLocator;
14
+ this.nameProvider = services.references.NameProvider;
12
15
  }
13
16
  nodeKindProvider;
17
+ nameProvider;
18
+ parser;
19
+ locator;
14
20
  getSymbols({
15
21
  parseResult: {
16
- value: { specifications, models, views, likec4lib }
22
+ value: { specifications, models, deployments, views, likec4lib }
17
23
  }
18
24
  }) {
19
25
  return [
20
26
  ...likec4lib.map((l) => () => this.getLikec4LibSymbol(l)),
21
27
  ...specifications.map((s) => () => this.getSpecSymbol(s)),
22
28
  ...models.map((s) => () => this.getModelSymbol(s)),
29
+ ...deployments.map((s) => () => this.getDeploymentModelSymbol(s)),
23
30
  ...views.map((s) => () => this.getModelViewsSymbol(s))
24
31
  ].flatMap((fn) => {
25
32
  try {
26
33
  return fn() ?? [];
27
34
  } catch (e) {
28
- logError(e);
35
+ logWarnError(e);
29
36
  return [];
30
37
  }
31
38
  });
@@ -61,7 +68,7 @@ export class LikeC4DocumentSymbolProvider {
61
68
  return this.getTagSymbol(nd);
62
69
  }
63
70
  } catch (e) {
64
- logError(e);
71
+ logWarnError(e);
65
72
  return null;
66
73
  }
67
74
  nonexhaustive(nd);
@@ -94,6 +101,21 @@ export class LikeC4DocumentSymbolProvider {
94
101
  }
95
102
  ];
96
103
  }
104
+ getDeploymentModelSymbol(astModel) {
105
+ const cstModel = astModel.$cstNode;
106
+ if (!cstModel) return [];
107
+ const nameNode = GrammarUtils.findNodeForProperty(cstModel, "name");
108
+ if (!nameNode) return [];
109
+ return [
110
+ {
111
+ kind: this.symbolKind(astModel),
112
+ name: astModel.name,
113
+ range: cstModel.range,
114
+ selectionRange: nameNode.range,
115
+ children: astModel.elements.flatMap((e) => this.getDeploymentElementSymbol(e))
116
+ }
117
+ ];
118
+ }
97
119
  getElementsSymbol(el) {
98
120
  try {
99
121
  if (ast.isExtendElement(el)) {
@@ -103,7 +125,7 @@ export class LikeC4DocumentSymbolProvider {
103
125
  return this.getElementSymbol(el);
104
126
  }
105
127
  } catch (e) {
106
- logError(e);
128
+ logWarnError(e);
107
129
  }
108
130
  return [];
109
131
  }
@@ -196,6 +218,56 @@ export class LikeC4DocumentSymbolProvider {
196
218
  }
197
219
  ];
198
220
  }
221
+ getDeploymentElementSymbol(el) {
222
+ try {
223
+ if (ast.isDeploymentNode(el)) {
224
+ return this.getDeploymentNodeSymbol(el);
225
+ }
226
+ if (ast.isDeployedInstance(el)) {
227
+ return this.getDeployedInstanceSymbol(el);
228
+ }
229
+ } catch (e) {
230
+ logWarnError(e);
231
+ }
232
+ return [];
233
+ }
234
+ getDeploymentNodeSymbol(astElement) {
235
+ const cst = astElement.$cstNode;
236
+ const nameNode = this.nameProvider.getNameNode(astElement);
237
+ if (!nameNode || !cst) return [];
238
+ const name = this.nameProvider.getNameStrict(astElement);
239
+ const kind = astElement.kind.$refText;
240
+ const detail = kind;
241
+ return [
242
+ {
243
+ kind: this.symbolKind(astElement),
244
+ name,
245
+ range: cst.range,
246
+ selectionRange: nameNode.range,
247
+ detail,
248
+ children: astElement.body?.elements.flatMap((e) => this.getDeploymentElementSymbol(e)) ?? []
249
+ }
250
+ ];
251
+ }
252
+ getDeployedInstanceSymbol(astElement) {
253
+ const cst = astElement.$cstNode;
254
+ const nameNode = this.nameProvider.getNameNode(astElement);
255
+ if (!nameNode || !cst) return [];
256
+ const doc = AstUtils.getDocument(astElement);
257
+ const instance = this.parser.forDocument(doc).parseDeployedInstance(astElement);
258
+ const name = this.nameProvider.getNameStrict(astElement);
259
+ const detail = "instance of " + instance.element;
260
+ return [
261
+ {
262
+ kind: this.symbolKind(astElement),
263
+ name,
264
+ range: cst.range,
265
+ selectionRange: nameNode.range,
266
+ detail,
267
+ children: []
268
+ }
269
+ ];
270
+ }
199
271
  symbolKind(node) {
200
272
  return this.nodeKindProvider.getSymbolKind(node);
201
273
  }
@@ -1,4 +1,4 @@
1
- import { AsFqn, nonexhaustive } from "@likec4/core";
1
+ import { AsFqn, LinkedList, nonexhaustive } from "@likec4/core";
2
2
  import { AstUtils, CstUtils, GrammarUtils, MultiMap } from "langium";
3
3
  import { isDefined, isEmpty } from "remeda";
4
4
  import { ast, ElementOps } from "../ast.js";
@@ -29,7 +29,7 @@ export function computeDocumentFqn(document, services) {
29
29
  return;
30
30
  }
31
31
  const locator = services.workspace.AstNodeLocator;
32
- const traverseStack = elements.map((el) => [el, null]);
32
+ const traverseStack = LinkedList.from(elements.map((el) => [el, null]));
33
33
  let pair;
34
34
  while (pair = traverseStack.shift()) {
35
35
  try {
@@ -33,7 +33,7 @@ import {
33
33
  values
34
34
  } from "remeda";
35
35
  import { isParsedLikeC4LangiumDocument } from "../ast.js";
36
- import { logError, logger, logWarnError } from "../logger.js";
36
+ import { logger, logWarnError } from "../logger.js";
37
37
  import { assignNavigateTo, resolveRelativePaths } from "../view-utils/index.js";
38
38
  function buildModel(services, docs) {
39
39
  const c4Specification = {
@@ -542,7 +542,7 @@ export class LikeC4ModelBuilder {
542
542
  }
543
543
  const result = LikeC4Model.makeCompute(model)(view);
544
544
  if (!result.isSuccess) {
545
- logError(result.error);
545
+ logWarnError(result.error);
546
546
  return null;
547
547
  }
548
548
  let computedView = result.view;
@@ -588,7 +588,7 @@ export class LikeC4ModelBuilder {
588
588
  try {
589
589
  listener(docs);
590
590
  } catch (e) {
591
- logError(e);
591
+ logWarnError(e);
592
592
  }
593
593
  }
594
594
  }
@@ -60,6 +60,7 @@ declare const DocumentParserFromMixins: {
60
60
  parseFqnExpr(astNode: import("../generated/ast").FqnExpr): invariant;
61
61
  parseFqnRefExpr(astNode: import("../generated/ast").FqnRefExpr): invariant;
62
62
  parseFqnExpressions(astNode: import("../generated/ast").FqnExpressions): invariant[];
63
+ parseRelationWhereExpr(astNode: import("../generated/ast").RelationPredicateWhereV2): invariant;
63
64
  parseRelationExpr(astNode: import("../generated/ast").RelationExpr): invariant;
64
65
  parseDeployment(): void;
65
66
  parseDeploymentNode(astNode: import("../generated/ast").DeploymentNode): import("../ast").ParsedAstDeployment.Node;
@@ -117,6 +118,7 @@ declare const DocumentParserFromMixins: {
117
118
  parseFqnExpr(astNode: import("../generated/ast").FqnExpr): invariant;
118
119
  parseFqnRefExpr(astNode: import("../generated/ast").FqnRefExpr): invariant;
119
120
  parseFqnExpressions(astNode: import("../generated/ast").FqnExpressions): invariant[];
121
+ parseRelationWhereExpr(astNode: import("../generated/ast").RelationPredicateWhereV2): invariant;
120
122
  parseRelationExpr(astNode: import("../generated/ast").RelationExpr): invariant;
121
123
  parseDeployment(): void;
122
124
  parseDeploymentNode(astNode: import("../generated/ast").DeploymentNode): import("../ast").ParsedAstDeployment.Node;
@@ -183,6 +185,7 @@ declare const DocumentParserFromMixins: {
183
185
  parseFqnExpr(astNode: import("../generated/ast").FqnExpr): invariant;
184
186
  parseFqnRefExpr(astNode: import("../generated/ast").FqnRefExpr): invariant;
185
187
  parseFqnExpressions(astNode: import("../generated/ast").FqnExpressions): invariant[];
188
+ parseRelationWhereExpr(astNode: import("../generated/ast").RelationPredicateWhereV2): invariant;
186
189
  parseRelationExpr(astNode: import("../generated/ast").RelationExpr): invariant;
187
190
  isValid: import("../validation").IsValidFn;
188
191
  readonly services: LikeC4Services;
@@ -215,6 +218,7 @@ declare const DocumentParserFromMixins: {
215
218
  parseFqnExpr(astNode: import("../generated/ast").FqnExpr): invariant;
216
219
  parseFqnRefExpr(astNode: import("../generated/ast").FqnRefExpr): invariant;
217
220
  parseFqnExpressions(astNode: import("../generated/ast").FqnExpressions): invariant[];
221
+ parseRelationWhereExpr(astNode: import("../generated/ast").RelationPredicateWhereV2): invariant;
218
222
  parseRelationExpr(astNode: import("../generated/ast").RelationExpr): invariant;
219
223
  isValid: import("../validation").IsValidFn;
220
224
  readonly services: LikeC4Services;
@@ -261,6 +265,7 @@ declare const DocumentParserFromMixins: {
261
265
  parseFqnExpr(astNode: import("../generated/ast").FqnExpr): invariant;
262
266
  parseFqnRefExpr(astNode: import("../generated/ast").FqnRefExpr): invariant;
263
267
  parseFqnExpressions(astNode: import("../generated/ast").FqnExpressions): invariant[];
268
+ parseRelationWhereExpr(astNode: import("../generated/ast").RelationPredicateWhereV2): invariant;
264
269
  parseRelationExpr(astNode: import("../generated/ast").RelationExpr): invariant;
265
270
  isValid: import("../validation").IsValidFn;
266
271
  readonly services: LikeC4Services;
@@ -12,6 +12,7 @@ export declare function DeploymentModelParser<TBase extends WithExpressionV2>(B:
12
12
  parseFqnExpr(astNode: ast.FqnExpr): c4.FqnExpr;
13
13
  parseFqnRefExpr(astNode: ast.FqnRefExpr): c4.FqnExpr.NonWildcard;
14
14
  parseFqnExpressions(astNode: ast.FqnExpressions): c4.FqnExpr[];
15
+ parseRelationWhereExpr(astNode: ast.RelationPredicateWhereV2): c4.RelationExpr;
15
16
  parseRelationExpr(astNode: ast.RelationExpr): c4.RelationExpr;
16
17
  isValid: import("../../validation").IsValidFn;
17
18
  readonly services: import("../..").LikeC4Services;
@@ -1,5 +1,5 @@
1
1
  import type * as c4 from '@likec4/core';
2
- import { ast, type ParsedAstDeploymentView } from '../../ast';
2
+ import { type ParsedAstDeploymentView, ast } from '../../ast';
3
3
  import type { WithDeploymentModel } from './DeploymentModelParser';
4
4
  import type { WithExpressionV2 } from './FqnRefParser';
5
5
  export type WithDeploymentView = ReturnType<typeof DeploymentViewParser>;
@@ -13,6 +13,7 @@ export declare function DeploymentViewParser<TBase extends WithExpressionV2 & Wi
13
13
  parseFqnExpr(astNode: ast.FqnExpr): c4.FqnExpr;
14
14
  parseFqnRefExpr(astNode: ast.FqnRefExpr): c4.FqnExpr.NonWildcard;
15
15
  parseFqnExpressions(astNode: ast.FqnExpressions): c4.FqnExpr[];
16
+ parseRelationWhereExpr(astNode: ast.RelationPredicateWhereV2): c4.RelationExpr;
16
17
  parseRelationExpr(astNode: ast.RelationExpr): c4.RelationExpr;
17
18
  isValid: import("../../validation").IsValidFn;
18
19
  readonly services: import("../..").LikeC4Services;
@@ -70,6 +70,9 @@ export function DeploymentViewParser(B) {
70
70
  case ast.isRelationExpr(expr):
71
71
  exprs.unshift(this.parseRelationExpr(expr));
72
72
  break;
73
+ case ast.isRelationPredicateWhereV2(expr):
74
+ exprs.unshift(this.parseRelationWhereExpr(expr));
75
+ break;
73
76
  default:
74
77
  nonexhaustive(expr);
75
78
  }
@@ -8,6 +8,7 @@ export declare function ExpressionV2Parser<TBase extends Base>(B: TBase): {
8
8
  parseFqnExpr(astNode: ast.FqnExpr): c4.FqnExpr;
9
9
  parseFqnRefExpr(astNode: ast.FqnRefExpr): c4.FqnExpr.NonWildcard;
10
10
  parseFqnExpressions(astNode: ast.FqnExpressions): c4.FqnExpr[];
11
+ parseRelationWhereExpr(astNode: ast.RelationPredicateWhereV2): c4.RelationExpr;
11
12
  parseRelationExpr(astNode: ast.RelationExpr): c4.RelationExpr;
12
13
  isValid: import("../../validation").IsValidFn;
13
14
  readonly services: import("../..").LikeC4Services;
@@ -3,6 +3,7 @@ import { isNonNullish } from "remeda";
3
3
  import { ast } from "../../ast.js";
4
4
  import { logWarnError } from "../../logger.js";
5
5
  import { instanceRef } from "../../utils/fqnRef.js";
6
+ import { parseWhereClause } from "../model-parser-where.js";
6
7
  export function ExpressionV2Parser(B) {
7
8
  return class ExpressionV2Parser extends B {
8
9
  parseFqnRef(astNode) {
@@ -79,7 +80,19 @@ export function ExpressionV2Parser(B) {
79
80
  }
80
81
  return exprs.reverse();
81
82
  }
83
+ parseRelationWhereExpr(astNode) {
84
+ return {
85
+ where: {
86
+ expr: this.parseRelationExpr(astNode.subject),
87
+ condition: astNode.where ? parseWhereClause(astNode.where) : {
88
+ kind: { neq: "--always-true--" }
89
+ }
90
+ }
91
+ };
92
+ }
82
93
  parseRelationExpr(astNode) {
94
+ if (ast.isRelationPredicateWhere(astNode)) {
95
+ }
83
96
  if (ast.isDirectedRelationExpr(astNode)) {
84
97
  return {
85
98
  source: this.parseFqnExpr(astNode.source.from),
@@ -57,6 +57,7 @@ export declare function GlobalsParser<TBase extends WithViewsParser>(B: TBase):
57
57
  parseFqnExpr(astNode: ast.FqnExpr): c4.FqnExpr;
58
58
  parseFqnRefExpr(astNode: ast.FqnRefExpr): c4.FqnExpr.NonWildcard;
59
59
  parseFqnExpressions(astNode: ast.FqnExpressions): c4.FqnExpr[];
60
+ parseRelationWhereExpr(astNode: ast.RelationPredicateWhereV2): c4.RelationExpr;
60
61
  parseRelationExpr(astNode: ast.RelationExpr): c4.RelationExpr;
61
62
  parseDeployment(): void;
62
63
  parseDeploymentNode(astNode: ast.DeploymentNode): import("../../ast").ParsedAstDeployment.Node;
@@ -55,6 +55,7 @@ export declare function ViewsParser<TBase extends WithPredicates & WithDeploymen
55
55
  parseFqnExpr(astNode: ast.FqnExpr): c4.FqnExpr;
56
56
  parseFqnRefExpr(astNode: ast.FqnRefExpr): c4.FqnExpr.NonWildcard;
57
57
  parseFqnExpressions(astNode: ast.FqnExpressions): c4.FqnExpr[];
58
+ parseRelationWhereExpr(astNode: ast.RelationPredicateWhereV2): c4.RelationExpr;
58
59
  parseRelationExpr(astNode: ast.RelationExpr): c4.RelationExpr;
59
60
  parseDeployment(): void;
60
61
  parseDeploymentNode(astNode: ast.DeploymentNode): import("../../ast").ParsedAstDeployment.Node;
package/dist/module.d.ts CHANGED
@@ -1,11 +1,14 @@
1
+ import { GraphvizLayouter } from '@likec4/layouts';
1
2
  import { type Module, DocumentCache, WorkspaceCache } from 'langium';
2
3
  import { type DefaultSharedModuleContext, type LangiumServices, type LangiumSharedServices, type PartialLangiumServices } from 'langium/lsp';
4
+ import { LikeC4DocumentationProvider } from './documentation';
3
5
  import { LikeC4CodeLensProvider, LikeC4CompletionProvider, LikeC4DocumentHighlightProvider, LikeC4DocumentLinkProvider, LikeC4DocumentSymbolProvider, LikeC4HoverProvider, LikeC4SemanticTokenProvider } from './lsp';
4
6
  import { DeploymentsIndex, FqnIndex, LikeC4ModelBuilder, LikeC4ModelLocator, LikeC4ModelParser } from './model';
5
7
  import { LikeC4ModelChanges } from './model-change/ModelChanges';
6
8
  import { LikeC4NameProvider, LikeC4ScopeComputation, LikeC4ScopeProvider } from './references';
7
9
  import { Rpc } from './Rpc';
8
10
  import { LikeC4WorkspaceManager, NodeKindProvider, WorkspaceSymbolProvider } from './shared';
11
+ import { LikeC4Views } from './views';
9
12
  interface LikeC4AddedSharedServices {
10
13
  lsp: {
11
14
  NodeKindProvider: NodeKindProvider;
@@ -20,10 +23,15 @@ export type LikeC4SharedServices = LangiumSharedServices & LikeC4AddedSharedServ
20
23
  * Declaration of custom services - add your own service classes here.
21
24
  */
22
25
  export interface LikeC4AddedServices {
26
+ documentation: {
27
+ DocumentationProvider: LikeC4DocumentationProvider;
28
+ };
23
29
  WorkspaceCache: WorkspaceCache<string, any>;
24
30
  DocumentCache: DocumentCache<string, any>;
25
31
  Rpc: Rpc;
26
32
  likec4: {
33
+ Views: LikeC4Views;
34
+ Layouter: GraphvizLayouter;
27
35
  DeploymentsIndex: DeploymentsIndex;
28
36
  FqnIndex: FqnIndex;
29
37
  ModelParser: LikeC4ModelParser;
@@ -50,7 +58,7 @@ export interface LikeC4AddedServices {
50
58
  export type LikeC4Services = LangiumServices & LikeC4AddedServices;
51
59
  export declare const LikeC4Module: Module<LikeC4Services, PartialLangiumServices & LikeC4AddedServices>;
52
60
  export type LanguageServicesContext = Partial<DefaultSharedModuleContext>;
53
- 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>): {
61
+ 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>): {
54
62
  shared: LikeC4SharedServices;
55
63
  likec4: I;
56
64
  };
package/dist/module.js CHANGED
@@ -1,11 +1,21 @@
1
- import { DocumentCache, EmptyFileSystem, inject, WorkspaceCache } from "langium";
1
+ import { GraphvizLayouter, GraphvizWasmAdapter } from "@likec4/layouts";
2
+ import {
3
+ DocumentCache,
4
+ EmptyFileSystem,
5
+ inject,
6
+ WorkspaceCache
7
+ } from "langium";
2
8
  import {
3
9
  createDefaultModule,
4
10
  createDefaultSharedModule
5
11
  } from "langium/lsp";
12
+ import { LikeC4DocumentationProvider } from "./documentation/index.js";
6
13
  import { LikeC4Formatter } from "./formatting/LikeC4Formatter.js";
7
- import { LikeC4GeneratedModule, LikeC4GeneratedSharedModule } from "./generated/module.js";
8
- import { logToLspConnection } from "./logger.js";
14
+ import {
15
+ LikeC4GeneratedModule,
16
+ LikeC4GeneratedSharedModule
17
+ } from "./generated/module.js";
18
+ import { logger, logToLspConnection } from "./logger.js";
9
19
  import {
10
20
  LikeC4CodeLensProvider,
11
21
  LikeC4CompletionProvider,
@@ -15,12 +25,27 @@ import {
15
25
  LikeC4HoverProvider,
16
26
  LikeC4SemanticTokenProvider
17
27
  } from "./lsp/index.js";
18
- import { DeploymentsIndex, FqnIndex, LikeC4ModelBuilder, LikeC4ModelLocator, LikeC4ModelParser } from "./model/index.js";
28
+ import {
29
+ DeploymentsIndex,
30
+ FqnIndex,
31
+ LikeC4ModelBuilder,
32
+ LikeC4ModelLocator,
33
+ LikeC4ModelParser
34
+ } from "./model/index.js";
19
35
  import { LikeC4ModelChanges } from "./model-change/ModelChanges.js";
20
- import { LikeC4NameProvider, LikeC4ScopeComputation, LikeC4ScopeProvider } from "./references/index.js";
36
+ import {
37
+ LikeC4NameProvider,
38
+ LikeC4ScopeComputation,
39
+ LikeC4ScopeProvider
40
+ } from "./references/index.js";
21
41
  import { Rpc } from "./Rpc.js";
22
- import { LikeC4WorkspaceManager, NodeKindProvider, WorkspaceSymbolProvider } from "./shared/index.js";
42
+ import {
43
+ LikeC4WorkspaceManager,
44
+ NodeKindProvider,
45
+ WorkspaceSymbolProvider
46
+ } from "./shared/index.js";
23
47
  import { registerValidationChecks } from "./validation/index.js";
48
+ import { LikeC4Views } from "./views/index.js";
24
49
  const LikeC4SharedModule = {
25
50
  lsp: {
26
51
  NodeKindProvider: (services) => new NodeKindProvider(services),
@@ -34,10 +59,18 @@ function bind(Type) {
34
59
  return (services) => new Type(services);
35
60
  }
36
61
  export const LikeC4Module = {
62
+ documentation: {
63
+ DocumentationProvider: bind(LikeC4DocumentationProvider)
64
+ },
37
65
  WorkspaceCache: (services) => new WorkspaceCache(services.shared),
38
66
  DocumentCache: (services) => new DocumentCache(services.shared),
39
67
  Rpc: bind(Rpc),
40
68
  likec4: {
69
+ Layouter: (_services) => {
70
+ logger.debug("Creating GraphvizLayouter with GraphvizWasmAdapter");
71
+ return new GraphvizLayouter(new GraphvizWasmAdapter());
72
+ },
73
+ Views: bind(LikeC4Views),
41
74
  DeploymentsIndex: bind(DeploymentsIndex),
42
75
  ModelChanges: bind(LikeC4ModelChanges),
43
76
  FqnIndex: bind(FqnIndex),
@@ -98,10 +131,16 @@ export function createSharedServices(context = {}) {
98
131
  }
99
132
  export function createLanguageServices(context = {}) {
100
133
  const shared = createSharedServices(context);
101
- const likec4 = inject(createDefaultModule({ shared }), LikeC4GeneratedModule, LikeC4Module);
134
+ const likec4 = inject(
135
+ createDefaultModule({ shared }),
136
+ LikeC4GeneratedModule,
137
+ LikeC4Module
138
+ );
102
139
  shared.ServiceRegistry.register(likec4);
103
140
  registerValidationChecks(likec4);
104
- if (context.connection) {
141
+ if (!context.connection) {
142
+ shared.workspace.ConfigurationProvider.initialized({});
143
+ } else {
105
144
  likec4.Rpc.init();
106
145
  }
107
146
  return { shared, likec4 };
@@ -1,4 +1,4 @@
1
- import type { ComputedLikeC4Model, ComputedView, Fqn, ParsedLikeC4Model, RelationId, ViewChange, ViewId } from '@likec4/core';
1
+ import type { ComputedLikeC4Model, ComputedView, DiagramView, Fqn, ParsedLikeC4Model, RelationId, ViewChange, ViewId } from '@likec4/core';
2
2
  import { NotificationType, RequestType, RequestType0 } from 'vscode-jsonrpc';
3
3
  import type { DocumentUri, Location } from 'vscode-languageserver-types';
4
4
  export declare const onDidChangeModel: NotificationType<string>;
@@ -19,11 +19,29 @@ export declare const computeView: RequestType<{
19
19
  view: ComputedView | null;
20
20
  }, void>;
21
21
  export type ComputeViewRequest = typeof computeView;
22
+ /**
23
+ * Request to layout a view.
24
+ */
25
+ export declare const layoutView: RequestType<{
26
+ viewId: ViewId;
27
+ }, {
28
+ result: {
29
+ dot: string;
30
+ diagram: DiagramView;
31
+ } | null;
32
+ }, void>;
33
+ export type LayoutViewRequest = typeof layoutView;
34
+ /**
35
+ * Request to build documents.
36
+ */
22
37
  export interface BuildDocumentsParams {
23
38
  docs: DocumentUri[];
24
39
  }
25
40
  export declare const buildDocuments: RequestType<BuildDocumentsParams, void, void>;
26
41
  export type BuildDocumentsRequest = typeof buildDocuments;
42
+ /**
43
+ * Request to locate an element, relation, deployment or view.
44
+ */
27
45
  export type LocateParams = {
28
46
  element: Fqn;
29
47
  property?: string;
package/dist/protocol.js CHANGED
@@ -9,6 +9,7 @@ export const fetchComputedModel = new RequestType(
9
9
  export const computeView = new RequestType(
10
10
  "likec4/computeView"
11
11
  );
12
+ export const layoutView = new RequestType("likec4/layout-view");
12
13
  export const buildDocuments = new RequestType("likec4/build");
13
14
  export const locate = new RequestType("likec4/locate");
14
15
  export const changeView = new RequestType("likec4/change-view");
@@ -1,6 +1,6 @@
1
- import { type AstNodeDescription, DefaultScopeComputation, type PrecomputedScopes } from 'langium';
1
+ import { type AstNodeDescription, type PrecomputedScopes, DefaultScopeComputation } from 'langium';
2
2
  import type { CancellationToken } from 'vscode-languageserver';
3
- import { ast, type LikeC4LangiumDocument } from '../ast';
3
+ import { type LikeC4LangiumDocument, ast } from '../ast';
4
4
  import type { LikeC4Services } from '../module';
5
5
  type ElementsContainer = ast.Model | ast.ElementBody | ast.ExtendElementBody;
6
6
  type DeploymentsContainer = ast.ModelDeployments | ast.DeploymentNodeBody;
@@ -5,7 +5,7 @@ import {
5
5
  } from "langium";
6
6
  import { entries, filter, flatMap, forEachObj, groupBy, isNullish, isTruthy, pipe } from "remeda";
7
7
  import { ast } from "../ast.js";
8
- import { logError, logWarnError } from "../logger.js";
8
+ import { logWarnError } from "../logger.js";
9
9
  function uniqueDescriptions(descs) {
10
10
  return pipe(
11
11
  descs,
@@ -29,7 +29,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
29
29
  this.exportGlobals(globals, docExports, document);
30
30
  this.exportDeployments(deployments, docExports, document);
31
31
  } catch (e) {
32
- logError(e);
32
+ logWarnError(e);
33
33
  }
34
34
  return docExports;
35
35
  }
@@ -44,7 +44,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
44
44
  docExports.push(this.descriptions.createDescription(viewAst, viewAst.name, document));
45
45
  }
46
46
  } catch (e) {
47
- logError(e);
47
+ logWarnError(e);
48
48
  }
49
49
  }
50
50
  }
@@ -59,7 +59,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
59
59
  docExports.push(this.descriptions.createDescription(id, id.name, document));
60
60
  }
61
61
  } catch (e) {
62
- logError(e);
62
+ logWarnError(e);
63
63
  }
64
64
  }
65
65
  for (const globalStyleAst of globals.flatMap((g) => g.styles)) {
@@ -69,7 +69,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
69
69
  docExports.push(this.descriptions.createDescription(id, id.name, document));
70
70
  }
71
71
  } catch (e) {
72
- logError(e);
72
+ logWarnError(e);
73
73
  }
74
74
  }
75
75
  }
@@ -83,7 +83,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
83
83
  docExports.push(this.descriptions.createDescription(elAst, elAst.name, document));
84
84
  }
85
85
  } catch (e) {
86
- logError(e);
86
+ logWarnError(e);
87
87
  }
88
88
  }
89
89
  }
@@ -96,7 +96,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
96
96
  docExports.push(this.descriptions.createDescription(iconAst, iconAst.name, document));
97
97
  }
98
98
  } catch (e) {
99
- logError(e);
99
+ logWarnError(e);
100
100
  }
101
101
  }
102
102
  exportSpecification(specifications, docExports, document) {
@@ -151,7 +151,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
151
151
  nonexhaustive(spec);
152
152
  }
153
153
  } catch (e) {
154
- logError(e);
154
+ logWarnError(e);
155
155
  }
156
156
  }
157
157
  }
@@ -181,7 +181,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
181
181
  ...this.processContainer(model, scopes, document)
182
182
  );
183
183
  } catch (e) {
184
- logError(e);
184
+ logWarnError(e);
185
185
  }
186
186
  }
187
187
  for (const deployment of root.deployments) {