1namespace ts { 2 describe("unittests:: PrinterAPI", () => { 3 function makePrintsCorrectly(prefix: string) { 4 return function printsCorrectly(name: string, options: PrinterOptions, printCallback: (printer: Printer) => string) { 5 it(name, () => { 6 Harness.Baseline.runBaseline(`printerApi/${prefix}.${name}.js`, 7 printCallback(createPrinter({ newLine: NewLineKind.CarriageReturnLineFeed, ...options }))); 8 }); 9 }; 10 } 11 12 describe("printFile", () => { 13 const printsCorrectly = makePrintsCorrectly("printsFileCorrectly"); 14 describe("comment handling", () => { 15 // Avoid eagerly creating the sourceFile so that `createSourceFile` doesn't run unless one of these tests is run. 16 let sourceFile: SourceFile; 17 before(() => { 18 sourceFile = createSourceFile("source.ts", ` 19 interface A<T> { 20 // comment1 21 readonly prop?: T; 22 23 // comment2 24 method(): void; 25 26 // comment3 27 new <T>(): A<T>; 28 29 // comment4 30 <T>(): A<T>; 31 } 32 33 // comment5 34 type B = number | string | object; 35 type C = A<number> & { x: string; }; // comment6 36 37 // comment7 38 enum E1 { 39 // comment8 40 first 41 } 42 43 const enum E2 { 44 second 45 } 46 47 // comment9 48 console.log(1 + 2); 49 50 // comment10 51 function functionWithDefaultArgValue(argument: string = "defaultValue"): void { } 52 `, ScriptTarget.ES2015); 53 }); 54 printsCorrectly("default", {}, printer => printer.printFile(sourceFile)); 55 printsCorrectly("removeComments", { removeComments: true }, printer => printer.printFile(sourceFile)); 56 }); 57 58 // https://github.com/microsoft/TypeScript/issues/14948 59 // eslint-disable-next-line no-template-curly-in-string 60 printsCorrectly("templateLiteral", {}, printer => printer.printFile(createSourceFile("source.ts", "let greeting = `Hi ${name}, how are you?`;", ScriptTarget.ES2017))); 61 62 // https://github.com/microsoft/TypeScript/issues/18071 63 printsCorrectly("regularExpressionLiteral", {}, printer => printer.printFile(createSourceFile("source.ts", "let regex = /abc/;", ScriptTarget.ES2017))); 64 65 // https://github.com/microsoft/TypeScript/issues/22239 66 printsCorrectly("importStatementRemoveComments", { removeComments: true }, printer => printer.printFile(createSourceFile("source.ts", "import {foo} from 'foo';", ScriptTarget.ESNext))); 67 printsCorrectly("classHeritageClauses", {}, printer => printer.printFile(createSourceFile( 68 "source.ts", 69 `class A extends B implements C implements D {}`, 70 ScriptTarget.ES2017 71 ))); 72 73 // https://github.com/microsoft/TypeScript/issues/35093 74 printsCorrectly("definiteAssignmentAssertions", {}, printer => printer.printFile(createSourceFile( 75 "source.ts", 76 `class A { 77 prop!: string; 78 } 79 80 let x!: string;`, 81 ScriptTarget.ES2017 82 ))); 83 84 // https://github.com/microsoft/TypeScript/issues/35054 85 printsCorrectly("jsx attribute escaping", {}, printer => { 86 return printer.printFile(createSourceFile( 87 "source.ts", 88 String.raw`<a x='\\"'/>`, 89 ScriptTarget.ESNext, 90 /*setParentNodes*/ undefined, 91 ScriptKind.TSX 92 )); 93 }); 94 }); 95 96 describe("No duplicate ref directives when emiting .d.ts->.d.ts", () => { 97 it("without statements", () => { 98 const host = new fakes.CompilerHost(new vfs.FileSystem(true, { 99 files: { 100 "/test.d.ts": `/// <reference types="node" />\n/// <reference path="./src/test.d.ts />\n` 101 } 102 })); 103 const program = createProgram(["/test.d.ts"], { }, host); 104 const file = program.getSourceFile("/test.d.ts")!; 105 const printer = createPrinter({ newLine: NewLineKind.CarriageReturnLineFeed }); 106 const output = printer.printFile(file); 107 assert.equal(output.split(/\r?\n/g).length, 3); 108 }); 109 it("with statements", () => { 110 const host = new fakes.CompilerHost(new vfs.FileSystem(true, { 111 files: { 112 "/test.d.ts": `/// <reference types="node" />\n/// <reference path="./src/test.d.ts />\nvar a: number;\n` 113 } 114 })); 115 const program = createProgram(["/test.d.ts"], { }, host); 116 const file = program.getSourceFile("/test.d.ts")!; 117 const printer = createPrinter({ newLine: NewLineKind.CarriageReturnLineFeed }); 118 const output = printer.printFile(file); 119 assert.equal(output.split(/\r?\n/g).length, 4); 120 }); 121 }); 122 123 describe("printBundle", () => { 124 const printsCorrectly = makePrintsCorrectly("printsBundleCorrectly"); 125 let bundle: Bundle; 126 before(() => { 127 bundle = factory.createBundle([ 128 createSourceFile("a.ts", ` 129 /*! [a.ts] */ 130 131 // comment0 132 const a = 1; 133 `, ScriptTarget.ES2015), 134 createSourceFile("b.ts", ` 135 /*! [b.ts] */ 136 137 // comment1 138 const b = 2; 139 `, ScriptTarget.ES2015) 140 ]); 141 }); 142 printsCorrectly("default", {}, printer => printer.printBundle(bundle)); 143 printsCorrectly("removeComments", { removeComments: true }, printer => printer.printBundle(bundle)); 144 }); 145 146 describe("printNode", () => { 147 const printsCorrectly = makePrintsCorrectly("printsNodeCorrectly"); 148 printsCorrectly("class", {}, printer => printer.printNode( 149 EmitHint.Unspecified, 150 factory.createClassDeclaration( 151 /*modifiers*/ undefined, 152 /*name*/ factory.createIdentifier("C"), 153 /*typeParameters*/ undefined, 154 /*heritageClauses*/ undefined, 155 [factory.createPropertyDeclaration( 156 factory.createNodeArray([factory.createToken(SyntaxKind.PublicKeyword)]), 157 factory.createIdentifier("prop"), 158 /*questionToken*/ undefined, 159 /*type*/ undefined, 160 /*initializer*/ undefined 161 )] 162 ), 163 createSourceFile("source.ts", "", ScriptTarget.ES2015) 164 )); 165 166 printsCorrectly("namespaceExportDeclaration", {}, printer => printer.printNode( 167 EmitHint.Unspecified, 168 factory.createNamespaceExportDeclaration("B"), 169 createSourceFile("source.ts", "", ScriptTarget.ES2015) 170 )); 171 172 printsCorrectly("newExpressionWithPropertyAccessOnCallExpression", {}, printer => printer.printNode( 173 EmitHint.Unspecified, 174 factory.createNewExpression( 175 factory.createPropertyAccessExpression( 176 factory.createCallExpression(factory.createIdentifier("f"), /*typeArguments*/ undefined, /*argumentsArray*/ undefined), 177 "x"), 178 /*typeArguments*/ undefined, 179 /*argumentsArray*/ undefined 180 ), 181 createSourceFile("source.ts", "", ScriptTarget.ESNext)) 182 ); 183 184 printsCorrectly("newExpressionOnConditionalExpression", {}, printer => printer.printNode( 185 EmitHint.Unspecified, 186 factory.createNewExpression( 187 factory.createConditionalExpression( 188 factory.createIdentifier("x"), factory.createToken(SyntaxKind.QuestionToken), 189 factory.createIdentifier("y"), factory.createToken(SyntaxKind.ColonToken), 190 factory.createIdentifier("z")), 191 /*typeArguments*/ undefined, 192 /*argumentsArray*/ undefined 193 ), 194 createSourceFile("source.ts", "", ScriptTarget.ESNext)) 195 ); 196 197 printsCorrectly("emptyGlobalAugmentation", {}, printer => printer.printNode( 198 EmitHint.Unspecified, 199 factory.createModuleDeclaration( 200 /*modifiers*/ [factory.createToken(SyntaxKind.DeclareKeyword)], 201 factory.createIdentifier("global"), 202 factory.createModuleBlock(emptyArray), 203 NodeFlags.GlobalAugmentation), 204 createSourceFile("source.ts", "", ScriptTarget.ES2015) 205 )); 206 207 printsCorrectly("emptyGlobalAugmentationWithNoDeclareKeyword", {}, printer => printer.printNode( 208 EmitHint.Unspecified, 209 factory.createModuleDeclaration( 210 /*modifiers*/ undefined, 211 factory.createIdentifier("global"), 212 factory.createModuleBlock(emptyArray), 213 NodeFlags.GlobalAugmentation), 214 createSourceFile("source.ts", "", ScriptTarget.ES2015) 215 )); 216 217 // https://github.com/Microsoft/TypeScript/issues/15971 218 printsCorrectly("classWithOptionalMethodAndProperty", {}, printer => printer.printNode( 219 EmitHint.Unspecified, 220 factory.createClassDeclaration( 221 /*modifiers*/ [factory.createToken(SyntaxKind.DeclareKeyword)], 222 /*name*/ factory.createIdentifier("X"), 223 /*typeParameters*/ undefined, 224 /*heritageClauses*/ undefined, 225 [ 226 factory.createMethodDeclaration( 227 /*modifiers*/ undefined, 228 /*asteriskToken*/ undefined, 229 /*name*/ factory.createIdentifier("method"), 230 /*questionToken*/ factory.createToken(SyntaxKind.QuestionToken), 231 /*typeParameters*/ undefined, 232 [], 233 /*type*/ factory.createKeywordTypeNode(SyntaxKind.VoidKeyword), 234 /*body*/ undefined 235 ), 236 factory.createPropertyDeclaration( 237 /*modifiers*/ undefined, 238 /*name*/ factory.createIdentifier("property"), 239 /*questionToken*/ factory.createToken(SyntaxKind.QuestionToken), 240 /*type*/ factory.createKeywordTypeNode(SyntaxKind.StringKeyword), 241 /*initializer*/ undefined 242 ), 243 ] 244 ), 245 createSourceFile("source.ts", "", ScriptTarget.ES2015) 246 )); 247 248 // https://github.com/Microsoft/TypeScript/issues/15651 249 printsCorrectly("functionTypes", {}, printer => printer.printNode( 250 EmitHint.Unspecified, 251 setEmitFlags(factory.createTupleTypeNode([ 252 factory.createFunctionTypeNode( 253 /*typeArguments*/ undefined, 254 [factory.createParameterDeclaration( 255 /*modifiers*/ undefined, 256 /*dotDotDotToken*/ undefined, 257 factory.createIdentifier("args") 258 )], 259 factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) 260 ), 261 factory.createFunctionTypeNode( 262 [factory.createTypeParameterDeclaration(/*modifiers*/ undefined, "T")], 263 [factory.createParameterDeclaration( 264 /*modifiers*/ undefined, 265 /*dotDotDotToken*/ undefined, 266 factory.createIdentifier("args") 267 )], 268 factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) 269 ), 270 factory.createFunctionTypeNode( 271 /*typeArguments*/ undefined, 272 [factory.createParameterDeclaration( 273 /*modifiers*/ undefined, 274 factory.createToken(SyntaxKind.DotDotDotToken), 275 factory.createIdentifier("args") 276 )], 277 factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) 278 ), 279 factory.createFunctionTypeNode( 280 /*typeArguments*/ undefined, 281 [factory.createParameterDeclaration( 282 /*modifiers*/ undefined, 283 /*dotDotDotToken*/ undefined, 284 factory.createIdentifier("args"), 285 factory.createToken(SyntaxKind.QuestionToken) 286 )], 287 factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) 288 ), 289 factory.createFunctionTypeNode( 290 /*typeArguments*/ undefined, 291 [factory.createParameterDeclaration( 292 /*modifiers*/ undefined, 293 /*dotDotDotToken*/ undefined, 294 factory.createIdentifier("args"), 295 /*questionToken*/ undefined, 296 factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) 297 )], 298 factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) 299 ), 300 factory.createFunctionTypeNode( 301 /*typeArguments*/ undefined, 302 [factory.createParameterDeclaration( 303 /*modifiers*/ undefined, 304 /*dotDotDotToken*/ undefined, 305 factory.createObjectBindingPattern([]) 306 )], 307 factory.createKeywordTypeNode(SyntaxKind.AnyKeyword) 308 ), 309 ]), EmitFlags.SingleLine), 310 createSourceFile("source.ts", "", ScriptTarget.ES2015) 311 )); 312 }); 313 }); 314} 315