@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,48 +0,0 @@
|
|
|
1
|
-
import { hasAtLeast, invariant } from '@likec4/core'
|
|
2
|
-
import type { LangiumDocument, LangiumDocumentFactory } from 'langium'
|
|
3
|
-
import { DefaultWorkspaceManager } from 'langium'
|
|
4
|
-
import type { LangiumSharedServices } from 'langium/lsp'
|
|
5
|
-
import type { WorkspaceFolder } from 'vscode-languageserver'
|
|
6
|
-
import { URI } from 'vscode-uri'
|
|
7
|
-
import * as BuiltIn from '../likec4lib'
|
|
8
|
-
|
|
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
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Load all additional documents that shall be visible in the context of the given workspace
|
|
19
|
-
* folders and add them to the collector. This can be used to include built-in libraries of
|
|
20
|
-
* your language, which can be either loaded from provided files or constructed in memory.
|
|
21
|
-
*/
|
|
22
|
-
protected override async loadAdditionalDocuments(
|
|
23
|
-
folders: WorkspaceFolder[],
|
|
24
|
-
collector: (document: LangiumDocument) => void
|
|
25
|
-
): Promise<void> {
|
|
26
|
-
collector(this.documentFactory.fromString(BuiltIn.Content, URI.parse(BuiltIn.Uri)))
|
|
27
|
-
await super.loadAdditionalDocuments(folders, collector)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
public workspace() {
|
|
31
|
-
if (this.folders && hasAtLeast(this.folders, 1)) {
|
|
32
|
-
return this.folders[0]
|
|
33
|
-
}
|
|
34
|
-
return null
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
public get workspaceUri() {
|
|
38
|
-
const workspace = this.workspace()
|
|
39
|
-
invariant(workspace, 'Workspace not initialized')
|
|
40
|
-
return URI.parse(workspace.uri)
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
public get workspaceURL() {
|
|
44
|
-
const workspace = this.workspace()
|
|
45
|
-
invariant(workspace, 'Workspace not initialized')
|
|
46
|
-
return new URL(workspace.uri)
|
|
47
|
-
}
|
|
48
|
-
}
|
package/src/shared/index.ts
DELETED
package/src/test/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from './testServices'
|
package/src/test/setup.ts
DELETED
package/src/test/testServices.ts
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import { LikeC4Model } from '@likec4/core'
|
|
2
|
-
import { DocumentState, EmptyFileSystem, TextDocument } from 'langium'
|
|
3
|
-
import * as assert from 'node:assert'
|
|
4
|
-
import stripIndent from 'strip-indent'
|
|
5
|
-
import { type Diagnostic, DiagnosticSeverity } from 'vscode-languageserver-types'
|
|
6
|
-
import { URI, Utils } from 'vscode-uri'
|
|
7
|
-
import type { LikeC4LangiumDocument } from '../ast'
|
|
8
|
-
import { createLanguageServices } from '../module'
|
|
9
|
-
|
|
10
|
-
export function createTestServices(workspace = 'file:///test/workspace') {
|
|
11
|
-
const services = createLanguageServices(EmptyFileSystem).likec4
|
|
12
|
-
const metaData = services.LanguageMetaData
|
|
13
|
-
const langiumDocuments = services.shared.workspace.LangiumDocuments
|
|
14
|
-
const documentBuilder = services.shared.workspace.DocumentBuilder
|
|
15
|
-
const modelBuilder = services.likec4.ModelBuilder
|
|
16
|
-
const workspaceUri = URI.parse(workspace)
|
|
17
|
-
const formatter = services.lsp.Formatter
|
|
18
|
-
const workspaceFolder = {
|
|
19
|
-
name: 'test',
|
|
20
|
-
uri: workspaceUri.toString(),
|
|
21
|
-
}
|
|
22
|
-
let isInitialized = false
|
|
23
|
-
let documentIndex = 1
|
|
24
|
-
|
|
25
|
-
const parse = async (input: string, uri?: string) => {
|
|
26
|
-
if (!isInitialized) {
|
|
27
|
-
await services.shared.workspace.WorkspaceLock.write(async (_cancelToken) => {
|
|
28
|
-
if (isInitialized) {
|
|
29
|
-
return
|
|
30
|
-
}
|
|
31
|
-
isInitialized = true
|
|
32
|
-
services.shared.workspace.WorkspaceManager.initialize({
|
|
33
|
-
capabilities: {},
|
|
34
|
-
processId: null,
|
|
35
|
-
rootUri: null,
|
|
36
|
-
workspaceFolders: [workspaceFolder],
|
|
37
|
-
})
|
|
38
|
-
await services.shared.workspace.WorkspaceManager.initializeWorkspace([workspaceFolder])
|
|
39
|
-
})
|
|
40
|
-
}
|
|
41
|
-
const docUri = Utils.resolvePath(
|
|
42
|
-
workspaceUri,
|
|
43
|
-
'./src/',
|
|
44
|
-
uri ?? `${documentIndex++}${metaData.fileExtensions[0]}`,
|
|
45
|
-
)
|
|
46
|
-
const document = services.shared.workspace.LangiumDocumentFactory.fromString(
|
|
47
|
-
stripIndent(input),
|
|
48
|
-
docUri,
|
|
49
|
-
)
|
|
50
|
-
langiumDocuments.addDocument(document)
|
|
51
|
-
await services.shared.workspace.WorkspaceLock.write(async (_cancelToken) => {
|
|
52
|
-
await documentBuilder.build([document], { validation: false })
|
|
53
|
-
})
|
|
54
|
-
return document as LikeC4LangiumDocument
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
const validate = async (input: string | LikeC4LangiumDocument, uri?: string) => {
|
|
58
|
-
const document = typeof input === 'string' ? await parse(input, uri) : input
|
|
59
|
-
await services.shared.workspace.WorkspaceLock.write(async (_cancelToken) => {
|
|
60
|
-
await documentBuilder.build([document], { validation: true })
|
|
61
|
-
})
|
|
62
|
-
const diagnostics = document.diagnostics ?? []
|
|
63
|
-
const warnings = diagnostics.flatMap(d => d.severity === DiagnosticSeverity.Warning ? d.message : [])
|
|
64
|
-
const errors = diagnostics.flatMap(d => d.severity === DiagnosticSeverity.Error ? d.message : [])
|
|
65
|
-
return {
|
|
66
|
-
document,
|
|
67
|
-
diagnostics,
|
|
68
|
-
warnings,
|
|
69
|
-
errors,
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
const format = async (input: string | LikeC4LangiumDocument, uri?: string) => {
|
|
74
|
-
const document = typeof input === 'string' ? await parse(input, uri) : input
|
|
75
|
-
await services.shared.workspace.WorkspaceLock.write(async (_cancelToken) => {
|
|
76
|
-
await documentBuilder.build([document], { validation: true })
|
|
77
|
-
})
|
|
78
|
-
|
|
79
|
-
const edits = await formatter?.formatDocument(
|
|
80
|
-
document,
|
|
81
|
-
{
|
|
82
|
-
options: { tabSize: 2, insertSpaces: true },
|
|
83
|
-
textDocument: { uri: document.uri.toString() },
|
|
84
|
-
},
|
|
85
|
-
)
|
|
86
|
-
|
|
87
|
-
return TextDocument.applyEdits(document.textDocument, edits ?? [])
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
type ValidateAllResult = {
|
|
91
|
-
diagnostics: Diagnostic[]
|
|
92
|
-
errors: string[]
|
|
93
|
-
warnings: string[]
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const validateAll = async () => {
|
|
97
|
-
await services.shared.workspace.WorkspaceLock.write(async (_cancelToken) => {
|
|
98
|
-
const docs = langiumDocuments.all.toArray()
|
|
99
|
-
await documentBuilder.build(docs, { validation: true })
|
|
100
|
-
})
|
|
101
|
-
await documentBuilder.waitUntil(DocumentState.Validated)
|
|
102
|
-
const docs = langiumDocuments.all.toArray()
|
|
103
|
-
assert.ok(docs.length > 0, 'no documents to validate')
|
|
104
|
-
const diagnostics = docs.flatMap(doc => doc.diagnostics ?? [])
|
|
105
|
-
const warnings = diagnostics.flatMap(d => d.severity === DiagnosticSeverity.Warning ? d.message : [])
|
|
106
|
-
const errors = diagnostics.flatMap(d => d.severity === DiagnosticSeverity.Error ? d.message : [])
|
|
107
|
-
return {
|
|
108
|
-
diagnostics,
|
|
109
|
-
errors,
|
|
110
|
-
warnings,
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
const buildModel = async () => {
|
|
115
|
-
await validateAll()
|
|
116
|
-
const model = await modelBuilder.buildComputedModel()
|
|
117
|
-
if (!model) throw new Error('No model found')
|
|
118
|
-
return model
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
const buildLikeC4Model = async () => {
|
|
122
|
-
await validateAll()
|
|
123
|
-
const model = await modelBuilder.buildComputedModel()
|
|
124
|
-
if (!model) throw new Error('No model found')
|
|
125
|
-
return LikeC4Model.create(model)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* This will clear all documents
|
|
130
|
-
*/
|
|
131
|
-
const resetState = async () => {
|
|
132
|
-
await services.shared.workspace.WorkspaceLock.write(async (cancelToken) => {
|
|
133
|
-
const docs = langiumDocuments.all.toArray().map(doc => doc.uri)
|
|
134
|
-
await documentBuilder.update([], docs, cancelToken)
|
|
135
|
-
})
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
return {
|
|
139
|
-
services,
|
|
140
|
-
parse,
|
|
141
|
-
validate,
|
|
142
|
-
validateAll,
|
|
143
|
-
buildModel,
|
|
144
|
-
buildLikeC4Model,
|
|
145
|
-
resetState,
|
|
146
|
-
format,
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
export type TestServices = ReturnType<typeof createTestServices>
|
|
151
|
-
export type TestParseFn = TestServices['validate']
|
|
152
|
-
export type TestValidateFn = TestServices['validate']
|
package/src/utils/disposable.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { Disposable } from 'langium'
|
|
2
|
-
import { logError } from '../logger'
|
|
3
|
-
|
|
4
|
-
export abstract class ADisposable implements Disposable {
|
|
5
|
-
protected toDispose: Disposable[] = []
|
|
6
|
-
protected isDisposed = false
|
|
7
|
-
|
|
8
|
-
onDispose(...disposable: Disposable[]): void {
|
|
9
|
-
this.toDispose.push(...disposable)
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
dispose(): void {
|
|
13
|
-
this.throwIfDisposed()
|
|
14
|
-
this.isDisposed = true
|
|
15
|
-
let item: Disposable | undefined
|
|
16
|
-
while (item = this.toDispose.pop()) {
|
|
17
|
-
try {
|
|
18
|
-
item.dispose()
|
|
19
|
-
} catch (e) {
|
|
20
|
-
logError(e)
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
protected throwIfDisposed(): void {
|
|
26
|
-
if (this.isDisposed) {
|
|
27
|
-
throw new Error('This has already been disposed')
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
package/src/utils/elementRef.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import type * as c4 from '@likec4/core'
|
|
2
|
-
import type { ast } from '../ast'
|
|
3
|
-
/**
|
|
4
|
-
* Returns referenced AST Element
|
|
5
|
-
*/
|
|
6
|
-
export function elementRef(node: ast.ElementRef | ast.StrictFqnElementRef) {
|
|
7
|
-
return node.el.ref
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Returns FQN of StrictFqnElementRef
|
|
12
|
-
* a.b.c.d - for c node returns a.b.c
|
|
13
|
-
*/
|
|
14
|
-
export function getFqnElementRef(node: ast.StrictFqnElementRef): c4.Fqn {
|
|
15
|
-
// invariant(isElementRefHead(node), 'Expected head StrictElementRef')
|
|
16
|
-
const name = [node.el.$refText]
|
|
17
|
-
let parent = node.parent
|
|
18
|
-
while (parent) {
|
|
19
|
-
name.push(parent.el.$refText)
|
|
20
|
-
parent = parent.parent
|
|
21
|
-
}
|
|
22
|
-
if (name.length === 1) {
|
|
23
|
-
return name[0] as c4.Fqn
|
|
24
|
-
}
|
|
25
|
-
return name.reverse().join('.') as c4.Fqn
|
|
26
|
-
}
|
package/src/utils/fqnRef.ts
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { AstUtils } from 'langium'
|
|
2
|
-
import { isNullish } from 'remeda'
|
|
3
|
-
import { ast } from '../ast'
|
|
4
|
-
|
|
5
|
-
export function instanceRef(deploymentRef: ast.FqnRef): ast.DeployedInstance | null {
|
|
6
|
-
let referenceable
|
|
7
|
-
while ((referenceable = deploymentRef.value?.ref)) {
|
|
8
|
-
if (ast.isDeploymentNode(referenceable)) {
|
|
9
|
-
return null
|
|
10
|
-
}
|
|
11
|
-
if (ast.isDeployedInstance(referenceable)) {
|
|
12
|
-
return referenceable
|
|
13
|
-
}
|
|
14
|
-
if (isNullish(deploymentRef.parent)) {
|
|
15
|
-
return null
|
|
16
|
-
}
|
|
17
|
-
deploymentRef = deploymentRef.parent
|
|
18
|
-
}
|
|
19
|
-
return null
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
export function deploymentNodeRef(deploymentRef: ast.FqnRef): ast.DeploymentNode | null {
|
|
23
|
-
let referenceable = deploymentRef.value.ref ?? null
|
|
24
|
-
if (!referenceable || ast.isDeploymentNode(referenceable)) {
|
|
25
|
-
return referenceable
|
|
26
|
-
}
|
|
27
|
-
const artifact = instanceRef(deploymentRef)
|
|
28
|
-
// Because path in deploymentRef may be omitted,
|
|
29
|
-
// we find artifact first and then its container
|
|
30
|
-
return artifact ? AstUtils.getContainerOfType(artifact, ast.isDeploymentNode) ?? null : null
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export function isReferenceToLogicalModel(node: ast.FqnRef) {
|
|
34
|
-
// iterate up the root parent
|
|
35
|
-
while (node.parent) {
|
|
36
|
-
node = node.parent
|
|
37
|
-
}
|
|
38
|
-
return ast.isElement(node.value.ref)
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Returns true if node references deployment model
|
|
43
|
-
*/
|
|
44
|
-
export function isReferenceToDeploymentModel(node: ast.FqnRef) {
|
|
45
|
-
let referenceable
|
|
46
|
-
while ((referenceable = node.value?.ref)) {
|
|
47
|
-
if (ast.isDeploymentElement(referenceable)) {
|
|
48
|
-
return true
|
|
49
|
-
}
|
|
50
|
-
if (isNullish(node.parent)) {
|
|
51
|
-
return false
|
|
52
|
-
}
|
|
53
|
-
node = node.parent
|
|
54
|
-
}
|
|
55
|
-
return false
|
|
56
|
-
}
|
package/src/utils/index.ts
DELETED
package/src/utils/printDocs.ts
DELETED
package/src/utils/stringHash.ts
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import { type AstNode, type ValidationAcceptor, type ValidationCheck } from 'langium'
|
|
2
|
-
import { isPromise } from 'remeda'
|
|
3
|
-
import type { CancellationToken } from 'vscode-jsonrpc'
|
|
4
|
-
import { logWarnError } from '../logger'
|
|
5
|
-
|
|
6
|
-
export const RESERVED_WORDS = [
|
|
7
|
-
'this',
|
|
8
|
-
'it',
|
|
9
|
-
'self',
|
|
10
|
-
'super',
|
|
11
|
-
'likec4lib',
|
|
12
|
-
'global',
|
|
13
|
-
]
|
|
14
|
-
|
|
15
|
-
export function tryOrLog<T extends AstNode>(fn: ValidationCheck<T>): ValidationCheck<T> {
|
|
16
|
-
return async function tryOrLogFn(node: T, accept: ValidationAcceptor, cancelToken: CancellationToken) {
|
|
17
|
-
try {
|
|
18
|
-
const result = fn(node, accept, cancelToken)
|
|
19
|
-
if (isPromise(result)) {
|
|
20
|
-
await result
|
|
21
|
-
}
|
|
22
|
-
return
|
|
23
|
-
} catch (e) {
|
|
24
|
-
const message = e instanceof Error ? e.message : String(e)
|
|
25
|
-
accept('error', `Validation failed: ${message}`, { node })
|
|
26
|
-
logWarnError(e)
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
import { FqnRef, isSameHierarchy, nonNullable } from '@likec4/core'
|
|
2
|
-
import { type ValidationCheck, AstUtils } from 'langium'
|
|
3
|
-
import { ast } from '../ast'
|
|
4
|
-
import type { LikeC4Services } from '../module'
|
|
5
|
-
import type { LikeC4NameProvider } from '../references'
|
|
6
|
-
import { RESERVED_WORDS, tryOrLog } from './_shared'
|
|
7
|
-
|
|
8
|
-
const { getDocument } = AstUtils
|
|
9
|
-
|
|
10
|
-
export const deploymentNodeChecks = (services: LikeC4Services): ValidationCheck<ast.DeploymentNode> => {
|
|
11
|
-
const DeploymentsIndex = services.likec4.DeploymentsIndex
|
|
12
|
-
const Names = services.references.NameProvider
|
|
13
|
-
return tryOrLog((el, accept) => {
|
|
14
|
-
const nodeName = Names.getName(el)
|
|
15
|
-
if (!nodeName) {
|
|
16
|
-
accept('error', 'DeploymentNode must be named', {
|
|
17
|
-
node: el,
|
|
18
|
-
})
|
|
19
|
-
return
|
|
20
|
-
}
|
|
21
|
-
const range = nonNullable(Names.getNameNode(el), 'name CstNode not found').range
|
|
22
|
-
|
|
23
|
-
if (RESERVED_WORDS.includes(nodeName)) {
|
|
24
|
-
accept('error', `Reserved word: ${nodeName}`, {
|
|
25
|
-
node: el,
|
|
26
|
-
range,
|
|
27
|
-
})
|
|
28
|
-
}
|
|
29
|
-
const fqnName = DeploymentsIndex.getFqn(el)
|
|
30
|
-
|
|
31
|
-
const withSameName = DeploymentsIndex.byFqn(fqnName).limit(2).toArray()
|
|
32
|
-
if (withSameName.length > 1) {
|
|
33
|
-
accept(
|
|
34
|
-
'error',
|
|
35
|
-
`Duplicate node name "${fqnName}"`,
|
|
36
|
-
{
|
|
37
|
-
node: el,
|
|
38
|
-
range,
|
|
39
|
-
},
|
|
40
|
-
)
|
|
41
|
-
}
|
|
42
|
-
})
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export const deployedInstanceChecks = (services: LikeC4Services): ValidationCheck<ast.DeployedInstance> => {
|
|
46
|
-
const DeploymentsIndex = services.likec4.DeploymentsIndex
|
|
47
|
-
const Names = services.references.NameProvider as LikeC4NameProvider
|
|
48
|
-
// const Locator = services.workspace.AstNodeLocator
|
|
49
|
-
return tryOrLog((el, accept) => {
|
|
50
|
-
const artifactName = Names.getName(el)
|
|
51
|
-
if (!artifactName) {
|
|
52
|
-
accept('error', 'Deployed instance must be named, unique inside node', {
|
|
53
|
-
node: el,
|
|
54
|
-
})
|
|
55
|
-
return
|
|
56
|
-
}
|
|
57
|
-
const range = nonNullable(Names.getNameNode(el), 'name CstNode not found').range
|
|
58
|
-
|
|
59
|
-
if (RESERVED_WORDS.includes(artifactName)) {
|
|
60
|
-
accept('error', `Reserved word: ${artifactName}`, {
|
|
61
|
-
node: el,
|
|
62
|
-
range,
|
|
63
|
-
})
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const fqnName = DeploymentsIndex.getFqn(el)
|
|
67
|
-
|
|
68
|
-
const withSameName = DeploymentsIndex.byFqn(fqnName).limit(2).toArray()
|
|
69
|
-
if (withSameName.length > 1) {
|
|
70
|
-
accept(
|
|
71
|
-
'error',
|
|
72
|
-
`Duplicate instance name "${fqnName}"`,
|
|
73
|
-
{
|
|
74
|
-
node: el,
|
|
75
|
-
range,
|
|
76
|
-
},
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
})
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
export const deploymentRelationChecks = (services: LikeC4Services): ValidationCheck<ast.DeploymentRelation> => {
|
|
83
|
-
const ModelParser = services.likec4.ModelParser
|
|
84
|
-
return tryOrLog((el, accept) => {
|
|
85
|
-
const source = el.source?.value?.ref
|
|
86
|
-
if (!source) {
|
|
87
|
-
let sourceCstText = el.source?.$cstNode?.text ?? ''
|
|
88
|
-
accept('error', `DeploymentRelation source '${sourceCstText}' not resolved`, {
|
|
89
|
-
node: el,
|
|
90
|
-
property: 'source',
|
|
91
|
-
})
|
|
92
|
-
return
|
|
93
|
-
}
|
|
94
|
-
const target = el.target?.value?.ref
|
|
95
|
-
if (!target) {
|
|
96
|
-
let targetCstText = el.target?.$cstNode?.text ?? ''
|
|
97
|
-
accept('error', `DeploymentRelation target '${targetCstText}' not resolved`, {
|
|
98
|
-
node: el,
|
|
99
|
-
property: 'target',
|
|
100
|
-
})
|
|
101
|
-
return
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
const doc = getDocument(el)
|
|
105
|
-
const parser = ModelParser.forDocument(doc)
|
|
106
|
-
|
|
107
|
-
const sourceFqnRef = parser.parseFqnRef(el.source)
|
|
108
|
-
if (FqnRef.isModelRef(sourceFqnRef)) {
|
|
109
|
-
accept('error', 'DeploymentRelation must refer deployment element', {
|
|
110
|
-
node: el,
|
|
111
|
-
property: 'source',
|
|
112
|
-
})
|
|
113
|
-
return
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
const targetFqnRef = parser.parseFqnRef(el.target)
|
|
117
|
-
if (FqnRef.isModelRef(targetFqnRef)) {
|
|
118
|
-
accept('error', 'DeploymentRelation must refer deployment element', {
|
|
119
|
-
node: el,
|
|
120
|
-
property: 'target',
|
|
121
|
-
})
|
|
122
|
-
return
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
if (isSameHierarchy(sourceFqnRef.deployment, targetFqnRef.deployment)) {
|
|
126
|
-
accept('error', 'Invalid parent-child relationship', {
|
|
127
|
-
node: el,
|
|
128
|
-
})
|
|
129
|
-
}
|
|
130
|
-
})
|
|
131
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { nonexhaustive } from '@likec4/core'
|
|
2
|
-
import type { ValidationCheck } from 'langium'
|
|
3
|
-
import { ast, elementExpressionFromPredicate } from '../ast'
|
|
4
|
-
import type { LikeC4Services } from '../module'
|
|
5
|
-
import { tryOrLog } from './_shared'
|
|
6
|
-
|
|
7
|
-
export const dynamicViewRulePredicate = (
|
|
8
|
-
_services: LikeC4Services,
|
|
9
|
-
): ValidationCheck<ast.DynamicViewPredicateIterator> => {
|
|
10
|
-
return tryOrLog((predicate, accept) => {
|
|
11
|
-
const expr = elementExpressionFromPredicate(predicate.value)
|
|
12
|
-
switch (true) {
|
|
13
|
-
case ast.isElementKindExpression(expr):
|
|
14
|
-
case ast.isElementTagExpression(expr):
|
|
15
|
-
case ast.isWildcardExpression(expr): {
|
|
16
|
-
accept('warning', `Predicate is ignored, as not supported in dynamic views`, {
|
|
17
|
-
node: predicate,
|
|
18
|
-
})
|
|
19
|
-
return
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
})
|
|
23
|
-
}
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { isAncestor } from '@likec4/core'
|
|
2
|
-
import type { ValidationCheck } from 'langium'
|
|
3
|
-
import { ast } from '../ast'
|
|
4
|
-
import { logError } from '../logger'
|
|
5
|
-
import type { LikeC4Services } from '../module'
|
|
6
|
-
import { elementRef } from '../utils/elementRef'
|
|
7
|
-
import { tryOrLog } from './_shared'
|
|
8
|
-
|
|
9
|
-
export const dynamicViewStep = (services: LikeC4Services): ValidationCheck<ast.DynamicViewStep> => {
|
|
10
|
-
const fqnIndex = services.likec4.FqnIndex
|
|
11
|
-
return tryOrLog((el, accept) => {
|
|
12
|
-
const sourceEl: ast.Element | undefined = elementRef(el.source)
|
|
13
|
-
const source = sourceEl && fqnIndex.getFqn(sourceEl)
|
|
14
|
-
if (!source) {
|
|
15
|
-
accept('error', 'Source not found (not parsed/indexed yet)', {
|
|
16
|
-
node: el,
|
|
17
|
-
property: 'source',
|
|
18
|
-
})
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const targetEl: ast.Element | undefined = elementRef(el.target)
|
|
22
|
-
const target = targetEl && fqnIndex.getFqn(targetEl)
|
|
23
|
-
if (!target) {
|
|
24
|
-
accept('error', 'Target not found (not parsed/indexed yet)', {
|
|
25
|
-
node: el,
|
|
26
|
-
property: 'target',
|
|
27
|
-
})
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (source && target && (isAncestor(source, target) || isAncestor(target, source))) {
|
|
31
|
-
accept('error', 'Invalid parent-child relationship', {
|
|
32
|
-
node: el,
|
|
33
|
-
})
|
|
34
|
-
}
|
|
35
|
-
})
|
|
36
|
-
}
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { AstUtils, type ValidationCheck } from 'langium'
|
|
2
|
-
import type { ast } from '../ast'
|
|
3
|
-
import type { LikeC4Services } from '../module'
|
|
4
|
-
import { RESERVED_WORDS, tryOrLog } from './_shared'
|
|
5
|
-
|
|
6
|
-
const { getDocument } = AstUtils
|
|
7
|
-
|
|
8
|
-
export const elementChecks = (services: LikeC4Services): ValidationCheck<ast.Element> => {
|
|
9
|
-
const fqnIndex = services.likec4.FqnIndex
|
|
10
|
-
const locator = services.workspace.AstNodeLocator
|
|
11
|
-
return tryOrLog((el, accept) => {
|
|
12
|
-
const fqn = fqnIndex.getFqn(el)
|
|
13
|
-
if (!fqn) {
|
|
14
|
-
accept('error', 'Not indexed element', {
|
|
15
|
-
node: el,
|
|
16
|
-
property: 'name'
|
|
17
|
-
})
|
|
18
|
-
return
|
|
19
|
-
}
|
|
20
|
-
if (RESERVED_WORDS.includes(el.name)) {
|
|
21
|
-
accept('error', `Reserved word: ${el.name}`, {
|
|
22
|
-
node: el,
|
|
23
|
-
property: 'name'
|
|
24
|
-
})
|
|
25
|
-
}
|
|
26
|
-
const doc = getDocument(el)
|
|
27
|
-
const docUri = doc.uri
|
|
28
|
-
const elPath = locator.getAstNodePath(el)
|
|
29
|
-
const withSameFqn = fqnIndex
|
|
30
|
-
.byFqn(fqn)
|
|
31
|
-
.filter(v => v.documentUri !== docUri || v.path !== elPath)
|
|
32
|
-
.head()
|
|
33
|
-
if (withSameFqn) {
|
|
34
|
-
const isAnotherDoc = withSameFqn.documentUri !== docUri
|
|
35
|
-
accept(
|
|
36
|
-
'error',
|
|
37
|
-
`Duplicate element name ${el.name !== fqn ? el.name + ' (' + fqn + ')' : el.name}`,
|
|
38
|
-
{
|
|
39
|
-
node: el,
|
|
40
|
-
property: 'name',
|
|
41
|
-
...isAnotherDoc && {
|
|
42
|
-
relatedInformation: [
|
|
43
|
-
{
|
|
44
|
-
location: {
|
|
45
|
-
range: (withSameFqn.nameSegment?.range ?? withSameFqn.selectionSegment?.range)!,
|
|
46
|
-
uri: withSameFqn.documentUri.toString()
|
|
47
|
-
},
|
|
48
|
-
message: `conflicting element`
|
|
49
|
-
}
|
|
50
|
-
]
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
)
|
|
54
|
-
}
|
|
55
|
-
})
|
|
56
|
-
}
|