Merge pull request #915 from Microsoft/sigHelp

Basic generic signature help
This commit is contained in:
Jason Freeman 2014-10-20 12:46:16 -07:00
commit a1e69b0dc2
9 changed files with 248 additions and 187 deletions

View File

@ -993,16 +993,34 @@ module ts {
// This is for caching the result of getSymbolDisplayBuilder. Do not access directly.
var _displayBuilder: SymbolDisplayBuilder;
function getSymbolDisplayBuilder(): SymbolDisplayBuilder {
// Enclosing declaration is optional when we don't want to get qualified name in the enclosing declaration scope
// Meaning needs to be specified if the enclosing declaration is given
/**
* Writes only the name of the symbol out to the writer. Uses the original source text
* for the name of the symbol if it is available to match how the user inputted the name.
*/
function appendSymbolNameOnly(symbol: Symbol, writer: SymbolWriter): void {
if (symbol.declarations && symbol.declarations.length > 0) {
var declaration = symbol.declarations[0];
if (declaration.name) {
writer.writeSymbol(identifierToString(declaration.name), symbol);
return;
}
}
writer.writeSymbol(symbol.name, symbol);
}
/**
* Enclosing declaration is optional when we don't want to get qualified name in the enclosing declaration scope
* Meaning needs to be specified if the enclosing declaration is given
*/
function buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void {
var parentSymbol: Symbol;
function writeSymbolName(symbol: Symbol): void {
function appendParentTypeArgumentsAndSymbolName(symbol: Symbol): void {
if (parentSymbol) {
// Write type arguments of instantiated class/interface here
if (flags & SymbolFormatFlags.WriteTypeParametersOrArguments) {
if (symbol.flags & SymbolFlags.Instantiated) {
buildTypeArgumentListDisplay(getTypeParametersOfClassOrInterface(parentSymbol),
buildDisplayForTypeArgumentsAndDelimiters(getTypeParametersOfClassOrInterface(parentSymbol),
(<TransientSymbol>symbol).mapper, writer, enclosingDeclaration);
}
else {
@ -1012,15 +1030,7 @@ module ts {
writePunctuation(writer, SyntaxKind.DotToken);
}
parentSymbol = symbol;
if (symbol.declarations && symbol.declarations.length > 0) {
var declaration = symbol.declarations[0];
if (declaration.name) {
writer.writeSymbol(identifierToString(declaration.name), symbol);
return;
}
}
writer.writeSymbol(symbol.name, symbol);
appendSymbolNameOnly(symbol, writer);
}
// Let the writer know we just wrote out a symbol. The declaration emitter writer uses
@ -1046,7 +1056,7 @@ module ts {
if (accessibleSymbolChain) {
for (var i = 0, n = accessibleSymbolChain.length; i < n; i++) {
writeSymbolName(accessibleSymbolChain[i]);
appendParentTypeArgumentsAndSymbolName(accessibleSymbolChain[i]);
}
}
else {
@ -1060,7 +1070,7 @@ module ts {
return;
}
writeSymbolName(symbol);
appendParentTypeArgumentsAndSymbolName(symbol);
}
}
}
@ -1074,7 +1084,7 @@ module ts {
return;
}
return writeSymbolName(symbol);
return appendParentTypeArgumentsAndSymbolName(symbol);
}
function buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, globalFlags?: TypeFormatFlags, typeStack?: Type[]) {
@ -1315,8 +1325,15 @@ module ts {
}
}
function buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags) {
var targetSymbol = getTargetSymbol(symbol);
if (targetSymbol.flags & SymbolFlags.Class || targetSymbol.flags & SymbolFlags.Interface) {
buildDisplayForTypeParametersAndDelimiters(getTypeParametersOfClassOrInterface(symbol), writer, enclosingDeclaraiton, flags);
}
}
function buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
buildSymbolDisplay(tp.symbol, writer);
appendSymbolNameOnly(tp.symbol, writer);
var constraint = getConstraintOfTypeParameter(tp);
if (constraint) {
writeSpace(writer);
@ -1326,7 +1343,21 @@ module ts {
}
}
function buildTypeParameterListDisplay(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
if (getDeclarationFlagsFromSymbol(p) & NodeFlags.Rest) {
writePunctuation(writer, SyntaxKind.DotDotDotToken);
}
appendSymbolNameOnly(p, writer);
if (p.valueDeclaration.flags & NodeFlags.QuestionMark || (<VariableDeclaration>p.valueDeclaration).initializer) {
writePunctuation(writer, SyntaxKind.QuestionToken);
}
writePunctuation(writer, SyntaxKind.ColonToken);
writeSpace(writer);
buildTypeDisplay(getTypeOfSymbol(p), writer, enclosingDeclaration, flags, typeStack);
}
function buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
if (typeParameters && typeParameters.length) {
writePunctuation(writer, SyntaxKind.LessThanToken);
for (var i = 0; i < typeParameters.length; i++) {
@ -1340,7 +1371,7 @@ module ts {
}
}
function buildTypeArgumentListDisplay(typeParameters: TypeParameter[], mapper: TypeMapper, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
function buildDisplayForTypeArgumentsAndDelimiters(typeParameters: TypeParameter[], mapper: TypeMapper, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
if (typeParameters && typeParameters.length) {
writePunctuation(writer, SyntaxKind.LessThanToken);
for (var i = 0; i < typeParameters.length; i++) {
@ -1354,42 +1385,19 @@ module ts {
}
}
function buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags) {
var targetSymbol = getTargetSymbol(symbol);
if (targetSymbol.flags & SymbolFlags.Class || targetSymbol.flags & SymbolFlags.Interface) {
buildTypeParameterListDisplay(getTypeParametersOfClassOrInterface(symbol), writer, enclosingDeclaraiton, flags);
}
}
function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
if (signature.target && (flags & TypeFormatFlags.WriteTypeArgumentsOfSignature)) {
// Instantiated signature, write type arguments instead
buildTypeArgumentListDisplay(signature.target.typeParameters, signature.mapper, writer, enclosingDeclaration);
}
else {
buildTypeParameterListDisplay(signature.typeParameters, writer, enclosingDeclaration, flags, typeStack);
}
function buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
writePunctuation(writer, SyntaxKind.OpenParenToken);
for (var i = 0; i < signature.parameters.length; i++) {
for (var i = 0; i < parameters.length; i++) {
if (i > 0) {
writePunctuation(writer, SyntaxKind.CommaToken);
writeSpace(writer);
}
var p = signature.parameters[i];
if (getDeclarationFlagsFromSymbol(p) & NodeFlags.Rest) {
writePunctuation(writer, SyntaxKind.DotDotDotToken);
}
buildSymbolDisplay(p, writer);
if (p.valueDeclaration.flags & NodeFlags.QuestionMark || (<VariableDeclaration>p.valueDeclaration).initializer) {
writePunctuation(writer, SyntaxKind.QuestionToken);
}
writePunctuation(writer, SyntaxKind.ColonToken);
writeSpace(writer);
buildTypeDisplay(getTypeOfSymbol(p), writer, enclosingDeclaration, flags, typeStack);
buildParameterDisplay(parameters[i], writer, enclosingDeclaration, flags, typeStack);
}
writePunctuation(writer, SyntaxKind.CloseParenToken);
}
function buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
if (flags & TypeFormatFlags.WriteArrowStyleSignature) {
writeSpace(writer);
writePunctuation(writer, SyntaxKind.EqualsGreaterThanToken);
@ -1398,9 +1406,22 @@ module ts {
writePunctuation(writer, SyntaxKind.ColonToken);
}
writeSpace(writer);
buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags, typeStack);
}
function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
if (signature.target && (flags & TypeFormatFlags.WriteTypeArgumentsOfSignature)) {
// Instantiated signature, write type arguments instead
// This is achieved by passing in the mapper separately
buildDisplayForTypeArgumentsAndDelimiters(signature.target.typeParameters, signature.mapper, writer, enclosingDeclaration);
}
else {
buildDisplayForTypeParametersAndDelimiters(signature.typeParameters, writer, enclosingDeclaration, flags, typeStack);
}
buildDisplayForParametersAndDelimiters(signature.parameters, writer, enclosingDeclaration, flags, typeStack);
buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, typeStack);
}
return _displayBuilder || (_displayBuilder = {
symbolToString: symbolToString,
@ -1408,10 +1429,13 @@ module ts {
buildSymbolDisplay: buildSymbolDisplay,
buildTypeDisplay: buildTypeDisplay,
buildTypeParameterDisplay: buildTypeParameterDisplay,
buildTypeParameterListDisplay: buildTypeParameterListDisplay,
buildTypeArgumentListDisplay: buildTypeArgumentListDisplay,
buildParameterDisplay: buildParameterDisplay,
buildDisplayForParametersAndDelimiters: buildDisplayForParametersAndDelimiters,
buildDisplayForTypeParametersAndDelimiters: buildDisplayForTypeParametersAndDelimiters,
buildDisplayForTypeArgumentsAndDelimiters: buildDisplayForTypeArgumentsAndDelimiters,
buildTypeParameterDisplayFromSymbol: buildTypeParameterDisplayFromSymbol,
buildSignatureDisplay: buildSignatureDisplay
buildSignatureDisplay: buildSignatureDisplay,
buildReturnTypeDisplay: buildReturnTypeDisplay
});
}

View File

@ -1080,7 +1080,7 @@ module ts {
return isParameter();
case ParsingContext.TypeArguments:
case ParsingContext.TupleElementTypes:
return isType();
return token === SyntaxKind.CommaToken || isType();
}
Debug.fail("Non-exhaustive case in 'isListElement'.");
@ -2393,13 +2393,29 @@ module ts {
function parseTypeArguments(): NodeArray<TypeNode> {
var typeArgumentListStart = scanner.getTokenPos();
var errorCountBeforeTypeParameterList = file.syntacticErrors.length;
var result = parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
// We pass parseSingleTypeArgument instead of parseType as the element parser
// because parseSingleTypeArgument knows how to parse a missing type argument.
// This is useful for signature help. parseType has the disadvantage that when
// it sees a missing type, it changes the LookAheadMode to Error, and the result
// is a broken binary expression, which breaks signature help.
var result = parseBracketedList(ParsingContext.TypeArguments, parseSingleTypeArgument, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
if (!result.length && file.syntacticErrors.length === errorCountBeforeTypeParameterList) {
grammarErrorAtPos(typeArgumentListStart, scanner.getStartPos() - typeArgumentListStart, Diagnostics.Type_argument_list_cannot_be_empty);
}
return result;
}
function parseSingleTypeArgument(): TypeNode {
if (token === SyntaxKind.CommaToken) {
var errorStart = scanner.getTokenPos();
var errorLength = scanner.getTextPos() - errorStart;
grammarErrorAtPos(errorStart, errorLength, Diagnostics.Type_expected);
return createNode(SyntaxKind.Missing);
}
return parseType();
}
function parsePrimaryExpression(): Expression {
switch (token) {
case SyntaxKind.ThisKeyword:

View File

@ -677,8 +677,12 @@ module ts {
buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void;
buildSignatureDisplay(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaraiton?: Node, flags?: TypeFormatFlags): void;
buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
}
export interface SymbolWriter {

View File

@ -1460,7 +1460,7 @@ module ts {
}
}
function mapToDisplayParts(writeDisplayParts: (writer: DisplayPartsSymbolWriter) => void): SymbolDisplayPart[] {
export function mapToDisplayParts(writeDisplayParts: (writer: DisplayPartsSymbolWriter) => void): SymbolDisplayPart[] {
writeDisplayParts(displayPartWriter);
var result = displayPartWriter.displayParts();
displayPartWriter.clear();

View File

@ -258,6 +258,13 @@ module ts.SignatureHelp {
return undefined;
}
function getChildListThatStartsWithOpenerToken(parent: Node, openerToken: Node, sourceFile: SourceFile): Node {
var children = parent.getChildren(sourceFile);
var indexOfOpenerToken = children.indexOf(openerToken);
Debug.assert(indexOfOpenerToken >= 0 && children.length > indexOfOpenerToken + 1);
return children[indexOfOpenerToken + 1];
}
/**
* The selectedItemIndex could be negative for several reasons.
* 1. There are too many arguments for all of the overloads
@ -287,74 +294,51 @@ module ts.SignatureHelp {
function createSignatureHelpItems(candidates: Signature[], bestSignature: Signature, argumentInfoOrTypeArgumentInfo: ListItemInfo): SignatureHelpItems {
var argumentListOrTypeArgumentList = argumentInfoOrTypeArgumentInfo.list;
var parent = <CallExpression>argumentListOrTypeArgumentList.parent;
var isTypeParameterHelp = parent.typeArguments && parent.typeArguments.pos === argumentListOrTypeArgumentList.pos;
Debug.assert(isTypeParameterHelp || parent.arguments.pos === argumentListOrTypeArgumentList.pos);
var callTargetNode = (<CallExpression>argumentListOrTypeArgumentList.parent).func;
var callTargetSymbol = typeInfoResolver.getSymbolInfo(callTargetNode);
var callTargetDisplayParts = callTargetSymbol && symbolToDisplayParts(typeInfoResolver, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined);
var items: SignatureHelpItem[] = map(candidates, candidateSignature => {
var parameters = candidateSignature.parameters;
var parameterHelpItems: SignatureHelpParameter[] = parameters.length === 0 ? emptyArray : map(parameters, p => {
var displayParts: SymbolDisplayPart[] = [];
var signatureHelpParameters: SignatureHelpParameter[];
var prefixParts: SymbolDisplayPart[] = [];
var suffixParts: SymbolDisplayPart[] = [];
if (candidateSignature.hasRestParameter && parameters[parameters.length - 1] === p) {
displayParts.push(punctuationPart(SyntaxKind.DotDotDotToken));
}
displayParts.push(symbolPart(p.name, p));
var isOptional = !!(p.valueDeclaration.flags & NodeFlags.QuestionMark);
if (isOptional) {
displayParts.push(punctuationPart(SyntaxKind.QuestionToken));
}
displayParts.push(punctuationPart(SyntaxKind.ColonToken));
displayParts.push(spacePart());
var typeParts = typeToDisplayParts(typeInfoResolver, typeInfoResolver.getTypeOfSymbol(p), argumentListOrTypeArgumentList);
displayParts.push.apply(displayParts, typeParts);
return {
name: p.name,
documentation: p.getDocumentationComment(),
displayParts: displayParts,
isOptional: isOptional
};
});
var callTargetNode = (<CallExpression>argumentListOrTypeArgumentList.parent).func;
var callTargetSymbol = typeInfoResolver.getSymbolInfo(callTargetNode);
var prefixParts = callTargetSymbol ? symbolToDisplayParts(typeInfoResolver, callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined) : [];
var separatorParts = [punctuationPart(SyntaxKind.CommaToken), spacePart()];
// TODO(jfreeman): Constraints?
if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) {
prefixParts.push(punctuationPart(SyntaxKind.LessThanToken));
for (var i = 0, n = candidateSignature.typeParameters.length; i < n; i++) {
if (i) {
prefixParts.push.apply(prefixParts, separatorParts);
}
var tp = candidateSignature.typeParameters[i].symbol;
prefixParts.push(symbolPart(tp.name, tp));
}
prefixParts.push(punctuationPart(SyntaxKind.GreaterThanToken));
if (callTargetDisplayParts) {
prefixParts.push.apply(prefixParts, callTargetDisplayParts);
}
prefixParts.push(punctuationPart(SyntaxKind.OpenParenToken));
if (isTypeParameterHelp) {
prefixParts.push(punctuationPart(SyntaxKind.LessThanToken));
var typeParameters = candidateSignature.typeParameters;
signatureHelpParameters = typeParameters && typeParameters.length > 0 ? map(typeParameters, createSignatureHelpParameterForTypeParameter) : emptyArray;
suffixParts.push(punctuationPart(SyntaxKind.GreaterThanToken));
var parameterParts = mapToDisplayParts(writer =>
typeInfoResolver.getSymbolDisplayBuilder().buildDisplayForParametersAndDelimiters(candidateSignature.parameters, writer, argumentListOrTypeArgumentList));
suffixParts.push.apply(suffixParts, parameterParts);
}
else {
var typeParameterParts = mapToDisplayParts(writer =>
typeInfoResolver.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, argumentListOrTypeArgumentList));
prefixParts.push.apply(prefixParts, typeParameterParts);
prefixParts.push(punctuationPart(SyntaxKind.OpenParenToken));
var parameters = candidateSignature.parameters;
signatureHelpParameters = parameters.length > 0 ? map(parameters, createSignatureHelpParameterForParameter) : emptyArray;
suffixParts.push(punctuationPart(SyntaxKind.CloseParenToken));
}
var suffixParts = [punctuationPart(SyntaxKind.CloseParenToken)];
suffixParts.push(punctuationPart(SyntaxKind.ColonToken));
suffixParts.push(spacePart());
var typeParts = typeToDisplayParts(typeInfoResolver, candidateSignature.getReturnType(), argumentListOrTypeArgumentList);
suffixParts.push.apply(suffixParts, typeParts);
var returnTypeParts = mapToDisplayParts(writer =>
typeInfoResolver.getSymbolDisplayBuilder().buildReturnTypeDisplay(candidateSignature, writer, argumentListOrTypeArgumentList));
suffixParts.push.apply(suffixParts, returnTypeParts);
return {
isVariadic: candidateSignature.hasRestParameter,
prefixDisplayParts: prefixParts,
suffixDisplayParts: suffixParts,
separatorDisplayParts: separatorParts,
parameters: parameterHelpItems,
separatorDisplayParts: [punctuationPart(SyntaxKind.CommaToken), spacePart()],
parameters: signatureHelpParameters,
documentation: candidateSignature.getDocumentationComment()
};
});
@ -400,12 +384,32 @@ module ts.SignatureHelp {
argumentIndex: argumentIndex,
argumentCount: argumentCount
};
function createSignatureHelpParameterForParameter(parameter: Symbol): SignatureHelpParameter {
var displayParts = mapToDisplayParts(writer =>
typeInfoResolver.getSymbolDisplayBuilder().buildParameterDisplay(parameter, writer, argumentListOrTypeArgumentList));
var isOptional = !!(parameter.valueDeclaration.flags & NodeFlags.QuestionMark);
return {
name: parameter.name,
documentation: parameter.getDocumentationComment(),
displayParts: displayParts,
isOptional: isOptional
};
}
function createSignatureHelpParameterForTypeParameter(typeParameter: TypeParameter): SignatureHelpParameter {
var displayParts = mapToDisplayParts(writer =>
typeInfoResolver.getSymbolDisplayBuilder().buildTypeParameterDisplay(typeParameter, writer, argumentListOrTypeArgumentList));
return {
name: typeParameter.symbol.name,
documentation: emptyArray,
displayParts: displayParts,
isOptional: false
};
}
}
}
function getChildListThatStartsWithOpenerToken(parent: Node, openerToken: Node, sourceFile: SourceFile): Node {
var children = parent.getChildren(sourceFile);
var indexOfOpenerToken = children.indexOf(openerToken);
return children[indexOfOpenerToken + 1];
}
}

View File

@ -6,26 +6,12 @@
//// return null;
////}
////
////class testClass<T extends IFoo, U, M extends IFoo> {
//// constructor(a:T, b:U, c:M){ }
////}
////// Function calls
////testFunction</*1*/
////testFunction<any, /*2*/
////testFunction<any, any, any>(/*3*/
////testFunction<any, any,/*4*/ any>(null, null, null);
////testFunction<, ,/*5*/>(null, null, null);
////// Constructor calls
////new testClass</*construcor1*/
////new testClass<IFoo, /*construcor2*/
////new testClass</*construcor3*/>(null, null, null)
////new testClass<,,/*construcor4*/>(null, null, null)
////new testClass<IFoo,/*construcor5*/IFoo,IFoo>(null, null, null)
////// Generic types
////testClass</*type1*/
////var x : testClass</*type2*/
////class Bar<T> extends testClass</*type3*/
////var x : testClass<,, /*type4*/any>;
// goTo.marker("1");
// verify.currentSignatureParamterCountIs(3);
@ -38,56 +24,14 @@
// verify.currentParameterHelpArgumentNameIs("U");
// verify.currentParameterSpanIs("U");
goTo.marker("3");
verify.currentParameterHelpArgumentNameIs("a");
verify.currentParameterSpanIs("a: T");
goTo.marker("3");
verify.currentParameterHelpArgumentNameIs("a");
verify.currentParameterSpanIs("a: T");
// goTo.marker("4");
// verify.currentParameterHelpArgumentNameIs("M");
// verify.currentParameterSpanIs("M extends IFoo");
goTo.marker("4");
verify.currentParameterHelpArgumentNameIs("M");
verify.currentParameterSpanIs("M extends IFoo");
// goTo.marker("5");
// verify.currentParameterHelpArgumentNameIs("M");
// verify.currentParameterSpanIs("M extends IFoo");
// goTo.marker("construcor1");
// verify.currentSignatureHelpIs("testClass<T extends IFoo, U, M extends IFoo>(a: T, b: U, c: M): testClass<T, U, M>");
// verify.currentParameterHelpArgumentNameIs("T");
// verify.currentParameterSpanIs("T extends IFoo");
// goTo.marker("construcor2");
// verify.currentParameterHelpArgumentNameIs("U");
// verify.currentParameterSpanIs("U");
//goTo.marker("construcor3");
//verify.currentParameterHelpArgumentNameIs("T");
//verify.currentParameterSpanIs("T extends IFoo");
// goTo.marker("construcor4");
// verify.currentParameterHelpArgumentNameIs("M");
// verify.currentParameterSpanIs("M extends IFoo");
// goTo.marker("construcor5");
// verify.currentParameterHelpArgumentNameIs("U");
// verify.currentParameterSpanIs("U");
// goTo.marker("type1");
// verify.signatureHelpCountIs(1);
// verify.currentSignatureHelpIs("testClass<T extends IFoo, U, M extends IFoo>");
// verify.currentParameterHelpArgumentNameIs("T");
// verify.currentParameterSpanIs("T extends IFoo");
// goTo.marker("type2");
// verify.signatureHelpCountIs(1);
// verify.currentParameterHelpArgumentNameIs("T");
// verify.currentParameterSpanIs("T extends IFoo");
// goTo.marker("type3");
// verify.signatureHelpCountIs(1);
// verify.currentParameterHelpArgumentNameIs("T");
// verify.currentParameterSpanIs("T extends IFoo");
// goTo.marker("type4");
// verify.signatureHelpCountIs(1);
// verify.currentParameterHelpArgumentNameIs("M");
// verify.currentParameterSpanIs("M extends IFoo");
goTo.marker("5");
verify.currentParameterHelpArgumentNameIs("M");
verify.currentParameterSpanIs("M extends IFoo");

View File

@ -0,0 +1,35 @@
/// <reference path="fourslash.ts"/>
////interface IFoo { }
////
////class testClass<T extends IFoo, U, M extends IFoo> {
//// constructor(a:T, b:U, c:M){ }
////}
////
////// Constructor calls
////new testClass</*construcor1*/
////new testClass<IFoo, /*construcor2*/
////new testClass</*construcor3*/>(null, null, null)
////new testClass<,,/*construcor4*/>(null, null, null)
////new testClass<IFoo,/*construcor5*/IFoo,IFoo>(null, null, null)
// goTo.marker("construcor1");
// verify.currentSignatureHelpIs("testClass<T extends IFoo, U, M extends IFoo>(a: T, b: U, c: M): testClass<T, U, M>");
// verify.currentParameterHelpArgumentNameIs("T");
// verify.currentParameterSpanIs("T extends IFoo");
// goTo.marker("construcor2");
// verify.currentParameterHelpArgumentNameIs("U");
// verify.currentParameterSpanIs("U");
goTo.marker("construcor3");
verify.currentParameterHelpArgumentNameIs("T");
verify.currentParameterSpanIs("T extends IFoo");
goTo.marker("construcor4");
verify.currentParameterHelpArgumentNameIs("M");
verify.currentParameterSpanIs("M extends IFoo");
goTo.marker("construcor5");
verify.currentParameterHelpArgumentNameIs("U");
verify.currentParameterSpanIs("U");

View File

@ -0,0 +1,34 @@
/// <reference path="fourslash.ts"/>
////interface IFoo { }
////
////class testClass<T extends IFoo, U, M extends IFoo> {
//// constructor(a:T, b:U, c:M){ }
////}
////
////// Generic types
////testClass</*type1*/
////var x : testClass</*type2*/
////class Bar<T> extends testClass</*type3*/
////var x : testClass<,, /*type4*/any>;
// goTo.marker("type1");
// verify.signatureHelpCountIs(1);
// verify.currentSignatureHelpIs("testClass<T extends IFoo, U, M extends IFoo>");
// verify.currentParameterHelpArgumentNameIs("T");
// verify.currentParameterSpanIs("T extends IFoo");
// goTo.marker("type2");
// verify.signatureHelpCountIs(1);
// verify.currentParameterHelpArgumentNameIs("T");
// verify.currentParameterSpanIs("T extends IFoo");
// goTo.marker("type3");
// verify.signatureHelpCountIs(1);
// verify.currentParameterHelpArgumentNameIs("T");
// verify.currentParameterSpanIs("T extends IFoo");
// goTo.marker("type4");
// verify.signatureHelpCountIs(1);
// verify.currentParameterHelpArgumentNameIs("M");
// verify.currentParameterSpanIs("M extends IFoo");

View File

@ -15,6 +15,6 @@ verify.currentParameterSpanIs("x: string");
edit.insert("'',");
verify.signatureHelpCountIs(2);
// verify.currentSignatureHelpIs("fn2(x: string, y: number): any");
// verify.currentParameterHelpArgumentNameIs("y");
// verify.currentParameterSpanIs("y: number");
verify.currentSignatureHelpIs("fn2(x: string, y: number): any");
verify.currentParameterHelpArgumentNameIs("y");
verify.currentParameterSpanIs("y: number");