mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Add quotes when renaming numerical indices (#53596)
This commit is contained in:
parent
30fb9fa57e
commit
e02ef9fddb
@ -568,15 +568,17 @@ export class SessionClient implements LanguageService {
|
||||
return notImplemented();
|
||||
}
|
||||
|
||||
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): RenameLocation[] {
|
||||
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, preferences: UserPreferences | boolean | undefined): RenameLocation[] {
|
||||
if (!this.lastRenameEntry ||
|
||||
this.lastRenameEntry.inputs.fileName !== fileName ||
|
||||
this.lastRenameEntry.inputs.position !== position ||
|
||||
this.lastRenameEntry.inputs.findInStrings !== findInStrings ||
|
||||
this.lastRenameEntry.inputs.findInComments !== findInComments) {
|
||||
if (providePrefixAndSuffixTextForRename !== undefined) {
|
||||
const providePrefixAndSuffixTextForRename = typeof preferences === "boolean" ? preferences : preferences?.providePrefixAndSuffixTextForRename;
|
||||
const quotePreference = typeof preferences === "boolean" ? undefined : preferences?.quotePreference;
|
||||
if (providePrefixAndSuffixTextForRename !== undefined || quotePreference !== undefined) {
|
||||
// User preferences have to be set through the `Configure` command
|
||||
this.configure({ providePrefixAndSuffixTextForRename });
|
||||
this.configure({ providePrefixAndSuffixTextForRename, quotePreference });
|
||||
// Options argument is not used, so don't pass in options
|
||||
this.getRenameInfo(fileName, position, /*preferences*/{}, findInStrings, findInComments);
|
||||
// Restore previous user preferences
|
||||
|
||||
@ -1802,13 +1802,18 @@ export class TestState {
|
||||
isMarker(markerOrRange) ?
|
||||
markerOrRange :
|
||||
{ fileName: markerOrRange.fileName, position: markerOrRange.pos };
|
||||
const { findInStrings = false, findInComments = false, providePrefixAndSuffixTextForRename = true } = options || {};
|
||||
const {
|
||||
findInStrings = false,
|
||||
findInComments = false,
|
||||
providePrefixAndSuffixTextForRename = true,
|
||||
quotePreference = "double"
|
||||
} = options || {};
|
||||
const locations = this.languageService.findRenameLocations(
|
||||
fileName,
|
||||
position,
|
||||
findInStrings,
|
||||
findInComments,
|
||||
providePrefixAndSuffixTextForRename,
|
||||
{ providePrefixAndSuffixTextForRename, quotePreference },
|
||||
);
|
||||
|
||||
if (!locations) {
|
||||
@ -1818,7 +1823,8 @@ export class TestState {
|
||||
const renameOptions = options ?
|
||||
(options.findInStrings !== undefined ? `// @findInStrings: ${findInStrings}\n` : "") +
|
||||
(options.findInComments !== undefined ? `// @findInComments: ${findInComments}\n` : "") +
|
||||
(options.providePrefixAndSuffixTextForRename !== undefined ? `// @providePrefixAndSuffixTextForRename: ${providePrefixAndSuffixTextForRename}\n` : "") :
|
||||
(options.providePrefixAndSuffixTextForRename !== undefined ? `// @providePrefixAndSuffixTextForRename: ${providePrefixAndSuffixTextForRename}\n` : "") +
|
||||
(options.quotePreference !== undefined ? `// @quotePreference: ${quotePreference}\n` : "") :
|
||||
"";
|
||||
|
||||
return renameOptions + (renameOptions ? "\n" : "") + this.getBaselineForDocumentSpansWithFileContents(
|
||||
|
||||
@ -1910,6 +1910,7 @@ export interface RenameOptions {
|
||||
readonly findInStrings?: boolean;
|
||||
readonly findInComments?: boolean;
|
||||
readonly providePrefixAndSuffixTextForRename?: boolean;
|
||||
readonly quotePreference?: "auto" | "double" | "single";
|
||||
}
|
||||
export type BaselineCommandWithMarkerOrRange = {
|
||||
type: "findAllReferences" | "goToDefinition" | "getDefinitionAtPosition" | "goToSourceDefinition" | "goToType" | "goToImplementation";
|
||||
|
||||
@ -527,8 +527,8 @@ class LanguageServiceShimProxy implements ts.LanguageService {
|
||||
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));
|
||||
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, preferences?: ts.UserPreferences | boolean): ts.RenameLocation[] {
|
||||
return unwrapJSONCallResult(this.shim.findRenameLocations(fileName, position, findInStrings, findInComments, preferences));
|
||||
}
|
||||
getDefinitionAtPosition(fileName: string, position: number): ts.DefinitionInfo[] {
|
||||
return unwrapJSONCallResult(this.shim.getDefinitionAtPosition(fileName, position));
|
||||
|
||||
@ -136,7 +136,6 @@ import {
|
||||
toFileNameLowerCase,
|
||||
tracing,
|
||||
unmangleScopedPackageName,
|
||||
UserPreferences,
|
||||
version,
|
||||
WithMetadata,
|
||||
} from "./_namespaces/ts";
|
||||
@ -497,14 +496,14 @@ function getRenameLocationsWorker(
|
||||
initialLocation: DocumentPosition,
|
||||
findInStrings: boolean,
|
||||
findInComments: boolean,
|
||||
{ providePrefixAndSuffixTextForRename }: UserPreferences
|
||||
preferences: protocol.UserPreferences
|
||||
): readonly RenameLocation[] {
|
||||
const perProjectResults = getPerProjectReferences(
|
||||
projects,
|
||||
defaultProject,
|
||||
initialLocation,
|
||||
/*isForRename*/ true,
|
||||
(project, position) => project.getLanguageService().findRenameLocations(position.fileName, position.pos, findInStrings, findInComments, providePrefixAndSuffixTextForRename),
|
||||
(project, position) => project.getLanguageService().findRenameLocations(position.fileName, position.pos, findInStrings, findInComments, preferences),
|
||||
(renameLocation, cb) => cb(documentSpanLocation(renameLocation)),
|
||||
);
|
||||
|
||||
|
||||
@ -72,6 +72,7 @@ import {
|
||||
getNodeKind,
|
||||
getPropertySymbolFromBindingElement,
|
||||
getPropertySymbolsFromContextualType,
|
||||
getQuoteFromPreference,
|
||||
getReferencedFileLocation,
|
||||
getSuperContainer,
|
||||
getSymbolId,
|
||||
@ -151,6 +152,7 @@ import {
|
||||
isNamespaceExportDeclaration,
|
||||
isNewExpressionTarget,
|
||||
isNoSubstitutionTemplateLiteral,
|
||||
isNumericLiteral,
|
||||
isObjectBindingElementWithoutPropertyName,
|
||||
isObjectLiteralExpression,
|
||||
isObjectLiteralMethod,
|
||||
@ -205,6 +207,7 @@ import {
|
||||
PropertyAssignment,
|
||||
PropertyDeclaration,
|
||||
punctuationPart,
|
||||
QuotePreference,
|
||||
rangeIsOnSingleLine,
|
||||
ReferencedSymbol,
|
||||
ReferencedSymbolDefinitionInfo,
|
||||
@ -673,8 +676,8 @@ function getDefinitionKindAndDisplayParts(symbol: Symbol, checker: TypeChecker,
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export function toRenameLocation(entry: Entry, originalNode: Node, checker: TypeChecker, providePrefixAndSuffixText: boolean): RenameLocation {
|
||||
return { ...entryToDocumentSpan(entry), ...(providePrefixAndSuffixText && getPrefixAndSuffixText(entry, originalNode, checker)) };
|
||||
export function toRenameLocation(entry: Entry, originalNode: Node, checker: TypeChecker, providePrefixAndSuffixText: boolean, quotePreference: QuotePreference): RenameLocation {
|
||||
return { ...entryToDocumentSpan(entry), ...(providePrefixAndSuffixText && getPrefixAndSuffixText(entry, originalNode, checker, quotePreference)) };
|
||||
}
|
||||
|
||||
function toReferencedSymbolEntry(entry: Entry, symbol: Symbol | undefined): ReferencedSymbolEntry {
|
||||
@ -716,7 +719,7 @@ function entryToDocumentSpan(entry: Entry): DocumentSpan {
|
||||
}
|
||||
|
||||
interface PrefixAndSuffix { readonly prefixText?: string; readonly suffixText?: string; }
|
||||
function getPrefixAndSuffixText(entry: Entry, originalNode: Node, checker: TypeChecker): PrefixAndSuffix {
|
||||
function getPrefixAndSuffixText(entry: Entry, originalNode: Node, checker: TypeChecker, quotePreference: QuotePreference): PrefixAndSuffix {
|
||||
if (entry.kind !== EntryKind.Span && isIdentifier(originalNode)) {
|
||||
const { node, kind } = entry;
|
||||
const parent = node.parent;
|
||||
@ -760,6 +763,12 @@ function getPrefixAndSuffixText(entry: Entry, originalNode: Node, checker: TypeC
|
||||
}
|
||||
}
|
||||
|
||||
// If the node is a numerical indexing literal, then add quotes around the property access.
|
||||
if (entry.kind !== EntryKind.Span && isNumericLiteral(entry.node) && isAccessExpression(entry.node.parent)) {
|
||||
const quote = getQuoteFromPreference(quotePreference);
|
||||
return { prefixText: quote, suffixText: quote };
|
||||
}
|
||||
|
||||
return emptyOptions;
|
||||
}
|
||||
|
||||
|
||||
@ -105,6 +105,7 @@ import {
|
||||
getNonAssignedNameOfDeclaration,
|
||||
getNormalizedAbsolutePath,
|
||||
getObjectFlags,
|
||||
getQuotePreference,
|
||||
getScriptKind,
|
||||
getSetExternalModuleIndicator,
|
||||
getSnapshotText,
|
||||
@ -2128,7 +2129,7 @@ export function createLanguageService(
|
||||
return DocumentHighlights.getDocumentHighlights(program, cancellationToken, sourceFile, position, sourceFilesToSearch);
|
||||
}
|
||||
|
||||
function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): RenameLocation[] | undefined {
|
||||
function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, preferences?: UserPreferences | boolean): RenameLocation[] | undefined {
|
||||
synchronizeHostData();
|
||||
const sourceFile = getValidSourceFile(fileName);
|
||||
const node = getAdjustedRenameLocation(getTouchingPropertyName(sourceFile, position));
|
||||
@ -2145,8 +2146,10 @@ export function createLanguageService(
|
||||
});
|
||||
}
|
||||
else {
|
||||
const quotePreference = getQuotePreference(sourceFile, preferences ?? emptyOptions);
|
||||
const providePrefixAndSuffixTextForRename = typeof preferences === "boolean" ? preferences : preferences?.providePrefixAndSuffixTextForRename;
|
||||
return getReferencesWorker(node, position, { findInStrings, findInComments, providePrefixAndSuffixTextForRename, use: FindAllReferences.FindReferencesUse.Rename },
|
||||
(entry, originalNode, checker) => FindAllReferences.toRenameLocation(entry, originalNode, checker, providePrefixAndSuffixTextForRename || false));
|
||||
(entry, originalNode, checker) => FindAllReferences.toRenameLocation(entry, originalNode, checker, providePrefixAndSuffixTextForRename || false, quotePreference));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -256,7 +256,7 @@ export interface LanguageServiceShim extends Shim {
|
||||
* Returns a JSON-encoded value of the type:
|
||||
* { fileName: string, textSpan: { start: number, length: number } }[]
|
||||
*/
|
||||
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): string;
|
||||
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, preferences?: UserPreferences | boolean): string;
|
||||
|
||||
/**
|
||||
* Returns a JSON-encoded value of the type:
|
||||
@ -952,10 +952,10 @@ class LanguageServiceShimObject extends ShimBase implements LanguageServiceShim
|
||||
);
|
||||
}
|
||||
|
||||
public findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): string {
|
||||
public findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, preferences: UserPreferences): string {
|
||||
return this.forwardJSONCall(
|
||||
`findRenameLocations('${fileName}', ${position}, ${findInStrings}, ${findInComments}, ${providePrefixAndSuffixTextForRename})`,
|
||||
() => this.languageService.findRenameLocations(fileName, position, findInStrings, findInComments, providePrefixAndSuffixTextForRename)
|
||||
`findRenameLocations('${fileName}', ${position}, ${findInStrings}, ${findInComments})`,
|
||||
() => this.languageService.findRenameLocations(fileName, position, findInStrings, findInComments, preferences)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -575,6 +575,8 @@ export interface LanguageService {
|
||||
/** @deprecated Use the signature with `UserPreferences` instead. */
|
||||
getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): RenameInfo;
|
||||
|
||||
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, preferences: UserPreferences): readonly RenameLocation[] | undefined;
|
||||
/** @deprecated Pass `providePrefixAndSuffixTextForRename` as part of a `UserPreferences` parameter. */
|
||||
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): readonly RenameLocation[] | undefined;
|
||||
|
||||
getSmartSelectionRange(fileName: string, position: number): SelectionRange;
|
||||
|
||||
@ -10095,6 +10095,8 @@ declare namespace ts {
|
||||
getRenameInfo(fileName: string, position: number, preferences: UserPreferences): RenameInfo;
|
||||
/** @deprecated Use the signature with `UserPreferences` instead. */
|
||||
getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): RenameInfo;
|
||||
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, preferences: UserPreferences): readonly RenameLocation[] | undefined;
|
||||
/** @deprecated Pass `providePrefixAndSuffixTextForRename` as part of a `UserPreferences` parameter. */
|
||||
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): readonly RenameLocation[] | undefined;
|
||||
getSmartSelectionRange(fileName: string, position: number): SelectionRange;
|
||||
getDefinitionAtPosition(fileName: string, position: number): readonly DefinitionInfo[] | undefined;
|
||||
|
||||
@ -6153,6 +6153,8 @@ declare namespace ts {
|
||||
getRenameInfo(fileName: string, position: number, preferences: UserPreferences): RenameInfo;
|
||||
/** @deprecated Use the signature with `UserPreferences` instead. */
|
||||
getRenameInfo(fileName: string, position: number, options?: RenameInfoOptions): RenameInfo;
|
||||
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, preferences: UserPreferences): readonly RenameLocation[] | undefined;
|
||||
/** @deprecated Pass `providePrefixAndSuffixTextForRename` as part of a `UserPreferences` parameter. */
|
||||
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): readonly RenameLocation[] | undefined;
|
||||
getSmartSelectionRange(fileName: string, position: number): SelectionRange;
|
||||
getDefinitionAtPosition(fileName: string, position: number): readonly DefinitionInfo[] | undefined;
|
||||
|
||||
@ -0,0 +1,11 @@
|
||||
// === findRenameLocations ===
|
||||
// === /tests/cases/fourslash/renameNumericalIndex.ts ===
|
||||
// const foo = { /*RENAME*/<|[|0RENAME|]: true|> };
|
||||
// foo[/*START PREFIX*/"[|0RENAME|]"/*END SUFFIX*/];
|
||||
|
||||
|
||||
|
||||
// === findRenameLocations ===
|
||||
// === /tests/cases/fourslash/renameNumericalIndex.ts ===
|
||||
// const foo = { <|[|0RENAME|]: true|> };
|
||||
// foo[/*START PREFIX*/"/*RENAME*/[|0RENAME|]"/*END SUFFIX*/];
|
||||
@ -0,0 +1,15 @@
|
||||
// === findRenameLocations ===
|
||||
// @quotePreference: single
|
||||
|
||||
// === /tests/cases/fourslash/renameNumericalIndexSingleQuoted.ts ===
|
||||
// const foo = { /*RENAME*/<|[|0RENAME|]: true|> };
|
||||
// foo[/*START PREFIX*/'[|0RENAME|]'/*END SUFFIX*/];
|
||||
|
||||
|
||||
|
||||
// === findRenameLocations ===
|
||||
// @quotePreference: single
|
||||
|
||||
// === /tests/cases/fourslash/renameNumericalIndexSingleQuoted.ts ===
|
||||
// const foo = { <|[|0RENAME|]: true|> };
|
||||
// foo[/*START PREFIX*/'/*RENAME*/[|0RENAME|]'/*END SUFFIX*/];
|
||||
@ -839,7 +839,7 @@ declare namespace FourSlashInterface {
|
||||
readonly providePrefixAndSuffixTextForRename?: boolean;
|
||||
};
|
||||
|
||||
type RenameOptions = { readonly findInStrings?: boolean, readonly findInComments?: boolean, readonly providePrefixAndSuffixTextForRename?: boolean };
|
||||
type RenameOptions = { readonly findInStrings?: boolean, readonly findInComments?: boolean, readonly providePrefixAndSuffixTextForRename?: boolean, readonly quotePreference?: "auto" | "double" | "single" };
|
||||
type RenameLocationOptions = Range | { readonly range: Range, readonly prefixText?: string, readonly suffixText?: string };
|
||||
type DiagnosticIgnoredInterpolations = { template: string }
|
||||
type BaselineCommand = {
|
||||
|
||||
6
tests/cases/fourslash/renameNumericalIndex.ts
Normal file
6
tests/cases/fourslash/renameNumericalIndex.ts
Normal file
@ -0,0 +1,6 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
////const foo = { [|0|]: true };
|
||||
////foo[[|0|]];
|
||||
|
||||
verify.baselineRenameAtRangesWithText("0");
|
||||
@ -0,0 +1,6 @@
|
||||
/// <reference path="fourslash.ts" />
|
||||
|
||||
////const foo = { [|0|]: true };
|
||||
////foo[[|0|]];
|
||||
|
||||
verify.baselineRenameAtRangesWithText("0", { quotePreference: "single" });
|
||||
Loading…
x
Reference in New Issue
Block a user