diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 097d0c76c08..29ded915826 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -995,14 +995,26 @@ module ts { 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 + function buildPlainSymbolName(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); + } + function buildSymbolDisplay(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void { var parentSymbol: Symbol; - function writeSymbolName(symbol: Symbol): void { + function appendSymbolName(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), (symbol).mapper, writer, enclosingDeclaration); } else { @@ -1012,15 +1024,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); + buildPlainSymbolName(symbol, writer); } // Let the writer know we just wrote out a symbol. The declaration emitter writer uses @@ -1046,7 +1050,7 @@ module ts { if (accessibleSymbolChain) { for (var i = 0, n = accessibleSymbolChain.length; i < n; i++) { - writeSymbolName(accessibleSymbolChain[i]); + appendSymbolName(accessibleSymbolChain[i]); } } else { @@ -1060,7 +1064,7 @@ module ts { return; } - writeSymbolName(symbol); + appendSymbolName(symbol); } } } @@ -1074,7 +1078,7 @@ module ts { return; } - return writeSymbolName(symbol); + return appendSymbolName(symbol); } function buildTypeDisplay(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) { @@ -1302,8 +1306,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); + buildPlainSymbolName(tp.symbol, writer); var constraint = getConstraintOfTypeParameter(tp); if (constraint) { writeSpace(writer); @@ -1313,7 +1324,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); + } + buildPlainSymbolName(p, writer); + if (p.valueDeclaration.flags & NodeFlags.QuestionMark || (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++) { @@ -1327,7 +1352,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++) { @@ -1341,42 +1366,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(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) { writePunctuation(writer, SyntaxKind.OpenParenToken); for (var i = 0; i < signature.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 || (p.valueDeclaration).initializer) { - writePunctuation(writer, SyntaxKind.QuestionToken); - } - writePunctuation(writer, SyntaxKind.ColonToken); - writeSpace(writer); - - buildTypeDisplay(getTypeOfSymbol(p), writer, enclosingDeclaration, flags, typeStack); + buildParameterDisplay(signature.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); @@ -1385,9 +1387,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, writer, enclosingDeclaration, flags, typeStack); + buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, typeStack); + } return _displayBuilder || (_displayBuilder = { symbolToString: symbolToString, @@ -1395,10 +1410,12 @@ module ts { buildSymbolDisplay: buildSymbolDisplay, buildTypeDisplay: buildTypeDisplay, buildTypeParameterDisplay: buildTypeParameterDisplay, - buildTypeParameterListDisplay: buildTypeParameterListDisplay, - buildTypeArgumentListDisplay: buildTypeArgumentListDisplay, + buildParameterDisplay: buildParameterDisplay, + buildDisplayForTypeParametersAndDelimiters: buildDisplayForTypeParametersAndDelimiters, + buildDisplayForTypeArgumentsAndDelimiters: buildDisplayForTypeArgumentsAndDelimiters, buildTypeParameterDisplayFromSymbol: buildTypeParameterDisplayFromSymbol, - buildSignatureDisplay: buildSignatureDisplay + buildSignatureDisplay: buildSignatureDisplay, + buildReturnTypeDisplay: buildReturnTypeDisplay }); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index d062da142d7..25532c94f9c 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -672,8 +672,11 @@ 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; + buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]): void; + buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]): void; } export interface SymbolWriter { diff --git a/src/services/services.ts b/src/services/services.ts index 6b38cbd5b3b..5411cac8d0c 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -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(); diff --git a/src/services/signatureHelp.ts b/src/services/signatureHelp.ts index f5f678c3021..327a61477e7 100644 --- a/src/services/signatureHelp.ts +++ b/src/services/signatureHelp.ts @@ -296,24 +296,10 @@ module ts.SignatureHelp { var items: SignatureHelpItem[] = map(candidates, candidateSignature => { var parameters = candidateSignature.parameters; var parameterHelpItems: SignatureHelpParameter[] = parameters.length === 0 ? emptyArray : map(parameters, p => { - var displayParts: SymbolDisplayPart[] = []; - - if (candidateSignature.hasRestParameter && parameters[parameters.length - 1] === p) { - displayParts.push(punctuationPart(SyntaxKind.DotDotDotToken)); - } - - displayParts.push(symbolPart(p.name, p)); + var displayParts = mapToDisplayParts(writer => + typeInfoResolver.getSymbolDisplayBuilder().buildParameterDisplay(p, writer, argumentListOrTypeArgumentList)); 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, @@ -328,38 +314,21 @@ module ts.SignatureHelp { 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)); - } - + var typeParameterParts = mapToDisplayParts(writer => + typeInfoResolver.getSymbolDisplayBuilder().buildDisplayForTypeParametersAndDelimiters(candidateSignature.typeParameters, writer, argumentListOrTypeArgumentList)); + prefixParts.push.apply(prefixParts, typeParameterParts); prefixParts.push(punctuationPart(SyntaxKind.OpenParenToken)); 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, + separatorDisplayParts: [punctuationPart(SyntaxKind.CommaToken), spacePart()], parameters: parameterHelpItems, documentation: candidateSignature.getDocumentationComment() };