mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-30 01:04:49 -05:00
Add 'fileToRename' property to RenameInfo (#24702)
* Add 'fileToRename' property to RenameInfo * Update tests * Support directory rename
This commit is contained in:
@@ -397,6 +397,7 @@ namespace ts.server {
|
||||
|
||||
return this.lastRenameEntry = {
|
||||
canRename: body.info.canRename,
|
||||
fileToRename: body.info.fileToRename,
|
||||
displayName: body.info.displayName,
|
||||
fullDisplayName: body.info.fullDisplayName,
|
||||
kind: body.info.kind,
|
||||
|
||||
@@ -420,12 +420,12 @@ namespace FourSlash {
|
||||
}
|
||||
}
|
||||
|
||||
public goToEachRange(action: () => void) {
|
||||
public goToEachRange(action: (range: Range) => void) {
|
||||
const ranges = this.getRanges();
|
||||
assert(ranges.length);
|
||||
for (const range of ranges) {
|
||||
this.selectRange(range);
|
||||
action();
|
||||
action(range);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1525,7 +1525,7 @@ Actual: ${stringify(fullActual)}`);
|
||||
}
|
||||
}
|
||||
|
||||
public verifyRenameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string) {
|
||||
public verifyRenameInfoSucceeded(displayName: string | undefined, fullDisplayName: string | undefined, kind: string | undefined, kindModifiers: string | undefined, fileToRename: string | undefined, expectedRange: Range | undefined): void {
|
||||
const renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition);
|
||||
if (!renameInfo.canRename) {
|
||||
this.raiseError("Rename did not succeed");
|
||||
@@ -1535,12 +1535,15 @@ Actual: ${stringify(fullActual)}`);
|
||||
this.validate("fullDisplayName", fullDisplayName, renameInfo.fullDisplayName);
|
||||
this.validate("kind", kind, renameInfo.kind);
|
||||
this.validate("kindModifiers", kindModifiers, renameInfo.kindModifiers);
|
||||
this.validate("fileToRename", fileToRename, renameInfo.fileToRename);
|
||||
|
||||
if (this.getRanges().length !== 1) {
|
||||
this.raiseError("Expected a single range to be selected in the test file.");
|
||||
if (!expectedRange) {
|
||||
if (this.getRanges().length !== 1) {
|
||||
this.raiseError("Expected a single range to be selected in the test file.");
|
||||
}
|
||||
expectedRange = this.getRanges()[0];
|
||||
}
|
||||
|
||||
const expectedRange = this.getRanges()[0];
|
||||
if (renameInfo.triggerSpan.start !== expectedRange.pos ||
|
||||
ts.textSpanEnd(renameInfo.triggerSpan) !== expectedRange.end) {
|
||||
this.raiseError("Expected triggerSpan [" + expectedRange.pos + "," + expectedRange.end + "). Got [" +
|
||||
@@ -3977,7 +3980,7 @@ namespace FourSlashInterface {
|
||||
this.state.goToRangeStart(range);
|
||||
}
|
||||
|
||||
public eachRange(action: () => void) {
|
||||
public eachRange(action: (range: FourSlash.Range) => void) {
|
||||
this.state.goToEachRange(action);
|
||||
}
|
||||
|
||||
@@ -4456,8 +4459,8 @@ namespace FourSlashInterface {
|
||||
this.state.verifySemanticClassifications(classifications);
|
||||
}
|
||||
|
||||
public renameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string) {
|
||||
this.state.verifyRenameInfoSucceeded(displayName, fullDisplayName, kind, kindModifiers);
|
||||
public renameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string, fileToRename?: string, expectedRange?: FourSlash.Range) {
|
||||
this.state.verifyRenameInfoSucceeded(displayName, fullDisplayName, kind, kindModifiers, fileToRename, expectedRange);
|
||||
}
|
||||
|
||||
public renameInfoFailed(message?: string) {
|
||||
|
||||
@@ -1093,6 +1093,12 @@ namespace ts.server.protocol {
|
||||
*/
|
||||
canRename: boolean;
|
||||
|
||||
/**
|
||||
* File or directory to rename.
|
||||
* If set, `getEditsForFileRename` should be called instead of `findRenameLocations`.
|
||||
*/
|
||||
fileToRename?: string;
|
||||
|
||||
/**
|
||||
* Error message if item can not be renamed.
|
||||
*/
|
||||
|
||||
@@ -1096,7 +1096,7 @@ namespace ts.server {
|
||||
return projectInfo;
|
||||
}
|
||||
|
||||
private getRenameInfo(args: protocol.FileLocationRequestArgs) {
|
||||
private getRenameInfo(args: protocol.FileLocationRequestArgs): RenameInfo {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
const position = this.getPositionInFile(args, file);
|
||||
return project.getLanguageService().getRenameInfo(file, position);
|
||||
|
||||
@@ -25,8 +25,9 @@ namespace ts.Rename {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// Can't rename a module name.
|
||||
if (isStringLiteralLike(node) && tryGetImportFromModuleSpecifier(node)) return undefined;
|
||||
if (isStringLiteralLike(node) && tryGetImportFromModuleSpecifier(node)) {
|
||||
return getRenameInfoForModule(node, sourceFile, symbol);
|
||||
}
|
||||
|
||||
const kind = SymbolDisplay.getSymbolKind(typeChecker, symbol, node);
|
||||
const specifierName = (isImportOrExportSpecifierName(node) || isStringOrNumericLiteralLike(node) && node.parent.kind === SyntaxKind.ComputedPropertyName)
|
||||
@@ -37,9 +38,28 @@ namespace ts.Rename {
|
||||
return getRenameInfoSuccess(displayName, fullDisplayName, kind, SymbolDisplay.getSymbolModifiers(symbol), node, sourceFile);
|
||||
}
|
||||
|
||||
function getRenameInfoForModule(node: StringLiteralLike, sourceFile: SourceFile, moduleSymbol: Symbol): RenameInfo | undefined {
|
||||
const moduleSourceFile = find(moduleSymbol.declarations, isSourceFile);
|
||||
if (!moduleSourceFile) return undefined;
|
||||
const withoutIndex = node.text.endsWith("/index") || node.text.endsWith("/index.js") ? undefined : tryRemoveSuffix(removeFileExtension(moduleSourceFile.fileName), "/index");
|
||||
const name = withoutIndex === undefined ? moduleSourceFile.fileName : withoutIndex;
|
||||
const kind = withoutIndex === undefined ? ScriptElementKind.moduleElement : ScriptElementKind.directory;
|
||||
return {
|
||||
canRename: true,
|
||||
fileToRename: name,
|
||||
kind,
|
||||
displayName: name,
|
||||
localizedErrorMessage: undefined,
|
||||
fullDisplayName: name,
|
||||
kindModifiers: ScriptElementKindModifier.none,
|
||||
triggerSpan: createTriggerSpanForNode(node, sourceFile),
|
||||
};
|
||||
}
|
||||
|
||||
function getRenameInfoSuccess(displayName: string, fullDisplayName: string, kind: ScriptElementKind, kindModifiers: string, node: Node, sourceFile: SourceFile): RenameInfo {
|
||||
return {
|
||||
canRename: true,
|
||||
fileToRename: undefined,
|
||||
kind,
|
||||
displayName,
|
||||
localizedErrorMessage: undefined,
|
||||
|
||||
@@ -784,6 +784,11 @@ namespace ts {
|
||||
|
||||
export interface RenameInfo {
|
||||
canRename: boolean;
|
||||
/**
|
||||
* File or directory to rename.
|
||||
* If set, `getEditsForFileRename` should be called instead of `findRenameLocations`.
|
||||
*/
|
||||
fileToRename?: string;
|
||||
localizedErrorMessage?: string;
|
||||
displayName: string;
|
||||
fullDisplayName: string;
|
||||
|
||||
Reference in New Issue
Block a user