From f4da4cd2a1747faae673690c42c56d6b84d04259 Mon Sep 17 00:00:00 2001 From: Patrick Stevens <3138005+Smaug123@users.noreply.github.com> Date: Sun, 6 Oct 2024 19:45:13 +0100 Subject: [PATCH] Add more helpers to Fantomas library (#7) --- WoofWare.Whippet.Fantomas/Ast.fs | 78 +++ WoofWare.Whippet.Fantomas/AstHelper.fs | 467 ++++++++++++++++++ WoofWare.Whippet.Fantomas/List.fs | 23 + WoofWare.Whippet.Fantomas/SurfaceBaseline.txt | 141 +++++- WoofWare.Whippet.Fantomas/SynAttributes.fs | 4 + WoofWare.Whippet.Fantomas/SynBinding.fs | 24 + WoofWare.Whippet.Fantomas/SynTypeDefn.fs | 22 + .../WoofWare.Whippet.Fantomas.fsproj | 2 + WoofWare.Whippet.Fantomas/version.json | 4 +- 9 files changed, 762 insertions(+), 3 deletions(-) create mode 100644 WoofWare.Whippet.Fantomas/AstHelper.fs create mode 100644 WoofWare.Whippet.Fantomas/List.fs diff --git a/WoofWare.Whippet.Fantomas/Ast.fs b/WoofWare.Whippet.Fantomas/Ast.fs index 6dea48c..2afa744 100644 --- a/WoofWare.Whippet.Fantomas/Ast.fs +++ b/WoofWare.Whippet.Fantomas/Ast.fs @@ -7,6 +7,7 @@ open Fantomas.FCS.SyntaxTrivia /// Helper methods to convert between source code and FCS ASTs. [] module Ast = + /// Given the contents of an F# source file, parse it into an AST. This is sync-over-async internally, which is /// naughty. let parse (fileContents : string) : ParsedInput = @@ -45,3 +46,80 @@ module Ast = let cfg = FormatConfig.Default CodeFormatter.FormatASTAsync (parseTree, cfg) |> Async.RunSynchronously |> Some + + /// For each namespace in the AST, returns the types defined therein. + let getTypes (ast : ParsedInput) : (LongIdent * SynTypeDefn list) list = + match ast with + | ParsedInput.SigFile psfi -> failwith "Signature files not supported" + | ParsedInput.ImplFile pifi -> + pifi.Contents + |> List.collect (fun (SynModuleOrNamespace.SynModuleOrNamespace (ns, _, _, decls, _, _, _, _, _)) -> + decls + |> List.collect (fun decl -> + match decl with + | SynModuleDecl.Types (defns, _) -> defns |> List.map (fun defn -> ns, defn) + | _ -> [] + ) + ) + |> List.map (fun (li, ty) -> (li |> List.map _.idText), (ty, li)) + |> List.groupBy fst + |> List.map (fun (_name, data) -> + let ns = snd (snd data.[0]) + let data = data |> List.map (fun (_, (ty, _)) -> ty) + ns, data + ) + + /// For each namespace in the AST, returns the records contained therein. + let getRecords (ast : ParsedInput) : (LongIdent * RecordType list) list = + match ast with + | ParsedInput.SigFile psfi -> + psfi.Contents + |> List.collect (fun (SynModuleOrNamespaceSig.SynModuleOrNamespaceSig (ns, _, _, decls, _, _, _, _, _)) -> + decls + |> List.collect (fun decl -> + match decl with + | SynModuleSigDecl.Types (defns, _) -> + defns + |> List.choose (fun defn -> + match defn with + | SynTypeDefnSig.SynTypeDefnSig (sci, typeRepr, members, _, _) -> + match typeRepr with + | SynTypeDefnSigRepr.Simple (SynTypeDefnSimpleRepr.Record (access, fields, _), _) -> + (ns, + RecordType.OfRecord + sci + (failwith "Signature files not yet supported") + access + fields) + |> Some + | _ -> None + ) + | _ -> [] + ) + ) + | ParsedInput.ImplFile pifi -> + pifi.Contents + |> List.collect (fun (SynModuleOrNamespace.SynModuleOrNamespace (ns, _, _, decls, _, _, _, _, _)) -> + decls + |> List.collect (fun decl -> + match decl with + | SynModuleDecl.Types (defns, _) -> + defns + |> List.choose (fun defn -> + match defn with + | SynTypeDefn.SynTypeDefn (sci, typeRepr, smd, _, _, _) -> + match typeRepr with + | SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record (access, fields, _), _) -> + (ns, RecordType.OfRecord sci smd access fields) |> Some + | _ -> None + ) + | _ -> [] + ) + ) + |> List.map (fun (li, ty) -> (li |> List.map _.idText), (ty, li)) + |> List.groupBy fst + |> List.map (fun (_name, data) -> + let ns = snd (snd data.[0]) + let data = data |> List.map (fun (_, (ty, _)) -> ty) + ns, data + ) diff --git a/WoofWare.Whippet.Fantomas/AstHelper.fs b/WoofWare.Whippet.Fantomas/AstHelper.fs new file mode 100644 index 0000000..55b1dc1 --- /dev/null +++ b/WoofWare.Whippet.Fantomas/AstHelper.fs @@ -0,0 +1,467 @@ +namespace WoofWare.Whippet.Fantomas + +open Fantomas.FCS.Syntax +open Fantomas.FCS.Text.Range +open Fantomas.FCS.Xml +open WoofWare.Whippet.Fantomas + +/// Information about a single parameter to a method. +/// Several of these might be tupled up. +type ParameterInfo = + { + /// Attributes which apply to this parameter. + Attributes : SynAttribute list + /// True if the parameter is optional (i.e. `?foo`) + IsOptional : bool + /// Name of the parameter, if there is one. + Id : Ident option + /// Type of the parameter. + Type : SynType + } + +/// A combination of several ParameterInfo tupled together. +type TupledArg = + { + /// True if there are parentheses around this tuple. + HasParen : bool + /// The various parameters tupled into this arg. + Args : ParameterInfo list + } + +/// A member of an interface definition. +type MemberInfo = + { + /// The type of the member, e.g. the `int` in `member this.Foo : unit -> int`. + ReturnType : SynType + /// Accessibility modifier, e.g. `member private this.Foo ...` + Accessibility : SynAccess option + /// Each element of this list is a list of args in a tuple, or just one arg if not a tuple. + Args : TupledArg list + /// Name of this member. + Identifier : Ident + /// Attribute applying to this member. + Attributes : SynAttribute list + /// Docstring of this member. + XmlDoc : PreXmlDoc option + /// True if there's an `inline` modifier on this member. + IsInline : bool + /// True if there's a `mutable` modifier on this member. + IsMutable : bool + } + +/// A property can be `with get() = ...`, `with set param = ...`, or `with get() = ... and set param = ...`. +[] +type PropertyAccessors = + /// This property has only a getter. + | Get + /// This property has only a setter. + | Set + /// This property has both a getter and a setter. + | GetSet + +/// A property in an interface definition, i.e. something with a `get` and/or `set`. +type PropertyInfo = + { + /// Type of the property. + Type : SynType + /// Accessibility modifier of the property. + Accessibility : SynAccess option + /// Attributes on the property. + Attributes : SynAttribute list + /// Docstring of the property. + XmlDoc : PreXmlDoc option + /// How this property can be accessed. + Accessors : PropertyAccessors + /// True if there's an `inline` modifier on this property. + IsInline : bool + /// Name of the property. + Identifier : Ident + } + +/// Structured representation of an interface type definition. +type InterfaceType = + { + /// Attributes on the type. + Attributes : SynAttribute list + /// Name of the type being defined. + Name : LongIdent + /// Any `inherit` statements: `type Foo = inherit Bar`. + Inherits : SynType list + /// Interface members. + Members : MemberInfo list + /// Interface properties. + Properties : PropertyInfo list + /// Any generic type parameters the type has. + Generics : SynTyparDecls option + /// Accessibility modifier: `type private Foo = ...` + Accessibility : SynAccess option + } + +/// Structured representation of a record type definition. +type RecordType = + { + /// Name of the type being defined. + Name : Ident + /// Fields in the record. + Fields : SynField list + /// Any additional members which are not record fields. + Members : SynMemberDefns option + /// Docstring of the type. + XmlDoc : PreXmlDoc option + /// Any generic parameters the type has. + Generics : SynTyparDecls option + /// Accessibility: `type private Foo = { ... }` + TypeAccessibility : SynAccess option + /// Accessibility: `type Foo = private { ... }` + ImplAccessibility : SynAccess option + /// Attributes on the type. + Attributes : SynAttribute list + } + + /// Parse from the AST. + static member OfRecord + (sci : SynComponentInfo) + (smd : SynMemberDefns) + (access : SynAccess option) + (recordFields : SynField list) + : RecordType + = + match sci with + | SynComponentInfo.SynComponentInfo (attrs, typars, _, longId, doc, _, implAccess, _) -> + { + Name = List.last longId + Fields = recordFields + Members = if smd.IsEmpty then None else Some smd + XmlDoc = if doc.IsEmpty then None else Some doc + Generics = typars + ImplAccessibility = implAccess + TypeAccessibility = access + Attributes = attrs |> List.collect (fun l -> l.Attributes) + } + + /// Construct the AST object which represents the definition of this record type. + static member ToAst (record : RecordType) : SynTypeDefn = + let name = + SynComponentInfo.create record.Name + |> SynComponentInfo.setAccessibility record.TypeAccessibility + |> match record.XmlDoc with + | None -> id + | Some doc -> SynComponentInfo.withDocString doc + |> SynComponentInfo.setGenerics record.Generics + + SynTypeDefnRepr.recordWithAccess record.ImplAccessibility (Seq.toList record.Fields) + |> SynTypeDefn.create name + |> SynTypeDefn.withMemberDefns (defaultArg record.Members SynMemberDefns.Empty) + +/// Methods for manipulating UnionCase. +[] +module UnionCase = + /// Construct our structured `UnionCase` from an FCS `SynUnionCase`: extract everything + /// we care about from the AST representation. + let ofSynUnionCase (case : SynUnionCase) : UnionCase = + match case with + | SynUnionCase.SynUnionCase (attributes, ident, caseType, xmlDoc, access, _, _) -> + + let ident = + match ident with + | SynIdent.SynIdent (ident, _) -> ident + + let fields = + match caseType with + | SynUnionCaseKind.Fields cases -> cases + | SynUnionCaseKind.FullType _ -> failwith "unexpected FullType union" + + { + Name = ident + XmlDoc = if xmlDoc.IsEmpty then None else Some xmlDoc + Access = access + Attributes = attributes |> List.collect (fun t -> t.Attributes) + Fields = fields |> List.map SynField.extract + } + + /// Functorial `map`. + let mapIdentFields<'a, 'b> (f : 'a -> 'b) (unionCase : UnionCase<'a>) : UnionCase<'b> = + { + Attributes = unionCase.Attributes + Name = unionCase.Name + Access = unionCase.Access + XmlDoc = unionCase.XmlDoc + Fields = unionCase.Fields |> List.map (SynField.mapIdent f) + } + +/// Structured representation of a discriminated union definition. +type UnionType = + { + /// The name of the DU: for example, `type Foo = | Blah` has this being `Foo`. + Name : Ident + /// Any additional members which are not union cases. + Members : SynMemberDefns option + /// Any docstring associated with the DU itself (not its cases). + XmlDoc : PreXmlDoc option + /// Generic type parameters this DU takes: `type Foo<'a> = | ...`. + Generics : SynTyparDecls option + /// Attributes of the DU (not its cases): `[] type Foo = | ...` + Attributes : SynAttribute list + /// Accessibility modifier of the DU: `type private Foo = ...` + TypeAccessibility : SynAccess option + /// Accessibility modifier of the DU's implementation: `type Foo = private | ...` + ImplAccessibility : SynAccess option + /// The actual DU cases themselves. + Cases : UnionCase list + } + + /// Build a structured representation from a DU pulled from the AST. + static member OfUnion + (sci : SynComponentInfo) + (smd : SynMemberDefns) + (access : SynAccess option) + (cases : SynUnionCase list) + : UnionType + = + match sci with + | SynComponentInfo.SynComponentInfo (attrs, typars, _, longId, doc, _, implAccess, _) -> + { + Name = List.last longId + Members = if smd.IsEmpty then None else Some smd + XmlDoc = if doc.IsEmpty then None else Some doc + Generics = typars + Attributes = attrs |> List.collect (fun l -> l.Attributes) + TypeAccessibility = access + ImplAccessibility = implAccess + Cases = cases |> List.map UnionCase.ofSynUnionCase + } + +/// Miscellaneous methods for manipulating AST types. +[] +module AstHelper = + + /// Construct a record from the given fields. + let instantiateRecord (fields : (SynLongIdent * SynExpr) list) : SynExpr = + let fields = + fields + |> List.map (fun (rfn, synExpr) -> SynExprRecordField ((rfn, true), Some range0, Some synExpr, None)) + + SynExpr.Record (None, None, fields, range0) + + let rec private extractOpensFromDecl (moduleDecls : SynModuleDecl list) : SynOpenDeclTarget list = + moduleDecls + |> List.choose (fun moduleDecl -> + match moduleDecl with + | SynModuleDecl.Open (target, _) -> Some target + | _ -> None + ) + + /// Get all the `open` statements from the input. + let extractOpens (ast : ParsedInput) : SynOpenDeclTarget list = + match ast with + | ParsedInput.SigFile _ -> failwith "Signature files not yet supported" + | ParsedInput.ImplFile (ParsedImplFileInput (_, _, _, _, _, modules, _, _, _)) -> + modules + |> List.collect (fun (SynModuleOrNamespace (_, _, _, decls, _, _, _, _, _)) -> extractOpensFromDecl decls) + + let rec private convertSigParam (ty : SynType) : ParameterInfo * bool = + match ty with + | SynType.Paren (inner, _) -> + let result, _ = convertSigParam inner + result, true + | SynType.LongIdent (SynLongIdent.SynLongIdent (ident, _, _)) -> + { + Attributes = [] + IsOptional = false + Id = None + Type = SynType.createLongIdent ident + }, + false + | SynType.SignatureParameter (attrs, opt, id, usedType, _) -> + let attrs = attrs |> List.collect (fun attrs -> attrs.Attributes) + + { + Attributes = attrs + IsOptional = opt + Id = id + Type = usedType + }, + false + | SynType.Var (typar, _) -> + { + Attributes = [] + IsOptional = false + Id = None + Type = SynType.var typar + }, + false + | _ -> failwithf "expected SignatureParameter, got: %+A" ty + + let rec private extractTupledTypes (tupleType : SynTupleTypeSegment list) : TupledArg = + match tupleType with + | [] -> + { + HasParen = false + Args = [] + } + | [ SynTupleTypeSegment.Type param ] -> + let converted, hasParen = convertSigParam param + + { + HasParen = hasParen + Args = [ converted ] + } + | SynTupleTypeSegment.Type param :: SynTupleTypeSegment.Star _ :: rest -> + let rest = extractTupledTypes rest + let converted, _ = convertSigParam param + + { + HasParen = false + Args = converted :: rest.Args + } + | _ -> failwithf "Didn't have alternating type-and-star in interface member definition: %+A" tupleType + + let private parseMember (slotSig : SynValSig) (flags : SynMemberFlags) : Choice = + if not flags.IsInstance then + failwith "member was not an instance member" + + let propertyAccessors = + match flags.MemberKind with + | SynMemberKind.Member -> None + | SynMemberKind.PropertyGet -> Some PropertyAccessors.Get + | SynMemberKind.PropertySet -> Some PropertyAccessors.Set + | SynMemberKind.PropertyGetSet -> Some PropertyAccessors.GetSet + | kind -> failwithf "Unrecognised member kind: %+A" kind + + match slotSig with + | SynValSig (attrs, + SynIdent.SynIdent (ident, _), + _typeParams, + synType, + _arity, + isInline, + isMutable, + xmlDoc, + accessibility, + synExpr, + _, + _) -> + + match synExpr with + | Some _ -> failwith "literal members are not supported" + | None -> () + + let attrs = attrs |> List.collect _.Attributes + + let args, ret = SynType.getType synType + + let args = + args + |> List.map (fun (args, hasParen) -> + match args with + | SynType.Tuple (false, path, _) -> extractTupledTypes path + | SynType.SignatureParameter _ -> + let arg, hasParen = convertSigParam args + + { + HasParen = hasParen + Args = [ arg ] + } + | SynType.LongIdent (SynLongIdent (ident, _, _)) -> + { + HasParen = false + Args = + { + Attributes = [] + IsOptional = false + Id = None + Type = SynType.createLongIdent ident + } + |> List.singleton + } + | SynType.Var (typar, _) -> + { + HasParen = false + Args = + { + Attributes = [] + IsOptional = false + Id = None + Type = SynType.var typar + } + |> List.singleton + } + | arg -> + { + HasParen = false + Args = + { + Attributes = [] + IsOptional = false + Id = None + Type = arg + } + |> List.singleton + } + |> fun ty -> + { ty with + HasParen = ty.HasParen || hasParen + } + ) + + match propertyAccessors with + | None -> + { + ReturnType = ret + Args = args + Identifier = ident + Attributes = attrs + XmlDoc = Some xmlDoc + Accessibility = accessibility + IsInline = isInline + IsMutable = isMutable + } + |> Choice1Of2 + | Some accessors -> + { + Type = ret + Accessibility = accessibility + Attributes = attrs + XmlDoc = Some xmlDoc + Accessors = accessors + IsInline = isInline + Identifier = ident + } + |> Choice2Of2 + + /// Assumes that the input type is an ObjectModel, i.e. a `type Foo = member ...` + let parseInterface (interfaceType : SynTypeDefn) : InterfaceType = + let (SynTypeDefn (SynComponentInfo (attrs, typars, _, interfaceName, _, _, accessibility, _), + synTypeDefnRepr, + _, + _, + _, + _)) = + interfaceType + + let attrs = attrs |> List.collect (fun s -> s.Attributes) + + let members, inherits = + match synTypeDefnRepr with + | SynTypeDefnRepr.ObjectModel (_kind, members, _) -> + members + |> List.map (fun defn -> + match defn with + | SynMemberDefn.AbstractSlot (slotSig, flags, _, _) -> Choice1Of2 (parseMember slotSig flags) + | SynMemberDefn.Inherit (baseType, _asIdent, _) -> Choice2Of2 baseType + | _ -> failwith $"Unrecognised member definition: %+A{defn}" + ) + | _ -> failwith $"Unrecognised SynTypeDefnRepr for an interface type: %+A{synTypeDefnRepr}" + |> List.partitionChoice + + let members, properties = members |> List.partitionChoice + + { + Members = members + Properties = properties + Name = interfaceName + Inherits = inherits + Attributes = attrs + Generics = typars + Accessibility = accessibility + } diff --git a/WoofWare.Whippet.Fantomas/List.fs b/WoofWare.Whippet.Fantomas/List.fs new file mode 100644 index 0000000..825f1e9 --- /dev/null +++ b/WoofWare.Whippet.Fantomas/List.fs @@ -0,0 +1,23 @@ +namespace WoofWare.Whippet.Fantomas + +[] +module private List = + let partitionChoice<'a, 'b> (xs : Choice<'a, 'b> list) : 'a list * 'b list = + let xs, ys = + (([], []), xs) + ||> List.fold (fun (xs, ys) v -> + match v with + | Choice1Of2 x -> x :: xs, ys + | Choice2Of2 y -> xs, y :: ys + ) + + List.rev xs, List.rev ys + + let allSome<'a> (l : 'a option list) : 'a list option = + let rec go acc (l : 'a option list) = + match l with + | [] -> Some (List.rev acc) + | None :: _ -> None + | Some head :: tail -> go (head :: acc) tail + + go [] l diff --git a/WoofWare.Whippet.Fantomas/SurfaceBaseline.txt b/WoofWare.Whippet.Fantomas/SurfaceBaseline.txt index 6013bdf..42e6fc5 100644 --- a/WoofWare.Whippet.Fantomas/SurfaceBaseline.txt +++ b/WoofWare.Whippet.Fantomas/SurfaceBaseline.txt @@ -1,6 +1,12 @@ WoofWare.Whippet.Fantomas.Ast inherit obj +WoofWare.Whippet.Fantomas.Ast.getRecords [static method]: Fantomas.FCS.Syntax.ParsedInput -> (Fantomas.FCS.Syntax.Ident list * WoofWare.Whippet.Fantomas.RecordType list) list +WoofWare.Whippet.Fantomas.Ast.getTypes [static method]: Fantomas.FCS.Syntax.ParsedInput -> (Fantomas.FCS.Syntax.Ident list * Fantomas.FCS.Syntax.SynTypeDefn list) list WoofWare.Whippet.Fantomas.Ast.parse [static method]: string -> Fantomas.FCS.Syntax.ParsedInput WoofWare.Whippet.Fantomas.Ast.render [static method]: Fantomas.FCS.Syntax.SynModuleOrNamespace list -> string option +WoofWare.Whippet.Fantomas.AstHelper inherit obj +WoofWare.Whippet.Fantomas.AstHelper.extractOpens [static method]: Fantomas.FCS.Syntax.ParsedInput -> Fantomas.FCS.Syntax.SynOpenDeclTarget list +WoofWare.Whippet.Fantomas.AstHelper.instantiateRecord [static method]: (Fantomas.FCS.Syntax.SynLongIdent * Fantomas.FCS.Syntax.SynExpr) list -> Fantomas.FCS.Syntax.SynExpr +WoofWare.Whippet.Fantomas.AstHelper.parseInterface [static method]: Fantomas.FCS.Syntax.SynTypeDefn -> WoofWare.Whippet.Fantomas.InterfaceType WoofWare.Whippet.Fantomas.CompExprBinding inherit obj - union type with 4 cases WoofWare.Whippet.Fantomas.CompExprBinding+Do inherit WoofWare.Whippet.Fantomas.CompExprBinding WoofWare.Whippet.Fantomas.CompExprBinding+Do.body [property]: [read-only] Fantomas.FCS.Syntax.SynExpr @@ -44,11 +50,111 @@ WoofWare.Whippet.Fantomas.Ident.create [static method]: string -> Fantomas.FCS.S WoofWare.Whippet.Fantomas.Ident.createSanitisedParamName [static method]: string -> Fantomas.FCS.Syntax.Ident WoofWare.Whippet.Fantomas.Ident.createSanitisedTypeName [static method]: string -> Fantomas.FCS.Syntax.Ident WoofWare.Whippet.Fantomas.Ident.lowerFirstLetter [static method]: Fantomas.FCS.Syntax.Ident -> Fantomas.FCS.Syntax.Ident +WoofWare.Whippet.Fantomas.InterfaceType inherit obj +WoofWare.Whippet.Fantomas.InterfaceType..ctor [constructor]: (Fantomas.FCS.Syntax.SynAttribute list, Fantomas.FCS.Syntax.Ident list, Fantomas.FCS.Syntax.SynType list, WoofWare.Whippet.Fantomas.MemberInfo list, WoofWare.Whippet.Fantomas.PropertyInfo list, Fantomas.FCS.Syntax.SynTyparDecls option, Fantomas.FCS.Syntax.SynAccess option) +WoofWare.Whippet.Fantomas.InterfaceType.Accessibility [property]: [read-only] Fantomas.FCS.Syntax.SynAccess option +WoofWare.Whippet.Fantomas.InterfaceType.Attributes [property]: [read-only] Fantomas.FCS.Syntax.SynAttribute list +WoofWare.Whippet.Fantomas.InterfaceType.Generics [property]: [read-only] Fantomas.FCS.Syntax.SynTyparDecls option +WoofWare.Whippet.Fantomas.InterfaceType.get_Accessibility [method]: unit -> Fantomas.FCS.Syntax.SynAccess option +WoofWare.Whippet.Fantomas.InterfaceType.get_Attributes [method]: unit -> Fantomas.FCS.Syntax.SynAttribute list +WoofWare.Whippet.Fantomas.InterfaceType.get_Generics [method]: unit -> Fantomas.FCS.Syntax.SynTyparDecls option +WoofWare.Whippet.Fantomas.InterfaceType.get_Inherits [method]: unit -> Fantomas.FCS.Syntax.SynType list +WoofWare.Whippet.Fantomas.InterfaceType.get_Members [method]: unit -> WoofWare.Whippet.Fantomas.MemberInfo list +WoofWare.Whippet.Fantomas.InterfaceType.get_Name [method]: unit -> Fantomas.FCS.Syntax.Ident list +WoofWare.Whippet.Fantomas.InterfaceType.get_Properties [method]: unit -> WoofWare.Whippet.Fantomas.PropertyInfo list +WoofWare.Whippet.Fantomas.InterfaceType.Inherits [property]: [read-only] Fantomas.FCS.Syntax.SynType list +WoofWare.Whippet.Fantomas.InterfaceType.Members [property]: [read-only] WoofWare.Whippet.Fantomas.MemberInfo list +WoofWare.Whippet.Fantomas.InterfaceType.Name [property]: [read-only] Fantomas.FCS.Syntax.Ident list +WoofWare.Whippet.Fantomas.InterfaceType.Properties [property]: [read-only] WoofWare.Whippet.Fantomas.PropertyInfo list +WoofWare.Whippet.Fantomas.MemberInfo inherit obj +WoofWare.Whippet.Fantomas.MemberInfo..ctor [constructor]: (Fantomas.FCS.Syntax.SynType, Fantomas.FCS.Syntax.SynAccess option, WoofWare.Whippet.Fantomas.TupledArg list, Fantomas.FCS.Syntax.Ident, Fantomas.FCS.Syntax.SynAttribute list, Fantomas.FCS.Xml.PreXmlDoc option, bool, bool) +WoofWare.Whippet.Fantomas.MemberInfo.Accessibility [property]: [read-only] Fantomas.FCS.Syntax.SynAccess option +WoofWare.Whippet.Fantomas.MemberInfo.Args [property]: [read-only] WoofWare.Whippet.Fantomas.TupledArg list +WoofWare.Whippet.Fantomas.MemberInfo.Attributes [property]: [read-only] Fantomas.FCS.Syntax.SynAttribute list +WoofWare.Whippet.Fantomas.MemberInfo.get_Accessibility [method]: unit -> Fantomas.FCS.Syntax.SynAccess option +WoofWare.Whippet.Fantomas.MemberInfo.get_Args [method]: unit -> WoofWare.Whippet.Fantomas.TupledArg list +WoofWare.Whippet.Fantomas.MemberInfo.get_Attributes [method]: unit -> Fantomas.FCS.Syntax.SynAttribute list +WoofWare.Whippet.Fantomas.MemberInfo.get_Identifier [method]: unit -> Fantomas.FCS.Syntax.Ident +WoofWare.Whippet.Fantomas.MemberInfo.get_IsInline [method]: unit -> bool +WoofWare.Whippet.Fantomas.MemberInfo.get_IsMutable [method]: unit -> bool +WoofWare.Whippet.Fantomas.MemberInfo.get_ReturnType [method]: unit -> Fantomas.FCS.Syntax.SynType +WoofWare.Whippet.Fantomas.MemberInfo.get_XmlDoc [method]: unit -> Fantomas.FCS.Xml.PreXmlDoc option +WoofWare.Whippet.Fantomas.MemberInfo.Identifier [property]: [read-only] Fantomas.FCS.Syntax.Ident +WoofWare.Whippet.Fantomas.MemberInfo.IsInline [property]: [read-only] bool +WoofWare.Whippet.Fantomas.MemberInfo.IsMutable [property]: [read-only] bool +WoofWare.Whippet.Fantomas.MemberInfo.ReturnType [property]: [read-only] Fantomas.FCS.Syntax.SynType +WoofWare.Whippet.Fantomas.MemberInfo.XmlDoc [property]: [read-only] Fantomas.FCS.Xml.PreXmlDoc option +WoofWare.Whippet.Fantomas.ParameterInfo inherit obj +WoofWare.Whippet.Fantomas.ParameterInfo..ctor [constructor]: (Fantomas.FCS.Syntax.SynAttribute list, bool, Fantomas.FCS.Syntax.Ident option, Fantomas.FCS.Syntax.SynType) +WoofWare.Whippet.Fantomas.ParameterInfo.Attributes [property]: [read-only] Fantomas.FCS.Syntax.SynAttribute list +WoofWare.Whippet.Fantomas.ParameterInfo.get_Attributes [method]: unit -> Fantomas.FCS.Syntax.SynAttribute list +WoofWare.Whippet.Fantomas.ParameterInfo.get_Id [method]: unit -> Fantomas.FCS.Syntax.Ident option +WoofWare.Whippet.Fantomas.ParameterInfo.get_IsOptional [method]: unit -> bool +WoofWare.Whippet.Fantomas.ParameterInfo.get_Type [method]: unit -> Fantomas.FCS.Syntax.SynType +WoofWare.Whippet.Fantomas.ParameterInfo.Id [property]: [read-only] Fantomas.FCS.Syntax.Ident option +WoofWare.Whippet.Fantomas.ParameterInfo.IsOptional [property]: [read-only] bool +WoofWare.Whippet.Fantomas.ParameterInfo.Type [property]: [read-only] Fantomas.FCS.Syntax.SynType WoofWare.Whippet.Fantomas.PreXmlDoc inherit obj WoofWare.Whippet.Fantomas.PreXmlDoc.create [static method]: string -> Fantomas.FCS.Xml.PreXmlDoc WoofWare.Whippet.Fantomas.PreXmlDoc.create' [static method]: string seq -> Fantomas.FCS.Xml.PreXmlDoc WoofWare.Whippet.Fantomas.Primitives inherit obj WoofWare.Whippet.Fantomas.Primitives.qualifyType [static method]: string -> Fantomas.FCS.Syntax.Ident list option +WoofWare.Whippet.Fantomas.PropertyAccessors inherit obj, implements WoofWare.Whippet.Fantomas.PropertyAccessors System.IEquatable, System.Collections.IStructuralEquatable, WoofWare.Whippet.Fantomas.PropertyAccessors System.IComparable, System.IComparable, System.Collections.IStructuralComparable - union type with 3 cases +WoofWare.Whippet.Fantomas.PropertyAccessors+Tags inherit obj +WoofWare.Whippet.Fantomas.PropertyAccessors+Tags.Get [static field]: int = 0 +WoofWare.Whippet.Fantomas.PropertyAccessors+Tags.GetSet [static field]: int = 2 +WoofWare.Whippet.Fantomas.PropertyAccessors+Tags.Set [static field]: int = 1 +WoofWare.Whippet.Fantomas.PropertyAccessors.Equals [method]: (WoofWare.Whippet.Fantomas.PropertyAccessors, System.Collections.IEqualityComparer) -> bool +WoofWare.Whippet.Fantomas.PropertyAccessors.Get [static property]: [read-only] WoofWare.Whippet.Fantomas.PropertyAccessors +WoofWare.Whippet.Fantomas.PropertyAccessors.get_Get [static method]: unit -> WoofWare.Whippet.Fantomas.PropertyAccessors +WoofWare.Whippet.Fantomas.PropertyAccessors.get_GetSet [static method]: unit -> WoofWare.Whippet.Fantomas.PropertyAccessors +WoofWare.Whippet.Fantomas.PropertyAccessors.get_IsGet [method]: unit -> bool +WoofWare.Whippet.Fantomas.PropertyAccessors.get_IsGetSet [method]: unit -> bool +WoofWare.Whippet.Fantomas.PropertyAccessors.get_IsSet [method]: unit -> bool +WoofWare.Whippet.Fantomas.PropertyAccessors.get_Set [static method]: unit -> WoofWare.Whippet.Fantomas.PropertyAccessors +WoofWare.Whippet.Fantomas.PropertyAccessors.get_Tag [method]: unit -> int +WoofWare.Whippet.Fantomas.PropertyAccessors.GetSet [static property]: [read-only] WoofWare.Whippet.Fantomas.PropertyAccessors +WoofWare.Whippet.Fantomas.PropertyAccessors.IsGet [property]: [read-only] bool +WoofWare.Whippet.Fantomas.PropertyAccessors.IsGetSet [property]: [read-only] bool +WoofWare.Whippet.Fantomas.PropertyAccessors.IsSet [property]: [read-only] bool +WoofWare.Whippet.Fantomas.PropertyAccessors.Set [static property]: [read-only] WoofWare.Whippet.Fantomas.PropertyAccessors +WoofWare.Whippet.Fantomas.PropertyAccessors.Tag [property]: [read-only] int +WoofWare.Whippet.Fantomas.PropertyInfo inherit obj +WoofWare.Whippet.Fantomas.PropertyInfo..ctor [constructor]: (Fantomas.FCS.Syntax.SynType, Fantomas.FCS.Syntax.SynAccess option, Fantomas.FCS.Syntax.SynAttribute list, Fantomas.FCS.Xml.PreXmlDoc option, WoofWare.Whippet.Fantomas.PropertyAccessors, bool, Fantomas.FCS.Syntax.Ident) +WoofWare.Whippet.Fantomas.PropertyInfo.Accessibility [property]: [read-only] Fantomas.FCS.Syntax.SynAccess option +WoofWare.Whippet.Fantomas.PropertyInfo.Accessors [property]: [read-only] WoofWare.Whippet.Fantomas.PropertyAccessors +WoofWare.Whippet.Fantomas.PropertyInfo.Attributes [property]: [read-only] Fantomas.FCS.Syntax.SynAttribute list +WoofWare.Whippet.Fantomas.PropertyInfo.get_Accessibility [method]: unit -> Fantomas.FCS.Syntax.SynAccess option +WoofWare.Whippet.Fantomas.PropertyInfo.get_Accessors [method]: unit -> WoofWare.Whippet.Fantomas.PropertyAccessors +WoofWare.Whippet.Fantomas.PropertyInfo.get_Attributes [method]: unit -> Fantomas.FCS.Syntax.SynAttribute list +WoofWare.Whippet.Fantomas.PropertyInfo.get_Identifier [method]: unit -> Fantomas.FCS.Syntax.Ident +WoofWare.Whippet.Fantomas.PropertyInfo.get_IsInline [method]: unit -> bool +WoofWare.Whippet.Fantomas.PropertyInfo.get_Type [method]: unit -> Fantomas.FCS.Syntax.SynType +WoofWare.Whippet.Fantomas.PropertyInfo.get_XmlDoc [method]: unit -> Fantomas.FCS.Xml.PreXmlDoc option +WoofWare.Whippet.Fantomas.PropertyInfo.Identifier [property]: [read-only] Fantomas.FCS.Syntax.Ident +WoofWare.Whippet.Fantomas.PropertyInfo.IsInline [property]: [read-only] bool +WoofWare.Whippet.Fantomas.PropertyInfo.Type [property]: [read-only] Fantomas.FCS.Syntax.SynType +WoofWare.Whippet.Fantomas.PropertyInfo.XmlDoc [property]: [read-only] Fantomas.FCS.Xml.PreXmlDoc option +WoofWare.Whippet.Fantomas.RecordType inherit obj +WoofWare.Whippet.Fantomas.RecordType..ctor [constructor]: (Fantomas.FCS.Syntax.Ident, Fantomas.FCS.Syntax.SynField list, Fantomas.FCS.Syntax.SynMemberDefn list option, Fantomas.FCS.Xml.PreXmlDoc option, Fantomas.FCS.Syntax.SynTyparDecls option, Fantomas.FCS.Syntax.SynAccess option, Fantomas.FCS.Syntax.SynAccess option, Fantomas.FCS.Syntax.SynAttribute list) +WoofWare.Whippet.Fantomas.RecordType.Attributes [property]: [read-only] Fantomas.FCS.Syntax.SynAttribute list +WoofWare.Whippet.Fantomas.RecordType.Fields [property]: [read-only] Fantomas.FCS.Syntax.SynField list +WoofWare.Whippet.Fantomas.RecordType.Generics [property]: [read-only] Fantomas.FCS.Syntax.SynTyparDecls option +WoofWare.Whippet.Fantomas.RecordType.get_Attributes [method]: unit -> Fantomas.FCS.Syntax.SynAttribute list +WoofWare.Whippet.Fantomas.RecordType.get_Fields [method]: unit -> Fantomas.FCS.Syntax.SynField list +WoofWare.Whippet.Fantomas.RecordType.get_Generics [method]: unit -> Fantomas.FCS.Syntax.SynTyparDecls option +WoofWare.Whippet.Fantomas.RecordType.get_ImplAccessibility [method]: unit -> Fantomas.FCS.Syntax.SynAccess option +WoofWare.Whippet.Fantomas.RecordType.get_Members [method]: unit -> Fantomas.FCS.Syntax.SynMemberDefn list option +WoofWare.Whippet.Fantomas.RecordType.get_Name [method]: unit -> Fantomas.FCS.Syntax.Ident +WoofWare.Whippet.Fantomas.RecordType.get_TypeAccessibility [method]: unit -> Fantomas.FCS.Syntax.SynAccess option +WoofWare.Whippet.Fantomas.RecordType.get_XmlDoc [method]: unit -> Fantomas.FCS.Xml.PreXmlDoc option +WoofWare.Whippet.Fantomas.RecordType.ImplAccessibility [property]: [read-only] Fantomas.FCS.Syntax.SynAccess option +WoofWare.Whippet.Fantomas.RecordType.Members [property]: [read-only] Fantomas.FCS.Syntax.SynMemberDefn list option +WoofWare.Whippet.Fantomas.RecordType.Name [property]: [read-only] Fantomas.FCS.Syntax.Ident +WoofWare.Whippet.Fantomas.RecordType.OfRecord [static method]: Fantomas.FCS.Syntax.SynComponentInfo -> Fantomas.FCS.Syntax.SynMemberDefn list -> Fantomas.FCS.Syntax.SynAccess option -> Fantomas.FCS.Syntax.SynField list -> WoofWare.Whippet.Fantomas.RecordType +WoofWare.Whippet.Fantomas.RecordType.ToAst [static method]: WoofWare.Whippet.Fantomas.RecordType -> Fantomas.FCS.Syntax.SynTypeDefn +WoofWare.Whippet.Fantomas.RecordType.TypeAccessibility [property]: [read-only] Fantomas.FCS.Syntax.SynAccess option +WoofWare.Whippet.Fantomas.RecordType.XmlDoc [property]: [read-only] Fantomas.FCS.Xml.PreXmlDoc option WoofWare.Whippet.Fantomas.SynArgInfo inherit obj WoofWare.Whippet.Fantomas.SynArgInfo.empty [static property]: [read-only] Fantomas.FCS.Syntax.SynArgInfo WoofWare.Whippet.Fantomas.SynArgInfo.get_empty [static method]: unit -> Fantomas.FCS.Syntax.SynArgInfo @@ -65,8 +171,10 @@ WoofWare.Whippet.Fantomas.SynAttribute.get_requireQualifiedAccess [static method WoofWare.Whippet.Fantomas.SynAttribute.requireQualifiedAccess [static property]: [read-only] Fantomas.FCS.Syntax.SynAttribute WoofWare.Whippet.Fantomas.SynAttributes inherit obj WoofWare.Whippet.Fantomas.SynAttributes.ofAttrs [static method]: Fantomas.FCS.Syntax.SynAttribute list -> Fantomas.FCS.Syntax.SynAttributeList list +WoofWare.Whippet.Fantomas.SynAttributes.toAttrs [static method]: Fantomas.FCS.Syntax.SynAttributeList list -> Fantomas.FCS.Syntax.SynAttribute list WoofWare.Whippet.Fantomas.SynBinding inherit obj WoofWare.Whippet.Fantomas.SynBinding.basic [static method]: Fantomas.FCS.Syntax.Ident list -> Fantomas.FCS.Syntax.SynPat list -> Fantomas.FCS.Syntax.SynExpr -> Fantomas.FCS.Syntax.SynBinding +WoofWare.Whippet.Fantomas.SynBinding.basicTuple [static method]: Fantomas.FCS.Syntax.SynPat list -> Fantomas.FCS.Syntax.SynExpr -> Fantomas.FCS.Syntax.SynBinding WoofWare.Whippet.Fantomas.SynBinding.makeInline [static method]: Fantomas.FCS.Syntax.SynBinding -> Fantomas.FCS.Syntax.SynBinding WoofWare.Whippet.Fantomas.SynBinding.makeInstanceMember [static method]: Fantomas.FCS.Syntax.SynBinding -> Fantomas.FCS.Syntax.SynBinding WoofWare.Whippet.Fantomas.SynBinding.makeNotInline [static method]: Fantomas.FCS.Syntax.SynBinding -> Fantomas.FCS.Syntax.SynBinding @@ -292,6 +400,9 @@ WoofWare.Whippet.Fantomas.SynTypeDefn.create [static method]: Fantomas.FCS.Synta WoofWare.Whippet.Fantomas.SynTypeDefn.getAttribute [static method]: string -> Fantomas.FCS.Syntax.SynTypeDefn -> Fantomas.FCS.Syntax.SynAttribute option WoofWare.Whippet.Fantomas.SynTypeDefn.getName [static method]: Fantomas.FCS.Syntax.SynTypeDefn -> Fantomas.FCS.Syntax.Ident list WoofWare.Whippet.Fantomas.SynTypeDefn.hasAttribute [static method]: string -> Fantomas.FCS.Syntax.SynTypeDefn -> bool +WoofWare.Whippet.Fantomas.SynTypeDefn.isDu [static method]: Fantomas.FCS.Syntax.SynTypeDefn -> bool +WoofWare.Whippet.Fantomas.SynTypeDefn.isEnum [static method]: Fantomas.FCS.Syntax.SynTypeDefn -> bool +WoofWare.Whippet.Fantomas.SynTypeDefn.isRecord [static method]: Fantomas.FCS.Syntax.SynTypeDefn -> bool WoofWare.Whippet.Fantomas.SynTypeDefn.withMemberDefns [static method]: Fantomas.FCS.Syntax.SynMemberDefn list -> Fantomas.FCS.Syntax.SynTypeDefn -> Fantomas.FCS.Syntax.SynTypeDefn WoofWare.Whippet.Fantomas.SynTypeDefnRepr inherit obj WoofWare.Whippet.Fantomas.SynTypeDefnRepr.augmentation [static method]: unit -> Fantomas.FCS.Syntax.SynTypeDefnRepr @@ -336,6 +447,15 @@ WoofWare.Whippet.Fantomas.SynUnionCase.create [static method]: Fantomas.FCS.Synt WoofWare.Whippet.Fantomas.SynValInfo inherit obj WoofWare.Whippet.Fantomas.SynValInfo.empty [static property]: [read-only] Fantomas.FCS.Syntax.SynValInfo WoofWare.Whippet.Fantomas.SynValInfo.get_empty [static method]: unit -> Fantomas.FCS.Syntax.SynValInfo +WoofWare.Whippet.Fantomas.TupledArg inherit obj +WoofWare.Whippet.Fantomas.TupledArg..ctor [constructor]: (bool, WoofWare.Whippet.Fantomas.ParameterInfo list) +WoofWare.Whippet.Fantomas.TupledArg.Args [property]: [read-only] WoofWare.Whippet.Fantomas.ParameterInfo list +WoofWare.Whippet.Fantomas.TupledArg.get_Args [method]: unit -> WoofWare.Whippet.Fantomas.ParameterInfo list +WoofWare.Whippet.Fantomas.TupledArg.get_HasParen [method]: unit -> bool +WoofWare.Whippet.Fantomas.TupledArg.HasParen [property]: [read-only] bool +WoofWare.Whippet.Fantomas.UnionCase inherit obj +WoofWare.Whippet.Fantomas.UnionCase.mapIdentFields [static method]: ('a -> 'b) -> 'a WoofWare.Whippet.Fantomas.UnionCase -> 'b WoofWare.Whippet.Fantomas.UnionCase +WoofWare.Whippet.Fantomas.UnionCase.ofSynUnionCase [static method]: Fantomas.FCS.Syntax.SynUnionCase -> Fantomas.FCS.Syntax.Ident option WoofWare.Whippet.Fantomas.UnionCase WoofWare.Whippet.Fantomas.UnionCase`1 inherit obj WoofWare.Whippet.Fantomas.UnionCase`1..ctor [constructor]: (Fantomas.FCS.Syntax.Ident, Fantomas.FCS.Xml.PreXmlDoc option, Fantomas.FCS.Syntax.SynAccess option, Fantomas.FCS.Syntax.SynAttribute list, 'ident WoofWare.Whippet.Fantomas.SynFieldData list) WoofWare.Whippet.Fantomas.UnionCase`1.Access [property]: [read-only] Fantomas.FCS.Syntax.SynAccess option @@ -347,4 +467,23 @@ WoofWare.Whippet.Fantomas.UnionCase`1.get_Fields [method]: unit -> 'ident WoofWa WoofWare.Whippet.Fantomas.UnionCase`1.get_Name [method]: unit -> Fantomas.FCS.Syntax.Ident WoofWare.Whippet.Fantomas.UnionCase`1.get_XmlDoc [method]: unit -> Fantomas.FCS.Xml.PreXmlDoc option WoofWare.Whippet.Fantomas.UnionCase`1.Name [property]: [read-only] Fantomas.FCS.Syntax.Ident -WoofWare.Whippet.Fantomas.UnionCase`1.XmlDoc [property]: [read-only] Fantomas.FCS.Xml.PreXmlDoc option \ No newline at end of file +WoofWare.Whippet.Fantomas.UnionCase`1.XmlDoc [property]: [read-only] Fantomas.FCS.Xml.PreXmlDoc option +WoofWare.Whippet.Fantomas.UnionType inherit obj +WoofWare.Whippet.Fantomas.UnionType..ctor [constructor]: (Fantomas.FCS.Syntax.Ident, Fantomas.FCS.Syntax.SynMemberDefn list option, Fantomas.FCS.Xml.PreXmlDoc option, Fantomas.FCS.Syntax.SynTyparDecls option, Fantomas.FCS.Syntax.SynAttribute list, Fantomas.FCS.Syntax.SynAccess option, Fantomas.FCS.Syntax.SynAccess option, Fantomas.FCS.Syntax.Ident option WoofWare.Whippet.Fantomas.UnionCase list) +WoofWare.Whippet.Fantomas.UnionType.Attributes [property]: [read-only] Fantomas.FCS.Syntax.SynAttribute list +WoofWare.Whippet.Fantomas.UnionType.Cases [property]: [read-only] Fantomas.FCS.Syntax.Ident option WoofWare.Whippet.Fantomas.UnionCase list +WoofWare.Whippet.Fantomas.UnionType.Generics [property]: [read-only] Fantomas.FCS.Syntax.SynTyparDecls option +WoofWare.Whippet.Fantomas.UnionType.get_Attributes [method]: unit -> Fantomas.FCS.Syntax.SynAttribute list +WoofWare.Whippet.Fantomas.UnionType.get_Cases [method]: unit -> Fantomas.FCS.Syntax.Ident option WoofWare.Whippet.Fantomas.UnionCase list +WoofWare.Whippet.Fantomas.UnionType.get_Generics [method]: unit -> Fantomas.FCS.Syntax.SynTyparDecls option +WoofWare.Whippet.Fantomas.UnionType.get_ImplAccessibility [method]: unit -> Fantomas.FCS.Syntax.SynAccess option +WoofWare.Whippet.Fantomas.UnionType.get_Members [method]: unit -> Fantomas.FCS.Syntax.SynMemberDefn list option +WoofWare.Whippet.Fantomas.UnionType.get_Name [method]: unit -> Fantomas.FCS.Syntax.Ident +WoofWare.Whippet.Fantomas.UnionType.get_TypeAccessibility [method]: unit -> Fantomas.FCS.Syntax.SynAccess option +WoofWare.Whippet.Fantomas.UnionType.get_XmlDoc [method]: unit -> Fantomas.FCS.Xml.PreXmlDoc option +WoofWare.Whippet.Fantomas.UnionType.ImplAccessibility [property]: [read-only] Fantomas.FCS.Syntax.SynAccess option +WoofWare.Whippet.Fantomas.UnionType.Members [property]: [read-only] Fantomas.FCS.Syntax.SynMemberDefn list option +WoofWare.Whippet.Fantomas.UnionType.Name [property]: [read-only] Fantomas.FCS.Syntax.Ident +WoofWare.Whippet.Fantomas.UnionType.OfUnion [static method]: Fantomas.FCS.Syntax.SynComponentInfo -> Fantomas.FCS.Syntax.SynMemberDefn list -> Fantomas.FCS.Syntax.SynAccess option -> Fantomas.FCS.Syntax.SynUnionCase list -> WoofWare.Whippet.Fantomas.UnionType +WoofWare.Whippet.Fantomas.UnionType.TypeAccessibility [property]: [read-only] Fantomas.FCS.Syntax.SynAccess option +WoofWare.Whippet.Fantomas.UnionType.XmlDoc [property]: [read-only] Fantomas.FCS.Xml.PreXmlDoc option \ No newline at end of file diff --git a/WoofWare.Whippet.Fantomas/SynAttributes.fs b/WoofWare.Whippet.Fantomas/SynAttributes.fs index 2531fcf..577a303 100644 --- a/WoofWare.Whippet.Fantomas/SynAttributes.fs +++ b/WoofWare.Whippet.Fantomas/SynAttributes.fs @@ -17,3 +17,7 @@ module SynAttributes = Range = range0 } ) + + /// Get all the attributes out of this SynAttributes, as a list of individual attributes. + let toAttrs (attrs : SynAttributes) : SynAttribute list = + attrs |> List.collect (fun attr -> attr.Attributes) diff --git a/WoofWare.Whippet.Fantomas/SynBinding.fs b/WoofWare.Whippet.Fantomas/SynBinding.fs index 3403413..ff88f8d 100644 --- a/WoofWare.Whippet.Fantomas/SynBinding.fs +++ b/WoofWare.Whippet.Fantomas/SynBinding.fs @@ -43,6 +43,30 @@ module SynBinding = SynLeadingKeyword.Let range0 } + /// A simple binding: + /// `let {a, b} = {body}` + let basicTuple (args : SynPat list) (body : SynExpr) : SynBinding = + let valInfo : SynValInfo = + args + |> List.map getArgInfo + |> fun x -> SynValInfo.SynValInfo (x, SynArgInfo.SynArgInfo ([], false, None)) + + SynBinding.SynBinding ( + None, + SynBindingKind.Normal, + false, + false, + [], + PreXmlDoc.Empty, + SynValData.SynValData (None, valInfo, None), + SynPat.tupleNoParen args, + None, + body, + range0, + DebugPointAtBinding.Yes range0, + triviaZero false + ) + /// A simple binding: /// `let {name} {args} = {body}` /// diff --git a/WoofWare.Whippet.Fantomas/SynTypeDefn.fs b/WoofWare.Whippet.Fantomas/SynTypeDefn.fs index 87744d5..0bd93f3 100644 --- a/WoofWare.Whippet.Fantomas/SynTypeDefn.fs +++ b/WoofWare.Whippet.Fantomas/SynTypeDefn.fs @@ -1,5 +1,6 @@ namespace WoofWare.Whippet.Fantomas +open System open Fantomas.FCS.Syntax open Fantomas.FCS.SyntaxTrivia open Fantomas.FCS.Text.Range @@ -8,6 +9,24 @@ open Fantomas.FCS.Text.Range [] module SynTypeDefn = + /// Returns true iff the input type is an F# record. + let isRecord (SynTypeDefn.SynTypeDefn (_, repr, _, _, _, _)) : bool = + match repr with + | SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Record _, _) -> true + | _ -> false + + /// Returns true iff the input type is a discriminated union. + let isDu (SynTypeDefn.SynTypeDefn (_, repr, _, _, _, _)) : bool = + match repr with + | SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Union _, _) -> true + | _ -> false + + /// Returns true iff the input type is an enum: `type Foo = | X = 1 ...` + let isEnum (SynTypeDefn.SynTypeDefn (_, repr, _, _, _, _)) : bool = + match repr with + | SynTypeDefnRepr.Simple (SynTypeDefnSimpleRepr.Enum _, _) -> true + | _ -> false + /// Build a `SynTypeDefn` from its components: /// the "front matter" `SynComponentInfo`, and the "body" `SynTypeDefnRepr`. let inline create (componentInfo : SynComponentInfo) (repr : SynTypeDefnRepr) : SynTypeDefn = @@ -36,6 +55,9 @@ module SynTypeDefn = | SynTypeDefn (SynComponentInfo.SynComponentInfo (_, _, _, id, _, _, _, _), _, _, _, _, _) -> id /// Select from this type definition the first attribute with the given name: `[] type Blah = ...` + /// + /// Pass e.g. `typeof.Name` as the name for maximum type safety. + /// Don't fully qualify the input; this should basically just be an Ident rather than a LongIdent. let getAttribute (attrName : string) (defn : SynTypeDefn) : SynAttribute option = match defn with | SynTypeDefn (SynComponentInfo.SynComponentInfo (attrs, _, _, _, _, _, _, _), _, _, _, _, _) -> diff --git a/WoofWare.Whippet.Fantomas/WoofWare.Whippet.Fantomas.fsproj b/WoofWare.Whippet.Fantomas/WoofWare.Whippet.Fantomas.fsproj index e55093c..249de32 100644 --- a/WoofWare.Whippet.Fantomas/WoofWare.Whippet.Fantomas.fsproj +++ b/WoofWare.Whippet.Fantomas/WoofWare.Whippet.Fantomas.fsproj @@ -17,6 +17,7 @@ + @@ -45,6 +46,7 @@ + True diff --git a/WoofWare.Whippet.Fantomas/version.json b/WoofWare.Whippet.Fantomas/version.json index ff2b96d..9731be2 100644 --- a/WoofWare.Whippet.Fantomas/version.json +++ b/WoofWare.Whippet.Fantomas/version.json @@ -1,5 +1,5 @@ { - "version": "0.1", + "version": "0.2", "publicReleaseRefSpec": [ "^refs/heads/main$" ], @@ -9,4 +9,4 @@ ":/global.json", ":/Directory.Build.props" ] -} +} \ No newline at end of file