mirror of
https://github.com/Smaug123/WoofWare.Myriad
synced 2025-10-08 05:28:39 +00:00
Permit public mocks (#94)
This commit is contained in:
@@ -30,6 +30,29 @@ namespace SomeNamespace
|
|||||||
|
|
||||||
open WoofWare.Myriad.Plugins
|
open WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
/// Mock record type for an interface
|
||||||
|
type public PublicTypeInternalFalseMock =
|
||||||
|
{
|
||||||
|
Mem1 : string * int -> string list
|
||||||
|
Mem2 : string -> int
|
||||||
|
Mem3 : int * option<System.Threading.CancellationToken> -> string
|
||||||
|
}
|
||||||
|
|
||||||
|
static member Empty : PublicTypeInternalFalseMock =
|
||||||
|
{
|
||||||
|
Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
||||||
|
Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
||||||
|
Mem3 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IPublicTypeInternalFalse with
|
||||||
|
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1)
|
||||||
|
member this.Mem2 (arg_0_0) = this.Mem2 (arg_0_0)
|
||||||
|
member this.Mem3 (arg_0_0, arg_0_1) = this.Mem3 (arg_0_0, arg_0_1)
|
||||||
|
namespace SomeNamespace
|
||||||
|
|
||||||
|
open WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
/// Mock record type for an interface
|
/// Mock record type for an interface
|
||||||
type internal InternalTypeMock =
|
type internal InternalTypeMock =
|
||||||
{
|
{
|
||||||
@@ -70,6 +93,26 @@ namespace SomeNamespace
|
|||||||
|
|
||||||
open WoofWare.Myriad.Plugins
|
open WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
|
/// Mock record type for an interface
|
||||||
|
type private PrivateTypeInternalFalseMock =
|
||||||
|
{
|
||||||
|
Mem1 : string * int -> unit
|
||||||
|
Mem2 : string -> int
|
||||||
|
}
|
||||||
|
|
||||||
|
static member Empty : PrivateTypeInternalFalseMock =
|
||||||
|
{
|
||||||
|
Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
||||||
|
Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PrivateTypeInternalFalse with
|
||||||
|
member this.Mem1 (arg_0_0, arg_0_1) = this.Mem1 (arg_0_0, arg_0_1)
|
||||||
|
member this.Mem2 (arg_0_0) = this.Mem2 (arg_0_0)
|
||||||
|
namespace SomeNamespace
|
||||||
|
|
||||||
|
open WoofWare.Myriad.Plugins
|
||||||
|
|
||||||
/// Mock record type for an interface
|
/// Mock record type for an interface
|
||||||
type internal VeryPublicTypeMock<'a, 'b> =
|
type internal VeryPublicTypeMock<'a, 'b> =
|
||||||
{
|
{
|
||||||
|
@@ -8,6 +8,12 @@ type IPublicType =
|
|||||||
abstract Mem2 : string -> int
|
abstract Mem2 : string -> int
|
||||||
abstract Mem3 : x : int * ?ct : System.Threading.CancellationToken -> string
|
abstract Mem3 : x : int * ?ct : System.Threading.CancellationToken -> string
|
||||||
|
|
||||||
|
[<GenerateMock false>]
|
||||||
|
type IPublicTypeInternalFalse =
|
||||||
|
abstract Mem1 : string * int -> string list
|
||||||
|
abstract Mem2 : string -> int
|
||||||
|
abstract Mem3 : x : int * ?ct : System.Threading.CancellationToken -> string
|
||||||
|
|
||||||
[<GenerateMock>]
|
[<GenerateMock>]
|
||||||
type internal InternalType =
|
type internal InternalType =
|
||||||
abstract Mem1 : string * int -> unit
|
abstract Mem1 : string * int -> unit
|
||||||
@@ -18,6 +24,11 @@ type private PrivateType =
|
|||||||
abstract Mem1 : string * int -> unit
|
abstract Mem1 : string * int -> unit
|
||||||
abstract Mem2 : string -> int
|
abstract Mem2 : string -> int
|
||||||
|
|
||||||
|
[<GenerateMock false>]
|
||||||
|
type private PrivateTypeInternalFalse =
|
||||||
|
abstract Mem1 : string * int -> unit
|
||||||
|
abstract Mem2 : string -> int
|
||||||
|
|
||||||
[<GenerateMock>]
|
[<GenerateMock>]
|
||||||
type VeryPublicType<'a, 'b> =
|
type VeryPublicType<'a, 'b> =
|
||||||
abstract Mem1 : 'a -> 'b
|
abstract Mem1 : 'a -> 'b
|
||||||
|
@@ -13,8 +13,14 @@ type RemoveOptionsAttribute () =
|
|||||||
/// This generator creates a record which implements the interface,
|
/// This generator creates a record which implements the interface,
|
||||||
/// but where each method is represented as a record field, so you can use
|
/// but where each method is represented as a record field, so you can use
|
||||||
/// record update syntax to easily specify partially-implemented mock objects.
|
/// record update syntax to easily specify partially-implemented mock objects.
|
||||||
type GenerateMockAttribute () =
|
/// You may optionally specify `isInternal = false` to get a mock with the public visibility modifier.
|
||||||
|
type GenerateMockAttribute (isInternal : bool) =
|
||||||
inherit Attribute ()
|
inherit Attribute ()
|
||||||
|
/// The default value of `isInternal`, the optional argument to the GenerateMockAttribute constructor.
|
||||||
|
static member DefaultIsInternal = true
|
||||||
|
|
||||||
|
/// Shorthand for the "isExtensionMethod = false" constructor; see documentation there for details.
|
||||||
|
new () = GenerateMockAttribute GenerateMockAttribute.DefaultIsInternal
|
||||||
|
|
||||||
/// Attribute indicating a record type to which the "Add JSON serializer" Myriad
|
/// Attribute indicating a record type to which the "Add JSON serializer" Myriad
|
||||||
/// generator should apply during build.
|
/// generator should apply during build.
|
||||||
|
@@ -1,5 +1,8 @@
|
|||||||
WoofWare.Myriad.Plugins.GenerateMockAttribute inherit System.Attribute
|
WoofWare.Myriad.Plugins.GenerateMockAttribute inherit System.Attribute
|
||||||
|
WoofWare.Myriad.Plugins.GenerateMockAttribute..ctor [constructor]: bool
|
||||||
WoofWare.Myriad.Plugins.GenerateMockAttribute..ctor [constructor]: unit
|
WoofWare.Myriad.Plugins.GenerateMockAttribute..ctor [constructor]: unit
|
||||||
|
WoofWare.Myriad.Plugins.GenerateMockAttribute.DefaultIsInternal [static property]: [read-only] bool
|
||||||
|
WoofWare.Myriad.Plugins.GenerateMockAttribute.get_DefaultIsInternal [static method]: unit -> bool
|
||||||
WoofWare.Myriad.Plugins.HttpClientAttribute inherit System.Attribute
|
WoofWare.Myriad.Plugins.HttpClientAttribute inherit System.Attribute
|
||||||
WoofWare.Myriad.Plugins.HttpClientAttribute..ctor [constructor]: unit
|
WoofWare.Myriad.Plugins.HttpClientAttribute..ctor [constructor]: unit
|
||||||
WoofWare.Myriad.Plugins.JsonParseAttribute inherit System.Attribute
|
WoofWare.Myriad.Plugins.JsonParseAttribute inherit System.Attribute
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"version": "2.0",
|
"version": "2.1",
|
||||||
"publicReleaseRefSpec": [
|
"publicReleaseRefSpec": [
|
||||||
"^refs/heads/main$"
|
"^refs/heads/main$"
|
||||||
],
|
],
|
||||||
|
@@ -6,6 +6,11 @@ open Fantomas.FCS.SyntaxTrivia
|
|||||||
open Fantomas.FCS.Xml
|
open Fantomas.FCS.Xml
|
||||||
open Myriad.Core
|
open Myriad.Core
|
||||||
|
|
||||||
|
type internal GenerateMockOutputSpec =
|
||||||
|
{
|
||||||
|
IsInternal : bool
|
||||||
|
}
|
||||||
|
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module internal InterfaceMockGenerator =
|
module internal InterfaceMockGenerator =
|
||||||
open Fantomas.FCS.Text.Range
|
open Fantomas.FCS.Text.Range
|
||||||
@@ -17,6 +22,7 @@ module internal InterfaceMockGenerator =
|
|||||||
| Some id -> id
|
| Some id -> id
|
||||||
|
|
||||||
let createType
|
let createType
|
||||||
|
(spec : GenerateMockOutputSpec)
|
||||||
(name : string)
|
(name : string)
|
||||||
(interfaceType : InterfaceType)
|
(interfaceType : InterfaceType)
|
||||||
(xmlDoc : PreXmlDoc)
|
(xmlDoc : PreXmlDoc)
|
||||||
@@ -249,13 +255,14 @@ module internal InterfaceMockGenerator =
|
|||||||
|
|
||||||
SynMemberDefn.Interface (interfaceName, Some range0, Some members, range0)
|
SynMemberDefn.Interface (interfaceName, Some range0, Some members, range0)
|
||||||
|
|
||||||
// TODO: allow an arg to the attribute, specifying a custom visibility
|
|
||||||
let access =
|
let access =
|
||||||
match interfaceType.Accessibility with
|
match interfaceType.Accessibility, spec.IsInternal with
|
||||||
| Some (SynAccess.Public _)
|
| Some (SynAccess.Public _), true
|
||||||
| Some (SynAccess.Internal _)
|
| None, true -> SynAccess.Internal range0
|
||||||
| None -> SynAccess.Internal range0
|
| Some (SynAccess.Public _), false -> SynAccess.Public range0
|
||||||
| Some (SynAccess.Private _) -> SynAccess.Private range0
|
| None, false -> SynAccess.Public range0
|
||||||
|
| Some (SynAccess.Internal _), _ -> SynAccess.Internal range0
|
||||||
|
| Some (SynAccess.Private _), _ -> SynAccess.Private range0
|
||||||
|
|
||||||
let record =
|
let record =
|
||||||
{
|
{
|
||||||
@@ -307,7 +314,7 @@ module internal InterfaceMockGenerator =
|
|||||||
let createRecord
|
let createRecord
|
||||||
(namespaceId : LongIdent)
|
(namespaceId : LongIdent)
|
||||||
(opens : SynOpenDeclTarget list)
|
(opens : SynOpenDeclTarget list)
|
||||||
(interfaceType : SynTypeDefn)
|
(interfaceType : SynTypeDefn, spec : GenerateMockOutputSpec)
|
||||||
: SynModuleOrNamespace
|
: SynModuleOrNamespace
|
||||||
=
|
=
|
||||||
let interfaceType = AstHelper.parseInterface interfaceType
|
let interfaceType = AstHelper.parseInterface interfaceType
|
||||||
@@ -324,7 +331,7 @@ module internal InterfaceMockGenerator =
|
|||||||
s
|
s
|
||||||
|> fun s -> s + "Mock"
|
|> fun s -> s + "Mock"
|
||||||
|
|
||||||
let typeDecl = createType name interfaceType docString fields
|
let typeDecl = createType spec name interfaceType docString fields
|
||||||
|
|
||||||
|
|
||||||
SynModuleOrNamespace.CreateNamespace (
|
SynModuleOrNamespace.CreateNamespace (
|
||||||
@@ -349,9 +356,29 @@ type InterfaceMockGenerator () =
|
|||||||
let namespaceAndInterfaces =
|
let namespaceAndInterfaces =
|
||||||
types
|
types
|
||||||
|> List.choose (fun (ns, types) ->
|
|> List.choose (fun (ns, types) ->
|
||||||
match types |> List.filter Ast.hasAttribute<GenerateMockAttribute> with
|
types
|
||||||
| [] -> None
|
|> List.choose (fun typeDef ->
|
||||||
| types -> Some (ns, types)
|
match Ast.getAttribute<GenerateMockAttribute> typeDef with
|
||||||
|
| None -> None
|
||||||
|
| Some attr ->
|
||||||
|
let arg =
|
||||||
|
match SynExpr.stripOptionalParen attr.ArgExpr with
|
||||||
|
| SynExpr.Const (SynConst.Bool value, _) -> value
|
||||||
|
| SynExpr.Const (SynConst.Unit, _) -> GenerateMockAttribute.DefaultIsInternal
|
||||||
|
| arg ->
|
||||||
|
failwith
|
||||||
|
$"Unrecognised argument %+A{arg} to [<%s{nameof GenerateMockAttribute}>]. Literals are not supported. Use `true` or `false` (or unit) only."
|
||||||
|
|
||||||
|
let spec =
|
||||||
|
{
|
||||||
|
IsInternal = arg
|
||||||
|
}
|
||||||
|
|
||||||
|
Some (typeDef, spec)
|
||||||
|
)
|
||||||
|
|> function
|
||||||
|
| [] -> None
|
||||||
|
| ty -> Some (ns, ty)
|
||||||
)
|
)
|
||||||
|
|
||||||
let opens = AstHelper.extractOpens ast
|
let opens = AstHelper.extractOpens ast
|
||||||
|
Reference in New Issue
Block a user