-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathcompletionEntryDetails.ts
123 lines (119 loc) · 4.7 KB
/
completionEntryDetails.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
import { PrevCompletionMap, PrevCompletionsAdditionalData } from './completionsAtPosition'
import constructMethodSnippet from './constructMethodSnippet'
import { RequestOutputTypes } from './ipcTypes'
import namespaceAutoImports from './namespaceAutoImports'
import { GetConfig } from './types'
import { wordStartAtPos } from './utils'
export const lastResolvedCompletion = {
value: undefined as undefined | RequestOutputTypes['getLastResolvedCompletion'],
}
export default function completionEntryDetails(
inputArgs: Parameters<ts.LanguageService['getCompletionEntryDetails']>,
languageService: ts.LanguageService,
prevCompletionsMap: PrevCompletionMap,
c: GetConfig,
{ enableMethodCompletion, completionsSymbolMap }: PrevCompletionsAdditionalData,
): ts.CompletionEntryDetails | undefined {
const [fileName, position, entryName, formatOptions, source, preferences, data, ...args] = inputArgs
lastResolvedCompletion.value = { name: entryName, range: prevCompletionsMap[entryName]?.range }
const program = languageService.getProgram()
const sourceFile = program?.getSourceFile(fileName)
if (!program || !sourceFile) return
const { documentationOverride, documentationAppend, detailPrepend, textChanges } = prevCompletionsMap[entryName] ?? {}
if (documentationOverride) {
const prior: ts.CompletionEntryDetails = {
name: entryName,
kind: ts.ScriptElementKind.alias,
kindModifiers: '',
displayParts: typeof documentationOverride === 'string' ? [{ kind: 'text', text: documentationOverride }] : documentationOverride,
}
if (textChanges) {
prior.codeActions = [
// ...(prior.codeActions ?? []),
{
description: 'Includes Text Changes',
changes: [
{
fileName,
textChanges,
},
],
},
]
}
return prior
}
let prior = languageService.getCompletionEntryDetails(
fileName,
position,
prevCompletionsMap[entryName]?.originalName || entryName,
formatOptions,
source,
preferences,
data,
...args,
)
if (detailPrepend) {
prior ??= {
name: entryName,
kind: ts.ScriptElementKind.alias,
kindModifiers: '',
displayParts: [],
}
prior.displayParts = [{ kind: 'text', text: detailPrepend }, ...prior.displayParts]
}
if (!prior) return
// might be incorrect: write [].entries() -> []|.entries|() -> []./*position*/e
const nextChar = sourceFile.getFullText().slice(position, position + 1)
if (enableMethodCompletion && c('enableMethodSnippets') && !['(', '.', '`'].includes(nextChar)) {
const symbol = completionsSymbolMap.get(entryName)?.find(c => c.source === source)?.symbol
if (symbol) {
const resolveData = {
isAmbiguous: false,
}
const methodSnippet = constructMethodSnippet(languageService, sourceFile, position, symbol, c, resolveData)
if (methodSnippet) {
const wordStartOffset = source ? wordStartAtPos(sourceFile.getFullText(), position) : undefined
const data = JSON.stringify({
methodSnippet,
isAmbiguous: resolveData.isAmbiguous,
wordStartOffset,
})
prior.documentation = [{ kind: 'text', text: `<!--tep ${data} e-->` }, ...(prior.documentation ?? [])]
}
}
}
if (source) {
const namespaceImport = namespaceAutoImports(
c,
languageService.getProgram()!.getSourceFile(fileName)!,
source,
preferences ?? {},
formatOptions ?? {},
position,
entryName,
prior,
)
if (namespaceImport) {
const { textChanges, description } = namespaceImport
const namespace = textChanges[0]!.newText.slice(0, -1)
// todo-low think of cleanin up builtin code actions descriptions
prior.codeActions = [
// ...(prior.codeActions ?? []),
{
description,
changes: [
{
fileName,
textChanges,
},
],
},
]
}
}
if (documentationAppend) {
prior.documentation = [...(prior.documentation ?? []), { kind: 'text', text: documentationAppend }]
}
return prior
}