Switch signature help over to using display parts. This allows for classified sig help on the editor side.

This commit is contained in:
Cyrus Najmabadi
2014-09-24 23:44:13 -07:00
parent db0a223b1e
commit c87615aba9
4 changed files with 77 additions and 28 deletions

View File

@@ -820,7 +820,14 @@ module FourSlash {
this.taoInvalidReason = 'verifyCurrentSignatureHelpIs NYI';
var help = this.getActiveSignatureHelpItem();
assert.equal(help.prefix + help.parameters.map(p => p.display).join(help.separator) + help.suffix, expected);
assert.equal(
this.partsToString(help.prefixDisplayParts) +
help.parameters.map(p => this.partsToString(p.displayParts)).join(this.partsToString(help.separatorDisplayParts)) +
this.partsToString(help.suffixDisplayParts), expected);
}
private partsToString(parts: ts.SymbolDisplayPart[]): string {
return parts.map(p => p.text).join("");
}
public verifyCurrentParameterIsVariable(isVariable: boolean) {
@@ -844,7 +851,7 @@ module FourSlash {
var activeSignature = this.getActiveSignatureHelpItem();
var activeParameter = this.getActiveParameter();
assert.equal(activeParameter.display, parameter);
assert.equal(this.partsToString(activeParameter.displayParts), parameter);
}
public verifyCurrentParameterHelpDocComment(docComment: string) {

View File

@@ -856,8 +856,8 @@ module ts {
export class SignatureHelpParameter {
constructor(public name: string,
public documentation: string,
public display: string,
public documentation: SymbolDisplayPart[],
public displayParts: SymbolDisplayPart[],
public isOptional: boolean) {
}
}
@@ -871,11 +871,11 @@ module ts {
*/
export class SignatureHelpItem {
constructor(public isVariadic: boolean,
public prefix: string,
public suffix: string,
public separator: string,
public prefixDisplayParts: SymbolDisplayPart[],
public suffixDisplayParts: SymbolDisplayPart[],
public separatorDisplayParts: SymbolDisplayPart[],
public parameters: SignatureHelpParameter[],
public documentation: string) {
public documentation: SymbolDisplayPart[]) {
}
}
@@ -1630,6 +1630,11 @@ module ts {
});
}
export function getSymbolDocumentationDisplayParts(symbol: Symbol): SymbolDisplayPart[] {
var documentation = symbol.getDocumentationComment();
return documentation === "" ? [] : [new SymbolDisplayPart(documentation, SymbolDisplayPartKind.text, /*symbol:*/ null)];
}
export function createLanguageService(host: LanguageServiceHost, documentRegistry: DocumentRegistry): LanguageService {
var syntaxTreeCache: SyntaxTreeCache = new SyntaxTreeCache(host);
var formattingRulesProvider: TypeScript.Services.Formatting.RulesProvider;
@@ -2376,8 +2381,7 @@ module ts {
return undefined;
}
var documentation = symbol.getDocumentationComment();
var documentationParts = documentation === "" ? [] : [new SymbolDisplayPart(documentation, SymbolDisplayPartKind.text, /*symbol:*/ null)];
var documentationParts = getSymbolDocumentationDisplayParts(symbol);
// Having all this logic here is pretty unclean. Consider moving to the roslyn model
// where all symbol display logic is encapsulated into visitors and options.
@@ -3731,9 +3735,9 @@ module ts {
// Reset writer back to undefined to make sure that we produce an error message if CompilerHost.writeFile method is called when we are not in getEmitOutput
writer = undefined;
return emitOutput;
}
return emitOutput;
}
// Signature help
/**
* This is a semantic operation.

View File

@@ -252,29 +252,66 @@ module ts.SignatureHelp {
var items = map(candidates, candidateSignature => {
var parameters = candidateSignature.parameters;
var parameterHelpItems = parameters.length === 0 ? emptyArray : map(parameters, p => {
var display = p.name;
var displayParts: SymbolDisplayPart[] = [];
if (candidateSignature.hasRestParameter && parameters[parameters.length - 1] === p) {
display = "..." + display;
displayParts.push(new SymbolDisplayPart(tokenToString(SyntaxKind.DotDotDotToken), SymbolDisplayPartKind.punctuation, undefined));
}
displayParts.push(new SymbolDisplayPart(p.name, SymbolDisplayPartKind.parameterName, p));
var isOptional = !!(p.valueDeclaration.flags & NodeFlags.QuestionMark);
if (isOptional) {
display += "?";
displayParts.push(new SymbolDisplayPart(tokenToString(SyntaxKind.QuestionToken), SymbolDisplayPartKind.punctuation, undefined));
}
display += ": " + typeInfoResolver.typeToString(typeInfoResolver.getTypeOfSymbol(p), argumentListOrTypeArgumentList);
return new SignatureHelpParameter(p.name, "", display, isOptional);
displayParts.push(new SymbolDisplayPart(tokenToString(SyntaxKind.ColonToken), SymbolDisplayPartKind.punctuation, undefined));
displayParts.push(new SymbolDisplayPart(" ", SymbolDisplayPartKind.space, undefined));
var typeParts = typeInfoResolver.typeToDisplayParts(typeInfoResolver.getTypeOfSymbol(p), argumentListOrTypeArgumentList);
displayParts.push.apply(displayParts, typeParts);
return new SignatureHelpParameter(p.name, getSymbolDocumentationDisplayParts(p), displayParts, isOptional);
});
var callTargetNode = (<CallExpression>argumentListOrTypeArgumentList.parent).func;
var callTargetSymbol = typeInfoResolver.getSymbolInfo(callTargetNode);
var signatureName = callTargetSymbol ? typeInfoResolver.symbolToString(callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined) : "";
var prefix = signatureName;
var prefixParts = callTargetSymbol ? typeInfoResolver.symbolToDisplayParts(callTargetSymbol, /*enclosingDeclaration*/ undefined, /*meaning*/ undefined) : [];
var separatorParts = [
new SymbolDisplayPart(tokenToString(SyntaxKind.CommaToken), SymbolDisplayPartKind.punctuation, undefined),
new SymbolDisplayPart(" ", SymbolDisplayPartKind.space, undefined)
];
// TODO(jfreeman): Constraints?
if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) {
prefix += "<" + map(candidateSignature.typeParameters, tp => tp.symbol.name).join(", ") + ">";
prefixParts.push(new SymbolDisplayPart(tokenToString(SyntaxKind.LessThanToken), SymbolDisplayPartKind.punctuation, undefined));
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(new SymbolDisplayPart(tp.name, SymbolDisplayPartKind.typeParameterName, tp));
}
prefixParts.push(new SymbolDisplayPart(tokenToString(SyntaxKind.GreaterThanToken), SymbolDisplayPartKind.punctuation, undefined));
}
prefix += "(";
var suffix = "): " + typeInfoResolver.typeToString(candidateSignature.getReturnType(), argumentListOrTypeArgumentList);
return new SignatureHelpItem(candidateSignature.hasRestParameter, prefix, suffix, ", ", parameterHelpItems, "");
prefixParts.push(new SymbolDisplayPart(tokenToString(SyntaxKind.OpenParenToken), SymbolDisplayPartKind.punctuation, undefined));
var suffixParts = [new SymbolDisplayPart(tokenToString(SyntaxKind.CloseParenToken), SymbolDisplayPartKind.punctuation, undefined)];
suffixParts.push(new SymbolDisplayPart(tokenToString(SyntaxKind.ColonToken), SymbolDisplayPartKind.punctuation, undefined));
suffixParts.push(new SymbolDisplayPart(" ", SymbolDisplayPartKind.space, undefined));
var typeParts = typeInfoResolver.typeToDisplayParts(candidateSignature.getReturnType(), argumentListOrTypeArgumentList);
suffixParts.push.apply(suffixParts, typeParts);
return new SignatureHelpItem(candidateSignature.hasRestParameter, prefixParts, suffixParts, separatorParts, parameterHelpItems, null);
});
var selectedItemIndex = candidates.indexOf(bestSignature);
if (selectedItemIndex < 0) {
selectedItemIndex = 0;
@@ -339,11 +376,11 @@ module ts.SignatureHelp {
// by 2 to exclude commas. Use bit shifting in order to take the floor of the division.
var argumentIndex = indexOfNodeContainingPosition < 0 ? argumentCount - 1 : indexOfNodeContainingPosition >> 1;
return new SignatureHelpState(argumentIndex, argumentCount);
}
function getChildListThatStartsWithOpenerToken(parent: Node, openerToken: Node, sourceFile: SourceFile): Node {
}
function getChildListThatStartsWithOpenerToken(parent: Node, openerToken: Node, sourceFile: SourceFile): Node {
var children = parent.getChildren(sourceFile);
var indexOfOpenerToken = children.indexOf(openerToken);
return children[indexOfOpenerToken + 1];
return children[indexOfOpenerToken + 1];
}
}

View File

@@ -17,6 +17,7 @@
//// }
////}
debugger;
goTo.marker('superOverload1');
verify.signatureHelpCountIs(2);
verify.currentSignatureHelpIs("SuperOverloadlBase(): SuperOverloadlBase");