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

Don't add additional newline before middle attribute scenario #934

Merged
merged 1 commit into from
Jun 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 46 additions & 0 deletions src/Fantomas.Tests/TypeDeclarationTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1345,3 +1345,49 @@ type Message =
{ [<JsonProperty("body")>]
Body: string }
"""

[<Test>]
let ``attribute on abstract member followed by type with attribute, 933`` () =
formatSourceString false """
[<AllowNullLiteral>]
type SubGroupStackOptions =
[<Emit "$0[$1]{{=$2}}">]
abstract Item: name:string -> bool with get, set

[<AllowNullLiteral>]
type DataGroup =
abstract className: string option with get, set
""" config
|> prepend newline
|> should equal """
[<AllowNullLiteral>]
type SubGroupStackOptions =
[<Emit "$0[$1]{{=$2}}">]
abstract Item: name:string -> bool with get, set

[<AllowNullLiteral>]
type DataGroup =
abstract className: string option with get, set
"""

[<Test>]
let ``attribute on abstract member followed by let binding with attribute`` () =
formatSourceString false """
[<AllowNullLiteral>]
type SubGroupStackOptions =
[<Emit "$0[$1]{{=$2}}">]
abstract Item: name:string -> bool with get, set

[<AllowNullLiteral>]
let foo bar = zero
""" config
|> prepend newline
|> should equal """
[<AllowNullLiteral>]
type SubGroupStackOptions =
[<Emit "$0[$1]{{=$2}}">]
abstract Item: name:string -> bool with get, set

[<AllowNullLiteral>]
let foo bar = zero
"""
38 changes: 19 additions & 19 deletions src/Fantomas/AstTransformer.fs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ module private Ast =
FsAstNode = modOrNs
Childs =
[yield! (if isModule = SynModuleOrNamespaceKind.DeclaredNamespace then collectIdents longIdent else [])
yield! attrs |> List.map visitSynAttributeList
yield! attrs |> List.map (visitSynAttributeList modOrNs)
yield! (decls |> List.map visitSynModuleDecl)]}

and visitSynModuleDecl(ast: SynModuleDecl) : Node =
Expand Down Expand Up @@ -125,7 +125,7 @@ module private Ast =
Range = r range
Properties = p []
FsAstNode = ast
Childs = attrs |> List.map visitSynAttributeList}
Childs = attrs |> List.map (visitSynAttributeList ast)}
| SynModuleDecl.HashDirective(hash,range) ->
{Type = "SynModuleDecl.HashDirective"
Range = r range
Expand Down Expand Up @@ -810,7 +810,7 @@ module private Ast =
if access.IsSome then yield "access" ==> (access.Value |> visitSynAccess)]
FsAstNode = mbrDef
Childs =
[yield! attrs |> List.map visitSynAttributeList
[yield! attrs |> List.map (visitSynAttributeList mbrDef)
yield visitSynSimplePats ctorArgs]}
| SynMemberDefn.ImplicitInherit(inheritType,inheritArgs,inheritAlias,range) ->
{Type = "SynMemberDefn.ImplicitInherit"
Expand Down Expand Up @@ -871,7 +871,7 @@ module private Ast =
if getSetRange.IsSome then yield "getSetRange" ==> (getSetRange.Value |> r)]
FsAstNode = mbrDef
Childs =
[yield! attrs |> List.map visitSynAttributeList
[yield! attrs |> List.map (visitSynAttributeList mbrDef)
if typeOpt.IsSome then yield visitSynType typeOpt.Value
yield visitSynExpr synExpr]}

Expand Down Expand Up @@ -902,7 +902,7 @@ module private Ast =
FsAstNode = sp
Childs =
[yield visitSynSimplePat simplePat
yield! attrs |> List.map visitSynAttributeList]}
yield! attrs |> List.map (visitSynAttributeList sp)]}

and visitSynSimplePats(sp: SynSimplePats): Node =
match sp with
Expand Down Expand Up @@ -933,7 +933,7 @@ module private Ast =
if access.IsSome then yield "access" ==> (access.Value |> visitSynAccess)]
FsAstNode = binding
Childs =
[yield! attrs |> List.map visitSynAttributeList
[yield! attrs |> List.map (visitSynAttributeList binding)
yield visitSynValData valData
yield visitSynPat headPat
if returnInfo.IsSome then yield visitSynBindingReturnInfo returnInfo.Value
Expand All @@ -960,7 +960,7 @@ module private Ast =
if access.IsSome then yield "access" ==> (access.Value |> visitSynAccess)]
FsAstNode = svs
Childs =
[yield! attrs |> List.map visitSynAttributeList
[yield! attrs |> List.map (visitSynAttributeList svs)
yield visitSynValTyparDecls explicitValDecls
yield visitSynType synType
yield visitSynValInfo arity
Expand All @@ -983,7 +983,7 @@ module private Ast =
Properties = p []
FsAstNode = std
Childs =
[yield! attrs |> List.map visitSynAttributeList
[yield! attrs |> List.map (visitSynAttributeList std)
yield visitSynTypar typar]}

and visitSynTypar(typar: SynTypar): Node =
Expand Down Expand Up @@ -1012,7 +1012,7 @@ module private Ast =
FsAstNode = returnInfo
Childs =
[yield visitSynType typeName
yield! (attrs |> List.map visitSynAttributeList)]}
yield! (attrs |> List.map (visitSynAttributeList returnInfo))]}

and visitSynPat(sp: SynPat): Node =
match sp with
Expand Down Expand Up @@ -1052,7 +1052,7 @@ module private Ast =
FsAstNode = sp
Childs =
[yield visitSynPat synPat
yield! attrs |> List.map visitSynAttributeList]}
yield! attrs |> List.map (visitSynAttributeList sp)]}
| SynPat.Or(synPat,synPat2,range) ->
{Type = "SynPat.Or"
Range = r range
Expand Down Expand Up @@ -1177,7 +1177,7 @@ module private Ast =
if access.IsSome then yield "access" ==> (access.Value |> visitSynAccess)]
FsAstNode = sci
Childs =
[yield! (attribs |> List.map visitSynAttributeList)
[yield! (attribs |> List.map (visitSynAttributeList sci))
yield! (typeParams |> List.map(visitSynTyparDecl))]}

and visitSynTypeDefnRepr(stdr: SynTypeDefnRepr): Node =
Expand Down Expand Up @@ -1346,7 +1346,7 @@ module private Ast =
if access.IsSome then yield "access" ==> (access.Value |> visitSynAccess)]
FsAstNode = sedr
Childs =
[yield! attrs |> List.map visitSynAttributeList
[yield! attrs |> List.map (visitSynAttributeList sedr)
yield visitSynUnionCase unionCase]}

and visitSynAttribute(attr: SynAttribute): Node =
Expand All @@ -1360,10 +1360,10 @@ module private Ast =
FsAstNode = attr
Childs = [visitSynExpr attr.ArgExpr]}

and visitSynAttributeList(attrs: SynAttributeList): Node =
and visitSynAttributeList (parent:obj) (attrs: SynAttributeList): Node =
{Type = "SynAttributeList"
Range = r attrs.Range
Properties = p []
Properties = p ["parent", parent]
FsAstNode = attrs
Childs = attrs.Attributes |> List.map visitSynAttribute
}
Expand All @@ -1379,7 +1379,7 @@ module private Ast =
FsAstNode = uc
Childs =
[yield visitSynUnionCaseType uct
yield! attrs |> List.map visitSynAttributeList]}
yield! attrs |> List.map (visitSynAttributeList uc)]}

and visitSynUnionCaseType(uct: SynUnionCaseType) =
match uct with
Expand All @@ -1405,7 +1405,7 @@ module private Ast =
Range = r range
Properties = p []
FsAstNode = sec
Childs = [yield! attrs |> List.map visitSynAttributeList; yield visitIdent ident]}
Childs = [yield! attrs |> List.map (visitSynAttributeList sec); yield visitIdent ident]}

and visitSynField(sfield: SynField): Node =
match sfield with
Expand All @@ -1418,7 +1418,7 @@ module private Ast =
if access.IsSome then yield "access" ==> (access.Value |> visitSynAccess)]
FsAstNode = sfield
Childs =
[yield! attrs |> List.map visitSynAttributeList
[yield! attrs |> List.map (visitSynAttributeList sfield)
yield visitSynType typ]}

and visitSynType(st: SynType) =
Expand Down Expand Up @@ -1566,7 +1566,7 @@ module private Ast =
p [if ident.IsSome then yield "ident" ==> i ident.Value
yield "optional" ==> optional]
FsAstNode = sai
Childs = [yield! attrs |> List.map visitSynAttributeList]}
Childs = [yield! attrs |> List.map (visitSynAttributeList sai)]}

and visitSynAccess(a: SynAccess) =
match a with
Expand Down Expand Up @@ -1613,7 +1613,7 @@ module private Ast =
FsAstNode = modOrNs
Childs =
[yield! (if isModule = SynModuleOrNamespaceKind.DeclaredNamespace then visitLongIdent longIdent else [])
yield! attrs |> List.map visitSynAttributeList
yield! attrs |> List.map (visitSynAttributeList modOrNs)
yield! (decls |> List.map visitSynModuleSigDecl)]}

and visitSynModuleSigDecl(ast: SynModuleSigDecl) : Node =
Expand Down
10 changes: 8 additions & 2 deletions src/Fantomas/Trivia.fs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,9 @@ let private findConstNodeAfter (nodes: TriviaNodeAssigner list) (range: range) =

let private mapNodeToTriviaNode (node: Node) =
node.Range
|> Option.map (fun range -> TriviaNodeAssigner(MainNode(node.Type), range))
|> Option.map (fun range ->
let attributeParent = Map.tryFind "parent" node.Properties
TriviaNodeAssigner(MainNode(node.Type), range, attributeParent))

let private commentIsAfterLastTriviaNode (triviaNodes: TriviaNodeAssigner list) (range: range) =
match List.filter isMainNodeButNotAnonModule triviaNodes with
Expand Down Expand Up @@ -223,7 +225,11 @@ let private triviaBetweenAttributeAndParentBinding (triviaNodes: TriviaNodeAssig
| a, p when (a.Type = MainNode("SynAttributeList") && a.Range.StartLine < line && a.Range.StartLine = a.Range.EndLine) ->
match p.Type with
| MainNode("SynModuleDecl.Let") when (p.Range.StartLine > line) -> true
| MainNode("SynAttributeList") when (p.Range.StartLine > line) -> true
| MainNode("SynAttributeList") when (p.Range.StartLine > line) ->
// This is an edge case scenario where the trivia needs to fit between two attributes of the same parent node.
match p.AttributeParent, a.AttributeParent with
| Some pp, Some ap -> pp = ap
| _ -> false
| MainNode("SynModuleDecl.Types") when (p.Range.StartLine > line) -> true
| _ -> false
| _ -> false)
Expand Down
3 changes: 2 additions & 1 deletion src/Fantomas/TriviaTypes.fs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,10 @@ type TriviaNode =
ContentAfter: TriviaContent list
Range: range }

type internal TriviaNodeAssigner(nodeType: TriviaNodeType, range: range) =
type internal TriviaNodeAssigner(nodeType: TriviaNodeType, range: range, ?attributeParent: obj) =
member this.Type = nodeType
member this.Range = range
member this.AttributeParent = attributeParent
member val ContentBefore = ResizeArray<TriviaContent>() with get,set
member val ContentItself = Option<TriviaContent>.None with get,set
member val ContentAfter = ResizeArray<TriviaContent>() with get,set