• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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                    /*decorators*/ undefined,
152                    /*modifiers*/ undefined,
153                    /*name*/ factory.createIdentifier("C"),
154                    /*typeParameters*/ undefined,
155                    /*heritageClauses*/ undefined,
156                    [factory.createPropertyDeclaration(
157                        /*decorators*/ undefined,
158                        factory.createNodeArray([factory.createToken(SyntaxKind.PublicKeyword)]),
159                        factory.createIdentifier("prop"),
160                        /*questionToken*/ undefined,
161                        /*type*/ undefined,
162                        /*initializer*/ undefined
163                    )]
164                ),
165                createSourceFile("source.ts", "", ScriptTarget.ES2015)
166            ));
167
168            printsCorrectly("namespaceExportDeclaration", {}, printer => printer.printNode(
169                EmitHint.Unspecified,
170                factory.createNamespaceExportDeclaration("B"),
171                createSourceFile("source.ts", "", ScriptTarget.ES2015)
172            ));
173
174            printsCorrectly("newExpressionWithPropertyAccessOnCallExpression", {}, printer => printer.printNode(
175                EmitHint.Unspecified,
176                factory.createNewExpression(
177                    factory.createPropertyAccessExpression(
178                        factory.createCallExpression(factory.createIdentifier("f"), /*typeArguments*/ undefined, /*argumentsArray*/ undefined),
179                        "x"),
180                    /*typeArguments*/ undefined,
181                    /*argumentsArray*/ undefined
182                ),
183                createSourceFile("source.ts", "", ScriptTarget.ESNext))
184            );
185
186            printsCorrectly("newExpressionOnConditionalExpression", {}, printer => printer.printNode(
187                EmitHint.Unspecified,
188                factory.createNewExpression(
189                    factory.createConditionalExpression(
190                        factory.createIdentifier("x"), factory.createToken(SyntaxKind.QuestionToken),
191                        factory.createIdentifier("y"), factory.createToken(SyntaxKind.ColonToken),
192                        factory.createIdentifier("z")),
193                    /*typeArguments*/ undefined,
194                    /*argumentsArray*/ undefined
195                ),
196                createSourceFile("source.ts", "", ScriptTarget.ESNext))
197            );
198
199            printsCorrectly("emptyGlobalAugmentation", {}, printer => printer.printNode(
200                EmitHint.Unspecified,
201                factory.createModuleDeclaration(
202                    /*decorators*/ undefined,
203                    /*modifiers*/ [factory.createToken(SyntaxKind.DeclareKeyword)],
204                    factory.createIdentifier("global"),
205                    factory.createModuleBlock(emptyArray),
206                    NodeFlags.GlobalAugmentation),
207                createSourceFile("source.ts", "", ScriptTarget.ES2015)
208            ));
209
210            printsCorrectly("emptyGlobalAugmentationWithNoDeclareKeyword", {}, printer => printer.printNode(
211                EmitHint.Unspecified,
212                factory.createModuleDeclaration(
213                    /*decorators*/ undefined,
214                    /*modifiers*/ undefined,
215                    factory.createIdentifier("global"),
216                    factory.createModuleBlock(emptyArray),
217                    NodeFlags.GlobalAugmentation),
218                createSourceFile("source.ts", "", ScriptTarget.ES2015)
219            ));
220
221            // https://github.com/Microsoft/TypeScript/issues/15971
222            printsCorrectly("classWithOptionalMethodAndProperty", {}, printer => printer.printNode(
223                EmitHint.Unspecified,
224                factory.createClassDeclaration(
225                    /*decorators*/ undefined,
226                    /*modifiers*/ [factory.createToken(SyntaxKind.DeclareKeyword)],
227                    /*name*/ factory.createIdentifier("X"),
228                    /*typeParameters*/ undefined,
229                    /*heritageClauses*/ undefined,
230                    [
231                        factory.createMethodDeclaration(
232                            /*decorators*/ undefined,
233                            /*modifiers*/ undefined,
234                            /*asteriskToken*/ undefined,
235                            /*name*/ factory.createIdentifier("method"),
236                            /*questionToken*/ factory.createToken(SyntaxKind.QuestionToken),
237                            /*typeParameters*/ undefined,
238                            [],
239                            /*type*/ factory.createKeywordTypeNode(SyntaxKind.VoidKeyword),
240                            /*body*/ undefined
241                        ),
242                        factory.createPropertyDeclaration(
243                            /*decorators*/ undefined,
244                            /*modifiers*/ undefined,
245                            /*name*/ factory.createIdentifier("property"),
246                            /*questionToken*/ factory.createToken(SyntaxKind.QuestionToken),
247                            /*type*/ factory.createKeywordTypeNode(SyntaxKind.StringKeyword),
248                            /*initializer*/ undefined
249                        ),
250                    ]
251                ),
252                createSourceFile("source.ts", "", ScriptTarget.ES2015)
253            ));
254
255            // https://github.com/Microsoft/TypeScript/issues/15651
256            printsCorrectly("functionTypes", {}, printer => printer.printNode(
257                EmitHint.Unspecified,
258                setEmitFlags(factory.createTupleTypeNode([
259                    factory.createFunctionTypeNode(
260                        /*typeArguments*/ undefined,
261                        [factory.createParameterDeclaration(
262                            /*decorators*/ undefined,
263                            /*modifiers*/ undefined,
264                            /*dotDotDotToken*/ undefined,
265                            factory.createIdentifier("args")
266                        )],
267                        factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)
268                    ),
269                    factory.createFunctionTypeNode(
270                        [factory.createTypeParameterDeclaration("T")],
271                        [factory.createParameterDeclaration(
272                            /*decorators*/ undefined,
273                            /*modifiers*/ undefined,
274                            /*dotDotDotToken*/ undefined,
275                            factory.createIdentifier("args")
276                        )],
277                        factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)
278                    ),
279                    factory.createFunctionTypeNode(
280                        /*typeArguments*/ undefined,
281                        [factory.createParameterDeclaration(
282                            /*decorators*/ undefined,
283                            /*modifiers*/ undefined,
284                            factory.createToken(SyntaxKind.DotDotDotToken),
285                            factory.createIdentifier("args")
286                        )],
287                        factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)
288                    ),
289                    factory.createFunctionTypeNode(
290                        /*typeArguments*/ undefined,
291                        [factory.createParameterDeclaration(
292                            /*decorators*/ undefined,
293                            /*modifiers*/ undefined,
294                            /*dotDotDotToken*/ undefined,
295                            factory.createIdentifier("args"),
296                            factory.createToken(SyntaxKind.QuestionToken)
297                        )],
298                        factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)
299                    ),
300                    factory.createFunctionTypeNode(
301                        /*typeArguments*/ undefined,
302                        [factory.createParameterDeclaration(
303                            /*decorators*/ undefined,
304                            /*modifiers*/ undefined,
305                            /*dotDotDotToken*/ undefined,
306                            factory.createIdentifier("args"),
307                            /*questionToken*/ undefined,
308                            factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)
309                        )],
310                        factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)
311                    ),
312                    factory.createFunctionTypeNode(
313                        /*typeArguments*/ undefined,
314                        [factory.createParameterDeclaration(
315                            /*decorators*/ undefined,
316                            /*modifiers*/ undefined,
317                            /*dotDotDotToken*/ undefined,
318                            factory.createObjectBindingPattern([])
319                        )],
320                        factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)
321                    ),
322                ]), EmitFlags.SingleLine),
323                createSourceFile("source.ts", "", ScriptTarget.ES2015)
324            ));
325        });
326    });
327}
328