Generating source code

The Fantomas.Core NuGet package can also be used to format code programmatically.
The public API is available from the static CodeFormatter class. It exposes a couple of APIs to format code, one being to format code from a raw syntax tree.
This API assumes the user already parsed a syntax tree or constructed an artificial one.

Key motivation

It can be very tempting to generate some F# code by doing some string concatenations.
In simple scenarios this can work out, but in the long run it doesn't scale well:

For mercy's sake don't use string concatenation when generating F# code, use Fantomas instead. It is battle tested and proven technology!

Generating source code from scratch

Example syntax tree

To illustrate the API, lets generate a simple value binding: let a = 0.

#r "nuget: Fantomas.Core, 5.*" // Note that this will also load Fantomas.FCS, which contains the syntax tree types.

open FSharp.Compiler.Text
open FSharp.Compiler.Xml
open FSharp.Compiler.Syntax
open FSharp.Compiler.SyntaxTrivia

let implementationSyntaxTree =
    ParsedInput.ImplFile(
        ParsedImplFileInput(
            "filename.fsx",
            true,
            QualifiedNameOfFile(Ident("", Range.Zero)),
            [],
            [],
            [ SynModuleOrNamespace(
                  [],
                  false,
                  SynModuleOrNamespaceKind.AnonModule,
                  [ SynModuleDecl.Let(
                        false,
                        [ SynBinding(
                              None,
                              SynBindingKind.Normal,
                              false,
                              false,
                              [],
                              PreXmlDoc.Empty,
                              SynValData(None, SynValInfo([], SynArgInfo([], false, None)), None),
                              SynPat.Named(SynIdent(Ident("a", Range.Zero), None), false, None, Range.Zero),
                              None,
                              SynExpr.Const(SynConst.Int32(0), Range.Zero),
                              Range.Zero,
                              DebugPointAtBinding.Yes Range.Zero,
                              { EqualsRange = Some Range.Zero
                                LeadingKeyword = SynLeadingKeyword.Let Range.Zero }
                          ) ],
                        Range.Zero
                    ) ],
                  PreXmlDoc.Empty,
                  [],
                  None,
                  Range.Zero,
                  { LeadingKeyword = SynModuleOrNamespaceLeadingKeyword.None }
              ) ],
            (false, false),
            { ConditionalDirectives = []
              CodeComments = [] }
        )
    )

open Fantomas.Core

CodeFormatter.FormatASTAsync(implementationSyntaxTree) |> Async.RunSynchronously
"let a = 0
"

Constructing the entire syntax tree can be a bit overwhelming at first. There is a lot of information to provide and a lot to unpack if you have never seen any of this before.

Let's deconstruct a couple of things:

The more you interact with AST, the easier you pick up which node represents what.

Fantomas.FCS

When looking at the example, we notice that we've opened a couple of FSharp.Compiler.* namespaces.
Don't be fooled by this, Fantomas.Core and Fantomas.FCS do not reference FSharp.Compiler.Service!
Instead, Fantomas.FCS is a custom version of the F# compiler (built from source) that only exposes the F# parser and the syntax tree.

Fantomas.FCS exposes the exact same namespaces because it builds from the exact same F# compiler source code.
The key difference is that Fantomas.FCS will most likely contain a more recent version of the F# parser.
You can read the CHANGELOG to see what git commit was used to build Fantomas.FCS.

You can use Fantomas.FCS in your own projects, but be aware that it is not binary compatible with FSharp.Compiler.Service.
Example usage:

#r "nuget: Fantomas.FCS"

open FSharp.Compiler.Text
open Fantomas.FCS

Parse.parseFile false (SourceText.ofString "let a = 1") []
(ImplFile
   (ParsedImplFileInput
      ("tmp.fsx", true, QualifiedNameOfFile Tmp$fsx, [], [],
       [SynModuleOrNamespace
          ([Tmp], false, AnonModule,
           [Let
              (false,
               [SynBinding
                  (None, Normal, false, false, [],
                   PreXmlDoc ((1,0), FSharp.Compiler.Xml.XmlDocCollector),
                   SynValData
                     (None, SynValInfo ([], SynArgInfo ([], false, None)), None),
                   Named (SynIdent (a, None), false, None, tmp.fsx (1,4--1,5)),
                   None, Const (Int32 1, tmp.fsx (1,8--1,9)), tmp.fsx (1,4--1,5),
                   Yes tmp.fsx (1,0--1,9),
                   { LeadingKeyword = Let tmp.fsx (1,0--1,3)
                     EqualsRange = Some tmp.fsx (1,6--1,7) })],
               tmp.fsx (1,0--1,9))], PreXmlDocEmpty, [], None,
           tmp.fsx (1,0--1,9), { LeadingKeyword = None })], (false, false),
       { ConditionalDirectives = []
         CodeComments = [] })), [])

Tips and tricks

Online tool

The syntax tree can have an overwhelming type hierarchy.
We wholeheartedly recommend to use our online tool when working with AST.

F# AST Viewer

This shows you what AST nodes the parser created for a given input text.
From there on you can use our search bar to find the corresponding documentation:

Search bar

Match the AST the parser would produce

Fantomas will very selectively use information from the AST.
Please make sure you construct the same AST as the parser would.

// You typically make some helper functions along the way
let mkCodeFromExpression (e: SynExpr) : string =
    ParsedInput.ImplFile(
        ParsedImplFileInput(
            "filename.fsx",
            true,
            QualifiedNameOfFile(Ident("", Range.Zero)),
            [],
            [],
            [ SynModuleOrNamespace(
                  [],
                  false,
                  SynModuleOrNamespaceKind.AnonModule,
                  [ SynModuleDecl.Expr(e, Range.Zero) ],
                  PreXmlDoc.Empty,
                  [],
                  None,
                  Range.Zero,
                  { LeadingKeyword = SynModuleOrNamespaceLeadingKeyword.None }
              ) ],
            (false, false),
            { ConditionalDirectives = []
              CodeComments = [] }
        )
    )
    |> CodeFormatter.FormatASTAsync
    |> Async.RunSynchronously

let numberExpr = SynExpr.Const(SynConst.Int32(7), Range.Zero)
let wrappedNumber = SynExpr.Paren(numberExpr, Range.Zero, None, Range.Zero)
mkCodeFromExpression wrappedNumber
"(7
"

Notice that last but one argument None, it represents the range of the closing ).
The F# parser would include Some range when it parses code, so you need to provide a Some range value as well.
Even though the range is empty. Fantomas is designed to work with AST created by the parser.
Creating a SynExpr.Paren node is not enough to get both parentheses!
The CodeFormatter.FormatASTAsync API is really a side-effect and not a first class citizen.
It will work when you play ball with the exact shape of the parser.

let betterWrappedNumber =
    SynExpr.Paren(numberExpr, Range.Zero, Some Range.Zero, Range.Zero)

mkCodeFromExpression betterWrappedNumber
"(7)
"

As a rule of thumb: create what the parser creates, use the online tool!
Just because you can create AST nodes, does not mean Fantomas will do the right thing.

Look at the Fantomas code base

As mentioned, not every AST node is being used in Fantomas. There are numerous things that do not have any influence on the generation of code.
For example creating SynExpr.Lambda.

When you want to construct fun a b -> a + b, the AST the online tool produces looks like:

Lambda
  (false, false,
    SimplePats
    ([Id (a, None, false, false, false, tmp.fsx (1,4--1,5))],
    tmp.fsx (1,4--1,5)),
    Lambda
    (false, true,
    SimplePats
        ([Id (b, None, false, false, false, tmp.fsx (1,6--1,7))],
        tmp.fsx (1,6--1,7)),
    App
        (NonAtomic, false,
        App
            (NonAtomic, true,
            LongIdent
            (false,
                SynLongIdent
                ([op_Addition], [], [Some (OriginalNotation "+")]),
                None, tmp.fsx (1,13--1,14)), Ident a,
            tmp.fsx (1,11--1,14)), Ident b, tmp.fsx (1,11--1,16)),
    None, tmp.fsx (1,0--1,16),
    { ArrowRange = Some tmp.fsx (1,8--1,10) }),
    Some
    ([Named (SynIdent (a, None), false, None, tmp.fsx (1,4--1,5));
        Named (SynIdent (b, None), false, None, tmp.fsx (1,6--1,7))],
    App
        (NonAtomic, false,
        App
            (NonAtomic, true,
            LongIdent
            (false,
                SynLongIdent
                ([op_Addition], [], [Some (OriginalNotation "+")]),
                None, tmp.fsx (1,13--1,14)), Ident a,
            tmp.fsx (1,11--1,14)), Ident b, tmp.fsx (1,11--1,16))),
    tmp.fsx (1,0--1,16), { ArrowRange = Some tmp.fsx (1,8--1,10) })

but the Fantomas CodePrinter does not use all this data. We can easily create a Lambda without the nested body structure, as Fantomas will use the parsedData information.

// this dummy expr will never be used!
let dummyExpr = SynExpr.Const(SynConst.Unit, Range.Zero)

let lambdaExpr =
    let args =
        [ SynPat.Named(SynIdent(Ident("a", Range.Zero), None), false, None, Range.Zero)
          SynPat.Named(SynIdent(Ident("b", Range.Zero), None), false, None, Range.Zero) ]

    let expr =
        SynExpr.App(
            ExprAtomicFlag.NonAtomic,
            false,
            SynExpr.App(
                ExprAtomicFlag.NonAtomic,
                true,
                SynExpr.LongIdent(
                    false,
                    SynLongIdent(
                        [ Ident("_actually_not_used_", Range.Zero) ],
                        [],
                        [ Some(IdentTrivia.OriginalNotation("+")) ]
                    ),
                    None,
                    Range.Zero

                ),
                SynExpr.Ident(Ident("a", Range.Zero)),
                Range.Zero
            ),
            SynExpr.Ident(Ident("b", Range.Zero)),
            Range.Zero
        )

    SynExpr.Lambda(
        false,
        false,
        SynSimplePats.SimplePats([], Range.Zero), // not used
        dummyExpr, // not used
        Some(args, expr), // The good stuff is in here!
        Range.Zero,
        { ArrowRange = Some Range.Zero }
    )

mkCodeFromExpression lambdaExpr
"fun a b -> a + b
"

Notice how minimal the AST is, versus to what the parser produced. A subset of the data was enough.
How to know which nodes to include? Take a look at CodePrinter.fs and SourceParser.fs!

Create your own set of helper functions

Throughout all these examples, we have duplicated a lot of code. You can typically easily refactor this into some helper functions.
The Fantomas maintainers are not affiliated with any projects that expose AST construction helpers.
Relying on these projects, is at your own risk. The constructed AST might not be suitable for what Fantomas expects.

Updates

Since code generation is considered to be a nice to have functionality, there is no compatibility between any Fantomas.FCS.
We do not apply any semantic versioning to Fantomas.FCS. Breaking changes can be expected at any given point.

Multiple items
namespace FSharp

--------------------
namespace Microsoft.FSharp
namespace FSharp.Compiler
namespace FSharp.Compiler.Text
namespace FSharp.Compiler.Xml
namespace FSharp.Compiler.Syntax
namespace FSharp.Compiler.SyntaxTrivia
val implementationSyntaxTree: ParsedInput
type ParsedInput = | ImplFile of ParsedImplFileInput | SigFile of ParsedSigFileInput member FileName: string member QualifiedName: QualifiedNameOfFile member Range: range member ScopedPragmas: ScopedPragma list
<summary> Represents the syntax tree for a parsed implementation or signature file </summary>
union case ParsedInput.ImplFile: ParsedImplFileInput -> ParsedInput
<summary> A parsed implementation file </summary>
Multiple items
union case ParsedImplFileInput.ParsedImplFileInput: fileName: string * isScript: bool * qualifiedNameOfFile: QualifiedNameOfFile * scopedPragmas: ScopedPragma list * hashDirectives: ParsedHashDirective list * contents: SynModuleOrNamespace list * flags: bool * bool * trivia: ParsedImplFileInputTrivia -> ParsedImplFileInput

--------------------
type ParsedImplFileInput = | ParsedImplFileInput of fileName: string * isScript: bool * qualifiedNameOfFile: QualifiedNameOfFile * scopedPragmas: ScopedPragma list * hashDirectives: ParsedHashDirective list * contents: SynModuleOrNamespace list * flags: bool * bool * trivia: ParsedImplFileInputTrivia member Contents: SynModuleOrNamespace list member FileName: string member HashDirectives: ParsedHashDirective list member IsExe: bool member IsLastCompiland: bool member IsScript: bool member QualifiedName: QualifiedNameOfFile member ScopedPragmas: ScopedPragma list member Trivia: ParsedImplFileInputTrivia
<summary> Represents the full syntax tree, file name and other parsing information for an implementation file </summary>
Multiple items
union case QualifiedNameOfFile.QualifiedNameOfFile: Ident -> QualifiedNameOfFile

--------------------
type QualifiedNameOfFile = | QualifiedNameOfFile of Ident member Id: Ident member Range: range member Text: string
<summary> Represents a qualifying name for anonymous module specifications and implementations, </summary>
Multiple items
[<Struct>] type Ident = new: text: string * range: range -> Ident member idRange: range member idText: string
<summary> Represents an identifier in F# code </summary>

--------------------
Ident ()
new: text: string * range: range -> Ident
Multiple items
module Range from FSharp.Compiler.Text

--------------------
[<Struct>] type Range = member End: pos member EndColumn: int member EndLine: int member EndRange: range member FileName: string member IsSynthetic: bool member Start: pos member StartColumn: int member StartLine: int member StartRange: range ...
<summary> Represents a range within a file </summary>
property Range.Zero: range with get
<summary> The range where all values are zero </summary>
Multiple items
union case SynModuleOrNamespace.SynModuleOrNamespace: longId: LongIdent * isRecursive: bool * kind: SynModuleOrNamespaceKind * decls: SynModuleDecl list * xmlDoc: PreXmlDoc * attribs: SynAttributes * accessibility: SynAccess option * range: range * trivia: SynModuleOrNamespaceTrivia -> SynModuleOrNamespace

--------------------
type SynModuleOrNamespace = | SynModuleOrNamespace of longId: LongIdent * isRecursive: bool * kind: SynModuleOrNamespaceKind * decls: SynModuleDecl list * xmlDoc: PreXmlDoc * attribs: SynAttributes * accessibility: SynAccess option * range: range * trivia: SynModuleOrNamespaceTrivia member Range: range
<summary> Represents the definition of a module or namespace </summary>
[<Struct>] type SynModuleOrNamespaceKind = | NamedModule | AnonModule | DeclaredNamespace | GlobalNamespace member IsModule: bool
<summary> Represents the kind of a module or namespace definition </summary>
union case SynModuleOrNamespaceKind.AnonModule: SynModuleOrNamespaceKind
<summary> A module is anonymously named, e.g. a script </summary>
type SynModuleDecl = | ModuleAbbrev of ident: Ident * longId: LongIdent * range: range | NestedModule of moduleInfo: SynComponentInfo * isRecursive: bool * decls: SynModuleDecl list * isContinuing: bool * range: range * trivia: SynModuleDeclNestedModuleTrivia | Let of isRecursive: bool * bindings: SynBinding list * range: range | Expr of expr: SynExpr * range: range | Types of typeDefns: SynTypeDefn list * range: range | Exception of exnDefn: SynExceptionDefn * range: range | Open of target: SynOpenDeclTarget * range: range | Attributes of attributes: SynAttributes * range: range | HashDirective of hashDirective: ParsedHashDirective * range: range | NamespaceFragment of fragment: SynModuleOrNamespace member Range: range
<summary> Represents a definition within a module </summary>
union case SynModuleDecl.Let: isRecursive: bool * bindings: SynBinding list * range: range -> SynModuleDecl
<summary> A 'let' definition within a module </summary>
Multiple items
union case SynBinding.SynBinding: accessibility: SynAccess option * kind: SynBindingKind * isInline: bool * isMutable: bool * attributes: SynAttributes * xmlDoc: PreXmlDoc * valData: SynValData * headPat: SynPat * returnInfo: SynBindingReturnInfo option * expr: SynExpr * range: range * debugPoint: DebugPointAtBinding * trivia: SynBindingTrivia -> SynBinding

--------------------
type SynBinding = | SynBinding of accessibility: SynAccess option * kind: SynBindingKind * isInline: bool * isMutable: bool * attributes: SynAttributes * xmlDoc: PreXmlDoc * valData: SynValData * headPat: SynPat * returnInfo: SynBindingReturnInfo option * expr: SynExpr * range: range * debugPoint: DebugPointAtBinding * trivia: SynBindingTrivia member RangeOfBindingWithRhs: range member RangeOfBindingWithoutRhs: range member RangeOfHeadPattern: range
<summary> Represents a binding for a 'let' or 'member' declaration </summary>
union case Option.None: Option<'T>
type SynBindingKind = | StandaloneExpression | Normal | Do
<summary> The kind associated with a binding - "let", "do" or a standalone expression </summary>
union case SynBindingKind.Normal: SynBindingKind
<summary> A normal 'let' binding in a module </summary>
type PreXmlDoc = member ToXmlDoc: check: bool * paramNamesOpt: string list option -> XmlDoc static member Create: unprocessedLines: string array * range: range -> PreXmlDoc static member Merge: a: PreXmlDoc -> b: PreXmlDoc -> PreXmlDoc member IsEmpty: bool static member Empty: PreXmlDoc
<summary> Represents the XmlDoc fragments as collected from the lexer during parsing </summary>
property PreXmlDoc.Empty: PreXmlDoc with get
<summary> Get the empty PreXmlDoc </summary>
Multiple items
union case SynValData.SynValData: memberFlags: SynMemberFlags option * valInfo: SynValInfo * thisIdOpt: Ident option -> SynValData

--------------------
type SynValData = | SynValData of memberFlags: SynMemberFlags option * valInfo: SynValInfo * thisIdOpt: Ident option member SynValInfo: SynValInfo
<summary> Represents extra information about the declaration of a value </summary>
Multiple items
union case SynValInfo.SynValInfo: curriedArgInfos: SynArgInfo list list * returnInfo: SynArgInfo -> SynValInfo
<summary> SynValInfo(curriedArgInfos, returnInfo) </summary>

--------------------
type SynValInfo = | SynValInfo of curriedArgInfos: SynArgInfo list list * returnInfo: SynArgInfo member ArgNames: string list member CurriedArgInfos: SynArgInfo list list
<summary> The argument names and other metadata for a member or function </summary>
Multiple items
union case SynArgInfo.SynArgInfo: attributes: SynAttributes * optional: bool * ident: Ident option -> SynArgInfo

--------------------
type SynArgInfo = | SynArgInfo of attributes: SynAttributes * optional: bool * ident: Ident option member Attributes: SynAttributes member Ident: Ident option
<summary> Represents the argument names and other metadata for a parameter for a member or function </summary>
type SynPat = | Const of constant: SynConst * range: range | Wild of range: range | Named of ident: SynIdent * isThisVal: bool * accessibility: SynAccess option * range: range | Typed of pat: SynPat * targetType: SynType * range: range | Attrib of pat: SynPat * attributes: SynAttributes * range: range | Or of lhsPat: SynPat * rhsPat: SynPat * range: range * trivia: SynPatOrTrivia | ListCons of lhsPat: SynPat * rhsPat: SynPat * range: range * trivia: SynPatListConsTrivia | Ands of pats: SynPat list * range: range | As of lhsPat: SynPat * rhsPat: SynPat * range: range | LongIdent of longDotId: SynLongIdent * extraId: Ident option * typarDecls: SynValTyparDecls option * argPats: SynArgPats * accessibility: SynAccess option * range: range ... member Range: range
<summary> Represents a syntax tree for an F# pattern </summary>
union case SynPat.Named: ident: SynIdent * isThisVal: bool * accessibility: SynAccess option * range: range -> SynPat
<summary> A name pattern 'ident' </summary>
Multiple items
union case SynIdent.SynIdent: ident: Ident * trivia: IdentTrivia option -> SynIdent

--------------------
type SynIdent = | SynIdent of ident: Ident * trivia: IdentTrivia option
<summary> Represents an identifier with potentially additional trivia information. </summary>
type SynExpr = | Paren of expr: SynExpr * leftParenRange: range * rightParenRange: range option * range: range | Quote of operator: SynExpr * isRaw: bool * quotedExpr: SynExpr * isFromQueryExpression: bool * range: range | Const of constant: SynConst * range: range | Typed of expr: SynExpr * targetType: SynType * range: range | Tuple of isStruct: bool * exprs: SynExpr list * commaRanges: range list * range: range | AnonRecd of isStruct: bool * copyInfo: (SynExpr * BlockSeparator) option * recordFields: (Ident * range option * SynExpr) list * range: range | ArrayOrList of isArray: bool * exprs: SynExpr list * range: range | Record of baseInfo: (SynType * SynExpr * range * BlockSeparator option * range) option * copyInfo: (SynExpr * BlockSeparator) option * recordFields: SynExprRecordField list * range: range | New of isProtected: bool * targetType: SynType * expr: SynExpr * range: range | ObjExpr of objType: SynType * argOptions: (SynExpr * Ident option) option * withKeyword: range option * bindings: SynBinding list * members: SynMemberDefns * extraImpls: SynInterfaceImpl list * newExprRange: range * range: range ... member IsArbExprAndThusAlreadyReportedError: bool member Range: range member RangeOfFirstPortion: range member RangeWithoutAnyExtraDot: range
<summary> Represents a syntax tree for F# expressions </summary>
union case SynExpr.Const: constant: SynConst * range: range -> SynExpr
<summary> F# syntax: 1, 1.3, () etc. </summary>
type SynConst = | Unit | Bool of bool | SByte of sbyte | Byte of byte | Int16 of int16 | UInt16 of uint16 | Int32 of int32 | UInt32 of uint32 | Int64 of int64 | UInt64 of uint64 ... member Range: dflt: range -> range
<summary> The unchecked abstract syntax tree of constants in F# types and expressions. </summary>
union case SynConst.Int32: int32 -> SynConst
<summary> F# syntax: 13, 0x4000, 0o0777 </summary>
type DebugPointAtBinding = | Yes of range: range | NoneAtDo | NoneAtLet | NoneAtSticky | NoneAtInvisible member Combine: y: DebugPointAtBinding -> DebugPointAtBinding
<summary> Represents whether a debug point should be present for a 'let' binding, that is whether the construct corresponds to a debug point in the original source. </summary>
union case DebugPointAtBinding.Yes: range: range -> DebugPointAtBinding
union case Option.Some: Value: 'T -> Option<'T>
type SynLeadingKeyword = | Let of letRange: range | LetRec of letRange: range * recRange: range | And of andRange: range | Use of useRange: range | UseRec of useRange: range * recRange: range | Extern of externRange: range | Member of memberRange: range | MemberVal of memberRange: range * valRange: range | Override of overrideRange: range | OverrideVal of overrideRange: range * valRange: range ... member Range: range
<summary> Represents the leading keyword in a SynBinding or SynValSig </summary>
union case SynLeadingKeyword.Let: letRange: range -> SynLeadingKeyword
type SynModuleOrNamespaceLeadingKeyword = | Module of moduleRange: range | Namespace of namespaceRange: range | None
<summary> Represents the leading keyword in a SynModuleOrNamespace or SynModuleOrNamespaceSig </summary>
union case SynModuleOrNamespaceLeadingKeyword.None: SynModuleOrNamespaceLeadingKeyword
namespace Fantomas
namespace Fantomas.Core
type CodeFormatter = static member FormatASTAsync: ast: ParsedInput * ?source: string * ?config: FormatConfig -> Async<string> static member FormatDocumentAsync: isSignature: bool * source: string * ?config: FormatConfig -> Async<string> static member FormatSelectionAsync: isSignature: bool * source: string * selection: Range * ?config: FormatConfig -> Async<string * range> static member GetVersion: unit -> string static member IsValidFSharpCodeAsync: isSignature: bool * source: string -> Async<bool> static member MakeRange: fileName: string * startLine: int * startCol: int * endLine: int * endCol: int -> range static member ParseAsync: isSignature: bool * source: string -> Async<(ParsedInput * string list) array>
static member CodeFormatter.FormatASTAsync: ast: ParsedInput * ?source: string * ?config: FormatConfig.FormatConfig -> Async<string>
Multiple items
module Async from Fantomas.Core

--------------------
type Async = static member AsBeginEnd: computation: ('Arg -> Async<'T>) -> ('Arg * AsyncCallback * obj -> IAsyncResult) * (IAsyncResult -> 'T) * (IAsyncResult -> unit) static member AwaitEvent: event: IEvent<'Del,'T> * ?cancelAction: (unit -> unit) -> Async<'T> (requires delegate and 'Del :> Delegate) static member AwaitIAsyncResult: iar: IAsyncResult * ?millisecondsTimeout: int -> Async<bool> static member AwaitTask: task: Task<'T> -> Async<'T> + 1 overload static member AwaitWaitHandle: waitHandle: WaitHandle * ?millisecondsTimeout: int -> Async<bool> static member CancelDefaultToken: unit -> unit static member Catch: computation: Async<'T> -> Async<Choice<'T,exn>> static member Choice: computations: seq<Async<'T option>> -> Async<'T option> static member FromBeginEnd: beginAction: (AsyncCallback * obj -> IAsyncResult) * endAction: (IAsyncResult -> 'T) * ?cancelAction: (unit -> unit) -> Async<'T> + 3 overloads static member FromContinuations: callback: (('T -> unit) * (exn -> unit) * (OperationCanceledException -> unit) -> unit) -> Async<'T> ...

--------------------
type Async<'T>
static member Async.RunSynchronously: computation: Async<'T> * ?timeout: int * ?cancellationToken: System.Threading.CancellationToken -> 'T
namespace Fantomas.FCS
module Parse from Fantomas.FCS
val parseFile: isSignature: bool -> sourceText: ISourceText -> defines: string list -> ParsedInput * Parse.FSharpParserDiagnostic list
module SourceText from FSharp.Compiler.Text
<summary> Functions related to ISourceText objects </summary>
val ofString: string -> ISourceText
<summary> Creates an ISourceText object from the given string </summary>
val mkCodeFromExpression: e: SynExpr -> string
val e: SynExpr
Multiple items
val string: value: 'T -> string

--------------------
type string = System.String
union case SynModuleDecl.Expr: expr: SynExpr * range: range -> SynModuleDecl
<summary> An 'expr' within a module. </summary>
val numberExpr: SynExpr
val wrappedNumber: SynExpr
union case SynExpr.Paren: expr: SynExpr * leftParenRange: range * rightParenRange: range option * range: range -> SynExpr
<summary> F# syntax: (expr) Parenthesized expressions. Kept in AST to distinguish A.M((x, y)) from A.M(x, y), among other things. </summary>
val betterWrappedNumber: SynExpr
val dummyExpr: SynExpr
union case SynConst.Unit: SynConst
<summary> F# syntax: () </summary>
val lambdaExpr: SynExpr
val args: SynPat list
val expr: SynExpr
union case SynExpr.App: flag: ExprAtomicFlag * isInfix: bool * funcExpr: SynExpr * argExpr: SynExpr * range: range -> SynExpr
<summary> F# syntax: f x flag: indicates if the application is syntactically atomic, e.g. f.[1] is atomic, but 'f x' is not isInfix is true for the first app of an infix operator, e.g. 1+2 becomes App(App(+, 1), 2), where the inner node is marked isInfix </summary>
[<Struct>] type ExprAtomicFlag = | Atomic = 0 | NonAtomic = 1
<summary> Indicates if an expression is an atomic expression. An atomic expression has no whitespace unless enclosed in parentheses, e.g. 1, "3", ident, ident.[expr] and (expr). If an atomic expression has type T, then the largest expression ending at the same range as the atomic expression also has type T. </summary>
ExprAtomicFlag.NonAtomic: ExprAtomicFlag = 1
union case SynExpr.LongIdent: isOptional: bool * longDotId: SynLongIdent * altNameRefCell: SynSimplePatAlternativeIdInfo ref option * range: range -> SynExpr
<summary> F# syntax: ident.ident...ident isOptional: true if preceded by a '?' for an optional named parameter altNameRefCell: Normally 'None' except for some compiler-generated variables in desugaring pattern matching. See SynSimplePat.Id </summary>
Multiple items
union case SynLongIdent.SynLongIdent: id: LongIdent * dotRanges: range list * trivia: IdentTrivia option list -> SynLongIdent

--------------------
type SynLongIdent = | SynLongIdent of id: LongIdent * dotRanges: range list * trivia: IdentTrivia option list member Dots: range list member IdentsWithTrivia: SynIdent list member LongIdent: LongIdent member Range: range member RangeWithoutAnyExtraDot: range member ThereIsAnExtraDotAtTheEnd: bool member Trivia: IdentTrivia list
<summary> Represents a long identifier with possible '.' at end. Typically dotRanges.Length = lid.Length-1, but they may be same if (incomplete) code ends in a dot, e.g. "Foo.Bar." The dots mostly matter for parsing, and are typically ignored by the typechecker, but if dotRanges.Length = lid.Length, then the parser must have reported an error, so the typechecker is allowed more freedom about typechecking these expressions. LongIdent can be empty list - it is used to denote that name of some AST element is absent (i.e. empty type name in inherit) </summary>
type IdentTrivia = | OriginalNotation of text: string | OriginalNotationWithParen of leftParenRange: range * text: string * rightParenRange: range | HasParenthesis of leftParenRange: range * rightParenRange: range
union case IdentTrivia.OriginalNotation: text: string -> IdentTrivia
<summary> The ident originally had a different notation. Example: a + b The operator ident will be compiled into "op_Addition", while the original notation was "+" </summary>
union case SynExpr.Ident: ident: Ident -> SynExpr
<summary> F# syntax: ident Optimized representation for SynExpr.LongIdent (false, [id], id.idRange) </summary>
union case SynExpr.Lambda: fromMethod: bool * inLambdaSeq: bool * args: SynSimplePats * body: SynExpr * parsedData: (SynPat list * SynExpr) option * range: range * trivia: SynExprLambdaTrivia -> SynExpr
<summary> First bool indicates if lambda originates from a method. Patterns here are always "simple" Second bool indicates if this is a "later" part of an iterated sequence of lambdas parsedData keeps original parsed patterns and expression, prior to transforming to "simple" patterns and iterated lambdas F# syntax: fun pat -&gt; expr </summary>
type SynSimplePats = | SimplePats of pats: SynSimplePat list * range: range | Typed of pats: SynSimplePats * targetType: SynType * range: range member Range: range
<summary> Represents a simple set of variable bindings a, (a, b) or (a: Type, b: Type) at a lambda, function definition or other binding point, after the elimination of pattern matching from the construct, e.g. after changing a "function pat1 -&gt; rule1 | ..." to a "fun v -&gt; match v with ..." </summary>
union case SynSimplePats.SimplePats: pats: SynSimplePat list * range: range -> SynSimplePats