/Languages/Ruby/IronRuby.Tests/Runtime/ClrTests.cs
C# | 3557 lines | 2955 code | 425 blank | 177 comment | 58 complexity | 014209dbc0be4dec9eb1e47ef9acca39 MD5 | raw file
Possible License(s): CPL-1.0, BSD-3-Clause, ISC, GPL-2.0, MPL-2.0-no-copyleft-exception
Large files files are truncated, but you can click here to view the full file
- /* ****************************************************************************
- *
- * Copyright (c) Microsoft Corporation.
- *
- * This source code is subject to terms and conditions of the Apache License, Version 2.0. A
- * copy of the license can be found in the License.html file at the root of this distribution. If
- * you cannot locate the Apache License, Version 2.0, please send an email to
- * ironruby@microsoft.com. By using this source code in any fashion, you are agreeing to be bound
- * by the terms of the Apache License, Version 2.0.
- *
- * You must not remove this notice, or any other, from this software.
- *
- *
- * ***************************************************************************/
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using System.Diagnostics;
- using System.Linq.Expressions;
- using System.Reflection;
- using System.Runtime.CompilerServices;
- using System.Runtime.InteropServices;
- using IronRuby.Builtins;
- using IronRuby.Runtime;
- using Microsoft.Scripting.Hosting;
- using Microsoft.Scripting.Math;
- using Microsoft.Scripting.Runtime;
- using Microsoft.Scripting.Utils;
- #if !CLR2
- using BigInt = System.Numerics.BigInteger;
- using System.Reflection.Emit;
- #endif
- namespace IronRuby.Tests {
- public partial class Tests {
- public readonly string FuncFullName = typeof(Func<>).FullName.Split('`')[0].Replace(".", "::");
- public readonly string ActionFullName = typeof(Action).FullName.Split('`')[0].Replace(".", "::");
- #region Members: Fields, Methods, Properties, Indexers
- public class ClassWithFields {
- public int Field = 1;
- public readonly int RoField = 2;
- public static int StaticField = 3;
- public const int ConstField = 4;
- }
- public void ClrFields1() {
- Context.DefineGlobalVariable("obj", new ClassWithFields());
- AssertOutput(delegate() {
- CompilerTest(@"
- C = $obj.class
- puts $obj.field
- puts $obj.RoField
- $obj.field = 10
- puts $obj.field
- ($obj.RoField = 20) rescue puts $!.class
- puts C.static_field
- puts C.const_field
- C.static_field = 30
- puts C.static_field
- (C.const_field = 40) rescue puts $!.class
- ");
- }, @"
- 1
- 2
- 10
- NoMethodError
- 3
- 4
- 30
- NoMethodError
- ");
- }
- public class ClassWithField1 {
- public int F = 1;
- }
- public class ClassWithField2 : ClassWithField1 {
- public new static int F = 2;
- }
- public void ClrFields2() {
- Context.DefineGlobalVariable("obj", new ClassWithField2());
- AssertOutput(delegate() {
- CompilerTest(@"
- puts $obj.class.F
- puts $obj.F
- ");
- }, @"
- 2
- 1
- ");
- }
- public class ClassWithMethods1 {
- public int RoProperty { get { return 3; } }
- public int RwProperty { get { return 4; } set { } }
- public int WoProperty { set { } }
-
- public int M() { return 1; }
- public static int StaticMethod() { return 2; }
- }
- public void ClrMethods1() {
- Context.DefineGlobalVariable("obj", new ClassWithMethods1());
- Context.DefineGlobalVariable("cls", typeof(ClassWithMethods1));
- AssertOutput(delegate() {
- CompilerTest(@"
- C = $obj.class
- puts $obj.m
- puts C.static_method
- puts $cls.static_methods rescue puts $!.class
- ($obj.RoProperty = 10) rescue puts $!.class
- $obj.WoProperty = 20
- $obj.RwProperty = 30
- puts $obj.RoProperty
- puts $obj.WoProperty rescue puts $!.class
- puts $obj.RwProperty
- ");
- }, @"
- 1
- 2
- NoMethodError
- NoMethodError
- 3
- NoMethodError
- 4
- ");
- }
- /// <summary>
- /// Order of initialization of CLR methods.
- /// </summary>
- public void ClrMethods2() {
- Context.ObjectClass.SetConstant("C", Context.GetClass(typeof(ClassWithMethods1)));
- XTestOutput(@"
- class C
- def m; 2; end # replace CLR method with Ruby method before we use the CLR one
- remove_method :m # remove Ruby method
- new.m rescue p $! # we shouldn't call the CLR method
- end
- ", @"
- ");
- }
- public class ClassWithEquals1 {
- // define overload of Equals so that we get a method group with mixed instance and static methods inherited from Object's method group
- public static bool Equals(object o1, object o2, object o3) { return o1.Equals(o2); }
- }
- /// <summary>
- /// Mixing instance and static methods - instance Object::Equals(Object), static Object::Equals(Object, Object).
- /// </summary>
- public void ClrMethods3() {
- Context.ObjectClass.SetConstant("C", Context.GetClass(typeof(ClassWithEquals1)));
- TestOutput(@"
- puts 1.Equals(2) # instance
- puts 1.Equals(2,3) rescue p $! # static invoked with instance
- puts C.Equals(C) # instance invoked on a class (statically)
- puts C.Equals(3,3) # static
- puts C.Equals(3,3,4) # overload
- ", @"
- false
- #<ArgumentError: wrong number of arguments (2 for 1)>
- true
- true
- true
- ");
- }
- /// <summary>
- /// Builtin types only expose CLR methods under unmangled names (mangling is no applied).
- /// </summary>
- public void ClrMethods4() {
- TestOutput(@"
- a = Exception.new
- p a.method(:data) rescue p $!
- p a.method(:Data)
- ", @"
- #<NameError: undefined method `data' for class `Exception'>
- #<Method: Exception#Data>
- ");
- }
- public void ClrMembers1() {
- TestOutput(@"
- a = [1,2,3]
- p m = a.clr_member(:count)
- p m[]
- p m = a.clr_member(:index_of)
- p m.clr_members.size
- p m.overload(Object).clr_members
- ", @"
- #<Method: Array#count>
- 3
- #<Method: Array#index_of>
- 3
- [Int32 IndexOf(System.Object)]
- ");
- TestOutput(@"
- class C < Array
- end
- p C.new.clr_member(:index_of).call(1)
- ", @"
- -1
- ");
- }
- public class ClassWithIndexer1 {
- public int[,] Values = new int[,] { { 0, 10 }, { 20, 30 } };
- public int this[int i, int j] { get { return Values[i, j]; } set { Values[i, j] = value; } }
- }
- public void ClrIndexers1() {
- Context.ObjectClass.SetConstant("CI", Context.GetClass(typeof(ClassWithIndexer1)));
- // default indexers:
- AssertOutput(() => CompilerTest(@"
- c = CI.new
- c[0,1] += 1
- p c[0, 1]
- "), @"
- 11
- ");
- // non-default indexers:
- // TODO: We need to use VB or generate IL to test this.
- // TODO: improve access
- // If a property accessor with parameters is called without arguments the result is a PropertyAccessor object with [], []= defined.
- // Then the calls could look like c.foo[1,2] = 3.
- // AssertOutput(() => CompilerTest(@"
- //c = CI.new
- //c.method(:foo=).call(1, 0, c.method(:foo).call(1, 0) + 5)
- //p c.method(:foo).call(1, 0)
- //"), @"
- //25
- //");
- }
- #endregion
- #region Visibility
- public class ProtectedA {
- protected string Foo(int a) { return "Foo(I): " + a; }
- public string Bar(int a) { return "Bar(I): " + a; }
- protected string PG<T>(T a) { return "PG<T>(T)"; }
- }
- public class ProtectedB : ProtectedA {
- public string Foo(object a) { return "Foo(O): " + a.ToString(); }
- internal protected string Bar(object a) { return "Bar(O): " + a; }
- protected int Prop1 { get; set; }
- public int Prop2 { get; internal protected set; }
- private string Baz(int a) { return "Baz(I): " + a; }
- public string Baz(object a) { return "Baz(O): " + a; }
- protected static string StaticM() { return "StaticM"; }
- protected static string StaticGenericM<T>(T f) { return "StaticGenericM: " + f.ToString(); }
- internal protected string PG<T>(T a, int b) { return "PG<T>(T,int)"; }
- // TODO:
- // protected int Fld;
- // protected static int Fld;
- // protected event Func<object> Evnt;
- }
- public void ClrVisibility1() {
- Debug.Assert(!Engine.Runtime.Setup.PrivateBinding);
- Context.ObjectClass.SetConstant("A", Context.GetClass(typeof(ProtectedA)));
- Context.ObjectClass.SetConstant("B", Context.GetClass(typeof(ProtectedB)));
- // methods:
- AssertOutput(delegate() {
- CompilerTest(@"
- class C < B; end
- a, b, c = A.new, B.new, C.new
- puts c.foo(1)
- puts b.foo(2)
- puts b.bar(22)
- a.foo(3) rescue p $!
- class A
- def foo; 4; end
- def bar; 5; end
- end
- puts c.foo(6)
- b.bar(7) rescue p $!
- B.StaticM rescue p $!
- puts C.StaticM
- puts C.method(:StaticGenericM).of(Fixnum)[123]
- ");
- }, @"
- Foo(I): 1
- Foo(O): 2
- Bar(I): 22
- #<NoMethodError: CLR protected method `foo' called for *ProtectedA*>
- Foo(O): 6
- #<NoMethodError: CLR protected method `bar' called for *ProtectedB*>
- #<NoMethodError: CLR protected method `StaticM' called for *ProtectedB*>
- StaticM
- StaticGenericM: 123
- ", OutputFlags.Match);
- // generic methods:
- TestOutput(@"
- class C < B; end
- c = C.new
- puts c.method(:PG).of(Fixnum).call(1)
- puts c.method(:PG).of(Fixnum).call(1,2)
- ", @"
- PG<T>(T)
- PG<T>(T,int)
- ");
- // properties:
- AssertOutput(delegate() {
- CompilerTest(@"
- class C < B; end
- a, b, c = A.new, B.new, C.new
- c.prop1 = 1
- c.prop2 = 2
- puts c.prop1
- puts c.prop2
- (b.prop2 = 10) rescue p $!
- puts b.prop2
- ");
- }, @"
- 1
- 2
- #<NoMethodError: CLR protected method `prop2=' called for *ProtectedB*>
- 0
- ", OutputFlags.Match);
- }
- [Options(PrivateBinding = true)]
- public void ClrVisibility2() {
- Debug.Assert(Engine.Runtime.Setup.PrivateBinding);
- if (_driver.PartialTrust) return;
- Context.ObjectClass.SetConstant("A", Context.GetClass(typeof(ProtectedA)));
- Context.ObjectClass.SetConstant("B", Context.GetClass(typeof(ProtectedB)));
- // methods, properties:
- TestOutput(@"
- class C < B; end
- a, b, c = A.new, B.new, C.new
- puts a.foo(3)
- class A
- def bar; 5; end
- end
- puts b.bar(7)
- puts b.baz(1)
- b.prop2 = 10
- puts b.prop2
- ",
- @"
- Foo(I): 3
- Bar(O): 7
- Baz(I): 1
- 10
- ");
- }
- public delegate void TestDelegate(string a);
- public void SpecialMethods() {
- var result = Engine.Execute(@"
- System::AppDomain.CurrentDomain.CreateInstance(""mscorlib"", ""System.Object"")
- ");
- Assert(result is System.Runtime.Remoting.ObjectHandle);
- var dm = (DynamicMethod)Engine.Execute(@"
- System::Reflection::Emit::DynamicMethod.new(""foo"", 1.GetType(), System::Array[System::Type].new(0))
- ");
- Assert(dm.ReturnType == typeof(int));
- var invoke = typeof(TestDelegate).GetMethod("Invoke");
- var d = invoke.CreateDelegate(typeof(Action<string>));
- Assert(d is Action<string>);
- }
- #endregion
- #region Member Enumeration
- /// <summary>
- /// No CLR names should be returned for builtin types and singletons.
- /// </summary>
- public void ClrMethodEnumeration1() {
- // built-ins:
- var irModules = new[] { "IronRuby" };
- using (Context.ClassHierarchyLocker()) {
- Context.ObjectClass.EnumerateConstants((module, name, value) => {
- RubyModule m = value as RubyModule;
- if (m != null && Array.IndexOf(irModules, m.Name) == -1) {
- var s = m.GetOrCreateSingletonClass();
- AssertNoClrNames(ModuleOps.GetInstanceMethods(m, true), m.Name);
- AssertNoClrNames(ModuleOps.GetPrivateInstanceMethods(m, true), m.Name);
- AssertNoClrNames(ModuleOps.GetInstanceMethods(s, true), m.Name);
- AssertNoClrNames(ModuleOps.GetPrivateInstanceMethods(s, true), m.Name);
- }
- return false;
- });
- }
- // singletons:
- AssertNoClrNames(Engine.Execute<object>(@"class << self; instance_methods + private_instance_methods; end"), null);
- AssertNoClrNames(Engine.Execute<object>(@"class << self; class << self; instance_methods + private_instance_methods; end; end"), null);
- AssertNoClrNames(Engine.Execute<object>(@"class << Class; instance_methods + private_instance_methods; end"), null);
- }
- public void ClrMethodEnumeration2() {
- TestOutput(@"
- class System::Decimal
- instance_methods(false).each do |name|
- mangled = '__' + name
-
- alias_method(mangled, name)
- private mangled
-
- define_method(name) do |*args|
- puts ""method called: #{name}""
- send mangled, *args
- end
- end
- end
- x, y = System::Decimal.new(1), System::Decimal.new(2)
- x + y
- x.CompareTo(y)
- ", @"
- method called: +
- method called: compare_to
- ");
- }
- public class ClassWithGeneratedMembers1 : I1 {
- private class OK {
- }
- // C# generates display class, anonymous type, anonymos methods and a static field:
- private IEnumerable<int> GetInts() {
- var t = new { a = 1, b = 2 };
- Func<int> f = () => 1;
- yield return f();
- yield return t.a;
- yield return Field;
- }
- private static int Field = 3;
- int I1.f() { return 0; }
- }
- [Options(PrivateBinding = true)]
- public void ClrMethodEnumeration_InvalidNames1() {
- Context.ObjectClass.SetConstant("Foo", Context.GetClass(typeof(ClassWithGeneratedMembers1)));
- TestOutput(@"
- class Foo
- def <=>; end
- def <<; end
- def &; end
- def f?; end
- def f!; end
- def f=; end
- end
- puts Foo.constants
- puts Foo.singleton_methods(false).sort
- puts Foo.instance_methods(false).sort
- ", @"
- OK
- field
- field=
- &
- <<
- <=>
- f!
- f=
- f?
- get_ints
- ");
- }
- private void AssertNoClrNames(object/*!*/ methods, string moduleName) {
- var array = (RubyArray)methods;
- int idx = array.FindIndex((name) => name is ClrName);
- Assert(idx == -1, moduleName + "::" + (idx == -1 ? null : ((ClrName)array[idx]).ActualName));
- }
- #endregion
- #region Generic Methods
- #pragma warning disable 67 // event not used
- public class GenericMethods {
- public static string M0<T>() {
- return "M0<" + typeof(T).Name + ">()";
- }
- public static string M1() {
- return "M1()";
- }
-
- public static string M1<T>() {
- return "M1<" + typeof(T).Name + ">()";
- }
- public static string M1<S, T>() {
- return "M1<" + typeof(S).Name + ", " + typeof(T).Name + ">()";
- }
- public static string M1<T>(int foo) {
- return "M1<" + typeof(T).Name + ">(Fixnum)";
- }
- public static string M2(int foo) {
- return "M2(Fixnum)";
- }
- public static string M2<T>(int foo) {
- return "M2<" + typeof(T).Name + ">(Fixnum)";
- }
- public static int Field;
- public static object Property { get; set; }
- public static event Action<Object> Event;
- }
- #pragma warning restore
- public void ClrGenericMethods1() {
- Context.ObjectClass.SetConstant("GM", Context.GetClass(typeof(GenericMethods)));
- TestOutput(@"
- m = GM.method(:M1)
- puts m.call
- puts m.of().call
- puts m.of(String).call
- puts m.of(String, Fixnum).call
- puts m.call(1) rescue p $!
- puts m.of(String, String, String) rescue p $!
- ", @"
- M1()
- M1()
- M1<MutableString>()
- M1<MutableString, Int32>()
- #<ArgumentError: generic arguments could not be infered for method 'M1'>
- #<ArgumentError: wrong number of generic arguments for `M1'>
- "
- );
- TestOutput(@"
- m = GM.method(:M2)
- puts m.call(1)
- puts GM.method(:field).of(Fixnum) rescue p $!
- puts GM.method(:property).of(Fixnum) rescue p $!
- puts GM.method(:event).of(Fixnum) rescue p $!
- ", @"
- M2(Fixnum)
- #<ArgumentError: wrong number of generic arguments for `field'>
- #<ArgumentError: wrong number of generic arguments for `property'>
- #<ArgumentError: wrong number of generic arguments for `event'>
- "
- );
- }
- public abstract class GenericMethods2 {
- public abstract T Foo<T>(T arg);
- }
- internal class GenericMethods3 : GenericMethods2 {
- public override T Foo<T>(T arg) {
- return arg;
- }
- }
- public void ClrGenericMethods2() {
- Context.ObjectClass.SetConstant("GM3", new GenericMethods3());
- TestOutput(@"
- puts GM3.foo(123)
- ", @"
- 123
- ");
- }
- public class Inference1 {
- public int ByRef<T>(ref T x) {
- x = (T)(object)((int)(object)x + 1);
- return 0;
- }
- public int Array<T>(T[] x) {
- return 1;
- }
- public int Multiple<S, R>(IEnumerable<S> source, Func<S, R> selector) {
- return 2;
- }
- public int DeepShape<T>(Dictionary<Dictionary<T, string>, Dictionary<int, T>> arg) {
- return 3;
- }
- public int Complex<A,B,C>(ref Dictionary<List<Dictionary<Func<A, B[][,,,][], C>[], int>>, Func<Dictionary<int, A>, B, C>>[] arg) {
- return 4;
- }
- public int Where<T>(IEnumerable<T> e, Func<T, bool> f) {
- return 5;
- }
- public int Where<T>(IEnumerable<T> e, Func<T, int, bool> f) {
- return 6;
- }
- public int Where<T>(IEnumerable<T> e, object f) {
- return 7;
- }
- public int Apply<T>(IEnumerable<T> e, Action<T> f) {
- return 8;
- }
- public int Mixed<T>(T arg) {
- return 8;
- }
- public int Mixed(object arg) {
- return 9;
- }
- }
- public void ClrGenericParametersInference1() {
- Context.ObjectClass.SetConstant("F", Context.GetClass(typeof(Func<object,string>)));
- Context.ObjectClass.SetConstant("SB", Context.GetClass(typeof(StrongBox<int>)));
- Context.ObjectClass.SetConstant("SBx",
- new StrongBox<Dictionary<List<Dictionary<Func<int, bool[][,,,][], double>[], int>>, Func<Dictionary<int, int>, bool, double>>[]>(null)
- );
- Context.ObjectClass.SetConstant("I", new Inference1());
- Context.ObjectClass.SetConstant("E", Context.GetClass(typeof(InteropTests.Generics1.Extensions)));
-
- TestOutput(@"
- p I.Array(System::Array[Fixnum].new(3))
- p I.Multiple([1,2,3], F.new { |x| x.to_s })
- E.Select([1,2], F.new { |x| x.to_s + '!' }).each { |a| puts a }
- E.Select([1,2], lambda { |x| x + 1 }).each { |a| puts a }
- ", @"
- 1
- 2
- 1!
- 2!
- 2
- 3
- ");
- TestOutput(@"
- p I.ByRef(2)
- sb = SB.new(10)
- p I.ByRef(sb), sb.Value
- ", @"
- [0, 3]
- 0
- 11
- ");
- TestOutput(@"
- include System::Collections::Generic
- p I.DeepShape(Dictionary[List[Fixnum], Dictionary[Fixnum, Fixnum]].new) rescue p $!
- p I.DeepShape(Dictionary[Dictionary[Fixnum, System::String], Dictionary[Fixnum, Fixnum]].new)
- ", @"
- #<ArgumentError: generic arguments could not be infered for method 'DeepShape'>
- 3
- ");
- TestOutput(@"
- p I.Complex(SBx)
- ", @"
- 4
- ");
-
- TestOutput(@"
- l1 = lambda { |x| }
- l2 = lambda { |x, y| }
- l3 = lambda { |*| }
- a = System::Array[Object].new(1)
- p I.Where(a, l1)
- p I.Where(a, l2)
- p I.Where(a, l3) rescue puts 'ambiguous'
- p I.Where(a, 123)
- ", @"
- 5
- 6
- ambiguous
- 7
- ");
- // TODO:
- // XTestOutput(@"
- //a = System::Array[Fixnum].new(1)
- //p I.Apply(a, lambda { |x| })
- //", @"
- //5
- //");
- // an inferred type is more specific than object:
- TestOutput(@"
- p I.Mixed(1)
- ", @"
- 8
- ");
- }
- #endregion
- #region Extension Methods
- public void ClrExtensionMethods0() {
- bool expectExact = typeof(Enumerable).Assembly.FullName == "System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
- Dictionary<string, int> expected = new Dictionary<string, int>();
- foreach (string name in new[] {
- "AsQueryable", "AsQueryable", "Where", "Where", "OfType", "Cast", "Select", "Select", "SelectMany", "SelectMany", "SelectMany", "SelectMany", "Join", "Join", "GroupJoin",
- "GroupJoin", "OrderBy", "OrderBy", "OrderByDescending", "OrderByDescending", "ThenBy", "ThenBy", "ThenByDescending", "ThenByDescending", "Take", "TakeWhile",
- "TakeWhile", "Skip", "SkipWhile", "SkipWhile", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "Distinct", "Distinct",
- "Concat", "Zip", "Union", "Union", "Intersect", "Intersect", "Except", "Except", "First", "First", "FirstOrDefault", "FirstOrDefault", "Last", "Last",
- "LastOrDefault", "LastOrDefault", "Single", "Single", "SingleOrDefault", "SingleOrDefault", "ElementAt", "ElementAtOrDefault", "DefaultIfEmpty", "DefaultIfEmpty",
- "Contains", "Contains", "Reverse", "SequenceEqual", "SequenceEqual", "Any", "Any", "All", "Count", "Count", "LongCount", "LongCount", "Min", "Min", "Max", "Max",
- "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Average", "Average",
- "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average",
- "Average", "Average", "Average", "Aggregate", "Aggregate", "Aggregate", "Where", "Where", "Select", "Select", "SelectMany", "SelectMany", "SelectMany", "SelectMany",
- "Take", "TakeWhile", "TakeWhile", "Skip", "SkipWhile", "SkipWhile", "Join", "Join", "GroupJoin", "GroupJoin", "OrderBy", "OrderBy", "OrderByDescending",
- "OrderByDescending", "ThenBy", "ThenBy", "ThenByDescending", "ThenByDescending", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy",
- "GroupBy", "Concat", "Zip", "Distinct", "Distinct", "Union", "Union", "Intersect", "Intersect", "Except", "Except", "Reverse", "SequenceEqual", "SequenceEqual",
- "AsEnumerable", "ToArray", "ToList", "ToDictionary", "ToDictionary", "ToDictionary", "ToDictionary", "ToLookup", "ToLookup", "ToLookup", "ToLookup", "DefaultIfEmpty",
- "DefaultIfEmpty", "OfType", "Cast", "First", "First", "FirstOrDefault", "FirstOrDefault", "Last", "Last", "LastOrDefault", "LastOrDefault", "Single", "Single",
- "SingleOrDefault", "SingleOrDefault", "ElementAt", "ElementAtOrDefault", "Any", "Any", "All", "Count", "Count", "LongCount", "LongCount", "Contains", "Contains",
- "Aggregate", "Aggregate", "Aggregate", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum",
- "Sum", "Sum", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min",
- "Min", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max",
- "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average",
- "Average", "Average", "Average", "Average", "Average", "AsParallel", "AsParallel", "AsOrdered", "AsOrdered", "AsUnordered", "AsParallel", "AsSequential",
- "WithDegreeOfParallelism", "WithCancellation", "WithExecutionMode", "WithMergeOptions", "ForAll", "Where", "Where", "Select", "Select", "Zip", "Zip", "Join", "Join",
- "Join", "Join", "GroupJoin", "GroupJoin", "GroupJoin", "GroupJoin", "SelectMany", "SelectMany", "SelectMany", "SelectMany", "OrderBy", "OrderBy", "OrderByDescending",
- "OrderByDescending", "ThenBy", "ThenBy", "ThenByDescending", "ThenByDescending", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy", "GroupBy",
- "Aggregate", "Aggregate", "Aggregate", "Aggregate", "Aggregate", "Count", "Count", "LongCount", "LongCount", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum",
- "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Sum", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min",
- "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Min", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max",
- "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Max", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average",
- "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Average", "Any", "Any", "All", "Contains", "Contains", "Take",
- "TakeWhile", "TakeWhile", "Skip", "SkipWhile", "SkipWhile", "Concat", "Concat", "SequenceEqual", "SequenceEqual", "SequenceEqual", "SequenceEqual", "Distinct",
- "Distinct", "Union", "Union", "Union", "Union", "Intersect", "Intersect", "Intersect", "Intersect", "Except", "Except", "Except", "Except", "AsEnumerable", "ToArray",
- "ToList", "ToDictionary", "ToDictionary", "ToDictionary", "ToDictionary", "ToLookup", "ToLookup", "ToLookup", "ToLookup", "Reverse", "OfType", "Cast", "First", "First",
- "FirstOrDefault", "FirstOrDefault", "Last", "Last", "LastOrDefault", "LastOrDefault", "Single", "Single", "SingleOrDefault", "SingleOrDefault", "DefaultIfEmpty",
- "DefaultIfEmpty", "ElementAt", "ElementAtOrDefault", "Unwrap", "Unwrap",
- }) {
- int count;
- if (!expected.TryGetValue(name, out count)) {
- count = 0;
- }
- expected[name] = count + 1;
- }
- var methods = ReflectionUtils.GetVisibleExtensionMethods(typeof(Enumerable).Assembly);
- new List<MethodInfo>(ReflectionUtils.GetVisibleExtensionMethodsSlow(typeof(Enumerable).Assembly));
- Dictionary<string, int> actual = new Dictionary<string, int>();
- foreach (MethodInfo method in methods) {
- int count;
- if (!actual.TryGetValue(method.Name, out count)) {
- count = 0;
- }
- actual[method.Name] = count + 1;
- }
- foreach (string name in actual.Keys) {
- Assert(expected.ContainsKey(name));
- Assert(expectExact ? expected[name] == actual[name] : expected[name] >= actual[name]);
- }
- }
- public void ClrExtensionMethods1() {
- Context.ObjectClass.SetConstant("SystemCoreAssembly", typeof(Expression).Assembly.FullName);
- TestOutput(@"
- load_assembly SystemCoreAssembly
- using_clr_extensions System::Linq
- a = System::Array[Fixnum].new([1,2,3])
- p a.first_or_default
- #TODO: p a.method(:of_type).of(Fixnum).call.to_a #=> [1, 2, 3]
- ", @"
- 1
- ");
- }
- /// <summary>
- /// Loads an assembly that defines more extension methods in the given namespace.
- /// </summary>
- public void ClrExtensionMethods2() {
- Context.ObjectClass.SetConstant("SystemCoreAssembly", typeof(Expression).Assembly.FullName);
- Context.ObjectClass.SetConstant("DummyLinqAssembly", typeof(System.Linq.Dummy).Assembly.FullName);
- TestOutput(@"
- load_assembly DummyLinqAssembly
- using_clr_extensions System::Linq
- load_assembly SystemCoreAssembly
- p System::Array[Fixnum].new([1,2,3]).first_or_default
- ", @"
- 1
- ");
- }
- /// <summary>
- /// Extension methods not available by default onlty after their declaring namespace is "used".
- /// </summary>
- public void ClrExtensionMethods3() {
- Context.ObjectClass.SetConstant("SystemCoreAssembly", typeof(Expression).Assembly.FullName);
- Context.ObjectClass.SetConstant("DummyLinqAssembly", typeof(System.Linq.Dummy).Assembly.FullName);
-
- TestOutput(@"
- load_assembly DummyLinqAssembly
- load_assembly SystemCoreAssembly
- a = System::Array[Fixnum].new([1,2,3])
- a.first_or_default rescue p $!
- using_clr_extensions System::Linq
- p a.first_or_default
- ", @"
- #<NoMethodError: undefined method `first_or_default' for [1, 2, 3]:System::Int32[]>
- 1
- ");
- }
- /// <summary>
- /// Extension methods defined using generic parameters and constraints.
- /// </summary>
- public void ClrExtensionMethods4() {
- Runtime.LoadAssembly(typeof(IronRubyTests.ExtensionMethods2.EMs).Assembly);
- TestOutput(@"
- L = System::Collections::Generic::List
- D = System::Collections::Generic::Dictionary
- using_clr_extensions IronRubyTests::ExtensionMethods2
- include IronRubyTests::ExtensionMethods2
- puts L[X].new.f1
- L[A].new.f1 rescue puts '!f1'
- puts D[B, A].new.f2
- puts D[A, A].new.f2
- D[A, X].new.f2 rescue puts '!f2'
- puts f3 = L[X].new.method(:f3)
- puts f3.of(X, Object)[1]
- puts L[Y].new.f3(X.new)
- L[A].new.f3(X.new) rescue puts '!f3'
- puts S.new.f4
- puts 1.f4
- #TODO: A.new.method(:f4) rescue p $!
- A.new.f4 rescue puts '!f4'
- puts A.new.f5
- puts B.new.f5
- class A; def f5; 'Ruby f5'; end; end
- puts A.new.f5
- puts B.new.f5 # f5 is an extension on all types (TODO)
- puts System::Array[A].new(1).f6
- System::Array[Fixnum].new(1).f6 rescue puts '!f6'
- puts L[System::Array[D[B, L[A]]]].new.f6
- L[System::Array[D[B, L[Fixnum]]]].new.f6 rescue puts '!f6'
- ", @"
- f1
- !f1
- f2
- f2
- !f2
- #<Method: System::Collections::Generic::List[IronRubyTests::ExtensionMethods2::X]#f3>
- f3
- f3
- !f3
- f4
- f4
- !f4
- f5
- f5
- Ruby f5
- Ruby f5
- f6
- !f6
- f6
- !f6
- ");
- }
- /// <summary>
- /// Extension methods are available on CLR interfaces implemented by Ruby classes.
- /// </summary>
- public void ClrExtensionMethods5() {
- #if TODO
- Runtime.LoadAssembly(typeof(System.Linq.Enumerable).Assembly);
- XTestOutput(@"
- using_clr_extensions System::Linq
- class Sequence
- include System::Collections::Generic::IEnumerable[Object]
-
- def initialize array
- @array = array
- end
-
- def get_enumerator
- @array.GetEnumerator()
- end
- end
- class Array
- def to_seq
- Sequence.new self
- end
- end
- a = Sequence.new [1, 2, 3]
- p a.select(lambda { |n| n * 2 })
- ", @"
- [2, 3, 6]
- ");
- #endif
- }
- #endregion
- #region Overloads: Inheritance, Selection
- public static class OverloadInheritance1 {
- public class A {
- public string Foo(int a, int b, int c) {
- return "Foo: " + a.ToString() + ", " + b.ToString() + ", " + c.ToString();
- }
- public string Skip() {
- return "Skip";
- }
- }
- public class B : A {
- public string Foo(int a) {
- return "Foo: " + a.ToString();
- }
- public virtual string Foo(int a, int b) {
- return "Foo: " + a.ToString() + ", " + b.ToString();
- }
- public string Bar(int a) {
- return "Bar: " + a.ToString();
- }
- public string Hidden(int a) {
- return "Hidden: " + a.ToString();
- }
- public string Middle(int a) {
- return "Middle: " + a.ToString();
- }
- }
- public class C : B {
- public new string Foo(int a) {
- return "NewFoo: " + a.ToString();
- }
- public override string Foo(int a, int b) {
- return "OverriddenFoo: " + a.ToString() + ", " + b.ToString();
- }
- public string Bar(int a, int b) {
- return "Bar: " + a.ToString() + ", " + b.ToString();
- }
- public string Hidden(int a, int b) {
- return "Hidden: " + a.ToString() + ", " + b.ToString();
- }
- public string Skip(int a) {
- return "Skip: " + a.ToString();
- }
- }
- }
- public void ClrOverloadInheritance1() {
- Context.ObjectClass.SetConstant("Obj", new OverloadInheritance1.C());
- AssertOutput(() => CompilerTest(@"
- puts Obj.foo(1)
- puts Obj.foo(1, 2)
- puts Obj.foo(1, 2, 3)
- puts Obj.bar(1)
- puts Obj.bar(1, 2)
- puts Obj.middle(1)
- puts Obj.skip
- puts Obj.skip(1)
- Obj.GetHashCode
- "), @"
- NewFoo: 1
- OverriddenFoo: 1, 2
- Foo: 1, 2, 3
- Bar: 1
- Bar: 1, 2
- Middle: 1
- Skip
- Skip: 1
- ");
- AssertOutput(() => CompilerTest(@"
- p Obj.method(:foo)
- p Obj.method(:bar)
- p Obj.method(:middle)
- p Obj.method(:skip)
- "), @"
- #<Method: *C#foo>
- #<Method: *C#bar>
- #<Method: *C(*B)#middle>
- #<Method: *C#skip>
- ", OutputFlags.Match);
- // hides Hidden method when called using mangled name "hidden":
- Context.GetClass(typeof(OverloadInheritance1.B)).HideMethod("hidden");
- AssertOutput(() => CompilerTest(@"
- puts Obj.hidden(1) rescue puts 'error'
- puts Obj.Hidden(1)
- puts Obj.hidden(1, 2)
- puts Obj.Hidden(1, 2)
- "), @"
- error
- Hidden: 1
- Hidden: 1, 2
- Hidden: 1, 2
- ");
- }
- public static class OverloadInheritance2 {
- public class A { public virtual string f(int a) { return "f1"; } }
- public class B : A { }
- public class C : B { }
- public class D : C { public virtual string f(int a, int b) { return "f2"; } }
- public class E : D { }
- public class F : E { public virtual string f(int a, int b, int c, int d) { return "f4"; } }
- public class G : F { }
- public class X : B { public virtual string f(int a, int b, int c) { return "f3"; } }
- public class Y : X { }
- public static void Load(RubyContext/*!*/ context) {
- context.ObjectClass.SetConstant("A", context.GetClass(typeof(A)));
- context.ObjectClass.SetConstant("B", context.GetClass(typeof(B)));
- context.ObjectClass.SetConstant("C", context.GetClass(typeof(C)));
- context.ObjectClass.SetConstant("D", context.GetClass(typeof(D)));
- context.ObjectClass.SetConstant("E", context.GetClass(typeof(E)));
- context.ObjectClass.SetConstant("F", context.GetClass(typeof(F)));
- context.ObjectClass.SetConstant("G", context.GetClass(typeof(G)));
- context.ObjectClass.SetConstant("X", context.GetClass(typeof(X)));
- context.ObjectClass.SetConstant("Y", context.GetClass(typeof(Y)));
- }
- }
- /// <summary>
- /// Dynamic site and group caching.
- /// </summary>
- public void ClrOverloadInheritance2() {
- OverloadInheritance2.Load(Context);
- // method definition hides overloads:
- AssertOutput(() => CompilerTest(@"
- puts E.new.f(1,2) # marks D::f2 and A::f1 as used in d.s.
- class C; def f; 'f:C'; end; end # overrides A::f1 => invalidates all 'f'-groups in subtree of C
- puts E.new.f(1) rescue puts 'error' # recreates D::f2 => A::f1 not visible
- puts E.new.f(1,2) # D::f still visible => marked as used in d.s.
- "), @"
- f2
- error
- f2
- ");
- // module inclusion hides overloads:
- AssertOutput(() => CompilerTest(@"
- puts Y.new.f(1)
- module M; def f; 'f:M' end; end
- class X; include M; end # hides A::f1, but not X::f3
- puts Y.new.f(1) rescue puts 'error'
- puts Y.new.f(1,2,3)
- "), @"
- f1
- error
- f3
- ");
- }
- public void ClrOverloadInheritance3() {
- OverloadInheritance2.Load(Context);
- // method definition hides overloads:
- AssertOutput(() => CompilerTest(@"
- p D.instance_method(:f).clr_members.collect { |x| x.to_string } # creates groups in A and D that are not used in d.s.
- class B; def f; 'f:B'; end; end # hides A::f1
- p D.instance_method(:f).clr_members.collect { |x| x.to_string } # only one overload should be present in the group
- "), @"
- ['System.String f(Int32)', 'System.String f(Int32, Int32)']
- ['System.String f(Int32, Int32)']
- ");
- }
- public void ClrOverloadInheritance4() {
- OverloadInheritance2.Load(Context);
- AssertOutput(() => CompilerTest(@"
- puts D.new.f(1)
- puts D.new.f(1,2)
- class B;
- def f; 'f:B'; end
- end
- puts D.new.f(1) rescue puts 'error'
- puts D.new.f(1,2)
- class B
- remove_method :f # f not used in DS, DS needs to be invalidated though
- end
- puts D.new.f(1)
- puts D.new.f(1,2)
- "), @"
- f1
- f2
- error
- f2
- f1
- f2
- ");
- }
- /// <summary>
- /// Removing an overload barrier.
- /// </summary>
- public void ClrOverloadInheritance5() {
- OverloadInheritance2.Load(Context);
- AssertOutput(() => CompilerTest(@"
- puts E.new.f(1)
- class C; def f; 'f:C'; end; end
- E.new.f(1) rescue puts 'error'
- puts E.new.f(1,2)
- puts G.new.f(1,2,3,4) # group created after C:f barrier defined
- C.send :remove_method, :f
- puts G.new.f(1)
- puts E.new.f(1)
- "), @"
- f1
- error
- f2
- f4
- f1
- f1
- ");
- }
- /// <summary>
- /// Removing an overload barrier.
- /// </summary>
- public void ClrOverloadInheritance6() {
- OverloadInheritance2.Load(Context);
- TestOutput(@"
- class E; def f; 'f:E'; end; end;
- f = F.new
- puts f.f(1,2,3,4) # creates { f4 } group on F
- class E; remove_method(:f); end # invalidates group on F
- puts f.f(1)
- ", @"
- f4
- f1
- ");
- }
- /// <summary>
- /// Removing an overload barrier.
- /// </summary>
- public void ClrOverloadInheritance7() {
- OverloadInheritance2.Load(Context);
- TestOutput(@"
- D.new.f(1,2) # creates A: {f1} and D: {f1, f2} groups
- class E; def f; 'f:E'; end; end;
- puts F.new.f(1,2,3,4) # creates { f4 } group on F, sets E#f.InvalidateOnRemoval
- class C; def f; 'f:C'; end; end; # invalidates D group, doesn't invalidate F group as it doesn't contain any overloads from above
- class E; remove_method :f; end; # invalidates group on F
- puts F.new.f(1,2)
- puts F.new.f(1,2,3,4)
- F.new.f(1) rescue puts '!f1'
- ", @"
- f4
- f2
- f4
- !f1
- ");
- }
- public void ClrOverloadInheritance_ExtensionMethods1() {
- Runtime.LoadAssembly(Assembly.GetExecutingAssembly());
- OverloadInheritance2.Load(Context);
- TestOutput(@"
- using_clr_extensions IronRubyTests::ExtensionMethods1
- d = D.new
- puts d.f(1) # f1 on A
- puts d.f(1,2,3,4,5) # e5 on C
- puts d.f(1,2,3,4,5,6) # e6 on A
- class B; def f; end; end
- d.f(1) rescue p $! # f1 on A
- puts d.f(1,2,3,4,5) # e5 on C
- d.f(1,2,3,4,5,6) rescue p $! # e6 on A
- class B; remove_method :f; end
- puts d.f(1) # f1 on A
- puts d.f(1,2,3,4,5) # e5 on C
- puts d.f(1,2,3,4,5,6) # e6 on A
- ", @"
- f1
- e5
- e6
- #<ArgumentError: wrong number of arguments (1 for 2)>
- e5
- #<ArgumentError: wrong number of arguments (6 for 5)>
- f1
- e5
- e6
- "
- );
- }
- public void ClrOverloadInheritance_ExtensionMethods2() {
- Runtime.LoadAssembly(Assembly.GetExecutingAssembly());
- OverloadInheritance2.Load(Context);
- TestOutput(@"
- using_clr_extensions nil
- puts F.new.f(1,2,3,4,5,6,7) # no namespace
-
- using_clr_extensions IronRubyTests::ExtensionMethods1
- puts F.new.f(1,2,3,4) # same signatures => regular method is preferred
- ", @"
- e7
- f4
- "
- );
- }
- public class OverloadInheritance_ClrMembers1 {
- public class A {
- public int foo(int a) { return 1; }
- public int Foo(int a) { return 2; }
- }
- public class B : A {
- public int Foo(short a) { return 3; }
- }
- public class C : B {
- public int foo(bool a) { return 4; }
- }
- public class D : C {
- public int Foo(double a) { return 5; }
- }
- public static void Load(RubyContext/*!*/ context) {
- context.ObjectClass.SetConstant("A", context.GetClass(typeof(A)));
- context.ObjectClass.SetConstant("B", context.GetClass(typeof(B)));
- context.ObjectClass.SetConstant("C", context.GetClass(typeof(C)));
- context.ObjectClass.SetConstant("D", context.GetClass(typeof(D)));
- }
- }
- /// <summary>
- /// Method group should include methods of both casings.
- /// It might depend on the order of method calls what overloads are available otherwise.
- /// D.new.foo finds Foo and
- /// - includes [foo(double), foo(int)] into the group if C.new.foo was invoked previously
- /// - includes [Foo(bool)] into the group otherwise.
- /// </summary>
- public void ClrOverloadInheritance_ClrMembers1() {
- OverloadInheritance_ClrMembers1.Load(Context);
- TestOutput(@"
- p C.new.method(:foo).clr_members.size
- p D.new.method(:foo).clr_members.size
- p A.new.method(:foo).clr_members.size
- p B.new.method(:foo).clr_members.size
- ", @"
- 4
- 5
- 2
- 3
- ");
- TestOutput(@"
- p C.new.method(:Foo).clr_members.size
- p D.new.method(:Foo).clr_members.size
- p A.new.method(:Foo).clr_members.size
- p B.new.method(:Foo).clr_members.size
- ", @"
- 2
- 3
- 1
- 2
- ");
- // prefer overload whose name matches the call site exactly:
- TestOutput(@"
- p A.new.foo(1)
- ", @"
- 1
- ");
- }
- // TODO: CLR overloads
- // - alias/pri/pub/pro/mf/dm/generics/explicit-overload
- public class OverloadedMethods {
- public static string M1(RubyScope scope) {
- return "M1()";
- }
- public static string M1(RubyContext context, MutableString foo) {
- return "M1(String)";
- }
- public static string M1(BinaryOpStorage storage, RubyContext context, double foo) {
- return "M1(Float)";
- }
- public static string M1(int foo, MutableString bar) {
- return "M1(Fixnum, String)";
- }
- public static string M1(MutableString foo, MutableString bar) {
- return "M1(String, String)";
- }
- public static string M1(int foo, params object[] bar) {
- return "M1(Fixnum, Object*)";
- }
- public static string M1(int foo, object bar) {
- return "M1(Fixnum, Object)";
- }
- public static string M1(int foo) {
- return "M1(Fixnum)";
- }
- public static string M2(int foo) {
- return "M2(Fixnum)";
- }
- public static string M2(object foo) {
- return "M2(Object)";
- }
- public static string M2<T>(int foo) {
- return "M2<" + typeof(T).Name + ">(Fixnum)";
- }
- public static string M2<T>(object foo) {
- return "M2<" + typeof(T).Name + ">(Object)";
- }
- }
-
- public void ClrOverloadSelection1() {
- Context.ObjectClass.SetConstant("OM", Context.GetClass(typeof(OverloadedMethods)));
- AssertOutput(() => CompilerTest(@"
- m = OM.method(:M1)
- puts m.overload.call
- puts m.overload(String).call('')
- puts m.overload(Float).call(1.0)
- puts m.overload(Fixnum, String).call(1, '')
- puts m.overload(String, String).call('', '')
- puts m.overload(Fixnum, System::Array.of(Object)).call(1, 2, 3)
- puts m.overload(Fixnum, Object).call(1, 2)
- puts m.overload(Fixnum).call(1)
- "), @"
- M1()
- M1(String)
- M1(Float)
- M1(Fixnum, String)
- M1(String, String)
- M1(Fixnum, Object*)
- M1(Fixnum, Object)
- M1(Fixnum)
- "
- );
- AssertOutput(() => CompilerTest(@"
- m = OM.method(:M2)
- puts m.clr_members.size
- puts m.of.clr_members.size
- puts m.of(Object).clr_members.size
- puts m.overload(Object).clr_members.size
- puts m.of(Object).overload(Object).clr_members.size
- puts m.overload(Object).of(Object).clr_members.size
- "), @"
- 4
- 2
- 2
- 2
- 1
- 1
- "
- );
- AssertOutput(() => CompilerTest(@"
- m = OM.method(:M2)
- puts m.call(1)
- puts m.of(Float).call('')
- puts m.of(Float).overload(Fixnum).call(1)
- puts m.overload(Object).of(String).call(1)
- "), @"
- M2(Fixnum)
- M2<Double>(Object)
- M2<Double>(Fixnum)
- M2<MutableString>(Object)
- "
- );
- AssertOutput(() => CompilerTest(@"
- m = OM.method(:M2)
- m.overload(Object, String) rescue p $!
- m.overload() rescue p $!
- "), @"
- #<ArgumentError: no overload of `M2' matches given parameter types>
- #<ArgumentError: no overload of `M2' matches given parameter types>
- "
- );
- // overlods called on a Ruby method
- AssertOutput(() => CompilerTest(@"
- def foo a,b
- [a,b]
- end
- def bar a,*b
- [a,*b]
- end
- p method(:foo).overload(Object, Object).call(1,2)
- method(:foo).overload(Object) rescue p $!
- p method(:bar).overload(Object).call(1)
- p method(:bar).overload(Object, Object).call(1,2)
- p method(:bar).overload(Object, Object, Object).call(1,2,3)
- "), @"
- [1, 2]
- #<ArgumentError: no overload of `foo' matches given parameter types>
- [1]
- [1, 2]
- [1, 2, 3]
- "
- );
- // overlods called on a Ruby attribute accessor
- AssertOutput(() => CompilerTest(@"
- class C
- attr_reader :foo
- attr_writer :foo
-
- c = new
- c.foo = 1
- p instance_method(:foo).overload.bind(c).call
- instance_method(:foo=).overload(Object).bind(c).call(2)
- p c.foo
- end
- "), @"
- 1
- 2
- "
- );
- }
- public static class OverloadSelection2 {
- public class A {
- public A() {
- }
- public A(int a) {
- }
- public A(RubyClass cls, double a) {
- }
- public static int Foo() { return 1; }
- public static int Foo(RubyScope scope, BlockParam block, int a) { return 2; }
- }
- public class B : A {
- public static int Foo(double a) { return 3; }
- public static int Foo(RubyClass cls, string b) { return 4; }
- }
- public static void Load(RubyContext/*!*/ context) {
- context.ObjectClass.SetConstant("A", context.GetClass(typeof(A)));
- context.ObjectClass.SetConstant("B", context.GetClass(typeof(B)));
- }
- }
- public void ClrOverloadSelection2() {
- OverloadSelection2.Load(Context);
- // static methods:
- TestOutput(@"
- m = B.method(:foo)
- puts m.overload(Fixnum).clr_members.size # RubyScope and BlockParam are hidden
- puts m.overload(System::String) rescue p $! # RubyClass is not hidden here
- ", @"
- 1
- #<ArgumentError: no overload of `foo' matches given parameter types>
- ");
- // library methods:
- TestOutput(@"
- m = method(:print)
- puts m.arity
- puts m.overload().arity
- puts m.overload(Object).arity
- puts m.overload(System::Array[Object]).arity
- ", @"
- -1
- 0
- 1
- -1
- ");
- }
- public class ClassWithSlot1 {
- public int Foo() {
- return 1;
- }
- public override string ToString() {
- return "base";
- }
- }
- public class ClassWithNewSlot1 : ClassWithSlot1 {
- public new string ToString() {
- return "subclass";
- }
- public new int Foo() {
- return 2;
- }
- }
- public void ClrNewSlot1() {
- Context.ObjectClass.SetConstant("NewSlot", Context.GetClass(typeof(ClassWithNewSlot1)));
- Context.ObjectClass.SetConstant("Base", Context.GetClass(typeof(ClassWithSlot1)));
- TestOutput(@"
- c = NewSlot.new
- p c.to_string
- p c.clr_member(Object, :to_string).call
- p c.foo
- p c.clr_member(Base, :foo).call
- ", @"
- 'subclass'
- 'base'
- 2
- 1
- ");
- }
- #endregion
- #region Interfaces
- public class ClassWithInterfaces1 : IEnumerable {
- public IEnumerator GetEnumerator() {
- yield return 1;
- yield return 2;
- yield return 3;
- }
- }
- public interface InterfaceFoo1 {
- int Foo();
- }
- public interface InterfaceFoo2 {
- int Foo();
- int this[int i] { get; }
- event Action Evnt;
- int EvntValue { get; }
- }
- public interface InterfaceBar1 {
- int Bar();
- int Bar(int i);
- }
- public interface InterfaceBaz1 {
- int Baz();
- }
- internal class InterfaceClassBase1 {
- // inherited:
- public IEnumerator GetEnumerator() {
- yield return 1;
- …
Large files files are truncated, but you can click here to view the full file