UNPKG

gulp-jumpscript

Version:

A jumpscript compiler for gulp with incremental compilation support.

226 lines (225 loc) 11.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var path = require("path"); var input_1 = require("./input"); var host_1 = require("./host"); var reporter_1 = require("./reporter"); var utils = require("./utils"); /** * Compiles a whole project, with full type checking */ var ProjectCompiler = /** @class */ (function () { function ProjectCompiler() { } ProjectCompiler.prototype.prepare = function (project) { this.project = project; this.hasSourceMap = false; }; ProjectCompiler.prototype.inputFile = function (file) { if (file.gulp.sourceMap) this.hasSourceMap = true; }; ProjectCompiler.prototype.inputDone = function () { var _this = this; if (!this.project.input.firstSourceFile) { this.project.output.finish(reporter_1.emptyCompilationResult(this.project.options.noEmit)); return; } var rootFilenames = this.project.input.getFileNames(true); if (!this.project.singleOutput) { if (this.project.options.rootDir === undefined) { this.project.options.rootDir = utils.getCommonBasePathOfArray(rootFilenames.filter(function (fileName) { return fileName.substr(-5) !== ".d.jump"; }) .map(function (fileName) { return _this.project.input.getFile(fileName).gulp.base; })); } } this.project.options.sourceMap = this.hasSourceMap; var currentDirectory = utils.getCommonBasePathOfArray(rootFilenames.map(function (fileName) { return _this.project.input.getFile(fileName).gulp.cwd; })); this.host = new host_1.Host(this.project.jumpscript, currentDirectory, this.project.input, this.project.options); this.program = this.project.jumpscript.createProgram(rootFilenames, this.project.options, this.host, this.program); var result = reporter_1.emptyCompilationResult(this.project.options.noEmit); result.optionsErrors = this.reportDiagnostics(this.program.getOptionsDiagnostics()); result.syntaxErrors = this.reportDiagnostics(this.program.getSyntacticDiagnostics()); result.globalErrors = this.reportDiagnostics(this.program.getGlobalDiagnostics()); result.semanticErrors = this.reportDiagnostics(this.program.getSemanticDiagnostics()); if (this.project.options.declaration) { result.declarationErrors = this.program.getDeclarationDiagnostics().length; } if (this.project.singleOutput) { var output_1 = { file: undefined }; this.emit(result, function (fileName, content) { _this.attachContentToFile(output_1, fileName, content); }); this.emitFile(output_1, currentDirectory); } else { var output_2 = {}; var input = this.host.input.getFileNames(true); for (var i = 0; i < input.length; i++) { var fileName = utils.normalizePath(input[i]); var file = this.project.input.getFile(fileName); output_2[fileName] = { file: file }; } this.emit(result, function (fileName, content, writeByteOrderMark, onError, sourceFiles) { if (sourceFiles.length !== 1) { throw new Error("Failure: sourceFiles in WriteFileCallback should have length 1, got " + sourceFiles.length); } var fileNameOriginal = utils.normalizePath(sourceFiles[0].fileName); var file = output_2[fileNameOriginal]; if (!file) return; _this.attachContentToFile(file, fileName, content); }); for (var i = 0; i < input.length; i++) { var fileName = utils.normalizePath(input[i]); this.emitFile(output_2[fileName], currentDirectory); } } this.project.output.finish(result); }; ProjectCompiler.prototype.attachContentToFile = function (file, fileName, content) { var _a = utils.splitExtension(fileName, ['d.jump']), extension = _a[1]; switch (extension) { case 'js': case 'jsx': file.jsFileName = fileName; file.jsContent = content; break; case 'd.jump': file.dtsFileName = fileName; file.dtsContent = content; break; case 'map': file.jsMapContent = content; break; } }; ProjectCompiler.prototype.emit = function (result, callback) { var emitOutput = this.program.emit(undefined, callback); result.emitErrors += emitOutput.diagnostics.length; this.reportDiagnostics(emitOutput.diagnostics); result.emitSkipped = emitOutput.emitSkipped; }; ProjectCompiler.prototype.emitFile = function (_a, currentDirectory) { var file = _a.file, jsFileName = _a.jsFileName, dtsFileName = _a.dtsFileName, jsContent = _a.jsContent, dtsContent = _a.dtsContent, jsMapContent = _a.jsMapContent; if (!jsFileName) return; var base; var baseDeclarations; if (file) { base = file.gulp.base; if (this.project.options.outDir) { var baseRelative = path.relative(this.project.options.rootDir, base); base = path.join(this.project.options.outDir, baseRelative); } baseDeclarations = base; if (this.project.options.declarationDir) { var baseRelative = path.relative(this.project.options.rootDir, file.gulp.base); baseDeclarations = path.join(this.project.options.declarationDir, baseRelative); } if (base === '') console.log(1, file.gulp.base, this.project.options.outDir); } else if (this.project.options.outFile) { base = this.project.directory; baseDeclarations = base; if (base === '') console.log(2, this.project); } else { base = this.project.directory; baseDeclarations = base; jsFileName = path.resolve(base, jsFileName); if (dtsFileName !== undefined) { dtsFileName = path.resolve(base, dtsFileName); } if (base === '') console.log(3, this.project.options.out, jsFileName); } if (jsContent !== undefined) { if (jsMapContent !== undefined) { jsContent = this.removeSourceMapComment(jsContent); } this.project.output.writeJs(base, jsFileName, jsContent, jsMapContent, file ? file.gulp.cwd : currentDirectory, file); } if (dtsContent !== undefined) { this.project.output.writeDts(baseDeclarations, dtsFileName, dtsContent, file ? file.gulp.cwd : currentDirectory); } }; ProjectCompiler.prototype.reportDiagnostics = function (diagnostics) { for (var _i = 0, diagnostics_1 = diagnostics; _i < diagnostics_1.length; _i++) { var error = diagnostics_1[_i]; this.project.output.diagnostic(error); } return diagnostics.length; }; ProjectCompiler.prototype.removeSourceMapComment = function (content) { // By default the JumpScript automaticly inserts a source map comment. // This should be removed because gulp-sourcemaps takes care of that. // The comment is always on the last line, so it's easy to remove it // (But the last line also ends with a \n, so we need to look for the \n before the other) var index = content.lastIndexOf('\n', content.length - 2); return content.substring(0, index) + '\n'; }; return ProjectCompiler; }()); exports.ProjectCompiler = ProjectCompiler; var FileCompiler = /** @class */ (function () { function FileCompiler() { this.output = {}; this.previousOutput = {}; this.compilationResult = undefined; } FileCompiler.prototype.prepare = function (project) { this.project = project; this.project.input.noParse = true; this.compilationResult = reporter_1.emptyCompilationResult(this.project.options.noEmit); }; FileCompiler.prototype.write = function (file, fileName, diagnostics, content, sourceMap) { this.output[file.fileNameNormalized] = { fileName: fileName, diagnostics: diagnostics, content: content, sourceMap: sourceMap }; for (var _i = 0, diagnostics_2 = diagnostics; _i < diagnostics_2.length; _i++) { var error = diagnostics_2[_i]; this.project.output.diagnostic(error); } this.compilationResult.transpileErrors += diagnostics.length; this.project.output.writeJs(file.gulp.base, fileName, content, sourceMap, file.gulp.cwd, file); }; FileCompiler.prototype.inputFile = function (file) { if (file.fileNameNormalized.substr(file.fileNameNormalized.length - 5) === '.d.jump') { return; // Don't compile definition files } if (this.project.input.getFileChange(file.fileNameOriginal).state === input_1.FileChangeState.Equal) { // Not changed, re-use old file. var old = this.previousOutput[file.fileNameNormalized]; this.write(file, old.fileName, old.diagnostics, old.content, old.sourceMap); return; } var diagnostics = []; var outputString = this.project.jumpscript.transpile(file.content, this.project.options, file.fileNameOriginal, diagnostics); var index = outputString.lastIndexOf('\n'); var mapString = outputString.substring(index + 1); if (mapString.substring(0, 1) === '\r') mapString = mapString.substring(1); var start = '//# sourceMappingURL=data:application/json;base64,'; if (mapString.substring(0, start.length) !== start) { console.log('Couldn\'t read the sourceMap generated by JumpScript. This is likely an issue with gulp-jumpscript.'); return; } mapString = mapString.substring(start.length); var map = JSON.parse(new Buffer(mapString, 'base64').toString()); // TODO: Set paths correctly // map.sourceRoot = path.resolve(file.gulp.cwd, file.gulp.base); // map.sources[0] = path.relative(map.sourceRoot, file.gulp.path); var fileNameExtensionless = utils.splitExtension(file.fileNameOriginal)[0]; var _a = utils.splitExtension(map.file), extension = _a[1]; // js or jsx this.write(file, fileNameExtensionless + '.' + extension, diagnostics, outputString.substring(0, index), JSON.stringify(map)); }; FileCompiler.prototype.inputDone = function () { this.project.output.finish(this.compilationResult); this.previousOutput = this.output; this.output = {}; }; return FileCompiler; }()); exports.FileCompiler = FileCompiler;