UNPKG

ph-dev-tools

Version:
132 lines (113 loc) 4 kB
/** * Created by Papa on 3/30/2016. */ import * as fs from "fs"; import * as ts from "typescript"; import {generateEntityDefinitions} from "./parser/EntityDefinitionGenerator"; import {EntityCandidate} from "./parser/EntityCandidate"; import {Configuration} from "./options/Options"; import {QEntityFileBuilder} from "./builder/entity/QEntityFileBuilder"; import {PathBuilder} from "./builder/PathBuilder"; export function watchFiles( configuration:Configuration, options:ts.CompilerOptions, rootFileNames:string[] ) { const files:ts.Map<{ version:number }> = {}; const pathBuilder = new PathBuilder(configuration); // initialize the list of files rootFileNames.forEach( fileName => { files[fileName] = {version: 0}; }); // Create the language service host to allow the LS to communicate with the host const servicesHost:ts.LanguageServiceHost = { getCompilationSettings: () => options, 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(), getDefaultLibFileName: ( options ) => ts.getDefaultLibFilePath(options) }; // Create the language service files const services = ts.createLanguageService(servicesHost, ts.createDocumentRegistry()); // First time around, process all files processFiles(rootFileNames, options); // Now let's watch the files rootFileNames.forEach( 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++; // process file processFiles([fileName], options); }); }); function processFiles( rootFileNames:string[], options:ts.CompilerOptions ):void { options.target = ts.ScriptTarget.ES5; let entities:EntityCandidate[] = generateEntityDefinitions(rootFileNames, options); emitFiles(entities); } function emitFiles( entities:EntityCandidate[] ):void { entities.forEach(( entity:EntityCandidate ) => { // TODO: work here next - read all of the configured templates and generate all of the artifacts let fullGenerationPath = pathBuilder.getFullPathToGeneratedSource(entity.path); let entityFileBuilder = new QEntityFileBuilder(entity, fullGenerationPath, pathBuilder.workingDirPath); let generationPath = pathBuilder.setupFileForGeneration(entity.path); var entitySourceString = entityFileBuilder.build(); fs.writeFileSync(generationPath, entitySourceString); }); } function emitFile( fileName:string ) { let output = services.getEmitOutput(fileName); if (!output.emitSkipped) { console.log(`Emitting ${fileName}`); } else { console.log(`Emitting ${fileName} failed`); logErrors(fileName); } output.outputFiles.forEach( o => { fs.writeFileSync(o.name, o.text, "utf8"); }); } function logErrors( fileName:string ) { let allDiagnostics = services.getCompilerOptionsDiagnostics() .concat(services.getSyntacticDiagnostics(fileName)) .concat(services.getSemanticDiagnostics(fileName)); 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}`); } }); } }