Made a test encoder/decored for a simple namespace declaration with Fantomas OAK Ast, see fantomas tools page
given
Oak (1,0-1,15)
ModuleOrNamespaceNode (1,0-1,15)
ModuleOrNamespaceHeaderNode (1,0-1,15)
MultipleTextsNode (1,0-1,9)
namespace (1,0-1,9)
IdentListNode (1,10-1,15)
A (1,10-1,11)
B (1,12-1,13)
C (1,14-1,15)
it will output A.B.C
(lowered)
you can run it as dotnet fsi script.fsx
or in vscode with dotnet
sdk installed. cheers!
let oakAst =
"hello.one.two"
|> FantomasWriter.makeNamespace []
oakAst
|> FantomasReader.extractNsFromOak
|> Option.iter (printfn "NAMESPACE: %s")
Fabulous.AST
if you want to make your life easier and drop the custom write part for Oak, you can make use of the awesome Fabulous.AST DSL nuget package
#r "nuget:Fabulous.AST"
open System
open Fabulous.AST
open type Fabulous.AST.Ast
// using Fabulous.AST life becomes easier for writing oak
let oakAst =
Ast.Oak(){
Ast.Namespace("hello.one.two") {}
}
|> Gen.mkOak
Here a Gist of It
#r "nuget:Fantomas.Core" | |
open Fantomas.Core | |
open Fantomas.Core.SyntaxOak | |
open Fantomas.FCS.Text | |
open System | |
(** `namespace A.B.C` : https://fsprojects.github.io/fantomas-tools | |
Oak (1,0-1,15) | |
ModuleOrNamespaceNode (1,0-1,15) | |
ModuleOrNamespaceHeaderNode (1,0-1,15) | |
MultipleTextsNode (1,0-1,9) | |
namespace (1,0-1,9) | |
IdentListNode (1,10-1,15) | |
A (1,10-1,11) | |
B (1,12-1,13) | |
C (1,14-1,15) | |
*) | |
module FantomasWriter = | |
let text v = SingleTextNode(v, Range.Zero) | |
let toMultipleTexts lst = MultipleTextsNode(lst |> Seq.map text |> Seq.toList ,Range.Zero) | |
let toIdentList (lst: string seq) = | |
let ll = | |
lst | |
|> Seq.map (fun l -> | |
let content = l |> text | |
if l = "." then | |
content |> IdentifierOrDot.KnownDot | |
else | |
content |> IdentifierOrDot.Ident | |
) | |
|> Seq.toList | |
if ll.Length > 0 then | |
IdentListNode(ll, Range.Zero) |> Some | |
else | |
None | |
let makeModuleOrNamespaceHeaderNode (nameSpaceString: string) = | |
let ns = nameSpaceString.ToLower().Trim().Split([|'.'|]) | |
if ns.Length > 0 then | |
ModuleOrNamespaceHeaderNode( | |
None, | |
None, | |
[ "namespace" ] |> toMultipleTexts, | |
None, | |
false, | |
ns |> toIdentList, | |
Range.Zero) |> Some | |
else | |
None | |
let makeNamespace (nameSpaceString: string) decls = | |
let nsOpt = makeModuleOrNamespaceHeaderNode nameSpaceString | |
Oak([], | |
[ | |
ModuleOrNamespaceNode(nsOpt, decls, Range.Zero) | |
], Range.Zero) | |
module FantomasReader = | |
let extractNs (iln: IdentListNode) = | |
iln.Content | |
|> List.collect (fun iod -> | |
match iod with | |
| IdentifierOrDot.Ident(stn) -> [ stn.Text ] | |
| _ -> [] | |
) | |
|> fun l -> | |
if l.Length > 0 then | |
String.Join('.',l) |> Some | |
else | |
None | |
// Define a function to extract the namespace from an Oak AST | |
let extractNsFromOak (oak: Oak) = | |
oak.ModulesOrNamespaces.Head.Header | |
|> Option.bind ( | |
fun header -> | |
match header.LeadingKeyword.Content with | |
| [x] when x.Text = "namespace" -> | |
header.Name | |
|> Option.bind extractNs | |
| _ -> None | |
) | |
// Example usage | |
let oakAst = FantomasWriter.makeNamespace "hello.one.two" [] | |
oakAst | |
|> FantomasReader.extractNsFromOak | |
|> Option.iter (printfn "NAMESPACE: %s") |
Top comments (0)