chore: add ESLint Lodash plugin (#1148)

This is one step towards enforcing the linter until we barely have to
check for style issues on code reviews.

Signed-off-by: Juan Cruz Viotti <jviotti@openmailbox.org>
This commit is contained in:
Juan Cruz Viotti 2017-03-08 19:11:15 -04:00 committed by GitHub
parent 6c8bc117ab
commit df8611df11
18 changed files with 192 additions and 52 deletions

View File

@ -4,6 +4,8 @@ env:
es6: true
node: true
mocha: true
plugins:
- lodash
extends: 'eslint:recommended'
rules:
@ -571,3 +573,75 @@ rules:
- error
- before: true
after: false
# Lodash
lodash/chain-style:
- error
- explicit
lodash/identity-shorthand:
- error
- always
lodash/import-scope:
- error
- full
lodash/matches-prop-shorthand:
- error
- always
lodash/matches-shorthand:
- error
- always
lodash/no-commit:
- error
lodash/path-style:
- error
- array
lodash/prefer-compact:
- error
lodash/prefer-filter:
- error
- 5
lodash/prefer-flat-map:
- error
lodash/prefer-invoke-map:
- error
lodash/prefer-map:
- error
lodash/prefer-reject:
- error
lodash/prefer-thru:
- error
lodash/prefer-wrapper-method:
- error
lodash/prop-shorthand:
- error
- always
lodash/prefer-constant:
- error
- true
- true
lodash/prefer-get:
- error
- 2
lodash/prefer-includes:
- error
- includeNative: true
lodash/prefer-is-nil:
- error
lodash/prefer-lodash-chain:
- error
lodash/prefer-lodash-method:
- error
lodash/prefer-lodash-typecheck:
- error
lodash/prefer-matches:
- error
- 3
lodash/prefer-noop:
- error
lodash/prefer-over-quantifier:
- error
lodash/prefer-startswith:
- error
lodash/prefer-times:
- error

View File

@ -127,9 +127,10 @@ return isElevated().then((elevated) => {
// Translate the current arguments to point to the AppImage
// Relative paths are resolved from `/tmp/.mount_XXXXXX/usr`
const translatedArguments = _.map(_.tail(process.argv), (argv) => {
return argv.replace(path.join(process.env.APPDIR, 'usr/'), '');
});
const translatedArguments = _.chain(process.argv)
.tail()
.invokeMap('replace', path.join(process.env.APPDIR, 'usr/'), '')
.value();
return commandPrefix
.concat([ process.env.APPIMAGE ])

View File

@ -43,18 +43,14 @@ exports.HUMAN_FRIENDLY = {
* @memberof HUMAN_FRIENDLY
* @returns {String} message
*/
EPERM: () => {
return 'You\'re not authorized to perform this operation';
},
EPERM: _.constant('You\'re not authorized to perform this operation'),
/**
* @property {Function} EACCES
* @memberof HUMAN_FRIENDLY
* @returns {String} message
*/
EACCES: () => {
return 'You\'re don\'t have access to this resource';
}
EACCES: _.constant('You don\'t have access to this resource')
/* eslint-enable new-cap */

View File

@ -189,7 +189,7 @@ FlashState.service('FlashStateModel', function() {
* }
*/
this.wasLastFlashCancelled = () => {
return _.get(this.getFlashResults(), 'cancelled', false);
return _.get(this.getFlashResults(), [ 'cancelled' ], false);
};
/**

View File

@ -111,7 +111,7 @@ SelectionStateModel.service('SelectionStateModel', function(DrivesModel) {
* const image = SelectionStateModel.getImage();
*/
this.getImage = () => {
return _.get(Store.getState().toJS(), 'selection.image');
return _.get(Store.getState().toJS(), [ 'selection', 'image' ]);
};
/**
@ -125,7 +125,11 @@ SelectionStateModel.service('SelectionStateModel', function(DrivesModel) {
* const imagePath = SelectionStateModel.getImagePath();
*/
this.getImagePath = () => {
return _.get(Store.getState().toJS(), 'selection.image.path');
return _.get(Store.getState().toJS(), [
'selection',
'image',
'path'
]);
};
/**
@ -139,7 +143,11 @@ SelectionStateModel.service('SelectionStateModel', function(DrivesModel) {
* const imageSize = SelectionStateModel.getImageSize();
*/
this.getImageSize = () => {
return _.get(Store.getState().toJS(), 'selection.image.size');
return _.get(Store.getState().toJS(), [
'selection',
'image',
'size'
]);
};
/**
@ -153,7 +161,11 @@ SelectionStateModel.service('SelectionStateModel', function(DrivesModel) {
* const imageUrl = SelectionStateModel.getImageUrl();
*/
this.getImageUrl = () => {
return _.get(Store.getState().toJS(), 'selection.image.url');
return _.get(Store.getState().toJS(), [
'selection',
'image',
'url'
]);
};
/**
@ -167,7 +179,11 @@ SelectionStateModel.service('SelectionStateModel', function(DrivesModel) {
* const imageName = SelectionStateModel.getImageName();
*/
this.getImageName = () => {
return _.get(Store.getState().toJS(), 'selection.image.name');
return _.get(Store.getState().toJS(), [
'selection',
'image',
'name'
]);
};
/**
@ -181,7 +197,11 @@ SelectionStateModel.service('SelectionStateModel', function(DrivesModel) {
* const imageLogo = SelectionStateModel.getImageLogo();
*/
this.getImageLogo = () => {
return _.get(Store.getState().toJS(), 'selection.image.logo');
return _.get(Store.getState().toJS(), [
'selection',
'image',
'logo'
]);
};
/**
@ -195,7 +215,11 @@ SelectionStateModel.service('SelectionStateModel', function(DrivesModel) {
* const imageSupportUrl = SelectionStateModel.getImageSupportUrl();
*/
this.getImageSupportUrl = () => {
return _.get(Store.getState().toJS(), 'selection.image.supportUrl');
return _.get(Store.getState().toJS(), [
'selection',
'image',
'supportUrl'
]);
};
/**
@ -209,7 +233,11 @@ SelectionStateModel.service('SelectionStateModel', function(DrivesModel) {
* const imageRecommendedDriveSize = SelectionStateModel.getImageRecommendedDriveSize();
*/
this.getImageRecommendedDriveSize = () => {
return _.get(Store.getState().toJS(), 'selection.image.recommendedDriveSize');
return _.get(Store.getState().toJS(), [
'selection',
'image',
'recommendedDriveSize'
]);
};
/**
@ -316,7 +344,7 @@ SelectionStateModel.service('SelectionStateModel', function(DrivesModel) {
return false;
}
return drive === _.get(this.getDrive(), 'device');
return drive === _.get(this.getDrive(), [ 'device' ]);
};
});

View File

@ -75,6 +75,30 @@ const ACTIONS = _.fromPairs(_.map([
return [ message, message ];
}));
/**
* @summary Find a drive from the list of available drives
* @function
* @private
*
* @param {Object} state - application state
* @param {String} device - drive device
* @returns {(Object|Undefined)} drive
*
* @example
* const drive = findDrive(state, '/dev/disk2');
*/
const findDrive = (state, device) => {
/* eslint-disable lodash/prefer-lodash-method */
return state.get('availableDrives').find((drive) => {
return drive.get('device') === device;
});
/* eslint-enable lodash/prefer-lodash-method */
};
/**
* @summary The redux store reducer
* @function
@ -156,7 +180,7 @@ const storeReducer = (state = DEFAULT_STATE, action) => {
throw new Error(`Invalid state type: ${action.data.type}`);
}
if (_.isUndefined(action.data.percentage) || _.isNull(action.data.percentage)) {
if (_.isNil(action.data.percentage)) {
throw new Error('Missing state percentage');
}
@ -172,7 +196,7 @@ const storeReducer = (state = DEFAULT_STATE, action) => {
throw new Error(`Invalid state eta: ${action.data.eta}`);
}
if (_.isUndefined(action.data.speed) || _.isNull(action.data.speed)) {
if (_.isNil(action.data.speed)) {
throw new Error('Missing state speed');
}
@ -231,9 +255,7 @@ const storeReducer = (state = DEFAULT_STATE, action) => {
throw new Error(`Invalid drive: ${action.data}`);
}
const selectedDrive = state.get('availableDrives').find((drive) => {
return drive.get('device') === action.data;
});
const selectedDrive = findDrive(state, action.data);
if (!selectedDrive) {
throw new Error(`The drive is not available: ${action.data}`);
@ -280,10 +302,7 @@ const storeReducer = (state = DEFAULT_STATE, action) => {
throw new Error(`Invalid image logo: ${action.data.logo}`);
}
const selectedDevice = state.getIn([ 'selection', 'drive' ]);
const selectedDrive = state.get('availableDrives').find((drive) => {
return drive.get('device') === selectedDevice;
});
const selectedDrive = findDrive(state, state.getIn([ 'selection', 'drive' ]));
return _.attempt(() => {
if (selectedDrive && !_.every([

View File

@ -42,8 +42,8 @@ SupportedFormats.service('SupportedFormatsModel', function() {
*/
const getExtensionsFromTypeGetter = (type) => {
return () => {
return _.map(_.filter(imageStream.supportedFileTypes, (fileType) => {
return fileType.type === type;
return _.map(_.filter(imageStream.supportedFileTypes, {
type
}), 'extension');
};
};

View File

@ -159,7 +159,7 @@ analytics.service('AnalyticsService', function($log, $window, $mixpanel, Setting
* }
*/
this.shouldReportError = (error) => {
return !_.has(error, 'report') || Boolean(error.report);
return !_.has(error, [ 'report' ]) || Boolean(error.report);
};
/**

View File

@ -37,10 +37,15 @@ driveScanner.factory('DriveScannerService', (SettingsModel) => {
const DRIVE_SCANNER_FIRST_SCAN_DELAY_MS = 0;
const emitter = new EventEmitter();
/* eslint-disable lodash/prefer-lodash-method */
const availableDrives = Rx.Observable.timer(
DRIVE_SCANNER_FIRST_SCAN_DELAY_MS,
DRIVE_SCANNER_INTERVAL_MS
)
/* eslint-enable lodash/prefer-lodash-method */
.flatMap(() => {
return Rx.Observable.fromNodeCallback(drivelist.list)();
})
@ -63,8 +68,8 @@ driveScanner.factory('DriveScannerService', (SettingsModel) => {
return drives;
}
return _.reject(drives, (drive) => {
return drive.system;
return _.reject(drives, {
system: true
});
})
.pausable(new Rx.Subject());

View File

@ -26,6 +26,11 @@
const angular = require('angular');
const MODULE_NAME = 'Etcher.Utils.ByteSize';
const ByteSize = angular.module(MODULE_NAME, []);
/* eslint-disable lodash/prefer-lodash-method */
ByteSize.filter('gigabyte', require('./filters/gigabyte'));
/* eslint-enable lodash/prefer-lodash-method */
module.exports = MODULE_NAME;

View File

@ -26,6 +26,11 @@
const angular = require('angular');
const MODULE_NAME = 'Etcher.Utils.Path';
const Path = angular.module(MODULE_NAME, []);
/* eslint-disable lodash/prefer-lodash-method */
Path.filter('basename', require('./filters/basename'));
/* eslint-enable lodash/prefer-lodash-method */
module.exports = MODULE_NAME;

View File

@ -51,8 +51,8 @@ exports.getEntries = (archive) => {
const EMPTY_ENTRY_SIZE = 0;
return resolve(_.chain(zip.entries())
.omitBy((entry) => {
return entry.size === EMPTY_ENTRY_SIZE;
.omitBy({
size: EMPTY_ENTRY_SIZE
})
.map((metadata) => {
return {

View File

@ -39,5 +39,5 @@ exports.getArchiveMimeType = (file) => {
const MAGIC_NUMBER_BUFFER_END = 261;
const chunk = readChunk.sync(file, MAGIC_NUMBER_BUFFER_START, MAGIC_NUMBER_BUFFER_END);
return _.get(archiveType(chunk), 'mime', 'application/octet-stream');
return _.get(archiveType(chunk), [ 'mime' ], 'application/octet-stream');
};

View File

@ -49,7 +49,7 @@ const UNKNOWN_SIZE = 0;
* }
*/
exports.isDriveLocked = (drive) => {
return Boolean(_.get(drive, 'protected', false));
return Boolean(_.get(drive, [ 'protected' ], false));
};
/**
@ -71,7 +71,7 @@ exports.isDriveLocked = (drive) => {
* }
*/
exports.isSystemDrive = (drive) => {
return Boolean(_.get(drive, 'system', false));
return Boolean(_.get(drive, [ 'system' ], false));
};
/**
@ -108,8 +108,8 @@ exports.isSystemDrive = (drive) => {
* }
*/
exports.isSourceDrive = (drive, image) => {
const mountpoints = _.get(drive, 'mountpoints', []);
const imagePath = _.get(image, 'path');
const mountpoints = _.get(drive, [ 'mountpoints' ], []);
const imagePath = _.get(image, [ 'path' ]);
if (!imagePath || _.isEmpty(mountpoints)) {
return false;
@ -142,7 +142,7 @@ exports.isSourceDrive = (drive, image) => {
* }
*/
exports.isDriveLargeEnough = (drive, image) => {
return _.get(drive, 'size', UNKNOWN_SIZE) >= _.get(image, 'size', UNKNOWN_SIZE);
return _.get(drive, [ 'size' ], UNKNOWN_SIZE) >= _.get(image, [ 'size' ], UNKNOWN_SIZE);
};
/**
@ -206,5 +206,5 @@ exports.isDriveValid = (drive, image) => {
* }
*/
exports.isDriveSizeRecommended = (drive, image) => {
return _.get(drive, 'size', UNKNOWN_SIZE) >= _.get(image, 'recommendedDriveSize', UNKNOWN_SIZE);
return _.get(drive, [ 'size' ], UNKNOWN_SIZE) >= _.get(image, [ 'recommendedDriveSize' ], UNKNOWN_SIZE);
};

View File

@ -32,7 +32,7 @@ const _ = require('lodash');
* }
*/
exports.isEnabled = (environment) => {
const value = _.get(environment, 'ETCHER_CLI_ROBOT', false);
const value = _.get(environment, [ 'ETCHER_CLI_ROBOT' ], false);
return Boolean(value === 'false' ? false : value);
};
@ -177,7 +177,7 @@ exports.recomposeErrorMessage = (message) => {
* > 'foo'
*/
exports.getCommand = (message) => {
return _.get(message, 'command');
return _.get(message, [ 'command' ]);
};
/**
@ -200,7 +200,7 @@ exports.getCommand = (message) => {
* > { foo: 1 }
*/
exports.getData = (message) => {
return _.get(message, 'data', {});
return _.get(message, [ 'data' ], {});
};
/**

View File

@ -112,6 +112,7 @@
"electron-packager": "^7.0.1",
"electron-prebuilt": "1.4.4",
"eslint": "^3.16.1",
"eslint-plugin-lodash": "^2.3.5",
"file-exists": "^1.0.0",
"html-angular-validate": "^0.1.9",
"jsonfile": "^2.3.1",

View File

@ -90,7 +90,7 @@ describe('CLI: Errors', function() {
it('should provide a friendly message for EACCES', function() {
const error = new Error('foo bar');
error.code = 'EACCES';
const message = 'EACCES: You\'re don\'t have access to this resource';
const message = 'EACCES: You don\'t have access to this resource';
m.chai.expect(errors.getErrorMessage(error)).to.equal(message);
});

View File

@ -16,6 +16,8 @@
'use strict';
const _ = require('lodash');
module.exports = {
subjectParser: 'angular',
@ -40,16 +42,20 @@ module.exports = {
},
transformTemplateData: (data) => {
data.features = data.commits.filter((commit) => {
return commit.subject.type === 'feat';
data.features = _.filter(data.commits, {
subject: {
type: 'feat'
}
});
data.fixes = data.commits.filter((commit) => {
return commit.subject.type === 'fix';
data.fixes = _.filter(data.commits, {
subject: {
type: 'fix'
}
});
data.misc = data.commits.filter((commit) => {
return ![ 'fix', 'feat' ].includes(commit.subject.type);
data.misc = _.filter(data.commits, (commit) => {
return !_.includes([ 'fix', 'feat' ], commit.subject.type);
});
return data;