@domainlang/language 0.1.20 → 0.1.82
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/out/domain-lang-module.d.ts +0 -2
- package/out/domain-lang-module.js +3 -11
- package/out/domain-lang-module.js.map +1 -1
- package/out/generated/ast.d.ts +19 -8
- package/out/generated/ast.js +10 -1
- package/out/generated/ast.js.map +1 -1
- package/out/generated/grammar.d.ts +1 -1
- package/out/generated/grammar.js +123 -28
- package/out/generated/grammar.js.map +1 -1
- package/out/generated/module.d.ts +1 -1
- package/out/generated/module.js +1 -1
- package/out/index.d.ts +0 -3
- package/out/index.js +0 -5
- package/out/index.js.map +1 -1
- package/out/lsp/hover/domain-lang-hover.js +4 -0
- package/out/lsp/hover/domain-lang-hover.js.map +1 -1
- package/out/sdk/index.d.ts +1 -1
- package/out/sdk/loader-node.d.ts +3 -7
- package/out/sdk/loader-node.js +9 -24
- package/out/sdk/loader-node.js.map +1 -1
- package/out/sdk/types.d.ts +21 -0
- package/out/services/dependency-analyzer.d.ts +39 -3
- package/out/services/dependency-analyzer.js +47 -22
- package/out/services/dependency-analyzer.js.map +1 -1
- package/out/services/dependency-resolver.d.ts +45 -68
- package/out/services/dependency-resolver.js +43 -243
- package/out/services/dependency-resolver.js.map +1 -1
- package/out/services/git-url-resolver.browser.d.ts +12 -4
- package/out/services/git-url-resolver.browser.js +1 -5
- package/out/services/git-url-resolver.browser.js.map +1 -1
- package/out/services/git-url-resolver.d.ts +56 -22
- package/out/services/git-url-resolver.js +36 -70
- package/out/services/git-url-resolver.js.map +1 -1
- package/out/services/governance-validator.d.ts +37 -1
- package/out/services/governance-validator.js +10 -4
- package/out/services/governance-validator.js.map +1 -1
- package/out/services/import-resolver.d.ts +6 -65
- package/out/services/import-resolver.js +5 -223
- package/out/services/import-resolver.js.map +1 -1
- package/out/services/performance-optimizer.d.ts +1 -1
- package/out/services/workspace-manager.d.ts +10 -57
- package/out/services/workspace-manager.js +21 -187
- package/out/services/workspace-manager.js.map +1 -1
- package/out/syntaxes/domain-lang.monarch.js +1 -1
- package/out/syntaxes/domain-lang.monarch.js.map +1 -1
- package/out/utils/import-utils.d.ts +12 -4
- package/out/utils/import-utils.js +135 -35
- package/out/utils/import-utils.js.map +1 -1
- package/out/validation/constants.d.ts +0 -103
- package/out/validation/constants.js +1 -140
- package/out/validation/constants.js.map +1 -1
- package/out/validation/domain.js +1 -46
- package/out/validation/domain.js.map +1 -1
- package/out/validation/import.d.ts +22 -46
- package/out/validation/import.js +85 -187
- package/out/validation/import.js.map +1 -1
- package/out/validation/maps.js +6 -10
- package/out/validation/maps.js.map +1 -1
- package/out/validation/metadata.js +1 -5
- package/out/validation/metadata.js.map +1 -1
- package/package.json +6 -8
- package/src/domain-lang-module.ts +6 -18
- package/src/domain-lang.langium +12 -7
- package/src/generated/ast.ts +20 -7
- package/src/generated/grammar.ts +123 -28
- package/src/generated/module.ts +1 -1
- package/src/index.ts +0 -7
- package/src/lsp/hover/domain-lang-hover.ts +2 -0
- package/src/sdk/index.ts +2 -0
- package/src/sdk/loader-node.ts +9 -29
- package/src/sdk/types.ts +23 -0
- package/src/services/dependency-analyzer.ts +84 -24
- package/src/services/dependency-resolver.ts +84 -301
- package/src/services/git-url-resolver.browser.ts +14 -9
- package/src/services/git-url-resolver.ts +93 -86
- package/src/services/governance-validator.ts +47 -5
- package/src/services/import-resolver.ts +8 -270
- package/src/services/performance-optimizer.ts +1 -1
- package/src/services/workspace-manager.ts +46 -237
- package/src/syntaxes/domain-lang.monarch.ts +1 -1
- package/src/utils/import-utils.ts +160 -38
- package/src/validation/constants.ts +1 -181
- package/src/validation/domain.ts +1 -54
- package/src/validation/import.ts +104 -228
- package/src/validation/maps.ts +6 -10
- package/src/validation/metadata.ts +1 -5
- package/out/lsp/domain-lang-code-actions.d.ts +0 -55
- package/out/lsp/domain-lang-code-actions.js +0 -143
- package/out/lsp/domain-lang-code-actions.js.map +0 -1
- package/out/lsp/domain-lang-workspace-manager.d.ts +0 -21
- package/out/lsp/domain-lang-workspace-manager.js +0 -93
- package/out/lsp/domain-lang-workspace-manager.js.map +0 -1
- package/out/lsp/manifest-diagnostics.d.ts +0 -82
- package/out/lsp/manifest-diagnostics.js +0 -230
- package/out/lsp/manifest-diagnostics.js.map +0 -1
- package/out/services/semver.d.ts +0 -98
- package/out/services/semver.js +0 -195
- package/out/services/semver.js.map +0 -1
- package/out/services/types.d.ts +0 -340
- package/out/services/types.js +0 -46
- package/out/services/types.js.map +0 -1
- package/out/validation/manifest.d.ts +0 -144
- package/out/validation/manifest.js +0 -327
- package/out/validation/manifest.js.map +0 -1
- package/src/lsp/domain-lang-code-actions.ts +0 -189
- package/src/lsp/domain-lang-workspace-manager.ts +0 -104
- package/src/lsp/manifest-diagnostics.ts +0 -290
- package/src/services/semver.ts +0 -213
- package/src/services/types.ts +0 -415
- package/src/validation/manifest.ts +0 -439
package/out/validation/domain.js
CHANGED
|
@@ -14,50 +14,5 @@ function validateDomainHasVision(domain, accept) {
|
|
|
14
14
|
});
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
|
|
18
|
-
* Validates that a domain hierarchy does not contain circular references.
|
|
19
|
-
*
|
|
20
|
-
* The `Domain A in B` syntax expresses subdomain containment.
|
|
21
|
-
* Circular containment (A in B, B in C, C in A) is semantically invalid
|
|
22
|
-
* because it violates the fundamental concept of domain decomposition.
|
|
23
|
-
*
|
|
24
|
-
* @param domain - The domain to validate
|
|
25
|
-
* @param accept - The validation acceptor for reporting issues
|
|
26
|
-
*/
|
|
27
|
-
function validateNoCyclicDomainHierarchy(domain, accept) {
|
|
28
|
-
// Only check if this domain has a parent
|
|
29
|
-
if (!domain.parent?.ref) {
|
|
30
|
-
return;
|
|
31
|
-
}
|
|
32
|
-
const visited = new Set();
|
|
33
|
-
const path = [domain.name];
|
|
34
|
-
let current = domain.parent.ref;
|
|
35
|
-
while (current) {
|
|
36
|
-
// Check if we've encountered this domain before (cycle detected)
|
|
37
|
-
if (visited.has(current)) {
|
|
38
|
-
// We found a cycle - report it
|
|
39
|
-
path.push(current.name);
|
|
40
|
-
accept('error', ValidationMessages.DOMAIN_CIRCULAR_HIERARCHY(path), {
|
|
41
|
-
node: domain,
|
|
42
|
-
property: 'parent',
|
|
43
|
-
codeDescription: buildCodeDescription('language.md', 'domain-hierarchy')
|
|
44
|
-
});
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
// Check if we've looped back to the starting domain
|
|
48
|
-
if (current === domain) {
|
|
49
|
-
path.push(domain.name);
|
|
50
|
-
accept('error', ValidationMessages.DOMAIN_CIRCULAR_HIERARCHY(path), {
|
|
51
|
-
node: domain,
|
|
52
|
-
property: 'parent',
|
|
53
|
-
codeDescription: buildCodeDescription('language.md', 'domain-hierarchy')
|
|
54
|
-
});
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
visited.add(current);
|
|
58
|
-
path.push(current.name);
|
|
59
|
-
current = current.parent?.ref;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
export const domainChecks = [validateDomainHasVision, validateNoCyclicDomainHierarchy];
|
|
17
|
+
export const domainChecks = [validateDomainHasVision];
|
|
63
18
|
//# sourceMappingURL=domain.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"domain.js","sourceRoot":"","sources":["../../src/validation/domain.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE1E;;;;;GAKG;AACH,SAAS,uBAAuB,CAC5B,MAAc,EACd,MAA0B;IAE1B,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACjB,MAAM,CAAC,SAAS,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;YAChE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,QAAQ;YACjB,eAAe,EAAE,oBAAoB,CAAC,aAAa,EAAE,eAAe,CAAC;SACxE,CAAC,CAAC;IACP,CAAC;AACL,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"domain.js","sourceRoot":"","sources":["../../src/validation/domain.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE1E;;;;;GAKG;AACH,SAAS,uBAAuB,CAC5B,MAAc,EACd,MAA0B;IAE1B,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACjB,MAAM,CAAC,SAAS,EAAE,kBAAkB,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;YAChE,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,QAAQ;YACjB,eAAe,EAAE,oBAAoB,CAAC,aAAa,EAAE,eAAe,CAAC;SACxE,CAAC,CAAC;IACP,CAAC;AACL,CAAC;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,uBAAuB,CAAC,CAAC"}
|
|
@@ -1,68 +1,44 @@
|
|
|
1
1
|
import type { ValidationAcceptor, ValidationChecks } from 'langium';
|
|
2
|
-
import {
|
|
3
|
-
import type { DomainLangAstType, ImportStatement } from '../generated/ast.js';
|
|
2
|
+
import type { DomainLangAstType, ImportStatement, Model } from '../generated/ast.js';
|
|
4
3
|
import type { DomainLangServices } from '../domain-lang-module.js';
|
|
5
4
|
import type { LangiumDocument } from 'langium';
|
|
6
5
|
/**
|
|
7
6
|
* Validates import statements in DomainLang.
|
|
8
7
|
*
|
|
9
|
-
* Uses async validators (Langium 4.x supports MaybePromise<void>) to leverage
|
|
10
|
-
* the shared WorkspaceManager service with its cached manifest/lock file reading.
|
|
11
|
-
*
|
|
12
8
|
* Checks:
|
|
13
|
-
* -
|
|
14
|
-
* -
|
|
15
|
-
* -
|
|
9
|
+
* - Import paths are resolvable
|
|
10
|
+
* - Named imports exist in target document
|
|
11
|
+
* - Import aliases don't conflict with local names
|
|
16
12
|
*/
|
|
17
13
|
export declare class ImportValidator {
|
|
18
|
-
private readonly
|
|
14
|
+
private readonly documents;
|
|
19
15
|
constructor(services: DomainLangServices);
|
|
20
16
|
/**
|
|
21
|
-
* Validates an import
|
|
22
|
-
*
|
|
23
|
-
* Langium validators can return MaybePromise<void>, enabling async operations
|
|
24
|
-
* like reading manifests via the shared, cached WorkspaceManager.
|
|
25
|
-
*/
|
|
26
|
-
checkImportPath(imp: ImportStatement, accept: ValidationAcceptor, document: LangiumDocument, _cancelToken: Cancellation.CancellationToken): Promise<void>;
|
|
27
|
-
/**
|
|
28
|
-
* Determines if an import URI is external (requires manifest).
|
|
29
|
-
*
|
|
30
|
-
* Per PRS-010:
|
|
31
|
-
* - Local relative: ./path, ../path
|
|
32
|
-
* - Path aliases: @/path, @alias/path (resolved via manifest paths section)
|
|
33
|
-
* - External: owner/package (requires manifest dependencies)
|
|
34
|
-
*/
|
|
35
|
-
private isExternalImport;
|
|
36
|
-
/**
|
|
37
|
-
* Gets the normalized dependency configuration for an alias.
|
|
17
|
+
* Validates that an import path is resolvable.
|
|
38
18
|
*/
|
|
39
|
-
|
|
19
|
+
checkImportPath(imp: ImportStatement, accept: ValidationAcceptor, document: LangiumDocument): Promise<void>;
|
|
40
20
|
/**
|
|
41
|
-
* Validates
|
|
21
|
+
* Validates that named imports exist in the target document.
|
|
42
22
|
*/
|
|
43
|
-
|
|
23
|
+
checkNamedImports(imp: ImportStatement, accept: ValidationAcceptor, document: LangiumDocument): Promise<void>;
|
|
44
24
|
/**
|
|
45
|
-
*
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
*
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Gets the cache directory for a dependency.
|
|
54
|
-
* Per PRS-010: Project-local cache at .dlang/packages/{owner}/{repo}/{commit}/
|
|
25
|
+
* Gets all exportable symbols from a model.
|
|
26
|
+
*
|
|
27
|
+
* In DomainLang, top-level declarations are implicitly exported:
|
|
28
|
+
* - Domains
|
|
29
|
+
* - BoundedContexts
|
|
30
|
+
* - Classifications
|
|
31
|
+
* - Groups
|
|
55
32
|
*/
|
|
56
|
-
private
|
|
33
|
+
private getExportedSymbols;
|
|
57
34
|
/**
|
|
58
|
-
* Checks
|
|
35
|
+
* Checks for unused imports.
|
|
36
|
+
*
|
|
37
|
+
* This is a warning, not an error, to avoid being too strict.
|
|
59
38
|
*/
|
|
60
|
-
|
|
39
|
+
checkUnusedImports(imp: ImportStatement, _accept: ValidationAcceptor, _model: Model): void;
|
|
61
40
|
}
|
|
62
41
|
/**
|
|
63
42
|
* Creates validation checks for import statements.
|
|
64
|
-
*
|
|
65
|
-
* Returns async validators that leverage the shared WorkspaceManager
|
|
66
|
-
* for cached manifest/lock file reading.
|
|
67
43
|
*/
|
|
68
|
-
export declare function createImportChecks(
|
|
44
|
+
export declare function createImportChecks(_services: DomainLangServices): ValidationChecks<DomainLangAstType>;
|
package/out/validation/import.js
CHANGED
|
@@ -1,236 +1,134 @@
|
|
|
1
|
-
import
|
|
2
|
-
import path from 'node:path';
|
|
3
|
-
import { ValidationMessages, buildCodeDescription, IssueCodes } from './constants.js';
|
|
1
|
+
import { resolveImportPath } from '../utils/import-utils.js';
|
|
4
2
|
/**
|
|
5
3
|
* Validates import statements in DomainLang.
|
|
6
4
|
*
|
|
7
|
-
* Uses async validators (Langium 4.x supports MaybePromise<void>) to leverage
|
|
8
|
-
* the shared WorkspaceManager service with its cached manifest/lock file reading.
|
|
9
|
-
*
|
|
10
5
|
* Checks:
|
|
11
|
-
* -
|
|
12
|
-
* -
|
|
13
|
-
* -
|
|
6
|
+
* - Import paths are resolvable
|
|
7
|
+
* - Named imports exist in target document
|
|
8
|
+
* - Import aliases don't conflict with local names
|
|
14
9
|
*/
|
|
15
10
|
export class ImportValidator {
|
|
16
11
|
constructor(services) {
|
|
17
|
-
this.
|
|
12
|
+
this.documents = services.shared.workspace.LangiumDocuments;
|
|
18
13
|
}
|
|
19
14
|
/**
|
|
20
|
-
* Validates an import
|
|
21
|
-
*
|
|
22
|
-
* Langium validators can return MaybePromise<void>, enabling async operations
|
|
23
|
-
* like reading manifests via the shared, cached WorkspaceManager.
|
|
15
|
+
* Validates that an import path is resolvable.
|
|
24
16
|
*/
|
|
25
|
-
async checkImportPath(imp, accept, document
|
|
17
|
+
async checkImportPath(imp, accept, document) {
|
|
26
18
|
if (!imp.uri) {
|
|
27
|
-
accept('error',
|
|
19
|
+
accept('error', 'Import statement must have a URI', {
|
|
28
20
|
node: imp,
|
|
29
|
-
keyword: 'import'
|
|
30
|
-
codeDescription: buildCodeDescription('language.md', 'imports'),
|
|
31
|
-
data: { code: IssueCodes.ImportMissingUri }
|
|
21
|
+
keyword: 'import'
|
|
32
22
|
});
|
|
33
23
|
return;
|
|
34
24
|
}
|
|
35
|
-
|
|
36
|
-
|
|
25
|
+
try {
|
|
26
|
+
await resolveImportPath(document, imp.uri);
|
|
37
27
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const manifest = await this.workspaceManager.getManifest();
|
|
42
|
-
if (!manifest) {
|
|
43
|
-
accept('error', ValidationMessages.IMPORT_REQUIRES_MANIFEST(imp.uri), {
|
|
28
|
+
catch (error) {
|
|
29
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
30
|
+
accept('error', `Cannot resolve import: ${message}`, {
|
|
44
31
|
node: imp,
|
|
45
|
-
property: 'uri'
|
|
46
|
-
codeDescription: buildCodeDescription('language.md', 'imports'),
|
|
47
|
-
data: { code: IssueCodes.ImportRequiresManifest, specifier: imp.uri }
|
|
32
|
+
property: 'uri'
|
|
48
33
|
});
|
|
49
|
-
return;
|
|
50
34
|
}
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
data: { code: IssueCodes.ImportNotInManifest, alias }
|
|
59
|
-
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Validates that named imports exist in the target document.
|
|
38
|
+
*/
|
|
39
|
+
async checkNamedImports(imp, accept, document) {
|
|
40
|
+
// Only check if we have named imports
|
|
41
|
+
if (!imp.symbols || imp.symbols.length === 0) {
|
|
60
42
|
return;
|
|
61
43
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
44
|
+
if (!imp.uri) {
|
|
45
|
+
return; // Already reported by checkImportPath
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
// Resolve the target document
|
|
49
|
+
const targetUri = await resolveImportPath(document, imp.uri);
|
|
50
|
+
const targetDoc = await this.documents.getOrCreateDocument(targetUri);
|
|
51
|
+
if (!targetDoc.parseResult?.value) {
|
|
52
|
+
accept('error', `Cannot load imported document: ${imp.uri}`, {
|
|
68
53
|
node: imp,
|
|
69
|
-
property: 'uri'
|
|
70
|
-
codeDescription: buildCodeDescription('language.md', 'imports'),
|
|
71
|
-
data: { code: IssueCodes.ImportNotInstalled, alias }
|
|
54
|
+
property: 'uri'
|
|
72
55
|
});
|
|
73
56
|
return;
|
|
74
57
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
if (uri.startsWith('./') || uri.startsWith('../')) {
|
|
88
|
-
return false;
|
|
89
|
-
}
|
|
90
|
-
if (uri.startsWith('@')) {
|
|
91
|
-
return false;
|
|
92
|
-
}
|
|
93
|
-
return true;
|
|
94
|
-
}
|
|
95
|
-
/**
|
|
96
|
-
* Gets the normalized dependency configuration for an alias.
|
|
97
|
-
*/
|
|
98
|
-
getDependency(manifest, alias) {
|
|
99
|
-
const dep = manifest.dependencies?.[alias];
|
|
100
|
-
if (!dep) {
|
|
101
|
-
return undefined;
|
|
102
|
-
}
|
|
103
|
-
if (typeof dep === 'string') {
|
|
104
|
-
return { source: alias, ref: dep };
|
|
105
|
-
}
|
|
106
|
-
if (!dep.source && !dep.path) {
|
|
107
|
-
return { ...dep, source: alias };
|
|
108
|
-
}
|
|
109
|
-
return dep;
|
|
110
|
-
}
|
|
111
|
-
/**
|
|
112
|
-
* Validates dependency configuration.
|
|
113
|
-
*/
|
|
114
|
-
validateDependencyConfig(dependency, alias, accept, imp) {
|
|
115
|
-
if (dependency.source && dependency.path) {
|
|
116
|
-
accept('error', ValidationMessages.IMPORT_CONFLICTING_SOURCE_PATH(alias), {
|
|
117
|
-
node: imp,
|
|
118
|
-
property: 'uri',
|
|
119
|
-
codeDescription: buildCodeDescription('language.md', 'imports'),
|
|
120
|
-
data: { code: IssueCodes.ImportConflictingSourcePath, alias }
|
|
121
|
-
});
|
|
122
|
-
return;
|
|
58
|
+
// Get all exported symbols from target document
|
|
59
|
+
const targetModel = targetDoc.parseResult.value;
|
|
60
|
+
const exportedSymbols = this.getExportedSymbols(targetModel);
|
|
61
|
+
// Check each imported symbol
|
|
62
|
+
for (const symbol of imp.symbols) {
|
|
63
|
+
if (!exportedSymbols.has(symbol)) {
|
|
64
|
+
accept('error', `Symbol '${symbol}' not found in ${imp.uri}`, {
|
|
65
|
+
node: imp,
|
|
66
|
+
property: 'symbols'
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
123
70
|
}
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
node: imp,
|
|
127
|
-
property: 'uri',
|
|
128
|
-
codeDescription: buildCodeDescription('language.md', 'imports'),
|
|
129
|
-
data: { code: IssueCodes.ImportMissingSourceOrPath, alias }
|
|
130
|
-
});
|
|
71
|
+
catch {
|
|
72
|
+
// Import path error already reported by checkImportPath
|
|
131
73
|
return;
|
|
132
74
|
}
|
|
133
|
-
if (dependency.source && !dependency.ref) {
|
|
134
|
-
accept('error', ValidationMessages.IMPORT_MISSING_REF(alias), {
|
|
135
|
-
node: imp,
|
|
136
|
-
property: 'uri',
|
|
137
|
-
codeDescription: buildCodeDescription('language.md', 'imports'),
|
|
138
|
-
data: { code: IssueCodes.ImportMissingRef, alias }
|
|
139
|
-
});
|
|
140
|
-
}
|
|
141
|
-
if (dependency.path) {
|
|
142
|
-
this.validateLocalPathDependency(dependency.path, alias, accept, imp);
|
|
143
|
-
}
|
|
144
75
|
}
|
|
145
76
|
/**
|
|
146
|
-
*
|
|
77
|
+
* Gets all exportable symbols from a model.
|
|
78
|
+
*
|
|
79
|
+
* In DomainLang, top-level declarations are implicitly exported:
|
|
80
|
+
* - Domains
|
|
81
|
+
* - BoundedContexts
|
|
82
|
+
* - Classifications
|
|
83
|
+
* - Groups
|
|
147
84
|
*/
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
}
|
|
156
|
-
return;
|
|
157
|
-
}
|
|
158
|
-
const workspaceRoot = this.workspaceManager.getWorkspaceRoot();
|
|
159
|
-
const resolvedPath = path.resolve(workspaceRoot, dependencyPath);
|
|
160
|
-
const relativeToWorkspace = path.relative(workspaceRoot, resolvedPath);
|
|
161
|
-
if (relativeToWorkspace.startsWith('..') || path.isAbsolute(relativeToWorkspace)) {
|
|
162
|
-
accept('error', ValidationMessages.IMPORT_ESCAPES_WORKSPACE(alias), {
|
|
163
|
-
node: imp,
|
|
164
|
-
property: 'uri',
|
|
165
|
-
codeDescription: buildCodeDescription('language.md', 'imports'),
|
|
166
|
-
data: { code: IssueCodes.ImportEscapesWorkspace, alias }
|
|
167
|
-
});
|
|
85
|
+
getExportedSymbols(model) {
|
|
86
|
+
const symbols = new Set();
|
|
87
|
+
// Iterate through all structure elements
|
|
88
|
+
for (const element of model.children ?? []) {
|
|
89
|
+
// Check if element has a name and add it
|
|
90
|
+
if ('name' in element && typeof element.name === 'string') {
|
|
91
|
+
symbols.add(element.name);
|
|
92
|
+
}
|
|
168
93
|
}
|
|
94
|
+
return symbols;
|
|
169
95
|
}
|
|
170
96
|
/**
|
|
171
|
-
*
|
|
97
|
+
* Checks for unused imports.
|
|
98
|
+
*
|
|
99
|
+
* This is a warning, not an error, to avoid being too strict.
|
|
172
100
|
*/
|
|
173
|
-
|
|
174
|
-
//
|
|
175
|
-
|
|
176
|
-
const lockedDep = lockFile.dependencies[packageKey];
|
|
177
|
-
if (!lockedDep) {
|
|
178
|
-
accept('error', ValidationMessages.IMPORT_NOT_INSTALLED(alias), {
|
|
179
|
-
node: imp,
|
|
180
|
-
property: 'uri',
|
|
181
|
-
codeDescription: buildCodeDescription('language.md', 'imports'),
|
|
182
|
-
data: { code: IssueCodes.ImportNotInstalled, alias }
|
|
183
|
-
});
|
|
101
|
+
checkUnusedImports(imp, _accept, _model) {
|
|
102
|
+
// Skip check for wildcard imports (no named imports)
|
|
103
|
+
if (!imp.symbols || imp.symbols.length === 0) {
|
|
184
104
|
return;
|
|
185
105
|
}
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
if (!cacheExists) {
|
|
190
|
-
accept('error', ValidationMessages.IMPORT_NOT_INSTALLED(alias), {
|
|
191
|
-
node: imp,
|
|
192
|
-
property: 'uri',
|
|
193
|
-
codeDescription: buildCodeDescription('language.md', 'imports'),
|
|
194
|
-
data: { code: IssueCodes.ImportNotInstalled, alias }
|
|
195
|
-
});
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
/**
|
|
199
|
-
* Gets the cache directory for a dependency.
|
|
200
|
-
* Per PRS-010: Project-local cache at .dlang/packages/{owner}/{repo}/{commit}/
|
|
201
|
-
*/
|
|
202
|
-
getCacheDirectory(workspaceRoot, source, commitHash) {
|
|
203
|
-
const [owner, repo] = source.split('/');
|
|
204
|
-
return path.join(workspaceRoot, '.dlang', 'packages', owner, repo, commitHash);
|
|
205
|
-
}
|
|
206
|
-
/**
|
|
207
|
-
* Checks if a directory exists (async).
|
|
208
|
-
*/
|
|
209
|
-
async directoryExists(dirPath) {
|
|
210
|
-
try {
|
|
211
|
-
const stat = await fs.stat(dirPath);
|
|
212
|
-
return stat.isDirectory();
|
|
213
|
-
}
|
|
214
|
-
catch {
|
|
215
|
-
return false;
|
|
216
|
-
}
|
|
106
|
+
// For now, just a placeholder - would require tracking symbol usage
|
|
107
|
+
// across the entire document, which is complex
|
|
108
|
+
// TODO: Implement symbol usage tracking
|
|
217
109
|
}
|
|
218
110
|
}
|
|
219
111
|
/**
|
|
220
112
|
* Creates validation checks for import statements.
|
|
221
|
-
*
|
|
222
|
-
* Returns async validators that leverage the shared WorkspaceManager
|
|
223
|
-
* for cached manifest/lock file reading.
|
|
224
113
|
*/
|
|
225
|
-
export function createImportChecks(
|
|
226
|
-
const validator = new ImportValidator(services);
|
|
114
|
+
export function createImportChecks(_services) {
|
|
227
115
|
return {
|
|
228
|
-
|
|
229
|
-
ImportStatement: async (imp, accept, cancelToken) => {
|
|
116
|
+
ImportStatement: (imp, accept) => {
|
|
230
117
|
const document = imp.$document;
|
|
231
118
|
if (!document)
|
|
232
119
|
return;
|
|
233
|
-
|
|
120
|
+
// Note: Langium's validation is synchronous, so async checks won't
|
|
121
|
+
// execute during document validation. These checks will run during
|
|
122
|
+
// the build phase when documents are fully loaded.
|
|
123
|
+
// For now, just do basic syntax validation
|
|
124
|
+
if (!imp.uri) {
|
|
125
|
+
accept('error', 'Import statement must have a URI', {
|
|
126
|
+
node: imp,
|
|
127
|
+
keyword: 'import'
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
// TODO: Implement async validation in a separate build phase
|
|
131
|
+
// This would require using DocumentBuilder.onBuildPhase() or similar
|
|
234
132
|
}
|
|
235
133
|
};
|
|
236
134
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import.js","sourceRoot":"","sources":["../../src/validation/import.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"import.js","sourceRoot":"","sources":["../../src/validation/import.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAI7D;;;;;;;GAOG;AACH,MAAM,OAAO,eAAe;IAGxB,YAAY,QAA4B;QACpC,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,gBAAgB,CAAC;IAChE,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,eAAe,CACjB,GAAoB,EACpB,MAA0B,EAC1B,QAAyB;QAEzB,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;YACX,MAAM,CAAC,OAAO,EAAE,kCAAkC,EAAE;gBAChD,IAAI,EAAE,GAAG;gBACT,OAAO,EAAE,QAAQ;aACpB,CAAC,CAAC;YACH,OAAO;QACX,CAAC;QAED,IAAI,CAAC;YACD,MAAM,iBAAiB,CAAC,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;QAC/C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,MAAM,CAAC,OAAO,EAAE,0BAA0B,OAAO,EAAE,EAAE;gBACjD,IAAI,EAAE,GAAG;gBACT,QAAQ,EAAE,KAAK;aAClB,CAAC,CAAC;QACP,CAAC;IACL,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,iBAAiB,CACnB,GAAoB,EACpB,MAA0B,EAC1B,QAAyB;QAEzB,sCAAsC;QACtC,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3C,OAAO;QACX,CAAC;QAED,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;YACX,OAAO,CAAC,sCAAsC;QAClD,CAAC;QAED,IAAI,CAAC;YACD,8BAA8B;YAC9B,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,QAAQ,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;YAC7D,MAAM,SAAS,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,mBAAmB,CAAC,SAAS,CAAC,CAAC;YAEtE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,KAAK,EAAE,CAAC;gBAChC,MAAM,CAAC,OAAO,EAAE,kCAAkC,GAAG,CAAC,GAAG,EAAE,EAAE;oBACzD,IAAI,EAAE,GAAG;oBACT,QAAQ,EAAE,KAAK;iBAClB,CAAC,CAAC;gBACH,OAAO;YACX,CAAC;YAED,gDAAgD;YAChD,MAAM,WAAW,GAAG,SAAS,CAAC,WAAW,CAAC,KAAc,CAAC;YACzD,MAAM,eAAe,GAAG,IAAI,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAC;YAE7D,6BAA6B;YAC7B,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;gBAC/B,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;oBAC/B,MAAM,CAAC,OAAO,EACV,WAAW,MAAM,kBAAkB,GAAG,CAAC,GAAG,EAAE,EAC5C;wBACI,IAAI,EAAE,GAAG;wBACT,QAAQ,EAAE,SAAS;qBACtB,CACJ,CAAC;gBACN,CAAC;YACL,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACL,wDAAwD;YACxD,OAAO;QACX,CAAC;IACL,CAAC;IAED;;;;;;;;OAQG;IACK,kBAAkB,CAAC,KAAY;QACnC,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;QAElC,yCAAyC;QACzC,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;YACzC,yCAAyC;YACzC,IAAI,MAAM,IAAI,OAAO,IAAI,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACxD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC9B,CAAC;QACL,CAAC;QAED,OAAO,OAAO,CAAC;IACnB,CAAC;IAED;;;;OAIG;IACH,kBAAkB,CACd,GAAoB,EACpB,OAA2B,EAC3B,MAAa;QAEb,qDAAqD;QACrD,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC3C,OAAO;QACX,CAAC;QAED,oEAAoE;QACpE,+CAA+C;QAC/C,wCAAwC;IAC5C,CAAC;CACJ;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAA6B;IAE5D,OAAO;QACH,eAAe,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;YAC7B,MAAM,QAAQ,GAAG,GAAG,CAAC,SAAS,CAAC;YAC/B,IAAI,CAAC,QAAQ;gBAAE,OAAO;YAEtB,mEAAmE;YACnE,mEAAmE;YACnE,mDAAmD;YAEnD,2CAA2C;YAC3C,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;gBACX,MAAM,CAAC,OAAO,EAAE,kCAAkC,EAAE;oBAChD,IAAI,EAAE,GAAG;oBACT,OAAO,EAAE,QAAQ;iBACpB,CAAC,CAAC;YACP,CAAC;YAED,6DAA6D;YAC7D,qEAAqE;QACzE,CAAC;KACJ,CAAC;AACN,CAAC"}
|
package/out/validation/maps.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ValidationMessages, buildCodeDescription } from './constants.js';
|
|
2
1
|
/**
|
|
3
2
|
* Validates that a context map contains at least one bounded context.
|
|
4
3
|
* Empty context maps are not useful for documentation purposes.
|
|
@@ -8,10 +7,9 @@ import { ValidationMessages, buildCodeDescription } from './constants.js';
|
|
|
8
7
|
*/
|
|
9
8
|
function validateContextMapHasContexts(map, accept) {
|
|
10
9
|
if (!map.boundedContexts || map.boundedContexts.length === 0) {
|
|
11
|
-
accept('warning',
|
|
10
|
+
accept('warning', `Context Map '${map.name}' contains no bounded contexts`, {
|
|
12
11
|
node: map,
|
|
13
|
-
keyword: 'contains'
|
|
14
|
-
codeDescription: buildCodeDescription('language.md', 'context-maps')
|
|
12
|
+
keyword: 'contains'
|
|
15
13
|
});
|
|
16
14
|
}
|
|
17
15
|
}
|
|
@@ -27,10 +25,9 @@ function validateContextMapHasRelationships(map, accept) {
|
|
|
27
25
|
const relationshipCount = map.relationships?.length ?? 0;
|
|
28
26
|
// Only warn if multiple contexts exist without relationships
|
|
29
27
|
if (contextCount > 1 && relationshipCount === 0) {
|
|
30
|
-
accept('info',
|
|
28
|
+
accept('info', `Context Map '${map.name}' contains ${contextCount} contexts but no documented relationships`, {
|
|
31
29
|
node: map,
|
|
32
|
-
keyword: 'ContextMap'
|
|
33
|
-
codeDescription: buildCodeDescription('language.md', 'context-maps')
|
|
30
|
+
keyword: 'ContextMap'
|
|
34
31
|
});
|
|
35
32
|
}
|
|
36
33
|
}
|
|
@@ -43,10 +40,9 @@ function validateContextMapHasRelationships(map, accept) {
|
|
|
43
40
|
*/
|
|
44
41
|
function validateDomainMapHasDomains(map, accept) {
|
|
45
42
|
if (!map.domains || map.domains.length === 0) {
|
|
46
|
-
accept('warning',
|
|
43
|
+
accept('warning', `Domain Map '${map.name}' contains no domains`, {
|
|
47
44
|
node: map,
|
|
48
|
-
keyword: 'contains'
|
|
49
|
-
codeDescription: buildCodeDescription('language.md', 'domain-maps')
|
|
45
|
+
keyword: 'contains'
|
|
50
46
|
});
|
|
51
47
|
}
|
|
52
48
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"maps.js","sourceRoot":"","sources":["../../src/validation/maps.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"maps.js","sourceRoot":"","sources":["../../src/validation/maps.ts"],"names":[],"mappings":"AAGA;;;;;;GAMG;AACH,SAAS,6BAA6B,CAClC,GAAe,EACf,MAA0B;IAE1B,IAAI,CAAC,GAAG,CAAC,eAAe,IAAI,GAAG,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3D,MAAM,CAAC,SAAS,EAAE,gBAAgB,GAAG,CAAC,IAAI,gCAAgC,EAAE;YACxE,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,UAAU;SACtB,CAAC,CAAC;IACP,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,SAAS,kCAAkC,CACvC,GAAe,EACf,MAA0B;IAE1B,MAAM,YAAY,GAAG,GAAG,CAAC,eAAe,EAAE,MAAM,IAAI,CAAC,CAAC;IACtD,MAAM,iBAAiB,GAAG,GAAG,CAAC,aAAa,EAAE,MAAM,IAAI,CAAC,CAAC;IAEzD,6DAA6D;IAC7D,IAAI,YAAY,GAAG,CAAC,IAAI,iBAAiB,KAAK,CAAC,EAAE,CAAC;QAC9C,MAAM,CAAC,MAAM,EAAE,gBAAgB,GAAG,CAAC,IAAI,cAAc,YAAY,2CAA2C,EAAE;YAC1G,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,YAAY;SACxB,CAAC,CAAC;IACP,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,SAAS,2BAA2B,CAChC,GAAc,EACd,MAA0B;IAE1B,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3C,MAAM,CAAC,SAAS,EAAE,eAAe,GAAG,CAAC,IAAI,uBAAuB,EAAE;YAC9D,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,UAAU;SACtB,CAAC,CAAC;IACP,CAAC;AACL,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC5B,6BAA6B;IAC7B,kCAAkC;CACrC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG;IAC3B,2BAA2B;CAC9B,CAAC"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { ValidationMessages, buildCodeDescription } from './constants.js';
|
|
2
1
|
/**
|
|
3
2
|
* Validation checks for Metadata elements.
|
|
4
3
|
* - Ensures metadata keys are defined before use
|
|
@@ -6,10 +5,7 @@ import { ValidationMessages, buildCodeDescription } from './constants.js';
|
|
|
6
5
|
export const metadataChecks = {
|
|
7
6
|
Metadata(metadata, accept) {
|
|
8
7
|
if (!metadata.name) {
|
|
9
|
-
accept('error',
|
|
10
|
-
node: metadata,
|
|
11
|
-
codeDescription: buildCodeDescription('language.md', 'metadata')
|
|
12
|
-
});
|
|
8
|
+
accept('error', 'Metadata must have a name', { node: metadata });
|
|
13
9
|
}
|
|
14
10
|
},
|
|
15
11
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/validation/metadata.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/validation/metadata.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,MAAM,CAAC,MAAM,cAAc,GAAwC;IAC/D,QAAQ,CAAC,QAAkB,EAAE,MAAM;QAC/B,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;YACjB,MAAM,CAAC,OAAO,EAAE,2BAA2B,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrE,CAAC;IACL,CAAC;CACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@domainlang/language",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.82",
|
|
4
4
|
"displayName": "DomainLang Language",
|
|
5
5
|
"description": "Core language library for DomainLang - parse, validate, and query Domain-Driven Design models programmatically",
|
|
6
6
|
"author": "larsbaunwall",
|
|
@@ -23,14 +23,14 @@
|
|
|
23
23
|
"parser",
|
|
24
24
|
"sdk"
|
|
25
25
|
],
|
|
26
|
-
"homepage": "https://
|
|
26
|
+
"homepage": "https://github.com/larsbaunwall/DomainLang#readme",
|
|
27
27
|
"repository": {
|
|
28
28
|
"type": "git",
|
|
29
|
-
"url": "https://github.com/
|
|
29
|
+
"url": "https://github.com/larsbaunwall/DomainLang",
|
|
30
30
|
"directory": "dsl/domain-lang/packages/language"
|
|
31
31
|
},
|
|
32
32
|
"bugs": {
|
|
33
|
-
"url": "https://github.com/
|
|
33
|
+
"url": "https://github.com/larsbaunwall/DomainLang/issues"
|
|
34
34
|
},
|
|
35
35
|
"type": "module",
|
|
36
36
|
"engines": {
|
|
@@ -86,15 +86,13 @@
|
|
|
86
86
|
"test:coverage": "vitest run --coverage"
|
|
87
87
|
},
|
|
88
88
|
"dependencies": {
|
|
89
|
-
"langium": "~4.
|
|
90
|
-
"monaco-editor": "0.55.1",
|
|
91
|
-
"vite": "6.4.1",
|
|
89
|
+
"langium": "~4.1.0",
|
|
92
90
|
"yaml": "^2.5.0"
|
|
93
91
|
},
|
|
94
92
|
"devDependencies": {
|
|
95
93
|
"@types/node": "~20.17.48",
|
|
96
94
|
"@vitest/coverage-v8": "^3.1.4",
|
|
97
|
-
"langium-cli": "~4.
|
|
95
|
+
"langium-cli": "~4.1.0",
|
|
98
96
|
"shx": "~0.4.0",
|
|
99
97
|
"typescript": "~5.8.3",
|
|
100
98
|
"vitest": "~3.1.3"
|