From eeb5e0f8b20f24b824c8178e216a32c6ba667ba7 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Fri, 21 Nov 2014 18:46:57 -0800 Subject: [PATCH] Type Parameters in interface --- src/harness/fourslash.ts | 24 +- ...nfoDisplayPartsTypeParameterInInterface.ts | 263 ++++++++++++++++++ 2 files changed, 282 insertions(+), 5 deletions(-) create mode 100644 tests/cases/fourslash/quickInfoDisplayPartsTypeParameterInInterface.ts diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index f37dd8db902..c63791c90eb 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -805,16 +805,30 @@ module FourSlash { this.scenarioActions.push(''); this.scenarioActions.push(''); - function getJsonString(object: any) { - return (JSON.stringify(object, /*replacer*/undefined, " ")); + function getDisplayPartsJson(displayParts: ts.SymbolDisplayPart[]) { + var result = ""; + ts.forEach(displayParts, part => { + if (result) { + result += ",\n "; + } + else { + result = "[\n "; + } + result += JSON.stringify(part); + }); + if (result) { + result += "\n]"; + } + + return result; } var actualQuickInfo = this.languageService.getQuickInfoAtPosition(this.activeFile.fileName, this.currentCaretPosition); assert.equal(actualQuickInfo.kind, kind, this.messageAtLastKnownMarker("QuickInfo kind")); assert.equal(actualQuickInfo.kindModifiers, kindModifiers, this.messageAtLastKnownMarker("QuickInfo kindModifiers")); - assert.equal(getJsonString(actualQuickInfo.textSpan), getJsonString(textSpan), this.messageAtLastKnownMarker("QuickInfo textSpan")); - assert.equal(getJsonString(actualQuickInfo.displayParts), getJsonString(displayParts), this.messageAtLastKnownMarker("QuickInfo displayParts")); - assert.equal(getJsonString(actualQuickInfo.documentation), getJsonString(documentation), this.messageAtLastKnownMarker("QuickInfo documentation")); + assert.equal(JSON.stringify(actualQuickInfo.textSpan), JSON.stringify(textSpan), this.messageAtLastKnownMarker("QuickInfo textSpan")); + assert.equal(getDisplayPartsJson(actualQuickInfo.displayParts), getDisplayPartsJson(displayParts), this.messageAtLastKnownMarker("QuickInfo displayParts")); + assert.equal(getDisplayPartsJson(actualQuickInfo.documentation), getDisplayPartsJson(documentation), this.messageAtLastKnownMarker("QuickInfo documentation")); } public verifyRenameLocations(findInStrings: boolean, findInComments: boolean) { diff --git a/tests/cases/fourslash/quickInfoDisplayPartsTypeParameterInInterface.ts b/tests/cases/fourslash/quickInfoDisplayPartsTypeParameterInInterface.ts new file mode 100644 index 00000000000..95797166ea2 --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsTypeParameterInInterface.ts @@ -0,0 +1,263 @@ +/// + +////interface /*1*/I { +//// new (/*4*/a: /*5*/U, /*6*/b: /*7*/T): /*8*/U; +//// (/*10*/a: /*11*/U, /*12*/b: /*13*/T): /*14*/U; +//// /*15*/method(/*17*/a: /*18*/U, /*19*/b: /*20*/T): /*21*/U; +////} +////var /*22*/iVal: /*23*/I; +////new /*24*/iVal("hello", "hello"); +/////*25*/iVal("hello", "hello"); +/////*26*/iVal./*27*/method("hello", "hello"); +////interface /*28*/I1> { +//// new >(/*33*/a: /*34*/U, /*35*/b: /*36*/T): /*37*/U; +//// >(/*40*/a: /*41*/U, /*42*/b: /*43*/T): /*44*/U; +//// /*45*/method>(/*48*/a: /*49*/U, /*50*/b: /*51*/T): /*52*/U; +////} +////var /*53*/iVal1: /*54*/I1>; +////new /*56*/iVal1(/*57*/iVal, /*58*/iVal); +/////*59*/iVal1(/*60*/iVal, /*61*/iVal); +/////*62*/iVal1./*63*/method(/*64*/iVal, /*65*/iVal); + +var marker = 0; +var markerName: string; + +function goToMarker() { + marker++; + markerName = marker.toString(); + goTo.marker(markerName); +} + +function getTypeParameterDisplay(instanceType: ts.SymbolDisplayPart[], + name: string, optionalExtends?: ts.SymbolDisplayPart[]) { + return instanceType || + function () { + var typeParameterDisplay = [{ text: name, kind: "typeParameterName" }]; + if (optionalExtends) { + typeParameterDisplay.push({ text: " ", kind: "space" }, { text: "extends", kind: "keyword" }, + { text: " ", kind: "space" }); + typeParameterDisplay = typeParameterDisplay.concat(optionalExtends); + } + return typeParameterDisplay + } (); +} + +function getInterfaceDisplay(name: string, optionalInstanceType?: ts.SymbolDisplayPart[], + optionalExtends?: ts.SymbolDisplayPart[]) { + var interfaceDisplay = [{ text: name, kind: "interfaceName" }, { text: "<", kind: "punctuation" }]; + interfaceDisplay = interfaceDisplay.concat(getTypeParameterDisplay(optionalInstanceType, "T", optionalExtends)); + interfaceDisplay.push({ text: ">", kind: "punctuation" }); + return interfaceDisplay; +} + +function verifyInterfaceDisplay(name: string, optionalExtends?: ts.SymbolDisplayPart[]) { + goToMarker(); + + verify.verifyQuickInfoDisplayParts("interface", "", { start: test.markerByName(markerName).position, length: name.length }, + [{ text: "interface", kind: "keyword" }, { text: " ", kind: "space" }].concat( + getInterfaceDisplay(name, undefined, optionalExtends)), []); +} + +function verifyTypeParameter(name: string, inDisplay: ts.SymbolDisplayPart[]) { + goToMarker(); + + var typeParameterDisplay = [{ text: "(", kind: "punctuation" }, { text: "type parameter", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: name, kind: "typeParameterName" }, + { text: " ", kind: "space" }, { text: "in", kind: "keyword" }, { text: " ", kind: "space" }]; + typeParameterDisplay = typeParameterDisplay.concat(inDisplay); + + verify.verifyQuickInfoDisplayParts("type parameter", "", { start: test.markerByName(markerName).position, length: name.length }, + typeParameterDisplay, []); +} + +function verifyParameter(name: string, typeParameterName: string, optionalExtends?: ts.SymbolDisplayPart[]) { + goToMarker(); + var parameterDisplay = [{ text: "(", kind: "punctuation" }, { text: "parameter", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: name, kind: "parameterName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: typeParameterName, kind: "typeParameterName" }]; + if (optionalExtends) { + parameterDisplay.push({ text: " ", kind: "space" }, { text: "extends", kind: "keyword" }, + { text: " ", kind: "space" }); + parameterDisplay = parameterDisplay.concat(optionalExtends); + } + verify.verifyQuickInfoDisplayParts("parameter", "", { start: test.markerByName(markerName).position, length: name.length }, + parameterDisplay, []); +} + +function getSignatureDisplay(isArrow: boolean, optionalInstanceType?: ts.SymbolDisplayPart[], + optionalExtends?: ts.SymbolDisplayPart[]) { + var functionDisplay: ts.SymbolDisplayPart[] = []; + + functionDisplay.push({ text: "<", kind: "punctuation" }); + + functionDisplay = functionDisplay.concat( + getTypeParameterDisplay(optionalInstanceType, "U", optionalExtends)); + + functionDisplay.push({ text: ">", kind: "punctuation" }, { text: "(", kind: "punctuation" }, + { text: "a", kind: "parameterName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }); + functionDisplay = functionDisplay.concat( + getTypeParameterDisplay(optionalInstanceType, "U")); + functionDisplay.push({ text: ",", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "b", kind: "parameterName" }, + { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }); + functionDisplay = functionDisplay.concat( + getTypeParameterDisplay(optionalInstanceType, "T")); + + functionDisplay.push({ text: ")", kind: "punctuation" }); + if (isArrow) { + functionDisplay.push({ text: " ", kind: "space" }, { text: "=>", kind: "punctuation" }); + } + else { + functionDisplay.push({ text: ":", kind: "punctuation" }); + } + functionDisplay.push({ text: " ", kind: "space" }); + + functionDisplay = functionDisplay.concat( + getTypeParameterDisplay(optionalInstanceType, "U")); + + return functionDisplay; +} + +function getMethodDisplay(name: string, interfaceName: string, optionalInstanceType?: ts.SymbolDisplayPart[], + optionalExtends?: ts.SymbolDisplayPart[]) { + return getInterfaceDisplay(interfaceName, optionalInstanceType, optionalExtends).concat( + { text: ".", kind: "punctuation" }, { text: name, kind: "methodName" }).concat( + getSignatureDisplay(/*isArrow*/ false, optionalInstanceType, optionalExtends)); +} + +function getCallOrNewSignatureDisplay(isNew: boolean, isArrow: boolean, interfaceName?: string, + optionalInstanceType?: ts.SymbolDisplayPart[], optionalExtends?: ts.SymbolDisplayPart[]) { + var result: ts.SymbolDisplayPart[] = []; + if (isNew) { + result.push({ text: "new", kind: "keyword" }, { text: " ", kind: "space" }); + } + if (interfaceName) { + result.push({ text: interfaceName, kind: "interfaceName" }); + } + + return result.concat(getSignatureDisplay(isArrow, optionalInstanceType, optionalExtends)); +} + +function verifyMethodDisplay(name: string, interfaceName: string, + optionalInstanceType?: ts.SymbolDisplayPart[], optionalExtends?: ts.SymbolDisplayPart[]) { + goToMarker(); + var functionDisplay = [{ text: "(", kind: "punctuation" }, { text: "method", kind: "text" }, + { text: ")", kind: "punctuation" }, { text: " ", kind: "space" }].concat( + getMethodDisplay(name, interfaceName, optionalInstanceType, optionalExtends)); + + verify.verifyQuickInfoDisplayParts("method", "", + { start: test.markerByName(markerName).position, length: name.length }, + functionDisplay, []); +} + +function verifyInterfaceVar(name: string, typeDisplay: ts.SymbolDisplayPart[]) { + goToMarker(); + verify.verifyQuickInfoDisplayParts("var", "", { start: test.markerByName(markerName).position, length: name.length }, + [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: name, kind: "localName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }].concat(typeDisplay), + []); +} + +var stringTypeDisplay = [{ text: "string", kind: "keyword" }]; +var extendsTypeDisplay = getInterfaceDisplay("I", stringTypeDisplay); + + +// Declaration +verifyInterfaceDisplay("I"); +verifyTypeParameter("T", getInterfaceDisplay("I")); + +// New declaration +verifyTypeParameter("U", getCallOrNewSignatureDisplay(/*isNew*/ true, /*isArrow*/ false)); +verifyParameter("a", "U"); +verifyTypeParameter("U", getCallOrNewSignatureDisplay(/*isNew*/ true, /*isArrow*/ false)); +verifyParameter("b", "T"); +verifyTypeParameter("T", getInterfaceDisplay("I")); +verifyTypeParameter("U", getCallOrNewSignatureDisplay(/*isNew*/ true, /*isArrow*/ false)); + +// Call declaration +verifyTypeParameter("U", getCallOrNewSignatureDisplay(/*isNew*/ false, /*isArrow*/ false)); +verifyParameter("a", "U"); +verifyTypeParameter("U", getCallOrNewSignatureDisplay(/*isNew*/ false, /*isArrow*/ false)); +verifyParameter("b", "T"); +verifyTypeParameter("T", getInterfaceDisplay("I")); +verifyTypeParameter("U", getCallOrNewSignatureDisplay(/*isNew*/ false, /*isArrow*/ false)); + +// Method declaration +verifyMethodDisplay("method", "I"); +verifyTypeParameter("U", getMethodDisplay("method", "I")); +verifyParameter("a", "U"); +verifyTypeParameter("U", getMethodDisplay("method", "I")); +verifyParameter("b", "T"); +verifyTypeParameter("T", getInterfaceDisplay("I")); +verifyTypeParameter("U", getMethodDisplay("method", "I")); + +// Instance +verifyInterfaceVar("iVal", getInterfaceDisplay("I", stringTypeDisplay)); +verifyInterfaceDisplay("I"); + +// new +verifyInterfaceVar("iVal", getCallOrNewSignatureDisplay(/*isNew*/ true, /*isArrow*/ true, "I", stringTypeDisplay)); + +// call +verifyInterfaceVar("iVal", getCallOrNewSignatureDisplay(/*isNew*/ false, /*isArrow*/ true, "I", stringTypeDisplay)); + +// Method call +verifyInterfaceVar("iVal", getInterfaceDisplay("I", stringTypeDisplay)); +verifyMethodDisplay("method", "I", stringTypeDisplay); + +// With constraint +// Declaration +verifyInterfaceDisplay("I1", extendsTypeDisplay); +verifyTypeParameter("T", getInterfaceDisplay("I1", /*instance*/undefined, extendsTypeDisplay)); +verifyInterfaceDisplay("I"); + +// New declaration +verifyTypeParameter("U", getCallOrNewSignatureDisplay(/*isNew*/ true, /*isArrow*/ false, /*interfaceName*/undefined, /*instance*/undefined, extendsTypeDisplay)); +verifyInterfaceDisplay("I"); +verifyParameter("a", "U", extendsTypeDisplay); +verifyTypeParameter("U", getCallOrNewSignatureDisplay(/*isNew*/ true, /*isArrow*/ false, /*interfaceName*/undefined, /*instance*/undefined, extendsTypeDisplay)); +verifyParameter("b", "T", extendsTypeDisplay); +verifyTypeParameter("T", getInterfaceDisplay("I1", /*instance*/undefined, extendsTypeDisplay)); +verifyTypeParameter("U", getCallOrNewSignatureDisplay(/*isNew*/ true, /*isArrow*/ false, /*interfaceName*/undefined, /*instance*/undefined, extendsTypeDisplay)); + +// Call declaration +verifyTypeParameter("U", getCallOrNewSignatureDisplay(/*isNew*/ false, /*isArrow*/ false, /*interfaceName*/undefined, /*instance*/undefined, extendsTypeDisplay)); +verifyInterfaceDisplay("I"); +verifyParameter("a", "U", extendsTypeDisplay); +verifyTypeParameter("U", getCallOrNewSignatureDisplay(/*isNew*/ false, /*isArrow*/ false, /*interfaceName*/undefined, /*instance*/undefined, extendsTypeDisplay)); +verifyParameter("b", "T", extendsTypeDisplay); +verifyTypeParameter("T", getInterfaceDisplay("I1", /*instance*/undefined, extendsTypeDisplay)); +verifyTypeParameter("U", getCallOrNewSignatureDisplay(/*isNew*/ false, /*isArrow*/ false, /*interfaceName*/undefined, /*instance*/undefined, extendsTypeDisplay)); + +// Method declaration +verifyMethodDisplay("method", "I1", /*instance*/ undefined, extendsTypeDisplay); +verifyTypeParameter("U", getMethodDisplay("method", "I1", /*instance*/ undefined, extendsTypeDisplay)); +verifyInterfaceDisplay("I"); +verifyParameter("a", "U", extendsTypeDisplay); +verifyTypeParameter("U", getMethodDisplay("method", "I1", /*instance*/ undefined, extendsTypeDisplay)); +verifyParameter("b", "T", extendsTypeDisplay); +verifyTypeParameter("T", getInterfaceDisplay("I1", /*instance*/undefined, extendsTypeDisplay)); +verifyTypeParameter("U", getMethodDisplay("method", "I1", /*instance*/ undefined, extendsTypeDisplay)); + +// Instance +verifyInterfaceVar("iVal1", getInterfaceDisplay("I1", extendsTypeDisplay)); +verifyInterfaceDisplay("I1", extendsTypeDisplay); +verifyInterfaceDisplay("I"); + +// new +verifyInterfaceVar("iVal1", getCallOrNewSignatureDisplay(/*isNew*/ true, /*isArrow*/ true, "I1", extendsTypeDisplay)); +verifyInterfaceVar("iVal", getInterfaceDisplay("I", stringTypeDisplay)); +verifyInterfaceVar("iVal", getInterfaceDisplay("I", stringTypeDisplay)); + +// call +verifyInterfaceVar("iVal1", getCallOrNewSignatureDisplay(/*isNew*/ false, /*isArrow*/ true, "I1", extendsTypeDisplay)); +verifyInterfaceVar("iVal", getInterfaceDisplay("I", stringTypeDisplay)); +verifyInterfaceVar("iVal", getInterfaceDisplay("I", stringTypeDisplay)); + +// Method call +verifyInterfaceVar("iVal1", getInterfaceDisplay("I1", extendsTypeDisplay)); +verifyMethodDisplay("method", "I1", extendsTypeDisplay); +verifyInterfaceVar("iVal", getInterfaceDisplay("I", stringTypeDisplay)); +verifyInterfaceVar("iVal", getInterfaceDisplay("I", stringTypeDisplay));