-
-
Notifications
You must be signed in to change notification settings - Fork 193
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
Fix issues with multiline generic type parameters #2852
Conversation
Thanks for following up on this. I need to play with this some more and we may want to have the conversation over at the style guide as well. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @josh-degraw, many thanks again for taking the lead in this during https://amplifying-fsharp.github.io/sessions/2023/04/14/
I think the change is sensible but this does change the style and so I would like to see this covered by https://learn.microsoft.com/en-us/dotnet/fsharp/style-guide/formatting#formatting-explicit-generic-type-arguments-and-constraints
And also to have a link for people who will open an issue claiming the additional space is a bug. (Trust me, it will be reported 🙈).
Could you open an issue in https://github.com/fsharp/fslang-design/issues so we can further discuss these implications?
And please also retarget this branch to v6.1
.
Thanks!
(Position -> option<string>) * | ||
FSharp.Compiler.Syntax.ParsedInput> = | ||
: cmap< | ||
DeclName, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This indent no longer is a multitude of the indent_size
, we should look into why this is happening. Gut feeling this is related due to
fantomas/src/Fantomas.Core/CodePrinter.fs
Line 2887 in 4d8d328
+> atCurrentColumnIndent (genType rt.Type) |
Nonetheless, we should investigate this one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you still consider this a problem or are we okay with this indent level?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I think I can live with this.
This sample screams "use type alias" anyway.
@@ -3037,7 +3045,8 @@ let genType (t: Type) = | |||
+> optSingle genIdentListNodeWithDot node.PostIdentifier | |||
+> genSingleTextNode node.LessThen | |||
+> addExtraSpace | |||
+> col sepComma node.Arguments genType | |||
+> leadingExpressionIsMultiline (colGenericTypeParameters node.Arguments) (fun isMultiline -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should add some tests where the <
and >
contain trivia.
Cases like:
type X =
Teq< //
int
//
>
won't be covered right now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also please add a code comment on why we are doing this in the first place.
""" | ||
|
||
[<Test>] | ||
let `` Aligned bracket style in anonymous record is respected for multiple types, #2706`` () = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should have the same test for the other styles.
4d8d328
to
fe504e3
Compare
9329316
to
87d2a45
Compare
eeb8f27
to
9056cf1
Compare
Sorry it's taken me so long to finally get back around to trying to finish this up haha. I'm not sure if something has changed on the parser level since I originally worked on this, but a test that previously succeeded is now failing and I'm having trouble figuring out the best way to address it. I extracted the relevant bits into its own test but essentially this kind of expression (which is how my PR originally formatted this in the updated tests here): let bv =
unbox<
Foo<
'innerContextLongLongLong,
'bb -> 'b
>
>
bf Is no longer an idempotent operation. It seems like if I increase the indent of the final let bv =
unbox<
Foo<
'innerContextLongLongLong,
'bb -> 'b
>
>
bf it becomes idempotent again, but since this worked before I rebased this PR I'm not sure if this is a bug in the AST parsing layer or just in my code here. |
@josh-degraw thanks for picking this up again! Much appreciated! I'm afraid this one kinda sucks: The So, instead of I'm not sure what we need to do to keep this as a function application. |
Yeah like I mentioned it seems like just increasing the indent for the closing angle bracket at least fixes the parser issue, but that's still valid code with the additional indent right? If not I guess we'd have to carve out an exemption for this scenario or wrap in parentheses or something |
Ok, consider this example: foo<
'bar
-> int
>
barry This looks like it is a Adding a space before |
Added a workaround of |
I tried that but that messes with a bunch of other tests, wouldn't we want to only do this in this specific situation? |
Hmm, I think the safest thing to do would be to have it all the time. Digging into the exact case of |
Fair enough. Looks like most of the tests that fail with that change were added in this PR anyway haha. I'll update the tests to reflect this |
@josh-degraw took a quick peek if it is possible. It seems less intrusive at first glance to remove the space. This of course can still go wrong in things like We should check what happens in those scenarios. If we need to update all these individually I don't think it is worth it. |
Can you maybe help me know in what situations these nodes would apply here? I'm not quite sure exactly how to test for these just going off of the node names themselves (not quite there yet haha..) |
Sure thing. SynExpr.App has historically been a tricky one to format. Because it really depends on what expressions it has before we decide how we can format it. Some examples: // ExprAppSingleParenArgNode
Foo(
//
bar
)
// ExprAppWithLambdaNode
bar(fun x -> x)
// ExprAppNode
a [ Href "some-link"] [
str "content"
]
// ExprInfixAppNode
x - y
// ExprSameInfixAppsNode
x * y * z All of these expressions are This is sometimes very convenient but at the same has its drawbacks. A clear pro: sometimes you really need to deal with these shapes very carefully and it helps to have separation. A clear con: the is no single entry A lot of what we have today is somewhat historical as well. Infix applications are a good example of that. Almost all of the code pre-dates the style guide and it is just what we have today. We split the applications into different Oak nodes in: fantomas/src/Fantomas.Core/ASTTransformer.fs Lines 1184 to 1315 in 21bae08
So, to answer your question, that would be the list you need to check. On a side note, some of these nodes probably shouldn't exist because they are too focused on what we do with them inside Anyway, you should check what happens if any of these nodes can be used with I hope this helps a little. |
@@ -266,25 +262,27 @@ let private asJson (arm: IArmResource) = | |||
> | |||
""" | |||
|
|||
let forcedLongDefnConfig = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a fan of this configuration.
The only thing you are trying to achieve is to spread things over multiple lines, using MaxLineLength = 30
. All the other settings are irrelevant and misleading to readers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, fully agree, this latest commit was mainly a WIP
|}> | ||
""" | ||
config | ||
let ``Multiline type argument with AppLongIdentAndSingleParenArg`` () = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: lowercase unit test names.
[<Test>] | ||
let ``type application including nested multiline function type`` () = | ||
forcedLongDefnConfig | ||
{ config with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nitpick but this doesn't comply with the pull request ground rules.
I don't really see a compelling reason to deviate from the standard unit template.
All our tests are the same, I'm not a fan of mixing that up in this PR.
Be aware that in its current form this is not working out for every [<Test>]
let ``dual list application`` () =
formatSourceString
"""
unbox<Foo<'innerContextLongLongLong,'bb -> 'b>> [
ClassName "meh"
] [
str "foo"
]
"""
{ config with
MaxLineLength = 12
MultilineBracketStyle = Stroustrup }
|> prepend newline
|> should
equal
"""
unbox<
Foo<
'innerContextLongLongLong,
'bb
-> 'b
>
> [
ClassName
"meh"
] [
str
"foo"
]
""" |
Yeah I know, I'm still having a little trouble pinpointing the spot to fix some of these |
Don't hesitate to reach out if you wanna pair on this sometime! |
That might be helpful. I felt like a few I found right where I thought I needed to make changes to fix some of these issues but it didn't work haha |
* Expose TransformAST api. * Add additional unit test. * Revert changelog entry
66fdc2d
to
0209297
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright, I think this is worth merging in and release as an alpha.
Thank you for your endurance here @josh-degraw!
Closes #2706, from Amplifying F# session