mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-10 21:07:52 -05:00
Format typeparameters information
This commit is contained in:
@@ -102,6 +102,7 @@ module ts {
|
||||
isValidPropertyAccess: isValidPropertyAccess,
|
||||
getSignatureFromDeclaration: getSignatureFromDeclaration,
|
||||
writeSignature: writeSignature,
|
||||
writeTypeParameter: writeTypeParameter,
|
||||
isImplementationOfOverload: isImplementationOfOverload
|
||||
};
|
||||
|
||||
@@ -964,12 +965,19 @@ module ts {
|
||||
|
||||
// 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 writeSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags): void {
|
||||
function writeSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void {
|
||||
function writeSymbolName(symbol: Symbol): void {
|
||||
if (symbol.declarations && symbol.declarations.length > 0) {
|
||||
var declaration = symbol.declarations[0];
|
||||
if (declaration.name) {
|
||||
writer.writeSymbol(identifierToString(declaration.name), symbol);
|
||||
if (flags & SymbolFormatFlags.WriteTypeParametersOfClassOrInterface) {
|
||||
var rootSymbol = getRootSymbol(symbol);
|
||||
if (rootSymbol.flags & SymbolFlags.Class || rootSymbol.flags & SymbolFlags.Interface) {
|
||||
writeTypeParameters(getTypeParametersOfClassOrInterface(symbol), writer, enclosingDeclaration);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1268,26 +1276,33 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function writeSignature(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
if (signature.typeParameters) {
|
||||
function writeTypeParameter(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
writeSymbol(tp.symbol, writer);
|
||||
var constraint = getConstraintOfTypeParameter(tp);
|
||||
if (constraint) {
|
||||
writeSpace(writer);
|
||||
writeKeyword(writer, SyntaxKind.ExtendsKeyword);
|
||||
writeSpace(writer);
|
||||
writeType(constraint, writer, enclosingDeclaration, flags, typeStack);
|
||||
}
|
||||
}
|
||||
|
||||
function writeTypeParameters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
if (typeParameters) {
|
||||
writePunctuation(writer, SyntaxKind.LessThanToken);
|
||||
for (var i = 0; i < signature.typeParameters.length; i++) {
|
||||
for (var i = 0; i < typeParameters.length; i++) {
|
||||
if (i > 0) {
|
||||
writePunctuation(writer, SyntaxKind.CommaToken);
|
||||
writeSpace(writer);
|
||||
}
|
||||
var tp = signature.typeParameters[i];
|
||||
writeSymbol(tp.symbol, writer);
|
||||
var constraint = getConstraintOfTypeParameter(tp);
|
||||
if (constraint) {
|
||||
writeSpace(writer);
|
||||
writeKeyword(writer, SyntaxKind.ExtendsKeyword);
|
||||
writeSpace(writer);
|
||||
writeType(constraint, writer, enclosingDeclaration, flags, typeStack);
|
||||
}
|
||||
writeTypeParameter(typeParameters[i], writer, enclosingDeclaration, flags, typeStack);
|
||||
}
|
||||
writePunctuation(writer, SyntaxKind.GreaterThanToken);
|
||||
}
|
||||
}
|
||||
|
||||
function writeSignature(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, typeStack?: Type[]) {
|
||||
writeTypeParameters(signature.typeParameters, writer, enclosingDeclaration, flags, typeStack);
|
||||
writePunctuation(writer, SyntaxKind.OpenParenToken);
|
||||
for (var i = 0; i < signature.parameters.length; i++) {
|
||||
if (i > 0) {
|
||||
|
||||
@@ -645,7 +645,7 @@ module ts {
|
||||
typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string;
|
||||
writeType(type: Type, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||
symbolToString(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): string;
|
||||
writeSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags): void;
|
||||
writeSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): void;
|
||||
getFullyQualifiedName(symbol: Symbol): string;
|
||||
getAugmentedPropertiesOfApparentType(type: Type): Symbol[];
|
||||
getRootSymbol(symbol: Symbol): Symbol;
|
||||
@@ -653,6 +653,7 @@ module ts {
|
||||
getResolvedSignature(node: CallExpression, candidatesOutArray?: Signature[]): Signature;
|
||||
getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature;
|
||||
writeSignature(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||
writeTypeParameter(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
|
||||
isImplementationOfOverload(node: FunctionDeclaration): boolean;
|
||||
|
||||
// Returns the constant value of this enum member, or 'undefined' if the enum member has a
|
||||
@@ -684,6 +685,11 @@ module ts {
|
||||
WriteArrowStyleSignature= 0x00000008, // Write arrow style signature
|
||||
}
|
||||
|
||||
export enum SymbolFormatFlags {
|
||||
None = 0x00000000,
|
||||
WriteTypeParametersOfClassOrInterface = 0x00000001, // Write c<T> instead of just writing symbol name c of generic class
|
||||
}
|
||||
|
||||
export enum SymbolAccessibility {
|
||||
Accessible,
|
||||
NotAccessible,
|
||||
|
||||
@@ -1405,29 +1405,30 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function mapToDisplayParts(writeDisplayParts: (writer: DisplayPartsSymbolWriter) => void): SymbolDisplayPart[] {
|
||||
var displayPartWriter = getDisplayPartWriter();
|
||||
writeDisplayParts(displayPartWriter);
|
||||
var result = displayPartWriter.displayParts();
|
||||
releaseDisplayPartWriter(displayPartWriter);
|
||||
return result;
|
||||
}
|
||||
|
||||
export function typeToDisplayParts(typechecker: TypeChecker, type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] {
|
||||
var displayPartWriter = getDisplayPartWriter();
|
||||
typechecker.writeType(type, displayPartWriter, enclosingDeclaration, flags);
|
||||
var result = displayPartWriter.displayParts();
|
||||
releaseDisplayPartWriter(displayPartWriter);
|
||||
return result;
|
||||
return mapToDisplayParts(writer => {
|
||||
typechecker.writeType(type, writer, enclosingDeclaration, flags);
|
||||
});
|
||||
}
|
||||
|
||||
export function symbolToDisplayParts(typeChecker: TypeChecker, symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): SymbolDisplayPart[] {
|
||||
var displayPartWriter = getDisplayPartWriter();
|
||||
typeChecker.writeSymbol(symbol, displayPartWriter, enclosingDeclaration, meaning);
|
||||
var result = displayPartWriter.displayParts();
|
||||
releaseDisplayPartWriter(displayPartWriter);
|
||||
|
||||
return result;
|
||||
export function symbolToDisplayParts(typeChecker: TypeChecker, symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags, flags?: SymbolFormatFlags): SymbolDisplayPart[] {
|
||||
return mapToDisplayParts(writer => {
|
||||
typeChecker.writeSymbol(symbol, writer, enclosingDeclaration, meaning, flags);
|
||||
});
|
||||
}
|
||||
|
||||
function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[] {
|
||||
var displayPartWriter = getDisplayPartWriter();
|
||||
typechecker.writeSignature(signature, displayPartWriter, enclosingDeclaration, flags);
|
||||
var result = displayPartWriter.displayParts();
|
||||
releaseDisplayPartWriter(displayPartWriter);
|
||||
return result;
|
||||
function signatureToDisplayParts(typechecker: TypeChecker, signature: Signature, enclosingDeclaration?: Node, flags?: TypeFormatFlags): SymbolDisplayPart[]{
|
||||
return mapToDisplayParts(writer => {
|
||||
typechecker.writeSignature(signature, writer, enclosingDeclaration, flags);
|
||||
});
|
||||
}
|
||||
|
||||
export function getDefaultCompilerOptions(): CompilerOptions {
|
||||
@@ -2792,13 +2793,13 @@ module ts {
|
||||
if (symbolFlags & SymbolFlags.Class && !hasAddedSymbolInfo) {
|
||||
displayParts.push(keywordPart(SyntaxKind.ClassKeyword));
|
||||
displayParts.push(spacePart());
|
||||
displayParts.push.apply(displayParts, symbolToDisplayParts(typeResolver, symbol, sourceFile));
|
||||
displayParts.push.apply(displayParts, symbolToDisplayParts(typeResolver, symbol, sourceFile, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOfClassOrInterface));
|
||||
}
|
||||
if (symbolFlags & SymbolFlags.Interface) {
|
||||
addNewLineIfDisplayPartsExist();
|
||||
displayParts.push(keywordPart(SyntaxKind.InterfaceKeyword));
|
||||
displayParts.push(spacePart());
|
||||
displayParts.push.apply(displayParts, symbolToDisplayParts(typeResolver, symbol, sourceFile));
|
||||
displayParts.push.apply(displayParts, symbolToDisplayParts(typeResolver, symbol, sourceFile, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOfClassOrInterface));
|
||||
}
|
||||
if (symbolFlags & SymbolFlags.Enum) {
|
||||
addNewLineIfDisplayPartsExist();
|
||||
@@ -2819,6 +2820,25 @@ module ts {
|
||||
displayParts.push(punctuationPart(SyntaxKind.CloseParenToken));
|
||||
displayParts.push(spacePart());
|
||||
displayParts.push.apply(displayParts, symbolToDisplayParts(typeResolver, symbol, enclosingDeclaration));
|
||||
displayParts.push(spacePart());
|
||||
displayParts.push(keywordPart(SyntaxKind.InKeyword));
|
||||
displayParts.push(spacePart());
|
||||
if (symbol.parent) {
|
||||
// Class/Interface type parameter
|
||||
displayParts.push.apply(displayParts, symbolToDisplayParts(typeResolver, symbol.parent, enclosingDeclaration, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOfClassOrInterface))
|
||||
}
|
||||
else {
|
||||
// Method/function type parameter
|
||||
var signatureDeclaration = <SignatureDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeParameter).parent;
|
||||
var signature = typeResolver.getSignatureFromDeclaration(signatureDeclaration);
|
||||
if (signatureDeclaration.kind === SyntaxKind.ConstructSignature) {
|
||||
displayParts.push(keywordPart(SyntaxKind.NewKeyword));
|
||||
displayParts.push(spacePart());
|
||||
} else if (signatureDeclaration.kind !== SyntaxKind.CallSignature) {
|
||||
displayParts.push.apply(displayParts, symbolToDisplayParts(typeResolver, signatureDeclaration.symbol, sourceFile, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOfClassOrInterface))
|
||||
}
|
||||
displayParts.push.apply(displayParts, signatureToDisplayParts(typeResolver, signature, sourceFile, TypeFormatFlags.NoTruncation));
|
||||
}
|
||||
}
|
||||
if (symbolFlags & SymbolFlags.EnumMember) {
|
||||
addPrefixForAnyFunctionOrVar(symbol, "enum member");
|
||||
@@ -2848,7 +2868,16 @@ module ts {
|
||||
symbolFlags & SymbolFlags.Variable) {
|
||||
displayParts.push(punctuationPart(SyntaxKind.ColonToken));
|
||||
displayParts.push(spacePart());
|
||||
displayParts.push.apply(displayParts, typeToDisplayParts(typeResolver, type, enclosingDeclaration, TypeFormatFlags.NoTruncation));
|
||||
// If the type is type parameter, format it specially
|
||||
if (type.symbol && type.symbol.flags & SymbolFlags.TypeParameter) {
|
||||
var typeParameterParts = mapToDisplayParts(writer => {
|
||||
typeResolver.writeTypeParameter(<TypeParameter>type, writer, enclosingDeclaration, TypeFormatFlags.NoTruncation);
|
||||
});
|
||||
displayParts.push.apply(displayParts, typeParameterParts);
|
||||
}
|
||||
else {
|
||||
displayParts.push.apply(displayParts, typeToDisplayParts(typeResolver, type, enclosingDeclaration, TypeFormatFlags.NoTruncation));
|
||||
}
|
||||
}
|
||||
else if (symbolFlags & SymbolFlags.Function ||
|
||||
symbolFlags & SymbolFlags.Method ||
|
||||
@@ -2880,9 +2909,8 @@ module ts {
|
||||
displayParts.push(textPart(symbolKind));
|
||||
displayParts.push(punctuationPart(SyntaxKind.CloseParenToken));
|
||||
displayParts.push(spacePart());
|
||||
//if (symbol.declarations && symbol.declarations.length) {
|
||||
displayParts.push.apply(displayParts, symbolToDisplayParts(typeResolver, symbol, sourceFile));
|
||||
//}
|
||||
// Write type parameters of class/Interface if it is property/method of the generic class/interface
|
||||
displayParts.push.apply(displayParts, symbolToDisplayParts(typeResolver, symbol, sourceFile, /*meaning*/ undefined, SymbolFormatFlags.WriteTypeParametersOfClassOrInterface));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
////a./**/
|
||||
|
||||
goTo.marker();
|
||||
// TODO. show as Array<number> or Array<T>.length instead
|
||||
verify.memberListContains('length', "(property) Array.length: number", /*docComments*/ undefined, /*kind*/ "property");
|
||||
verify.memberListContains('toString', "(method) Array.toString(): string", /*docComments*/ undefined, /*kind*/ "method");
|
||||
verify.memberListContains('length', "(property) Array<T>.length: number", /*docComments*/ undefined, /*kind*/ "property");
|
||||
verify.memberListContains('toString', "(method) Array<T>.toString(): string", /*docComments*/ undefined, /*kind*/ "method");
|
||||
|
||||
|
||||
@@ -20,5 +20,5 @@
|
||||
goTo.marker();
|
||||
verify.completionListContains('watch', '(property) iBaseScope.watch: () => void');
|
||||
verify.completionListContains('moveUp', '(property) iMover.moveUp: () => void');
|
||||
//verify.completionListContains('family', '(property) iScope<number>.family: number');
|
||||
// TODO
|
||||
debugger;
|
||||
verify.completionListContains('family', '(property) iScope<TModel>.family: number');
|
||||
|
||||
@@ -4,6 +4,4 @@
|
||||
////function foo4<T extends Date>(test: any): any { return null; }
|
||||
|
||||
goTo.marker();
|
||||
// TODO: formatting type parameter with extends info
|
||||
//verify.quickInfoIs('parameter) test: T extends Date');
|
||||
verify.quickInfoIs('(parameter) test: T');
|
||||
verify.quickInfoIs('(parameter) test: T extends Date');
|
||||
48
tests/cases/fourslash/quickInfoGenerics.ts
Normal file
48
tests/cases/fourslash/quickInfoGenerics.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////class Con/*1*/tainer<T> {
|
||||
//// x: T;
|
||||
////}
|
||||
////interface IList</*2*/T> {
|
||||
//// getItem(i: number): /*3*/T;
|
||||
////}
|
||||
////class List</*4*/T extends IList<number>> implements IList<T> {
|
||||
//// private __it/*6*/em: /*5*/T[];
|
||||
//// public get/*7*/Item(i: number) {
|
||||
//// return this.__item[i];
|
||||
//// }
|
||||
//// public /*8*/method</*9*/S extends IList<T>>(s: S, p: /*10*/T[]) {
|
||||
//// return s;
|
||||
//// }
|
||||
////}
|
||||
////function foo4</*11*/T extends Date>(test: T): T;
|
||||
////function foo4</*12*/S extends string>(test: S): S;
|
||||
////function foo4(test: any): any;
|
||||
////function foo4</*13*/T extends Date>(test: any): any { return null; }
|
||||
|
||||
goTo.marker("1");
|
||||
verify.quickInfoIs("class Container<T>", undefined);
|
||||
goTo.marker("2");
|
||||
verify.quickInfoIs("(type parameter) T in IList<T>", undefined);
|
||||
goTo.marker("3");
|
||||
verify.quickInfoIs("(type parameter) T in IList<T>", undefined);
|
||||
goTo.marker("4");
|
||||
verify.quickInfoIs("(type parameter) T in List<T extends IList<number>>", undefined);
|
||||
goTo.marker("5");
|
||||
verify.quickInfoIs("(type parameter) T in List<T extends IList<number>>", undefined);
|
||||
goTo.marker("6");
|
||||
verify.quickInfoIs("(property) List<T extends IList<number>>.__item: T[]", undefined);
|
||||
goTo.marker("7");
|
||||
verify.quickInfoIs("(method) List<T extends IList<number>>.getItem(i: number): T", undefined);
|
||||
goTo.marker("8");
|
||||
verify.quickInfoIs("(method) List<T extends IList<number>>.method<S extends IList<T>>(s: S, p: T[]): S", undefined);
|
||||
goTo.marker("9");
|
||||
verify.quickInfoIs("(type parameter) S in List<T extends IList<number>>.method<S extends IList<T>>(s: S, p: T[]): S", undefined);
|
||||
goTo.marker("10");
|
||||
verify.quickInfoIs("(type parameter) T in List<T extends IList<number>>", undefined);
|
||||
goTo.marker("11");
|
||||
verify.quickInfoIs("(type parameter) T in foo4<T extends Date>(test: T): T", undefined);
|
||||
goTo.marker("12");
|
||||
verify.quickInfoIs("(type parameter) S in foo4<S extends string>(test: S): S", undefined);
|
||||
goTo.marker("13");
|
||||
verify.quickInfoIs("(type parameter) T in foo4<T extends Date>(test: any): any", undefined);
|
||||
@@ -5,4 +5,4 @@
|
||||
////}
|
||||
|
||||
goTo.marker();
|
||||
verify.quickInfoIs('Container<T>', null, 'Container<T>');
|
||||
verify.quickInfoIs('class Container<T>', null);
|
||||
@@ -0,0 +1,9 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////interface Fo/*1*/o<T/*2*/T extends Date> {}
|
||||
|
||||
goTo.marker('1');
|
||||
verify.quickInfoIs('interface Foo<TT extends Date>', null);
|
||||
|
||||
goTo.marker('2');
|
||||
verify.quickInfoIs('(type parameter) TT in Foo<TT extends Date>', null);
|
||||
@@ -9,20 +9,20 @@
|
||||
//// }
|
||||
//// var b: B<string>;
|
||||
//// var r3 = b.foo; // number
|
||||
//// var r/*2*/4 = b.ba/*1*/r; // string
|
||||
//// var r/*2*/4 = b.b/*1*/ar; // string
|
||||
////}
|
||||
|
||||
diagnostics.setEditValidation(IncrementalEditValidation.None);
|
||||
|
||||
goTo.marker('1');
|
||||
verify.quickInfoIs("string", undefined, "MM.B<T>.bar", "property");
|
||||
verify.quickInfoIs("(property) B<T>.bar: string", undefined);
|
||||
edit.deleteAtCaret(1);
|
||||
edit.insert('z');
|
||||
verify.quickInfoIs("any");
|
||||
verify.not.quickInfoExists();
|
||||
verify.numberOfErrorsInCurrentFile(1);
|
||||
edit.backspace(1);
|
||||
edit.insert('r');
|
||||
verify.quickInfoIs("string", undefined, "MM.B<T>.bar", "property");
|
||||
edit.insert('a');
|
||||
verify.quickInfoIs("(property) B<T>.bar: string", undefined);
|
||||
goTo.marker('2');
|
||||
verify.quickInfoIs("string", undefined, "r4", "var");
|
||||
verify.quickInfoIs("(var) r4: string", undefined);
|
||||
verify.numberOfErrorsInCurrentFile(0);
|
||||
@@ -1,31 +0,0 @@
|
||||
/// <reference path='fourslash.ts' />
|
||||
|
||||
////class Con/*1*/tainer<T> {
|
||||
//// x: T;
|
||||
////}
|
||||
////interface IList</*2*/T> {
|
||||
//// getItem(i: number): /*3*/T;
|
||||
////}
|
||||
////class List</*4*/T extends IList<T>> implements IList<T> {
|
||||
//// private __it/*6*/em: /*5*/T[];
|
||||
//// public get/*7*/Item(i: number) {
|
||||
//// return this.__item[i];
|
||||
//// }
|
||||
////}
|
||||
|
||||
goTo.marker("1");
|
||||
verify.quickInfoIs(undefined, undefined, "Container<T>", "class");
|
||||
goTo.marker("2");
|
||||
verify.quickInfoIs(undefined, undefined, "T in IList<T>", "type parameter");
|
||||
goTo.marker("3");
|
||||
verify.quickInfoIs(undefined, undefined, "T in IList<T>", "type parameter");
|
||||
goTo.marker("4");
|
||||
verify.quickInfoIs(undefined, undefined, "T in List<T extends IList<T>>", "type parameter");
|
||||
goTo.marker("5");
|
||||
verify.quickInfoIs(undefined, undefined, "T in List<T extends IList<T>>", "type parameter");
|
||||
goTo.marker("6");
|
||||
verify.quickInfoIs(undefined, undefined, "List<T extends IList<T>>.__item", "property");
|
||||
goTo.marker("7");
|
||||
verify.quickInfoIs(undefined, undefined, "List<T extends IList<T>>.getItem", "method");
|
||||
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
////interface Fo/*1*/o<T/*2*/T extends Date> {}
|
||||
|
||||
goTo.marker('1');
|
||||
verify.quickInfoIs('Foo<TT extends Date>', null, 'Foo<TT extends Date>')
|
||||
|
||||
goTo.marker('2');
|
||||
verify.quickInfoIs('TT extends Date', null, 'TT in Foo<TT extends Date>')
|
||||
Reference in New Issue
Block a user