• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// @module: commonjs
2// @skipLibCheck: true
3// @noImplicitAny:true
4// @strictNullChecks:true
5
6// @filename: node_modules/typescript/package.json
7{
8    "name": "typescript",
9    "types": "/.ts/typescript.d.ts"
10}
11
12// @filename: APISample_watcher.ts
13/*
14 * Note: This test is a public API sample. The sample sources can be found
15 *       at: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#incremental-build-support-using-the-language-services
16 *       Please log a "breaking change" issue for any API breaking change affecting this issue
17 */
18
19declare var process: any;
20declare var console: any;
21declare var fs: {
22    existsSync(path: string): boolean;
23    readdirSync(path: string): string[];
24    readFileSync(filename: string, encoding?: string): string;
25    writeFileSync(filename: string, data: any, options?: { encoding?: string; mode?: number; flag?: string; } | string): void;
26    watchFile(filename: string, options: { persistent?: boolean; interval?: number; }, listener: (curr: { mtime: Date }, prev: { mtime: Date }) => void): void;
27};
28declare var path: any;
29
30import * as ts from "typescript";
31
32function watch(rootFileNames: string[], options: ts.CompilerOptions) {
33    const files: ts.MapLike<{ version: number }> = {};
34
35    // initialize the list of files
36    rootFileNames.forEach(fileName => {
37        files[fileName] = { version: 0 };
38    });
39
40    // Create the language service host to allow the LS to communicate with the host
41    const servicesHost: ts.LanguageServiceHost = {
42        getScriptFileNames: () => rootFileNames,
43        getScriptVersion: (fileName) => files[fileName] && files[fileName].version.toString(),
44        getScriptSnapshot: (fileName) => {
45            if (!fs.existsSync(fileName)) {
46                return undefined;
47            }
48
49            return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString());
50        },
51        getCurrentDirectory: () => process.cwd(),
52        getCompilationSettings: () => options,
53        getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options),
54        fileExists: fileName => fs.existsSync(fileName),
55        readFile: fileName => fs.readFileSync(fileName),
56    };
57
58    // Create the language service files
59    const services = ts.createLanguageService(servicesHost, ts.createDocumentRegistry())
60
61    // Now let's watch the files
62    rootFileNames.forEach(fileName => {
63        // First time around, emit all files
64        emitFile(fileName);
65
66        // Add a watch on the file to handle next change
67        fs.watchFile(fileName,
68            { persistent: true, interval: 250 },
69            (curr, prev) => {
70                // Check timestamp
71                if (+curr.mtime <= +prev.mtime) {
72                    return;
73                }
74
75                // Update the version to signal a change in the file
76                files[fileName].version++;
77
78                // write the changes to disk
79                emitFile(fileName);
80            });
81    });
82
83    function emitFile(fileName: string) {
84        let output = services.getEmitOutput(fileName);
85
86        if (!output.emitSkipped) {
87            console.log(`Emitting ${fileName}`);
88        }
89        else {
90            console.log(`Emitting ${fileName} failed`);
91            logErrors(fileName);
92        }
93
94        output.outputFiles.forEach(o => {
95            fs.writeFileSync(o.name, o.text, "utf8");
96        });
97    }
98
99    function logErrors(fileName: string) {
100        let allDiagnostics = services.getCompilerOptionsDiagnostics()
101            .concat(services.getSyntacticDiagnostics(fileName))
102            .concat(services.getSemanticDiagnostics(fileName));
103
104        allDiagnostics.forEach(diagnostic => {
105            let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
106            if (diagnostic.file) {
107                let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start!);
108                console.log(`  Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
109            }
110            else {
111                console.log(`  Error: ${message}`);
112            }
113        });
114    }
115}
116
117// Initialize files constituting the program as all .ts files in the current directory
118const currentDirectoryFiles = fs.readdirSync(process.cwd()).
119    filter(fileName=> fileName.length >= 3 && fileName.substr(fileName.length - 3, 3) === ".ts");
120
121// Start the watcher
122watch(currentDirectoryFiles, { module: ts.ModuleKind.CommonJS });
123