Skip to content

add new npm deps with improved gulp for dev #328

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Nov 30, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 24 additions & 37 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
// Available variables which can be used inside of strings.
// ${workspaceRoot}: the root folder of the team
// ${file}: the current opened file
// ${fileBasename}: the current opened file's basename
// ${fileDirname}: the current opened file's dirname
// ${fileExtname}: the current opened file's extension
// ${cwd}: the current working directory of the spawned process
// A task runner that calls a custom npm script that compiles the extension.
{
"version": "2.0.0",
"presentation": {
Expand All @@ -16,48 +8,49 @@
},
"tasks": [
{
"label": "compile",
"label": "Compile",
"type": "npm",
"script": "compile",
"group": "build",
"isBackground": true,
"problemMatcher": [
"$tsc",
{
"base": "$tslint5",
"fileLocation": "relative"
}
]
},
{
"type": "npm",
"script": "lint",
"problemMatcher": {
"base": "$tslint5",
"fileLocation": "relative"
],
"group": {
"kind": "build",
"isDefault": true
}
},
{
"type": "npm",
"script": "watch",
"isBackground": true,
"problemMatcher": "$tsc-watch"
},
{
"label": "Hygiene",
"type": "gulp",
"task": "hygiene",
"task": "hygiene-watch",
"isBackground": true,
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"problemMatcher": [
"$tsc",
{
"base": "$tslint5",
"fileLocation": "relative"
}
]
],
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "lint-staged",
"type": "npm",
"script": "lint-staged",
"label": "Hygiene (staged)",
"type": "gulp",
"task": "hygiene-staged",
"problemMatcher": [
"$tsc",
{
Expand All @@ -67,15 +60,9 @@
]
},
{
"label": "Hygiene (all)",
"type": "gulp",
"task": "hygiene-watch",
"isBackground": true,
"presentation": {
"echo": true,
"reveal": "always",
"focus": false,
"panel": "shared"
},
"task": "hygiene",
"problemMatcher": [
"$tsc",
{
Expand Down
218 changes: 158 additions & 60 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const tsfmt = require('typescript-formatter');
const tslint = require('tslint');
const relative = require('relative');
const ts = require('gulp-typescript');
const watch = require('gulp-watch');
const watch = require('gulp-debounced-watch');
const cp = require('child_process');
const colors = require('colors/safe');

Expand Down Expand Up @@ -42,7 +42,7 @@ const eolFilter = [
'!.vscodeignore',
'!LICENSE',
'!**/node_modules/**',
'!**/*.{svg,exe,png,bmp,scpt,bat,cmd,cur,ttf,woff,eot,txt,md,json,yml}',
'!**/*.{svg,exe,png,bmp,scpt,bat,cmd,cur,ttf,woff,eot,txt,md,json,yml,pyc}',
'!out/**/*',
'!images/**/*',
'!.vscode/**/*',
Expand Down Expand Up @@ -84,7 +84,21 @@ function reportFailures(failures) {
});
}

const hygiene = exports.hygiene = (some, options) => {

/**
* @typedef {Object} hygieneOptions - creates a new type named 'SpecialType'
* @property {boolean=} skipEOL - skipEOL check.
* @property {boolean=} skipIndentationCheck - Skip indentation checks.
* @property {boolean=} skipFormatCheck - Skip format checks.
*/

/**
*
* @param {string[]} some
* @param {hygieneOptions} options
* @returns {NodeJS.EventEmitter}
*/
const hygiene = (some, options) => {
options = options || {};
let errorCount = 0;
const eol = es.through(function (file) {
Expand Down Expand Up @@ -185,19 +199,29 @@ const hygiene = exports.hygiene = (some, options) => {
return tsProject(reporter);
}

const result = gulp.src(some || all, {
// Misc file checks.
let result = gulp.src(some || all, {
base: '.'
})
.pipe(filter(f => !f.stat.isDirectory()))
.pipe(filter(eolFilter))
.pipe(options.skipEOL ? es.through() : eol)
.pipe(filter(indentationFilter))
.pipe(indentation);
.pipe(filter(indentationFilter));

if (!options.skipIndentationCheck) {
result = result
.pipe(indentation);
}

// Type script checks.
let typescript = result
.pipe(filter(tslintFilter));

const typescript = result
.pipe(filter(tslintFilter))
.pipe(formatting)
.pipe(tsl)
if (!options.skipFormatCheck) {
typescript = typescript
.pipe(formatting);
}
typescript = typescript.pipe(tsl)
.pipe(tscFilesTracker)
.pipe(tsc());

Expand All @@ -211,68 +235,142 @@ const hygiene = exports.hygiene = (some, options) => {
}));
};

gulp.task('hygiene', () => hygiene());
exports.hygiene = hygiene;

gulp.task('hygiene', () => run({ mode: 'all', skipFormatCheck: true, skipIndentationCheck: true }));

gulp.task('hygiene-staged', () => run({ mode: 'changes' }));

gulp.task('hygiene-watch', ['hygiene-staged', 'hygiene-watch-runner']);

gulp.task('hygiene-watch', function () {
return watch(all, function () {
console.clear();
console.log('Checking hygiene...');
run(true, true);
gulp.task('hygiene-watch-runner', function () {
return watch(all, { events: ['add', 'change'] }, function (event) {
const start = new Date();
console.log(`[${start.toLocaleTimeString()}] Starting '${colors.cyan('hygiene-watch-runner')}'...`);
// Skip indentation and formatting checks to speed up linting.
return run({ mode: 'watch', skipFormatCheck: true, skipIndentationCheck: true })
.then(() => {
const end = new Date();
const time = (end.getTime() - start.getTime()) / 1000;
console.log(`[${end.toLocaleTimeString()}] Finished '${colors.cyan('hygiene-watch-runner')}' after ${time} seconds`);
});
});
});

function run(lintOnlyModifiedFiles, doNotExit) {
function exitProcessOnError(ex) {
console.error();
/**
* @typedef {Object} runOptions
* @property {boolean=} exitOnError - Exit on error.
* @property {'watch'|'changes'|'staged'|'all'} [mode=] - Mode.
* @property {string[]=} files - Optional list of files to be modified.
* @property {boolean=} skipIndentationCheck - Skip indentation checks.
* @property {boolean=} skipFormatCheck - Skip format checks.
*/

/**
* Run the linters.
* @param {runOptions} options
* @param {Error} ex
*/
function exitHandler(options, ex) {
console.error();
if (ex) {
console.error(ex);
console.error(colors.red(ex));
if (!doNotExit) {
process.exit(1);
}
if (lintOnlyModifiedFiles && doNotExit) {
console.log('Watching for changes...');
}
}
process.on('unhandledRejection', (reason, p) => {
if (options.exitOnError) {
process.exit(1);
}
if (options.mode === 'watch') {
console.log('Watching for changes...');
}
}

/**
* Run the linters.
* @param {runOptions} options
* @return {Promise<void>}
*/
function run(options) {
options = options ? options : {};
process.once('unhandledRejection', (reason, p) => {
console.log('Unhandled Rejection at: Promise', p, 'reason:', reason);
exitProcessOnError();
exitHandler(options);
});

cp.exec('git config core.autocrlf', (err, out) => {
const skipEOL = out.trim() === 'true';
if (!lintOnlyModifiedFiles && process.argv.length > 2) {
return hygiene(process.argv.slice(2), {
skipEOL: skipEOL
}).on('error', exitProcessOnError);
}
return getGitSkipEOL()
.then(skipEOL => {
if (typeof options.mode !== 'string' && process.argv.length > 2) {
return new Promise((resolve, reject) => {
return hygiene(process.argv.slice(2), {
skipEOL: skipEOL
})
.once('error', reject)
.once('end', resolve);
});
}

let filesPromise;
if (lintOnlyModifiedFiles) {
filesPromise = Promise.all([getCachedFiles(), getModifiedFiles()]).then(filesList => {
const files1 = filesList[0];
const files2 = filesList[1];
files2.forEach(file => {
if (files1.indexOf(file) === -1) {
files1.push(file);
}
return getFilesToProcess(options)
.then(files => {
return new Promise((resolve, reject) => {
hygiene(files, {
skipEOL: skipEOL,
skipFormatCheck: options.skipFormatCheck,
skipIndentationCheck: options.skipIndentationCheck
})
.once('end', () => {
if (options.mode === 'watch') {
console.log(colors.green('Hygiene passed with 0 errors 👍.'));
console.log('Watching for changes...');
}
resolve();
})
.once('error', reject);
});
});
return files1;
});
} else {
filesPromise = getCachedFiles();
})
.catch(exitHandler.bind(options));
}
function getGitSkipEOL() {
return new Promise(resolve => {
cp.exec('git config core.autocrlf', (err, out) => {
const skipEOL = out.trim() === 'true';
resolve(skipEOL);
});
});
}
/**
* Gets a list of files to be processed.
* @param {runOptions} options
* @return {Promise<string[]>}
*/
function getFilesToProcess(options) {
switch (options.mode) {
case 'all': {
return Promise.resolve(all);
}
case 'watch':
case 'changes': {
return Promise.all([getCachedFiles(), getModifiedFiles()])
.then(filesList => mergeFiles(filesList[0], filesList[1]));
}
default: {
return getCachedFiles();
}
}
}
/**
* Merges a list of files.
* @param {string[]} files1
* @param {string[]} files2
*/
function mergeFiles(files1, files2) {
const files = files2.slice();
files.forEach(file => {
if (files.indexOf(file) === -1) {
files.push(file);
}
filesPromise.then(files => {
hygiene(files, {
skipEOL: skipEOL
})
.on('end', () => {
if (lintOnlyModifiedFiles && doNotExit) {
console.log(colors.green('Hygiene passed with 0 errors 👍.'));
console.log('Watching for changes...');
}
})
.on('error', exitProcessOnError);
}).catch(exitProcessOnError);
});
return files;
}
function getCachedFiles() {
return new Promise(resolve => {
Expand Down Expand Up @@ -306,5 +404,5 @@ function getModifiedFiles() {
}
// this allows us to run hygiene as a git pre-commit hook.
if (require.main === module) {
run();
run({ exitOnError: true, mode: 'staged' });
}
Loading