@likec4/language-server 1.27.3 → 1.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/dist/LikeC4LanguageServices.js +6 -7
  2. package/dist/ast.d.ts +16 -9
  3. package/dist/ast.js +58 -79
  4. package/dist/bundled.mjs +2130 -2127
  5. package/dist/config/schema.d.ts +3 -3
  6. package/dist/config/schema.js +12 -5
  7. package/dist/documentation/documentation-provider.js +3 -1
  8. package/dist/formatting/LikeC4Formatter.d.ts +0 -2
  9. package/dist/formatting/LikeC4Formatter.js +24 -53
  10. package/dist/generated/ast.d.ts +128 -233
  11. package/dist/generated/ast.js +134 -306
  12. package/dist/generated/grammar.js +1 -1
  13. package/dist/lsp/CompletionProvider.d.ts +3 -0
  14. package/dist/lsp/CompletionProvider.js +128 -113
  15. package/dist/lsp/DocumentLinkProvider.js +6 -3
  16. package/dist/lsp/HoverProvider.js +3 -1
  17. package/dist/lsp/SemanticTokenProvider.js +33 -43
  18. package/dist/model/builder/MergedSpecification.d.ts +5 -3
  19. package/dist/model/builder/MergedSpecification.js +21 -7
  20. package/dist/model/builder/buildModel.d.ts +6 -1
  21. package/dist/model/builder/buildModel.js +20 -15
  22. package/dist/model/deployments-index.js +4 -2
  23. package/dist/model/fqn-index.d.ts +4 -2
  24. package/dist/model/fqn-index.js +28 -5
  25. package/dist/model/model-builder.d.ts +2 -2
  26. package/dist/model/model-builder.js +54 -16
  27. package/dist/model/model-locator.js +7 -4
  28. package/dist/model/model-parser.d.ts +215 -52
  29. package/dist/model/model-parser.js +6 -2
  30. package/dist/model/parser/Base.d.ts +11 -2
  31. package/dist/model/parser/Base.js +138 -3
  32. package/dist/model/parser/DeploymentModelParser.d.ts +19 -2
  33. package/dist/model/parser/DeploymentModelParser.js +19 -29
  34. package/dist/model/parser/DeploymentViewParser.d.ts +18 -2
  35. package/dist/model/parser/DeploymentViewParser.js +6 -24
  36. package/dist/model/parser/FqnRefParser.d.ts +18 -3
  37. package/dist/model/parser/FqnRefParser.js +264 -40
  38. package/dist/model/parser/GlobalsParser.d.ts +35 -18
  39. package/dist/model/parser/ImportsParser.d.ts +32 -0
  40. package/dist/model/parser/ImportsParser.js +26 -0
  41. package/dist/model/parser/ModelParser.d.ts +26 -2
  42. package/dist/model/parser/ModelParser.js +21 -41
  43. package/dist/model/parser/PredicatesParser.d.ts +35 -12
  44. package/dist/model/parser/PredicatesParser.js +20 -271
  45. package/dist/model/parser/SpecificationParser.d.ts +8 -0
  46. package/dist/model/parser/SpecificationParser.js +5 -9
  47. package/dist/model/parser/ViewsParser.d.ts +36 -19
  48. package/dist/model/parser/ViewsParser.js +15 -11
  49. package/dist/model-change/changeElementStyle.d.ts +2 -2
  50. package/dist/model-change/changeElementStyle.js +2 -1
  51. package/dist/references/name-provider.js +8 -2
  52. package/dist/references/scope-computation.d.ts +1 -1
  53. package/dist/references/scope-computation.js +33 -3
  54. package/dist/references/scope-provider.d.ts +7 -8
  55. package/dist/references/scope-provider.js +59 -41
  56. package/dist/shared/NodeKindProvider.js +4 -2
  57. package/dist/test/testServices.d.ts +2 -0
  58. package/dist/test/testServices.js +4 -1
  59. package/dist/utils/elementRef.d.ts +1 -1
  60. package/dist/utils/elementRef.js +6 -1
  61. package/dist/utils/fqnRef.d.ts +3 -0
  62. package/dist/utils/fqnRef.js +15 -4
  63. package/dist/utils/index.d.ts +1 -0
  64. package/dist/utils/index.js +9 -0
  65. package/dist/utils/projectId.d.ts +2 -1
  66. package/dist/utils/projectId.js +11 -1
  67. package/dist/validation/_shared.js +2 -2
  68. package/dist/validation/deployment-checks.js +24 -10
  69. package/dist/validation/element-ref.d.ts +4 -0
  70. package/dist/validation/element-ref.js +12 -0
  71. package/dist/validation/element.d.ts +1 -1
  72. package/dist/validation/element.js +1 -1
  73. package/dist/validation/imports.d.ts +5 -0
  74. package/dist/validation/imports.js +30 -0
  75. package/dist/validation/index.d.ts +1 -1
  76. package/dist/validation/index.js +47 -45
  77. package/dist/validation/relation.d.ts +2 -2
  78. package/dist/validation/relation.js +24 -27
  79. package/dist/validation/specification.d.ts +9 -9
  80. package/dist/validation/specification.js +9 -9
  81. package/dist/validation/view-predicates/{element-with.d.ts → fqn-expr-with.d.ts} +1 -1
  82. package/dist/validation/view-predicates/fqn-expr-with.js +42 -0
  83. package/dist/validation/view-predicates/fqn-ref-expr.d.ts +4 -0
  84. package/dist/validation/view-predicates/fqn-ref-expr.js +53 -0
  85. package/dist/validation/view-predicates/incoming.d.ts +1 -1
  86. package/dist/validation/view-predicates/incoming.js +2 -2
  87. package/dist/validation/view-predicates/index.d.ts +6 -6
  88. package/dist/validation/view-predicates/index.js +6 -6
  89. package/dist/validation/view-predicates/outgoing.d.ts +1 -1
  90. package/dist/validation/view-predicates/outgoing.js +8 -4
  91. package/dist/validation/view-predicates/{expanded-element.d.ts → relation-expr.d.ts} +1 -1
  92. package/dist/validation/view-predicates/relation-expr.js +39 -0
  93. package/dist/validation/view-predicates/relation-with.d.ts +1 -1
  94. package/dist/validation/view-predicates/relation-with.js +8 -5
  95. package/dist/workspace/AstNodeDescriptionProvider.d.ts +1 -1
  96. package/dist/workspace/AstNodeDescriptionProvider.js +2 -3
  97. package/dist/workspace/IndexManager.d.ts +1 -1
  98. package/dist/workspace/IndexManager.js +5 -4
  99. package/dist/workspace/LangiumDocuments.d.ts +1 -1
  100. package/dist/workspace/LangiumDocuments.js +3 -5
  101. package/dist/workspace/ProjectsManager.d.ts +25 -7
  102. package/dist/workspace/ProjectsManager.js +76 -32
  103. package/dist/workspace/WorkspaceManager.d.ts +4 -5
  104. package/dist/workspace/WorkspaceManager.js +53 -20
  105. package/package.json +12 -10
  106. package/dist/validation/dynamic-view-rule.d.ts +0 -4
  107. package/dist/validation/dynamic-view-rule.js +0 -17
  108. package/dist/validation/view-predicates/element-with.js +0 -31
  109. package/dist/validation/view-predicates/expanded-element.js +0 -12
  110. package/dist/validation/view-predicates/expression-v2.d.ts +0 -5
  111. package/dist/validation/view-predicates/expression-v2.js +0 -83
@@ -9,46 +9,47 @@ import {
9
9
  deploymentRelationChecks,
10
10
  extendDeploymentChecks
11
11
  } from "./deployment-checks.js";
12
- import { dynamicViewRulePredicate } from "./dynamic-view-rule.js";
13
12
  import { dynamicViewStep } from "./dynamic-view-step.js";
14
- import { elementChecks } from "./element.js";
13
+ import { checkElement } from "./element.js";
14
+ import { checkElementRef } from "./element-ref.js";
15
+ import { checkImported, checkImportsFromPoject } from "./imports.js";
15
16
  import { iconPropertyRuleChecks, notesPropertyRuleChecks, opacityPropertyRuleChecks } from "./property-checks.js";
16
- import { relationBodyChecks, relationChecks } from "./relation.js";
17
+ import { checkRelationBody, relationChecks } from "./relation.js";
17
18
  import {
18
- deploymentNodeKindChecks,
19
- elementKindChecks,
20
- globalPredicateChecks,
21
- globalsChecks,
22
- globalStyleIdChecks,
23
- modelRuleChecks,
24
- relationshipChecks,
25
- specificationRuleChecks,
26
- tagChecks
19
+ checkDeploymentNodeKind,
20
+ checkElementKind,
21
+ checkGlobalPredicate,
22
+ checkGlobals,
23
+ checkGlobalStyleId,
24
+ checkModel,
25
+ checkRelationshipKind,
26
+ checkSpecificationRule,
27
+ checkTag
27
28
  } from "./specification.js";
28
29
  import { viewChecks } from "./view.js";
29
30
  import {
30
- elementPredicateWithChecks,
31
- expandElementExprChecks,
32
- fqnRefExprChecks,
33
- incomingExpressionChecks,
34
- outgoingExpressionChecks,
35
- relationExprChecks,
36
- relationPredicateWithChecks
31
+ checkFqnExprWith,
32
+ checkFqnRefExpr,
33
+ checkIncomingRelationExpr,
34
+ checkOutgoingRelationExpr,
35
+ checkRelationExpr,
36
+ checkRelationExprWith
37
37
  } from "./view-predicates/index.js";
38
38
  function validatableAstNodeGuards(predicates) {
39
39
  return (n) => predicates.some((p) => p(n));
40
40
  }
41
41
  const isValidatableAstNode = validatableAstNodeGuards([
42
+ ast.isImportsFromPoject,
43
+ ast.isImported,
42
44
  ast.isGlobals,
43
45
  ast.isGlobalPredicateGroup,
44
46
  ast.isGlobalDynamicPredicateGroup,
45
47
  ast.isGlobalStyle,
46
48
  ast.isGlobalStyleGroup,
47
- ast.isDynamicViewPredicateIterator,
48
- ast.isElementPredicateWith,
49
- ast.isRelationPredicateWith,
50
- ast.isElementExpression,
51
- ast.isRelationExpression,
49
+ ast.isFqnExprWith,
50
+ ast.isRelationExprWith,
51
+ ast.isFqnExpr,
52
+ ast.isRelationExpr,
52
53
  ast.isDynamicViewParallelSteps,
53
54
  ast.isDynamicViewStep,
54
55
  ast.isDeploymentViewRule,
@@ -58,7 +59,6 @@ const isValidatableAstNode = validatableAstNodeGuards([
58
59
  ast.isFqnRefExpr,
59
60
  ast.isViewProperty,
60
61
  ast.isStyleProperty,
61
- ast.isPredicate,
62
62
  ast.isTags,
63
63
  ast.isViewRule,
64
64
  ast.isDynamicViewRule,
@@ -74,6 +74,7 @@ const isValidatableAstNode = validatableAstNodeGuards([
74
74
  ast.isStringProperty,
75
75
  ast.isNavigateToProperty,
76
76
  ast.isElement,
77
+ ast.isElementRef,
77
78
  ast.isExtendElement,
78
79
  ast.isExtendDeployment,
79
80
  ast.isSpecificationElementKind,
@@ -117,35 +118,36 @@ export function registerValidationChecks(services) {
117
118
  const registry = services.validation.ValidationRegistry;
118
119
  registry.register({
119
120
  DeployedInstance: deployedInstanceChecks(services),
120
- DeploymentNodeKind: deploymentNodeKindChecks(services),
121
+ DeploymentNodeKind: checkDeploymentNodeKind(services),
121
122
  DeploymentNode: deploymentNodeChecks(services),
122
123
  DeploymentRelation: deploymentRelationChecks(services),
123
124
  ExtendDeployment: extendDeploymentChecks(services),
124
- FqnRefExpr: fqnRefExprChecks(services),
125
- RelationExpr: relationExprChecks(services),
125
+ FqnRefExpr: checkFqnRefExpr(services),
126
+ RelationExpr: checkRelationExpr(services),
126
127
  NotesProperty: notesPropertyRuleChecks(services),
127
128
  OpacityProperty: opacityPropertyRuleChecks(services),
128
129
  IconProperty: iconPropertyRuleChecks(services),
129
- SpecificationRule: specificationRuleChecks(services),
130
- Model: modelRuleChecks(services),
131
- Globals: globalsChecks(services),
132
- GlobalPredicateGroup: globalPredicateChecks(services),
133
- GlobalDynamicPredicateGroup: globalPredicateChecks(services),
134
- GlobalStyleId: globalStyleIdChecks(services),
130
+ SpecificationRule: checkSpecificationRule(services),
131
+ Model: checkModel(services),
132
+ Globals: checkGlobals(services),
133
+ GlobalPredicateGroup: checkGlobalPredicate(services),
134
+ GlobalDynamicPredicateGroup: checkGlobalPredicate(services),
135
+ GlobalStyleId: checkGlobalStyleId(services),
135
136
  DynamicViewStep: dynamicViewStep(services),
136
137
  LikeC4View: viewChecks(services),
137
- Element: elementChecks(services),
138
- ElementKind: elementKindChecks(services),
138
+ Element: checkElement(services),
139
+ ElementRef: checkElementRef(services),
140
+ ElementKind: checkElementKind(services),
139
141
  Relation: relationChecks(services),
140
- RelationBody: relationBodyChecks(services),
141
- Tag: tagChecks(services),
142
- DynamicViewPredicateIterator: dynamicViewRulePredicate(services),
143
- ElementPredicateWith: elementPredicateWithChecks(services),
144
- RelationPredicateWith: relationPredicateWithChecks(services),
145
- ExpandElementExpression: expandElementExprChecks(services),
146
- RelationshipKind: relationshipChecks(services),
147
- IncomingRelationExpression: incomingExpressionChecks(services),
148
- OutgoingRelationExpression: outgoingExpressionChecks(services)
142
+ RelationBody: checkRelationBody(services),
143
+ Tag: checkTag(services),
144
+ FqnExprWith: checkFqnExprWith(services),
145
+ RelationExprWith: checkRelationExprWith(services),
146
+ RelationshipKind: checkRelationshipKind(services),
147
+ IncomingRelationExpr: checkIncomingRelationExpr(services),
148
+ OutgoingRelationExpr: checkOutgoingRelationExpr(services),
149
+ ImportsFromPoject: checkImportsFromPoject(services),
150
+ Imported: checkImported(services)
149
151
  });
150
152
  const connection = services.shared.lsp.Connection;
151
153
  if (connection) {
@@ -1,5 +1,5 @@
1
- import type { ValidationCheck } from 'langium';
1
+ import { type ValidationCheck } from 'langium';
2
2
  import { ast } from '../ast';
3
3
  import type { LikeC4Services } from '../module';
4
4
  export declare const relationChecks: (services: LikeC4Services) => ValidationCheck<ast.Relation>;
5
- export declare const relationBodyChecks: (_services: LikeC4Services) => ValidationCheck<ast.RelationBody>;
5
+ export declare const checkRelationBody: (_services: LikeC4Services) => ValidationCheck<ast.RelationBody>;
@@ -1,50 +1,47 @@
1
- import { isSameHierarchy } from "@likec4/core";
2
- import { isDefined } from "remeda";
3
- import { ast } from "../ast.js";
4
- import { elementRef } from "../utils/elementRef.js";
1
+ import { FqnRef, isSameHierarchy } from "@likec4/core";
2
+ import { AstUtils } from "langium";
3
+ import { safeCall } from "../utils/index.js";
5
4
  import { tryOrLog } from "./_shared.js";
6
5
  export const relationChecks = (services) => {
7
- const fqnIndex = services.likec4.FqnIndex;
6
+ const modelParser = services.likec4.ModelParser;
8
7
  return tryOrLog((el, accept) => {
9
- const targetEl = elementRef(el.target);
10
- const target = targetEl && fqnIndex.getFqn(targetEl);
8
+ const parser = modelParser.forDocument(AstUtils.getDocument(el));
9
+ const source = safeCall(() => parser._resolveRelationSource(el));
10
+ if (!source) {
11
+ accept("error", "Source not resolved", {
12
+ node: el,
13
+ property: "source"
14
+ });
15
+ return;
16
+ }
17
+ const target = safeCall(() => parser.parseFqnRef(el.target));
11
18
  if (!target) {
12
19
  accept("error", "Target not resolved", {
13
20
  node: el,
14
21
  property: "target"
15
22
  });
23
+ return;
16
24
  }
17
- let sourceEl;
18
- if (isDefined(el.source)) {
19
- sourceEl = elementRef(el.source);
20
- if (!sourceEl) {
21
- return accept("error", "Source not resolved", {
25
+ if (FqnRef.isImportRef(source)) {
26
+ if (FqnRef.isImportRef(target)) {
27
+ accept("warning", "Relationship between imported elements may not be visible in origin projects", {
28
+ node: el
29
+ });
30
+ } else {
31
+ accept("warning", "Relationship from imported element to local element may not be visible in origin project", {
22
32
  node: el,
23
33
  property: "source"
24
34
  });
25
35
  }
26
- } else {
27
- if (!ast.isElementBody(el.$container)) {
28
- return accept("error", "Sourceless relation must be nested", {
29
- node: el
30
- });
31
- }
32
- sourceEl = el.$container.$container;
33
- }
34
- const source = fqnIndex.getFqn(sourceEl);
35
- if (!source) {
36
- accept("error", "Source not resolved", {
37
- node: el
38
- });
39
36
  }
40
- if (source && target && isSameHierarchy(source, target)) {
37
+ if (isSameHierarchy(FqnRef.toModelFqn(source), FqnRef.toModelFqn(target))) {
41
38
  accept("error", "Invalid parent-child relationship", {
42
39
  node: el
43
40
  });
44
41
  }
45
42
  });
46
43
  };
47
- export const relationBodyChecks = (_services) => {
44
+ export const checkRelationBody = (_services) => {
48
45
  return tryOrLog((body, accept) => {
49
46
  const relation = body.$container;
50
47
  if (relation.tags?.values && body.tags?.values) {
@@ -1,12 +1,12 @@
1
1
  import { type ValidationCheck } from 'langium';
2
2
  import { ast } from '../ast';
3
3
  import type { LikeC4Services } from '../module';
4
- export declare const specificationRuleChecks: (_: LikeC4Services) => ValidationCheck<ast.SpecificationRule>;
5
- export declare const modelRuleChecks: (_: LikeC4Services) => ValidationCheck<ast.Model>;
6
- export declare const globalsChecks: (_: LikeC4Services) => ValidationCheck<ast.Globals>;
7
- export declare const elementKindChecks: (services: LikeC4Services) => ValidationCheck<ast.ElementKind>;
8
- export declare const deploymentNodeKindChecks: (services: LikeC4Services) => ValidationCheck<ast.DeploymentNodeKind>;
9
- export declare const tagChecks: (services: LikeC4Services) => ValidationCheck<ast.Tag>;
10
- export declare const relationshipChecks: (services: LikeC4Services) => ValidationCheck<ast.RelationshipKind>;
11
- export declare const globalPredicateChecks: (services: LikeC4Services) => ValidationCheck<ast.GlobalPredicateGroup | ast.GlobalDynamicPredicateGroup>;
12
- export declare const globalStyleIdChecks: (services: LikeC4Services) => ValidationCheck<ast.GlobalStyleId>;
4
+ export declare const checkSpecificationRule: (_: LikeC4Services) => ValidationCheck<ast.SpecificationRule>;
5
+ export declare const checkModel: (_: LikeC4Services) => ValidationCheck<ast.Model>;
6
+ export declare const checkGlobals: (_: LikeC4Services) => ValidationCheck<ast.Globals>;
7
+ export declare const checkElementKind: (services: LikeC4Services) => ValidationCheck<ast.ElementKind>;
8
+ export declare const checkDeploymentNodeKind: (services: LikeC4Services) => ValidationCheck<ast.DeploymentNodeKind>;
9
+ export declare const checkTag: (services: LikeC4Services) => ValidationCheck<ast.Tag>;
10
+ export declare const checkRelationshipKind: (services: LikeC4Services) => ValidationCheck<ast.RelationshipKind>;
11
+ export declare const checkGlobalPredicate: (services: LikeC4Services) => ValidationCheck<ast.GlobalPredicateGroup | ast.GlobalDynamicPredicateGroup>;
12
+ export declare const checkGlobalStyleId: (services: LikeC4Services) => ValidationCheck<ast.GlobalStyleId>;
@@ -2,7 +2,7 @@ import { AstUtils } from "langium";
2
2
  import { ast } from "../ast.js";
3
3
  import { projectIdFrom } from "../utils/index.js";
4
4
  import { RESERVED_WORDS, tryOrLog } from "./_shared.js";
5
- export const specificationRuleChecks = (_) => {
5
+ export const checkSpecificationRule = (_) => {
6
6
  return tryOrLog((node, accept) => {
7
7
  if (node.$containerIndex && node.$containerIndex > 0) {
8
8
  accept("warning", `Prefer one specification per document`, {
@@ -12,7 +12,7 @@ export const specificationRuleChecks = (_) => {
12
12
  }
13
13
  });
14
14
  };
15
- export const modelRuleChecks = (_) => {
15
+ export const checkModel = (_) => {
16
16
  return tryOrLog((node, accept) => {
17
17
  if (node.$containerIndex && node.$containerIndex > 0) {
18
18
  accept("warning", `Prefer one model per document`, {
@@ -22,7 +22,7 @@ export const modelRuleChecks = (_) => {
22
22
  }
23
23
  });
24
24
  };
25
- export const globalsChecks = (_) => {
25
+ export const checkGlobals = (_) => {
26
26
  return tryOrLog((node, accept) => {
27
27
  if (node.$containerIndex && node.$containerIndex > 0) {
28
28
  accept("warning", `Prefer one global block per document`, {
@@ -32,7 +32,7 @@ export const globalsChecks = (_) => {
32
32
  }
33
33
  });
34
34
  };
35
- export const elementKindChecks = (services) => {
35
+ export const checkElementKind = (services) => {
36
36
  const index = services.shared.workspace.IndexManager;
37
37
  return tryOrLog((node, accept) => {
38
38
  if (RESERVED_WORDS.includes(node.name)) {
@@ -63,7 +63,7 @@ export const elementKindChecks = (services) => {
63
63
  }
64
64
  });
65
65
  };
66
- export const deploymentNodeKindChecks = (services) => {
66
+ export const checkDeploymentNodeKind = (services) => {
67
67
  const index = services.shared.workspace.IndexManager;
68
68
  return tryOrLog((node, accept) => {
69
69
  if (RESERVED_WORDS.includes(node.name)) {
@@ -94,7 +94,7 @@ export const deploymentNodeKindChecks = (services) => {
94
94
  }
95
95
  });
96
96
  };
97
- export const tagChecks = (services) => {
97
+ export const checkTag = (services) => {
98
98
  const index = services.shared.workspace.IndexManager;
99
99
  return tryOrLog((node, accept) => {
100
100
  const tagname = "#" + node.name;
@@ -124,7 +124,7 @@ export const tagChecks = (services) => {
124
124
  }
125
125
  });
126
126
  };
127
- export const relationshipChecks = (services) => {
127
+ export const checkRelationshipKind = (services) => {
128
128
  const index = services.shared.workspace.IndexManager;
129
129
  return tryOrLog((node, accept) => {
130
130
  if (RESERVED_WORDS.includes(node.name)) {
@@ -143,7 +143,7 @@ export const relationshipChecks = (services) => {
143
143
  }
144
144
  });
145
145
  };
146
- export const globalPredicateChecks = (services) => {
146
+ export const checkGlobalPredicate = (services) => {
147
147
  const index = services.shared.workspace.IndexManager;
148
148
  return tryOrLog((node, accept) => {
149
149
  const projectId = projectIdFrom(node);
@@ -158,7 +158,7 @@ export const globalPredicateChecks = (services) => {
158
158
  }
159
159
  });
160
160
  };
161
- export const globalStyleIdChecks = (services) => {
161
+ export const checkGlobalStyleId = (services) => {
162
162
  const index = services.shared.workspace.IndexManager;
163
163
  return tryOrLog((node, accept) => {
164
164
  const projectId = projectIdFrom(node);
@@ -1,4 +1,4 @@
1
1
  import type { ValidationCheck } from 'langium';
2
2
  import { ast } from '../../ast';
3
3
  import type { LikeC4Services } from '../../module';
4
- export declare const elementPredicateWithChecks: (_services: LikeC4Services) => ValidationCheck<ast.ElementPredicateWith>;
4
+ export declare const checkFqnExprWith: (services: LikeC4Services) => ValidationCheck<ast.FqnExprWith>;
@@ -0,0 +1,42 @@
1
+ import { FqnExpr, nonexhaustive } from "@likec4/core";
2
+ import { AstUtils } from "langium";
3
+ import { getViewRulePredicateContainer } from "../../ast.js";
4
+ import { tryOrLog } from "../_shared.js";
5
+ export const checkFqnExprWith = (services) => {
6
+ const modelParser = services.likec4.ModelParser;
7
+ return tryOrLog((el, accept) => {
8
+ const container = getViewRulePredicateContainer(el);
9
+ if (container?.$type !== "DynamicViewIncludePredicate" && container?.isInclude !== true) {
10
+ accept("error", 'Invalid usage inside "exclude"', {
11
+ node: el
12
+ });
13
+ return;
14
+ }
15
+ const isInsideDynamicView = container.$type === "DynamicViewIncludePredicate";
16
+ const parser = modelParser.forDocument(AstUtils.getDocument(container));
17
+ let expr = FqnExpr.unwrap(parser.parseFqnExprWith(el).custom.expr);
18
+ switch (true) {
19
+ case (FqnExpr.isWildcard(expr) && isInsideDynamicView):
20
+ case (FqnExpr.isElementKindExpr(expr) && isInsideDynamicView):
21
+ case (FqnExpr.isElementTagExpr(expr) && isInsideDynamicView): {
22
+ accept("warning", `Predicate is ignored, as not supported in dynamic views`, {
23
+ node: el
24
+ });
25
+ return;
26
+ }
27
+ case FqnExpr.isWildcard(expr):
28
+ case FqnExpr.isModelRef(expr):
29
+ case FqnExpr.isDeploymentRef(expr):
30
+ return;
31
+ case FqnExpr.isElementKindExpr(expr):
32
+ case FqnExpr.isElementTagExpr(expr):
33
+ accept("error", "Invalid target (expect reference to specific element)", {
34
+ node: el,
35
+ property: "subject"
36
+ });
37
+ return;
38
+ default:
39
+ nonexhaustive(expr);
40
+ }
41
+ });
42
+ };
@@ -0,0 +1,4 @@
1
+ import type { ValidationCheck } from 'langium';
2
+ import { ast } from '../../ast';
3
+ import type { LikeC4Services } from '../../module';
4
+ export declare const checkFqnRefExpr: (services: LikeC4Services) => ValidationCheck<ast.FqnRefExpr>;
@@ -0,0 +1,53 @@
1
+ import { FqnExpr, FqnRef } from "@likec4/core";
2
+ import { AstUtils } from "langium";
3
+ import { isTruthy } from "remeda";
4
+ import { ast, getViewRulePredicateContainer, isFqnRefInsideDeployment } from "../../ast.js";
5
+ import { tryOrLog } from "../_shared.js";
6
+ export const checkFqnRefExpr = (services) => {
7
+ const modelParser = services.likec4.ModelParser;
8
+ return tryOrLog((node, accept) => {
9
+ const parser = modelParser.forDocument(AstUtils.getDocument(node));
10
+ const expr = parser.parseFqnRefExpr(node);
11
+ const viewRulePredicate = getViewRulePredicateContainer(node);
12
+ const isInsideDeploymentButNotStyle = isFqnRefInsideDeployment(node) && !AstUtils.hasContainerOfType(
13
+ node,
14
+ (n) => ast.isDeploymentViewRuleStyle(n) || ast.isViewRuleStyle(n)
15
+ );
16
+ if (viewRulePredicate?.$type === "DeploymentViewRulePredicate" || isInsideDeploymentButNotStyle) {
17
+ const isPartOfRelationExpr = AstUtils.hasContainerOfType(node, ast.isRelationExpr);
18
+ if (!isPartOfRelationExpr) {
19
+ if (FqnExpr.isModelRef(expr)) {
20
+ accept("error", "Deployment view predicate must reference deployment model", {
21
+ node
22
+ });
23
+ return;
24
+ }
25
+ if (FqnExpr.isDeploymentRef(expr) && FqnRef.isInsideInstanceRef(expr.ref)) {
26
+ accept("error", "Must reference deployment nodes or instances, but not internals", {
27
+ node
28
+ });
29
+ return;
30
+ }
31
+ }
32
+ if (isTruthy(node.selector) && !ast.isDeploymentNode(node.ref.value?.ref)) {
33
+ accept("warning", `Selector '${node.selector}' applies to deployment nodes only, ignored here`, {
34
+ node,
35
+ property: "selector"
36
+ });
37
+ }
38
+ return;
39
+ }
40
+ if (viewRulePredicate?.$type === "DynamicViewIncludePredicate") {
41
+ switch (true) {
42
+ case FqnExpr.isElementKindExpr(expr):
43
+ case FqnExpr.isElementTagExpr(expr):
44
+ case FqnExpr.isWildcard(expr): {
45
+ accept("warning", `Predicate is ignored, as not supported in dynamic views`, {
46
+ node
47
+ });
48
+ return;
49
+ }
50
+ }
51
+ }
52
+ });
53
+ };
@@ -1,4 +1,4 @@
1
1
  import { type ValidationCheck } from 'langium';
2
2
  import { ast } from '../../ast';
3
3
  import type { LikeC4Services } from '../../module';
4
- export declare const incomingExpressionChecks: (_services: LikeC4Services) => ValidationCheck<ast.IncomingRelationExpression>;
4
+ export declare const checkIncomingRelationExpr: (_services: LikeC4Services) => ValidationCheck<ast.IncomingRelationExpr>;
@@ -2,9 +2,9 @@ import { AstUtils } from "langium";
2
2
  import { isNullish } from "remeda";
3
3
  import { ast } from "../../ast.js";
4
4
  import { tryOrLog } from "../_shared.js";
5
- export const incomingExpressionChecks = (_services) => {
5
+ export const checkIncomingRelationExpr = (_services) => {
6
6
  return tryOrLog((el, accept) => {
7
- if (ast.isWildcardExpression(el.to) && !ast.isInOutRelationExpression(el.$container)) {
7
+ if (el.to.$type === "WildcardExpression" && !ast.isInOutRelationExpr(el.$container)) {
8
8
  const view = AstUtils.getContainerOfType(el, ast.isElementView);
9
9
  if (isNullish(view?.viewOf)) {
10
10
  accept("warning", "Predicate is ignored as it concerns all relationships", {
@@ -1,6 +1,6 @@
1
- export * from './element-with';
2
- export * from './expanded-element';
3
- export * from './expression-v2';
4
- export * from './incoming';
5
- export * from './outgoing';
6
- export * from './relation-with';
1
+ export { checkFqnExprWith } from './fqn-expr-with';
2
+ export { checkFqnRefExpr } from './fqn-ref-expr';
3
+ export { checkIncomingRelationExpr } from './incoming';
4
+ export { checkOutgoingRelationExpr } from './outgoing';
5
+ export { checkRelationExpr } from './relation-expr';
6
+ export { checkRelationExprWith } from './relation-with';
@@ -1,6 +1,6 @@
1
- export * from "./element-with.js";
2
- export * from "./expanded-element.js";
3
- export * from "./expression-v2.js";
4
- export * from "./incoming.js";
5
- export * from "./outgoing.js";
6
- export * from "./relation-with.js";
1
+ export { checkFqnExprWith } from "./fqn-expr-with.js";
2
+ export { checkFqnRefExpr } from "./fqn-ref-expr.js";
3
+ export { checkIncomingRelationExpr } from "./incoming.js";
4
+ export { checkOutgoingRelationExpr } from "./outgoing.js";
5
+ export { checkRelationExpr } from "./relation-expr.js";
6
+ export { checkRelationExprWith } from "./relation-with.js";
@@ -1,4 +1,4 @@
1
1
  import { type ValidationCheck } from 'langium';
2
2
  import { ast } from '../../ast';
3
3
  import type { LikeC4Services } from '../../module';
4
- export declare const outgoingExpressionChecks: (_services: LikeC4Services) => ValidationCheck<ast.OutgoingRelationExpression>;
4
+ export declare const checkOutgoingRelationExpr: (_services: LikeC4Services) => ValidationCheck<ast.OutgoingRelationExpr>;
@@ -1,12 +1,16 @@
1
1
  import { AstUtils } from "langium";
2
2
  import { isNullish } from "remeda";
3
- import { ast } from "../../ast.js";
3
+ import { ast, getViewRulePredicateContainer } from "../../ast.js";
4
4
  import { tryOrLog } from "../_shared.js";
5
- export const outgoingExpressionChecks = (_services) => {
5
+ export const checkOutgoingRelationExpr = (_services) => {
6
6
  return tryOrLog((el, accept) => {
7
- if (ast.isWildcardExpression(el.from) && !ast.isDirectedRelationExpression(el.$container)) {
7
+ const viewRulePredicate = getViewRulePredicateContainer(el);
8
+ if (viewRulePredicate?.$type !== "ViewRulePredicate") {
9
+ return;
10
+ }
11
+ if (el.$container.$type !== "DirectedRelationExpr" && el.from.$type === "WildcardExpression") {
8
12
  const view = AstUtils.getContainerOfType(el, ast.isElementView);
9
- if (isNullish(view?.viewOf)) {
13
+ if (view && isNullish(view.viewOf)) {
10
14
  accept("warning", "Predicate is ignored as it concerns all relationships", {
11
15
  node: el
12
16
  });
@@ -1,4 +1,4 @@
1
1
  import { type ValidationCheck } from 'langium';
2
2
  import { ast } from '../../ast';
3
3
  import type { LikeC4Services } from '../../module';
4
- export declare const expandElementExprChecks: (_services: LikeC4Services) => ValidationCheck<ast.ExpandElementExpression>;
4
+ export declare const checkRelationExpr: (services: LikeC4Services) => ValidationCheck<ast.RelationExpr>;
@@ -0,0 +1,39 @@
1
+ import { FqnExpr, RelationExpr } from "@likec4/core";
2
+ import { AstUtils } from "langium";
3
+ import { ast } from "../../ast.js";
4
+ import { tryOrLog } from "../_shared.js";
5
+ export const checkRelationExpr = (services) => {
6
+ const ModelParser = services.likec4.ModelParser;
7
+ return tryOrLog((node, accept) => {
8
+ const predicate = AstUtils.getContainerOfType(node, ast.isDeploymentViewRulePredicate);
9
+ if (!predicate || predicate.isInclude !== true) {
10
+ return;
11
+ }
12
+ const doc = AstUtils.getDocument(node);
13
+ const parser = ModelParser.forDocument(doc);
14
+ let relationExpr = RelationExpr.unwrap(parser.parseRelationExpr(node));
15
+ const ModelRefOnlyExclude = "Model reference is allowed in exclude predicate only";
16
+ if (RelationExpr.isDirect(relationExpr)) {
17
+ if (FqnExpr.isModelRef(relationExpr.source) || FqnExpr.isModelRef(relationExpr.target)) {
18
+ accept("error", ModelRefOnlyExclude, {
19
+ node
20
+ });
21
+ }
22
+ return;
23
+ }
24
+ let expr;
25
+ if (RelationExpr.isIncoming(relationExpr)) {
26
+ expr = relationExpr.incoming;
27
+ } else if (RelationExpr.isOutgoing(relationExpr)) {
28
+ expr = relationExpr.outgoing;
29
+ } else {
30
+ expr = relationExpr.inout;
31
+ }
32
+ if (FqnExpr.isModelRef(expr)) {
33
+ accept("error", ModelRefOnlyExclude, {
34
+ node
35
+ });
36
+ return;
37
+ }
38
+ });
39
+ };
@@ -1,4 +1,4 @@
1
1
  import { type ValidationCheck } from 'langium';
2
2
  import { ast } from '../../ast';
3
3
  import type { LikeC4Services } from '../../module';
4
- export declare const relationPredicateWithChecks: (_services: LikeC4Services) => ValidationCheck<ast.RelationPredicateWith>;
4
+ export declare const checkRelationExprWith: (_services: LikeC4Services) => ValidationCheck<ast.RelationExprWith>;
@@ -1,13 +1,16 @@
1
- import { AstUtils } from "langium";
2
- import { ast } from "../../ast.js";
1
+ import { getViewRulePredicateContainer } from "../../ast.js";
3
2
  import { tryOrLog } from "../_shared.js";
4
- export const relationPredicateWithChecks = (_services) => {
3
+ export const checkRelationExprWith = (_services) => {
5
4
  return tryOrLog((el, accept) => {
6
- const container = AstUtils.getContainerOfType(el, ast.isViewRulePredicate);
7
- if (ast.isExcludePredicate(container)) {
5
+ const container = getViewRulePredicateContainer(el);
6
+ if (!container || container.$type == "DynamicViewIncludePredicate") {
7
+ return;
8
+ }
9
+ if (!container.isInclude) {
8
10
  accept("error", 'Invalid usage inside "exclude"', {
9
11
  node: el
10
12
  });
13
+ return;
11
14
  }
12
15
  });
13
16
  };
@@ -1,7 +1,7 @@
1
1
  import { type AstNode, type AstNodeDescription, type LangiumDocument, DefaultAstNodeDescriptionProvider } from 'langium';
2
2
  import type { LikeC4Services } from '../module';
3
3
  export declare class AstNodeDescriptionProvider extends DefaultAstNodeDescriptionProvider {
4
- private projects;
4
+ protected services: LikeC4Services;
5
5
  constructor(services: LikeC4Services);
6
6
  createDescription(node: AstNode, name: string | undefined, document?: LangiumDocument): AstNodeDescription;
7
7
  }
@@ -3,15 +3,14 @@ import {
3
3
  DefaultAstNodeDescriptionProvider
4
4
  } from "langium";
5
5
  export class AstNodeDescriptionProvider extends DefaultAstNodeDescriptionProvider {
6
- projects;
7
6
  constructor(services) {
8
7
  super(services);
9
- this.projects = services.shared.workspace.ProjectsManager;
8
+ this.services = services;
10
9
  }
11
10
  createDescription(node, name, document) {
12
11
  const doc = document ?? AstUtils.getDocument(node);
13
12
  const description = super.createDescription(node, name, document);
14
- doc.likec4ProjectId ??= this.projects.belongsTo(doc.uri);
13
+ doc.likec4ProjectId ??= this.services.shared.workspace.ProjectsManager.belongsTo(doc.uri);
15
14
  description.likec4ProjectId = doc.likec4ProjectId;
16
15
  return description;
17
16
  }
@@ -3,7 +3,7 @@ import { type AstNodeDescription, type LangiumDocument, type Stream, DefaultInde
3
3
  import { CancellationToken } from 'vscode-jsonrpc';
4
4
  import type { LikeC4SharedServices } from '../module';
5
5
  export declare class IndexManager extends DefaultIndexManager {
6
- private projects;
6
+ protected services: LikeC4SharedServices;
7
7
  constructor(services: LikeC4SharedServices);
8
8
  updateContent(document: LangiumDocument, cancelToken?: CancellationToken): Promise<void>;
9
9
  projectElements(projectId: ProjectId, nodeType?: string, uris?: Set<string>): Stream<AstNodeDescription>;