@hydranium/conformance 1.0.0-next.10
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/LICENSE +21 -0
- package/README.md +97 -0
- package/lib/conformance-suite.d.ts +97 -0
- package/lib/conformance-suite.d.ts.map +1 -0
- package/lib/conformance-suite.js +97 -0
- package/lib/conformance-suite.js.map +1 -0
- package/lib/data/index.d.ts +69 -0
- package/lib/data/index.d.ts.map +1 -0
- package/lib/data/index.js +223 -0
- package/lib/data/index.js.map +1 -0
- package/lib/glsp/index.d.ts +124 -0
- package/lib/glsp/index.d.ts.map +1 -0
- package/lib/glsp/index.js +99 -0
- package/lib/glsp/index.js.map +1 -0
- package/lib/index.d.ts +11 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +19 -0
- package/lib/index.js.map +1 -0
- package/lib/jest/index.d.ts +34 -0
- package/lib/jest/index.d.ts.map +1 -0
- package/lib/jest/index.js +59 -0
- package/lib/jest/index.js.map +1 -0
- package/lib/lsp/index.d.ts +88 -0
- package/lib/lsp/index.d.ts.map +1 -0
- package/lib/lsp/index.js +198 -0
- package/lib/lsp/index.js.map +1 -0
- package/lib/model.d.ts +111 -0
- package/lib/model.d.ts.map +1 -0
- package/lib/model.js +28 -0
- package/lib/model.js.map +1 -0
- package/lib/vitest/index.d.ts +48 -0
- package/lib/vitest/index.d.ts.map +1 -0
- package/lib/vitest/index.js +45 -0
- package/lib/vitest/index.js.map +1 -0
- package/package.json +120 -0
- package/src/conformance-suite.ts +148 -0
- package/src/data/index.ts +297 -0
- package/src/glsp/index.ts +217 -0
- package/src/index.ts +20 -0
- package/src/jest/index.ts +81 -0
- package/src/lsp/index.ts +269 -0
- package/src/model.ts +122 -0
- package/src/vitest/index.ts +81 -0
package/lib/lsp/index.js
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
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
|
+
* The `@hydranium/conformance/lsp` slice — protocol conformance for the LSP
|
|
11
|
+
* head. The driver port is a STRUCTURAL minimum (`LspConformanceDriver`) that
|
|
12
|
+
* `@hydranium/core/testing/node`'s `LspHarness` satisfies with NO adapter: the kit
|
|
13
|
+
* names only `string`, plain coordinates, and tiny structural minima
|
|
14
|
+
* (`{ message }`, `{ items }`, `{ capabilities }`), never
|
|
15
|
+
* `vscode-languageserver-protocol` wire types, so the harness's richer return
|
|
16
|
+
* types are assignable to the narrower port.
|
|
17
|
+
*
|
|
18
|
+
* **This slice does not read `LanguageFixture.edit` at all.** The didChange
|
|
19
|
+
* check drives `valid → invalid` using `invalid.text`, so there is no
|
|
20
|
+
* adopter-supplied assertion to run and `edit.expect` is never called.
|
|
21
|
+
* `completionPosition` is the one extra this slice does read.
|
|
22
|
+
*/
|
|
23
|
+
import assert from 'node:assert/strict';
|
|
24
|
+
import { resolveDeferred, resolveModel } from '../model.js';
|
|
25
|
+
/** True when `diagnostic` carries a message in either LSP shape (plain string or markup). */
|
|
26
|
+
function hasTextMessage(diagnostic) {
|
|
27
|
+
const { message } = diagnostic;
|
|
28
|
+
return typeof message === 'string' || typeof message?.value === 'string';
|
|
29
|
+
}
|
|
30
|
+
/** Document version sent on the `didChange` of the re-diagnose check (the open is v1). */
|
|
31
|
+
const CHANGED_VERSION = 2;
|
|
32
|
+
/**
|
|
33
|
+
* Build the LSP check battery: server-level checks once, then the
|
|
34
|
+
* grammar-bearing checks per language. Completion is an OPTIONAL LSP capability,
|
|
35
|
+
* so both completion checks are opt-in on the same `fixture.completionPosition`
|
|
36
|
+
* signal — the functional completion check and the `completionProvider` baseline
|
|
37
|
+
* advertisement each run only when at least one fixture supplies a position, and
|
|
38
|
+
* otherwise report skipped with a named reason rather than passing vacuously or
|
|
39
|
+
* mandating a capability of servers that do not offer completion.
|
|
40
|
+
* `textDocumentSync` stays mandatory: the document-sync and
|
|
41
|
+
* diagnostics checks depend on it. Each check connects a fresh driver, drives the
|
|
42
|
+
* `initialize` handshake, and disposes the driver. Exported for the kit's own
|
|
43
|
+
* unit tests; adopters call `runLspConformance`.
|
|
44
|
+
*/
|
|
45
|
+
export function buildLspChecks(options) {
|
|
46
|
+
const { connect } = options;
|
|
47
|
+
const checks = [];
|
|
48
|
+
// Server-level (once): initialize advertises the mandatory document-sync capability.
|
|
49
|
+
checks.push({
|
|
50
|
+
title: 'initialize advertises the baseline document-sync capability (textDocumentSync)',
|
|
51
|
+
body: async () => {
|
|
52
|
+
const driver = await connect();
|
|
53
|
+
try {
|
|
54
|
+
const result = await driver.initialize();
|
|
55
|
+
assert.notStrictEqual(result.capabilities.textDocumentSync, undefined, 'initialize did not advertise textDocumentSync');
|
|
56
|
+
}
|
|
57
|
+
finally {
|
|
58
|
+
driver.dispose();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
// Server-level (once): the `completionProvider` advertisement, on the same
|
|
63
|
+
// opt-in gate as the functional completion check below.
|
|
64
|
+
const completionOptedIn = options.languages.some(language => language.completionPosition !== undefined);
|
|
65
|
+
if (completionOptedIn) {
|
|
66
|
+
checks.push({
|
|
67
|
+
title: 'initialize advertises completionProvider (completion opted in)',
|
|
68
|
+
body: async () => {
|
|
69
|
+
const driver = await connect();
|
|
70
|
+
try {
|
|
71
|
+
const result = await driver.initialize();
|
|
72
|
+
assert.notStrictEqual(result.capabilities.completionProvider, undefined, 'initialize did not advertise completionProvider');
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
driver.dispose();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
checks.push({
|
|
82
|
+
title: 'initialize advertises completionProvider (completion opted in)',
|
|
83
|
+
skipReason: 'no fixture supplied a completionPosition (completion is opt-in)'
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
// Server-level (once): shutdown resolves.
|
|
87
|
+
checks.push({
|
|
88
|
+
title: 'shutdown resolves cleanly',
|
|
89
|
+
body: async () => {
|
|
90
|
+
const driver = await connect();
|
|
91
|
+
try {
|
|
92
|
+
await driver.initialize();
|
|
93
|
+
await driver.shutdown();
|
|
94
|
+
}
|
|
95
|
+
finally {
|
|
96
|
+
driver.dispose();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
for (const language of options.languages) {
|
|
101
|
+
const { valid, invalid, completionPosition } = language;
|
|
102
|
+
const tag = `[${valid.languageId}]`;
|
|
103
|
+
checks.push({
|
|
104
|
+
title: `didOpen(valid) publishes empty diagnostics ${tag}`,
|
|
105
|
+
body: async () => {
|
|
106
|
+
const driver = await connect();
|
|
107
|
+
try {
|
|
108
|
+
await driver.initialize();
|
|
109
|
+
// Resolved AFTER `connect` + `initialize`, so a deferred fixture
|
|
110
|
+
// may name a workspace this check's driver just brought up.
|
|
111
|
+
const model = resolveModel(valid);
|
|
112
|
+
const diagnostics = driver.nextDiagnostics(model.uri);
|
|
113
|
+
driver.openDocument(model.uri, model.text, model.languageId);
|
|
114
|
+
assert.deepStrictEqual(await diagnostics, []);
|
|
115
|
+
}
|
|
116
|
+
finally {
|
|
117
|
+
driver.dispose();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
});
|
|
121
|
+
checks.push({
|
|
122
|
+
title: `didOpen(invalid) publishes at least one diagnostic, each with a message ${tag}`,
|
|
123
|
+
body: async () => {
|
|
124
|
+
const driver = await connect();
|
|
125
|
+
try {
|
|
126
|
+
await driver.initialize();
|
|
127
|
+
const model = resolveModel(invalid);
|
|
128
|
+
const diagnostics = driver.nextDiagnostics(model.uri);
|
|
129
|
+
driver.openDocument(model.uri, model.text, model.languageId);
|
|
130
|
+
const published = await diagnostics;
|
|
131
|
+
assert.ok(published.length >= 1, 'didOpen(invalid) published no diagnostics');
|
|
132
|
+
assert.ok(published.every(hasTextMessage), 'a published diagnostic was missing a message');
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
driver.dispose();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
checks.push({
|
|
140
|
+
title: `didChange(valid → invalid) re-publishes at least one diagnostic ${tag}`,
|
|
141
|
+
body: async () => {
|
|
142
|
+
const driver = await connect();
|
|
143
|
+
try {
|
|
144
|
+
await driver.initialize();
|
|
145
|
+
const model = resolveModel(valid);
|
|
146
|
+
const initial = driver.nextDiagnostics(model.uri);
|
|
147
|
+
driver.openDocument(model.uri, model.text, model.languageId);
|
|
148
|
+
await initial;
|
|
149
|
+
const reDiagnosed = driver.nextDiagnostics(model.uri);
|
|
150
|
+
driver.changeDocument(model.uri, resolveDeferred(invalid.text), CHANGED_VERSION);
|
|
151
|
+
assert.ok((await reDiagnosed).length >= 1, 'didChange(valid → invalid) re-published no diagnostics');
|
|
152
|
+
}
|
|
153
|
+
finally {
|
|
154
|
+
driver.dispose();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
// Opt-in: completion runs only when the fixture supplies a position.
|
|
159
|
+
if (completionPosition) {
|
|
160
|
+
checks.push({
|
|
161
|
+
title: `completion answers with a well-formed item list ${tag}`,
|
|
162
|
+
body: async () => {
|
|
163
|
+
const driver = await connect();
|
|
164
|
+
try {
|
|
165
|
+
await driver.initialize();
|
|
166
|
+
const model = resolveModel(valid);
|
|
167
|
+
const diagnostics = driver.nextDiagnostics(model.uri);
|
|
168
|
+
driver.openDocument(model.uri, model.text, model.languageId);
|
|
169
|
+
await diagnostics;
|
|
170
|
+
const { items } = await driver.completion(model.uri, completionPosition);
|
|
171
|
+
assert.ok(Array.isArray(items), 'completion did not return an items array');
|
|
172
|
+
// Supplying a `completionPosition` IS the claim that
|
|
173
|
+
// completion answers there, so an empty list is a failure
|
|
174
|
+
// rather than a vacuous pass. `items` is already typed as a
|
|
175
|
+
// list and the driver normalises to one, so the bare
|
|
176
|
+
// `Array.isArray` this replaced could not fail at all.
|
|
177
|
+
assert.ok(items.length > 0, 'completion returned no items at the position the fixture opted in with');
|
|
178
|
+
for (const item of items) {
|
|
179
|
+
const label = item.label;
|
|
180
|
+
assert.ok(typeof label === 'string' && label.length > 0, `completion returned an item with no label: ${JSON.stringify(item)}`);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
finally {
|
|
184
|
+
driver.dispose();
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
checks.push({
|
|
191
|
+
title: `completion answers with a well-formed item list ${tag}`,
|
|
192
|
+
skipReason: 'fixture supplied no completionPosition'
|
|
193
|
+
});
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return checks;
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/lsp/index.ts"],"names":[],"mappings":"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"}
|
package/lib/model.d.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
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
|
+
* A fixture value that may be given directly or DEFERRED to check time.
|
|
11
|
+
*
|
|
12
|
+
* Fixtures are written as literals at module load, but some values are not
|
|
13
|
+
* knowable then. The driving case: a grammar whose valid model needs a
|
|
14
|
+
* MANDATORY cross-document reference cannot be self-contained, so its URI has
|
|
15
|
+
* to sit inside a booted workspace — and if the adopter wants pristine input
|
|
16
|
+
* per check, the workspace root does not exist until `connect` runs. A thunk
|
|
17
|
+
* moves the read to the point where it can succeed.
|
|
18
|
+
*
|
|
19
|
+
* Resolved once per check via {@link resolveModel}, never at suite-build time,
|
|
20
|
+
* so a thunk may safely read state that `connect` just established. `languageId`
|
|
21
|
+
* is deliberately NOT deferrable — it is read while building check titles, i.e.
|
|
22
|
+
* before any driver exists.
|
|
23
|
+
*/
|
|
24
|
+
export type Deferred<T> = T | (() => T);
|
|
25
|
+
/**
|
|
26
|
+
* A single model document an adopter supplies to the conformance kit: a URI,
|
|
27
|
+
* the language id the server registered the grammar under, and the model
|
|
28
|
+
* text. Head-agnostic — the SAME `valid` / `invalid` pair feeds the
|
|
29
|
+
* data-server slice (in the RPC envelope) and the LSP slice (over the
|
|
30
|
+
* `didOpen` wire); no head's wire types appear here.
|
|
31
|
+
*
|
|
32
|
+
* `uri` and `text` accept a {@link Deferred} thunk; `languageId` does not (see
|
|
33
|
+
* there for why). Read through {@link resolveModel} rather than field-by-field,
|
|
34
|
+
* so one check sees one consistent set of values.
|
|
35
|
+
*/
|
|
36
|
+
export interface ConformanceModel {
|
|
37
|
+
readonly uri: Deferred<string>;
|
|
38
|
+
readonly languageId: string;
|
|
39
|
+
readonly text: Deferred<string>;
|
|
40
|
+
}
|
|
41
|
+
/** A {@link ConformanceModel} with every {@link Deferred} field already read. */
|
|
42
|
+
export interface ResolvedConformanceModel {
|
|
43
|
+
readonly uri: string;
|
|
44
|
+
readonly languageId: string;
|
|
45
|
+
readonly text: string;
|
|
46
|
+
}
|
|
47
|
+
/** Read a possibly-deferred fixture value. */
|
|
48
|
+
export declare function resolveDeferred<T>(value: Deferred<T>): T;
|
|
49
|
+
/**
|
|
50
|
+
* Read a fixture model's deferred fields, ONCE, at the top of a check body.
|
|
51
|
+
*
|
|
52
|
+
* Resolving the whole model rather than each field at its use site is the point:
|
|
53
|
+
* a thunk may legitimately return a different value on a later check (that is
|
|
54
|
+
* what makes per-check pristine input possible), so a check that re-read `uri`
|
|
55
|
+
* mid-body could act on two different documents.
|
|
56
|
+
*/
|
|
57
|
+
export declare function resolveModel(model: ConformanceModel): ResolvedConformanceModel;
|
|
58
|
+
/**
|
|
59
|
+
* An edit applied to a fixture's document, plus the adopter's grammar-aware
|
|
60
|
+
* assertion that the edit took effect. `to` is the replacement model text;
|
|
61
|
+
* `expect` receives the post-edit transfer/AST root (typed `unknown` because
|
|
62
|
+
* the kit owns no grammar) and returns whether the edit is observable — only
|
|
63
|
+
* the adopter knows what "the edit landed" means for its grammar.
|
|
64
|
+
*/
|
|
65
|
+
export interface EditSpec {
|
|
66
|
+
/** Replacement model text; {@link Deferred} for the same reasons as `ConformanceModel.text`. */
|
|
67
|
+
readonly to: Deferred<string>;
|
|
68
|
+
readonly expect: (root: unknown) => boolean;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* The per-language fixture. `valid` and `invalid` are defined once and reused
|
|
72
|
+
* across heads; the two extras are per-head opt-ins.
|
|
73
|
+
*
|
|
74
|
+
* Requiring BOTH a valid and an invalid model is the false-green guard — a
|
|
75
|
+
* vacuous "invalid" model that actually parses clean fails the diagnostics
|
|
76
|
+
* checks rather than passing silently.
|
|
77
|
+
*
|
|
78
|
+
* **Which slice reads which field.** The type cannot express this, so it is
|
|
79
|
+
* stated here:
|
|
80
|
+
*
|
|
81
|
+
* - `valid` / `invalid` — read by every slice.
|
|
82
|
+
* - `edit` — read by the **data slice only**. The LSP slice's didChange check
|
|
83
|
+
* uses `invalid.text` and never calls `edit.expect`, so an LSP-only adopter
|
|
84
|
+
* has nothing to supply here.
|
|
85
|
+
* - `completionPosition` — read by the **LSP slice only**.
|
|
86
|
+
*
|
|
87
|
+
* Both extras are optional and their checks report *skipped* when absent,
|
|
88
|
+
* rather than silently not running. Making either mandatory would defeat the
|
|
89
|
+
* shared fixture: the head that ignores the field has to invent a value for it,
|
|
90
|
+
* and the two heads' inventions drift apart until one fixture contradicts the
|
|
91
|
+
* other. A required field that one head ignores does not produce a shared
|
|
92
|
+
* fixture; it produces a misleading one.
|
|
93
|
+
*
|
|
94
|
+
* The GLSP fixture is separate (per-diagram-type, generic over the adopter
|
|
95
|
+
* action type) — see `./glsp`.
|
|
96
|
+
*/
|
|
97
|
+
export interface LanguageFixture {
|
|
98
|
+
readonly valid: ConformanceModel;
|
|
99
|
+
readonly invalid: ConformanceModel;
|
|
100
|
+
/**
|
|
101
|
+
* Optional: an edit plus its observability assertion. The data slice's
|
|
102
|
+
* round-trip and subscription-delivery checks run only when it is supplied.
|
|
103
|
+
*/
|
|
104
|
+
readonly edit?: EditSpec;
|
|
105
|
+
/** Optional: a position at which the LSP completion check requests completion. */
|
|
106
|
+
readonly completionPosition?: {
|
|
107
|
+
readonly line: number;
|
|
108
|
+
readonly character: number;
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=model.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.d.ts","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF;;;;;;;;;;;;;;GAcG;AACH,MAAM,MAAM,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AAExC;;;;;;;;;;GAUG;AACH,MAAM,WAAW,gBAAgB;IAC9B,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAClC;AAED,iFAAiF;AACjF,MAAM,WAAW,wBAAwB;IACtC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACxB;AAED,8CAA8C;AAC9C,wBAAgB,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAExD;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,gBAAgB,GAAG,wBAAwB,CAM9E;AAED;;;;;;GAMG;AACH,MAAM,WAAW,QAAQ;IACtB,gGAAgG;IAChG,QAAQ,CAAC,EAAE,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC;CAC9C;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,WAAW,eAAe;IAC7B,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IACnC;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,EAAE,QAAQ,CAAC;IACzB,kFAAkF;IAClF,QAAQ,CAAC,kBAAkB,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;CACtF"}
|
package/lib/model.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
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
|
+
/** Read a possibly-deferred fixture value. */
|
|
10
|
+
export function resolveDeferred(value) {
|
|
11
|
+
return typeof value === 'function' ? value() : value;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Read a fixture model's deferred fields, ONCE, at the top of a check body.
|
|
15
|
+
*
|
|
16
|
+
* Resolving the whole model rather than each field at its use site is the point:
|
|
17
|
+
* a thunk may legitimately return a different value on a later check (that is
|
|
18
|
+
* what makes per-check pristine input possible), so a check that re-read `uri`
|
|
19
|
+
* mid-body could act on two different documents.
|
|
20
|
+
*/
|
|
21
|
+
export function resolveModel(model) {
|
|
22
|
+
return {
|
|
23
|
+
uri: resolveDeferred(model.uri),
|
|
24
|
+
languageId: model.languageId,
|
|
25
|
+
text: resolveDeferred(model.text)
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=model.js.map
|
package/lib/model.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model.js","sourceRoot":"","sources":["../src/model.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AA2ClF,8CAA8C;AAC9C,MAAM,UAAU,eAAe,CAAI,KAAkB;IAClD,OAAO,OAAO,KAAK,KAAK,UAAU,CAAC,CAAC,CAAE,KAAiB,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;AACrE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,KAAuB;IACjD,OAAO;QACJ,GAAG,EAAE,eAAe,CAAC,KAAK,CAAC,GAAG,CAAC;QAC/B,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,IAAI,EAAE,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC;KACnC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
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
|
+
* The Vitest adapter for `@hydranium/conformance` — the Vitest sibling of the
|
|
11
|
+
* `@hydranium/conformance/jest` adapter. It binds Vitest's `describe` / `it` /
|
|
12
|
+
* `it.skip` / `afterAll` to the runner-agnostic {@link ConformanceRunner} port
|
|
13
|
+
* and exposes the `run{Data,Lsp,Glsp}Conformance` entry points an
|
|
14
|
+
* adopter-on-Vitest calls, each building its slice's pure check list and
|
|
15
|
+
* emitting it through the bound runner. The core (`.` / `/data` / `/lsp` /
|
|
16
|
+
* `/glsp`) imports no runner and asserts with `node:assert`; the
|
|
17
|
+
* `@hydranium/conformance/jest` sibling is this same binding against Jest's
|
|
18
|
+
* globals.
|
|
19
|
+
*
|
|
20
|
+
* Adopters import the `run*` functions AND the slice types from here, so a
|
|
21
|
+
* Vitest-based suite needs a single import site.
|
|
22
|
+
*/
|
|
23
|
+
import type { TransferDiagnostic, TransferElement } from '@hydranium/protocol';
|
|
24
|
+
import { type DataConformanceOptions } from '../data/index.js';
|
|
25
|
+
import { type LspConformanceOptions } from '../lsp/index.js';
|
|
26
|
+
import { type GlspConformanceDriver, type GlspConformanceOptions } from '../glsp/index.js';
|
|
27
|
+
export type { DataConformanceDriver, DataConformanceOptions } from '../data/index.js';
|
|
28
|
+
export type { LspConformanceCompletionList, LspConformanceDiagnostic, LspConformanceDriver, LspConformanceInitializeResult, LspConformanceOptions } from '../lsp/index.js';
|
|
29
|
+
export type { GlspConformanceDriver, GlspConformanceOptions, GlspCreateOperationSpec, GlspFixture } from '../glsp/index.js';
|
|
30
|
+
/**
|
|
31
|
+
* Run the data-server conformance battery against an adopter's live server
|
|
32
|
+
* under Vitest. Emits a `describe` with one `it` per check (server-level once,
|
|
33
|
+
* grammar-bearing per language) and a ran-vs-skipped summary.
|
|
34
|
+
*/
|
|
35
|
+
export declare function runDataConformance<TTransfer extends TransferElement, TDiagnostic extends TransferDiagnostic = TransferDiagnostic>(options: DataConformanceOptions<TTransfer, TDiagnostic>): void;
|
|
36
|
+
/**
|
|
37
|
+
* Run the LSP conformance battery against an adopter's live server under Vitest.
|
|
38
|
+
* Emits a `describe` with one `it` per check (server-level once, grammar-bearing
|
|
39
|
+
* per language) and a ran-vs-skipped summary.
|
|
40
|
+
*/
|
|
41
|
+
export declare function runLspConformance(options: LspConformanceOptions): void;
|
|
42
|
+
/**
|
|
43
|
+
* Run the GLSP conformance battery against an adopter's live diagram server
|
|
44
|
+
* under Vitest. Emits a `describe` with one `it` per check (per diagram type)
|
|
45
|
+
* and a ran-vs-skipped summary.
|
|
46
|
+
*/
|
|
47
|
+
export declare function runGlspConformance<TAction, TDriver extends GlspConformanceDriver<TAction>>(options: GlspConformanceOptions<TAction, TDriver>): void;
|
|
48
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vitest/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAG/E,OAAO,EAAmB,KAAK,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAChF,OAAO,EAAkB,KAAK,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAC7E,OAAO,EAAmB,KAAK,qBAAqB,EAAE,KAAK,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAI5G,YAAY,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AACtF,YAAY,EACT,4BAA4B,EAC5B,wBAAwB,EACxB,oBAAoB,EACpB,8BAA8B,EAC9B,qBAAqB,EACvB,MAAM,iBAAiB,CAAC;AACzB,YAAY,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,uBAAuB,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAU5H;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,SAAS,SAAS,eAAe,EAAE,WAAW,SAAS,kBAAkB,GAAG,kBAAkB,EAC9H,OAAO,EAAE,sBAAsB,CAAC,SAAS,EAAE,WAAW,CAAC,GACvD,IAAI,CAEN;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,qBAAqB,GAAG,IAAI,CAEtE;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,SAAS,qBAAqB,CAAC,OAAO,CAAC,EACvF,OAAO,EAAE,sBAAsB,CAAC,OAAO,EAAE,OAAO,CAAC,GACjD,IAAI,CAEN"}
|
|
@@ -0,0 +1,45 @@
|
|
|
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
|
+
import { afterAll, describe, it } from 'vitest';
|
|
10
|
+
import { emitConformanceSuite } from '../conformance-suite.js';
|
|
11
|
+
import { buildDataChecks } from '../data/index.js';
|
|
12
|
+
import { buildLspChecks } from '../lsp/index.js';
|
|
13
|
+
import { buildGlspChecks } from '../glsp/index.js';
|
|
14
|
+
/** Vitest bound to the kit's runner-agnostic {@link ConformanceRunner} port. */
|
|
15
|
+
const vitestRunner = {
|
|
16
|
+
describe: (name, register) => describe(name, register),
|
|
17
|
+
test: (name, body) => it(name, body),
|
|
18
|
+
skip: name => it.skip(name, () => undefined),
|
|
19
|
+
afterAll: fn => afterAll(fn)
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Run the data-server conformance battery against an adopter's live server
|
|
23
|
+
* under Vitest. Emits a `describe` with one `it` per check (server-level once,
|
|
24
|
+
* grammar-bearing per language) and a ran-vs-skipped summary.
|
|
25
|
+
*/
|
|
26
|
+
export function runDataConformance(options) {
|
|
27
|
+
emitConformanceSuite(vitestRunner, options.suiteTitle ?? 'conformance: data-server', buildDataChecks(options));
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Run the LSP conformance battery against an adopter's live server under Vitest.
|
|
31
|
+
* Emits a `describe` with one `it` per check (server-level once, grammar-bearing
|
|
32
|
+
* per language) and a ran-vs-skipped summary.
|
|
33
|
+
*/
|
|
34
|
+
export function runLspConformance(options) {
|
|
35
|
+
emitConformanceSuite(vitestRunner, options.suiteTitle ?? 'conformance: lsp', buildLspChecks(options));
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Run the GLSP conformance battery against an adopter's live diagram server
|
|
39
|
+
* under Vitest. Emits a `describe` with one `it` per check (per diagram type)
|
|
40
|
+
* and a ran-vs-skipped summary.
|
|
41
|
+
*/
|
|
42
|
+
export function runGlspConformance(options) {
|
|
43
|
+
emitConformanceSuite(vitestRunner, options.suiteTitle ?? 'conformance: glsp', buildGlspChecks(options));
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vitest/index.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAkBlF,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAC;AAChD,OAAO,EAA0B,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACvF,OAAO,EAAE,eAAe,EAA+B,MAAM,kBAAkB,CAAC;AAChF,OAAO,EAAE,cAAc,EAA8B,MAAM,iBAAiB,CAAC;AAC7E,OAAO,EAAE,eAAe,EAA2D,MAAM,kBAAkB,CAAC;AAc5G,gFAAgF;AAChF,MAAM,YAAY,GAAsB;IACrC,QAAQ,EAAE,CAAC,IAAI,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IACtD,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;IACpC,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS,CAAC;IAC5C,QAAQ,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC;CAC9B,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAC/B,OAAuD;IAEvD,oBAAoB,CAAC,YAAY,EAAE,OAAO,CAAC,UAAU,IAAI,0BAA0B,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;AAClH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAA8B;IAC7D,oBAAoB,CAAC,YAAY,EAAE,OAAO,CAAC,UAAU,IAAI,kBAAkB,EAAE,cAAc,CAAC,OAAO,CAAC,CAAC,CAAC;AACzG,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAC/B,OAAiD;IAEjD,oBAAoB,CAAC,YAAY,EAAE,OAAO,CAAC,UAAU,IAAI,mBAAmB,EAAE,eAAe,CAAC,OAAO,CAAC,CAAC,CAAC;AAC3G,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hydranium/conformance",
|
|
3
|
+
"version": "1.0.0-next.10",
|
|
4
|
+
"description": "Protocol conformance kit (TCK) for hydranium adopters. Per-head slices (/data, /lsp, /glsp) of fixture-parameterized, protocol-only smoke checks an adopter runs against its own server.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"hydranium",
|
|
7
|
+
"langium",
|
|
8
|
+
"language-server",
|
|
9
|
+
"lsp",
|
|
10
|
+
"testing",
|
|
11
|
+
"conformance"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/eclipse-emfcloud/hydranium/tree/main/packages/conformance",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/eclipse-emfcloud/hydranium/issues"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/eclipse-emfcloud/hydranium.git",
|
|
20
|
+
"directory": "packages/conformance"
|
|
21
|
+
},
|
|
22
|
+
"license": "MIT",
|
|
23
|
+
"author": {
|
|
24
|
+
"name": "Hydranium Team"
|
|
25
|
+
},
|
|
26
|
+
"sideEffects": false,
|
|
27
|
+
"type": "module",
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./lib/index.d.ts",
|
|
31
|
+
"default": "./lib/index.js"
|
|
32
|
+
},
|
|
33
|
+
"./data": {
|
|
34
|
+
"types": "./lib/data/index.d.ts",
|
|
35
|
+
"default": "./lib/data/index.js"
|
|
36
|
+
},
|
|
37
|
+
"./lib/data": {
|
|
38
|
+
"types": "./lib/data/index.d.ts",
|
|
39
|
+
"default": "./lib/data/index.js"
|
|
40
|
+
},
|
|
41
|
+
"./lsp": {
|
|
42
|
+
"types": "./lib/lsp/index.d.ts",
|
|
43
|
+
"default": "./lib/lsp/index.js"
|
|
44
|
+
},
|
|
45
|
+
"./lib/lsp": {
|
|
46
|
+
"types": "./lib/lsp/index.d.ts",
|
|
47
|
+
"default": "./lib/lsp/index.js"
|
|
48
|
+
},
|
|
49
|
+
"./glsp": {
|
|
50
|
+
"types": "./lib/glsp/index.d.ts",
|
|
51
|
+
"default": "./lib/glsp/index.js"
|
|
52
|
+
},
|
|
53
|
+
"./lib/glsp": {
|
|
54
|
+
"types": "./lib/glsp/index.d.ts",
|
|
55
|
+
"default": "./lib/glsp/index.js"
|
|
56
|
+
},
|
|
57
|
+
"./jest": {
|
|
58
|
+
"types": "./lib/jest/index.d.ts",
|
|
59
|
+
"default": "./lib/jest/index.js"
|
|
60
|
+
},
|
|
61
|
+
"./lib/jest": {
|
|
62
|
+
"types": "./lib/jest/index.d.ts",
|
|
63
|
+
"default": "./lib/jest/index.js"
|
|
64
|
+
},
|
|
65
|
+
"./vitest": {
|
|
66
|
+
"types": "./lib/vitest/index.d.ts",
|
|
67
|
+
"default": "./lib/vitest/index.js"
|
|
68
|
+
},
|
|
69
|
+
"./lib/vitest": {
|
|
70
|
+
"types": "./lib/vitest/index.d.ts",
|
|
71
|
+
"default": "./lib/vitest/index.js"
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
"main": "lib/index.js",
|
|
75
|
+
"types": "lib/index.d.ts",
|
|
76
|
+
"files": [
|
|
77
|
+
"lib",
|
|
78
|
+
"src",
|
|
79
|
+
"!lib/**/*.tsbuildinfo"
|
|
80
|
+
],
|
|
81
|
+
"scripts": {
|
|
82
|
+
"build": "tsc -b",
|
|
83
|
+
"clean": "rimraf lib tsconfig.tsbuildinfo",
|
|
84
|
+
"lint": "eslint src test --max-warnings 0",
|
|
85
|
+
"prepack": "node -e \"const m=require('./package.json'),fs=require('node:fs');const missing=[m.main,...Object.values(m.bin||{})].filter(entry=>entry&&!fs.existsSync(entry));if(missing.length){console.error('prepack '+m.name+': not built ('+missing.join(', ')+' missing). Run the build before packing: a files entry that matches nothing is skipped silently, so the tarball would ship src only.');process.exit(1);}\"",
|
|
86
|
+
"test": "npm run typecheck:test && vitest run && cross-env NODE_OPTIONS=--experimental-vm-modules NODE_NO_WARNINGS=1 jest",
|
|
87
|
+
"typecheck:test": "tsc --noEmit -p tsconfig.test.json",
|
|
88
|
+
"watch": "tsc -b -w --preserveWatchOutput"
|
|
89
|
+
},
|
|
90
|
+
"devDependencies": {
|
|
91
|
+
"@hydranium/protocol": "1.0.0-next.10",
|
|
92
|
+
"@jest/globals": "^29.7.0",
|
|
93
|
+
"@types/jest": "^29.5.12",
|
|
94
|
+
"jest": "^29.7.0",
|
|
95
|
+
"rimraf": "^5.0.0",
|
|
96
|
+
"ts-jest": "^29.2.0",
|
|
97
|
+
"typescript": "^5.8.0",
|
|
98
|
+
"vitest": "^4.0.0"
|
|
99
|
+
},
|
|
100
|
+
"peerDependencies": {
|
|
101
|
+
"@hydranium/protocol": "1.0.0-next.10",
|
|
102
|
+
"@jest/globals": "^29.0.0",
|
|
103
|
+
"vitest": "^4.0.0"
|
|
104
|
+
},
|
|
105
|
+
"peerDependenciesMeta": {
|
|
106
|
+
"@jest/globals": {
|
|
107
|
+
"optional": true
|
|
108
|
+
},
|
|
109
|
+
"vitest": {
|
|
110
|
+
"optional": true
|
|
111
|
+
}
|
|
112
|
+
},
|
|
113
|
+
"engines": {
|
|
114
|
+
"node": ">=22.13"
|
|
115
|
+
},
|
|
116
|
+
"publishConfig": {
|
|
117
|
+
"access": "public"
|
|
118
|
+
},
|
|
119
|
+
"//prepack": "The publish guard, and it deliberately is NOT a `prepare`: npm runs a workspace `prepare` BEFORE the root `postinstall` that applies patches/vscode-jsonrpc+9.0.1.patch, so building there fails on a cold clone and npm rolls the entire install back. `prepack` runs only when a tarball is made (`npm pack`, `npm publish`) and never on install, so it cannot break the install it has no business touching. It FAILS rather than rebuilds, because the rebuild is exactly the part that ordering defeats. What it defends against: `files` lists `lib`, `lib` is gitignored, and a `files` entry matching nothing is skipped SILENTLY — so `npm publish` from an unbuilt tree emits a tarball of `src` and nothing else, with no error."
|
|
120
|
+
}
|