Skip to content

Commit fa6e025

Browse files
committed
feat(handy!): display import info in completion details for imported symbols. Disabled for now by default as requires symbol patch (setting: suggestions.displayImportedInfo).
1 parent 1c6d4e4 commit fa6e025

File tree

3 files changed

+92
-10
lines changed

3 files changed

+92
-10
lines changed

src/configurationType.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,12 @@ export type Configuration = {
114114
* @default space
115115
*/
116116
'suggestions.keywordsInsertText': 'none' | 'space'
117+
/**
118+
* Will be `format-short` by default in future as super useful!
119+
* Requires symbol patch
120+
* @default disable
121+
*/
122+
'suggestions.displayImportedInfo': 'disable' | 'short-format' | 'long-format'
117123
// TODO! corrent watching!
118124
/**
119125
* Wether to enable snippets for array methods like `items.map(item => )`
@@ -446,10 +452,29 @@ export type Configuration = {
446452
* @default []
447453
*/
448454
'autoImport.alwaysIgnoreInImportAll': string[]
455+
/**
456+
* @default {}
457+
*/
458+
'autoImport.changeToNamespaceImport': {
459+
[module: string]: {
460+
/**
461+
* @default module (key)
462+
*/
463+
namespace?: string
464+
/**
465+
* @default false
466+
*/
467+
useDefaultImport?: boolean
468+
/**
469+
* Set to `false` if module is acessible from global variable
470+
* @default true */
471+
addImport?: boolean
472+
}
473+
}
449474
/**
450475
* Enable to display additional information about source declaration in completion's documentation
451476
* For now only displays function's body
452-
* Requires symbol patching
477+
* Requires symbol patch
453478
* @default false
454479
*/
455480
displayAdditionalInfoInCompletions: boolean
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import { sharedCompletionContext } from './sharedContext'
2+
3+
export default (entries: ts.CompletionEntry[]) => {
4+
const { c, prevCompletionsMap } = sharedCompletionContext
5+
6+
const displayImportedInfo = c('suggestions.displayImportedInfo')
7+
if (displayImportedInfo === 'disable') return
8+
9+
for (const entry of entries) {
10+
const symbol = entry['symbol'] as ts.Symbol
11+
if (!symbol) continue
12+
const [node] = symbol.getDeclarations() ?? []
13+
if (!node) continue
14+
let importDeclaration: ts.ImportDeclaration | undefined
15+
if (ts.isImportSpecifier(node) && ts.isNamedImports(node.parent) && ts.isImportDeclaration(node.parent.parent.parent)) {
16+
importDeclaration = node.parent.parent.parent
17+
} else if (ts.isImportClause(node) && ts.isImportDeclaration(node.parent)) {
18+
importDeclaration = node.parent
19+
} else if (ts.isNamespaceImport(node) && ts.isImportClause(node.parent) && ts.isImportDeclaration(node.parent.parent)) {
20+
// todo-low(builtin) maybe reformat text
21+
importDeclaration = node.parent.parent
22+
}
23+
if (importDeclaration) {
24+
prevCompletionsMap[entry.name] ??= {}
25+
let importPath = importDeclaration.moduleSpecifier.getText()
26+
const symbolsLimit = 40
27+
if (importPath.length > symbolsLimit) importPath = importPath.slice(0, symbolsLimit / 2) + '...' + importPath.slice(-symbolsLimit / 2)
28+
const detailPrepend = displayImportedInfo === 'short-format' ? `(from ${importPath}) ` : `Imported from ${importPath}\n\n`
29+
prevCompletionsMap[entry.name]!.detailPrepend = detailPrepend
30+
}
31+
}
32+
}

typescript/src/completionsAtPosition.ts

Lines changed: 34 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,31 @@ import { compact, oneOf } from '@zardoy/utils'
2424
import filterWIthIgnoreAutoImports from './completions/ignoreAutoImports'
2525
import escapeStringRegexp from 'escape-string-regexp'
2626
import addSourceDefinition from './completions/addSourceDefinition'
27+
import { sharedCompletionContext } from './completions/sharedContext'
28+
import displayImportedInfo from './completions/displayImportedInfo'
2729

28-
export type PrevCompletionMap = Record<string, { originalName?: string; documentationOverride?: string | ts.SymbolDisplayPart[]; documentationAppend?: string }>
30+
export type PrevCompletionMap = Record<
31+
string,
32+
{
33+
originalName?: string
34+
/** use only if codeactions cant be returned (no source) */
35+
documentationOverride?: string | ts.SymbolDisplayPart[]
36+
detailPrepend?: string
37+
documentationAppend?: string
38+
// textChanges?: ts.TextChange[]
39+
}
40+
>
2941
export type PrevCompletionsAdditionalData = {
3042
enableMethodCompletion: boolean
3143
}
3244

45+
type GetCompletionAtPositionReturnType = {
46+
completions: ts.CompletionInfo
47+
/** Let default getCompletionEntryDetails to know original name or let add documentation from here */
48+
prevCompletionsMap: PrevCompletionMap
49+
prevCompletionsAdittionalData: PrevCompletionsAdditionalData
50+
}
51+
3352
export const getCompletionsAtPosition = (
3453
fileName: string,
3554
position: number,
@@ -39,14 +58,7 @@ export const getCompletionsAtPosition = (
3958
scriptSnapshot: ts.IScriptSnapshot,
4059
formatOptions: ts.FormatCodeSettings | undefined,
4160
additionalData: { scriptKind: ts.ScriptKind; compilerOptions: ts.CompilerOptions },
42-
):
43-
| {
44-
completions: ts.CompletionInfo
45-
/** Let default getCompletionEntryDetails to know original name or let add documentation from here */
46-
prevCompletionsMap: PrevCompletionMap
47-
prevCompletionsAdittionalData: PrevCompletionsAdditionalData
48-
}
49-
| undefined => {
61+
): GetCompletionAtPositionReturnType | undefined => {
5062
const prevCompletionsMap: PrevCompletionMap = {}
5163
const program = languageService.getProgram()
5264
const sourceFile = program?.getSourceFile(fileName)
@@ -55,6 +67,18 @@ export const getCompletionsAtPosition = (
5567
const exactNode = findChildContainingExactPosition(sourceFile, position)
5668
const isCheckedFile =
5769
!tsFull.isSourceFileJS(sourceFile as any) || !!tsFull.isCheckJsEnabledForFile(sourceFile as any, additionalData.compilerOptions as any)
70+
Object.assign(sharedCompletionContext, {
71+
position,
72+
languageService,
73+
sourceFile,
74+
program,
75+
isCheckedFile,
76+
node: exactNode,
77+
prevCompletionsMap,
78+
c,
79+
formatOptions: formatOptions || {},
80+
preferences: options || {},
81+
} satisfies typeof sharedCompletionContext)
5882
const unpatch = patchBuiltinMethods(c, languageService, isCheckedFile)
5983
const getPrior = () => {
6084
try {
@@ -233,6 +257,7 @@ export const getCompletionsAtPosition = (
233257
// #endregion
234258

235259
prior.entries = addSourceDefinition(prior.entries, prevCompletionsMap, c) ?? prior.entries
260+
displayImportedInfo(prior.entries)
236261

237262
if (c('improveJsxCompletions') && leftNode) prior.entries = improveJsxCompletions(prior.entries, leftNode, position, sourceFile, c('jsxCompletionsMap'))
238263

0 commit comments

Comments
 (0)