mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Add 'renameFile' command to services (#23573)
* Add 'renameFile' command to services * renameFile -> getEditsForFileRename * Support `<reference path>` directives
This commit is contained in:
@@ -2212,6 +2212,15 @@ namespace ts {
|
||||
return absolutePath;
|
||||
}
|
||||
|
||||
export function getRelativePath(path: string, directoryPath: string, getCanonicalFileName: GetCanonicalFileName) {
|
||||
const relativePath = getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false);
|
||||
return ensurePathIsRelative(relativePath);
|
||||
}
|
||||
|
||||
export function ensurePathIsRelative(path: string): string {
|
||||
return !pathIsRelative(path) ? "./" + path : path;
|
||||
}
|
||||
|
||||
export function getBaseFileName(path: string) {
|
||||
if (path === undefined) {
|
||||
return undefined;
|
||||
|
||||
@@ -444,6 +444,12 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
export function resolveModuleNameFromCache(moduleName: string, containingFile: string, cache: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations | undefined {
|
||||
const containingDirectory = getDirectoryPath(containingFile);
|
||||
const perFolderCache = cache && cache.getOrCreateCacheForDirectory(containingDirectory);
|
||||
return perFolderCache && perFolderCache.get(moduleName);
|
||||
}
|
||||
|
||||
export function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations {
|
||||
const traceEnabled = isTraceEnabled(compilerOptions, host);
|
||||
if (traceEnabled) {
|
||||
|
||||
@@ -622,9 +622,6 @@ namespace ts {
|
||||
|
||||
Debug.assert(!!missingFilePaths);
|
||||
|
||||
// unconditionally set moduleResolutionCache to undefined to avoid unnecessary leaks
|
||||
moduleResolutionCache = undefined;
|
||||
|
||||
// Release any files we have acquired in the old program but are
|
||||
// not part of the new program.
|
||||
if (oldProgram && host.onReleaseOldSourceFile) {
|
||||
@@ -670,7 +667,8 @@ namespace ts {
|
||||
sourceFileToPackageName,
|
||||
redirectTargetsSet,
|
||||
isEmittedFile,
|
||||
getConfigFileParsingDiagnostics
|
||||
getConfigFileParsingDiagnostics,
|
||||
getResolvedModuleWithFailedLookupLocationsFromCache,
|
||||
};
|
||||
|
||||
verifyCompilerOptions();
|
||||
@@ -679,6 +677,10 @@ namespace ts {
|
||||
|
||||
return program;
|
||||
|
||||
function getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations {
|
||||
return moduleResolutionCache && resolveModuleNameFromCache(moduleName, containingFile, moduleResolutionCache);
|
||||
}
|
||||
|
||||
function toPath(fileName: string): Path {
|
||||
return ts.toPath(fileName, currentDirectory, getCanonicalFileName);
|
||||
}
|
||||
|
||||
@@ -2725,6 +2725,8 @@ namespace ts {
|
||||
/* @internal */ redirectTargetsSet: Map<true>;
|
||||
/** Is the file emitted file */
|
||||
/* @internal */ isEmittedFile(file: string): boolean;
|
||||
|
||||
/* @internal */ getResolvedModuleWithFailedLookupLocationsFromCache(moduleName: string, containingFile: string): ResolvedModuleWithFailedLookupLocations | undefined;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
|
||||
@@ -3280,6 +3280,15 @@ Actual: ${stringify(fullActual)}`);
|
||||
private static textSpansEqual(a: ts.TextSpan, b: ts.TextSpan) {
|
||||
return a && b && a.start === b.start && a.length === b.length;
|
||||
}
|
||||
|
||||
public getEditsForFileRename(options: FourSlashInterface.GetEditsForFileRenameOptions): void {
|
||||
const changes = this.languageService.getEditsForFileRename(options.oldPath, options.newPath, this.formatCodeSettings);
|
||||
this.applyChanges(changes);
|
||||
for (const fileName in options.newFileContents) {
|
||||
this.openFile(fileName);
|
||||
this.verifyCurrentFileContent(options.newFileContents[fileName]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function runFourSlashTest(basePath: string, testType: FourSlashTestType, fileName: string) {
|
||||
@@ -4371,6 +4380,10 @@ namespace FourSlashInterface {
|
||||
public allRangesAppearInImplementationList(markerName: string) {
|
||||
this.state.verifyRangesInImplementationList(markerName);
|
||||
}
|
||||
|
||||
public getEditsForFileRename(options: GetEditsForFileRenameOptions) {
|
||||
this.state.getEditsForFileRename(options);
|
||||
}
|
||||
}
|
||||
|
||||
export class Edit {
|
||||
@@ -4713,4 +4726,10 @@ namespace FourSlashInterface {
|
||||
range?: FourSlash.Range;
|
||||
code: number;
|
||||
}
|
||||
|
||||
export interface GetEditsForFileRenameOptions {
|
||||
readonly oldPath: string;
|
||||
readonly newPath: string;
|
||||
readonly newFileContents: { readonly [fileName: string]: string };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -528,6 +528,9 @@ namespace Harness.LanguageService {
|
||||
organizeImports(_scope: ts.OrganizeImportsScope, _formatOptions: ts.FormatCodeSettings): ReadonlyArray<ts.FileTextChanges> {
|
||||
throw new Error("Not supported on the shim.");
|
||||
}
|
||||
getEditsForFileRename(): ReadonlyArray<ts.FileTextChanges> {
|
||||
throw new Error("Not supported on the shim.");
|
||||
}
|
||||
getEmitOutput(fileName: string): ts.EmitOutput {
|
||||
return unwrapJSONCallResult(this.shim.getEmitOutput(fileName));
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
"../services/navigateTo.ts",
|
||||
"../services/navigationBar.ts",
|
||||
"../services/organizeImports.ts",
|
||||
"../services/getEditsForFileRename.ts",
|
||||
"../services/outliningElementsCollector.ts",
|
||||
"../services/patternMatcher.ts",
|
||||
"../services/preProcess.ts",
|
||||
|
||||
@@ -263,6 +263,8 @@ namespace ts.server {
|
||||
CommandNames.GetEditsForRefactorFull,
|
||||
CommandNames.OrganizeImports,
|
||||
CommandNames.OrganizeImportsFull,
|
||||
CommandNames.GetEditsForFileRename,
|
||||
CommandNames.GetEditsForFileRenameFull,
|
||||
];
|
||||
|
||||
it("should not throw when commands are executed with invalid arguments", () => {
|
||||
|
||||
@@ -632,6 +632,10 @@ namespace ts.server {
|
||||
return notImplemented();
|
||||
}
|
||||
|
||||
getEditsForFileRename() {
|
||||
return notImplemented();
|
||||
}
|
||||
|
||||
private convertCodeEditsToTextChanges(edits: protocol.FileCodeEdits[]): FileTextChanges[] {
|
||||
return edits.map(edit => {
|
||||
const fileName = edit.fileName;
|
||||
|
||||
@@ -121,6 +121,9 @@ namespace ts.server.protocol {
|
||||
OrganizeImports = "organizeImports",
|
||||
/* @internal */
|
||||
OrganizeImportsFull = "organizeImports-full",
|
||||
GetEditsForFileRename = "getEditsForFileRename",
|
||||
/* @internal */
|
||||
GetEditsForFileRenameFull = "getEditsForFileRename-full",
|
||||
|
||||
// NOTE: If updating this, be sure to also update `allCommandNames` in `harness/unittests/session.ts`.
|
||||
}
|
||||
@@ -610,6 +613,22 @@ namespace ts.server.protocol {
|
||||
edits: ReadonlyArray<FileCodeEdits>;
|
||||
}
|
||||
|
||||
export interface GetEditsForFileRenameRequest extends Request {
|
||||
command: CommandTypes.GetEditsForFileRename;
|
||||
arguments: GetEditsForFileRenameRequestArgs;
|
||||
}
|
||||
|
||||
// Note: The file from FileRequestArgs is just any file in the project.
|
||||
// We will generate code changes for every file in that project, so the choice is arbitrary.
|
||||
export interface GetEditsForFileRenameRequestArgs extends FileRequestArgs {
|
||||
readonly oldFilePath: string;
|
||||
readonly newFilePath: string;
|
||||
}
|
||||
|
||||
export interface GetEditsForFileRenameResponse extends Response {
|
||||
edits: ReadonlyArray<FileCodeEdits>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Request for the available codefixes at a specific position.
|
||||
*/
|
||||
|
||||
+13
-1
@@ -1665,6 +1665,12 @@ namespace ts.server {
|
||||
}
|
||||
}
|
||||
|
||||
private getEditsForFileRename(args: protocol.GetEditsForFileRenameRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.FileCodeEdits> | ReadonlyArray<FileTextChanges> {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
const changes = project.getLanguageService().getEditsForFileRename(args.oldFilePath, args.newFilePath, this.getFormatOptions(file));
|
||||
return simplifiedResult ? this.mapTextChangesToCodeEdits(project, changes) : changes;
|
||||
}
|
||||
|
||||
private getCodeFixes(args: protocol.CodeFixRequestArgs, simplifiedResult: boolean): ReadonlyArray<protocol.CodeFixAction> | ReadonlyArray<CodeFixAction> {
|
||||
if (args.errorCodes.length === 0) {
|
||||
return undefined;
|
||||
@@ -2118,7 +2124,13 @@ namespace ts.server {
|
||||
},
|
||||
[CommandNames.OrganizeImportsFull]: (request: protocol.OrganizeImportsRequest) => {
|
||||
return this.requiredResponse(this.organizeImports(request.arguments, /*simplifiedResult*/ false));
|
||||
}
|
||||
},
|
||||
[CommandNames.GetEditsForFileRename]: (request: protocol.GetEditsForFileRenameRequest) => {
|
||||
return this.requiredResponse(this.getEditsForFileRename(request.arguments, /*simplifiedResult*/ true));
|
||||
},
|
||||
[CommandNames.GetEditsForFileRenameFull]: (request: protocol.GetEditsForFileRenameRequest) => {
|
||||
return this.requiredResponse(this.getEditsForFileRename(request.arguments, /*simplifiedResult*/ false));
|
||||
},
|
||||
});
|
||||
|
||||
public addProtocolHandler(command: string, handler: (request: protocol.Request) => HandlerResponse) {
|
||||
|
||||
@@ -66,6 +66,7 @@
|
||||
"../services/navigateTo.ts",
|
||||
"../services/navigationBar.ts",
|
||||
"../services/organizeImports.ts",
|
||||
"../services/getEditsForFileRename.ts",
|
||||
"../services/outliningElementsCollector.ts",
|
||||
"../services/patternMatcher.ts",
|
||||
"../services/preProcess.ts",
|
||||
|
||||
@@ -72,6 +72,7 @@
|
||||
"../services/navigateTo.ts",
|
||||
"../services/navigationBar.ts",
|
||||
"../services/organizeImports.ts",
|
||||
"../services/getEditsForFileRename.ts",
|
||||
"../services/outliningElementsCollector.ts",
|
||||
"../services/patternMatcher.ts",
|
||||
"../services/preProcess.ts",
|
||||
|
||||
@@ -39,7 +39,6 @@ namespace ts.codefix {
|
||||
}
|
||||
|
||||
function convertToImportCodeFixContext(context: CodeFixContext, symbolToken: Node, symbolName: string): ImportCodeFixContext {
|
||||
const useCaseSensitiveFileNames = context.host.useCaseSensitiveFileNames ? context.host.useCaseSensitiveFileNames() : false;
|
||||
const { program } = context;
|
||||
const checker = program.getTypeChecker();
|
||||
|
||||
@@ -51,7 +50,7 @@ namespace ts.codefix {
|
||||
checker,
|
||||
compilerOptions: program.getCompilerOptions(),
|
||||
cachedImportDeclarations: [],
|
||||
getCanonicalFileName: createGetCanonicalFileName(useCaseSensitiveFileNames),
|
||||
getCanonicalFileName: createGetCanonicalFileName(hostUsesCaseSensitiveFileNames(context.host)),
|
||||
symbolName,
|
||||
symbolToken,
|
||||
preferences: context.preferences,
|
||||
@@ -547,11 +546,6 @@ namespace ts.codefix {
|
||||
return startsWith(path, "..");
|
||||
}
|
||||
|
||||
function getRelativePath(path: string, directoryPath: string, getCanonicalFileName: GetCanonicalFileName) {
|
||||
const relativePath = getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, /*isAbsolutePathAnUrl*/ false);
|
||||
return !pathIsRelative(relativePath) ? "./" + relativePath : relativePath;
|
||||
}
|
||||
|
||||
function getCodeActionsForAddImport(
|
||||
exportInfos: ReadonlyArray<SymbolExportInfo>,
|
||||
ctx: ImportCodeFixContext,
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
export function getEditsForFileRename(program: Program, oldFilePath: string, newFilePath: string, host: LanguageServiceHost, formatContext: formatting.FormatContext): ReadonlyArray<FileTextChanges> {
|
||||
const pathUpdater = getPathUpdater(oldFilePath, newFilePath, host);
|
||||
return textChanges.ChangeTracker.with({ host, formatContext }, changeTracker => {
|
||||
for (const { sourceFile, toUpdate } of getImportsToUpdate(program, oldFilePath)) {
|
||||
const newPath = pathUpdater(isRef(toUpdate) ? toUpdate.fileName : toUpdate.text);
|
||||
if (newPath !== undefined) {
|
||||
const range = isRef(toUpdate) ? toUpdate : createTextRange(toUpdate.getStart(sourceFile) + 1, toUpdate.end - 1);
|
||||
changeTracker.replaceRangeWithText(sourceFile, range, isRef(toUpdate) ? newPath : removeFileExtension(newPath));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
interface ToUpdate {
|
||||
readonly sourceFile: SourceFile;
|
||||
readonly toUpdate: StringLiteralLike | FileReference;
|
||||
}
|
||||
function isRef(toUpdate: StringLiteralLike | FileReference): toUpdate is FileReference {
|
||||
return "fileName" in toUpdate;
|
||||
}
|
||||
|
||||
function getImportsToUpdate(program: Program, oldFilePath: string): ReadonlyArray<ToUpdate> {
|
||||
const checker = program.getTypeChecker();
|
||||
const result: ToUpdate[] = [];
|
||||
for (const sourceFile of program.getSourceFiles()) {
|
||||
for (const ref of sourceFile.referencedFiles) {
|
||||
if (!program.getSourceFileFromReference(sourceFile, ref) && resolveTripleslashReference(ref.fileName, sourceFile.fileName) === oldFilePath) {
|
||||
result.push({ sourceFile, toUpdate: ref });
|
||||
}
|
||||
}
|
||||
|
||||
for (const importStringLiteral of sourceFile.imports) {
|
||||
// If it resolved to something already, ignore.
|
||||
if (checker.getSymbolAtLocation(importStringLiteral)) continue;
|
||||
|
||||
const resolved = program.getResolvedModuleWithFailedLookupLocationsFromCache(importStringLiteral.text, sourceFile.fileName);
|
||||
if (contains(resolved.failedLookupLocations, oldFilePath)) {
|
||||
result.push({ sourceFile, toUpdate: importStringLiteral });
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getPathUpdater(oldFilePath: string, newFilePath: string, host: LanguageServiceHost): (oldPath: string) => string | undefined {
|
||||
// Get the relative path from old to new location, and append it on to the end of imports and normalize.
|
||||
const rel = getRelativePath(newFilePath, getDirectoryPath(oldFilePath), createGetCanonicalFileName(hostUsesCaseSensitiveFileNames(host)));
|
||||
return oldPath => {
|
||||
if (!pathIsRelative(oldPath)) return;
|
||||
return ensurePathIsRelative(normalizePath(combinePaths(getDirectoryPath(oldPath), rel)));
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1128,7 +1128,6 @@ namespace ts {
|
||||
let lastProjectVersion: string;
|
||||
let lastTypesRootVersion = 0;
|
||||
|
||||
const useCaseSensitivefileNames = host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames();
|
||||
const cancellationToken = new CancellationTokenObject(host.getCancellationToken && host.getCancellationToken());
|
||||
|
||||
const currentDirectory = host.getCurrentDirectory();
|
||||
@@ -1145,7 +1144,8 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitivefileNames);
|
||||
const useCaseSensitiveFileNames = hostUsesCaseSensitiveFileNames(host);
|
||||
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
|
||||
|
||||
function getValidSourceFile(fileName: string): SourceFile {
|
||||
const sourceFile = program.getSourceFile(fileName);
|
||||
@@ -1202,7 +1202,7 @@ namespace ts {
|
||||
getSourceFileByPath: getOrCreateSourceFileByPath,
|
||||
getCancellationToken: () => cancellationToken,
|
||||
getCanonicalFileName,
|
||||
useCaseSensitiveFileNames: () => useCaseSensitivefileNames,
|
||||
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
|
||||
getNewLine: () => getNewLineCharacter(newSettings, () => getNewLineOrDefaultFromHost(host)),
|
||||
getDefaultLibFileName: (options) => host.getDefaultLibFileName(options),
|
||||
writeFile: noop,
|
||||
@@ -1951,6 +1951,10 @@ namespace ts {
|
||||
return OrganizeImports.organizeImports(sourceFile, formatContext, host, program, preferences);
|
||||
}
|
||||
|
||||
function getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings): ReadonlyArray<FileTextChanges> {
|
||||
return ts.getEditsForFileRename(getProgram(), oldFilePath, newFilePath, host, formatting.getFormatContext(formatOptions));
|
||||
}
|
||||
|
||||
function applyCodeActionCommand(action: CodeActionCommand): Promise<ApplyCodeActionCommandResult>;
|
||||
function applyCodeActionCommand(action: CodeActionCommand[]): Promise<ApplyCodeActionCommandResult[]>;
|
||||
function applyCodeActionCommand(action: CodeActionCommand | CodeActionCommand[]): Promise<ApplyCodeActionCommandResult | ApplyCodeActionCommandResult[]>;
|
||||
@@ -2251,6 +2255,7 @@ namespace ts {
|
||||
getCombinedCodeFix,
|
||||
applyCodeActionCommand,
|
||||
organizeImports,
|
||||
getEditsForFileRename,
|
||||
getEmitOutput,
|
||||
getNonBoundSourceFile,
|
||||
getSourceFile,
|
||||
|
||||
@@ -365,8 +365,12 @@ namespace ts.textChanges {
|
||||
this.insertText(sourceFile, token.getStart(sourceFile), text);
|
||||
}
|
||||
|
||||
public replaceRangeWithText(sourceFile: SourceFile, range: TextRange, text: string) {
|
||||
this.changes.push({ kind: ChangeKind.Text, sourceFile, range, text });
|
||||
}
|
||||
|
||||
private insertText(sourceFile: SourceFile, pos: number, text: string): void {
|
||||
this.changes.push({ kind: ChangeKind.Text, sourceFile, range: { pos, end: pos }, text });
|
||||
this.replaceRangeWithText(sourceFile, createTextRange(pos), text);
|
||||
}
|
||||
|
||||
/** Prefer this over replacing a node with another that has a type annotation, as it avoids reformatting the other parts of the node. */
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
"navigateTo.ts",
|
||||
"navigationBar.ts",
|
||||
"organizeImports.ts",
|
||||
"getEditsForFileRename.ts",
|
||||
"outliningElementsCollector.ts",
|
||||
"patternMatcher.ts",
|
||||
"preProcess.ts",
|
||||
|
||||
@@ -334,6 +334,7 @@ namespace ts {
|
||||
getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange, preferences: UserPreferences | undefined): ApplicableRefactorInfo[];
|
||||
getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string, preferences: UserPreferences | undefined): RefactorEditInfo | undefined;
|
||||
organizeImports(scope: OrganizeImportsScope, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): ReadonlyArray<FileTextChanges>;
|
||||
getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings): ReadonlyArray<FileTextChanges>;
|
||||
|
||||
getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput;
|
||||
|
||||
|
||||
@@ -1213,6 +1213,14 @@ namespace ts {
|
||||
? isStringOrNumericLiteral(name.expression) ? name.expression.text : undefined
|
||||
: getTextOfIdentifierOrLiteral(name);
|
||||
}
|
||||
|
||||
export function hostUsesCaseSensitiveFileNames(host: LanguageServiceHost): boolean {
|
||||
return host.useCaseSensitiveFileNames ? host.useCaseSensitiveFileNames() : false;
|
||||
}
|
||||
|
||||
export function hostGetCanonicalFileName(host: LanguageServiceHost): GetCanonicalFileName {
|
||||
return createGetCanonicalFileName(hostUsesCaseSensitiveFileNames(host));
|
||||
}
|
||||
}
|
||||
|
||||
// Display-part writer helpers
|
||||
|
||||
+16
-1
@@ -3402,6 +3402,7 @@ declare namespace ts {
|
||||
set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void;
|
||||
}
|
||||
function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): ModuleResolutionCache;
|
||||
function resolveModuleNameFromCache(moduleName: string, containingFile: string, cache: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations | undefined;
|
||||
function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations;
|
||||
function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations;
|
||||
function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache): ResolvedModuleWithFailedLookupLocations;
|
||||
@@ -4446,6 +4447,7 @@ declare namespace ts {
|
||||
getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange, preferences: UserPreferences | undefined): ApplicableRefactorInfo[];
|
||||
getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string, preferences: UserPreferences | undefined): RefactorEditInfo | undefined;
|
||||
organizeImports(scope: OrganizeImportsScope, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): ReadonlyArray<FileTextChanges>;
|
||||
getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings): ReadonlyArray<FileTextChanges>;
|
||||
getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput;
|
||||
getProgram(): Program;
|
||||
dispose(): void;
|
||||
@@ -5410,7 +5412,8 @@ declare namespace ts.server.protocol {
|
||||
GetSupportedCodeFixes = "getSupportedCodeFixes",
|
||||
GetApplicableRefactors = "getApplicableRefactors",
|
||||
GetEditsForRefactor = "getEditsForRefactor",
|
||||
OrganizeImports = "organizeImports"
|
||||
OrganizeImports = "organizeImports",
|
||||
GetEditsForFileRename = "getEditsForFileRename"
|
||||
}
|
||||
/**
|
||||
* A TypeScript Server message
|
||||
@@ -5806,6 +5809,17 @@ declare namespace ts.server.protocol {
|
||||
interface OrganizeImportsResponse extends Response {
|
||||
edits: ReadonlyArray<FileCodeEdits>;
|
||||
}
|
||||
interface GetEditsForFileRenameRequest extends Request {
|
||||
command: CommandTypes.GetEditsForFileRename;
|
||||
arguments: GetEditsForFileRenameRequestArgs;
|
||||
}
|
||||
interface GetEditsForFileRenameRequestArgs extends FileRequestArgs {
|
||||
readonly oldFilePath: string;
|
||||
readonly newFilePath: string;
|
||||
}
|
||||
interface GetEditsForFileRenameResponse extends Response {
|
||||
edits: ReadonlyArray<FileCodeEdits>;
|
||||
}
|
||||
/**
|
||||
* Request for the available codefixes at a specific position.
|
||||
*/
|
||||
@@ -8322,6 +8336,7 @@ declare namespace ts.server {
|
||||
private getApplicableRefactors;
|
||||
private getEditsForRefactor;
|
||||
private organizeImports;
|
||||
private getEditsForFileRename;
|
||||
private getCodeFixes;
|
||||
private getCombinedCodeFix;
|
||||
private applyCodeActionCommand;
|
||||
|
||||
@@ -3402,6 +3402,7 @@ declare namespace ts {
|
||||
set(directory: string, result: ResolvedModuleWithFailedLookupLocations): void;
|
||||
}
|
||||
function createModuleResolutionCache(currentDirectory: string, getCanonicalFileName: (s: string) => string): ModuleResolutionCache;
|
||||
function resolveModuleNameFromCache(moduleName: string, containingFile: string, cache: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations | undefined;
|
||||
function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations;
|
||||
function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations;
|
||||
function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache): ResolvedModuleWithFailedLookupLocations;
|
||||
@@ -4446,6 +4447,7 @@ declare namespace ts {
|
||||
getApplicableRefactors(fileName: string, positionOrRaneg: number | TextRange, preferences: UserPreferences | undefined): ApplicableRefactorInfo[];
|
||||
getEditsForRefactor(fileName: string, formatOptions: FormatCodeSettings, positionOrRange: number | TextRange, refactorName: string, actionName: string, preferences: UserPreferences | undefined): RefactorEditInfo | undefined;
|
||||
organizeImports(scope: OrganizeImportsScope, formatOptions: FormatCodeSettings, preferences: UserPreferences | undefined): ReadonlyArray<FileTextChanges>;
|
||||
getEditsForFileRename(oldFilePath: string, newFilePath: string, formatOptions: FormatCodeSettings): ReadonlyArray<FileTextChanges>;
|
||||
getEmitOutput(fileName: string, emitOnlyDtsFiles?: boolean): EmitOutput;
|
||||
getProgram(): Program;
|
||||
dispose(): void;
|
||||
|
||||
@@ -345,6 +345,11 @@ declare namespace FourSlashInterface {
|
||||
getSuggestionDiagnostics(expected: ReadonlyArray<Diagnostic>): void;
|
||||
ProjectInfo(expected: string[]): void;
|
||||
allRangesAppearInImplementationList(markerName: string): void;
|
||||
getEditsForFileRename(options: {
|
||||
oldPath: string;
|
||||
newPath: string;
|
||||
newFileContents: { [fileName: string]: string };
|
||||
});
|
||||
}
|
||||
class edit {
|
||||
backspace(count?: number): void;
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
// @Filename: /a.ts
|
||||
/////// <reference path="./src/old.ts" />
|
||||
////import old from "./src/old";
|
||||
|
||||
// @Filename: /src/a.ts
|
||||
/////// <reference path="./old.ts" />
|
||||
////import old from "./old";
|
||||
|
||||
// @Filename: /src/foo/a.ts
|
||||
/////// <reference path="../old.ts" />
|
||||
////import old from "../old";
|
||||
|
||||
verify.getEditsForFileRename({
|
||||
oldPath: "/src/old.ts",
|
||||
newPath: "/src/new.ts",
|
||||
newFileContents: {
|
||||
"/a.ts": '/// <reference path="./src/new.ts" />\nimport old from "./src/new";',
|
||||
"/src/a.ts": '/// <reference path="./new.ts" />\nimport old from "./new";',
|
||||
"/src/foo/a.ts": '/// <reference path="../new.ts" />\nimport old from "../new";',
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user