diff --git a/.github/workflows/pr.yml b/.github/workflows/pr.yml index b326b04..19fb3df 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pr.yml @@ -28,11 +28,6 @@ jobs: with: dotnet-version: 6.0.425 - - name: Setup .NET Core 8 - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 8.0.124 - - name: Build on Windows if: matrix.os == 'windows-latest' run: .\build.cmd diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index 5f5108e..26e60a8 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -32,11 +32,6 @@ jobs: with: dotnet-version: 6.0.425 - - name: Setup .NET Core 8 - uses: actions/setup-dotnet@v4 - with: - dotnet-version: 8.0.124 - - name: Build on Windows if: matrix.os == 'windows-latest' run: .\build.cmd diff --git a/tests/GenerativeInterfacesTests.fs b/tests/GenerativeInterfacesTests.fs index f963e22..78e0525 100644 --- a/tests/GenerativeInterfacesTests.fs +++ b/tests/GenerativeInterfacesTests.fs @@ -41,6 +41,24 @@ type GenerativeInterfacesProvider (config: TypeProviderConfig) as this = let contract = createInterface "IContract" members container.AddMember contract + // IExtended inherits from IContract and adds an extra method + let extended = createInterface "IExtended" [ "GetLength", [("s", typeof)], typeof ] + extended.AddInterfaceImplementation(contract) + container.AddMember extended + + // Impl is a concrete class that implements both IMarker and IContract + let impl = ProvidedTypeDefinition("Impl", Some typeof, isErased = false) + let getString = ProvidedMethod("GetString", [], typeof, invokeCode = fun _args -> <@@ "hello" @@>) + getString.AddMethodAttrs(MethodAttributes.Virtual) + let sum = ProvidedMethod("Sum", [ProvidedParameter("x", typeof); ProvidedParameter("y", typeof)], typeof, + invokeCode = fun args -> <@@ (%%args.[1] : int) + (%%args.[2] : int) @@>) + sum.AddMethodAttrs(MethodAttributes.Virtual) + impl.AddMember getString + impl.AddMember sum + impl.AddInterfaceImplementation(marker) + impl.AddInterfaceImplementation(contract) + container.AddMember impl + tempAssembly.AddTypes [container] this.AddNamespace(container.Namespace, [container]) @@ -89,3 +107,53 @@ let ``Interfaces with methods are generated correctly``() = Assert.True(contractSum.IsAbstract, "Expected Sum method to be abstract") Assert.True(contractSum.IsVirtual, "Expected Sum method to be virtual") +[] +let ``Interface inheritance: IExtended extends IContract``() = + testProvidedAssembly <| fun container -> + let extended = container.GetNestedType "IExtended" + Assert.NotNull(extended) + Assert.True(extended.IsInterface, "Expected IExtended to be an interface") + + // IExtended declares its own method + let getLength = extended.GetMethod("GetLength") + Assert.NotNull(getLength) + Assert.True(getLength.IsAbstract, "Expected GetLength to be abstract") + + // IExtended inherits IContract + let ifaces = extended.GetInterfaces() + let hasIContract = ifaces |> Array.exists (fun i -> i.Name = "IContract") + Assert.True(hasIContract, "Expected IExtended to implement IContract") + +[] +let ``Concrete class implementing interfaces is generated correctly``() = + testProvidedAssembly <| fun container -> + let impl = container.GetNestedType "Impl" + Assert.NotNull(impl) + Assert.False(impl.IsInterface, "Impl should not be an interface") + Assert.False(impl.IsAbstract, "Impl should not be abstract") + + // Impl implements both IMarker and IContract + let ifaces = impl.GetInterfaces() + let hasIMarker = ifaces |> Array.exists (fun i -> i.Name = "IMarker") + let hasIContract = ifaces |> Array.exists (fun i -> i.Name = "IContract") + Assert.True(hasIMarker, "Expected Impl to implement IMarker") + Assert.True(hasIContract, "Expected Impl to implement IContract") + +[] +let ``Concrete class methods satisfy interface contract``() = + testProvidedAssembly <| fun container -> + let impl = container.GetNestedType "Impl" + Assert.NotNull(impl) + + let getString = impl.GetMethod("GetString") + Assert.NotNull(getString) + Assert.False(getString.IsAbstract, "GetString on Impl should not be abstract") + + let sum = impl.GetMethod("Sum") + Assert.NotNull(sum) + let ps = sum.GetParameters() + Assert.Equal(2, ps.Length) + Assert.Equal(typeof, ps.[0].ParameterType) + Assert.Equal(typeof, ps.[1].ParameterType) + Assert.Equal(typeof, sum.ReturnType) +