diff --git a/Documentation/project-docs/DefaultInterfaceMethods.md b/Documentation/project-docs/DefaultInterfaceMethods.md new file mode 100644 index 00000000000..688218abc13 --- /dev/null +++ b/Documentation/project-docs/DefaultInterfaceMethods.md @@ -0,0 +1,144 @@ +# Xamarin.Android and C# 8.0 default interface methods + +We have been trying to implement support for C# 8.0 default interface methods (DIMs) in Xamarin.Android, to reflect Java 8 default interface methods (DIMs). Here we are going to write some notes about it. + +## Reference materials + +There are [couple](https://github.com/dotnet/csharplang/issues/52) [of](https://github.com/dotnet/csharplang/issues/288) [relevant](https://github.com/dotnet/csharplang/blob/master/proposals/default-interface-methods.md) [issues](https://github.com/dotnet/roslyn/issues/17952) (and docs), but not everything is consistent. This post is written based on the implementation (mono's `csc-dim` version of csc) I have been using and packaging. + +## What are different from Java + +The feature is similar, but there are actually some caucious differences. + +This is how C# 8.0 DIMs work: + +``` +~/Desktop$ cat dim.cs +using System; + +public interface IFoo +{ + int X () { return 1; } + int Y => 2; +} + +public class Bar : IFoo +{ +} + +public class Baz +{ + public static void Main () + { + var bar = new Bar (); + var foo = (IFoo) bar; + Console.WriteLine (foo.X ()); + Console.WriteLine (bar.X ()); + } +} +~/Desktop$ csc-dim dim.cs -langversion:latest +Microsoft (R) Visual C# Compiler version 42.42.42.42424 () +Copyright (C) Microsoft Corporation. All rights reserved. + +dim.cs(20,26): error CS1061: 'Bar' does not contain a definition for 'X' and no extension method 'X' accepting a first argument of type 'Bar' could be found (are you missing a using directive or an assembly reference?) +``` + +(`csc-dim` is a special C# compiler distributed in the latest mono, which is anohter roslyn csc build which enabled C# 8 DIMs. We need `-langversion:latest` to actually use DIMs even with it.) + +You cannot call `new Bar ().X ()` because `X()` does not exist in `Bar`. In Java 8, `Bar.X()` is publicly accessible. In current C# 8.0 language specification, `Bar.X()` is **explicitly implemented** and **has no public API**. It's like existing non-DIMs that are not implicitly declared in a class. + +(It is explained at https://github.com/dotnet/csharplang/issues/288#issue-215243291 too. See "Concrete methods in interfaces".) + +It is actually argurable design, but that is another story. we're explaining only the fact part. + +It should be noted that we are under different circumstances than others: + +- We have no control over the API. We have no position to define API. Even Googlers don't especially in java.\* API. +- Android API, or even Java 8 API, has grown up to convert non-DIMs to DIMs. +- We have existing customers who have implemented existing Xamarin.Android interfaces. + +Therefore my investigation on C# 8.0 DIMs was in quite different direction from what others do/did. + +Let's see what kinf of default interface methods Android API has: + +- `java.lang.Iterable#spliterator()` is a DIM which was added at API Level 24 (Android N). Google had moved to OpenJDK class libraries at API Level 24 and there was a bunch of additions like this. +- Similarly, `java.lang.Iterable#remove()` is a DIM, but it had existed before API Level 24 as non-DIM. Since this method was public, there would be customers who have used this method. + + +Would there be any behavioral difference result in that Xamarin.Android cannot support DIMs? Not anything so far. + +What happens if, some customer has code that uses this non-default version of the method, like: + +``` +public class MyIterator : Java.Lang.IIterator +{ + // (there must be customer implementation of Remove() because it was not default before) + public void Remove () { ... } +} + +public void ReduceAndSkipSome (MyIterator iterator) +{ + IIterator i = iterator; // RValue can be anything. This is a PoC so just let it as is, but with explicit interface type. + while (i.HasNext ()) { + var current = i.Next (); + if (MatchesSomeCondition (current) + i.Remove (); // therefore it should still compile. + } +} +``` + +This will work. + +What if once we replace non-DIM IIterator.Remove() with a DIM, and customer rebuilt project without touching any of their source code, will it invoke `MyIterator.Remove()` ? The answer is **yes**. It is not `IIterator.Remove()` and it should still work just like it used to do. + +There won't be ABI breakage, but there is a problem that Java developers won't face. If a Xamarin.Android interface provides some DIMs and a third party library class `C` implements it without implicitly overriding it, the class is not as useful as one in Java, because of the reason I explained at first. There is no callable `new Bar().X()` where `X` is a DIM in `Foo` which `Bar` implements. + +To avoid that uselessness, the `C` developer needs to override ALL those DIMs. That's what current specification supporters claim developers to do. The current specification is likely the most consistent with the existing interface specification indeed. + +Another case Java developers would get stuck: + +``` +public interface IComparer +{ + int Compare (Object o1, Object o2); +} +public interface IList +{ + void Sort (IComparer comparer) { ... } // DIM +} +public class Vector : IList { ... } // implements everything in IList +public class MyVector : Vector +{ + void IList.Sort (IComparer comparer) { ...} // ERROR!! +} +``` + +This doesn't compile because "`MyVector` does not implement `IList`"... to make it compile, you will have to explicitly add `IList` as an implemented interface to `MyVector` declaration: + +``` +public class MyVector : Vector, IList { ... } +``` + +Then it will compile (and you don't have to implement non-DIMs in `IList` because `Vector` implements them). It is weird but that's how C# works. + + +### What Xamarin.Android currently does + +In the stable releases as of now, we don't bind any "new" default interface methods because generating them as non-default interface methods means the interface will be messy to implement (for example, what if you are told "you are supposed to implement `forEachRemaining()` and `remove()` in all of your `Iterator` implementation classes" ?). It is safe to ignore them because they don't need implementation. + +On the other hand, we generate managed methods for default interface methods IF they had existed as non-DIM in the earlier API Levels. There is a supplemental reason for that: `Mono.Android.dll` is offered per API Level, but it is not only from the corresponding API Level. Each `Mono.Android.dll` is a result of "merging" APIs from the earlier API. It is to bring API consistency across API Levels (if you look for `api-merge` in `xamarin-android/src/Mono.Android/Mono.Android.targets` you'll see how it is done). With this API model, it kind of makes sense to keep non-DIM as is, regardless of whether it is DIM now or not. + +For example, `javax.security.auth.Destroyable#destroy()` is a DIM in API Level 24 or later, but we mark it as non-DIM because it had existed since API Level 1. + + +### What Xamarin.Android will change + +We keep "already existed as non-DIMs" as is i.e. `Javax.Security.Auth.Destroyable.Destroy()` will remain DIM. I'm not sure if we will ever change that. This means Xamarin.Android application and library developers will be suffered from "extraneous work to implement some interface methods" to some extent. + +On the other hand, there will be totally new interface methods as DIMs such as `Java.Util.IIterator.ForEachRemaining()`. + +For non-abstract overrides such as `Java.Util.IPrimitiveIteratorOfDouble.ForEachRemaining()`, it will override the DIM as non-abstract, explicitly. + +For abstract overrides such as `Java.Util.IPrimitiveIterator.ForEachRemaining()`, it will override the DIM as abstract, explicitly. + + diff --git a/Xamarin.Android-Tests.sln b/Xamarin.Android-Tests.sln index 308a55fd1eb..31bb7178a37 100644 --- a/Xamarin.Android-Tests.sln +++ b/Xamarin.Android-Tests.sln @@ -76,6 +76,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Performance-Tests", "Perfor EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "timing", "build-tools\timing\timing.csproj", "{37CAA28C-40BE-4253-BA68-CC5D7316A617}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Android.DefaultInterfaceMethods-Tests", "tests\CodeGen-Binding\Xamarin.Android.DefaultInterfaceMethods-Tests\Xamarin.Android.DefaultInterfaceMethods-Tests.csproj", "{80E5171A-56DF-48AC-8AD9-65028319C1B8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Xamarin.Android.DefaultInterfaceMethods-Lib", "tests\CodeGen-Binding\Xamarin.Android.DefaultInterfaceMethods-Lib\Xamarin.Android.DefaultInterfaceMethods-Lib.csproj", "{E2F0F78B-6088-4282-A49C-122EE28611FF}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution tests\Xamarin.Forms-Performance-Integration\Xamarin.Forms.Performance.Integration.projitems*{195be9c2-1f91-40dc-bd6d-de860bf083fb}*SharedItemsImports = 13 @@ -194,6 +198,14 @@ Global {37CAA28C-40BE-4253-BA68-CC5D7316A617}.Debug|Any CPU.Build.0 = Debug|Any CPU {37CAA28C-40BE-4253-BA68-CC5D7316A617}.Release|Any CPU.ActiveCfg = Release|Any CPU {37CAA28C-40BE-4253-BA68-CC5D7316A617}.Release|Any CPU.Build.0 = Release|Any CPU + {80E5171A-56DF-48AC-8AD9-65028319C1B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {80E5171A-56DF-48AC-8AD9-65028319C1B8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {80E5171A-56DF-48AC-8AD9-65028319C1B8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {80E5171A-56DF-48AC-8AD9-65028319C1B8}.Release|Any CPU.Build.0 = Release|Any CPU + {E2F0F78B-6088-4282-A49C-122EE28611FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E2F0F78B-6088-4282-A49C-122EE28611FF}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E2F0F78B-6088-4282-A49C-122EE28611FF}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E2F0F78B-6088-4282-A49C-122EE28611FF}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -225,6 +237,8 @@ Global {F4DAFD78-BE76-46C9-A1AD-85D8C91CD77B} = {9B63992C-2201-4BB0-BD00-D637B481A995} {2DD1EE75-6D8D-4653-A800-0A24367F7F38} = {9B63992C-2201-4BB0-BD00-D637B481A995} {37CAA28C-40BE-4253-BA68-CC5D7316A617} = {68B8E272-5B12-47AA-8923-550B9CE535C7} + {80E5171A-56DF-48AC-8AD9-65028319C1B8} = {2EFFECF5-1CCA-4005-AE62-1D6F01C88DF4} + {E2F0F78B-6088-4282-A49C-122EE28611FF} = {2EFFECF5-1CCA-4005-AE62-1D6F01C88DF4} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8643CD20-B195-4919-8135-27549488237E} diff --git a/external/Java.Interop b/external/Java.Interop index 78f73018f0e..e6be186c23f 160000 --- a/external/Java.Interop +++ b/external/Java.Interop @@ -1 +1 @@ -Subproject commit 78f73018f0e440c80e47e21e009c6f493b7103ff +Subproject commit e6be186c23f0843a1774bafe450f535be7129128 diff --git a/src/Mono.Android/Java.Nio.Channels/AsynchronousServerSocketChannel.cs b/src/Mono.Android/Java.Nio.Channels/AsynchronousServerSocketChannel.cs new file mode 100644 index 00000000000..60f4aa526b5 --- /dev/null +++ b/src/Mono.Android/Java.Nio.Channels/AsynchronousServerSocketChannel.cs @@ -0,0 +1,21 @@ +#if ANDROID_26 + +using System; +using Java.Net; + +namespace Java.Nio.Channels +{ + partial class AsynchronousServerSocketChannel + { + INetworkChannel INetworkChannel.Bind (SocketAddress address) + { + return Bind (address); + } + INetworkChannel INetworkChannel.SetOption (ISocketOption option, Java.Lang.Object value) + { + return SetOption (option, value); + } + } +} + +#endif diff --git a/src/Mono.Android/Java.Nio.Channels/AsynchronousSocketChannel.cs b/src/Mono.Android/Java.Nio.Channels/AsynchronousSocketChannel.cs new file mode 100644 index 00000000000..70cd94982c0 --- /dev/null +++ b/src/Mono.Android/Java.Nio.Channels/AsynchronousSocketChannel.cs @@ -0,0 +1,21 @@ +#if ANDROID_26 + +using System; +using Java.Net; + +namespace Java.Nio.Channels +{ + partial class AsynchronousSocketChannel + { + INetworkChannel INetworkChannel.Bind (SocketAddress address) + { + return Bind (address); + } + INetworkChannel INetworkChannel.SetOption (ISocketOption option, Java.Lang.Object value) + { + return SetOption (option, value); + } + } +} + +#endif diff --git a/src/Mono.Android/Java.Nio.Channels/DatagramChannel.cs b/src/Mono.Android/Java.Nio.Channels/DatagramChannel.cs new file mode 100644 index 00000000000..9c567deee43 --- /dev/null +++ b/src/Mono.Android/Java.Nio.Channels/DatagramChannel.cs @@ -0,0 +1,17 @@ +using System; +using Java.Net; + +namespace Java.Nio.Channels +{ + partial class DatagramChannel + { + INetworkChannel INetworkChannel.Bind (SocketAddress address) + { + return Bind (address); + } + INetworkChannel INetworkChannel.SetOption (ISocketOption option, Java.Lang.Object value) + { + return SetOption (option, value); + } + } +} diff --git a/src/Mono.Android/Java.Nio.Channels/ServerSocketChannel.cs b/src/Mono.Android/Java.Nio.Channels/ServerSocketChannel.cs new file mode 100644 index 00000000000..994c3165f49 --- /dev/null +++ b/src/Mono.Android/Java.Nio.Channels/ServerSocketChannel.cs @@ -0,0 +1,17 @@ +using System; +using Java.Net; + +namespace Java.Nio.Channels +{ + partial class ServerSocketChannel + { + INetworkChannel INetworkChannel.Bind (SocketAddress address) + { + return Bind (address); + } + INetworkChannel INetworkChannel.SetOption (ISocketOption option, Java.Lang.Object value) + { + return SetOption (option, value); + } + } +} diff --git a/src/Mono.Android/Java.Nio.Channels/SocketChannel.cs b/src/Mono.Android/Java.Nio.Channels/SocketChannel.cs new file mode 100644 index 00000000000..573c6a2fad7 --- /dev/null +++ b/src/Mono.Android/Java.Nio.Channels/SocketChannel.cs @@ -0,0 +1,17 @@ +using System; +using Java.Net; + +namespace Java.Nio.Channels +{ + partial class SocketChannel + { + INetworkChannel INetworkChannel.Bind (SocketAddress address) + { + return Bind (address); + } + INetworkChannel INetworkChannel.SetOption (ISocketOption option, Java.Lang.Object value) + { + return SetOption (option, value); + } + } +} diff --git a/src/Mono.Android/Java.Util/Spliterators.cs b/src/Mono.Android/Java.Util/Spliterators.cs index d6a327dc480..99dbbe3de0c 100644 --- a/src/Mono.Android/Java.Util/Spliterators.cs +++ b/src/Mono.Android/Java.Util/Spliterators.cs @@ -1,4 +1,4 @@ -#if ANDROID_24 +#if false//ANDROID_24 using System; using Android.Runtime; using Java.Interop; @@ -6,7 +6,6 @@ namespace Java.Util { - // FIXME: this should not be required to be hand-bound. public partial class Spliterators { public partial class AbstractSpliterator diff --git a/src/Mono.Android/Mono.Android.csproj b/src/Mono.Android/Mono.Android.csproj index 2e805278a6a..f782fde347b 100644 --- a/src/Mono.Android/Mono.Android.csproj +++ b/src/Mono.Android/Mono.Android.csproj @@ -301,6 +301,7 @@ + diff --git a/src/Mono.Android/Mono.Android.targets b/src/Mono.Android/Mono.Android.targets index f8242c06ada..1acde6c0f70 100644 --- a/src/Mono.Android/Mono.Android.targets +++ b/src/Mono.Android/Mono.Android.targets @@ -3,6 +3,10 @@ + + ..\..\packages\xamarin.android.csc.dim.0.1.2\tools\ + latest + @@ -78,6 +82,7 @@ "$(XAInstallPrefix)xbuild\Xamarin\Android\generator.exe" <_GenFlags>--public --product-version=7 + <_DefaultInterfaceMethods>--default-interface-methods <_ApiLevel>--api-level=$(AndroidApiLevel) <_Out>-o "$(IntermediateOutputPath)mcw" <_Codegen>--codegen-target=XAJavaInterop1 @@ -92,7 +97,7 @@ <_Dirs>--enumdir=$(IntermediateOutputPath)mcw diff --git a/src/Mono.Android/metadata b/src/Mono.Android/metadata index 1525b120dd0..a24cd51e720 100644 --- a/src/Mono.Android/metadata +++ b/src/Mono.Android/metadata @@ -1173,29 +1173,13 @@ public - - - - - - + + + + java.net.SocketOption + Java.Lang.Object + Java.Lang.Object public @@ -1208,50 +1192,36 @@ Java.Util.Concurrent.ICompletionStage - - - + Java.Lang.Object + + Java.Util.ISpliterator + Java.Util.ISpliterator + + + Java.Util.ISpliterator Java.Lang.Object Java.Util.IIterator - Java.Lang.Object - - - Java.Util.ISpliterator + + + + + Android.Service.QuickSettings @@ -1320,8 +1290,10 @@ AudioFocusRequestClass - + + Java.Time.Temporal.ITemporal + @@ -1389,6 +1361,10 @@ --> ColorObject + + AnimationStart2 + AnimationEnd2 + + false + + + java.util.function.Consumer + diff --git a/src/Mono.Android/packages.config b/src/Mono.Android/packages.config new file mode 100644 index 00000000000..940176f8108 --- /dev/null +++ b/src/Mono.Android/packages.config @@ -0,0 +1,5 @@ + + + + + diff --git a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixAbstractMethodsStep.cs b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixAbstractMethodsStep.cs index 101ecc5052b..32e582c0eef 100644 --- a/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixAbstractMethodsStep.cs +++ b/src/Xamarin.Android.Build.Tasks/Linker/MonoDroid.Tuner/FixAbstractMethodsStep.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq; using Mono.Cecil; @@ -163,7 +164,7 @@ bool FixAbstractMethods (TypeDefinition type) if (ifaceDef.HasGenericParameters) continue; - foreach (var iMethod in ifaceDef.Methods) { + foreach (var iMethod in ifaceDef.Methods.Where (m => m.IsAbstract)) { bool exists = false; foreach (var tMethod in typeMethods) { diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/Generator.cs b/src/Xamarin.Android.Build.Tasks/Tasks/Generator.cs index e3555270254..9fb962f1ca3 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/Generator.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/Generator.cs @@ -41,6 +41,8 @@ public class BindingsGenerator : AndroidToolTask public bool UseShortFileNames { get; set; } + public bool EnableDefaultInterfaceMethods { get; set; } + // apart from ReferencedManagedLibraries we need it to find mscorlib.dll. [Required] public string MonoAndroidFrameworkDirectories { get; set; } @@ -64,6 +66,7 @@ public override bool Execute () Log.LogDebugMessage (" AssemblyName: {0}", AssemblyName); Log.LogDebugMessage (" AndroidApiLevel: {0}", AndroidApiLevel); Log.LogDebugMessage (" UseShortFileNames: {0}", UseShortFileNames); + Log.LogDebugMessage (" EnableDefaultInterfaceMethods: {0}", EnableDefaultInterfaceMethods); Log.LogDebugTaskItems (" TransformFiles:", TransformFiles); Log.LogDebugTaskItems (" ReferencedManagedLibraries:", ReferencedManagedLibraries); Log.LogDebugTaskItems (" AnnotationsZipFiles:", AnnotationsZipFiles); @@ -119,6 +122,8 @@ protected override string GenerateCommandLineCommands () cmd.AppendSwitchIfNotNull ("--enumdir=", EnumDirectory); cmd.AppendSwitchIfNotNull ("--enummetadata=", EnumMetadataDirectory); cmd.AppendSwitchIfNotNull ("--assembly=", AssemblyName); + if (EnableDefaultInterfaceMethods) + cmd.AppendSwitch ("--default-interface-methods"); if (!NoStdlib) { string fxpath = MonoAndroidFrameworkDirectories.Split (';').First (p => new DirectoryInfo (p).GetFiles ("mscorlib.dll").Any ()); diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs index ff18627c040..dd08038bc48 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs @@ -446,5 +446,59 @@ public String greet (String name, java.util.Date date) Assert.IsTrue (xml.Contains (" - name to display."), "missing doc"); } } + + [Test] + [TestCaseSource ("ClassParseOptions")] + public void BindDefaultInterfaceMethods (string classParser) + { + var proj = new XamarinAndroidBindingProject () { + IsRelease = true, + }; + proj.Packages.Add (new Package { Id = "xamarin.android.csc.dim", Version = "0.1.2" }); + // The sources for the .jar is in the jar itself. + string classesJarBase64 = @" +UEsDBBQACAgIANWk6UwAAAAAAAAAAAAAAAAJAAQATUVUQS1JTkYv/soAAAMAUEsHCAAAAAACAAAAAAA +AAFBLAwQUAAgICADVpOlMAAAAAAAAAAAAAAAAFAAAAE1FVEEtSU5GL01BTklGRVNULk1G803My0xLLS +7RDUstKs7Mz7NSMNQz4OVyLkpNLElN0XWqBAlY6BnEG5obKmj4FyUm56QqOOcXFeQXJZYA1WvycvFyA +QBQSwcIFGFrLUQAAABFAAAAUEsDBAoAAAgAAK2k6UwAAAAAAAAAAAAAAAAEAAAAY29tL1BLAwQKAAAI +AACtpOlMAAAAAAAAAAAAAAAADAAAAGNvbS94YW1hcmluL1BLAwQKAAAIAACwpOlMAAAAAAAAAAAAAAA +AEQAAAGNvbS94YW1hcmluL3Rlc3QvUEsDBBQACAgIAJmk6UwAAAAAAAAAAAAAAAAuAAAAY29tL3hhbW +FyaW4vdGVzdC9EZWZhdWx0SW50ZXJmYWNlTWV0aG9kcy5jbGFzc3WOvU7DMBSFjxsnKeWnXUE8QLrgh +ScAhBSJnwHE7qQ3JVUSC8dGFc/EwsrAA/BQiOuqLKnw8Pn4+LuWv38+vwCcY5biKMVUIKqMYWbzXEBe +mgUJTG/qju58W5B91EXDTbIkd6HtX3jj0G+DzPL5E28v3q8FJg/G25Ku6zB1ekWV9o3LO0e20iXdkns +2i/5spV+1QFaaVq11q23dKUe9U//4ArMwoRrdLdV9saLSJQICI4QVc4ogmTGfThBugFH0zuR/MpNNE7 +x015NDL3C868VDL2XuYbL1joMTjI+BNpYC+/xcaA820uEvUEsHCIw1aijpAAAAhQEAAFBLAwQUAAgIC +ACYpOlMAAAAAAAAAAAAAAAAHAAAAERlZmF1bHRJbnRlcmZhY2VNZXRob2RzLmphdmF1zLEOwiAQBuCd +p7hRl0Zd2YyLgw9xwlGJFCocTWPTdxdSHarxxv///utR3bElUKFrRuwwWt8wJZZC9PnqrALrmaJBRXA +ig9nx+RNciG9BJzEJKKeXtnowIcBmCxNE4hw97CTMP6glPmJcuf1f91y5w7cbgtWQ3rCOBnSZymJhNX +nkPJYnUsziBVBLBwgzfz2miQAAAPUAAABQSwECFAAUAAgICADVpOlMAAAAAAIAAAAAAAAACQAEAAAAA +AAAAAAAAAAAAAAATUVUQS1JTkYv/soAAFBLAQIUABQACAgIANWk6UwUYWstRAAAAEUAAAAUAAAAAAAA +AAAAAAAAAD0AAABNRVRBLUlORi9NQU5JRkVTVC5NRlBLAQIKAAoAAAgAAK2k6UwAAAAAAAAAAAAAAAA +EAAAAAAAAAAAAAAAAAMMAAABjb20vUEsBAgoACgAACAAAraTpTAAAAAAAAAAAAAAAAAwAAAAAAAAAAA +AAAAAA5QAAAGNvbS94YW1hcmluL1BLAQIKAAoAAAgAALCk6UwAAAAAAAAAAAAAAAARAAAAAAAAAAAAA +AAAAA8BAABjb20veGFtYXJpbi90ZXN0L1BLAQIUABQACAgIAJmk6UyMNWoo6QAAAIUBAAAuAAAAAAAA +AAAAAAAAAD4BAABjb20veGFtYXJpbi90ZXN0L0RlZmF1bHRJbnRlcmZhY2VNZXRob2RzLmNsYXNzUEs +BAhQAFAAICAgAmKTpTDN/PaaJAAAA9QAAABwAAAAAAAAAAAAAAAAAgwIAAERlZmF1bHRJbnRlcmZhY2 +VNZXRob2RzLmphdmFQSwUGAAAAAAcABwDOAQAAVgMAAAAA +"; + proj.Jars.Add (new AndroidItem.EmbeddedJar ("dim.jar") { + BinaryContent = () => Convert.FromBase64String (classesJarBase64) + }); + proj.AndroidClassParser = classParser; + proj.SetProperty ("CscToolPath", "$(MSBuildThisFileDirectory)\\..\\packages\\xamarin.android.csc.dim.0.1.2\\tools"); + proj.SetProperty ("AndroidEnableDefaultInterfaceMethods", "True"); + proj.SetProperty ("LangVersion", "latest"); + using (var b = CreateDllBuilder (Path.Combine ("temp", TestName), false, false)) { + proj.NuGetRestore (b.ProjectDirectory); + Assert.IsTrue (b.Build (proj), "Build should have succeeded."); + string asmpath = Path.GetFullPath (Path.Combine (Path.GetDirectoryName (new Uri (GetType ().Assembly.CodeBase).LocalPath), b.ProjectDirectory, b.Output.OutputPath, (proj.AssemblyName ?? proj.ProjectName) + ".dll")); + Assert.IsTrue (File.Exists (asmpath), "assembly does not exist"); + var cs = b.Output.GetIntermediaryAsText (Path.Combine ("generated", "src", "Com.Xamarin.Test.IDefaultInterfaceMethods.cs")); + Assert.IsTrue (cs.Contains ("int Quux ();"), "Quux not generated."); + Assert.IsTrue (cs.Contains ("virtual unsafe int Foo ()"), "Foo not generated."); + Assert.IsTrue (cs.Contains ("virtual unsafe int Bar {"), "Bar not generated."); + Assert.IsTrue (cs.Contains ("set {"), "(Baz) setter not generated."); + } + } } } diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Bindings.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Bindings.targets index 2fdb17639ba..efb301d68ac 100755 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Bindings.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Bindings.targets @@ -489,6 +489,7 @@ Copyright (C) 2012 Xamarin Inc. All rights reserved. ToolPath="$(MonoAndroidToolsDirectory)" ToolExe="$(BindingsGeneratorToolExe)" UseShortFileNames="$(UseShortGeneratorFileNames)" + EnableDefaultInterfaceMethods="$(AndroidEnableDefaultInterfaceMethods)" /> diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Additions/AboutAdditions.txt b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Additions/AboutAdditions.txt new file mode 100644 index 00000000000..c511f1d4ee1 --- /dev/null +++ b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Additions/AboutAdditions.txt @@ -0,0 +1,48 @@ +Additions allow you to add arbitrary C# to the generated classes +before they are compiled. This can be helpful for providing convenience +methods or adding pure C# classes. + +== Adding Methods to Generated Classes == + +Let's say the library being bound has a Rectangle class with a constructor +that takes an x and y position, and a width and length size. It will look like +this: + +public partial class Rectangle +{ + public Rectangle (int x, int y, int width, int height) + { + // JNI bindings + } +} + +Imagine we want to add a constructor to this class that takes a Point and +Size structure instead of 4 ints. We can add a new file called Rectangle.cs +with a partial class containing our new method: + +public partial class Rectangle +{ + public Rectangle (Point location, Size size) : + this (location.X, location.Y, size.Width, size.Height) + { + } +} + +At compile time, the additions class will be added to the generated class +and the final assembly will a Rectangle class with both constructors. + + +== Adding C# Classes == + +Another thing that can be done is adding fully C# managed classes to the +generated library. In the above example, let's assume that there isn't a +Point class available in Java or our library. The one we create doesn't need +to interact with Java, so we'll create it like a normal class in C#. + +By adding a Point.cs file with this class, it will end up in the binding library: + +public class Point +{ + public int X { get; set; } + public int Y { get; set; } +} diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Jars/AboutJars.txt b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Jars/AboutJars.txt new file mode 100644 index 00000000000..e833d78bc58 --- /dev/null +++ b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Jars/AboutJars.txt @@ -0,0 +1,36 @@ +This directory is for Android .jars. + +There are 4 types of jars that are supported: + +== Input Jar and Embedded Jar == + +This is the jar that bindings should be generated for. + +For example, if you were binding the Google Maps library, this would +be Google's "maps.jar". + +The difference between EmbeddedJar and InputJar is, EmbeddedJar is to be +embedded in the resulting dll as EmbeddedResource, while InputJar is not. +There are couple of reasons you wouldn't like to embed the target jar +in your dll (the ones that could be internally loaded by +feature e.g. maps.jar, or you cannot embed jars that are under some +proprietary license). + +Set the build action for these jars in the properties page to "InputJar". + + +== Reference Jar and Embedded Reference Jar == + +These are jars that are referenced by the input jar. C# bindings will +not be created for these jars. These jars will be used to resolve +types used by the input jar. + +NOTE: Do not add "android.jar" as a reference jar. It will be added automatically +based on the Target Framework selected. + +Set the build action for these jars in the properties page to "ReferenceJar". + +"EmbeddedJar" works like "ReferenceJar", but like "EmbeddedJar", it is +embedded in your dll. But at application build time, they are not included +in the final apk, like ReferenceJar files. + diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Jars/DefaultInterfaceMethods.java b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Jars/DefaultInterfaceMethods.java new file mode 100644 index 00000000000..84a310f5c54 --- /dev/null +++ b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Jars/DefaultInterfaceMethods.java @@ -0,0 +1,10 @@ +package com.xamarin.test; + +public interface DefaultInterfaceMethods +{ + default int foo () { return 0; } + default int getBar () { return 1; } + default int getBaz () { return 2; } + default void setBaz (int value) { } + default int toImplement () { throw new UnsupportedOperationException (); } +} diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Jars/ImplementedClass.java b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Jars/ImplementedClass.java new file mode 100644 index 00000000000..4feeb9c2a8a --- /dev/null +++ b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Jars/ImplementedClass.java @@ -0,0 +1,6 @@ +package com.xamarin.test; + +public class ImplementedClass implements DefaultInterfaceMethods +{ + public int toImplement () { return -1; } +} diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Properties/AssemblyInfo.cs b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..895af20109e --- /dev/null +++ b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using Android.App; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle ("Xamarin.Android.DefaultInterfaceMethods-Lib")] +[assembly: AssemblyDescription ("")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("")] +[assembly: AssemblyProduct ("")] +[assembly: AssemblyCopyright ("${AuthorCopyright}")] +[assembly: AssemblyTrademark ("")] +[assembly: AssemblyCulture ("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion ("1.0.0")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Transforms/EnumFields.xml b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Transforms/EnumFields.xml new file mode 100644 index 00000000000..b95f58ccd8c --- /dev/null +++ b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Transforms/EnumFields.xml @@ -0,0 +1,19 @@ + + + + diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Transforms/EnumMethods.xml b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Transforms/EnumMethods.xml new file mode 100644 index 00000000000..c65a473ca7a --- /dev/null +++ b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Transforms/EnumMethods.xml @@ -0,0 +1,19 @@ + + + + diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Transforms/Metadata.xml b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Transforms/Metadata.xml new file mode 100644 index 00000000000..8f3bde759f9 --- /dev/null +++ b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Transforms/Metadata.xml @@ -0,0 +1,10 @@ + + + + diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Xamarin.Android.DefaultInterfaceMethods-Lib.csproj b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Xamarin.Android.DefaultInterfaceMethods-Lib.csproj new file mode 100644 index 00000000000..78ff7a2845c --- /dev/null +++ b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/Xamarin.Android.DefaultInterfaceMethods-Lib.csproj @@ -0,0 +1,67 @@ + + + + + + Debug + AnyCPU + {E2F0F78B-6088-4282-A49C-122EE28611FF} + {10368E6C-D01B-4462-8E8B-01FC667A7035};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + Xamarin.Android.DefaultInterfaceMethodsLib + Xamarin.Android.DefaultInterfaceMethods-Lib + v9.0 + Resources + Assets + true + class-parse + True + Latest + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + None + + + true + pdbonly + true + bin\Release + prompt + 4 + true + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/packages.config b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/packages.config new file mode 100644 index 00000000000..ef211d7c05d --- /dev/null +++ b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Lib/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Assets/AboutAssets.txt b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Assets/AboutAssets.txt new file mode 100644 index 00000000000..a9b0638eb1b --- /dev/null +++ b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Assets/AboutAssets.txt @@ -0,0 +1,19 @@ +Any raw assets you want to be deployed with your application can be placed in +this directory (and child directories) and given a Build Action of "AndroidAsset". + +These files will be deployed with your package and will be accessible using Android's +AssetManager, like this: + +public class ReadAsset : Activity +{ + protected override void OnCreate (Bundle bundle) + { + base.OnCreate (bundle); + + InputStream input = Assets.Open ("my_asset.txt"); + } +} + +Additionally, some Android functions will automatically load asset files: + +Typeface tf = Typeface.CreateFromAsset (Context.Assets, "fonts/samplefont.ttf"); diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/MainActivity.cs b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/MainActivity.cs new file mode 100644 index 00000000000..1e1ec957d6c --- /dev/null +++ b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/MainActivity.cs @@ -0,0 +1,27 @@ +using System; +using System.Reflection; + +using Android.App; +using Android.OS; +using Android.Runtime; +using Com.Xamarin.Test; +using Java.Interop; +using Xamarin.Android.NUnitLite; + +namespace Xamarin.Android.DefaultInterfaceMethodsTests +{ + [Activity (Label = "Xamarin.Android.DefaultInterfaceMethods-Tests", MainLauncher = true)] + public class MainActivity : TestSuiteActivity + { + protected override void OnCreate (Bundle bundle) + { + // tests can be inside the main assembly + AddTest (Assembly.GetExecutingAssembly ()); + // or in any reference assemblies + // AddTest (typeof (Your.Library.TestClass).Assembly); + + // Once you called base.OnCreate(), you cannot add more assemblies. + base.OnCreate (bundle); + } + } +} diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Properties/AndroidManifest.xml b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Properties/AndroidManifest.xml new file mode 100644 index 00000000000..be0ab0ee935 --- /dev/null +++ b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Properties/AndroidManifest.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Properties/AssemblyInfo.cs b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000000..a5ecc52af40 --- /dev/null +++ b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,27 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using Android.App; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle ("Xamarin.Android.DefaultInterfaceMethods-Tests")] +[assembly: AssemblyDescription ("")] +[assembly: AssemblyConfiguration ("")] +[assembly: AssemblyCompany ("")] +[assembly: AssemblyProduct ("")] +[assembly: AssemblyCopyright ("${AuthorCopyright}")] +[assembly: AssemblyTrademark ("")] +[assembly: AssemblyCulture ("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion ("1.0.0")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Resources/AboutResources.txt b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Resources/AboutResources.txt new file mode 100644 index 00000000000..10f52d46021 --- /dev/null +++ b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Resources/AboutResources.txt @@ -0,0 +1,44 @@ +Images, layout descriptions, binary blobs and string dictionaries can be included +in your application as resource files. Various Android APIs are designed to +operate on the resource IDs instead of dealing with images, strings or binary blobs +directly. + +For example, a sample Android app that contains a user interface layout (main.axml), +an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) +would keep its resources in the "Resources" directory of the application: + +Resources/ + drawable/ + icon.png + + layout/ + main.axml + + values/ + strings.xml + +In order to get the build system to recognize Android resources, set the build action to +"AndroidResource". The native Android APIs do not operate directly with filenames, but +instead operate on resource IDs. When you compile an Android application that uses resources, +the build system will package the resources for distribution and generate a class called "R" +(this is an Android convention) that contains the tokens for each one of the resources +included. For example, for the above Resources layout, this is what the R class would expose: + +public class R { + public class drawable { + public const int icon = 0x123; + } + + public class layout { + public const int main = 0x456; + } + + public class strings { + public const int first_string = 0xabc; + public const int second_string = 0xbcd; + } +} + +You would then use R.drawable.icon to reference the drawable/icon.png file, or R.layout.main +to reference the layout/main.axml file, or R.strings.first_string to reference the first +string in the dictionary file values/strings.xml. diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Resources/mipmap-hdpi/Icon.png b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Resources/mipmap-hdpi/Icon.png new file mode 100644 index 00000000000..f4c804644c5 Binary files /dev/null and b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Resources/mipmap-hdpi/Icon.png differ diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Resources/mipmap-mdpi/Icon.png b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Resources/mipmap-mdpi/Icon.png new file mode 100644 index 00000000000..ef1e1ee7dc3 Binary files /dev/null and b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Resources/mipmap-mdpi/Icon.png differ diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Resources/mipmap-xhdpi/Icon.png b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Resources/mipmap-xhdpi/Icon.png new file mode 100644 index 00000000000..b7e2e57aa90 Binary files /dev/null and b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Resources/mipmap-xhdpi/Icon.png differ diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Resources/mipmap-xxhdpi/Icon.png b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Resources/mipmap-xxhdpi/Icon.png new file mode 100644 index 00000000000..8d20a38d178 Binary files /dev/null and b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Resources/mipmap-xxhdpi/Icon.png differ diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Resources/mipmap-xxxhdpi/Icon.png b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Resources/mipmap-xxxhdpi/Icon.png new file mode 100644 index 00000000000..6d9919c41a3 Binary files /dev/null and b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Resources/mipmap-xxxhdpi/Icon.png differ diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/TestsSample.cs b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/TestsSample.cs new file mode 100644 index 00000000000..84f8094ddf5 --- /dev/null +++ b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/TestsSample.cs @@ -0,0 +1,22 @@ +using System; +using Com.Xamarin.Test; +using NUnit.Framework; + +namespace Xamarin.Android.DefaultInterfaceMethodsTests +{ + [TestFixture] + public class DimTest + { + [Test] + public void TestCSharp8DefaultInterfaceMethods () + { + // C# 8 syntax is awkward. + // If you use "var" then it is declared as the class, and fails to resolve. + // Those default interface methods are only callable via interface! + IDefaultInterfaceMethods c = new ImplementedClass (); + Assert.AreEqual (0, c.Foo (), "#1"); + Assert.AreEqual (1, c.Bar, "#2"); + Assert.AreEqual (-1, c.ToImplement (), "#3"); + } + } +} diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Xamarin.Android.DefaultInterfaceMethods-Tests.csproj b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Xamarin.Android.DefaultInterfaceMethods-Tests.csproj new file mode 100644 index 00000000000..6859e10fda4 --- /dev/null +++ b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/Xamarin.Android.DefaultInterfaceMethods-Tests.csproj @@ -0,0 +1,81 @@ + + + + + Debug + AnyCPU + {80E5171A-56DF-48AC-8AD9-65028319C1B8} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + Xamarin.Android.DefaultInterfaceMethodsTests + Xamarin.Android.DefaultInterfaceMethods-Tests + v9.0 + True + Resources\Resource.designer.cs + Resource + Resources + Assets + true + Properties\AndroidManifest.xml + armeabi-v7a;x86;arm64-v8a;x86_64 + Latest + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + None + false + + true + + + true + pdbonly + true + bin\Release + prompt + 4 + true + true + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {E2F0F78B-6088-4282-A49C-122EE28611FF} + Xamarin.Android.DefaultInterfaceMethods-Lib + + + + + diff --git a/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/packages.config b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/packages.config new file mode 100644 index 00000000000..7b2eb74810c --- /dev/null +++ b/tests/CodeGen-Binding/Xamarin.Android.DefaultInterfaceMethods-Tests/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file