Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/xodio/eslint-plugin-xod-fp
Limit the chaos while doing FP in JS
https://github.com/xodio/eslint-plugin-xod-fp
eslint eslint-rules functional-programming ramda
Last synced: 9 days ago
JSON representation
Limit the chaos while doing FP in JS
- Host: GitHub
- URL: https://github.com/xodio/eslint-plugin-xod-fp
- Owner: xodio
- License: mit
- Created: 2017-01-20T15:51:32.000Z (almost 8 years ago)
- Default Branch: master
- Last Pushed: 2017-01-23T16:47:53.000Z (almost 8 years ago)
- Last Synced: 2024-10-31T20:48:18.364Z (16 days ago)
- Topics: eslint, eslint-rules, functional-programming, ramda
- Language: JavaScript
- Homepage:
- Size: 19.5 KB
- Stars: 0
- Watchers: 5
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# eslint-plugin-xod-fp
ESLint plugins to check code written in functional style with
[Ramda](http://ramdajs.com/).## Installation
You'll first need to install [ESLint](http://eslint.org):
```
$ npm i eslint --save-dev
```Next, install `eslint-plugin-xod-fp`:
```
$ npm install eslint-plugin-xod-fp --save-dev
```**Note:** If you installed ESLint globally (using the `-g` flag) then you must
also install `eslint-plugin-xod-fp` globally.## Usage
Add `xod-ramda` to the plugins section of your `.eslintrc` configuration file.
You can omit the `eslint-plugin-` prefix:```json
{
"plugins": [
"xod-fp"
]
}
```Then configure the rules you want to use under the rules section.
```json
{
"rules": {
"xod-fp/max-composition-depth": [ "error", 5 ],
}
}
```## Supported Rules
* `max-composition-depth`: limit compositional calls nesting
### Rule: `max-composition-depth`
Ensure that function compositions are not too deep.
#### Valid
```js
// :: Node -> Boolean
const isCallExpression = R.propEq('type', 'CallExpression');// :: Node -> Boolean
const isArrowFunctionExpression = R.propEq('type', 'ArrowFunctionExpression');// :: Node -> Boolean
const isCurry = R.allPass([
R.propEq('type', 'CallExpression'),
R.pathEq(['callee', 'type'], 'MemberExpression'),
R.pathEq(['callee', 'object', 'type'], 'Identifier'),
R.pathEq(['callee', 'object', 'name'], 'R'),
R.pathEq(['callee', 'property', 'type'], 'Identifier'),
R.pathEq(['callee', 'property', 'name'], 'curry'),
]);// :: Node -> Boolean
const isCallNotCurry = R.both(
isCallExpression,
R.complement(isCurry)
);// :: Options -> Node -> Boolean
const isNestingExpression = opts => R.anyPass([
opts.ignoreCurry ? isCallNotCurry : isCallExpression,
opts.ignoreArrow ? R.F : isArrowFunctionExpression,
]);// :: Node -> [Node] -- a chain of parents to the root
const parents = R.ifElse(
R.prop('parent'),
R.compose(parent => R.concat([parent], parents(parent)), R.prop('parent')),
R.always([])
);// :: Options -> Node -> Number
const nestingDepth = R.curry((opts, node) => R.compose(
R.length,
R.uniq,
R.map(R.prop('start')),
R.filter(isNestingExpression(opts)),
parents
)(node));
```#### Invalid
```js
// :: Options -> Node -> Number
// -- No R.compose (depth is 7)
const nestingDepth = R.curry((opts, node) =>
R.length(R.uniq(R.map(
R.prop('start'), R.filter(isNestingExpression(opts)), parents(node)
)))
);// :: Options -> Node -> Number
// -- Too complex inlining (depth is 8)
const nestingDepth = R.curry((opts, node) => R.compose(
R.length,
R.uniq,
R.map(R.prop('start')),
R.filter(opts => R.anyPass([
opts.ignoreCurry ? R.allPass([
R.propEq('type', 'CallExpression'),
R.pathEq(['callee', 'type'], 'MemberExpression'),
R.pathEq(['callee', 'object', 'type'], 'Identifier'),
R.pathEq(['callee', 'object', 'name'], 'R'),
R.pathEq(['callee', 'property', 'type'], 'Identifier'),
R.pathEq(['callee', 'property', 'name'], 'curry'),
]) : R.propEq('type', 'CallExpression'),
opts.ignoreArrow ? R.F : R.propEq('type', 'ArrowFunctionExpression'),
])),
R.ifElse(
R.prop('parent'),
R.compose(parent => R.concat([parent], parents(parent)), R.prop('parent')),
R.always([])
)
)(node));
```#### Options
#### `max`
Defaults to 4.
Maximal nesting depth. Nested function call or arrow function expression
increment the depth.#### `ignoreArrow`
Defaults to false.
Pass `{ ignoreArrow: true }` to not to take arrow functions into account when
counting the depth.#### `ignoreCurry`
Defaults to false.
Pass `{ ignoreCurry: true }` to not to take `R.curry` calls into account when
counting the depth.Calling `R.curry` is just a fighting with JavaScript to make it more
FP-compatible. If you see `R.curry` you probably would not think about it
at all trying to understand what an overall function does. So it is a good
idea to ignore currying in depth calculation as well.#### `ignoreMocha`
Defaults to false.
Pass `{ ignoreMocha: true }` to not to take `it` and `describe` calls of
[Mocha](https://mochajs.org/) into account when counting the depth. Child
arrow functions of `it` and `describe` will be ignored as well.Mocha’s functions are part of testing DSL and are not part of functions logic,
so do not add to a function complexity thus can be ignored.