@adecore/editor-react 0.31.12 → 0.32.0

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 (137) hide show
  1. package/dist/AnchoredPopup.js +73 -19
  2. package/dist/AttributionCard.js +162 -4
  3. package/dist/BaselineStatus.js +62 -8
  4. package/dist/CallHierarchyPanel.js +977 -60
  5. package/dist/ChangeReview.js +76 -25
  6. package/dist/CodeAuthorsCard.js +314 -14
  7. package/dist/CompletionPopup.js +490 -83
  8. package/dist/DiffView.js +548 -181
  9. package/dist/EditorContextMenu.js +352 -34
  10. package/dist/EditorView.js +276 -99
  11. package/dist/FindReplace.js +525 -67
  12. package/dist/HoverCard.js +378 -38
  13. package/dist/HoverSections.js +367 -56
  14. package/dist/LanguagePopups.js +95 -34
  15. package/dist/Markdown.js +41 -6
  16. package/dist/PanelResizeHandle.js +199 -66
  17. package/dist/PathText.js +49 -7
  18. package/dist/PeekPanel.js +675 -72
  19. package/dist/PickPopup.js +304 -34
  20. package/dist/RenameCard.js +679 -85
  21. package/dist/RenderedDocs.js +329 -58
  22. package/dist/SignatureCard.js +91 -7
  23. package/dist/SplitDiffView.js +344 -254
  24. package/dist/SymbolPicker.js +440 -85
  25. package/dist/call-hierarchy-model.js +102 -68
  26. package/dist/call-hierarchy.js +458 -359
  27. package/dist/code-actions-model.js +88 -76
  28. package/dist/code-actions.js +372 -283
  29. package/dist/code-authors.js +64 -55
  30. package/dist/code-vision-model.js +134 -127
  31. package/dist/code-vision.js +224 -206
  32. package/dist/completion-call.js +94 -67
  33. package/dist/completion-model.js +334 -244
  34. package/dist/completion.js +840 -649
  35. package/dist/conflict-model.js +35 -29
  36. package/dist/context-menu-rows.js +42 -17
  37. package/dist/context-menu.js +64 -46
  38. package/dist/definition-link.js +88 -85
  39. package/dist/diagnostics-model.js +74 -55
  40. package/dist/diagnostics.js +121 -100
  41. package/dist/diff-expansion.js +38 -35
  42. package/dist/diff-overlays.js +144 -22
  43. package/dist/diff-syntax.js +65 -42
  44. package/dist/diff-wordmarks.js +26 -23
  45. package/dist/doc-comment-model.js +265 -216
  46. package/dist/editor-language.js +177 -152
  47. package/dist/error-message.js +2 -2
  48. package/dist/find-query.js +49 -36
  49. package/dist/folding.js +81 -62
  50. package/dist/format-on-type.js +86 -67
  51. package/dist/highlight-layers.js +19 -20
  52. package/dist/highlights.js +105 -83
  53. package/dist/history.js +44 -38
  54. package/dist/holder.js +18 -18
  55. package/dist/host-types.js +1 -1
  56. package/dist/hover-content.js +167 -129
  57. package/dist/hover.js +285 -245
  58. package/dist/index.js +10 -10
  59. package/dist/inlay-hints.js +369 -324
  60. package/dist/key-priority.js +34 -31
  61. package/dist/language-ids.js +45 -42
  62. package/dist/line-edits.js +74 -28
  63. package/dist/line-text.js +18 -3
  64. package/dist/locales/en.json +38 -38
  65. package/dist/locales/nl.json +41 -41
  66. package/dist/models.js +1 -1
  67. package/dist/navigation-history.js +40 -41
  68. package/dist/navigation.js +141 -123
  69. package/dist/panel-size.js +8 -8
  70. package/dist/patch-decorations.js +236 -160
  71. package/dist/patch-layout.js +331 -262
  72. package/dist/paths.js +3 -3
  73. package/dist/peek-model.js +86 -69
  74. package/dist/peek.js +254 -192
  75. package/dist/pick.js +164 -157
  76. package/dist/popup-focus.js +5 -5
  77. package/dist/popup-placement.js +36 -21
  78. package/dist/popups.js +13 -13
  79. package/dist/project-language.js +228 -211
  80. package/dist/project-problems.js +81 -69
  81. package/dist/proposal-model.js +163 -126
  82. package/dist/recent-choices.js +25 -25
  83. package/dist/refresher.js +44 -49
  84. package/dist/rename-model.js +113 -113
  85. package/dist/rename.js +321 -233
  86. package/dist/rendered-docs.d.ts +4 -2
  87. package/dist/rendered-docs.js +384 -318
  88. package/dist/rendering-context.js +5 -3
  89. package/dist/rendering.js +22 -4
  90. package/dist/review-group.js +42 -39
  91. package/dist/row-host.d.ts +4 -2
  92. package/dist/row-host.js +90 -78
  93. package/dist/selection-ranges.js +21 -17
  94. package/dist/semantic-delta.js +22 -19
  95. package/dist/semantic-model.js +86 -73
  96. package/dist/semantic-tokens.js +201 -162
  97. package/dist/shortcut-keys.js +16 -10
  98. package/dist/signature-model.js +34 -28
  99. package/dist/signature.js +177 -129
  100. package/dist/snippet-field-transforms.js +118 -106
  101. package/dist/snippet-indent.js +48 -43
  102. package/dist/snippet-range-order.js +11 -11
  103. package/dist/snippet-session.js +703 -667
  104. package/dist/snippet-transform-client.js +59 -59
  105. package/dist/snippet-transform-format.js +285 -263
  106. package/dist/snippet-transform-protocol.js +1 -1
  107. package/dist/snippet-transform-queue.js +163 -153
  108. package/dist/snippet-transform-worker.js +42 -35
  109. package/dist/snippet-variable-names.js +1 -36
  110. package/dist/snippet-variables.js +53 -63
  111. package/dist/snippet.js +477 -405
  112. package/dist/split-alignment.js +47 -35
  113. package/dist/split-scroll.js +42 -40
  114. package/dist/symbol-links.js +33 -25
  115. package/dist/symbol-picker-model.js +126 -116
  116. package/dist/symbol-picker.js +98 -59
  117. package/dist/symbols.js +117 -88
  118. package/dist/testing.js +248 -165
  119. package/dist/timers.js +35 -30
  120. package/dist/use-panel-body.js +49 -8
  121. package/dist/use-problem-counts.js +29 -15
  122. package/dist/view-state.js +54 -33
  123. package/dist/word-diff.js +18 -18
  124. package/dist/workspace-edit.js +300 -249
  125. package/package.json +6 -6
  126. package/src/CallHierarchyPanel.tsx +2 -2
  127. package/src/DiffView.tsx +3 -3
  128. package/src/FindReplace.tsx +2 -2
  129. package/src/LanguagePopups.tsx +2 -0
  130. package/src/PeekPanel.tsx +3 -3
  131. package/src/RenderedDocs.tsx +9 -10
  132. package/src/SymbolPicker.tsx +2 -2
  133. package/src/diff-overlays.tsx +6 -4
  134. package/src/locales/en.json +38 -38
  135. package/src/locales/nl.json +41 -41
  136. package/src/rendered-docs.ts +14 -3
  137. package/src/row-host.ts +14 -3
package/dist/signature.js CHANGED
@@ -10,142 +10,190 @@ const PAUSE_MS = 60;
10
10
  * so the active parameter follows; the server answering nothing is the caret leaving the call.
11
11
  */
12
12
  export class SignatureFeature {
13
- language;
14
- timers;
15
- timer;
16
- request = 0;
17
- controller = null;
18
- help = null;
19
- anchor = null;
20
- constructor(language, timers = realTimers) {
21
- this.language = language;
22
- this.timers = timers;
23
- const { editor } = language;
24
- const offs = [
25
- editor.onTextChange((change) => this.edited(change)),
26
- editor.onCaret(() => this.retrigger()),
27
- editor.onBlur(() => this.close()),
28
- language.onKey((event) => {
29
- if (event.key === 'Escape' && this.isOpen && this.language.popups.getState().callHierarchy === null) {
30
- this.close();
31
- return true;
32
- }
33
- if (isShortcut(this.language.shortcuts.parameterInfo, event)) {
34
- this.invoke();
35
- return true;
36
- }
37
- if ((event.key === 'ArrowUp' || event.key === 'ArrowDown') && !event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) {
38
- return this.cycle(event.key === 'ArrowDown' ? 1 : -1);
39
- }
40
- return false;
41
- }, KEY_PRIORITY.signature)
42
- ];
43
- language.onDispose(() => {
44
- for (const off of offs) {
45
- off();
46
- }
47
- this.close();
48
- });
49
- }
50
- get isOpen() {
51
- return this.language.popups.getState().signature !== null;
13
+ language;
14
+ timers;
15
+ timer;
16
+ request = 0;
17
+ controller = null;
18
+ help = null;
19
+ anchor = null;
20
+ constructor(language, timers = realTimers) {
21
+ this.language = language;
22
+ this.timers = timers;
23
+ const {
24
+ editor
25
+ } = language;
26
+ const offs = [editor.onTextChange(change => this.edited(change)), editor.onCaret(() => this.retrigger()), editor.onBlur(() => this.close()), language.onKey(event => {
27
+ if (event.key === 'Escape' && this.isOpen && this.language.popups.getState().callHierarchy === null) {
28
+ this.close();
29
+ return true;
30
+ }
31
+ if (isShortcut(this.language.shortcuts.parameterInfo, event)) {
32
+ this.invoke();
33
+ return true;
34
+ }
35
+ if ((event.key === 'ArrowUp' || event.key === 'ArrowDown') && !event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) {
36
+ return this.cycle(event.key === 'ArrowDown' ? 1 : -1);
37
+ }
38
+ return false;
39
+ }, KEY_PRIORITY.signature)];
40
+ language.onDispose(() => {
41
+ for (const off of offs) {
42
+ off();
43
+ }
44
+ this.close();
45
+ });
46
+ }
47
+ get isOpen() {
48
+ return this.language.popups.getState().signature !== null;
49
+ }
50
+ /* Asks for the parameters of the call at the caret, as its key does. */
51
+ invoke() {
52
+ this.ask({
53
+ triggerKind: 1,
54
+ isRetrigger: false
55
+ });
56
+ }
57
+ /* Asks for the parameters as if `(` had just been typed, which is what a call opened by a completion is. */
58
+ trigger() {
59
+ this.ask({
60
+ triggerKind: 2,
61
+ triggerCharacter: '(',
62
+ isRetrigger: false
63
+ });
64
+ }
65
+ /* Shows the next or previous overload; false when the card has fewer than two, which leaves the arrow to the caret. */
66
+ cycle(step) {
67
+ const {
68
+ help
69
+ } = this;
70
+ if (help === null || help.signatures.length < 2 || !this.isOpen) {
71
+ return false;
52
72
  }
53
- /* Asks for the parameters of the call at the caret, as its key does. */
54
- invoke() {
55
- this.ask({ triggerKind: 1, isRetrigger: false });
73
+ const count = help.signatures.length;
74
+ const next = {
75
+ ...help,
76
+ activeSignature: (Math.min(Math.max(0, help.activeSignature ?? 0), count - 1) + step + count) % count
77
+ };
78
+ const model = signatureViewOf(next);
79
+ if (model === null || this.anchor === null) {
80
+ return false;
56
81
  }
57
- /* Asks for the parameters as if `(` had just been typed, which is what a call opened by a completion is. */
58
- trigger() {
59
- this.ask({ triggerKind: 2, triggerCharacter: '(', isRetrigger: false });
82
+ this.help = next;
83
+ this.language.popups.setState({
84
+ signature: {
85
+ anchor: this.anchor,
86
+ model
87
+ }
88
+ });
89
+ return true;
90
+ }
91
+ close() {
92
+ this.request++;
93
+ this.controller?.abort();
94
+ this.timers.clear(this.timer);
95
+ this.help = null;
96
+ this.anchor = null;
97
+ if (this.isOpen) {
98
+ this.language.popups.setState({
99
+ signature: null
100
+ });
60
101
  }
61
- /* Shows the next or previous overload; false when the card has fewer than two, which leaves the arrow to the caret. */
62
- cycle(step) {
63
- const { help } = this;
64
- if (help === null || help.signatures.length < 2 || !this.isOpen) {
65
- return false;
66
- }
67
- const count = help.signatures.length;
68
- const next = { ...help, activeSignature: (Math.min(Math.max(0, help.activeSignature ?? 0), count - 1) + step + count) % count };
69
- const model = signatureViewOf(next);
70
- if (model === null || this.anchor === null) {
71
- return false;
72
- }
73
- this.help = next;
74
- this.language.popups.setState({ signature: { anchor: this.anchor, model } });
75
- return true;
102
+ }
103
+ options() {
104
+ const {
105
+ project,
106
+ uri
107
+ } = this.language;
108
+ const options = project.service.providerOptions(METHOD, uri);
109
+ return options === undefined ? null : {
110
+ triggers: options.triggerCharacters ?? [],
111
+ retriggers: options.retriggerCharacters ?? []
112
+ };
113
+ }
114
+ edited(change) {
115
+ const options = this.options();
116
+ if (change.source !== 'input' || options === null) {
117
+ this.close();
118
+ return;
76
119
  }
77
- close() {
78
- this.request++;
79
- this.controller?.abort();
80
- this.timers.clear(this.timer);
81
- this.help = null;
82
- this.anchor = null;
83
- if (this.isOpen) {
84
- this.language.popups.setState({ signature: null });
85
- }
120
+ const text = change.changes.length === 1 ? change.changes[0].text : '';
121
+ const last = Array.from(text).at(-1) ?? '';
122
+ if (text.length === 1 && options.triggers.includes(last)) {
123
+ this.ask({
124
+ triggerKind: 2,
125
+ triggerCharacter: last,
126
+ isRetrigger: this.isOpen
127
+ });
128
+ } else if (this.isOpen) {
129
+ this.ask({
130
+ triggerKind: text.length === 1 && options.retriggers.includes(last) ? 2 : 3,
131
+ ...(options.retriggers.includes(last) ? {
132
+ triggerCharacter: last
133
+ } : {}),
134
+ isRetrigger: true
135
+ });
86
136
  }
87
- options() {
88
- const { project, uri } = this.language;
89
- const options = project.service.providerOptions(METHOD, uri);
90
- return options === undefined ? null : { triggers: options.triggerCharacters ?? [], retriggers: options.retriggerCharacters ?? [] };
137
+ }
138
+ retrigger() {
139
+ if (this.isOpen) {
140
+ this.ask({
141
+ triggerKind: 3,
142
+ isRetrigger: true
143
+ });
91
144
  }
92
- edited(change) {
93
- const options = this.options();
94
- if (change.source !== 'input' || options === null) {
95
- this.close();
96
- return;
97
- }
98
- const text = change.changes.length === 1 ? change.changes[0].text : '';
99
- const last = Array.from(text).at(-1) ?? '';
100
- if (text.length === 1 && options.triggers.includes(last)) {
101
- this.ask({ triggerKind: 2, triggerCharacter: last, isRetrigger: this.isOpen });
102
- }
103
- else if (this.isOpen) {
104
- this.ask({
105
- triggerKind: text.length === 1 && options.retriggers.includes(last) ? 2 : 3,
106
- ...(options.retriggers.includes(last) ? { triggerCharacter: last } : {}),
107
- isRetrigger: true
108
- });
109
- }
145
+ }
146
+ ask(context) {
147
+ const {
148
+ project,
149
+ uri
150
+ } = this.language;
151
+ if (!project.service.supports(METHOD, uri)) {
152
+ return;
110
153
  }
111
- retrigger() {
112
- if (this.isOpen) {
113
- this.ask({ triggerKind: 3, isRetrigger: true });
114
- }
154
+ this.timers.clear(this.timer);
155
+ const request = ++this.request;
156
+ const full = {
157
+ ...context,
158
+ ...(this.help === null ? {} : {
159
+ activeSignatureHelp: this.help
160
+ })
161
+ };
162
+ this.timer = this.timers.set(() => void this.fetch(full, request), PAUSE_MS);
163
+ }
164
+ async fetch(context, request) {
165
+ const {
166
+ editor,
167
+ project,
168
+ uri
169
+ } = this.language;
170
+ const caret = editor.getCaret();
171
+ this.controller?.abort();
172
+ const controller = new AbortController();
173
+ this.controller = controller;
174
+ let help;
175
+ try {
176
+ help = await project.service.signatureHelp(uri, caret, context, {
177
+ signal: controller.signal
178
+ });
179
+ } catch {
180
+ return;
115
181
  }
116
- ask(context) {
117
- const { project, uri } = this.language;
118
- if (!project.service.supports(METHOD, uri)) {
119
- return;
120
- }
121
- this.timers.clear(this.timer);
122
- const request = ++this.request;
123
- const full = { ...context, ...(this.help === null ? {} : { activeSignatureHelp: this.help }) };
124
- this.timer = this.timers.set(() => void this.fetch(full, request), PAUSE_MS);
182
+ if (request !== this.request) {
183
+ return;
125
184
  }
126
- async fetch(context, request) {
127
- const { editor, project, uri } = this.language;
128
- const caret = editor.getCaret();
129
- this.controller?.abort();
130
- const controller = new AbortController();
131
- this.controller = controller;
132
- let help;
133
- try {
134
- help = await project.service.signatureHelp(uri, caret, context, { signal: controller.signal });
135
- }
136
- catch {
137
- return;
138
- }
139
- if (request !== this.request) {
140
- return;
141
- }
142
- const model = signatureViewOf(help);
143
- if (model === null) {
144
- this.close();
145
- return;
146
- }
147
- this.help = help;
148
- this.anchor ??= caret;
149
- this.language.popups.setState({ signature: { anchor: this.anchor, model } });
185
+ const model = signatureViewOf(help);
186
+ if (model === null) {
187
+ this.close();
188
+ return;
150
189
  }
151
- }
190
+ this.help = help;
191
+ this.anchor ??= caret;
192
+ this.language.popups.setState({
193
+ signature: {
194
+ anchor: this.anchor,
195
+ model
196
+ }
197
+ });
198
+ }
199
+ }
@@ -1,116 +1,128 @@
1
1
  import { comparePositions, shiftPosition } from './diagnostics-model.js';
2
2
  /* Navigation frames can pop before a worker replies; their tracked targets live independently. */
3
3
  export class SnippetFieldTransforms {
4
- entries = new Set();
5
- applying = null;
6
- editor;
7
- lease;
8
- apply;
9
- constructor(editor, lease, apply) {
10
- this.editor = editor;
11
- this.lease = lease;
12
- this.apply = apply;
4
+ entries = new Set();
5
+ applying = null;
6
+ editor;
7
+ lease;
8
+ apply;
9
+ constructor(editor, lease, apply) {
10
+ this.editor = editor;
11
+ this.lease = lease;
12
+ this.apply = apply;
13
+ }
14
+ get pending() {
15
+ return this.entries.size > 0;
16
+ }
17
+ get ranges() {
18
+ return [...this.entries].reduce((sum, entry) => sum + entry.targets.length, 0);
19
+ }
20
+ async settle() {
21
+ await Promise.all([...this.entries].map(entry => entry.done));
22
+ }
23
+ enqueue(targets, current) {
24
+ if (targets.length === 0 || this.lease === null) {
25
+ return;
13
26
  }
14
- get pending() {
15
- return this.entries.size > 0;
27
+ let finish;
28
+ const done = new Promise(resolve => {
29
+ finish = resolve;
30
+ });
31
+ const entry = {
32
+ targets,
33
+ current,
34
+ done,
35
+ finish,
36
+ cancelled: false
37
+ };
38
+ this.entries.add(entry);
39
+ const jobs = [],
40
+ keys = new Map();
41
+ const slots = targets.map(target => {
42
+ const job = {
43
+ ...target.transform,
44
+ value: target.value
45
+ },
46
+ key = JSON.stringify(job);
47
+ let slot = keys.get(key);
48
+ if (slot === undefined) {
49
+ slot = jobs.length;
50
+ keys.set(key, slot);
51
+ jobs.push(job);
52
+ }
53
+ return slot;
54
+ });
55
+ const valid = () => !entry.cancelled && entry.current() && targets.every(target => this.editor.textInRange(target.range) === target.value);
56
+ void this.lease.request(jobs, {
57
+ kind: 'exit',
58
+ current: valid
59
+ }).then(values => {
60
+ if (!valid()) {
61
+ return;
62
+ }
63
+ this.applying = entry;
64
+ try {
65
+ this.apply(targets, slots.map(slot => values[slot]));
66
+ } finally {
67
+ this.applying = null;
68
+ }
69
+ }).catch(() => {
70
+ /* Failed exits retain the raw field value without retrying. */
71
+ }).finally(() => {
72
+ this.entries.delete(entry);
73
+ finish();
74
+ });
75
+ }
76
+ prune() {
77
+ for (const entry of this.entries) {
78
+ if (!entry.current()) {
79
+ this.cancel(entry);
80
+ }
16
81
  }
17
- get ranges() {
18
- return [...this.entries].reduce((sum, entry) => sum + entry.targets.length, 0);
82
+ }
83
+ clear() {
84
+ for (const entry of this.entries) {
85
+ this.cancel(entry);
19
86
  }
20
- async settle() {
21
- await Promise.all([...this.entries].map((entry) => entry.done));
22
- }
23
- enqueue(targets, current) {
24
- if (targets.length === 0 || this.lease === null) {
25
- return;
26
- }
27
- let finish;
28
- const done = new Promise((resolve) => {
29
- finish = resolve;
30
- });
31
- const entry = { targets, current, done, finish, cancelled: false };
32
- this.entries.add(entry);
33
- const jobs = [], keys = new Map();
34
- const slots = targets.map((target) => {
35
- const job = { ...target.transform, value: target.value }, key = JSON.stringify(job);
36
- let slot = keys.get(key);
37
- if (slot === undefined) {
38
- slot = jobs.length;
39
- keys.set(key, slot);
40
- jobs.push(job);
41
- }
42
- return slot;
43
- });
44
- const valid = () => !entry.cancelled && entry.current() && targets.every((target) => this.editor.textInRange(target.range) === target.value);
45
- void this.lease
46
- .request(jobs, { kind: 'exit', current: valid })
47
- .then((values) => {
48
- if (!valid()) {
49
- return;
50
- }
51
- this.applying = entry;
52
- try {
53
- this.apply(targets, slots.map((slot) => values[slot]));
54
- }
55
- finally {
56
- this.applying = null;
57
- }
58
- })
59
- .catch(() => {
60
- /* Failed exits retain the raw field value without retrying. */
61
- })
62
- .finally(() => {
63
- this.entries.delete(entry);
64
- finish();
65
- });
66
- }
67
- prune() {
68
- for (const entry of this.entries) {
69
- if (!entry.current()) {
70
- this.cancel(entry);
71
- }
72
- }
73
- }
74
- clear() {
75
- for (const entry of this.entries) {
87
+ }
88
+ cancel(entry) {
89
+ entry.cancelled = true;
90
+ this.entries.delete(entry);
91
+ entry.finish();
92
+ }
93
+ edited(changes, detached) {
94
+ for (const entry of this.entries) {
95
+ if (entry === this.applying) {
96
+ continue;
97
+ }
98
+ for (const target of entry.targets) {
99
+ let {
100
+ start,
101
+ end
102
+ } = target.range;
103
+ for (const change of changes) {
104
+ const empty = comparePositions(start, end) === 0;
105
+ const insert = comparePositions(change.range.start, change.range.end) === 0;
106
+ const overlaps = insert ? empty ? comparePositions(start, change.range.start) === 0 : comparePositions(start, change.range.start) < 0 && comparePositions(change.range.start, end) < 0 : empty ? comparePositions(change.range.start, start) <= 0 && comparePositions(start, change.range.end) < 0 : comparePositions(change.range.start, end) < 0 && comparePositions(start, change.range.end) < 0;
107
+ if (overlaps && !(detached !== undefined && empty && insert)) {
76
108
  this.cancel(entry);
109
+ break;
110
+ }
111
+ const insertAtEnd = insert && !empty && comparePositions(end, change.range.start) === 0;
112
+ start = shiftPosition(start, change);
113
+ end = insertAtEnd ? end : shiftPosition(end, change);
77
114
  }
78
- }
79
- cancel(entry) {
80
- entry.cancelled = true;
81
- this.entries.delete(entry);
82
- entry.finish();
83
- }
84
- edited(changes, detached) {
85
- for (const entry of this.entries) {
86
- if (entry === this.applying) {
87
- continue;
88
- }
89
- for (const target of entry.targets) {
90
- let { start, end } = target.range;
91
- for (const change of changes) {
92
- const empty = comparePositions(start, end) === 0;
93
- const insert = comparePositions(change.range.start, change.range.end) === 0;
94
- const overlaps = insert
95
- ? empty
96
- ? comparePositions(start, change.range.start) === 0
97
- : comparePositions(start, change.range.start) < 0 && comparePositions(change.range.start, end) < 0
98
- : empty
99
- ? comparePositions(change.range.start, start) <= 0 && comparePositions(start, change.range.end) < 0
100
- : comparePositions(change.range.start, end) < 0 && comparePositions(start, change.range.end) < 0;
101
- if (overlaps && !(detached !== undefined && empty && insert)) {
102
- this.cancel(entry);
103
- break;
104
- }
105
- const insertAtEnd = insert && !empty && comparePositions(end, change.range.start) === 0;
106
- start = shiftPosition(start, change);
107
- end = insertAtEnd ? end : shiftPosition(end, change);
108
- }
109
- target.range = detached === undefined ? { start, end } : detached({ ...target.range, order: target.order });
110
- if (entry.cancelled) {
111
- break;
112
- }
113
- }
115
+ target.range = detached === undefined ? {
116
+ start,
117
+ end
118
+ } : detached({
119
+ ...target.range,
120
+ order: target.order
121
+ });
122
+ if (entry.cancelled) {
123
+ break;
114
124
  }
125
+ }
115
126
  }
116
- }
127
+ }
128
+ }
@@ -2,48 +2,53 @@ import { snippetOrderOf, withSnippetOrder } from './snippet-range-order.js';
2
2
  import { MAX_SNIPPET_TEXT } from './snippet.js';
3
3
  /* Indentation edits map the offsets once, including child projections in copied parents. */
4
4
  export function indentSnippet(parsed, before) {
5
- const prefix = /^[\t ]*/.exec(before)?.[0] ?? '';
6
- if (prefix === '' || !parsed.text.includes('\n')) {
7
- return parsed;
8
- }
9
- const insertions = [];
10
- for (let offset = parsed.text.indexOf('\n'); offset !== -1; offset = parsed.text.indexOf('\n', offset + 1)) {
11
- insertions.push(offset + 1);
12
- }
13
- if (parsed.text.length + insertions.length * prefix.length > MAX_SNIPPET_TEXT) {
14
- return { text: parsed.text, stops: [], limited: true };
15
- }
16
- const shift = (offset, after = true) => {
17
- let low = 0;
18
- let high = insertions.length;
19
- while (low < high) {
20
- const middle = (low + high) >>> 1;
21
- if (insertions[middle] < offset || (after && insertions[middle] === offset)) {
22
- low = middle + 1;
23
- }
24
- else {
25
- high = middle;
26
- }
27
- }
28
- return offset + low * prefix.length;
29
- };
30
- const range = (range) => withSnippetOrder({
31
- ...range,
32
- start: shift(range.start),
33
- end: shift(range.end, range.start === range.end || range.tail === true)
34
- }, snippetOrderOf(range));
5
+ const prefix = /^[\t ]*/.exec(before)?.[0] ?? '';
6
+ if (prefix === '' || !parsed.text.includes('\n')) {
7
+ return parsed;
8
+ }
9
+ const insertions = [];
10
+ for (let offset = parsed.text.indexOf('\n'); offset !== -1; offset = parsed.text.indexOf('\n', offset + 1)) {
11
+ insertions.push(offset + 1);
12
+ }
13
+ if (parsed.text.length + insertions.length * prefix.length > MAX_SNIPPET_TEXT) {
35
14
  return {
36
- text: parsed.text.replace(/\n/g, '\n' + prefix),
37
- stops: parsed.stops.map((stop) => range(stop)),
38
- ...(parsed.transforms === undefined ? {} : { transforms: parsed.transforms.map((transform) => range(transform)) }),
39
- ...(parsed.fields === undefined
40
- ? {}
41
- : {
42
- fields: parsed.fields.map((field) => ({
43
- ...field,
44
- ranges: field.ranges.map((child) => range(child)),
45
- ...(field.linked === undefined ? {} : { linked: field.linked.map((child) => range(child)) })
46
- }))
47
- })
15
+ text: parsed.text,
16
+ stops: [],
17
+ limited: true
48
18
  };
49
- }
19
+ }
20
+ const shift = (offset, after = true) => {
21
+ let low = 0;
22
+ let high = insertions.length;
23
+ while (low < high) {
24
+ const middle = low + high >>> 1;
25
+ if (insertions[middle] < offset || after && insertions[middle] === offset) {
26
+ low = middle + 1;
27
+ } else {
28
+ high = middle;
29
+ }
30
+ }
31
+ return offset + low * prefix.length;
32
+ };
33
+ const range = range => withSnippetOrder({
34
+ ...range,
35
+ start: shift(range.start),
36
+ end: shift(range.end, range.start === range.end || range.tail === true)
37
+ }, snippetOrderOf(range));
38
+ return {
39
+ text: parsed.text.replace(/\n/g, '\n' + prefix),
40
+ stops: parsed.stops.map(stop => range(stop)),
41
+ ...(parsed.transforms === undefined ? {} : {
42
+ transforms: parsed.transforms.map(transform => range(transform))
43
+ }),
44
+ ...(parsed.fields === undefined ? {} : {
45
+ fields: parsed.fields.map(field => ({
46
+ ...field,
47
+ ranges: field.ranges.map(child => range(child)),
48
+ ...(field.linked === undefined ? {} : {
49
+ linked: field.linked.map(child => range(child))
50
+ })
51
+ }))
52
+ })
53
+ };
54
+ }