@@ -11,14 +11,25 @@ import {
11
11
CompletionParams ,
12
12
CompletionTriggerKind ,
13
13
InsertTextFormat ,
14
+ InsertReplaceEdit ,
14
15
LanguageClientConnection ,
16
+ Range ,
15
17
ServerCapabilities ,
16
18
TextEdit ,
17
19
} from "../languageclient"
18
20
import { Point , TextEditor } from "atom"
19
21
import * as ac from "atom/autocomplete-plus"
20
22
import { Suggestion , TextSuggestion , SnippetSuggestion } from "../types/autocomplete-extended"
21
23
24
+ /**
25
+ * Defines the behavior of suggestion acceptance.
26
+ * Assume you have "cons|ole" in the editor (`|` is the cursor position)
27
+ * and the autocomplete suggestion is `const`.
28
+ * - if `false` -> the edits are inserted : const|ole
29
+ * - if `true`` -> the edits are replaced: const|
30
+ */
31
+ type ShouldReplace = boolean
32
+
22
33
/**
23
34
* Holds a list of suggestions generated from the CompletionItem[]
24
35
* list sent by the server, as well as metadata about the context
@@ -73,14 +84,16 @@ export default class AutocompleteAdapter {
73
84
* @param onDidConvertCompletionItem An optional function that takes a {CompletionItem},
74
85
* an {atom$AutocompleteSuggestion} and a {atom$AutocompleteRequest}
75
86
* allowing you to adjust converted items.
87
+ * @param shouldReplace The behavior of suggestion acceptance (see {ShouldReplace}).
76
88
* @returns A {Promise} of an {Array} of {atom$AutocompleteSuggestion}s containing the
77
89
* AutoComplete+ suggestions to display.
78
90
*/
79
91
public async getSuggestions (
80
92
server : ActiveServer ,
81
93
request : ac . SuggestionsRequestedEvent ,
82
94
onDidConvertCompletionItem ?: CompletionItemAdjuster ,
83
- minimumWordLength ?: number
95
+ minimumWordLength ?: number ,
96
+ shouldReplace : ShouldReplace = false
84
97
) : Promise < ac . AnySuggestion [ ] > {
85
98
const triggerChars =
86
99
server . capabilities . completionProvider != null
@@ -101,6 +114,7 @@ export default class AutocompleteAdapter {
101
114
request ,
102
115
triggerChar ,
103
116
triggerOnly ,
117
+ shouldReplace ,
104
118
onDidConvertCompletionItem
105
119
)
106
120
@@ -140,6 +154,7 @@ export default class AutocompleteAdapter {
140
154
request : ac . SuggestionsRequestedEvent ,
141
155
triggerChar : string ,
142
156
triggerOnly : boolean ,
157
+ shouldReplace : ShouldReplace ,
143
158
onDidConvertCompletionItem ?: CompletionItemAdjuster
144
159
) : Promise < Suggestion [ ] > {
145
160
const cache = this . _suggestionCache . get ( server )
@@ -181,6 +196,7 @@ export default class AutocompleteAdapter {
181
196
completions ,
182
197
request ,
183
198
triggerColumns ,
199
+ shouldReplace ,
184
200
onDidConvertCompletionItem
185
201
)
186
202
this . _suggestionCache . set ( server , {
@@ -339,6 +355,7 @@ export default class AutocompleteAdapter {
339
355
* @param completionItems An {Array} of {CompletionItem} objects or a {CompletionList} containing completion
340
356
* items to be converted.
341
357
* @param request The {atom$AutocompleteRequest} to satisfy.
358
+ * @param shouldReplace The behavior of suggestion acceptance (see {ShouldReplace}).
342
359
* @param onDidConvertCompletionItem A function that takes a {CompletionItem}, an {atom$AutocompleteSuggestion}
343
360
* and a {atom$AutocompleteRequest} allowing you to adjust converted items.
344
361
* @returns A {Map} of AutoComplete+ suggestions ordered by the CompletionItems sortText.
@@ -347,6 +364,7 @@ export default class AutocompleteAdapter {
347
364
completionItems : CompletionItem [ ] | CompletionList | null ,
348
365
request : ac . SuggestionsRequestedEvent ,
349
366
triggerColumns : [ number , number ] ,
367
+ shouldReplace : ShouldReplace ,
350
368
onDidConvertCompletionItem ?: CompletionItemAdjuster
351
369
) : Map < Suggestion , PossiblyResolvedCompletionItem > {
352
370
const completionsArray = Array . isArray ( completionItems )
@@ -361,6 +379,7 @@ export default class AutocompleteAdapter {
361
379
{ } as Suggestion ,
362
380
request ,
363
381
triggerColumns ,
382
+ shouldReplace ,
364
383
onDidConvertCompletionItem
365
384
) ,
366
385
new PossiblyResolvedCompletionItem ( s , false ) ,
@@ -374,6 +393,7 @@ export default class AutocompleteAdapter {
374
393
* @param item An {CompletionItem} containing a completion item to be converted.
375
394
* @param suggestion A {atom$AutocompleteSuggestion} to have the conversion applied to.
376
395
* @param request The {atom$AutocompleteRequest} to satisfy.
396
+ * @param shouldReplace The behavior of suggestion acceptance (see {ShouldReplace}).
377
397
* @param onDidConvertCompletionItem A function that takes a {CompletionItem}, an {atom$AutocompleteSuggestion}
378
398
* and a {atom$AutocompleteRequest} allowing you to adjust converted items.
379
399
* @returns The {atom$AutocompleteSuggestion} passed in as suggestion with the conversion applied.
@@ -383,6 +403,7 @@ export default class AutocompleteAdapter {
383
403
suggestion : Suggestion ,
384
404
request : ac . SuggestionsRequestedEvent ,
385
405
triggerColumns : [ number , number ] ,
406
+ shouldReplace : ShouldReplace ,
386
407
onDidConvertCompletionItem ?: CompletionItemAdjuster
387
408
) : Suggestion {
388
409
AutocompleteAdapter . applyCompletionItemToSuggestion ( item , suggestion as TextSuggestion )
@@ -391,7 +412,8 @@ export default class AutocompleteAdapter {
391
412
request . editor ,
392
413
triggerColumns ,
393
414
request . bufferPosition ,
394
- suggestion as TextSuggestion
415
+ suggestion as TextSuggestion ,
416
+ shouldReplace
395
417
)
396
418
AutocompleteAdapter . applySnippetToSuggestion ( item , suggestion as SnippetSuggestion )
397
419
if ( onDidConvertCompletionItem != null ) {
@@ -442,20 +464,31 @@ export default class AutocompleteAdapter {
442
464
* @param textEdit A {TextEdit} from a CompletionItem to apply.
443
465
* @param editor An Atom {TextEditor} used to obtain the necessary text replacement.
444
466
* @param suggestion An {atom$AutocompleteSuggestion} to set the replacementPrefix and text properties of.
467
+ * @param shouldReplace The behavior of suggestion acceptance (see {ShouldReplace}).
445
468
*/
446
469
public static applyTextEditToSuggestion (
447
- textEdit : TextEdit | undefined ,
470
+ textEdit : TextEdit | InsertReplaceEdit | undefined ,
448
471
editor : TextEditor ,
449
472
triggerColumns : [ number , number ] ,
450
473
originalBufferPosition : Point ,
451
- suggestion : TextSuggestion
474
+ suggestion : TextSuggestion ,
475
+ shouldReplace : ShouldReplace
452
476
) : void {
453
477
if ( ! textEdit ) {
454
478
return
455
479
}
456
- if ( textEdit . range . start . character !== triggerColumns [ 0 ] ) {
457
- const range = Convert . lsRangeToAtomRange ( textEdit . range )
458
- suggestion . customReplacmentPrefix = editor . getTextInBufferRange ( [ range . start , originalBufferPosition ] )
480
+ let range : Range
481
+ if ( "range" in textEdit ) {
482
+ range = textEdit . range
483
+ } else if ( shouldReplace ) {
484
+ range = textEdit . replace
485
+ } else {
486
+ range = textEdit . insert
487
+ }
488
+
489
+ if ( range . start . character !== triggerColumns [ 0 ] ) {
490
+ const atomRange = Convert . lsRangeToAtomRange ( range )
491
+ suggestion . customReplacmentPrefix = editor . getTextInBufferRange ( [ atomRange . start , originalBufferPosition ] )
459
492
}
460
493
suggestion . text = textEdit . newText
461
494
}
0 commit comments