diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 7e364730ede..0114d213398 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -769,7 +769,7 @@ module FourSlash { return "\nActual " + name + ":\n\t" + actualValue + "\nExpected value:\n\t" + expectedValue; } - public verifyQuickInfo(negative: boolean, expectedText?: string, expectedDocumentation?: string) { + public verifyQuickInfoString(negative: boolean, expectedText?: string, expectedDocumentation?: string) { [expectedText, expectedDocumentation].forEach(str => { if (str) { this.scenarioActions.push(''); @@ -798,6 +798,39 @@ module FourSlash { } } + + public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: { start: number; length: number; }, + displayParts: ts.SymbolDisplayPart[], + documentation: ts.SymbolDisplayPart[]) { + this.scenarioActions.push(''); + this.scenarioActions.push(''); + + 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(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) { var renameInfo = this.languageService.getRenameInfo(this.activeFile.fileName, this.currentCaretPosition); if (renameInfo.canRename) { diff --git a/src/lib/es6.d.ts b/src/lib/es6.d.ts index 0940f26cac5..5706924e8e3 100644 --- a/src/lib/es6.d.ts +++ b/src/lib/es6.d.ts @@ -1,4 +1,4 @@ -declare type PropertyKey = string | number | Symbol; +declare type PropertyKey = string | number | Symbol; interface Symbol { /** Returns a string representation of an object. */ diff --git a/src/services/services.ts b/src/services/services.ts index d233cf70ff9..2ec69e8c661 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1368,7 +1368,10 @@ module ts { function writeIndent() { if (lineStart) { - displayParts.push(displayPart(getIndentString(indent), SymbolDisplayPartKind.space)); + var indentString = getIndentString(indent); + if (indentString) { + displayParts.push(displayPart(indentString, SymbolDisplayPartKind.space)); + } lineStart = false; } } @@ -1468,6 +1471,8 @@ module ts { return isFirstDeclarationOfSymbolParameter(symbol) ? SymbolDisplayPartKind.parameterName : SymbolDisplayPartKind.localName; } else if (flags & SymbolFlags.Property) { return SymbolDisplayPartKind.propertyName; } + else if (flags & SymbolFlags.GetAccessor) { return SymbolDisplayPartKind.propertyName; } + else if (flags & SymbolFlags.SetAccessor) { return SymbolDisplayPartKind.propertyName; } else if (flags & SymbolFlags.EnumMember) { return SymbolDisplayPartKind.enumMemberName; } else if (flags & SymbolFlags.Function) { return SymbolDisplayPartKind.functionName; } else if (flags & SymbolFlags.Class) { return SymbolDisplayPartKind.className; } @@ -1476,6 +1481,9 @@ module ts { else if (flags & SymbolFlags.Module) { return SymbolDisplayPartKind.moduleName; } else if (flags & SymbolFlags.Method) { return SymbolDisplayPartKind.methodName; } else if (flags & SymbolFlags.TypeParameter) { return SymbolDisplayPartKind.typeParameterName; } + else if (flags & SymbolFlags.TypeAlias) { return SymbolDisplayPartKind.aliasName; } + else if (flags & SymbolFlags.Import) { return SymbolDisplayPartKind.aliasName; } + return SymbolDisplayPartKind.text; } @@ -2753,6 +2761,7 @@ module ts { if (flags & SymbolFlags.TypeParameter) return ScriptElementKind.typeParameterElement; if (flags & SymbolFlags.EnumMember) return ScriptElementKind.variableElement; if (flags & SymbolFlags.Import) return ScriptElementKind.alias; + if (flags & SymbolFlags.Module) return ScriptElementKind.moduleElement; } return result; @@ -2934,6 +2943,7 @@ module ts { case ScriptElementKind.memberVariableElement: case ScriptElementKind.variableElement: case ScriptElementKind.constElement: + case ScriptElementKind.letElement: case ScriptElementKind.parameterElement: case ScriptElementKind.localVariableElement: // If it is call or construct signature of lambda's write type name @@ -2971,7 +2981,8 @@ module ts { if (functionDeclaration.kind === SyntaxKind.Constructor) { // show (constructor) Type(...) signature - addPrefixForAnyFunctionOrVar(type.symbol, ScriptElementKind.constructorImplementationElement); + symbolKind = ScriptElementKind.constructorImplementationElement; + addPrefixForAnyFunctionOrVar(type.symbol, symbolKind); } else { // (function/method) symbol(..signature) @@ -3003,7 +3014,7 @@ module ts { displayParts.push(spacePart()); addFullSymbolName(symbol); displayParts.push(spacePart()); - displayParts.push(punctuationPart(SyntaxKind.EqualsToken)); + displayParts.push(operatorPart(SyntaxKind.EqualsToken)); displayParts.push(spacePart()); displayParts.push.apply(displayParts, typeToDisplayParts(typeResolver, typeResolver.getDeclaredTypeOfSymbol(symbol), enclosingDeclaration)); } @@ -3075,7 +3086,7 @@ module ts { var importDeclaration = declaration; if (isExternalModuleImportDeclaration(importDeclaration)) { displayParts.push(spacePart()); - displayParts.push(punctuationPart(SyntaxKind.EqualsToken)); + displayParts.push(operatorPart(SyntaxKind.EqualsToken)); displayParts.push(spacePart()); displayParts.push(keywordPart(SyntaxKind.RequireKeyword)); displayParts.push(punctuationPart(SyntaxKind.OpenParenToken)); @@ -3086,7 +3097,7 @@ module ts { var internalAliasSymbol = typeResolver.getSymbolInfo(importDeclaration.moduleReference); if (internalAliasSymbol) { displayParts.push(spacePart()); - displayParts.push(punctuationPart(SyntaxKind.EqualsToken)); + displayParts.push(operatorPart(SyntaxKind.EqualsToken)); displayParts.push(spacePart()); addFullSymbolName(internalAliasSymbol, enclosingDeclaration); } @@ -3812,6 +3823,10 @@ module ts { return undefined; } } + else { + // unsupported modifier + return undefined; + } var keywords: Node[] = []; var modifierFlag: NodeFlags = getFlagFromModifier(modifier); diff --git a/tests/cases/fourslash/fourslash.ts b/tests/cases/fourslash/fourslash.ts index c0372d46063..8940ec98f2c 100644 --- a/tests/cases/fourslash/fourslash.ts +++ b/tests/cases/fourslash/fourslash.ts @@ -87,6 +87,10 @@ module FourSlashInterface { public ranges(): Range[] { return FourSlash.currentTestState.getRanges(); } + + public markerByName(s: string): Marker { + return FourSlash.currentTestState.getMarkerByName(s); + } } export class diagnostics { @@ -227,7 +231,7 @@ module FourSlashInterface { } public quickInfoIs(expectedText?: string, expectedDocumentation?: string) { - FourSlash.currentTestState.verifyQuickInfo(this.negative, expectedText, expectedDocumentation); + FourSlash.currentTestState.verifyQuickInfoString(this.negative, expectedText, expectedDocumentation); } public quickInfoExists() { @@ -430,6 +434,11 @@ module FourSlashInterface { public renameLocations(findInStrings: boolean, findInComments: boolean) { FourSlash.currentTestState.verifyRenameLocations(findInStrings, findInComments); } + + public verifyQuickInfoDisplayParts(kind: string, kindModifiers: string, textSpan: { start: number; length: number; }, + displayParts: ts.SymbolDisplayPart[], documentation: ts.SymbolDisplayPart[]) { + FourSlash.currentTestState.verifyQuickInfoDisplayParts(kind, kindModifiers, textSpan, displayParts, documentation); + } } export class edit { @@ -650,6 +659,12 @@ module fs { export var diagnostics = new FourSlashInterface.diagnostics(); export var cancellation = new FourSlashInterface.cancellation(); } +module ts { + export interface SymbolDisplayPart { + text: string; + kind: string; + } +} function verifyOperationIsCancelled(f) { FourSlash.verifyOperationIsCancelled(f); } diff --git a/tests/cases/fourslash/getOccurrencesConst.ts b/tests/cases/fourslash/getOccurrencesConst.ts new file mode 100644 index 00000000000..107ad4a5c24 --- /dev/null +++ b/tests/cases/fourslash/getOccurrencesConst.ts @@ -0,0 +1,14 @@ +/// + +/////*1*/const enum E1 { +//// v1, +//// v2 +////} +//// +/////*2*/const c = 0; + +goTo.marker("1"); +verify.occurrencesAtPositionCount(0); + +goTo.marker("2"); +verify.occurrencesAtPositionCount(0); diff --git a/tests/cases/fourslash/quickInfoDisplayPartsArrowFunctionExpression.ts b/tests/cases/fourslash/quickInfoDisplayPartsArrowFunctionExpression.ts new file mode 100644 index 00000000000..3d996ae53ca --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsArrowFunctionExpression.ts @@ -0,0 +1,50 @@ +/// + +////var /*1*/x = /*5*/a => 10; +////var /*2*/y = (/*6*/a, /*7*/b) => 10; +////var /*3*/z = (/*8*/a: number) => 10; +////var /*4*/z2 = () => 10; + +var marker = 0; +function verifyInstance(instanceName: string, paramCount: number, type: string) { + marker++; + goTo.marker(marker.toString()); + var displayParts = [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: instanceName, kind: "localName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "(", kind: "punctuation" }]; + + for (var i = 0; i < paramCount; i++) { + if (i) { + displayParts.push({ text: ",", kind: "punctuation" }, { text: " ", kind: "space" }); + } + displayParts.push({ text: !i ? "a" : "b", kind: "parameterName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: type, kind: "keyword" }); + } + displayParts.push({ text: ")", kind: "punctuation" }, { text: " ", kind: "space" }, + { text: "=>", kind: "punctuation" }, { text: " ", kind: "space" }, + { text: "number", kind: "keyword" }); + + + verify.verifyQuickInfoDisplayParts("var", "", { start: test.markerByName(marker.toString()).position, length: instanceName.length }, + displayParts, []); +} + +function verifyParameter(parameterName: string, type: string) { + marker++; + goTo.marker(marker.toString()); + verify.verifyQuickInfoDisplayParts("parameter", "", { start: test.markerByName(marker.toString()).position, length: parameterName.length }, + [{ text: "(", kind: "punctuation" }, { text: "parameter", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: parameterName, kind: "parameterName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: type, kind: "keyword" }], + []); +} + +verifyInstance("x", 1, "any"); +verifyInstance("y", 2, "any"); +verifyInstance("z", 1, "number"); +verifyInstance("z2", 0, "any"); + +verifyParameter("a", "any"); +verifyParameter("a", "any"); +verifyParameter("b", "any"); +verifyParameter("a", "number"); diff --git a/tests/cases/fourslash/quickInfoDisplayPartsClass.ts b/tests/cases/fourslash/quickInfoDisplayPartsClass.ts new file mode 100644 index 00000000000..ee38c717922 --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsClass.ts @@ -0,0 +1,39 @@ +/// + +////class /*1*/c { +////} +////var /*2*/cInstance = new /*3*/c(); +////var /*4*/cVal = /*5*/c; + +goTo.marker('1'); +verify.verifyQuickInfoDisplayParts("class", "", { start: test.markerByName("1").position, length: "c".length }, + [{ text: "class", kind: "keyword" }, { text: " ", kind: "space" }, { text: "c", kind: "className" }], + []); + +goTo.marker('2'); +verify.verifyQuickInfoDisplayParts("var", "", { start: test.markerByName("2").position, length: "cInstance".length }, + [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "cInstance", kind: "localName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "c", kind: "className" }], + []); + +goTo.marker('3'); +verify.verifyQuickInfoDisplayParts("constructor", "", { start: test.markerByName("3").position, length: "c".length }, + [{ text: "(", kind: "punctuation" }, { text: "constructor", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "c", kind: "className" }, + { text: "(", kind: "punctuation" }, { text: ")", kind: "punctuation" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "c", kind: "className" }], + []); + +goTo.marker('4'); +verify.verifyQuickInfoDisplayParts("var", "", { start: test.markerByName("4").position, length: "cVal".length }, + [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "cVal", kind: "localName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, + { text: "typeof", kind: "keyword" }, { text: " ", kind: "space" }, { text: "c", kind: "className" }], + []); + +goTo.marker('5'); +verify.verifyQuickInfoDisplayParts("class", "", { start: test.markerByName("5").position, length: "c".length }, + [{ text: "class", kind: "keyword" }, { text: " ", kind: "space" }, { text: "c", kind: "className" }], + []); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoDisplayPartsClassAccessors.ts b/tests/cases/fourslash/quickInfoDisplayPartsClassAccessors.ts new file mode 100644 index 00000000000..f3a0f90ea33 --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsClassAccessors.ts @@ -0,0 +1,129 @@ +/// + +////class c { +//// public get /*1*/publicProperty() { return ""; } +//// public set /*1s*/publicProperty(x: string) { } +//// private get /*2*/privateProperty() { return ""; } +//// private set /*2s*/privateProperty(x: string) { } +//// protected get /*21*/protectedProperty() { return ""; } +//// protected set /*21s*/protectedProperty(x: string) { } +//// static get /*3*/staticProperty() { return ""; } +//// static set /*3s*/staticProperty(x: string) { } +//// private static get /*4*/privateStaticProperty() { return ""; } +//// private static set /*4s*/privateStaticProperty(x: string) { } +//// protected static get /*41*/protectedStaticProperty() { return ""; } +//// protected static set /*41s*/protectedStaticProperty(x: string) { } +//// method() { +//// var x : string; +//// x = this./*5*/publicProperty; +//// x = this./*6*/privateProperty; +//// x = this./*61*/protectedProperty; +//// x = c./*7*/staticProperty; +//// x = c./*8*/privateStaticProperty; +//// x = c./*81*/protectedStaticProperty; +//// this./*5s*/publicProperty = ""; +//// this./*6s*/privateProperty = ""; +//// this./*61s*/protectedProperty = ""; +//// c./*7s*/staticProperty = ""; +//// c./*8s*/privateStaticProperty = ""; +//// c./*81s*/protectedStaticProperty = ""; +//// } +////} +////var cInstance = new c(); +////var y: string; +////y = /*9*/cInstance./*10*/publicProperty; +////y = /*11*/c./*12*/staticProperty; +/////*9s*/cInstance./*10s*/publicProperty = y; +/////*11s*/c./*12s*/staticProperty = y; + +function verifyClassProperty(markerName: string, kindModifiers: string, propertyName: string) { + goTo.marker(markerName); + verify.verifyQuickInfoDisplayParts("property", kindModifiers, { start: test.markerByName(markerName).position, length: propertyName.length }, + [{ text: "(", kind: "punctuation" }, { text: "property", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, + { text: "c", kind: "className" }, { text: ".", kind: "punctuation" }, { text: propertyName, kind: "propertyName" }, + { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "string", kind: "keyword" }], + []); +} + +function verifyPublicProperty(markerName: string) { + verifyClassProperty(markerName, "public", "publicProperty"); +} + +function verifyPrivateProperty(markerName: string) { + verifyClassProperty(markerName, "private", "privateProperty"); +} + +function verifyProtectedProperty(markerName: string) { + verifyClassProperty(markerName, "protected", "protectedProperty"); +} + +function verifyStaticProperty(markerName: string) { + verifyClassProperty(markerName, "static", "staticProperty"); +} + +function verifyPrivateStaticProperty(markerName: string) { + verifyClassProperty(markerName, "private,static", "privateStaticProperty"); +} + +function verifyProtectedStaticProperty(markerName: string) { + verifyClassProperty(markerName, "protected,static", "protectedStaticProperty"); +} + +verifyPublicProperty('1'); +verifyPublicProperty('1s'); +verifyPrivateProperty('2'); +verifyPrivateProperty('2s'); +verifyProtectedProperty('21'); +verifyProtectedProperty('21s'); +verifyStaticProperty('3'); +verifyStaticProperty('3s'); +verifyPrivateStaticProperty('4'); +verifyPrivateStaticProperty('4s'); +verifyProtectedStaticProperty('41'); +verifyProtectedStaticProperty('41s'); + +verifyPublicProperty('5'); +verifyPublicProperty('5s'); +verifyPrivateProperty('6'); +verifyPrivateProperty('6s'); +verifyProtectedProperty('61'); +verifyProtectedProperty('61s'); +verifyStaticProperty('7'); +verifyStaticProperty('7s'); +verifyPrivateStaticProperty('8'); +verifyPrivateStaticProperty('8s'); +verifyProtectedStaticProperty('81'); +verifyProtectedStaticProperty('81s'); + +goTo.marker('9'); +verify.verifyQuickInfoDisplayParts("var", "", { start: test.markerByName("9").position, length: "cInstance".length }, + [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "cInstance", kind: "localName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "c", kind: "className" }], + []); + +verifyPublicProperty('10'); + +goTo.marker('11'); +verify.verifyQuickInfoDisplayParts("class", "", { start: test.markerByName("11").position, length: "c".length }, + [{ text: "class", kind: "keyword" }, { text: " ", kind: "space" }, { text: "c", kind: "className" }], + []); + +verifyStaticProperty('12'); + +goTo.marker('9s'); +verify.verifyQuickInfoDisplayParts("var", "", { start: test.markerByName("9s").position, length: "cInstance".length }, + [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "cInstance", kind: "localName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "c", kind: "className" }], + []); + +verifyPublicProperty('10s'); + +goTo.marker('11s'); +verify.verifyQuickInfoDisplayParts("class", "", { start: test.markerByName("11s").position, length: "c".length }, + [{ text: "class", kind: "keyword" }, { text: " ", kind: "space" }, { text: "c", kind: "className" }], + []); + +verifyStaticProperty('12s'); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoDisplayPartsClassConstructor.ts b/tests/cases/fourslash/quickInfoDisplayPartsClassConstructor.ts new file mode 100644 index 00000000000..1145e43e1da --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsClassConstructor.ts @@ -0,0 +1,126 @@ +/// + +////class c { +//// /*1*/constructor() { +//// } +////} +////var /*2*/cInstance = new /*3*/c(); +////var /*4*/cVal = /*5*/c; +////class cWithOverloads { +//// /*6*/constructor(x: string); +//// /*7*/constructor(x: number); +//// /*8*/constructor(x: any) { +//// } +////} +////var /*9*/cWithOverloadsInstance = new /*10*/cWithOverloads("hello"); +////var /*11*/cWithOverloadsInstance2 = new /*12*/cWithOverloads(10); +////var /*13*/cWithOverloadsVal = /*14*/cWithOverloads; +////class cWithMultipleOverloads { +//// /*15*/constructor(x: string); +//// /*16*/constructor(x: number); +//// /*17*/constructor(x: boolean); +//// /*18*/constructor(x: any) { +//// } +////} +////var /*19*/cWithMultipleOverloadsInstance = new /*20*/cWithMultipleOverloads("hello"); +////var /*21*/cWithMultipleOverloadsInstance2 = new /*22*/cWithMultipleOverloads(10); +////var /*23*/cWithMultipleOverloadsInstance3 = new /*24*/cWithMultipleOverloads(true); +////var /*25*/cWithMultipleOverloadsVal = /*26*/cWithMultipleOverloads; + +function verifyNonOverloadSignature(marker: string, textSpanLength: number) { + goTo.marker(marker); + verify.verifyQuickInfoDisplayParts("constructor", "", { start: test.markerByName(marker).position, length: textSpanLength }, + [{ text: "(", kind: "punctuation" }, { text: "constructor", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "c", kind: "className" }, + { text: "(", kind: "punctuation" }, { text: ")", kind: "punctuation" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "c", kind: "className" }], + []); +} + +function verifyClassInstance(markerName: string, instanceName: string, className: string) { + goTo.marker(markerName); + verify.verifyQuickInfoDisplayParts("var", "", { start: test.markerByName(markerName).position, length: instanceName.length }, + [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: instanceName, kind: "localName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: className, kind: "className" }], + []); +} + +function verifyClass(markerName: string, className: string) { + goTo.marker(markerName); + verify.verifyQuickInfoDisplayParts("class", "", { start: test.markerByName(markerName).position, length: className.length }, + [{ text: "class", kind: "keyword" }, { text: " ", kind: "space" }, { text: className, kind: "className" }], + []); +} + +function verifyTypeOfClass(markerName: string, typeOfVarName: string, className: string) { + goTo.marker(markerName); + verify.verifyQuickInfoDisplayParts("var", "", { start: test.markerByName(markerName).position, length: typeOfVarName.length }, + [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: typeOfVarName, kind: "localName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, + { text: "typeof", kind: "keyword" }, { text: " ", kind: "space" }, { text: className, kind: "className" }], + []); +} + +function verifySingleOverloadSignature(marker: string, textSpanLength: number, parameterType: string) { + goTo.marker(marker); + verify.verifyQuickInfoDisplayParts("constructor", "", { start: test.markerByName(marker).position, length: textSpanLength }, + [{ text: "(", kind: "punctuation" }, { text: "constructor", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "cWithOverloads", kind: "className" }, { text: "(", kind: "punctuation" }, + { text: "x", kind: "parameterName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: parameterType, kind: "keyword" }, + { text: ")", kind: "punctuation" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "cWithOverloads", kind: "className" }, + { text: " ", kind: "space" }, { text: "(", kind: "punctuation" }, + { text: "+", kind: "operator" }, { text: "1", kind: "numericLiteral" }, + { text: " ", kind: "space" }, { text: "overload", kind: "text" }, + { text: ")", kind: "punctuation" }], + []); +} + +function verifyMultipleOverloadSignature(marker: string, textSpanLength: number, parameterType: string) { + goTo.marker(marker); + verify.verifyQuickInfoDisplayParts("constructor", "", { start: test.markerByName(marker).position, length: textSpanLength }, + [{ text: "(", kind: "punctuation" }, { text: "constructor", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "cWithMultipleOverloads", kind: "className" }, { text: "(", kind: "punctuation" }, + { text: "x", kind: "parameterName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: parameterType, kind: "keyword" }, + { text: ")", kind: "punctuation" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "cWithMultipleOverloads", kind: "className" }, + { text: " ", kind: "space" }, { text: "(", kind: "punctuation" }, + { text: "+", kind: "operator" }, { text: "2", kind: "numericLiteral" }, + { text: " ", kind: "space" }, { text: "overloads", kind: "text" }, + { text: ")", kind: "punctuation" }], + []); +} + + +verifyNonOverloadSignature("1", "constructor".length); +verifyClassInstance("2", "cInstance", "c"); +verifyNonOverloadSignature("3", "c".length); +verifyTypeOfClass("4", "cVal", "c"); +verifyClass("5", "c"); + +verifySingleOverloadSignature("6", "constructor".length, "string"); +verifySingleOverloadSignature("7", "constructor".length, "number"); +verifySingleOverloadSignature("8", "constructor".length, "string"); +verifyClassInstance("9", "cWithOverloadsInstance", "cWithOverloads"); +verifySingleOverloadSignature("10", "cWithOverloads".length, "string"); +verifyClassInstance("11", "cWithOverloadsInstance2", "cWithOverloads"); +verifySingleOverloadSignature("12", "cWithOverloads".length, "number"); +verifyTypeOfClass("13", "cWithOverloadsVal", "cWithOverloads"); +verifyClass("14", "cWithOverloads"); + +verifyMultipleOverloadSignature("15", "constructor".length, "string"); +verifyMultipleOverloadSignature("16", "constructor".length, "number"); +verifyMultipleOverloadSignature("17", "constructor".length, "boolean"); +verifyMultipleOverloadSignature("18", "constructor".length, "string"); +verifyClassInstance("19", "cWithMultipleOverloadsInstance", "cWithMultipleOverloads"); +verifyMultipleOverloadSignature("20", "cWithMultipleOverloads".length, "string"); +verifyClassInstance("21", "cWithMultipleOverloadsInstance2", "cWithMultipleOverloads"); +verifyMultipleOverloadSignature("22", "cWithMultipleOverloads".length, "number"); +verifyClassInstance("23", "cWithMultipleOverloadsInstance3", "cWithMultipleOverloads"); +verifyMultipleOverloadSignature("24", "cWithMultipleOverloads".length, "boolean"); +verifyTypeOfClass("25", "cWithMultipleOverloadsVal", "cWithMultipleOverloads"); +verifyClass("26", "cWithMultipleOverloads"); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoDisplayPartsClassMethod.ts b/tests/cases/fourslash/quickInfoDisplayPartsClassMethod.ts new file mode 100644 index 00000000000..dbe225aa124 --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsClassMethod.ts @@ -0,0 +1,86 @@ +/// + +////class c { +//// public /*1*/publicMethod() { } +//// private /*2*/privateMethod() { } +//// protected /*21*/protectedMethod() { } +//// static /*3*/staticMethod() { } +//// private static /*4*/privateStaticMethod() { } +//// protected static /*41*/protectedStaticMethod() { } +//// method() { +//// this./*5*/publicMethod(); +//// this./*6*/privateMethod(); +//// this./*61*/protectedMethod(); +//// c./*7*/staticMethod(); +//// c./*8*/privateStaticMethod(); +//// c./*81*/protectedStaticMethod(); +//// } +////} +////var cInstance = new c(); +/////*9*/cInstance./*10*/publicMethod(); +/////*11*/c./*12*/staticMethod(); + +function verifyClassMethod(markerName: string, kindModifiers: string, methodName: string) { + goTo.marker(markerName); + verify.verifyQuickInfoDisplayParts("method", kindModifiers, { start: test.markerByName(markerName).position, length: methodName.length }, + [{ text: "(", kind: "punctuation" }, { text: "method", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, + { text: "c", kind: "className" }, { text: ".", kind: "punctuation" }, { text: methodName, kind: "methodName" }, + { text: "(", kind: "punctuation" }, { text: ")", kind: "punctuation" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "void", kind: "keyword" }], + []); +} + +function verifyPublicMethod(markerName: string) { + verifyClassMethod(markerName, "public", "publicMethod"); +} + +function verifyPrivateMethod(markerName: string) { + verifyClassMethod(markerName, "private", "privateMethod"); +} + +function verifyProtectedMethod(markerName: string) { + verifyClassMethod(markerName, "protected", "protectedMethod"); +} + +function verifyStaticMethod(markerName: string) { + verifyClassMethod(markerName, "static", "staticMethod"); +} + +function verifyPrivateStaticMethod(markerName: string) { + verifyClassMethod(markerName, "private,static", "privateStaticMethod"); +} + +function verifyProtectedStaticMethod(markerName: string) { + verifyClassMethod(markerName, "protected,static", "protectedStaticMethod"); +} + +verifyPublicMethod('1'); +verifyPrivateMethod('2'); +verifyProtectedMethod('21'); +verifyStaticMethod('3'); +verifyPrivateStaticMethod('4'); +verifyProtectedStaticMethod('41'); + +verifyPublicMethod('5'); +verifyPrivateMethod('6'); +verifyProtectedMethod('61'); +verifyStaticMethod('7'); +verifyPrivateStaticMethod('8'); +verifyProtectedStaticMethod('81'); + +goTo.marker('9'); +verify.verifyQuickInfoDisplayParts("var", "", { start: test.markerByName("9").position, length: "cInstance".length }, + [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "cInstance", kind: "localName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "c", kind: "className" }], + []); + +verifyPublicMethod('10'); + +goTo.marker('11'); +verify.verifyQuickInfoDisplayParts("class", "", { start: test.markerByName("11").position, length: "c".length }, + [{ text: "class", kind: "keyword" }, { text: " ", kind: "space" }, { text: "c", kind: "className" }], + []); + +verifyStaticMethod('12'); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoDisplayPartsClassProperty.ts b/tests/cases/fourslash/quickInfoDisplayPartsClassProperty.ts new file mode 100644 index 00000000000..a03bc3cd42b --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsClassProperty.ts @@ -0,0 +1,85 @@ +/// + +////class c { +//// public /*1*/publicProperty: string; +//// private /*2*/privateProperty: string; +//// protected /*21*/protectedProperty: string; +//// static /*3*/staticProperty: string; +//// private static /*4*/privateStaticProperty: string; +//// protected static /*41*/protectedStaticProperty: string; +//// method() { +//// this./*5*/publicProperty; +//// this./*6*/privateProperty; +//// this./*61*/protectedProperty; +//// c./*7*/staticProperty; +//// c./*8*/privateStaticProperty; +//// c./*81*/protectedStaticProperty; +//// } +////} +////var cInstance = new c(); +/////*9*/cInstance./*10*/publicProperty; +/////*11*/c./*12*/staticProperty; + +function verifyClassProperty(markerName: string, kindModifiers: string, propertyName: string) { + goTo.marker(markerName); + verify.verifyQuickInfoDisplayParts("property", kindModifiers, { start: test.markerByName(markerName).position, length: propertyName.length }, + [{ text: "(", kind: "punctuation" }, { text: "property", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, + { text: "c", kind: "className" }, { text: ".", kind: "punctuation" }, { text: propertyName, kind: "propertyName" }, + { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "string", kind: "keyword" }], + []); +} + +function verifyPublicProperty(markerName: string) { + verifyClassProperty(markerName, "public", "publicProperty"); +} + +function verifyPrivateProperty(markerName: string) { + verifyClassProperty(markerName, "private", "privateProperty"); +} + +function verifyProtectedProperty(markerName: string) { + verifyClassProperty(markerName, "protected", "protectedProperty"); +} + +function verifyStaticProperty(markerName: string) { + verifyClassProperty(markerName, "static", "staticProperty"); +} + +function verifyPrivateStaticProperty(markerName: string) { + verifyClassProperty(markerName, "private,static", "privateStaticProperty"); +} + +function verifyProtectedStaticProperty(markerName: string) { + verifyClassProperty(markerName, "protected,static", "protectedStaticProperty"); +} + +verifyPublicProperty('1'); +verifyPrivateProperty('2'); +verifyProtectedProperty('21'); +verifyStaticProperty('3'); +verifyPrivateStaticProperty('4'); +verifyProtectedStaticProperty('41'); + +verifyPublicProperty('5'); +verifyPrivateProperty('6'); +verifyProtectedProperty('61'); +verifyStaticProperty('7'); +verifyPrivateStaticProperty('8'); +verifyProtectedStaticProperty('81'); + +goTo.marker('9'); +verify.verifyQuickInfoDisplayParts("var", "", { start: test.markerByName("9").position, length: "cInstance".length }, + [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "cInstance", kind: "localName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "c", kind: "className" }], + []); + +verifyPublicProperty('10'); + +goTo.marker('11'); +verify.verifyQuickInfoDisplayParts("class", "", { start: test.markerByName("11").position, length: "c".length }, + [{ text: "class", kind: "keyword" }, { text: " ", kind: "space" }, { text: "c", kind: "className" }], + []); + +verifyStaticProperty('12'); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoDisplayPartsConst.ts b/tests/cases/fourslash/quickInfoDisplayPartsConst.ts new file mode 100644 index 00000000000..62295017dfc --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsConst.ts @@ -0,0 +1,83 @@ +/// + +////const /*1*/a = 10; +////function foo() { +//// const /*2*/b = /*3*/a; +//// if (b) { +//// const /*4*/b1 = 10; +//// } +////} +////module m { +//// const /*5*/c = 10; +//// export const /*6*/d = 10; +//// if (c) { +//// const /*7*/e = 10; +//// } +////} +////const /*8*/f: () => number = () => 10; +////const /*9*/g = /*10*/f; +/////*11*/f(); +////const /*12*/h: { (a: string): number; (a: number): string; } = a => a; +////const /*13*/i = /*14*/h; +/////*15*/h(10); +/////*16*/h("hello"); + +var marker = 0; +function verifyConst(name: string, typeDisplay: ts.SymbolDisplayPart[], optionalNameDisplay?: ts.SymbolDisplayPart[], optionalKindModifiers?: string) { + marker++; + goTo.marker(marker.toString()); + verify.verifyQuickInfoDisplayParts("const", optionalKindModifiers || "", { start: test.markerByName(marker.toString()).position, length: name.length }, + [{ text: "(", kind: "punctuation" }, { text: "const", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }].concat(optionalNameDisplay || [{ text: name, kind: "localName" }]).concat( + { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }).concat(typeDisplay), + []); +} + +var numberTypeDisplay: ts.SymbolDisplayPart[] = [{ text: "number", kind: "keyword" }]; + +verifyConst("a", numberTypeDisplay); +verifyConst("b", numberTypeDisplay); +verifyConst("a", numberTypeDisplay); +verifyConst("b1", numberTypeDisplay); +verifyConst("c", numberTypeDisplay); +verifyConst("d", numberTypeDisplay, [{ text: "m", kind: "moduleName" }, { text: ".", kind: "punctuation" }, { text: "d", kind: "localName" }], "export"); +verifyConst("e", numberTypeDisplay); + +var functionTypeReturningNumber: ts.SymbolDisplayPart[] = [{ text: "(", kind: "punctuation" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "=>", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "number", kind: "keyword" }]; +verifyConst("f", functionTypeReturningNumber); +verifyConst("g", functionTypeReturningNumber); +verifyConst("f", functionTypeReturningNumber); +verifyConst("f", functionTypeReturningNumber); + + +function getFunctionType(parametertype: string, returnType: string, isArrow?: boolean): ts.SymbolDisplayPart[] { + var functionTypeDisplay = [{ text: "(", kind: "punctuation" }, { text: "a", kind: "parameterName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: parametertype, kind: "keyword" }, { text: ")", kind: "punctuation" }]; + + if (isArrow) { + functionTypeDisplay = functionTypeDisplay.concat({ text: " ", kind: "space" }, { text: "=>", kind: "punctuation" }); + } + else { + functionTypeDisplay = functionTypeDisplay.concat({ text: ":", kind: "punctuation" }); + } + + return functionTypeDisplay.concat({ text: " ", kind: "space" }, { text: returnType, kind: "keyword" }); +} + +var typeLiteralWithOverloadCall: ts.SymbolDisplayPart[] = [{ text: "{", kind: "punctuation" }, { text: "\n", kind: "lineBreak" }, + { text: " ", kind: "space" }].concat(getFunctionType("string", "number")).concat( + { text: ";", kind: "punctuation" }, { text: "\n", kind: "lineBreak" }, + { text: " ", kind: "space" }).concat(getFunctionType("number", "string")).concat( + { text: ";", kind: "punctuation" }, { text: "\n", kind: "lineBreak" }, { text: "}", kind: "punctuation" }); + +verifyConst("h", typeLiteralWithOverloadCall); +verifyConst("i", typeLiteralWithOverloadCall); +verifyConst("h", typeLiteralWithOverloadCall); + +var overloadDisplay: ts.SymbolDisplayPart[] = [{ text: " ", kind: "space" }, { text: "(", kind: "punctuation" }, + { text: "+", kind: "operator" }, { text: "1", kind: "numericLiteral" }, + { text: " ", kind: "space" }, { text: "overload", kind: "text" }, { text: ")", kind: "punctuation" }]; + +verifyConst("h", getFunctionType("number", "string", /*isArrow*/true).concat(overloadDisplay)); +verifyConst("h", getFunctionType("string", "number", /*isArrow*/true).concat(overloadDisplay)); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoDisplayPartsEnum.ts b/tests/cases/fourslash/quickInfoDisplayPartsEnum.ts new file mode 100644 index 00000000000..405f9db936e --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsEnum.ts @@ -0,0 +1,76 @@ +/// + +////enum /*1*/E { +//// /*2*/e1, +//// /*3*/e2 = 10, +//// /*4*/e3 +////} +////var /*5*/eInstance: /*6*/E; +/////*7*/eInstance = /*8*/E./*9*/e1; +/////*10*/eInstance = /*11*/E./*12*/e2; +/////*13*/eInstance = /*14*/E./*15*/e3; +////const enum /*16*/constE { +//// /*17*/e1, +//// /*18*/e2 = 10, +//// /*19*/e3 +////} +////var /*20*/eInstance1: /*21*/constE; +/////*22*/eInstance1 = /*23*/constE./*24*/e1; +/////*25*/eInstance1 = /*26*/constE./*27*/e2; +/////*28*/eInstance1 = /*29*/constE./*30*/e3; + +var marker = 0; +function verifyEnumDeclaration(enumName: string, instanceName: string, isConst?: boolean) { + verifyEnumDisplay(); + + verifyEnumMemberDisplay("e1", 0); + verifyEnumMemberDisplay("e2", 10); + verifyEnumMemberDisplay("e3", 11); + + verifyInstance(); + verifyEnumDisplay(); + + verifyInstance(); + verifyEnumDisplay(); + verifyEnumMemberDisplay("e1", 0); + + verifyInstance(); + verifyEnumDisplay(); + verifyEnumMemberDisplay("e2", 10); + + verifyInstance(); + verifyEnumDisplay(); + verifyEnumMemberDisplay("e3", 11); + + function verifyEnumDisplay() { + marker++; + goTo.marker(marker.toString()); + verify.verifyQuickInfoDisplayParts("enum", "", { start: test.markerByName(marker.toString()).position, length: enumName.length }, + (isConst ? [{ text: "const", kind: "keyword" }, { text: " ", kind: "space" }] : []).concat( + [{ text: "enum", kind: "keyword" }, { text: " ", kind: "space" }, { text: enumName, kind: "enumName" }]), + []);; + } + + function verifyEnumMemberDisplay(enumMemberName: string, initializer: number) { + marker++; + goTo.marker(marker.toString()); + verify.verifyQuickInfoDisplayParts("var", "", { start: test.markerByName(marker.toString()).position, length: enumMemberName.length }, + [{ text: "(", kind: "punctuation" }, { text: "enum member", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: enumName, kind: "enumName" }, { text: ".", kind: "punctuation" }, { text: enumMemberName, kind: "enumMemberName" }, + { text: " ", kind: "space" }, { text: "=", kind: "operator" }, { text: " ", kind: "space" }, { text: initializer.toString(), kind: "numericLiteral" }], + []); + } + + function verifyInstance() { + marker++; + goTo.marker(marker.toString()); + verify.verifyQuickInfoDisplayParts("var", "", { start: test.markerByName(marker.toString()).position, length: instanceName.length }, + [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: instanceName, kind: "localName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: enumName, kind: "enumName" }], + []); + } +} + +verifyEnumDeclaration("E", "eInstance"); +verifyEnumDeclaration("constE", "eInstance1", /*isConst*/ true); diff --git a/tests/cases/fourslash/quickInfoDisplayPartsExternalModuleAlias.ts b/tests/cases/fourslash/quickInfoDisplayPartsExternalModuleAlias.ts new file mode 100644 index 00000000000..2c43326469c --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsExternalModuleAlias.ts @@ -0,0 +1,44 @@ +/// + +// @Filename: quickInfoDisplayPartsExternalModuleAlias_file0.ts +////export module m1 { +//// export class c { +//// } +////} + +// @Filename: quickInfoDisplayPartsExternalModuleAlias_file1.ts +////import /*1*/a1 = require(/*mod1*/"quickInfoDisplayPartsExternalModuleAlias_file0"); +////new /*2*/a1.m1.c(); +////export import /*3*/a2 = require(/*mod2*/"quickInfoDisplayPartsExternalModuleAlias_file0"); +////new /*4*/a2.m1.c(); + +var marker = 0; +function goToMarker() { + marker++; + goTo.marker(marker.toString()); +} + +function verifyImport(name: string, isExported: boolean) { + goToMarker(); + verify.verifyQuickInfoDisplayParts("alias", isExported ? "export" : "", { start: test.markerByName(marker.toString()).position, length: name.length }, + [{ text: "import", kind: "keyword" }, { text: " ", kind: "space" }, { text: name, kind: "aliasName" }, + { text: " ", kind: "space" }, { text: "=", kind: "operator" }, { text: " ", kind: "space" }, + { text: "require", kind: "keyword" }, { text: "(", kind: "punctuation" }, + { text: "\"quickInfoDisplayPartsExternalModuleAlias_file0\"", kind: "stringLiteral" }, + { text: ")", kind: "punctuation" }], + []); +} +verifyImport("a1", /*isExported*/false); +verifyImport("a1", /*isExported*/false); +verifyImport("a2", /*isExported*/true); +verifyImport("a2", /*isExported*/true); + +function verifyExternalModuleStringLiteral(marker: string) { + goTo.marker(marker); + verify.verifyQuickInfoDisplayParts("module", "", { start: test.markerByName(marker).position, length: "\"quickInfoDisplayPartsExternalModuleAlias_file0\"".length }, + [{ text: "module", kind: "keyword" }, { text: " ", kind: "space" }, { text: "a1", kind: "aliasName" }], + []); +} + +verifyExternalModuleStringLiteral("mod1"); +verifyExternalModuleStringLiteral("mod2"); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoDisplayPartsExternalModules.ts b/tests/cases/fourslash/quickInfoDisplayPartsExternalModules.ts new file mode 100644 index 00000000000..5a2f5e76d7f --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsExternalModules.ts @@ -0,0 +1,63 @@ +/// + +////export module /*1*/m { +//// var /*2*/moduleElemWithoutExport = 10; +//// export var /*3*/moduleElemWithExport = 10; +////} +////export var /*4*/a = /*5*/m; +////export var /*6*/b: typeof /*7*/m; +////export module /*8*/m1./*9*/m2 { +//// var /*10*/moduleElemWithoutExport = 10; +//// export var /*11*/moduleElemWithExport = 10; +////} +////export var /*12*/x = /*13*/m1./*14*/m2; +////export var /*15*/y: typeof /*16*/m1./*17*/m2; + +var marker = 0; +function goToMarker() { + marker++; + goTo.marker(marker.toString()); +} + +function verifyModule(name: string, optionalParentName?: string) { + goToMarker(); + var moduleNameDisplay = [{ text: name, kind: "moduleName" }]; + if (optionalParentName) { + moduleNameDisplay = [{ text: optionalParentName, kind: "moduleName" }, { text: ".", kind: "punctuation" }].concat(moduleNameDisplay); + } + verify.verifyQuickInfoDisplayParts("module", "export", { start: test.markerByName(marker.toString()).position, length: name.length }, + [{ text: "module", kind: "keyword" }, { text: " ", kind: "space" }].concat(moduleNameDisplay), + []); +} + +function verifyVar(name: string, optionalFullName?: ts.SymbolDisplayPart[], typeDisplay: ts.SymbolDisplayPart[]= [{ text: "number", kind: "keyword" }]) { + goToMarker(); + verify.verifyQuickInfoDisplayParts("var", name === "moduleElemWithoutExport" ? "" : "export", { start: test.markerByName(marker.toString()).position, length: name.length }, + [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }].concat(optionalFullName || [{ text: name, kind: "localName" }]).concat( + { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }).concat(typeDisplay), + []); +} + +verifyModule("m"); +verifyVar("moduleElemWithoutExport"); +verifyVar("moduleElemWithExport", [{ text: "m", kind: "moduleName" }, { text: ".", kind: "punctuation" }, { text: "moduleElemWithExport", kind: "localName" }]); + +verifyVar("a", /*optionalFullName*/ undefined, [{ text: "typeof", kind: "keyword" }, { text: " ", kind: "space" }, { text: "m", kind: "moduleName" }]); +verifyModule("m"); +verifyVar("b", /*optionalFullName*/ undefined, [{ text: "typeof", kind: "keyword" }, { text: " ", kind: "space" }, { text: "m", kind: "moduleName" }]); +verifyModule("m"); + +verifyModule("m1"); +verifyModule("m2", "m1"); +verifyVar("moduleElemWithoutExport"); +verifyVar("moduleElemWithExport", [{ text: "m1", kind: "moduleName" }, { text: ".", kind: "punctuation" }, + { text: "m2", kind: "moduleName" }, { text: ".", kind: "punctuation" }, { text: "moduleElemWithExport", kind: "localName" }]); +verifyVar("x", /*optionalFullName*/ undefined, [{ text: "typeof", kind: "keyword" }, { text: " ", kind: "space" }, + { text: "m1", kind: "moduleName" }, { text: ".", kind: "punctuation" }, { text: "m2", kind: "moduleName" }]); +verifyModule("m1"); +verifyModule("m2", "m1"); +verifyVar("y", /*optionalFullName*/ undefined, [{ text: "typeof", kind: "keyword" }, { text: " ", kind: "space" }, + { text: "m1", kind: "moduleName" }, { text: ".", kind: "punctuation" }, { text: "m2", kind: "moduleName" }]); +verifyModule("m1"); +verifyModule("m2", "m1"); diff --git a/tests/cases/fourslash/quickInfoDisplayPartsFunction.ts b/tests/cases/fourslash/quickInfoDisplayPartsFunction.ts new file mode 100644 index 00000000000..a3c94a511b9 --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsFunction.ts @@ -0,0 +1,76 @@ +/// + +////function /*1*/foo(param: string, optionalParam?: string, paramWithInitializer = "hello", ...restParam: string[]) { +////} +////function /*2*/foowithoverload(a: string): string; +////function /*3*/foowithoverload(a: number): number; +////function /*4*/foowithoverload(a: any): any { +//// return a; +////} +////function /*5*/foowith3overload(a: string): string; +////function /*6*/foowith3overload(a: number): number; +////function /*7*/foowith3overload(a: boolean): boolean; +////function /*8*/foowith3overload(a: any): any { +//// return a; +////} +/////*9*/foo("hello"); +/////*10*/foowithoverload("hello"); +/////*11*/foowithoverload(10); +/////*12*/foowith3overload("hello"); +/////*13*/foowith3overload(10); +/////*14*/foowith3overload(true); + +var marker = 0; +function verifyFunctionWithoutOverload() { + marker++; + goTo.marker(marker.toString()); + verify.verifyQuickInfoDisplayParts("function", "", { start: test.markerByName(marker.toString()).position, length: "foo".length }, + [{ text: "(", kind: "punctuation" }, { text: "function", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "foo", kind: "functionName" }, { text: "(", kind: "punctuation" }, + { text: "param", kind: "parameterName" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "string", kind: "keyword" }, + { text: ",", kind: "punctuation" }, { text: " ", kind: "space" }, + { text: "optionalParam", kind: "parameterName" }, { text: "?", kind: "punctuation" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "string", kind: "keyword" }, + { text: ",", kind: "punctuation" }, { text: " ", kind: "space" }, + { text: "paramWithInitializer", kind: "parameterName" }, { text: "?", kind: "punctuation" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "string", kind: "keyword" }, + { text: ",", kind: "punctuation" }, { text: " ", kind: "space" }, + { text: "...", kind: "punctuation" }, { text: "restParam", kind: "parameterName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "string", kind: "keyword" }, { text: "[", kind: "punctuation" }, { text: "]", kind: "punctuation" }, + { text: ")", kind: "punctuation" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "void", kind: "keyword" }], + []); +} + +function verifyFunctionWithOverload(functionName: string, type: string, overloadCount: number) { + marker++; + goTo.marker(marker.toString()); + verify.verifyQuickInfoDisplayParts("function", "", { start: test.markerByName(marker.toString()).position, length: functionName.length }, + [{ text: "(", kind: "punctuation" }, { text: "function", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: functionName, kind: "functionName" }, { text: "(", kind: "punctuation" }, + { text: "a", kind: "parameterName" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: type, kind: "keyword" }, + { text: ")", kind: "punctuation" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: type, kind: "keyword" }, + { text: " ", kind: "space" }, { text: "(", kind: "punctuation" }, { text: "+", kind: "operator" }, { text: overloadCount.toString(), kind: "numericLiteral" }, + { text: " ", kind: "space" }, { text: overloadCount === 1 ? "overload" : "overloads", kind: "text" }, { text: ")", kind: "punctuation" }], + []); +} + + +// Declarations +verifyFunctionWithoutOverload(); + +verifyFunctionWithOverload("foowithoverload", "string", 1); +verifyFunctionWithOverload("foowithoverload", "number", 1); +verifyFunctionWithOverload("foowithoverload", "string", 1); + +verifyFunctionWithOverload("foowith3overload", "string", 2); +verifyFunctionWithOverload("foowith3overload", "number", 2); +verifyFunctionWithOverload("foowith3overload", "boolean", 2); +verifyFunctionWithOverload("foowith3overload", "string", 2); + +// Calls +verifyFunctionWithoutOverload(); + +verifyFunctionWithOverload("foowithoverload", "string", 1); +verifyFunctionWithOverload("foowithoverload", "number", 1); + +verifyFunctionWithOverload("foowith3overload", "string", 2); +verifyFunctionWithOverload("foowith3overload", "number", 2); +verifyFunctionWithOverload("foowith3overload", "boolean", 2); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoDisplayPartsFunctionExpression.ts b/tests/cases/fourslash/quickInfoDisplayPartsFunctionExpression.ts new file mode 100644 index 00000000000..2b88812d60d --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsFunctionExpression.ts @@ -0,0 +1,45 @@ +/// + +////var /*1*/x = function /*2*/foo() { +//// /*3*/foo(); +////}; +////var /*4*/y = function () { +////}; +////(function /*5*/foo1() { +//// /*6*/foo1(); +////})(); + +var marker = 0; +function verifyInstance(instanceName: string) { + marker++; + goTo.marker(marker.toString()); + verify.verifyQuickInfoDisplayParts("var", "", { start: test.markerByName(marker.toString()).position, length: instanceName.length }, + [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: instanceName, kind: "localName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "(", kind: "punctuation" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "=>", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "void", kind: "keyword" }], + []); +} + +function verifyNamedFunctionExpression(functionName: string) { + marker++; + goTo.marker(marker.toString()); + verify.verifyQuickInfoDisplayParts("local function", "", { start: test.markerByName(marker.toString()).position, length: functionName.length }, + [{ text: "(", kind: "punctuation" }, { text: "local function", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: functionName, kind: "functionName" }, { text: "(", kind: "punctuation" }, + { text: ")", kind: "punctuation" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "void", kind: "keyword" }], + []); +} + +verifyInstance("x"); +// Declaration +verifyNamedFunctionExpression("foo"); +// Call +verifyNamedFunctionExpression("foo"); + +verifyInstance("y"); + +// Declaration +verifyNamedFunctionExpression("foo1"); +// Call +verifyNamedFunctionExpression("foo1"); diff --git a/tests/cases/fourslash/quickInfoDisplayPartsInterface.ts b/tests/cases/fourslash/quickInfoDisplayPartsInterface.ts new file mode 100644 index 00000000000..410d45d32a1 --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsInterface.ts @@ -0,0 +1,22 @@ +/// + +////interface /*1*/i { +////} +////var /*2*/iInstance: /*3*/i; + +goTo.marker('1'); +verify.verifyQuickInfoDisplayParts("interface", "", { start: test.markerByName("1").position, length: "i".length }, + [{ text: "interface", kind: "keyword" }, { text: " ", kind: "space" }, { text: "i", kind: "interfaceName" }], + []); + +goTo.marker('2'); +verify.verifyQuickInfoDisplayParts("var", "", { start: test.markerByName("2").position, length: "iInstance".length }, + [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "iInstance", kind: "localName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "i", kind: "interfaceName" }], + []); + +goTo.marker('3'); +verify.verifyQuickInfoDisplayParts("interface", "", { start: test.markerByName("3").position, length: "i".length }, + [{ text: "interface", kind: "keyword" }, { text: " ", kind: "space" }, { text: "i", kind: "interfaceName" }], + []); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoDisplayPartsInterfaceMembers.ts b/tests/cases/fourslash/quickInfoDisplayPartsInterfaceMembers.ts new file mode 100644 index 00000000000..1b7fdad23aa --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsInterfaceMembers.ts @@ -0,0 +1,75 @@ +/// + +////interface I { +//// /*1*/property: string; +//// /*2*/method(): string; +//// (): string; +//// new (): I; +////} +////var iInstance: I; +/////*3*/iInstance./*4*/property = /*5*/iInstance./*6*/method(); +/////*7*/iInstance(); +////var /*8*/anotherInstance = new /*9*/iInstance(); + +function verifyInterfaceProperty(markerName: string) { + goTo.marker(markerName); + verify.verifyQuickInfoDisplayParts("property", "", { start: test.markerByName(markerName).position, length: "property".length }, + [{ text: "(", kind: "punctuation" }, { text: "property", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, + { text: "I", kind: "interfaceName" }, { text: ".", kind: "punctuation" }, { text: "property", kind: "propertyName" }, + { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "string", kind: "keyword" }], + []); +} + +function verifyInterfaceMethod(markerName: string) { + goTo.marker(markerName); + verify.verifyQuickInfoDisplayParts("method", "", { start: test.markerByName(markerName).position, length: "method".length }, + [{ text: "(", kind: "punctuation" }, { text: "method", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, + { text: "I", kind: "interfaceName" }, { text: ".", kind: "punctuation" }, { text: "method", kind: "methodName" }, + { text: "(", kind: "punctuation" }, { text: ")", kind: "punctuation" }, + { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "string", kind: "keyword" }], + []); +} + +function verifyInterfaceInstanceVar(markerName: string, instanceName: string) { + goTo.marker(markerName); + verify.verifyQuickInfoDisplayParts("var", "", { start: test.markerByName(markerName).position, length: instanceName.length }, + [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: instanceName, kind: "localName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "I", kind: "interfaceName" }], + []); +} + +verifyInterfaceProperty('1'); +verifyInterfaceMethod("2"); + +verifyInterfaceInstanceVar("3", "iInstance"); +verifyInterfaceProperty("4"); +verifyInterfaceInstanceVar("5", "iInstance"); +verifyInterfaceMethod("6"); + +// Call signature +goTo.marker("7"); +verify.verifyQuickInfoDisplayParts("var", "", { start: test.markerByName("7").position, length: "iInstance".length }, + [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "iInstance", kind: "localName" }, + { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "I", kind: "interfaceName" }, + { text: "(", kind: "punctuation" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "=>", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "string", kind: "keyword" }], + []); + +verifyInterfaceInstanceVar("8", "anotherInstance"); + +// Cosntruct signature +goTo.marker("9"); +verify.verifyQuickInfoDisplayParts("var", "", { start: test.markerByName("9").position, length: "iInstance".length }, + [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "iInstance", kind: "localName" }, + { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, + { text: "new", kind: "keyword" }, { text: " ", kind: "space" }, { text: "I", kind: "interfaceName" }, + { text: "(", kind: "punctuation" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "=>", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "I", kind: "interfaceName" }], + []); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoDisplayPartsInternalModuleAlias.ts b/tests/cases/fourslash/quickInfoDisplayPartsInternalModuleAlias.ts new file mode 100644 index 00000000000..335544a62db --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsInternalModuleAlias.ts @@ -0,0 +1,47 @@ +/// + +////module m.m1 { +//// export class c { +//// } +////} +////module m2 { +//// import /*1*/a1 = m; +//// new /*2*/a1.m1.c(); +//// import /*3*/a2 = m.m1; +//// new /*4*/a2.c(); +//// export import /*5*/a3 = m; +//// new /*6*/a3.m1.c(); +//// export import /*7*/a4 = m.m1; +//// new /*8*/a4.c(); +////} + +var marker = 0; +function goToMarker() { + marker++; + goTo.marker(marker.toString()); +} + +function verifyImport(name: string, assigningDisplay:ts.SymbolDisplayPart[], optionalParentName?: string) { + goToMarker(); + var moduleNameDisplay = [{ text: name, kind: "aliasName" }]; + if (optionalParentName) { + moduleNameDisplay = [{ text: optionalParentName, kind: "moduleName" }, { text: ".", kind: "punctuation" }].concat(moduleNameDisplay); + } + verify.verifyQuickInfoDisplayParts("alias", optionalParentName ? "export" : "", { start: test.markerByName(marker.toString()).position, length: name.length }, + [{ text: "import", kind: "keyword" }, { text: " ", kind: "space" }].concat(moduleNameDisplay).concat( + { text: " ", kind: "space" }, { text: "=", kind: "operator" }, { text: " ", kind: "space" }).concat(assigningDisplay), + []); +} + +var moduleMDisplay = [{ text: "m", kind: "moduleName" }]; +var moduleMDotM1Display = moduleMDisplay.concat({ text: ".", kind: "punctuation" }, { text: "m1", kind: "moduleName" }); + +verifyImport("a1", moduleMDisplay); +verifyImport("a1", moduleMDisplay); +verifyImport("a2", moduleMDotM1Display); +verifyImport("a2", moduleMDotM1Display); + +verifyImport("a3", moduleMDisplay, "m2"); +verifyImport("a3", moduleMDisplay, "m2"); +verifyImport("a4", moduleMDotM1Display, "m2"); +verifyImport("a4", moduleMDotM1Display, "m2"); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoDisplayPartsLet.ts b/tests/cases/fourslash/quickInfoDisplayPartsLet.ts new file mode 100644 index 00000000000..b54617faa0e --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsLet.ts @@ -0,0 +1,83 @@ +/// + +////let /*1*/a = 10; +////function foo() { +//// let /*2*/b = /*3*/a; +//// if (b) { +//// let /*4*/b1 = 10; +//// } +////} +////module m { +//// let /*5*/c = 10; +//// export let /*6*/d = 10; +//// if (c) { +//// let /*7*/e = 10; +//// } +////} +////let /*8*/f: () => number; +////let /*9*/g = /*10*/f; +/////*11*/f(); +////let /*12*/h: { (a: string): number; (a: number): string; }; +////let /*13*/i = /*14*/h; +/////*15*/h(10); +/////*16*/h("hello"); + +var marker = 0; +function verifyVar(name: string, typeDisplay: ts.SymbolDisplayPart[], optionalNameDisplay?: ts.SymbolDisplayPart[], optionalKindModifiers?: string) { + marker++; + goTo.marker(marker.toString()); + verify.verifyQuickInfoDisplayParts("let", optionalKindModifiers || "", { start: test.markerByName(marker.toString()).position, length: name.length }, + [{ text: "(", kind: "punctuation" }, { text: "let", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }].concat(optionalNameDisplay || [{ text: name, kind: "localName" }]).concat( + { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }).concat(typeDisplay), + []); +} + +var numberTypeDisplay: ts.SymbolDisplayPart[] = [{ text: "number", kind: "keyword" }]; + +verifyVar("a", numberTypeDisplay); +verifyVar("b", numberTypeDisplay); +verifyVar("a", numberTypeDisplay); +verifyVar("b1", numberTypeDisplay); +verifyVar("c", numberTypeDisplay); +verifyVar("d", numberTypeDisplay, [{ text: "m", kind: "moduleName" }, { text: ".", kind: "punctuation" }, { text: "d", kind: "localName" }], "export"); +verifyVar("e", numberTypeDisplay); + +var functionTypeReturningNumber: ts.SymbolDisplayPart[] = [{ text: "(", kind: "punctuation" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "=>", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "number", kind: "keyword" }]; +verifyVar("f", functionTypeReturningNumber); +verifyVar("g", functionTypeReturningNumber); +verifyVar("f", functionTypeReturningNumber); +verifyVar("f", functionTypeReturningNumber); + + +function getFunctionType(parametertype: string, returnType: string, isArrow?: boolean): ts.SymbolDisplayPart[] { + var functionTypeDisplay = [{ text: "(", kind: "punctuation" }, { text: "a", kind: "parameterName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: parametertype, kind: "keyword" }, { text: ")", kind: "punctuation" }]; + + if (isArrow) { + functionTypeDisplay = functionTypeDisplay.concat({ text: " ", kind: "space" }, { text: "=>", kind: "punctuation" }); + } + else { + functionTypeDisplay = functionTypeDisplay.concat({ text: ":", kind: "punctuation" }); + } + + return functionTypeDisplay.concat({ text: " ", kind: "space" }, { text: returnType, kind: "keyword" }); +} + +var typeLiteralWithOverloadCall: ts.SymbolDisplayPart[] = [{ text: "{", kind: "punctuation" }, { text: "\n", kind: "lineBreak" }, + { text: " ", kind: "space" }].concat(getFunctionType("string", "number")).concat( + { text: ";", kind: "punctuation" }, { text: "\n", kind: "lineBreak" }, + { text: " ", kind: "space" }).concat(getFunctionType("number", "string")).concat( + { text: ";", kind: "punctuation" }, { text: "\n", kind: "lineBreak" }, { text: "}", kind: "punctuation" }); + +verifyVar("h", typeLiteralWithOverloadCall); +verifyVar("i", typeLiteralWithOverloadCall); +verifyVar("h", typeLiteralWithOverloadCall); + +var overloadDisplay: ts.SymbolDisplayPart[] = [{ text: " ", kind: "space" }, { text: "(", kind: "punctuation" }, + { text: "+", kind: "operator" }, { text: "1", kind: "numericLiteral" }, + { text: " ", kind: "space" }, { text: "overload", kind: "text" }, { text: ")", kind: "punctuation" }]; + +verifyVar("h", getFunctionType("number", "string", /*isArrow*/true).concat(overloadDisplay)); +verifyVar("h", getFunctionType("string", "number", /*isArrow*/true).concat(overloadDisplay)); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoDisplayPartsLocalFunction.ts b/tests/cases/fourslash/quickInfoDisplayPartsLocalFunction.ts new file mode 100644 index 00000000000..b9578c7f522 --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsLocalFunction.ts @@ -0,0 +1,92 @@ +/// + +////function /*1*/outerFoo() { +//// function /*2*/foo(param: string, optionalParam?: string, paramWithInitializer = "hello", ...restParam: string[]) { +//// } +//// function /*3*/foowithoverload(a: string): string; +//// function /*4*/foowithoverload(a: number): number; +//// function /*5*/foowithoverload(a: any): any { +//// return a; +//// } +//// function /*6*/foowith3overload(a: string): string; +//// function /*7*/foowith3overload(a: number): number; +//// function /*8*/foowith3overload(a: boolean): boolean; +//// function /*9*/foowith3overload(a: any): any { +//// return a; +//// } +//// /*10*/foo("hello"); +//// /*11*/foowithoverload("hello"); +//// /*12*/foowithoverload(10); +//// /*13*/foowith3overload("hello"); +//// /*14*/foowith3overload(10); +//// /*15*/foowith3overload(true); +////} +/////*16*/outerFoo(); + +var marker = 0; +function verifyOuterFunction() { + marker++; + goTo.marker(marker.toString()); + verify.verifyQuickInfoDisplayParts("function", "", { start: test.markerByName(marker.toString()).position, length: "outerFoo".length }, + [{ text: "(", kind: "punctuation" }, { text: "function", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "outerFoo", kind: "functionName" }, { text: "(", kind: "punctuation" }, + { text: ")", kind: "punctuation" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "void", kind: "keyword" }], + []); +} + +function verifyFunctionWithoutOverload() { + marker++; + goTo.marker(marker.toString()); + verify.verifyQuickInfoDisplayParts("local function", "", { start: test.markerByName(marker.toString()).position, length: "foo".length }, + [{ text: "(", kind: "punctuation" }, { text: "local function", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "foo", kind: "functionName" }, { text: "(", kind: "punctuation" }, + { text: "param", kind: "parameterName" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "string", kind: "keyword" }, + { text: ",", kind: "punctuation" }, { text: " ", kind: "space" }, + { text: "optionalParam", kind: "parameterName" }, { text: "?", kind: "punctuation" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "string", kind: "keyword" }, + { text: ",", kind: "punctuation" }, { text: " ", kind: "space" }, + { text: "paramWithInitializer", kind: "parameterName" }, { text: "?", kind: "punctuation" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "string", kind: "keyword" }, + { text: ",", kind: "punctuation" }, { text: " ", kind: "space" }, + { text: "...", kind: "punctuation" }, { text: "restParam", kind: "parameterName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "string", kind: "keyword" }, { text: "[", kind: "punctuation" }, { text: "]", kind: "punctuation" }, + { text: ")", kind: "punctuation" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "void", kind: "keyword" }], + []); +} + +function verifyFunctionWithOverload(functionName: string, type: string, overloadCount: number) { + marker++; + goTo.marker(marker.toString()); + verify.verifyQuickInfoDisplayParts("local function", "", { start: test.markerByName(marker.toString()).position, length: functionName.length }, + [{ text: "(", kind: "punctuation" }, { text: "local function", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: functionName, kind: "functionName" }, { text: "(", kind: "punctuation" }, + { text: "a", kind: "parameterName" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: type, kind: "keyword" }, + { text: ")", kind: "punctuation" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: type, kind: "keyword" }, + { text: " ", kind: "space" }, { text: "(", kind: "punctuation" }, { text: "+", kind: "operator" }, { text: overloadCount.toString(), kind: "numericLiteral" }, + { text: " ", kind: "space" }, { text: overloadCount === 1 ? "overload" : "overloads", kind: "text" }, { text: ")", kind: "punctuation" }], + []); +} + + +// Declarations +verifyOuterFunction(); + +verifyFunctionWithoutOverload(); + +verifyFunctionWithOverload("foowithoverload", "string", 1); +verifyFunctionWithOverload("foowithoverload", "number", 1); +verifyFunctionWithOverload("foowithoverload", "string", 1); + +verifyFunctionWithOverload("foowith3overload", "string", 2); +verifyFunctionWithOverload("foowith3overload", "number", 2); +verifyFunctionWithOverload("foowith3overload", "boolean", 2); +verifyFunctionWithOverload("foowith3overload", "string", 2); + +// Calls +verifyFunctionWithoutOverload(); + +verifyFunctionWithOverload("foowithoverload", "string", 1); +verifyFunctionWithOverload("foowithoverload", "number", 1); + +verifyFunctionWithOverload("foowith3overload", "string", 2); +verifyFunctionWithOverload("foowith3overload", "number", 2); +verifyFunctionWithOverload("foowith3overload", "boolean", 2); +verifyOuterFunction(); diff --git a/tests/cases/fourslash/quickInfoDisplayPartsModules.ts b/tests/cases/fourslash/quickInfoDisplayPartsModules.ts new file mode 100644 index 00000000000..c86bce474ff --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsModules.ts @@ -0,0 +1,63 @@ +/// + +////module /*1*/m { +//// var /*2*/moduleElemWithoutExport = 10; +//// export var /*3*/moduleElemWithExport = 10; +////} +////var /*4*/a = /*5*/m; +////var /*6*/b: typeof /*7*/m; +////module /*8*/m1./*9*/m2 { +//// var /*10*/moduleElemWithoutExport = 10; +//// export var /*11*/moduleElemWithExport = 10; +////} +////var /*12*/x = /*13*/m1./*14*/m2; +////var /*15*/y: typeof /*16*/m1./*17*/m2; + +var marker = 0; +function goToMarker() { + marker++; + goTo.marker(marker.toString()); +} + +function verifyModule(name: string, optionalParentName?: string) { + goToMarker(); + var moduleNameDisplay = [{ text: name, kind: "moduleName" }]; + if (optionalParentName) { + moduleNameDisplay = [{ text: optionalParentName, kind: "moduleName" }, { text: ".", kind: "punctuation" }].concat(moduleNameDisplay); + } + verify.verifyQuickInfoDisplayParts("module", optionalParentName ? "export" : "", { start: test.markerByName(marker.toString()).position, length: name.length }, + [{ text: "module", kind: "keyword" }, { text: " ", kind: "space" }].concat(moduleNameDisplay), + []); +} + +function verifyVar(name: string, optionalFullName?: ts.SymbolDisplayPart[], typeDisplay: ts.SymbolDisplayPart[]= [{ text: "number", kind: "keyword" }]) { + goToMarker(); + verify.verifyQuickInfoDisplayParts("var", optionalFullName ? "export" : "", { start: test.markerByName(marker.toString()).position, length: name.length }, + [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }].concat(optionalFullName || [{ text: name, kind: "localName" }]).concat( + { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }).concat(typeDisplay), + []); +} + +verifyModule("m"); +verifyVar("moduleElemWithoutExport"); +verifyVar("moduleElemWithExport", [{ text: "m", kind: "moduleName" }, { text: ".", kind: "punctuation" }, { text: "moduleElemWithExport", kind: "localName" }]); + +verifyVar("a", /*optionalFullName*/ undefined, [{ text: "typeof", kind: "keyword" }, { text: " ", kind: "space" }, { text: "m", kind: "moduleName" }]); +verifyModule("m"); +verifyVar("b", /*optionalFullName*/ undefined, [{ text: "typeof", kind: "keyword" }, { text: " ", kind: "space" }, { text: "m", kind: "moduleName" }]); +verifyModule("m"); + +verifyModule("m1"); +verifyModule("m2", "m1"); +verifyVar("moduleElemWithoutExport"); +verifyVar("moduleElemWithExport", [{ text: "m1", kind: "moduleName" }, { text: ".", kind: "punctuation" }, + { text: "m2", kind: "moduleName" }, { text: ".", kind: "punctuation" }, { text: "moduleElemWithExport", kind: "localName" }]); +verifyVar("x", /*optionalFullName*/ undefined, [{ text: "typeof", kind: "keyword" }, { text: " ", kind: "space" }, + { text: "m1", kind: "moduleName" }, { text: ".", kind: "punctuation" }, { text: "m2", kind: "moduleName" }]); +verifyModule("m1"); +verifyModule("m2", "m1"); +verifyVar("y", /*optionalFullName*/ undefined, [{ text: "typeof", kind: "keyword" }, { text: " ", kind: "space" }, + { text: "m1", kind: "moduleName" }, { text: ".", kind: "punctuation" }, { text: "m2", kind: "moduleName" }]); +verifyModule("m1"); +verifyModule("m2", "m1"); diff --git a/tests/cases/fourslash/quickInfoDisplayPartsParameters.ts b/tests/cases/fourslash/quickInfoDisplayPartsParameters.ts new file mode 100644 index 00000000000..a825030c987 --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsParameters.ts @@ -0,0 +1,45 @@ +/// + +////function /*1*/foo(/*2*/param: string, /*3*/optionalParam?: string, /*4*/paramWithInitializer = "hello", .../*5*/restParam: string[]) { +//// /*6*/param = "Hello"; +//// /*7*/optionalParam = "World"; +//// /*8*/paramWithInitializer = "Hello"; +//// /*9*/restParam[0] = "World"; +////} + +goTo.marker("1"); +verify.verifyQuickInfoDisplayParts("function", "", { start: test.markerByName('1').position, length: "foo".length }, + [{ text: "(", kind: "punctuation" }, { text: "function", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "foo", kind: "functionName" }, { text: "(", kind: "punctuation" }, + { text: "param", kind: "parameterName" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "string", kind: "keyword" }, + { text: ",", kind: "punctuation" }, { text: " ", kind: "space" }, + { text: "optionalParam", kind: "parameterName" }, { text: "?", kind: "punctuation" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "string", kind: "keyword" }, + { text: ",", kind: "punctuation" }, { text: " ", kind: "space" }, + { text: "paramWithInitializer", kind: "parameterName" }, { text: "?", kind: "punctuation" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "string", kind: "keyword" }, + { text: ",", kind: "punctuation" }, { text: " ", kind: "space" }, + { text: "...", kind: "punctuation" }, { text: "restParam", kind: "parameterName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "string", kind: "keyword" } , { text: "[", kind: "punctuation" }, { text: "]", kind: "punctuation" }, + { text: ")", kind: "punctuation" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "void", kind: "keyword" }], + []); + +var marker = 1; +function verifyParam(parameterName: string, isRest: boolean) { + marker++; + goTo.marker(marker.toString()); + var displayParts = [{ text: "(", kind: "punctuation" }, { text: "parameter", kind: "text" }, { text: ")", kind: "punctuation" }, { text: " ", kind: "space" }, + { text: parameterName, kind: "parameterName" }, { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "string", kind: "keyword" }]; + if (isRest) { + displayParts.push({ text: "[", kind: "punctuation" }, { text: "]", kind: "punctuation" }); + } + verify.verifyQuickInfoDisplayParts("parameter", "", { start: test.markerByName(marker.toString()).position, length: parameterName.length }, displayParts, []); +} + +verifyParam('param', /*isRest*/false); +verifyParam('optionalParam', /*isRest*/false); +verifyParam('paramWithInitializer', /*isRest*/false); +verifyParam('restParam', /*isRest*/true); + +verifyParam('param', /*isRest*/false); +verifyParam('optionalParam', /*isRest*/false); +verifyParam('paramWithInitializer', /*isRest*/false); +verifyParam('restParam', /*isRest*/true); diff --git a/tests/cases/fourslash/quickInfoDisplayPartsTypeAlias.ts b/tests/cases/fourslash/quickInfoDisplayPartsTypeAlias.ts new file mode 100644 index 00000000000..5441ca35364 --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsTypeAlias.ts @@ -0,0 +1,42 @@ +/// + +////class /*1*/c { +////} +////type /*2*/t1 = /*3*/c; +////var /*4*/cInstance: /*5*/t1 = new /*6*/c(); + +function verifyClassDisplay(markerName: string) { + goTo.marker(markerName); + verify.verifyQuickInfoDisplayParts("class", "", { start: test.markerByName(markerName).position, length: "c".length }, + [{ text: "class", kind: "keyword" }, { text: " ", kind: "space" }, { text: "c", kind: "className" }], + []); +} + +function verifyTypeAliasDisplay(markerName: string) { + goTo.marker(markerName); + verify.verifyQuickInfoDisplayParts("type", "", { start: test.markerByName(markerName).position, length: "t1".length }, + [{ text: "type", kind: "keyword" }, { text: " ", kind: "space" }, { text: "t1", kind: "aliasName" }, + { text: " ", kind: "space" }, { text: "=", kind: "operator" }, { text: " ", kind: "space" }, { text: "c", kind: "className" }], + []); +} + +verifyClassDisplay('1'); +verifyTypeAliasDisplay('2'); +verifyClassDisplay('3'); + +goTo.marker('4'); +verify.verifyQuickInfoDisplayParts("var", "", { start: test.markerByName("4").position, length: "cInstance".length }, + [{ text: "(", kind: "punctuation" }, { text: "var", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "cInstance", kind: "localName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "c", kind: "className" }], + []); + +verifyTypeAliasDisplay('5'); + +goTo.marker('6'); +verify.verifyQuickInfoDisplayParts("constructor", "", { start: test.markerByName("6").position, length: "c".length }, + [{ text: "(", kind: "punctuation" }, { text: "constructor", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "c", kind: "className" }, + { text: "(", kind: "punctuation" }, { text: ")", kind: "punctuation" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "c", kind: "className" }], + []); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoDisplayPartsTypeParameterInClass.ts b/tests/cases/fourslash/quickInfoDisplayPartsTypeParameterInClass.ts new file mode 100644 index 00000000000..dd32c8b236a --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsTypeParameterInClass.ts @@ -0,0 +1,239 @@ +/// + +////class /*1*/c { +//// /*3*/constructor(/*4*/a: /*5*/T) { +//// } +//// /*6*/method(/*8*/a: /*9*/U, /*10*/b: /*11*/T) { +//// return /*12*/a; +//// } +////} +////var /*13*/cInstance = new /*14*/c("Hello"); +////var /*15*/cVal = /*16*/c; +/////*17*/cInstance./*18*/method("hello", "cello"); +////class /*19*/c2> { +//// /*22*/constructor(/*23*/a: /*24*/T) { +//// } +//// /*25*/method>(/*28*/a: /*29*/U, /*30*/b: /*31*/T) { +//// return /*32*/a; +//// } +////} +////var /*33*/cInstance1 = new /*34*/c2(/*35*/cInstance); +////var /*36*/cVal2 = /*37*/c2; +/////*38*/cInstance1./*39*/method(/*40*/cInstance, /*41*/cInstance); + +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 getClassDisplay(name: string, optionalInstanceType?: ts.SymbolDisplayPart[], + optionalExtends?: ts.SymbolDisplayPart[]) { + var classDisplay = [{ text: name, kind: "className" }, { text: "<", kind: "punctuation" }]; + classDisplay = classDisplay.concat(getTypeParameterDisplay(optionalInstanceType, "T", optionalExtends)); + classDisplay.push({ text: ">", kind: "punctuation" }); + return classDisplay; +} + +function verifyClassDisplay(name: string, optionalExtends?: ts.SymbolDisplayPart[]) { + goToMarker(); + + verify.verifyQuickInfoDisplayParts("class", "", { start: test.markerByName(markerName).position, length: name.length }, + [{ text: "class", kind: "keyword" }, { text: " ", kind: "space" }].concat( + getClassDisplay(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 verifyConstructor(name: string, optionalInstanceType?: ts.SymbolDisplayPart[], + optionalExtends?: ts.SymbolDisplayPart[]) { + goToMarker(); + var constructorDisplay = [{ text: "(", kind: "punctuation" }, { text: "constructor", kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }]; + constructorDisplay = constructorDisplay.concat(getClassDisplay(name, optionalInstanceType, optionalExtends)); + + constructorDisplay.push({ text: "(", kind: "punctuation" }, { text: "a", kind: "parameterName" }, + { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }); + + constructorDisplay = constructorDisplay.concat( + getTypeParameterDisplay(optionalInstanceType, "T")); + + constructorDisplay.push({ text: ")", kind: "punctuation" }, + { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }); + + constructorDisplay = constructorDisplay.concat(getClassDisplay(name, optionalInstanceType)); + + verify.verifyQuickInfoDisplayParts("constructor", "", { start: test.markerByName(markerName).position, length: optionalInstanceType ? name.length : "constructor".length }, + constructorDisplay, []); +} + +function verifyParameter(name: string, type: 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: type, 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 getMethodDisplay(name: string, className: string, + optionalInstanceType?: ts.SymbolDisplayPart[], optionalExtends?: ts.SymbolDisplayPart[]) { + var functionDisplay = getClassDisplay(className, optionalInstanceType, optionalExtends); + + functionDisplay.push({ text: ".", kind: "punctuation" }, { text: name, kind: "methodName" }, + { 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" }, + { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }); + + functionDisplay = functionDisplay.concat( + getTypeParameterDisplay(optionalInstanceType, "U")); + + return functionDisplay; +} + +function verifyMethodDisplay(name: string, className: 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, className, optionalInstanceType, optionalExtends)); + + verify.verifyQuickInfoDisplayParts("method", "", + { start: test.markerByName(markerName).position, length: name.length }, + functionDisplay, []); +} + +function verifyClassInstance(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), + []); +} + +function verifyVarTypeOf(name: string, typeOfSymbol: 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" }, { text: "typeof", kind: "keyword" }, + { text: " ", kind: "space" }].concat(typeOfSymbol), + []); +} + +var stringTypeDisplay = [{ text: "string", kind: "keyword" }]; +var extendsTypeDisplay = getClassDisplay("c", stringTypeDisplay); + +// Declaration +verifyClassDisplay("c"); +verifyTypeParameter("T", getClassDisplay("c")); + +// Constructor declaration +verifyConstructor("c"); +verifyParameter("a", "T"); +verifyTypeParameter("T", getClassDisplay("c")); + +// Method declaration +verifyMethodDisplay("method", "c"); +verifyTypeParameter("U", getMethodDisplay("method", "c")); +verifyParameter("a", "U"); +verifyTypeParameter("U", getMethodDisplay("method", "c")); +verifyParameter("b", "T"); +verifyTypeParameter("T", getClassDisplay("c")); +verifyParameter("a", "U"); + +// Instance creation +verifyClassInstance("cInstance", getClassDisplay("c", stringTypeDisplay)); +verifyConstructor("c", stringTypeDisplay); + +// typeof assignment +verifyVarTypeOf("cVal", { text: "c", kind: "className" }); +verifyClassDisplay("c"); + +// Method call +verifyClassInstance("cInstance", getClassDisplay("c", stringTypeDisplay)); +verifyMethodDisplay("method", "c", stringTypeDisplay); + +// With constraint +// Declaration +verifyClassDisplay("c2", getClassDisplay("c", stringTypeDisplay)); +verifyTypeParameter("T", getClassDisplay("c2", /*instanceType*/undefined, extendsTypeDisplay)); +verifyClassDisplay("c"); + +// Constructor declaration +verifyConstructor("c2", /*instanceType*/undefined, extendsTypeDisplay); +verifyParameter("a", "T", extendsTypeDisplay); +verifyTypeParameter("T", getClassDisplay("c2", /*instanceType*/undefined, extendsTypeDisplay)); + +// Method declaration +verifyMethodDisplay("method", "c2", /*instance*/undefined, extendsTypeDisplay); +verifyTypeParameter("U", getMethodDisplay("method", "c2", /*instance*/undefined, extendsTypeDisplay)); +verifyClassDisplay("c"); +verifyParameter("a", "U", extendsTypeDisplay); +verifyTypeParameter("U", getMethodDisplay("method", "c2", /*instance*/undefined, extendsTypeDisplay)); +verifyParameter("b", "T", extendsTypeDisplay); +verifyTypeParameter("T", getClassDisplay("c2", /*instanceType*/undefined, extendsTypeDisplay)); +verifyParameter("a", "U", extendsTypeDisplay); + +// Instance creation +verifyClassInstance("cInstance1", getClassDisplay("c2", extendsTypeDisplay)); +verifyConstructor("c2", extendsTypeDisplay); +verifyClassInstance("cInstance", getClassDisplay("c", stringTypeDisplay)); + +// typeof assignment +verifyVarTypeOf("cVal2", { text: "c2", kind: "className" }); +verifyClassDisplay("c2", getClassDisplay("c", stringTypeDisplay)); + +// Method call +verifyClassInstance("cInstance1", getClassDisplay("c2", extendsTypeDisplay)); +verifyMethodDisplay("method", "c2", extendsTypeDisplay); +verifyClassInstance("cInstance", getClassDisplay("c", stringTypeDisplay)); +verifyClassInstance("cInstance", getClassDisplay("c", stringTypeDisplay)); \ No newline at end of file diff --git a/tests/cases/fourslash/quickInfoDisplayPartsTypeParameterInFunction.ts b/tests/cases/fourslash/quickInfoDisplayPartsTypeParameterInFunction.ts new file mode 100644 index 00000000000..0daabd43ad7 --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsTypeParameterInFunction.ts @@ -0,0 +1,118 @@ +/// + + +////function /*1*/foo(/*3*/a: /*4*/U) { +//// return /*5*/a; +////} +/////*6*/foo("Hello"); +////function /*7*/foo2(/*9*/a: /*10*/U) { +//// return /*11*/a; +////} +/////*12*/foo2("hello"); + +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 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 getFunctionDisplay(name: string, optionalInstanceType?: ts.SymbolDisplayPart[], + optionalExtends?: ts.SymbolDisplayPart[]) { + var functionDisplay = [{ text: name, kind: "functionName" }, { 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: "punctuation" }, + { text: " ", kind: "space" }); + + functionDisplay = functionDisplay.concat( + getTypeParameterDisplay(optionalInstanceType, "U")); + + return functionDisplay; +} + +function verifyFunctionDisplay(name: string, optionalInstanceType?: ts.SymbolDisplayPart[], + optionalExtends?: ts.SymbolDisplayPart[]) { + goToMarker(); + var functionDisplay = [{ text: "(", kind: "punctuation" }, { text: "function", kind: "text" }, + { text: ")", kind: "punctuation" }, { text: " ", kind: "space" }].concat( + getFunctionDisplay(name, optionalInstanceType, optionalExtends)); + + verify.verifyQuickInfoDisplayParts("function", "", + { start: test.markerByName(markerName).position, length: name.length }, + functionDisplay, []); +} + +var stringTypeDisplay = [{ text: "string", kind: "keyword" }]; + +// Declaration +verifyFunctionDisplay("foo"); +verifyTypeParameter("U", getFunctionDisplay("foo")); +verifyParameter("a", "U"); +verifyTypeParameter("U", getFunctionDisplay("foo")); +verifyParameter("a", "U"); + +// Call +verifyFunctionDisplay("foo", stringTypeDisplay); + +// With constraint +// Declaration +verifyFunctionDisplay("foo2", /*instance*/ undefined, stringTypeDisplay); +verifyTypeParameter("U", getFunctionDisplay("foo2", /*instance*/ undefined, stringTypeDisplay)); +verifyParameter("a", "U", stringTypeDisplay); +verifyTypeParameter("U", getFunctionDisplay("foo2", /*instance*/ undefined, stringTypeDisplay)); +verifyParameter("a", "U", stringTypeDisplay); + +// Call +verifyFunctionDisplay("foo2", stringTypeDisplay); \ No newline at end of file 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)); diff --git a/tests/cases/fourslash/quickInfoDisplayPartsVar.ts b/tests/cases/fourslash/quickInfoDisplayPartsVar.ts new file mode 100644 index 00000000000..56ccceb3ab3 --- /dev/null +++ b/tests/cases/fourslash/quickInfoDisplayPartsVar.ts @@ -0,0 +1,76 @@ +/// + +////var /*1*/a = 10; +////function foo() { +//// var /*2*/b = /*3*/a; +////} +////module m { +//// var /*4*/c = 10; +//// export var /*5*/d = 10; +////} +////var /*6*/f: () => number; +////var /*7*/g = /*8*/f; +/////*9*/f(); +////var /*10*/h: { (a: string): number; (a: number): string; }; +////var /*11*/i = /*12*/h; +/////*13*/h(10); +/////*14*/h("hello"); + +var marker = 0; +function verifyVar(name: string, isLocal: boolean, typeDisplay: ts.SymbolDisplayPart[], optionalNameDisplay?: ts.SymbolDisplayPart[], optionalKindModifiers?: string) { + marker++; + goTo.marker(marker.toString()); + var kind = isLocal ? "local var" : "var"; + verify.verifyQuickInfoDisplayParts(kind, optionalKindModifiers || "", { start: test.markerByName(marker.toString()).position, length: name.length }, + [{ text: "(", kind: "punctuation" }, { text: kind, kind: "text" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }].concat(optionalNameDisplay || [{ text: name, kind: "localName" }]).concat( + { text: ":", kind: "punctuation" }, { text: " ", kind: "space" }).concat(typeDisplay), + []); +} + +var numberTypeDisplay: ts.SymbolDisplayPart[] = [{ text: "number", kind: "keyword" }]; + +verifyVar("a", /*isLocal*/false, numberTypeDisplay); +verifyVar("b", /*isLocal*/true, numberTypeDisplay); +verifyVar("a", /*isLocal*/false, numberTypeDisplay); +verifyVar("c", /*isLocal*/false, numberTypeDisplay); +verifyVar("d", /*isLocal*/false, numberTypeDisplay, [{ text: "m", kind: "moduleName" }, { text: ".", kind: "punctuation" }, { text: "d", kind: "localName" }], "export"); + +var functionTypeReturningNumber: ts.SymbolDisplayPart[] = [{ text: "(", kind: "punctuation" }, { text: ")", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: "=>", kind: "punctuation" }, { text: " ", kind: "space" }, { text: "number", kind: "keyword" }]; +verifyVar("f", /*isLocal*/ false, functionTypeReturningNumber); +verifyVar("g", /*isLocal*/ false, functionTypeReturningNumber); +verifyVar("f", /*isLocal*/ false, functionTypeReturningNumber); +verifyVar("f", /*isLocal*/ false, functionTypeReturningNumber); + + +function getFunctionType(parametertype: string, returnType: string, isArrow?: boolean): ts.SymbolDisplayPart[] { + var functionTypeDisplay = [{ text: "(", kind: "punctuation" }, { text: "a", kind: "parameterName" }, { text: ":", kind: "punctuation" }, + { text: " ", kind: "space" }, { text: parametertype, kind: "keyword" }, { text: ")", kind: "punctuation" }]; + + if (isArrow) { + functionTypeDisplay = functionTypeDisplay.concat({ text: " ", kind: "space" }, { text: "=>", kind: "punctuation" }); + } + else { + functionTypeDisplay = functionTypeDisplay.concat({ text: ":", kind: "punctuation" }); + } + + return functionTypeDisplay.concat({ text: " ", kind: "space" }, { text: returnType, kind: "keyword" }); +} + +var typeLiteralWithOverloadCall: ts.SymbolDisplayPart[] = [{ text: "{", kind: "punctuation" }, { text: "\n", kind: "lineBreak" }, + { text: " ", kind: "space" }].concat(getFunctionType("string", "number")).concat( + { text: ";", kind: "punctuation" }, { text: "\n", kind: "lineBreak" }, + { text: " ", kind: "space" }).concat(getFunctionType("number", "string")).concat( + { text: ";", kind: "punctuation" }, { text: "\n", kind: "lineBreak" }, { text: "}", kind: "punctuation" }); + +verifyVar("h", /*isLocal*/ false, typeLiteralWithOverloadCall); +verifyVar("i", /*isLocal*/ false, typeLiteralWithOverloadCall); +verifyVar("h", /*isLocal*/ false, typeLiteralWithOverloadCall); + +var overloadDisplay: ts.SymbolDisplayPart[] = [{ text: " ", kind: "space" }, { text: "(", kind: "punctuation" }, + { text: "+", kind: "operator" }, { text: "1", kind: "numericLiteral" }, + { text: " ", kind: "space" }, { text: "overload", kind: "text" }, { text: ")", kind: "punctuation" }]; + +verifyVar("h", /*isLocal*/ false, getFunctionType("number", "string", /*isArrow*/true).concat(overloadDisplay)); +verifyVar("h", /*isLocal*/ false, getFunctionType("string", "number", /*isArrow*/true).concat(overloadDisplay)); \ No newline at end of file