Allow getting import completion details with misspelled name (#23624)
This commit is contained in:
parent
2e78d1ef21
commit
645258cc7d
|
@ -2419,14 +2419,7 @@ Actual: ${stringify(fullActual)}`);
|
|||
public applyCodeActionFromCompletion(markerName: string, options: FourSlashInterface.VerifyCompletionActionOptions) {
|
||||
this.goToMarker(markerName);
|
||||
|
||||
const actualCompletion = this.getCompletionListAtCaret({ ...ts.defaultPreferences, includeCompletionsForModuleExports: true }).entries.find(e =>
|
||||
e.name === options.name && e.source === options.source);
|
||||
|
||||
if (!actualCompletion.hasAction) {
|
||||
this.raiseError(`Completion for ${options.name} does not have an associated action.`);
|
||||
}
|
||||
|
||||
const details = this.getCompletionEntryDetails(options.name, actualCompletion.source, options.preferences);
|
||||
const details = this.getCompletionEntryDetails(options.name, options.source, options.preferences);
|
||||
if (details.codeActions.length !== 1) {
|
||||
this.raiseError(`Expected one code action, got ${details.codeActions.length}`);
|
||||
}
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace ts.Completions {
|
|||
return getLabelCompletionAtPosition(contextToken.parent);
|
||||
}
|
||||
|
||||
const completionData = getCompletionData(program, log, sourceFile, position, preferences);
|
||||
const completionData = getCompletionData(program, log, sourceFile, position, preferences, /*detailsEntryId*/ undefined);
|
||||
if (!completionData) {
|
||||
return undefined;
|
||||
}
|
||||
|
@ -486,9 +486,9 @@ namespace ts.Completions {
|
|||
previousToken: Node;
|
||||
readonly isJsxInitializer: IsJsxInitializer;
|
||||
}
|
||||
function getSymbolCompletionFromEntryId(program: Program, log: Log, sourceFile: SourceFile, position: number, { name, source }: CompletionEntryIdentifier,
|
||||
function getSymbolCompletionFromEntryId(program: Program, log: Log, sourceFile: SourceFile, position: number, entryId: CompletionEntryIdentifier,
|
||||
): SymbolCompletion | { type: "request", request: Request } | { type: "none" } {
|
||||
const completionData = getCompletionData(program, log, sourceFile, position, { includeCompletionsForModuleExports: true, includeCompletionsWithInsertText: true });
|
||||
const completionData = getCompletionData(program, log, sourceFile, position, { includeCompletionsForModuleExports: true, includeCompletionsWithInsertText: true }, entryId);
|
||||
if (!completionData) {
|
||||
return { type: "none" };
|
||||
}
|
||||
|
@ -505,7 +505,9 @@ namespace ts.Completions {
|
|||
return firstDefined<Symbol, SymbolCompletion>(symbols, (symbol): SymbolCompletion => { // TODO: Shouldn't need return type annotation (GH#12632)
|
||||
const origin = symbolToOriginInfoMap[getSymbolId(symbol)];
|
||||
const info = getCompletionEntryDisplayNameForSymbol(symbol, program.getCompilerOptions().target, origin, completionKind);
|
||||
return info && info.name === name && getSourceFromOrigin(origin) === source ? { type: "symbol" as "symbol", symbol, location, symbolToOriginInfoMap, previousToken, isJsxInitializer } : undefined;
|
||||
return info && info.name === entryId.name && getSourceFromOrigin(origin) === entryId.source
|
||||
? { type: "symbol" as "symbol", symbol, location, symbolToOriginInfoMap, previousToken, isJsxInitializer }
|
||||
: undefined;
|
||||
}) || { type: "none" };
|
||||
}
|
||||
|
||||
|
@ -755,6 +757,7 @@ namespace ts.Completions {
|
|||
sourceFile: SourceFile,
|
||||
position: number,
|
||||
preferences: Pick<UserPreferences, "includeCompletionsForModuleExports" | "includeCompletionsWithInsertText">,
|
||||
detailsEntryId: CompletionEntryIdentifier | undefined,
|
||||
): CompletionData | Request | undefined {
|
||||
const typeChecker = program.getTypeChecker();
|
||||
|
||||
|
@ -1302,6 +1305,11 @@ namespace ts.Completions {
|
|||
const tokenTextLowerCase = tokenText.toLowerCase();
|
||||
|
||||
codefix.forEachExternalModuleToImportFrom(typeChecker, sourceFile, program.getSourceFiles(), moduleSymbol => {
|
||||
// Perf -- ignore other modules if this is a request for details
|
||||
if (detailsEntryId && detailsEntryId.source && stripQuotes(moduleSymbol.name) !== detailsEntryId.source) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (let symbol of typeChecker.getExportsOfModule(moduleSymbol)) {
|
||||
// Don't add a completion for a re-export, only for the original.
|
||||
// The actual import fix might end up coming from a re-export -- we don't compute that until getting completion details.
|
||||
|
@ -1320,7 +1328,7 @@ namespace ts.Completions {
|
|||
}
|
||||
|
||||
const origin: SymbolOriginInfo = { type: "export", moduleSymbol, isDefaultExport };
|
||||
if (stringContainsCharactersInOrder(getSymbolName(symbol, origin, target).toLowerCase(), tokenTextLowerCase)) {
|
||||
if (detailsEntryId || stringContainsCharactersInOrder(getSymbolName(symbol, origin, target).toLowerCase(), tokenTextLowerCase)) {
|
||||
symbols.push(symbol);
|
||||
symbolToOriginInfoMap[getSymbolId(symbol)] = origin;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
/// <reference path="fourslash.ts" />
|
||||
|
||||
// @Filename: /a.ts
|
||||
////export const abc = 0;
|
||||
|
||||
// @Filename: /b.ts
|
||||
////acb/**/;
|
||||
|
||||
goTo.marker("");
|
||||
verify.applyCodeActionFromCompletion("", {
|
||||
name: "abc",
|
||||
source: "/a",
|
||||
description: `Import 'abc' from module "./a"`,
|
||||
newFileContent: `import { abc } from "./a";
|
||||
|
||||
acb;`,
|
||||
});
|
Loading…
Reference in a new issue