@likec4/language-server 1.31.0 → 1.32.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 (82) hide show
  1. package/dist/LikeC4LanguageServices.d.ts +2 -1
  2. package/dist/LikeC4LanguageServices.js +4 -3
  3. package/dist/Rpc.js +11 -4
  4. package/dist/ast.d.ts +12 -15
  5. package/dist/ast.js +4 -1
  6. package/dist/bundled.mjs +2545 -2476
  7. package/dist/formatting/LikeC4Formatter.js +7 -6
  8. package/dist/generated/ast.d.ts +60 -19
  9. package/dist/generated/ast.js +79 -24
  10. package/dist/generated/grammar.js +1 -1
  11. package/dist/lsp/CompletionProvider.js +1 -1
  12. package/dist/lsp/DocumentLinkProvider.js +4 -3
  13. package/dist/lsp/HoverProvider.js +9 -1
  14. package/dist/lsp/SemanticTokenProvider.js +18 -4
  15. package/dist/mcp/LikeC4MCPServerFactory.d.ts +5 -2
  16. package/dist/mcp/LikeC4MCPServerFactory.js +2 -72
  17. package/dist/mcp/LikeC4MCPTools.js +5 -3
  18. package/dist/mcp/sseserver/MCPServerFactory.d.ts +8 -0
  19. package/dist/mcp/sseserver/MCPServerFactory.js +78 -0
  20. package/dist/mcp/sseserver/with-mcp-server.d.ts +2 -0
  21. package/dist/mcp/sseserver/with-mcp-server.js +5 -1
  22. package/dist/mcp/utils.d.ts +5 -4
  23. package/dist/mcp/utils.js +2 -2
  24. package/dist/model/builder/MergedExtends.d.ts +4 -4
  25. package/dist/model/builder/MergedExtends.js +1 -1
  26. package/dist/model/builder/MergedSpecification.d.ts +4 -3
  27. package/dist/model/builder/MergedSpecification.js +9 -8
  28. package/dist/model/builder/assignTagColors.d.ts +7 -0
  29. package/dist/model/builder/assignTagColors.js +51 -0
  30. package/dist/model/builder/buildModel.d.ts +2 -2
  31. package/dist/model/builder/buildModel.js +40 -18
  32. package/dist/model/deployments-index.js +2 -2
  33. package/dist/model/fqn-index.d.ts +1 -1
  34. package/dist/model/fqn-index.js +6 -6
  35. package/dist/model/model-builder.d.ts +10 -4
  36. package/dist/model/model-builder.js +22 -19
  37. package/dist/model/model-locator.d.ts +10 -2
  38. package/dist/model/model-locator.js +65 -9
  39. package/dist/model/model-parser-where.d.ts +1 -1
  40. package/dist/model/model-parser-where.js +1 -1
  41. package/dist/model/model-parser.d.ts +19 -11
  42. package/dist/model/model-parser.js +11 -7
  43. package/dist/model/parser/Base.d.ts +1 -0
  44. package/dist/model/parser/Base.js +24 -3
  45. package/dist/model/parser/DeploymentModelParser.d.ts +2 -1
  46. package/dist/model/parser/DeploymentModelParser.js +7 -5
  47. package/dist/model/parser/DeploymentViewParser.d.ts +4 -3
  48. package/dist/model/parser/DeploymentViewParser.js +2 -1
  49. package/dist/model/parser/FqnRefParser.d.ts +2 -1
  50. package/dist/model/parser/FqnRefParser.js +2 -5
  51. package/dist/model/parser/GlobalsParser.d.ts +24 -24
  52. package/dist/model/parser/GlobalsParser.js +4 -4
  53. package/dist/model/parser/ImportsParser.d.ts +1 -0
  54. package/dist/model/parser/ModelParser.d.ts +2 -1
  55. package/dist/model/parser/ModelParser.js +1 -1
  56. package/dist/model/parser/PredicatesParser.d.ts +13 -12
  57. package/dist/model/parser/SpecificationParser.d.ts +6 -2
  58. package/dist/model/parser/SpecificationParser.js +21 -31
  59. package/dist/model/parser/ViewsParser.d.ts +24 -23
  60. package/dist/model/parser/ViewsParser.js +12 -19
  61. package/dist/model-change/changeElementStyle.d.ts +2 -2
  62. package/dist/model-change/changeElementStyle.js +6 -2
  63. package/dist/module.d.ts +1 -1
  64. package/dist/module.js +5 -2
  65. package/dist/protocol.d.ts +24 -3
  66. package/dist/protocol.js +4 -0
  67. package/dist/references/scope-computation.js +2 -3
  68. package/dist/test/testServices.d.ts +15 -0
  69. package/dist/test/testServices.js +1 -1
  70. package/dist/validation/index.d.ts +1 -1
  71. package/dist/validation/index.js +10 -3
  72. package/dist/validation/property-checks.d.ts +1 -0
  73. package/dist/validation/property-checks.js +62 -0
  74. package/dist/validation/relation.js +1 -1
  75. package/dist/validation/specification.js +1 -1
  76. package/dist/view-utils/assignNavigateTo.d.ts +1 -1
  77. package/dist/view-utils/assignNavigateTo.js +3 -3
  78. package/dist/views/likec4-views.d.ts +1 -3
  79. package/dist/views/likec4-views.js +68 -44
  80. package/package.json +23 -21
  81. /package/dist/mcp/sseserver/{SSELikeC4MCPServer.d.ts → MCPServer.d.ts} +0 -0
  82. /package/dist/mcp/sseserver/{SSELikeC4MCPServer.js → MCPServer.js} +0 -0
@@ -1,3 +1,4 @@
1
+ import { nonNullable } from "@likec4/core/utils";
1
2
  import { filter, isNonNullish, isTruthy, mapToObj, pipe } from "remeda";
2
3
  import { ast, toRelationshipStyleExcludeDefaults } from "../../ast.js";
3
4
  import { logger, logWarnError } from "../../logger.js";
@@ -14,27 +15,16 @@ export function SpecificationParser(B) {
14
15
  c4Specification
15
16
  } = this.doc;
16
17
  const isValid = this.isValid;
17
- const element_specs = specifications.flatMap((s) => s.elements.filter(this.isValid));
18
- for (const { kind, props } of element_specs) {
18
+ for (const elementSpec of specifications.flatMap((s) => s.elements.filter(isValid))) {
19
19
  try {
20
- const kindName = kind.name;
21
- if (!isTruthy(kindName)) {
22
- continue;
23
- }
24
- if (kindName in c4Specification.elements) {
25
- logger.warn(`Element kind "${kindName}" is already defined`);
26
- continue;
27
- }
28
- const style = this.parseElementStyle(props.find(ast.isElementStyleProperty));
29
- const bodyProps = pipe(
30
- props.filter(ast.isSpecificationElementStringProperty) ?? [],
31
- filter((p) => this.isValid(p) && isNonNullish(p.value)),
32
- mapToObj((p) => [p.key, removeIndent(p.value)])
33
- );
34
- c4Specification.elements[kindName] = {
35
- ...bodyProps,
36
- style
37
- };
20
+ Object.assign(c4Specification.elements, this.parseElementSpecificationNode(elementSpec));
21
+ } catch (e) {
22
+ logWarnError(e);
23
+ }
24
+ }
25
+ for (const deploymentNodeSpec of specifications.flatMap((s) => s.deploymentNodes.filter(isValid))) {
26
+ try {
27
+ Object.assign(c4Specification.deployments, this.parseElementSpecificationNode(deploymentNodeSpec));
38
28
  } catch (e) {
39
29
  logWarnError(e);
40
30
  }
@@ -66,16 +56,13 @@ export function SpecificationParser(B) {
66
56
  const tags_specs = specifications.flatMap((s) => s.tags.filter(this.isValid));
67
57
  for (const tagSpec of tags_specs) {
68
58
  const tag = tagSpec.tag.name;
59
+ const astPath = this.getAstNodePath(tagSpec.tag);
60
+ const color = tagSpec.color && this.parseColorLiteral(tagSpec.color);
69
61
  if (isTruthy(tag)) {
70
- c4Specification.tags.add(tag);
71
- }
72
- }
73
- const deploymentNodes_specs = specifications.flatMap((s) => s.deploymentNodes.filter(isValid));
74
- for (const deploymentNode of deploymentNodes_specs) {
75
- try {
76
- Object.assign(c4Specification.deployments, this.parseSpecificationDeploymentNodeKind(deploymentNode));
77
- } catch (e) {
78
- logWarnError(e);
62
+ c4Specification.tags[tag] = {
63
+ astPath,
64
+ ...color ? { color } : {}
65
+ };
79
66
  }
80
67
  }
81
68
  const colors_specs = specifications.flatMap((s) => s.colors.filter(isValid));
@@ -87,18 +74,20 @@ export function SpecificationParser(B) {
87
74
  continue;
88
75
  }
89
76
  c4Specification.colors[colorName] = {
90
- color
77
+ color: nonNullable(this.parseColorLiteral(color), `Color "${colorName}" is not valid: ${color}`)
91
78
  };
92
79
  } catch (e) {
93
80
  logWarnError(e);
94
81
  }
95
82
  }
96
83
  }
97
- parseSpecificationDeploymentNodeKind({ kind, props }) {
84
+ parseElementSpecificationNode(specAst) {
85
+ const { kind, props } = specAst;
98
86
  const kindName = kind.name;
99
87
  if (!isTruthy(kindName)) {
100
88
  throw new Error("DeploymentNodeKind name is not resolved");
101
89
  }
90
+ const tags = this.parseTags(specAst);
102
91
  const style = this.parseElementStyle(props.find(ast.isElementStyleProperty));
103
92
  const bodyProps = pipe(
104
93
  props.filter(ast.isSpecificationElementStringProperty) ?? [],
@@ -108,6 +97,7 @@ export function SpecificationParser(B) {
108
97
  return {
109
98
  [kindName]: {
110
99
  ...bodyProps,
100
+ ...tags && { tags },
111
101
  style
112
102
  }
113
103
  };
@@ -1,39 +1,38 @@
1
- import type * as c4 from '@likec4/core';
1
+ import * as c4 from '@likec4/core';
2
2
  import { type ParsedAstDynamicView, type ParsedAstElementView, ast } from '../../ast';
3
- import type { NotationProperty } from '../../generated/ast';
4
3
  import type { WithDeploymentView } from './DeploymentViewParser';
5
4
  import type { WithPredicates } from './PredicatesParser';
6
5
  export type WithViewsParser = ReturnType<typeof ViewsParser>;
6
+ type ViewRuleStyleOrGlobalRef = c4.ElementViewRuleStyle | c4.ViewRuleGlobalStyle;
7
7
  export declare function ViewsParser<TBase extends WithPredicates & WithDeploymentView>(B: TBase): {
8
8
  new (...args: any[]): {
9
9
  parseViews(): void;
10
- parseElementView(astNode: ast.ElementView, additionalStyles: c4.ViewRuleStyleOrGlobalRef[]): ParsedAstElementView;
11
- parseViewRule(astRule: ast.ViewRule): c4.ViewRule;
12
- parseViewRulePredicate(astNode: ast.ViewRulePredicate): c4.ViewRulePredicate;
10
+ parseElementView(astNode: ast.ElementView, additionalStyles: ViewRuleStyleOrGlobalRef[]): ParsedAstElementView;
11
+ parseElementViewRule(astRule: ast.ViewRule): c4.ElementViewRule;
12
+ parseViewRulePredicate(astNode: ast.ViewRulePredicate): c4.ElementViewPredicate;
13
13
  parseViewRuleGlobalPredicateRef(astRule: ast.ViewRuleGlobalPredicateRef | ast.DynamicViewGlobalPredicateRef): c4.ViewRuleGlobalPredicateRef;
14
- parseViewRuleStyleOrGlobalRef(astRule: ast.ViewRuleStyleOrGlobalRef): c4.ViewRuleStyleOrGlobalRef;
15
- parseViewRuleGroup(astNode: ast.ViewRuleGroup): c4.ViewRuleGroup;
16
- parseViewRuleStyle(astRule: ast.ViewRuleStyle | ast.GlobalStyle): c4.ViewRuleStyle;
17
- parseRuleStyle(styleProperties: ast.StyleProperty[], elementExpressionsIterator: ast.FqnExpressions, notationProperty?: NotationProperty): c4.ViewRuleStyle;
14
+ parseViewRuleStyleOrGlobalRef(astRule: ast.ViewRuleStyleOrGlobalRef): ViewRuleStyleOrGlobalRef;
15
+ parseViewRuleGroup(astNode: ast.ViewRuleGroup): c4.ElementViewRuleGroup;
16
+ parseViewRuleStyle(astRule: ast.ViewRuleStyle | ast.GlobalStyle): c4.ElementViewRuleStyle;
18
17
  parseViewRuleGlobalStyle(astRule: ast.ViewRuleGlobalStyle): c4.ViewRuleGlobalStyle;
19
- parseDynamicElementView(astNode: ast.DynamicView, additionalStyles: c4.ViewRuleStyleOrGlobalRef[]): ParsedAstDynamicView;
18
+ parseDynamicElementView(astNode: ast.DynamicView, additionalStyles: ViewRuleStyleOrGlobalRef[]): ParsedAstDynamicView;
20
19
  parseDynamicViewRule(astRule: ast.DynamicViewRule): c4.DynamicViewRule;
21
20
  parseDynamicViewIncludePredicate(astRule: ast.DynamicViewIncludePredicate): c4.DynamicViewIncludeRule;
22
21
  parseDynamicParallelSteps(node: ast.DynamicViewParallelSteps): c4.DynamicViewParallelSteps;
23
22
  parseDynamicStep(node: ast.DynamicViewStep): c4.DynamicViewStep;
24
- parsePredicate(astNode: ast.ExpressionV2): c4.ModelLayer.Expression;
25
- parseElementPredicate(astNode: ast.FqnExprOrWith): c4.ModelLayer.AnyFqnExpr;
26
- parseElementPredicateOrWhere(astNode: ast.FqnExprOrWhere): c4.ModelLayer.FqnExprOrWhere;
27
- parseElementExpression(astNode: ast.FqnExpr): c4.ModelLayer.FqnExpr;
28
- parseElementPredicateWhere(astNode: ast.FqnExprWhere): c4.ModelLayer.FqnExpr.Where;
29
- parseElementPredicateWith(astNode: ast.FqnExprWith): c4.ModelLayer.FqnExpr.Custom;
30
- parseRelationPredicate(astNode: ast.RelationExprOrWith): c4.ModelLayer.AnyRelationExpr;
31
- parseRelationPredicateOrWhere(astNode: ast.RelationExprOrWhere): c4.ModelLayer.RelationExprOrWhere;
32
- parseRelationPredicateWhere(astNode: ast.RelationExprWhere): c4.ModelLayer.RelationExpr.Where;
33
- parseRelationPredicateWith(astNode: ast.RelationExprWith): c4.ModelLayer.RelationExpr.Custom;
34
- parseRelationExpression(astNode: ast.RelationExpr): c4.ModelLayer.RelationExpr;
23
+ parsePredicate(astNode: ast.ExpressionV2): c4.ModelExpression;
24
+ parseElementPredicate(astNode: ast.FqnExprOrWith): c4.ModelFqnExpr.Any;
25
+ parseElementPredicateOrWhere(astNode: ast.FqnExprOrWhere): c4.ModelFqnExpr.OrWhere;
26
+ parseElementExpression(astNode: ast.FqnExpr): c4.ModelFqnExpr;
27
+ parseElementPredicateWhere(astNode: ast.FqnExprWhere): c4.ModelFqnExpr.Where;
28
+ parseElementPredicateWith(astNode: ast.FqnExprWith): c4.ModelFqnExpr.Custom;
29
+ parseRelationPredicate(astNode: ast.RelationExprOrWith): c4.ModelRelationExpr.Any;
30
+ parseRelationPredicateOrWhere(astNode: ast.RelationExprOrWhere): c4.ModelRelationExpr.OrWhere;
31
+ parseRelationPredicateWhere(astNode: ast.RelationExprWhere): c4.ModelRelationExpr.Where;
32
+ parseRelationPredicateWith(astNode: ast.RelationExprWith): c4.ModelRelationExpr.Custom;
33
+ parseRelationExpression(astNode: ast.RelationExpr): c4.ModelRelationExpr;
35
34
  parseFqnRef(astNode: ast.FqnRef): c4.FqnRef;
36
- parseExpressionV2(astNode: ast.ExpressionV2): c4.ExpressionV2;
35
+ parseExpressionV2(astNode: ast.ExpressionV2): c4.Expression;
37
36
  parseFqnExprOrWith(astNode: ast.FqnExprOrWith): c4.FqnExpr.Any;
38
37
  parseFqnExprWith(astNode: ast.FqnExprWith): c4.FqnExpr.Custom;
39
38
  parseFqnExprOrWhere(astNode: ast.FqnExprOrWhere): c4.FqnExpr.OrWhere;
@@ -68,11 +67,12 @@ export declare function ViewsParser<TBase extends WithPredicates & WithDeploymen
68
67
  convertLinks(source?: ast.LinkProperty["$container"]): c4.Link[] | undefined;
69
68
  parseLinks(source?: ast.LinkProperty["$container"]): c4.Link[] | undefined;
70
69
  parseIconProperty(prop: ast.IconProperty | undefined): c4.IconUrl | undefined;
70
+ parseColorLiteral(astNode: ast.ColorLiteral): c4.ColorLiteral | undefined;
71
71
  parseElementStyle(elementProps: Array<ast.ElementProperty> | ast.ElementStyleProperty | undefined): import("../../ast").ParsedElementStyle;
72
72
  parseStyleProps(styleProps: Array<ast.StyleProperty> | undefined): import("../../ast").ParsedElementStyle;
73
73
  parseDeploymentView(astNode: ast.DeploymentView): import("../../ast").ParsedAstDeploymentView;
74
74
  parseDeploymentViewRule(astRule: ast.DeploymentViewRule): c4.DeploymentViewRule;
75
- parseDeploymentViewRulePredicate(astRule: ast.DeploymentViewRulePredicate): c4.DeploymentViewRulePredicate;
75
+ parseDeploymentViewRulePredicate(astRule: ast.DeploymentViewRulePredicate): c4.DeploymentViewPredicate;
76
76
  parseDeploymentViewRuleStyle(astRule: ast.DeploymentViewRuleStyle): c4.DeploymentViewRuleStyle;
77
77
  parseDeployment(): void;
78
78
  parseDeploymentNode(astNode: ast.DeploymentNode): import("../../ast").ParsedAstDeployment.Node;
@@ -82,3 +82,4 @@ export declare function ViewsParser<TBase extends WithPredicates & WithDeploymen
82
82
  parseDeploymentRelation(astNode: ast.DeploymentRelation): import("../../ast").ParsedAstDeploymentRelation;
83
83
  };
84
84
  } & TBase;
85
+ export {};
@@ -1,4 +1,5 @@
1
- import { invariant, isNonEmptyArray, ModelLayer, nonexhaustive } from "@likec4/core";
1
+ import * as c4 from "@likec4/core";
2
+ import { invariant, isNonEmptyArray, nonexhaustive } from "@likec4/core";
2
3
  import { isArray, isDefined, isNonNullish, isTruthy } from "remeda";
3
4
  import {
4
5
  ast,
@@ -76,7 +77,7 @@ export function ViewsParser(B) {
76
77
  const links = this.convertLinks(body);
77
78
  const manualLayout = parseViewManualLayout(astNode);
78
79
  const view = {
79
- __: "element",
80
+ [c4._type]: "element",
80
81
  id,
81
82
  astPath,
82
83
  title,
@@ -87,7 +88,7 @@ export function ViewsParser(B) {
87
88
  ...additionalStyles,
88
89
  ...body.rules.flatMap((n) => {
89
90
  try {
90
- return this.isValid(n) ? this.parseViewRule(n) : [];
91
+ return this.isValid(n) ? this.parseElementViewRule(n) : [];
91
92
  } catch (e) {
92
93
  logWarnError(e);
93
94
  return [];
@@ -107,7 +108,7 @@ export function ViewsParser(B) {
107
108
  }
108
109
  return view;
109
110
  }
110
- parseViewRule(astRule) {
111
+ parseElementViewRule(astRule) {
111
112
  if (ast.isViewRulePredicate(astRule)) {
112
113
  return this.parseViewRulePredicate(astRule);
113
114
  }
@@ -186,23 +187,15 @@ export function ViewsParser(B) {
186
187
  };
187
188
  }
188
189
  parseViewRuleStyle(astRule) {
189
- const styleProps = astRule.props.filter(ast.isStyleProperty);
190
- const targets = astRule.targets;
191
- const notation = astRule.props.find(ast.isNotationProperty);
192
- return this.parseRuleStyle(styleProps, targets, notation);
193
- }
194
- parseRuleStyle(styleProperties, elementExpressionsIterator, notationProperty) {
195
- const styleProps = this.parseStyleProps(styleProperties);
196
- const notation = removeIndent(notationProperty?.value);
197
- const targets = this.parseFqnExpressions(elementExpressionsIterator).filter(
198
- (e) => ModelLayer.Expression.isFqnExpr(e)
190
+ const targets = this.parseFqnExpressions(astRule.targets).filter(
191
+ (e) => c4.ModelExpression.isFqnExpr(e)
199
192
  );
193
+ const style = this.parseStyleProps(astRule.props.filter(ast.isStyleProperty));
194
+ const notation = removeIndent(astRule.props.find(ast.isNotationProperty)?.value);
200
195
  return {
201
196
  targets,
202
- ...notation && { notation },
203
- style: {
204
- ...styleProps
205
- }
197
+ style,
198
+ ...notation && { notation }
206
199
  };
207
200
  }
208
201
  parseViewRuleGlobalStyle(astRule) {
@@ -230,7 +223,7 @@ export function ViewsParser(B) {
230
223
  ViewOps.writeId(astNode, id);
231
224
  const manualLayout = parseViewManualLayout(astNode);
232
225
  return {
233
- __: "dynamic",
226
+ [c4._type]: "dynamic",
234
227
  id,
235
228
  astPath,
236
229
  title,
@@ -1,4 +1,4 @@
1
- import { type Fqn, type NonEmptyArray, type ViewChange } from '@likec4/core';
1
+ import { type DeploymentFqn, type Fqn, type NonEmptyArray, type ViewChange } from '@likec4/core';
2
2
  import { type Range, TextEdit } from 'vscode-languageserver-types';
3
3
  import { type ParsedAstView, type ParsedLikeC4LangiumDocument, ast } from '../ast';
4
4
  import type { LikeC4Services } from '../module';
@@ -6,7 +6,7 @@ type ChangeElementStyleArg = {
6
6
  view: ParsedAstView;
7
7
  doc: ParsedLikeC4LangiumDocument;
8
8
  viewAst: ast.LikeC4View;
9
- targets: NonEmptyArray<Fqn>;
9
+ targets: NonEmptyArray<Fqn | DeploymentFqn>;
10
10
  style: ViewChange.ChangeElementStyle['style'];
11
11
  };
12
12
  export declare function changeElementStyle(services: LikeC4Services, { view, viewAst, targets, style, }: ChangeElementStyleArg): {
@@ -1,4 +1,8 @@
1
- import { invariant, isAncestor } from "@likec4/core";
1
+ import {
2
+ _type,
3
+ invariant,
4
+ isAncestor
5
+ } from "@likec4/core";
2
6
  import { GrammarUtils } from "langium";
3
7
  import { entries, filter, findLast, isTruthy, last } from "remeda";
4
8
  import { TextEdit } from "vscode-languageserver-types";
@@ -43,7 +47,7 @@ export function changeElementStyle(services, {
43
47
  viewAst.body.rules,
44
48
  (r) => ast.isViewRuleStyle(r) || ast.isDeploymentViewRuleStyle(r)
45
49
  );
46
- const viewOf = view.__ === "element" ? view.viewOf : null;
50
+ const viewOf = view[_type] === "element" ? view.viewOf ?? null : null;
47
51
  const existing = [];
48
52
  const insert = [];
49
53
  targets.forEach((target) => {
package/dist/module.d.ts CHANGED
@@ -4,7 +4,7 @@ import { type DefaultSharedModuleContext, type LangiumServices, type LangiumShar
4
4
  import { LikeC4DocumentationProvider } from './documentation';
5
5
  import { type LikeC4LanguageServices } from './LikeC4LanguageServices';
6
6
  import { LikeC4CodeLensProvider, LikeC4CompletionProvider, LikeC4DocumentHighlightProvider, LikeC4DocumentLinkProvider, LikeC4DocumentSymbolProvider, LikeC4HoverProvider, LikeC4SemanticTokenProvider } from './lsp';
7
- import { type LikeC4MCPServer, LikeC4MCPServerFactory } from './mcp/LikeC4MCPServerFactory';
7
+ import { type LikeC4MCPServer, type LikeC4MCPServerFactory } from './mcp/LikeC4MCPServerFactory';
8
8
  import { type LikeC4MCPTools } from './mcp/LikeC4MCPTools';
9
9
  import { type LikeC4ModelBuilder, DeploymentsIndex, FqnIndex, LikeC4ModelLocator, LikeC4ModelParser } from './model';
10
10
  import { LikeC4ModelChanges } from './model-change/ModelChanges';
package/dist/module.js CHANGED
@@ -26,7 +26,10 @@ import {
26
26
  LikeC4HoverProvider,
27
27
  LikeC4SemanticTokenProvider
28
28
  } from "./lsp/index.js";
29
- import { LikeC4MCPServerFactory, NoopLikeC4MCPServer } from "./mcp/LikeC4MCPServerFactory.js";
29
+ import {
30
+ NoopLikeC4MCPServer,
31
+ NoopLikeC4MCPServerFactory
32
+ } from "./mcp/LikeC4MCPServerFactory.js";
30
33
  import { DefaultLikeC4MCPTools } from "./mcp/LikeC4MCPTools.js";
31
34
  import {
32
35
  DefaultLikeC4ModelBuilder,
@@ -79,7 +82,7 @@ export const LikeC4Module = {
79
82
  mcp: {
80
83
  Tools: bind(DefaultLikeC4MCPTools),
81
84
  Server: bind(NoopLikeC4MCPServer),
82
- ServerFactory: bind(LikeC4MCPServerFactory)
85
+ ServerFactory: bind(NoopLikeC4MCPServerFactory)
83
86
  },
84
87
  likec4: {
85
88
  LanguageServices: bind(DefaultLikeC4LanguageServices),
@@ -1,6 +1,6 @@
1
- import type { ComputedLikeC4ModelData, ComputedView, DiagramView, Fqn, LayoutedLikeC4ModelData, NonEmptyArray, ProjectId, RelationId, ViewChange, ViewId } from '@likec4/core';
1
+ import type { ComputedLikeC4ModelData, ComputedView, DeploymentFqn, DiagramView, Fqn, LayoutedLikeC4ModelData, NonEmptyArray, ProjectId, RelationId, ViewChange, ViewId } from '@likec4/core';
2
2
  import { NotificationType, RequestType, RequestType0 } from 'vscode-jsonrpc';
3
- import type { DiagnosticSeverity, DocumentUri, Location, Position } from 'vscode-languageserver-types';
3
+ import type { DiagnosticSeverity, DocumentUri, Location, Position, Range } from 'vscode-languageserver-types';
4
4
  export declare namespace DidChangeModelNotification {
5
5
  const type: NotificationType<string>;
6
6
  type Type = typeof type;
@@ -143,7 +143,7 @@ export declare namespace Locate {
143
143
  projectId?: string | undefined;
144
144
  relation: RelationId;
145
145
  } | {
146
- deployment: Fqn;
146
+ deployment: DeploymentFqn;
147
147
  projectId?: string | undefined;
148
148
  property?: string;
149
149
  } | {
@@ -186,3 +186,24 @@ export declare namespace FetchTelemetryMetrics {
186
186
  const req: RequestType0<Res, void>;
187
187
  type Req = typeof req;
188
188
  }
189
+ /**
190
+ * Request to fetch all tags of a document
191
+ */
192
+ export declare namespace GetDocumentTags {
193
+ type Params = {
194
+ documentUri: DocumentUri;
195
+ };
196
+ type Res = {
197
+ /**
198
+ * Used tags in the document
199
+ */
200
+ tags: Array<{
201
+ name: string;
202
+ range: Range;
203
+ color: string;
204
+ isSpecification?: boolean;
205
+ }>;
206
+ };
207
+ const req: RequestType<Params, Res, void>;
208
+ type Req = typeof req;
209
+ }
package/dist/protocol.js CHANGED
@@ -47,3 +47,7 @@ export var FetchTelemetryMetrics;
47
47
  ((FetchTelemetryMetrics2) => {
48
48
  FetchTelemetryMetrics2.req = new RequestType0("likec4/metrics");
49
49
  })(FetchTelemetryMetrics || (FetchTelemetryMetrics = {}));
50
+ export var GetDocumentTags;
51
+ ((GetDocumentTags2) => {
52
+ GetDocumentTags2.req = new RequestType("likec4/document-tags");
53
+ })(GetDocumentTags || (GetDocumentTags = {}));
@@ -132,7 +132,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
132
132
  case ast.isSpecificationTag(spec): {
133
133
  if (isTruthy(spec.tag.name)) {
134
134
  docExports.push(
135
- this.descriptions.createDescription(spec.tag, "#" + spec.tag.name, document)
135
+ this.descriptions.createDescription(spec.tag, spec.tag.name, document)
136
136
  );
137
137
  }
138
138
  continue;
@@ -140,8 +140,7 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
140
140
  case ast.isSpecificationRelationshipKind(spec): {
141
141
  if (isTruthy(spec.kind.name)) {
142
142
  docExports.push(
143
- this.descriptions.createDescription(spec.kind, spec.kind.name, document),
144
- this.descriptions.createDescription(spec.kind, "." + spec.kind.name, document)
143
+ this.descriptions.createDescription(spec.kind, spec.kind.name, document)
145
144
  );
146
145
  }
147
146
  continue;
@@ -1,3 +1,4 @@
1
+ import type { ComputedLikeC4ModelData } from '@likec4/core';
1
2
  import type { LikeC4LangiumDocument } from '../ast';
2
3
  export declare function createTestServices(workspace?: string): {
3
4
  services: any;
@@ -19,6 +20,20 @@ export declare function createTestServices(workspace?: string): {
19
20
  resetState: () => Promise<void>;
20
21
  format: (input: string | LikeC4LangiumDocument, uri?: string) => Promise<any>;
21
22
  };
23
+ /**
24
+ * @example
25
+ * ```ts
26
+ * const { projects } = await createMultiProjectTestServices({
27
+ * project1: {
28
+ * doc1: `...`,
29
+ * doc2: `...`,
30
+ * },
31
+ * project2: {
32
+ * doc1: `...`,
33
+ * },
34
+ * })
35
+ * ```
36
+ */
22
37
  export declare function createMultiProjectTestServices<const Projects extends Record<string, Record<string, string>>>(data: Projects): Promise<{
23
38
  services: any;
24
39
  projects: { readonly [K in keyof Projects]: { readonly [L in keyof Projects[K]]: LikeC4LangiumDocument; }; };
@@ -104,7 +104,7 @@ export function createTestServices(workspace = "file:///test/workspace") {
104
104
  }
105
105
  const likec4model = await modelBuilder.buildLikeC4Model();
106
106
  if (!likec4model) throw new Error("No model found");
107
- return likec4model.$model;
107
+ return likec4model.$data;
108
108
  };
109
109
  const buildLikeC4Model = async () => {
110
110
  if (langiumDocuments.all.some((doc) => doc.state < DocumentState.Validated)) {
@@ -3,7 +3,7 @@ import { type LikeC4LangiumDocument, ast } from '../ast';
3
3
  import type { LikeC4Services } from '../module';
4
4
  type Guard<N extends AstNode> = (n: AstNode) => n is N;
5
5
  type Guarded<G> = G extends Guard<infer N> ? N : never;
6
- declare const isValidatableAstNode: (n: AstNode) => n is ast.DeployedInstance | ast.DeploymentNode | ast.DeploymentViewRulePredicate | ast.DeploymentViewRuleStyle | ast.ViewRuleAutoLayout | ast.DynamicViewGlobalPredicateRef | ast.DynamicViewIncludePredicate | ast.ViewRuleGlobalStyle | ast.ViewRuleStyle | ast.ElementStringProperty | ast.ElementStyleProperty | ast.IconProperty | ast.LinkProperty | ast.MetadataBody | ast.ElementKindExpression | ast.ElementTagExpression | ast.FqnRefExpr | ast.WildcardExpression | ast.FqnExprWhere | ast.FqnExprWith | ast.DirectedRelationExpr | ast.InOutRelationExpr | ast.IncomingRelationExpr | ast.OutgoingRelationExpr | ast.RelationExprWhere | ast.RelationExprWith | ast.Element | ast.ExtendDeployment | ast.ExtendElement | ast.Imported | ast.DeploymentView | ast.DynamicView | ast.ElementView | ast.RelationStringProperty | ast.ArrowProperty | ast.ColorProperty | ast.LineProperty | ast.PaddingSizeProperty | ast.ShapeSizeProperty | ast.TextSizeProperty | ast.MetadataAttribute | ast.NotationProperty | ast.NotesProperty | ast.SpecificationElementStringProperty | ast.SpecificationRelationshipStringProperty | ast.ViewStringProperty | ast.BorderProperty | ast.MultipleProperty | ast.OpacityProperty | ast.ShapeProperty | ast.ViewRuleGlobalPredicateRef | ast.ViewRuleGroup | ast.ViewRulePredicate | ast.SpecificationRelationshipKind | ast.GlobalStyle | ast.SpecificationColor | ast.NavigateToProperty | ast.DynamicViewStep | ast.ElementRef | ast.DeploymentRelation | ast.Tags | ast.SpecificationDeploymentNodeKind | ast.DynamicViewParallelSteps | ast.GlobalDynamicPredicateGroup | ast.Relation | ast.SpecificationElementKind | ast.Globals | ast.GlobalPredicateGroup | ast.GlobalStyleGroup | ast.ImportsFromPoject | ast.SpecificationRule | ast.SpecificationTag;
6
+ declare const isValidatableAstNode: (n: AstNode) => n is ast.HexColor | ast.RGBAColor | ast.DeployedInstance | ast.DeploymentNode | ast.DeploymentViewRulePredicate | ast.DeploymentViewRuleStyle | ast.ViewRuleAutoLayout | ast.DynamicViewGlobalPredicateRef | ast.DynamicViewIncludePredicate | ast.ViewRuleGlobalStyle | ast.ViewRuleStyle | ast.ElementStringProperty | ast.ElementStyleProperty | ast.IconProperty | ast.LinkProperty | ast.MetadataBody | ast.ElementKindExpression | ast.ElementTagExpression | ast.FqnRefExpr | ast.WildcardExpression | ast.FqnExprWhere | ast.FqnExprWith | ast.DirectedRelationExpr | ast.InOutRelationExpr | ast.IncomingRelationExpr | ast.OutgoingRelationExpr | ast.RelationExprWhere | ast.RelationExprWith | ast.Element | ast.ExtendDeployment | ast.ExtendElement | ast.Imported | ast.DeploymentView | ast.DynamicView | ast.ElementView | ast.RelationStringProperty | ast.ArrowProperty | ast.ColorProperty | ast.LineProperty | ast.PaddingSizeProperty | ast.ShapeSizeProperty | ast.TextSizeProperty | ast.MetadataAttribute | ast.NotationProperty | ast.NotesProperty | ast.SpecificationElementStringProperty | ast.SpecificationRelationshipStringProperty | ast.ViewStringProperty | ast.BorderProperty | ast.MultipleProperty | ast.OpacityProperty | ast.ShapeProperty | ast.ViewRuleGlobalPredicateRef | ast.ViewRuleGroup | ast.ViewRulePredicate | ast.SpecificationRelationshipKind | ast.GlobalStyle | ast.SpecificationColor | ast.NavigateToProperty | ast.DynamicViewStep | ast.ElementRef | ast.DeploymentRelation | ast.Tags | ast.SpecificationDeploymentNodeKind | ast.DynamicViewParallelSteps | ast.GlobalDynamicPredicateGroup | ast.Relation | ast.SpecificationElementKind | ast.Globals | ast.GlobalPredicateGroup | ast.GlobalStyleGroup | ast.SpecificationTag | ast.ImportsFromPoject | ast.SpecificationRule;
7
7
  type ValidatableAstNode = Guarded<typeof isValidatableAstNode>;
8
8
  export declare function checksFromDiagnostics(doc: LikeC4LangiumDocument): {
9
9
  isValid: (n: ValidatableAstNode) => boolean;
@@ -13,7 +13,12 @@ import { dynamicViewStep } from "./dynamic-view-step.js";
13
13
  import { checkElement } from "./element.js";
14
14
  import { checkElementRef } from "./element-ref.js";
15
15
  import { checkImported, checkImportsFromPoject } from "./imports.js";
16
- import { iconPropertyRuleChecks, notesPropertyRuleChecks, opacityPropertyRuleChecks } from "./property-checks.js";
16
+ import {
17
+ colorLiteralRuleChecks,
18
+ iconPropertyRuleChecks,
19
+ notesPropertyRuleChecks,
20
+ opacityPropertyRuleChecks
21
+ } from "./property-checks.js";
17
22
  import { checkRelationBody, relationChecks } from "./relation.js";
18
23
  import {
19
24
  checkDeploymentNodeKind,
@@ -82,7 +87,8 @@ const isValidatableAstNode = validatableAstNodeGuards([
82
87
  ast.isSpecificationDeploymentNodeKind,
83
88
  ast.isSpecificationTag,
84
89
  ast.isSpecificationColor,
85
- ast.isSpecificationRule
90
+ ast.isSpecificationRule,
91
+ ast.isColorLiteral
86
92
  ]);
87
93
  const findInvalidContainer = (node) => {
88
94
  let nd = node;
@@ -147,7 +153,8 @@ export function registerValidationChecks(services) {
147
153
  IncomingRelationExpr: checkIncomingRelationExpr(services),
148
154
  OutgoingRelationExpr: checkOutgoingRelationExpr(services),
149
155
  ImportsFromPoject: checkImportsFromPoject(services),
150
- Imported: checkImported(services)
156
+ Imported: checkImported(services),
157
+ ColorLiteral: colorLiteralRuleChecks(services)
151
158
  });
152
159
  const connection = services.shared.lsp.Connection;
153
160
  if (connection) {
@@ -4,3 +4,4 @@ import type { LikeC4Services } from '../module';
4
4
  export declare const opacityPropertyRuleChecks: (_: LikeC4Services) => ValidationCheck<ast.OpacityProperty>;
5
5
  export declare const iconPropertyRuleChecks: (_: LikeC4Services) => ValidationCheck<ast.IconProperty>;
6
6
  export declare const notesPropertyRuleChecks: (_: LikeC4Services) => ValidationCheck<ast.NotesProperty>;
7
+ export declare const colorLiteralRuleChecks: (_: LikeC4Services) => ValidationCheck<ast.ColorLiteral>;
@@ -1,4 +1,6 @@
1
+ import { nonexhaustive } from "@likec4/core";
1
2
  import { AstUtils } from "langium";
3
+ import { isNumber, isString } from "remeda";
2
4
  import { ast } from "../ast.js";
3
5
  import { tryOrLog } from "./_shared.js";
4
6
  export const opacityPropertyRuleChecks = (_) => {
@@ -43,3 +45,63 @@ export const notesPropertyRuleChecks = (_) => {
43
45
  }
44
46
  };
45
47
  };
48
+ export const colorLiteralRuleChecks = (_) => {
49
+ return (node, accept) => {
50
+ if (node.$type === "HexColor") {
51
+ if (node.hex === void 0) {
52
+ accept("error", `Invalid HEX`, {
53
+ node,
54
+ property: "hex"
55
+ });
56
+ return;
57
+ }
58
+ const length = isNumber(node.hex) ? node.hex.toString().length : node.hex.length;
59
+ if (length !== 6 && length !== 3 && length !== 8) {
60
+ accept("error", `Invalid value "${node.$cstNode?.text}", must be 3, 6 or 8 characters long`, {
61
+ node,
62
+ property: "hex"
63
+ });
64
+ }
65
+ return;
66
+ }
67
+ if (node.$type === "RGBAColor") {
68
+ if (!isNumber(node.red) || node.red < 0 || node.red > 255) {
69
+ accept("error", `Invalid value, must be between 0 and 255`, {
70
+ node,
71
+ property: "red"
72
+ });
73
+ }
74
+ if (!isNumber(node.green) || node.green < 0 || node.green > 255) {
75
+ accept("error", `Invalid value, must be between 0 and 255`, {
76
+ node,
77
+ property: "green"
78
+ });
79
+ }
80
+ if (!isNumber(node.blue) || node.blue < 0 || node.blue > 255) {
81
+ accept("error", `Invalid value, must be between 0 and 255`, {
82
+ node,
83
+ property: "blue"
84
+ });
85
+ }
86
+ if (isNumber(node.alpha)) {
87
+ if (node.alpha < 0 || node.alpha > 1) {
88
+ accept("error", `Invalid value, must be between 0 and 1`, {
89
+ node,
90
+ property: "alpha"
91
+ });
92
+ }
93
+ }
94
+ if (isString(node.alpha)) {
95
+ const alpha = parseFloat(node.alpha);
96
+ if (alpha < 0 || alpha > 100) {
97
+ accept("error", `Invalid value, must be between 0% and 100%`, {
98
+ node,
99
+ property: "alpha"
100
+ });
101
+ }
102
+ }
103
+ return;
104
+ }
105
+ nonexhaustive(node);
106
+ };
107
+ };
@@ -34,7 +34,7 @@ export const relationChecks = (services) => {
34
34
  });
35
35
  }
36
36
  }
37
- if (isSameHierarchy(FqnRef.toModelFqn(source), FqnRef.toModelFqn(target))) {
37
+ if (isSameHierarchy(FqnRef.flatten(source), FqnRef.flatten(target))) {
38
38
  accept("error", "Invalid parent-child relationship", {
39
39
  node: el
40
40
  });
@@ -97,7 +97,7 @@ export const checkDeploymentNodeKind = (services) => {
97
97
  export const checkTag = (services) => {
98
98
  const index = services.shared.workspace.IndexManager;
99
99
  return tryOrLog((node, accept) => {
100
- const tagname = "#" + node.name;
100
+ const tagname = node.name;
101
101
  const projectId = projectIdFrom(node);
102
102
  const sameTag = index.projectElements(projectId, ast.Tag).filter((n) => n.name === tagname && n.node !== node).head();
103
103
  if (sameTag) {
@@ -1,2 +1,2 @@
1
- import { ComputedView } from '@likec4/core';
1
+ import { type ComputedView } from '@likec4/core';
2
2
  export declare function assignNavigateTo<R extends Iterable<ComputedView>>(views: R): R;
@@ -1,9 +1,9 @@
1
- import { ComputedNode, ComputedView } from "@likec4/core";
1
+ import { isElementView } from "@likec4/core";
2
2
  import { find, isNullish } from "remeda";
3
3
  export function assignNavigateTo(views) {
4
4
  const allElementViews = /* @__PURE__ */ new Map();
5
5
  for (const v of views) {
6
- if (ComputedView.isElement(v) && v.viewOf && isNullish(v.extends)) {
6
+ if (isElementView(v) && v.viewOf && isNullish(v.extends)) {
7
7
  const viewsOf = allElementViews.get(v.viewOf) ?? [];
8
8
  viewsOf.push(v.id);
9
9
  allElementViews.set(v.viewOf, viewsOf);
@@ -11,7 +11,7 @@ export function assignNavigateTo(views) {
11
11
  }
12
12
  for (const { id, nodes } of views) {
13
13
  for (const node of nodes) {
14
- const modelRef = ComputedNode.modelRef(node);
14
+ const modelRef = node.modelRef;
15
15
  if (node.navigateTo || !modelRef) {
16
16
  continue;
17
17
  }
@@ -1,4 +1,4 @@
1
- import type { ComputedView, DiagramView, OverviewGraph, ProjectId, ViewId } from '@likec4/core';
1
+ import type { ComputedView, DiagramView, ProjectId, ViewId } from '@likec4/core';
2
2
  import { GraphvizLayouter } from '@likec4/layouts';
3
3
  import { CancellationToken } from 'vscode-jsonrpc';
4
4
  import type { LikeC4Services } from '../module';
@@ -18,7 +18,6 @@ export interface LikeC4Views {
18
18
  layoutView(viewId: ViewId, projectId?: ProjectId | undefined, cancelToken?: CancellationToken): Promise<GraphvizOut | null>;
19
19
  diagrams(projectId?: ProjectId | undefined, cancelToken?: CancellationToken): Promise<Array<DiagramView>>;
20
20
  viewsAsGraphvizOut(projectId?: ProjectId | undefined, cancelToken?: CancellationToken): Promise<Array<GraphvizSvgOut>>;
21
- overviewGraph(): Promise<OverviewGraph>;
22
21
  }
23
22
  export declare class DefaultLikeC4Views implements LikeC4Views {
24
23
  private services;
@@ -33,6 +32,5 @@ export declare class DefaultLikeC4Views implements LikeC4Views {
33
32
  layoutView(viewId: ViewId, projectId?: ProjectId | undefined, cancelToken?: CancellationToken): Promise<GraphvizOut | null>;
34
33
  diagrams(projectId?: ProjectId | undefined, cancelToken?: CancellationToken): Promise<Array<DiagramView>>;
35
34
  viewsAsGraphvizOut(projectId?: ProjectId | undefined, cancelToken?: CancellationToken): Promise<Array<GraphvizSvgOut>>;
36
- overviewGraph(): Promise<OverviewGraph>;
37
35
  }
38
36
  export {};