This change allows always breaking before braces on C# setter and getter properties
Fixes #61968
Paths
| Differential D148467
[clang-format] Add a new AfterCSharpProperty to BraceWrapping AcceptedPublic Authored by MyDeveloperDay on Apr 16 2023, 8:18 AM.
Details
Summary This change allows always breaking before braces on C# setter and getter properties Fixes #61968
Diff Detail Event TimelineHerald added projects: Restricted Project, Restricted Project. · View Herald TranscriptApr 16 2023, 8:18 AM MyDeveloperDay added inline comments.
Comment Actions for default set;get or get;set for when AfterCSharpProperty is true, public Foo { set; get; } Comment Actions
I've not enough domain knowledge to name it.
MyDeveloperDay marked 8 inline comments as done. Comment ActionsAddress review comments, still would like to solve the indenting issue. Comment Actions
At least from my experience, the getter is specified before the setter, though I'm unsure how important this is in your eyes. When autoproperty is used: public Foo { get; set; } // OR public FooTwo { set; get; } // What I prefer. When a non-autoproperty is used: /* When only one thing is provided in the getter and setter. */ public Foo { get { return _next; } set { _next = value; } } // What I prefer. // OR public Foo { get => return _next; set => _next = value; } // Another option that I like (which really doesn't apply to this code change). // OR public Foo { get { return _next; } set { _next = value; } } // ---------------------------------- /* When more than one thing is provided in the getter and setter. */ public Foo { get { // ... return _next; } set { _next = value; // ... } } Please note that the above examples *slightly* ignore the different variations in how the braces could be set (new line or not). I hope this input is enough/helps. Please let me know if you'd like any clarification. Comment Actions
Lets hold off the idea of swapping set;get around from this patch, but this is something that I think we could do.. (using the FormatTokenLexer.cpp to swap trivial set;get into get;set but lets leave that for another feature, as it would be code altering) honeslty I think we need another option maybe enum AllowShortCSharpProperties { Leave, Never, Empty, Always } Leave = Don't touch them set; get; set { val = value; } get { return = value; } Empty = only one the same line when empty set; get set { val = value; } get { return = value; } Always = always short form for trivial set; get; set { val = value; } get { return = value; } I'm trying to decide if I put that option in this change or in a seperate change (thoughts @HazardyKnusperkeks, @owenpan ) FYI, I've solved the indention issue in my branch which has been broken forever from what I can tell. verifyFormat("class A\n" "{\n" " string Bar {\n" " get;\n" " set\n" " {\n" " val = value;\n" " }\n" " }\n" "}", Style); Comment Actions add init support and fix indentation issue when only one property is defined but the is an auto-property Comment Actions
I'm not too privy to your workflow, but if by "in a separate change" you mean like "in a different PR", I'd probably say implement it in a different change, for the sake of revision history. Comment Actions
I'd say do it now. No need to introduce a new option, when we want to change it directly. Or at least make it the enum right now, with just 2 values. Comment Actions There is more to this than meets the eye.. what we have so far, from existing AfterFunction use and the propsed here AfterCSharpProperty is... public Foo { <--- controlled by **AfterFunction **(rightly or wrongly) get { <--- proposing to controlled by **AfterCSharpProperty** return; } set { val= value; } } But for trivial Properties, these are automatically assumed to be wanted on the same line. public Foo { set; get} Trivial Properties are defined as: all ordering variants (public/internal/private) set;get; public set;get public init;get get;set My problem is AfterFunction ONLY kicks in if this isn't a TrivialProperty.. We can't currently force TrivialProperties to be handled differently. AfterFunction = true we get public Foo { set; get} // we can't get to public Foo { set; get } Handling of Trivial Properties I feel there should be an "AllowCSharpPropertiesOnASingleLine" to match other options, otherwise it should follow AfterFunction (AllowCSharpPropertiesOnASingleLine default would need to be true to match current behaviour) AllowCSharpPropertiesOnASingleLine =true, AfterFunction = true/false public Foo { set; get } AllowCSharpPropertiesOnASingleLine = false, AfterFunction = true public Foo { set; get } So then how do we handle set;get vs set; get; Should AfterCSharpProperty be use in this case? or do we introduce "BreakBetweenCSharpProperties " (default false) I know it seems strange to add 3 options to handle this, but I think it would give people the best of both worlds you can have the following in the same file (which is actually quite common) BreakBetweenCSharpProperties = false public Foo { get { return value; } set { value = 123; } } public Bar { get; set; } If we useAfterCSharpProperty to control BreakBetweenCSharpProperties then I think we have to have the following and we can't control Bar how we might want public Foo { get { return value; } set { value = 123; } } public Bar { get; set; } From what I can tell...Microsoft .NET Framework seems to be BreakBetweenCSharpProperties = true It would seem they don't seem to put Trivial Properties/AutoProperties on the same line Comment Actions Adds additional options to give us much greater control over how we format C# properties especially auto properties (Submitting this for safe keeping, I need to try and minimize the if expression, I'm sure it could be simplified into a few less clauses) Comment Actions Sorry had a clang-format reflow comments moment, revert the unrelated comment changes Comment Actions In my C# project, these settings give me just what we tend to use. BreakBeforeBraces: Custom BraceWrapping: AfterFunction: true AfterCSharpProperty: true AllowShortCSharpPropertiesOnASingleLine: false AlwaysBreakBetweenShortCSharpProperties: false for AutoProperties public int min_value { get; set; } but for formal properties, public int Margin { get { return this.value> 0? 10 : 0; } } although I like the idea of being able to change this to this with AfterCSharpProperty: false public int Margin { get { return this.value> 0? 10 : 0; } } MyDeveloperDay marked 10 inline comments as done. Comment ActionsAddress review comment, add convenience functions to simplify conditions Comment Actions There is another case I need to cover Style.BraceWrapping.AfterCSharpProperty = false; Style.AllowShortCSharpPropertiesOnASingleLine = false; Style.AlwaysBreakBetweenShortCSharpProperties = false; Style.BraceWrapping.AfterFunction = true; verifyFormat("class A\n" "{\n" " string Bar1\n" " {\n" " set; get;\n" " }\n" "}", Style); This is currently formatting as class A { string Bar1 { set; get; } } which doesn't feel quite right.
This revision is now accepted and ready to land.Apr 21 2023, 12:28 AM Comment Actions Just an update on this, it works well but some of the cases are not tolerant to comments, I'm working my way through those issues
Revision Contents
Diff 515298 clang/docs/ClangFormatStyleOptions.rst
clang/docs/ReleaseNotes.rst
clang/include/clang/Format/Format.h
clang/lib/Format/Format.cpp
clang/lib/Format/TokenAnnotator.h
clang/lib/Format/TokenAnnotator.cpp
clang/lib/Format/UnwrappedLineParser.cpp
clang/unittests/Format/FormatTestCSharp.cpp
|
Please sort. :)