@hydranium/cli 1.0.0-next.31 → 1.0.0-next.312
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 +79 -205
- package/bin/hydranium-cli.js +13 -0
- package/heap-analysis/heap/core/load.mjs +2 -2
- 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.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 +2 -1
- 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-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-model-args.d.ts.map +1 -1
- package/lib/commands/generate-transfer-model-args.js +7 -0
- 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 +6 -3
- package/lib/commands/generate-transfer-model-config.js.map +1 -1
- package/lib/commands/generate-transfer-model.d.ts +15 -1
- package/lib/commands/generate-transfer-model.d.ts.map +1 -1
- package/lib/commands/generate-transfer-model.js +46 -8
- package/lib/commands/generate-transfer-model.js.map +1 -1
- 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 +68 -17
- package/lib/commands/headless-harness.js.map +1 -1
- package/lib/commands/init-args.d.ts.map +1 -1
- package/lib/commands/init-args.js +32 -27
- package/lib/commands/init-args.js.map +1 -1
- 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 +18 -14
- package/lib/commands/init-templates.d.ts.map +1 -1
- package/lib/commands/init-templates.js +732 -677
- package/lib/commands/init-templates.js.map +1 -1
- package/lib/commands/init-wizard.d.ts.map +1 -1
- package/lib/commands/init-wizard.js +17 -27
- 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 +45 -19
- package/lib/commands/init.d.ts.map +1 -1
- package/lib/commands/init.js +80 -43
- 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 +5 -5
- package/lib/commands/query-args.js.map +1 -1
- package/lib/commands/query.d.ts +3 -4
- package/lib/commands/query.d.ts.map +1 -1
- package/lib/commands/query.js +2 -2
- 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 +2 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -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 +52 -39
- package/src/cli.ts +7 -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 +2 -1
- 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-languages.ts +132 -0
- package/src/commands/generate-transfer-model-args.ts +7 -0
- package/src/commands/generate-transfer-model-config.ts +6 -3
- package/src/commands/generate-transfer-model.ts +56 -8
- package/src/commands/harness-args.ts +99 -31
- package/src/commands/headless-harness.ts +86 -26
- package/src/commands/init-args.ts +32 -27
- package/src/commands/init-prompt.ts +5 -6
- package/src/commands/init-templates.ts +790 -696
- package/src/commands/init-wizard.ts +17 -27
- package/src/commands/init-workspace.ts +31 -16
- package/src/commands/init.ts +126 -58
- 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 +5 -4
- package/src/commands/query.ts +4 -6
- 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 +2 -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/gitignore +1 -0
- package/templates/protocol/gitignore +3 -0
- package/templates/protocol/src/__GRAMMAR_ID__-diagram-types.ts +41 -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__/gmodel-factory.ts +60 -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/ast.ts +23 -0
- package/templates/server/src/node/services.ts +16 -0
- package/templates/server/test/__GRAMMAR_ID__-diagram.test.ts +112 -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/workspace/nodes.__EXTENSION__ +5 -0
- package/templates/workspace/references.__EXTENSION__ +2 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// GLSP state for the __GRAMMAR__ diagram.
|
|
2
|
+
//
|
|
3
|
+
// `FullTextHydraniumGlspState` is the simplest of the framework source-model
|
|
4
|
+
// strategies (the others project a structured transfer model, over one document
|
|
5
|
+
// or several): the source model is the whole document text, serialised through
|
|
6
|
+
// the per-URI `Serializer` and round-tripped by re-parsing. Both seams resolve
|
|
7
|
+
// through shared services, so narrowing the root type is all an adopter adds.
|
|
8
|
+
//
|
|
9
|
+
// It cannot field-merge — every concurrent edit on a whole-document model is a
|
|
10
|
+
// same-document collision, so undo / redo degrade to drop-on-divergence. Move to
|
|
11
|
+
// `ReconcilingTransferHydraniumGlspState` when you need field-level undo.
|
|
12
|
+
|
|
13
|
+
import { FullTextHydraniumGlspState } from '@hydranium/glsp-server';
|
|
14
|
+
import { injectable } from 'inversify';
|
|
15
|
+
import type { __ENTRY_RULE__ } from '../../language-server/ast.js';
|
|
16
|
+
|
|
17
|
+
@injectable()
|
|
18
|
+
export class __GRAMMAR__GlspState extends FullTextHydraniumGlspState<__ENTRY_RULE__> {}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Source-model storage for the __GRAMMAR__ diagram, inheriting both framework
|
|
2
|
+
// defaults: `loadSourceModel` (open + settle + `setSourceRoot`) and
|
|
3
|
+
// `saveSourceModel` (flush the store's text for the primary and every tracked
|
|
4
|
+
// secondary through the diagram's client session).
|
|
5
|
+
//
|
|
6
|
+
// No serializer runs on the save path — a save persists what the diagram's
|
|
7
|
+
// operations already wrote to the store.
|
|
8
|
+
//
|
|
9
|
+
// The subclass exists so a bespoke load or save has a stable place to land.
|
|
10
|
+
|
|
11
|
+
import { type FullTextSourceModel, HydraniumGlspStorage } from '@hydranium/glsp-server';
|
|
12
|
+
import { injectable } from 'inversify';
|
|
13
|
+
import type { __ENTRY_RULE__ } from '../../language-server/ast.js';
|
|
14
|
+
|
|
15
|
+
@injectable()
|
|
16
|
+
export class __GRAMMAR__GlspStorage extends HydraniumGlspStorage<__ENTRY_RULE__, FullTextSourceModel> {}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
// Submission handler for the __GRAMMAR__ diagram.
|
|
2
|
+
//
|
|
3
|
+
// Inherits the framework's `readyEvent = IntegrityService.SettledState`, which
|
|
4
|
+
// is load-bearing rather than incidental: the GModel factory resolves
|
|
5
|
+
// `target.ref`, so it needs a fully-linked AST. Without the gate those reads
|
|
6
|
+
// fire mid-build and warn about resolution before scopes are computed.
|
|
7
|
+
//
|
|
8
|
+
// Only `formatSourceRoot` is overridden, so the submit log names the model and
|
|
9
|
+
// its node count instead of a bare `$type`.
|
|
10
|
+
|
|
11
|
+
import { ModelState } from '@eclipse-glsp/server';
|
|
12
|
+
import { type FullTextSourceModel, HydraniumGlspSubmissionHandler } from '@hydranium/glsp-server';
|
|
13
|
+
import { inject, injectable } from 'inversify';
|
|
14
|
+
import type { __ENTRY_RULE__ } from '../../language-server/ast.js';
|
|
15
|
+
import type { __GRAMMAR__GlspState } from './state.js';
|
|
16
|
+
|
|
17
|
+
@injectable()
|
|
18
|
+
export class __GRAMMAR__SubmissionHandler extends HydraniumGlspSubmissionHandler<__ENTRY_RULE__, FullTextSourceModel> {
|
|
19
|
+
@inject(ModelState) declare protected modelState: __GRAMMAR__GlspState;
|
|
20
|
+
|
|
21
|
+
protected override formatSourceRoot(root: __ENTRY_RULE__ | undefined): string {
|
|
22
|
+
return root ? `__ENTRY_RULE__ nodes=${root.nodes.length}` : 'none';
|
|
23
|
+
}
|
|
24
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Shared lexical basis for this project's grammars. Imported, never registered:
|
|
2
|
+
// it has no entry rule and no `langium-config.json` entry, so it is a fragment
|
|
3
|
+
// rather than a language.
|
|
4
|
+
//
|
|
5
|
+
// Keeping the tokens here rather than in one of the languages means a grammar
|
|
6
|
+
// imports `common` for its TOKENS and another language only when it needs that
|
|
7
|
+
// language's TYPES — separate reasons that are worth keeping separate.
|
|
8
|
+
|
|
9
|
+
hidden terminal WS: /\s+/;
|
|
10
|
+
terminal ID: /[_a-zA-Z][\w_]*/;
|
|
11
|
+
hidden terminal SL_COMMENT: /\/\/[^\n\r]*/;
|
|
12
|
+
hidden terminal ML_COMMENT: /\/\*[\s\S]*?\*\//;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Concrete-syntax emitter for __GRAMMAR__ — the parser's inverse, turning a
|
|
2
|
+
// model back into text this grammar accepts. Derived from the starter grammar
|
|
3
|
+
// exactly as `generated/ast.ts` is, so replacing the grammar replaces this too.
|
|
4
|
+
//
|
|
5
|
+
// Without it every structured write fails: the framework's default binding at
|
|
6
|
+
// `services.serializer.Serializer` THROWS, because a concrete syntax is
|
|
7
|
+
// language knowledge no framework can derive. A client session's `update` /
|
|
8
|
+
// `save`, the data head's `saveModelDocument` and a GLSP `SaveModelAction`
|
|
9
|
+
// all reach it.
|
|
10
|
+
//
|
|
11
|
+
// `AbstractSerializer`'s generic property walk lays out FORMAT-structured
|
|
12
|
+
// output — its YAML and JSON subclasses are what it exists for — and cannot
|
|
13
|
+
// produce a keyword-delimited syntax like `node a -> b`. So `serializeNode` is
|
|
14
|
+
// a per-`$type` emitter here and the two array hooks are unreachable.
|
|
15
|
+
|
|
16
|
+
import { AbstractSerializer } from '@hydranium/core';
|
|
17
|
+
import type { AstNode } from '@hydranium/langium';
|
|
18
|
+
import { type __ENTRY_RULE__, type __NODE_RULE__, is__ENTRY_RULE__, is__NODE_RULE__ } from './ast.js';
|
|
19
|
+
|
|
20
|
+
export class __GRAMMAR__Serializer extends AbstractSerializer<__ENTRY_RULE__> {
|
|
21
|
+
protected override serializeNode(node: AstNode | Record<string, unknown>): string {
|
|
22
|
+
if (is__ENTRY_RULE__(node)) {
|
|
23
|
+
return node.nodes.map(child => this.emitNode(child)).join('\n');
|
|
24
|
+
}
|
|
25
|
+
if (is__NODE_RULE__(node)) {
|
|
26
|
+
return this.emitNode(node);
|
|
27
|
+
}
|
|
28
|
+
// Defensive: a rule added to the grammar with no emitter added here.
|
|
29
|
+
throw new Error(`__GRAMMAR__Serializer: no emitter for $type ${(node as AstNode).$type}`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Unreachable — this grammar's one list is emitted by its `__ENTRY_RULE__` parent. */
|
|
33
|
+
protected override serializeArray(): string {
|
|
34
|
+
throw new Error('__GRAMMAR__Serializer: arrays are emitted by the per-$type parent, not the generic dispatch.');
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** Unreachable — same reasoning as {@link serializeArray}. */
|
|
38
|
+
protected override serializeReferenceArray(): string {
|
|
39
|
+
throw new Error('__GRAMMAR__Serializer: reference arrays are emitted by the per-$type parent, not the generic dispatch.');
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* `serializeReferenceText` rather than `node.target?.$refText`: it is the one
|
|
44
|
+
* read that spans BOTH input shapes. A transfer model reaching
|
|
45
|
+
* `serializeTransfer` carries `target` as a plain string rather than a
|
|
46
|
+
* `Reference`, and a serializer that reaches for `$refText` directly emits
|
|
47
|
+
* the AST correctly and drops every reference on the transfer path.
|
|
48
|
+
*/
|
|
49
|
+
private emitNode(node: __NODE_RULE__): string {
|
|
50
|
+
const target = this.serializeReferenceText(node.target);
|
|
51
|
+
return target === undefined ? `node ${node.name}` : `node ${node.name} -> ${target}`;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// The language's AST entry point: a re-export of what `langium generate`
|
|
2
|
+
// emits, plus anywhere you augment those types.
|
|
3
|
+
//
|
|
4
|
+
// Import the AST from HERE rather than from `./generated/ast.js`, so any
|
|
5
|
+
// augmentation below travels with every import. One `langium-cli` run over N
|
|
6
|
+
// grammars emits ONE combined AST module sharing one reflection, so a further
|
|
7
|
+
// grammar needs no change here.
|
|
8
|
+
//
|
|
9
|
+
// `generate:transfer-model` reads this file as its `--augmentation-file`: the
|
|
10
|
+
// generated wire types are derived from the AST *as augmented*, not from the
|
|
11
|
+
// raw generated module. Augment a type here and the transfer model follows.
|
|
12
|
+
//
|
|
13
|
+
// A `@derived` property is computed at build time rather than parsed, so it is
|
|
14
|
+
// declared here and populated by an AST-extension contribution:
|
|
15
|
+
//
|
|
16
|
+
// declare module './generated/ast.js' {
|
|
17
|
+
// interface __ENTRY_RULE__ {
|
|
18
|
+
// /** @derived Populated by an `ast.extensions.computedProperties` contribution. */
|
|
19
|
+
// readonly _summary?: string;
|
|
20
|
+
// }
|
|
21
|
+
// }
|
|
22
|
+
|
|
23
|
+
export * from './generated/ast.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
// Zero-arg service factory for the headless `hydranium-cli` tooling: the
|
|
2
|
+
// `reflect` / `lint-grammar` / `validate` subcommands import this via
|
|
3
|
+
// `--services ./lib/node/services.js`. The head wires its own filesystem here.
|
|
4
|
+
//
|
|
5
|
+
// Behind the package's `./node` entry rather than its root because it reads
|
|
6
|
+
// the real filesystem: the root stays loadable in a browser worker, which has
|
|
7
|
+
// no `node:fs`.
|
|
8
|
+
//
|
|
9
|
+
// The contract is language-count-agnostic — a second grammar needs no edit here.
|
|
10
|
+
|
|
11
|
+
import { NodeFileSystem } from '@hydranium/core/node';
|
|
12
|
+
import { create__NAME__Services } from '../language-server/__PROJECT_ID__-module.js';
|
|
13
|
+
|
|
14
|
+
export function createServices(): ReturnType<typeof create__NAME__Services> {
|
|
15
|
+
return create__NAME__Services({ ...NodeFileSystem });
|
|
16
|
+
}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
// The starter diagram, run the way a client runs it: an in-process GLSP server
|
|
2
|
+
// opens a document. A create-node operation adds a node, and an undo and a redo
|
|
3
|
+
// take it out and put it back; every step must keep the nodes the document
|
|
4
|
+
// already had, and its comments, since the diagram writes the document from its
|
|
5
|
+
// AST, which carries none. A reference into another document draws no edge,
|
|
6
|
+
// since the graph holds no node for its target, but resolves, even when the
|
|
7
|
+
// diagram opened its document before the workspace was up.
|
|
8
|
+
|
|
9
|
+
import 'reflect-metadata';
|
|
10
|
+
import { type Action, CreateNodeOperation, RedoAction, ServerModule, SetDirtyStateAction, UndoAction } from '@eclipse-glsp/server';
|
|
11
|
+
import { initializeWorkspaceProgrammatically } from '@hydranium/core';
|
|
12
|
+
import { makeScratchWorkspace, type ScratchWorkspace } from '@hydranium/core/testing/node';
|
|
13
|
+
import { HydraniumGlspAppModule } from '@hydranium/glsp-server';
|
|
14
|
+
import { type GlspHarness, makeGlspHarness } from '@hydranium/glsp-server/testing';
|
|
15
|
+
import { waitFor } from '@hydranium/protocol/testing';
|
|
16
|
+
import { __GRAMMAR_ID_CONST___DIAGRAM_TYPE, __GRAMMAR_ID_CONST___NODE_TYPE } from '__PROTOCOL_PACKAGE__';
|
|
17
|
+
import { afterEach, describe, expect, it } from 'vitest';
|
|
18
|
+
import { __GRAMMAR__DiagramModule } from '../src/glsp/__GRAMMAR_ID__/diagram-module.js';
|
|
19
|
+
import type { __GRAMMAR__GlspState } from '../src/glsp/__GRAMMAR_ID__/state.js';
|
|
20
|
+
import { createServices } from '../src/node/services.js';
|
|
21
|
+
|
|
22
|
+
let workspace: ScratchWorkspace | undefined;
|
|
23
|
+
let diagram: GlspHarness<__GRAMMAR__GlspState> | undefined;
|
|
24
|
+
|
|
25
|
+
afterEach(() => {
|
|
26
|
+
diagram?.dispose();
|
|
27
|
+
workspace?.dispose();
|
|
28
|
+
diagram = undefined;
|
|
29
|
+
workspace = undefined;
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
/** Send `action` and wait for the dirty state the server answers it with, which it sends once the edit is written. */
|
|
33
|
+
async function send(harness: GlspHarness<__GRAMMAR__GlspState>, action: Action, reason: string): Promise<void> {
|
|
34
|
+
const before = harness.actions.length;
|
|
35
|
+
harness.dispatch(action);
|
|
36
|
+
await waitFor(() => harness.actions.slice(before).some(sent => SetDirtyStateAction.is(sent) && sent.reason === reason), {
|
|
37
|
+
message: `no '${reason}' dirty state`
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
describe('__GRAMMAR__ diagram', () => {
|
|
42
|
+
it('creates a node after the existing ones, keeping their comments, and undoes and redoes it', async () => {
|
|
43
|
+
workspace = makeScratchWorkspace({ prefix: '__GRAMMAR_ID__-diagram-' });
|
|
44
|
+
const original = '// keep this comment\nnode first -> second\n// about second\nnode second';
|
|
45
|
+
const file = workspace.write('model.__EXTENSION__', original);
|
|
46
|
+
const { shared } = createServices();
|
|
47
|
+
await initializeWorkspaceProgrammatically(shared, workspace.root);
|
|
48
|
+
diagram = makeGlspHarness<__GRAMMAR__GlspState>({
|
|
49
|
+
serverModule: new ServerModule().configureDiagramModule(new __GRAMMAR__DiagramModule()),
|
|
50
|
+
diagramType: __GRAMMAR_ID_CONST___DIAGRAM_TYPE,
|
|
51
|
+
appModules: [new HydraniumGlspAppModule({ shared })]
|
|
52
|
+
});
|
|
53
|
+
await diagram.start();
|
|
54
|
+
await diagram.openDocument(file);
|
|
55
|
+
const uri = workspace.uri('model.__EXTENSION__');
|
|
56
|
+
const text = (): string | undefined => shared.workspace.TextDocuments.get(uri)?.getText();
|
|
57
|
+
|
|
58
|
+
await send(diagram, CreateNodeOperation.create(__GRAMMAR_ID_CONST___NODE_TYPE), 'operation');
|
|
59
|
+
const created = text();
|
|
60
|
+
await send(diagram, UndoAction.create(), 'undo');
|
|
61
|
+
const undone = text();
|
|
62
|
+
await send(diagram, RedoAction.create(), 'redo');
|
|
63
|
+
|
|
64
|
+
expect({ created, undone, redone: text() }).toEqual({
|
|
65
|
+
created: `${original}\nnode Node`,
|
|
66
|
+
undone: original,
|
|
67
|
+
redone: `${original}\nnode Node`
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
it('draws no edge for a reference that resolves into another document', async () => {
|
|
72
|
+
workspace = makeScratchWorkspace({ prefix: '__GRAMMAR_ID__-diagram-' });
|
|
73
|
+
workspace.write('declaring.__EXTENSION__', 'node second');
|
|
74
|
+
const file = workspace.write('referencing.__EXTENSION__', 'node first -> second');
|
|
75
|
+
const { shared } = createServices();
|
|
76
|
+
await initializeWorkspaceProgrammatically(shared, workspace.root);
|
|
77
|
+
diagram = makeGlspHarness<__GRAMMAR__GlspState>({
|
|
78
|
+
serverModule: new ServerModule().configureDiagramModule(new __GRAMMAR__DiagramModule()),
|
|
79
|
+
diagramType: __GRAMMAR_ID_CONST___DIAGRAM_TYPE,
|
|
80
|
+
appModules: [new HydraniumGlspAppModule({ shared })]
|
|
81
|
+
});
|
|
82
|
+
await diagram.start();
|
|
83
|
+
await diagram.openDocument(file);
|
|
84
|
+
|
|
85
|
+
// The reference resolves, so the missing edge is the document rule and
|
|
86
|
+
// not a dangling reference.
|
|
87
|
+
expect(diagram.state.sourceRoot?.nodes[0].target?.ref?.name).toBe('second');
|
|
88
|
+
expect(diagram.state.root.children.map(child => child.type)).toEqual([__GRAMMAR_ID_CONST___NODE_TYPE]);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
it('resolves a cross-document reference in a document opened before the workspace is up', async () => {
|
|
92
|
+
workspace = makeScratchWorkspace({ prefix: '__GRAMMAR_ID__-diagram-' });
|
|
93
|
+
workspace.write('declaring.__EXTENSION__', 'node second');
|
|
94
|
+
const file = workspace.write('referencing.__EXTENSION__', 'node first -> second');
|
|
95
|
+
const { shared } = createServices();
|
|
96
|
+
diagram = makeGlspHarness<__GRAMMAR__GlspState>({
|
|
97
|
+
serverModule: new ServerModule().configureDiagramModule(new __GRAMMAR__DiagramModule()),
|
|
98
|
+
diagramType: __GRAMMAR_ID_CONST___DIAGRAM_TYPE,
|
|
99
|
+
appModules: [new HydraniumGlspAppModule({ shared })]
|
|
100
|
+
});
|
|
101
|
+
await diagram.start();
|
|
102
|
+
// The open waits for the workspace. One that did not would have linked
|
|
103
|
+
// within this timer against a workspace holding only itself, and the
|
|
104
|
+
// bring-up does not relink it. Its budget covers the bring-up as well.
|
|
105
|
+
const opening = diagram.openDocument(file, 10_000);
|
|
106
|
+
await new Promise(resolve => setTimeout(resolve, 200));
|
|
107
|
+
await initializeWorkspaceProgrammatically(shared, workspace.root);
|
|
108
|
+
await opening;
|
|
109
|
+
|
|
110
|
+
expect(diagram.state.sourceRoot?.nodes[0].target?.ref?.name).toBe('second');
|
|
111
|
+
});
|
|
112
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineConfig } from 'vitest/config';
|
|
2
|
+
|
|
3
|
+
// Vitest transforms TypeScript itself and resolves `.js` specifiers to their
|
|
4
|
+
// `.ts` source, so tests import from `../src/` with the same specifiers the
|
|
5
|
+
// compiled output uses. `include` is scoped to `test/` so `lib/` is never
|
|
6
|
+
// scanned; `npm test` runs `typecheck:test` first, because vitest's
|
|
7
|
+
// transform strips types without checking them.
|
|
8
|
+
|
|
9
|
+
export default defineConfig({
|
|
10
|
+
test: {
|
|
11
|
+
environment: 'node',
|
|
12
|
+
include: ['test/**/*.{test,spec}.ts']
|
|
13
|
+
}
|
|
14
|
+
});
|