diff --git a/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs b/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs index 95ba940f7..783d3c038 100644 --- a/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs +++ b/tests/generator-Tests/Unit-Tests/CodeGeneratorTests.cs @@ -229,6 +229,44 @@ public void SupportedOSPlatform () StringAssert.DoesNotContain ("[global::System.Runtime.Versioning.SupportedOSPlatformAttribute (\"android30.0\")]", builder.ToString (), "Should contain SupportedOSPlatform!"); } + + [Test] + public void InheritedInterfaceAsClass () + { + // This is a somewhat cheating way to repro a real issue. + // The real issue is: + // - Binding an interface which implements 'android.provider.BaseColumns' + // - android.provider.BaseColumns is an interface in android.jar + // - Mono.Android.dll has both: + // - [Register ("android.provider.BaseColumns")] public abstract class BaseColumns + // - [Register ("android.provider.BaseColumns")] public interface IBaseColumns + // Our Java type resolution is "last one wins" and happens to pick the class instead of + // the interface. So our code is trying to bind an interface that implements a class. + var xml = @" + + + + + + + + + + "; + + var gens = ParseApiDefinition (xml); + + // Disable "BuildingCoreAssembly" + (gens.Single (g => g.Name == "Object") as ClassGen).FromXml = false; + + var klass = gens.Single (g => g.Name == "IMyClass"); + + generator.Context.ContextTypes.Push (klass); + generator.WriteType (klass, string.Empty, new GenerationInfo ("", "", "MyAssembly")); + generator.Context.ContextTypes.Pop (); + + Assert.Pass ("WriteType did not NRE"); + } } [TestFixture] diff --git a/tools/generator/SourceWriters/BoundInterface.cs b/tools/generator/SourceWriters/BoundInterface.cs index ab02953c4..05194f4a7 100644 --- a/tools/generator/SourceWriters/BoundInterface.cs +++ b/tools/generator/SourceWriters/BoundInterface.cs @@ -137,7 +137,11 @@ void AddInheritedInterfaces (InterfaceGen iface, CodeGenerationOptions opt) foreach (var isym in iface.Interfaces) { var igen = (isym is GenericSymbol ? (isym as GenericSymbol).Gen : isym) as InterfaceGen; - if (igen.IsConstSugar (opt) || igen.RawVisibility != "public") + // igen *should not* be null here because we *should* only be inheriting interfaces, but + // in the case of constants on that interface we create a C# *class* that is registered for the + // Java *interface*. Thus when we do type resolution, we are actually pointed to the + // Foo abstract class instead of the IFoo interface. + if (igen is null || igen.IsConstSugar (opt) || igen.RawVisibility != "public") continue; Implements.Add (opt.GetOutputName (isym.FullName));