Skip to content

Commit 87a6577

Browse files
authored
Correctly print out attributes of SynMemberDefn.GetSetMember (#3115)
* Correctly print out attributes of SynMemberDefn.GetSetMember * Add changelog entry
1 parent a4788cb commit 87a6577

File tree

5 files changed

+96
-9
lines changed

5 files changed

+96
-9
lines changed

Diff for: CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# Changelog
22

3+
## 6.3.12 - 2024-09-05
4+
5+
### Fixed
6+
* Fantomas deletes attributes from getters. [#3114](https://github.com/fsprojects/fantomas/issues/3114)
7+
38
## 6.3.11 - 2024-08-16
49

510
### Fixed

Diff for: src/Fantomas.Core.Tests/AttributeTests.fs

+48
Original file line numberDiff line numberDiff line change
@@ -1050,3 +1050,51 @@ let ``trivia in nested multiline tuple expression in attribute, 2525`` () =
10501050
Justification = "Bytecode delta only")>]
10511051
()
10521052
"""
1053+
1054+
[<Test>]
1055+
let ``attributes on member and get, set properties`` () =
1056+
formatSourceString
1057+
"""
1058+
type Object3D() =
1059+
[<X>]
1060+
member this.position
1061+
with [<Y>] set v = _position <- v
1062+
and [<Z>] get () = _position
1063+
"""
1064+
config
1065+
|> prepend newline
1066+
|> should
1067+
equal
1068+
"""
1069+
type Object3D() =
1070+
[<X>]
1071+
member this.position
1072+
with [<Y>] set v = _position <- v
1073+
and [<Z>] get () = _position
1074+
"""
1075+
1076+
[<Test>]
1077+
let ``attributes on get,set properties, 3114`` () =
1078+
formatSourceString
1079+
"""
1080+
[<Erase>]
1081+
type Object3D() =
1082+
let mutable _position: Vector3 = null
1083+
1084+
member this.position
1085+
with [<Emit("$0.position")>] set v = _position <- v
1086+
and [<Emit("$0.position = $1")>] get () = _position
1087+
"""
1088+
config
1089+
|> prepend newline
1090+
|> should
1091+
equal
1092+
"""
1093+
[<Erase>]
1094+
type Object3D() =
1095+
let mutable _position: Vector3 = null
1096+
1097+
member this.position
1098+
with [<Emit("$0.position")>] set v = _position <- v
1099+
and [<Emit("$0.position = $1")>] get () = _position
1100+
"""

Diff for: src/Fantomas.Core/ASTTransformer.fs

+39-9
Original file line numberDiff line numberDiff line change
@@ -2650,17 +2650,30 @@ let mkWithGetSet (withKeyword: range option) (getSet: GetSetKeywords option) =
26502650

26512651
let mkPropertyGetSetBinding
26522652
(creationAide: CreationAide)
2653+
(withOrAndKeyword: range)
26532654
(accessibility: SynAccess option)
26542655
(leadingKeyword: SingleTextNode)
26552656
(binding: SynBinding)
26562657
: PropertyGetSetBindingNode =
26572658
match binding with
26582659
| SynBinding(
2660+
attributes = attributes
26592661
headPat = SynPat.LongIdent(extraId = Some extraIdent; argPats = SynArgPats.Pats ps)
26602662
returnInfo = returnInfo
26612663
expr = expr
26622664
trivia = { EqualsRange = Some mEq
26632665
InlineKeyword = inlineKw }) ->
2666+
// Attribute are not accurate in this case.
2667+
// The binding could contain attributes for the entire member and the getter or setter member.
2668+
// We use the `with` or `and` keyword to filter them.
2669+
let attributes =
2670+
attributes
2671+
|> List.map (fun al ->
2672+
{ al with
2673+
Attributes =
2674+
al.Attributes
2675+
|> List.filter (fun a -> Position.posGt a.Range.Start withOrAndKeyword.End) })
2676+
26642677
let e = parseExpressionInSynBinding returnInfo expr
26652678
let returnTypeNode = mkBindingReturnInfo creationAide returnInfo
26662679

@@ -2694,6 +2707,7 @@ let mkPropertyGetSetBinding
26942707

26952708
PropertyGetSetBindingNode(
26962709
Option.map (stn "inline") inlineKw,
2710+
mkAttributes creationAide attributes,
26972711
mkSynAccess accessibility,
26982712
leadingKeyword,
26992713
pats,
@@ -2863,7 +2877,7 @@ let mkMemberDefn (creationAide: CreationAide) (md: SynMemberDefn) =
28632877
GetKeyword = Some getKeyword
28642878
SetKeyword = Some setKeyword
28652879
WithKeyword = withKeyword
2866-
AndKeyword = andKeyword }) ->
2880+
AndKeyword = Some andKeyword }) ->
28672881

28682882
let firstAccessibility, firstBinding, firstKeyword, lastBinding, lastKeyword =
28692883
if Position.posLt getKeyword.Start setKeyword.Start then
@@ -2885,27 +2899,43 @@ let mkMemberDefn (creationAide: CreationAide) (md: SynMemberDefn) =
28852899
| SynBinding(headPat = SynPat.LongIdent(accessibility = Some vis)) when
28862900
rangeBeforePos memberName.Range vis.Range.Start
28872901
->
2888-
mkPropertyGetSetBinding creationAide (Some vis) firstKeyword firstBinding
2889-
| _ -> mkPropertyGetSetBinding creationAide None firstKeyword firstBinding
2902+
mkPropertyGetSetBinding creationAide withKeyword (Some vis) firstKeyword firstBinding
2903+
| _ -> mkPropertyGetSetBinding creationAide withKeyword None firstKeyword firstBinding
28902904

28912905
let lastBinding =
28922906
match lastBinding with
28932907
| SynBinding(headPat = SynPat.LongIdent(accessibility = Some vis)) when
28942908
rangeBeforePos memberName.Range vis.Range.Start
28952909
->
2896-
mkPropertyGetSetBinding creationAide (Some vis) lastKeyword lastBinding
2897-
| _ -> mkPropertyGetSetBinding creationAide None lastKeyword lastBinding
2910+
mkPropertyGetSetBinding creationAide andKeyword (Some vis) lastKeyword lastBinding
2911+
| _ -> mkPropertyGetSetBinding creationAide andKeyword None lastKeyword lastBinding
2912+
2913+
// Attributes placed on the member will be included in both bindings for the getter and setter.
2914+
// We need to filter out the attributes above the leading keyword (typically `member`).
2915+
let memberAttributes =
2916+
ats
2917+
|> List.choose (fun al ->
2918+
let filteredAttributeList =
2919+
{ al with
2920+
Attributes =
2921+
al.Attributes
2922+
|> List.filter (fun a -> Position.posLt a.Range.End lk.Range.Start) }
2923+
2924+
if filteredAttributeList.Attributes.IsEmpty then
2925+
None
2926+
else
2927+
Some filteredAttributeList)
28982928

28992929
MemberDefnPropertyGetSetNode(
29002930
mkXmlDoc px,
2901-
mkAttributes creationAide ats,
2931+
mkAttributes creationAide memberAttributes,
29022932
mkSynLeadingKeyword lk,
29032933
Option.map (stn "inline") inlineKw,
29042934
mkSynAccess accessibility,
29052935
mkSynLongIdent memberName,
29062936
stn "with" withKeyword,
29072937
firstBinding,
2908-
Option.map (stn "and") andKeyword,
2938+
Some(stn "and" andKeyword),
29092939
Some lastBinding,
29102940
memberDefinitionRange
29112941
)
@@ -2945,7 +2975,7 @@ let mkMemberDefn (creationAide: CreationAide) (md: SynMemberDefn) =
29452975
match getKeyword, setKeyword with
29462976
| Some getKeyword, None ->
29472977
let bindingNode =
2948-
mkPropertyGetSetBinding creationAide visProperty (stn "get" getKeyword) binding
2978+
mkPropertyGetSetBinding creationAide withKeyword visProperty (stn "get" getKeyword) binding
29492979

29502980
MemberDefnPropertyGetSetNode(
29512981
mkXmlDoc px,
@@ -2963,7 +2993,7 @@ let mkMemberDefn (creationAide: CreationAide) (md: SynMemberDefn) =
29632993
|> MemberDefn.PropertyGetSet
29642994
| None, Some setKeyword ->
29652995
let bindingNode =
2966-
mkPropertyGetSetBinding creationAide visProperty (stn "set" setKeyword) binding
2996+
mkPropertyGetSetBinding creationAide withKeyword visProperty (stn "set" setKeyword) binding
29672997

29682998
MemberDefnPropertyGetSetNode(
29692999
mkXmlDoc px,

Diff for: src/Fantomas.Core/CodePrinter.fs

+1
Original file line numberDiff line numberDiff line change
@@ -3877,6 +3877,7 @@ let genMemberDefn (md: MemberDefn) =
38773877
| MemberDefn.PropertyGetSet node ->
38783878
let genProperty (node: PropertyGetSetBindingNode) =
38793879
genInlineOpt node.Inline
3880+
+> genOnelinerAttributes node.Attributes
38803881
+> genAccessOpt node.Accessibility
38813882
+> genSingleTextNode node.LeadingKeyword
38823883
+> sepSpace

Diff for: src/Fantomas.Core/SyntaxOak.fs

+3
Original file line numberDiff line numberDiff line change
@@ -2521,6 +2521,7 @@ type MemberDefnAbstractSlotNode
25212521
type PropertyGetSetBindingNode
25222522
(
25232523
inlineNode: SingleTextNode option,
2524+
attributes: MultipleAttributeListNode option,
25242525
accessibility: SingleTextNode option,
25252526
leadingKeyword: SingleTextNode,
25262527
parameters: Pattern list,
@@ -2533,6 +2534,7 @@ type PropertyGetSetBindingNode
25332534

25342535
override val Children: Node array =
25352536
[| yield! noa inlineNode
2537+
yield! noa attributes
25362538
yield! noa accessibility
25372539
yield leadingKeyword
25382540
yield! List.map Pattern.Node parameters
@@ -2541,6 +2543,7 @@ type PropertyGetSetBindingNode
25412543
yield Expr.Node expr |]
25422544

25432545
member val Inline = inlineNode
2546+
member val Attributes = attributes
25442547
member val Accessibility = accessibility
25452548
member val LeadingKeyword = leadingKeyword
25462549
member val Parameters = parameters

0 commit comments

Comments
 (0)