mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
330 lines
7.2 KiB
330 lines
7.2 KiB
// Copyright (c) 2018 Daniel Grunwald |
|
// |
|
// Permission is hereby granted, free of charge, to any person obtaining a copy of this |
|
// software and associated documentation files (the "Software"), to deal in the Software |
|
// without restriction, including without limitation the rights to use, copy, modify, merge, |
|
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons |
|
// to whom the Software is furnished to do so, subject to the following conditions: |
|
// |
|
// The above copyright notice and this permission notice shall be included in all copies or |
|
// substantial portions of the Software. |
|
// |
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, |
|
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR |
|
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE |
|
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
|
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
// DEALINGS IN THE SOFTWARE. |
|
|
|
using System; |
|
using System.Collections; |
|
using System.Collections.Generic; |
|
|
|
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty |
|
{ |
|
internal class NullPropagation |
|
{ |
|
private class MyClass |
|
{ |
|
public int IntVal; |
|
public readonly int ReadonlyIntVal; |
|
public MyStruct StructField; |
|
public readonly MyStruct ReadonlyStructField; |
|
public string Text; |
|
public MyClass Field; |
|
public MyClass Property { get; set; } |
|
public MyClass this[int index] => null; |
|
public MyClass Method(int arg) |
|
{ |
|
return null; |
|
} |
|
|
|
public void Done() |
|
{ |
|
} |
|
} |
|
|
|
private struct MyStruct |
|
{ |
|
public int IntVal; |
|
public readonly int ReadonlyIntVal; |
|
public MyClass Field; |
|
public MyStruct? Property1 => null; |
|
public MyStruct Property2 => default(MyStruct); |
|
public MyStruct? this[int index] => null; |
|
public MyStruct? Method1(int arg) |
|
{ |
|
return null; |
|
} |
|
public MyStruct Method2(int arg) |
|
{ |
|
return default(MyStruct); |
|
} |
|
|
|
public void Done() |
|
{ |
|
} |
|
} |
|
|
|
private class Container<T1, T2> |
|
{ |
|
public GenericStruct<T1, T2> Other; |
|
} |
|
|
|
private struct GenericStruct<T1, T2> |
|
{ |
|
public T1 Field1; |
|
public T2 Field2; |
|
public Container<T1, T2> Other; |
|
|
|
public override string ToString() |
|
{ |
|
return "(" + Field1?.ToString() + ", " + Field2?.ToString() + ")"; |
|
} |
|
|
|
public int? GetTextLength() |
|
{ |
|
return Field1?.ToString().Length + Field2?.ToString().Length + 4; |
|
} |
|
|
|
public string Chain1() |
|
{ |
|
return Other?.Other.Other?.Other.Field1?.ToString(); |
|
} |
|
|
|
public string Chain2() |
|
{ |
|
return Other?.Other.Other?.Other.Field1?.ToString()?.GetType().Name; |
|
} |
|
|
|
public int? Test2() |
|
{ |
|
return Field1?.ToString().Length ?? 42; |
|
} |
|
|
|
public int? GetTextLengthNRE() |
|
{ |
|
return (Field1?.ToString()).Length; |
|
} |
|
} |
|
|
|
public interface ITest |
|
{ |
|
int Int(); |
|
ITest Next(); |
|
} |
|
|
|
private int GetInt() |
|
{ |
|
return 9; |
|
} |
|
|
|
private string GetString() |
|
{ |
|
return null; |
|
} |
|
|
|
private MyClass GetMyClass() |
|
{ |
|
return null; |
|
} |
|
|
|
private MyStruct? GetMyStruct() |
|
{ |
|
return null; |
|
} |
|
|
|
public string Substring() |
|
{ |
|
return GetString()?.Substring(GetInt()); |
|
} |
|
|
|
public void CallSubstringAndIgnoreResult() |
|
{ |
|
GetString()?.Substring(GetInt()); |
|
} |
|
|
|
private void Use<T>(T t) |
|
{ |
|
} |
|
|
|
public void CallDone() |
|
{ |
|
GetMyClass()?.Done(); |
|
GetMyClass()?.Field?.Done(); |
|
GetMyClass()?.Field.Done(); |
|
GetMyClass()?.Property?.Done(); |
|
GetMyClass()?.Property.Done(); |
|
GetMyClass()?.Method(GetInt())?.Done(); |
|
GetMyClass()?.Method(GetInt()).Done(); |
|
GetMyClass()?[GetInt()]?.Done(); |
|
GetMyClass()?[GetInt()].Done(); |
|
} |
|
|
|
public void CallDoneStruct() |
|
{ |
|
GetMyStruct()?.Done(); |
|
GetMyStruct()?.Field?.Done(); |
|
GetMyStruct()?.Field.Done(); |
|
GetMyStruct()?.Property1?.Done(); |
|
GetMyStruct()?.Property2.Done(); |
|
GetMyStruct()?.Method1(GetInt())?.Done(); |
|
GetMyStruct()?.Method2(GetInt()).Done(); |
|
GetMyStruct()?[GetInt()]?.Done(); |
|
} |
|
|
|
public void RequiredParentheses() |
|
{ |
|
(GetMyClass()?.Field).Done(); |
|
(GetMyClass()?.Method(GetInt())).Done(); |
|
(GetMyStruct()?.Property2)?.Done(); |
|
} |
|
|
|
public int?[] ChainsOnClass() |
|
{ |
|
return new int?[9] { |
|
GetMyClass()?.IntVal, |
|
GetMyClass()?.Field.IntVal, |
|
GetMyClass()?.Field?.IntVal, |
|
GetMyClass()?.Property.IntVal, |
|
GetMyClass()?.Property?.IntVal, |
|
GetMyClass()?.Method(GetInt()).IntVal, |
|
GetMyClass()?.Method(GetInt())?.IntVal, |
|
GetMyClass()?[GetInt()].IntVal, |
|
GetMyClass()?[GetInt()]?.IntVal |
|
}; |
|
} |
|
|
|
public int?[] ChainsStruct() |
|
{ |
|
return new int?[8] { |
|
GetMyStruct()?.IntVal, |
|
GetMyStruct()?.Field.IntVal, |
|
GetMyStruct()?.Field?.IntVal, |
|
GetMyStruct()?.Property2.IntVal, |
|
GetMyStruct()?.Property1?.IntVal, |
|
GetMyStruct()?.Method2(GetInt()).IntVal, |
|
GetMyStruct()?.Method1(GetInt())?.IntVal, |
|
GetMyStruct()?[GetInt()]?.IntVal |
|
}; |
|
} |
|
|
|
public int CoalescingReturn() |
|
{ |
|
return GetMyClass()?.IntVal ?? 1; |
|
} |
|
|
|
public void Coalescing() |
|
{ |
|
Use(GetMyClass()?.IntVal ?? 1); |
|
} |
|
|
|
public void CoalescingString() |
|
{ |
|
Use(GetMyClass()?.Text ?? "Hello"); |
|
} |
|
|
|
public void CallOnValueTypeField() |
|
{ |
|
Use(GetMyClass()?.IntVal.ToString()); |
|
Use(GetMyStruct()?.IntVal.ToString()); |
|
Use(GetMyClass()?.ReadonlyIntVal.ToString()); |
|
Use(GetMyStruct()?.ReadonlyIntVal.ToString()); |
|
GetMyClass()?.StructField.Done(); |
|
GetMyClass()?.ReadonlyStructField.Done(); |
|
} |
|
|
|
public void InvokeDelegate(EventHandler eh) |
|
{ |
|
eh?.Invoke(null, EventArgs.Empty); |
|
} |
|
|
|
public int? InvokeDelegate(Func<int> f) |
|
{ |
|
return f?.Invoke(); |
|
} |
|
|
|
private void NotNullPropagation(MyClass c) |
|
{ |
|
// don't decompile this to "(c?.IntVal ?? 0) != 0" |
|
if (c != null && c.IntVal != 0) |
|
{ |
|
Console.WriteLine("non-zero"); |
|
} |
|
if (c == null || c.IntVal == 0) |
|
{ |
|
Console.WriteLine("null or zero"); |
|
} |
|
Console.WriteLine("end of method"); |
|
} |
|
|
|
private void Setter(MyClass c) |
|
{ |
|
if (c != null) |
|
{ |
|
c.IntVal = 1; |
|
} |
|
Console.WriteLine(); |
|
if (c != null) |
|
{ |
|
c.Property = null; |
|
} |
|
} |
|
|
|
private static int? GenericUnconstrainedInt<T>(T t) where T : ITest |
|
{ |
|
return t?.Int(); |
|
} |
|
|
|
private static int? GenericClassConstraintInt<T>(T t) where T : class, ITest |
|
{ |
|
return t?.Int(); |
|
} |
|
|
|
private static int? GenericStructConstraintInt<T>(T? t) where T : struct, ITest |
|
{ |
|
return t?.Int(); |
|
} |
|
|
|
private static int? GenericRefUnconstrainedInt<T>(ref T t) where T : ITest |
|
{ |
|
return t?.Int(); |
|
} |
|
|
|
private static int? GenericRefClassConstraintInt<T>(ref T t) where T : class, ITest |
|
{ |
|
return t?.Int(); |
|
} |
|
|
|
private static int? GenericRefStructConstraintInt<T>(ref T? t) where T : struct, ITest |
|
{ |
|
return t?.Int(); |
|
} |
|
|
|
public int? Issue1709(object obj) |
|
{ |
|
return (obj as ICollection)?.Count + (obj as ICollection<int>)?.Count; |
|
} |
|
|
|
private static void Issue1689(List<byte[]> setsOfNumbers) |
|
{ |
|
Console.WriteLine(setsOfNumbers?[0]?[1].ToString() == "2"); |
|
Console.WriteLine(setsOfNumbers?[1]?[1].ToString() == null); |
|
} |
|
|
|
private static dynamic DynamicNullProp(dynamic a) |
|
{ |
|
return a?.b.c(1)?.d[10]; |
|
} |
|
|
|
private static string Issue3181() |
|
{ |
|
#if EXPECTED_OUTPUT |
|
return ((int?)null)?.ToString(); |
|
#else |
|
int? x = null; |
|
return x?.ToString(); |
|
#endif |
|
} |
|
} |
|
}
|
|
|