Merge pull request #8159 from Microsoft/declFileFirstTypeArgumentIsGenericFunctionType

Fixes scenarios of generating declaration file when first type argument is generic function type
This commit is contained in:
Sheetal Nandi
2016-04-19 10:41:06 -07:00
12 changed files with 714 additions and 5 deletions

View File

@@ -1990,7 +1990,7 @@ namespace ts {
}
if (pos < end) {
writePunctuation(writer, SyntaxKind.LessThanToken);
writeType(typeArguments[pos], TypeFormatFlags.None);
writeType(typeArguments[pos], TypeFormatFlags.InFirstTypeArgument);
pos++;
while (pos < end) {
writePunctuation(writer, SyntaxKind.CommaToken);
@@ -2143,6 +2143,19 @@ namespace ts {
}
}
function shouldAddParenthesisAroundFunctionType(callSignature: Signature, flags: TypeFormatFlags) {
if (flags & TypeFormatFlags.InElementType) {
return true;
}
else if (flags & TypeFormatFlags.InFirstTypeArgument) {
// Add parenthesis around function type for the first type argument to avoid ambiguity
const typeParameters = callSignature.target && (flags & TypeFormatFlags.WriteTypeArgumentsOfSignature) ?
callSignature.target.typeParameters : callSignature.typeParameters;
return typeParameters && typeParameters.length !== 0;
}
return false;
}
function writeLiteralType(type: ObjectType, flags: TypeFormatFlags) {
const resolved = resolveStructuredTypeMembers(type);
if (!resolved.properties.length && !resolved.stringIndexInfo && !resolved.numberIndexInfo) {
@@ -2153,11 +2166,12 @@ namespace ts {
}
if (resolved.callSignatures.length === 1 && !resolved.constructSignatures.length) {
if (flags & TypeFormatFlags.InElementType) {
const parenthesizeSignature = shouldAddParenthesisAroundFunctionType(resolved.callSignatures[0], flags);
if (parenthesizeSignature) {
writePunctuation(writer, SyntaxKind.OpenParenToken);
}
buildSignatureDisplay(resolved.callSignatures[0], writer, enclosingDeclaration, globalFlagsToPass | TypeFormatFlags.WriteArrowStyleSignature, /*kind*/ undefined, symbolStack);
if (flags & TypeFormatFlags.InElementType) {
if (parenthesizeSignature) {
writePunctuation(writer, SyntaxKind.CloseParenToken);
}
return;
@@ -2317,12 +2331,14 @@ namespace ts {
function buildDisplayForTypeArgumentsAndDelimiters(typeParameters: TypeParameter[], mapper: TypeMapper, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
if (typeParameters && typeParameters.length) {
writePunctuation(writer, SyntaxKind.LessThanToken);
let flags = TypeFormatFlags.InFirstTypeArgument;
for (let i = 0; i < typeParameters.length; i++) {
if (i > 0) {
writePunctuation(writer, SyntaxKind.CommaToken);
writeSpace(writer);
flags = TypeFormatFlags.None;
}
buildTypeDisplay(mapper(typeParameters[i]), writer, enclosingDeclaration, TypeFormatFlags.None);
buildTypeDisplay(mapper(typeParameters[i]), writer, enclosingDeclaration, flags);
}
writePunctuation(writer, SyntaxKind.GreaterThanToken);
}

View File

@@ -1377,6 +1377,7 @@ namespace ts {
function emitSignatureDeclaration(node: SignatureDeclaration) {
const prevEnclosingDeclaration = enclosingDeclaration;
enclosingDeclaration = node;
let closeParenthesizedFunctionType = false;
if (node.kind === SyntaxKind.IndexSignature) {
// Index signature can have readonly modifier
@@ -1388,6 +1389,16 @@ namespace ts {
if (node.kind === SyntaxKind.ConstructSignature || node.kind === SyntaxKind.ConstructorType) {
write("new ");
}
else if (node.kind === SyntaxKind.FunctionType) {
const currentOutput = writer.getText();
// Do not generate incorrect type when function type with type parameters is type argument
// This could happen if user used space between two '<' making it error free
// e.g var x: A< <Tany>(a: Tany)=>Tany>;
if (node.typeParameters && currentOutput.charAt(currentOutput.length - 1) === "<") {
closeParenthesizedFunctionType = true;
write("(");
}
}
emitTypeParameters(node.typeParameters);
write("(");
}
@@ -1421,6 +1432,9 @@ namespace ts {
write(";");
writeLine();
}
else if (closeParenthesizedFunctionType) {
write(")");
}
function getReturnTypeVisibilityError(symbolAccessibilityResult: SymbolAccessibilityResult): SymbolAccessibilityDiagnostic {
let diagnosticMessage: DiagnosticMessage;

View File

@@ -1820,6 +1820,7 @@ namespace ts {
WriteTypeArgumentsOfSignature = 0x00000020, // Write the type arguments instead of type parameters of the signature
InElementType = 0x00000040, // Writing an array or union element type
UseFullyQualifiedType = 0x00000080, // Write out the fully qualified type name (eg. Module.Type, instead of Type)
InFirstTypeArgument = 0x00000100, // Writing first type argument of the instantiated type
}
export const enum SymbolFormatFlags {