From ec225c160dd76cb67e0f3c25b98d0fa8683d75e0 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 18 Feb 2012 23:10:08 +0100 Subject: [PATCH] Fixed bugs related to ID strings. --- ...arpCode.NRefactory.ConsistencyCheck.csproj | 1 + .../IDStringConsistencyCheck.cs | 51 +++++++++ .../Program.cs | 2 + .../Parser/TypeSystemConvertVisitorTests.cs | 1 + .../Documentation/IDStringTests.cs | 19 ++++ .../TypeSystem/ReflectionHelperTests.cs | 7 ++ .../GetPotentiallyNestedClassTypeReference.cs | 2 +- .../Documentation/IDStringMemberReference.cs | 6 +- .../Documentation/IDStringProvider.cs | 105 ++++++++++-------- ICSharpCode.NRefactory/Editor/ITextSource.cs | 2 + .../Editor/StringTextSource.cs | 2 +- .../DefaultResolvedTypeDefinition.cs | 11 +- .../TypeSystem/ReflectionHelper.cs | 21 ++-- 13 files changed, 169 insertions(+), 61 deletions(-) create mode 100644 ICSharpCode.NRefactory.ConsistencyCheck/IDStringConsistencyCheck.cs diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/ICSharpCode.NRefactory.ConsistencyCheck.csproj b/ICSharpCode.NRefactory.ConsistencyCheck/ICSharpCode.NRefactory.ConsistencyCheck.csproj index 19a76c9595..0b17f39c13 100644 --- a/ICSharpCode.NRefactory.ConsistencyCheck/ICSharpCode.NRefactory.ConsistencyCheck.csproj +++ b/ICSharpCode.NRefactory.ConsistencyCheck/ICSharpCode.NRefactory.ConsistencyCheck.csproj @@ -49,6 +49,7 @@ + diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/IDStringConsistencyCheck.cs b/ICSharpCode.NRefactory.ConsistencyCheck/IDStringConsistencyCheck.cs new file mode 100644 index 0000000000..fd14075cb4 --- /dev/null +++ b/ICSharpCode.NRefactory.ConsistencyCheck/IDStringConsistencyCheck.cs @@ -0,0 +1,51 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// 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.Linq; +using ICSharpCode.NRefactory.Documentation; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.ConsistencyCheck +{ + public class IDStringConsistencyCheck + { + public static void Run(Solution solution) + { + foreach (var project in solution.Projects) { + var compilation = project.Compilation; + var context = compilation.TypeResolveContext; + foreach (var typeDef in compilation.MainAssembly.GetAllTypeDefinitions()) { + Check(typeDef, context); + foreach (var member in typeDef.Members) { + Check(member, context); + } + } + } + } + + static void Check(IEntity entity, ITypeResolveContext context) + { + string id = IDStringProvider.GetIDString(entity); + IEntity resolvedEntity = IDStringProvider.FindEntity(id, context); + if (resolvedEntity != entity) + throw new InvalidOperationException(id); + } + } +} diff --git a/ICSharpCode.NRefactory.ConsistencyCheck/Program.cs b/ICSharpCode.NRefactory.ConsistencyCheck/Program.cs index ba9fc950a6..cbacb31705 100644 --- a/ICSharpCode.NRefactory.ConsistencyCheck/Program.cs +++ b/ICSharpCode.NRefactory.ConsistencyCheck/Program.cs @@ -56,6 +56,8 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck solution.AllFiles.Count(), solution.Projects.Count); + using (new Timer("ID String test... ")) + IDStringConsistencyCheck.Run(solution); //RunTestOnAllFiles("Roundtripping test", RoundtripTest.RunTest); RunTestOnAllFiles("Resolver test", ResolverTest.RunTest); RunTestOnAllFiles("Resolver test (randomized order)", RandomizedOrderResolverTest.RunTest); diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs index 7dc1a3ba05..4486baa117 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs @@ -19,6 +19,7 @@ using System; using System.IO; using System.Linq; +using ICSharpCode.NRefactory.Documentation; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.TypeSystem.TestCase; diff --git a/ICSharpCode.NRefactory.Tests/Documentation/IDStringTests.cs b/ICSharpCode.NRefactory.Tests/Documentation/IDStringTests.cs index 2a2b902b05..2770bca3ac 100644 --- a/ICSharpCode.NRefactory.Tests/Documentation/IDStringTests.cs +++ b/ICSharpCode.NRefactory.Tests/Documentation/IDStringTests.cs @@ -336,5 +336,24 @@ namespace Acme Assert.AreEqual("M:System.Collections.Generic.List`1.ConvertAll``1(System.Converter{`0,``0})", IDStringProvider.GetIDString(list.Methods.Single(m => m.Name == "ConvertAll"))); } + + [Test] + public void ExplicitGenericInterfaceImplementation_IDString() + { + string program = @" +namespace xxx { +interface IGeneric { void Test(ref T a); } +class Impl : IGeneric { + void IGeneric.Test(ref X a); +} } +"; + Init(program); + ITypeDefinition impl = GetTypeDefinition("xxx", "Impl", 1); + IMethod method = impl.Methods.Single(m => m.Name == "Test"); + + Assert.AreEqual( + "M:xxx.Impl`1.xxx#IGeneric{System#String[@]@T}#Test``1(``0@)", + IDStringProvider.GetIDString(method)); + } } } diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs index f241574d27..194a15a192 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs @@ -188,6 +188,13 @@ namespace ICSharpCode.NRefactory.TypeSystem Assert.AreEqual("System.Converter`2[[`0],[``0]]", typeRef.Resolve(new SimpleTypeResolveContext(convertAll)).ReflectionName); } + [Test] + public void ArrayOfTypeParameter() + { + var context = new SimpleTypeResolveContext(compilation.MainAssembly); + Assert.AreEqual("`0[,]", ReflectionHelper.ParseReflectionName("`0[,]").Resolve(context).ReflectionName); + } + [Test, ExpectedException(typeof(ArgumentNullException))] public void ParseNullReflectionName() { diff --git a/ICSharpCode.NRefactory/Documentation/GetPotentiallyNestedClassTypeReference.cs b/ICSharpCode.NRefactory/Documentation/GetPotentiallyNestedClassTypeReference.cs index 15e9e0eba6..f0fbe3ed8d 100644 --- a/ICSharpCode.NRefactory/Documentation/GetPotentiallyNestedClassTypeReference.cs +++ b/ICSharpCode.NRefactory/Documentation/GetPotentiallyNestedClassTypeReference.cs @@ -44,7 +44,7 @@ namespace ICSharpCode.NRefactory.Documentation { string[] parts = typeName.Split('.'); var assemblies = new [] { context.CurrentAssembly, context.Compilation.MainAssembly }.Concat(context.Compilation.ReferencedAssemblies); - for (int i = parts.Length - 1; i >= 0; i++) { + for (int i = parts.Length - 1; i >= 0; i--) { string ns = string.Join(".", parts, 0, i); string name = parts[i]; int topLevelTPC = (i == parts.Length - 1 ? typeParameterCount : 0); diff --git a/ICSharpCode.NRefactory/Documentation/IDStringMemberReference.cs b/ICSharpCode.NRefactory/Documentation/IDStringMemberReference.cs index cfb2d1573f..5fffb231de 100644 --- a/ICSharpCode.NRefactory/Documentation/IDStringMemberReference.cs +++ b/ICSharpCode.NRefactory/Documentation/IDStringMemberReference.cs @@ -26,21 +26,17 @@ namespace ICSharpCode.NRefactory.Documentation { readonly ITypeReference declaringTypeReference; readonly char memberType; - readonly string memberName; readonly string memberIDString; - public IDStringMemberReference(ITypeReference declaringTypeReference, char memberType, string memberName, string memberIDString) + public IDStringMemberReference(ITypeReference declaringTypeReference, char memberType, string memberIDString) { this.declaringTypeReference = declaringTypeReference; this.memberType = memberType; - this.memberName = memberName; this.memberIDString = memberIDString; } bool CanMatch(IUnresolvedMember member) { - if (member.Name != memberName) - return false; switch (member.EntityType) { case EntityType.Field: return memberType == 'F'; diff --git a/ICSharpCode.NRefactory/Documentation/IDStringProvider.cs b/ICSharpCode.NRefactory/Documentation/IDStringProvider.cs index 096d63203b..26e7c02339 100644 --- a/ICSharpCode.NRefactory/Documentation/IDStringProvider.cs +++ b/ICSharpCode.NRefactory/Documentation/IDStringProvider.cs @@ -41,7 +41,7 @@ namespace ICSharpCode.NRefactory.Documentation switch (entity.EntityType) { case EntityType.TypeDefinition: b.Append("T:"); - AppendTypeName(b, (ITypeDefinition)entity); + AppendTypeName(b, (ITypeDefinition)entity, false); return b.ToString(); case EntityType.Field: b.Append("F:"); @@ -58,8 +58,12 @@ namespace ICSharpCode.NRefactory.Documentation break; } IMember member = (IMember)entity; - AppendTypeName(b, member.DeclaringType); + AppendTypeName(b, member.DeclaringType, false); b.Append('.'); + if (member.IsExplicitInterfaceImplementation && member.Name.IndexOf('.') < 0 && member.InterfaceImplementations.Count == 1) { + AppendTypeName(b, member.InterfaceImplementations[0].DeclaringType, true); + b.Append('#'); + } b.Append(member.Name.Replace('.', '#')); IMethod method = member as IMethod; if (method != null && method.TypeParameters.Count > 0) { @@ -72,13 +76,13 @@ namespace ICSharpCode.NRefactory.Documentation var parameters = parameterizedMember.Parameters; for (int i = 0; i < parameters.Count; i++) { if (i > 0) b.Append(','); - AppendTypeName(b, parameters[i].Type); + AppendTypeName(b, parameters[i].Type, false); } b.Append(')'); } if (member.EntityType == EntityType.Operator && (member.Name == "op_Implicit" || member.Name == "op_Explicit")) { b.Append('~'); - AppendTypeName(b, member.ReturnType); + AppendTypeName(b, member.ReturnType, false); } return b.ToString(); } @@ -90,59 +94,68 @@ namespace ICSharpCode.NRefactory.Documentation if (type == null) throw new ArgumentNullException("type"); StringBuilder b = new StringBuilder(); - AppendTypeName(b, type); + AppendTypeName(b, type, false); return b.ToString(); } - static void AppendTypeName(StringBuilder b, IType type) + static void AppendTypeName(StringBuilder b, IType type, bool explicitInterfaceImpl) { switch (type.Kind) { case TypeKind.Dynamic: - b.Append("System.Object"); + b.Append(explicitInterfaceImpl ? "System#Object" : "System.Object"); break; case TypeKind.TypeParameter: ITypeParameter tp = (ITypeParameter)type; - b.Append('`'); - if (tp.OwnerType == EntityType.Method) + if (explicitInterfaceImpl) { + b.Append(tp.Name); + } else { b.Append('`'); - b.Append(tp.Index); + if (tp.OwnerType == EntityType.Method) + b.Append('`'); + b.Append(tp.Index); + } break; case TypeKind.Array: ArrayType array = (ArrayType)type; - AppendTypeName(b, array.ElementType); + AppendTypeName(b, array.ElementType, explicitInterfaceImpl); b.Append('['); if (array.Dimensions > 1) { for (int i = 0; i < array.Dimensions; i++) { - if (i > 0) b.Append(','); - b.Append("0:"); + if (i > 0) + b.Append(explicitInterfaceImpl ? '@' : ','); + if (!explicitInterfaceImpl) + b.Append("0:"); } } b.Append(']'); break; case TypeKind.Pointer: - AppendTypeName(b, ((PointerType)type).ElementType); + AppendTypeName(b, ((PointerType)type).ElementType, explicitInterfaceImpl); b.Append('*'); break; case TypeKind.ByReference: - AppendTypeName(b, ((ByReferenceType)type).ElementType); + AppendTypeName(b, ((ByReferenceType)type).ElementType, explicitInterfaceImpl); b.Append('@'); break; default: IType declType = type.DeclaringType; if (declType != null) { - AppendTypeName(b, declType); - b.Append('.'); + AppendTypeName(b, declType, explicitInterfaceImpl); + b.Append(explicitInterfaceImpl ? '#' : '.'); b.Append(type.Name); - AppendTypeParameters(b, type, declType.TypeParameterCount); + AppendTypeParameters(b, type, declType.TypeParameterCount, explicitInterfaceImpl); } else { - b.Append(type.FullName); - AppendTypeParameters(b, type, 0); + if (explicitInterfaceImpl) + b.Append(type.FullName.Replace('.', '#')); + else + b.Append(type.FullName); + AppendTypeParameters(b, type, 0, explicitInterfaceImpl); } break; } } - static void AppendTypeParameters(StringBuilder b, IType type, int outerTypeParameterCount) + static void AppendTypeParameters(StringBuilder b, IType type, int outerTypeParameterCount, bool explicitInterfaceImpl) { int tpc = type.TypeParameterCount - outerTypeParameterCount; if (tpc > 0) { @@ -151,8 +164,9 @@ namespace ICSharpCode.NRefactory.Documentation b.Append('{'); var ta = pt.TypeArguments; for (int i = outerTypeParameterCount; i < ta.Count; i++) { - if (i > outerTypeParameterCount) b.Append(','); - AppendTypeName(b, ta[i]); + if (i > outerTypeParameterCount) + b.Append(explicitInterfaceImpl ? '@' : ','); + AppendTypeName(b, ta[i], explicitInterfaceImpl); } b.Append('}'); } else { @@ -182,7 +196,7 @@ namespace ICSharpCode.NRefactory.Documentation parenPos = memberIDString.LastIndexOf('~'); if (parenPos < 0) parenPos = memberIDString.Length; - int dotPos = memberIDString.LastIndexOf('.', 0, parenPos); + int dotPos = memberIDString.LastIndexOf('.', parenPos - 1); if (dotPos < 0) throw new ReflectionNameParseException(0, "Could not find '.' separating type name from member name"); string typeName = memberIDString.Substring(0, dotPos); @@ -190,11 +204,12 @@ namespace ICSharpCode.NRefactory.Documentation ITypeReference typeReference = ParseTypeName(typeName, ref pos); if (pos != typeName.Length) throw new ReflectionNameParseException(pos, "Expected end of type name"); - string memberName = memberIDString.Substring(dotPos + 1, parenPos - (dotPos + 1)); - int memberTypeParameterCount; - memberName = ReflectionHelper.SplitTypeParameterCountFromReflectionName(memberName, out memberTypeParameterCount); - memberName = memberName.Replace('#', '.'); - return new IDStringMemberReference(typeReference, typeChar, memberName, memberIDString); +// string memberName = memberIDString.Substring(dotPos + 1, parenPos - (dotPos + 1)); +// pos = memberName.LastIndexOf("``"); +// if (pos > 0) +// memberName = memberName.Substring(0, pos); +// memberName = memberName.Replace('#', '.'); + return new IDStringMemberReference(typeReference, typeChar, memberIDString); } #endregion @@ -255,6 +270,7 @@ namespace ICSharpCode.NRefactory.Documentation string reflectionTypeName = typeName; if (pos == typeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); + ITypeReference result; if (reflectionTypeName[pos] == '`') { // type parameter reference pos++; @@ -264,25 +280,26 @@ namespace ICSharpCode.NRefactory.Documentation // method type parameter reference pos++; int index = ReflectionHelper.ReadTypeParameterCount(reflectionTypeName, ref pos); - return new TypeParameterReference(EntityType.Method, index); + result = new TypeParameterReference(EntityType.Method, index); } else { // class type parameter reference int index = ReflectionHelper.ReadTypeParameterCount(reflectionTypeName, ref pos); - return new TypeParameterReference(EntityType.TypeDefinition, index); + result = new TypeParameterReference(EntityType.TypeDefinition, index); + } + } else { + // not a type parameter reference: read the actual type name + List typeArguments = new List(); + int typeParameterCount; + string typeNameWithoutSuffix = ReadTypeName(typeName, ref pos, true, out typeParameterCount, typeArguments); + result = new GetPotentiallyNestedClassTypeReference(typeNameWithoutSuffix, typeParameterCount); + while (pos < typeName.Length && typeName[pos] == '.') { + pos++; + string nestedTypeName = ReadTypeName(typeName, ref pos, false, out typeParameterCount, typeArguments); + result = new NestedTypeReference(result, nestedTypeName, typeParameterCount); + } + if (typeArguments.Count > 0) { + result = new ParameterizedTypeReference(result, typeArguments); } - } - // not a type parameter reference: read the actual type name - List typeArguments = new List(); - int typeParameterCount; - string typeNameWithoutSuffix = ReadTypeName(typeName, ref pos, true, out typeParameterCount, typeArguments); - ITypeReference result = new GetPotentiallyNestedClassTypeReference(typeNameWithoutSuffix, typeParameterCount); - while (pos < typeName.Length && typeName[pos] == '.') { - pos++; - string nestedTypeName = ReadTypeName(typeName, ref pos, false, out typeParameterCount, typeArguments); - result = new NestedTypeReference(result, nestedTypeName, typeParameterCount); - } - if (typeArguments.Count > 0) { - result = new ParameterizedTypeReference(result, typeArguments); } while (pos < typeName.Length) { switch (typeName[pos]) { diff --git a/ICSharpCode.NRefactory/Editor/ITextSource.cs b/ICSharpCode.NRefactory/Editor/ITextSource.cs index 2f9b37bcbb..859c3fa5a3 100644 --- a/ICSharpCode.NRefactory/Editor/ITextSource.cs +++ b/ICSharpCode.NRefactory/Editor/ITextSource.cs @@ -120,6 +120,8 @@ namespace ICSharpCode.NRefactory.Editor /// Length of the area to search. /// String comparison to use. /// The last index where the search term was found; or -1 if no occurrence was found. + /// The search proceeds backwards from (startIndex+count) to startIndex. + /// This is different than the meaning of the parameters on string.LastIndexOf! int LastIndexOf(string searchText, int startIndex, int count, StringComparison comparisonType); /* What about: diff --git a/ICSharpCode.NRefactory/Editor/StringTextSource.cs b/ICSharpCode.NRefactory/Editor/StringTextSource.cs index f54558be91..bafc74cbb1 100644 --- a/ICSharpCode.NRefactory/Editor/StringTextSource.cs +++ b/ICSharpCode.NRefactory/Editor/StringTextSource.cs @@ -112,7 +112,7 @@ namespace ICSharpCode.NRefactory.Editor /// public int LastIndexOf(string searchText, int startIndex, int count, StringComparison comparisonType) { - return text.LastIndexOf(searchText, startIndex, count, comparisonType); + return text.LastIndexOf(searchText, startIndex + count - 1, count, comparisonType); } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs index cbc02b9af7..68b99345b3 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs @@ -494,6 +494,15 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } #region GetMembers() + IEnumerable GetFilteredMembers(Predicate filter) + { + for (int i = 0; i < unresolvedMembers.Count; i++) { + if (filter == null || filter(unresolvedMembers[i])) { + yield return resolvedMembers[i]; + } + } + } + IEnumerable GetFilteredMembers(Predicate filter) where TUnresolved : class, IUnresolvedMember where TResolved : class, IMember { for (int i = 0; i < unresolvedMembers.Count; i++) { @@ -557,7 +566,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public virtual IEnumerable GetMembers(Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { - return GetFilteredMembers(filter); + return GetFilteredMembers(filter); } else { return GetMembersHelper.GetMembers(this, filter, options); } diff --git a/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs b/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs index 6039b8ca86..e95c622e89 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs @@ -249,6 +249,7 @@ namespace ICSharpCode.NRefactory.TypeSystem { if (pos == reflectionTypeName.Length) throw new ReflectionNameParseException(pos, "Unexpected end"); + ITypeReference reference; if (reflectionTypeName[pos] == '`') { // type parameter reference pos++; @@ -258,23 +259,25 @@ namespace ICSharpCode.NRefactory.TypeSystem // method type parameter reference pos++; int index = ReadTypeParameterCount(reflectionTypeName, ref pos); - return new TypeParameterReference(EntityType.Method, index); + reference = new TypeParameterReference(EntityType.Method, index); } else { // class type parameter reference int index = ReadTypeParameterCount(reflectionTypeName, ref pos); - return new TypeParameterReference(EntityType.TypeDefinition, index); + reference = new TypeParameterReference(EntityType.TypeDefinition, index); } + } else { + // not a type parameter reference: read the actual type name + int tpc; + string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); + string assemblyName = SkipAheadAndReadAssemblyName(reflectionTypeName, pos); + reference = CreateGetClassTypeReference(assemblyName, typeName, tpc); } - // not a type parameter reference: read the actual type name - int tpc; - string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); - string assemblyName = SkipAheadAndReadAssemblyName(reflectionTypeName, pos); - ITypeReference reference = CreateGetClassTypeReference(assemblyName, typeName, tpc); // read type suffixes while (pos < reflectionTypeName.Length) { switch (reflectionTypeName[pos++]) { case '+': - typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); + int tpc; + string typeName = ReadTypeName(reflectionTypeName, ref pos, out tpc); reference = new NestedTypeReference(reference, typeName, tpc); break; case '*': @@ -289,7 +292,7 @@ namespace ICSharpCode.NRefactory.TypeSystem throw new ReflectionNameParseException(pos, "Unexpected end"); if (reflectionTypeName[pos] == '[') { // it's a generic type - List typeArguments = new List(tpc); + List typeArguments = new List(); pos++; typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos)); if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']')