mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 21:53:42 -06:00
Merge pull request #915 from Microsoft/sigHelp
Basic generic signature help
This commit is contained in:
commit
a1e69b0dc2
@ -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
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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];
|
||||
}
|
||||
}
|
||||
@ -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");
|
||||
@ -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");
|
||||
34
tests/cases/fourslash/genericParameterHelpTypeReferences.ts
Normal file
34
tests/cases/fourslash/genericParameterHelpTypeReferences.ts
Normal 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");
|
||||
@ -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");
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user