Last active
January 6, 2025 18:26
-
-
Save jkone27/9ec341d310d82a634a3a093890d16964 to your computer and use it in GitHub Desktop.
fantomas extract namespace declaration from oak synthax F# AST
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment