• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1namespace ts {
2    const caseInsensitiveBasePath = "c:/dev/";
3    const caseInsensitiveTsconfigPath = "c:/dev/tsconfig.json";
4    const caseInsensitiveHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ true, { cwd: caseInsensitiveBasePath, files: {
5        "c:/dev/a.ts": "",
6        "c:/dev/a.d.ts": "",
7        "c:/dev/a.js": "",
8        "c:/dev/b.ts": "",
9        "c:/dev/b.js": "",
10        "c:/dev/c.d.ts": "",
11        "c:/dev/z/a.ts": "",
12        "c:/dev/z/abz.ts": "",
13        "c:/dev/z/aba.ts": "",
14        "c:/dev/z/b.ts": "",
15        "c:/dev/z/bbz.ts": "",
16        "c:/dev/z/bba.ts": "",
17        "c:/dev/x/a.ts": "",
18        "c:/dev/x/aa.ts": "",
19        "c:/dev/x/b.ts": "",
20        "c:/dev/x/y/a.ts": "",
21        "c:/dev/x/y/b.ts": "",
22        "c:/dev/js/a.js": "",
23        "c:/dev/js/b.js": "",
24        "c:/dev/js/d.min.js": "",
25        "c:/dev/js/ab.min.js": "",
26        "c:/ext/ext.ts": "",
27        "c:/ext/b/a..b.ts": "",
28    }}));
29
30    const caseSensitiveBasePath = "/dev/";
31    const caseSensitiveHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ false, { cwd: caseSensitiveBasePath, files: {
32        "/dev/a.ts": "",
33        "/dev/a.d.ts": "",
34        "/dev/a.js": "",
35        "/dev/b.ts": "",
36        "/dev/b.js": "",
37        "/dev/A.ts": "",
38        "/dev/B.ts": "",
39        "/dev/c.d.ts": "",
40        "/dev/z/a.ts": "",
41        "/dev/z/abz.ts": "",
42        "/dev/z/aba.ts": "",
43        "/dev/z/b.ts": "",
44        "/dev/z/bbz.ts": "",
45        "/dev/z/bba.ts": "",
46        "/dev/x/a.ts": "",
47        "/dev/x/b.ts": "",
48        "/dev/x/y/a.ts": "",
49        "/dev/x/y/b.ts": "",
50        "/dev/q/a/c/b/d.ts": "",
51        "/dev/js/a.js": "",
52        "/dev/js/b.js": "",
53    }}));
54
55    const caseInsensitiveMixedExtensionHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ true, { cwd: caseInsensitiveBasePath, files: {
56        "c:/dev/a.ts": "",
57        "c:/dev/a.d.ts": "",
58        "c:/dev/a.js": "",
59        "c:/dev/b.tsx": "",
60        "c:/dev/b.d.ts": "",
61        "c:/dev/b.jsx": "",
62        "c:/dev/c.tsx": "",
63        "c:/dev/c.js": "",
64        "c:/dev/d.js": "",
65        "c:/dev/e.jsx": "",
66        "c:/dev/f.other": "",
67    }}));
68
69    const caseInsensitiveCommonFoldersHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ true, { cwd: caseInsensitiveBasePath, files: {
70        "c:/dev/a.ts": "",
71        "c:/dev/a.d.ts": "",
72        "c:/dev/a.js": "",
73        "c:/dev/b.ts": "",
74        "c:/dev/x/a.ts": "",
75        "c:/dev/node_modules/a.ts": "",
76        "c:/dev/bower_components/a.ts": "",
77        "c:/dev/jspm_packages/a.ts": "",
78    }}));
79
80    const caseInsensitiveDottedFoldersHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ true, { cwd: caseInsensitiveBasePath, files: {
81        "c:/dev/x/d.ts": "",
82        "c:/dev/x/y/d.ts": "",
83        "c:/dev/x/y/.e.ts": "",
84        "c:/dev/x/.y/a.ts": "",
85        "c:/dev/.z/.b.ts": "",
86        "c:/dev/.z/c.ts": "",
87        "c:/dev/w/.u/e.ts": "",
88        "c:/dev/g.min.js/.g/g.ts": "",
89    }}));
90
91    const caseInsensitiveOrderingDiffersWithCaseHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ true, { cwd: caseInsensitiveBasePath, files: {
92        "c:/dev/xylophone.ts": "",
93        "c:/dev/Yosemite.ts": "",
94        "c:/dev/zebra.ts": "",
95    }}));
96
97    const caseSensitiveOrderingDiffersWithCaseHost = new fakes.ParseConfigHost(new vfs.FileSystem(/*ignoreCase*/ false, { cwd: caseSensitiveBasePath, files: {
98        "/dev/xylophone.ts": "",
99        "/dev/Yosemite.ts": "",
100        "/dev/zebra.ts": "",
101    }}));
102
103    function assertParsed(actual: ParsedCommandLine, expected: ParsedCommandLine): void {
104        assert.deepEqual(actual.fileNames, expected.fileNames);
105        assert.deepEqual(actual.wildcardDirectories, expected.wildcardDirectories);
106        assert.deepEqual(actual.errors, expected.errors);
107    }
108
109    function validateMatches(expected: ParsedCommandLine, json: any, host: ParseConfigHost, basePath: string, existingOptions?: CompilerOptions, configFileName?: string, resolutionStack?: Path[]) {
110        {
111            const jsonText = JSON.stringify(json);
112            const result = parseJsonText(caseInsensitiveTsconfigPath, jsonText);
113            const actual = parseJsonSourceFileConfigFileContent(result, host, basePath, existingOptions, configFileName, resolutionStack);
114            for (const error of expected.errors) {
115                if (error.file) {
116                    error.file = result;
117                }
118            }
119            assertParsed(actual, expected);
120        }
121        {
122            const actual = parseJsonConfigFileContent(json, host, basePath, existingOptions, configFileName, resolutionStack);
123            expected.errors = expected.errors.map((error): Diagnostic => ({
124                category: error.category,
125                code: error.code,
126                file: undefined,
127                length: undefined,
128                messageText: error.messageText,
129                start: undefined,
130                reportsUnnecessary: undefined,
131                reportsDeprecated: undefined
132            }));
133            assertParsed(actual, expected);
134        }
135    }
136
137    function createDiagnosticForConfigFile(json: any, start: number, length: number, diagnosticMessage: DiagnosticMessage, arg0: string) {
138        const text = JSON.stringify(json);
139        const file = {
140            fileName: caseInsensitiveTsconfigPath,
141            kind: SyntaxKind.SourceFile,
142            text
143        } as SourceFile;
144        return createFileDiagnostic(file, start, length, diagnosticMessage, arg0);
145    }
146
147    describe("unittests:: config:: matchFiles", () => {
148        it("with defaults", () => {
149            const json = {};
150            const expected: ParsedCommandLine = {
151                options: {},
152                errors: [],
153                fileNames: [
154                    "c:/dev/a.ts",
155                    "c:/dev/b.ts",
156                    "c:/dev/x/a.ts"
157                ],
158                wildcardDirectories: {
159                    "c:/dev": WatchDirectoryFlags.Recursive
160                },
161            };
162            validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
163        });
164
165        describe("with literal file list", () => {
166            it("without exclusions", () => {
167                const json = {
168                    files: [
169                        "a.ts",
170                        "b.ts"
171                    ]
172                };
173                const expected: ParsedCommandLine = {
174                    options: {},
175                    errors: [],
176                    fileNames: [
177                        "c:/dev/a.ts",
178                        "c:/dev/b.ts"
179                    ],
180                    wildcardDirectories: {},
181                };
182                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
183            });
184            it("missing files are still present", () => {
185                const json = {
186                    files: [
187                        "z.ts",
188                        "x.ts"
189                    ]
190                };
191                const expected: ParsedCommandLine = {
192                    options: {},
193                    errors: [],
194                    fileNames: [
195                        "c:/dev/z.ts",
196                        "c:/dev/x.ts"
197                    ],
198                    wildcardDirectories: {},
199                };
200                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
201            });
202            it("are not removed due to excludes", () => {
203                const json = {
204                    files: [
205                        "a.ts",
206                        "b.ts"
207                    ],
208                    exclude: [
209                        "b.ts"
210                    ]
211                };
212                const expected: ParsedCommandLine = {
213                    options: {},
214                    errors: [],
215                    fileNames: [
216                        "c:/dev/a.ts",
217                        "c:/dev/b.ts"
218                    ],
219                    wildcardDirectories: {},
220                };
221                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
222            });
223        });
224
225        describe("with literal include list", () => {
226            it("without exclusions", () => {
227                const json = {
228                    include: [
229                        "a.ts",
230                        "b.ts"
231                    ]
232                };
233                const expected: ParsedCommandLine = {
234                    options: {},
235                    errors: [],
236                    fileNames: [
237                        "c:/dev/a.ts",
238                        "c:/dev/b.ts"
239                    ],
240                    wildcardDirectories: {},
241                };
242                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
243            });
244            it("with non .ts file extensions are excluded", () => {
245                const json = {
246                    include: [
247                        "a.js",
248                        "b.js"
249                    ]
250                };
251                const expected: ParsedCommandLine = {
252                    options: {},
253                    errors: [
254                        createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
255                            caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]")
256                    ],
257                    fileNames: [],
258                    wildcardDirectories: {},
259                };
260                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
261            });
262            it("with missing files are excluded", () => {
263                const json = {
264                    include: [
265                        "z.ts",
266                        "x.ts"
267                    ]
268                };
269                const expected: ParsedCommandLine = {
270                    options: {},
271                    errors: [
272                        createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
273                            caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]")
274                    ],
275                    fileNames: [],
276                    wildcardDirectories: {},
277                };
278                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
279            });
280            it("with literal excludes", () => {
281                const json = {
282                    include: [
283                        "a.ts",
284                        "b.ts"
285                    ],
286                    exclude: [
287                        "b.ts"
288                    ]
289                };
290                const expected: ParsedCommandLine = {
291                    options: {},
292                    errors: [],
293                    fileNames: [
294                        "c:/dev/a.ts"
295                    ],
296                    wildcardDirectories: {},
297                };
298                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
299            });
300            it("with wildcard excludes", () => {
301                const json = {
302                    include: [
303                        "a.ts",
304                        "b.ts",
305                        "z/a.ts",
306                        "z/abz.ts",
307                        "z/aba.ts",
308                        "x/b.ts"
309                    ],
310                    exclude: [
311                        "*.ts",
312                        "z/??z.ts",
313                        "*/b.ts"
314                    ]
315                };
316                const expected: ParsedCommandLine = {
317                    options: {},
318                    errors: [],
319                    fileNames: [
320                        "c:/dev/z/a.ts",
321                        "c:/dev/z/aba.ts"
322                    ],
323                    wildcardDirectories: {},
324                };
325                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
326            });
327            it("with recursive excludes", () => {
328                const json = {
329                    include: [
330                        "a.ts",
331                        "b.ts",
332                        "x/a.ts",
333                        "x/b.ts",
334                        "x/y/a.ts",
335                        "x/y/b.ts"
336                    ],
337                    exclude: [
338                        "**/b.ts"
339                    ]
340                };
341                const expected: ParsedCommandLine = {
342                    options: {},
343                    errors: [],
344                    fileNames: [
345                        "c:/dev/a.ts",
346                        "c:/dev/x/a.ts",
347                        "c:/dev/x/y/a.ts"
348                    ],
349                    wildcardDirectories: {},
350                };
351                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
352            });
353            it("with case sensitive exclude", () => {
354                const json = {
355                    include: [
356                        "B.ts"
357                    ],
358                    exclude: [
359                        "**/b.ts"
360                    ]
361                };
362                const expected: ParsedCommandLine = {
363                    options: {},
364                    errors: [],
365                    fileNames: [
366                        "/dev/B.ts"
367                    ],
368                    wildcardDirectories: {},
369                };
370                validateMatches(expected, json, caseSensitiveHost, caseSensitiveBasePath);
371            });
372            it("with common package folders and no exclusions", () => {
373                const json = {
374                    include: [
375                        "a.ts",
376                        "b.ts",
377                        "node_modules/a.ts",
378                        "bower_components/a.ts",
379                        "jspm_packages/a.ts"
380                    ]
381                };
382                const expected: ParsedCommandLine = {
383                    options: {},
384                    errors: [],
385                    fileNames: [
386                        "c:/dev/a.ts",
387                        "c:/dev/b.ts",
388                        "c:/dev/node_modules/a.ts",
389                        "c:/dev/bower_components/a.ts",
390                        "c:/dev/jspm_packages/a.ts"
391                    ],
392                    wildcardDirectories: {},
393                };
394                validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
395            });
396            it("with common package folders and exclusions", () => {
397                const json = {
398                    include: [
399                        "a.ts",
400                        "b.ts",
401                        "node_modules/a.ts",
402                        "bower_components/a.ts",
403                        "jspm_packages/a.ts"
404                    ],
405                    exclude: [
406                        "a.ts",
407                        "b.ts"
408                    ]
409                };
410                const expected: ParsedCommandLine = {
411                    options: {},
412                    errors: [],
413                    fileNames: [
414                        "c:/dev/node_modules/a.ts",
415                        "c:/dev/bower_components/a.ts",
416                        "c:/dev/jspm_packages/a.ts"
417                    ],
418                    wildcardDirectories: {},
419                };
420                validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
421            });
422            it("with common package folders and empty exclude", () => {
423                const json = {
424                    include: [
425                        "a.ts",
426                        "b.ts",
427                        "node_modules/a.ts",
428                        "bower_components/a.ts",
429                        "jspm_packages/a.ts"
430                    ]
431                };
432                const expected: ParsedCommandLine = {
433                    options: {},
434                    errors: [],
435                    fileNames: [
436                        "c:/dev/a.ts",
437                        "c:/dev/b.ts",
438                        "c:/dev/node_modules/a.ts",
439                        "c:/dev/bower_components/a.ts",
440                        "c:/dev/jspm_packages/a.ts"
441                    ],
442                    wildcardDirectories: {},
443                };
444                validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
445            });
446        });
447
448        describe("with wildcard include list", () => {
449            it("is sorted in include order, then in alphabetical order", () => {
450                const json = {
451                    include: [
452                        "z/*.ts",
453                        "x/*.ts"
454                    ]
455                };
456                const expected: ParsedCommandLine = {
457                    options: {},
458                    errors: [],
459                    fileNames: [
460                        "c:/dev/z/a.ts",
461                        "c:/dev/z/aba.ts",
462                        "c:/dev/z/abz.ts",
463                        "c:/dev/z/b.ts",
464                        "c:/dev/z/bba.ts",
465                        "c:/dev/z/bbz.ts",
466                        "c:/dev/x/a.ts",
467                        "c:/dev/x/aa.ts",
468                        "c:/dev/x/b.ts"
469                    ],
470                    wildcardDirectories: {
471                        "c:/dev/z": WatchDirectoryFlags.None,
472                        "c:/dev/x": WatchDirectoryFlags.None
473                    },
474                };
475                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
476            });
477            it("same named declarations are excluded", () => {
478                const json = {
479                    include: [
480                        "*.ts"
481                    ]
482                };
483                const expected: ParsedCommandLine = {
484                    options: {},
485                    errors: [],
486                    fileNames: [
487                        "c:/dev/a.ts",
488                        "c:/dev/b.ts",
489                        "c:/dev/c.d.ts"
490                    ],
491                    wildcardDirectories: {
492                        "c:/dev": WatchDirectoryFlags.None
493                    },
494                };
495                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
496            });
497            it("`*` matches only ts files", () => {
498                const json = {
499                    include: [
500                        "*"
501                    ]
502                };
503                const expected: ParsedCommandLine = {
504                    options: {},
505                    errors: [],
506                    fileNames: [
507                        "c:/dev/a.ts",
508                        "c:/dev/b.ts",
509                        "c:/dev/c.d.ts"
510                    ],
511                    wildcardDirectories: {
512                        "c:/dev": WatchDirectoryFlags.None
513                    },
514                };
515                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
516            });
517            it("`?` matches only a single character", () => {
518                const json = {
519                    include: [
520                        "x/?.ts"
521                    ]
522                };
523                const expected: ParsedCommandLine = {
524                    options: {},
525                    errors: [],
526                    fileNames: [
527                        "c:/dev/x/a.ts",
528                        "c:/dev/x/b.ts"
529                    ],
530                    wildcardDirectories: {
531                        "c:/dev/x": WatchDirectoryFlags.None
532                    },
533                };
534                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
535            });
536            it("with recursive directory", () => {
537                const json = {
538                    include: [
539                        "**/a.ts"
540                    ]
541                };
542                const expected: ParsedCommandLine = {
543                    options: {},
544                    errors: [],
545                    fileNames: [
546                        "c:/dev/a.ts",
547                        "c:/dev/x/a.ts",
548                        "c:/dev/x/y/a.ts",
549                        "c:/dev/z/a.ts"
550                    ],
551                    wildcardDirectories: {
552                        "c:/dev": WatchDirectoryFlags.Recursive
553                    },
554                };
555                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
556            });
557            it("with multiple recursive directories", () => {
558                const json = {
559                    include: [
560                        "x/y/**/a.ts",
561                        "x/**/a.ts",
562                        "z/**/a.ts"
563                    ]
564                };
565                const expected: ParsedCommandLine = {
566                    options: {},
567                    errors: [],
568                    fileNames: [
569                        "c:/dev/x/y/a.ts",
570                        "c:/dev/x/a.ts",
571                        "c:/dev/z/a.ts"
572                    ],
573                    wildcardDirectories: {
574                        "c:/dev/x": WatchDirectoryFlags.Recursive,
575                        "c:/dev/z": WatchDirectoryFlags.Recursive
576                    },
577                };
578                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
579            });
580            it("case sensitive", () => {
581                const json = {
582                    include: [
583                        "**/A.ts"
584                    ]
585                };
586                const expected: ParsedCommandLine = {
587                    options: {},
588                    errors: [],
589                    fileNames: [
590                        "/dev/A.ts"
591                    ],
592                    wildcardDirectories: {
593                        "/dev": WatchDirectoryFlags.Recursive
594                    },
595                };
596                validateMatches(expected, json, caseSensitiveHost, caseSensitiveBasePath);
597            });
598            it("with missing files are excluded", () => {
599                const json = {
600                    include: [
601                        "*/z.ts"
602                    ]
603                };
604                const expected: ParsedCommandLine = {
605                    options: {},
606                    errors: [
607                        createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
608                            caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]")
609                    ],
610                    fileNames: [],
611                    wildcardDirectories: {
612                        "c:/dev": WatchDirectoryFlags.Recursive
613                    },
614                };
615                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
616            });
617            it("always include literal files", () => {
618                const json = {
619                    files: [
620                        "a.ts"
621                    ],
622                    include: [
623                        "*/z.ts"
624                    ],
625                    exclude: [
626                        "**/a.ts"
627                    ]
628                };
629                const expected: ParsedCommandLine = {
630                    options: {},
631                    errors: [],
632                    fileNames: [
633                        "c:/dev/a.ts"
634                    ],
635                    wildcardDirectories: {
636                        "c:/dev": WatchDirectoryFlags.Recursive
637                    },
638                };
639                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
640            });
641            it("exclude folders", () => {
642                const json = {
643                    include: [
644                        "**/*"
645                    ],
646                    exclude: [
647                        "z",
648                        "x"
649                    ]
650                };
651                const expected: ParsedCommandLine = {
652                    options: {},
653                    errors: [],
654                    fileNames: [
655                        "c:/dev/a.ts",
656                        "c:/dev/b.ts",
657                        "c:/dev/c.d.ts"
658                    ],
659                    wildcardDirectories: {
660                        "c:/dev": WatchDirectoryFlags.Recursive
661                    }
662                };
663                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
664            });
665            describe("with common package folders", () => {
666                it("and no exclusions", () => {
667                    const json = {
668                        include: [
669                            "**/a.ts"
670                        ]
671                    };
672                    const expected: ParsedCommandLine = {
673                        options: {},
674                        errors: [],
675                        fileNames: [
676                            "c:/dev/a.ts",
677                            "c:/dev/x/a.ts"
678                        ],
679                        wildcardDirectories: {
680                            "c:/dev": WatchDirectoryFlags.Recursive
681                        },
682                    };
683                    validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
684                });
685                it("and exclusions", () => {
686                    const json = {
687                        include: [
688                            "**/?.ts"
689                        ],
690                        exclude: [
691                            "a.ts"
692                        ]
693                    };
694                    const expected: ParsedCommandLine = {
695                        options: {},
696                        errors: [],
697                        fileNames: [
698                            "c:/dev/b.ts",
699                            "c:/dev/x/a.ts"
700                        ],
701                        wildcardDirectories: {
702                            "c:/dev": WatchDirectoryFlags.Recursive
703                        },
704                    };
705                    validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
706                });
707                it("and empty exclude", () => {
708                    const json = {
709                        include: [
710                            "**/a.ts"
711                        ],
712                        exclude: [] as string[]
713                    };
714                    const expected: ParsedCommandLine = {
715                        options: {},
716                        errors: [],
717                        fileNames: [
718                            "c:/dev/a.ts",
719                            "c:/dev/x/a.ts"
720                        ],
721                        wildcardDirectories: {
722                            "c:/dev": WatchDirectoryFlags.Recursive
723                        },
724                    };
725                    validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
726                });
727                it("and explicit recursive include", () => {
728                    const json = {
729                        include: [
730                            "**/a.ts",
731                            "**/node_modules/a.ts"
732                        ]
733                    };
734                    const expected: ParsedCommandLine = {
735                        options: {},
736                        errors: [],
737                        fileNames: [
738                            "c:/dev/a.ts",
739                            "c:/dev/x/a.ts",
740                            "c:/dev/node_modules/a.ts"
741                        ],
742                        wildcardDirectories: {
743                            "c:/dev": WatchDirectoryFlags.Recursive
744                        },
745                    };
746                    validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
747                });
748                it("and wildcard include", () => {
749                    const json = {
750                        include: [
751                            "*/a.ts"
752                        ]
753                    };
754                    const expected: ParsedCommandLine = {
755                        options: {},
756                        errors: [],
757                        fileNames: [
758                            "c:/dev/x/a.ts"
759                        ],
760                        wildcardDirectories: {
761                            "c:/dev": WatchDirectoryFlags.Recursive
762                        },
763                    };
764                    validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
765                });
766                it("and explicit wildcard include", () => {
767                    const json = {
768                        include: [
769                            "*/a.ts",
770                            "node_modules/a.ts"
771                        ]
772                    };
773                    const expected: ParsedCommandLine = {
774                        options: {},
775                        errors: [],
776                        fileNames: [
777                            "c:/dev/x/a.ts",
778                            "c:/dev/node_modules/a.ts"
779                        ],
780                        wildcardDirectories: {
781                            "c:/dev": WatchDirectoryFlags.Recursive
782                        },
783                    };
784                    validateMatches(expected, json, caseInsensitiveCommonFoldersHost, caseInsensitiveBasePath);
785                });
786            });
787            it("exclude .js files when allowJs=false", () => {
788                const json = {
789                    compilerOptions: {
790                        allowJs: false
791                    },
792                    include: [
793                        "js/*"
794                    ]
795                };
796                const expected: ParsedCommandLine = {
797                    options: {
798                        allowJs: false
799                    },
800                    errors: [
801                        createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
802                            caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]")
803                    ],
804                    fileNames: [],
805                    wildcardDirectories: {
806                        "c:/dev/js": WatchDirectoryFlags.None
807                    }
808                };
809                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
810            });
811            it("include .js files when allowJs=true", () => {
812                const json = {
813                    compilerOptions: {
814                        allowJs: true
815                    },
816                    include: [
817                        "js/*"
818                    ]
819                };
820                const expected: ParsedCommandLine = {
821                    options: {
822                        allowJs: true
823                    },
824                    errors: [],
825                    fileNames: [
826                        "c:/dev/js/a.js",
827                        "c:/dev/js/b.js"
828                    ],
829                    wildcardDirectories: {
830                        "c:/dev/js": WatchDirectoryFlags.None
831                    }
832                };
833                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
834            });
835            it("include explicitly listed .min.js files when allowJs=true", () => {
836                const json = {
837                    compilerOptions: {
838                        allowJs: true
839                    },
840                    include: [
841                        "js/*.min.js"
842                    ]
843                };
844                const expected: ParsedCommandLine = {
845                    options: {
846                        allowJs: true
847                    },
848                    errors: [],
849                    fileNames: [
850                        "c:/dev/js/ab.min.js",
851                        "c:/dev/js/d.min.js"
852                    ],
853                    wildcardDirectories: {
854                        "c:/dev/js": WatchDirectoryFlags.None
855                    }
856                };
857                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
858            });
859            it("include paths outside of the project", () => {
860                const json = {
861                    include: [
862                        "*",
863                        "c:/ext/*"
864                    ]
865                };
866                const expected: ParsedCommandLine = {
867                    options: {},
868                    errors: [],
869                    fileNames: [
870                        "c:/dev/a.ts",
871                        "c:/dev/b.ts",
872                        "c:/dev/c.d.ts",
873                        "c:/ext/ext.ts"
874                    ],
875                    wildcardDirectories: {
876                        "c:/dev": WatchDirectoryFlags.None,
877                        "c:/ext": WatchDirectoryFlags.None
878                    }
879                };
880                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
881            });
882            it("include paths outside of the project using relative paths", () => {
883                const json = {
884                    include: [
885                        "*",
886                        "../ext/*"
887                    ],
888                    exclude: [
889                        "**"
890                    ]
891                };
892                const expected: ParsedCommandLine = {
893                    options: {},
894                    errors: [],
895                    fileNames: [
896                        "c:/ext/ext.ts"
897                    ],
898                    wildcardDirectories: {
899                        "c:/ext": WatchDirectoryFlags.None
900                    }
901                };
902                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
903            });
904            it("exclude paths outside of the project using relative paths", () => {
905                const json = {
906                    include: [
907                        "c:/**/*"
908                    ],
909                    exclude: [
910                        "../**"
911                    ]
912                };
913                const expected: ParsedCommandLine = {
914                    options: {},
915                    errors: [
916                        createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
917                            caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(json.exclude))]
918                    ,
919                    fileNames: [],
920                    wildcardDirectories: {}
921                };
922                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
923            });
924            it("include files with .. in their name", () => {
925                const json = {
926                    include: [
927                        "c:/ext/b/a..b.ts"
928                    ],
929                    exclude: [
930                        "**"
931                    ]
932                };
933                const expected: ParsedCommandLine = {
934                    options: {},
935                    errors: [],
936                    fileNames: [
937                        "c:/ext/b/a..b.ts"
938                    ],
939                    wildcardDirectories: {}
940                };
941                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
942            });
943            it("exclude files with .. in their name", () => {
944                const json = {
945                    include: [
946                        "c:/ext/**/*"
947                    ],
948                    exclude: [
949                        "c:/ext/b/a..b.ts"
950                    ]
951                };
952                const expected: ParsedCommandLine = {
953                    options: {},
954                    errors: [],
955                    fileNames: [
956                        "c:/ext/ext.ts",
957                    ],
958                    wildcardDirectories: {
959                        "c:/ext": WatchDirectoryFlags.Recursive
960                    }
961                };
962                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
963            });
964            it("with jsx=none, allowJs=false", () => {
965                const json = {
966                    compilerOptions: {
967                        allowJs: false
968                    }
969                };
970                const expected: ParsedCommandLine = {
971                    options: {
972                        allowJs: false
973                    },
974                    errors: [],
975                    fileNames: [
976                        "c:/dev/a.ts",
977                        "c:/dev/b.tsx",
978                        "c:/dev/c.tsx",
979                    ],
980                    wildcardDirectories: {
981                        "c:/dev": WatchDirectoryFlags.Recursive
982                    }
983                };
984                validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
985            });
986            it("with jsx=preserve, allowJs=false", () => {
987                const json = {
988                    compilerOptions: {
989                        jsx: "preserve",
990                        allowJs: false
991                    }
992                };
993                const expected: ParsedCommandLine = {
994                    options: {
995                        jsx: JsxEmit.Preserve,
996                        allowJs: false
997                    },
998                    errors: [],
999                    fileNames: [
1000                        "c:/dev/a.ts",
1001                        "c:/dev/b.tsx",
1002                        "c:/dev/c.tsx",
1003                    ],
1004                    wildcardDirectories: {
1005                        "c:/dev": WatchDirectoryFlags.Recursive
1006                    }
1007                };
1008                validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
1009            });
1010            it("with jsx=react-native, allowJs=false", () => {
1011                const json = {
1012                    compilerOptions: {
1013                        jsx: "react-native",
1014                        allowJs: false
1015                    }
1016                };
1017                const expected: ParsedCommandLine = {
1018                    options: {
1019                        jsx: JsxEmit.ReactNative,
1020                        allowJs: false
1021                    },
1022                    errors: [],
1023                    fileNames: [
1024                        "c:/dev/a.ts",
1025                        "c:/dev/b.tsx",
1026                        "c:/dev/c.tsx",
1027                    ],
1028                    wildcardDirectories: {
1029                        "c:/dev": WatchDirectoryFlags.Recursive
1030                    }
1031                };
1032                validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
1033            });
1034            it("with jsx=none, allowJs=true", () => {
1035                const json = {
1036                    compilerOptions: {
1037                        allowJs: true
1038                    }
1039                };
1040                const expected: ParsedCommandLine = {
1041                    options: {
1042                        allowJs: true
1043                    },
1044                    errors: [],
1045                    fileNames: [
1046                        "c:/dev/a.ts",
1047                        "c:/dev/b.tsx",
1048                        "c:/dev/c.tsx",
1049                        "c:/dev/d.js",
1050                        "c:/dev/e.jsx",
1051                    ],
1052                    wildcardDirectories: {
1053                        "c:/dev": WatchDirectoryFlags.Recursive
1054                    }
1055                };
1056                validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
1057            });
1058            it("with jsx=preserve, allowJs=true", () => {
1059                const json = {
1060                    compilerOptions: {
1061                        jsx: "preserve",
1062                        allowJs: true
1063                    }
1064                };
1065                const expected: ParsedCommandLine = {
1066                    options: {
1067                        jsx: JsxEmit.Preserve,
1068                        allowJs: true
1069                    },
1070                    errors: [],
1071                    fileNames: [
1072                        "c:/dev/a.ts",
1073                        "c:/dev/b.tsx",
1074                        "c:/dev/c.tsx",
1075                        "c:/dev/d.js",
1076                        "c:/dev/e.jsx",
1077                    ],
1078                    wildcardDirectories: {
1079                        "c:/dev": WatchDirectoryFlags.Recursive
1080                    }
1081                };
1082                validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
1083            });
1084            it("with jsx=react-native, allowJs=true", () => {
1085                const json = {
1086                    compilerOptions: {
1087                        jsx: "react-native",
1088                        allowJs: true
1089                    }
1090                };
1091                const expected: ParsedCommandLine = {
1092                    options: {
1093                        jsx: JsxEmit.ReactNative,
1094                        allowJs: true
1095                    },
1096                    errors: [],
1097                    fileNames: [
1098                        "c:/dev/a.ts",
1099                        "c:/dev/b.tsx",
1100                        "c:/dev/c.tsx",
1101                        "c:/dev/d.js",
1102                        "c:/dev/e.jsx",
1103                    ],
1104                    wildcardDirectories: {
1105                        "c:/dev": WatchDirectoryFlags.Recursive
1106                    }
1107                };
1108                validateMatches(expected, json, caseInsensitiveMixedExtensionHost, caseInsensitiveBasePath);
1109            });
1110            it("exclude .min.js files using wildcards", () => {
1111                const json = {
1112                    compilerOptions: {
1113                        allowJs: true
1114                    },
1115                    include: [
1116                        "js/*.min.js"
1117                    ],
1118                    exclude: [
1119                        "js/a*"
1120                    ]
1121                };
1122                const expected: ParsedCommandLine = {
1123                    options: {
1124                        allowJs: true
1125                    },
1126                    errors: [],
1127                    fileNames: [
1128                        "c:/dev/js/d.min.js"
1129                    ],
1130                    wildcardDirectories: {
1131                        "c:/dev/js": WatchDirectoryFlags.None
1132                    }
1133                };
1134                validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
1135            });
1136
1137            describe("with trailing recursive directory", () => {
1138                it("in includes", () => {
1139                    const json = {
1140                        include: [
1141                            "**"
1142                        ]
1143                    };
1144                    const expected: ParsedCommandLine = {
1145                        options: {},
1146                        errors: [
1147                            createDiagnosticForConfigFile(json, 12, 4, Diagnostics.File_specification_cannot_end_in_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**"),
1148                            createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
1149                                caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]")
1150                        ],
1151                        fileNames: [],
1152                        wildcardDirectories: {}
1153                    };
1154                    validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
1155                });
1156                it("in excludes", () => {
1157                    const json = {
1158                        include: [
1159                            "**/*"
1160                        ],
1161                        exclude: [
1162                            "**"
1163                        ]
1164                    };
1165                    const expected: ParsedCommandLine = {
1166                        options: {},
1167                        errors: [
1168                            createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
1169                                caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(json.exclude))
1170                        ],
1171                        fileNames: [],
1172                        wildcardDirectories: {}
1173                    };
1174                    validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
1175                });
1176            });
1177            describe("with multiple recursive directory patterns", () => {
1178                it("in includes", () => {
1179                    const json = {
1180                        include: [
1181                            "**/x/**/*"
1182                        ]
1183                    };
1184                    const expected: ParsedCommandLine = {
1185                        options: {},
1186                        errors: [],
1187                        fileNames: [
1188                            "c:/dev/x/a.ts",
1189                            "c:/dev/x/aa.ts",
1190                            "c:/dev/x/b.ts",
1191                            "c:/dev/x/y/a.ts",
1192                            "c:/dev/x/y/b.ts",
1193                        ],
1194                        wildcardDirectories: {
1195                            "c:/dev": WatchDirectoryFlags.Recursive
1196                        }
1197                    };
1198                    validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
1199                });
1200                it("in excludes", () => {
1201                    const json = {
1202                        include: [
1203                            "**/a.ts"
1204                        ],
1205                        exclude: [
1206                            "**/x/**"
1207                        ]
1208                    };
1209                    const expected: ParsedCommandLine = {
1210                        options: {},
1211                        errors: [],
1212                        fileNames: [
1213                            "c:/dev/a.ts",
1214                            "c:/dev/z/a.ts"
1215                        ],
1216                        wildcardDirectories: {
1217                            "c:/dev": WatchDirectoryFlags.Recursive
1218                        }
1219                    };
1220                    validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
1221                });
1222            });
1223
1224            describe("with parent directory symbols after a recursive directory pattern", () => {
1225                it("in includes immediately after", () => {
1226                    const json = {
1227                        include: [
1228                            "**/../*"
1229                        ]
1230                    };
1231                    const expected: ParsedCommandLine = {
1232                        options: {},
1233                        errors: [
1234                            createDiagnosticForConfigFile(json, 12, 9, Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/../*"),
1235                            createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
1236                                caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]")
1237                        ],
1238                        fileNames: [],
1239                        wildcardDirectories: {}
1240                    };
1241                    validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
1242                });
1243
1244                it("in includes after a subdirectory", () => {
1245                    const json = {
1246                        include: [
1247                            "**/y/../*"
1248                        ]
1249                    };
1250                    const expected: ParsedCommandLine = {
1251                        options: {},
1252                        errors: [
1253                            createDiagnosticForConfigFile(json, 12, 11, Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/../*"),
1254                            createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
1255                                caseInsensitiveTsconfigPath, JSON.stringify(json.include), "[]")
1256                        ],
1257                        fileNames: [],
1258                        wildcardDirectories: {}
1259                    };
1260                    validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
1261                });
1262
1263                it("in excludes immediately after", () => {
1264                    const json = {
1265                        include: [
1266                            "**/a.ts"
1267                        ],
1268                        exclude: [
1269                            "**/.."
1270                        ]
1271                    };
1272                    const expected: ParsedCommandLine = {
1273                        options: {},
1274                        errors: [
1275                            createDiagnosticForConfigFile(json, 34, 7, Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/..")
1276                        ],
1277                        fileNames: [
1278                            "c:/dev/a.ts",
1279                            "c:/dev/x/a.ts",
1280                            "c:/dev/x/y/a.ts",
1281                            "c:/dev/z/a.ts"
1282                        ],
1283                        wildcardDirectories: {
1284                            "c:/dev": WatchDirectoryFlags.Recursive
1285                        }
1286                    };
1287                    validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
1288                });
1289
1290                it("in excludes after a subdirectory", () => {
1291                    const json = {
1292                        include: [
1293                            "**/a.ts"
1294                        ],
1295                        exclude: [
1296                            "**/y/.."
1297                        ]
1298                    };
1299                    const expected: ParsedCommandLine = {
1300                        options: {},
1301                        errors: [
1302                            createDiagnosticForConfigFile(json, 34, 9, Diagnostics.File_specification_cannot_contain_a_parent_directory_that_appears_after_a_recursive_directory_wildcard_Asterisk_Asterisk_Colon_0, "**/y/..")
1303                        ],
1304                        fileNames: [
1305                            "c:/dev/a.ts",
1306                            "c:/dev/x/a.ts",
1307                            "c:/dev/x/y/a.ts",
1308                            "c:/dev/z/a.ts"
1309                        ],
1310                        wildcardDirectories: {
1311                            "c:/dev": WatchDirectoryFlags.Recursive
1312                        }
1313                    };
1314                    validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
1315                });
1316            });
1317
1318            describe("with implicit globbification", () => {
1319                it("Expands 'z' to 'z/**/*'", () => {
1320                    const json = {
1321                        include: ["z"]
1322                    };
1323                    const expected: ParsedCommandLine = {
1324                        options: {},
1325                        errors: [],
1326                        fileNames: [ "a.ts", "aba.ts", "abz.ts", "b.ts", "bba.ts", "bbz.ts" ].map(x => `c:/dev/z/${x}`),
1327                        wildcardDirectories: {
1328                            "c:/dev/z": WatchDirectoryFlags.Recursive
1329                        }
1330                    };
1331                    validateMatches(expected, json, caseInsensitiveHost, caseInsensitiveBasePath);
1332                });
1333            });
1334        });
1335
1336        describe("with files or folders that begin with a .", () => {
1337            it("that are not explicitly included", () => {
1338                const json = {
1339                    include: [
1340                        "x/**/*",
1341                        "w/*/*"
1342                    ]
1343                };
1344                const expected: ParsedCommandLine = {
1345                    options: {},
1346                    errors: [],
1347                    fileNames: [
1348                        "c:/dev/x/d.ts",
1349                        "c:/dev/x/y/d.ts",
1350                    ],
1351                    wildcardDirectories: {
1352                        "c:/dev/x": WatchDirectoryFlags.Recursive,
1353                        "c:/dev/w": WatchDirectoryFlags.Recursive
1354                    }
1355                };
1356                validateMatches(expected, json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
1357            });
1358            describe("that are explicitly included", () => {
1359                it("without wildcards", () => {
1360                    const json = {
1361                        include: [
1362                            "x/.y/a.ts",
1363                            "c:/dev/.z/.b.ts"
1364                        ]
1365                    };
1366                    const expected: ParsedCommandLine = {
1367                        options: {},
1368                        errors: [],
1369                        fileNames: [
1370                            "c:/dev/x/.y/a.ts",
1371                            "c:/dev/.z/.b.ts"
1372                        ],
1373                        wildcardDirectories: {}
1374                    };
1375                    validateMatches(expected, json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
1376                });
1377                it("with recursive wildcards that match directories", () => {
1378                    const json = {
1379                        include: [
1380                            "**/.*/*"
1381                        ]
1382                    };
1383                    const expected: ParsedCommandLine = {
1384                        options: {},
1385                        errors: [],
1386                        fileNames: [
1387                            "c:/dev/.z/c.ts",
1388                            "c:/dev/g.min.js/.g/g.ts",
1389                            "c:/dev/w/.u/e.ts",
1390                            "c:/dev/x/.y/a.ts"
1391                        ],
1392                        wildcardDirectories: {
1393                            "c:/dev": WatchDirectoryFlags.Recursive
1394                        }
1395                    };
1396                    validateMatches(expected, json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
1397                });
1398                it("with recursive wildcards that match nothing", () => {
1399                    const json = {
1400                        include: [
1401                            "x/**/.y/*",
1402                            ".z/**/.*"
1403                        ]
1404                    };
1405                    const expected: ParsedCommandLine = {
1406                        options: {},
1407                        errors: [],
1408                        fileNames: [
1409                            "c:/dev/x/.y/a.ts",
1410                            "c:/dev/.z/.b.ts"
1411                        ],
1412                        wildcardDirectories: {
1413                            "c:/dev/.z": WatchDirectoryFlags.Recursive,
1414                            "c:/dev/x": WatchDirectoryFlags.Recursive
1415                        }
1416                    };
1417                    validateMatches(expected, json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath);
1418                });
1419                it("with wildcard excludes that implicitly exclude dotted files", () => {
1420                    const json = {
1421                        include: [
1422                            "**/.*/*"
1423                        ],
1424                        exclude: [
1425                            "**/*"
1426                        ]
1427                    };
1428                    const expected: ParsedCommandLine = {
1429                        options: {},
1430                        errors: [
1431                            createCompilerDiagnostic(Diagnostics.No_inputs_were_found_in_config_file_0_Specified_include_paths_were_1_and_exclude_paths_were_2,
1432                                caseInsensitiveTsconfigPath, JSON.stringify(json.include), JSON.stringify(json.exclude))
1433                        ],
1434                        fileNames: [],
1435                        wildcardDirectories: {}
1436                    };
1437                    validateMatches(expected, json, caseInsensitiveDottedFoldersHost, caseInsensitiveBasePath, /*existingOptions*/ undefined, caseInsensitiveTsconfigPath);
1438                });
1439            });
1440        });
1441
1442        describe("exclude or include patterns which start with **", () => {
1443            it("can exclude dirs whose pattern starts with **", () => {
1444                const json = {
1445                    exclude: [
1446                        "**/x"
1447                    ]
1448                };
1449                const expected: ParsedCommandLine = {
1450                    options: {},
1451                    errors: [],
1452                    fileNames: [
1453                        "/dev/A.ts",
1454                        "/dev/B.ts",
1455                        "/dev/a.ts",
1456                        "/dev/b.ts",
1457                        "/dev/c.d.ts",
1458                        "/dev/q/a/c/b/d.ts",
1459                        "/dev/z/a.ts",
1460                        "/dev/z/aba.ts",
1461                        "/dev/z/abz.ts",
1462                        "/dev/z/b.ts",
1463                        "/dev/z/bba.ts",
1464                        "/dev/z/bbz.ts",
1465                    ],
1466                    wildcardDirectories: {
1467                        "/dev": WatchDirectoryFlags.Recursive
1468                    }
1469                };
1470                validateMatches(expected, json, caseSensitiveHost, caseSensitiveBasePath);
1471            });
1472            it("can include dirs whose pattern starts with **", () => {
1473                const json = {
1474                    include: [
1475                        "**/x",
1476                        "**/a/**/b"
1477                    ]
1478                };
1479                const expected: ParsedCommandLine = {
1480                    options: {},
1481                    errors: [],
1482                    fileNames: [
1483                        "/dev/x/a.ts",
1484                        "/dev/x/b.ts",
1485                        "/dev/x/y/a.ts",
1486                        "/dev/x/y/b.ts",
1487                        "/dev/q/a/c/b/d.ts",
1488                    ],
1489                    wildcardDirectories: {
1490                        "/dev": WatchDirectoryFlags.Recursive
1491                    }
1492                };
1493                validateMatches(expected, json, caseSensitiveHost, caseSensitiveBasePath);
1494            });
1495        });
1496
1497        it("can include files in the same order on multiple platforms", () => {
1498            function getExpected(basePath: string): ParsedCommandLine {
1499                return {
1500                    options: {},
1501                    errors: [],
1502                    fileNames: [
1503                        `${basePath}Yosemite.ts`, // capital always comes before lowercase letters
1504                        `${basePath}xylophone.ts`,
1505                        `${basePath}zebra.ts`
1506                    ],
1507                    wildcardDirectories: {
1508                        [basePath.slice(0, basePath.length - 1)]: WatchDirectoryFlags.Recursive
1509                    },
1510                };
1511            }
1512            const json = {};
1513            validateMatches(getExpected(caseSensitiveBasePath), json, caseSensitiveOrderingDiffersWithCaseHost, caseSensitiveBasePath);
1514            validateMatches(getExpected(caseInsensitiveBasePath), json, caseInsensitiveOrderingDiffersWithCaseHost, caseInsensitiveBasePath);
1515        });
1516
1517        it("when recursive symlinked directories are present", () => {
1518            const fs = new vfs.FileSystem(/*ignoreCase*/ true, {
1519                cwd: caseInsensitiveBasePath, files: {
1520                    "c:/dev/index.ts": ""
1521                }
1522            });
1523            fs.mkdirpSync("c:/dev/a/b/c");
1524            fs.symlinkSync("c:/dev/A", "c:/dev/a/self");
1525            fs.symlinkSync("c:/dev/a", "c:/dev/a/b/parent");
1526            fs.symlinkSync("c:/dev/a", "c:/dev/a/b/c/grandparent");
1527            const host = new fakes.ParseConfigHost(fs);
1528            const json = {};
1529            const expected: ParsedCommandLine = {
1530                options: {},
1531                errors: [],
1532                fileNames: [
1533                    "c:/dev/index.ts"
1534                ],
1535                wildcardDirectories: {
1536                    "c:/dev": WatchDirectoryFlags.Recursive
1537                },
1538            };
1539            validateMatches(expected, json, host, caseInsensitiveBasePath);
1540        });
1541    });
1542}
1543