Rename to be smarter

This commit is contained in:
Andrew Branch
2019-04-18 16:23:06 -07:00
parent f0f7d82d7a
commit d8936fd290
14 changed files with 76 additions and 49 deletions

View File

@@ -424,7 +424,7 @@ namespace ts.server {
return renameInfo;
}
getSelectionRange() {
getSmartSelectionRange() {
return notImplemented();
}

View File

@@ -472,8 +472,8 @@ namespace Harness.LanguageService {
getRenameInfo(fileName: string, position: number, options?: ts.RenameInfoOptions): ts.RenameInfo {
return unwrapJSONCallResult(this.shim.getRenameInfo(fileName, position, options));
}
getSelectionRange(fileName: string, position: number): ts.SelectionRange {
return unwrapJSONCallResult(this.shim.getSelectionRange(fileName, position));
getSmartSelectionRange(fileName: string, position: number): ts.SelectionRange {
return unwrapJSONCallResult(this.shim.getSmartSelectionRange(fileName, position));
}
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): ts.RenameLocation[] {
return unwrapJSONCallResult(this.shim.findRenameLocations(fileName, position, findInStrings, findInComments, providePrefixAndSuffixTextForRename));

View File

@@ -2059,14 +2059,14 @@ namespace ts.server {
this.projectService.configurePlugin(args);
}
private getSelectionRange(args: protocol.SelectionRangeRequestArgs, simplifiedResult: boolean) {
private getSmartSelectionRange(args: protocol.SelectionRangeRequestArgs, simplifiedResult: boolean) {
const { locations } = args;
const { file, languageService } = this.getFileAndLanguageServiceForSyntacticOperation(args);
const scriptInfo = Debug.assertDefined(this.projectService.getScriptInfo(file));
return map(locations, location => {
const pos = this.getPosition(location, scriptInfo);
const selectionRange = languageService.getSelectionRange(file, pos);
const selectionRange = languageService.getSmartSelectionRange(file, pos);
return simplifiedResult ? this.mapSelectionRange(selectionRange, scriptInfo) : selectionRange;
});
}
@@ -2438,10 +2438,10 @@ namespace ts.server {
return this.notRequired();
},
[CommandNames.SelectionRange]: (request: protocol.SelectionRangeRequest) => {
return this.requiredResponse(this.getSelectionRange(request.arguments, /*simplifiedResult*/ true));
return this.requiredResponse(this.getSmartSelectionRange(request.arguments, /*simplifiedResult*/ true));
},
[CommandNames.SelectionRangeFull]: (request: protocol.SelectionRangeRequest) => {
return this.requiredResponse(this.getSelectionRange(request.arguments, /*simplifiedResult*/ false));
return this.requiredResponse(this.getSmartSelectionRange(request.arguments, /*simplifiedResult*/ false));
},
});

View File

@@ -2087,8 +2087,8 @@ namespace ts {
};
}
function getSelectionRange(fileName: string, position: number): SelectionRange {
return SelectionRange.getSelectionRange(position, syntaxTreeCache.getCurrentSourceFile(fileName));
function getSmartSelectionRange(fileName: string, position: number): SelectionRange {
return SmartSelectionRange.getSmartSelectionRange(position, syntaxTreeCache.getCurrentSourceFile(fileName));
}
function getApplicableRefactors(fileName: string, positionOrRange: number | TextRange, preferences: UserPreferences = emptyOptions): ApplicableRefactorInfo[] {
@@ -2138,7 +2138,7 @@ namespace ts {
getBreakpointStatementAtPosition,
getNavigateToItems,
getRenameInfo,
getSelectionRange,
getSmartSelectionRange,
findRenameLocations,
getNavigationBarItems,
getNavigationTree,

View File

@@ -165,7 +165,7 @@ namespace ts {
* { canRename: boolean, localizedErrorMessage: string, displayName: string, fullDisplayName: string, kind: string, kindModifiers: string, triggerSpan: { start; length } }
*/
getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): string;
getSelectionRange(fileName: string, position: number): string;
getSmartSelectionRange(fileName: string, position: number): string;
/**
* Returns a JSON-encoded value of the type:
@@ -839,10 +839,10 @@ namespace ts {
);
}
public getSelectionRange(fileName: string, position: number): string {
public getSmartSelectionRange(fileName: string, position: number): string {
return this.forwardJSONCall(
`getSelectionRange('${fileName}', ${position})`,
() => this.languageService.getSelectionRange(fileName, position)
`getSmartSelectionRange('${fileName}', ${position})`,
() => this.languageService.getSmartSelectionRange(fileName, position)
);
}

View File

@@ -1,6 +1,6 @@
/* @internal */
namespace ts.SelectionRange {
export function getSelectionRange(pos: number, sourceFile: SourceFile): SelectionRange {
namespace ts.SmartSelectionRange {
export function getSmartSelectionRange(pos: number, sourceFile: SourceFile): SelectionRange {
let selectionRange: SelectionRange = {
textSpan: createTextSpanFromBounds(sourceFile.getFullStart(), sourceFile.getEnd())
};

View File

@@ -28,7 +28,7 @@
"patternMatcher.ts",
"preProcess.ts",
"rename.ts",
"selectionRange.ts",
"smartSelection.ts",
"signatureHelp.ts",
"sourcemaps.ts",
"suggestionDiagnostics.ts",

View File

@@ -297,7 +297,7 @@ namespace ts {
getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): RenameInfo;
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): ReadonlyArray<RenameLocation> | undefined;
getSelectionRange(fileName: string, position: number): SelectionRange;
getSmartSelectionRange(fileName: string, position: number): SelectionRange;
getDefinitionAtPosition(fileName: string, position: number): ReadonlyArray<DefinitionInfo> | undefined;
getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined;

View File

@@ -4,7 +4,7 @@ namespace ts.projectSystem {
const host = createServerHost([file, libFile]);
const session = createSession(host);
openFilesForSession([file], session);
return function getSelectionRange(locations: protocol.SelectionRangeRequestArgs["locations"]) {
return function getSmartSelectionRange(locations: protocol.SelectionRangeRequestArgs["locations"]) {
return executeSessionRequest<protocol.SelectionRangeRequest, protocol.SelectionRangeResponse>(
session,
CommandNames.SelectionRange,
@@ -14,7 +14,7 @@ namespace ts.projectSystem {
describe("unittests:: tsserver:: selectionRange", () => {
it("works for simple JavaScript", () => {
const getSelectionRange = setup("/file.js", `
const getSmartSelectionRange = setup("/file.js", `
class Foo {
bar(a, b) {
if (a === b) {
@@ -24,7 +24,7 @@ class Foo {
}
}`);
const locations = getSelectionRange([
const locations = getSmartSelectionRange([
{
line: 4,
offset: 13,
@@ -87,14 +87,14 @@ class Foo {
});
it("works for simple TypeScript", () => {
const getSelectionRange = setup("/file.ts", `
const getSmartSelectionRange = setup("/file.ts", `
export interface IService {
_serviceBrand: any;
open(host: number, data: any): Promise<any>;
bar(): void
}`);
const locations = getSelectionRange([
const locations = getSmartSelectionRange([
{ line: 5, offset: 12 }, // ho/**/st
{ line: 6, offset: 16 }, // void/**/
]);
@@ -136,10 +136,10 @@ export interface IService {
});
it("works for complex TypeScript", () => {
const getSelectionRange = setup("/file.ts", `
const getSmartSelectionRange = setup("/file.ts", `
type X<T, P> = IsExactlyAny<P> extends true ? T : ({ [K in keyof P]: IsExactlyAny<P[K]> extends true ? K extends keyof T ? T[K] : P[K] : P[K]; } & Pick<T, Exclude<keyof T, keyof P>>)
`);
const locations = getSelectionRange([
const locations = getSmartSelectionRange([
{
line: 2,
offset: 133,
@@ -195,13 +195,13 @@ type X<T, P> = IsExactlyAny<P> extends true ? T : ({ [K in keyof P]: IsExactlyAn
});
it("works for object types", () => {
const getSelectionRange = setup("/file.js", `
const getSmartSelectionRange = setup("/file.js", `
type X = {
foo?: string;
readonly bar: { x: number };
meh
}`);
const locations = getSelectionRange([
const locations = getSmartSelectionRange([
{ line: 3, offset: 5 },
{ line: 4, offset: 5 },
{ line: 4, offset: 14 },
@@ -285,8 +285,8 @@ type X = {
it("works for string literals and template strings", () => {
// tslint:disable-next-line:no-invalid-template-strings
const getSelectionRange = setup("/file.ts", "`a b ${\n 'c'\n} d`");
const locations = getSelectionRange([
const getSmartSelectionRange = setup("/file.ts", "`a b ${\n 'c'\n} d`");
const locations = getSmartSelectionRange([
{ line: 2, offset: 4 },
{ line: 1, offset: 4 },
]);
@@ -327,13 +327,13 @@ type X = {
});
it("works for ES2015 import lists", () => {
const getSelectionRange = setup("/file.ts", `
const getSmartSelectionRange = setup("/file.ts", `
import { x as y, z } from './z';
import { b } from './';
console.log(1);`);
const locations = getSelectionRange([{ line: 2, offset: 10 }]);
const locations = getSmartSelectionRange([{ line: 2, offset: 10 }]);
assert.deepEqual(locations, [
{
textSpan: { // x
@@ -367,10 +367,10 @@ console.log(1);`);
});
it("works for complex mapped types", () => {
const getSelectionRange = setup("/file.ts", `
const getSmartSelectionRange = setup("/file.ts", `
type M = { -readonly [K in keyof any]-?: any };`);
const locations = getSelectionRange([
const locations = getSmartSelectionRange([
{ line: 2, offset: 12 }, // -readonly
{ line: 2, offset: 14 }, // eadonly
{ line: 2, offset: 22 }, // [
@@ -476,10 +476,10 @@ type M = { -readonly [K in keyof any]-?: any };`);
});
it("works for parameters", () => {
const getSelectionRange = setup("/file.ts", `
const getSmartSelectionRange = setup("/file.ts", `
function f(p, q?, ...r: any[] = []) {}`);
const locations = getSelectionRange([
const locations = getSmartSelectionRange([
{ line: 2, offset: 12 }, // p
{ line: 2, offset: 15 }, // q
{ line: 2, offset: 19 }, // ...
@@ -537,9 +537,9 @@ function f(p, q?, ...r: any[] = []) {}`);
});
it("works for binding elements", () => {
const getSelectionRange = setup("/file.ts", `
const getSmartSelectionRange = setup("/file.ts", `
const { x, y: a, ...zs = {} } = {};`);
const locations = getSelectionRange([
const locations = getSmartSelectionRange([
{ line: 2, offset: 9 }, // x
{ line: 2, offset: 15 }, // a
{ line: 2, offset: 21 }, // zs
@@ -578,12 +578,12 @@ const { x, y: a, ...zs = {} } = {};`);
});
it("consumes all whitespace in a multi-line function parameter list", () => {
const getSelectionRange = setup("/file.ts", `
const getSmartSelectionRange = setup("/file.ts", `
function f(
a,
b
) {}`);
const locations = getSelectionRange([{ line: 4, offset: 5 }]); // b
const locations = getSmartSelectionRange([{ line: 4, offset: 5 }]); // b
assert.deepEqual(locations, [{
textSpan: { // b
start: { line: 4, offset: 5 },
@@ -604,8 +604,8 @@ function f(
});
it("snaps to nodes directly behind the cursor instead of trivia ahead of the cursor", () => {
const getSelectionRange = setup("/file.ts", `let x: string`);
const locations = getSelectionRange([{ line: 1, offset: 4 }]);
const getSmartSelectionRange = setup("/file.ts", `let x: string`);
const locations = getSmartSelectionRange([{ line: 1, offset: 4 }]);
assert.deepEqual(locations![0].textSpan, {
start: { line: 1, offset: 1 },
end: { line: 1, offset: 4 },
@@ -613,7 +613,7 @@ function f(
});
it("creates a stop for JSDoc ranges", () => {
const getSelectionRange = setup("/file.js", "" +
const getSmartSelectionRange = setup("/file.js", "" +
`// Not a JSDoc comment
/**
* @param {number} x The number to square
@@ -621,7 +621,7 @@ function f(
function square(x) {
return x * x;
}`);
const locations = getSelectionRange([{ line: 5, offset: 10 }]); // square(x)
const locations = getSmartSelectionRange([{ line: 5, offset: 10 }]); // square(x)
assert.deepEqual(locations, [{
textSpan: { // square
start: { line: 5 , offset: 10 },
@@ -641,8 +641,8 @@ function square(x) {
});
it("skips lone VariableDeclarations in a declaration list", () => {
const getSelectionRange = setup("/file.ts", `const x = 3;`);
const locations = getSelectionRange([{ line: 1, offset: 7 }]); // x
const getSmartSelectionRange = setup("/file.ts", `const x = 3;`);
const locations = getSmartSelectionRange([{ line: 1, offset: 7 }]); // x
assert.deepEqual(locations, [{
textSpan: {
start: { line: 1, offset: 7 },

View File

@@ -4788,6 +4788,7 @@ declare namespace ts {
getSignatureHelpItems(fileName: string, position: number, options: SignatureHelpItemsOptions | undefined): SignatureHelpItems | undefined;
getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): RenameInfo;
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): ReadonlyArray<RenameLocation> | undefined;
getSmartSelectionRange(fileName: string, position: number): SelectionRange;
getDefinitionAtPosition(fileName: string, position: number): ReadonlyArray<DefinitionInfo> | undefined;
getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined;
getTypeDefinitionAtPosition(fileName: string, position: number): ReadonlyArray<DefinitionInfo> | undefined;
@@ -5239,6 +5240,10 @@ declare namespace ts {
displayParts: SymbolDisplayPart[];
isOptional: boolean;
}
interface SelectionRange {
textSpan: TextSpan;
parent?: SelectionRange;
}
/**
* Represents a single signature to show in signature help.
* The id is used for subsequent calls into the language service to ask questions about the
@@ -5790,7 +5795,8 @@ declare namespace ts.server.protocol {
GetEditsForRefactor = "getEditsForRefactor",
OrganizeImports = "organizeImports",
GetEditsForFileRename = "getEditsForFileRename",
ConfigurePlugin = "configurePlugin"
ConfigurePlugin = "configurePlugin",
SelectionRange = "selectionRange",
}
/**
* A TypeScript Server message
@@ -6753,6 +6759,20 @@ declare namespace ts.server.protocol {
}
interface ConfigurePluginResponse extends Response {
}
interface SelectionRangeRequest extends FileRequest {
command: CommandTypes.SelectionRange;
arguments: SelectionRangeRequestArgs;
}
interface SelectionRangeRequestArgs extends FileRequestArgs {
locations: Location[];
}
interface SelectionRangeResponse extends Response {
body?: SelectionRange[];
}
interface SelectionRange {
textSpan: TextSpan;
parent?: SelectionRange;
}
/**
* Information found in an "open" request.
*/
@@ -9026,6 +9046,8 @@ declare namespace ts.server {
private getBraceMatching;
private getDiagnosticsForProject;
private configurePlugin;
private getSmartSelectionRange;
private mapSelectionRange;
getCanonicalFileName(fileName: string): string;
exit(): void;
private notRequired;

View File

@@ -4788,6 +4788,7 @@ declare namespace ts {
getSignatureHelpItems(fileName: string, position: number, options: SignatureHelpItemsOptions | undefined): SignatureHelpItems | undefined;
getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): RenameInfo;
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): ReadonlyArray<RenameLocation> | undefined;
getSmartSelectionRange(fileName: string, position: number): SelectionRange;
getDefinitionAtPosition(fileName: string, position: number): ReadonlyArray<DefinitionInfo> | undefined;
getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined;
getTypeDefinitionAtPosition(fileName: string, position: number): ReadonlyArray<DefinitionInfo> | undefined;
@@ -5239,6 +5240,10 @@ declare namespace ts {
displayParts: SymbolDisplayPart[];
isOptional: boolean;
}
interface SelectionRange {
textSpan: TextSpan;
parent?: SelectionRange;
}
/**
* Represents a single signature to show in signature help.
* The id is used for subsequent calls into the language service to ask questions about the