Fix parameter emit for synthetic function types

This commit is contained in:
Ron Buckton 2017-06-07 15:13:24 -07:00
parent d450b8b2ab
commit 00a926cc4e
4 changed files with 146 additions and 58 deletions

View File

@ -959,7 +959,7 @@ namespace ts {
function emitConstructorType(node: ConstructorTypeNode) {
write("new ");
emitTypeParameters(node, node.typeParameters);
emitParametersForArrow(node, node.parameters);
emitParameters(node, node.parameters);
write(" => ");
emit(node.type);
}
@ -2283,11 +2283,25 @@ namespace ts {
emitList(parentNode, parameters, ListFormat.Parameters);
}
function emitParametersForArrow(parentNode: Node, parameters: NodeArray<ParameterDeclaration>) {
if (parameters &&
parameters.length === 1 &&
parameters[0].type === undefined &&
parameters[0].pos === parentNode.pos) {
function canEmitSimpleArrowHead(parentNode: FunctionTypeNode | ArrowFunction, parameters: NodeArray<ParameterDeclaration>) {
const parameter = singleOrUndefined(parameters);
return parameter
&& parameter.pos === parentNode.pos // may not have parsed tokens between parent and parameter
&& !(isArrowFunction(parentNode) && parentNode.type) // arrow function may not have return type annotation
&& !some(parentNode.decorators) // parent may not have decorators
&& !some(parentNode.modifiers) // parent may not have modifiers
&& !some(parentNode.typeParameters) // parent may not have type parameters
&& !some(parameter.decorators) // parameter may not have decorators
&& !some(parameter.modifiers) // parameter may not have modifiers
&& !parameter.dotDotDotToken // parameter may not be rest
&& !parameter.questionToken // parameter may not be optional
&& !parameter.type // parameter may not have a type annotation
&& !parameter.initializer // parameter may not have an initializer
&& isIdentifier(parameter.name); // parameter name must be identifier
}
function emitParametersForArrow(parentNode: FunctionTypeNode | ArrowFunction, parameters: NodeArray<ParameterDeclaration>) {
if (canEmitSimpleArrowHead(parentNode, parameters)) {
emit(parameters[0]);
}
else {

View File

@ -228,7 +228,7 @@ namespace ts {
// Signature elements
export function createTypeParameterDeclaration(name: string | Identifier, constraint: TypeNode | undefined, defaultType: TypeNode | undefined) {
export function createTypeParameterDeclaration(name: string | Identifier, constraint?: TypeNode, defaultType?: TypeNode) {
const node = createSynthesizedNode(SyntaxKind.TypeParameter) as TypeParameterDeclaration;
node.name = asName(name);
node.constraint = constraint;

View File

@ -81,63 +81,136 @@ namespace ts {
describe("printNode", () => {
const printsCorrectly = makePrintsCorrectly("printsNodeCorrectly");
let sourceFile: SourceFile;
before(() => sourceFile = createSourceFile("source.ts", "", ScriptTarget.ES2015));
// tslint:disable boolean-trivia
const syntheticNode = createClassDeclaration(
undefined,
undefined,
/*name*/ createIdentifier("C"),
undefined,
undefined,
createNodeArray([
createProperty(
undefined,
printsCorrectly("class", {}, printer => printer.printNode(
EmitHint.Unspecified,
createClassDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*name*/ createIdentifier("C"),
/*typeParameters*/ undefined,
/*heritageClauses*/ undefined,
[createProperty(
/*decorators*/ undefined,
createNodeArray([createToken(SyntaxKind.PublicKeyword)]),
createIdentifier("prop"),
undefined,
undefined,
undefined
)
])
);
/*questionToken*/ undefined,
/*type*/ undefined,
/*initializer*/ undefined
)]
),
createSourceFile("source.ts", "", ScriptTarget.ES2015)
));
printsCorrectly("namespaceExportDeclaration", {}, printer => printer.printNode(
EmitHint.Unspecified,
createNamespaceExportDeclaration("B"),
createSourceFile("source.ts", "", ScriptTarget.ES2015)
));
// https://github.com/Microsoft/TypeScript/issues/15971
const classWithOptionalMethodAndProperty = createClassDeclaration(
undefined,
/* modifiers */ createNodeArray([createToken(SyntaxKind.DeclareKeyword)]),
/* name */ createIdentifier("X"),
undefined,
undefined,
createNodeArray([
createMethod(
undefined,
undefined,
undefined,
/* name */ createIdentifier("method"),
/* questionToken */ createToken(SyntaxKind.QuestionToken),
undefined,
undefined,
/* type */ createKeywordTypeNode(SyntaxKind.VoidKeyword),
undefined
printsCorrectly("classWithOptionalMethodAndProperty", {}, printer => printer.printNode(
EmitHint.Unspecified,
createClassDeclaration(
/*decorators*/ undefined,
/*modifiers*/ [createToken(SyntaxKind.DeclareKeyword)],
/*name*/ createIdentifier("X"),
/*typeParameters*/ undefined,
/*heritageClauses*/ undefined,
[
createMethod(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ createIdentifier("method"),
/*questionToken*/ createToken(SyntaxKind.QuestionToken),
/*typeParameters*/ undefined,
[],
/*type*/ createKeywordTypeNode(SyntaxKind.VoidKeyword),
/*body*/ undefined
),
createProperty(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*name*/ createIdentifier("property"),
/*questionToken*/ createToken(SyntaxKind.QuestionToken),
/*type*/ createKeywordTypeNode(SyntaxKind.StringKeyword),
/*initializer*/ undefined
),
]
),
createSourceFile("source.ts", "", ScriptTarget.ES2015)
));
// https://github.com/Microsoft/TypeScript/issues/15651
printsCorrectly("functionTypes", {}, printer => printer.printNode(
EmitHint.Unspecified,
createTupleTypeNode([
createFunctionTypeNode(
/*typeArguments*/ undefined,
[createParameter(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
createIdentifier("args")
)],
createKeywordTypeNode(SyntaxKind.AnyKeyword)
),
createProperty(
undefined,
undefined,
/* name */ createIdentifier("property"),
/* questionToken */ createToken(SyntaxKind.QuestionToken),
/* type */ createKeywordTypeNode(SyntaxKind.StringKeyword),
undefined
createFunctionTypeNode(
[createTypeParameterDeclaration("T")],
[createParameter(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
createIdentifier("args")
)],
createKeywordTypeNode(SyntaxKind.AnyKeyword)
),
])
);
// tslint:enable boolean-trivia
printsCorrectly("class", {}, printer => printer.printNode(EmitHint.Unspecified, syntheticNode, sourceFile));
printsCorrectly("namespaceExportDeclaration", {}, printer => printer.printNode(EmitHint.Unspecified, createNamespaceExportDeclaration("B"), sourceFile));
printsCorrectly("classWithOptionalMethodAndProperty", {}, printer => printer.printNode(EmitHint.Unspecified, classWithOptionalMethodAndProperty, sourceFile));
createFunctionTypeNode(
/*typeArguments*/ undefined,
[createParameter(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createToken(SyntaxKind.DotDotDotToken),
createIdentifier("args")
)],
createKeywordTypeNode(SyntaxKind.AnyKeyword)
),
createFunctionTypeNode(
/*typeArguments*/ undefined,
[createParameter(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
createIdentifier("args"),
createToken(SyntaxKind.QuestionToken)
)],
createKeywordTypeNode(SyntaxKind.AnyKeyword)
),
createFunctionTypeNode(
/*typeArguments*/ undefined,
[createParameter(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
createIdentifier("args"),
/*questionToken*/ undefined,
createKeywordTypeNode(SyntaxKind.AnyKeyword)
)],
createKeywordTypeNode(SyntaxKind.AnyKeyword)
),
createFunctionTypeNode(
/*typeArguments*/ undefined,
[createParameter(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
createObjectBindingPattern([])
)],
createKeywordTypeNode(SyntaxKind.AnyKeyword)
),
]),
createSourceFile("source.ts", "", ScriptTarget.ES2015)
));
});
});
}

View File

@ -0,0 +1 @@
[args => any, <T>(args) => any, (...args) => any, (args?) => any, (args: any) => any, ({}) => any]