@hydranium/core 1.0.0-next.155 → 1.0.0-next.158

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 (55) hide show
  1. package/lib/documents/ast-document-manager.d.ts +3 -2
  2. package/lib/documents/ast-document-manager.d.ts.map +1 -1
  3. package/lib/documents/ast-document-manager.js.map +1 -1
  4. package/lib/documents/hydranium-text-documents.d.ts +3 -2
  5. package/lib/documents/hydranium-text-documents.d.ts.map +1 -1
  6. package/lib/documents/hydranium-text-documents.js +3 -2
  7. package/lib/documents/hydranium-text-documents.js.map +1 -1
  8. package/lib/langium/module.d.ts +38 -12
  9. package/lib/langium/module.d.ts.map +1 -1
  10. package/lib/langium/module.js +15 -22
  11. package/lib/langium/module.js.map +1 -1
  12. package/lib/langium/workspace/document-uri-policy.d.ts +7 -5
  13. package/lib/langium/workspace/document-uri-policy.d.ts.map +1 -1
  14. package/lib/langium/workspace/document-uri-policy.js +7 -5
  15. package/lib/langium/workspace/document-uri-policy.js.map +1 -1
  16. package/lib/langium/workspace/file-not-found.d.ts +17 -0
  17. package/lib/langium/workspace/file-not-found.d.ts.map +1 -0
  18. package/lib/langium/workspace/file-not-found.js +20 -0
  19. package/lib/langium/workspace/file-not-found.js.map +1 -0
  20. package/lib/langium/workspace/file-system-provider.d.ts +81 -13
  21. package/lib/langium/workspace/file-system-provider.d.ts.map +1 -1
  22. package/lib/langium/workspace/file-system-provider.js +81 -35
  23. package/lib/langium/workspace/file-system-provider.js.map +1 -1
  24. package/lib/langium/workspace/hydranium-workspace-manager.d.ts +51 -2
  25. package/lib/langium/workspace/hydranium-workspace-manager.d.ts.map +1 -1
  26. package/lib/langium/workspace/hydranium-workspace-manager.js +82 -4
  27. package/lib/langium/workspace/hydranium-workspace-manager.js.map +1 -1
  28. package/lib/langium/workspace/in-memory-file-system-provider.d.ts +2 -2
  29. package/lib/langium/workspace/in-memory-file-system-provider.d.ts.map +1 -1
  30. package/lib/langium/workspace/in-memory-file-system-provider.js +3 -23
  31. package/lib/langium/workspace/in-memory-file-system-provider.js.map +1 -1
  32. package/lib/langium/workspace/persistent-file-system-provider.d.ts +0 -7
  33. package/lib/langium/workspace/persistent-file-system-provider.d.ts.map +1 -1
  34. package/lib/langium/workspace/persistent-file-system-provider.js +0 -7
  35. package/lib/langium/workspace/persistent-file-system-provider.js.map +1 -1
  36. package/lib/langium/workspace/virtual-document.d.ts +44 -26
  37. package/lib/langium/workspace/virtual-document.d.ts.map +1 -1
  38. package/lib/langium/workspace/virtual-document.js +76 -33
  39. package/lib/langium/workspace/virtual-document.js.map +1 -1
  40. package/lib/node/node-file-system-provider.d.ts +10 -9
  41. package/lib/node/node-file-system-provider.d.ts.map +1 -1
  42. package/lib/node/node-file-system-provider.js +12 -47
  43. package/lib/node/node-file-system-provider.js.map +1 -1
  44. package/package.json +5 -5
  45. package/src/documents/ast-document-manager.ts +3 -2
  46. package/src/documents/hydranium-text-documents.ts +3 -2
  47. package/src/langium/module.ts +56 -34
  48. package/src/langium/workspace/document-uri-policy.ts +7 -5
  49. package/src/langium/workspace/file-not-found.ts +23 -0
  50. package/src/langium/workspace/file-system-provider.ts +136 -39
  51. package/src/langium/workspace/hydranium-workspace-manager.ts +98 -6
  52. package/src/langium/workspace/in-memory-file-system-provider.ts +3 -24
  53. package/src/langium/workspace/persistent-file-system-provider.ts +0 -7
  54. package/src/langium/workspace/virtual-document.ts +92 -33
  55. package/src/node/node-file-system-provider.ts +12 -48
@@ -1 +1 @@
1
- {"version":3,"file":"node-file-system-provider.js","sourceRoot":"","sources":["../../src/node/node-file-system-provider.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAGlF,OAAO,EAAuB,GAAG,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AACxE,OAAO,EAAE,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,GAAG,MAAM,kBAAkB,CAAC;AAGxC,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AAEtE,OAAO,EAAE,mBAAmB,EAAoC,MAAM,+BAA+B,CAAC;AACtG,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,wDAAwD,CAAC;AACvH,OAAO,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,MAAM,0CAA0C,CAAC;AAElG;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,OAAO,yBAA0B,SAAQ,sBAAsB;IAK5C;IAJb,gBAAgB,CAAmB;IACzB,MAAM,CAAS;IAElC,YACsB,QAAqC,EACxD,UAA0B,EAAE;QAE5B,KAAK,EAAE,CAAC;QAHW,aAAQ,GAAR,QAAQ,CAA6B;QAIxD,IAAI,CAAC,gBAAgB,GAAG,QAAQ,CAAC,SAAS,CAAC,gBAAgB,CAAC;QAC5D,IAAI,CAAC,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IACrG,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACO,cAAc,CAAC,GAAQ;QAC9B,OAAO,GAAG,CAAC,MAAM,KAAK,MAAM,CAAC;IAChC,CAAC;IAED,4EAA4E;IAC5E,uEAAuE;IACvE,yEAAyE;IACzE,iEAAiE;IACxD,QAAQ,CAAC,GAAQ;QACvB,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACxD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3F,CAAC;IAEQ,YAAY,CAAC,GAAQ;QAC3B,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACxD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,MAAM,CAAC;QACjB,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;QACD,OAAO,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC;IAClC,CAAC;IAEQ,UAAU,CAAC,GAAQ;QACzB,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACxD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAC1C,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7F,CAAC;IAEQ,cAAc,CAAC,GAAQ;QAC7B,MAAM,MAAM,GAAG,oBAAoB,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACxD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC;QACzB,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;QACD,OAAO,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC;IAEQ,IAAI,CAAC,GAAQ;QACnB,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACpD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QAClC,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;IACvF,CAAC;IAEQ,QAAQ,CAAC,GAAQ;QACvB,MAAM,MAAM,GAAG,gBAAgB,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;QACpD,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACxB,OAAO,MAAM,CAAC;QACjB,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,UAAU,CAAC,GAAG,CAAC,CAAC;QACzB,CAAC;QACD,OAAO,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC9B,CAAC;IAED,4EAA4E;IAC5E,qBAAqB;IACZ,KAAK,CAAC,MAAM,CAAC,GAAQ;QAC3B,IAAI,oBAAoB,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YAC1D,OAAO,IAAI,CAAC;QACf,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IAC/D,CAAC;IAEQ,UAAU,CAAC,GAAQ;QACzB,IAAI,oBAAoB,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,KAAK,SAAS,EAAE,CAAC;YAC1D,OAAO,IAAI,CAAC;QACf,CAAC;QACD,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACnE,CAAC;IAED,0EAA0E;IAC1E,4EAA4E;IAC5E,qEAAqE;IAC5D,aAAa,CAAC,GAAQ;QAC5B,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACpF,CAAC;IAEQ,iBAAiB,CAAC,GAAQ;QAChC,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACvE,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6CG;IACH,KAAK,CAAC,SAAS,CAAC,GAAQ,EAAE,OAAe;QACtC,wEAAwE;QACxE,wEAAwE;QACxE,sEAAsE;QACtE,uEAAuE;QACvE,wEAAwE;QACxE,qEAAqE;QACrE,iEAAiE;QACjE,8DAA8D;QAC9D,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,gBAAgB,CAAC,GAAG,CAAC,CAAC;QAC/B,CAAC;QACD,MAAM,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnE,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,IAAI,GAAG,CAAC,MAAM,CAAC;QAC7D,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,WAAW,CAAC,CAAC;QACjD,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;YAChD,wEAAwE;YACxE,MAAM,GAAG,CAAC,SAAS,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QAC7C,CAAC;aAAM,CAAC;YACL,MAAM,OAAO,GAAG,GAAG,WAAW,IAAI,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,MAAM,CAAC;YACpE,IAAI,CAAC;gBACF,MAAM,IAAI,GAAG,QAAQ,EAAE,IAAI,CAAC;gBAC5B,MAAM,GAAG,CAAC,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC;gBAChD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;oBACtB,+DAA+D;oBAC/D,+DAA+D;oBAC/D,0BAA0B;oBAC1B,MAAM,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;gBAClC,CAAC;gBACD,MAAM,qBAAqB,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;YACrD,CAAC;YAAC,OAAO,GAAY,EAAE,CAAC;gBACrB,qEAAqE;gBACrE,4DAA4D;gBAC5D,MAAM,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;gBACvC,MAAM,GAAG,CAAC;YACb,CAAC;QACJ,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACxC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YACzB,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACvD,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,GAAQ;QACnB,yEAAyE;QACzE,qEAAqE;QACrE,uEAAuE;QACvE,kEAAkE;QAClE,iEAAiE;QACjE,wDAAwD;QACxD,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,OAAO,SAAS,CAAC;QACpB,CAAC;QACD,IAAI,CAAC;YACF,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YACxC,OAAO,IAAI,CAAC,OAAO,CAAC;QACvB,CAAC;QAAC,MAAM,CAAC;YACN,4DAA4D;YAC5D,OAAO,SAAS,CAAC;QACpB,CAAC;IACJ,CAAC;IAED;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,GAAQ;QACd,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YACzB,OAAO,GAAG,CAAC;QACd,CAAC;QACD,IAAI,CAAC;YACF,OAAO,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;QAC7C,CAAC;QAAC,MAAM,CAAC;YACN,OAAO,SAAS,CAAC;QACpB,CAAC;IACJ,CAAC;CACH;AAED,0EAA0E;AAC1E,SAAS,UAAU,CAAC,GAAQ;IACzB,OAAO,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,kFAAkF;AAClF,SAAS,UAAU,CAAC,GAAQ;IACzB,OAAO,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;AAClE,CAAC;AAED,sFAAsF;AACtF,SAAS,gBAAgB,CAAC,GAAQ;IAC/B,OAAO,IAAI,KAAK,CAAC,iBAAiB,CAAC,MAAM,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC;AACvE,CAAC;AAED,oEAAoE;AACpE,SAAS,MAAM,CAAC,IAAY;IACzB,OAAO,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AACzC,CAAC;AAcD;;;;;GAKG;AACH,KAAK,UAAU,YAAY,CAAC,IAAY;IACrC,IAAI,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,GAAG,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC;IACrF,CAAC;IAAC,MAAM,CAAC;QACN,OAAO,SAAS,CAAC;IACpB,CAAC;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG;IAC3B,kBAAkB,EAAE,mBAAmB,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,yBAAyB,CAAC,QAAQ,CAAC,CAAC;CAC9F,CAAC"}
1
+ {"version":3,"file":"node-file-system-provider.js","sourceRoot":"","sources":["../../src/node/node-file-system-provider.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hydranium/core",
3
- "version": "1.0.0-next.155",
3
+ "version": "1.0.0-next.158",
4
4
  "description": "Foundational runtime of the hydranium framework: AST coordination layer (services, integrity, AST extension, serialization, multi-client documents) plus the LSP textual head at the /lsp subpath. Consumed by protocol-head packages (@hydranium/data-server, @hydranium/glsp-server).",
5
5
  "keywords": [
6
6
  "hydranium",
@@ -104,8 +104,8 @@
104
104
  "diff": "^5.2.0"
105
105
  },
106
106
  "devDependencies": {
107
- "@hydranium/langium": "1.0.0-next.155",
108
- "@hydranium/protocol": "1.0.0-next.155",
107
+ "@hydranium/langium": "1.0.0-next.158",
108
+ "@hydranium/protocol": "1.0.0-next.158",
109
109
  "@playwright/test": "^1.40.0",
110
110
  "@types/diff": "^5.2.0",
111
111
  "rimraf": "^5.0.0",
@@ -117,8 +117,8 @@
117
117
  "vscode-languageserver-types": "^3.17.5"
118
118
  },
119
119
  "peerDependencies": {
120
- "@hydranium/langium": "1.0.0-next.155",
121
- "@hydranium/protocol": "1.0.0-next.155",
120
+ "@hydranium/langium": "1.0.0-next.158",
121
+ "@hydranium/protocol": "1.0.0-next.158",
122
122
  "@playwright/test": "^1.40.0",
123
123
  "vscode-jsonrpc": "9.0.1",
124
124
  "vscode-languageserver": "~10.0.1",
@@ -65,8 +65,9 @@ export interface WritableFileSystemProvider extends FileSystemProvider {
65
65
  * - A non-`file:` URI (or any URI the provider cannot stat) passes through
66
66
  * **unchanged** — it is treated as present, never reported absent.
67
67
  * - A provider with no disk to check (in-memory / browser / empty) simply
68
- * omits this method; `RealpathDocumentUriPolicy` then degrades to the
69
- * syntactic `DefaultDocumentUriPolicy` behaviour automatically.
68
+ * omits this method; the framework's `FileSystemProviderRegistry` then
69
+ * returns the URI unchanged, and `RealpathDocumentUriPolicy` answers as
70
+ * the syntactic `DefaultDocumentUriPolicy` does.
70
71
  *
71
72
  * Synchronous (a `realpath` is a kernel-cached syscall) and optional — the
72
73
  * only consumers are the document-identity policy's `canonicalUri`/`loadUri`.
@@ -819,8 +819,9 @@ export class HydraniumTextDocuments<T extends TextDocument = TextDocument> exten
819
819
  * serve is rebuilt from its text, and any other — an editor's `untitled:`
820
820
  * buffer, a file never saved, or one deleted meanwhile — is removed
821
821
  * from the workspace. A `virtual:` document survives, since the framework's
822
- * providers serve it from the index; an edited one therefore keeps its last
823
- * client's text, and keeping it read-only is the client's job.
822
+ * provider for that scheme serves it from the index, whatever provider the
823
+ * host passes as `context.fileSystemProvider`; an edited one therefore keeps
824
+ * its last client's text, and keeping it read-only is the client's job.
824
825
  *
825
826
  * The answer is read in the document's disk queue, so the rebuild follows
826
827
  * any save still queued rather than reverting past it; a file that goes
@@ -37,7 +37,12 @@ import { HydraniumTextDocuments } from '../documents/hydranium-text-documents.js
37
37
  import { DefaultAstDocumentManager, type AstDocumentManager, type WritableFileSystemProvider } from '../documents/ast-document-manager.js';
38
38
  import { DefaultSelfSaveRegistry, type SelfSaveRegistry } from '../documents/self-save-registry.js';
39
39
  import { DefaultFileSystemTaskQueue, type FileSystemTaskQueue } from '../documents/file-system-task-queue.js';
40
- import { DefaultEmptyFileSystemProvider } from './workspace/file-system-provider.js';
40
+ import {
41
+ DefaultEmptyFileSystemProvider,
42
+ DefaultFileSystemProviderRegistry,
43
+ type FileSystemProviderRegistry
44
+ } from './workspace/file-system-provider.js';
45
+ import { VIRTUAL_SCHEME, VirtualFileSystemProvider } from './workspace/virtual-document.js';
41
46
  import { type ServerLanguageServices } from './language-module.js';
42
47
  import { ExtendedServiceRegistry } from './service-registry.js';
43
48
 
@@ -178,20 +183,36 @@ export interface ServerAddedSharedServices<
178
183
  */
179
184
  /* override */ WorkspaceLock: HydraniumWorkspaceLock;
180
185
  /**
181
- * Tighten Langium's read-only `FileSystemProvider` slot to
182
- * {@link WritableFileSystemProvider}. The framework's save path
183
- * ({@link AstDocumentManager.save}, integrity corrections,
184
- * a session's `save`) requires write semantics — a read-only slot
185
- * type forces an `as WritableFileSystemProvider` cast at the binding
186
- * line and defers the failure of a read-only implementation to the
187
- * first save. The `.`-entry default is
188
- * {@link DefaultEmptyFileSystemProvider}, which is what keeps the core
189
- * barrel free of `node:fs` and therefore browser-bundleable; a Node host
190
- * binds `@hydranium/core/node`'s Node-backed provider (wired to
191
- * {@link SelfSaveRegistry}) instead, and adopters override with their own
186
+ * Tighten Langium's read-only `FileSystemProvider` slot to a
187
+ * {@link FileSystemProviderRegistry}, which is writable: the
188
+ * framework's save path ({@link AstDocumentManager.save}, integrity
189
+ * corrections, a session's `save`) requires write semantics, and a
190
+ * read-only slot type defers the failure of a read-only
191
+ * implementation to the first save.
192
+ *
193
+ * Bound to {@link DefaultFileSystemProviderRegistry}, which dispatches
194
+ * by scheme to the {@link ServerAddedSharedServices.fileSystemProviders}
195
+ * group and sends every other scheme to its `host`: the provider
196
+ * `context.fileSystemProvider` returns when it is writable, or else
197
+ * `DefaultEmptyFileSystemProvider`, which is what keeps the core
198
+ * barrel free of `node:fs` and therefore browser-bundleable. A Node
199
+ * host passes `@hydranium/core/node`'s Node-backed provider (wired to
200
+ * {@link SelfSaveRegistry}) instead, and adopters pass their own
192
201
  * writable implementation when neither fits.
202
+ *
203
+ * To reach the members of its own provider, an adopter declares this
204
+ * slot as `FileSystemProviderRegistry<MyProvider>` through
205
+ * {@link WithServiceOverrides}, binds a
206
+ * `DefaultFileSystemProviderRegistry` with that host from a factory
207
+ * whose return type names the narrowed slot (a module's `DeepPartial`
208
+ * checks no host member otherwise), and reads
209
+ * `FileSystemProvider.host`. A
210
+ * registry that serves a seeded document under none of its providers
211
+ * loses the document at its last close, which
212
+ * {@link HydraniumWorkspaceManager.warnIfDocumentsUnserved} reports
213
+ * once at startup.
193
214
  */
194
- /* override */ FileSystemProvider: WritableFileSystemProvider;
215
+ /* override */ FileSystemProvider: FileSystemProviderRegistry;
195
216
  ProjectManager: ProjectManager<TProject>;
196
217
  SelfSaveRegistry: SelfSaveRegistry;
197
218
  /**
@@ -307,6 +328,15 @@ export interface ServerAddedSharedServices<
307
328
  * contribute none never touch it.
308
329
  */
309
330
  additionalDocuments: Record<string, AdditionalDocumentContribution>;
331
+ /**
332
+ * Shared contribution group of file system providers keyed by the URI
333
+ * scheme each answers for, which {@link FileSystemProviderRegistry}
334
+ * dispatches to. The framework registers {@link VirtualFileSystemProvider}
335
+ * under `virtual`; an adopter deep-merges a provider for a scheme of its
336
+ * own, and an entry under `virtual` replaces the framework's. A scheme with
337
+ * no entry goes to the registry's `host`.
338
+ */
339
+ fileSystemProviders: Record<string, WritableFileSystemProvider>;
310
340
  }
311
341
 
312
342
  /**
@@ -491,7 +521,7 @@ export function createServerSharedModule(
491
521
  ConfigurationProvider: services => new HydraniumConfigurationProvider(services),
492
522
  // Override Langium's factory so a `fromModel` (code-built) virtual
493
523
  // document retains serialized text via the per-language Serializer,
494
- // making it re-read-safe through the virtual-aware FileSystemProvider.
524
+ // making it re-read-safe through `VirtualFileSystemProvider`.
495
525
  LangiumDocumentFactory: services => new HydraniumLangiumDocumentFactory(services),
496
526
  // Langium's default routes through no identity seam and treats every
497
527
  // failed load alike, so leaving this unbound opts a server out of both
@@ -504,27 +534,16 @@ export function createServerSharedModule(
504
534
  ProjectManager: services => new SingleProjectManager(services),
505
535
  SelfSaveRegistry: services => new DefaultSelfSaveRegistry(services),
506
536
  DocumentUriPolicy: () => new DefaultDocumentUriPolicy(),
507
- // Writable filesystem with two paths:
508
- // - Adopter passed `context.fileSystemProvider` and it returned a
509
- // writable implementation (has `writeFile`) — use it. Honours the
510
- // Langium-conventional context channel for passing a custom backing
511
- // (in-memory, browser, test stub like `DefaultEmptyFileSystemProvider`).
512
- // - Otherwise — the portable default `DefaultEmptyFileSystemProvider`
513
- // (no-op writes, no disk access). Node hosts opt into real disk I/O
514
- // by binding `@hydranium/core/node`'s `DefaultFileSystemProvider`
515
- // (Node-backed, wired to `SelfSaveRegistry` so framework `writeFile`
516
- // calls register their mtime and adopters can suppress the
517
- // `didChangeWatchedFiles` echo) — typically via this same
518
- // `context.fileSystemProvider` channel or by rebinding
519
- // the slot. Keeping the `.`-entry default empty is what lets the
520
- // core barrel stay free of `node:fs` (browser-bundleable); see the
521
- // `@hydranium/core/node` carve.
537
+ // The host is the provider `context.fileSystemProvider` returns
538
+ // when it is writable (has `writeFile`); anything narrower gets the
539
+ // empty provider, which is what keeps the core barrel free of
540
+ // `node:fs`.
522
541
  FileSystemProvider: services => {
523
542
  const fromContext = context.fileSystemProvider?.(services);
524
- if (fromContext && typeof (fromContext as Partial<WritableFileSystemProvider>).writeFile === 'function') {
525
- return fromContext as WritableFileSystemProvider;
526
- }
527
- return new DefaultEmptyFileSystemProvider(services);
543
+ const writable = typeof (fromContext as Partial<WritableFileSystemProvider> | undefined)?.writeFile === 'function';
544
+ return new DefaultFileSystemProviderRegistry(services, {
545
+ host: writable ? (fromContext as WritableFileSystemProvider) : new DefaultEmptyFileSystemProvider(services)
546
+ });
528
547
  },
529
548
  AstDocumentManager: services => new DefaultAstDocumentManager(services),
530
549
  FileSystemTaskQueue: services => new DefaultFileSystemTaskQueue(services),
@@ -548,6 +567,9 @@ export function createServerSharedModule(
548
567
  // profiler passes self-register imperatively, not here.
549
568
  buildPhasePasses: {},
550
569
  // Empty default so `services.additionalDocuments` always resolves.
551
- additionalDocuments: {}
570
+ additionalDocuments: {},
571
+ fileSystemProviders: {
572
+ [VIRTUAL_SCHEME]: services => new VirtualFileSystemProvider(services)
573
+ }
552
574
  };
553
575
  }
@@ -156,11 +156,13 @@ export class DefaultDocumentUriPolicy implements DocumentUriPolicy {
156
156
  * `loadUri` returns `undefined` for an absent path (honest about existence, so a
157
157
  * caller about to read the filesystem skips it).
158
158
  *
159
- * If the bound provider has no `realpath` (in-memory / browser / empty),
160
- * both methods degrade to {@link DefaultDocumentUriPolicy} automatically — the
161
- * `loadUri` ternary tests the *method's presence*, not its return, so the
162
- * existence signal is preserved: `loadUri` returns `undefined` only when
163
- * `realpath` is present and reports the path absent.
159
+ * If the provider for a URI's scheme has no `realpath` (in-memory / browser /
160
+ * empty), the framework's `FileSystemProviderRegistry` returns the URI
161
+ * unchanged and both methods answer as {@link DefaultDocumentUriPolicy} does. A
162
+ * slot bound to a provider without `realpath` degrades the same way: the
163
+ * `loadUri` ternary tests the *method's presence*, not its return, so
164
+ * `loadUri` returns `undefined` only when `realpath` is present and reports the
165
+ * path absent.
164
166
  */
165
167
  export class RealpathDocumentUriPolicy extends DefaultDocumentUriPolicy {
166
168
  protected readonly fs: RealpathCapableFileSystem;
@@ -0,0 +1,23 @@
1
+ /********************************************************************************
2
+ * Copyright (c) 2026 CrossBreeze, EclipseSource and others.
3
+ *
4
+ * This program and the accompanying materials are made available under the
5
+ * terms of the MIT License which is available in the project root.
6
+ *
7
+ * SPDX-License-Identifier: MIT
8
+ ********************************************************************************/
9
+
10
+ import { type URI } from '@hydranium/langium';
11
+
12
+ // Not re-exported from the workspace barrel: the framework's providers share
13
+ // it, and it is no API of theirs.
14
+
15
+ /**
16
+ * A missing-file error shaped as a Node file system raises it, with code
17
+ * `ENOENT` and the path: callers tell a missing file from any other failure by
18
+ * those two fields, whichever provider is bound. The last close relies on it to
19
+ * tell a document gone meanwhile from any other failed rebuild.
20
+ */
21
+ export function notFound(message: string, uri: URI): Error {
22
+ return Object.assign(new Error(message), { code: 'ENOENT', path: uri.fsPath });
23
+ }
@@ -13,14 +13,14 @@ import type { FileSystemNode, URI } from '@hydranium/langium';
13
13
  import { type WritableFileSystemProvider } from '../../documents/ast-document-manager.js';
14
14
  import { type LogNameOptions } from '../diagnostics/logger.js';
15
15
  import { type ServerSharedServicesMinimal } from '../shared-services.js';
16
- import { serveVirtualDocument, serveVirtualNode } from './virtual-document.js';
17
16
 
18
17
  /**
19
- * Empty-filesystem default {@link WritableFileSystemProvider}. For
20
- * in-memory / browser / test / CLI hosts that don't have a real filesystem.
21
- * All writes are no-ops. This is the portable `.`-entry default; the
22
- * Node-backed `DefaultFileSystemProvider`
23
- * lives in `@hydranium/core/node` (it pulls `node:fs`).
18
+ * Empty-filesystem {@link WritableFileSystemProvider}. For browser / test / CLI
19
+ * hosts that don't have a real filesystem. All writes are no-ops. On the
20
+ * portable `.` entry it is the {@link FileSystemProviderRegistry.host} when
21
+ * `context.fileSystemProvider` gives no writable provider; the Node-backed
22
+ * `DefaultFileSystemProvider` lives in `@hydranium/core/node` (it pulls
23
+ * `node:fs`).
24
24
  */
25
25
  export class DefaultEmptyFileSystemProvider extends EmptyFileSystemProvider implements WritableFileSystemProvider {
26
26
  protected readonly tracer: Tracer;
@@ -37,56 +37,153 @@ export class DefaultEmptyFileSystemProvider extends EmptyFileSystemProvider impl
37
37
  // no-op
38
38
  }
39
39
 
40
- // Serve virtual documents from the registered document (there is no disk to
41
- // read); delegate everything else to the empty base (which throws, or
42
- // answers "absent"). The base declares these param-less, so the param is
43
- // optional here.
44
- //
45
- // The async reads are `async` so the base's refusal becomes a rejection: it
46
- // throws SYNCHRONOUSLY from a method declared to return a promise, and a
40
+ // `async` so the base's refusal becomes a rejection: it throws
41
+ // SYNCHRONOUSLY from a method declared to return a promise, and a
47
42
  // synchronous throw escapes the promise chain — `.catch()` never attaches
48
43
  // and `Promise.all` dies while its argument array is still being built, so
49
- // a caller reading several URIs cannot handle the miss it asked about.
50
- override async readFile(uri?: URI): Promise<string> {
51
- const served = this.served(uri);
52
- return served !== undefined ? served : super.readFile();
44
+ // a caller reading several URIs cannot handle the miss it asked about. The
45
+ // base declares `readFile` and `readBinary` param-less, so the param is
46
+ // optional there.
47
+ override async readFile(_uri?: URI): Promise<string> {
48
+ return super.readFile();
53
49
  }
54
50
 
55
- override readFileSync(uri?: URI): string {
56
- const served = this.served(uri);
57
- return served !== undefined ? served : super.readFileSync();
51
+ override async readBinary(_uri?: URI): Promise<Uint8Array> {
52
+ return super.readBinary();
58
53
  }
59
54
 
60
- override async readBinary(uri?: URI): Promise<Uint8Array> {
61
- const served = this.served(uri);
62
- return served !== undefined ? new TextEncoder().encode(served) : super.readBinary();
55
+ override async stat(uri: URI): Promise<FileSystemNode> {
56
+ return super.stat(uri);
57
+ }
58
+ }
59
+
60
+ /**
61
+ * The provider bound on `workspace.FileSystemProvider`: it dispatches each call
62
+ * by the URI's scheme to the provider registered for it in the shared
63
+ * `fileSystemProviders` group, and to the {@link host} for any scheme without
64
+ * one.
65
+ *
66
+ * So one provider answers for each scheme, and a host's provider needs to know
67
+ * only its own: the framework registers `virtual:` there, and an adopter adds a
68
+ * scheme by contributing to the group. The host takes every unclaimed scheme
69
+ * rather than `file:` alone, which keeps an in-memory workspace under `memory:`
70
+ * or any other scheme on the host's provider.
71
+ *
72
+ * `THost` types the host, so an adopter whose own provider has more members
73
+ * than the base declares the slot as `FileSystemProviderRegistry<MyProvider>`,
74
+ * binds a {@link DefaultFileSystemProviderRegistry} with that host, and reads
75
+ * those members through `services.workspace.FileSystemProvider.host`.
76
+ */
77
+ export interface FileSystemProviderRegistry<
78
+ THost extends WritableFileSystemProvider = WritableFileSystemProvider
79
+ > extends WritableFileSystemProvider {
80
+ /** The provider for every scheme no entry of `fileSystemProviders` claims. */
81
+ readonly host: THost;
82
+ /** The provider that answers for `uri`. */
83
+ providerFor(uri: URI): WritableFileSystemProvider;
84
+ }
85
+
86
+ /** Options for {@link DefaultFileSystemProviderRegistry}. */
87
+ export interface FileSystemProviderRegistryOptions<
88
+ THost extends WritableFileSystemProvider = WritableFileSystemProvider
89
+ > extends LogNameOptions {
90
+ /**
91
+ * The provider for every scheme no entry of `fileSystemProviders` claims.
92
+ * The framework passes the provider `context.fileSystemProvider` returns,
93
+ * or a {@link DefaultEmptyFileSystemProvider} when that is not writable.
94
+ */
95
+ host: THost;
96
+ }
97
+
98
+ /**
99
+ * The framework's {@link FileSystemProviderRegistry}.
100
+ *
101
+ * A directory is listed by the provider of its own scheme, so a workspace
102
+ * root's tree comes from that provider alone.
103
+ *
104
+ * `realpath` and `mtimeMs` are always present and forward to the scheme's
105
+ * provider. Where that provider lacks one, `realpath` returns the URI unchanged
106
+ * and `mtimeMs` returns `undefined`: the answers `RealpathDocumentUriPolicy`
107
+ * and the self-save filter already give a provider without them.
108
+ */
109
+ export class DefaultFileSystemProviderRegistry<
110
+ THost extends WritableFileSystemProvider = WritableFileSystemProvider
111
+ > implements FileSystemProviderRegistry<THost> {
112
+ readonly host: THost;
113
+ protected readonly tracer: Tracer;
114
+
115
+ constructor(
116
+ protected readonly services: ServerSharedServicesMinimal & { fileSystemProviders: Record<string, WritableFileSystemProvider> },
117
+ options: FileSystemProviderRegistryOptions<THost>
118
+ ) {
119
+ this.host = options.host;
120
+ this.tracer = services.Tracer.for(options.logName ?? this.constructor.name).trace('instantiated');
63
121
  }
64
122
 
65
- override readBinarySync(uri?: URI): Uint8Array {
66
- const served = this.served(uri);
67
- return served !== undefined ? new TextEncoder().encode(served) : super.readBinarySync();
123
+ /**
124
+ * The group is read per call, not in the constructor, so a registered
125
+ * provider is built on first use and may read slots that reach back to this
126
+ * one. Only an OWN key of the group counts: the DI container resolves any
127
+ * key found on the prototype chain, so a scheme such as `constructor` would
128
+ * otherwise dispatch to a function.
129
+ */
130
+ providerFor(uri: URI): WritableFileSystemProvider {
131
+ const providers = this.services.fileSystemProviders;
132
+ return Object.hasOwn(providers, uri.scheme) ? providers[uri.scheme] : this.host;
68
133
  }
69
134
 
70
- // The base declares these two WITH a URI parameter, so they stay required.
71
- override async stat(uri: URI): Promise<FileSystemNode> {
72
- const served = serveVirtualNode(this.services, uri);
73
- return served !== undefined ? served : super.stat(uri);
135
+ // The async methods are `async` so a provider that throws synchronously from
136
+ // one still rejects, for the reason `DefaultEmptyFileSystemProvider` gives.
137
+ async writeFile(uri: URI, content: string): Promise<void> {
138
+ return this.providerFor(uri).writeFile(uri, content);
139
+ }
140
+
141
+ async mtimeMs(uri: URI): Promise<number | undefined> {
142
+ return this.providerFor(uri).mtimeMs?.(uri);
143
+ }
144
+
145
+ realpath(uri: URI): URI | undefined {
146
+ const provider = this.providerFor(uri);
147
+ return provider.realpath ? provider.realpath(uri) : uri;
148
+ }
149
+
150
+ async stat(uri: URI): Promise<FileSystemNode> {
151
+ return this.providerFor(uri).stat(uri);
152
+ }
153
+
154
+ statSync(uri: URI): FileSystemNode {
155
+ return this.providerFor(uri).statSync(uri);
156
+ }
157
+
158
+ async exists(uri: URI): Promise<boolean> {
159
+ return this.providerFor(uri).exists(uri);
160
+ }
161
+
162
+ existsSync(uri: URI): boolean {
163
+ return this.providerFor(uri).existsSync(uri);
164
+ }
165
+
166
+ async readBinary(uri: URI): Promise<Uint8Array> {
167
+ return this.providerFor(uri).readBinary(uri);
168
+ }
169
+
170
+ readBinarySync(uri: URI): Uint8Array {
171
+ return this.providerFor(uri).readBinarySync(uri);
74
172
  }
75
173
 
76
- override statSync(uri: URI): FileSystemNode {
77
- return serveVirtualNode(this.services, uri) ?? super.statSync(uri);
174
+ async readFile(uri: URI): Promise<string> {
175
+ return this.providerFor(uri).readFile(uri);
78
176
  }
79
177
 
80
- override async exists(uri?: URI): Promise<boolean> {
81
- return this.existsSync(uri);
178
+ readFileSync(uri: URI): string {
179
+ return this.providerFor(uri).readFileSync(uri);
82
180
  }
83
181
 
84
- override existsSync(uri?: URI): boolean {
85
- return this.served(uri) !== undefined;
182
+ async readDirectory(uri: URI): Promise<FileSystemNode[]> {
183
+ return this.providerFor(uri).readDirectory(uri);
86
184
  }
87
185
 
88
- /** Text of the virtual document registered at `uri`, if there is one. */
89
- protected served(uri: URI | undefined): string | undefined {
90
- return uri !== undefined ? serveVirtualDocument(this.services, uri) : undefined;
186
+ readDirectorySync(uri: URI): FileSystemNode[] {
187
+ return this.providerFor(uri).readDirectorySync(uri);
91
188
  }
92
189
  }
@@ -8,7 +8,7 @@
8
8
  ********************************************************************************/
9
9
 
10
10
  import { Deferred, type Logger, type Tracer } from '@hydranium/protocol';
11
- import { DefaultWorkspaceManager, DocumentState, type LangiumDocument, UriUtils, type URI } from '@hydranium/langium';
11
+ import { DefaultWorkspaceManager, DocumentState, type LangiumDocument, type Stream, UriUtils, type URI } from '@hydranium/langium';
12
12
  import { type CancellationToken, type InitializeParams } from 'vscode-languageserver';
13
13
  import type { WorkspaceFolder } from 'vscode-languageserver-types';
14
14
  import { type LogNameOptions, resolveLogFilePlaceholder, toLogFileWorkspaceToken } from '../diagnostics/logger.js';
@@ -93,6 +93,18 @@ export function installOperationCancelledSuppression(logger: Logger): void {
93
93
  });
94
94
  }
95
95
 
96
+ /** Options for {@link HydraniumWorkspaceManager}. */
97
+ export interface HydraniumWorkspaceManagerOptions extends LogNameOptions {
98
+ /**
99
+ * Whether startup warns about seeded documents the bound
100
+ * `FileSystemProvider` cannot serve (see
101
+ * {@link HydraniumWorkspaceManager.warnIfDocumentsUnserved}). Defaults to
102
+ * `true`; turn it off for a host that drops such documents at their last
103
+ * close on purpose.
104
+ */
105
+ warnUnservedDocuments?: boolean;
106
+ }
107
+
96
108
  /**
97
109
  * Framework {@link DefaultWorkspaceManager} subclass that integrates the
98
110
  * project tier with Langium's workspace startup.
@@ -163,8 +175,12 @@ export class HydraniumWorkspaceManager extends DefaultWorkspaceManager {
163
175
  protected readonly additionalDocuments: Record<string, AdditionalDocumentContribution>;
164
176
  /** Registry consulted by {@link warnIfUnroutable} to check a seeded document routes. */
165
177
  protected readonly languageRegistry: ServerSharedServicesMinimal['ServiceRegistry'];
178
+ /** Whether startup runs {@link warnIfDocumentsUnserved}. */
179
+ protected readonly warnUnservedDocuments: boolean;
180
+ /** URIs of the documents the running startup's file traversal loaded; see {@link loadWorkspaceDocuments}. */
181
+ protected readonly traversedUris = new Set<string>();
166
182
 
167
- constructor(services: ServerSharedServicesMinimal, options: LogNameOptions = {}) {
183
+ constructor(services: ServerSharedServicesMinimal, options: HydraniumWorkspaceManagerOptions = {}) {
168
184
  super(services);
169
185
  this.projectManager = services.workspace.ProjectManager;
170
186
  this.projectManager.onProjectsChanged(event => this.onProjectsChanged(event));
@@ -173,6 +189,7 @@ export class HydraniumWorkspaceManager extends DefaultWorkspaceManager {
173
189
  this.writableFileSystemProvider = services.workspace.FileSystemProvider;
174
190
  this.additionalDocuments = services.additionalDocuments;
175
191
  this.languageRegistry = services.ServiceRegistry;
192
+ this.warnUnservedDocuments = options.warnUnservedDocuments ?? true;
176
193
  this.tracer = services.Tracer.for(options.logName ?? 'WorkspaceManager').trace('instantiated');
177
194
  installOperationCancelledSuppression(this.tracer);
178
195
  }
@@ -201,16 +218,16 @@ export class HydraniumWorkspaceManager extends DefaultWorkspaceManager {
201
218
  // seeded. `tags` is read at the done-emit, so the document count pushed
202
219
  // inside the callback appears in the log line.
203
220
  const tags: string[] = [`${contributions.length} contributions`];
204
- let documentCount = 0;
221
+ const seeded: LangiumDocument[] = [];
205
222
  await this.tracer.time(
206
223
  'Load additional documents',
207
224
  async () => {
208
225
  await collectAdditionalDocuments(this.additionalDocuments, folders, document => {
209
- documentCount++;
226
+ seeded.push(document);
210
227
  this.warnIfUnroutable(document);
211
228
  collector(document);
212
229
  });
213
- tags.push(`${documentCount} documents`);
230
+ tags.push(`${seeded.length} documents`);
214
231
  },
215
232
  'info',
216
233
  { logAfterMs: 0, tags }
@@ -272,11 +289,86 @@ export class HydraniumWorkspaceManager extends DefaultWorkspaceManager {
272
289
  discovered.push(document);
273
290
  }
274
291
  }
275
- const documents = await super.performStartup(folders);
292
+ this.traversedUris.clear();
293
+ let documents: LangiumDocument[];
294
+ try {
295
+ documents = await super.performStartup(folders);
296
+ if (this.warnUnservedDocuments) {
297
+ await this.warnIfDocumentsUnserved(documents.filter(document => !this.traversedUris.has(document.uri.toString())));
298
+ }
299
+ } finally {
300
+ this.traversedUris.clear();
301
+ }
276
302
  this.probePathDivergence(folders);
277
303
  return this.withDiscoveredDescriptors(documents, discovered);
278
304
  }
279
305
 
306
+ /**
307
+ * Record each document the file traversal loads, so startup can tell them
308
+ * from the documents `loadAdditionalDocuments` seeded, through the
309
+ * `additionalDocuments` group or an override of its own.
310
+ *
311
+ * The traversal found each of its documents through the provider, so asking
312
+ * it again whether they exist costs one call per workspace file and cannot
313
+ * come out false. Telling them apart by scheme does not work either: the
314
+ * registry's host answers every scheme no other provider claims, a seeded
315
+ * scheme nobody serves included. An override that loads documents without
316
+ * delegating here leaves them unrecorded, so startup asks the provider
317
+ * about each of them.
318
+ */
319
+ protected override async loadWorkspaceDocuments(uris: Stream<URI>, collector: (document: LangiumDocument) => void): Promise<void> {
320
+ await super.loadWorkspaceDocuments(uris, document => {
321
+ this.traversedUris.add(document.uri.toString());
322
+ collector(document);
323
+ });
324
+ }
325
+
326
+ /**
327
+ * Warn once when the bound `FileSystemProvider` cannot serve a seeded
328
+ * document, naming each such document's scheme.
329
+ *
330
+ * The last close keeps a document only if the provider says it `exists`, so
331
+ * each such document leaves the workspace the first time an editor closes
332
+ * it, and whatever resolved against it breaks. The framework's registry
333
+ * serves `virtual:` through the `fileSystemProviders` group and every other
334
+ * scheme through its host, which knows nothing of a scheme an adopter
335
+ * invented for its seeded documents, and nothing else reports the loss. A
336
+ * provider that throws counts as not serving the document, since a startup
337
+ * that failed on a diagnostic would be worse than the loss.
338
+ *
339
+ * Runs over every document startup collected outside the file traversal,
340
+ * which is what `loadAdditionalDocuments` seeded, through the
341
+ * `additionalDocuments` group or an override of that method, once startup
342
+ * has added them to the workspace, unless `warnUnservedDocuments` is
343
+ * `false`.
344
+ */
345
+ protected async warnIfDocumentsUnserved(documents: readonly LangiumDocument[]): Promise<void> {
346
+ const unserved: URI[] = [];
347
+ for (const document of documents) {
348
+ let served = false;
349
+ try {
350
+ served = await this.writableFileSystemProvider.exists(document.uri);
351
+ } catch {
352
+ // Counted as unserved, below.
353
+ }
354
+ if (!served) {
355
+ unserved.push(document.uri);
356
+ }
357
+ }
358
+ if (unserved.length === 0) {
359
+ return;
360
+ }
361
+ const schemes = [...new Set(unserved.map(uri => uri.scheme))];
362
+ const named = unserved.slice(0, 3).map(uri => uri.toString());
363
+ this.tracer.warn(
364
+ `${unserved.length} seeded document(s) under ${schemes.map(scheme => `${scheme}:`).join(', ')} cannot be served by the bound workspace.FileSystemProvider ` +
365
+ `(${named.join(', ')}${unserved.length > 3 ? ', …' : ''}), so each leaves the workspace at its ` +
366
+ `last close. Register a provider under the key ${schemes.map(scheme => `'${scheme}'`).join(', ')} in the shared ` +
367
+ 'fileSystemProviders group, or serve the scheme from the host provider; set warnUnservedDocuments: false ' +
368
+ 'to accept the loss.'
369
+ );
370
+ }
371
+
280
372
  /**
281
373
  * Add back the documents project discovery created that Langium's file
282
374
  * traversal then filtered out.