@hydranium/cli 1.0.0-next.4 → 1.0.0-next.400
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +102 -204
- package/bin/hydranium-cli.js +13 -0
- package/heap-analysis/heap/core/load.mjs +2 -2
- package/heap-analysis/heap/langium/langium.classifier.mjs +22 -11
- package/lib/cli-version.js.map +1 -1
- package/lib/cli.js +7 -2
- package/lib/cli.js.map +1 -1
- package/lib/commands/analyze-heap-args.d.ts.map +1 -1
- package/lib/commands/analyze-heap-args.js +1 -2
- package/lib/commands/analyze-heap-args.js.map +1 -1
- package/lib/commands/analyze-heap.d.ts +3 -0
- package/lib/commands/analyze-heap.d.ts.map +1 -1
- package/lib/commands/analyze-heap.js +2 -1
- package/lib/commands/analyze-heap.js.map +1 -1
- package/lib/commands/ast-ground-truth-args.d.ts +3 -2
- package/lib/commands/ast-ground-truth-args.d.ts.map +1 -1
- package/lib/commands/ast-ground-truth-args.js +11 -9
- package/lib/commands/ast-ground-truth-args.js.map +1 -1
- package/lib/commands/ast-ground-truth-driver.js +4 -2
- package/lib/commands/ast-ground-truth-driver.js.map +1 -1
- package/lib/commands/ast-ground-truth.js +1 -1
- package/lib/commands/ast-ground-truth.js.map +1 -1
- package/lib/commands/client-session.d.ts +17 -0
- package/lib/commands/client-session.d.ts.map +1 -0
- package/lib/commands/client-session.js +27 -0
- package/lib/commands/client-session.js.map +1 -0
- package/lib/commands/create-args.d.ts +17 -0
- package/lib/commands/create-args.d.ts.map +1 -0
- package/lib/commands/create-args.js +53 -0
- package/lib/commands/create-args.js.map +1 -0
- package/lib/commands/create.d.ts +38 -0
- package/lib/commands/create.d.ts.map +1 -0
- package/lib/commands/create.js +43 -0
- package/lib/commands/create.js.map +1 -0
- package/lib/commands/delete-args.d.ts +17 -0
- package/lib/commands/delete-args.d.ts.map +1 -0
- package/lib/commands/delete-args.js +49 -0
- package/lib/commands/delete-args.js.map +1 -0
- package/lib/commands/delete.d.ts +30 -0
- package/lib/commands/delete.d.ts.map +1 -0
- package/lib/commands/delete.js +32 -0
- package/lib/commands/delete.js.map +1 -0
- package/lib/commands/generate-ast-builder.d.ts +49 -0
- package/lib/commands/generate-ast-builder.d.ts.map +1 -0
- package/lib/commands/generate-ast-builder.js +191 -0
- package/lib/commands/generate-ast-builder.js.map +1 -0
- package/lib/commands/generate-languages.d.ts +35 -0
- package/lib/commands/generate-languages.d.ts.map +1 -0
- package/lib/commands/generate-languages.js +105 -0
- package/lib/commands/generate-languages.js.map +1 -0
- package/lib/commands/generate-transfer-builder.d.ts +33 -0
- package/lib/commands/generate-transfer-builder.d.ts.map +1 -0
- package/lib/commands/generate-transfer-builder.js +86 -0
- package/lib/commands/generate-transfer-builder.js.map +1 -0
- package/lib/commands/generate-transfer-model-args.d.ts.map +1 -1
- package/lib/commands/generate-transfer-model-args.js +30 -5
- package/lib/commands/generate-transfer-model-args.js.map +1 -1
- package/lib/commands/generate-transfer-model-config.d.ts.map +1 -1
- package/lib/commands/generate-transfer-model-config.js +10 -3
- package/lib/commands/generate-transfer-model-config.js.map +1 -1
- package/lib/commands/generate-transfer-model.d.ts +49 -9
- package/lib/commands/generate-transfer-model.d.ts.map +1 -1
- package/lib/commands/generate-transfer-model.js +235 -70
- package/lib/commands/generate-transfer-model.js.map +1 -1
- package/lib/commands/generated-module-path.d.ts +16 -0
- package/lib/commands/generated-module-path.d.ts.map +1 -0
- package/lib/commands/generated-module-path.js +21 -0
- package/lib/commands/generated-module-path.js.map +1 -0
- package/lib/commands/harness-args.d.ts +44 -42
- package/lib/commands/harness-args.d.ts.map +1 -1
- package/lib/commands/harness-args.js +109 -27
- package/lib/commands/harness-args.js.map +1 -1
- package/lib/commands/headless-harness.d.ts +37 -20
- package/lib/commands/headless-harness.d.ts.map +1 -1
- package/lib/commands/headless-harness.js +71 -19
- package/lib/commands/headless-harness.js.map +1 -1
- package/lib/commands/init-args.d.ts +2 -0
- package/lib/commands/init-args.d.ts.map +1 -1
- package/lib/commands/init-args.js +74 -31
- package/lib/commands/init-args.js.map +1 -1
- package/lib/commands/init-hosts.d.ts +24 -0
- package/lib/commands/init-hosts.d.ts.map +1 -0
- package/lib/commands/init-hosts.js +37 -0
- package/lib/commands/init-hosts.js.map +1 -0
- package/lib/commands/init-prompt.d.ts +3 -3
- package/lib/commands/init-prompt.d.ts.map +1 -1
- package/lib/commands/init-prompt.js +4 -5
- package/lib/commands/init-prompt.js.map +1 -1
- package/lib/commands/init-templates.d.ts +20 -14
- package/lib/commands/init-templates.d.ts.map +1 -1
- package/lib/commands/init-templates.js +3015 -750
- package/lib/commands/init-templates.js.map +1 -1
- package/lib/commands/init-wizard.d.ts +3 -0
- package/lib/commands/init-wizard.d.ts.map +1 -1
- package/lib/commands/init-wizard.js +46 -31
- package/lib/commands/init-wizard.js.map +1 -1
- package/lib/commands/init-workspace.d.ts +13 -11
- package/lib/commands/init-workspace.d.ts.map +1 -1
- package/lib/commands/init-workspace.js +21 -7
- package/lib/commands/init-workspace.js.map +1 -1
- package/lib/commands/init.d.ts +58 -22
- package/lib/commands/init.d.ts.map +1 -1
- package/lib/commands/init.js +203 -48
- package/lib/commands/init.js.map +1 -1
- package/lib/commands/kebab.d.ts +15 -0
- package/lib/commands/kebab.d.ts.map +1 -0
- package/lib/commands/kebab.js +17 -0
- package/lib/commands/kebab.js.map +1 -0
- package/lib/commands/lint-grammar-args.d.ts +3 -2
- package/lib/commands/lint-grammar-args.d.ts.map +1 -1
- package/lib/commands/lint-grammar-args.js +13 -10
- package/lib/commands/lint-grammar-args.js.map +1 -1
- package/lib/commands/lint-grammar-driver.js +2 -1
- package/lib/commands/lint-grammar-driver.js.map +1 -1
- package/lib/commands/lint-grammar-report.js.map +1 -1
- package/lib/commands/lint-grammar.js +1 -1
- package/lib/commands/lint-grammar.js.map +1 -1
- package/lib/commands/measure-memory-args.d.ts +3 -2
- package/lib/commands/measure-memory-args.d.ts.map +1 -1
- package/lib/commands/measure-memory-args.js +22 -11
- package/lib/commands/measure-memory-args.js.map +1 -1
- package/lib/commands/measure-memory-driver.js +5 -3
- package/lib/commands/measure-memory-driver.js.map +1 -1
- package/lib/commands/measure-memory.js +1 -1
- package/lib/commands/measure-memory.js.map +1 -1
- package/lib/commands/model-docs-args.d.ts +4 -3
- package/lib/commands/model-docs-args.d.ts.map +1 -1
- package/lib/commands/model-docs-args.js +12 -10
- package/lib/commands/model-docs-args.js.map +1 -1
- package/lib/commands/model-docs-driver.js +2 -1
- package/lib/commands/model-docs-driver.js.map +1 -1
- package/lib/commands/model-docs.js +1 -1
- package/lib/commands/model-docs.js.map +1 -1
- package/lib/commands/projects-args.d.ts.map +1 -1
- package/lib/commands/projects-args.js +5 -5
- package/lib/commands/projects-args.js.map +1 -1
- package/lib/commands/projects.d.ts +3 -4
- package/lib/commands/projects.d.ts.map +1 -1
- package/lib/commands/projects.js +2 -2
- package/lib/commands/projects.js.map +1 -1
- package/lib/commands/query-args.d.ts.map +1 -1
- package/lib/commands/query-args.js +6 -5
- package/lib/commands/query-args.js.map +1 -1
- package/lib/commands/query.d.ts +6 -5
- package/lib/commands/query.d.ts.map +1 -1
- package/lib/commands/query.js +5 -4
- package/lib/commands/query.js.map +1 -1
- package/lib/commands/reflect-args.d.ts +3 -2
- package/lib/commands/reflect-args.d.ts.map +1 -1
- package/lib/commands/reflect-args.js +13 -10
- package/lib/commands/reflect-args.js.map +1 -1
- package/lib/commands/reflect-driver.js +2 -1
- package/lib/commands/reflect-driver.js.map +1 -1
- package/lib/commands/reflect-report.js.map +1 -1
- package/lib/commands/reflect.js +1 -1
- package/lib/commands/reflect.js.map +1 -1
- package/lib/commands/save-args.d.ts.map +1 -1
- package/lib/commands/save-args.js +7 -4
- package/lib/commands/save-args.js.map +1 -1
- package/lib/commands/save.d.ts +8 -4
- package/lib/commands/save.d.ts.map +1 -1
- package/lib/commands/save.js +12 -23
- package/lib/commands/save.js.map +1 -1
- package/lib/commands/validate-args.d.ts +3 -2
- package/lib/commands/validate-args.d.ts.map +1 -1
- package/lib/commands/validate-args.js +13 -10
- package/lib/commands/validate-args.js.map +1 -1
- package/lib/commands/validate-driver.js +2 -1
- package/lib/commands/validate-driver.js.map +1 -1
- package/lib/commands/validate-report.js.map +1 -1
- package/lib/commands/validate.js +1 -1
- package/lib/commands/validate.js.map +1 -1
- package/lib/commands/watch-args.d.ts.map +1 -1
- package/lib/commands/watch-args.js +6 -4
- package/lib/commands/watch-args.js.map +1 -1
- package/lib/commands/watch.d.ts +3 -4
- package/lib/commands/watch.d.ts.map +1 -1
- package/lib/commands/watch.js +20 -2
- package/lib/commands/watch.js.map +1 -1
- package/lib/driver-heap.d.ts +52 -0
- package/lib/driver-heap.d.ts.map +1 -0
- package/lib/driver-heap.js +51 -0
- package/lib/driver-heap.js.map +1 -0
- package/lib/index.d.ts +3 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -0
- package/lib/index.js.map +1 -1
- package/lib/log-level.d.ts +21 -11
- package/lib/log-level.d.ts.map +1 -1
- package/lib/log-level.js +25 -14
- package/lib/log-level.js.map +1 -1
- package/lib/spawn-data-server.d.ts +9 -4
- package/lib/spawn-data-server.d.ts.map +1 -1
- package/lib/spawn-data-server.js +5 -4
- package/lib/spawn-data-server.js.map +1 -1
- package/lib/stderr-connection-logger.d.ts +12 -0
- package/lib/stderr-connection-logger.d.ts.map +1 -0
- package/lib/stderr-connection-logger.js +16 -0
- package/lib/stderr-connection-logger.js.map +1 -0
- package/lib/testing/echo-server.js +9 -1
- package/lib/testing/echo-server.js.map +1 -1
- package/package.json +90 -38
- package/src/cli.ts +7 -2
- package/src/commands/analyze-heap-args.ts +1 -2
- package/src/commands/analyze-heap.ts +4 -1
- package/src/commands/ast-ground-truth-args.ts +15 -12
- package/src/commands/ast-ground-truth-driver.ts +4 -2
- package/src/commands/ast-ground-truth.ts +1 -1
- package/src/commands/client-session.ts +33 -0
- package/src/commands/create-args.ts +68 -0
- package/src/commands/create.ts +83 -0
- package/src/commands/delete-args.ts +64 -0
- package/src/commands/delete.ts +61 -0
- package/src/commands/generate-ast-builder.ts +236 -0
- package/src/commands/generate-languages.ts +132 -0
- package/src/commands/generate-transfer-builder.ts +101 -0
- package/src/commands/generate-transfer-model-args.ts +30 -5
- package/src/commands/generate-transfer-model-config.ts +10 -3
- package/src/commands/generate-transfer-model.ts +316 -68
- package/src/commands/generated-module-path.ts +22 -0
- package/src/commands/harness-args.ts +99 -31
- package/src/commands/headless-harness.ts +89 -28
- package/src/commands/init-args.ts +76 -31
- package/src/commands/init-hosts.ts +51 -0
- package/src/commands/init-prompt.ts +5 -6
- package/src/commands/init-templates.ts +3183 -760
- package/src/commands/init-wizard.ts +55 -31
- package/src/commands/init-workspace.ts +31 -16
- package/src/commands/init.ts +261 -63
- package/src/commands/kebab.ts +17 -0
- package/src/commands/lint-grammar-args.ts +17 -13
- package/src/commands/lint-grammar-driver.ts +2 -1
- package/src/commands/lint-grammar.ts +1 -1
- package/src/commands/measure-memory-args.ts +27 -14
- package/src/commands/measure-memory-driver.ts +5 -3
- package/src/commands/measure-memory.ts +1 -1
- package/src/commands/model-docs-args.ts +16 -13
- package/src/commands/model-docs-driver.ts +2 -1
- package/src/commands/model-docs.ts +1 -1
- package/src/commands/projects-args.ts +5 -4
- package/src/commands/projects.ts +4 -6
- package/src/commands/query-args.ts +6 -4
- package/src/commands/query.ts +9 -9
- package/src/commands/reflect-args.ts +17 -13
- package/src/commands/reflect-driver.ts +2 -1
- package/src/commands/reflect.ts +1 -1
- package/src/commands/save-args.ts +7 -3
- package/src/commands/save.ts +24 -27
- package/src/commands/validate-args.ts +17 -13
- package/src/commands/validate-driver.ts +2 -1
- package/src/commands/validate.ts +1 -1
- package/src/commands/watch-args.ts +6 -3
- package/src/commands/watch.ts +28 -7
- package/src/driver-heap.ts +65 -0
- package/src/index.ts +3 -0
- package/src/log-level.ts +42 -14
- package/src/spawn-data-server.ts +17 -5
- package/src/stderr-connection-logger.ts +18 -0
- package/src/testing/echo-server.ts +11 -2
- package/templates/client/gitignore +3 -0
- package/templates/client/src/__GRAMMAR_ID__-diagram-module.ts +82 -0
- package/templates/editorconfig +15 -0
- package/templates/gitignore +1 -0
- package/templates/host-browser/esbuild.mjs +82 -0
- package/templates/host-browser/gitignore +4 -0
- package/templates/host-browser/hydranium-mark.svg +40 -0
- package/templates/host-browser/index.html +287 -0
- package/templates/host-browser/playwright.config.mts +24 -0
- package/templates/host-browser/src/data-status.ts +15 -0
- package/templates/host-browser/src/diagram-save.ts +60 -0
- package/templates/host-browser/src/diagram.ts +121 -0
- package/templates/host-browser/src/editor.ts +102 -0
- package/templates/host-browser/src/log.ts +14 -0
- package/templates/host-browser/src/monaco-editor-core-worker.d.ts +7 -0
- package/templates/host-browser/src/monaco-editor-worker.ts +10 -0
- package/templates/host-browser/src/posix-path-shim.ts +23 -0
- package/templates/host-browser/src/shown-file.ts +61 -0
- package/templates/host-browser/src/workspace.ts +5 -0
- package/templates/host-browser/tsconfig.e2e.json +16 -0
- package/templates/host-browser/tsconfig.page.json +16 -0
- package/templates/host-browser/tsconfig.worker.json +16 -0
- package/templates/host-theia-browser/esbuild.mjs +24 -0
- package/templates/host-theia-browser/gitignore +9 -0
- package/templates/host-theia-browser/playwright.config.mts +42 -0
- package/templates/host-theia-browser/start.mjs +50 -0
- package/templates/host-theia-browser/tsconfig.e2e.json +16 -0
- package/templates/host-theia-electron/esbuild.mjs +27 -0
- package/templates/host-theia-electron/gitignore +8 -0
- package/templates/host-theia-electron/playwright.config.mts +12 -0
- package/templates/host-theia-electron/start.mjs +47 -0
- package/templates/host-theia-electron/tsconfig.e2e.json +16 -0
- package/templates/host-vscode/esbuild.mjs +38 -0
- package/templates/host-vscode/gitignore +7 -0
- package/templates/host-vscode/playwright.config.mts +14 -0
- package/templates/host-vscode/src/__GRAMMAR_ID__-diagram-editor.ts +19 -0
- package/templates/host-vscode/src/show-model-command.ts +24 -0
- package/templates/host-vscode/src/webview/__GRAMMAR_ID__-diagram.ts +18 -0
- package/templates/host-vscode/src/webview/diagram.css +40 -0
- package/templates/host-vscode/start.mjs +22 -0
- package/templates/host-vscode/test/install-vscode.mts +21 -0
- package/templates/host-vscode/test/vscode-version.mts +10 -0
- package/templates/host-vscode/tsconfig.e2e.json +17 -0
- package/templates/host-vscode/tsconfig.json +19 -0
- package/templates/host-vscode/tsconfig.webview.json +17 -0
- package/templates/oxlintrc.json +4 -0
- package/templates/protocol/gitignore +3 -0
- package/templates/protocol/src/__GRAMMAR_ID__-diagram-types.ts +47 -0
- package/templates/server/gitignore +6 -0
- package/templates/server/src/glsp/__GRAMMAR_ID__/create-node-operation-handler.ts +62 -0
- package/templates/server/src/glsp/__GRAMMAR_ID__/delete-operation-handler.ts +63 -0
- package/templates/server/src/glsp/__GRAMMAR_ID__/gmodel-factory.ts +144 -0
- package/templates/server/src/glsp/__GRAMMAR_ID__/state.ts +18 -0
- package/templates/server/src/glsp/__GRAMMAR_ID__/storage.ts +16 -0
- package/templates/server/src/glsp/__GRAMMAR_ID__/submission-handler.ts +24 -0
- package/templates/server/src/grammar/common.langium +12 -0
- package/templates/server/src/language-server/__GRAMMAR_ID__-serializer.ts +53 -0
- package/templates/server/src/language-server/__GRAMMAR_ID__-validation.ts +30 -0
- package/templates/server/src/language-server/ast.ts +23 -0
- package/templates/server/src/node/services.ts +16 -0
- package/templates/server/test/__GRAMMAR_ID__-diagram.test.ts +403 -0
- package/templates/server/test/tsconfig.json +4 -0
- package/templates/server/tsconfig.test.json +10 -0
- package/templates/server/vitest.config.ts +14 -0
- package/templates/theia/gitignore +3 -0
- package/templates/theia/src/browser/__GRAMMAR_ID__-diagram-frontend-module.ts +65 -0
- package/templates/theia/src/browser/__PROJECT_ID__-connection-preload-module.ts +15 -0
- package/templates/theia/src/browser/__PROJECT_ID__-data-connection.ts +15 -0
- package/templates/theia/src/browser/__PROJECT_ID__-data-port.ts +11 -0
- package/templates/theia/src/browser/__PROJECT_ID__-glsp-client-contribution.ts +13 -0
- package/templates/theia/src/browser/__PROJECT_ID__-show-model-command.ts +51 -0
- package/templates/theia/src/common/__PROJECT_ID__-glsp-contribution.ts +3 -0
- package/templates/theia/src/node/__PROJECT_ID__-connection-backend-module.ts +12 -0
- package/templates/theia/src/node/__PROJECT_ID__-data-backend-module.ts +15 -0
- package/templates/theia/src/node/__PROJECT_ID__-glsp-backend-module.ts +16 -0
- package/templates/theia/style/diagram.css +20 -0
- package/templates/theia/tsconfig.json +24 -0
- package/templates/vscode-servers/gitignore +4 -0
- package/templates/vscode-servers/tsconfig.json +19 -0
- package/templates/workspace/nodes.__EXTENSION__ +5 -0
- package/templates/workspace/references.__EXTENSION__ +2 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-transfer-model-config.js","sourceRoot":"","sources":["../../src/commands/generate-transfer-model-config.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"generate-transfer-model-config.js","sourceRoot":"","sources":["../../src/commands/generate-transfer-model-config.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,6 +23,37 @@ export interface GenerateTransferModelOptions {
|
|
|
23
23
|
augmentationFile: string;
|
|
24
24
|
/** Destination path for the generated transfer model. */
|
|
25
25
|
outFile: string;
|
|
26
|
+
/**
|
|
27
|
+
* Destination for a generated AST-node builder module. Omitted by consumers
|
|
28
|
+
* that construct no AST nodes; the transfer model is emitted either way.
|
|
29
|
+
*
|
|
30
|
+
* Emitted from this command rather than its own because the AST source is
|
|
31
|
+
* already parsed here, and because a consumer that regenerates one artefact
|
|
32
|
+
* and not the other has the two disagreeing about the same grammar.
|
|
33
|
+
*/
|
|
34
|
+
astBuilderFile?: string;
|
|
35
|
+
/**
|
|
36
|
+
* Destination for a generated test module binding `makeTransferNodeBuilder`
|
|
37
|
+
* from `@hydranium/protocol/testing` to the transfer model, as `transferNode`,
|
|
38
|
+
* the way {@link astBuilderFile} binds `astNode`. Belongs in a test tree:
|
|
39
|
+
* production code has no use for a builder that fills grammar defaults.
|
|
40
|
+
*
|
|
41
|
+
* When it sits in another package than {@link outFile}, it imports the model
|
|
42
|
+
* by that package's name, so the package's main entry must re-export the
|
|
43
|
+
* generated model, and with it each type's constant: an interface the entry
|
|
44
|
+
* narrows hides the generated constant of the same name unless the entry
|
|
45
|
+
* re-exports that constant too, and the builder keeps the generated
|
|
46
|
+
* interface unless the entry declares `<LanguageId>TransferTypes` with the
|
|
47
|
+
* narrowed entry.
|
|
48
|
+
*/
|
|
49
|
+
transferBuilderFile?: string;
|
|
50
|
+
/**
|
|
51
|
+
* Destination for a generated module stating each grammar's language id and
|
|
52
|
+
* file extensions, read from the `module.ts` beside {@link astFile}. Lets a
|
|
53
|
+
* package without Langium, such as one shared with clients, name the ids
|
|
54
|
+
* without copying them by hand.
|
|
55
|
+
*/
|
|
56
|
+
languagesFile?: string;
|
|
26
57
|
/** Name used for the base element type in the output. Defaults to `TransferElement`. */
|
|
27
58
|
elementTypeName?: string;
|
|
28
59
|
/** Name used for the terminal-patterns const in the output. Defaults to `ModelTerminals`. */
|
|
@@ -54,10 +85,17 @@ export interface GenerateTransferModelOptions {
|
|
|
54
85
|
regenCommand?: string;
|
|
55
86
|
}
|
|
56
87
|
/**
|
|
57
|
-
* Generate once, then re-generate whenever
|
|
88
|
+
* Generate once, then re-generate whenever an input file changes (the AST, the
|
|
89
|
+
* augmentation file, and `module.ts` when a languages file is written),
|
|
58
90
|
* until `signal` aborts (the CLI wires this to SIGINT). Regeneration is debounced
|
|
59
91
|
* so an editor's multi-event save fires a single run, and a generation error is
|
|
60
92
|
* logged without tearing down the watch. Resolves when the signal aborts.
|
|
93
|
+
*
|
|
94
|
+
* Polled by path rather than watched through OS events: langium-cli removes
|
|
95
|
+
* its output directory and writes the files back, which an event watch, Node's
|
|
96
|
+
* and chokidar's alike, stops hearing after the first run. A run that finds an
|
|
97
|
+
* input missing is skipped, since the file's return is a change of its own, so
|
|
98
|
+
* nothing generates from a half-written output.
|
|
61
99
|
*/
|
|
62
100
|
export declare function watchTransferModel(options: GenerateTransferModelOptions, context: {
|
|
63
101
|
signal: AbortSignal;
|
|
@@ -85,10 +123,11 @@ export declare function parseTerminals(astSource: SourceFile, terminalsSourceNam
|
|
|
85
123
|
}>;
|
|
86
124
|
/**
|
|
87
125
|
* Type-guard expression (against an `item: unknown`) for one member of a non-literal type-alias
|
|
88
|
-
* union.
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* `
|
|
126
|
+
* union. A string literal is compared as written, so the escapes Langium wrote stay valid.
|
|
127
|
+
* Covers the full set of Langium data-type primitives. The `typeof`-checkable ones
|
|
128
|
+
* (`string`/`number`/`boolean`/`bigint`) use `typeof`, and `Date`, the one Langium primitive
|
|
129
|
+
* `typeof` reports as `'object'`, uses `instanceof`. Any other member is a named type whose
|
|
130
|
+
* generated `is<Member>` guard is called.
|
|
92
131
|
*/
|
|
93
132
|
export declare function typeAliasMemberGuard(member: string): string;
|
|
94
133
|
/**
|
|
@@ -101,10 +140,11 @@ export declare function typeAliasMemberGuard(member: string): string;
|
|
|
101
140
|
* name.
|
|
102
141
|
*
|
|
103
142
|
* Each referenced member is inlined and de-duplicated, preserving first-seen
|
|
104
|
-
* order
|
|
105
|
-
* namespace-qualified reference (the
|
|
106
|
-
*
|
|
107
|
-
* emitting a
|
|
143
|
+
* order; when no member holds a literal, the union is `never`. The definition
|
|
144
|
+
* is returned UNCHANGED when it holds no namespace-qualified reference (the
|
|
145
|
+
* single-language case) or when any referenced member is not a pure
|
|
146
|
+
* string-literal union — passing it through rather than emitting a
|
|
147
|
+
* half-resolved union.
|
|
108
148
|
*/
|
|
109
149
|
export declare function resolveNamespacedStringUnion(astSource: SourceFile, definition: string): string;
|
|
110
150
|
//# sourceMappingURL=generate-transfer-model.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-transfer-model.d.ts","sourceRoot":"","sources":["../../src/commands/generate-transfer-model.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;
|
|
1
|
+
{"version":3,"file":"generate-transfer-model.d.ts","sourceRoot":"","sources":["../../src/commands/generate-transfer-model.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAOlF,OAAO,EAQJ,KAAK,UAAU,EACjB,MAAM,UAAU,CAAC;AAGlB;;;;;;;;GAQG;AACH,MAAM,WAAW,4BAA4B;IAC1C,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,uEAAuE;IACvE,gBAAgB,EAAE,MAAM,CAAC;IACzB,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;OAOG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;;;;;;;;;OAaG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;OAKG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,wFAAwF;IACxF,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,6FAA6F;IAC7F,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;;;;OAQG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;OAKG;IACH,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;IAC3B,gEAAgE;IAChE,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACxB;AAoCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,4BAA4B,EAAE,OAAO,EAAE;IAAE,MAAM,EAAE,WAAW,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAsDzH;AAOD,wCAAwC;AACxC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,4BAA4B,GAAG,IAAI,CAsSjF;AA2LD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAC3B,SAAS,EAAE,UAAU,EACrB,mBAAmB,EAAE,MAAM,EAC3B,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,GAC1B,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CA8B1C;AAsFD;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAe3D;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,4BAA4B,CAAC,SAAS,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAqB9F"}
|
|
@@ -8,7 +8,11 @@
|
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
import * as fs from 'fs';
|
|
10
10
|
import * as path from 'path';
|
|
11
|
-
import {
|
|
11
|
+
import { emitAstBuilder } from './generate-ast-builder.js';
|
|
12
|
+
import { emitLanguages } from './generate-languages.js';
|
|
13
|
+
import { emitTransferBuilder } from './generate-transfer-builder.js';
|
|
14
|
+
import { Project, SyntaxKind, ts } from 'ts-morph';
|
|
15
|
+
import { describeError } from '@hydranium/protocol';
|
|
12
16
|
const DEFAULT_ELEMENT_TYPE_NAME = 'TransferElement';
|
|
13
17
|
const DEFAULT_TERMINALS_NAME = 'ModelTerminals';
|
|
14
18
|
const DEFAULT_REGEN_COMMAND = 'Run the hydranium-cli generate-transfer-model command to regenerate.';
|
|
@@ -18,11 +22,20 @@ const DEFAULT_REGEN_COMMAND = 'Run the hydranium-cli generate-transfer-model com
|
|
|
18
22
|
* `<LanguageId>Terminals` const then spreads these.
|
|
19
23
|
*/
|
|
20
24
|
const NAMESPACED_TERMINALS_NAME = 'Terminals';
|
|
25
|
+
/** How often `--watch` polls its input files. */
|
|
26
|
+
const WATCH_POLL_INTERVAL_MS = 250;
|
|
21
27
|
/**
|
|
22
|
-
* Generate once, then re-generate whenever
|
|
28
|
+
* Generate once, then re-generate whenever an input file changes (the AST, the
|
|
29
|
+
* augmentation file, and `module.ts` when a languages file is written),
|
|
23
30
|
* until `signal` aborts (the CLI wires this to SIGINT). Regeneration is debounced
|
|
24
31
|
* so an editor's multi-event save fires a single run, and a generation error is
|
|
25
32
|
* logged without tearing down the watch. Resolves when the signal aborts.
|
|
33
|
+
*
|
|
34
|
+
* Polled by path rather than watched through OS events: langium-cli removes
|
|
35
|
+
* its output directory and writes the files back, which an event watch, Node's
|
|
36
|
+
* and chokidar's alike, stops hearing after the first run. A run that finds an
|
|
37
|
+
* input missing is skipped, since the file's return is a change of its own, so
|
|
38
|
+
* nothing generates from a half-written output.
|
|
26
39
|
*/
|
|
27
40
|
export function watchTransferModel(options, context) {
|
|
28
41
|
const runSafely = () => {
|
|
@@ -30,23 +43,42 @@ export function watchTransferModel(options, context) {
|
|
|
30
43
|
generateTransferModel(options);
|
|
31
44
|
}
|
|
32
45
|
catch (error) {
|
|
33
|
-
console.error(`Transfer-model generation failed: ${
|
|
46
|
+
console.error(`Transfer-model generation failed: ${describeError(error)}`);
|
|
34
47
|
}
|
|
35
48
|
};
|
|
36
49
|
runSafely();
|
|
37
|
-
|
|
50
|
+
// A grammar's language id and extensions reach only `module.ts`, so the
|
|
51
|
+
// languages module would go stale without it.
|
|
52
|
+
const watched = [
|
|
53
|
+
options.astFile,
|
|
54
|
+
options.augmentationFile,
|
|
55
|
+
...(options.languagesFile !== undefined ? [languagesModuleFile(options)] : [])
|
|
56
|
+
];
|
|
38
57
|
let timer;
|
|
39
|
-
const
|
|
58
|
+
const rerun = () => {
|
|
59
|
+
if (watched.every(file => fs.existsSync(file))) {
|
|
60
|
+
runSafely();
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
// The poll reports every stat it takes; a replaced file has a new inode, a
|
|
64
|
+
// rewritten one a new mtime, a removed or returning one zeroed stats.
|
|
65
|
+
const onPoll = (current, previous) => {
|
|
66
|
+
if (current.ino === previous.ino && current.mtimeMs === previous.mtimeMs && current.size === previous.size) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
40
69
|
if (timer) {
|
|
41
70
|
clearTimeout(timer);
|
|
42
71
|
}
|
|
43
|
-
timer = setTimeout(
|
|
72
|
+
timer = setTimeout(rerun, 150);
|
|
44
73
|
};
|
|
45
|
-
const
|
|
74
|
+
for (const file of watched) {
|
|
75
|
+
fs.watchFile(file, { interval: WATCH_POLL_INTERVAL_MS }, onPoll);
|
|
76
|
+
}
|
|
77
|
+
console.log(`Watching ${watched.join(', ')} for changes. Press Ctrl-C to stop.`);
|
|
46
78
|
return new Promise(resolve => {
|
|
47
79
|
context.signal.addEventListener('abort', () => {
|
|
48
|
-
for (const
|
|
49
|
-
|
|
80
|
+
for (const file of watched) {
|
|
81
|
+
fs.unwatchFile(file, onPoll);
|
|
50
82
|
}
|
|
51
83
|
if (timer) {
|
|
52
84
|
clearTimeout(timer);
|
|
@@ -55,6 +87,10 @@ export function watchTransferModel(options, context) {
|
|
|
55
87
|
}, { once: true });
|
|
56
88
|
});
|
|
57
89
|
}
|
|
90
|
+
/** The langium-cli `module.ts` beside the AST file, which the languages module is read from. */
|
|
91
|
+
function languagesModuleFile(options) {
|
|
92
|
+
return path.join(path.dirname(options.astFile), 'module.ts');
|
|
93
|
+
}
|
|
58
94
|
/** Run the transfer-model generator. */
|
|
59
95
|
export function generateTransferModel(options) {
|
|
60
96
|
const elementTypeName = options.elementTypeName ?? DEFAULT_ELEMENT_TYPE_NAME;
|
|
@@ -92,9 +128,13 @@ export function generateTransferModel(options) {
|
|
|
92
128
|
if (skipTypeAliases.has(name)) {
|
|
93
129
|
continue;
|
|
94
130
|
}
|
|
95
|
-
const
|
|
96
|
-
if (
|
|
97
|
-
typeAliases.push({
|
|
131
|
+
const typeNode = alias.getTypeNode();
|
|
132
|
+
if (typeNode) {
|
|
133
|
+
typeAliases.push({
|
|
134
|
+
name,
|
|
135
|
+
definition: mapType(resolveNamespacedStringUnion(astSource, typeNode.getText()), elementTypeName),
|
|
136
|
+
members: unionMembers(typeNode).map(member => mapType(member, elementTypeName))
|
|
137
|
+
});
|
|
98
138
|
}
|
|
99
139
|
}
|
|
100
140
|
// 5. Parse augmentations from the consumer's `declare module` blocks.
|
|
@@ -108,7 +148,6 @@ export function generateTransferModel(options) {
|
|
|
108
148
|
// 7. Classify interfaces: abstract (union $type) vs concrete (literal $type).
|
|
109
149
|
const interfaceNames = [];
|
|
110
150
|
const abstractTypes = new Set();
|
|
111
|
-
const concreteTypes = new Set();
|
|
112
151
|
for (const name of Object.keys(reflectionTypes)) {
|
|
113
152
|
const iface = astInterfaces.get(name);
|
|
114
153
|
if (!iface) {
|
|
@@ -120,9 +159,6 @@ export function generateTransferModel(options) {
|
|
|
120
159
|
if (typeText.includes('|')) {
|
|
121
160
|
abstractTypes.add(name);
|
|
122
161
|
}
|
|
123
|
-
else {
|
|
124
|
-
concreteTypes.add(name);
|
|
125
|
-
}
|
|
126
162
|
}
|
|
127
163
|
// 8. Resolve extends-chains. Filter out type-alias supertypes (Langium reflection
|
|
128
164
|
// includes them for the grammar hierarchy but TypeScript can't extend a union
|
|
@@ -157,12 +193,13 @@ export function generateTransferModel(options) {
|
|
|
157
193
|
out.push(' readonly $type: string;');
|
|
158
194
|
out.push('}');
|
|
159
195
|
out.push('');
|
|
160
|
-
//
|
|
196
|
+
// Langium's per-type constant under the same name, for every reflection type
|
|
197
|
+
// the model emits, abstract ones and unions included.
|
|
198
|
+
const reflectedTypes = Object.keys(reflectionTypes).filter(name => astInterfaces.has(name) || typeAliasNames.has(name));
|
|
161
199
|
out.push('// --- Type Constants ---');
|
|
162
|
-
for (const name of
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
}
|
|
200
|
+
for (const name of reflectedTypes) {
|
|
201
|
+
const keys = reflectionTypes[name].properties.map(property => `${property.name}: '${property.name}'`);
|
|
202
|
+
out.push(`export const ${name} = { ${[`$type: '${name}'`, ...keys].join(', ')} } as const;`);
|
|
166
203
|
}
|
|
167
204
|
out.push('');
|
|
168
205
|
// Type aliases.
|
|
@@ -172,7 +209,7 @@ export function generateTransferModel(options) {
|
|
|
172
209
|
out.push(`export type ${name} = ${definition};`);
|
|
173
210
|
const literals = extractStringLiterals(definition);
|
|
174
211
|
if (literals) {
|
|
175
|
-
const items = literals.map(
|
|
212
|
+
const items = literals.map(quote).join(', ');
|
|
176
213
|
out.push(`export const ${name}Values = [${items}] as const;`);
|
|
177
214
|
}
|
|
178
215
|
}
|
|
@@ -200,7 +237,7 @@ export function generateTransferModel(options) {
|
|
|
200
237
|
out.push(` readonly $type: ${typeValue};`);
|
|
201
238
|
}
|
|
202
239
|
else {
|
|
203
|
-
out.push(` readonly $type:
|
|
240
|
+
out.push(` readonly $type: '${name}';`);
|
|
204
241
|
}
|
|
205
242
|
const emitted = new Set(['$type']);
|
|
206
243
|
for (const prop of iface.getProperties()) {
|
|
@@ -256,24 +293,24 @@ export function generateTransferModel(options) {
|
|
|
256
293
|
out.push(` return is${elementTypeName}(item) && (${checks});`);
|
|
257
294
|
}
|
|
258
295
|
else {
|
|
259
|
-
out.push(` return is${elementTypeName}(item) && item.$type === ${name}
|
|
296
|
+
out.push(` return is${elementTypeName}(item) && item.$type === '${name}';`);
|
|
260
297
|
}
|
|
261
298
|
out.push('}');
|
|
262
299
|
out.push('');
|
|
263
300
|
}
|
|
264
|
-
for (const { name, definition } of typeAliases) {
|
|
301
|
+
for (const { name, definition, members } of typeAliases) {
|
|
265
302
|
const literals = extractStringLiterals(definition);
|
|
266
303
|
if (literals) {
|
|
267
|
-
const checks = literals.map(l => `item ===
|
|
304
|
+
const checks = literals.map(l => `item === ${quote(l)}`).join(' || ') || 'false';
|
|
268
305
|
out.push(`export function is${name}(item: unknown): item is ${name} {`);
|
|
269
306
|
out.push(` return ${checks};`);
|
|
270
307
|
out.push('}');
|
|
271
308
|
out.push('');
|
|
272
309
|
}
|
|
273
310
|
else {
|
|
274
|
-
// Union (or single) of named members
|
|
275
|
-
//
|
|
276
|
-
|
|
311
|
+
// Union (or single) of named members, Langium data-type primitives and the string
|
|
312
|
+
// literals a data-type rule's keywords add beside them. Each member maps to its own
|
|
313
|
+
// check via typeAliasMemberGuard.
|
|
277
314
|
const checks = members.map(typeAliasMemberGuard).join(' || ');
|
|
278
315
|
out.push(`export function is${name}(item: unknown): item is ${name} {`);
|
|
279
316
|
out.push(` return ${checks};`);
|
|
@@ -281,6 +318,8 @@ export function generateTransferModel(options) {
|
|
|
281
318
|
out.push('');
|
|
282
319
|
}
|
|
283
320
|
}
|
|
321
|
+
out.push(...renderTypeMap(languageId, reflectedTypes));
|
|
322
|
+
out.push(...renderReflection(languageId, elementTypeName, reflectedTypes, reflectionTypes));
|
|
284
323
|
// Coverage check: warn on reflection types not emitted.
|
|
285
324
|
const processedSet = new Set(sorted);
|
|
286
325
|
for (const name of Object.keys(reflectionTypes)) {
|
|
@@ -293,10 +332,89 @@ export function generateTransferModel(options) {
|
|
|
293
332
|
fs.mkdirSync(path.dirname(options.outFile), { recursive: true });
|
|
294
333
|
if (fs.existsSync(options.outFile) && fs.readFileSync(options.outFile, 'utf-8') === content) {
|
|
295
334
|
console.log('Transfer model is up to date.');
|
|
296
|
-
return;
|
|
297
335
|
}
|
|
298
|
-
|
|
299
|
-
|
|
336
|
+
else {
|
|
337
|
+
fs.writeFileSync(options.outFile, content, 'utf-8');
|
|
338
|
+
console.log(`Generated: ${options.outFile}`);
|
|
339
|
+
}
|
|
340
|
+
if (options.astBuilderFile !== undefined) {
|
|
341
|
+
const emitted = emitAstBuilder(astSource, {
|
|
342
|
+
outFile: options.astBuilderFile,
|
|
343
|
+
astFile: options.astFile,
|
|
344
|
+
languageId,
|
|
345
|
+
regenCommand
|
|
346
|
+
});
|
|
347
|
+
if (!emitted) {
|
|
348
|
+
console.warn(`Warning: no '${languageId}AstType' alias in ${options.astFile}; skipping the AST builder.`);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
if (options.transferBuilderFile !== undefined) {
|
|
352
|
+
emitTransferBuilder({ outFile: options.transferBuilderFile, transferModelFile: options.outFile, languageId, regenCommand });
|
|
353
|
+
}
|
|
354
|
+
if (options.languagesFile !== undefined) {
|
|
355
|
+
const moduleSource = project.addSourceFileAtPath(languagesModuleFile(options));
|
|
356
|
+
emitLanguages(moduleSource, { outFile: options.languagesFile, regenCommand });
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* `<LanguageId>TransferTypes`, each `$type` to its interface, so an encoder or a
|
|
361
|
+
* builder can type a node by the grammar the way Langium's `<LanguageId>AstType`
|
|
362
|
+
* does on the AST side.
|
|
363
|
+
*/
|
|
364
|
+
function renderTypeMap(languageId, types) {
|
|
365
|
+
return ['// --- Type Map ---', `export type ${languageId}TransferTypes = {`, ...types.map(name => ` ${name}: ${name};`), '};', ''];
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* `<LanguageId>TransferReflection`, the grammar metadata with the method names
|
|
369
|
+
* Langium's `AstReflection` uses. A plain object with no framework import, so
|
|
370
|
+
* the file stays self-contained, and nothing references it but its importers:
|
|
371
|
+
* the `is` guards test `$type` directly, so a guard never pulls it in. `types`
|
|
372
|
+
* keeps its literal type, which is how the transfer-node builder tells which
|
|
373
|
+
* fields the grammar defaults.
|
|
374
|
+
*/
|
|
375
|
+
function renderReflection(languageId, elementTypeName, types, reflectionTypes) {
|
|
376
|
+
const metaData = `${languageId}TransferTypeMetaData`;
|
|
377
|
+
// Index signatures, not `Readonly<Record<…>>`: a grammar type may be named
|
|
378
|
+
// `Record` or `Readonly`, which Langium does not reserve as it does `Object`.
|
|
379
|
+
const out = [
|
|
380
|
+
'// --- Reflection ---',
|
|
381
|
+
`export interface ${metaData} {`,
|
|
382
|
+
' readonly name: string;',
|
|
383
|
+
' readonly properties: {',
|
|
384
|
+
' readonly [name: string]: { readonly name: string; readonly defaultValue?: unknown; readonly optional?: boolean; readonly referenceType?: string };',
|
|
385
|
+
' };',
|
|
386
|
+
' readonly superTypes: readonly string[];',
|
|
387
|
+
'}',
|
|
388
|
+
'',
|
|
389
|
+
`export const ${languageId}TransferReflection = {`,
|
|
390
|
+
' types: {'
|
|
391
|
+
];
|
|
392
|
+
for (const name of types) {
|
|
393
|
+
const { properties, superTypes } = reflectionTypes[name];
|
|
394
|
+
const propertyEntries = properties.map(property => {
|
|
395
|
+
const fields = [`name: '${property.name}'`];
|
|
396
|
+
if (property.defaultValue !== undefined) {
|
|
397
|
+
fields.push(`defaultValue: ${property.defaultValue}`);
|
|
398
|
+
}
|
|
399
|
+
if (property.optional) {
|
|
400
|
+
fields.push('optional: true');
|
|
401
|
+
}
|
|
402
|
+
if (property.referenceType !== undefined) {
|
|
403
|
+
fields.push(`referenceType: '${property.referenceType}'`);
|
|
404
|
+
}
|
|
405
|
+
return `${property.name}: { ${fields.join(', ')} }`;
|
|
406
|
+
});
|
|
407
|
+
const supers = superTypes.map(superType => `'${superType}'`).join(', ');
|
|
408
|
+
const propertiesText = propertyEntries.length > 0 ? `{ ${propertyEntries.join(', ')} }` : '{}';
|
|
409
|
+
out.push(` ${name}: { name: '${name}', properties: ${propertiesText}, superTypes: [${supers}] },`);
|
|
410
|
+
}
|
|
411
|
+
out.push(` } as const satisfies { readonly [type: string]: ${metaData} },`, '', ' getAllTypes(): string[] {', ' return Object.keys(this.types);', ' },', '',
|
|
412
|
+
// An own-property check, not `types[type] ?? …`: a name the object
|
|
413
|
+
// prototype carries, `toString` say, would read the inherited member and
|
|
414
|
+
// make `isSubtype` throw. `hasOwnProperty.call` rather than `Object.hasOwn`
|
|
415
|
+
// because the adopter's protocol package may target a lib without it.
|
|
416
|
+
` getTypeMetaData(type: string): ${metaData} {`, ' return Object.prototype.hasOwnProperty.call(this.types, type)', ` ? (this.types as { readonly [type: string]: ${metaData} })[type]`, ' : { name: type, properties: {}, superTypes: [] };', ' },', '', ' isSubtype(subtype: string, supertype: string): boolean {', ' return subtype === supertype || this.getTypeMetaData(subtype).superTypes.some(type => this.isSubtype(type, supertype));', ' },', '', ' getAllSubTypes(type: string): string[] {', ' return this.getAllTypes().filter(candidate => this.isSubtype(candidate, type));', ' },', '', ' isInstance(item: unknown, type: string): boolean {', ` return is${elementTypeName}(item) && this.isSubtype(item.$type, type);`, ' }', '};', '');
|
|
417
|
+
return out;
|
|
300
418
|
}
|
|
301
419
|
// ---------------------------------------------------------------------------
|
|
302
420
|
// AST source parsing helpers
|
|
@@ -335,10 +453,11 @@ function findAstReflectionClass(source) {
|
|
|
335
453
|
throw new Error('Could not find a class extending AbstractAstReflection in the AST source.');
|
|
336
454
|
}
|
|
337
455
|
/**
|
|
338
|
-
* Extract `superTypes` for each entry of the
|
|
339
|
-
* initializer. We rely on the Langium
|
|
340
|
-
*
|
|
341
|
-
* `.$type
|
|
456
|
+
* Extract `superTypes` and the grammar properties for each entry of the
|
|
457
|
+
* reflection class's `types` property initializer. We rely on the Langium
|
|
458
|
+
* convention that `X.$type === 'X'` and `X.p === 'p'`, so a type expression
|
|
459
|
+
* resolves to the literal type-name string by stripping `.$type`, and a
|
|
460
|
+
* property's name is its key.
|
|
342
461
|
*/
|
|
343
462
|
function parseReflectionTypes(reflectionClass) {
|
|
344
463
|
const result = {};
|
|
@@ -359,29 +478,31 @@ function parseReflectionTypes(reflectionClass) {
|
|
|
359
478
|
const value = entry.getLastChildByKind(SyntaxKind.ObjectLiteralExpression);
|
|
360
479
|
const supersProp = value?.getProperty('superTypes');
|
|
361
480
|
const supersInit = supersProp?.getFirstChildByKind(SyntaxKind.ArrayLiteralExpression);
|
|
362
|
-
const superTypes = [];
|
|
363
|
-
|
|
364
|
-
for (const element of supersInit.getElements()) {
|
|
365
|
-
const text = element.getText();
|
|
366
|
-
const dotMatch = /^([A-Za-z_$][\w$]*)\.\$type$/.exec(text);
|
|
367
|
-
if (dotMatch) {
|
|
368
|
-
superTypes.push(dotMatch[1]);
|
|
369
|
-
continue;
|
|
370
|
-
}
|
|
371
|
-
// Bare identifier or quoted string fall-back.
|
|
372
|
-
const stringMatch = /^['"](.+)['"]$/.exec(text);
|
|
373
|
-
if (stringMatch) {
|
|
374
|
-
superTypes.push(stringMatch[1]);
|
|
375
|
-
}
|
|
376
|
-
else {
|
|
377
|
-
superTypes.push(text);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
result[name] = { superTypes };
|
|
481
|
+
const superTypes = supersInit?.getElements().map(element => typeNameOf(element.getText())) ?? [];
|
|
482
|
+
result[name] = { superTypes, properties: parseReflectionProperties(value) };
|
|
382
483
|
}
|
|
383
484
|
return result;
|
|
384
485
|
}
|
|
486
|
+
function parseReflectionProperties(entry) {
|
|
487
|
+
const propertiesInit = entry?.getProperty('properties')?.getFirstChildByKind(SyntaxKind.ObjectLiteralExpression);
|
|
488
|
+
const properties = [];
|
|
489
|
+
for (const property of propertiesInit?.getChildrenOfKind(SyntaxKind.PropertyAssignment) ?? []) {
|
|
490
|
+
const meta = property.getInitializerIfKind(SyntaxKind.ObjectLiteralExpression);
|
|
491
|
+
const field = (key) => meta?.getProperty(key)?.asKind(SyntaxKind.PropertyAssignment)?.getInitializer()?.getText();
|
|
492
|
+
const referenceType = field('referenceType');
|
|
493
|
+
properties.push({
|
|
494
|
+
name: property.getName(),
|
|
495
|
+
defaultValue: field('defaultValue'),
|
|
496
|
+
optional: field('optional') === 'true',
|
|
497
|
+
referenceType: referenceType === undefined ? undefined : typeNameOf(referenceType)
|
|
498
|
+
});
|
|
499
|
+
}
|
|
500
|
+
return properties;
|
|
501
|
+
}
|
|
502
|
+
/** `X.$type` or a quoted `'X'` to `X`; any other text passes through. */
|
|
503
|
+
function typeNameOf(text) {
|
|
504
|
+
return /^([A-Za-z_$][\w$]*)\.\$type$/.exec(text)?.[1] ?? /^['"](.+)['"]$/.exec(text)?.[1] ?? text;
|
|
505
|
+
}
|
|
385
506
|
/**
|
|
386
507
|
* Collect terminal regex literals from the AST file.
|
|
387
508
|
*
|
|
@@ -500,12 +621,16 @@ function mapType(text, elementTypeName) {
|
|
|
500
621
|
}
|
|
501
622
|
/**
|
|
502
623
|
* Type-guard expression (against an `item: unknown`) for one member of a non-literal type-alias
|
|
503
|
-
* union.
|
|
504
|
-
*
|
|
505
|
-
*
|
|
506
|
-
* `
|
|
624
|
+
* union. A string literal is compared as written, so the escapes Langium wrote stay valid.
|
|
625
|
+
* Covers the full set of Langium data-type primitives. The `typeof`-checkable ones
|
|
626
|
+
* (`string`/`number`/`boolean`/`bigint`) use `typeof`, and `Date`, the one Langium primitive
|
|
627
|
+
* `typeof` reports as `'object'`, uses `instanceof`. Any other member is a named type whose
|
|
628
|
+
* generated `is<Member>` guard is called.
|
|
507
629
|
*/
|
|
508
630
|
export function typeAliasMemberGuard(member) {
|
|
631
|
+
if (member.startsWith("'") || member.startsWith('"')) {
|
|
632
|
+
return `item === ${member}`;
|
|
633
|
+
}
|
|
509
634
|
switch (member) {
|
|
510
635
|
case 'string':
|
|
511
636
|
case 'number':
|
|
@@ -528,10 +653,11 @@ export function typeAliasMemberGuard(member) {
|
|
|
528
653
|
* name.
|
|
529
654
|
*
|
|
530
655
|
* Each referenced member is inlined and de-duplicated, preserving first-seen
|
|
531
|
-
* order
|
|
532
|
-
* namespace-qualified reference (the
|
|
533
|
-
*
|
|
534
|
-
* emitting a
|
|
656
|
+
* order; when no member holds a literal, the union is `never`. The definition
|
|
657
|
+
* is returned UNCHANGED when it holds no namespace-qualified reference (the
|
|
658
|
+
* single-language case) or when any referenced member is not a pure
|
|
659
|
+
* string-literal union — passing it through rather than emitting a
|
|
660
|
+
* half-resolved union.
|
|
535
661
|
*/
|
|
536
662
|
export function resolveNamespacedStringUnion(astSource, definition) {
|
|
537
663
|
const references = [...definition.matchAll(/\b([A-Za-z_]\w*)\.([A-Za-z_]\w*)\b/g)];
|
|
@@ -553,15 +679,54 @@ export function resolveNamespacedStringUnion(astSource, definition) {
|
|
|
553
679
|
}
|
|
554
680
|
}
|
|
555
681
|
}
|
|
556
|
-
return literals.map(
|
|
682
|
+
return literals.length > 0 ? literals.map(quote).join(' | ') : 'never';
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* The members of a type-alias union as TypeScript parses them. If a data-type rule groups
|
|
686
|
+
* alternatives in parentheses, the alias Langium generates contains the same group, as in
|
|
687
|
+
* `'a' | ('b' | Keyword)`, so each group is flattened into its members. Splitting the text on
|
|
688
|
+
* `|` breaks such a group and any keyword that contains `|`, such as `'||'`, and the
|
|
689
|
+
* resulting guard does not compile.
|
|
690
|
+
*/
|
|
691
|
+
function unionMembers(typeNode) {
|
|
692
|
+
if (typeNode.isKind(SyntaxKind.UnionType)) {
|
|
693
|
+
return typeNode.getTypeNodes().flatMap(member => unionMembers(member));
|
|
694
|
+
}
|
|
695
|
+
if (typeNode.isKind(SyntaxKind.ParenthesizedType)) {
|
|
696
|
+
return unionMembers(typeNode.getTypeNode());
|
|
697
|
+
}
|
|
698
|
+
return [typeNode.getText()];
|
|
557
699
|
}
|
|
558
|
-
/**
|
|
700
|
+
/**
|
|
701
|
+
* The values of a union of string literals, or undefined when the definition holds anything
|
|
702
|
+
* else. The TypeScript scanner decodes each literal, so a keyword with a quote in it reads the
|
|
703
|
+
* same whichever quotes and escapes Langium wrote it with. Langium writes the keyword names of
|
|
704
|
+
* a language without keywords as `never`, which adds no value.
|
|
705
|
+
*/
|
|
559
706
|
function extractStringLiterals(definition) {
|
|
560
|
-
const
|
|
561
|
-
|
|
562
|
-
|
|
707
|
+
const scanner = ts.createScanner(ts.ScriptTarget.Latest, true, ts.LanguageVariant.Standard, definition);
|
|
708
|
+
const literals = [];
|
|
709
|
+
let members = 0;
|
|
710
|
+
for (let token = scanner.scan(); token !== ts.SyntaxKind.EndOfFileToken; token = scanner.scan()) {
|
|
711
|
+
if (token === ts.SyntaxKind.StringLiteral) {
|
|
712
|
+
literals.push(scanner.getTokenValue());
|
|
713
|
+
members++;
|
|
714
|
+
}
|
|
715
|
+
else if (token === ts.SyntaxKind.NeverKeyword) {
|
|
716
|
+
members++;
|
|
717
|
+
}
|
|
718
|
+
else if (token !== ts.SyntaxKind.BarToken) {
|
|
719
|
+
return undefined;
|
|
720
|
+
}
|
|
563
721
|
}
|
|
564
|
-
return
|
|
722
|
+
return members > 0 ? literals : undefined;
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* `value` as a string literal in the single quotes the generated file uses. A keyword can
|
|
726
|
+
* contain a quote or a backslash, and either one ends or escapes the literal unless escaped.
|
|
727
|
+
*/
|
|
728
|
+
function quote(value) {
|
|
729
|
+
return `'${value.replaceAll('\\', '\\\\').replaceAll("'", "\\'")}'`;
|
|
565
730
|
}
|
|
566
731
|
function topologicalSort(names, getDeps) {
|
|
567
732
|
const visited = new Set();
|