@likec4/language-server 1.23.1 → 1.24.1

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 (73) hide show
  1. package/dist/LikeC4FileSystem.d.ts +1 -0
  2. package/dist/LikeC4FileSystem.js +7 -0
  3. package/dist/Rpc.js +13 -11
  4. package/dist/ast.d.ts +13 -29
  5. package/dist/ast.js +3 -70
  6. package/dist/bundled.mjs +2441 -2610
  7. package/dist/generated/ast.d.ts +36 -8
  8. package/dist/generated/ast.js +44 -2
  9. package/dist/generated/grammar.js +1 -1
  10. package/dist/index.d.ts +1 -0
  11. package/dist/index.js +1 -0
  12. package/dist/likec4lib.d.ts +2 -0
  13. package/dist/likec4lib.js +3 -0
  14. package/dist/lsp/CodeLensProvider.js +10 -6
  15. package/dist/lsp/CompletionProvider.js +20 -2
  16. package/dist/lsp/DocumentLinkProvider.d.ts +3 -3
  17. package/dist/lsp/DocumentLinkProvider.js +5 -5
  18. package/dist/lsp/DocumentSymbolProvider.d.ts +1 -1
  19. package/dist/lsp/DocumentSymbolProvider.js +5 -2
  20. package/dist/lsp/HoverProvider.js +20 -7
  21. package/dist/lsp/SemanticTokenProvider.js +18 -1
  22. package/dist/model/builder/MergedExtends.d.ts +12 -0
  23. package/dist/model/builder/MergedExtends.js +67 -0
  24. package/dist/model/builder/MergedSpecification.d.ts +29 -0
  25. package/dist/model/builder/MergedSpecification.js +203 -0
  26. package/dist/model/builder/buildModel.d.ts +3 -0
  27. package/dist/model/builder/buildModel.js +194 -0
  28. package/dist/model/deployments-index.d.ts +5 -56
  29. package/dist/model/deployments-index.js +61 -137
  30. package/dist/model/fqn-index.d.ts +50 -19
  31. package/dist/model/fqn-index.js +176 -69
  32. package/dist/model/index.d.ts +0 -1
  33. package/dist/model/index.js +0 -1
  34. package/dist/model/model-builder.d.ts +10 -9
  35. package/dist/model/model-builder.js +102 -547
  36. package/dist/model/model-locator.d.ts +2 -1
  37. package/dist/model/model-locator.js +7 -9
  38. package/dist/model/model-parser.d.ts +156 -150
  39. package/dist/model/model-parser.js +68 -38
  40. package/dist/model/parser/Base.d.ts +3 -3
  41. package/dist/model/parser/Base.js +15 -9
  42. package/dist/model/parser/DeploymentModelParser.d.ts +4 -3
  43. package/dist/model/parser/DeploymentModelParser.js +54 -3
  44. package/dist/model/parser/DeploymentViewParser.d.ts +3 -2
  45. package/dist/model/parser/FqnRefParser.d.ts +2 -2
  46. package/dist/model/parser/GlobalsParser.d.ts +3 -2
  47. package/dist/model/parser/ModelParser.d.ts +4 -4
  48. package/dist/model/parser/ModelParser.js +45 -4
  49. package/dist/model/parser/PredicatesParser.d.ts +2 -2
  50. package/dist/model/parser/SpecificationParser.d.ts +2 -2
  51. package/dist/model/parser/ViewsParser.d.ts +3 -2
  52. package/dist/module.d.ts +2 -3
  53. package/dist/module.js +2 -3
  54. package/dist/references/scope-computation.d.ts +1 -1
  55. package/dist/references/scope-computation.js +14 -11
  56. package/dist/references/scope-provider.d.ts +16 -4
  57. package/dist/references/scope-provider.js +64 -30
  58. package/dist/test/testServices.d.ts +2 -1
  59. package/dist/test/testServices.js +23 -20
  60. package/dist/utils/elementRef.d.ts +1 -1
  61. package/dist/utils/elementRef.js +3 -3
  62. package/dist/validation/deployment-checks.d.ts +1 -0
  63. package/dist/validation/deployment-checks.js +12 -0
  64. package/dist/validation/index.d.ts +1 -1
  65. package/dist/validation/index.js +8 -1
  66. package/dist/views/configurable-layouter.js +3 -3
  67. package/dist/views/likec4-views.d.ts +1 -0
  68. package/dist/views/likec4-views.js +11 -11
  69. package/package.json +12 -13
  70. package/dist/bundled.d.ts +0 -8
  71. package/dist/bundled.js +0 -25
  72. package/dist/model/fqn-computation.d.ts +0 -3
  73. package/dist/model/fqn-computation.js +0 -72
package/dist/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import { LikeC4FileSystem } from './LikeC4FileSystem';
2
2
  import { type LikeC4Services, type LikeC4SharedServices } from './module';
3
3
  export { getLspConnectionSink, logger as lspLogger } from './logger';
4
4
  export type { DocumentParser, LikeC4ModelBuilder, LikeC4ModelLocator, LikeC4ModelParser } from './model';
5
+ export { isLikeC4Builtin } from './likec4lib';
5
6
  export { createCustomLanguageServices, createLanguageServices, LikeC4Module } from './module';
6
7
  export type { LikeC4Services, LikeC4SharedServices } from './module';
7
8
  export type { LikeC4Views } from './views';
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@ import { getTelemetrySink, logger } from "./logger.js";
6
6
  import { createCustomLanguageServices } from "./module.js";
7
7
  import { ConfigurableLayouter } from "./views/configurable-layouter.js";
8
8
  export { getLspConnectionSink, logger as lspLogger } from "./logger.js";
9
+ export { isLikeC4Builtin } from "./likec4lib.js";
9
10
  export { createCustomLanguageServices, createLanguageServices, LikeC4Module } from "./module.js";
10
11
  export { LikeC4FileSystem };
11
12
  export async function startLanguageServer() {
@@ -1,4 +1,6 @@
1
+ import { type URI } from 'langium';
1
2
  import { LibIcons } from './generated-lib/icons';
2
3
  export declare const Scheme = "likec4builtin";
3
4
  export declare const Uri: "likec4builtin:///likec4/lib/icons.c4";
4
5
  export { LibIcons as Content };
6
+ export declare function isLikeC4Builtin(uri: URI): boolean;
package/dist/likec4lib.js CHANGED
@@ -2,3 +2,6 @@ import { LibIcons } from "./generated-lib/icons.js";
2
2
  export const Scheme = "likec4builtin";
3
3
  export const Uri = `${Scheme}:///likec4/lib/icons.c4`;
4
4
  export { LibIcons as Content };
5
+ export function isLikeC4Builtin(uri) {
6
+ return uri.scheme === Scheme;
7
+ }
@@ -1,19 +1,23 @@
1
- import { DocumentState } from "langium";
2
- import { isParsedLikeC4LangiumDocument, ViewOps } from "../ast.js";
1
+ import { DocumentState, interruptAndCheck } from "langium";
2
+ import { isLikeC4LangiumDocument, ViewOps } from "../ast.js";
3
3
  import { logger } from "../logger.js";
4
4
  export class LikeC4CodeLensProvider {
5
5
  constructor(services) {
6
6
  this.services = services;
7
7
  }
8
8
  async provideCodeLens(doc, _params, cancelToken) {
9
- if (doc.state !== DocumentState.Validated) {
10
- logger.debug(`Waiting for document ${doc.uri.path} to be validated`);
9
+ if (!isLikeC4LangiumDocument(doc)) {
10
+ return;
11
+ }
12
+ if (doc.state <= DocumentState.Linked) {
13
+ logger.debug(`Waiting for document ${doc.uri.path} to be Linked`);
11
14
  await this.services.shared.workspace.DocumentBuilder.waitUntil(DocumentState.Validated, doc.uri, cancelToken);
12
15
  logger.debug(`Document ${doc.uri.path} is validated`);
13
16
  }
14
- if (!isParsedLikeC4LangiumDocument(doc)) {
15
- return;
17
+ if (cancelToken) {
18
+ await interruptAndCheck(cancelToken);
16
19
  }
20
+ this.services.likec4.ModelParser.parse(doc);
17
21
  const views = doc.parseResult.value.views.flatMap((v) => v.views);
18
22
  return views.flatMap((ast) => {
19
23
  const viewId = ViewOps.readId(ast);
@@ -1,3 +1,4 @@
1
+ import { ThemeColors } from "@likec4/core";
1
2
  import { AstUtils } from "langium";
2
3
  import {
3
4
  DefaultCompletionProvider
@@ -12,7 +13,8 @@ const STYLE_FIELDS = [
12
13
  "border",
13
14
  "opacity",
14
15
  "multiple",
15
- "size"
16
+ "size",
17
+ "textSize"
16
18
  ].join(",");
17
19
  export class LikeC4CompletionProvider extends DefaultCompletionProvider {
18
20
  completionOptions = {
@@ -45,6 +47,22 @@ export class LikeC4CompletionProvider extends DefaultCompletionProvider {
45
47
  insertText: `${keyword.value} '\${0}'`
46
48
  });
47
49
  }
50
+ if (keyword.value === "color") {
51
+ return acceptor(context, {
52
+ label: keyword.value,
53
+ kind: CompletionItemKind.Property,
54
+ insertTextFormat: InsertTextFormat.Snippet,
55
+ insertText: `${keyword.value} \${1|${ThemeColors.join(",")}|}$0`
56
+ });
57
+ }
58
+ if (keyword.value === "opacity") {
59
+ return acceptor(context, {
60
+ label: keyword.value,
61
+ kind: CompletionItemKind.Property,
62
+ insertTextFormat: InsertTextFormat.Snippet,
63
+ insertText: `${keyword.value} \${0:100}%`
64
+ });
65
+ }
48
66
  if (["views", "specification", "model", "deployment", "with"].includes(keyword.value)) {
49
67
  return acceptor(context, {
50
68
  label: keyword.value,
@@ -123,7 +141,7 @@ export class LikeC4CompletionProvider extends DefaultCompletionProvider {
123
141
  detail: `Extend another view`,
124
142
  kind: CompletionItemKind.Class,
125
143
  insertTextFormat: InsertTextFormat.Snippet,
126
- insertText: "extend ${1:element} {\n $0\n}"
144
+ insertText: "extend $1 {\n $0\n}"
127
145
  });
128
146
  }
129
147
  if (keyword.value === "autoLayout") {
@@ -1,11 +1,11 @@
1
- import type { LangiumDocument, MaybePromise } from 'langium';
1
+ import type { LangiumDocument } from 'langium';
2
2
  import type { DocumentLinkProvider } from 'langium/lsp';
3
- import type { DocumentLink, DocumentLinkParams } from 'vscode-languageserver';
3
+ import type { CancellationToken, DocumentLink, DocumentLinkParams } from 'vscode-languageserver';
4
4
  import type { LikeC4Services } from '../module';
5
5
  export declare class LikeC4DocumentLinkProvider implements DocumentLinkProvider {
6
6
  private services;
7
7
  constructor(services: LikeC4Services);
8
- getDocumentLinks(doc: LangiumDocument, _params: DocumentLinkParams): MaybePromise<DocumentLink[]>;
8
+ getDocumentLinks(doc: LangiumDocument, _params: DocumentLinkParams, cancelToken?: CancellationToken): Promise<DocumentLink[]>;
9
9
  resolveLink(doc: LangiumDocument, link: string): string;
10
10
  relativeLink(doc: LangiumDocument, link: string): string | null;
11
11
  }
@@ -1,20 +1,20 @@
1
1
  import { AstUtils, GrammarUtils } from "langium";
2
2
  import { hasLeadingSlash, hasProtocol, isRelative, withoutBase, withoutLeadingSlash } from "ufo";
3
- import { ast, isParsedLikeC4LangiumDocument } from "../ast.js";
3
+ import { ast, isLikeC4LangiumDocument } from "../ast.js";
4
4
  import { logWarnError } from "../logger.js";
5
5
  export class LikeC4DocumentLinkProvider {
6
6
  constructor(services) {
7
7
  this.services = services;
8
8
  }
9
- getDocumentLinks(doc, _params) {
10
- if (!isParsedLikeC4LangiumDocument(doc)) {
9
+ async getDocumentLinks(doc, _params, cancelToken) {
10
+ if (!isLikeC4LangiumDocument(doc)) {
11
11
  return [];
12
12
  }
13
13
  return AstUtils.streamAllContents(doc.parseResult.value).filter(ast.isLinkProperty).map((n) => {
14
14
  try {
15
15
  const range = GrammarUtils.findNodeForProperty(n.$cstNode, "value")?.range;
16
- const target = this.resolveLink(doc, n.value);
17
- if (range && hasProtocol(target)) {
16
+ const target = range && this.resolveLink(doc, n.value);
17
+ if (target && hasProtocol(target)) {
18
18
  return {
19
19
  range,
20
20
  target
@@ -25,7 +25,7 @@ export declare class LikeC4DocumentSymbolProvider implements DocumentSymbolProvi
25
25
  protected getTagSymbol(astTag: ast.SpecificationTag): DocumentSymbol | null;
26
26
  protected getLibIconSymbol(astTag: ast.LibIcon): DocumentSymbol | null;
27
27
  protected getViewSymbol(astView: ast.LikeC4View): DocumentSymbol[];
28
- protected getDeploymentElementSymbol(el: ast.DeploymentElement | ast.DeploymentRelation): DocumentSymbol[];
28
+ protected getDeploymentElementSymbol(el: ast.DeploymentElement | ast.DeploymentRelation | ast.ExtendDeployment): DocumentSymbol[];
29
29
  protected getDeploymentNodeSymbol(astElement: ast.DeploymentNode): DocumentSymbol[];
30
30
  protected getDeployedInstanceSymbol(astElement: ast.DeployedInstance): DocumentSymbol[];
31
31
  protected symbolKind(node: AstNode): SymbolKind;
@@ -4,7 +4,7 @@ import { filter, isEmpty, isTruthy, map, pipe } from "remeda";
4
4
  import { SymbolKind } from "vscode-languageserver-types";
5
5
  import { ast } from "../ast.js";
6
6
  import { logWarnError } from "../logger.js";
7
- import { getFqnElementRef } from "../utils/elementRef.js";
7
+ import { readStrictFqn } from "../utils/elementRef.js";
8
8
  export class LikeC4DocumentSymbolProvider {
9
9
  constructor(services) {
10
10
  this.services = services;
@@ -137,7 +137,7 @@ export class LikeC4DocumentSymbolProvider {
137
137
  return [
138
138
  {
139
139
  kind: this.symbolKind(astElement),
140
- name: getFqnElementRef(astElement.element),
140
+ name: readStrictFqn(astElement.element),
141
141
  range: cst.range,
142
142
  selectionRange: nameNode.range,
143
143
  children: body.elements.flatMap((e) => this.getElementsSymbol(e))
@@ -226,6 +226,9 @@ export class LikeC4DocumentSymbolProvider {
226
226
  if (ast.isDeployedInstance(el)) {
227
227
  return this.getDeployedInstanceSymbol(el);
228
228
  }
229
+ if (ast.isExtendDeployment(el)) {
230
+ return [];
231
+ }
229
232
  } catch (e) {
230
233
  logWarnError(e);
231
234
  }
@@ -1,6 +1,5 @@
1
1
  import { AstUtils } from "langium";
2
2
  import { AstNodeHoverProvider } from "langium/lsp";
3
- import stripIndent from "strip-indent";
4
3
  import { ast } from "../ast.js";
5
4
  export class LikeC4HoverProvider extends AstNodeHoverProvider {
6
5
  parser;
@@ -15,9 +14,7 @@ export class LikeC4HoverProvider extends AstNodeHoverProvider {
15
14
  return {
16
15
  contents: {
17
16
  kind: "markdown",
18
- value: stripIndent(`
19
- tag: \`${node.name}\`
20
- `)
17
+ value: "tag `" + node.name + "`"
21
18
  }
22
19
  };
23
20
  }
@@ -28,7 +25,7 @@ export class LikeC4HoverProvider extends AstNodeHoverProvider {
28
25
  if (el.title !== node.name) {
29
26
  lines.push(`### ${el.title}`);
30
27
  }
31
- lines.push("Deployment: `" + el.kind + "` ");
28
+ lines.push("deployment node `" + el.kind + "` ");
32
29
  return {
33
30
  contents: {
34
31
  kind: "markdown",
@@ -42,7 +39,7 @@ export class LikeC4HoverProvider extends AstNodeHoverProvider {
42
39
  const el = this.locator.getParsedElement(instance.element);
43
40
  const lines = [instance.id + " ", `instance of \`${instance.element}\``];
44
41
  if (el) {
45
- lines.push(`### ${el.title}`, "Element: `" + el.kind + "` ");
42
+ lines.push(`### ${el.title}`, "element kind `" + el.kind + "` ");
46
43
  }
47
44
  return {
48
45
  contents: {
@@ -51,12 +48,28 @@ export class LikeC4HoverProvider extends AstNodeHoverProvider {
51
48
  }
52
49
  };
53
50
  }
51
+ if (ast.isElementKind(node)) {
52
+ return {
53
+ contents: {
54
+ kind: "markdown",
55
+ value: "element kind `" + node.name + "`"
56
+ }
57
+ };
58
+ }
59
+ if (ast.isDeploymentNodeKind(node)) {
60
+ return {
61
+ contents: {
62
+ kind: "markdown",
63
+ value: "deployment node `" + node.name + "`"
64
+ }
65
+ };
66
+ }
54
67
  if (ast.isElement(node)) {
55
68
  const el = this.locator.getParsedElement(node);
56
69
  if (!el) {
57
70
  return;
58
71
  }
59
- const lines = [el.id, `### ${el.title}`, "Element: `" + el.kind + "` "];
72
+ const lines = [el.id, `### ${el.title}`, "element kind `" + el.kind + "` "];
60
73
  return {
61
74
  contents: {
62
75
  kind: "markdown",
@@ -191,7 +191,7 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
191
191
  });
192
192
  return "prune";
193
193
  }
194
- if (ast.isFqnRef(node)) {
194
+ if (ast.isFqnRef(node) || ast.isStrictFqnRef(node)) {
195
195
  acceptor({
196
196
  node,
197
197
  property: "value",
@@ -334,6 +334,23 @@ export class LikeC4SemanticTokenProvider extends AbstractSemanticTokenProvider {
334
334
  type: SemanticTokenTypes.keyword,
335
335
  modifier: []
336
336
  });
337
+ if (ast.isElement(node)) {
338
+ if (node.props.length > 0) {
339
+ acceptor({
340
+ node,
341
+ property: "props",
342
+ type: SemanticTokenTypes.string
343
+ });
344
+ }
345
+ return;
346
+ }
347
+ if (node.title) {
348
+ acceptor({
349
+ node,
350
+ property: "title",
351
+ type: SemanticTokenTypes.string
352
+ });
353
+ }
337
354
  }
338
355
  highlightView(node, acceptor) {
339
356
  if (node.name) {
@@ -0,0 +1,12 @@
1
+ import type * as c4 from '@likec4/core';
2
+ import type { ParsedAstExtend } from '../../ast';
3
+ export declare class MergedExtends {
4
+ private mergedData;
5
+ merge(parsedExtends: ParsedAstExtend[]): void;
6
+ apply<E extends {
7
+ id: c4.Fqn;
8
+ tags?: c4.NonEmptyArray<c4.Tag> | null;
9
+ links?: c4.NonEmptyArray<c4.Link> | null;
10
+ metadata?: Record<string, string>;
11
+ }>(el: E): E;
12
+ }
@@ -0,0 +1,67 @@
1
+ import {
2
+ hasAtLeast,
3
+ isEmpty,
4
+ unique
5
+ } from "remeda";
6
+ export class MergedExtends {
7
+ mergedData = /* @__PURE__ */ new Map();
8
+ merge(parsedExtends) {
9
+ for (const parsedExtend of parsedExtends) {
10
+ const { id, links, tags, metadata } = parsedExtend;
11
+ const existing = this.mergedData.get(id) ?? {
12
+ links: [],
13
+ tags: [],
14
+ metadata: {}
15
+ };
16
+ if (links) {
17
+ existing.links.push(...links);
18
+ }
19
+ if (tags) {
20
+ existing.tags = unique([
21
+ ...existing.tags,
22
+ ...tags
23
+ ]);
24
+ }
25
+ if (metadata) {
26
+ existing.metadata = {
27
+ ...existing.metadata,
28
+ ...metadata
29
+ };
30
+ }
31
+ this.mergedData.set(id, existing);
32
+ }
33
+ }
34
+ apply(el) {
35
+ const extendData = this.mergedData.get(el.id);
36
+ if (!extendData) {
37
+ return el;
38
+ }
39
+ let links = extendData.links;
40
+ if (el.links && el.links.length > 0) {
41
+ links = [
42
+ ...el.links,
43
+ ...links
44
+ ];
45
+ }
46
+ let tags = extendData.tags;
47
+ if (el.tags && el.tags.length > 0) {
48
+ tags = unique([
49
+ ...el.tags,
50
+ ...tags
51
+ ]);
52
+ }
53
+ let metadata = extendData.metadata;
54
+ if (el.metadata) {
55
+ metadata = {
56
+ ...el.metadata,
57
+ ...extendData.metadata
58
+ };
59
+ }
60
+ return {
61
+ ...el,
62
+ tags: hasAtLeast(tags, 1) ? tags : null,
63
+ links: hasAtLeast(links, 1) ? links : null,
64
+ ...!isEmpty(metadata) && { metadata }
65
+ };
66
+ }
67
+ }
@@ -0,0 +1,29 @@
1
+ import type * as c4 from '@likec4/core';
2
+ import type { ParsedAstDeploymentRelation, ParsedAstElement, ParsedAstRelation, ParsedAstSpecification, ParsedLikeC4LangiumDocument } from '../../ast';
3
+ /**
4
+ * The `MergedSpecification` class is responsible for merging multiple parsed
5
+ * LikeC4Langium documents into a single specification. It consolidates tags,
6
+ * elements, deployments, relationships, and colors from the provided documents
7
+ * and provides methods to convert parsed models into C4 model elements and relations.
8
+ */
9
+ export declare class MergedSpecification {
10
+ readonly specs: ParsedAstSpecification;
11
+ readonly globals: c4.ModelGlobals;
12
+ constructor(docs: ParsedLikeC4LangiumDocument[]);
13
+ /**
14
+ * Converts a parsed model into a C4 model element.
15
+ */
16
+ toModelElement: ({ tags, links, style: { color, shape, icon, opacity, border, size, multiple, padding, textSize, }, id, kind, title, description, technology, metadata, }: ParsedAstElement) => c4.Element | null;
17
+ /**
18
+ * Converts a parsed model into a C4 model relation.
19
+ */
20
+ toModelRelation: ({ astPath, source, target, kind, links, id, ...model }: ParsedAstRelation) => c4.ModelRelation | null;
21
+ /**
22
+ * Converts a parsed deployment model into a C4 deployment model
23
+ */
24
+ toDeploymentElement: (parsed: c4.DeploymentElement) => c4.DeploymentElement | null;
25
+ /**
26
+ * Converts a parsed deployment relation into a C4 deployment relation.
27
+ */
28
+ toDeploymentRelation: ({ astPath, source, target, kind, links, id, ...model }: ParsedAstDeploymentRelation) => c4.DeploymentRelation | null;
29
+ }
@@ -0,0 +1,203 @@
1
+ import {
2
+ DeploymentElement
3
+ } from "@likec4/core";
4
+ import {
5
+ isBoolean,
6
+ isEmpty,
7
+ isNonNullish,
8
+ isNumber
9
+ } from "remeda";
10
+ import { logger, logWarnError } from "../../logger.js";
11
+ export class MergedSpecification {
12
+ specs = {
13
+ tags: /* @__PURE__ */ new Set(),
14
+ elements: {},
15
+ deployments: {},
16
+ relationships: {},
17
+ colors: {}
18
+ };
19
+ globals = {
20
+ predicates: {},
21
+ dynamicPredicates: {},
22
+ styles: {}
23
+ };
24
+ constructor(docs) {
25
+ for (const doc of docs) {
26
+ const {
27
+ c4Specification: spec,
28
+ c4Globals
29
+ } = doc;
30
+ spec.tags.forEach((t) => this.specs.tags.add(t));
31
+ Object.assign(this.specs.elements, spec.elements);
32
+ Object.assign(this.specs.relationships, spec.relationships);
33
+ Object.assign(this.specs.colors, spec.colors);
34
+ Object.assign(this.specs.deployments, spec.deployments);
35
+ Object.assign(this.globals.predicates, c4Globals.predicates);
36
+ Object.assign(this.globals.dynamicPredicates, c4Globals.dynamicPredicates);
37
+ Object.assign(this.globals.styles, c4Globals.styles);
38
+ }
39
+ }
40
+ /**
41
+ * Converts a parsed model into a C4 model element.
42
+ */
43
+ toModelElement = ({
44
+ tags,
45
+ links,
46
+ style: {
47
+ color,
48
+ shape,
49
+ icon,
50
+ opacity,
51
+ border,
52
+ size,
53
+ multiple,
54
+ padding,
55
+ textSize
56
+ },
57
+ id,
58
+ kind,
59
+ title,
60
+ description,
61
+ technology,
62
+ metadata
63
+ }) => {
64
+ try {
65
+ const __kind = this.specs.elements[kind];
66
+ if (!__kind) {
67
+ logger.warn`No kind '${kind}' found for ${id}`;
68
+ return null;
69
+ }
70
+ color ??= __kind.style.color;
71
+ shape ??= __kind.style.shape;
72
+ icon ??= __kind.style.icon;
73
+ opacity ??= __kind.style.opacity;
74
+ border ??= __kind.style.border;
75
+ technology ??= __kind.technology;
76
+ multiple ??= __kind.style.multiple;
77
+ size ??= __kind.style.size;
78
+ padding ??= __kind.style.padding;
79
+ textSize ??= __kind.style.textSize;
80
+ return {
81
+ ...color && { color },
82
+ ...shape && { shape },
83
+ ...icon && { icon },
84
+ ...metadata && !isEmpty(metadata) && { metadata },
85
+ ...__kind.notation && { notation: __kind.notation },
86
+ style: {
87
+ ...border && { border },
88
+ ...size && { size },
89
+ ...padding && { padding },
90
+ ...textSize && { textSize },
91
+ ...isBoolean(multiple) && { multiple },
92
+ ...isNumber(opacity) && { opacity }
93
+ },
94
+ links: links ?? null,
95
+ tags: tags ?? null,
96
+ technology: technology ?? null,
97
+ description: description ?? null,
98
+ title,
99
+ kind,
100
+ id
101
+ };
102
+ } catch (e) {
103
+ logWarnError(e);
104
+ }
105
+ return null;
106
+ };
107
+ /**
108
+ * Converts a parsed model into a C4 model relation.
109
+ */
110
+ toModelRelation = ({
111
+ astPath,
112
+ source,
113
+ target,
114
+ kind,
115
+ links,
116
+ id,
117
+ ...model
118
+ }) => {
119
+ if (isNonNullish(kind) && this.specs.relationships[kind]) {
120
+ return {
121
+ ...this.specs.relationships[kind],
122
+ ...model,
123
+ ...links && { links },
124
+ source,
125
+ target,
126
+ kind,
127
+ id
128
+ };
129
+ }
130
+ return {
131
+ ...links && { links },
132
+ ...model,
133
+ source,
134
+ target,
135
+ id
136
+ };
137
+ };
138
+ /**
139
+ * Converts a parsed deployment model into a C4 deployment model
140
+ */
141
+ toDeploymentElement = (parsed) => {
142
+ if (!DeploymentElement.isDeploymentNode(parsed)) {
143
+ return parsed;
144
+ }
145
+ try {
146
+ const __kind = this.specs.deployments[parsed.kind];
147
+ if (!__kind) {
148
+ logger.warn`No kind ${parsed.kind} found for ${parsed.id}`;
149
+ return null;
150
+ }
151
+ let {
152
+ technology = __kind.technology,
153
+ notation = __kind.notation,
154
+ style
155
+ } = parsed;
156
+ return {
157
+ ...parsed,
158
+ ...notation && { notation },
159
+ ...technology && { technology },
160
+ style: {
161
+ border: "dashed",
162
+ opacity: 10,
163
+ ...__kind.style,
164
+ ...style
165
+ }
166
+ };
167
+ } catch (e) {
168
+ logWarnError(e);
169
+ }
170
+ return null;
171
+ };
172
+ /**
173
+ * Converts a parsed deployment relation into a C4 deployment relation.
174
+ */
175
+ toDeploymentRelation = ({
176
+ astPath,
177
+ source,
178
+ target,
179
+ kind,
180
+ links,
181
+ id,
182
+ ...model
183
+ }) => {
184
+ if (isNonNullish(kind) && this.specs.relationships[kind]) {
185
+ return {
186
+ ...this.specs.relationships[kind],
187
+ ...model,
188
+ ...links && { links },
189
+ source,
190
+ target,
191
+ kind,
192
+ id
193
+ };
194
+ }
195
+ return {
196
+ ...links && { links },
197
+ ...model,
198
+ source,
199
+ target,
200
+ id
201
+ };
202
+ };
203
+ }
@@ -0,0 +1,3 @@
1
+ import type * as c4 from '@likec4/core';
2
+ import type { ParsedLikeC4LangiumDocument } from '../../ast';
3
+ export declare function buildModel(docs: ParsedLikeC4LangiumDocument[]): c4.ParsedLikeC4Model;