Allow per-file setting for rename default behavior preferences (#29593)
<!-- Thank you for submitting a pull request! Here's a checklist you might find useful. * [ ] There is an associated issue that is labeled 'Bug' or 'help wanted' or is in the Community milestone * [ ] Code is up-to-date with the `master` branch * [ ] You've successfully run `jake runtests` locally * [ ] You've signed the CLA * [ ] There are new or updated unit tests validating the change Refer to CONTRIBUTING.MD for more details. https://github.com/Microsoft/TypeScript/blob/master/CONTRIBUTING.md --> Fixes #29585. #29314 and #29385 made it so their respective settings are only recognized when provided to the host as a whole. This PR makes it so that the relevant settings for the preferences on the file override those of the preferences on the host.
This commit is contained in:
parent
96706a75ed
commit
62cf44cb9b
4 changed files with 112 additions and 6 deletions
|
@ -904,7 +904,7 @@ namespace ts.server {
|
|||
|
||||
getPreferences(file: NormalizedPath): protocol.UserPreferences {
|
||||
const info = this.getScriptInfoForNormalizedPath(file);
|
||||
return info && info.getPreferences() || this.hostConfiguration.preferences;
|
||||
return { ...this.hostConfiguration.preferences, ...info && info.getPreferences() };
|
||||
}
|
||||
|
||||
getHostFormatCodeOptions(): FormatCodeSettings {
|
||||
|
|
|
@ -1178,8 +1178,7 @@ namespace ts.server {
|
|||
private getRenameInfo(args: protocol.FileLocationRequestArgs): RenameInfo {
|
||||
const { file, project } = this.getFileAndProject(args);
|
||||
const position = this.getPositionInFile(args, file);
|
||||
const preferences = this.getHostPreferences();
|
||||
return project.getLanguageService().getRenameInfo(file, position, { allowRenameOfImportPath: preferences.allowRenameOfImportPath });
|
||||
return project.getLanguageService().getRenameInfo(file, position, { allowRenameOfImportPath: this.getPreferences(file).allowRenameOfImportPath });
|
||||
}
|
||||
|
||||
private getProjects(args: protocol.FileRequestArgs, getScriptInfoEnsuringProjectsUptoDate?: boolean, ignoreNoProjectError?: boolean): Projects {
|
||||
|
@ -1234,12 +1233,12 @@ namespace ts.server {
|
|||
{ fileName: args.file, pos: position },
|
||||
!!args.findInStrings,
|
||||
!!args.findInComments,
|
||||
this.getHostPreferences()
|
||||
this.getPreferences(file)
|
||||
);
|
||||
if (!simplifiedResult) return locations;
|
||||
|
||||
const defaultProject = this.getDefaultProject(args);
|
||||
const renameInfo: protocol.RenameInfo = this.mapRenameInfo(defaultProject.getLanguageService().getRenameInfo(file, position, { allowRenameOfImportPath: this.getHostPreferences().allowRenameOfImportPath }), Debug.assertDefined(this.projectService.getScriptInfo(file)));
|
||||
const renameInfo: protocol.RenameInfo = this.mapRenameInfo(defaultProject.getLanguageService().getRenameInfo(file, position, { allowRenameOfImportPath: this.getPreferences(file).allowRenameOfImportPath }), Debug.assertDefined(this.projectService.getScriptInfo(file)));
|
||||
return { info: renameInfo, locs: this.toSpanGroups(locations) };
|
||||
}
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace ts.FindAllReferences {
|
|||
readonly implementations?: boolean;
|
||||
/**
|
||||
* True to opt in for enhanced renaming of shorthand properties and import/export specifiers.
|
||||
* The options controls the behavior for the whole rename operation; it cannot be changed on a per-file basis.
|
||||
* Default is false for backwards compatibility.
|
||||
*/
|
||||
readonly providePrefixAndSuffixTextForRename?: boolean;
|
||||
|
|
|
@ -7,6 +7,7 @@ namespace ts.projectSystem {
|
|||
const session = createSession(createServerHost([aTs, bTs]));
|
||||
openFilesForSession([bTs], session);
|
||||
|
||||
// rename fails with allowRenameOfImportPath disabled
|
||||
const response1 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(bTs, 'a";'));
|
||||
assert.deepEqual<protocol.RenameResponseBody | undefined>(response1, {
|
||||
info: {
|
||||
|
@ -16,6 +17,7 @@ namespace ts.projectSystem {
|
|||
locs: [{ file: bTs.path, locs: [protocolRenameSpanFromSubstring(bTs.content, "./a")] }],
|
||||
});
|
||||
|
||||
// rename succeeds with allowRenameOfImportPath enabled in host
|
||||
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, {
|
||||
|
@ -30,6 +32,23 @@ namespace ts.projectSystem {
|
|||
},
|
||||
locs: [{ file: bTs.path, locs: [protocolRenameSpanFromSubstring(bTs.content, "./a")] }],
|
||||
});
|
||||
|
||||
// rename succeeds with allowRenameOfImportPath enabled in file
|
||||
session.getProjectService().setHostConfiguration({ preferences: { allowRenameOfImportPath: false } });
|
||||
session.getProjectService().setHostConfiguration({ file: "/b.ts", formatOptions: {}, preferences: { allowRenameOfImportPath: true } });
|
||||
const response3 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(bTs, 'a";'));
|
||||
assert.deepEqual<protocol.RenameResponseBody | undefined>(response3, {
|
||||
info: {
|
||||
canRename: true,
|
||||
fileToRename: aTs.path,
|
||||
displayName: aTs.path,
|
||||
fullDisplayName: aTs.path,
|
||||
kind: ScriptElementKind.moduleElement,
|
||||
kindModifiers: "",
|
||||
triggerSpan: protocolTextSpanFromSubstring(bTs.content, "a", { index: 1 }),
|
||||
},
|
||||
locs: [{ file: bTs.path, locs: [protocolRenameSpanFromSubstring(bTs.content, "./a")] }],
|
||||
});
|
||||
});
|
||||
|
||||
it("works with prefixText and suffixText when enabled", () => {
|
||||
|
@ -61,7 +80,7 @@ namespace ts.projectSystem {
|
|||
],
|
||||
});
|
||||
|
||||
// rename with prefixText and suffixText enabled
|
||||
// rename with prefixText and suffixText enabled in host
|
||||
session.getProjectService().setHostConfiguration({ preferences: { providePrefixAndSuffixTextForRename: true } });
|
||||
const response2 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(aTs, "x"));
|
||||
assert.deepEqual<protocol.RenameResponseBody | undefined>(response2, {
|
||||
|
@ -84,6 +103,93 @@ namespace ts.projectSystem {
|
|||
},
|
||||
],
|
||||
});
|
||||
|
||||
// rename with prefixText and suffixText enabled for file
|
||||
session.getProjectService().setHostConfiguration({ preferences: { providePrefixAndSuffixTextForRename: false } });
|
||||
session.getProjectService().setHostConfiguration({ file: "/a.ts", formatOptions: {}, preferences: { providePrefixAndSuffixTextForRename: true } });
|
||||
const response3 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(aTs, "x"));
|
||||
assert.deepEqual<protocol.RenameResponseBody | undefined>(response3, {
|
||||
info: {
|
||||
canRename: true,
|
||||
fileToRename: undefined,
|
||||
displayName: "x",
|
||||
fullDisplayName: "x",
|
||||
kind: ScriptElementKind.constElement,
|
||||
kindModifiers: ScriptElementKindModifier.none,
|
||||
triggerSpan: protocolTextSpanFromSubstring(aTs.content, "x"),
|
||||
},
|
||||
locs: [
|
||||
{
|
||||
file: aTs.path,
|
||||
locs: [
|
||||
protocolRenameSpanFromSubstring(aTs.content, "x"),
|
||||
protocolRenameSpanFromSubstring(aTs.content, "x", { index: 1 }, { prefixText: "x: " }),
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("rename behavior is based on file of rename initiation", () => {
|
||||
const aTs: File = { path: "/a.ts", content: "const x = 1; export { x };" };
|
||||
const bTs: File = { path: "/b.ts", content: `import { x } from "./a"; const y = x + 1;` };
|
||||
const host = createServerHost([aTs, bTs]);
|
||||
const session = createSession(host);
|
||||
openFilesForSession([aTs, bTs], session);
|
||||
|
||||
// rename from file with prefixText and suffixText enabled
|
||||
session.getProjectService().setHostConfiguration({ file: "/a.ts", formatOptions: {}, preferences: { providePrefixAndSuffixTextForRename: true } });
|
||||
const response1 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(aTs, "x"));
|
||||
assert.deepEqual<protocol.RenameResponseBody | undefined>(response1, {
|
||||
info: {
|
||||
canRename: true,
|
||||
fileToRename: undefined,
|
||||
displayName: "x",
|
||||
fullDisplayName: "x",
|
||||
kind: ScriptElementKind.constElement,
|
||||
kindModifiers: ScriptElementKindModifier.none,
|
||||
triggerSpan: protocolTextSpanFromSubstring(aTs.content, "x"),
|
||||
},
|
||||
locs: [
|
||||
{
|
||||
file: aTs.path,
|
||||
locs: [
|
||||
protocolRenameSpanFromSubstring(aTs.content, "x"),
|
||||
protocolRenameSpanFromSubstring(aTs.content, "x", { index: 2 }, { suffixText: " as x" }),
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
|
||||
// rename from file with prefixText and suffixText disabled
|
||||
const response2 = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(bTs, "x"));
|
||||
assert.deepEqual<protocol.RenameResponseBody | undefined>(response2, {
|
||||
info: {
|
||||
canRename: true,
|
||||
fileToRename: undefined,
|
||||
displayName: "x",
|
||||
fullDisplayName: "x",
|
||||
kind: ScriptElementKind.alias,
|
||||
kindModifiers: ScriptElementKindModifier.none,
|
||||
triggerSpan: protocolTextSpanFromSubstring(bTs.content, "x"),
|
||||
},
|
||||
locs: [
|
||||
{
|
||||
file: bTs.path,
|
||||
locs: [
|
||||
protocolRenameSpanFromSubstring(bTs.content, "x"),
|
||||
protocolRenameSpanFromSubstring(bTs.content, "x", { index: 1 })
|
||||
]
|
||||
},
|
||||
{
|
||||
file: aTs.path,
|
||||
locs: [
|
||||
protocolRenameSpanFromSubstring(aTs.content, "x"),
|
||||
protocolRenameSpanFromSubstring(aTs.content, "x", { index: 2 }),
|
||||
],
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue