Porting https://github.com/Microsoft/TypeScript/pull/29314 to release-3.3
This commit is contained in:
Benjamin Lichtman
2019-01-17 13:41:45 -08:00
committed by GitHub
parent 49689894d7
commit 8680908150
14 changed files with 163 additions and 36 deletions
+1
View File
@@ -5864,6 +5864,7 @@ namespace ts {
/** Determines whether we import `foo/index.ts` as "foo", "foo/index", or "foo/index.js" */
readonly importModuleSpecifierEnding?: "minimal" | "index" | "js";
readonly allowTextChangesInNewFiles?: boolean;
readonly providePrefixAndSuffixTextForRename?: boolean;
}
/** Represents a bigint literal value without requiring bigint support */
+3 -2
View File
@@ -1170,7 +1170,7 @@ Actual: ${stringify(fullActual)}`);
}
public verifyRenameLocations(startRanges: ArrayOrSingle<Range>, options: FourSlashInterface.RenameLocationsOptions) {
const { findInStrings = false, findInComments = false, ranges = this.getRanges() } = ts.isArray(options) ? { findInStrings: false, findInComments: false, ranges: options } : options;
const { findInStrings = false, findInComments = false, ranges = this.getRanges(), providePrefixAndSuffixTextForRename = true } = ts.isArray(options) ? { findInStrings: false, findInComments: false, ranges: options, providePrefixAndSuffixTextForRename: true } : options;
for (const startRange of toArray(startRanges)) {
this.goToRangeStart(startRange);
@@ -1182,7 +1182,7 @@ Actual: ${stringify(fullActual)}`);
}
const references = this.languageService.findRenameLocations(
this.activeFile.fileName, this.currentCaretPosition, findInStrings, findInComments);
this.activeFile.fileName, this.currentCaretPosition, findInStrings, findInComments, providePrefixAndSuffixTextForRename);
const sort = (locations: ReadonlyArray<ts.RenameLocation> | undefined) =>
locations && ts.sort(locations, (r1, r2) => ts.compareStringsCaseSensitive(r1.fileName, r2.fileName) || r1.textSpan.start - r2.textSpan.start);
@@ -5087,6 +5087,7 @@ namespace FourSlashInterface {
readonly findInStrings?: boolean;
readonly findInComments?: boolean;
readonly ranges: ReadonlyArray<RenameLocationOptions>;
readonly providePrefixAndSuffixTextForRename?: boolean;
};
export type RenameLocationOptions = FourSlash.Range | { readonly range: FourSlash.Range, readonly prefixText?: string, readonly suffixText?: string };
}
+2 -2
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));
}
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): ts.RenameLocation[] {
return unwrapJSONCallResult(this.shim.findRenameLocations(fileName, position, findInStrings, findInComments));
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): ts.RenameLocation[] {
return unwrapJSONCallResult(this.shim.findRenameLocations(fileName, position, findInStrings, findInComments, providePrefixAndSuffixTextForRename));
}
getDefinitionAtPosition(fileName: string, position: number): ts.DefinitionInfo[] {
return unwrapJSONCallResult(this.shim.getDefinitionAtPosition(fileName, position));
+1
View File
@@ -2906,6 +2906,7 @@ namespace ts.server.protocol {
readonly allowTextChangesInNewFiles?: boolean;
readonly lazyConfiguredProjectsFromExternalProject?: boolean;
readonly allowRenameOfImportPath?: boolean;
readonly providePrefixAndSuffixTextForRename?: boolean;
}
export interface CompilerOptions {
+5 -3
View File
@@ -314,7 +314,8 @@ namespace ts.server {
defaultProject: Project,
initialLocation: DocumentPosition,
findInStrings: boolean,
findInComments: boolean
findInComments: boolean,
hostPreferences: UserPreferences
): ReadonlyArray<RenameLocation> {
const outputs: RenameLocation[] = [];
@@ -323,7 +324,7 @@ namespace ts.server {
defaultProject,
initialLocation,
({ project, location }, tryAddToTodo) => {
for (const output of project.getLanguageService().findRenameLocations(location.fileName, location.pos, findInStrings, findInComments) || emptyArray) {
for (const output of project.getLanguageService().findRenameLocations(location.fileName, location.pos, findInStrings, findInComments, hostPreferences.providePrefixAndSuffixTextForRename) || emptyArray) {
if (!contains(outputs, output, documentSpansEqual) && !tryAddToTodo(project, documentSpanLocation(output))) {
outputs.push(output);
}
@@ -1232,7 +1233,8 @@ namespace ts.server {
this.getDefaultProject(args),
{ fileName: args.file, pos: position },
!!args.findInStrings,
!!args.findInComments
!!args.findInComments,
this.getHostPreferences()
);
if (!simplifiedResult) return locations;
+50 -15
View File
@@ -39,6 +39,11 @@ namespace ts.FindAllReferences {
readonly isForRename?: boolean;
/** True if we are searching for implementations. We will have a different method of adding references if so. */
readonly implementations?: boolean;
/**
* True to opt in for enhanced renaming of shorthand properties and import/export specifiers.
* Default is false for backwards compatibility.
*/
readonly providePrefixAndSuffixTextForRename?: boolean;
}
export function findReferencedSymbols(program: Program, cancellationToken: CancellationToken, sourceFiles: ReadonlyArray<SourceFile>, sourceFile: SourceFile, position: number): ReferencedSymbol[] | undefined {
@@ -157,8 +162,8 @@ namespace ts.FindAllReferences {
return { displayParts, kind: symbolKind };
}
export function toRenameLocation(entry: Entry, originalNode: Node, checker: TypeChecker): RenameLocation {
return { ...entryToDocumentSpan(entry), ...getPrefixAndSuffixText(entry, originalNode, checker) };
export function toRenameLocation(entry: Entry, originalNode: Node, checker: TypeChecker, providePrefixAndSuffixText: boolean): RenameLocation {
return { ...entryToDocumentSpan(entry), ...(providePrefixAndSuffixText && getPrefixAndSuffixText(entry, originalNode, checker)) };
}
export function toReferenceEntry(entry: Entry): ReferenceEntry {
@@ -484,7 +489,7 @@ namespace ts.FindAllReferences.Core {
/** Core find-all-references algorithm for a normal symbol. */
function getReferencedSymbolsForSymbol(originalSymbol: Symbol, node: Node | undefined, sourceFiles: ReadonlyArray<SourceFile>, sourceFilesSet: ReadonlyMap<true>, checker: TypeChecker, cancellationToken: CancellationToken, options: Options): SymbolAndEntries[] {
const symbol = node && skipPastExportOrImportSpecifierOrUnion(originalSymbol, node, checker, !!options.isForRename) || originalSymbol;
const symbol = node && skipPastExportOrImportSpecifierOrUnion(originalSymbol, node, checker, /*useLocalSymbolForExportSpecifier*/ !isForRenameWithPrefixAndSuffixText(options)) || originalSymbol;
// Compute the meaning from the location and the symbol it references
const searchMeaning = node ? getIntersectingMeaningFromDeclarations(node, symbol) : SemanticMeaning.All;
@@ -492,7 +497,7 @@ namespace ts.FindAllReferences.Core {
const result: SymbolAndEntries[] = [];
const state = new State(sourceFiles, sourceFilesSet, node ? getSpecialSearchKind(node) : SpecialSearchKind.None, checker, cancellationToken, searchMeaning, options, result);
const exportSpecifier = !options.isForRename ? undefined : find(symbol.declarations, isExportSpecifier);
const exportSpecifier = !isForRenameWithPrefixAndSuffixText(options) ? undefined : find(symbol.declarations, isExportSpecifier);
if (exportSpecifier) {
// When renaming at an export specifier, rename the export and not the thing being exported.
getReferencesAtExportSpecifier(exportSpecifier.name, symbol, exportSpecifier, state.createSearch(node, originalSymbol, /*comingFrom*/ undefined), state, /*addReferencesHere*/ true, /*alwaysGetReferences*/ true);
@@ -502,7 +507,7 @@ namespace ts.FindAllReferences.Core {
searchForImportsOfExport(node, symbol, { exportingModuleSymbol: Debug.assertDefined(symbol.parent, "Expected export symbol to have a parent"), exportKind: ExportKind.Default }, state);
}
else {
const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, !!options.isForRename, !!options.implementations) : [symbol] });
const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, !!options.isForRename, !!options.providePrefixAndSuffixTextForRename, !!options.implementations) : [symbol] });
// Try to get the smallest valid scope that we can limit our search to;
// otherwise we'll need to search globally (i.e. include each file).
@@ -538,9 +543,9 @@ namespace ts.FindAllReferences.Core {
}
/** Handle a few special cases relating to export/import specifiers. */
function skipPastExportOrImportSpecifierOrUnion(symbol: Symbol, node: Node, checker: TypeChecker, isForRename: boolean): Symbol | undefined {
function skipPastExportOrImportSpecifierOrUnion(symbol: Symbol, node: Node, checker: TypeChecker, useLocalSymbolForExportSpecifier: boolean): Symbol | undefined {
const { parent } = node;
if (isExportSpecifier(parent) && !isForRename) {
if (isExportSpecifier(parent) && useLocalSymbolForExportSpecifier) {
return getLocalSymbolForExportSpecifier(node as Identifier, symbol, parent, checker);
}
// If the symbol is declared as part of a declaration like `{ type: "a" } | { type: "b" }`, use the property on the union type to get more references.
@@ -1071,6 +1076,8 @@ namespace ts.FindAllReferences.Core {
addReferencesHere: boolean,
alwaysGetReferences?: boolean,
): void {
Debug.assert(!alwaysGetReferences || !!state.options.providePrefixAndSuffixTextForRename, "If alwaysGetReferences is true, then prefix/suffix text must be enabled");
const { parent, propertyName, name } = exportSpecifier;
const exportDeclaration = parent.parent;
const localSymbol = getLocalSymbolForExportSpecifier(referenceLocation, referenceSymbol, exportSpecifier, state.checker);
@@ -1102,7 +1109,7 @@ namespace ts.FindAllReferences.Core {
}
// For `export { foo as bar }`, rename `foo`, but not `bar`.
if (!state.options.isForRename || alwaysGetReferences) {
if (!isForRenameWithPrefixAndSuffixText(state.options) || alwaysGetReferences) {
const exportKind = referenceLocation.originalKeywordKind === SyntaxKind.DefaultKeyword ? ExportKind.Default : ExportKind.Named;
const exportSymbol = Debug.assertDefined(exportSpecifier.symbol);
const exportInfo = Debug.assertDefined(getExportInfo(exportSymbol, exportKind, state.checker));
@@ -1110,7 +1117,7 @@ namespace ts.FindAllReferences.Core {
}
// At `export { x } from "foo"`, also search for the imported symbol `"foo".x`.
if (search.comingFrom !== ImportExport.Export && exportDeclaration.moduleSpecifier && !propertyName && !state.options.isForRename) {
if (search.comingFrom !== ImportExport.Export && exportDeclaration.moduleSpecifier && !propertyName && !isForRenameWithPrefixAndSuffixText(state.options)) {
const imported = state.checker.getExportSpecifierLocalTargetSymbol(exportSpecifier);
if (imported) searchForImportedSymbol(imported, state);
}
@@ -1145,7 +1152,7 @@ namespace ts.FindAllReferences.Core {
const { symbol } = importOrExport;
if (importOrExport.kind === ImportExport.Import) {
if (!state.options.isForRename) {
if (!(isForRenameWithPrefixAndSuffixText(state.options))) {
searchForImportedSymbol(symbol, state);
}
}
@@ -1514,16 +1521,16 @@ namespace ts.FindAllReferences.Core {
// For certain symbol kinds, we need to include other symbols in the search set.
// This is not needed when searching for re-exports.
function populateSearchSymbolSet(symbol: Symbol, location: Node, checker: TypeChecker, isForRename: boolean, implementations: boolean): Symbol[] {
function populateSearchSymbolSet(symbol: Symbol, location: Node, checker: TypeChecker, isForRename: boolean, providePrefixAndSuffixText: boolean, implementations: boolean): Symbol[] {
const result: Symbol[] = [];
forEachRelatedSymbol<void>(symbol, location, checker, isForRename,
forEachRelatedSymbol<void>(symbol, location, checker, isForRename, !(isForRename && providePrefixAndSuffixText),
(sym, root, base) => { result.push(base || root || sym); },
/*allowBaseTypes*/ () => !implementations);
return result;
}
function forEachRelatedSymbol<T>(
symbol: Symbol, location: Node, checker: TypeChecker, isForRenamePopulateSearchSymbolSet: boolean,
symbol: Symbol, location: Node, checker: TypeChecker, isForRenamePopulateSearchSymbolSet: boolean, onlyIncludeBindingElementAtReferenceLocation: boolean,
cbSymbol: (symbol: Symbol, rootSymbol?: Symbol, baseSymbol?: Symbol, kind?: NodeEntryKind) => T | undefined,
allowBaseTypes: (rootSymbol: Symbol) => boolean,
): T | undefined {
@@ -1577,9 +1584,25 @@ namespace ts.FindAllReferences.Core {
}
// symbolAtLocation for a binding element is the local symbol. See if the search symbol is the property.
// Don't do this when populating search set for a rename -- just rename the local.
// Don't do this when populating search set for a rename when prefix and suffix text will be provided -- just rename the local.
if (!isForRenamePopulateSearchSymbolSet) {
const bindingElementPropertySymbol = isObjectBindingElementWithoutPropertyName(location.parent) ? getPropertySymbolFromBindingElement(checker, location.parent) : undefined;
let bindingElementPropertySymbol: Symbol | undefined;
if (onlyIncludeBindingElementAtReferenceLocation) {
bindingElementPropertySymbol = isObjectBindingElementWithoutPropertyName(location.parent) ? getPropertySymbolFromBindingElement(checker, location.parent) : undefined;
}
else {
bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, checker);
}
return bindingElementPropertySymbol && fromRoot(bindingElementPropertySymbol, EntryKind.SearchedPropertyFoundLocal);
}
Debug.assert(isForRenamePopulateSearchSymbolSet);
// due to the above assert and the arguments at the uses of this function,
// (onlyIncludeBindingElementAtReferenceLocation <=> !providePrefixAndSuffixTextForRename) holds
const includeOriginalSymbolOfBindingElement = onlyIncludeBindingElementAtReferenceLocation;
if (includeOriginalSymbolOfBindingElement) {
const bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, checker);
return bindingElementPropertySymbol && fromRoot(bindingElementPropertySymbol, EntryKind.SearchedPropertyFoundLocal);
}
@@ -1597,6 +1620,13 @@ namespace ts.FindAllReferences.Core {
? getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.name, checker, base => cbSymbol(sym, rootSymbol, base, kind))
: undefined));
}
function getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol: Symbol, checker: TypeChecker): Symbol | undefined {
const bindingElement = getDeclarationOfKind<BindingElement>(symbol, SyntaxKind.BindingElement);
if (bindingElement && isObjectBindingElementWithoutPropertyName(bindingElement)) {
return getPropertySymbolFromBindingElement(checker, bindingElement);
}
}
}
interface RelatedSymbol {
@@ -1606,6 +1636,7 @@ namespace ts.FindAllReferences.Core {
function getRelatedSymbol(search: Search, referenceSymbol: Symbol, referenceLocation: Node, state: State): RelatedSymbol | undefined {
const { checker } = state;
return forEachRelatedSymbol(referenceSymbol, referenceLocation, checker, /*isForRenamePopulateSearchSymbolSet*/ false,
/*onlyIncludeBindingElementAtReferenceLocation*/ !state.options.isForRename || !!state.options.providePrefixAndSuffixTextForRename,
(sym, rootSymbol, baseSymbol, kind): RelatedSymbol | undefined => search.includes(baseSymbol || rootSymbol || sym)
// For a base type, use the symbol for the derived type. For a synthetic (e.g. union) property, use the union symbol.
? { symbol: rootSymbol && !(getCheckFlags(sym) & CheckFlags.Synthetic) ? rootSymbol : sym, kind }
@@ -1696,4 +1727,8 @@ namespace ts.FindAllReferences.Core {
t.symbol && t.symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? t.symbol : undefined);
return res.length === 0 ? undefined : res;
}
function isForRenameWithPrefixAndSuffixText(options: Options) {
return options.isForRename && options.providePrefixAndSuffixTextForRename;
}
}
+3 -2
View File
@@ -1549,7 +1549,7 @@ namespace ts {
return DocumentHighlights.getDocumentHighlights(program, cancellationToken, sourceFile, position, sourceFilesToSearch);
}
function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): RenameLocation[] | undefined {
function findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): RenameLocation[] | undefined {
synchronizeHostData();
const sourceFile = getValidSourceFile(fileName);
const node = getTouchingPropertyName(sourceFile, position);
@@ -1559,7 +1559,8 @@ namespace ts {
({ fileName: sourceFile.fileName, textSpan: createTextSpanFromNode(node.tagName, sourceFile) }));
}
else {
return getReferencesWorker(node, position, { findInStrings, findInComments, isForRename: true }, FindAllReferences.toRenameLocation);
return getReferencesWorker(node, position, { findInStrings, findInComments, providePrefixAndSuffixTextForRename, isForRename: true },
(entry, originalNode, checker) => FindAllReferences.toRenameLocation(entry, originalNode, checker, providePrefixAndSuffixTextForRename || false));
}
}
+4 -4
View File
@@ -170,7 +170,7 @@ namespace ts {
* Returns a JSON-encoded value of the type:
* { fileName: string, textSpan: { start: number, length: number } }[]
*/
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): string;
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): string;
/**
* Returns a JSON-encoded value of the type:
@@ -838,10 +838,10 @@ namespace ts {
);
}
public findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean): string {
public findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): string {
return this.forwardJSONCall(
`findRenameLocations('${fileName}', ${position}, ${findInStrings}, ${findInComments})`,
() => this.languageService.findRenameLocations(fileName, position, findInStrings, findInComments)
`findRenameLocations('${fileName}', ${position}, ${findInStrings}, ${findInComments}, ${providePrefixAndSuffixTextForRename})`,
() => this.languageService.findRenameLocations(fileName, position, findInStrings, findInComments, providePrefixAndSuffixTextForRename)
);
}
+1 -1
View File
@@ -295,7 +295,7 @@ 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): ReadonlyArray<RenameLocation> | undefined;
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): ReadonlyArray<RenameLocation> | undefined;
getDefinitionAtPosition(fileName: string, position: number): ReadonlyArray<DefinitionInfo> | undefined;
getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined;
+30 -4
View File
@@ -32,13 +32,39 @@ namespace ts.projectSystem {
});
});
it("works with prefixText and suffixText", () => {
it("works with prefixText and suffixText when enabled", () => {
const aTs: File = { path: "/a.ts", content: "const x = 0; const o = { x };" };
const session = createSession(createServerHost([aTs]));
const host = createServerHost([aTs]);
const session = createSession(host);
openFilesForSession([aTs], session);
const response = executeSessionRequest<protocol.RenameRequest, protocol.RenameResponse>(session, protocol.CommandTypes.Rename, protocolFileLocationFromSubstring(aTs, "x"));
assert.deepEqual<protocol.RenameResponseBody | undefined>(response, {
// rename with prefixText and suffixText disabled
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: 1 }),
],
},
],
});
// rename with prefixText and suffixText enabled
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, {
info: {
canRename: true,
fileToRename: undefined,
+3 -1
View File
@@ -3013,6 +3013,7 @@ declare namespace ts {
/** Determines whether we import `foo/index.ts` as "foo", "foo/index", or "foo/index.js" */
readonly importModuleSpecifierEnding?: "minimal" | "index" | "js";
readonly allowTextChangesInNewFiles?: boolean;
readonly providePrefixAndSuffixTextForRename?: boolean;
}
/** Represents a bigint literal value without requiring bigint support */
interface PseudoBigInt {
@@ -4707,7 +4708,7 @@ declare namespace ts {
getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan | undefined;
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): ReadonlyArray<RenameLocation> | undefined;
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): ReadonlyArray<RenameLocation> | undefined;
getDefinitionAtPosition(fileName: string, position: number): ReadonlyArray<DefinitionInfo> | undefined;
getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined;
getTypeDefinitionAtPosition(fileName: string, position: number): ReadonlyArray<DefinitionInfo> | undefined;
@@ -7927,6 +7928,7 @@ declare namespace ts.server.protocol {
readonly allowTextChangesInNewFiles?: boolean;
readonly lazyConfiguredProjectsFromExternalProject?: boolean;
readonly allowRenameOfImportPath?: boolean;
readonly providePrefixAndSuffixTextForRename?: boolean;
}
interface CompilerOptions {
allowJs?: boolean;
+2 -1
View File
@@ -3013,6 +3013,7 @@ declare namespace ts {
/** Determines whether we import `foo/index.ts` as "foo", "foo/index", or "foo/index.js" */
readonly importModuleSpecifierEnding?: "minimal" | "index" | "js";
readonly allowTextChangesInNewFiles?: boolean;
readonly providePrefixAndSuffixTextForRename?: boolean;
}
/** Represents a bigint literal value without requiring bigint support */
interface PseudoBigInt {
@@ -4707,7 +4708,7 @@ declare namespace ts {
getBreakpointStatementAtPosition(fileName: string, position: number): TextSpan | undefined;
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): ReadonlyArray<RenameLocation> | undefined;
findRenameLocations(fileName: string, position: number, findInStrings: boolean, findInComments: boolean, providePrefixAndSuffixTextForRename?: boolean): ReadonlyArray<RenameLocation> | undefined;
getDefinitionAtPosition(fileName: string, position: number): ReadonlyArray<DefinitionInfo> | undefined;
getDefinitionAndBoundSpan(fileName: string, position: number): DefinitionInfoAndBoundSpan | undefined;
getTypeDefinitionAtPosition(fileName: string, position: number): ReadonlyArray<DefinitionInfo> | undefined;
@@ -0,0 +1,56 @@
/// <reference path='fourslash.ts' />
// @Filename: /file1.ts
////declare function log(s: string | number): void;
////const [|{| "isWriteAccess": true, "isDefinition": true |}q|] = 1;
////export { [|{| "isWriteAccess": true, "isDefinition": true |}q|] };
////const x = {
//// [|{| "isWriteAccess": true, "isDefinition": true |}z|]: 'value'
////}
////const { [|{| "isWriteAccess": true, "isDefinition": true |}z|] } = x;
////log([|z|]);
// @Filename: /file2.ts
////declare function log(s: string | number): void;
////import { [|{| "isWriteAccess": true, "isDefinition": true |}q|] } from "./file1";
////log([|q|] + 1);
verify.noErrors();
const [q0, q1, z0, z1, z2, q2, q3] = test.ranges();
const qFile1Ranges = [q0, q1];
const qFile2Ranges = [q2, q3];
const qFile1ReferenceGroup: FourSlashInterface.ReferenceGroup = {
definition: "const q: 1",
ranges: qFile1Ranges
};
const qFile2ReferenceGroup: FourSlashInterface.ReferenceGroup = {
definition: "(alias) const q: 1\nimport q",
ranges: qFile2Ranges
};
verify.referenceGroups([q0, q1], [qFile1ReferenceGroup, qFile2ReferenceGroup]);
verify.referenceGroups([q2, q3], [qFile2ReferenceGroup, qFile1ReferenceGroup]);
verify.renameLocations(q0, { ranges: [q0, { range: q1, suffixText: " as q" }], providePrefixAndSuffixTextForRename: true });
verify.renameLocations(q1, { ranges: [{ range: q1, prefixText: "q as " }, q2, q3], providePrefixAndSuffixTextForRename: true });
verify.renameLocations([q2, q3], { ranges: [{ range: q2, prefixText: "q as " }, q3], providePrefixAndSuffixTextForRename: true });
verify.renameLocations([q0, q1, q2, q3], { ranges: [q0, q1, q2, q3], providePrefixAndSuffixTextForRename: false });
const zReferenceGroup1: FourSlashInterface.ReferenceGroup = {
definition: "(property) z: string",
ranges: [z0]
};
const zReferenceGroup2: FourSlashInterface.ReferenceGroup = {
definition: "const z: string",
ranges: [z1, z2]
};
verify.referenceGroups([z0], [{ ...zReferenceGroup1, ranges: [z0, z1] }]);
verify.referenceGroups([z1], [zReferenceGroup1, zReferenceGroup2]);
verify.referenceGroups([z2], [zReferenceGroup2]);
verify.renameLocations([z0], { ranges: [z0, { range: z1, suffixText: ": z" }], providePrefixAndSuffixTextForRename: true });
verify.renameLocations([z1, z2], { ranges: [{ range: z1, prefixText: "z: " }, z2], providePrefixAndSuffixTextForRename: true });
verify.renameLocations([z0, z1, z2], { ranges: [z0, z1, z2], providePrefixAndSuffixTextForRename: false });
+2 -1
View File
@@ -633,7 +633,8 @@ declare namespace FourSlashInterface {
readonly findInStrings?: boolean;
readonly findInComments?: boolean;
readonly ranges: ReadonlyArray<RenameLocationOptions>;
}
readonly providePrefixAndSuffixTextForRename?: boolean;
};
type RenameLocationOptions = Range | { readonly range: Range, readonly prefixText?: string, readonly suffixText?: string };
}
declare function verifyOperationIsCancelled(f: any): void;