Giter VIP home page Giter VIP logo

eslint-plugin-lodash-fp's Introduction

eslint-plugin-lodash-fp Build Status

ESLint rules for lodash/fp

Install

$ npm install --save-dev eslint eslint-plugin-lodash-fp

Usage

Configure it in package.json.

{
  "name": "my-awesome-project",
  "eslintConfig": {
    "env": {
      "es6": true
    },
    "parserOptions": {
      "ecmaVersion": 7,
      "sourceType": "module"
    },
    "plugins": [
      "lodash-fp"
    ],
    "rules": {
      "lodash-fp/consistent-compose": "off",
      "lodash-fp/consistent-name": [
        "error",
        "_"
      ],
      "lodash-fp/no-argumentless-calls": "error",
      "lodash-fp/no-chain": "error",
      "lodash-fp/no-extraneous-args": "error",
      "lodash-fp/no-extraneous-function-wrapping": "error",
      "lodash-fp/no-extraneous-iteratee-args": "error",
      "lodash-fp/no-extraneous-partials": "off",
      "lodash-fp/no-for-each": "off",
      "lodash-fp/no-partial-of-curried": "error",
      "lodash-fp/no-single-composition": "error",
      "lodash-fp/no-submodule-destructuring": "error",
      "lodash-fp/no-unused-result": "error",
      "lodash-fp/prefer-compact": "error",
      "lodash-fp/prefer-composition-grouping": "error",
      "lodash-fp/prefer-constant": [
        "error",
        {
          "arrowFunctions": false
        }
      ],
      "lodash-fp/prefer-flat-map": "error",
      "lodash-fp/prefer-get": "error",
      "lodash-fp/prefer-identity": [
        "error",
        {
          "arrowFunctions": false
        }
      ],
      "lodash-fp/preferred-alias": "off",
      "lodash-fp/use-fp": "error"
    }
  }
}

Rules

Recommended configuration

This plugin exports a recommended configuration that enforces good practices.

To enable this configuration, use the extends property in your package.json.

{
	"name": "my-awesome-project",
	"eslintConfig": {
		"extends": "plugin:lodash-fp/recommended"
	}
}

See ESLint documentation for more information about extending configuration files.

MIT ยฉ Jeroen Engels

eslint-plugin-lodash-fp's People

Contributors

dependabot[bot] avatar dfadler avatar friday avatar graingert avatar iddan avatar izaakschroeder avatar jfmengels avatar kavsingh avatar knpwrs avatar mapreal19 avatar marcusvmsa avatar re1ro avatar rpadovani avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

eslint-plugin-lodash-fp's Issues

`no-single-composition` rule

Require composition methods to have at least two functions passed to it.
(Might as well check that it doesn't have 0)

Fail

_.flow(fn);

Good

_.flow(fn1, fn2);

`no-lodash-foreach` rule

Forbid the use of _.forEach, _.each, _.eachRight and _.forEachRight.
Purpose: Prevent the use of side-effects, and favor _.map, _.reduce instead.

Fail

import _, {forEach} from 'lodash/fp';
forEach(fn, array);
_.forEach(fn, array);

no unused result false positive

import _ from 'lodash/fp';
import assign from 'lodash';
import { someFn } from './utils';

class Foo {
    constructor() {
        assign(this, someFn());
    }
}

it thinks that assign is unused here, even though it mutates (because it is from lodash, not lodash/fp)

Invalid JS triggers error of "Cannot read property 'type' of null

For example, this:

export function foo(bar) {
  return 
}

Results in this:

Cannot read property 'type' of null
TypeError: Cannot read property 'type' of null
    at Object.isIdentityFunction (/Users/work/Code/tradavo/visuality-js/node_modules/eslint-plugin-lodash-fp/rules/core/ast-util.js:108:25)
    at Linter.handleFunctionExpression (/Users/work/Code/tradavo/visuality-js/node_modules/eslint-plugin-lodash-fp/rules/prefer-identity.js:10:17)
    at emitOne (events.js:120:20)
    at Linter.emit (events.js:210:7)
    at NodeEventGenerator.applySelector (/Users/work/Code/tradavo/visuality-js/node_modules/eslint/lib/util/node-event-generator.js:265:26)
    at NodeEventGenerator.applySelectors (/Users/work/Code/tradavo/visuality-js/node_modules/eslint/lib/util/node-event-generator.js:294:22)
    at NodeEventGenerator.enterNode (/Users/work/Code/tradavo/visuality-js/node_modules/eslint/lib/util/node-event-generator.js:308:14)
    at CodePathAnalyzer.enterNode (/Users/work/Code/tradavo/visuality-js/node_modules/eslint/lib/code-path-analysis/code-path-analyzer.js:602:23)
    at Traverser.enter (/Users/work/Code/tradavo/visuality-js/node_modules/eslint/lib/linter.js:925:36)
    at Traverser.__execute (/Users/work/Code/tradavo/visuality-js/node_modules/estraverse/estraverse.js:397:31)
error Command failed with exit code 1.

This is only annoying in a CLI run of eslint, but a showstopper for people running eslint continuously in an editor, e.g., VS Code, where every single keystroke results in an error popover during normal code entry/typing.

`prefer-composition` rule

Use composition methods (_.compose, _.flow, ...) instead of chaining multiple map/filter/reduce/... array methods

a.map(fn1).filter(fn2).every(fn3);
// -->
_.flow(_.map(fn1), _.filter(fn2), _.every(fn3))(a);
// or
_.compose(_.every(fn3), _.filter(fn2), _.map(fn1))(a);

In the documentation, there should be a section saying that this should probably not be used with projects that use Observables, as it will create a lot of false positives.

Exclude bindAll from no-unused-result

The bindAll method is one that is intended to cause side effects by design and should be added to the array of methds excluded from no-unused-result.

`no-partial-of-curried` rule

(Name to be improved)

Forbid the use _.partial when the method you're applying it to is curried.

Example

const fn = _.partial(_.get, 'path'); // --> This is useless, could have done `_.get('path')`
const fn = _.partial(_.get, 'path', object);
// --> This will create a function that when called with of arguments, will simply return the function. Probably not the expected behavior.

`consistent-name` rule

Enforce a consistent name for the imported Lodash, with _ as the default.
Only applies to the default import, not of any cherrypicked method.

Fail

import lodash from 'lodash';
import foo from 'lodash/fp';
var bar = require('lodash');
var baz = require('lodash/fp');

Pass

import _ from 'lodash';
import _ from 'lodash/fp';
var _ = require('lodash');
var _ = require('lodash/fp');

/* eslint lodash-fp/consistent-name: ["error", "fp"] */
var fp = require('lodash/fp');

Cannot read property 'name' of undefined

Hey there, thanks for the great plugin. Am getting an error I can't seem to resolve when editing in Atom / Sublime Text.

Using Node 6

The error

Error: Cannot read property 'name' of undefined
TypeError: Cannot read property 'name' of undefined
    at isRequireOfLodashSubModule (/Users/kav/Sites/playground/animplay/node_modules/eslint-plugin-lodash-fp/rules/no-submodule-destructuring.js:16:21)
    at Object.info.merge.VariableDeclarator (/Users/kav/Sites/playground/animplay/node_modules/eslint-plugin-lodash-fp/rules/no-submodule-destructuring.js:34:52)
    at EventEmitter.predefinedRules.(anonymous function) (/Users/kav/Sites/playground/animplay/node_modules/eslint-plugin-lodash-fp/rules/core/enhance.js:86:34)
    at emitOne (events.js:82:20)
    at EventEmitter.emit (events.js:169:7)
    at NodeEventGenerator.enterNode (/Users/kav/Sites/playground/animplay/node_modules/eslint/lib/util/node-event-generator.js:40:22)
    at CodePathAnalyzer.enterNode (/Users/kav/Sites/playground/animplay/node_modules/eslint/lib/code-path-analysis/code-path-analyzer.js:607:23)
    at CommentEventGenerator.enterNode (/Users/kav/Sites/playground/animplay/node_modules/eslint/lib/util/comment-event-generator.js:97:23)
    at Controller.traverser.traverse.enter (/Users/kav/Sites/playground/animplay/node_modules/eslint/lib/eslint.js:886:36)
    at Controller.__execute (/Users/kav/Sites/playground/animplay/node_modules/estraverse/estraverse.js:397:31)

Import in the offending file

import { curry, find, flow, get, head, map } from 'lodash/fp';
import bodymovin from 'bodymovin';

/**
 * @type {number}
 */
const SEGMENT_LENGTH_SECONDS = 1;

...

eslintrc.yml

extends: [airbnb-base]
parser: babel-eslint
parserOptions: { ecmaVersion: 7, sourceType: module }
plugins: [babel, lodash-fp]
rules:
  babel/generator-star-spacing: 1
  babel/new-cap: 1
  babel/object-shorthand: 1
  babel/no-await-in-loop: 1
  lodash-fp/consistent-compose: [error, flow]
  lodash-fp/consistent-name: [error, _]
  lodash-fp/no-argumentless-calls: error
  lodash-fp/no-chain: error
  lodash-fp/no-extraneous-function-wrapping: error
  lodash-fp/no-single-composition: error
  lodash-fp/no-submodule-destructuring: error
  lodash-fp/prefer-compact: error
  lodash-fp/prefer-composition-grouping: error
  lodash-fp/prefer-constant: [error, { arrowFunctions: false }]
  lodash-fp/prefer-flat-map: error
  lodash-fp/prefer-get: error
  lodash-fp/prefer-identity: [error, { arrowFunctions: false }]
  lodash-fp/use-fp: error

package.json dev dependencies

"devDependencies": {
  "autoprefixer": "^6.3.6",
  "ava": "^0.14.0",
  "babel-core": "^6.7.7",
  "babel-eslint": "^6.0.4",
  "babel-loader": "^6.2.4",
  "babel-plugin-lodash": "^2.3.0",
  "babel-plugin-transform-es2015-modules-commonjs": "^6.7.7",
  "babel-plugin-transform-runtime": "^6.7.5",
  "babel-preset-es2015-webpack": "^6.4.1",
  "babel-preset-stage-0": "^6.5.0",
  "babel-register": "^6.7.2",
  "css-loader": "^0.23.1",
  "eslint": "^2.9.0",
  "eslint-config-airbnb-base": "^2.0.0",
  "eslint-plugin-babel": "^3.2.0",
  "eslint-plugin-import": "^1.6.1",
  "eslint-plugin-lodash-fp": "^1.1.1",
  "extract-text-webpack-plugin": "^1.0.1",
  "file-loader": "^0.8.5",
  "html-webpack-plugin": "^2.16.0",
  "json-loader": "^0.5.4",
  "postcss-loader": "^0.9.1",
  "promise-loader": "^1.0.0",
  "rimraf": "^2.5.2",
  "style-loader": "^0.13.1",
  "webpack": "^2.1.0-beta.6",
  "webpack-dev-server": "^2.0.0-beta"
},

Also tried using this eslint config:

extends: [airbnb-base, 'plugin:lodash-fp/recommended']
parser: babel-eslint
parserOptions: { ecmaVersion: 7, sourceType: module }
plugins: [babel, lodash-fp]
rules:
  babel/generator-star-spacing: 1
  babel/new-cap: 1
  babel/object-shorthand: 1
  babel/no-await-in-loop: 1

Did not fix it, instead an additional error is thrown in files that linted fine before:

Definition for rule 'lodash-fp/prefer-identify' was not found

Example of an offending import:

import { map, zipObject } from 'lodash/fp';

async function animationLoader(name) ...

Same things happen when I remove all rules and babel plugin from eslintrc.

Thanks heaps!

`use-currying` rule

(Name to be improved)

Make use of the fact that Lodash/fp methods are curried.

a.map((y) => _.eq(x, y))
// -->
a.map(_.eq(x))

a.map((x) => _.divide(x, y))
// -->
a.map(_.divide(_, y))

Looking for open source projects using Lodash FP

I'm looking for open-source projects that use Lodash FP, to test this plugin on.
I currently have a lack of real world project that uses it that I can test the rules on, which leads to me not being able to detect errors as early as I would like to.

Any project would do, but the more it uses it, the better.

TypeError: info.name.replace is not a function, when using eslint-watch

I get the following error when using eslint-watch, and I can't figure out why and how to solve it.

TypeError: info.name.replace is not a function
    at buildInfo (C:\Projects\careconsultation\CareConsultationServer\CareConsultation.WebApp\node_modules\eslint-plugin-lodash-fp\rules\core\lodash-util.js:17:28)

Rule `no-incorrect-submodule`

This rule should throw an error when importing a named export or destructuring a required module, when the module is a Lodash method path

Fail

import {find} from 'lodash/find';
import {find as f} from 'lodash/find';
import {find} from 'lodash/fp/find';
var {find} = require('lodash/find');
var {find: f} = require('lodash/find');
var {find} = require('lodash/fp/find');

Pass

import {find} from 'lodash';
import {find as f} from 'lodash';
import {find} from 'lodash/fp';
import find from 'lodash/find';
import find from 'lodash/fp/find';
var {find} = require('lodash');
var {find: f} = require('lodash');
var {find} = require('lodash/fp');
var find = require('lodash/find');
var find = require('lodash/fp/find');

(if someone has a better name for it, let me know)

`no-extraneous-function-wrapping` option to curry/partially apply a function

Add an option to no-extraneous-function-wrapping to error when a function, wrapping a non-Lodash function, can be made extraneous using curry.

Options

This rule supports the following options:

curry (name TBD...): When set to true, will lint an error even for non-Lodash functions, encouraging the practice of methods like _.curry, _.partial. Default is false. Note that this will probably lead to more false positives, as in some cases:

  • it will not be possible (adding a last function argument to _.flow/_compose)
  • or will need additional safe-guards like _.ary. For instance, array.map(parseInt) will probably cause you unexpected behavior, as parseInt will get called with parseInt(value, index) and parseInt takes two parameters (value and radix). Most Lodash-fp methods such as map therefore only pass one argument to their iteratee.

You can set the option in configuration like this:

"lodash-fp/no-extraneous-function-wrapping": ["error", {"curry": true}]
a.map((y) => foo(x, y))

// -->

// either
var _foo = _.curry(foo)
a.map(_foo(x))

// or
var _foo = _.partial(foo, x)
a.map(_foo)

a.map((x) => foo(x, y))
// -->
var _foo = _.curry(foo)
a.map(_foo(_, x))
// or
var _foo = _.partial(foo, _, y)
a.map(_foo);

Another option "placeholder": true could be given to enhance the normal and the curryed behavior by using a Lodash placeholder for curried functions

a.map((x) => _.find(x, y))
// -->
a.map(_.find(_, y))

// With `curry`
a.map((x) => foo(x, y))
// -->
a.map(_.curry(foo)(_, y))
// or
a.map(_.partial(foo, _, y))

correct function arg order

When simple static analysis can trivially work out that the argument order is obviously wrong:

// good
_.map(x => x.y, vals);

// bad
_.map(vals, x => x.y);

// bad
_.map([a, b, c], eg);

// ok - unnecessary wrap should catch it though.
function foo(vals, f) {
  return _.map(vals, f);
}

// ok - undefined var should catch it.
_.map(vals, ff);

// ok - nothing you can do about this, you're 'pwnd'.
const fff = getFn();
_.map(vals, fff);

// bad
function ffff(x) {
  return x.y;
}

_.map(vals, ffff);

`no-extraneous-args` better report methods with alternatives

I figure that for a lot of people starting with Lodash/fp will try stuff like _.get(defaultValue, path, object) with arguments in some order, only to find out that it has its arity fixed at 2.

With no-extraneous-args, you get a warning that one of the arguments will be ignored. What would be nice, is to take it one step further and to check if the method has an alias that doesn't ignore that argument.

Example:

`_.get(defaultValue, path, object);
// => Too many arguments. Are you looking for `_.getOr`?

The message should be improved, but that's the gist of it. I think it's fine to only display if the number of args matches exactly the number of arguments of the alias (e.g. _.get(a, b, c, d) would get the regular message).

Is this project dead?

I don't see any activity on here? I'd be willing to help out with this if you want.

Importing placeholder alone

Hey, I'm scattering through the docs and source code, but cant find if there is a way in lodash/fp to import just that except smth like:
import { placeholder as _ } from 'lodash/fp/curry'

which unfortunately is against no-submodule-destructuring. Using module bundler I do not want to import whole lodash/fp just to access placeholder.

false lodash-fp/no-extraneous-iteratee-args warning

For a call like: mapKeys(key =>${key.toUpperCase()})

Too many parameters in mapKeys's iteratee, it is only given 1 argument. (lodash-fp/no-extraneous-iteratee-args)

but

const toGlobal = key => `__${key.toUpperCase()}__`;
const keysToGlobals = mapKeys(toGlobal);

is fine

Warning method is immutable

There is a lot of method in lodash that can mutate the input params like:
_.fill
_.pull
_.assign
...

But these method in lodash/fp will create new object. so these function is very useless without assignment:
For example these code should give errors;

var test = {};
_.assign(test, {text: 'test'};
console.log(test.text === 'test');

`prefer-flat-map` being erroneously triggered

The rule prefer-flat-map is being trigger with the following line and I don't know why.

    const filterOut = _.flow(_.get('foods'), _.reject('tomato'), _.reject('strawberry'), _.reject({ id: 'SUGARID' }))

Thanks ๐ŸŽˆ

`preferred-alias` rule

Enforce the use of a consistent name for each method. For example, _.pluck is an alias for _.map, so the rule would enforce the use of one over the other.

The rule should by default enforce the use of the non-aliased name, example: map instead of pluck.
It should take as an option the list of overrides. I'm not sure of the shape of it. Off the top of my head, it'll probably look like this:

"lodash-fp/preferred-alias": ["error", {"aliases": ["pluck", "pipe"]}]

In this case, pluck should be enforced instead of map, and pipe instead of flow. Any unknown names can be ignored.

Some aliases should not be enforced, like getOr and get. getOr is an alias for get, but has a different arity (allowing it to have a default value parameter). I don't know if there are methods where other properties than the fixed arity is different, but they should not be enforced.

If someone wants a stab at it, the current list of fp aliases can be found here

It might be nice to have presets for aliases, like all the aliases that are there for Ramda users.
preset: 'ramda'?

Warn when iteratee method uses too many arguments

Rule name to be found.

In Lodash/fp, many methods with an iteratee have their iteratee called with a fixed arity, often one less than what they're used to in vanilla Lodash. It would be nice to warn the user of this.

Example:

// Vanilla
_.map([1, 2, 3], function(value, index) {
  return value + index; // OK, index will be 0, 1, 2 in order
});

// FP
_.map(function(value, index) {
  return value + index; // Not OK, as index is never passed (always `undefined`)
}, [1, 2, 3]);

How to validate `compose` from other libraries?

Hi, guys.

I'm using recompose library in my React project, and I'd like this plugin to work for its compose method. The rule I'm particularly interested in is no-single-composition.

Is there a way to make this plugin work with it?

Code example that doesn't fail, but should:

import { compose, withProps } from 'recompose';

export const SomeDiv = compose(
  withProps({ extraProp: 'bla-bla' })
)(() => <div>just some div</div>);

Grouping operations rule

(Name TBD)

In composition constructs, enforce the regrouping of similar methods that are one after the other. Applies to methods like _.map, _.filter, _.reject.

_.flow(
  _.map(fn1),
  _.map(fn2)
)(a);
// -->
_.map(
  _.flow(fn1, fn2)
)(a);

_.flow(
  _.map(fn1),
  _.map(fn2),
  _.filter(fn3)
)(a);
// -->
_.flow(
  _.map(_.flow(fn1, fn2)),
  _.filter(fn3)
)(a);

Plugin checks vanilla lodash methods

I have a project that both uses lodash and lodash/fp at the same time. This plugin triggers errors on vanilla lodash methods. It should ignore const get = require('lodash/get') and work only on const get = require('lodash/fp/get'); etc...

mergeAll is capped at 1 arguments regardless of order

Hello,

I'm using mergeAll like so:

mergeAll([objA, objB], {});

mergeAll is capped at 1 arguments and takes an array as its last argument. (lodash-fp/no-extraneous-args)

I've tried it array last but the result is an object that is merged incorrectly and the error is still present anyway.

I'm pretty sure it should be array first from my testing but I couldn't see this method documented anywhere.

Thanks

Plugin blows up no toString method (overloaded)

example code

const toString = arr => arr.join('');

toString([ 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd' ]);

This is a bit of a contrived example but I actually have good reason to overload the toString method.

This is the line that causes the problem:
https://github.com/jfmengels/eslint-plugin-lodash-fp/blob/master/rules/core/lodash-util.js#L71

I would recommend using Reflect.getOwnPropertyDescriptor(imports, node.name) !== undefined instead.

`no-extraneous-function-wrapping`

import {pipe, get, set} from 'lodash/fp';

pipe(
  get('foo'),
  foo => set('foo', foo, foo)
)({});
5:3  error  Found extraneous function wrap around curried method. Pass inner function directly  lodash-fp/no-extraneous-function-wrapping

lodash-fp/no-extraneous-function-wrapping doesn't get i use foo two times, not just for the last parameters.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.