Browse Source

Fixed bugs related to ID strings.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
ec225c160d
  1. 1
      ICSharpCode.NRefactory.ConsistencyCheck/ICSharpCode.NRefactory.ConsistencyCheck.csproj
  2. 51
      ICSharpCode.NRefactory.ConsistencyCheck/IDStringConsistencyCheck.cs
  3. 2
      ICSharpCode.NRefactory.ConsistencyCheck/Program.cs
  4. 1
      ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs
  5. 19
      ICSharpCode.NRefactory.Tests/Documentation/IDStringTests.cs
  6. 7
      ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs
  7. 2
      ICSharpCode.NRefactory/Documentation/GetPotentiallyNestedClassTypeReference.cs
  8. 6
      ICSharpCode.NRefactory/Documentation/IDStringMemberReference.cs
  9. 73
      ICSharpCode.NRefactory/Documentation/IDStringProvider.cs
  10. 2
      ICSharpCode.NRefactory/Editor/ITextSource.cs
  11. 2
      ICSharpCode.NRefactory/Editor/StringTextSource.cs
  12. 11
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs
  13. 15
      ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs

1
ICSharpCode.NRefactory.ConsistencyCheck/ICSharpCode.NRefactory.ConsistencyCheck.csproj

@ -49,6 +49,7 @@ @@ -49,6 +49,7 @@
<ItemGroup>
<Compile Include="CSharpProject.cs" />
<Compile Include="FindReferencesConsistencyCheck.cs" />
<Compile Include="IDStringConsistencyCheck.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="RandomizedOrderResolverTest.cs" />

51
ICSharpCode.NRefactory.ConsistencyCheck/IDStringConsistencyCheck.cs

@ -0,0 +1,51 @@ @@ -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);
}
}
}

2
ICSharpCode.NRefactory.ConsistencyCheck/Program.cs

@ -56,6 +56,8 @@ namespace ICSharpCode.NRefactory.ConsistencyCheck @@ -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);

1
ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs

@ -19,6 +19,7 @@ @@ -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;

19
ICSharpCode.NRefactory.Tests/Documentation/IDStringTests.cs

@ -336,5 +336,24 @@ namespace Acme @@ -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<A, B> { void Test<T>(ref T a); }
class Impl<T> : IGeneric<string[,], T> {
void IGeneric<string[,], T>.Test<X>(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));
}
}
}

7
ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs

@ -188,6 +188,13 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -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()
{

2
ICSharpCode.NRefactory/Documentation/GetPotentiallyNestedClassTypeReference.cs

@ -44,7 +44,7 @@ namespace ICSharpCode.NRefactory.Documentation @@ -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);

6
ICSharpCode.NRefactory/Documentation/IDStringMemberReference.cs

@ -26,21 +26,17 @@ namespace ICSharpCode.NRefactory.Documentation @@ -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';

73
ICSharpCode.NRefactory/Documentation/IDStringProvider.cs

@ -41,7 +41,7 @@ namespace ICSharpCode.NRefactory.Documentation @@ -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 @@ -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 @@ -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 @@ -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;
if (explicitInterfaceImpl) {
b.Append(tp.Name);
} else {
b.Append('`');
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(',');
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 {
if (explicitInterfaceImpl)
b.Append(type.FullName.Replace('.', '#'));
else
b.Append(type.FullName);
AppendTypeParameters(b, type, 0);
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 @@ -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 @@ -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 @@ -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 @@ -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,18 +280,18 @@ namespace ICSharpCode.NRefactory.Documentation @@ -264,18 +280,18 @@ 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<ITypeReference> typeArguments = new List<ITypeReference>();
int typeParameterCount;
string typeNameWithoutSuffix = ReadTypeName(typeName, ref pos, true, out typeParameterCount, typeArguments);
ITypeReference result = new GetPotentiallyNestedClassTypeReference(typeNameWithoutSuffix, typeParameterCount);
result = new GetPotentiallyNestedClassTypeReference(typeNameWithoutSuffix, typeParameterCount);
while (pos < typeName.Length && typeName[pos] == '.') {
pos++;
string nestedTypeName = ReadTypeName(typeName, ref pos, false, out typeParameterCount, typeArguments);
@ -284,6 +300,7 @@ namespace ICSharpCode.NRefactory.Documentation @@ -284,6 +300,7 @@ namespace ICSharpCode.NRefactory.Documentation
if (typeArguments.Count > 0) {
result = new ParameterizedTypeReference(result, typeArguments);
}
}
while (pos < typeName.Length) {
switch (typeName[pos]) {
case '[':

2
ICSharpCode.NRefactory/Editor/ITextSource.cs

@ -120,6 +120,8 @@ namespace ICSharpCode.NRefactory.Editor @@ -120,6 +120,8 @@ namespace ICSharpCode.NRefactory.Editor
/// <param name="count">Length of the area to search.</param>
/// <param name="comparisonType">String comparison to use.</param>
/// <returns>The last index where the search term was found; or -1 if no occurrence was found.</returns>
/// <remarks>The search proceeds backwards from (startIndex+count) to startIndex.
/// This is different than the meaning of the parameters on string.LastIndexOf!</remarks>
int LastIndexOf(string searchText, int startIndex, int count, StringComparison comparisonType);
/* What about:

2
ICSharpCode.NRefactory/Editor/StringTextSource.cs

@ -112,7 +112,7 @@ namespace ICSharpCode.NRefactory.Editor @@ -112,7 +112,7 @@ namespace ICSharpCode.NRefactory.Editor
/// <inheritdoc/>
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);
}
}
}

11
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultResolvedTypeDefinition.cs

@ -494,6 +494,15 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -494,6 +494,15 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
#region GetMembers()
IEnumerable<IMember> GetFilteredMembers(Predicate<IUnresolvedMember> filter)
{
for (int i = 0; i < unresolvedMembers.Count; i++) {
if (filter == null || filter(unresolvedMembers[i])) {
yield return resolvedMembers[i];
}
}
}
IEnumerable<TResolved> GetFilteredMembers<TUnresolved, TResolved>(Predicate<TUnresolved> 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 @@ -557,7 +566,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public virtual IEnumerable<IMember> GetMembers(Predicate<IUnresolvedMember> filter = null, GetMemberOptions options = GetMemberOptions.None)
{
if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) {
return GetFilteredMembers<IUnresolvedMember, IMember>(filter);
return GetFilteredMembers(filter);
} else {
return GetMembersHelper.GetMembers(this, filter, options);
}

15
ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs

@ -249,6 +249,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -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 @@ -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);
ITypeReference reference = CreateGetClassTypeReference(assemblyName, typeName, tpc);
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 @@ -289,7 +292,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
throw new ReflectionNameParseException(pos, "Unexpected end");
if (reflectionTypeName[pos] == '[') {
// it's a generic type
List<ITypeReference> typeArguments = new List<ITypeReference>(tpc);
List<ITypeReference> typeArguments = new List<ITypeReference>();
pos++;
typeArguments.Add(ParseReflectionName(reflectionTypeName, ref pos));
if (pos < reflectionTypeName.Length && reflectionTypeName[pos] == ']')

Loading…
Cancel
Save