@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.
- package/README.md +4 -1
- package/bin/likec4-language-server.mjs +5 -2
- package/dist/LikeC4FileSystem.js +2 -2
- package/dist/browser.d.ts +3 -3
- package/dist/browser.js +17 -2
- package/dist/bundled.d.ts +8 -0
- package/dist/bundled.js +25 -0
- package/dist/bundled.mjs +2587 -4306
- package/dist/generated-lib/icons.js +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +23 -2
- package/dist/logger.d.ts +9 -3
- package/dist/logger.js +35 -55
- package/dist/model/fqn-computation.js +2 -2
- package/dist/model/model-builder.js +13 -14
- package/dist/model-change/ModelChanges.js +2 -2
- package/dist/module.js +1 -4
- package/dist/references/scope-provider.js +3 -3
- package/dist/view-utils/manual-layout.js +2 -2
- package/dist/views/configurable-layouter.js +4 -4
- package/dist/views/likec4-views.d.ts +2 -1
- package/dist/views/likec4-views.js +2 -2
- package/package.json +14 -14
- package/dist/test/setup.d.ts +0 -1
- package/dist/test/setup.js +0 -7
- package/src/LikeC4FileSystem.ts +0 -38
- package/src/Rpc.ts +0 -134
- package/src/ast.ts +0 -556
- package/src/browser.ts +0 -35
- package/src/documentation/documentation-provider.ts +0 -52
- package/src/documentation/index.ts +0 -1
- package/src/formatting/LikeC4Formatter.ts +0 -639
- package/src/formatting/utils.ts +0 -26
- package/src/generated/ast.ts +0 -3735
- package/src/generated/grammar.ts +0 -10
- package/src/generated/module.ts +0 -33
- package/src/generated-lib/icons.ts +0 -1537
- package/src/index.ts +0 -30
- package/src/like-c4.langium +0 -901
- package/src/likec4lib.ts +0 -6
- package/src/logger.ts +0 -80
- package/src/lsp/CodeLensProvider.ts +0 -50
- package/src/lsp/CompletionProvider.ts +0 -147
- package/src/lsp/DocumentHighlightProvider.ts +0 -12
- package/src/lsp/DocumentLinkProvider.ts +0 -65
- package/src/lsp/DocumentSymbolProvider.ts +0 -313
- package/src/lsp/HoverProvider.ts +0 -92
- package/src/lsp/RenameProvider.ts +0 -8
- package/src/lsp/SemanticTokenProvider.ts +0 -383
- package/src/lsp/index.ts +0 -8
- package/src/model/deployments-index.ts +0 -209
- package/src/model/fqn-computation.ts +0 -83
- package/src/model/fqn-index.ts +0 -138
- package/src/model/index.ts +0 -6
- package/src/model/model-builder.ts +0 -724
- package/src/model/model-locator.ts +0 -146
- package/src/model/model-parser-where.ts +0 -84
- package/src/model/model-parser.ts +0 -86
- package/src/model/parser/Base.ts +0 -113
- package/src/model/parser/DeploymentModelParser.ts +0 -192
- package/src/model/parser/DeploymentViewParser.ts +0 -122
- package/src/model/parser/FqnRefParser.ts +0 -143
- package/src/model/parser/GlobalsParser.ts +0 -96
- package/src/model/parser/ModelParser.ts +0 -170
- package/src/model/parser/PredicatesParser.ts +0 -315
- package/src/model/parser/SpecificationParser.ts +0 -133
- package/src/model/parser/ViewsParser.ts +0 -428
- package/src/model-change/ModelChanges.ts +0 -101
- package/src/model-change/changeElementStyle.ts +0 -172
- package/src/model-change/changeViewLayout.ts +0 -47
- package/src/model-change/saveManualLayout.ts +0 -41
- package/src/module.ts +0 -255
- package/src/protocol.ts +0 -93
- package/src/references/index.ts +0 -3
- package/src/references/name-provider.ts +0 -37
- package/src/references/scope-computation.ts +0 -364
- package/src/references/scope-provider.ts +0 -201
- package/src/shared/NodeKindProvider.ts +0 -121
- package/src/shared/WorkspaceManager.ts +0 -48
- package/src/shared/WorkspaceSymbolProvider.ts +0 -3
- package/src/shared/index.ts +0 -3
- package/src/test/index.ts +0 -1
- package/src/test/setup.ts +0 -8
- package/src/test/testServices.ts +0 -152
- package/src/utils/disposable.ts +0 -30
- package/src/utils/elementRef.ts +0 -26
- package/src/utils/fqnRef.ts +0 -56
- package/src/utils/index.ts +0 -2
- package/src/utils/printDocs.ts +0 -3
- package/src/utils/stringHash.ts +0 -6
- package/src/validation/_shared.ts +0 -29
- package/src/validation/deployment-checks.ts +0 -131
- package/src/validation/dynamic-view-rule.ts +0 -23
- package/src/validation/dynamic-view-step.ts +0 -36
- package/src/validation/element.ts +0 -56
- package/src/validation/index.ts +0 -171
- package/src/validation/property-checks.ts +0 -52
- package/src/validation/relation.ts +0 -63
- package/src/validation/specification.ts +0 -205
- package/src/validation/view-predicates/element-with.ts +0 -36
- package/src/validation/view-predicates/expanded-element.ts +0 -16
- package/src/validation/view-predicates/expression-v2.ts +0 -101
- package/src/validation/view-predicates/incoming.ts +0 -20
- package/src/validation/view-predicates/index.ts +0 -6
- package/src/validation/view-predicates/outgoing.ts +0 -20
- package/src/validation/view-predicates/relation-with.ts +0 -17
- package/src/validation/view.ts +0 -37
- package/src/view-utils/assignNavigateTo.ts +0 -31
- package/src/view-utils/index.ts +0 -2
- package/src/view-utils/manual-layout.ts +0 -116
- package/src/view-utils/resolve-relative-paths.ts +0 -90
- package/src/views/configurable-layouter.ts +0 -65
- package/src/views/index.ts +0 -1
- package/src/views/likec4-views.ts +0 -139
|
@@ -1,122 +0,0 @@
|
|
|
1
|
-
import type * as c4 from '@likec4/core'
|
|
2
|
-
import { invariant, isNonEmptyArray, nonexhaustive } from '@likec4/core'
|
|
3
|
-
import { isNonNullish } from 'remeda'
|
|
4
|
-
import { type ParsedAstDeploymentView, ast, toAutoLayout, toElementStyle, ViewOps } from '../../ast'
|
|
5
|
-
import { logWarnError } from '../../logger'
|
|
6
|
-
import { stringHash } from '../../utils'
|
|
7
|
-
import { parseViewManualLayout } from '../../view-utils/manual-layout'
|
|
8
|
-
import { removeIndent, toSingleLine } from './Base'
|
|
9
|
-
import type { WithDeploymentModel } from './DeploymentModelParser'
|
|
10
|
-
import type { WithExpressionV2 } from './FqnRefParser'
|
|
11
|
-
|
|
12
|
-
export type WithDeploymentView = ReturnType<typeof DeploymentViewParser>
|
|
13
|
-
|
|
14
|
-
export function DeploymentViewParser<TBase extends WithExpressionV2 & WithDeploymentModel>(B: TBase) {
|
|
15
|
-
return class DeploymentViewParser extends B {
|
|
16
|
-
parseDeploymentView(
|
|
17
|
-
astNode: ast.DeploymentView,
|
|
18
|
-
): ParsedAstDeploymentView {
|
|
19
|
-
const body = astNode.body
|
|
20
|
-
invariant(body, 'DynamicElementView body is not defined')
|
|
21
|
-
// only valid props
|
|
22
|
-
const props = body.props.filter(this.isValid)
|
|
23
|
-
const astPath = this.getAstNodePath(astNode)
|
|
24
|
-
|
|
25
|
-
let id = astNode.name
|
|
26
|
-
if (!id) {
|
|
27
|
-
id = 'deployment_' + stringHash(
|
|
28
|
-
this.doc.uri.toString(),
|
|
29
|
-
astPath,
|
|
30
|
-
) as c4.ViewId
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
const title = toSingleLine(props.find(p => p.key === 'title')?.value) ?? null
|
|
34
|
-
const description = removeIndent(props.find(p => p.key === 'description')?.value) ?? null
|
|
35
|
-
|
|
36
|
-
const tags = this.convertTags(body)
|
|
37
|
-
const links = this.convertLinks(body)
|
|
38
|
-
|
|
39
|
-
ViewOps.writeId(astNode, id as c4.ViewId)
|
|
40
|
-
|
|
41
|
-
const manualLayout = parseViewManualLayout(astNode)
|
|
42
|
-
|
|
43
|
-
return {
|
|
44
|
-
__: 'deployment',
|
|
45
|
-
id: id as c4.ViewId,
|
|
46
|
-
astPath,
|
|
47
|
-
title,
|
|
48
|
-
description,
|
|
49
|
-
tags,
|
|
50
|
-
links: isNonEmptyArray(links) ? links : null,
|
|
51
|
-
rules: body.rules.flatMap(n => {
|
|
52
|
-
try {
|
|
53
|
-
return this.isValid(n) ? this.parseDeploymentViewRule(n) : []
|
|
54
|
-
} catch (e) {
|
|
55
|
-
logWarnError(e)
|
|
56
|
-
return []
|
|
57
|
-
}
|
|
58
|
-
}),
|
|
59
|
-
...(manualLayout && { manualLayout }),
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
parseDeploymentViewRule(astRule: ast.DeploymentViewRule): c4.DeploymentViewRule {
|
|
64
|
-
if (ast.isDeploymentViewRulePredicate(astRule)) {
|
|
65
|
-
return this.parseDeploymentViewRulePredicate(astRule)
|
|
66
|
-
}
|
|
67
|
-
if (ast.isViewRuleAutoLayout(astRule)) {
|
|
68
|
-
return toAutoLayout(astRule)
|
|
69
|
-
}
|
|
70
|
-
if (ast.isDeploymentViewRuleStyle(astRule)) {
|
|
71
|
-
return this.parseDeploymentViewRuleStyle(astRule)
|
|
72
|
-
}
|
|
73
|
-
nonexhaustive(astRule)
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
parseDeploymentViewRulePredicate(astRule: ast.DeploymentViewRulePredicate): c4.DeploymentViewRulePredicate {
|
|
77
|
-
const exprs = [] as c4.ExpressionV2[]
|
|
78
|
-
let iterator: ast.DeploymentViewRulePredicateExpression | undefined = astRule.expr
|
|
79
|
-
while (iterator) {
|
|
80
|
-
try {
|
|
81
|
-
const expr = iterator.value
|
|
82
|
-
if (isNonNullish(expr) && this.isValid(expr)) {
|
|
83
|
-
switch (true) {
|
|
84
|
-
case ast.isFqnExpr(expr):
|
|
85
|
-
exprs.unshift(this.parseFqnExpr(expr))
|
|
86
|
-
break
|
|
87
|
-
case ast.isElementPredicateWhereV2(expr):
|
|
88
|
-
exprs.unshift(this.parseElementWhereExpr(expr))
|
|
89
|
-
break
|
|
90
|
-
case ast.isRelationExpr(expr):
|
|
91
|
-
exprs.unshift(this.parseRelationExpr(expr))
|
|
92
|
-
break
|
|
93
|
-
case ast.isRelationPredicateWhereV2(expr):
|
|
94
|
-
exprs.unshift(this.parseRelationWhereExpr(expr))
|
|
95
|
-
break
|
|
96
|
-
default:
|
|
97
|
-
nonexhaustive(expr)
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
} catch (e) {
|
|
101
|
-
logWarnError(e)
|
|
102
|
-
}
|
|
103
|
-
iterator = iterator.prev
|
|
104
|
-
}
|
|
105
|
-
return astRule.isInclude ? { include: exprs } : { exclude: exprs }
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
parseDeploymentViewRuleStyle(astRule: ast.DeploymentViewRuleStyle): c4.DeploymentViewRuleStyle {
|
|
109
|
-
const styleProps = astRule.props.filter(ast.isStyleProperty)
|
|
110
|
-
const notationProperty = astRule.props.find(ast.isNotationProperty)
|
|
111
|
-
const notation = removeIndent(notationProperty?.value)
|
|
112
|
-
const targets = this.parseFqnExpressions(astRule.targets)
|
|
113
|
-
return {
|
|
114
|
-
targets,
|
|
115
|
-
...(notation && { notation }),
|
|
116
|
-
style: {
|
|
117
|
-
...toElementStyle(styleProps, this.isValid),
|
|
118
|
-
},
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import type * as c4 from '@likec4/core'
|
|
2
|
-
import { nonexhaustive, nonNullable } from '@likec4/core'
|
|
3
|
-
import { isNonNullish } from 'remeda'
|
|
4
|
-
import { ast } from '../../ast'
|
|
5
|
-
import { logWarnError } from '../../logger'
|
|
6
|
-
import { instanceRef } from '../../utils/fqnRef'
|
|
7
|
-
import { parseWhereClause } from '../model-parser-where'
|
|
8
|
-
import type { Base } from './Base'
|
|
9
|
-
|
|
10
|
-
export type WithExpressionV2 = ReturnType<typeof ExpressionV2Parser>
|
|
11
|
-
|
|
12
|
-
export function ExpressionV2Parser<TBase extends Base>(B: TBase) {
|
|
13
|
-
return class ExpressionV2Parser extends B {
|
|
14
|
-
parseFqnRef(astNode: ast.FqnRef): c4.FqnRef {
|
|
15
|
-
const refValue = nonNullable(
|
|
16
|
-
astNode.value.ref,
|
|
17
|
-
`FqnRef is empty ${astNode.$cstNode?.range.start.line}:${astNode.$cstNode?.range.start.character}`,
|
|
18
|
-
)
|
|
19
|
-
if (ast.isElement(refValue)) {
|
|
20
|
-
const deployedInstanceAst = instanceRef(astNode)
|
|
21
|
-
if (!deployedInstanceAst) {
|
|
22
|
-
return {
|
|
23
|
-
model: this.resolveFqn(refValue),
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
const deployment = this.resolveFqn(deployedInstanceAst)
|
|
27
|
-
const element = this.resolveFqn(refValue)
|
|
28
|
-
return {
|
|
29
|
-
deployment,
|
|
30
|
-
element,
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
if (ast.isDeploymentElement(refValue)) {
|
|
35
|
-
return {
|
|
36
|
-
deployment: this.resolveFqn(refValue),
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
nonexhaustive(refValue)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
parseFqnExpr(astNode: ast.FqnExpr): c4.FqnExpr {
|
|
43
|
-
if (ast.isWildcardExpression(astNode)) {
|
|
44
|
-
return {
|
|
45
|
-
wildcard: true,
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
if (ast.isFqnRefExpr(astNode)) {
|
|
49
|
-
return this.parseFqnRefExpr(astNode)
|
|
50
|
-
}
|
|
51
|
-
nonexhaustive(astNode)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
parseFqnRefExpr(astNode: ast.FqnRefExpr): c4.FqnExpr.NonWildcard {
|
|
55
|
-
const ref = this.parseFqnRef(astNode.ref)
|
|
56
|
-
switch (true) {
|
|
57
|
-
case astNode.selector === '._':
|
|
58
|
-
return {
|
|
59
|
-
ref,
|
|
60
|
-
selector: 'expanded',
|
|
61
|
-
} as c4.FqnExpr.NonWildcard
|
|
62
|
-
case astNode.selector === '.**':
|
|
63
|
-
return {
|
|
64
|
-
ref,
|
|
65
|
-
selector: 'descendants',
|
|
66
|
-
} as c4.FqnExpr.NonWildcard
|
|
67
|
-
case astNode.selector === '.*':
|
|
68
|
-
return {
|
|
69
|
-
ref,
|
|
70
|
-
selector: 'children',
|
|
71
|
-
} as c4.FqnExpr.NonWildcard
|
|
72
|
-
default:
|
|
73
|
-
return { ref } as c4.FqnExpr.NonWildcard
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
parseElementWhereExpr(astNode: ast.ElementPredicateWhereV2): c4.RelationExpr {
|
|
78
|
-
return {
|
|
79
|
-
where: {
|
|
80
|
-
expr: this.parseFqnExpr(astNode.subject as ast.FqnExpr),
|
|
81
|
-
condition: astNode.where ? parseWhereClause(astNode.where) : {
|
|
82
|
-
kind: { neq: '--always-true--' },
|
|
83
|
-
},
|
|
84
|
-
},
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
parseFqnExpressions(astNode: ast.FqnExpressions): c4.FqnExpr[] {
|
|
89
|
-
const exprs = [] as c4.FqnExpr[]
|
|
90
|
-
let iter: ast.FqnExpressions['prev'] = astNode
|
|
91
|
-
while (iter) {
|
|
92
|
-
try {
|
|
93
|
-
if (isNonNullish(iter.value) && this.isValid(iter.value)) {
|
|
94
|
-
exprs.push(this.parseFqnExpr(iter.value))
|
|
95
|
-
}
|
|
96
|
-
} catch (e) {
|
|
97
|
-
logWarnError(e)
|
|
98
|
-
}
|
|
99
|
-
iter = iter.prev
|
|
100
|
-
}
|
|
101
|
-
return exprs.reverse()
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
parseRelationWhereExpr(astNode: ast.RelationPredicateWhereV2): c4.RelationExpr {
|
|
105
|
-
return {
|
|
106
|
-
where: {
|
|
107
|
-
expr: this.parseRelationExpr(astNode.subject as ast.RelationExpr),
|
|
108
|
-
condition: astNode.where ? parseWhereClause(astNode.where) : {
|
|
109
|
-
kind: { neq: '--always-true--' },
|
|
110
|
-
},
|
|
111
|
-
},
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
parseRelationExpr(astNode: ast.RelationExpr): c4.RelationExpr {
|
|
116
|
-
if (ast.isRelationPredicateWhere(astNode)) {
|
|
117
|
-
}
|
|
118
|
-
if (ast.isDirectedRelationExpr(astNode)) {
|
|
119
|
-
return {
|
|
120
|
-
source: this.parseFqnExpr(astNode.source.from),
|
|
121
|
-
target: this.parseFqnExpr(astNode.target),
|
|
122
|
-
isBidirectional: astNode.source.isBidirectional,
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
if (ast.isInOutRelationExpr(astNode)) {
|
|
126
|
-
return {
|
|
127
|
-
inout: this.parseFqnExpr(astNode.inout.to),
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
if (ast.isOutgoingRelationExpr(astNode)) {
|
|
131
|
-
return {
|
|
132
|
-
outgoing: this.parseFqnExpr(astNode.from),
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
if (ast.isIncomingRelationExpr(astNode)) {
|
|
136
|
-
return {
|
|
137
|
-
incoming: this.parseFqnExpr(astNode.to),
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
nonexhaustive(astNode)
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import type * as c4 from '@likec4/core'
|
|
2
|
-
import { nonexhaustive } from '@likec4/core'
|
|
3
|
-
import { isTruthy } from 'remeda'
|
|
4
|
-
import { ast, type ParsedAstGlobals } from '../../ast'
|
|
5
|
-
import { logger, logWarnError } from '../../logger'
|
|
6
|
-
import type { WithViewsParser } from './ViewsParser'
|
|
7
|
-
|
|
8
|
-
export function GlobalsParser<TBase extends WithViewsParser>(B: TBase) {
|
|
9
|
-
return class GlobalsParser extends B {
|
|
10
|
-
parseGlobals() {
|
|
11
|
-
const { parseResult, c4Globals } = this.doc
|
|
12
|
-
const isValid = this.isValid
|
|
13
|
-
|
|
14
|
-
const globals = parseResult.value.globals.filter(isValid)
|
|
15
|
-
|
|
16
|
-
const elRelPredicates = globals.flatMap(r => r.predicates.filter(isValid))
|
|
17
|
-
for (const predicate of elRelPredicates) {
|
|
18
|
-
try {
|
|
19
|
-
const globalPredicateId = predicate.name as c4.GlobalPredicateId
|
|
20
|
-
if (!isTruthy(globalPredicateId)) {
|
|
21
|
-
continue
|
|
22
|
-
}
|
|
23
|
-
if (globalPredicateId in c4Globals.predicates) {
|
|
24
|
-
logger.warn(`Global predicate named "${globalPredicateId}" is already defined`)
|
|
25
|
-
continue
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
this.parseAndStoreGlobalPredicateGroupOrDynamic(predicate, globalPredicateId, c4Globals)
|
|
29
|
-
} catch (e) {
|
|
30
|
-
logWarnError(e)
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const styles = globals.flatMap(r => r.styles.filter(isValid))
|
|
35
|
-
for (const style of styles) {
|
|
36
|
-
try {
|
|
37
|
-
const globalStyleId = style.id.name as c4.GlobalStyleID
|
|
38
|
-
if (!isTruthy(globalStyleId)) {
|
|
39
|
-
continue
|
|
40
|
-
}
|
|
41
|
-
if (globalStyleId in c4Globals.styles) {
|
|
42
|
-
logger.warn(`Global style named "${globalStyleId}" is already defined`)
|
|
43
|
-
continue
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const styles = this.parseGlobalStyleOrGroup(style)
|
|
47
|
-
if (styles.length > 0) {
|
|
48
|
-
c4Globals.styles[globalStyleId] = styles as c4.NonEmptyArray<c4.ViewRuleStyle>
|
|
49
|
-
}
|
|
50
|
-
} catch (e) {
|
|
51
|
-
logWarnError(e)
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
parseAndStoreGlobalPredicateGroupOrDynamic(
|
|
57
|
-
astRule: ast.GlobalPredicateGroup | ast.GlobalDynamicPredicateGroup,
|
|
58
|
-
id: c4.GlobalPredicateId,
|
|
59
|
-
c4Globals: ParsedAstGlobals
|
|
60
|
-
) {
|
|
61
|
-
if (ast.isGlobalPredicateGroup(astRule)) {
|
|
62
|
-
const predicates = this.parseGlobalPredicateGroup(astRule)
|
|
63
|
-
if (predicates.length > 0) {
|
|
64
|
-
c4Globals.predicates[id] = predicates as c4.NonEmptyArray<c4.ViewRulePredicate>
|
|
65
|
-
}
|
|
66
|
-
return
|
|
67
|
-
}
|
|
68
|
-
if (ast.isGlobalDynamicPredicateGroup(astRule)) {
|
|
69
|
-
const predicates = this.parseGlobalDynamicPredicateGroup(astRule)
|
|
70
|
-
if (predicates.length > 0) {
|
|
71
|
-
c4Globals.dynamicPredicates[id] = predicates as c4.NonEmptyArray<c4.DynamicViewIncludeRule>
|
|
72
|
-
}
|
|
73
|
-
return
|
|
74
|
-
}
|
|
75
|
-
nonexhaustive(astRule)
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
parseGlobalPredicateGroup(astRule: ast.GlobalPredicateGroup): c4.ViewRulePredicate[] {
|
|
79
|
-
return astRule.predicates.map(p => this.parseViewRulePredicate(p))
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
parseGlobalDynamicPredicateGroup(astRule: ast.GlobalDynamicPredicateGroup): c4.DynamicViewIncludeRule[] {
|
|
83
|
-
return astRule.predicates.map(p => this.parseDynamicViewIncludePredicate(p))
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
parseGlobalStyleOrGroup(astRule: ast.GlobalStyle | ast.GlobalStyleGroup): c4.ViewRuleStyle[] {
|
|
87
|
-
if (ast.isGlobalStyle(astRule)) {
|
|
88
|
-
return [this.parseViewRuleStyle(astRule)]
|
|
89
|
-
}
|
|
90
|
-
if (ast.isGlobalStyleGroup(astRule)) {
|
|
91
|
-
return astRule.styles.map(s => this.parseViewRuleStyle(s))
|
|
92
|
-
}
|
|
93
|
-
nonexhaustive(astRule)
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
import type * as c4 from '@likec4/core'
|
|
2
|
-
import { isNonEmptyArray, nonexhaustive, nonNullable } from '@likec4/core'
|
|
3
|
-
import { filter, first, isEmpty, isNonNullish, isTruthy, map, mapToObj, pipe } from 'remeda'
|
|
4
|
-
import {
|
|
5
|
-
type ParsedAstElement,
|
|
6
|
-
type ParsedAstExtendElement,
|
|
7
|
-
type ParsedAstRelation,
|
|
8
|
-
ast,
|
|
9
|
-
resolveRelationPoints,
|
|
10
|
-
streamModel,
|
|
11
|
-
toElementStyle,
|
|
12
|
-
toRelationshipStyleExcludeDefaults,
|
|
13
|
-
} from '../../ast'
|
|
14
|
-
import { logWarnError } from '../../logger'
|
|
15
|
-
import { stringHash } from '../../utils/stringHash'
|
|
16
|
-
import { type Base, removeIndent, toSingleLine } from './Base'
|
|
17
|
-
|
|
18
|
-
export type WithModel = ReturnType<typeof ModelParser>
|
|
19
|
-
|
|
20
|
-
export function ModelParser<TBase extends Base>(B: TBase) {
|
|
21
|
-
return class ModelParser extends B {
|
|
22
|
-
parseModel() {
|
|
23
|
-
const doc = this.doc
|
|
24
|
-
for (const el of streamModel(doc)) {
|
|
25
|
-
try {
|
|
26
|
-
if (ast.isElement(el)) {
|
|
27
|
-
doc.c4Elements.push(this.parseElement(el))
|
|
28
|
-
continue
|
|
29
|
-
}
|
|
30
|
-
if (ast.isRelation(el)) {
|
|
31
|
-
if (this.isValid(el)) {
|
|
32
|
-
doc.c4Relations.push(this.parseRelation(el))
|
|
33
|
-
}
|
|
34
|
-
continue
|
|
35
|
-
}
|
|
36
|
-
if (ast.isExtendElement(el)) {
|
|
37
|
-
const parsed = this.parseExtendElement(el)
|
|
38
|
-
if (parsed) {
|
|
39
|
-
doc.c4ExtendElements.push(parsed)
|
|
40
|
-
}
|
|
41
|
-
continue
|
|
42
|
-
}
|
|
43
|
-
nonexhaustive(el)
|
|
44
|
-
} catch (e) {
|
|
45
|
-
logWarnError(e)
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
parseElement(astNode: ast.Element): ParsedAstElement {
|
|
51
|
-
const isValid = this.isValid
|
|
52
|
-
const id = this.resolveFqn(astNode)
|
|
53
|
-
const kind = nonNullable(astNode.kind.ref, 'Element kind is not resolved').name as c4.ElementKind
|
|
54
|
-
const tags = this.parseTags(astNode.body)
|
|
55
|
-
const stylePropsAst = astNode.body?.props.find(ast.isElementStyleProperty)?.props
|
|
56
|
-
const style = toElementStyle(stylePropsAst, isValid)
|
|
57
|
-
const metadata = this.getMetadata(astNode.body?.props.find(ast.isMetadataProperty))
|
|
58
|
-
const astPath = this.getAstNodePath(astNode)
|
|
59
|
-
|
|
60
|
-
let [title, description, technology] = astNode.props ?? []
|
|
61
|
-
|
|
62
|
-
const bodyProps = pipe(
|
|
63
|
-
astNode.body?.props ?? [],
|
|
64
|
-
filter(isValid),
|
|
65
|
-
filter(ast.isElementStringProperty),
|
|
66
|
-
mapToObj(p => [p.key, p.value || undefined]),
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
title = removeIndent(title ?? bodyProps.title)
|
|
70
|
-
description = removeIndent(bodyProps.description ?? description)
|
|
71
|
-
technology = toSingleLine(bodyProps.technology ?? technology)
|
|
72
|
-
|
|
73
|
-
const links = this.parseLinks(astNode.body)
|
|
74
|
-
|
|
75
|
-
// Property has higher priority than from style
|
|
76
|
-
const iconProp = astNode.body?.props.find(ast.isIconProperty)
|
|
77
|
-
if (iconProp && isValid(iconProp)) {
|
|
78
|
-
const value = iconProp.libicon?.ref?.name ?? iconProp.value
|
|
79
|
-
if (isTruthy(value)) {
|
|
80
|
-
style.icon = value as c4.IconUrl
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return {
|
|
85
|
-
id,
|
|
86
|
-
kind,
|
|
87
|
-
astPath,
|
|
88
|
-
title: title ?? astNode.name,
|
|
89
|
-
...(metadata && { metadata }),
|
|
90
|
-
...(tags && { tags }),
|
|
91
|
-
...(links && isNonEmptyArray(links) && { links }),
|
|
92
|
-
...(isTruthy(technology) && { technology }),
|
|
93
|
-
...(isTruthy(description) && { description }),
|
|
94
|
-
style,
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
parseExtendElement(astNode: ast.ExtendElement): ParsedAstExtendElement | null {
|
|
99
|
-
const isValid = this.isValid
|
|
100
|
-
const id = this.resolveFqn(astNode)
|
|
101
|
-
const tags = this.parseTags(astNode.body)
|
|
102
|
-
const metadata = this.getMetadata(astNode.body?.props.find(ast.isMetadataProperty))
|
|
103
|
-
const astPath = this.getAstNodePath(astNode)
|
|
104
|
-
const links = this.parseLinks(astNode.body) ?? []
|
|
105
|
-
|
|
106
|
-
if (!tags && isEmpty(metadata ?? {}) && isEmpty(links)) {
|
|
107
|
-
return null
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
id,
|
|
112
|
-
astPath,
|
|
113
|
-
...(metadata && { metadata }),
|
|
114
|
-
...(tags && { tags }),
|
|
115
|
-
...(links && isNonEmptyArray(links) && { links }),
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
parseRelation(astNode: ast.Relation): ParsedAstRelation {
|
|
120
|
-
const isValid = this.isValid
|
|
121
|
-
const coupling = resolveRelationPoints(astNode)
|
|
122
|
-
const target = this.resolveFqn(coupling.target)
|
|
123
|
-
const source = this.resolveFqn(coupling.source)
|
|
124
|
-
const tags = this.parseTags(astNode) ?? this.parseTags(astNode.body)
|
|
125
|
-
const links = this.parseLinks(astNode.body)
|
|
126
|
-
const kind = astNode.kind?.ref?.name as (c4.RelationshipKind | undefined)
|
|
127
|
-
const metadata = this.getMetadata(astNode.body?.props.find(ast.isMetadataProperty))
|
|
128
|
-
const astPath = this.getAstNodePath(astNode)
|
|
129
|
-
|
|
130
|
-
const bodyProps = mapToObj(
|
|
131
|
-
astNode.body?.props.filter(ast.isRelationStringProperty).filter(p => isNonNullish(p.value)) ?? [],
|
|
132
|
-
p => [p.key, p.value],
|
|
133
|
-
)
|
|
134
|
-
|
|
135
|
-
const navigateTo = pipe(
|
|
136
|
-
astNode.body?.props ?? [],
|
|
137
|
-
filter(ast.isRelationNavigateToProperty),
|
|
138
|
-
map(p => p.value.view.ref?.name),
|
|
139
|
-
filter(isTruthy),
|
|
140
|
-
first(),
|
|
141
|
-
)
|
|
142
|
-
|
|
143
|
-
const title = removeIndent(astNode.title ?? bodyProps.title) ?? ''
|
|
144
|
-
const description = removeIndent(bodyProps.description)
|
|
145
|
-
const technology = toSingleLine(astNode.technology) ?? removeIndent(bodyProps.technology)
|
|
146
|
-
|
|
147
|
-
const styleProp = astNode.body?.props.find(ast.isRelationStyleProperty)
|
|
148
|
-
const id = stringHash(
|
|
149
|
-
astPath,
|
|
150
|
-
source,
|
|
151
|
-
target,
|
|
152
|
-
) as c4.RelationId
|
|
153
|
-
return {
|
|
154
|
-
id,
|
|
155
|
-
astPath,
|
|
156
|
-
source,
|
|
157
|
-
target,
|
|
158
|
-
title,
|
|
159
|
-
...(metadata && { metadata }),
|
|
160
|
-
...(isTruthy(technology) && { technology }),
|
|
161
|
-
...(isTruthy(description) && { description }),
|
|
162
|
-
...(kind && { kind }),
|
|
163
|
-
...(tags && { tags }),
|
|
164
|
-
...(isNonEmptyArray(links) && { links }),
|
|
165
|
-
...toRelationshipStyleExcludeDefaults(styleProp?.props, isValid),
|
|
166
|
-
...(navigateTo && { navigateTo: navigateTo as c4.ViewId }),
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
}
|