Skip to content

Implementing copy/paste #57262

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 53 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from 33 commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
36e67a4
Testing basic changes
navya9singh Jan 18, 2024
5d931f8
Basix structure working
navya9singh Jan 26, 2024
17f9897
Allows different text in each cursor location
navya9singh Feb 1, 2024
64da77e
working changes
navya9singh Feb 1, 2024
89ef072
Merge branch 'main' of https://github.com/navya9singh/TypeScript into…
navya9singh Feb 1, 2024
4fe48f6
removing extra code
navya9singh Feb 1, 2024
17ff23a
Fixing protocol changes and tests
navya9singh Feb 9, 2024
1b89d2e
Removing deleted files
navya9singh Feb 9, 2024
e6515ea
Removing deleted files
navya9singh Feb 9, 2024
bfe79a9
fixing eslint errors
navya9singh Feb 9, 2024
ab542b5
fiixng formatting and baseline changes
navya9singh Feb 12, 2024
9ef3d85
Minor fixes
navya9singh Feb 12, 2024
281e2f1
Merge branch 'main' of https://github.com/navya9singh/TypeScript into…
navya9singh Feb 12, 2024
7f41f30
Fixing baselines
navya9singh Feb 12, 2024
d3816d3
changes based on reviews 1
navya9singh Feb 20, 2024
3914539
changes based on review 2
navya9singh Feb 20, 2024
83a4328
Merge branch 'main' of https://github.com/navya9singh/TypeScript into…
navya9singh Feb 20, 2024
c6b6f23
fixing formatting
navya9singh Feb 20, 2024
c8c3e29
baseline changes
navya9singh Feb 20, 2024
5192ff2
accepting baselines
navya9singh Feb 20, 2024
215e778
Removing updateGraph for reverting the file
navya9singh Feb 22, 2024
ccd35b1
Merge branch 'main' of https://github.com/navya9singh/TypeScript into…
navya9singh Mar 4, 2024
1fe2754
changing protocol name
navya9singh Mar 4, 2024
c67137b
Removing extra baselines
navya9singh Mar 4, 2024
e83eae1
Merge branch 'main' of https://github.com/navya9singh/TypeScript into…
navya9singh Mar 4, 2024
392dd75
adressing pr comments
navya9singh Mar 5, 2024
d7cbcd0
Merge branch 'main' of https://github.com/navya9singh/TypeScript into…
navya9singh Mar 8, 2024
778e2b4
protocol changes and fixed tests
navya9singh Mar 19, 2024
f302b65
missed change for fourslash tests
navya9singh Mar 19, 2024
7027ea3
changes to avoid duplicated imports for symbols that are added to exi…
navya9singh Mar 19, 2024
a9f7127
Merge branch 'main' of https://github.com/navya9singh/TypeScript into…
navya9singh Mar 19, 2024
8e486d6
fixing tests
navya9singh Mar 20, 2024
835acda
small fixes
navya9singh Mar 20, 2024
3b79cb1
new fixes for non exported symbols in import adder
navya9singh Mar 28, 2024
d7f7b15
Merging with main
navya9singh Mar 28, 2024
82fc3bf
adressing pr comments
navya9singh Mar 28, 2024
5e7e39b
Merge branch 'main' of https://github.com/navya9singh/TypeScript into…
navya9singh Apr 25, 2024
0ef7161
fixing merge conflicts
navya9singh Apr 25, 2024
4980cc5
Merge branch 'main' of https://github.com/navya9singh/TypeScript into…
navya9singh Apr 25, 2024
7c6a146
resolving merge conflicts
navya9singh Apr 26, 2024
eaa1aaf
Merge branch 'main' of https://github.com/navya9singh/TypeScript into…
navya9singh Apr 26, 2024
4ec4ccc
fixing tests
navya9singh Apr 29, 2024
1a36951
small fixes
navya9singh Apr 29, 2024
4d37a06
Adressing pr comments
navya9singh Apr 30, 2024
66ca5be
adressing pr comments
navya9singh Apr 30, 2024
e8189c3
adding `getPasteEdits` to session.ts and services.ts
navya9singh Apr 30, 2024
213587e
adding changes to handle pasted text
navya9singh May 1, 2024
68ce405
Removing baselines for deleted tests
navya9singh May 1, 2024
5e1ff78
adressing pr comments
navya9singh May 2, 2024
a3fbd69
adding changes tests and protocol
navya9singh May 2, 2024
8c23899
fixing test formatting
navya9singh May 7, 2024
1958d1a
Merge branch 'main' of https://github.com/navya9singh/TypeScript into…
navya9singh May 7, 2024
3fe8f48
fixing error in pasteEdit.ts
navya9singh May 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions src/harness/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ import {
notImplemented,
OrganizeImportsArgs,
OutliningSpan,
PasteEdits,
PasteEditsArgs,
PatternMatchKind,
Program,
QuickInfo,
Expand Down Expand Up @@ -1009,6 +1011,25 @@ export class SessionClient implements LanguageService {
return getSupportedCodeFixes();
}

getPasteEdits(
{ targetFile, pastedText, pasteLocations, copiedFrom }: PasteEditsArgs,
_formatOptions: FormatCodeSettings,
): PasteEdits {
const args: protocol.GetPasteEditsRequestArgs = {
file: targetFile,
pastedText,
pasteLocations: pasteLocations.map(range => ({ start: this.positionToOneBasedLineOffset(targetFile, range.pos), end: this.positionToOneBasedLineOffset(targetFile, range.end) })),
copiedFrom: copiedFrom ? { file: copiedFrom.file, range: copiedFrom.range.map(range => ({ start: this.positionToOneBasedLineOffset(copiedFrom.file, range.pos), end: this.positionToOneBasedLineOffset(copiedFrom.file, range.end) })) } : undefined,
};
const request = this.processRequest<protocol.GetPasteEditsRequest>(protocol.CommandTypes.GetPasteEdits, args);
const response = this.processResponse<protocol.GetPasteEditsResponse>(request);
if (!response.body) {
return { edits: [] };
}
const edits: FileTextChanges[] = this.convertCodeEditsToTextChanges(response.body.edits);
return { edits, fixId: response.body.fixId };
}

getProgram(): Program {
throw new Error("Program objects are not serializable through the server protocol.");
}
Expand Down
5 changes: 5 additions & 0 deletions src/harness/fourslashImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3562,6 +3562,11 @@ export class TestState {
assert.deepEqual(actualModuleSpecifiers, moduleSpecifiers);
}

public verifyPasteEdits(options: FourSlashInterface.PasteEditsOptions): void {
const editInfo = this.languageService.getPasteEdits({ targetFile: this.activeFile.fileName, pastedText: options.args.pastedText, pasteLocations: options.args.pasteLocations, copiedFrom: options.args.copiedFrom, preferences: options.args.preferences }, this.formatCodeSettings);
(options.fixId === editInfo.fixId) ? this.verifyNewContent({ newFileContent: options.newFileContents }, editInfo.edits) : this.raiseError(`Expected to find a fix ${editInfo.fixId}, but none exists`);
}

public verifyDocCommentTemplate(expected: ts.TextInsertion | undefined, options?: ts.DocCommentTemplateOptions) {
const name = "verifyDocCommentTemplate";
const actual = this.languageService.getDocCommentTemplateAtPosition(this.activeFile.fileName, this.currentCaretPosition, options || { generateReturnInDocTemplate: true }, this.formatCodeSettings)!;
Expand Down
10 changes: 10 additions & 0 deletions src/harness/fourslashInterfaceImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,10 @@ export class Verify extends VerifyNegatable {
public organizeImports(newContent: string, mode?: ts.OrganizeImportsMode, preferences?: ts.UserPreferences): void {
this.state.verifyOrganizeImports(newContent, mode, preferences);
}

public pasteEdits(options: PasteEditsOptions): void {
this.state.verifyPasteEdits(options);
}
}

export class Edit {
Expand Down Expand Up @@ -1923,6 +1927,12 @@ export interface MoveToFileOptions {
readonly preferences?: ts.UserPreferences;
}

export interface PasteEditsOptions {
readonly newFileContents: { readonly [fileName: string]: string; };
args: ts.PasteEditsArgs;
readonly fixId: string;
}

export type RenameLocationsOptions = readonly RenameLocationOptions[] | {
readonly findInStrings?: boolean;
readonly findInComments?: boolean;
Expand Down
12 changes: 12 additions & 0 deletions src/server/project.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2214,6 +2214,18 @@ export abstract class Project implements LanguageServiceHost, ModuleResolutionHo
return this.noDtsResolutionProject;
}

/** @internal */
runWithTemporaryFileUpdate(rootFile: string, updatedText: string, cb: (updatedProgram: Program | undefined, originalProgram: Program | undefined, updatedFile: SourceFile) => void) {
const originalProgram = this.program;
const originalText = this.program?.getSourceFile(rootFile)?.getText();
Debug.assert(this.program && this.program.getSourceFile(rootFile) && originalText);

this.getScriptInfo(rootFile)?.editContent(0, this.program.getSourceFile(rootFile)!.getText().length, updatedText);
this.updateGraph();
cb(this.program, originalProgram, (this.program?.getSourceFile(rootFile))!);
this.getScriptInfo(rootFile)?.editContent(0, this.program.getSourceFile(rootFile)!.getText().length, originalText);
}

/** @internal */
private getCompilerOptionsForNoDtsResolutionProject() {
return {
Expand Down
23 changes: 23 additions & 0 deletions src/server/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ export const enum CommandTypes {
GetApplicableRefactors = "getApplicableRefactors",
GetEditsForRefactor = "getEditsForRefactor",
GetMoveToRefactoringFileSuggestions = "getMoveToRefactoringFileSuggestions",
GetPasteEdits = "getPasteEdits",
/** @internal */
GetEditsForRefactorFull = "getEditsForRefactor-full",

Expand Down Expand Up @@ -625,6 +626,28 @@ export interface GetMoveToRefactoringFileSuggestions extends Response {
};
}

/**
* Request refactorings at a given position post pasting text from some other location.
*/

export interface GetPasteEditsRequest extends Request {
command: CommandTypes.GetPasteEdits;
arguments: GetPasteEditsRequestArgs;
}

export type GetPasteEditsRequestArgs = FileRequestArgs & {
pastedText: string[];
pasteLocations: TextSpan[];
copiedFrom?: { file: string; range: TextSpan[]; };
};
export interface GetPasteEditsResponse extends Response {
body: PasteEditsAction;
}
export interface PasteEditsAction {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the future we will likely want a name and/or id too so users can tell what type of edit is being made. We can leave that out until there are multiple providers, but means that we'll have to add a flag so older clients don't unexpectedly start using the wrong paste edit

edits: FileCodeEdits[];
fixId?: {};
}

export interface GetEditsForRefactorRequest extends Request {
command: CommandTypes.GetEditsForRefactor;
arguments: GetEditsForRefactorRequestArgs;
Expand Down
29 changes: 29 additions & 0 deletions src/server/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ import {
OperationCanceledException,
OrganizeImportsMode,
OutliningSpan,
PasteEdits,
Path,
perfLogger,
PerformanceEvent,
Expand Down Expand Up @@ -2796,6 +2797,27 @@ export class Session<TMessage = string> implements EventSender {
return project.getLanguageService().getMoveToRefactoringFileSuggestions(file, this.extractPositionOrRange(args, scriptInfo), this.getPreferences(file));
}

private getPasteEdits(args: protocol.GetPasteEditsRequestArgs): protocol.PasteEditsAction | undefined {
const { file, project } = this.getFileAndProject(args);
const copyFile = args.copiedFrom ? args.copiedFrom.file : undefined;
const result = project.getLanguageService().getPasteEdits(
{
targetFile: file,
pastedText: args.pastedText,
pasteLocations: args.pasteLocations.map(paste => this.getRange({ file, startLine: paste.start.line, startOffset: paste.start.offset, endLine: paste.end.line, endOffset: paste.end.offset }, project.getScriptInfoForNormalizedPath(file)!)),
copiedFrom: args.copiedFrom && copyFile
? { file: args.copiedFrom.file, range: args.copiedFrom.range.map(copies => this.getRange({ file: copyFile, startLine: copies.start.line, startOffset: copies.start.offset, endLine: copies.end.line, endOffset: copies.end.offset }, project.getScriptInfoForNormalizedPath(toNormalizedPath(copyFile))!)) }
: undefined,
preferences: this.getPreferences(file),
},
this.getFormatOptions(file),
);
if (result === undefined) {
return undefined;
}
return this.mapPasteEditsAction(result);
}

private organizeImports(args: protocol.OrganizeImportsRequestArgs, simplifiedResult: boolean): readonly protocol.FileCodeEdits[] | readonly FileTextChanges[] {
Debug.assert(args.scope.type === "file");
const { file, project } = this.getFileAndProject(args.scope.args);
Expand Down Expand Up @@ -2928,6 +2950,10 @@ export class Session<TMessage = string> implements EventSender {
return { fixName, description, changes: this.mapTextChangesToCodeEdits(changes), commands, fixId, fixAllDescription };
}

private mapPasteEditsAction({ edits, fixId }: PasteEdits): protocol.PasteEditsAction {
return { edits: this.mapTextChangesToCodeEdits(edits), fixId };
}

private mapTextChangesToCodeEdits(textChanges: readonly FileTextChanges[]): protocol.FileCodeEdits[] {
return textChanges.map(change => this.mapTextChangeToCodeEdit(change));
}
Expand Down Expand Up @@ -3521,6 +3547,9 @@ export class Session<TMessage = string> implements EventSender {
[protocol.CommandTypes.GetMoveToRefactoringFileSuggestions]: (request: protocol.GetMoveToRefactoringFileSuggestionsRequest) => {
return this.requiredResponse(this.getMoveToRefactoringFileSuggestions(request.arguments));
},
[protocol.CommandTypes.GetPasteEdits]: (request: protocol.GetPasteEditsRequest) => {
return this.requiredResponse(this.getPasteEdits(request.arguments));
},
[protocol.CommandTypes.GetEditsForRefactorFull]: (request: protocol.GetEditsForRefactorRequest) => {
return this.requiredResponse(this.getEditsForRefactor(request.arguments, /*simplifiedResult*/ false));
},
Expand Down
1 change: 1 addition & 0 deletions src/services/_namespaces/ts.PasteEdits.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "../pasteEdits";
2 changes: 2 additions & 0 deletions src/services/_namespaces/ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,5 @@ import * as textChanges from "./ts.textChanges";
export { textChanges };
import * as formatting from "./ts.formatting";
export { formatting };
import * as pasteEdits from "./ts.PasteEdits";
export { pasteEdits };
2 changes: 1 addition & 1 deletion src/services/codefixes/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -925,7 +925,7 @@ function replaceFirstIdentifierOfEntityName(name: EntityName, newIdentifier: Ide

/** @internal */
export function importSymbols(importAdder: ImportAdder, symbols: readonly Symbol[]) {
symbols.forEach(s => importAdder.addImportFromExportedSymbol(s, /*isValidTypeOnlyUseSite*/ true));
symbols.forEach(s => importAdder.addImportFromSymbol(s, /*isValidTypeOnlyUseSite*/ true));
}

/** @internal */
Expand Down
95 changes: 83 additions & 12 deletions src/services/codefixes/importFixes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ import {
SymbolExportInfo,
SymbolFlags,
SymbolId,
SymbolInfo,
SyntaxKind,
textChanges,
toPath,
Expand Down Expand Up @@ -207,7 +208,8 @@ registerCodeFix({
export interface ImportAdder {
hasFixes(): boolean;
addImportFromDiagnostic: (diagnostic: DiagnosticWithLocation, context: CodeFixContextBase) => void;
addImportFromExportedSymbol: (exportedSymbol: Symbol, isValidTypeOnlyUseSite?: boolean) => void;
addImportFromSymbol: (exportedSymbol: Symbol, isValidTypeOnlyUseSite?: boolean, targetFilePath?: string) => void;
addImportForUnresolvedIdentifier: (context: CodeFixContextBase, symbolToken: Identifier, useAutoImportProvider: boolean) => void;
writeFixes: (changeTracker: textChanges.ChangeTracker, oldFileQuotePreference?: QuotePreference) => void;
}

Expand All @@ -233,24 +235,38 @@ function createImportAdderWorker(sourceFile: SourceFile, program: Program, useAu
type NewImportsKey = `${0 | 1}|${string}`;
/** Use `getNewImportEntry` for access */
const newImports = new Map<NewImportsKey, Mutable<ImportsCollection & { useRequire: boolean; }>>();
return { addImportFromDiagnostic, addImportFromExportedSymbol, writeFixes, hasFixes };
return { addImportFromDiagnostic, addImportFromSymbol, writeFixes, hasFixes, addImportForUnresolvedIdentifier };

function addImportForUnresolvedIdentifier(context: CodeFixContextBase, symbolToken: Identifier, useAutoImportProvider: boolean) {
const info = getFixInfosWithoutDiagnostic(context, symbolToken, useAutoImportProvider);
if (!info || !info.length) return;
addImport(first(info));
}

function addImportFromDiagnostic(diagnostic: DiagnosticWithLocation, context: CodeFixContextBase) {
const info = getFixInfos(context, diagnostic.code, diagnostic.start, useAutoImportProvider);
if (!info || !info.length) return;
addImport(first(info));
}

function addImportFromExportedSymbol(exportedSymbol: Symbol, isValidTypeOnlyUseSite?: boolean) {
const moduleSymbol = Debug.checkDefined(exportedSymbol.parent);
const symbolName = getNameForExportedSymbol(exportedSymbol, getEmitScriptTarget(compilerOptions));
const checker = program.getTypeChecker();
const symbol = checker.getMergedSymbol(skipAlias(exportedSymbol, checker));
const exportInfo = getAllExportInfoForSymbol(sourceFile, symbol, symbolName, moduleSymbol, /*preferCapitalized*/ false, program, host, preferences, cancellationToken);
const useRequire = shouldUseRequire(sourceFile, program);
const fix = getImportFixForSymbol(sourceFile, Debug.checkDefined(exportInfo), program, /*position*/ undefined, !!isValidTypeOnlyUseSite, useRequire, host, preferences);
if (fix) {
addImport({ fix, symbolName, errorIdentifierText: undefined });
function addImportFromSymbol(exportedSymbol: Symbol, isValidTypeOnlyUseSite?: boolean, targetFilePath?: string) {
if (!exportedSymbol.parent && targetFilePath) {
const fix = getImportFixForNonExportedSymbol(sourceFile, exportedSymbol, ImportKind.Named, program, !!isValidTypeOnlyUseSite, targetFilePath);
if (fix?.kind === ImportFixKind.AddToExisting) {
addImport({ fix, symbolName: exportedSymbol.name, errorIdentifierText: undefined });
}
}
else {
const moduleSymbol = Debug.checkDefined(exportedSymbol.parent);
const symbolName = getNameForExportedSymbol(exportedSymbol, getEmitScriptTarget(compilerOptions));
const checker = program.getTypeChecker();
const symbol = checker.getMergedSymbol(skipAlias(exportedSymbol, checker));
const exportInfo = getAllExportInfoForSymbol(sourceFile, symbol, symbolName, moduleSymbol, /*preferCapitalized*/ false, program, host, preferences, cancellationToken);
const useRequire = shouldUseRequire(sourceFile, program);
const fix = getImportFixForSymbol(sourceFile, Debug.checkDefined(exportInfo), program, /*position*/ undefined, !!isValidTypeOnlyUseSite, useRequire, host, preferences);
if (fix) {
addImport({ fix, symbolName, errorIdentifierText: undefined });
}
}
}

Expand Down Expand Up @@ -588,6 +604,14 @@ function getImportFixForSymbol(sourceFile: SourceFile, exportInfos: readonly Sym
return getBestFix(getImportFixes(exportInfos, position, isValidTypeOnlyUseSite, useRequire, program, sourceFile, host, preferences).fixes, sourceFile, program, packageJsonImportFilter, host);
}

function getImportFixForNonExportedSymbol(sourceFile: SourceFile, symbol: Symbol, importKind: ImportKind, program: Program, isValidTypeOnlyUseSite: boolean, targetFilePath: string) {
const fix = getImportFixesForNonExportedSymbols(sourceFile, symbol, importKind, program, isValidTypeOnlyUseSite, targetFilePath);
if (fix.fixes[0] === undefined) return; // Not adding an import to an existing import
if (fix.fixes[0].kind === ImportFixKind.AddToExisting) {
return fix.fixes[0];
}
}

function codeFixActionToCodeAction({ description, changes, commands }: CodeFixAction): CodeAction {
return { description, changes, commands };
}
Expand Down Expand Up @@ -623,6 +647,30 @@ function getSingleExportInfoForSymbol(symbol: Symbol, symbolName: string, module
}
}

function getImportFixesForNonExportedSymbols(
sourceFile: SourceFile,
symbol: Symbol,
importKind: ImportKind,
program: Program,
isValidTypeOnlyUseSite: boolean,
targetFilePath: string,
importMap = createExistingImportMap(program.getTypeChecker(), sourceFile, program.getCompilerOptions()),
): { computedWithoutCacheCount: number; fixes: readonly ImportFixWithModuleSpecifier[]; } {
const checker = program.getTypeChecker();
const symbolInfo = [{
symbol,
targetFlags: SymbolFlags.Value,
importKind,
targetFilePath,
}];
const existingImports = flatMap(symbolInfo, importMap.getImportsForNonExportedSymbols);
const addToExisting = tryAddToExistingImport(existingImports, isValidTypeOnlyUseSite, checker, program.getCompilerOptions());
return {
computedWithoutCacheCount: 0,
fixes: [addToExisting!],
};
}

function getImportFixes(
exportInfos: readonly SymbolExportInfo[],
usagePosition: number | undefined,
Expand Down Expand Up @@ -823,6 +871,23 @@ function createExistingImportMap(checker: TypeChecker, importingFile: SourceFile
const importKind = getImportKind(importingFile, exportKind, compilerOptions);
return matchingDeclarations.map(declaration => ({ declaration, importKind, symbol, targetFlags }));
},
getImportsForNonExportedSymbols: ({ symbol, importKind, targetFlags, targetFilePath }: SymbolInfo): readonly FixAddToExistingImportInfo[] => {
let fix: FixAddToExistingImportInfo[] = [];
const values = importMap?.values();
Debug.assertIsDefined(values);
for (const value of values) {
value.forEach(v => {
if (v.kind === SyntaxKind.ImportDeclaration && cast(v.moduleSpecifier, isStringLiteral).text === targetFilePath) {
fix = [{ declaration: v, importKind, targetFlags, symbol }];
return fix;
}
else {
return emptyArray;
}
});
}
return fix;
},
};
}

Expand Down Expand Up @@ -1003,6 +1068,12 @@ function sortFixInfo(fixes: readonly (FixInfo & { fix: ImportFixWithModuleSpecif
compareModuleSpecifiers(a.fix, b.fix, sourceFile, program, packageJsonImportFilter.allowsImportingSpecifier, _toPath));
}

function getFixInfosWithoutDiagnostic(context: CodeFixContextBase, symbolToken: Identifier, useAutoImportProvider: boolean): readonly FixInfo[] | undefined {
const info = getFixesInfoForNonUMDImport(context, symbolToken, useAutoImportProvider);
const packageJsonImportFilter = createPackageJsonImportFilter(context.sourceFile, context.preferences, context.host);
return info && sortFixInfo(info, context.sourceFile, context.program, packageJsonImportFilter, context.host);
}

function getBestFix(fixes: readonly ImportFixWithModuleSpecifier[], sourceFile: SourceFile, program: Program, packageJsonImportFilter: PackageJsonImportFilter, host: LanguageServiceHost): ImportFixWithModuleSpecifier | undefined {
if (!some(fixes)) return;
// These will always be placed first if available, and are better than other kinds
Expand Down
2 changes: 1 addition & 1 deletion src/services/codefixes/inferFromUsage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -439,7 +439,7 @@ function tryReplaceImportTypeNodeWithAutoImport(
): boolean {
const importableReference = tryGetAutoImportableReferenceFromTypeNode(typeNode, scriptTarget);
if (importableReference && changes.tryInsertTypeAnnotation(sourceFile, declaration, importableReference.typeNode)) {
forEach(importableReference.symbols, s => importAdder.addImportFromExportedSymbol(s, /*isValidTypeOnlyUseSite*/ true));
forEach(importableReference.symbols, s => importAdder.addImportFromSymbol(s, /*isValidTypeOnlyUseSite*/ true));
return true;
}
return false;
Expand Down
8 changes: 8 additions & 0 deletions src/services/exportInfoMap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ export interface SymbolExportInfo {
isFromPackageJson: boolean;
}

/** @internal */
export interface SymbolInfo {
readonly symbol: Symbol;
importKind: ImportKind;
targetFlags: SymbolFlags;
targetFilePath: string;
}

interface CachedSymbolExportInfo {
// Used to rehydrate `symbol` and `moduleSymbol` when transient
id: number;
Expand Down
Loading