Skip to content

Commit 7bb4ef6

Browse files
committed
[Autocompletion] Rework replacement prefix heuristic
Closes #1528
1 parent 7b8f696 commit 7bb4ef6

File tree

7 files changed

+38
-26
lines changed

7 files changed

+38
-26
lines changed

dist/main/atom/autoCompleteProvider.js

+9-12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/main/atom/autoCompleteProvider.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/main/atom/utils/index.js

+1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/main/atom/utils/index.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lib/main/atom/autoCompleteProvider.ts

+8-12
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import * as Atom from "atom"
33
import * as ACP from "atom/autocomplete-plus"
44
import * as fuzzaldrin from "fuzzaldrin"
55
import {GetClientFunction, TSClient} from "../../client"
6-
import {FileLocationQuery, spanToRange, typeScriptScopes} from "./utils"
6+
import {FileLocationQuery, inits, spanToRange, typeScriptScopes} from "./utils"
77

88
type SuggestionWithDetails = ACP.TextSuggestion & {
99
details?: protocol.CompletionEntryDetails
@@ -74,12 +74,10 @@ export class AutocompleteProvider implements ACP.AutocompleteProvider {
7474
// Get additional details for the first few suggestions
7575
await this.getAdditionalDetails(suggestions.slice(0, 10), location)
7676

77-
const trimmed = prefix.trim()
78-
7977
return suggestions.map(suggestion => ({
8078
replacementPrefix: suggestion.replacementRange
8179
? opts.editor.getTextInBufferRange(suggestion.replacementRange)
82-
: getReplacementPrefix(prefix, trimmed, suggestion.text!),
80+
: getReplacementPrefix(opts, suggestion.text!),
8381
...suggestion,
8482
}))
8583
} catch (error) {
@@ -178,14 +176,12 @@ async function getSuggestionsInternal(
178176
}
179177

180178
// Decide what needs to be replaced in the editor buffer when inserting the completion
181-
function getReplacementPrefix(prefix: string, trimmed: string, replacement: string): string {
182-
if (trimmed === "." || trimmed === "{" || prefix === " ") {
183-
return ""
184-
} else if (replacement.startsWith("$")) {
185-
return "$" + prefix
186-
} else {
187-
return prefix
188-
}
179+
function getReplacementPrefix(opts: ACP.SuggestionsRequestedEvent, replacement: string): string {
180+
const prefix = opts.editor
181+
.getBuffer()
182+
.getTextInRange([[opts.bufferPosition.row, 0], opts.bufferPosition])
183+
for (const i of inits(replacement, 1)) if (prefix.endsWith(i)) return i
184+
return ""
189185
}
190186

191187
// When the user types each character in ".hello", we want to normalize the column such that it's

lib/main/atom/utils/index.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
export * from "./atom"
22
export * from "./ts"
3+
export * from "./misc"

lib/main/atom/utils/misc.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/** Yields all initial subsequences of its first argument, starting
2+
* from lengths given as the second argument
3+
* @param str Input value. Can be a string, or an array, or frankly anything
4+
* with the slice method and length
5+
* @param startsWith Minimum init string length
6+
* @returns All initial subsequences of str of length >= startsWith
7+
*/
8+
export function* inits<T extends Sliceable>(str: T, startWith: number = 0) {
9+
for (let i = startWith; i <= str.length; ++i) {
10+
yield str.slice(0, i)
11+
}
12+
}
13+
14+
interface Sliceable {
15+
readonly length: number
16+
slice: (start?: number, end?: number) => this
17+
}

0 commit comments

Comments
 (0)