@domainlang/language 0.5.2 → 0.6.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 (104) hide show
  1. package/out/domain-lang-module.js +3 -1
  2. package/out/domain-lang-module.js.map +1 -1
  3. package/out/generated/ast.d.ts +24 -0
  4. package/out/generated/ast.js.map +1 -1
  5. package/out/generated/grammar.js +22 -32
  6. package/out/generated/grammar.js.map +1 -1
  7. package/out/index.d.ts +2 -5
  8. package/out/index.js +10 -6
  9. package/out/index.js.map +1 -1
  10. package/out/lsp/domain-lang-code-actions.js +14 -8
  11. package/out/lsp/domain-lang-code-actions.js.map +1 -1
  12. package/out/lsp/domain-lang-completion.d.ts +3 -0
  13. package/out/lsp/domain-lang-completion.js +41 -13
  14. package/out/lsp/domain-lang-completion.js.map +1 -1
  15. package/out/lsp/domain-lang-formatter.js +24 -18
  16. package/out/lsp/domain-lang-formatter.js.map +1 -1
  17. package/out/lsp/domain-lang-index-manager.d.ts +102 -0
  18. package/out/lsp/domain-lang-index-manager.js +221 -0
  19. package/out/lsp/domain-lang-index-manager.js.map +1 -0
  20. package/out/lsp/domain-lang-scope.js +31 -17
  21. package/out/lsp/domain-lang-scope.js.map +1 -1
  22. package/out/lsp/domain-lang-workspace-manager.d.ts +51 -9
  23. package/out/lsp/domain-lang-workspace-manager.js +86 -63
  24. package/out/lsp/domain-lang-workspace-manager.js.map +1 -1
  25. package/out/lsp/hover/domain-lang-hover.d.ts +45 -1
  26. package/out/lsp/hover/domain-lang-hover.js +308 -232
  27. package/out/lsp/hover/domain-lang-hover.js.map +1 -1
  28. package/out/lsp/hover/domain-lang-keywords.d.ts +3 -7
  29. package/out/lsp/hover/domain-lang-keywords.js +115 -38
  30. package/out/lsp/hover/domain-lang-keywords.js.map +1 -1
  31. package/out/lsp/manifest-diagnostics.js +95 -50
  32. package/out/lsp/manifest-diagnostics.js.map +1 -1
  33. package/out/main.js +109 -17
  34. package/out/main.js.map +1 -1
  35. package/out/services/import-resolver.d.ts +16 -2
  36. package/out/services/import-resolver.js +37 -11
  37. package/out/services/import-resolver.js.map +1 -1
  38. package/out/services/types.d.ts +2 -2
  39. package/out/services/workspace-manager.d.ts +33 -31
  40. package/out/services/workspace-manager.js +92 -148
  41. package/out/services/workspace-manager.js.map +1 -1
  42. package/out/utils/document-utils.d.ts +41 -0
  43. package/out/utils/document-utils.js +64 -0
  44. package/out/utils/document-utils.js.map +1 -0
  45. package/out/utils/import-utils.d.ts +0 -17
  46. package/out/utils/import-utils.js +2 -32
  47. package/out/utils/import-utils.js.map +1 -1
  48. package/out/utils/manifest-utils.d.ts +56 -0
  49. package/out/utils/manifest-utils.js +119 -0
  50. package/out/utils/manifest-utils.js.map +1 -0
  51. package/out/validation/import.d.ts +1 -2
  52. package/out/validation/import.js +33 -20
  53. package/out/validation/import.js.map +1 -1
  54. package/package.json +1 -1
  55. package/src/domain-lang-module.ts +4 -1
  56. package/src/domain-lang.langium +37 -13
  57. package/src/generated/ast.ts +24 -0
  58. package/src/generated/grammar.ts +22 -32
  59. package/src/index.ts +12 -6
  60. package/src/lsp/domain-lang-code-actions.ts +13 -8
  61. package/src/lsp/domain-lang-completion.ts +61 -13
  62. package/src/lsp/domain-lang-formatter.ts +28 -23
  63. package/src/lsp/domain-lang-index-manager.ts +256 -0
  64. package/src/lsp/domain-lang-scope.ts +29 -17
  65. package/src/lsp/domain-lang-workspace-manager.ts +89 -66
  66. package/src/lsp/hover/domain-lang-hover.ts +332 -226
  67. package/src/lsp/hover/domain-lang-keywords.ts +129 -43
  68. package/src/lsp/manifest-diagnostics.ts +100 -59
  69. package/src/main.ts +127 -16
  70. package/src/services/import-resolver.ts +39 -11
  71. package/src/services/types.ts +2 -2
  72. package/src/services/workspace-manager.ts +101 -175
  73. package/src/utils/document-utils.ts +80 -0
  74. package/src/utils/import-utils.ts +2 -40
  75. package/src/utils/manifest-utils.ts +132 -0
  76. package/src/validation/import.ts +32 -22
  77. package/out/lsp/hover/ddd-pattern-explanations.d.ts +0 -50
  78. package/out/lsp/hover/ddd-pattern-explanations.js +0 -196
  79. package/out/lsp/hover/ddd-pattern-explanations.js.map +0 -1
  80. package/out/services/dependency-analyzer.d.ts +0 -58
  81. package/out/services/dependency-analyzer.js +0 -254
  82. package/out/services/dependency-analyzer.js.map +0 -1
  83. package/out/services/dependency-resolver.d.ts +0 -146
  84. package/out/services/dependency-resolver.js +0 -452
  85. package/out/services/dependency-resolver.js.map +0 -1
  86. package/out/services/git-url-resolver.browser.d.ts +0 -10
  87. package/out/services/git-url-resolver.browser.js +0 -19
  88. package/out/services/git-url-resolver.browser.js.map +0 -1
  89. package/out/services/git-url-resolver.d.ts +0 -158
  90. package/out/services/git-url-resolver.js +0 -416
  91. package/out/services/git-url-resolver.js.map +0 -1
  92. package/out/services/governance-validator.d.ts +0 -44
  93. package/out/services/governance-validator.js +0 -153
  94. package/out/services/governance-validator.js.map +0 -1
  95. package/out/services/semver.d.ts +0 -98
  96. package/out/services/semver.js +0 -195
  97. package/out/services/semver.js.map +0 -1
  98. package/src/lsp/hover/ddd-pattern-explanations.ts +0 -237
  99. package/src/services/dependency-analyzer.ts +0 -321
  100. package/src/services/dependency-resolver.ts +0 -551
  101. package/src/services/git-url-resolver.browser.ts +0 -26
  102. package/src/services/git-url-resolver.ts +0 -517
  103. package/src/services/governance-validator.ts +0 -177
  104. package/src/services/semver.ts +0 -213
@@ -144,8 +144,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
144
144
  "elements": [
145
145
  {
146
146
  "$type": "Keyword",
147
- "value": "Domain",
148
- "$comment": "/** A Domain represents a sphere of knowledge, influence, or activity. In DDD, it is the subject area to which the user applies a program. Example: Sales, Shipping, Accounting. */"
147
+ "value": "Domain"
149
148
  },
150
149
  {
151
150
  "$type": "Keyword",
@@ -312,7 +311,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
312
311
  "entry": false,
313
312
  "fragment": false,
314
313
  "parameters": [],
315
- "$comment": "/**\\n * Domain - A sphere of knowledge or activity in DDD.\\n * Can be nested via \`in\` to show subdomain hierarchy.\\n * The \`type\` property indicates strategic importance (Core, Supporting, Generic) per Bounded Context Canvas.\\n * Body is optional - allows header-only Domain definitions.\\n */"
314
+ "$comment": "/**\\n * Domain - A sphere of knowledge or activity in DDD.\\n * Can be nested via \`in\` to show subdomain hierarchy.\\n * The \`type\` property indicates strategic importance (Core, Supporting, Generic) per Bounded Context Canvas.\\n * Body is optional - allows header-only Domain definitions.\\n * \\n * [Read more on domainlang.net](https://domainlang.net/reference/language#domains)\\n */"
316
315
  },
317
316
  {
318
317
  "$type": "ParserRule",
@@ -325,8 +324,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
325
324
  "elements": [
326
325
  {
327
326
  "$type": "Keyword",
328
- "value": "BoundedContext",
329
- "$comment": "/** A Bounded Context defines the boundary within which a particular domain model is defined and applicable. It is a central pattern in DDD for managing complexity. Example: SalesContext, SupportContext. */"
327
+ "value": "BoundedContext"
330
328
  },
331
329
  {
332
330
  "$type": "Keyword",
@@ -879,7 +877,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
879
877
  "entry": false,
880
878
  "fragment": false,
881
879
  "parameters": [],
882
- "$comment": "/**\\n * Bounded Context - A boundary within which a domain model is defined.\\n * Central pattern in DDD for managing complexity and team boundaries.\\n * Belongs to exactly ONE domain (fundamental DDD principle).\\n * Body properties can appear in any order. Validation enforces at-most-once constraint.\\n * The \`classification\` property indicates strategic importance per Bounded Context Canvas.\\n * The \`evolution\` property indicates maturity stage per Wardley Maps/BC Canvas.\\n * The \`archetype\` property indicates behavioral role per DDD archetypes (Gateway, Execution, etc).\\n */"
880
+ "$comment": "/**\\n * Bounded Context - A boundary within which a domain model is defined.\\n * Central pattern in DDD for managing complexity and team boundaries.\\n * Belongs to exactly ONE domain (fundamental DDD principle).\\n * Body properties can appear in any order. Validation enforces at-most-once constraint.\\n * The \`classification\` property indicates strategic importance per Bounded Context Canvas.\\n * The \`evolution\` property indicates maturity stage per Wardley Maps/BC Canvas.\\n * The \`archetype\` property indicates behavioral role per DDD archetypes (Gateway, Execution, etc).\\n * \\n * [Read more on domainlang.net](https://domainlang.net/reference/language#bounded-contexts)\\n */"
883
881
  },
884
882
  {
885
883
  "$type": "ParserRule",
@@ -959,7 +957,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
959
957
  "entry": false,
960
958
  "fragment": false,
961
959
  "parameters": [],
962
- "$comment": "/**\\n * Team - People responsible for a Bounded Context or Domain.\\n * Represents organizational boundaries in DDD.\\n */"
960
+ "$comment": "/**\\n * Team - People responsible for a Bounded Context or Domain.\\n * Represents organizational boundaries in DDD.\\n * \\n * [Read more on domainlang.net](https://domainlang.net/reference/language#teams)\\n */"
963
961
  },
964
962
  {
965
963
  "$type": "ParserRule",
@@ -988,7 +986,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
988
986
  "entry": false,
989
987
  "fragment": false,
990
988
  "parameters": [],
991
- "$comment": "/**\\n * Classification - Reusable label for categorizing elements.\\n * Examples: Core, Supporting, Generic, Strategic, Commodity, Architectural, Business, Technical.\\n */"
989
+ "$comment": "/**\\n * Classification - Reusable label for categorizing elements.\\n * Examples: Core, Supporting, Generic, Strategic, Commodity, Architectural, Business, Technical.\\n * \\n * [Read more on domainlang.net](https://domainlang.net/reference/language#classifications)\\n */"
992
990
  },
993
991
  {
994
992
  "$type": "ParserRule",
@@ -1017,7 +1015,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
1017
1015
  "entry": false,
1018
1016
  "fragment": false,
1019
1017
  "parameters": [],
1020
- "$comment": "/**\\n * Metadata - Defines a key that can be used in metadata blocks.\\n * Examples: Language, Framework, Database, Repository.\\n * Can be defined locally or imported from stdlib.\\n */"
1018
+ "$comment": "/**\\n * Metadata - Defines a key that can be used in metadata blocks.\\n * Examples: Language, Framework, Database, Repository.\\n * Can be defined locally or imported from stdlib.\\n * \\n * [Read more on domainlang.net](https://domainlang.net/reference/language#metadata)\\n */"
1021
1019
  },
1022
1020
  {
1023
1021
  "$type": "ParserRule",
@@ -1057,8 +1055,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
1057
1055
  "elements": [
1058
1056
  {
1059
1057
  "$type": "Keyword",
1060
- "value": "ContextMap",
1061
- "$comment": "/** A Context Map visualizes and documents the relationships between Bounded Contexts, including their integration patterns. */"
1058
+ "value": "ContextMap"
1062
1059
  },
1063
1060
  {
1064
1061
  "$type": "Keyword",
@@ -1193,7 +1190,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
1193
1190
  "entry": false,
1194
1191
  "fragment": false,
1195
1192
  "parameters": [],
1196
- "$comment": "/**\\n * Context Map - Visualizes relationships between Bounded Contexts.\\n * Shows integration patterns and team interactions.\\n */"
1193
+ "$comment": "/**\\n * Context Map - Visualizes relationships between Bounded Contexts.\\n * Shows integration patterns and team interactions.\\n * \\n * [Read more on domainlang.net](https://domainlang.net/reference/language#context-maps)\\n */"
1197
1194
  },
1198
1195
  {
1199
1196
  "$type": "ParserRule",
@@ -1206,8 +1203,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
1206
1203
  "elements": [
1207
1204
  {
1208
1205
  "$type": "Keyword",
1209
- "value": "DomainMap",
1210
- "$comment": "/** A Domain Map visualizes and documents the relationships between Domains. */"
1206
+ "value": "DomainMap"
1211
1207
  },
1212
1208
  {
1213
1209
  "$type": "Keyword",
@@ -1301,7 +1297,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
1301
1297
  "entry": false,
1302
1298
  "fragment": false,
1303
1299
  "parameters": [],
1304
- "$comment": "/**\\n * Domain Map - Visualizes relationships between Domains.\\n * Shows high-level domain organization and subdomain structure.\\n */"
1300
+ "$comment": "/**\\n * Domain Map - Visualizes relationships between Domains.\\n * Shows high-level domain organization and subdomain structure.\\n * \\n * [Read more on domainlang.net](https://domainlang.net/reference/language#domain-maps)\\n */"
1305
1301
  },
1306
1302
  {
1307
1303
  "$type": "ParserRule",
@@ -1471,7 +1467,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
1471
1467
  "entry": false,
1472
1468
  "fragment": false,
1473
1469
  "parameters": [],
1474
- "$comment": "/**\\n * Relationship - Connection between two Bounded Contexts.\\n * Supports DDD integration patterns (ACL, OHS, PL, etc.) and relationship types.\\n */"
1470
+ "$comment": "/**\\n * Relationship - Connection between two Bounded Contexts.\\n * Supports DDD integration patterns (ACL, OHS, PL, etc.) and relationship types.\\n * \\n * [Read more on domainlang.net](https://domainlang.net/reference/language#relationships)\\n */"
1475
1471
  },
1476
1472
  {
1477
1473
  "$type": "ParserRule",
@@ -1830,7 +1826,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
1830
1826
  "entry": false,
1831
1827
  "fragment": false,
1832
1828
  "parameters": [],
1833
- "$comment": "/**\\n * Domain Terminology - Ubiquitous language terms with definitions.\\n * Supports synonyms and examples for richer glossaries.\\n */"
1829
+ "$comment": "/**\\n * Domain Terminology - Ubiquitous language terms with definitions.\\n * Supports synonyms and examples for richer glossaries.\\n * \\n * [Read more on domainlang.net](https://domainlang.net/reference/language#terminology)\\n */"
1834
1830
  },
1835
1831
  {
1836
1832
  "$type": "ParserRule",
@@ -1864,7 +1860,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
1864
1860
  "entry": false,
1865
1861
  "fragment": false,
1866
1862
  "parameters": [],
1867
- "$comment": "/**\\n * Decisions, Policies, and Business Rules.\\n * All types are interchangeable - use what reads best for your domain.\\n */"
1863
+ "$comment": "/**\\n * Decisions, Policies, and Business Rules.\\n * All types are interchangeable - use what reads best for your domain.\\n * \\n * [Read more on domainlang.net](https://domainlang.net/reference/language#decisions-policies-rules)\\n */"
1868
1864
  },
1869
1865
  {
1870
1866
  "$type": "ParserRule",
@@ -1877,8 +1873,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
1877
1873
  "elements": [
1878
1874
  {
1879
1875
  "$type": "Keyword",
1880
- "value": "Decision",
1881
- "$comment": "/** A documented choice or rule that affects the model or process. */"
1876
+ "value": "Decision"
1882
1877
  },
1883
1878
  {
1884
1879
  "$type": "Keyword",
@@ -1968,8 +1963,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
1968
1963
  "elements": [
1969
1964
  {
1970
1965
  "$type": "Keyword",
1971
- "value": "Policy",
1972
- "$comment": "/** A business rule or guideline that governs behavior within a context. */"
1966
+ "value": "Policy"
1973
1967
  },
1974
1968
  {
1975
1969
  "$type": "Keyword",
@@ -2059,8 +2053,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
2059
2053
  "elements": [
2060
2054
  {
2061
2055
  "$type": "Keyword",
2062
- "value": "Rule",
2063
- "$comment": "/** A business rule or guideline that governs behavior within a context. */"
2056
+ "value": "Rule"
2064
2057
  },
2065
2058
  {
2066
2059
  "$type": "Keyword",
@@ -2156,8 +2149,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
2156
2149
  "$type": "Keyword",
2157
2150
  "value": "import"
2158
2151
  }
2159
- ],
2160
- "$comment": "/** Imports types or namespaces from another file or module, enabling reuse and modularity. */"
2152
+ ]
2161
2153
  },
2162
2154
  {
2163
2155
  "$type": "Assignment",
@@ -2193,13 +2185,12 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
2193
2185
  ],
2194
2186
  "cardinality": "?"
2195
2187
  }
2196
- ],
2197
- "$comment": "/** Imports types or namespaces from another file or module, enabling reuse and modularity. */"
2188
+ ]
2198
2189
  },
2199
2190
  "entry": false,
2200
2191
  "fragment": false,
2201
2192
  "parameters": [],
2202
- "$comment": "/**\\n * Import Statement - Manifest-centric import system per PRS-010.\\n * \\n * Simplified syntax where import statements use short specifiers:\\n * - External dependencies (from manifest): import \\"core\\" as Core\\n * - Local files: import \\"./shared/types.dlang\\"\\n * - Workspace-relative: import \\"~/contexts/sales.dlang\\"\\n * \\n * All resolution details (source, version, integrity) live in model.yaml manifest.\\n * Named imports and inline integrity checks have been removed per PRS-010.\\n */"
2193
+ "$comment": "/**\\n * Import Statement - Manifest-centric import system per PRS-010.\\n * \\n * Simplified syntax where import statements use short specifiers:\\n * - External dependencies (from manifest): import \\"core\\" as Core\\n * - Local files: import \\"./shared/types.dlang\\"\\n * - Workspace-relative: import \\"~/contexts/sales.dlang\\"\\n * \\n * All resolution details (source, version, integrity) live in model.yaml manifest.\\n * Named imports and inline integrity checks have been removed per PRS-010.\\n * \\n * [Read more on domainlang.net](https://domainlang.net/reference/language#imports)\\n */"
2203
2194
  },
2204
2195
  {
2205
2196
  "$type": "ParserRule",
@@ -2212,8 +2203,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
2212
2203
  "elements": [
2213
2204
  {
2214
2205
  "$type": "Keyword",
2215
- "value": "Namespace",
2216
- "$comment": "/** Namespaces organize large models into hierarchical qualified names for symbol resolution. */"
2206
+ "value": "Namespace"
2217
2207
  },
2218
2208
  {
2219
2209
  "$type": "Keyword",
@@ -2259,7 +2249,7 @@ export const DomainLangGrammar = (): Grammar => loadedDomainLangGrammar ?? (load
2259
2249
  "entry": false,
2260
2250
  "fragment": false,
2261
2251
  "parameters": [],
2262
- "$comment": "/**\\n * Namespace Declaration - Hierarchical namespacing for organizing models.\\n * Combines package modularity with group-style nesting.\\n */"
2252
+ "$comment": "/**\\n * Namespace Declaration - Hierarchical namespacing for organizing models.\\n * Combines package modularity with group-style nesting.\\n * \\n * [Read more on domainlang.net](https://domainlang.net/reference/language#namespaces)\\n */"
2263
2253
  },
2264
2254
  {
2265
2255
  "$type": "ParserRule",
package/src/index.ts CHANGED
@@ -9,16 +9,22 @@ export * from './ast-augmentation.js';
9
9
  // Export centralized types (canonical source for all service types)
10
10
  export * from './services/types.js';
11
11
 
12
- // Export services
12
+ // Export services (read-only for LSP - no network operations)
13
13
  export * from './services/workspace-manager.js';
14
- export * from './services/dependency-resolver.js';
15
- export * from './services/dependency-analyzer.js';
16
- export * from './services/governance-validator.js';
17
14
  export * from './services/import-resolver.js';
18
15
  export * from './services/relationship-inference.js';
19
- export * from './services/git-url-resolver.js';
20
16
  export * from './services/performance-optimizer.js';
21
- export * from './services/semver.js';
17
+
18
+ // Export shared utilities
19
+ export * from './utils/manifest-utils.js';
20
+
21
+ // Note: The following services have been moved to CLI package:
22
+ // - git-url-resolver.ts → @domainlang/cli/services
23
+ // - dependency-resolver.ts → @domainlang/cli/services
24
+ // - dependency-analyzer.ts → @domainlang/cli/services
25
+ // - governance-validator.ts → @domainlang/cli/services
26
+ // - semver.ts → @domainlang/cli/services
22
27
 
23
28
  // Export LSP services
24
29
  export * from './lsp/manifest-diagnostics.js';
30
+ export { DomainLangIndexManager } from './lsp/domain-lang-index-manager.js';
@@ -46,16 +46,21 @@ export class DomainLangCodeActionProvider implements CodeActionProvider {
46
46
  document: LangiumDocument,
47
47
  params: CodeActionParams
48
48
  ): MaybePromise<Array<Command | CodeAction> | undefined> {
49
- const result: CodeAction[] = [];
50
- const acceptor = (ca: CodeAction | undefined): void => {
51
- if (ca) result.push(ca);
52
- };
49
+ try {
50
+ const result: CodeAction[] = [];
51
+ const acceptor = (ca: CodeAction | undefined): void => {
52
+ if (ca) result.push(ca);
53
+ };
53
54
 
54
- for (const diagnostic of params.context.diagnostics) {
55
- this.createCodeActions(diagnostic, document, acceptor);
56
- }
55
+ for (const diagnostic of params.context.diagnostics) {
56
+ this.createCodeActions(diagnostic, document, acceptor);
57
+ }
57
58
 
58
- return result.length > 0 ? result : undefined;
59
+ return result.length > 0 ? result : undefined;
60
+ } catch (error) {
61
+ console.error('Error in getCodeActions:', error);
62
+ return undefined;
63
+ }
59
64
  }
60
65
 
61
66
  /**
@@ -8,6 +8,7 @@
8
8
  * - Maintainable: Clear mapping from grammar to completions
9
9
  */
10
10
 
11
+ import type { AstNode } from 'langium';
11
12
  import { CompletionAcceptor, CompletionContext, DefaultCompletionProvider, NextFeature } from 'langium/lsp';
12
13
  import { CompletionItemKind, InsertTextFormat } from 'vscode-languageserver';
13
14
  import * as ast from '../generated/ast.js';
@@ -121,6 +122,20 @@ export class DomainLangCompletionProvider extends DefaultCompletionProvider {
121
122
  context: CompletionContext,
122
123
  next: NextFeature,
123
124
  acceptor: CompletionAcceptor
125
+ ): void {
126
+ try {
127
+ this.safeCompletionFor(context, next, acceptor);
128
+ } catch (error) {
129
+ console.error('Error in completionFor:', error);
130
+ // Fall back to default completion on error
131
+ super.completionFor(context, next, acceptor);
132
+ }
133
+ }
134
+
135
+ private safeCompletionFor(
136
+ context: CompletionContext,
137
+ next: NextFeature,
138
+ acceptor: CompletionAcceptor
124
139
  ): void {
125
140
  const node = context.node;
126
141
  if (!node) {
@@ -143,84 +158,117 @@ export class DomainLangCompletionProvider extends DefaultCompletionProvider {
143
158
  return;
144
159
  }
145
160
 
161
+ // Handle node-level completions
162
+ if (this.handleNodeCompletions(node, acceptor, context, next)) {
163
+ return;
164
+ }
165
+
166
+ // Handle container-level completions
167
+ const container = node.$container;
168
+ if (this.handleContainerCompletions(container, node, acceptor, context, next)) {
169
+ return;
170
+ }
171
+
172
+ // Let Langium handle default completions
173
+ super.completionFor(context, next, acceptor);
174
+ }
175
+
176
+ private handleNodeCompletions(
177
+ node: AstNode,
178
+ acceptor: CompletionAcceptor,
179
+ context: CompletionContext,
180
+ next: NextFeature
181
+ ): boolean {
146
182
  // If we're AT a BoundedContext node: only BC documentation blocks
147
183
  if (ast.isBoundedContext(node)) {
148
184
  this.addBoundedContextCompletions(node, acceptor, context);
149
185
  super.completionFor(context, next, acceptor);
150
- return;
186
+ return true;
151
187
  }
152
188
 
153
189
  // If we're AT a Domain node: only Domain documentation blocks
154
190
  if (ast.isDomain(node)) {
155
191
  this.addDomainCompletions(node, acceptor, context);
156
192
  super.completionFor(context, next, acceptor);
157
- return;
193
+ return true;
158
194
  }
159
195
 
160
196
  // If we're AT a ContextMap node: relationships and contains
161
197
  if (ast.isContextMap(node)) {
162
198
  this.addContextMapCompletions(node, acceptor, context);
163
199
  super.completionFor(context, next, acceptor);
164
- return;
200
+ return true;
165
201
  }
166
202
 
167
203
  // If we're AT a DomainMap node: contains
168
204
  if (ast.isDomainMap(node)) {
169
205
  this.addDomainMapCompletions(node, acceptor, context);
170
206
  super.completionFor(context, next, acceptor);
171
- return;
207
+ return true;
172
208
  }
173
209
 
174
210
  // If we're AT the Model or NamespaceDeclaration level: all top-level constructs
175
211
  if (ast.isModel(node) || ast.isNamespaceDeclaration(node)) {
176
212
  this.addTopLevelSnippets(acceptor, context);
177
213
  super.completionFor(context, next, acceptor);
178
- return;
214
+ return true;
179
215
  }
180
216
 
181
- const container = node.$container;
217
+ return false;
218
+ }
219
+
220
+ private handleContainerCompletions(
221
+ container: AstNode | undefined,
222
+ node: AstNode,
223
+ acceptor: CompletionAcceptor,
224
+ context: CompletionContext,
225
+ next: NextFeature
226
+ ): boolean {
227
+ if (!container) {
228
+ return false;
229
+ }
182
230
 
183
231
  // Inside BoundedContext body: suggest missing scalar properties and collections
184
232
  if (ast.isBoundedContext(container)) {
185
233
  this.addBoundedContextCompletions(container, acceptor, context);
186
234
  super.completionFor(context, next, acceptor);
187
- return;
235
+ return true;
188
236
  }
189
237
 
190
238
  // Inside Domain body: suggest missing scalar properties
191
239
  if (ast.isDomain(container)) {
192
240
  this.addDomainCompletions(container, acceptor, context);
193
241
  super.completionFor(context, next, acceptor);
194
- return;
242
+ return true;
195
243
  }
196
244
 
197
245
  // Inside ContextMap body: relationships and contains
198
246
  if (ast.isContextMap(container)) {
199
247
  this.addContextMapCompletions(container, acceptor, context);
200
248
  super.completionFor(context, next, acceptor);
201
- return;
249
+ return true;
202
250
  }
203
251
 
204
252
  // Inside DomainMap body: contains
205
253
  if (ast.isDomainMap(container)) {
206
254
  this.addDomainMapCompletions(container, acceptor, context);
207
255
  super.completionFor(context, next, acceptor);
208
- return;
256
+ return true;
209
257
  }
210
258
 
211
259
  if (ast.isRelationship(node) || ast.isRelationship(container)) {
212
260
  this.addRelationshipCompletions(acceptor, context);
213
261
  super.completionFor(context, next, acceptor);
214
- return;
262
+ return true;
215
263
  }
216
264
 
217
265
  // Top level container (Model or NamespaceDeclaration): all top-level constructs
218
266
  if (ast.isModel(container) || ast.isNamespaceDeclaration(container)) {
219
267
  this.addTopLevelSnippets(acceptor, context);
268
+ return true;
220
269
  }
221
270
 
222
- // Let Langium handle default completions
223
- super.completionFor(context, next, acceptor);
271
+ return false;
224
272
  }
225
273
 
226
274
  private addTopLevelSnippets(acceptor: CompletionAcceptor, context: CompletionContext): void {
@@ -9,29 +9,34 @@ import * as ast from '../generated/ast.js';
9
9
  export class DomainLangFormatter extends AbstractFormatter {
10
10
 
11
11
  protected format(node: AstNode): void {
12
- // Namespace declarations
13
- if (ast.isNamespaceDeclaration(node)) {
14
- this.formatBlock(node);
15
- }
16
-
17
- // Domain declarations
18
- if (ast.isDomain(node)) {
19
- this.formatBlock(node);
20
- }
21
-
22
- // Bounded contexts
23
- if (ast.isBoundedContext(node)) {
24
- this.formatBlock(node);
25
- }
26
-
27
- // Context maps
28
- if (ast.isContextMap(node)) {
29
- this.formatBlock(node);
30
- }
31
-
32
- // Domain maps
33
- if (ast.isDomainMap(node)) {
34
- this.formatBlock(node);
12
+ try {
13
+ // Namespace declarations
14
+ if (ast.isNamespaceDeclaration(node)) {
15
+ this.formatBlock(node);
16
+ }
17
+
18
+ // Domain declarations
19
+ if (ast.isDomain(node)) {
20
+ this.formatBlock(node);
21
+ }
22
+
23
+ // Bounded contexts
24
+ if (ast.isBoundedContext(node)) {
25
+ this.formatBlock(node);
26
+ }
27
+
28
+ // Context maps
29
+ if (ast.isContextMap(node)) {
30
+ this.formatBlock(node);
31
+ }
32
+
33
+ // Domain maps
34
+ if (ast.isDomainMap(node)) {
35
+ this.formatBlock(node);
36
+ }
37
+ } catch (error) {
38
+ console.error('Error in format:', error);
39
+ // Continue - don't crash formatting
35
40
  }
36
41
  }
37
42