Browse Source

Remove ToTypeReference: Implement ParseReflectionName with SRM TypeName.

pull/3532/head
Siegfried Pammer 5 months ago
parent
commit
c642678f7f
  1. 71
      ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs
  2. 7
      ICSharpCode.Decompiler.Tests/Semantics/ExplicitConversionTest.cs
  3. 49
      ICSharpCode.Decompiler.Tests/TypeSystem/ReflectionHelperTests.cs
  4. 40
      ICSharpCode.Decompiler/CSharp/Syntax/AstType.cs
  5. 27
      ICSharpCode.Decompiler/CSharp/Syntax/ComposedType.cs
  6. 10
      ICSharpCode.Decompiler/CSharp/Syntax/FunctionPointerAstType.cs
  7. 11
      ICSharpCode.Decompiler/CSharp/Syntax/InvocationAstType.cs
  8. 37
      ICSharpCode.Decompiler/CSharp/Syntax/MemberType.cs
  9. 17
      ICSharpCode.Decompiler/CSharp/Syntax/PrimitiveType.cs
  10. 28
      ICSharpCode.Decompiler/CSharp/Syntax/SimpleType.cs
  11. 14
      ICSharpCode.Decompiler/CSharp/Syntax/TupleAstType.cs
  12. 232
      ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs
  13. 20
      ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs

71
ICSharpCode.Decompiler.Tests/Semantics/ConversionTests.cs

@ -33,14 +33,33 @@ namespace ICSharpCode.Decompiler.Tests.Semantics @@ -33,14 +33,33 @@ namespace ICSharpCode.Decompiler.Tests.Semantics
{
// assign short names to the fake reflection types
using C = Conversion;
using dynamic = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.Dynamic;
using nint = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.NInt;
using nuint = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.NUInt;
using Null = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.Null;
using dynamic = ConversionTest.Dynamic;
using nint = ConversionTest.NInt;
using nuint = ConversionTest.NUInt;
[TestFixture, Parallelizable(ParallelScope.All)]
public unsafe class ConversionTest
{
/// <summary>
/// A reflection class used to represent <c>null</c>.
/// </summary>
public sealed class Null { }
/// <summary>
/// A reflection class used to represent <c>dynamic</c>.
/// </summary>
public sealed class Dynamic { }
/// <summary>
/// A reflection class used to represent <c>nint</c>.
/// </summary>
public sealed class NInt { }
/// <summary>
/// A reflection class used to represent <c>nuint</c>.
/// </summary>
public sealed class NUInt { }
CSharpConversions conversions;
ICompilation compilation;
@ -53,17 +72,37 @@ namespace ICSharpCode.Decompiler.Tests.Semantics @@ -53,17 +72,37 @@ namespace ICSharpCode.Decompiler.Tests.Semantics
conversions = new CSharpConversions(compilation);
}
public class ReplaceSpecialTypesVisitor : TypeVisitor
{
public override IType VisitTypeDefinition(ITypeDefinition type)
{
switch (type.FullName)
{
case "ICSharpCode.Decompiler.Tests.Semantics.ConversionTest.Dynamic":
return SpecialType.Dynamic;
case "ICSharpCode.Decompiler.Tests.Semantics.ConversionTest.Null":
return SpecialType.NullType;
case "ICSharpCode.Decompiler.Tests.Semantics.ConversionTest.NInt":
return SpecialType.NInt;
case "ICSharpCode.Decompiler.Tests.Semantics.ConversionTest.NUInt":
return SpecialType.NUInt;
default:
return base.VisitTypeDefinition(type);
}
}
}
Conversion ImplicitConversion(Type from, Type to)
{
IType from2 = compilation.FindType(from);
IType to2 = compilation.FindType(to);
IType from2 = compilation.FindType(from).AcceptVisitor(new ReplaceSpecialTypesVisitor());
IType to2 = compilation.FindType(to).AcceptVisitor(new ReplaceSpecialTypesVisitor());
return conversions.ImplicitConversion(from2, to2);
}
Conversion ExplicitConversion(Type from, Type to)
{
IType from2 = compilation.FindType(from);
IType to2 = compilation.FindType(to);
IType from2 = compilation.FindType(from).AcceptVisitor(new ReplaceSpecialTypesVisitor());
IType to2 = compilation.FindType(to).AcceptVisitor(new ReplaceSpecialTypesVisitor());
return conversions.ExplicitConversion(from2, to2);
}
@ -509,9 +548,9 @@ namespace ICSharpCode.Decompiler.Tests.Semantics @@ -509,9 +548,9 @@ namespace ICSharpCode.Decompiler.Tests.Semantics
bool IntegerLiteralConversion(object value, Type to)
{
IType fromType = compilation.FindType(value.GetType());
IType fromType = compilation.FindType(value.GetType()).AcceptVisitor(new ReplaceSpecialTypesVisitor());
ConstantResolveResult crr = new ConstantResolveResult(fromType, value);
IType to2 = compilation.FindType(to);
IType to2 = compilation.FindType(to).AcceptVisitor(new ReplaceSpecialTypesVisitor());
return conversions.ImplicitConversion(crr, to2).IsValid;
}
@ -587,18 +626,18 @@ namespace ICSharpCode.Decompiler.Tests.Semantics @@ -587,18 +626,18 @@ namespace ICSharpCode.Decompiler.Tests.Semantics
int BetterConversion(Type s, Type t1, Type t2)
{
IType sType = compilation.FindType(s);
IType t1Type = compilation.FindType(t1);
IType t2Type = compilation.FindType(t2);
IType sType = compilation.FindType(s).AcceptVisitor(new ReplaceSpecialTypesVisitor());
IType t1Type = compilation.FindType(t1).AcceptVisitor(new ReplaceSpecialTypesVisitor());
IType t2Type = compilation.FindType(t2).AcceptVisitor(new ReplaceSpecialTypesVisitor());
return conversions.BetterConversion(sType, t1Type, t2Type);
}
int BetterConversion(object value, Type t1, Type t2)
{
IType fromType = compilation.FindType(value.GetType());
IType fromType = compilation.FindType(value.GetType()).AcceptVisitor(new ReplaceSpecialTypesVisitor());
ConstantResolveResult crr = new ConstantResolveResult(fromType, value);
IType t1Type = compilation.FindType(t1);
IType t2Type = compilation.FindType(t2);
IType t1Type = compilation.FindType(t1).AcceptVisitor(new ReplaceSpecialTypesVisitor());
IType t2Type = compilation.FindType(t2).AcceptVisitor(new ReplaceSpecialTypesVisitor());
return conversions.BetterConversion(crr, t1Type, t2Type);
}

7
ICSharpCode.Decompiler.Tests/Semantics/ExplicitConversionTest.cs

@ -18,7 +18,6 @@ @@ -18,7 +18,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.Semantics;
@ -31,7 +30,7 @@ using NUnit.Framework; @@ -31,7 +30,7 @@ using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests.Semantics
{
using C = Conversion;
using dynamic = ICSharpCode.Decompiler.TypeSystem.ReflectionHelper.Dynamic;
using dynamic = ConversionTest.Dynamic;
[TestFixture, Parallelizable(ParallelScope.All)]
public class ExplicitConversionsTest
@ -50,8 +49,8 @@ namespace ICSharpCode.Decompiler.Tests.Semantics @@ -50,8 +49,8 @@ namespace ICSharpCode.Decompiler.Tests.Semantics
Conversion ExplicitConversion(Type from, Type to)
{
IType from2 = compilation.FindType(from);
IType to2 = compilation.FindType(to);
IType from2 = compilation.FindType(from).AcceptVisitor(new ConversionTest.ReplaceSpecialTypesVisitor());
IType to2 = compilation.FindType(to).AcceptVisitor(new ConversionTest.ReplaceSpecialTypesVisitor());
return conversions.ExplicitConversion(from2, to2);
}

49
ICSharpCode.Decompiler.Tests/TypeSystem/ReflectionHelperTests.cs

@ -19,7 +19,6 @@ @@ -19,7 +19,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
@ -71,20 +70,20 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -71,20 +70,20 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
}
[Test]
public void TestToTypeReferenceInnerClass()
public void TestFindTypeReflectionNameInnerClass()
{
Assert.That(compilation.FindType(typeof(Environment.SpecialFolder)).ReflectionName, Is.EqualTo("System.Environment+SpecialFolder"));
}
[Test]
public void TestToTypeReferenceUnboundGenericClass()
public void TestFindTypeReflectionNameUnboundGenericClass()
{
Assert.That(compilation.FindType(typeof(Action<>)).ReflectionName, Is.EqualTo("System.Action`1"));
Assert.That(compilation.FindType(typeof(Action<,>)).ReflectionName, Is.EqualTo("System.Action`2"));
}
[Test]
public void TestToTypeReferenceBoundGenericClass()
public void TestFindTypeReflectionNameBoundGenericClass()
{
Assert.That(compilation.FindType(typeof(Action<string>)).ReflectionName, Is.EqualTo("System.Action`1[[System.String]]"));
Assert.That(compilation.FindType(typeof(Action<int, short>)).ReflectionName, Is.EqualTo("System.Action`2[[System.Int32],[System.Int16]]"));
@ -92,69 +91,53 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -92,69 +91,53 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
[Test]
public void TestToTypeReferenceNullableType()
public void TestFindTypeReflectionNameNullableType()
{
Assert.That(compilation.FindType(typeof(int?)).ReflectionName, Is.EqualTo("System.Nullable`1[[System.Int32]]"));
}
[Test]
public void TestToTypeReferenceInnerClassInUnboundGenericType()
public void TestFindTypeReflectionNameInnerClassInUnboundGenericType()
{
Assert.That(compilation.FindType(typeof(Dictionary<,>.ValueCollection)).ReflectionName, Is.EqualTo("System.Collections.Generic.Dictionary`2+ValueCollection"));
}
[Test]
public void TestToTypeReferenceInnerClassInBoundGenericType()
public void TestFindTypeReflectionNameInnerClassInBoundGenericType()
{
Assert.That(compilation.FindType(typeof(Dictionary<string, int>.KeyCollection)).ReflectionName, Is.EqualTo("System.Collections.Generic.Dictionary`2+KeyCollection[[System.String],[System.Int32]]"));
}
[Test]
public void TestToTypeReferenceArrayType()
public void TestFindTypeReflectionNameArrayType()
{
Assert.That(compilation.FindType(typeof(int[])).ReflectionName, Is.EqualTo(typeof(int[]).FullName));
}
[Test]
public void TestToTypeReferenceMultidimensionalArrayType()
public void TestFindTypeReflectionNameMultidimensionalArrayType()
{
Assert.That(compilation.FindType(typeof(int[,])).ReflectionName, Is.EqualTo(typeof(int[,]).FullName));
}
[Test]
public void TestToTypeReferenceJaggedMultidimensionalArrayType()
public void TestFindTypeReflectionNameJaggedMultidimensionalArrayType()
{
Assert.That(compilation.FindType(typeof(int[,][,,])).ReflectionName, Is.EqualTo(typeof(int[,][,,]).FullName));
}
[Test]
public void TestToTypeReferencePointerType()
public void TestFindTypeReflectionNamePointerType()
{
Assert.That(compilation.FindType(typeof(int*)).ReflectionName, Is.EqualTo(typeof(int*).FullName));
}
[Test]
public void TestToTypeReferenceByReferenceType()
public void TestFindTypeReflectionNameByReferenceType()
{
Assert.That(compilation.FindType(typeof(int).MakeByRefType()).ReflectionName, Is.EqualTo(typeof(int).MakeByRefType().FullName));
}
[Test]
public void TestToTypeReferenceGenericType()
{
MethodInfo convertAllInfo = typeof(List<>).GetMethod("ConvertAll");
ITypeReference parameterType = convertAllInfo.GetParameters()[0].ParameterType.ToTypeReference(); // Converter[[`0],[``0]]
// cannot resolve generic types without knowing the parent entity:
IType resolvedWithoutEntity = parameterType.Resolve(new SimpleTypeResolveContext(compilation));
Assert.That(resolvedWithoutEntity.ReflectionName, Is.EqualTo("System.Converter`2[[`0],[``0]]"));
Assert.That(((ITypeParameter)((ParameterizedType)resolvedWithoutEntity).GetTypeArgument(0)).Owner, Is.Null);
// now try with parent entity:
IMethod convertAll = compilation.FindType(typeof(List<>)).GetMethods(m => m.Name == "ConvertAll").Single();
IType resolvedWithEntity = parameterType.Resolve(new SimpleTypeResolveContext(convertAll));
Assert.That(resolvedWithEntity.ReflectionName, Is.EqualTo("System.Converter`2[[`0],[``0]]"));
Assert.That(((ITypeParameter)((ParameterizedType)resolvedWithEntity).GetTypeArgument(0)).Owner, Is.SameAs(convertAll.DeclaringTypeDefinition));
}
[Test]
public void ParseReflectionName()
{
@ -204,21 +187,21 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -204,21 +187,21 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
public void ParseInvalidReflectionName2()
{
var context = new SimpleTypeResolveContext(compilation.MainModule);
Assert.Throws<ReflectionNameParseException>(() => ReflectionHelper.ParseReflectionName("`", context));
Assert.That(ReflectionHelper.ParseReflectionName("`", context).ReflectionName, Is.EqualTo("`"));
}
[Test]
public void ParseInvalidReflectionName3()
{
var context = new SimpleTypeResolveContext(compilation.MainModule);
Assert.Throws<ReflectionNameParseException>(() => ReflectionHelper.ParseReflectionName("``", context));
Assert.That(ReflectionHelper.ParseReflectionName("``", context).ReflectionName, Is.EqualTo("``"));
}
[Test]
public void ParseInvalidReflectionName4()
{
var context = new SimpleTypeResolveContext(compilation.MainModule);
Assert.Throws<ReflectionNameParseException>(() => ReflectionHelper.ParseReflectionName("System.Action`A", context));
Assert.That(ReflectionHelper.ParseReflectionName("System.Action`A", context).ReflectionName, Is.EqualTo("System.Action`A"));
}
[Test]
@ -232,7 +215,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -232,7 +215,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
public void ParseInvalidReflectionName5b()
{
var context = new SimpleTypeResolveContext(compilation.MainModule);
Assert.Throws<ReflectionNameParseException>(() => ReflectionHelper.ParseReflectionName("System.Environment+`", context));
Assert.That(ReflectionHelper.ParseReflectionName("System.Environment+`", context).ReflectionName, Is.EqualTo("System.Environment+`"));
}
[Test]
@ -246,7 +229,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem @@ -246,7 +229,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem
public void ParseInvalidReflectionName7()
{
var context = new SimpleTypeResolveContext(compilation.MainModule);
Assert.Throws<ReflectionNameParseException>(() => ReflectionHelper.ParseReflectionName("System.Int32[`]", context));
Assert.That(ReflectionHelper.ParseReflectionName("System.Int32[`]", context).ReflectionName, Is.EqualTo("System.Int32"));
}
[Test]

40
ICSharpCode.Decompiler/CSharp/Syntax/AstType.cs

@ -16,12 +16,10 @@ @@ -16,12 +16,10 @@
// 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.Generic;
using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.CSharp.Syntax
{
@ -60,11 +58,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -60,11 +58,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
return other == null || other.IsNull;
}
public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider)
{
return SpecialType.UnknownType;
}
}
#endregion
@ -102,11 +95,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -102,11 +95,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return visitor.VisitPatternPlaceholder(this, child, data);
}
public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider)
{
throw new NotSupportedException();
}
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
return child.DoMatch(other, match);
@ -137,34 +125,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -137,34 +125,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return st != null && st.Identifier == "var" && st.TypeArguments.Count == 0;
}
/// <summary>
/// Create an ITypeReference for this AstType.
/// Uses the context (ancestors of this node) to determine the correct <see cref="NameLookupMode"/>.
/// </summary>
/// <remarks>
/// The resulting type reference will read the context information from the
/// <see cref="ITypeResolveContext"/>:
/// For resolving type parameters, the CurrentTypeDefinition/CurrentMember is used.
/// For resolving simple names, the current namespace and usings from the CurrentUsingScope
/// (on CSharpTypeResolveContext only) is used.
/// </remarks>
public ITypeReference ToTypeReference(InterningProvider interningProvider = null)
{
return ToTypeReference(GetNameLookupMode(), interningProvider);
}
/// <summary>
/// Create an ITypeReference for this AstType.
/// </summary>
/// <remarks>
/// The resulting type reference will read the context information from the
/// <see cref="ITypeResolveContext"/>:
/// For resolving type parameters, the CurrentTypeDefinition/CurrentMember is used.
/// For resolving simple names, the current namespace and usings from the CurrentUsingScope
/// (on CSharpTypeResolveContext only) is used.
/// </remarks>
public abstract ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider = null);
/// <summary>
/// Gets the name lookup mode from the context (looking at the ancestors of this <see cref="AstType"/>).
/// </summary>

27
ICSharpCode.Decompiler/CSharp/Syntax/ComposedType.cs

@ -29,8 +29,6 @@ using System.Linq; @@ -29,8 +29,6 @@ using System.Linq;
using System.Text;
using ICSharpCode.Decompiler.CSharp.OutputVisitor;
using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.CSharp.Syntax
{
@ -200,31 +198,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -200,31 +198,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
this.HasRefSpecifier = true;
return this;
}
public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider = null)
{
if (interningProvider == null)
interningProvider = InterningProvider.Dummy;
ITypeReference t = this.BaseType.ToTypeReference(lookupMode, interningProvider);
if (this.HasNullableSpecifier)
{
t = interningProvider.Intern(NullableType.Create(t));
}
int pointerRank = this.PointerRank;
for (int i = 0; i < pointerRank; i++)
{
t = interningProvider.Intern(new PointerTypeReference(t));
}
foreach (var a in this.ArraySpecifiers.Reverse())
{
t = interningProvider.Intern(new ArrayTypeReference(t, a.Dimensions));
}
if (this.HasRefSpecifier)
{
t = interningProvider.Intern(new ByReferenceTypeReference(t));
}
return t;
}
}
/// <summary>

10
ICSharpCode.Decompiler/CSharp/Syntax/FunctionPointerAstType.cs

@ -24,11 +24,6 @@ @@ -24,11 +24,6 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
using System;
using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.CSharp.Syntax
{
public class FunctionPointerAstType : AstType
@ -73,10 +68,5 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -73,10 +68,5 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
&& this.Parameters.DoMatch(o.Parameters, match)
&& this.ReturnType.DoMatch(o.ReturnType, match);
}
public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider = null)
{
throw new NotImplementedException();
}
}
}

11
ICSharpCode.Decompiler/CSharp/Syntax/InvocationAstType.cs

@ -16,13 +16,7 @@ @@ -16,13 +16,7 @@
// 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.Generic;
using System.Text;
using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.CSharp.Syntax
{
@ -61,10 +55,5 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -61,10 +55,5 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
&& this.BaseType.DoMatch(o.BaseType, match)
&& this.Arguments.DoMatch(o.Arguments, match);
}
public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider = null)
{
throw new NotImplementedException();
}
}
}

37
ICSharpCode.Decompiler/CSharp/Syntax/MemberType.cs

@ -26,10 +26,6 @@ @@ -26,10 +26,6 @@
using System.Collections.Generic;
using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.CSharp.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.CSharp.Syntax
{
public class MemberType : AstType
@ -119,39 +115,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -119,39 +115,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
&& MatchString(this.MemberName, o.MemberName) && this.Target.DoMatch(o.Target, match)
&& this.TypeArguments.DoMatch(o.TypeArguments, match);
}
public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider = null)
{
if (interningProvider == null)
interningProvider = InterningProvider.Dummy;
TypeOrNamespaceReference t;
if (this.IsDoubleColon)
{
SimpleType st = this.Target as SimpleType;
if (st != null)
{
t = interningProvider.Intern(new AliasNamespaceReference(interningProvider.Intern(st.Identifier)));
}
else
{
t = null;
}
}
else
{
t = this.Target.ToTypeReference(lookupMode, interningProvider) as TypeOrNamespaceReference;
}
if (t == null)
return SpecialType.UnknownType;
var typeArguments = new List<ITypeReference>();
foreach (var ta in this.TypeArguments)
{
typeArguments.Add(ta.ToTypeReference(lookupMode, interningProvider));
}
string memberName = interningProvider.Intern(this.MemberName);
return interningProvider.Intern(new MemberTypeOrNamespaceReference(t, memberName, interningProvider.InternList(typeArguments), lookupMode));
}
}
}

17
ICSharpCode.Decompiler/CSharp/Syntax/PrimitiveType.cs

@ -27,9 +27,7 @@ @@ -27,9 +27,7 @@
using System;
using ICSharpCode.Decompiler.CSharp.OutputVisitor;
using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
namespace ICSharpCode.Decompiler.CSharp.Syntax
{
@ -111,21 +109,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -111,21 +109,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return Keyword;
}
public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider = null)
{
KnownTypeCode typeCode = GetTypeCodeForPrimitiveType(this.Keyword);
if (typeCode == KnownTypeCode.None)
{
if (this.Keyword == "__arglist")
return SpecialType.ArgList;
return new UnknownType(null, this.Keyword);
}
else
{
return KnownTypeReference.Get(typeCode);
}
}
public static KnownTypeCode GetTypeCodeForPrimitiveType(string keyword)
{
switch (keyword)

28
ICSharpCode.Decompiler/CSharp/Syntax/SimpleType.cs

@ -26,10 +26,6 @@ @@ -26,10 +26,6 @@
using System.Collections.Generic;
using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.CSharp.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.CSharp.Syntax
{
public class SimpleType : AstType
@ -64,11 +60,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -64,11 +60,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
{
return other == null || other.IsNull;
}
public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider)
{
return SpecialType.UnknownType;
}
}
#endregion
@ -146,25 +137,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -146,25 +137,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
SimpleType o = other as SimpleType;
return o != null && MatchString(this.Identifier, o.Identifier) && this.TypeArguments.DoMatch(o.TypeArguments, match);
}
public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider = null)
{
if (interningProvider == null)
interningProvider = InterningProvider.Dummy;
var typeArguments = new List<ITypeReference>();
foreach (var ta in this.TypeArguments)
{
typeArguments.Add(ta.ToTypeReference(lookupMode, interningProvider));
}
string identifier = interningProvider.Intern(this.Identifier);
if (typeArguments.Count == 0 && string.IsNullOrEmpty(identifier))
{
// empty SimpleType is used for typeof(List<>).
return SpecialType.UnboundTypeArgument;
}
var t = new SimpleTypeOrNamespaceReference(identifier, interningProvider.InternList(typeArguments), lookupMode);
return interningProvider.Intern(t);
}
}
}

14
ICSharpCode.Decompiler/CSharp/Syntax/TupleAstType.cs

@ -16,13 +16,7 @@ @@ -16,13 +16,7 @@
// 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.Immutable;
using System.Linq;
using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.CSharp.Syntax
{
@ -49,14 +43,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -49,14 +43,6 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
return visitor.VisitTupleType(this, data);
}
public override ITypeReference ToTypeReference(NameLookupMode lookupMode, InterningProvider interningProvider = null)
{
return new TupleTypeReference(
this.Elements.Select(e => e.Type.ToTypeReference(lookupMode, interningProvider)).ToImmutableArray(),
this.Elements.Select(e => e.Name).ToImmutableArray()
);
}
protected internal override bool DoMatch(AstNode other, Match match)
{
return other is TupleAstType o && Elements.DoMatch(o.Elements, match);

232
ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs

@ -18,6 +18,8 @@ @@ -18,6 +18,8 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
@ -29,31 +31,6 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -29,31 +31,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary>
public static class ReflectionHelper
{
/// <summary>
/// A reflection class used to represent <c>null</c>.
/// </summary>
public sealed class Null { }
/// <summary>
/// A reflection class used to represent <c>dynamic</c>.
/// </summary>
public sealed class Dynamic { }
/// <summary>
/// A reflection class used to represent <c>nint</c>.
/// </summary>
public sealed class NInt { }
/// <summary>
/// A reflection class used to represent <c>nuint</c>.
/// </summary>
public sealed class NUInt { }
/// <summary>
/// A reflection class used to represent an unbound type argument.
/// </summary>
public sealed class UnboundTypeArgument { }
#region ICompilation.FindType
/// <summary>
/// Retrieves the specified type in this compilation.
@ -65,7 +42,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -65,7 +42,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </remarks>
public static IType FindType(this ICompilation compilation, Type type)
{
return type.ToTypeReference().Resolve(new SimpleTypeResolveContext(compilation));
return ParseReflectionName(type.AssemblyQualifiedName, new SimpleTypeResolveContext(compilation));
}
public static IType FindType(this ICompilation compilation, StackType stackType, Sign sign = Sign.None)
@ -82,88 +59,6 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -82,88 +59,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
}
#endregion
#region Type.ToTypeReference()
/// <summary>
/// Creates a reference to the specified type.
/// </summary>
/// <param name="type">The type to be converted.</param>
/// <returns>Returns the type reference.</returns>
/// <remarks>
/// If the type is open (contains type parameters '`0' or '``0'),
/// an <see cref="ITypeResolveContext"/> with the appropriate CurrentTypeDefinition/CurrentMember is required
/// to resolve the type reference.
/// For closed types, the root type resolve context for the compilation is sufficient.
/// </remarks>
public static ITypeReference ToTypeReference(this Type type)
{
if (type == null)
return SpecialType.UnknownType;
if (type.IsGenericType && !type.IsGenericTypeDefinition)
{
ITypeReference def = ToTypeReference(type.GetGenericTypeDefinition());
Type[] arguments = type.GetGenericArguments();
ITypeReference[] args = new ITypeReference[arguments.Length];
bool allUnbound = true;
for (int i = 0; i < arguments.Length; i++)
{
args[i] = ToTypeReference(arguments[i]);
allUnbound &= args[i].Equals(SpecialType.UnboundTypeArgument);
}
if (allUnbound)
return def;
else
return new ParameterizedTypeReference(def, args);
}
else if (type.IsArray)
{
return new ArrayTypeReference(ToTypeReference(type.GetElementType()), type.GetArrayRank());
}
else if (type.IsPointer)
{
return new PointerTypeReference(ToTypeReference(type.GetElementType()));
}
else if (type.IsByRef)
{
return new ByReferenceTypeReference(ToTypeReference(type.GetElementType()));
}
else if (type.IsGenericParameter)
{
if (type.DeclaringMethod != null)
{
return TypeParameterReference.Create(SymbolKind.Method, type.GenericParameterPosition);
}
else
{
return TypeParameterReference.Create(SymbolKind.TypeDefinition, type.GenericParameterPosition);
}
}
else if (type.DeclaringType != null)
{
if (type == typeof(Dynamic))
return SpecialType.Dynamic;
else if (type == typeof(NInt))
return SpecialType.NInt;
else if (type == typeof(NUInt))
return SpecialType.NUInt;
else if (type == typeof(Null))
return SpecialType.NullType;
else if (type == typeof(UnboundTypeArgument))
return SpecialType.UnboundTypeArgument;
ITypeReference baseTypeRef = ToTypeReference(type.DeclaringType);
int typeParameterCount;
string name = SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount);
return new NestedTypeReference(baseTypeRef, name, typeParameterCount);
}
else
{
IModuleReference assemblyReference = new DefaultAssemblyReference(type.Assembly.FullName);
int typeParameterCount;
string name = SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount);
return new GetClassTypeReference(assemblyReference, type.Namespace, name, typeParameterCount);
}
}
#endregion
#region SplitTypeParameterCountFromReflectionName
/// <summary>
/// Removes the ` with type parameter count from the reflection name.
@ -214,16 +109,6 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -214,16 +109,6 @@ namespace ICSharpCode.Decompiler.TypeSystem
return compilation.FindType((KnownTypeCode)typeCode);
}
/// <summary>
/// Creates a reference to the specified type.
/// </summary>
/// <param name="typeCode">The type to be converted.</param>
/// <returns>Returns the type reference.</returns>
public static ITypeReference ToTypeReference(this TypeCode typeCode)
{
return KnownTypeReference.Get((KnownTypeCode)typeCode);
}
/// <summary>
/// Gets the type code for the specified type, or TypeCode.Empty if none of the other type codes match.
/// </summary>
@ -264,11 +149,112 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -264,11 +149,112 @@ namespace ICSharpCode.Decompiler.TypeSystem
{
if (reflectionTypeName == null)
throw new ArgumentNullException(nameof(reflectionTypeName));
int pos = 0;
IType r = ParseReflectionName(reflectionTypeName, ref pos).Resolve(resolveContext);
if (pos < reflectionTypeName.Length)
throw new ReflectionNameParseException(pos, "Expected end of type name");
return r;
if (!TypeName.TryParse(reflectionTypeName.AsSpan(), out var result))
{
throw new ReflectionNameParseException(0, "Invalid type name: " + reflectionTypeName);
}
return ResolveTypeName(result, resolveContext);
}
private static IType ResolveTypeName(TypeName result, ITypeResolveContext resolveContext)
{
if (result.IsArray)
{
return new ArrayType(
resolveContext.Compilation,
ResolveTypeName(result.GetElementType(), resolveContext),
result.GetArrayRank()
);
}
else if (result.IsByRef)
{
return new ByReferenceType(
ResolveTypeName(result.GetElementType(), resolveContext)
);
}
else if (result.IsConstructedGenericType)
{
IType genericType = ResolveTypeName(result.GetGenericTypeDefinition(), resolveContext);
var genericArgs = result.GetGenericArguments();
if (genericType.TypeParameterCount == 0)
{
return genericType;
}
IType[] resolvedTypes = new IType[genericType.TypeParameterCount];
for (int i = 0; i < genericArgs.Length; i++)
{
if (i < genericArgs.Length)
resolvedTypes[i] = ResolveTypeName(genericArgs[i], resolveContext);
else
resolvedTypes[i] = SpecialType.UnknownType;
}
return new ParameterizedType(genericType, resolvedTypes);
}
else if (result.IsNested)
{
var declaringType = ResolveTypeName(result.DeclaringType, resolveContext).GetDefinition();
var plainName = SplitTypeParameterCountFromReflectionName(result.Name, out int tpc);
if (declaringType != null)
{
foreach (var type in declaringType.NestedTypes)
{
if (type.Name == plainName && type.TypeParameterCount == tpc + declaringType.TypeParameterCount)
return type;
}
}
return new UnknownType(new FullTypeName(result.FullName));
}
else if (result.IsPointer)
{
return new PointerType(
ResolveTypeName(result.GetElementType(), resolveContext)
);
}
else
{
Debug.Assert(result.IsSimple);
if (result.FullName.Length > 1 && result.FullName[0] == '`')
{
if (result.FullName.Length > 2 && result.FullName[1] == '`')
{
if (int.TryParse(result.FullName.Substring(2), out int index))
{
if (resolveContext.CurrentMember is IMethod m && index < m.TypeParameters.Count)
{
return m.TypeParameters[index];
}
return DummyTypeParameter.GetMethodTypeParameter(index);
}
}
else if (int.TryParse(result.FullName.Substring(1), out int index))
{
if (resolveContext.CurrentTypeDefinition != null && index < resolveContext.CurrentTypeDefinition.TypeParameterCount)
{
return resolveContext.CurrentTypeDefinition.TypeParameters[index];
}
return DummyTypeParameter.GetClassTypeParameter(index);
}
}
var topLevelTypeName = new TopLevelTypeName(result.FullName);
if (result.AssemblyName != null)
{
var module = resolveContext.Compilation.FindModuleByAssemblyNameInfo(result.AssemblyName);
if (module != null)
{
return (IType)module.GetTypeDefinition(topLevelTypeName) ?? new UnknownType(topLevelTypeName);
}
}
foreach (var module in resolveContext.Compilation.Modules)
{
var type = module.GetTypeDefinition(topLevelTypeName);
if (type != null)
return type;
}
return new UnknownType(topLevelTypeName);
}
}
static bool IsReflectionNameSpecialCharacter(char c)

20
ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Semantics;
@ -814,6 +815,25 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -814,6 +815,25 @@ namespace ICSharpCode.Decompiler.TypeSystem
return null;
}
public static IModule FindModuleByAssemblyNameInfo(this ICompilation compilation, AssemblyNameInfo assemblyName)
{
foreach (var module in compilation.Modules)
{
if (string.Equals(module.FullAssemblyName, assemblyName.FullName, StringComparison.OrdinalIgnoreCase))
{
return module;
}
}
foreach (var module in compilation.Modules)
{
if (string.Equals(module.Name, assemblyName.Name, StringComparison.OrdinalIgnoreCase))
{
return module;
}
}
return null;
}
/// <summary>
/// When given a generic type definition, returns the self-parameterized type
/// (i.e. the type of "this" within the type definition).

Loading…
Cancel
Save