@hydranium/core 1.0.0-next.95 → 1.0.0-next.97

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/lib/index.d.ts +1 -0
  2. package/lib/index.d.ts.map +1 -1
  3. package/lib/index.js +1 -0
  4. package/lib/index.js.map +1 -1
  5. package/lib/langium/integrity/integrity-service.d.ts.map +1 -1
  6. package/lib/langium/integrity/integrity-service.js +8 -1
  7. package/lib/langium/integrity/integrity-service.js.map +1 -1
  8. package/lib/langium/language-module.d.ts +25 -0
  9. package/lib/langium/language-module.d.ts.map +1 -1
  10. package/lib/langium/language-module.js +14 -0
  11. package/lib/langium/language-module.js.map +1 -1
  12. package/lib/langium/model-service/model-service.d.ts +30 -18
  13. package/lib/langium/model-service/model-service.d.ts.map +1 -1
  14. package/lib/langium/model-service/model-service.js +41 -1
  15. package/lib/langium/model-service/model-service.js.map +1 -1
  16. package/lib/langium/residency/cst-residency-service.d.ts +4 -6
  17. package/lib/langium/residency/cst-residency-service.d.ts.map +1 -1
  18. package/lib/langium/residency/cst-residency-service.js.map +1 -1
  19. package/lib/langium/serialization/abstract-serializer.d.ts +11 -20
  20. package/lib/langium/serialization/abstract-serializer.d.ts.map +1 -1
  21. package/lib/langium/serialization/abstract-serializer.js +12 -21
  22. package/lib/langium/serialization/abstract-serializer.js.map +1 -1
  23. package/lib/langium/trivia/comment-preserver.d.ts +423 -0
  24. package/lib/langium/trivia/comment-preserver.d.ts.map +1 -0
  25. package/lib/langium/trivia/comment-preserver.js +906 -0
  26. package/lib/langium/trivia/comment-preserver.js.map +1 -0
  27. package/lib/langium/trivia/document-ending-preserver.d.ts +43 -0
  28. package/lib/langium/trivia/document-ending-preserver.d.ts.map +1 -0
  29. package/lib/langium/trivia/document-ending-preserver.js +48 -0
  30. package/lib/langium/trivia/document-ending-preserver.js.map +1 -0
  31. package/lib/langium/trivia/index.d.ts +14 -0
  32. package/lib/langium/trivia/index.d.ts.map +1 -0
  33. package/lib/langium/trivia/index.js +14 -0
  34. package/lib/langium/trivia/index.js.map +1 -0
  35. package/lib/langium/trivia/trivia-contribution.d.ts +37 -0
  36. package/lib/langium/trivia/trivia-contribution.d.ts.map +1 -0
  37. package/lib/langium/trivia/trivia-contribution.js +10 -0
  38. package/lib/langium/trivia/trivia-contribution.js.map +1 -0
  39. package/lib/langium/trivia/trivia-preserver.d.ts +50 -0
  40. package/lib/langium/trivia/trivia-preserver.d.ts.map +1 -0
  41. package/lib/langium/trivia/trivia-preserver.js +10 -0
  42. package/lib/langium/trivia/trivia-preserver.js.map +1 -0
  43. package/lib/langium/trivia/trivia-service.d.ts +70 -0
  44. package/lib/langium/trivia/trivia-service.d.ts.map +1 -0
  45. package/lib/langium/trivia/trivia-service.js +56 -0
  46. package/lib/langium/trivia/trivia-service.js.map +1 -0
  47. package/lib/testing/node/scratch-workspace.js +2 -2
  48. package/package.json +5 -5
  49. package/src/index.ts +1 -0
  50. package/src/langium/integrity/integrity-service.ts +9 -1
  51. package/src/langium/language-module.ts +38 -0
  52. package/src/langium/model-service/model-service.ts +58 -19
  53. package/src/langium/residency/cst-residency-service.ts +4 -6
  54. package/src/langium/serialization/abstract-serializer.ts +13 -32
  55. package/src/langium/trivia/comment-preserver.ts +1100 -0
  56. package/src/langium/trivia/document-ending-preserver.ts +55 -0
  57. package/src/langium/trivia/index.ts +14 -0
  58. package/src/langium/trivia/trivia-contribution.ts +39 -0
  59. package/src/langium/trivia/trivia-preserver.ts +54 -0
  60. package/src/langium/trivia/trivia-service.ts +99 -0
  61. package/src/testing/node/scratch-workspace.ts +2 -2
@@ -6,7 +6,6 @@
6
6
  *
7
7
  * SPDX-License-Identifier: MIT
8
8
  ********************************************************************************/
9
- import { isPromiseLike } from '@hydranium/protocol';
10
9
  import { isAstNode } from '@hydranium/langium';
11
10
  import { isDefaultValue, isReferenceProperty } from './serialization-util.js';
12
11
  function isRefTextObject(value) {
@@ -69,28 +68,20 @@ export class AbstractSerializer {
69
68
  * Entry point for AST-shape inputs. Typically the grammar root, but any
70
69
  * AST node works — the walker is recursive and shape-agnostic.
71
70
  *
72
- * Preserves the sync fast path: when every subclass override and every
73
- * adopter hook is sync, the return is a bare `string` (no Promise
74
- * allocation, no microtask). The async branch fires only if at least one
75
- * recursive `serializeNode` call resolved to a Promise.
71
+ * **Emits the model and nothing else — do not trim here.** Trailing
72
+ * whitespace belongs to the author, and a write path holding the prior
73
+ * document restores it from there; trimming at this end deletes it before
74
+ * that restore sees it. A serializer has no prior document to consult, so it
75
+ * cannot tell a deliberate blank line from an accidental one.
76
+ *
77
+ * **Nothing trims what a subclass emits**, at either end. Emitting leading
78
+ * whitespace therefore puts it in the file, where no write path removes it.
79
+ *
80
+ * Returns whatever `serializeNode` returns, so a fully sync subclass keeps a
81
+ * bare `string` with no promise allocation.
76
82
  */
77
83
  serializeAst(model) {
78
- const result = this.serializeNode(model, 0);
79
- if (isPromiseLike(result)) {
80
- return result.then(text => this.trimSerialized(text));
81
- }
82
- return this.trimSerialized(result);
83
- }
84
- /**
85
- * Trim the final serialized output. Leading whitespace is always removed;
86
- * trailing whitespace is removed unless {@link AbstractSerializerOptions.trimTrailingWhitespace}
87
- * is `false` (which preserves document-ending blank lines, e.g. inside a block scalar).
88
- */
89
- trimSerialized(text) {
90
- if (text === undefined) {
91
- return '';
92
- }
93
- return this.options.trimTrailingWhitespace === false ? text.trimStart() : text.trim();
84
+ return this.serializeNode(model, 0);
94
85
  }
95
86
  /**
96
87
  * Entry point for transfer-model-shape inputs (cross-references as plain
@@ -1 +1 @@
1
- {"version":3,"file":"abstract-serializer.js","sourceRoot":"","sources":["../../../src/langium/serialization/abstract-serializer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"abstract-serializer.js","sourceRoot":"","sources":["../../../src/langium/serialization/abstract-serializer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,423 @@
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 { type Tracer } from '@hydranium/protocol';
10
+ import { type AstNode, type CompositeCstNode, type CstNode, type LangiumDocument, type URI } from '@hydranium/langium';
11
+ import { type LogNameOptions } from '../diagnostics/logger.js';
12
+ import { type HydraniumLanguageServices } from '../language-module.js';
13
+ import { type TriviaContribution, type TriviaRegistry } from './trivia-contribution.js';
14
+ import { type TriviaPreserver } from './trivia-preserver.js';
15
+ /**
16
+ * Where a comment sat relative to the node it belongs to.
17
+ *
18
+ * The CST records source order but not ownership, so getting this wrong
19
+ * relocates a comment rather than losing it.
20
+ *
21
+ * - `atContainerStart` — before everything the container holds.
22
+ * - `leading` — on its own line(s) above the node that follows it.
23
+ * - `trailing` — on the same line the previous node ended on.
24
+ * - `trailingOnContainer` — on the container's own header line, or amongst its
25
+ * syntax with more of the container still to come.
26
+ * - `afterNode` — on its own line after the last node, still inside the
27
+ * container.
28
+ * - `atContainerEnd` — after everything the container holds.
29
+ */
30
+ export type CommentPlacement = 'atContainerStart' | 'leading' | 'trailing' | 'trailingOnContainer' | 'afterNode' | 'atContainerEnd';
31
+ /** One comment, bound to the AST node it hangs off rather than to an offset. */
32
+ export interface DocumentComment {
33
+ /** The comment's source text, delimiters included. */
34
+ readonly text: string;
35
+ /**
36
+ * The node the comment hangs off, held as the AST OBJECT rather than a path
37
+ * or an offset, so a write that mutates the tree IN PLACE — an integrity
38
+ * repair, a diagram gesture — is reflected without re-extracting.
39
+ *
40
+ * A transfer-model write supplies a separate object graph. A unique rename
41
+ * can still be matched when its type, parent slot and other properties agree;
42
+ * ambiguous matches are dropped.
43
+ */
44
+ readonly anchor: AstNode;
45
+ readonly placement: CommentPlacement;
46
+ /**
47
+ * Blank lines between the comment and what it leads, for the placements that
48
+ * emit it BEFORE its anchor.
49
+ *
50
+ * Captured for the placements that emit it after as well, where nothing reads
51
+ * it: there the spacing an author means is the gap above the comment, which
52
+ * {@link blankLinesBefore} carries.
53
+ */
54
+ readonly blankLinesAfter: number;
55
+ /**
56
+ * Blank lines between the comment and what PRECEDES it, for the placements
57
+ * that emit it after their anchor. A comment separated from the closing brace
58
+ * above it by a blank line reads as a new thought; re-emitting it flush
59
+ * against that brace silently rewrites the author's spacing.
60
+ */
61
+ readonly blankLinesBefore: number;
62
+ /**
63
+ * The indentation the comment sat at in the source, when it owned its line —
64
+ * `undefined` for one sharing a line with code, which is never reindented.
65
+ *
66
+ * A MULTI-LINE comment needs it to shift its continuation lines, which carry
67
+ * their original indentation inside {@link text}: emitting the block at a new
68
+ * indentation without shifting them leaves it hanging off its old column.
69
+ *
70
+ * A single-line one needs it whenever its anchor turns out to share a line,
71
+ * because the indentation read off a mid-line offset is the code's and not
72
+ * the comment's.
73
+ */
74
+ readonly sourceIndent?: string;
75
+ }
76
+ /** What {@link CommentPreserver} takes off a document. */
77
+ export interface CommentTrivia {
78
+ readonly comments: readonly DocumentComment[];
79
+ /** Original tree, retained to detect ambiguous or removed anchors at apply time. */
80
+ readonly sourceRoot: AstNode;
81
+ }
82
+ /** Construction options for {@link CommentPreserver}. */
83
+ export interface CommentPreserverOptions extends LogNameOptions {
84
+ /**
85
+ * Registry id, defaulting to `comments`. Set it only to run a second comment
86
+ * preserver beside the framework's; a subclass that REPLACES it keeps the
87
+ * default so the contribution sub-key and the id stay in step.
88
+ */
89
+ readonly id?: string;
90
+ /**
91
+ * How many comments spliced into shared lines are worth blaming one at a
92
+ * time when the result will not parse. Default {@link DEFAULT_ISOLATED_EDITS}.
93
+ *
94
+ * Isolating means re-splicing and re-parsing the whole document once per
95
+ * candidate, so the search costs the document's length times their number.
96
+ * Past this many the write drops them together instead — the same text it
97
+ * would reach anyway if every one of them were at fault, without spending
98
+ * that search on a build's write lock.
99
+ */
100
+ readonly maxIsolatedEdits?: number;
101
+ }
102
+ /**
103
+ * Where a node begins and ends in the text it was located in, and which node
104
+ * that is.
105
+ *
106
+ * Exported because {@link CommentPreserver.editFor} takes one, and an override
107
+ * that cannot name its own parameter type has to restate the shape — which then
108
+ * stops compiling the moment a field is added here.
109
+ */
110
+ export interface AnchorSpan {
111
+ readonly offset: number;
112
+ readonly end: number;
113
+ readonly owner: AstNode;
114
+ }
115
+ /**
116
+ * One splice, with what it takes to check the risky kind afterwards.
117
+ *
118
+ * `inline` is set only for an edit that opens a line inside syntax the
119
+ * serializer emitted whole; it carries what the comment must look like when the
120
+ * result is read back, since that edit is the one that can hand a comment to
121
+ * the wrong declaration.
122
+ *
123
+ * Exported for the same reason {@link AnchorSpan} is: the members that take one
124
+ * are protected, so an override has to be able to name it.
125
+ */
126
+ export interface InlineAwareEdit {
127
+ readonly at: number;
128
+ readonly text: string;
129
+ /** Capture order, so several comments on one anchor keep the order written. */
130
+ readonly order: number;
131
+ readonly inline?: {
132
+ readonly text: string;
133
+ readonly key: string;
134
+ };
135
+ }
136
+ /**
137
+ * Carries a document's comments across a write that re-serializes it from the
138
+ * AST: extract against the node each comment hangs off, then splice into the
139
+ * serializer's output, located by re-parsing it.
140
+ *
141
+ * **Emitting comments from inside a serializer instead drops them silently for
142
+ * most nodes.** A hand-written concrete-syntax serializer reaches its children
143
+ * through its own per-`$type` emitters, not through
144
+ * `AbstractSerializer.serializeNode`, so a hook on that seam is reached by some
145
+ * nodes and bypassed by the rest — and the ones it misses fail as absence,
146
+ * which no test notices unless it asserts on exact text.
147
+ */
148
+ export declare class CommentPreserver implements TriviaPreserver<CommentTrivia> {
149
+ protected readonly services: HydraniumLanguageServices;
150
+ /**
151
+ * **Registering a second preserver under this id throws.** A subclass added
152
+ * ALONGSIDE the framework's — rather than replacing it by rebinding the
153
+ * `comments` contribution sub-key — collides here, and the throw surfaces
154
+ * from the first write rather than from server start, because the service is
155
+ * constructed lazily. Pass an `id` to run both.
156
+ */
157
+ readonly id: string;
158
+ readonly label = "Comments";
159
+ /** Default {@link CommentPreserverOptions.maxIsolatedEdits}. */
160
+ static readonly DEFAULT_ISOLATED_EDITS = 24;
161
+ protected readonly tracer: Tracer;
162
+ protected readonly maxIsolatedEdits: number;
163
+ protected commentTokenNames?: readonly string[];
164
+ /** Set for the duration of one {@link apply}; see {@link cachedAnchorKey}. */
165
+ protected keyMemo?: Map<AstNode, string | undefined>;
166
+ /** Set for the duration of one {@link apply}; see {@link ambiguousRetainedKey}. */
167
+ protected listVerdicts?: Map<AstNode, Map<string, boolean>>;
168
+ constructor(services: HydraniumLanguageServices, options?: CommentPreserverOptions);
169
+ /**
170
+ * Every comment terminal the grammar declares, by token name.
171
+ *
172
+ * Deliberately NOT `GrammarConfig.multilineCommentRules`, which Langium
173
+ * populates only with terminals whose regex spans lines — so a grammar that
174
+ * comments with `//` answers an empty list there and every one of its
175
+ * comments would be invisible to a capture keyed on it.
176
+ */
177
+ protected getCommentTokenNames(): readonly string[];
178
+ /**
179
+ * Stable identity for one AST node, used to find it again in the
180
+ * re-serialized text — or `undefined` when no stable identity exists.
181
+ *
182
+ * **Read through the `NameProvider`, so the anchor is what the grammar treats
183
+ * as IDENTITY rather than whatever sits on `name`.** A grammar whose `name`
184
+ * is a display label, carrying its identifier on another property, would
185
+ * otherwise anchor comments to a value users retitle freely. A simple
186
+ * retitle can be matched, but the real identifier remains the safer key.
187
+ * `NameProviderOptions.nameProperties` names that property.
188
+ *
189
+ * **Whatever an override returns must survive a sibling being inserted into
190
+ * the same list.** A positional key does not: every comment after the
191
+ * insertion point is then written against the following declaration — a move,
192
+ * which reads as text the author wrote there and which nothing downstream can
193
+ * detect. That is why an unidentified node answers `undefined` here rather
194
+ * than falling back to a container index, and why this cannot delegate to
195
+ * `ElementKeyProvider`, whose name-based strategy makes exactly that fallback:
196
+ * its keys are derived and consumed within one snapshot, where no position can
197
+ * have shifted underneath them.
198
+ *
199
+ * Overriding is the supported route for a grammar that identifies some nodes
200
+ * outside the naming surface altogether — by a cross-reference that is unique
201
+ * among its siblings, say. Capture and lookup both read this one definition,
202
+ * so an override cannot make those two disagree.
203
+ *
204
+ * **Matching a rename does not read it.** That comparison asks the
205
+ * `NameProvider` what changed, so a node identified only by an override is
206
+ * carried across a write that leaves its identity alone and dropped by one
207
+ * that rewrites it — never misplaced, but never followed either.
208
+ */
209
+ protected anchorKey(node: AstNode): string | undefined;
210
+ /**
211
+ * Escape the characters {@link anchorKey} builds its keys out of, so a name
212
+ * containing one cannot spell a key another node also answers to — which
213
+ * would make two distinct nodes indistinguishable to the lookup.
214
+ */
215
+ protected escapeKeySegment(name: string): string;
216
+ /**
217
+ * Collect every comment in `document`, each bound to the node it hangs off.
218
+ *
219
+ * Call this BEFORE the mutation that prompts the write. The anchors are AST
220
+ * objects, so a rule that renames one in place is reflected automatically;
221
+ * capturing afterwards would work too, but capturing first is what keeps the
222
+ * CST and the comments describing the same state.
223
+ */
224
+ extract(document: LangiumDocument): CommentTrivia;
225
+ /** Recursive half of {@link extract}: one composite node's content, then its children. */
226
+ protected captureFrom(node: CstNode, source: string, commentTokens: readonly string[], into: DocumentComment[]): void;
227
+ /**
228
+ * Decide which node a comment belongs to, and how it sat against it.
229
+ *
230
+ * A comment on the same line the previous node ENDED on is that node's
231
+ * trailing comment — checked first, because by source order it also precedes
232
+ * whatever comes next, and reading it as the NEXT node's leading comment is
233
+ * what relocates an end-of-line note onto the following declaration.
234
+ */
235
+ protected classify(comment: CstNode, index: number, container: CompositeCstNode, source: string): DocumentComment;
236
+ /**
237
+ * Comment text with CRLF reduced to LF.
238
+ *
239
+ * Serializers emit LF, so splicing a comment captured from a CRLF document
240
+ * verbatim puts lone CR bytes in the middle of LF-terminated lines.
241
+ */
242
+ protected normalizeLineEndings(text: string): string;
243
+ /** Blank lines in a run of whitespace — one fewer than its newlines. */
244
+ protected countBlankLines(gap: string): number;
245
+ /**
246
+ * Splice the captured comments back into `serialized`.
247
+ *
248
+ * A comment whose anchor the write deleted, or whose anchor has no stable
249
+ * key, is dropped — counted at `debug`, because a silent drop is the failure
250
+ * this preserver exists to remove and an unexplained one just moves it.
251
+ */
252
+ apply(serialized: string, trivia: CommentTrivia, uri: URI): string;
253
+ /** {@link apply}'s body, inside the per-write memos it sets up. */
254
+ protected applyComments(serialized: string, trivia: CommentTrivia, uri: URI): string;
255
+ /**
256
+ * {@link anchorKey}, answered once per node per write.
257
+ *
258
+ * The key walks `$container` to the root building a segment each step, and
259
+ * every stage of a write asks about the same nodes — locating spans, matching
260
+ * a rename, judging a key the output kept. Recomputing makes each of those
261
+ * stages cost nodes × depth, and the stages that scan a sibling list do it
262
+ * once per comment.
263
+ */
264
+ protected cachedAnchorKey(node: AstNode): string | undefined;
265
+ /**
266
+ * Parse `text` as a throwaway document, or `undefined` when it is not
267
+ * readable — by reported error, or by a throw from a URI that routes to no
268
+ * services. Does NOT register the result, so `LangiumDocuments` is untouched.
269
+ */
270
+ protected parse(text: string, uri: URI): LangiumDocument | undefined;
271
+ /** The splice itself, run before {@link apply}'s parse check. */
272
+ protected spliceComments(serialized: string, trivia: CommentTrivia, uri: URI): string;
273
+ /**
274
+ * Whether this comment's edit has to be read back before it can be trusted.
275
+ *
276
+ * Both cases are the serializer having put the anchor on a line it shares.
277
+ * A comment that wants the line above has to open one mid-construct; a
278
+ * comment that wants the end of the anchor's line gets the end of a line that
279
+ * may belong to a later sibling, and a second such comment lands inside the
280
+ * first one's text and stops being a comment at all. Neither can be judged
281
+ * from the offsets alone — only from what the text says once re-read.
282
+ */
283
+ protected needsReadBack(comment: DocumentComment, span: AnchorSpan, serialized: string): boolean;
284
+ /**
285
+ * Splice `edits` into `serialized`, in the order given.
286
+ *
287
+ * Two inline edits landing on one offset collapse into a single opened line,
288
+ * so a stack of comments above one inline member comes back as a stack rather
289
+ * than with a blank line between each pair.
290
+ */
291
+ protected assembleComments(serialized: string, edits: readonly InlineAwareEdit[]): string;
292
+ /**
293
+ * Whether the output node now answering to `source`'s key is too likely to be
294
+ * a DIFFERENT node for the comment to follow it.
295
+ *
296
+ * A key surviving the write normally means the node did. It can also mean a
297
+ * sibling took the name over, which reads as the author having written the
298
+ * comment about a declaration they never saw.
299
+ *
300
+ * **What is detectable is a list whose members changed places; what is not is
301
+ * a payload that renames a node and gives its old name to another.** Those
302
+ * two writes produce the same text and the same keys, and the node carrying
303
+ * the old name afterwards is byte-identical under both readings, so no rule
304
+ * over this evidence separates them. A caller that knows which node it
305
+ * renamed is the only thing that could, and the transfer model carries no
306
+ * such record.
307
+ *
308
+ * **The evidence is the ORDER of the keys the two lists share.** Adding or
309
+ * removing siblings shifts the rest but leaves them in the same relative
310
+ * order; only names changing places can put two shared keys out of order. A
311
+ * list whose shared keys invert is therefore read as exchanged identities and
312
+ * those siblings lose their comments — which costs a deliberate reorder its
313
+ * comments, the conservative half of a trade whose other half is that a bare
314
+ * swap cannot move one.
315
+ *
316
+ * **Comparing counts or key SETS instead misses cases each way.** A swap
317
+ * alongside an insertion leaves the counts differing and the key set whole,
318
+ * so neither test sees it; a deletion alongside an insertion leaves the counts
319
+ * equal while every surviving sibling is still itself, so a count test drops
320
+ * comments that were never in doubt.
321
+ */
322
+ protected ambiguousRetainedKey(source: AstNode, output: AstNode): boolean;
323
+ /**
324
+ * Whether the two lists differ in a way a plain insertion or deletion cannot
325
+ * explain — the expensive half of {@link ambiguousRetainedKey}, split out so
326
+ * it can be answered once per list.
327
+ *
328
+ * What says the members may have swapped names rather than moved:
329
+ *
330
+ * - **The lists are the same length.** Every rename chain over a fixed set of
331
+ * slots looks exactly like the shift a deletion plus an insertion produces,
332
+ * and for members carrying nothing but a name the properties match under
333
+ * both readings. Neither this nor anything downstream can separate them.
334
+ * - **Keys present on both sides have changed places.** Adding or removing
335
+ * siblings shifts the rest but never reorders them, so an inversion is
336
+ * evidence no insertion or deletion can account for — and it is evidence
337
+ * the lengths alone miss, since a swap alongside an insertion leaves the
338
+ * counts differing and the key set whole.
339
+ */
340
+ protected reidentifiedList(sourceParent: AstNode, outputParent: AstNode, property: string): boolean;
341
+ /**
342
+ * The inline edits `candidate` did not round-trip: each one whose comment came
343
+ * back on a different anchor, and — when `candidate` does not parse at all —
344
+ * each one that cannot be put back beside the others without breaking it
345
+ * again. `serialized` is the unspliced text those trials are rebuilt from,
346
+ * since finding the single edit at fault means assembling the rest without it.
347
+ *
348
+ * Costs a parse and an extract, so it answers empty without either when
349
+ * nothing was spliced inline — which is every write into a document the
350
+ * serializer lays out one declaration per line.
351
+ */
352
+ protected unverifiedInlineEdits(candidate: string, edits: readonly InlineAwareEdit[], uri: URI, serialized: string): Set<InlineAwareEdit>;
353
+ protected renamedKey(anchor: AstNode, oldKey: string, renamed: Map<AstNode, string>): string | undefined;
354
+ protected matchRenamedAnchors(sourceRoot: AstNode, serialized: string, uri: URI, located: Map<string, AnchorSpan>, sourceOwners: Map<string, AstNode>, sourceCollisions: Set<string>): Map<AstNode, string>;
355
+ protected sameAsideFromName(source: AstNode, target: AstNode): boolean;
356
+ /**
357
+ * The properties `type` declares in the grammar — everything a rename match
358
+ * may compare, and nothing else.
359
+ *
360
+ * **Comparing own keys instead compares derived state, and matches nothing.**
361
+ * A built document carries whatever `ast.extensions` computed onto its nodes;
362
+ * the re-parsed serializer output is never built and carries none of it. Every
363
+ * candidate then differs on a property the grammar never mentioned, so no
364
+ * rename is ever matched — on the real write path only, because a document a
365
+ * test parses from a string has no computed state to disagree about.
366
+ */
367
+ protected comparableProperties(type: string): readonly string[];
368
+ protected sameValue(left: unknown, right: unknown): boolean;
369
+ /** The insertion this comment's placement implies, against its anchor's span. */
370
+ protected editFor(comment: DocumentComment, span: AnchorSpan, serialized: string): {
371
+ at: number;
372
+ text: string;
373
+ };
374
+ /**
375
+ * A multi-line comment's continuation lines, shifted by the same delta its
376
+ * first line moves — so a block emitted at a new indentation stays square
377
+ * instead of trailing its original column.
378
+ *
379
+ * **Only the leading whitespace run is touched, and an outdent removes at
380
+ * most what is there** — shifting further would eat the comment's own text.
381
+ *
382
+ * Single-line comments and ones sharing a line with code are returned
383
+ * unchanged.
384
+ */
385
+ protected reindent(comment: DocumentComment, targetIndent: string): string;
386
+ /** Whether everything from `offset` to the end of its line is whitespace. */
387
+ protected restOfLineIsBlank(text: string, offset: number): boolean;
388
+ /** Whether `offset` is preceded on its own line by whitespace alone. */
389
+ protected startOfLineIsBlank(text: string, offset: number): boolean;
390
+ /**
391
+ * End of the line `offset` sits on, as an insertion point for a trailing
392
+ * comment. Stops before a CR so an insertion into CRLF text lands inside the
393
+ * line rather than between its two terminator bytes.
394
+ */
395
+ protected endOfLineAt(text: string, offset: number): number;
396
+ /** Leading whitespace of the line `offset` sits on, so an insertion lines up with it. */
397
+ protected indentAt(text: string, offset: number): string;
398
+ /**
399
+ * Where every node landed in the serializer's output, keyed by
400
+ * {@link anchorKey}.
401
+ *
402
+ * Re-parses `serialized` through the document factory, which does NOT
403
+ * register the result, so this leaves `LangiumDocuments` alone. Output the
404
+ * grammar cannot read, by reported error or by a throw from a URI that
405
+ * routes to no services, yields `undefined`: the caller then writes the
406
+ * serializer's text unchanged rather than splicing into text already wrong.
407
+ *
408
+ * **A key claimed by two DIFFERENT nodes is removed, not merged.** A repeated
409
+ * identity is exactly what the integrity tier exists to repair, so collisions
410
+ * reach this method routinely; merging their spans puts every one of their
411
+ * comments on whichever came first. Removing the key drops those instead,
412
+ * which is the only outcome here that keeps a comment off a declaration its
413
+ * author did not write it on.
414
+ */
415
+ protected locate(serialized: string, uri: URI): Map<string, AnchorSpan> | undefined;
416
+ }
417
+ /** Registers {@link CommentPreserver}; bound at `trivia.preservers.comments`. */
418
+ export declare class CommentPreserverContribution implements TriviaContribution {
419
+ protected readonly services: HydraniumLanguageServices;
420
+ constructor(services: HydraniumLanguageServices);
421
+ registerTriviaPreservers(registry: TriviaRegistry): void;
422
+ }
423
+ //# sourceMappingURL=comment-preserver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comment-preserver.d.ts","sourceRoot":"","sources":["../../../src/langium/trivia/comment-preserver.ts"],"names":[],"mappings":"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"}