@likec4/language-server 1.21.0 → 1.22.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 (114) hide show
  1. package/README.md +4 -1
  2. package/bin/likec4-language-server.mjs +5 -2
  3. package/dist/LikeC4FileSystem.js +2 -2
  4. package/dist/browser.d.ts +3 -3
  5. package/dist/browser.js +17 -2
  6. package/dist/bundled.d.ts +8 -0
  7. package/dist/bundled.js +25 -0
  8. package/dist/bundled.mjs +2587 -4306
  9. package/dist/generated-lib/icons.js +1 -0
  10. package/dist/index.d.ts +3 -3
  11. package/dist/index.js +23 -2
  12. package/dist/logger.d.ts +9 -3
  13. package/dist/logger.js +35 -55
  14. package/dist/model/fqn-computation.js +2 -2
  15. package/dist/model/model-builder.js +13 -14
  16. package/dist/model-change/ModelChanges.js +2 -2
  17. package/dist/module.js +1 -4
  18. package/dist/references/scope-provider.js +3 -3
  19. package/dist/view-utils/manual-layout.js +2 -2
  20. package/dist/views/configurable-layouter.js +4 -4
  21. package/dist/views/likec4-views.d.ts +2 -1
  22. package/dist/views/likec4-views.js +2 -2
  23. package/package.json +14 -14
  24. package/dist/test/setup.d.ts +0 -1
  25. package/dist/test/setup.js +0 -7
  26. package/src/LikeC4FileSystem.ts +0 -38
  27. package/src/Rpc.ts +0 -134
  28. package/src/ast.ts +0 -556
  29. package/src/browser.ts +0 -35
  30. package/src/documentation/documentation-provider.ts +0 -52
  31. package/src/documentation/index.ts +0 -1
  32. package/src/formatting/LikeC4Formatter.ts +0 -639
  33. package/src/formatting/utils.ts +0 -26
  34. package/src/generated/ast.ts +0 -3735
  35. package/src/generated/grammar.ts +0 -10
  36. package/src/generated/module.ts +0 -33
  37. package/src/generated-lib/icons.ts +0 -1537
  38. package/src/index.ts +0 -30
  39. package/src/like-c4.langium +0 -901
  40. package/src/likec4lib.ts +0 -6
  41. package/src/logger.ts +0 -80
  42. package/src/lsp/CodeLensProvider.ts +0 -50
  43. package/src/lsp/CompletionProvider.ts +0 -147
  44. package/src/lsp/DocumentHighlightProvider.ts +0 -12
  45. package/src/lsp/DocumentLinkProvider.ts +0 -65
  46. package/src/lsp/DocumentSymbolProvider.ts +0 -313
  47. package/src/lsp/HoverProvider.ts +0 -92
  48. package/src/lsp/RenameProvider.ts +0 -8
  49. package/src/lsp/SemanticTokenProvider.ts +0 -383
  50. package/src/lsp/index.ts +0 -8
  51. package/src/model/deployments-index.ts +0 -209
  52. package/src/model/fqn-computation.ts +0 -83
  53. package/src/model/fqn-index.ts +0 -138
  54. package/src/model/index.ts +0 -6
  55. package/src/model/model-builder.ts +0 -724
  56. package/src/model/model-locator.ts +0 -146
  57. package/src/model/model-parser-where.ts +0 -84
  58. package/src/model/model-parser.ts +0 -86
  59. package/src/model/parser/Base.ts +0 -113
  60. package/src/model/parser/DeploymentModelParser.ts +0 -192
  61. package/src/model/parser/DeploymentViewParser.ts +0 -122
  62. package/src/model/parser/FqnRefParser.ts +0 -143
  63. package/src/model/parser/GlobalsParser.ts +0 -96
  64. package/src/model/parser/ModelParser.ts +0 -170
  65. package/src/model/parser/PredicatesParser.ts +0 -315
  66. package/src/model/parser/SpecificationParser.ts +0 -133
  67. package/src/model/parser/ViewsParser.ts +0 -428
  68. package/src/model-change/ModelChanges.ts +0 -101
  69. package/src/model-change/changeElementStyle.ts +0 -172
  70. package/src/model-change/changeViewLayout.ts +0 -47
  71. package/src/model-change/saveManualLayout.ts +0 -41
  72. package/src/module.ts +0 -255
  73. package/src/protocol.ts +0 -93
  74. package/src/references/index.ts +0 -3
  75. package/src/references/name-provider.ts +0 -37
  76. package/src/references/scope-computation.ts +0 -364
  77. package/src/references/scope-provider.ts +0 -201
  78. package/src/shared/NodeKindProvider.ts +0 -121
  79. package/src/shared/WorkspaceManager.ts +0 -48
  80. package/src/shared/WorkspaceSymbolProvider.ts +0 -3
  81. package/src/shared/index.ts +0 -3
  82. package/src/test/index.ts +0 -1
  83. package/src/test/setup.ts +0 -8
  84. package/src/test/testServices.ts +0 -152
  85. package/src/utils/disposable.ts +0 -30
  86. package/src/utils/elementRef.ts +0 -26
  87. package/src/utils/fqnRef.ts +0 -56
  88. package/src/utils/index.ts +0 -2
  89. package/src/utils/printDocs.ts +0 -3
  90. package/src/utils/stringHash.ts +0 -6
  91. package/src/validation/_shared.ts +0 -29
  92. package/src/validation/deployment-checks.ts +0 -131
  93. package/src/validation/dynamic-view-rule.ts +0 -23
  94. package/src/validation/dynamic-view-step.ts +0 -36
  95. package/src/validation/element.ts +0 -56
  96. package/src/validation/index.ts +0 -171
  97. package/src/validation/property-checks.ts +0 -52
  98. package/src/validation/relation.ts +0 -63
  99. package/src/validation/specification.ts +0 -205
  100. package/src/validation/view-predicates/element-with.ts +0 -36
  101. package/src/validation/view-predicates/expanded-element.ts +0 -16
  102. package/src/validation/view-predicates/expression-v2.ts +0 -101
  103. package/src/validation/view-predicates/incoming.ts +0 -20
  104. package/src/validation/view-predicates/index.ts +0 -6
  105. package/src/validation/view-predicates/outgoing.ts +0 -20
  106. package/src/validation/view-predicates/relation-with.ts +0 -17
  107. package/src/validation/view.ts +0 -37
  108. package/src/view-utils/assignNavigateTo.ts +0 -31
  109. package/src/view-utils/index.ts +0 -2
  110. package/src/view-utils/manual-layout.ts +0 -116
  111. package/src/view-utils/resolve-relative-paths.ts +0 -90
  112. package/src/views/configurable-layouter.ts +0 -65
  113. package/src/views/index.ts +0 -1
  114. package/src/views/likec4-views.ts +0 -139
@@ -1,171 +0,0 @@
1
- import { type AstNode, DocumentState } from 'langium'
2
- import { isNullish } from 'remeda'
3
- import { DiagnosticSeverity } from 'vscode-languageserver-types'
4
- import { type LikeC4AstNode, type LikeC4LangiumDocument, ast } from '../ast'
5
- import { logger } from '../logger'
6
- import type { LikeC4Services } from '../module'
7
- import { deployedInstanceChecks, deploymentNodeChecks, deploymentRelationChecks } from './deployment-checks'
8
- import { dynamicViewRulePredicate } from './dynamic-view-rule'
9
- import { dynamicViewStep } from './dynamic-view-step'
10
- import { elementChecks } from './element'
11
- import { iconPropertyRuleChecks, notesPropertyRuleChecks, opacityPropertyRuleChecks } from './property-checks'
12
- import { relationBodyChecks, relationChecks } from './relation'
13
- import {
14
- deploymentNodeKindChecks,
15
- elementKindChecks,
16
- globalPredicateChecks,
17
- globalsChecks,
18
- globalStyleIdChecks,
19
- modelRuleChecks,
20
- relationshipChecks,
21
- specificationRuleChecks,
22
- tagChecks,
23
- } from './specification'
24
- import { viewChecks } from './view'
25
- import {
26
- elementPredicateWithChecks,
27
- expandElementExprChecks,
28
- fqnRefExprChecks,
29
- incomingExpressionChecks,
30
- outgoingExpressionChecks,
31
- relationExprChecks,
32
- relationPredicateWithChecks,
33
- } from './view-predicates'
34
-
35
- type Guard<N extends AstNode> = (n: AstNode) => n is N
36
- type Guarded<G> = G extends Guard<infer N> ? N : never
37
-
38
- function validatableAstNodeGuards<const Predicates extends Guard<AstNode>[]>(
39
- predicates: Predicates,
40
- ) {
41
- return (n: AstNode): n is Guarded<Predicates[number]> => predicates.some(p => p(n))
42
- }
43
- const isValidatableAstNode = validatableAstNodeGuards([
44
- ast.isGlobals,
45
- ast.isGlobalPredicateGroup,
46
- ast.isGlobalDynamicPredicateGroup,
47
- ast.isGlobalStyle,
48
- ast.isGlobalStyleGroup,
49
- ast.isDynamicViewPredicateIterator,
50
- ast.isElementPredicateWith,
51
- ast.isRelationPredicateWith,
52
- ast.isElementExpression,
53
- ast.isRelationExpression,
54
- ast.isDynamicViewParallelSteps,
55
- ast.isDynamicViewStep,
56
- ast.isDeploymentViewRule,
57
- ast.isDeploymentViewRulePredicate,
58
- ast.isExpressionV2,
59
- ast.isRelationExpr,
60
- ast.isFqnRefExpr,
61
- ast.isViewProperty,
62
- ast.isStyleProperty,
63
- ast.isPredicate,
64
- ast.isTags,
65
- ast.isViewRule,
66
- ast.isDynamicViewRule,
67
- ast.isLikeC4View,
68
- ast.isViewRuleStyleOrGlobalRef,
69
- ast.isDeployedInstance,
70
- ast.isDeploymentNode,
71
- ast.isDeploymentRelation,
72
- ast.isRelationshipStyleProperty,
73
- ast.isMetadataProperty,
74
- ast.isRelation,
75
- ast.isElementProperty,
76
- ast.isStringProperty,
77
- ast.isNavigateToProperty,
78
- ast.isElement,
79
- ast.isExtendElement,
80
- ast.isSpecificationElementKind,
81
- ast.isSpecificationRelationshipKind,
82
- ast.isSpecificationDeploymentNodeKind,
83
- ast.isSpecificationTag,
84
- ast.isSpecificationColor,
85
- ast.isSpecificationRule,
86
- ])
87
- type ValidatableAstNode = Guarded<typeof isValidatableAstNode>
88
-
89
- const findInvalidContainer = (node: LikeC4AstNode): ValidatableAstNode | undefined => {
90
- let nd = node as LikeC4AstNode['$container']
91
- while (nd && !ast.isLikeC4Grammar(nd)) {
92
- if (isValidatableAstNode(nd)) {
93
- return nd
94
- }
95
- nd = nd.$container
96
- }
97
- return undefined
98
- }
99
-
100
- export function checksFromDiagnostics(doc: LikeC4LangiumDocument) {
101
- const errors = doc.state >= DocumentState.Validated
102
- ? (doc.diagnostics?.filter(d => d.severity === DiagnosticSeverity.Error) ?? [])
103
- : []
104
- const invalidNodes = new WeakSet()
105
- for (const { node } of errors) {
106
- if (isNullish(node) || invalidNodes.has(node)) {
107
- continue
108
- }
109
- invalidNodes.add(node)
110
- const container = findInvalidContainer(node)
111
- if (container) {
112
- invalidNodes.add(container)
113
- }
114
- }
115
- const isValid = (n: ValidatableAstNode) => !invalidNodes.has(n)
116
- return {
117
- isValid,
118
- invalidNodes,
119
- }
120
- }
121
- export type ChecksFromDiagnostics = ReturnType<typeof checksFromDiagnostics>
122
- export type IsValidFn = ChecksFromDiagnostics['isValid']
123
-
124
- export function registerValidationChecks(services: LikeC4Services) {
125
- logger.debug('registerValidationChecks')
126
- const registry = services.validation.ValidationRegistry
127
- registry.register<ast.LikeC4AstType>({
128
- DeployedInstance: deployedInstanceChecks(services),
129
- DeploymentNodeKind: deploymentNodeKindChecks(services),
130
- DeploymentNode: deploymentNodeChecks(services),
131
- DeploymentRelation: deploymentRelationChecks(services),
132
- FqnRefExpr: fqnRefExprChecks(services),
133
- RelationExpr: relationExprChecks(services),
134
- NotesProperty: notesPropertyRuleChecks(services),
135
- OpacityProperty: opacityPropertyRuleChecks(services),
136
- IconProperty: iconPropertyRuleChecks(services),
137
- SpecificationRule: specificationRuleChecks(services),
138
- Model: modelRuleChecks(services),
139
- Globals: globalsChecks(services),
140
- GlobalPredicateGroup: globalPredicateChecks(services),
141
- GlobalDynamicPredicateGroup: globalPredicateChecks(services),
142
- GlobalStyleId: globalStyleIdChecks(services),
143
- DynamicViewStep: dynamicViewStep(services),
144
- LikeC4View: viewChecks(services),
145
- Element: elementChecks(services),
146
- ElementKind: elementKindChecks(services),
147
- Relation: relationChecks(services),
148
- RelationBody: relationBodyChecks(services),
149
- Tag: tagChecks(services),
150
- DynamicViewPredicateIterator: dynamicViewRulePredicate(services),
151
- ElementPredicateWith: elementPredicateWithChecks(services),
152
- RelationPredicateWith: relationPredicateWithChecks(services),
153
- ExpandElementExpression: expandElementExprChecks(services),
154
- RelationshipKind: relationshipChecks(services),
155
- IncomingRelationExpression: incomingExpressionChecks(services),
156
- OutgoingRelationExpression: outgoingExpressionChecks(services),
157
- })
158
- const connection = services.shared.lsp.Connection
159
- if (connection) {
160
- // workaround for bug in langium
161
- services.shared.workspace.DocumentBuilder.onUpdate((_, deleted) => {
162
- for (const uri of deleted) {
163
- logger.debug(`clear diagnostics for deleted ${uri.path}`)
164
- void connection.sendDiagnostics({
165
- uri: uri.toString(),
166
- diagnostics: [],
167
- })
168
- }
169
- })
170
- }
171
- }
@@ -1,52 +0,0 @@
1
- import { type ValidationCheck, AstUtils } from 'langium'
2
- import { ast } from '../ast'
3
- import type { LikeC4Services } from '../module'
4
- import { tryOrLog } from './_shared'
5
-
6
- export const opacityPropertyRuleChecks = (
7
- _: LikeC4Services,
8
- ): ValidationCheck<ast.OpacityProperty> => {
9
- return tryOrLog((node, accept) => {
10
- const opacity = parseFloat(node.value)
11
- if (isNaN(opacity) || opacity < 0 || opacity > 100) {
12
- accept('warning', `Value ignored, must be between 0% and 100%`, {
13
- node,
14
- property: 'value',
15
- })
16
- }
17
- })
18
- }
19
-
20
- export const iconPropertyRuleChecks = (
21
- _: LikeC4Services,
22
- ): ValidationCheck<ast.IconProperty> => {
23
- return (node, accept) => {
24
- const container = node.$container
25
- const anotherIcon = container.props.some(p => ast.isIconProperty(p) && p !== node)
26
- if (anotherIcon) {
27
- accept('error', `Icon must be defined once`, {
28
- node,
29
- })
30
- }
31
- if (
32
- ast.isElementStyleProperty(container) && ast.isElementBody(container.$container)
33
- && container.$container.props.some(p => ast.isIconProperty(p))
34
- ) {
35
- accept('warning', `Redundant as icon defined on element`, {
36
- node,
37
- })
38
- }
39
- }
40
- }
41
-
42
- export const notesPropertyRuleChecks = (
43
- _: LikeC4Services,
44
- ): ValidationCheck<ast.NotesProperty> => {
45
- return (node, accept) => {
46
- if (!AstUtils.hasContainerOfType(node, ast.isDynamicViewStep)) {
47
- accept('error', `Notes can be defined only inside dynamic view`, {
48
- node,
49
- })
50
- }
51
- }
52
- }
@@ -1,63 +0,0 @@
1
- import { isSameHierarchy } from '@likec4/core'
2
- import type { ValidationCheck } from 'langium'
3
- import { isDefined } from 'remeda'
4
- import { ast } from '../ast'
5
- import type { LikeC4Services } from '../module'
6
- import { elementRef } from '../utils/elementRef'
7
- import { tryOrLog } from './_shared'
8
-
9
- export const relationChecks = (services: LikeC4Services): ValidationCheck<ast.Relation> => {
10
- const fqnIndex = services.likec4.FqnIndex
11
- return tryOrLog((el, accept) => {
12
- const targetEl: ast.Element | undefined = elementRef(el.target)
13
- const target = targetEl && fqnIndex.getFqn(targetEl)
14
- if (!target) {
15
- accept('error', 'Target not resolved', {
16
- node: el,
17
- property: 'target'
18
- })
19
- }
20
- let sourceEl
21
- if (isDefined(el.source)) {
22
- sourceEl = elementRef(el.source)
23
- if (!sourceEl) {
24
- return accept('error', 'Source not resolved', {
25
- node: el,
26
- property: 'source'
27
- })
28
- }
29
- } else {
30
- if (!ast.isElementBody(el.$container)) {
31
- return accept('error', 'Sourceless relation must be nested', {
32
- node: el
33
- })
34
- }
35
- sourceEl = el.$container.$container
36
- }
37
-
38
- const source = fqnIndex.getFqn(sourceEl)
39
-
40
- if (!source) {
41
- accept('error', 'Source not resolved', {
42
- node: el
43
- })
44
- }
45
-
46
- if (source && target && isSameHierarchy(source, target)) {
47
- accept('error', 'Invalid parent-child relationship', {
48
- node: el
49
- })
50
- }
51
- })
52
- }
53
-
54
- export const relationBodyChecks = (_services: LikeC4Services): ValidationCheck<ast.RelationBody> => {
55
- return tryOrLog((body, accept) => {
56
- const relation = body.$container
57
- if (relation.tags?.values && body.tags?.values) {
58
- accept('error', 'Relation cannot have tags in both header and body', {
59
- node: body.tags
60
- })
61
- }
62
- })
63
- }
@@ -1,205 +0,0 @@
1
- import { type ValidationCheck, AstUtils } from 'langium'
2
- import { ast } from '../ast'
3
- import type { LikeC4Services } from '../module'
4
- import { RESERVED_WORDS, tryOrLog } from './_shared'
5
-
6
- export const specificationRuleChecks = (
7
- _: LikeC4Services,
8
- ): ValidationCheck<ast.SpecificationRule> => {
9
- return tryOrLog((node, accept) => {
10
- if (node.$containerIndex && node.$containerIndex > 0) {
11
- accept('warning', `Prefer one specification per document`, {
12
- node: node,
13
- property: 'name',
14
- })
15
- }
16
- })
17
- }
18
-
19
- export const modelRuleChecks = (_: LikeC4Services): ValidationCheck<ast.Model> => {
20
- return tryOrLog((node, accept) => {
21
- if (node.$containerIndex && node.$containerIndex > 0) {
22
- accept('warning', `Prefer one model per document`, {
23
- node: node,
24
- property: 'name',
25
- })
26
- }
27
- })
28
- }
29
-
30
- export const globalsChecks = (_: LikeC4Services): ValidationCheck<ast.Globals> => {
31
- return tryOrLog((node, accept) => {
32
- if (node.$containerIndex && node.$containerIndex > 0) {
33
- accept('warning', `Prefer one global block per document`, {
34
- node: node,
35
- property: 'name',
36
- })
37
- }
38
- })
39
- }
40
-
41
- export const elementKindChecks = (services: LikeC4Services): ValidationCheck<ast.ElementKind> => {
42
- const index = services.shared.workspace.IndexManager
43
- return tryOrLog((node, accept) => {
44
- if (RESERVED_WORDS.includes(node.name)) {
45
- accept('error', `Reserved word: ${node.name}`, {
46
- node: node,
47
- property: 'name',
48
- })
49
- }
50
- const sameKind = index
51
- .allElements(ast.ElementKind)
52
- .filter(n => n.name === node.name && n.node !== node)
53
- .head()
54
- if (sameKind) {
55
- const isAnotherDoc = sameKind.documentUri !== AstUtils.getDocument(node).uri
56
- accept('error', `Duplicate element kind '${node.name}'`, {
57
- node: node,
58
- property: 'name',
59
- ...isAnotherDoc && {
60
- relatedInformation: [
61
- {
62
- location: {
63
- range: sameKind.nameSegment!.range,
64
- uri: sameKind.documentUri.toString(),
65
- },
66
- message: `conflicting definition`,
67
- },
68
- ],
69
- },
70
- })
71
- }
72
- })
73
- }
74
-
75
- export const deploymentNodeKindChecks = (services: LikeC4Services): ValidationCheck<ast.DeploymentNodeKind> => {
76
- const index = services.shared.workspace.IndexManager
77
- return tryOrLog((node, accept) => {
78
- if (RESERVED_WORDS.includes(node.name)) {
79
- accept('error', `Reserved word: ${node.name}`, {
80
- node: node,
81
- property: 'name',
82
- })
83
- }
84
- const sameKind = index
85
- .allElements(ast.DeploymentNodeKind)
86
- .filter(n => n.name === node.name && n.node !== node)
87
- .head()
88
- if (sameKind) {
89
- const isAnotherDoc = sameKind.documentUri !== AstUtils.getDocument(node).uri
90
- accept('error', `Duplicate deploymentNode kind '${node.name}'`, {
91
- node: node,
92
- property: 'name',
93
- ...isAnotherDoc && {
94
- relatedInformation: [
95
- {
96
- location: {
97
- range: sameKind.nameSegment!.range,
98
- uri: sameKind.documentUri.toString(),
99
- },
100
- message: `conflicting definition`,
101
- },
102
- ],
103
- },
104
- })
105
- }
106
- })
107
- }
108
-
109
- export const tagChecks = (services: LikeC4Services): ValidationCheck<ast.Tag> => {
110
- const index = services.shared.workspace.IndexManager
111
- return tryOrLog((node, accept) => {
112
- const tagname = '#' + node.name
113
- const sameTag = index
114
- .allElements(ast.Tag)
115
- .filter(n => n.name === tagname && n.node !== node)
116
- .head()
117
- if (sameTag) {
118
- const isAnotherDoc = sameTag.documentUri !== AstUtils.getDocument(node).uri
119
- accept(
120
- 'error',
121
- `Duplicate tag '${node.name}'`,
122
- {
123
- node,
124
- property: 'name',
125
- ...isAnotherDoc && {
126
- relatedInformation: [
127
- {
128
- location: {
129
- range: sameTag.nameSegment!.range,
130
- uri: sameTag.documentUri.toString(),
131
- },
132
- message: `conflicting definition`,
133
- },
134
- ],
135
- },
136
- },
137
- )
138
- }
139
- })
140
- }
141
-
142
- export const relationshipChecks = (
143
- services: LikeC4Services,
144
- ): ValidationCheck<ast.RelationshipKind> => {
145
- const index = services.shared.workspace.IndexManager
146
- return tryOrLog((node, accept) => {
147
- if (RESERVED_WORDS.includes(node.name)) {
148
- accept('error', `Reserved word: ${node.name}`, {
149
- node: node,
150
- property: 'name',
151
- })
152
- }
153
- const sameKinds = index
154
- .allElements(ast.RelationshipKind)
155
- .filter(n => n.name === node.name)
156
- .limit(2)
157
- .count()
158
- if (sameKinds > 1) {
159
- accept('error', `Duplicate RelationshipKind '${node.name}'`, {
160
- node: node,
161
- property: 'name',
162
- })
163
- }
164
- })
165
- }
166
-
167
- export const globalPredicateChecks = (
168
- services: LikeC4Services,
169
- ): ValidationCheck<ast.GlobalPredicateGroup | ast.GlobalDynamicPredicateGroup> => {
170
- const index = services.shared.workspace.IndexManager
171
- return tryOrLog((node, accept) => {
172
- const predicateGroups = index.allElements(ast.GlobalPredicateGroup)
173
- const dynamicPredicateGroups = index.allElements(ast.GlobalDynamicPredicateGroup)
174
- const sameName = predicateGroups
175
- .concat(dynamicPredicateGroups)
176
- .filter(s => s.name === node.name)
177
- .limit(2)
178
- .count()
179
- if (sameName > 1) {
180
- accept('error', `Duplicate GlobalPredicateGroup or GlobalDynamicPredicateGroup name '${node.name}'`, {
181
- node: node,
182
- property: 'name',
183
- })
184
- }
185
- })
186
- }
187
-
188
- export const globalStyleIdChecks = (
189
- services: LikeC4Services,
190
- ): ValidationCheck<ast.GlobalStyleId> => {
191
- const index = services.shared.workspace.IndexManager
192
- return tryOrLog((node, accept) => {
193
- const sameName = index
194
- .allElements(ast.GlobalStyleId)
195
- .filter(s => s.name === node.name)
196
- .limit(2)
197
- .count()
198
- if (sameName > 1) {
199
- accept('error', `Duplicate GlobalStyleId name '${node.name}'`, {
200
- node: node,
201
- property: 'name',
202
- })
203
- }
204
- })
205
- }
@@ -1,36 +0,0 @@
1
- import { nonexhaustive } from '@likec4/core'
2
- import type { ValidationCheck } from 'langium'
3
- import { AstUtils } from 'langium'
4
- import { ast } from '../../ast'
5
- import type { LikeC4Services } from '../../module'
6
- import { tryOrLog } from '../_shared'
7
-
8
- export const elementPredicateWithChecks = (
9
- _services: LikeC4Services,
10
- ): ValidationCheck<ast.ElementPredicateWith> => {
11
- return tryOrLog((el, accept) => {
12
- const container = AstUtils.getContainerOfType(el, ast.isViewRulePredicate)
13
- if (ast.isExcludePredicate(container)) {
14
- accept('error', 'Invalid usage inside "exclude"', {
15
- node: el,
16
- })
17
- }
18
- const subject = ast.isElementPredicateWhere(el.subject) ? el.subject.subject : el.subject
19
- switch (true) {
20
- case ast.isElementRef(subject):
21
- case ast.isElementDescedantsExpression(subject):
22
- case ast.isExpandElementExpression(subject):
23
- case ast.isWildcardExpression(subject):
24
- return
25
- case ast.isElementKindExpression(subject):
26
- case ast.isElementTagExpression(subject):
27
- accept('error', 'Invalid target (expect reference to specific element)', {
28
- node: el,
29
- property: 'subject',
30
- })
31
- return
32
- default:
33
- nonexhaustive(subject)
34
- }
35
- })
36
- }
@@ -1,16 +0,0 @@
1
- import { type ValidationCheck, AstUtils } from 'langium'
2
- import { ast } from '../../ast'
3
- import type { LikeC4Services } from '../../module'
4
- import { tryOrLog } from '../_shared'
5
-
6
- export const expandElementExprChecks = (
7
- _services: LikeC4Services,
8
- ): ValidationCheck<ast.ExpandElementExpression> => {
9
- return tryOrLog((el, accept) => {
10
- if (AstUtils.hasContainerOfType(el, ast.isRelationExpression)) {
11
- accept('warning', `Redundant usage, expand predicate resolves parent element only when used in relations`, {
12
- node: el,
13
- })
14
- }
15
- })
16
- }
@@ -1,101 +0,0 @@
1
- import { FqnExpr, FqnRef } from '@likec4/core'
2
- import { AstUtils, type ValidationCheck } from 'langium'
3
- import { isNonNullish, isNullish } from 'remeda'
4
- import { ast } from '../../ast'
5
- import type { LikeC4Services } from '../../module'
6
- import { tryOrLog } from '../_shared'
7
-
8
- export const relationExprChecks = (services: LikeC4Services): ValidationCheck<ast.RelationExpr> => {
9
- const ModelParser = services.likec4.ModelParser
10
- return tryOrLog((node, accept) => {
11
- if (node.$container.$type !== 'DeploymentViewRulePredicateExpression') {
12
- // skip validation for this node, validated by container
13
- return
14
- }
15
-
16
- const predicate = AstUtils.getContainerOfType(node, ast.isDeploymentViewRulePredicate)
17
- if (!predicate || predicate.isInclude !== true) {
18
- // no restriction for exclude predicate
19
- return
20
- }
21
-
22
- const doc = AstUtils.getDocument(node)
23
- const parser = ModelParser.forDocument(doc)
24
-
25
- const ModelRefOnlyExclude = 'Model reference is allowed in exclude predicate only'
26
-
27
- if (ast.isDirectedRelationExpr(node)) {
28
- if (FqnExpr.isModelRef(parser.parseFqnExpr(node.source.from))) {
29
- accept('error', ModelRefOnlyExclude, {
30
- node: node.source,
31
- property: 'from'
32
- })
33
- }
34
-
35
- if (FqnExpr.isModelRef(parser.parseFqnExpr(node.target))) {
36
- accept('error', ModelRefOnlyExclude, {
37
- node,
38
- property: 'target'
39
- })
40
- }
41
- return
42
- }
43
-
44
- let expr: ast.FqnExpr
45
- if (ast.isIncomingRelationExpr(node)) {
46
- expr = node.to
47
- } else if (ast.isOutgoingRelationExpr(node)) {
48
- expr = node.from
49
- } else {
50
- expr = node.inout.to
51
- }
52
- if (FqnExpr.isModelRef(parser.parseFqnExpr(expr))) {
53
- accept('error', ModelRefOnlyExclude, {
54
- node
55
- })
56
- return
57
- }
58
- })
59
- }
60
-
61
- export const fqnRefExprChecks = (services: LikeC4Services): ValidationCheck<ast.FqnRefExpr> => {
62
- const ModelParser = services.likec4.ModelParser
63
- // const DeploymentsIndex = services.likec4.DeploymentsIndex
64
- // const Names = services.references.NameProvider as LikeC4NameProvider
65
- // const Locator = services.workspace.AstNodeLocator
66
- // const fqnIndex = services.likec4.FqnIndex
67
- return tryOrLog((node, accept) => {
68
- const referenceTo = node.ref.value.ref
69
- if (isNullish(referenceTo)) {
70
- accept('error', 'Invalid empty reference', {
71
- node
72
- })
73
- return
74
- }
75
- const doc = AstUtils.getDocument(node)
76
- const expr = ModelParser.forDocument(doc).parseFqnRefExpr(node)
77
-
78
- // This expression is part of element predicate
79
- if (node.$container.$type === 'DeploymentViewRulePredicateExpression') {
80
- if (FqnExpr.isModelRef(expr)) {
81
- accept('error', 'Deployment view predicate must reference deployment model', {
82
- node
83
- })
84
- return
85
- }
86
- if (FqnExpr.isDeploymentRef(expr) && FqnRef.isInsideInstanceRef(expr.ref)) {
87
- accept('error', 'Must reference deployment nodes or instances, but not internals', {
88
- node
89
- })
90
- return
91
- }
92
- }
93
-
94
- if (!ast.isDeploymentNode(referenceTo) && isNonNullish(node.selector)) {
95
- accept('warning', `Selector '${node.selector}' applies to deployment nodes only, ignored here`, {
96
- node,
97
- property: 'selector'
98
- })
99
- }
100
- })
101
- }
@@ -1,20 +0,0 @@
1
- import { type ValidationCheck, AstUtils } from 'langium'
2
- import { isNullish } from 'remeda'
3
- import { ast } from '../../ast'
4
- import type { LikeC4Services } from '../../module'
5
- import { tryOrLog } from '../_shared'
6
-
7
- export const incomingExpressionChecks = (
8
- _services: LikeC4Services,
9
- ): ValidationCheck<ast.IncomingRelationExpression> => {
10
- return tryOrLog((el, accept) => {
11
- if (ast.isWildcardExpression(el.to) && !ast.isInOutRelationExpression(el.$container)) {
12
- const view = AstUtils.getContainerOfType(el, ast.isElementView)
13
- if (isNullish(view?.viewOf)) {
14
- accept('warning', 'Predicate is ignored as it concerns all relationships', {
15
- node: el,
16
- })
17
- }
18
- }
19
- })
20
- }
@@ -1,6 +0,0 @@
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,20 +0,0 @@
1
- import { type ValidationCheck, AstUtils } from 'langium'
2
- import { isNullish } from 'remeda'
3
- import { ast } from '../../ast'
4
- import type { LikeC4Services } from '../../module'
5
- import { tryOrLog } from '../_shared'
6
-
7
- export const outgoingExpressionChecks = (
8
- _services: LikeC4Services,
9
- ): ValidationCheck<ast.OutgoingRelationExpression> => {
10
- return tryOrLog((el, accept) => {
11
- if (ast.isWildcardExpression(el.from) && !ast.isDirectedRelationExpression(el.$container)) {
12
- const view = AstUtils.getContainerOfType(el, ast.isElementView)
13
- if (isNullish(view?.viewOf)) {
14
- accept('warning', 'Predicate is ignored as it concerns all relationships', {
15
- node: el,
16
- })
17
- }
18
- }
19
- })
20
- }