443 lines
20 KiB
Text
443 lines
20 KiB
Text
=== tests/cases/compiler/APISample_watcher.ts ===
|
|
|
|
/*
|
|
* Note: This test is a public API sample. The sample sources can be found
|
|
at: https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API#incremental-build-support-using-the-language-services
|
|
* Please log a "breaking change" issue for any API breaking change affecting this issue
|
|
*/
|
|
|
|
declare var process: any;
|
|
>process : any
|
|
|
|
declare var console: any;
|
|
>console : any
|
|
|
|
declare var fs: any;
|
|
>fs : any
|
|
|
|
declare var path: any;
|
|
>path : any
|
|
|
|
import * as ts from "typescript";
|
|
>ts : typeof ts
|
|
|
|
function watch(rootFileNames: string[], options: ts.CompilerOptions) {
|
|
>watch : (rootFileNames: string[], options: ts.CompilerOptions) => void
|
|
>rootFileNames : string[]
|
|
>options : ts.CompilerOptions
|
|
>ts : any
|
|
>CompilerOptions : ts.CompilerOptions
|
|
|
|
const files: ts.Map<{ version: number }> = {};
|
|
>files : ts.Map<{ version: number; }>
|
|
>ts : any
|
|
>Map : ts.Map<T>
|
|
>version : number
|
|
>{} : { [x: string]: undefined; }
|
|
|
|
// initialize the list of files
|
|
rootFileNames.forEach(fileName => {
|
|
>rootFileNames.forEach(fileName => { files[fileName] = { version: 0 }; }) : void
|
|
>rootFileNames.forEach : (callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void
|
|
>rootFileNames : string[]
|
|
>forEach : (callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void
|
|
>fileName => { files[fileName] = { version: 0 }; } : (fileName: string) => void
|
|
>fileName : string
|
|
|
|
files[fileName] = { version: 0 };
|
|
>files[fileName] = { version: 0 } : { version: number; }
|
|
>files[fileName] : { version: number; }
|
|
>files : ts.Map<{ version: number; }>
|
|
>fileName : string
|
|
>{ version: 0 } : { version: number; }
|
|
>version : number
|
|
>0 : number
|
|
|
|
});
|
|
|
|
// Create the language service host to allow the LS to communicate with the host
|
|
const servicesHost: ts.LanguageServiceHost = {
|
|
>servicesHost : ts.LanguageServiceHost
|
|
>ts : any
|
|
>LanguageServiceHost : ts.LanguageServiceHost
|
|
>{ getScriptFileNames: () => rootFileNames, getScriptVersion: (fileName) => files[fileName] && files[fileName].version.toString(), getScriptSnapshot: (fileName) => { if (!fs.existsSync(fileName)) { return undefined; } return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); }, getCurrentDirectory: () => process.cwd(), getCompilationSettings: () => options, getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options), } : { getScriptFileNames: () => string[]; getScriptVersion: (fileName: string) => string; getScriptSnapshot: (fileName: string) => ts.IScriptSnapshot; getCurrentDirectory: () => any; getCompilationSettings: () => ts.CompilerOptions; getDefaultLibFileName: (options: ts.CompilerOptions) => string; }
|
|
|
|
getScriptFileNames: () => rootFileNames,
|
|
>getScriptFileNames : () => string[]
|
|
>() => rootFileNames : () => string[]
|
|
>rootFileNames : string[]
|
|
|
|
getScriptVersion: (fileName) => files[fileName] && files[fileName].version.toString(),
|
|
>getScriptVersion : (fileName: string) => string
|
|
>(fileName) => files[fileName] && files[fileName].version.toString() : (fileName: string) => string
|
|
>fileName : string
|
|
>files[fileName] && files[fileName].version.toString() : string
|
|
>files[fileName] : { version: number; }
|
|
>files : ts.Map<{ version: number; }>
|
|
>fileName : string
|
|
>files[fileName].version.toString() : string
|
|
>files[fileName].version.toString : (radix?: number) => string
|
|
>files[fileName].version : number
|
|
>files[fileName] : { version: number; }
|
|
>files : ts.Map<{ version: number; }>
|
|
>fileName : string
|
|
>version : number
|
|
>toString : (radix?: number) => string
|
|
|
|
getScriptSnapshot: (fileName) => {
|
|
>getScriptSnapshot : (fileName: string) => ts.IScriptSnapshot
|
|
>(fileName) => { if (!fs.existsSync(fileName)) { return undefined; } return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()); } : (fileName: string) => ts.IScriptSnapshot
|
|
>fileName : string
|
|
|
|
if (!fs.existsSync(fileName)) {
|
|
>!fs.existsSync(fileName) : boolean
|
|
>fs.existsSync(fileName) : any
|
|
>fs.existsSync : any
|
|
>fs : any
|
|
>existsSync : any
|
|
>fileName : string
|
|
|
|
return undefined;
|
|
>undefined : undefined
|
|
}
|
|
|
|
return ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString());
|
|
>ts.ScriptSnapshot.fromString(fs.readFileSync(fileName).toString()) : ts.IScriptSnapshot
|
|
>ts.ScriptSnapshot.fromString : (text: string) => ts.IScriptSnapshot
|
|
>ts.ScriptSnapshot : typeof ts.ScriptSnapshot
|
|
>ts : typeof ts
|
|
>ScriptSnapshot : typeof ts.ScriptSnapshot
|
|
>fromString : (text: string) => ts.IScriptSnapshot
|
|
>fs.readFileSync(fileName).toString() : any
|
|
>fs.readFileSync(fileName).toString : any
|
|
>fs.readFileSync(fileName) : any
|
|
>fs.readFileSync : any
|
|
>fs : any
|
|
>readFileSync : any
|
|
>fileName : string
|
|
>toString : any
|
|
|
|
},
|
|
getCurrentDirectory: () => process.cwd(),
|
|
>getCurrentDirectory : () => any
|
|
>() => process.cwd() : () => any
|
|
>process.cwd() : any
|
|
>process.cwd : any
|
|
>process : any
|
|
>cwd : any
|
|
|
|
getCompilationSettings: () => options,
|
|
>getCompilationSettings : () => ts.CompilerOptions
|
|
>() => options : () => ts.CompilerOptions
|
|
>options : ts.CompilerOptions
|
|
|
|
getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options),
|
|
>getDefaultLibFileName : (options: ts.CompilerOptions) => string
|
|
>(options) => ts.getDefaultLibFilePath(options) : (options: ts.CompilerOptions) => string
|
|
>options : ts.CompilerOptions
|
|
>ts.getDefaultLibFilePath(options) : string
|
|
>ts.getDefaultLibFilePath : (options: ts.CompilerOptions) => string
|
|
>ts : typeof ts
|
|
>getDefaultLibFilePath : (options: ts.CompilerOptions) => string
|
|
>options : ts.CompilerOptions
|
|
|
|
};
|
|
|
|
// Create the language service files
|
|
const services = ts.createLanguageService(servicesHost, ts.createDocumentRegistry())
|
|
>services : ts.LanguageService
|
|
>ts.createLanguageService(servicesHost, ts.createDocumentRegistry()) : ts.LanguageService
|
|
>ts.createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService
|
|
>ts : typeof ts
|
|
>createLanguageService : (host: ts.LanguageServiceHost, documentRegistry?: ts.DocumentRegistry) => ts.LanguageService
|
|
>servicesHost : ts.LanguageServiceHost
|
|
>ts.createDocumentRegistry() : ts.DocumentRegistry
|
|
>ts.createDocumentRegistry : () => ts.DocumentRegistry
|
|
>ts : typeof ts
|
|
>createDocumentRegistry : () => ts.DocumentRegistry
|
|
|
|
// Now let's watch the files
|
|
rootFileNames.forEach(fileName => {
|
|
>rootFileNames.forEach(fileName => { // First time around, emit all files emitFile(fileName); // Add a watch on the file to handle next change fs.watchFile(fileName, { persistent: true, interval: 250 }, (curr, prev) => { // Check timestamp if (+curr.mtime <= +prev.mtime) { return; } // Update the version to signal a change in the file files[fileName].version++; // write the changes to disk emitFile(fileName); }); }) : void
|
|
>rootFileNames.forEach : (callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void
|
|
>rootFileNames : string[]
|
|
>forEach : (callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void
|
|
>fileName => { // First time around, emit all files emitFile(fileName); // Add a watch on the file to handle next change fs.watchFile(fileName, { persistent: true, interval: 250 }, (curr, prev) => { // Check timestamp if (+curr.mtime <= +prev.mtime) { return; } // Update the version to signal a change in the file files[fileName].version++; // write the changes to disk emitFile(fileName); }); } : (fileName: string) => void
|
|
>fileName : string
|
|
|
|
// First time around, emit all files
|
|
emitFile(fileName);
|
|
>emitFile(fileName) : void
|
|
>emitFile : (fileName: string) => void
|
|
>fileName : string
|
|
|
|
// Add a watch on the file to handle next change
|
|
fs.watchFile(fileName,
|
|
>fs.watchFile(fileName, { persistent: true, interval: 250 }, (curr, prev) => { // Check timestamp if (+curr.mtime <= +prev.mtime) { return; } // Update the version to signal a change in the file files[fileName].version++; // write the changes to disk emitFile(fileName); }) : any
|
|
>fs.watchFile : any
|
|
>fs : any
|
|
>watchFile : any
|
|
>fileName : string
|
|
|
|
{ persistent: true, interval: 250 },
|
|
>{ persistent: true, interval: 250 } : { persistent: boolean; interval: number; }
|
|
>persistent : boolean
|
|
>true : boolean
|
|
>interval : number
|
|
>250 : number
|
|
|
|
(curr, prev) => {
|
|
>(curr, prev) => { // Check timestamp if (+curr.mtime <= +prev.mtime) { return; } // Update the version to signal a change in the file files[fileName].version++; // write the changes to disk emitFile(fileName); } : (curr: any, prev: any) => void
|
|
>curr : any
|
|
>prev : any
|
|
|
|
// Check timestamp
|
|
if (+curr.mtime <= +prev.mtime) {
|
|
>+curr.mtime <= +prev.mtime : boolean
|
|
>+curr.mtime : number
|
|
>curr.mtime : any
|
|
>curr : any
|
|
>mtime : any
|
|
>+prev.mtime : number
|
|
>prev.mtime : any
|
|
>prev : any
|
|
>mtime : any
|
|
|
|
return;
|
|
}
|
|
|
|
// Update the version to signal a change in the file
|
|
files[fileName].version++;
|
|
>files[fileName].version++ : number
|
|
>files[fileName].version : number
|
|
>files[fileName] : { version: number; }
|
|
>files : ts.Map<{ version: number; }>
|
|
>fileName : string
|
|
>version : number
|
|
|
|
// write the changes to disk
|
|
emitFile(fileName);
|
|
>emitFile(fileName) : void
|
|
>emitFile : (fileName: string) => void
|
|
>fileName : string
|
|
|
|
});
|
|
});
|
|
|
|
function emitFile(fileName: string) {
|
|
>emitFile : (fileName: string) => void
|
|
>fileName : string
|
|
|
|
let output = services.getEmitOutput(fileName);
|
|
>output : ts.EmitOutput
|
|
>services.getEmitOutput(fileName) : ts.EmitOutput
|
|
>services.getEmitOutput : (fileName: string) => ts.EmitOutput
|
|
>services : ts.LanguageService
|
|
>getEmitOutput : (fileName: string) => ts.EmitOutput
|
|
>fileName : string
|
|
|
|
if (!output.emitSkipped) {
|
|
>!output.emitSkipped : boolean
|
|
>output.emitSkipped : boolean
|
|
>output : ts.EmitOutput
|
|
>emitSkipped : boolean
|
|
|
|
console.log(`Emitting ${fileName}`);
|
|
>console.log(`Emitting ${fileName}`) : any
|
|
>console.log : any
|
|
>console : any
|
|
>log : any
|
|
>`Emitting ${fileName}` : string
|
|
>fileName : string
|
|
}
|
|
else {
|
|
console.log(`Emitting ${fileName} failed`);
|
|
>console.log(`Emitting ${fileName} failed`) : any
|
|
>console.log : any
|
|
>console : any
|
|
>log : any
|
|
>`Emitting ${fileName} failed` : string
|
|
>fileName : string
|
|
|
|
logErrors(fileName);
|
|
>logErrors(fileName) : void
|
|
>logErrors : (fileName: string) => void
|
|
>fileName : string
|
|
}
|
|
|
|
output.outputFiles.forEach(o => {
|
|
>output.outputFiles.forEach(o => { fs.writeFileSync(o.name, o.text, "utf8"); }) : void
|
|
>output.outputFiles.forEach : (callbackfn: (value: ts.OutputFile, index: number, array: ts.OutputFile[]) => void, thisArg?: any) => void
|
|
>output.outputFiles : ts.OutputFile[]
|
|
>output : ts.EmitOutput
|
|
>outputFiles : ts.OutputFile[]
|
|
>forEach : (callbackfn: (value: ts.OutputFile, index: number, array: ts.OutputFile[]) => void, thisArg?: any) => void
|
|
>o => { fs.writeFileSync(o.name, o.text, "utf8"); } : (o: ts.OutputFile) => void
|
|
>o : ts.OutputFile
|
|
|
|
fs.writeFileSync(o.name, o.text, "utf8");
|
|
>fs.writeFileSync(o.name, o.text, "utf8") : any
|
|
>fs.writeFileSync : any
|
|
>fs : any
|
|
>writeFileSync : any
|
|
>o.name : string
|
|
>o : ts.OutputFile
|
|
>name : string
|
|
>o.text : string
|
|
>o : ts.OutputFile
|
|
>text : string
|
|
>"utf8" : string
|
|
|
|
});
|
|
}
|
|
|
|
function logErrors(fileName: string) {
|
|
>logErrors : (fileName: string) => void
|
|
>fileName : string
|
|
|
|
let allDiagnostics = services.getCompilerOptionsDiagnostics()
|
|
>allDiagnostics : ts.Diagnostic[]
|
|
>services.getCompilerOptionsDiagnostics() .concat(services.getSyntacticDiagnostics(fileName)) .concat(services.getSemanticDiagnostics(fileName)) : ts.Diagnostic[]
|
|
>services.getCompilerOptionsDiagnostics() .concat(services.getSyntacticDiagnostics(fileName)) .concat : { <U extends ts.Diagnostic[]>(...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }
|
|
>services.getCompilerOptionsDiagnostics() .concat(services.getSyntacticDiagnostics(fileName)) : ts.Diagnostic[]
|
|
>services.getCompilerOptionsDiagnostics() .concat : { <U extends ts.Diagnostic[]>(...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }
|
|
>services.getCompilerOptionsDiagnostics() : ts.Diagnostic[]
|
|
>services.getCompilerOptionsDiagnostics : () => ts.Diagnostic[]
|
|
>services : ts.LanguageService
|
|
>getCompilerOptionsDiagnostics : () => ts.Diagnostic[]
|
|
|
|
.concat(services.getSyntacticDiagnostics(fileName))
|
|
>concat : { <U extends ts.Diagnostic[]>(...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }
|
|
>services.getSyntacticDiagnostics(fileName) : ts.Diagnostic[]
|
|
>services.getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[]
|
|
>services : ts.LanguageService
|
|
>getSyntacticDiagnostics : (fileName: string) => ts.Diagnostic[]
|
|
>fileName : string
|
|
|
|
.concat(services.getSemanticDiagnostics(fileName));
|
|
>concat : { <U extends ts.Diagnostic[]>(...items: U[]): ts.Diagnostic[]; (...items: ts.Diagnostic[]): ts.Diagnostic[]; }
|
|
>services.getSemanticDiagnostics(fileName) : ts.Diagnostic[]
|
|
>services.getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[]
|
|
>services : ts.LanguageService
|
|
>getSemanticDiagnostics : (fileName: string) => ts.Diagnostic[]
|
|
>fileName : string
|
|
|
|
allDiagnostics.forEach(diagnostic => {
|
|
>allDiagnostics.forEach(diagnostic => { let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); if (diagnostic.file) { let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); console.log(` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); } else { console.log(` Error: ${message}`); } }) : void
|
|
>allDiagnostics.forEach : (callbackfn: (value: ts.Diagnostic, index: number, array: ts.Diagnostic[]) => void, thisArg?: any) => void
|
|
>allDiagnostics : ts.Diagnostic[]
|
|
>forEach : (callbackfn: (value: ts.Diagnostic, index: number, array: ts.Diagnostic[]) => void, thisArg?: any) => void
|
|
>diagnostic => { let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n"); if (diagnostic.file) { let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start); console.log(` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`); } else { console.log(` Error: ${message}`); } } : (diagnostic: ts.Diagnostic) => void
|
|
>diagnostic : ts.Diagnostic
|
|
|
|
let message = ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
|
|
>message : string
|
|
>ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n") : string
|
|
>ts.flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string
|
|
>ts : typeof ts
|
|
>flattenDiagnosticMessageText : (messageText: string | ts.DiagnosticMessageChain, newLine: string) => string
|
|
>diagnostic.messageText : string | ts.DiagnosticMessageChain
|
|
>diagnostic : ts.Diagnostic
|
|
>messageText : string | ts.DiagnosticMessageChain
|
|
>"\n" : string
|
|
|
|
if (diagnostic.file) {
|
|
>diagnostic.file : ts.SourceFile
|
|
>diagnostic : ts.Diagnostic
|
|
>file : ts.SourceFile
|
|
|
|
let { line, character } = diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start);
|
|
>line : number
|
|
>character : number
|
|
>diagnostic.file.getLineAndCharacterOfPosition(diagnostic.start) : ts.LineAndCharacter
|
|
>diagnostic.file.getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter
|
|
>diagnostic.file : ts.SourceFile
|
|
>diagnostic : ts.Diagnostic
|
|
>file : ts.SourceFile
|
|
>getLineAndCharacterOfPosition : (pos: number) => ts.LineAndCharacter
|
|
>diagnostic.start : number
|
|
>diagnostic : ts.Diagnostic
|
|
>start : number
|
|
|
|
console.log(` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`);
|
|
>console.log(` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`) : any
|
|
>console.log : any
|
|
>console : any
|
|
>log : any
|
|
>` Error ${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}` : string
|
|
>diagnostic.file.fileName : string
|
|
>diagnostic.file : ts.SourceFile
|
|
>diagnostic : ts.Diagnostic
|
|
>file : ts.SourceFile
|
|
>fileName : string
|
|
>line + 1 : number
|
|
>line : number
|
|
>1 : number
|
|
>character + 1 : number
|
|
>character : number
|
|
>1 : number
|
|
>message : string
|
|
}
|
|
else {
|
|
console.log(` Error: ${message}`);
|
|
>console.log(` Error: ${message}`) : any
|
|
>console.log : any
|
|
>console : any
|
|
>log : any
|
|
>` Error: ${message}` : string
|
|
>message : string
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
// Initialize files constituting the program as all .ts files in the current directory
|
|
const currentDirectoryFiles = fs.readdirSync(process.cwd()).
|
|
>currentDirectoryFiles : any
|
|
>fs.readdirSync(process.cwd()). filter(fileName=> fileName.length >= 3 && fileName.substr(fileName.length - 3, 3) === ".ts") : any
|
|
>fs.readdirSync(process.cwd()). filter : any
|
|
>fs.readdirSync(process.cwd()) : any
|
|
>fs.readdirSync : any
|
|
>fs : any
|
|
>readdirSync : any
|
|
>process.cwd() : any
|
|
>process.cwd : any
|
|
>process : any
|
|
>cwd : any
|
|
|
|
filter(fileName=> fileName.length >= 3 && fileName.substr(fileName.length - 3, 3) === ".ts");
|
|
>filter : any
|
|
>fileName=> fileName.length >= 3 && fileName.substr(fileName.length - 3, 3) === ".ts" : (fileName: any) => boolean
|
|
>fileName : any
|
|
>fileName.length >= 3 && fileName.substr(fileName.length - 3, 3) === ".ts" : boolean
|
|
>fileName.length >= 3 : boolean
|
|
>fileName.length : any
|
|
>fileName : any
|
|
>length : any
|
|
>3 : number
|
|
>fileName.substr(fileName.length - 3, 3) === ".ts" : boolean
|
|
>fileName.substr(fileName.length - 3, 3) : any
|
|
>fileName.substr : any
|
|
>fileName : any
|
|
>substr : any
|
|
>fileName.length - 3 : number
|
|
>fileName.length : any
|
|
>fileName : any
|
|
>length : any
|
|
>3 : number
|
|
>3 : number
|
|
>".ts" : string
|
|
|
|
// Start the watcher
|
|
watch(currentDirectoryFiles, { module: ts.ModuleKind.CommonJS });
|
|
>watch(currentDirectoryFiles, { module: ts.ModuleKind.CommonJS }) : void
|
|
>watch : (rootFileNames: string[], options: ts.CompilerOptions) => void
|
|
>currentDirectoryFiles : any
|
|
>{ module: ts.ModuleKind.CommonJS } : { [x: string]: ts.ModuleKind; module: ts.ModuleKind; }
|
|
>module : ts.ModuleKind
|
|
>ts.ModuleKind.CommonJS : ts.ModuleKind
|
|
>ts.ModuleKind : typeof ts.ModuleKind
|
|
>ts : typeof ts
|
|
>ModuleKind : typeof ts.ModuleKind
|
|
>CommonJS : ts.ModuleKind
|
|
|