diff --git a/CHANGELOG.md b/CHANGELOG.md index 964fc77b2..4417fbaf5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ details about the cause of the failure - Fix incorrect choice of method to invoke when using keyword arguments. - Fix non-delegate types incorrectly appearing as callable. - Indexers can now be used with interface objects +- Fixed a bug where indexers could not be used if they were inherited ## [2.5.0][] - 2020-06-14 diff --git a/src/runtime/classmanager.cs b/src/runtime/classmanager.cs index 0b084a49d..08918adc1 100644 --- a/src/runtime/classmanager.cs +++ b/src/runtime/classmanager.cs @@ -389,6 +389,25 @@ private static ClassInfo GetClassInfo(Type type) ci.members[name] = ob; } + if (ci.indexer == null && type.IsClass) + { + // Indexer may be inherited. + var parent = type.BaseType; + while (parent != null && ci.indexer == null) + { + foreach (var prop in parent.GetProperties()) { + var args = prop.GetIndexParameters(); + if (args.GetLength(0) > 0) + { + ci.indexer = new Indexer(); + ci.indexer.AddProperty(prop); + break; + } + } + parent = parent.BaseType; + } + } + return ci; } } diff --git a/src/testing/indexertest.cs b/src/testing/indexertest.cs index ae39eb2b1..78bb99a7c 100644 --- a/src/testing/indexertest.cs +++ b/src/testing/indexertest.cs @@ -411,4 +411,29 @@ public MultiDefaultKeyIndexerTest() : base() } } } + + public class PublicInheritedIndexerTest : PublicIndexerTest { } + + public class ProtectedInheritedIndexerTest : ProtectedIndexerTest { } + + public class PrivateInheritedIndexerTest : ProtectedIndexerTest { } + + public class InternalInheritedIndexerTest : InternalIndexerTest { } + + public interface IIndexer + { + string this[int index] { get; set; } + } + + public interface IInheritedIndexer : IIndexer { } + + public class InterfaceInheritedIndexerTest :IndexerBase, IInheritedIndexer { + private System.Collections.Generic.IDictionary d = new System.Collections.Generic.Dictionary(); + + public string this[int index] + { + get { return GetValue(index); } + set { t[index] = value; } + } + } } diff --git a/src/tests/test_indexer.py b/src/tests/test_indexer.py index 6da8e1386..b8a33fb46 100644 --- a/src/tests/test_indexer.py +++ b/src/tests/test_indexer.py @@ -614,3 +614,35 @@ def test_using_indexer_on_object_without_indexer(): with pytest.raises(TypeError): o[0] = 1 + + +def test_inherited_indexer(): + """Test that inherited indexers are accessible""" + from Python.Test import PublicInheritedIndexerTest + from Python.Test import ProtectedInheritedIndexerTest + from Python.Test import PrivateInheritedIndexerTest + from Python.Test import InternalInheritedIndexerTest + + pub = PublicInheritedIndexerTest() + pub[0] = "zero" + assert pub[0] == "zero" + + def assert_no_indexer(obj): + with pytest.raises(TypeError): + obj[0] + with pytest.raises(TypeError): + obj[0] = "zero" + + assert_no_indexer(PrivateInheritedIndexerTest) + assert_no_indexer(ProtectedInheritedIndexerTest) + assert_no_indexer(InternalInheritedIndexerTest) + + +def test_inherited_indexer_interface(): + """Test that indexers inherited from other interfaces are accessible""" + from Python.Test import InterfaceInheritedIndexerTest, IInheritedIndexer + + impl = InterfaceInheritedIndexerTest() + ifc = IInheritedIndexer(impl) + ifc[0] = "zero" + assert ifc[0] == "zero"