Skip to content

Commit

Permalink
Merge pull request #55 from buildo/pure-statement
Browse files Browse the repository at this point in the history
Add no-discarded-pure-expression
  • Loading branch information
gabro authored Feb 9, 2021
2 parents 13a9992 + 597b90f commit 551360f
Show file tree
Hide file tree
Showing 20 changed files with 894 additions and 25 deletions.
74 changes: 60 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,48 @@ and enable the rules you want, for example
}
```

If you want to enable rules that require type information (see the table below),
then you will also need to add some extra info:

```js
module.exports = {
plugins: ["fp-ts"],
parserOptions: {
tsconfigRootDir: __dirname,
project: ["./tsconfig.json"],
},
rules: {
"fp-ts/no-discarded-pure-expression": "error",
},
};
```

If your project is a multi-package monorepo, you can follow the instructions
[here](https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/MONOREPO.md).

> ⚠️ Note that you will need to make the ESLint config file a .js file, due to
> the need of setting `tsconfigRootDir` to `__dirname`. This is necessary to
> make both editor integrations and the CLI work with the correct path. More
> info here: https://github.com/typescript-eslint/typescript-eslint/issues/251
## List of supported rules

- [fp-ts/no-lib-imports](docs/rules/no-lib-imports.md): Disallow imports from
'fp-ts/lib' (autofixable 🔧)
- [fp-ts/no-pipeable](docs/rules/no-pipeable.md): Disallow imports from the
'pipeable' module (autofixable 🔧)
- [fp-ts/no-module-imports](docs/rules/no-module-imports.md): Disallow imports
from fp-ts modules (autofixable 🔧)
- [fp-ts/no-redundant-flow](docs/rules/no-redundant-flow.md): Remove redundant
uses of flow (autofixable 🔧)
- [fp-ts/prefer-traverse](docs/rules/prefer-traverse.md): Replace map + sequence
with traverse (autofixable 🔧)
- [fp-ts/prefer-chain](docs/rules/prefer-chain.md): Replace map + flatten with
chain (autofixable 🔧)
- [fp-ts/prefer-bimap](docs/rules/prefer-bimap.md): Replace map + mapLeft with
bimap (autofixable 🔧)
| Rule | Description | Fixable | Requires type-checking |
| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------ | :-----: | :--------------------: |
| [fp-ts/no-lib-imports](docs/rules/no-lib-imports.md) | Disallow imports from `fp-ts/lib/` | 🔧 | |
| [fp-ts/no-pipeable](docs/rules/no-pipeable.md) | Disallow imports from the `pipeable` module | 🔧 | |
| [fp-ts/no-module-imports](docs/rules/no-module-imports.md) | Disallow imports from fp-ts modules | 🔧 | |
| [fp-ts/no-redundant-flow](docs/rules/no-redundant-flow.md) | Remove redundant uses of `flow` | 🔧 | |
| [fp-ts/prefer-traverse](docs/rules/prefer-traverse.md) | Replace `map` + `sequence` with `traverse` | 💡 | |
| [fp-ts/prefer-chain](docs/rules/prefer-chain.md) | Replace `map` + `flatten` with `chain` | 💡 | |
| [fp-ts/prefer-bimap](docs/rules/prefer-bimap.md) | Replace `map` + `mapLeft` with `bimap` | 💡 | |
| [fp-ts/no-discarded-pure-expression](docs/rules/no-discarded-pure-expression.md) | Disallow expressions returning pure data types (like `Task` or `IO`) in statement position | 💡 | 🦄 |

### Fixable legend:

🔧 = auto-fixable via `--fix` (or via the appropriate editor configuration)

💡 = provides in-editor suggestions that need to be applied manually

## Configurations

Expand All @@ -74,6 +100,26 @@ The rules included in this configuration are:
- [fp-ts/no-lib-imports](docs/rules/no-lib-imports.md)
- [fp-ts/no-pipeable](docs/rules/no-pipeable.md)

### Recommended requiring type-checking

We also provide a `recommended-requiring-type-checking` which includes
recommended rules which require type information.

This configuration needs to be included _in addition_ to the `recommended` one:

```
{
"extends": [
"plugin:fp-ts/recommended"
"plugin:fp-ts/recommended-requiring-type-checking"
]
}
```

> 👉 You can read more about linting with type information, including
> performance condideration
> [here](https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/TYPED_LINTING.md)
### All

The plugin also defines an `all` configuration which includes every available
Expand Down
94 changes: 94 additions & 0 deletions docs/rules/no-discarded-pure-expression.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Disallow expressions returning pure data types (like `Task` or `IO`) where `void` or `unknown` is expected or in statement position (fp-ts/no-discarded-pure-expression)

Expressions which return a pure data type, such as `IO`, `Task` and their
variants, should normally be passed as an argument, returned, or run.

Failing to do so causes the program represented by `IO` or `Task` to never be
run, leading to surprising behavior which is normally difficult to debug.

This rule covers two common scenarios that are common programming errors:

- returning pure data types where `void` or `unknown` is expected (for instance,
in event handlers) without running them

- writing expressions that return pure data types in statement position (without
returning them or running them)

**💡 Fixable**: This rule provides in-editor suggested fixes.

## Rule Details

Examples of **incorrect** code for this rule:

```ts
import { task } from "fp-ts";

declare const myCommand: (n: number) => Task<string>;

function woops() {
myCommand(1); // the task will never run, since is not being run nor returned
}
```

```ts
declare const MyComponent: (props: { handler: () => void }) => JSX.Element;

declare const myCommand: (n: number) => Task<string>;

export function Foo() {
return (
<MyComponent
handler={() => myCommand(1)} // bug, the Task will never execute
/>;
)
}
```

```ts
import { task } from "fp-ts";

declare function foo(arg1: number, callbackUnknown: () => unknown): void;

declare const myCommand: (n: number) => Task<string>;

foo(
2,
() => myCommand(1) // bug, the Task will never execute
);
```

Examples of **correct** code for this rule:

```ts
import { task } from "fp-ts";

declare const myCommand: (n: number) => Task<string>;

function ok() {
return myCommand(1);
}
```

```ts
declare const MyComponent: (props: { handler: () => void }) => JSX.Element;

declare const myCommand: (n: number) => Task<string>;

export function Foo() {
return (
<MyComponent
handler={() => myCommand(1)()}
/>;
)
}
```

```ts
import { task } from "fp-ts";

declare function foo(arg1: number, callbackUnknown: () => unknown): void;

declare const myCommand: (n: number) => Task<string>;

foo(2, () => myCommand(1)());
```
2 changes: 1 addition & 1 deletion docs/rules/no-lib-imports.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ without the `lib` prefix, which improves ergonomics and tree-shakeability.
> Note: this change was introduced in fp-ts 2.8.0. If you are using an older
> version, do not enable this rule
**Fixable**: This rule is automatically fixable using the `--fix` flag on the
**🔧 Fixable**: This rule is automatically fixable using the `--fix` flag on the
command line.

## Rule Details
Expand Down
2 changes: 1 addition & 1 deletion docs/rules/no-module-imports.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Disallow imports from fp-ts modules, such as `fp-ts/Option`.
The `function` module is an exception and it's allowed nonetheless, since it's
not exported from fp-ts's index.

**Fixable**: This rule is automatically fixable using the `--fix` flag on the
**🔧 Fixable**: This rule is automatically fixable using the `--fix` flag on the
command line.

## Rule Details
Expand Down
2 changes: 1 addition & 1 deletion docs/rules/no-pipeable.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Disallow imports from the `pipeable` module. `pipeable` has been deprecated and
it will be removed in future versions of fp-ts. It's recommended to import
`pipe` from the `function` module instead.

**Fixable**: This rule is automatically fixable using the `--fix` flag on the
**🔧 Fixable**: This rule is automatically fixable using the `--fix` flag on the
command line.

> Note: the autofix is available only when importing `pipe`
Expand Down
3 changes: 1 addition & 2 deletions docs/rules/no-redundant-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
Suggest removing `flow` when it only has one argument. This can happen after a
refactoring that removed some combinators from a flow expression.

**Fixable**: This rule is automatically fixable using the `--fix` flag on the
command line.
**💡 Fixable**: This rule provides in-editor suggested fixes.

## Rule Details

Expand Down
3 changes: 1 addition & 2 deletions docs/rules/prefer-bimap.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
Suggest replacing the combination of `map` followed by `mapLeft` (or vice-versa)
with `bimap`.

**Fixable**: This rule is automatically fixable using the `--fix` flag on the
command line.
**💡 Fixable**: This rule provides in-editor suggested fixes.

## Rule Details

Expand Down
3 changes: 1 addition & 2 deletions docs/rules/prefer-chain.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
Suggest replacing the combination of `map` (or `mapWithIndex`) followed by
`flatten` with `chain` (or `chainWithIndex`).

**Fixable**: This rule is automatically fixable using the `--fix` flag on the
command line.
**💡 Fixable**: This rule provides in-editor suggested fixes.

## Rule Details

Expand Down
3 changes: 1 addition & 2 deletions docs/rules/prefer-traverse.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
Suggest replacing the combination of `map` (or `mapWithIndex`) followed by
`sequence` with `traverse` (or `traverseWithIndex`).

**Fixable**: This rule is automatically fixable using the `--fix` flag on the
command line.
**💡 Fixable**: This rule provides in-editor suggested fixes.

## Rule Details

Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"scripts": {
"preversion": "yarn lint && yarn test && yarn build",
"build": "rimraf lib && yarn tsc",
"pretest": "yarn --cwd tests/fixtures/fp-ts-project install",
"test": "jest",
"lint": "eslint src/**/*.ts"
},
Expand Down
8 changes: 8 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ const potentialErrors = {
"no-lib-imports": require("./rules/no-lib-imports").default,
"no-pipeable": require("./rules/no-pipeable").default,
"no-module-imports": require("./rules/no-module-imports").default,
"no-discarded-pure-expression": require("./rules/no-discarded-pure-expression")
.default,
};

const suggestions = {
Expand All @@ -27,6 +29,12 @@ export const configs = {
"fp-ts/no-pipeable": "error",
},
},
"recommended-requiring-type-checking": {
plugins: ["fp-ts"],
rules: {
"fp-ts/no-discarded-pure-expression": "error",
},
},
all: {
plugins: ["fp-ts"],
rules: {
Expand Down
Loading

0 comments on commit 551360f

Please sign in to comment.