mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Add user preference to opt-in to renaming import paths
This commit is contained in:
parent
c146d1f8af
commit
d029fae35c
@ -384,7 +384,8 @@ namespace ts.server {
|
||||
return notImplemented();
|
||||
}
|
||||
|
||||
getRenameInfo(fileName: string, position: number, findInStrings?: boolean, findInComments?: boolean): RenameInfo {
|
||||
getRenameInfo(fileName: string, position: number, _options?: RenameInfoOptions, findInStrings?: boolean, findInComments?: boolean): RenameInfo {
|
||||
// not using options they should be sent with a RenameInfo request, which this function does not perform
|
||||
const args: protocol.RenameRequestArgs = { ...this.createFileLocationRequestArgs(fileName, position), findInStrings, findInComments };
|
||||
|
||||
const request = this.processRequest<protocol.RenameRequest>(CommandNames.Rename, args);
|
||||
@ -428,7 +429,7 @@ namespace ts.server {
|
||||
this.lastRenameEntry.inputs.position !== position ||
|
||||
this.lastRenameEntry.inputs.findInStrings !== findInStrings ||
|
||||
this.lastRenameEntry.inputs.findInComments !== findInComments) {
|
||||
this.getRenameInfo(fileName, position, findInStrings, findInComments);
|
||||
this.getRenameInfo(fileName, position, { allowRenameOfImportPath: true }, findInStrings, findInComments);
|
||||
}
|
||||
|
||||
return this.lastRenameEntry!.locations;
|
||||
|
||||
@ -1308,8 +1308,9 @@ Actual: ${stringify(fullActual)}`);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
public verifyRenameInfoSucceeded(displayName: string | undefined, fullDisplayName: string | undefined, kind: string | undefined, kindModifiers: string | undefined, fileToRename: string | undefined, expectedRange: Range | undefined, allowRenameOfImportPath: boolean | undefined): void {
|
||||
allowRenameOfImportPath = allowRenameOfImportPath === undefined ? true : allowRenameOfImportPath;
|
||||
const renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition, { allowRenameOfImportPath });
|
||||
if (!renameInfo.canRename) {
|
||||
throw this.raiseError("Rename did not succeed");
|
||||
}
|
||||
@ -1334,8 +1335,9 @@ Actual: ${stringify(fullActual)}`);
|
||||
}
|
||||
}
|
||||
|
||||
public verifyRenameInfoFailed(message?: string) {
|
||||
const renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition);
|
||||
public verifyRenameInfoFailed(message?: string, allowRenameOfImportPath?: boolean) {
|
||||
allowRenameOfImportPath = allowRenameOfImportPath === undefined ? true : allowRenameOfImportPath;
|
||||
const renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition, { allowRenameOfImportPath });
|
||||
if (renameInfo.canRename) {
|
||||
throw this.raiseError("Rename was expected to fail");
|
||||
}
|
||||
@ -4091,12 +4093,12 @@ namespace FourSlashInterface {
|
||||
this.state.verifySemanticClassifications(classifications);
|
||||
}
|
||||
|
||||
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 renameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string, fileToRename?: string, expectedRange?: FourSlash.Range, allowRenameOfImportPath?: boolean) {
|
||||
this.state.verifyRenameInfoSucceeded(displayName, fullDisplayName, kind, kindModifiers, fileToRename, expectedRange, allowRenameOfImportPath);
|
||||
}
|
||||
|
||||
public renameInfoFailed(message?: string) {
|
||||
this.state.verifyRenameInfoFailed(message);
|
||||
public renameInfoFailed(message?: string, allowRenameOfImportPath?: boolean) {
|
||||
this.state.verifyRenameInfoFailed(message, allowRenameOfImportPath);
|
||||
}
|
||||
|
||||
public renameLocations(startRanges: ArrayOrSingle<FourSlash.Range>, options: RenameLocationsOptions) {
|
||||
|
||||
@ -469,8 +469,8 @@ namespace Harness.LanguageService {
|
||||
getSignatureHelpItems(fileName: string, position: number, options: ts.SignatureHelpItemsOptions | undefined): ts.SignatureHelpItems {
|
||||
return unwrapJSONCallResult(this.shim.getSignatureHelpItems(fileName, position, options));
|
||||
}
|
||||
getRenameInfo(fileName: string, position: number): ts.RenameInfo {
|
||||
return unwrapJSONCallResult(this.shim.getRenameInfo(fileName, position));
|
||||
getRenameInfo(fileName: string, position: number, options?: ts.RenameInfoOptions): ts.RenameInfo {
|
||||
return unwrapJSONCallResult(this.shim.getRenameInfo(fileName, position, options));
|
||||
}
|
||||
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): ts.RenameLocation[] {
|
||||
return unwrapJSONCallResult(this.shim.findRenameLocations(fileName, position, findInStrings, findInComments));
|
||||
|
||||
@ -2905,6 +2905,7 @@ namespace ts.server.protocol {
|
||||
readonly importModuleSpecifierPreference?: "relative" | "non-relative";
|
||||
readonly allowTextChangesInNewFiles?: boolean;
|
||||
readonly lazyConfiguredProjectsFromExternalProject?: boolean;
|
||||
readonly allowRenameOfImportPath?: boolean;
|
||||
}
|
||||
|
||||
export interface CompilerOptions {
|
||||
|
||||
@ -1177,7 +1177,8 @@ namespace ts.server {
|
||||
private getRenameInfo(args: protocol.FileLocationRequestArgs): RenameInfo {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
const position = this.getPositionInFile(args, file);
|
||||
return project.getLanguageService().getRenameInfo(file, position);
|
||||
const preferences = this.getHostPreferences();
|
||||
return project.getLanguageService().getRenameInfo(file, position, { allowRenameOfImportPath: preferences.allowRenameOfImportPath });
|
||||
}
|
||||
|
||||
private getProjects(args: protocol.FileRequestArgs, getScriptInfoEnsuringProjectsUptoDate?: boolean, ignoreNoProjectError?: boolean): Projects {
|
||||
@ -1236,7 +1237,7 @@ namespace ts.server {
|
||||
if (!simplifiedResult) return locations;
|
||||
|
||||
const defaultProject = this.getDefaultProject(args);
|
||||
const renameInfo: protocol.RenameInfo = this.mapRenameInfo(defaultProject.getLanguageService().getRenameInfo(file, position), Debug.assertDefined(this.projectService.getScriptInfo(file)));
|
||||
const renameInfo: protocol.RenameInfo = this.mapRenameInfo(defaultProject.getLanguageService().getRenameInfo(file, position, { allowRenameOfImportPath: this.getHostPreferences().allowRenameOfImportPath }), Debug.assertDefined(this.projectService.getScriptInfo(file)));
|
||||
return { info: renameInfo, locs: this.toSpanGroups(locations) };
|
||||
}
|
||||
|
||||
|
||||
@ -1,14 +1,14 @@
|
||||
/* @internal */
|
||||
namespace ts.Rename {
|
||||
export function getRenameInfo(program: Program, sourceFile: SourceFile, position: number): RenameInfo {
|
||||
export function getRenameInfo(program: Program, sourceFile: SourceFile, position: number, options?: RenameInfoOptions): RenameInfo {
|
||||
const node = getTouchingPropertyName(sourceFile, position);
|
||||
const renameInfo = node && nodeIsEligibleForRename(node)
|
||||
? getRenameInfoForNode(node, program.getTypeChecker(), sourceFile, declaration => program.isSourceFileDefaultLibrary(declaration.getSourceFile()))
|
||||
? getRenameInfoForNode(node, program.getTypeChecker(), sourceFile, options || {}, declaration => program.isSourceFileDefaultLibrary(declaration.getSourceFile()))
|
||||
: undefined;
|
||||
return renameInfo || getRenameInfoError(Diagnostics.You_cannot_rename_this_element);
|
||||
}
|
||||
|
||||
function getRenameInfoForNode(node: Node, typeChecker: TypeChecker, sourceFile: SourceFile, isDefinedInLibraryFile: (declaration: Node) => boolean): RenameInfo | undefined {
|
||||
function getRenameInfoForNode(node: Node, typeChecker: TypeChecker, sourceFile: SourceFile, options: RenameInfoOptions, isDefinedInLibraryFile: (declaration: Node) => boolean): RenameInfo | undefined {
|
||||
const symbol = typeChecker.getSymbolAtLocation(node);
|
||||
if (!symbol) return;
|
||||
// Only allow a symbol to be renamed if it actually has at least one declaration.
|
||||
@ -26,7 +26,7 @@ namespace ts.Rename {
|
||||
}
|
||||
|
||||
if (isStringLiteralLike(node) && tryGetImportFromModuleSpecifier(node)) {
|
||||
return getRenameInfoForModule(node, sourceFile, symbol);
|
||||
return options.allowRenameOfImportPath ? getRenameInfoForModule(node, sourceFile, symbol) : undefined;
|
||||
}
|
||||
|
||||
const kind = SymbolDisplay.getSymbolKind(typeChecker, symbol, node);
|
||||
|
||||
@ -2062,9 +2062,9 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getRenameInfo(fileName: string, position: number): RenameInfo {
|
||||
function getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): RenameInfo {
|
||||
synchronizeHostData();
|
||||
return Rename.getRenameInfo(program, getValidSourceFile(fileName), position);
|
||||
return Rename.getRenameInfo(program, getValidSourceFile(fileName), position, options);
|
||||
}
|
||||
|
||||
function getRefactorContext(file: SourceFile, positionOrRange: number | TextRange, preferences: UserPreferences, formatOptions?: FormatCodeSettings): RefactorContext {
|
||||
|
||||
@ -164,7 +164,7 @@ namespace ts {
|
||||
* Returns a JSON-encoded value of the type:
|
||||
* { canRename: boolean, localizedErrorMessage: string, displayName: string, fullDisplayName: string, kind: string, kindModifiers: string, triggerSpan: { start; length } }
|
||||
*/
|
||||
getRenameInfo(fileName: string, position: number): string;
|
||||
getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): string;
|
||||
|
||||
/**
|
||||
* Returns a JSON-encoded value of the type:
|
||||
@ -831,10 +831,10 @@ namespace ts {
|
||||
);
|
||||
}
|
||||
|
||||
public getRenameInfo(fileName: string, position: number): string {
|
||||
public getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): string {
|
||||
return this.forwardJSONCall(
|
||||
`getRenameInfo('${fileName}', ${position})`,
|
||||
() => this.languageService.getRenameInfo(fileName, position)
|
||||
() => this.languageService.getRenameInfo(fileName, position, options)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -294,7 +294,7 @@ namespace ts {
|
||||
|
||||
getSignatureHelpItems(fileName: string, position: number, options: SignatureHelpItemsOptions | undefined): SignatureHelpItems | undefined;
|
||||
|
||||
getRenameInfo(fileName: string, position: number): RenameInfo;
|
||||
getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): RenameInfo;
|
||||
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): ReadonlyArray<RenameLocation> | undefined;
|
||||
|
||||
getDefinitionAtPosition(fileName: string, position: number): ReadonlyArray<DefinitionInfo> | undefined;
|
||||
@ -848,6 +848,10 @@ namespace ts {
|
||||
localizedErrorMessage: string;
|
||||
}
|
||||
|
||||
export interface RenameInfoOptions {
|
||||
readonly allowRenameOfImportPath?: boolean;
|
||||
}
|
||||
|
||||
export interface SignatureHelpParameter {
|
||||
name: string;
|
||||
documentation: SymbolDisplayPart[];
|
||||
|
||||
@ -7,8 +7,18 @@ namespace ts.projectSystem {
|
||||
const session = createSession(createServerHost([aTs, bTs]));
|
||||
openFilesForSession([bTs], session);
|
||||
|
||||
const response = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(bTs, 'a";'));
|
||||
assert.deepEqual<protocol.RenameResponseBody | undefined>(response, {
|
||||
const response1 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(bTs, 'a";'));
|
||||
assert.deepEqual<protocol.RenameResponseBody | undefined>(response1, {
|
||||
info: {
|
||||
canRename: false,
|
||||
localizedErrorMessage: "You cannot rename this element."
|
||||
},
|
||||
locs: [{ file: bTs.path, locs: [protocolRenameSpanFromSubstring(bTs.content, "./a")] }],
|
||||
});
|
||||
|
||||
session.getProjectService().setHostConfiguration({ preferences: { allowRenameOfImportPath: true } });
|
||||
const response2 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(bTs, 'a";'));
|
||||
assert.deepEqual<protocol.RenameResponseBody | undefined>(response2, {
|
||||
info: {
|
||||
canRename: true,
|
||||
fileToRename: aTs.path,
|
||||
|
||||
@ -4706,7 +4706,7 @@ declare namespace ts {
|
||||
getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan | undefined;
|
||||
getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan | undefined;
|
||||
getSignatureHelpItems(fileName: string, position: number, options: SignatureHelpItemsOptions | undefined): SignatureHelpItems | undefined;
|
||||
getRenameInfo(fileName: string, position: number): RenameInfo;
|
||||
getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): RenameInfo;
|
||||
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): ReadonlyArray<RenameLocation> | undefined;
|
||||
getDefinitionAtPosition(fileName: string, position: number): ReadonlyArray<DefinitionInfo> | undefined;
|
||||
getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined;
|
||||
@ -5150,6 +5150,9 @@ declare namespace ts {
|
||||
canRename: false;
|
||||
localizedErrorMessage: string;
|
||||
}
|
||||
interface RenameInfoOptions {
|
||||
readonly allowRenameOfImportPath?: boolean;
|
||||
}
|
||||
interface SignatureHelpParameter {
|
||||
name: string;
|
||||
documentation: SymbolDisplayPart[];
|
||||
@ -7923,6 +7926,7 @@ declare namespace ts.server.protocol {
|
||||
readonly importModuleSpecifierPreference?: "relative" | "non-relative";
|
||||
readonly allowTextChangesInNewFiles?: boolean;
|
||||
readonly lazyConfiguredProjectsFromExternalProject?: boolean;
|
||||
readonly allowRenameOfImportPath?: boolean;
|
||||
}
|
||||
interface CompilerOptions {
|
||||
allowJs?: boolean;
|
||||
|
||||
@ -4706,7 +4706,7 @@ declare namespace ts {
|
||||
getNameOrDottedNameSpan(fileName: string, startPos: number, endPos: number): TextSpan | undefined;
|
||||
getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan | undefined;
|
||||
getSignatureHelpItems(fileName: string, position: number, options: SignatureHelpItemsOptions | undefined): SignatureHelpItems | undefined;
|
||||
getRenameInfo(fileName: string, position: number): RenameInfo;
|
||||
getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): RenameInfo;
|
||||
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): ReadonlyArray<RenameLocation> | undefined;
|
||||
getDefinitionAtPosition(fileName: string, position: number): ReadonlyArray<DefinitionInfo> | undefined;
|
||||
getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined;
|
||||
@ -5150,6 +5150,9 @@ declare namespace ts {
|
||||
canRename: false;
|
||||
localizedErrorMessage: string;
|
||||
}
|
||||
interface RenameInfoOptions {
|
||||
readonly allowRenameOfImportPath?: boolean;
|
||||
}
|
||||
interface SignatureHelpParameter {
|
||||
name: string;
|
||||
documentation: SymbolDisplayPart[];
|
||||
|
||||
@ -27,4 +27,5 @@ verify.renameLocations(r2, [r0, r1, r2]);
|
||||
for (const range of [r3b, r4b]) {
|
||||
goTo.rangeStart(range);
|
||||
verify.renameInfoSucceeded(/*displayName*/ "/a.ts", /*fullDisplayName*/ "/a.ts", /*kind*/ "module", /*kindModifiers*/ "", /*fileToRename*/ "/a.ts", range);
|
||||
verify.renameInfoFailed("You cannot rename this element.", /*allowRenameOfImportPath*/ false);
|
||||
}
|
||||
|
||||
@ -282,8 +282,8 @@ declare namespace FourSlashInterface {
|
||||
text: string;
|
||||
textSpan?: TextSpan;
|
||||
}[]): void;
|
||||
renameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string, fileToRename?: string, range?: Range): void;
|
||||
renameInfoFailed(message?: string): void;
|
||||
renameInfoSucceeded(displayName?: string, fullDisplayName?: string, kind?: string, kindModifiers?: string, fileToRename?: string, range?: Range, allowRenameOfImportPath?: boolean): void;
|
||||
renameInfoFailed(message?: string, allowRenameOfImportPath?: boolean): void;
|
||||
renameLocations(startRanges: ArrayOrSingle<Range>, options: RenameLocationsOptions): void;
|
||||
|
||||
/** Verify the quick info available at the current marker. */
|
||||
|
||||
@ -27,6 +27,7 @@ goTo.eachRange(range => {
|
||||
const name = target === "dir" ? "/dir" : target === "dir/index" ? "/dir/index.ts" : "/a.ts";
|
||||
const kind = target === "dir" ? "directory" : "module";
|
||||
verify.renameInfoSucceeded(/*displayName*/ name, /*fullDisplayName*/ name, /*kind*/ kind, /*kindModifiers*/ "", /*fileToRename*/ name, range);
|
||||
verify.renameInfoFailed("You cannot rename this element.", /*allowRenameOfImportPath*/ false);
|
||||
});
|
||||
|
||||
goTo.marker("global");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user