SiriusStarr/elm-review-pipeline-styles/1.0.0

NOTE: the latest version is 1.3.9

ReviewPipelineStyles.Predicates

This module contains various Predicates that can be used to filter pipelines.

Combining Predicates

and : Predicate anyType -> Predicate anyType -> Predicate anyType

Create a Predicate that matches pipelines that match both of two predicates.

or : Predicate anyType -> Predicate anyType -> Predicate anyType

Create a Predicate that matches pipelines that match either or both of two predicates.

doNot : Predicate anyType -> Predicate anyType

Negate a Predicate.

Predicates

spanMultipleLines : Predicate anyType

Checks whether or not a pipeline spans multiple lines of code.

haveMoreStepsThan : Int -> Predicate anyType

Checks whether the length of a pipeline is longer than a specified number. Note that the length of a pipeline is the number of operators in it, e.g.

foo
    |> bar
    |> baz

has length 2 for the purposes of this predicate.

haveFewerStepsThan : Int -> Predicate anyType

Checks whether the length of a pipeline is less than a specified number. Note that the length of a pipeline is the number of operators in it, e.g.

foo
    |> bar
    |> baz

has length 2 for the purposes of this predicate.

haveASimpleInputStep : Predicate ApplicationPipeline

Determine whether the pipeline has a simple input or not. This is somewhat subjective, of course, so use haveAnInputStepOf if you want to customize its behavior. A pipeline is considered to have a simple input if it has an unnecessary input, if its input is 40 characters or less, is only a single line, and is one of the following:

-- Unit
()
    |> foo


-- Name
a
    |> foo


-- Prefix operator
(+)
    |> foo


-- Int literal
1
    |> foo


-- Hex literal
0x0F
    |> foo


-- Float literal
1.5
    |> foo


-- String literal
"bar"
    |> foo


-- Char literal
'c'
    |> foo


-- Record access function
.field
    |> foo

or is one of the following where all subexpressions are simple:

-- Tuple
( a, "b" )
    |> foo


-- Record
{ a = "value" }
    |> foo


-- List
[]
    |> foo


-- Record access
a.field
    |> foo


-- Negation
elmFormatWontLetThisBeAnExample
    |> foo


-- Parentheses
elmFormatWontLetThisBeAnExample
    |> foo
haveAnUnnecessaryInputStep : Predicate ApplicationPipeline

Determine whether the pipeline has an input step that simply isn't necessary, e.g. foo |> bar |> baz, which may be written as bar foo |> baz.

This is not perfectly exhaustive as it does not consider operator precedence and the like but will suffice for finding most simple cases.

Note that this will potentially flag quite complex inputs, so you might want to use haveASimpleInputStep instead, since that only detects visually simple inputs.

haveAnInputStepOf : (Node Expression -> Bool) -> Predicate anyType

Like haveASimpleInputStep but with a user-providable function to check if an expression is simple.

separateATestFromItsLambda : Predicate ApplicationPipeline

Checks if a left "pizza" (<|) operator is used in the "canonical" fashion in a test suite, to separate the lambda containing the test from the test. All of the following will "pass" this predicate, and all other <|'s will not:

import Test exposing (..)


suite =
    describe "tests"
        [ test "foo" <|
            \() ->
                a
        , fuzz fooFuzz "fuzz" <|
            \foo ->
                a
        , fuzz2 fooFuzz barFuzz "fuzz2" <|
            \foo bar ->
                a
        , fuzz3 fooFuzz barFuzz bazFuzz "fuzz3" <|
            \foo bar baz ->
                a
        , fuzzWith { runs = 117 } fooFuzz "fuzzWith" <|
            \foo ->
                a
        ]
haveInternalComments : Predicate anyType

Checks whether any comments are located within the pipeline, e.g.

a =
    foo
        -- Comment
        |> bar
        |> baz

Comments around the pipeline are ignored, e.g.

a =
    -- Ignored
    foo
        |> bar
        |> baz


-- Ignored

Nesting Predicates

haveAParent : Predicate anyType

Checks whether the pipeline is nested to any degree within another pipeline. Note that this is quite a strict requirement and you probably want to use one of the other nesting predicates instead.

haveAParentNotSeparatedBy : List (NestedWithin -> Bool) -> Predicate anyType

Checks whether the immediate parent of a pipeline (if one exists) is not separated by one of a list of acceptable abstractions.

haveMoreNestedParentsThan : Int -> Predicate anyType

Checks whether the pipeline is nested to a greater degree than specified within other pipelines. For example, haveMoreNestedParentsThan 1 will forbid

a =
    foo
        |> (bar <| (a |> b |> c))
        |> baz
aLetBlock : NestedWithin -> Bool

Either within a let declaration or in the let expression of a let block from the surrounding pipeline.

aLambdaFunction : NestedWithin -> Bool

Within a lambda function in the surrounding pipeline.

aFlowControlStructure : NestedWithin -> Bool

Within a case expression of if...then expression in the surrounding pipeline.

aDataStructure : NestedWithin -> Bool

Within a tuple, list, or record in the surrounding pipeline.

Custom Predicates

If you need predicates beyond what is provided above, you can create them manually by writing a function of type Pipeline -> Bool or ModuleNameLookupTable -> Pipeline -> Bool and using one of the functions below.

Use the functions in Getting Information About Pipelines to build your custom predicate.

predicate : (Pipeline -> Bool) -> Predicate anyType

Given a function of type Pipeline -> Bool, create a Predicate from it. This is only useful if you want to write custom predicates. Note that this will allow you to create predicates that match any type of pipeline, so be careful in how you use it.

If you think a generally useful predicate is missing, please open an issue or PR on Github: https://github.com/SiriusStarr/elm-review-pipeline-styles/issues

predicateWithLookupTable : (ModuleNameLookupTable -> Pipeline -> Bool) -> Predicate anyType

Given a function of type ModuleNameLookupTable -> Pipeline -> Bool, create a Predicate from it. This is only useful if you want to write custom predicates and are going to need the full module name for expressions in the pipeline. Note that this will allow you to create predicates that match any type of pipeline, so be careful in how you use it.

If you think a generally useful predicate is missing, please open an issue or PR on Github: https://github.com/SiriusStarr/elm-review-pipeline-styles/issues

Getting Information About Pipelines

Note that some of the types returned by these functions are from stil4m/elm-syntax if you need to work with them directly.

getSteps : Pipeline -> List (Node Expression)

Get the "steps" in the pipeline. Note that this is in "logical" order, e.g. a 1 >> b >> c, c << b << a 1, a 1 |> b |> c, c <| b <| a 1, and c (b (a 1)) will all have the same steps of [a 1, b, c].

getParents : Pipeline -> List ( Operator (), NestedWithin )

Get the "parent" pipelines of the pipeline, i.e. a hierarchy of pipelines that this pipeline is nested within (start of the list being the most immediate parent). Note that you can use the functions in Nesting Predicates to interrogate the NestedWithin type and in Query Pipeline Types for the Operator type.

getNode : Pipeline -> Node Expression

Get the outermost Node of a pipeline; you probably don't need to work with this directly.

getInternalComments : Pipeline -> List (Node String)

Get a list of all comments that are inside of a pipeline.

Query Pipeline Types

isRightPizza : Operator () -> Bool

Check if an Operator is the right "pizza" operator (right function application), i.e. |>. An example of this pipeline is below:

foo
    |> bar
    |> baz
isLeftPizza : Operator () -> Bool

Check if an Operator is the left "pizza" operator (left function application), i.e. <|. An example of this pipeline is below:

foo <| bar <| baz
isRightComposition : Operator () -> Bool

Check if an Operator is the right composition operator, i.e. >>. An example of this pipeline is below:

foo
    >> bar
    >> baz
isLeftComposition : Operator () -> Bool

Check if an Operator is the left composition operator, i.e. <<. An example of this pipeline is below:

foo << bar << baz
isParentheticalApplication : Operator () -> Bool

Check if an Operator is simply parenthetical application (not an operator), i.e. successive function calls using parentheses, e.g.

foo (bar (baz (i (j k))))

Types

These are exposed only for the sake of type annotations; you shouldn't need to work with them directly.

type alias Predicate pipelineType =
Predicate pipelineType

A predicate for filtering pipelines, or a logical combination of them.

type alias Operator pipelineType =
Operator pipelineType

The operator type of a pipeline, e.g. |> or <<.

type alias Pipeline =
Pipeline

A detected pipeline. You only need be concerned with this type if you are writing a manual predicate.

type alias NestedWithin =
NestedWithin

The degree to which a parent or child is removed from a pipeline.

type alias ApplicationPipeline =
ApplicationPipeline

Pipelines that are function application.

type alias CompositionPipeline =
CompositionPipeline

Pipelines that are function composition.