|
- "use strict";
- var __assign = (this && this.__assign) || function () {
- __assign = Object.assign || function(t) {
- for (var s, i = 1, n = arguments.length; i < n; i++) {
- s = arguments[i];
- for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
- t[p] = s[p];
- }
- return t;
- };
- return __assign.apply(this, arguments);
- };
- Object.defineProperty(exports, "__esModule", { value: true });
- var fs = require("fs");
- var endsWith = require("lodash/endsWith");
- var path = require("path");
- var FilesRegister_1 = require("./FilesRegister");
- var FilesWatcher_1 = require("./FilesWatcher");
- var WorkSet_1 = require("./WorkSet");
- var NormalizedMessage_1 = require("./NormalizedMessage");
- var minimatch = require("minimatch");
- var VueProgram_1 = require("./VueProgram");
- var IncrementalChecker = /** @class */ (function () {
- function IncrementalChecker(typescriptPath, programConfigFile, compilerOptions, linterConfigFile, watchPaths, workNumber, workDivision, checkSyntacticErrors, vue) {
- this.typescript = require(typescriptPath);
- this.programConfigFile = programConfigFile;
- this.compilerOptions = compilerOptions;
- this.linterConfigFile = linterConfigFile;
- this.watchPaths = watchPaths;
- this.workNumber = workNumber || 0;
- this.workDivision = workDivision || 1;
- this.checkSyntacticErrors = checkSyntacticErrors || false;
- this.vue = vue || false;
- // Use empty array of exclusions in general to avoid having
- // to check of its existence later on.
- this.linterExclusions = [];
- // it's shared between compilations
- this.files = new FilesRegister_1.FilesRegister(function () { return ({
- // data shape
- source: undefined,
- linted: false,
- lints: []
- }); });
- }
- IncrementalChecker.loadProgramConfig = function (typescript, configFile, compilerOptions) {
- var tsconfig = typescript.readConfigFile(configFile, typescript.sys.readFile).config;
- tsconfig.compilerOptions = tsconfig.compilerOptions || {};
- tsconfig.compilerOptions = __assign({}, tsconfig.compilerOptions, compilerOptions);
- var parsed = typescript.parseJsonConfigFileContent(tsconfig, typescript.sys, path.dirname(configFile));
- return parsed;
- };
- IncrementalChecker.loadLinterConfig = function (configFile) {
- // tslint:disable-next-line:no-implicit-dependencies
- var tslint = require('tslint');
- return tslint.Configuration.loadConfigurationFromPath(configFile);
- };
- IncrementalChecker.createProgram = function (typescript, programConfig, files, watcher, oldProgram) {
- var host = typescript.createCompilerHost(programConfig.options);
- var realGetSourceFile = host.getSourceFile;
- host.getSourceFile = function (filePath, languageVersion, onError) {
- // first check if watcher is watching file - if not - check it's mtime
- if (!watcher.isWatchingFile(filePath)) {
- try {
- var stats = fs.statSync(filePath);
- files.setMtime(filePath, stats.mtime.valueOf());
- }
- catch (e) {
- // probably file does not exists
- files.remove(filePath);
- }
- }
- // get source file only if there is no source in files register
- if (!files.has(filePath) || !files.getData(filePath).source) {
- files.mutateData(filePath, function (data) {
- data.source = realGetSourceFile(filePath, languageVersion, onError);
- });
- }
- return files.getData(filePath).source;
- };
- return typescript.createProgram(programConfig.fileNames, programConfig.options, host, oldProgram // re-use old program
- );
- };
- IncrementalChecker.createLinter = function (program) {
- // tslint:disable-next-line:no-implicit-dependencies
- var tslint = require('tslint');
- return new tslint.Linter({ fix: false }, program);
- };
- IncrementalChecker.isFileExcluded = function (filePath, linterExclusions) {
- return (endsWith(filePath, '.d.ts') ||
- linterExclusions.some(function (matcher) { return matcher.match(filePath); }));
- };
- IncrementalChecker.prototype.nextIteration = function () {
- var _this = this;
- if (!this.watcher) {
- var watchExtensions = this.vue
- ? ['.ts', '.tsx', '.vue']
- : ['.ts', '.tsx'];
- this.watcher = new FilesWatcher_1.FilesWatcher(this.watchPaths, watchExtensions);
- // connect watcher with register
- this.watcher.on('change', function (filePath, stats) {
- _this.files.setMtime(filePath, stats.mtime.valueOf());
- });
- this.watcher.on('unlink', function (filePath) {
- _this.files.remove(filePath);
- });
- this.watcher.watch();
- }
- if (!this.linterConfig && this.linterConfigFile) {
- this.linterConfig = IncrementalChecker.loadLinterConfig(this.linterConfigFile);
- if (this.linterConfig.linterOptions &&
- this.linterConfig.linterOptions.exclude) {
- // Pre-build minimatch patterns to avoid additional overhead later on.
- // Note: Resolving the path is required to properly match against the full file paths,
- // and also deals with potential cross-platform problems regarding path separators.
- this.linterExclusions = this.linterConfig.linterOptions.exclude.map(function (pattern) { return new minimatch.Minimatch(path.resolve(pattern)); });
- }
- }
- this.program = this.vue ? this.loadVueProgram() : this.loadDefaultProgram();
- if (this.linterConfig) {
- this.linter = IncrementalChecker.createLinter(this.program);
- }
- };
- IncrementalChecker.prototype.loadVueProgram = function () {
- this.programConfig =
- this.programConfig ||
- VueProgram_1.VueProgram.loadProgramConfig(this.typescript, this.programConfigFile, this.compilerOptions);
- return VueProgram_1.VueProgram.createProgram(this.typescript, this.programConfig, path.dirname(this.programConfigFile), this.files, this.watcher, this.program);
- };
- IncrementalChecker.prototype.loadDefaultProgram = function () {
- this.programConfig =
- this.programConfig ||
- IncrementalChecker.loadProgramConfig(this.typescript, this.programConfigFile, this.compilerOptions);
- return IncrementalChecker.createProgram(this.typescript, this.programConfig, this.files, this.watcher, this.program);
- };
- IncrementalChecker.prototype.hasLinter = function () {
- return this.linter !== undefined;
- };
- IncrementalChecker.prototype.getDiagnostics = function (cancellationToken) {
- var _this = this;
- var diagnostics = [];
- // select files to check (it's semantic check - we have to include all files :/)
- var filesToCheck = this.program.getSourceFiles();
- // calculate subset of work to do
- var workSet = new WorkSet_1.WorkSet(filesToCheck, this.workNumber, this.workDivision);
- // check given work set
- workSet.forEach(function (sourceFile) {
- if (cancellationToken) {
- cancellationToken.throwIfCancellationRequested();
- }
- var diagnosticsToRegister = _this
- .checkSyntacticErrors
- ? []
- .concat(_this.program.getSemanticDiagnostics(sourceFile, cancellationToken))
- .concat(_this.program.getSyntacticDiagnostics(sourceFile, cancellationToken))
- : _this.program.getSemanticDiagnostics(sourceFile, cancellationToken);
- diagnostics.push.apply(diagnostics, diagnosticsToRegister);
- });
- // normalize and deduplicate diagnostics
- return NormalizedMessage_1.NormalizedMessage.deduplicate(diagnostics.map(function (d) {
- return NormalizedMessage_1.NormalizedMessage.createFromDiagnostic(_this.typescript.flattenDiagnosticMessageText, d);
- }));
- };
- IncrementalChecker.prototype.getLints = function (cancellationToken) {
- var _this = this;
- if (!this.hasLinter()) {
- throw new Error('Cannot get lints - checker has no linter.');
- }
- // select files to lint
- var filesToLint = this.files
- .keys()
- .filter(function (filePath) {
- return !_this.files.getData(filePath).linted &&
- !IncrementalChecker.isFileExcluded(filePath, _this.linterExclusions);
- });
- // calculate subset of work to do
- var workSet = new WorkSet_1.WorkSet(filesToLint, this.workNumber, this.workDivision);
- // lint given work set
- workSet.forEach(function (fileName) {
- cancellationToken.throwIfCancellationRequested();
- try {
- _this.linter.lint(fileName, undefined, _this.linterConfig);
- }
- catch (e) {
- if (fs.existsSync(fileName) &&
- // check the error type due to file system lag
- !(e instanceof Error) &&
- !(e.constructor.name === 'FatalError') &&
- !(e.message && e.message.trim().startsWith('Invalid source file'))) {
- // it's not because file doesn't exist - throw error
- throw e;
- }
- }
- });
- // set lints in files register
- this.linter.getResult().failures.forEach(function (lint) {
- var filePath = lint.getFileName();
- _this.files.mutateData(filePath, function (data) {
- data.linted = true;
- data.lints.push(lint);
- });
- });
- // set all files as linted
- this.files.keys().forEach(function (filePath) {
- _this.files.mutateData(filePath, function (data) {
- data.linted = true;
- });
- });
- // get all lints
- var lints = this.files
- .keys()
- .reduce(function (innerLints, filePath) {
- return innerLints.concat(_this.files.getData(filePath).lints);
- }, []);
- // normalize and deduplicate lints
- return NormalizedMessage_1.NormalizedMessage.deduplicate(lints.map(NormalizedMessage_1.NormalizedMessage.createFromLint));
- };
- return IncrementalChecker;
- }());
- exports.IncrementalChecker = IncrementalChecker;
|