From 33e497eb80961f0dbf923f0ebec030637de4e69e Mon Sep 17 00:00:00 2001 From: Siegfried Pammer Date: Sat, 2 Aug 2025 11:39:01 +0200 Subject: [PATCH] Refactor ParseReflectionName to return IType instead of ITypeReference --- ICSharpCode.BamlDecompiler/XamlContext.cs | 5 +- .../TypeSystem/ReflectionHelperTests.cs | 79 ++++++++++++------- .../TypeSystem/TypeSystemLoaderTests.cs | 4 +- .../TypeSystem/FullTypeName.cs | 2 +- .../TypeSystem/INamedElement.cs | 4 +- .../TypeSystem/ReflectionHelper.cs | 4 +- .../TypeSystem/TypeProvider.cs | 3 +- .../Builtin/FindTypeInAttributeDecoder.cs | 3 +- 8 files changed, 60 insertions(+), 44 deletions(-) diff --git a/ICSharpCode.BamlDecompiler/XamlContext.cs b/ICSharpCode.BamlDecompiler/XamlContext.cs index bd24cbeaf..846ee2956 100644 --- a/ICSharpCode.BamlDecompiler/XamlContext.cs +++ b/ICSharpCode.BamlDecompiler/XamlContext.cs @@ -27,10 +27,9 @@ using System.Reflection.Metadata; using System.Threading; using System.Xml.Linq; -using ICSharpCode.Decompiler.TypeSystem; - using ICSharpCode.BamlDecompiler.Baml; using ICSharpCode.BamlDecompiler.Xaml; +using ICSharpCode.Decompiler.TypeSystem; namespace ICSharpCode.BamlDecompiler { @@ -123,7 +122,7 @@ namespace ICSharpCode.BamlDecompiler { var typeRec = Baml.TypeIdMap[id]; (fullAssemblyName, assembly) = Baml.ResolveAssembly(typeRec.AssemblyId); - type = ReflectionHelper.ParseReflectionName(typeRec.TypeFullName).Resolve(new SimpleTypeResolveContext(TypeSystem)); + type = ReflectionHelper.ParseReflectionName(typeRec.TypeFullName, new SimpleTypeResolveContext(TypeSystem)); } var clrNs = type.Namespace; diff --git a/ICSharpCode.Decompiler.Tests/TypeSystem/ReflectionHelperTests.cs b/ICSharpCode.Decompiler.Tests/TypeSystem/ReflectionHelperTests.cs index 75e695964..812d5ab83 100644 --- a/ICSharpCode.Decompiler.Tests/TypeSystem/ReflectionHelperTests.cs +++ b/ICSharpCode.Decompiler.Tests/TypeSystem/ReflectionHelperTests.cs @@ -159,138 +159,157 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem public void ParseReflectionName() { var context = new SimpleTypeResolveContext(compilation.MainModule); - Assert.That(ReflectionHelper.ParseReflectionName("System.Int32").Resolve(context).ReflectionName, Is.EqualTo("System.Int32")); - Assert.That(ReflectionHelper.ParseReflectionName("System.Int32&").Resolve(context).ReflectionName, Is.EqualTo("System.Int32&")); - Assert.That(ReflectionHelper.ParseReflectionName("System.Int32*&").Resolve(context).ReflectionName, Is.EqualTo("System.Int32*&")); - Assert.That(ReflectionHelper.ParseReflectionName(typeof(int).AssemblyQualifiedName).Resolve(context).ReflectionName, Is.EqualTo("System.Int32")); - Assert.That(ReflectionHelper.ParseReflectionName("System.Action`1[[System.String]]").Resolve(context).ReflectionName, Is.EqualTo("System.Action`1[[System.String]]")); - Assert.That(ReflectionHelper.ParseReflectionName("System.Action`1[[System.String, mscorlib]]").Resolve(context).ReflectionName, Is.EqualTo("System.Action`1[[System.String]]")); - Assert.That(ReflectionHelper.ParseReflectionName(typeof(int[,][,,]).AssemblyQualifiedName).Resolve(context).ReflectionName, Is.EqualTo("System.Int32[,,][,]")); - Assert.That(ReflectionHelper.ParseReflectionName("System.Environment+SpecialFolder").Resolve(context).ReflectionName, Is.EqualTo("System.Environment+SpecialFolder")); + Assert.That(ReflectionHelper.ParseReflectionName("System.Int32", context).ReflectionName, Is.EqualTo("System.Int32")); + Assert.That(ReflectionHelper.ParseReflectionName("System.Int32&", context).ReflectionName, Is.EqualTo("System.Int32&")); + Assert.That(ReflectionHelper.ParseReflectionName("System.Int32*&", context).ReflectionName, Is.EqualTo("System.Int32*&")); + Assert.That(ReflectionHelper.ParseReflectionName(typeof(int).AssemblyQualifiedName, context).ReflectionName, Is.EqualTo("System.Int32")); + Assert.That(ReflectionHelper.ParseReflectionName("System.Action`1[[System.String]]", context).ReflectionName, Is.EqualTo("System.Action`1[[System.String]]")); + Assert.That(ReflectionHelper.ParseReflectionName("System.Action`1[[System.String, mscorlib]]", context).ReflectionName, Is.EqualTo("System.Action`1[[System.String]]")); + Assert.That(ReflectionHelper.ParseReflectionName(typeof(int[,][,,]).AssemblyQualifiedName, context).ReflectionName, Is.EqualTo("System.Int32[,,][,]")); + Assert.That(ReflectionHelper.ParseReflectionName("System.Environment+SpecialFolder", context).ReflectionName, Is.EqualTo("System.Environment+SpecialFolder")); } [Test] public void ParseOpenGenericReflectionName() { - ITypeReference typeRef = ReflectionHelper.ParseReflectionName("System.Converter`2[[`0],[``0]]"); - Assert.That(typeRef.Resolve(new SimpleTypeResolveContext(compilation.MainModule)).ReflectionName, Is.EqualTo("System.Converter`2[[`0],[``0]]")); + IType converter = ReflectionHelper.ParseReflectionName("System.Converter`2[[`0],[``0]]", new SimpleTypeResolveContext(compilation.MainModule)); + Assert.That(converter.ReflectionName, Is.EqualTo("System.Converter`2[[`0],[``0]]")); IMethod convertAll = compilation.FindType(typeof(List<>)).GetMethods(m => m.Name == "ConvertAll").Single(); - Assert.That(typeRef.Resolve(new SimpleTypeResolveContext(convertAll)).ReflectionName, Is.EqualTo("System.Converter`2[[`0],[``0]]")); + IType converter2 = ReflectionHelper.ParseReflectionName("System.Converter`2[[`0],[``0]]", new SimpleTypeResolveContext(convertAll)); + Assert.That(converter2.ReflectionName, Is.EqualTo("System.Converter`2[[`0],[``0]]")); } [Test] public void ArrayOfTypeParameter() { var context = new SimpleTypeResolveContext(compilation.MainModule); - Assert.That(ReflectionHelper.ParseReflectionName("`0[,]").Resolve(context).ReflectionName, Is.EqualTo("`0[,]")); + Assert.That(ReflectionHelper.ParseReflectionName("`0[,]", context).ReflectionName, Is.EqualTo("`0[,]")); } [Test] public void ParseNullReflectionName() { - Assert.Throws(() => ReflectionHelper.ParseReflectionName(null)); + var context = new SimpleTypeResolveContext(compilation.MainModule); + Assert.Throws(() => ReflectionHelper.ParseReflectionName(null, context)); } [Test] public void ParseInvalidReflectionName1() { - Assert.Throws(() => ReflectionHelper.ParseReflectionName(string.Empty)); + var context = new SimpleTypeResolveContext(compilation.MainModule); + Assert.Throws(() => ReflectionHelper.ParseReflectionName(string.Empty, context)); } [Test] public void ParseInvalidReflectionName2() { - Assert.Throws(() => ReflectionHelper.ParseReflectionName("`")); + var context = new SimpleTypeResolveContext(compilation.MainModule); + Assert.Throws(() => ReflectionHelper.ParseReflectionName("`", context)); } [Test] public void ParseInvalidReflectionName3() { - Assert.Throws(() => ReflectionHelper.ParseReflectionName("``")); + var context = new SimpleTypeResolveContext(compilation.MainModule); + Assert.Throws(() => ReflectionHelper.ParseReflectionName("``", context)); } [Test] public void ParseInvalidReflectionName4() { - Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Action`A")); + var context = new SimpleTypeResolveContext(compilation.MainModule); + Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Action`A", context)); } [Test] public void ParseInvalidReflectionName5() { - Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Environment+")); + var context = new SimpleTypeResolveContext(compilation.MainModule); + Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Environment+", context)); } [Test] public void ParseInvalidReflectionName5b() { - Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Environment+`")); + var context = new SimpleTypeResolveContext(compilation.MainModule); + Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Environment+`", context)); } [Test] public void ParseInvalidReflectionName6() { - Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Int32[")); + var context = new SimpleTypeResolveContext(compilation.MainModule); + Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Int32[", context)); } [Test] public void ParseInvalidReflectionName7() { - Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Int32[`]")); + var context = new SimpleTypeResolveContext(compilation.MainModule); + Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Int32[`]", context)); } [Test] public void ParseInvalidReflectionName8() { - Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Int32[,")); + var context = new SimpleTypeResolveContext(compilation.MainModule); + Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Int32[,", context)); } [Test] public void ParseInvalidReflectionName9() { - Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Int32]")); + var context = new SimpleTypeResolveContext(compilation.MainModule); + Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Int32]", context)); } [Test] public void ParseInvalidReflectionName10() { - Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Int32*a")); + var context = new SimpleTypeResolveContext(compilation.MainModule); + Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Int32*a", context)); } [Test] public void ParseInvalidReflectionName11() { - Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Action`1[[]]")); + var context = new SimpleTypeResolveContext(compilation.MainModule); + Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Action`1[[]]", context)); } [Test] public void ParseInvalidReflectionName12() { - Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Action`1[[System.Int32]a]")); + var context = new SimpleTypeResolveContext(compilation.MainModule); + Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Action`1[[System.Int32]a]", context)); } [Test] public void ParseInvalidReflectionName13() { - Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Action`1[[System.Int32],]")); + var context = new SimpleTypeResolveContext(compilation.MainModule); + Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Action`1[[System.Int32],]", context)); } [Test] public void ParseInvalidReflectionName14() { - Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Action`1[[System.Int32]")); + var context = new SimpleTypeResolveContext(compilation.MainModule); + Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Action`1[[System.Int32]", context)); } [Test] public void ParseInvalidReflectionName15() { - Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Action`1[[System.Int32")); + var context = new SimpleTypeResolveContext(compilation.MainModule); + Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Action`1[[System.Int32", context)); } [Test] public void ParseInvalidReflectionName16() { - Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Action`1[[System.Int32],[System.String")); + var context = new SimpleTypeResolveContext(compilation.MainModule); + Assert.Throws(() => ReflectionHelper.ParseReflectionName("System.Action`1[[System.Int32],[System.String", context)); } } } diff --git a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs index 94436f4d6..3f302a63e 100644 --- a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs +++ b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs @@ -1952,8 +1952,8 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem { var compilationWithSystemCore = new SimpleCompilation(SystemCore, Mscorlib); - var typeRef = ReflectionHelper.ParseReflectionName("System.Func`2, System.Core"); - ITypeDefinition c = typeRef.Resolve(new SimpleTypeResolveContext(compilationWithSystemCore)).GetDefinition(); + var type = ReflectionHelper.ParseReflectionName("System.Func`2, System.Core", new SimpleTypeResolveContext(compilationWithSystemCore)); + ITypeDefinition c = type.GetDefinition(); Assert.That(c, Is.Not.Null, "System.Func<,> not found"); Assert.That(c.ParentModule.AssemblyName, Is.EqualTo("mscorlib")); } diff --git a/ICSharpCode.Decompiler/TypeSystem/FullTypeName.cs b/ICSharpCode.Decompiler/TypeSystem/FullTypeName.cs index 36712ee64..72f01f490 100644 --- a/ICSharpCode.Decompiler/TypeSystem/FullTypeName.cs +++ b/ICSharpCode.Decompiler/TypeSystem/FullTypeName.cs @@ -78,7 +78,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Constructs a FullTypeName by parsing the given reflection name. /// Note that FullTypeName can only represent type definition names. If the reflection name /// might refer to a parameterized type or array etc., use - /// instead. + /// instead. /// /// /// Expected syntax: NamespaceName '.' TopLevelTypeName ['`'#] { '+' NestedTypeName ['`'#] } diff --git a/ICSharpCode.Decompiler/TypeSystem/INamedElement.cs b/ICSharpCode.Decompiler/TypeSystem/INamedElement.cs index 677f3c83d..29da70023 100644 --- a/ICSharpCode.Decompiler/TypeSystem/INamedElement.cs +++ b/ICSharpCode.Decompiler/TypeSystem/INamedElement.cs @@ -46,8 +46,8 @@ namespace ICSharpCode.Decompiler.TypeSystem /// Gets the full reflection name of the element. /// /// - /// For types, the reflection name can be parsed back into a ITypeReference by using - /// . + /// For types, the reflection name can be parsed back into a IType by using + /// . /// /// /// "System.Int32[]" for int[]
diff --git a/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs b/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs index df8e396f1..407bb98b5 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs @@ -260,12 +260,12 @@ namespace ICSharpCode.Decompiler.TypeSystem /// it will look in all other assemblies of the compilation. ///
/// - public static ITypeReference ParseReflectionName(string reflectionTypeName) + public static IType ParseReflectionName(string reflectionTypeName, ITypeResolveContext resolveContext) { if (reflectionTypeName == null) throw new ArgumentNullException(nameof(reflectionTypeName)); int pos = 0; - ITypeReference r = ParseReflectionName(reflectionTypeName, ref pos); + IType r = ParseReflectionName(reflectionTypeName, ref pos).Resolve(resolveContext); if (pos < reflectionTypeName.Length) throw new ReflectionNameParseException(pos, "Expected end of type name"); return r; diff --git a/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs b/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs index 39c2bcad3..1262beef9 100644 --- a/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs +++ b/ICSharpCode.Decompiler/TypeSystem/TypeProvider.cs @@ -168,8 +168,7 @@ namespace ICSharpCode.Decompiler.TypeSystem } try { - return ReflectionHelper.ParseReflectionName(name) - .Resolve(module != null ? new SimpleTypeResolveContext(module) : new SimpleTypeResolveContext(compilation)); + return ReflectionHelper.ParseReflectionName(name, module != null ? new SimpleTypeResolveContext(module) : new SimpleTypeResolveContext(compilation)); } catch (ReflectionNameParseException ex) { diff --git a/ICSharpCode.ILSpyX/Analyzers/Builtin/FindTypeInAttributeDecoder.cs b/ICSharpCode.ILSpyX/Analyzers/Builtin/FindTypeInAttributeDecoder.cs index 0b7e0f027..c4075bae2 100644 --- a/ICSharpCode.ILSpyX/Analyzers/Builtin/FindTypeInAttributeDecoder.cs +++ b/ICSharpCode.ILSpyX/Analyzers/Builtin/FindTypeInAttributeDecoder.cs @@ -112,8 +112,7 @@ namespace ICSharpCode.ILSpyX.Analyzers.Builtin } try { - IType type = ReflectionHelper.ParseReflectionName(name) - .Resolve(new SimpleTypeResolveContext(currentModule)); + IType type = ReflectionHelper.ParseReflectionName(name, new SimpleTypeResolveContext(currentModule)); return GetResultFromResolvedType(type); } catch (ReflectionNameParseException)