diff --git a/build/gulpfile.hygiene.js b/build/gulpfile.hygiene.js index edefbf721a4..2881697ecd8 100644 --- a/build/gulpfile.hygiene.js +++ b/build/gulpfile.hygiene.js @@ -13,6 +13,8 @@ const gulpeslint = require('gulp-eslint'); const tsfmt = require('typescript-formatter'); const tslint = require('tslint'); const vfs = require('vinyl-fs'); +const path = require('path'); +const fs = require('fs'); /** * Hygiene works by creating cascading subsets of all our files and @@ -219,14 +221,55 @@ const hygiene = exports.hygiene = (some, options) => { }); }); - const program = tslint.Linter.createProgram('src/tsconfig.json'); + let linterForProgram = {}; // maps tslint programs to its corresponding Linter const configuration = tslint.Configuration.findConfiguration('tslint-hygiene.json', '.'); - const tslintOptions = { fix: false, formatter: 'json' }; - const linter = new tslint.Linter(tslintOptions, program); + + function createLinter(tsconfig) { + const program = tslint.Linter.createProgram(tsconfig); + const tslintOptions = { fix: false, formatter: 'json' }; + return new tslint.Linter(tslintOptions, program); + } + + function findTsConfig(segments) { + let fsPath = segments.reduce((p, each) => path.join(p, each)); + let tsconfig = path.join(fsPath, 'tsconfig.json'); + if (fs.existsSync(tsconfig)) { + return tsconfig; + } else if (segments.length > 1) { + segments.splice(-1, 1); + return findTsConfig(segments); + } else { + return undefined; + } + } + + function getLinter(file) { + let segments = file.relative.split(path.sep); + + // hard code the location of the tsconfig.json for the source folder to eliminate the lookup for the tsconfig.json + if (segments[0] === 'src') { + if (!linterForProgram['src']) { + linterForProgram['src'] = createLinter('src/tsconfig.json'); + } + return linterForProgram['src']; + } + else { + segments.splice(-1, 1); + let tsconfig = findTsConfig(segments); + if (!tsconfig) { + return undefined; + } + if (!linterForProgram[tsconfig]) { + linterForProgram[tsconfig] = createLinter(tsconfig); + } + return linterForProgram[tsconfig]; + } + } const tsl = es.through(function (file) { const contents = file.contents.toString('utf8'); - if (file.relative.startsWith('src/')) { // only lint files in src program + let linter = getLinter(file); + if (linter) { linter.lint(file.relative, contents, configuration.results); } this.emit('data', file); @@ -263,18 +306,19 @@ const hygiene = exports.hygiene = (some, options) => { }, function () { process.stdout.write('\n'); - const tslintResult = linter.getResult(); - if (tslintResult.failures.length > 0) { - for (const failure of tslintResult.failures) { - const name = failure.getFailure() || failure.getFileName; - const position = failure.getStartPosition(); - const line = position.getLineAndCharacter().line; - const character = position.getLineAndCharacter().character; + for (let linter in linterForProgram) { + const tslintResult = linterForProgram[linter].getResult(); + if (tslintResult.failures.length > 0) { + for (const failure of tslintResult.failures) { + const name = failure.getFileName(); + const position = failure.getStartPosition(); + const line = position.getLineAndCharacter().line; + const character = position.getLineAndCharacter().character; - console.error(`${name}:${line + 1}:${character + 1}:${failure.getFailure()}`); + console.error(`${name}:${line + 1}:${character + 1}:${failure.getFailure()}`); + } + errorCount += tslintResult.failures.length; } - - errorCount += tslintResult.failures.length; } if (errorCount > 0) {