blob: 6ca0ec6ea921f166e50bba33c182769188223a66 [file] [log] [blame]
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var lodash = require("lodash");
var ts = require("typescript");
var benchmark_1 = require("../shared/benchmark");
var project_1 = require("../shared/project");
var Compiler = /** @class */ (function () {
function Compiler(config, log, project) {
var _this = this;
this.config = config;
this.log = log;
this.project = project;
this.compiledFiles = {};
this.emitQueue = [];
this.errors = [];
this.getSourceFile = function (filename, languageVersion, onError) {
if (_this.cachedProgram && !_this.isQueued(filename)) {
var sourceFile = _this.cachedProgram.getSourceFile(filename);
if (sourceFile) {
return sourceFile;
}
}
return _this.hostGetSourceFile(filename, languageVersion, onError);
};
config.whenReady(function () {
_this.log.debug("Setting up deferred project compilation");
_this.compileDeferred = lodash.debounce(function () {
_this.compileProject();
}, _this.config.compilerDelay);
});
}
Compiler.prototype.compile = function (file, callback) {
this.emitQueue.push({
callback: callback,
file: file
});
this.compileDeferred();
};
Compiler.prototype.compileProject = function () {
this.log.info("Compiling project using Typescript %s", ts.version);
if (this.project.handleFileEvent() === project_1.EventType.FileSystemChanged) {
this.setupRecompile();
}
var benchmark = new benchmark_1.Benchmark();
var tsconfig = this.project.getTsconfig();
this.outputDiagnostics(tsconfig.errors);
if (+ts.version[0] >= 3) {
this.program = ts.createProgram({
host: this.compilerHost,
options: tsconfig.options,
projectReferences: tsconfig.projectReferences,
rootNames: tsconfig.fileNames
});
}
else {
this.program = ts.createProgram(tsconfig.fileNames, tsconfig.options, this.compilerHost);
}
this.cachedProgram = this.program;
this.runDiagnostics(this.program, this.compilerHost);
this.program.emit();
this.log.info("Compiled %s files in %s ms.", tsconfig.fileNames.length, benchmark.elapsed());
this.onProgramCompiled();
};
Compiler.prototype.setupRecompile = function () {
var _this = this;
this.cachedProgram = undefined;
this.compilerHost = ts.createCompilerHost(this.project.getTsconfig().options);
this.hostGetSourceFile = this.compilerHost.getSourceFile;
this.compilerHost.getSourceFile = this.getSourceFile;
this.compilerHost.writeFile = function (filename, text) {
_this.compiledFiles[filename] = text;
};
};
Compiler.prototype.onProgramCompiled = function () {
var _this = this;
this.emitQueue.forEach(function (queued) {
var sourceFile = _this.program.getSourceFile(queued.file.originalPath);
if (!sourceFile) {
throw new Error("No source found for " + queued.file.originalPath + "!\n" +
"Is there a mismatch between the Typescript compiler options and the Karma config?");
}
var ambientModuleNames = sourceFile.ambientModuleNames;
queued.callback({
ambientModuleNames: ambientModuleNames,
hasError: _this.errors.indexOf(queued.file.originalPath) !== -1,
isAmbientModule: ambientModuleNames && ambientModuleNames.length > 0,
isDeclarationFile: _this.fileExtensionIs(sourceFile.fileName, ".d.ts"),
outputText: _this.compiledFiles[queued.file.path],
sourceFile: sourceFile,
sourceMapText: _this.compiledFiles[queued.file.path + ".map"]
});
});
this.emitQueue.length = 0;
};
Compiler.prototype.isQueued = function (filename) {
for (var _i = 0, _a = this.emitQueue; _i < _a.length; _i++) {
var queued = _a[_i];
if (queued.file.originalPath === filename) {
return true;
}
}
return false;
};
Compiler.prototype.runDiagnostics = function (program, host) {
this.errors = [];
var diagnostics = ts.getPreEmitDiagnostics(program);
this.outputDiagnostics(diagnostics, host);
};
Compiler.prototype.outputDiagnostics = function (diagnostics, host) {
var _this = this;
if (!diagnostics || diagnostics.length === 0) {
return;
}
diagnostics.forEach(function (diagnostic) {
if (diagnostic.file) {
_this.errors.push(diagnostic.file.fileName);
}
if (ts.formatDiagnostics && host) { // v1.8+
_this.log.error(ts.formatDiagnostics([diagnostic], host));
}
else { // v1.6, v1.7
var output = "";
if (diagnostic.file) {
var loc = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
output += diagnostic.file.fileName.replace(process.cwd(), "") +
"(" + (loc.line + 1) + "," + (loc.character + 1) + "): ";
}
var category = ts.DiagnosticCategory[diagnostic.category].toLowerCase();
output += category + " TS" + diagnostic.code + ": " +
ts.flattenDiagnosticMessageText(diagnostic.messageText, ts.sys.newLine) + ts.sys.newLine;
_this.log.error(output);
}
});
if (this.project.getTsconfig().options.noEmitOnError) {
ts.sys.exit(ts.ExitStatus.DiagnosticsPresent_OutputsSkipped);
}
};
Compiler.prototype.fileExtensionIs = function (path, extension) {
return path.length > extension.length && this.endsWith(path, extension);
};
Compiler.prototype.endsWith = function (str, suffix) {
var expectedPos = str.length - suffix.length;
return expectedPos >= 0 && str.indexOf(suffix, expectedPos) === expectedPos;
};
return Compiler;
}());
exports.Compiler = Compiler;
//# sourceMappingURL=compiler.js.map