@likec4/language-server 1.5.0 → 1.6.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.
@@ -1,6 +1,6 @@
1
1
  import { type Fqn, invariant, isAncestor, type NonEmptyArray, nonNullable, type ViewChanges } from '@likec4/core'
2
2
  import { GrammarUtils } from 'langium'
3
- import { entries, filter, findLast, last } from 'remeda'
3
+ import { entries, filter, findLast, isTruthy, last } from 'remeda'
4
4
  import { type Range, TextEdit } from 'vscode-languageserver-protocol'
5
5
  import { ast, type ParsedAstView, type ParsedLikeC4LangiumDocument } from '../ast'
6
6
  import type { FqnIndex } from '../model'
@@ -37,8 +37,8 @@ const isMatchingViewRule =
37
37
  if (!ast.isViewRuleStyle(rule)) {
38
38
  return false
39
39
  }
40
- const [target, ...rest] = rule.targets
41
- if (!target || rest.length > 0 || !ast.isElementRef(target)) {
40
+ const target = rule.target.value
41
+ if (!target || isTruthy(rule.target.prev) || !ast.isElementRef(target)) {
42
42
  return false
43
43
  }
44
44
  const ref = target.el.ref
@@ -127,7 +127,7 @@ export function changeElementStyle(services: LikeC4Services, {
127
127
  invariant(ruleCstNode, 'RuleCstNode not found')
128
128
  for (const [key, _value] of entries(style)) {
129
129
  const value = key === 'opacity' ? _value.toString() + '%' : _value
130
- const ruleProp = rule.styleprops.find(p => p.key === key)
130
+ const ruleProp = rule.props.find(p => p.key === key)
131
131
  // replace existing property
132
132
  if (ruleProp && ruleProp.$cstNode) {
133
133
  const { range: { start, end } } = nonNullable(
@@ -16,7 +16,7 @@ import type {
16
16
  ThemeColor,
17
17
  ViewID,
18
18
  ViewRule,
19
- ViewRuleExpression,
19
+ ViewRulePredicate,
20
20
  ViewRuleStyle
21
21
  } from '@likec4/core'
22
22
  import { indexBy, isString, map, prop } from 'remeda'
@@ -418,12 +418,12 @@ export function $expr(expr: Expression | C4Expression): C4Expression {
418
418
  }
419
419
  }
420
420
 
421
- export function $include(expr: Expression | C4Expression): ViewRuleExpression {
421
+ export function $include(expr: Expression | C4Expression): ViewRulePredicate {
422
422
  return {
423
423
  include: [$expr(expr)]
424
424
  }
425
425
  }
426
- export function $exclude(expr: Expression | C4Expression): ViewRuleExpression {
426
+ export function $exclude(expr: Expression | C4Expression): ViewRulePredicate {
427
427
  return {
428
428
  exclude: [$expr(expr)]
429
429
  }
@@ -5,7 +5,7 @@ import type {
5
5
  Element,
6
6
  ElementView,
7
7
  Relation,
8
- ViewRuleExpression
8
+ ViewRulePredicate
9
9
  } from '@likec4/core'
10
10
  import {
11
11
  ancestorsFqn,
@@ -16,7 +16,7 @@ import {
16
16
  isAncestor,
17
17
  isScopedElementView,
18
18
  isViewRuleAutoLayout,
19
- isViewRuleExpression,
19
+ isViewRulePredicate,
20
20
  nonexhaustive,
21
21
  parentFqn
22
22
  } from '@likec4/core'
@@ -92,7 +92,7 @@ export class ComputeCtx {
92
92
  this.reset()
93
93
  const { rules, ...view } = this.view
94
94
 
95
- const viewPredicates = rules.filter(isViewRuleExpression)
95
+ const viewPredicates = rules.filter(isViewRulePredicate)
96
96
  if (this.root && viewPredicates.length == 0) {
97
97
  this.addElement(this.graph.element(this.root))
98
98
  }
@@ -399,7 +399,7 @@ export class ComputeCtx {
399
399
  }, [] as ComputeCtx.Edge[])
400
400
  }
401
401
 
402
- protected processPredicates(viewRules: ViewRuleExpression[]): this {
402
+ protected processPredicates(viewRules: ViewRulePredicate[]): this {
403
403
  // eslint-disable-next-line @typescript-eslint/no-this-alias
404
404
  for (const rule of viewRules) {
405
405
  const isInclude = 'include' in rule
@@ -1,4 +1,4 @@
1
- import type { DynamicViewRule, DynamicViewStep, Fqn, ViewID, ViewRuleExpression } from '@likec4/core'
1
+ import type { DynamicViewRule, DynamicViewStep, Fqn, ViewID, ViewRulePredicate } from '@likec4/core'
2
2
  import { partition } from 'remeda'
3
3
  import { type FakeElementIds, fakeModel } from '../../compute-view/__test__/fixture'
4
4
  import { computeDynamicView } from '../index'
@@ -36,7 +36,7 @@ export function $step(expr: StepExpr, title?: string): DynamicViewStep {
36
36
  throw new Error(`Invalid step expression: ${expr}`)
37
37
  }
38
38
 
39
- export function compute(stepsAndRules: (DynamicViewStep | ViewRuleExpression)[]) {
39
+ export function compute(stepsAndRules: (DynamicViewStep | ViewRulePredicate)[]) {
40
40
  const [steps, rules] = partition(stepsAndRules, (s): s is DynamicViewStep => 'source' in s)
41
41
  const result = computeDynamicView(
42
42
  {
@@ -6,7 +6,7 @@ import {
6
6
  MultiMap,
7
7
  type PrecomputedScopes
8
8
  } from 'langium'
9
- import { isTruthy } from 'remeda'
9
+ import { isNullish, isTruthy } from 'remeda'
10
10
  import type { CancellationToken } from 'vscode-languageserver'
11
11
  import { ast, type LikeC4LangiumDocument } from '../ast'
12
12
  import { logError } from '../logger'
@@ -20,77 +20,130 @@ export class LikeC4ScopeComputation extends DefaultScopeComputation {
20
20
  ): Promise<AstNodeDescription[]> {
21
21
  const docExports: AstNodeDescription[] = []
22
22
  try {
23
- const { specifications, models, views } = document.parseResult.value
23
+ const { specifications, models, views, likec4lib } = document.parseResult.value
24
+
25
+ // Process library
26
+ this.exportLibrary(likec4lib, docExports, document)
24
27
 
25
28
  // Process specification
26
- for (
27
- const spec of specifications.flatMap(s => [
28
- ...s.elements,
29
- ...s.relationships,
30
- ...s.tags
31
- ])
32
- ) {
33
- try {
34
- switch (true) {
35
- case ast.isSpecificationElementKind(spec): {
36
- if (isTruthy(spec.kind.name)) {
37
- docExports.push(
38
- this.descriptions.createDescription(spec.kind, spec.kind.name, document)
39
- )
40
- }
41
- continue
42
- }
43
- case ast.isSpecificationTag(spec): {
44
- if (isTruthy(spec.tag.name)) {
45
- docExports.push(
46
- this.descriptions.createDescription(spec.tag, '#' + spec.tag.name, document)
47
- )
48
- }
49
- continue
50
- }
51
- case ast.isSpecificationRelationshipKind(spec): {
52
- if (isTruthy(spec.kind.name)) {
53
- docExports.push(
54
- this.descriptions.createDescription(spec.kind, spec.kind.name, document),
55
- this.descriptions.createDescription(spec.kind, '.' + spec.kind.name, document)
56
- )
57
- }
58
- continue
59
- }
60
- // Thow error if not exhaustive
61
- default:
62
- nonexhaustive(spec)
63
- }
64
- } catch (e) {
65
- logError(e)
29
+ this.exportSpecification(specifications, docExports, document)
30
+
31
+ // Process models
32
+ this.exportModel(models, docExports, document)
33
+
34
+ // Process views
35
+ this.exportViews(views, docExports, document)
36
+ } catch (e) {
37
+ logError(e)
38
+ }
39
+ return docExports
40
+ }
41
+
42
+ private exportViews(
43
+ views: ast.ModelViews[] | undefined,
44
+ docExports: AstNodeDescription[],
45
+ document: LikeC4LangiumDocument
46
+ ) {
47
+ if (isNullish(views) || views.length === 0) {
48
+ return
49
+ }
50
+ for (const viewAst of views.flatMap(v => v.views)) {
51
+ try {
52
+ if (isTruthy(viewAst.name)) {
53
+ docExports.push(this.descriptions.createDescription(viewAst, viewAst.name, document))
66
54
  }
55
+ } catch (e) {
56
+ logError(e)
67
57
  }
58
+ }
59
+ }
68
60
 
69
- // Process models
70
- for (const elAst of models.flatMap(m => m.elements)) {
71
- try {
72
- if (ast.isElement(elAst) && isTruthy(elAst.name)) {
73
- docExports.push(this.descriptions.createDescription(elAst, elAst.name, document))
74
- }
75
- } catch (e) {
76
- logError(e)
61
+ private exportModel(
62
+ models: ast.Model[] | undefined,
63
+ docExports: AstNodeDescription[],
64
+ document: LikeC4LangiumDocument
65
+ ) {
66
+ if (isNullish(models) || models.length === 0) {
67
+ return
68
+ }
69
+ for (const elAst of models.flatMap(m => m.elements)) {
70
+ try {
71
+ if (ast.isElement(elAst) && isTruthy(elAst.name)) {
72
+ docExports.push(this.descriptions.createDescription(elAst, elAst.name, document))
77
73
  }
74
+ } catch (e) {
75
+ logError(e)
78
76
  }
77
+ }
78
+ }
79
79
 
80
- // Process views
81
- for (const viewAst of views.flatMap(v => v.views)) {
82
- try {
83
- if (isTruthy(viewAst.name)) {
84
- docExports.push(this.descriptions.createDescription(viewAst, viewAst.name, document))
80
+ private exportLibrary(
81
+ likec4lib: ast.LikeC4Lib[] | undefined,
82
+ docExports: AstNodeDescription[],
83
+ document: LikeC4LangiumDocument
84
+ ) {
85
+ if (isNullish(likec4lib) || likec4lib.length === 0) {
86
+ return
87
+ }
88
+ for (const iconAst of likec4lib.flatMap(l => l.icons)) {
89
+ try {
90
+ docExports.push(this.descriptions.createDescription(iconAst, iconAst.name, document))
91
+ } catch (e) {
92
+ logError(e)
93
+ }
94
+ }
95
+ }
96
+
97
+ private exportSpecification(
98
+ specifications: ast.SpecificationRule[] | undefined,
99
+ docExports: AstNodeDescription[],
100
+ document: LikeC4LangiumDocument
101
+ ) {
102
+ if (isNullish(specifications) || specifications.length === 0) {
103
+ return
104
+ }
105
+ for (
106
+ const spec of specifications.flatMap(s => [
107
+ ...s.elements,
108
+ ...s.relationships,
109
+ ...s.tags
110
+ ])
111
+ ) {
112
+ try {
113
+ switch (true) {
114
+ case ast.isSpecificationElementKind(spec): {
115
+ if (isTruthy(spec.kind.name)) {
116
+ docExports.push(
117
+ this.descriptions.createDescription(spec.kind, spec.kind.name, document)
118
+ )
119
+ }
120
+ continue
85
121
  }
86
- } catch (e) {
87
- logError(e)
122
+ case ast.isSpecificationTag(spec): {
123
+ if (isTruthy(spec.tag.name)) {
124
+ docExports.push(
125
+ this.descriptions.createDescription(spec.tag, '#' + spec.tag.name, document)
126
+ )
127
+ }
128
+ continue
129
+ }
130
+ case ast.isSpecificationRelationshipKind(spec): {
131
+ if (isTruthy(spec.kind.name)) {
132
+ docExports.push(
133
+ this.descriptions.createDescription(spec.kind, spec.kind.name, document),
134
+ this.descriptions.createDescription(spec.kind, '.' + spec.kind.name, document)
135
+ )
136
+ }
137
+ continue
138
+ }
139
+ // Thow error if not exhaustive
140
+ default:
141
+ nonexhaustive(spec)
88
142
  }
143
+ } catch (e) {
144
+ logError(e)
89
145
  }
90
- } catch (e) {
91
- logError(e)
92
146
  }
93
- return docExports
94
147
  }
95
148
 
96
149
  override computeLocalScopes(
@@ -25,6 +25,7 @@ export class NodeKindProvider implements LspNodeKindProvider {
25
25
  return SymbolKind.Class
26
26
  }
27
27
  case (ast.isTag(node) || hasType(ast.Tag))
28
+ || (ast.isLibIcon(node) || hasType(ast.LibIcon))
28
29
  || (ast.isSpecificationTag(node) || hasType(ast.SpecificationTag)): {
29
30
  return SymbolKind.EnumMember
30
31
  }
@@ -1,21 +1,30 @@
1
1
  import { hasAtLeast, invariant } from '@likec4/core'
2
- import type { LangiumDocument } from 'langium'
2
+ import type { LangiumDocument, LangiumDocumentFactory } from 'langium'
3
3
  import { DefaultWorkspaceManager } from 'langium'
4
+ import type { LangiumSharedServices } from 'langium/lsp'
4
5
  import type { WorkspaceFolder } from 'vscode-languageserver'
5
6
  import { URI } from 'vscode-uri'
7
+ import * as BuiltIn from '../likec4lib'
6
8
 
7
9
  export class LikeC4WorkspaceManager extends DefaultWorkspaceManager {
10
+ private documentFactory: LangiumDocumentFactory
11
+
12
+ constructor(services: LangiumSharedServices) {
13
+ super(services)
14
+ this.documentFactory = services.workspace.LangiumDocumentFactory
15
+ }
16
+
8
17
  /**
9
18
  * Load all additional documents that shall be visible in the context of the given workspace
10
19
  * folders and add them to the collector. This can be used to include built-in libraries of
11
20
  * your language, which can be either loaded from provided files or constructed in memory.
12
21
  */
13
- protected override loadAdditionalDocuments(
14
- _folders: WorkspaceFolder[],
15
- _collector: (document: LangiumDocument) => void
22
+ protected override async loadAdditionalDocuments(
23
+ folders: WorkspaceFolder[],
24
+ collector: (document: LangiumDocument) => void
16
25
  ): Promise<void> {
17
- // collector(this.documentFactory.fromString(builtin.specification.document, URI.parse(builtin.specification.uri)))
18
- return Promise.resolve()
26
+ await super.loadAdditionalDocuments(folders, collector)
27
+ collector(this.documentFactory.fromString(BuiltIn.Content, URI.parse(BuiltIn.Uri)))
19
28
  }
20
29
 
21
30
  public workspace() {
@@ -1,33 +1,28 @@
1
1
  import { nonexhaustive } from '@likec4/core'
2
2
  import type { ValidationCheck } from 'langium'
3
3
  import { ast } from '../ast'
4
- import { logError } from '../logger'
5
4
  import type { LikeC4Services } from '../module'
6
5
 
7
- export const dynamicViewRulePredicate = (_services: LikeC4Services): ValidationCheck<ast.DynamicViewRulePredicate> => {
8
- return (el, accept) => {
9
- try {
10
- for (const expr of el.expressions) {
11
- switch (true) {
12
- case ast.isElementRef(expr):
13
- case ast.isDescedantsExpr(expr):
14
- case ast.isCustomElementExpr(expr):
15
- case ast.isExpandElementExpr(expr):
16
- continue
17
- case ast.isElementKindExpr(expr):
18
- case ast.isElementTagExpr(expr):
19
- case ast.isWildcardExpr(expr): {
20
- accept('warning', `Predicate is ignored, as not supported in dynamic views`, {
21
- node: expr
22
- })
23
- continue
24
- }
25
- default:
26
- nonexhaustive(expr)
27
- }
6
+ export const dynamicViewRulePredicate = (
7
+ _services: LikeC4Services
8
+ ): ValidationCheck<ast.DynamicViewRulePredicateIterator> => {
9
+ return (expr, accept) => {
10
+ switch (true) {
11
+ case ast.isElementRef(expr.value):
12
+ case ast.isElementDescedantsExpression(expr.value):
13
+ case ast.isCustomElementExpression(expr.value):
14
+ case ast.isExpandElementExpression(expr.value):
15
+ return
16
+ case ast.isElementKindExpression(expr.value):
17
+ case ast.isElementTagExpression(expr.value):
18
+ case ast.isWildcardExpression(expr.value): {
19
+ accept('warning', `Predicate is ignored, as not supported in dynamic views`, {
20
+ node: expr
21
+ })
22
+ return
28
23
  }
29
- } catch (e) {
30
- logError(e)
24
+ default:
25
+ nonexhaustive(expr.value)
31
26
  }
32
27
  }
33
28
  }
@@ -4,7 +4,7 @@ import type { LikeC4Services } from '../module'
4
4
  import { dynamicViewRulePredicate } from './dynamic-view-rule'
5
5
  import { dynamicViewStep } from './dynamic-view-step'
6
6
  import { elementChecks } from './element'
7
- import { opacityPropertyRuleChecks } from './property-checks'
7
+ import { iconPropertyRuleChecks, opacityPropertyRuleChecks } from './property-checks'
8
8
  import { relationChecks } from './relation'
9
9
  import {
10
10
  elementKindChecks,
@@ -28,6 +28,7 @@ export function registerValidationChecks(services: LikeC4Services) {
28
28
  const registry = services.validation.ValidationRegistry
29
29
  registry.register<ast.LikeC4AstType>({
30
30
  OpacityProperty: opacityPropertyRuleChecks(services),
31
+ IconProperty: iconPropertyRuleChecks(services),
31
32
  SpecificationRule: specificationRuleChecks(services),
32
33
  Model: modelRuleChecks(services),
33
34
  ModelViews: modelViewsChecks(services),
@@ -37,13 +38,13 @@ export function registerValidationChecks(services: LikeC4Services) {
37
38
  ElementKind: elementKindChecks(services),
38
39
  Relation: relationChecks(services),
39
40
  Tag: tagChecks(services),
40
- DynamicViewRulePredicate: dynamicViewRulePredicate(services),
41
- CustomElementExpr: customElementExprChecks(services),
42
- CustomRelationExpr: customRelationExprChecks(services),
43
- ExpandElementExpr: expandElementExprChecks(services),
41
+ DynamicViewRulePredicateIterator: dynamicViewRulePredicate(services),
42
+ CustomElementExpression: customElementExprChecks(services),
43
+ CustomRelationExpression: customRelationExprChecks(services),
44
+ ExpandElementExpression: expandElementExprChecks(services),
44
45
  RelationshipKind: relationshipChecks(services),
45
- IncomingExpr: incomingExpressionChecks(services),
46
- OutgoingExpr: outgoingExpressionChecks(services)
46
+ IncomingRelationExpression: incomingExpressionChecks(services),
47
+ OutgoingRelationExpression: outgoingExpressionChecks(services)
47
48
  })
48
49
  const connection = services.shared.lsp.Connection
49
50
  if (connection) {
@@ -1,5 +1,5 @@
1
1
  import type { ValidationCheck } from 'langium'
2
- import type { ast } from '../ast'
2
+ import { ast } from '../ast'
3
3
  import type { LikeC4Services } from '../module'
4
4
 
5
5
  export const opacityPropertyRuleChecks = (
@@ -15,3 +15,25 @@ export const opacityPropertyRuleChecks = (
15
15
  }
16
16
  }
17
17
  }
18
+
19
+ export const iconPropertyRuleChecks = (
20
+ _: LikeC4Services
21
+ ): ValidationCheck<ast.IconProperty> => {
22
+ return (node, accept) => {
23
+ const container = node.$container
24
+ const anotherIcon = container.props.some(p => ast.isIconProperty(p) && p !== node)
25
+ if (anotherIcon) {
26
+ accept('error', `Icon must be defined once`, {
27
+ node
28
+ })
29
+ }
30
+ if (
31
+ ast.isStyleProperties(container) && ast.isElementBody(container.$container)
32
+ && container.$container.props.some(p => ast.isIconProperty(p))
33
+ ) {
34
+ accept('warning', `Redundant as icon defined on element`, {
35
+ node
36
+ })
37
+ }
38
+ }
39
+ }
@@ -1,25 +1,27 @@
1
1
  import { nonexhaustive } from '@likec4/core'
2
2
  import type { ValidationCheck } from 'langium'
3
+ import { AstUtils } from 'langium'
3
4
  import { ast } from '../../ast'
4
5
  import type { LikeC4Services } from '../../module'
5
6
 
6
7
  export const customElementExprChecks = (
7
8
  _services: LikeC4Services
8
- ): ValidationCheck<ast.CustomElementExpr> => {
9
+ ): ValidationCheck<ast.CustomElementExpression> => {
9
10
  return (el, accept) => {
10
- if (ast.isExcludePredicate(el.$container)) {
11
+ const container = AstUtils.getContainerOfType(el, ast.isViewRulePredicate)
12
+ if (ast.isExcludePredicate(container)) {
11
13
  accept('error', 'Invalid usage inside "exclude"', {
12
14
  node: el
13
15
  })
14
16
  }
15
17
  switch (true) {
16
18
  case ast.isElementRef(el.target):
19
+ case ast.isElementDescedantsExpression(el.target):
20
+ case ast.isExpandElementExpression(el.target):
17
21
  return
18
- case ast.isExpandElementExpr(el.target):
19
- case ast.isElementKindExpr(el.target):
20
- case ast.isElementTagExpr(el.target):
21
- case ast.isWildcardExpr(el.target):
22
- case ast.isDescedantsExpr(el.target):
22
+ case ast.isElementKindExpression(el.target):
23
+ case ast.isElementTagExpression(el.target):
24
+ case ast.isWildcardExpression(el.target):
23
25
  accept('error', 'Invalid target (expect reference to specific element)', {
24
26
  node: el,
25
27
  property: 'target'
@@ -1,12 +1,13 @@
1
- import type { ValidationCheck } from 'langium'
1
+ import { AstUtils, type ValidationCheck } from 'langium'
2
2
  import { ast } from '../../ast'
3
3
  import type { LikeC4Services } from '../../module'
4
4
 
5
5
  export const customRelationExprChecks = (
6
6
  _services: LikeC4Services
7
- ): ValidationCheck<ast.CustomRelationExpr> => {
7
+ ): ValidationCheck<ast.CustomRelationExpression> => {
8
8
  return (el, accept) => {
9
- if (ast.isExcludePredicate(el.$container)) {
9
+ const container = AstUtils.getContainerOfType(el, ast.isViewRulePredicate)
10
+ if (ast.isExcludePredicate(container)) {
10
11
  accept('error', 'Invalid usage inside "exclude"', {
11
12
  node: el
12
13
  })
@@ -1,34 +1,23 @@
1
1
  import { nonexhaustive } from '@likec4/core'
2
- import type { ValidationCheck } from 'langium'
2
+ import { type AstNode, AstUtils, type ValidationCheck } from 'langium'
3
3
  import { ast } from '../../ast'
4
4
  import type { LikeC4Services } from '../../module'
5
5
 
6
6
  export const expandElementExprChecks = (
7
7
  _services: LikeC4Services
8
- ): ValidationCheck<ast.ExpandElementExpr> => {
8
+ ): ValidationCheck<ast.ExpandElementExpression> => {
9
9
  return (el, accept) => {
10
- switch (true) {
11
- case ast.isIncludePredicate(el.$container):
12
- case ast.isDynamicViewRulePredicate(el.$container):
13
- case ast.isViewRuleStyle(el.$container):
14
- return
15
- case ast.isCustomElementExpr(el.$container):
16
- return accept('warning', `Custom rules apply only to parent`, {
17
- node: el
18
- })
19
- case ast.isExcludePredicate(el.$container):
20
- return accept('warning', `Ignored, as can't be used in exclude`, {
21
- node: el
22
- })
23
- case ast.isInOutExpr(el.$container):
24
- case ast.isIncomingExpr(el.$container):
25
- case ast.isOutgoingExpr(el.$container):
26
- case ast.isRelationExpr(el.$container):
27
- return accept('warning', `Wrong usage of expanded element in relations predicate`, {
28
- node: el
29
- })
30
- default:
31
- nonexhaustive(el.$container)
10
+ const isInside = <T extends AstNode>(typePredicate: (n: AstNode) => n is T): boolean =>
11
+ !!AstUtils.getContainerOfType(el, typePredicate)
12
+ if (isInside(ast.isRelationExpression)) {
13
+ accept('warning', `Redundant usage, expand predicate resolves parent element only when used in relations`, {
14
+ node: el
15
+ })
16
+ }
17
+ if (isInside(ast.isExcludePredicate)) {
18
+ accept('warning', `Expand predicate is ignored in exclude`, {
19
+ node: el
20
+ })
32
21
  }
33
22
  }
34
23
  }
@@ -1,15 +1,15 @@
1
- import type { ValidationCheck } from 'langium'
1
+ import { AstUtils, type ValidationCheck } from 'langium'
2
2
  import { isNullish } from 'remeda'
3
3
  import { ast } from '../../ast'
4
4
  import type { LikeC4Services } from '../../module'
5
5
 
6
6
  export const incomingExpressionChecks = (
7
7
  _services: LikeC4Services
8
- ): ValidationCheck<ast.IncomingExpr> => {
8
+ ): ValidationCheck<ast.IncomingRelationExpression> => {
9
9
  return (el, accept) => {
10
- if (ast.isWildcardExpr(el.to) && ast.isViewRulePredicate(el.$container)) {
11
- const view = el.$container.$container.$container
12
- if (isNullish(view.viewOf)) {
10
+ if (ast.isWildcardExpression(el.to) && ast.isExpressions(el.$container)) {
11
+ const view = AstUtils.getContainerOfType(el, ast.isElementView)
12
+ if (isNullish(view?.viewOf)) {
13
13
  accept('warning', 'Predicate is ignored as it concerns all relationships', {
14
14
  node: el
15
15
  })
@@ -1,15 +1,15 @@
1
- import type { ValidationCheck } from 'langium'
1
+ import { AstUtils, type ValidationCheck } from 'langium'
2
2
  import { isNullish } from 'remeda'
3
3
  import { ast } from '../../ast'
4
4
  import type { LikeC4Services } from '../../module'
5
5
 
6
6
  export const outgoingExpressionChecks = (
7
7
  _services: LikeC4Services
8
- ): ValidationCheck<ast.OutgoingExpr> => {
8
+ ): ValidationCheck<ast.OutgoingRelationExpression> => {
9
9
  return (el, accept) => {
10
- if (ast.isWildcardExpr(el.from)) {
11
- const view = el.$container.$container.$container
12
- if (view.$type === 'ElementView' && isNullish(view.viewOf)) {
10
+ if (ast.isWildcardExpression(el.from) && ast.isExpressions(el.$container)) {
11
+ const view = AstUtils.getContainerOfType(el, ast.isElementView)
12
+ if (isNullish(view?.viewOf)) {
13
13
  accept('warning', 'Predicate is ignored as it concerns all relationships', {
14
14
  node: el
15
15
  })