Skip to content

Change find-all-references tests to test for groups #13760

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
2 commits merged into from
Feb 8, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 92 additions & 29 deletions src/harness/fourslash.ts
Original file line number Diff line number Diff line change
Expand Up @@ -452,7 +452,8 @@ namespace FourSlash {
}

private messageAtLastKnownMarker(message: string) {
return "Marker: " + this.lastKnownMarker + "\n" + message;
const locationDescription = this.lastKnownMarker ? this.lastKnownMarker : this.getLineColStringAtPosition(this.currentCaretPosition);
return `At ${locationDescription}: ${message}`;
}

private assertionMessageAtLastKnownMarker(msg: string) {
Expand Down Expand Up @@ -562,7 +563,7 @@ namespace FourSlash {
}

public verifyGoToDefinitionIs(endMarker: string | string[]) {
this.verifyGoToXWorker(endMarker instanceof Array ? endMarker : [endMarker], () => this.getGoToDefinition());
this.verifyGoToXWorker(toArray(endMarker), () => this.getGoToDefinition());
}

public verifyGoToDefinition(arg0: any, endMarkerNames?: string | string[]) {
Expand All @@ -582,7 +583,7 @@ namespace FourSlash {
if (endMarkerNames) {
this.verifyGoToXPlain(arg0, endMarkerNames, getDefs);
}
else if (arg0 instanceof Array) {
else if (ts.isArray(arg0)) {
const pairs: [string | string[], string | string[]][] = arg0;
for (const [start, end] of pairs) {
this.verifyGoToXPlain(start, end, getDefs);
Expand All @@ -599,13 +600,8 @@ namespace FourSlash {
}

private verifyGoToXPlain(startMarkerNames: string | string[], endMarkerNames: string | string[], getDefs: () => ts.DefinitionInfo[] | undefined) {
if (startMarkerNames instanceof Array) {
for (const start of startMarkerNames) {
this.verifyGoToXSingle(start, endMarkerNames, getDefs);
}
}
else {
this.verifyGoToXSingle(startMarkerNames, endMarkerNames, getDefs);
for (const start of toArray(startMarkerNames)) {
this.verifyGoToXSingle(start, endMarkerNames, getDefs);
}
}

Expand All @@ -617,7 +613,7 @@ namespace FourSlash {

private verifyGoToXSingle(startMarkerName: string, endMarkerNames: string | string[], getDefs: () => ts.DefinitionInfo[] | undefined) {
this.goToMarker(startMarkerName);
this.verifyGoToXWorker(endMarkerNames instanceof Array ? endMarkerNames : [endMarkerNames], getDefs);
this.verifyGoToXWorker(toArray(endMarkerNames), getDefs);
}

private verifyGoToXWorker(endMarkers: string[], getDefs: () => ts.DefinitionInfo[] | undefined) {
Expand Down Expand Up @@ -899,8 +895,74 @@ namespace FourSlash {
}
}

public verifyRangesWithSameTextReferenceEachOther() {
this.rangesByText().forEach(ranges => this.verifyRangesReferenceEachOther(ranges));
public verifyReferenceGroups(startRanges: Range | Range[], parts: Array<{ definition: string, ranges: Range[] }>): void {
interface ReferenceJson { definition: string; ranges: ts.ReferenceEntry[]; }
type ReferencesJson = ReferenceJson[];
const fullExpected = parts.map<ReferenceJson>(({ definition, ranges }) => ({ definition, ranges: ranges.map(rangeToReferenceEntry) }));

for (const startRange of toArray(startRanges)) {
this.goToRangeStart(startRange);
const fullActual = this.findReferencesAtCaret().map<ReferenceJson>(({ definition, references }) => ({
definition: definition.displayParts.map(d => d.text).join(""),
ranges: references
}));
this.assertObjectsEqual<ReferencesJson>(fullActual, fullExpected);
}

function rangeToReferenceEntry(r: Range) {
let { isWriteAccess, isDefinition } = (r.marker && r.marker.data) || { isWriteAccess: false, isDefinition: false };
isWriteAccess = !!isWriteAccess; isDefinition = !!isDefinition;
return { fileName: r.fileName, textSpan: { start: r.start, length: r.end - r.start }, isWriteAccess, isDefinition }
}
}

public verifyNoReferences(markerNameOrRange?: string | Range) {
if (markerNameOrRange) {
if (typeof markerNameOrRange === "string") {
this.goToMarker(markerNameOrRange);
}
else {
this.goToRangeStart(markerNameOrRange);
}
}

const refs = this.getReferencesAtCaret();
if (refs && refs.length) {
console.log(refs);
this.raiseError("Expected getReferences to fail");
}
}

public verifySingleReferenceGroup(definition: string, ranges?: Range[]) {
ranges = ranges || this.getRanges();
this.verifyReferenceGroups(ranges, [{ definition, ranges }]);
}

private assertObjectsEqual<T>(fullActual: T, fullExpected: T, msgPrefix = ""): void {
const recur = <U>(actual: U, expected: U, path: string) => {
const fail = (msg: string) => {
console.log("Expected:", stringify(fullExpected));
console.log("Actual: ", stringify(fullActual));
this.raiseError(`${msgPrefix}At ${path}: ${msg}`);
};

for (const key in actual) if (ts.hasProperty(actual as any, key)) {
const ak = actual[key], ek = expected[key];
if (typeof ak === "object" && typeof ek === "object") {
recur(ak, ek, path ? path + "." + key : key);
}
else if (ak !== ek) {
fail(`Expected '${key}' to be '${ek}', got '${ak}'`);
}
}
for (const key in expected) if (ts.hasProperty(expected as any, key)) {
if (!ts.hasProperty(actual as any, key)) {
fail(`${msgPrefix}Missing property '${key}'`);
}
}
};
recur(fullActual, fullExpected, "");

}

public verifyDisplayPartsOfReferencedSymbol(expected: ts.SymbolDisplayPart[]) {
Expand Down Expand Up @@ -974,7 +1036,7 @@ namespace FourSlash {
public verifyQuickInfos(namesAndTexts: { [name: string]: string | [string, string] }) {
for (const name in namesAndTexts) if (ts.hasProperty(namesAndTexts, name)) {
const text = namesAndTexts[name];
if (text instanceof Array) {
if (ts.isArray(text)) {
assert(text.length === 2);
const [expectedText, expectedDocumentation] = text;
this.verifyQuickInfoAt(name, expectedText, expectedDocumentation);
Expand Down Expand Up @@ -1411,13 +1473,6 @@ namespace FourSlash {
Harness.IO.log(membersString);
}

public printReferences() {
const references = this.getReferencesAtCaret();
ts.forEach(references, entry => {
Harness.IO.log(stringify(entry));
});
}

public printContext() {
ts.forEach(this.languageServiceAdapterHost.getFilenames(), Harness.IO.log);
}
Expand Down Expand Up @@ -3082,6 +3137,10 @@ ${code}
}
return ts.arrayFrom(set.keys());
}

function toArray<T>(x: T | T[]): T[] {
return ts.isArray(x) ? x : [x];
}
}

namespace FourSlashInterface {
Expand Down Expand Up @@ -3346,6 +3405,18 @@ namespace FourSlashInterface {
this.state.verifyReferencesOf(start, references);
}

public referenceGroups(startRanges: FourSlash.Range[], parts: Array<{ definition: string, ranges: FourSlash.Range[] }>) {
this.state.verifyReferenceGroups(startRanges, parts);
}

public noReferences(markerNameOrRange?: string | FourSlash.Range) {
this.state.verifyNoReferences(markerNameOrRange);
}

public singleReferenceGroup(definition: string, ranges?: FourSlash.Range[]) {
this.state.verifySingleReferenceGroup(definition, ranges);
}

public rangesReferenceEachOther(ranges?: FourSlash.Range[]) {
this.state.verifyRangesReferenceEachOther(ranges);
}
Expand All @@ -3354,10 +3425,6 @@ namespace FourSlashInterface {
this.state.verifyDisplayPartsOfReferencedSymbol(expected);
}

public rangesWithSameTextReferenceEachOther() {
this.state.verifyRangesWithSameTextReferenceEachOther();
}

public currentParameterHelpArgumentNameIs(name: string) {
this.state.verifyCurrentParameterHelpName(name);
}
Expand Down Expand Up @@ -3660,10 +3727,6 @@ namespace FourSlashInterface {
this.state.printNavigationBar();
}

public printReferences() {
this.state.printReferences();
}

public printContext() {
this.state.printContext();
}
Expand Down
19 changes: 4 additions & 15 deletions src/services/findAllReferences.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ namespace ts.FindAllReferences {
return getReferencedSymbolsForNode(typeChecker, cancellationToken, node, sourceFiles, findInStrings, findInComments, isForRename);
}

export function convertReferences(referenceSymbols: ReferencedSymbol[]): ReferenceEntry[] {
return referenceSymbols && flatMap(referenceSymbols, r => r.references);
}

export function getReferencedSymbolsForNode(typeChecker: TypeChecker, cancellationToken: CancellationToken, node: Node, sourceFiles: SourceFile[], findInStrings?: boolean, findInComments?: boolean, isForRename?: boolean, implementations?: boolean): ReferencedSymbol[] | undefined {
if (!implementations) {
const special = getReferencedSymbolsSpecial(node, sourceFiles, typeChecker, cancellationToken);
Expand Down Expand Up @@ -411,7 +415,6 @@ namespace ts.FindAllReferences {
textSpan: createTextSpan(0, 1),
displayParts: [{ text: name, kind: ScriptElementKind.keyword }]
}

const references: ReferenceEntry[] = [];
for (const sourceFile of sourceFiles) {
cancellationToken.throwIfCancellationRequested();
Expand Down Expand Up @@ -1316,20 +1319,6 @@ namespace ts.FindAllReferences {
return meaning;
}

export function convertReferences(referenceSymbols: ReferencedSymbol[]): ReferenceEntry[] {
if (!referenceSymbols) {
return undefined;
}

const referenceEntries: ReferenceEntry[] = [];

for (const referenceSymbol of referenceSymbols) {
addRange(referenceEntries, referenceSymbol.references);
}

return referenceEntries;
}

function isImplementation(node: Node): boolean {
if (!node) {
return false;
Expand Down
7 changes: 1 addition & 6 deletions src/services/services.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1415,7 +1415,6 @@ namespace ts {

function findReferences(fileName: string, position: number): ReferencedSymbol[] {
const referencedSymbols = findReferencedSymbols(fileName, position, /*findInStrings*/ false, /*findInComments*/ false, /*isForRename*/false);

// Only include referenced symbols that have a valid definition.
return filter(referencedSymbols, rs => !!rs.definition);
}
Expand Down Expand Up @@ -2015,9 +2014,5 @@ namespace ts {
throw new Error("getDefaultLibFilePath is only supported when consumed as a node module. ");
}

function initializeServices() {
objectAllocator = getServicesObjectAllocator();
}

initializeServices();
objectAllocator = getServicesObjectAllocator();
}
15 changes: 12 additions & 3 deletions tests/cases/fourslash/ambientShorthandFindAllRefs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,18 @@
////declare module "jquery";

// @Filename: user.ts
////import {[|x|]} from "jquery";
////import {[|{| "isWriteAccess": true, "isDefinition": true |}x|]} from "jquery";

// @Filename: user2.ts
////import {[|x|]} from "jquery";
////import {[|{| "isWriteAccess": true, "isDefinition": true |}x|]} from "jquery";

verify.rangesReferenceEachOther();
const ranges = test.ranges();
const [r0, r1] = ranges;
verify.referenceGroups(r0, [
{ definition: "import x", ranges: [r0] },
{ definition: 'module "jquery"', ranges: [r1] }
]);
verify.referenceGroups(r1, [
{ definition: 'module "jquery"', ranges: [r0] },
{ definition: "import x", ranges: [r1] }
]);
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
////
//// }
////
//// public /**/[|start|](){
//// public /**/[|{| "isWriteAccess": true, "isDefinition": true |}start|](){
//// return this;
//// }
////
Expand All @@ -23,11 +23,21 @@
////second.[|start|]();
////second.stop();

verify.rangesReferenceEachOther();
checkRefs();

cancellation.setCancelled();
verifyOperationIsCancelled(() => verify.rangesReferenceEachOther());
verifyOperationIsCancelled(checkRefs);

// verify that internal state is still correct
cancellation.resetCancelled();
verify.rangesReferenceEachOther();
checkRefs();

function checkRefs() {
const ranges = test.ranges();
const [r0, r1] = ranges;
verify.referenceGroups(r0, [{ definition: "(method) Test.start(): this", ranges }]);
verify.referenceGroups(r1, [
{ definition: "(method) Second.Test.start(): Second.Test", ranges: [r0] },
{ definition: "(method) Second.Test.start(): Second.Test", ranges: [r1] }
]);
}
6 changes: 3 additions & 3 deletions tests/cases/fourslash/findAllReferencesOfConstructor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,6 @@
////class d extends a.C { constructor() { [|super|](); }

const ranges = test.ranges();
for (const ctr of ranges.slice(0, 3)) {
verify.referencesOf(ctr, ranges);
}
const [r0, r1, r2] = ranges;
verify.referenceGroups([r0, r2], [{ definition: "constructor C(n: number): C (+1 overload)", ranges }]);
verify.referenceGroups(r1, [{ definition: "constructor C(): C (+1 overload)", ranges }]);
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
//// [|constructor|](){}
////}

verify.rangesReferenceEachOther();
verify.singleReferenceGroup("constructor C(n: number): C");
20 changes: 15 additions & 5 deletions tests/cases/fourslash/findAllRefsForComputedProperties.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,26 @@
/// <reference path='fourslash.ts'/>


////interface I {
//// ["[|prop1|]"]: () => void;
//// ["[|{| "isDefinition": true |}prop1|]"]: () => void;
////}
////
////class C implements I {
//// ["[|prop1|]"]: any;
//// ["[|{| "isDefinition": true |}prop1|]"]: any;
////}
////
////var x: I = {
//// ["[|prop1|]"]: function () { },
//// ["[|{| "isDefinition": true |}prop1|]"]: function () { },
////}

verify.rangesReferenceEachOther();
const ranges = test.ranges();
const [r0, r1, r2] = ranges;
verify.referenceGroups(r0, [{ definition: '(property) I[["prop1"]]: () => void', ranges }]);
verify.referenceGroups(r1, [
{ definition: '(property) I[["prop1"]]: () => void', ranges: [r0, r2] },
{ definition: '(property) C[["prop1"]]: any', ranges: [r1] }
]);
verify.referenceGroups(r2, [
{ definition: '(property) I[["prop1"]]: () => void', ranges: [r0, r1] },
{ definition: '(property) ["prop1"]: () => void', ranges: [r2] }
]);

18 changes: 14 additions & 4 deletions tests/cases/fourslash/findAllRefsForComputedProperties2.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
/// <reference path='fourslash.ts'/>

////interface I {
//// [[|42|]](): void;
//// [[|{| "isDefinition": true |}42|]](): void;
////}
////
////class C implements I {
//// [[|42|]]: any;
//// [[|{| "isDefinition": true |}42|]]: any;
////}
////
////var x: I = {
//// ["[|42|]"]: function () { }
//// ["[|{| "isDefinition": true |}42|]"]: function () { }
////}

verify.rangesReferenceEachOther();
const ranges = test.ranges();
const [r0, r1, r2] = ranges;
verify.referenceGroups(r0, [{ definition: "(method) I[[42]](): void", ranges }]);
verify.referenceGroups(r1, [
{ definition: "(method) I[[42]](): void", ranges: [r0, r2] },
{ definition: "(property) C[[42]]: any", ranges: [r1] }
]);
verify.referenceGroups(r2, [
{ definition: "(method) I[[42]](): void", ranges: [r0, r1] },
{ definition: '(property) ["42"]: () => void', ranges: [r2] }
]);
Loading