Skip to content

Commit

Permalink
Merge pull request #10 from buildo/no-redundant-flow
Browse files Browse the repository at this point in the history
Add no-redundant-flow
  • Loading branch information
gabro authored Jan 2, 2021
2 parents 1ebc455 + f59ab02 commit 479842c
Show file tree
Hide file tree
Showing 7 changed files with 163 additions and 1 deletion.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,5 @@ and enable the rules you want, for example
'pipeable' module
- [fp-ts/prefer-traverse](docs/rules/prefer-traverse.md): Replace map + sequence
with traverse
- [fp-ts/no-redundant-flow](docs/rules/no-redundant-flow.md): Remove redundant
uses of flow
31 changes: 31 additions & 0 deletions docs/rules/no-redundant-flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Remove redundant uses of flow (fp-ts/no-redundant-flow)

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.

## Rule Details

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

```ts
import { flow } from "fp-ts/pipeable";
import { some, Option } from "fp-ts/Option";

const f: (n: number): Option<number> = flow(some);
```

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

```ts
import { flow } from "fp-ts/pipeable";
import { some, filter, Option } from "fp-ts/Option";

const f: (n: number): Option<number> =
flow(
some,
filter((n) => n > 2)
);
```
1 change: 1 addition & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export const rules = {
"no-lib-imports": require("./rules/no-lib-imports"),
"no-pipeable": require("./rules/no-pipeable"),
"prefer-traverse": require("./rules/prefer-traverse"),
"no-redundant-flow": require("./rules/no-redundant-flow"),
};
44 changes: 44 additions & 0 deletions src/rules/no-redundant-flow.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { TSESLint } from "@typescript-eslint/experimental-utils";
import { isFlowExpression } from "../utils";

const messages = {
redundantFlow: "flow can be removed because it takes only one argument",
removeFlow: "remove flow",
} as const;
type MessageIds = keyof typeof messages;

export const meta: TSESLint.RuleMetaData<MessageIds> = {
type: "suggestion",
fixable: "code",
schema: [],
messages,
};

export function create(
context: TSESLint.RuleContext<MessageIds, []>
): TSESLint.RuleListener {
return {
CallExpression(node) {
if (node.arguments.length === 1 && isFlowExpression(node, context)) {
context.report({
node,
messageId: "redundantFlow",
suggest: [
{
messageId: "removeFlow",
fix(fixer) {
return [
fixer.removeRange([
node.callee.range[0],
node.callee.range[1] + 1,
]),
fixer.removeRange([node.range[1] - 1, node.range[1]]),
];
},
},
],
});
}
},
};
}
15 changes: 15 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,21 @@ export function calleeIdentifier(
return undefined;
}

export function isFlowExpression<
TMessageIds extends string,
TOptions extends readonly unknown[]
>(
node: TSESTree.CallExpression,
context: TSESLint.RuleContext<TMessageIds, TOptions>
): boolean {
const callee = calleeIdentifier(node);
return !!(
callee &&
callee.name === "flow" &&
isIdentifierImportedFrom(callee, /fp-ts\//, context)
);
}

export function isPipeOrFlowExpression<
TMessageIds extends string,
TOptions extends readonly unknown[]
Expand Down
2 changes: 1 addition & 1 deletion tests/rules/no-pipeable.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const ruleTester = new ESLintUtils.RuleTester({
},
});

ruleTester.run("no-lib-imports", rule, {
ruleTester.run("no-pipeable", rule, {
valid: [
'import { pipe } from "fp-ts/function"',
'import { pipe } from "fp-ts/lib/function"',
Expand Down
69 changes: 69 additions & 0 deletions tests/rules/no-redundant-flow.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import * as rule from "../../src/rules/no-redundant-flow";
import { ESLintUtils } from "@typescript-eslint/experimental-utils";

const ruleTester = new ESLintUtils.RuleTester({
parser: "@typescript-eslint/parser",
parserOptions: {
sourceType: "module",
},
});

ruleTester.run("no-redundant-flow", rule, {
valid: [
`import { flow } from "fp-ts/function"
flow(foo, bar)
`,
`import { flow } from "fp-ts/function"
flow(
foo,
bar
)
`,
],
invalid: [
{
code: `
import { flow } from "fp-ts/function"
const a = flow(foo)
`,
errors: [
{
messageId: "redundantFlow",
suggestions: [
{
messageId: "removeFlow",
output: `
import { flow } from "fp-ts/function"
const a = foo
`,
},
],
},
],
},
{
code: `
import { flow } from "fp-ts/function"
const a = flow(
foo
)
`,
errors: [
{
messageId: "redundantFlow",
suggestions: [
{
messageId: "removeFlow",
output: `
import { flow } from "fp-ts/function"
const a = ${""}
foo
`,
},
],
},
],
},
],
});

0 comments on commit 479842c

Please sign in to comment.