Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/Compiler/AbstractIL/ilwrite.fs
Original file line number Diff line number Diff line change
Expand Up @@ -1189,7 +1189,7 @@ let canGenPropertyDef cenv (prop: ILPropertyDef) =
// If we have GetMethod or SetMethod set (i.e. not None), try and see if we have MethodDefs for them.
// NOTE: They can be not-None and missing MethodDefs if we skip generating them for reference assembly in the earlier pass.
// Only generate property if we have at least getter or setter, otherwise, we skip.
[| prop.GetMethod; prop.SetMethod |]
[| prop.GetMethod; prop.SetMethod |]
|> Array.choose id
|> Array.exists (MethodDefIdxExists cenv)

Expand Down Expand Up @@ -1300,14 +1300,14 @@ and GenTypeDefPass2 pidx enc cenv (tdef: ILTypeDef) =
// Now generate or assign index numbers for tables referenced by the maps.
// Don't yet generate contents of these tables - leave that to pass3, as
// code may need to embed these entries.
tdef.Implements |> List.iter (GenImplementsPass2 cenv env tidx)
events |> List.iter (GenEventDefPass2 cenv tidx)
tdef.Implements |> List.iter (GenImplementsPass2 cenv env tidx)
tdef.Fields.AsList() |> List.iter (GenFieldDefPass2 tdef cenv tidx)
tdef.Methods |> Seq.iter (GenMethodDefPass2 tdef cenv tidx)
// Generation of property definitions for **ref assemblies** is checking existence of generated method definitions.
// Generation of property & event definitions for **ref assemblies** is checking existence of generated method definitions.
// Therefore, due to mutable state within "cenv", order of operations matters.
// Who could have thought that using shared mutable state can bring unexpected bugs...?
props |> List.iter (GenPropertyDefPass2 cenv tidx)
events |> List.iter (GenEventDefPass2 cenv tidx)
tdef.NestedTypes.AsList() |> GenTypeDefsPass2 tidx (enc@[tdef.Name]) cenv
with exn ->
failwith ("Error in pass2 for type "+tdef.Name+", error: " + exn.Message)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,104 @@ extends [runtime]System.Object

}"""]

[<Test>]
let ``Cli events are emitted even for CliEvent members which are not last in a file`` () =
FSharp """
module LibraryWithTwoClassesAndTwoEvents
open System

let event = new DelegateEvent<EventHandler<EventArgs>>()
type MyClass() =
[<CLIEvent>]
member this.EventFromFirstType = event.Publish

let event2 = new DelegateEvent<EventHandler<EventArgs>>()
type MyClass2() =
[<CLIEvent>]
member this.EventFromSecondType = event2.Publish
"""
|> withOptions ["--refonly"]
|> compile
|> shouldSucceed
|> verifyIL [
referenceAssemblyAttributeExpectedIL
""".class auto ansi serializable nested public MyClass
extends [runtime]System.Object
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
.method public specialname rtspecialname
instance void .ctor() cil managed
{

.maxstack 8
IL_0000: ldnull
IL_0001: throw
}

.method public hidebysig specialname
instance void add_EventFromFirstType(class [runtime]System.EventHandler`1<class [runtime]System.EventArgs> 'handler') cil managed
{

.maxstack 8
IL_0000: ldnull
IL_0001: throw
}

.method public hidebysig specialname
instance void remove_EventFromFirstType(class [runtime]System.EventHandler`1<class [runtime]System.EventArgs> 'handler') cil managed
{

.maxstack 8
IL_0000: ldnull
IL_0001: throw
}

.event class [runtime]System.EventHandler`1<class [runtime]System.EventArgs> EventFromFirstType
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CLIEventAttribute::.ctor() = ( 01 00 00 00 )
.addon instance void LibraryWithTwoClassesAndTwoEvents/MyClass::add_EventFromFirstType(class [runtime]System.EventHandler`1<class [runtime]System.EventArgs>)
.removeon instance void LibraryWithTwoClassesAndTwoEvents/MyClass::remove_EventFromFirstType(class [runtime]System.EventHandler`1<class [runtime]System.EventArgs>)
}
}

.class auto ansi serializable nested public MyClass2
extends [runtime]System.Object
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CompilationMappingAttribute::.ctor(valuetype [FSharp.Core]Microsoft.FSharp.Core.SourceConstructFlags) = ( 01 00 03 00 00 00 00 00 )
.method public specialname rtspecialname
instance void .ctor() cil managed
{

.maxstack 8
IL_0000: ldnull
IL_0001: throw
}

.method public hidebysig specialname
instance void add_EventFromSecondType(class [runtime]System.EventHandler`1<class [runtime]System.EventArgs> 'handler') cil managed
{

.maxstack 8
IL_0000: ldnull
IL_0001: throw
}

.method public hidebysig specialname
instance void remove_EventFromSecondType(class [runtime]System.EventHandler`1<class [runtime]System.EventArgs> 'handler') cil managed
{

.maxstack 8
IL_0000: ldnull
IL_0001: throw
}

.event class [runtime]System.EventHandler`1<class [runtime]System.EventArgs> EventFromSecondType
{
.custom instance void [FSharp.Core]Microsoft.FSharp.Core.CLIEventAttribute::.ctor() = ( 01 00 00 00 )
.addon instance void LibraryWithTwoClassesAndTwoEvents/MyClass2::add_EventFromSecondType(class [runtime]System.EventHandler`1<class [runtime]System.EventArgs>)
.removeon instance void LibraryWithTwoClassesAndTwoEvents/MyClass2::remove_EventFromSecondType(class [runtime]System.EventHandler`1<class [runtime]System.EventArgs>)
""" ]

[<Test>]
let ``Properties are emitted for CliMutable records`` () =
FSharp """
Expand Down