.NET Decompiler with support for PDB generation, ReadyToRun, Metadata (&more) - cross-platform!
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

// 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
}
}
}