Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Be more cautious when adding a sepSpace before paren lambda #2232

Merged
merged 6 commits into from
May 13, 2022

Conversation

dawedawe
Copy link
Member

@dawedawe dawedawe commented May 6, 2022

Fixes #2231
Fixes #2041

Not super sure about this one and it may need more discussion, but I think we are a bit too liberal adding spaces before the lparen of lambda arguments. This can easily break calls to Linq methods. See the example in #2231

@nojaf
Copy link
Contributor

nojaf commented May 9, 2022

Hey, sorry for the delay.
In this case, that AST node/combo is ruffly DotGet(App(longIdent, Paren(Lambda _)), longIdent2).
The space in this exact shape is something we should avoid.

This PR touches a bit more than that. Though I must admit it can be subtle.
You could try introducing a new active pattern in SourceParser to capture this.
It would be something along the lines of:

        // Foo(fun x -> y).Bar
        | DotGet(AppWithLambda(_, [], _, _, _, _), lids) ->
            !- "todo"

And to not need to repeat everything for AppWithLambda I would extract the logic in

        // functionName arg1 arg2 (fun x y z -> ...)
        | AppWithLambda (e, es, lpr, lambda, rpr, pr) -> ...

And parameterize the logic to add a space or not.
In the case of the dotget it should not add it.
For the | AppWithLambda it should use the existing logic.

I hope this helps, good luck.

@dawedawe
Copy link
Member Author

dawedawe commented May 9, 2022

I hope this helps, good luck.

It sure does. Thanks. I'll try to come up with something.

Copy link
Contributor

@nojaf nojaf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Getting closer, keep it up!

src/Fantomas.Core.Tests/ElmishTests.fs Outdated Show resolved Hide resolved
@@ -2088,215 +2088,12 @@ and genExpr astContext synExpr ctx =

expressionFitsOnRestOfLine short long

| DotGetAppWithLambda ((e, es, lpr, lambda, rpr, pr), lids) ->
genAppWithLambda (e, es, lpr, lambda, rpr, pr) false (Some lids) astContext
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wouldn't pass in the lids of the DotGet here to the genAppWithLambda function.
What you want to control from outside the genAppWithLambda is whether there should be a space or not.

I would pass in a function (that adds the space) instead of a boolean.

Something long the lines of:

        | DotGetAppWithLambda ((e, es, lpr, lambda, rpr, pr), lids) ->
            leadingExpressionIsMultiline 
                (genAppWithLambda astContext sepNone (e, es, lpr, lambda, rpr, pr))
                (fun isMultline -> // print lids and do the right thing based on isMultline)

        // functionName arg1 arg2 (fun x y z -> ...)
        | AppWithLambda (e, es, lpr, lambda, rpr, pr) ->
              let sepSpaceAfterFunctionName =
                  let sepSpaceBasedOnSetting e =
                      match e with
                      | Paren _ -> sepSpace
                      | UppercaseSynExpr -> (fun ctx -> onlyIf ctx.Config.SpaceBeforeUppercaseInvocation sepSpace ctx)
                      | LowercaseSynExpr -> (fun ctx -> onlyIf ctx.Config.SpaceBeforeLowercaseInvocation sepSpace ctx)

                  match es with
                  | [] -> sepSpaceBasedOnSetting e
                  | _ -> sepSpace

            genAppWithLambda astContext sepSpaceAfterFunctionName  (e, es, lpr, lambda, rpr, pr) 

The benefit here is that genAppWithLambda has no knowledge about lids so the function only does one thing (namely printing a function application that ends with a lambda).

Oh and in a lot of places astContext is the first argument.
This is a bit historically.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the review and the suggestions. Really appreciate your patience.

I hope I'm not too confused here but I think this is now more in line with our default config of SpaceBeforeUppercaseInvocation = false. As a consequence there were some tests which needed adjustments.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the changes in the existing tests are all valid.

+> genSynLongIdent true lids
+> unindent)
else
(indent >> genSynLongIdent true lids))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is dangerous that have an indent without later restoring using an unindent.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All tests also seem to run just fine when removing indent >> so not sure if we still need that here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmh, yeah. I think that was just an artefact of me screwing around.

| DotGetAppWithLambda ((e, es, lpr, lambda, rpr, pr), lids) ->
leadingExpressionIsMultiline
(genAppWithLambda astContext sepNone (e, es, lpr, lambda, rpr, pr))
(fun isMultline ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo isMultiline

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed

Copy link
Contributor

@nojaf nojaf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of very small things left, but this is looking good!

Copy link
Contributor

@nojaf nojaf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many thanks for this!

dawedawe added 6 commits May 13, 2022 14:00
- Fixes 2041 and 2231
- Adjust expected results of other tests
- Move logic of AppWithLambda to genAppWithLambda function
- narrow scope down to just fix 2231
- adjust tests
- add back test for fsprojects#2041
- add back CHANGELOG entry about fsprojects#2041
- Remove superfluous indent
@nojaf nojaf merged commit d94e1a1 into fsprojects:master May 13, 2022
@dawedawe dawedawe deleted the fix-2231 branch May 13, 2022 12:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants