Browse Source

NRefactory bug fixes:

- Use IType.Equals() instead of == operator
 - Change handling of partially parameterized types in IType.GetNestedTypes so that we don't leak type parameters from the wrong context
 - Add support for unbound types to C# resolver (e.g. in attribute arguments)
 - C# Parser: preserve variance modifier
 - Ensure all interface members are marked as 'abstract'
 - Add support for [TypeForwardedTo] and [ComImport] to CecilLoader.
newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
bb2f93a24b
  1. 10
      ICSharpCode.NRefactory.Demo/CSDemo.cs
  2. 2
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs
  3. 22
      ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs
  4. 36
      ICSharpCode.NRefactory.Tests/TypeSystem/GetMembersTests.cs
  5. 12
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs
  6. 52
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
  7. 28
      ICSharpCode.NRefactory.VB.Tests/Lexer/LexerPositionTests.cs
  8. 6
      ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs
  9. 12
      ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs
  10. 13
      ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs
  11. 4
      ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs
  12. 71
      ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs
  13. 10
      ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs
  14. 10
      ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs
  15. 6
      ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs
  16. 70
      ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs
  17. 17
      ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs
  18. 12
      ICSharpCode.NRefactory/TypeSystem/IType.cs
  19. 13
      ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs
  20. 18
      ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs
  21. 16
      ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs
  22. 29
      ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs

10
ICSharpCode.NRefactory.Demo/CSDemo.cs

@ -144,9 +144,13 @@ namespace ICSharpCode.NRefactory.Demo @@ -144,9 +144,13 @@ namespace ICSharpCode.NRefactory.Demo
{
AstNode node = e.Node.Tag as AstNode;
if (node != null) {
int startOffset = GetOffset(csharpCodeTextBox, node.StartLocation);
int endOffset = GetOffset(csharpCodeTextBox, node.EndLocation);
csharpCodeTextBox.Select(startOffset, endOffset - startOffset);
if (node.StartLocation.IsEmpty || node.EndLocation.IsEmpty) {
csharpCodeTextBox.DeselectAll();
} else {
int startOffset = GetOffset(csharpCodeTextBox, node.StartLocation);
int endOffset = GetOffset(csharpCodeTextBox, node.EndLocation);
csharpCodeTextBox.Select(startOffset, endOffset - startOffset);
}
}
}

2
ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs

@ -72,7 +72,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -72,7 +72,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
protected IType ResolveType(Type type)
{
IType t = type.ToTypeReference().Resolve(context);
if (t == SharedTypes.UnknownType)
if (SharedTypes.UnknownType.Equals(t))
throw new InvalidOperationException("Could not resolve type");
return t;
}

22
ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs

@ -5,11 +5,14 @@ using System; @@ -5,11 +5,14 @@ using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using NUnit.Framework;
namespace ICSharpCode.NRefactory.TypeSystem
{
using Unbound = ReflectionHelper.UnboundTypeArgument;
[TestFixture]
public class GetAllBaseTypesTest
{
@ -135,6 +138,25 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -135,6 +138,25 @@ namespace ICSharpCode.NRefactory.TypeSystem
GetAllBaseTypes(typeof(List<string>)));
}
[Test]
public void BaseTypesOfUnboundDictionary()
{
Assert.AreEqual(
new [] {
typeof(Dictionary<,>).FullName,
typeof(ICollection<>).FullName + "[[" + typeof(KeyValuePair<,>).FullName + "[[`0],[`1]]]]",
typeof(IDictionary<,>).FullName + "[[`0],[`1]]",
typeof(IEnumerable<>).FullName + "[[" + typeof(KeyValuePair<,>).FullName + "[[`0],[`1]]]]",
typeof(ICollection).FullName,
typeof(IDictionary).FullName,
typeof(IEnumerable).FullName,
typeof(object).FullName,
typeof(IDeserializationCallback).FullName,
typeof(ISerializable).FullName,
},
GetAllBaseTypes(typeof(Dictionary<,>)).Select(t => t.ReflectionName).ToArray());
}
[Test]
public void BaseTypeDefinitionsOfListOfString()
{

36
ICSharpCode.NRefactory.Tests/TypeSystem/GetMembersTests.cs

@ -2,6 +2,7 @@ @@ -2,6 +2,7 @@
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Linq;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using NUnit.Framework;
@ -71,5 +72,40 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -71,5 +72,40 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreEqual("System.Int32", indexer.Parameters[0].Type.Resolve(mscorlib).ReflectionName);
Assert.AreEqual("System.Int32", indexer.Parameters[1].Type.Resolve(mscorlib).ReflectionName);
}
[Test]
public void GetNestedTypesOfUnboundGenericClass()
{
ITypeDefinition dictionary = mscorlib.GetTypeDefinition(typeof(Dictionary<,>));
IType keyCollection = dictionary.GetNestedTypes(mscorlib).Single(t => t.Name == "KeyCollection");
Assert.IsTrue(keyCollection is ITypeDefinition);
}
[Test]
public void GetNestedTypesOfBoundGenericClass()
{
IType dictionary = typeof(Dictionary<string, int>).ToTypeReference().Resolve(mscorlib);
IType keyCollection = dictionary.GetNestedTypes(mscorlib).Single(t => t.Name == "KeyCollection");
Assert.AreEqual(typeof(Dictionary<string, int>.KeyCollection).ToTypeReference().Resolve(mscorlib), keyCollection);
}
[Test]
public void GetGenericNestedTypeOfBoundGenericClass()
{
// class A<X> { class B<Y> { } }
DefaultTypeDefinition a = new DefaultTypeDefinition(mscorlib, string.Empty, "A");
a.TypeParameters.Add(new DefaultTypeParameter(EntityType.TypeDefinition, 0, "X"));
DefaultTypeDefinition b = new DefaultTypeDefinition(a, "B");
b.TypeParameters.Add(a.TypeParameters[0]);
b.TypeParameters.Add(new DefaultTypeParameter(EntityType.TypeDefinition, 1, "Y"));
a.NestedTypes.Add(b);
Assert.AreSame(b, a.GetNestedTypes(mscorlib).Single());
ParameterizedType pt = new ParameterizedType(a, new [] { KnownTypeReference.String.Resolve(mscorlib) });
Assert.AreEqual("A`1+B`1[[System.String],[]]", pt.GetNestedTypes(mscorlib).Single().ReflectionName);
}
}
}

12
ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs

@ -4,10 +4,13 @@ @@ -4,10 +4,13 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
[assembly: ICSharpCode.NRefactory.TypeSystem.TestCase.TypeTestAttribute(
42, typeof(System.Action<>), typeof(IDictionary<string, IList<NUnit.Framework.TestAttribute>>))]
[assembly: TypeForwardedTo(typeof(Func<,>))]
namespace ICSharpCode.NRefactory.TypeSystem.TestCase
{
public delegate S GenericDelegate<in T, out S>(T input) where T : S where S : class;
@ -60,7 +63,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase @@ -60,7 +63,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase
}
public class Base<T> {
public class Nested {}
public class Nested<X> {}
}
public class Derived<A, B> : Base<B> {}
@ -95,4 +98,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase @@ -95,4 +98,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase
public void MethodWithOutParameter(out int x) { x = 0; }
public void MethodWithParamsArray(params object[] x) {}
}
[ComImport(), Guid("21B8916C-F28E-11D2-A473-00C04F8EF448"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IAssemblyEnum
{
[PreserveSig()]
int GetNextAssembly(uint dwFlags);
}
}

52
ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
using System;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using ICSharpCode.NRefactory.TypeSystem.TestCase;
@ -112,7 +113,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -112,7 +113,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
public void AssemblyAttribute()
{
var attributes = testCasePC.AssemblyAttributes;
var typeTest = attributes.First(a => a.AttributeType.Resolve(ctx).FullName == typeof(TypeTestAttribute).FullName);
var typeTest = attributes.Single(a => a.AttributeType.Resolve(ctx).FullName == typeof(TypeTestAttribute).FullName);
var posArgs = typeTest.GetPositionalArguments(ctx);
Assert.AreEqual(3, posArgs.Count);
// first argument is (int)42
@ -130,6 +131,17 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -130,6 +131,17 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreEqual("System.Collections.Generic.IList`1[[?]]", crt.TypeArguments[1].ReflectionName);
}
[Test]
public void TypeForwardedTo_Attribute()
{
var attributes = testCasePC.AssemblyAttributes;
var forwardAttribute = attributes.Single(a => a.AttributeType.Resolve(ctx).FullName == typeof(TypeForwardedToAttribute).FullName);
var posArgs = forwardAttribute.GetPositionalArguments(ctx);
Assert.AreEqual(1, posArgs.Count);
IType rt = (IType)posArgs[0].GetValue(ctx);
Assert.AreEqual("System.Func`2", rt.ReflectionName);
}
[Test]
public void TestClassTypeParameters()
{
@ -248,11 +260,29 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -248,11 +260,29 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreEqual(0x30, e.Fields[4].ConstantValue.GetValue(ctx));
}
[Test]
public void GetNestedTypesFromBaseClassTest()
{
ITypeDefinition d = ctx.GetTypeDefinition(typeof(Derived<,>));
IType pBase = d.BaseTypes.Single().Resolve(ctx);
Assert.AreEqual(typeof(Base<>).FullName + "[[`1]]", pBase.ReflectionName);
// Base<`1>.GetNestedTypes() = Base<`1>.Nested<>
Assert.AreEqual(new[] { typeof(Base<>.Nested<>).FullName + "[[`1],[]]" },
pBase.GetNestedTypes(ctx).Select(n => n.ReflectionName).ToArray());
// Derived<,>.GetNestedTypes() = Base<`1>.Nested<>
Assert.AreEqual(new[] { typeof(Base<>.Nested<>).FullName + "[[`1],[]]" },
d.GetNestedTypes(ctx).Select(n => n.ReflectionName).ToArray());
// This is 'leaking' the type parameter from B as is usual when retrieving any members from an unbound type.
}
[Test]
public void ParameterizedTypeGetNestedTypesFromBaseClassTest()
{
// Derived<string,int>.GetNestedTypes() = Base<int>.Nested<>
var d = typeof(Derived<string, int>).ToTypeReference().Resolve(ctx);
Assert.AreEqual(new[] { typeof(Base<>.Nested).FullName + "[[System.Int32]]" },
Assert.AreEqual(new[] { typeof(Base<>.Nested<>).FullName + "[[System.Int32],[]]" },
d.GetNestedTypes(ctx).Select(n => n.ReflectionName).ToArray());
}
@ -365,14 +395,14 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -365,14 +395,14 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.IsTrue(p.Type is ArrayTypeReference);
}
[Test, Ignore("C# Parser does not set the variance")]
[Test]
public void GenericDelegate_Variance()
{
ITypeDefinition type = ctx.GetTypeDefinition(typeof(GenericDelegate<,>));
Assert.AreEqual(VarianceModifier.Contravariant, type.TypeParameters[0].Variance);
Assert.AreEqual(VarianceModifier.Covariant, type.TypeParameters[1].Variance);
Assert.AreSame(type.TypeParameters[1], type.TypeParameters[0].Constraints[0]);
Assert.AreSame(type.TypeParameters[1], type.TypeParameters[0].Constraints[0].Resolve(ctx));
}
[Test]
@ -395,5 +425,19 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -395,5 +425,19 @@ namespace ICSharpCode.NRefactory.TypeSystem
Assert.AreEqual("System.Object", m.ReturnType.Resolve(ctx).FullName);
Assert.AreEqual("System.String", m.Parameters[0].Type.Resolve(ctx).FullName);
}
[Test]
public void ComInterfaceTest()
{
ITypeDefinition type = ctx.GetTypeDefinition(typeof(IAssemblyEnum));
// [ComImport]
Assert.AreEqual(1, type.Attributes.Count(a => a.AttributeType.Resolve(ctx).FullName == typeof(ComImportAttribute).FullName));
IMethod m = type.Methods.Single();
Assert.AreEqual("GetNextAssembly", m.Name);
Assert.AreEqual(Accessibility.Public, m.Accessibility);
Assert.IsTrue(m.IsAbstract);
Assert.IsFalse(m.IsVirtual);
}
}
}

28
ICSharpCode.NRefactory.VB.Tests/Lexer/LexerPositionTests.cs

@ -23,15 +23,15 @@ namespace ICSharpCode.NRefactory.VB.Tests.Lexer @@ -23,15 +23,15 @@ namespace ICSharpCode.NRefactory.VB.Tests.Lexer
Token t = l.NextToken();
Assert.AreEqual(Tokens.Public, t.Kind);
Assert.AreEqual(new AstLocation(1, 1), t.Location);
Assert.AreEqual(new AstLocation(7, 1), t.EndLocation);
Assert.AreEqual(new AstLocation(1, 7), t.EndLocation);
t = l.NextToken();
Assert.AreEqual(Tokens.EOL, t.Kind);
Assert.AreEqual(new AstLocation(7, 1), t.Location);
Assert.AreEqual(new AstLocation(1, 2), t.EndLocation);
Assert.AreEqual(new AstLocation(1, 7), t.Location);
Assert.AreEqual(new AstLocation(2, 1), t.EndLocation);
t = l.NextToken();
Assert.AreEqual(Tokens.Static, t.Kind);
Assert.AreEqual(new AstLocation(1, 2), t.Location);
Assert.AreEqual(new AstLocation(7, 2), t.EndLocation);
Assert.AreEqual(new AstLocation(2, 1), t.Location);
Assert.AreEqual(new AstLocation(2, 7), t.EndLocation);
}
[Test]
@ -41,15 +41,15 @@ namespace ICSharpCode.NRefactory.VB.Tests.Lexer @@ -41,15 +41,15 @@ namespace ICSharpCode.NRefactory.VB.Tests.Lexer
Token t = l.NextToken();
Assert.AreEqual(Tokens.Public, t.Kind);
Assert.AreEqual(new AstLocation(1, 1), t.Location);
Assert.AreEqual(new AstLocation(7, 1), t.EndLocation);
Assert.AreEqual(new AstLocation(1, 7), t.EndLocation);
t = l.NextToken();
Assert.AreEqual(Tokens.EOL, t.Kind);
Assert.AreEqual(new AstLocation(7, 1), t.Location);
Assert.AreEqual(new AstLocation(1, 2), t.EndLocation);
Assert.AreEqual(new AstLocation(1, 7), t.Location);
Assert.AreEqual(new AstLocation(2, 1), t.EndLocation);
t = l.NextToken();
Assert.AreEqual(Tokens.Static, t.Kind);
Assert.AreEqual(new AstLocation(1, 2), t.Location);
Assert.AreEqual(new AstLocation(7, 2), t.EndLocation);
Assert.AreEqual(new AstLocation(2, 1), t.Location);
Assert.AreEqual(new AstLocation(2, 7), t.EndLocation);
}
[Test]
@ -59,13 +59,13 @@ namespace ICSharpCode.NRefactory.VB.Tests.Lexer @@ -59,13 +59,13 @@ namespace ICSharpCode.NRefactory.VB.Tests.Lexer
l.NextToken(); // public
Token t = l.NextToken();
Assert.AreEqual(Tokens.EOL, t.Kind);
Assert.AreEqual(new AstLocation(7, 1), t.Location);
Assert.AreEqual(new AstLocation(7, 1), t.EndLocation);
Assert.AreEqual(new AstLocation(1, 7), t.Location);
Assert.AreEqual(new AstLocation(1, 7), t.EndLocation);
t = l.NextToken();
Assert.AreEqual(Tokens.EOF, t.Kind);
Assert.AreEqual(new AstLocation(7, 1), t.Location);
Assert.AreEqual(new AstLocation(7, 1), t.EndLocation);
Assert.AreEqual(new AstLocation(1, 7), t.Location);
Assert.AreEqual(new AstLocation(1, 7), t.EndLocation);
}
[Test]

6
ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// Identifier.cs
//
// Author:
@ -30,8 +30,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -30,8 +30,8 @@ namespace ICSharpCode.NRefactory.CSharp
{
public class Identifier : AstNode, IRelocatable
{
public static readonly Identifier Null = new NullIdentifier ();
class NullIdentifier : Identifier
public new static readonly Identifier Null = new NullIdentifier ();
sealed class NullIdentifier : Identifier
{
public override bool IsNull {
get {

12
ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// CSharpParser.cs
//
// Author:
@ -2158,8 +2158,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -2158,8 +2158,14 @@ namespace ICSharpCode.NRefactory.CSharp
continue;
TypeParameterDeclaration tp = new TypeParameterDeclaration();
// TODO: attributes
// if (arg.Variance != Variance.None)
// throw new NotImplementedException(); // TODO: variance
switch (arg.Variance) {
case Variance.Covariant:
tp.Variance = VarianceModifier.Covariant;
break;
case Variance.Contravariant:
tp.Variance = VarianceModifier.Contravariant;
break;
}
tp.AddChild (Identifier.Create (arg.Name, Convert (arg.Location)), InvocationExpression.Roles.Identifier);
parent.AddChild (tp, InvocationExpression.Roles.TypeParameter);
}

13
ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs

@ -589,9 +589,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -589,9 +589,10 @@ namespace ICSharpCode.NRefactory.CSharp
static void ApplyModifiers(TypeSystem.Implementation.AbstractMember m, Modifiers modifiers)
{
// members from interfaces are always Public.
// members from interfaces are always Public+Abstract.
if (m.DeclaringTypeDefinition.ClassType == ClassType.Interface) {
m.Accessibility = Accessibility.Public;
m.IsAbstract = true;
return;
}
m.Accessibility = GetAccessibility(modifiers) ?? Accessibility.Private;
@ -709,6 +710,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -709,6 +710,10 @@ namespace ICSharpCode.NRefactory.CSharp
return tp;
}
}
if (typeArguments.Count == 0 && string.IsNullOrEmpty(s.Identifier)) {
// empty SimpleType is used for typeof(List<>).
return SharedTypes.UnboundTypeArgument;
}
return new SimpleTypeOrNamespaceReference(s.Identifier, typeArguments, parentTypeDefinition, parentUsingScope, isInUsingDeclaration);
}
@ -742,7 +747,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -742,7 +747,7 @@ namespace ICSharpCode.NRefactory.CSharp
case "double":
return KnownTypeReference.Double;
case "decimal":
return ReflectionHelper.ToTypeReference(TypeCode.Decimal);
return KnownTypeReference.Decimal;
case "char":
return KnownTypeReference.Char;
case "void":
@ -943,12 +948,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -943,12 +948,10 @@ namespace ICSharpCode.NRefactory.CSharp
return new ConstantBinaryOperator(left, binaryOperatorExpression.Operator, right);
}
static readonly GetClassTypeReference systemType = new GetClassTypeReference("System", "Type", 0);
public override ConstantExpression VisitTypeOfExpression(TypeOfExpression typeOfExpression, object data)
{
if (isAttributeArgument) {
return new PrimitiveConstantExpression(systemType, convertVisitor.ConvertType(typeOfExpression.Type));
return new PrimitiveConstantExpression(KnownTypeReference.Type, convertVisitor.ConvertType(typeOfExpression.Type));
} else {
return null;
}

4
ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs

@ -111,8 +111,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -111,8 +111,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (attrType == null)
return SharedTypes.UnknownType;
if (type == SharedTypes.UnknownType || !(type.GetDefinition () != null && type.GetDefinition ().IsDerivedFrom (attrType, context)))
type = withSuffix.Resolve(context);
if (type.GetDefinition() == null || !type.GetDefinition().IsDerivedFrom(attrType, context))
type = withSuffix.Resolve(context);
return type;
}

71
ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs

@ -101,7 +101,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -101,7 +101,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
public DomRegion DeclarationRegion {
get { return region; }
get { return region; }
}
public ITypeReference Type {
@ -310,7 +310,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -310,7 +310,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
get { return true; }
}
bool IEntity.IsPrivate {
bool IEntity.IsPrivate {
get { return false; }
}
@ -375,7 +375,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -375,7 +375,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
cancellationToken.ThrowIfCancellationRequested();
if (expression.Type == SharedTypes.Dynamic)
if (SharedTypes.Dynamic.Equals(expression.Type))
return DynamicResult;
// C# 4.0 spec: §7.3.3 Unary operator overload resolution
@ -469,7 +469,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -469,7 +469,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
// C# 4.0 spec: §7.3.6.1
TypeCode code = ReflectionHelper.GetTypeCode(type);
if (isNullable && type == SharedTypes.Null)
if (isNullable && SharedTypes.Null.Equals(type))
code = TypeCode.SByte; // cause promotion of null to int32
switch (op) {
case UnaryOperatorType.Minus:
@ -626,7 +626,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -626,7 +626,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
cancellationToken.ThrowIfCancellationRequested();
if (lhs.Type == SharedTypes.Dynamic || rhs.Type == SharedTypes.Dynamic)
if (SharedTypes.Dynamic.Equals(lhs.Type) || SharedTypes.Dynamic.Equals(rhs.Type))
return DynamicResult;
// C# 4.0 spec: §7.3.4 Binary operator overload resolution
@ -656,14 +656,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -656,14 +656,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// TODO: find user-defined operators
if (lhsType == SharedTypes.Null && rhsType.IsReferenceType(context) == false
|| lhsType.IsReferenceType(context) == false && rhsType == SharedTypes.Null)
if (SharedTypes.Null.Equals(lhsType) && rhsType.IsReferenceType(context) == false
|| lhsType.IsReferenceType(context) == false && SharedTypes.Null.Equals(rhsType))
{
isNullable = true;
}
if (op == BinaryOperatorType.ShiftLeft || op == BinaryOperatorType.ShiftRight) {
// special case: the shift operators allow "var x = null << null", producing int?.
if (lhsType == SharedTypes.Null && rhsType == SharedTypes.Null)
if (SharedTypes.Null.Equals(lhsType) && SharedTypes.Null.Equals(rhsType))
isNullable = true;
// for shift operators, do unary promotion independently on both arguments
lhs = UnaryNumericPromotion(UnaryOperatorType.Plus, ref lhsType, isNullable, lhs);
@ -709,7 +709,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -709,7 +709,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} else if (rhsType is PointerType && IsInteger(ReflectionHelper.GetTypeCode(lhsType))) {
return new ResolveResult(rhsType);
}
if (lhsType == SharedTypes.Null && rhsType == SharedTypes.Null)
if (SharedTypes.Null.Equals(lhsType) && SharedTypes.Null.Equals(rhsType))
return new ErrorResolveResult(SharedTypes.Null);
}
break;
@ -737,7 +737,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -737,7 +737,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} else if (lhsType is PointerType && lhsType.Equals(rhsType)) {
return new ResolveResult(KnownTypeReference.Int64.Resolve(context));
}
if (lhsType == SharedTypes.Null && rhsType == SharedTypes.Null)
if (SharedTypes.Null.Equals(lhsType) && SharedTypes.Null.Equals(rhsType))
return new ErrorResolveResult(SharedTypes.Null);
}
break;
@ -920,10 +920,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -920,10 +920,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
TypeCode lhsCode = ReflectionHelper.GetTypeCode(NullableType.GetUnderlyingType(lhs.Type));
TypeCode rhsCode = ReflectionHelper.GetTypeCode(NullableType.GetUnderlyingType(rhs.Type));
// if one of the inputs is the null literal, promote that to the type of the other operand
if (isNullable && lhs.Type == SharedTypes.Null) {
if (isNullable && SharedTypes.Null.Equals(lhs.Type)) {
lhs = CastTo(rhsCode, isNullable, lhs, allowNullableConstants);
lhsCode = rhsCode;
} else if (isNullable && rhs.Type == SharedTypes.Null) {
} else if (isNullable && SharedTypes.Null.Equals(rhs.Type)) {
rhs = CastTo(lhsCode, isNullable, rhs, allowNullableConstants);
rhsCode = lhsCode;
}
@ -1516,10 +1516,27 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1516,10 +1516,27 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
#region ResolveSimpleName
enum SimpleNameLookupMode
{
/// <summary>
/// Normal name lookup in expressions
/// </summary>
Expression,
/// <summary>
/// Name lookup in expression, where the expression is the target of an invocation.
/// Such a lookup will only return methods and delegate-typed fields.
/// </summary>
InvocationTarget,
/// <summary>
/// Normal name lookup in type references.
/// </summary>
Type,
TypeInUsingDeclaration
/// <summary>
/// Name lookup in the type reference inside a using declaration.
/// </summary>
TypeInUsingDeclaration,
/// <summary>
/// Name lookup for unbound types "Dictionary&lt;,&gt;". Can only occur within typeof-expressions.
/// </summary>
UnboundType
}
public ResolveResult ResolveSimpleName(string identifier, IList<IType> typeArguments, bool isInvocationTarget = false)
@ -1571,6 +1588,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1571,6 +1588,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
cancellationToken.ThrowIfCancellationRequested();
int k = typeArguments.Count;
bool parameterizeResultType = k > 0;
if (parameterizeResultType) {
if (typeArguments.All(t => t.Equals(SharedTypes.UnboundTypeArgument)))
parameterizeResultType = false;
}
// look in type parameters of current method
if (k == 0) {
@ -1600,11 +1622,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1600,11 +1622,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (lookupMode == SimpleNameLookupMode.Expression || lookupMode == SimpleNameLookupMode.InvocationTarget) {
r = lookup.Lookup(t, identifier, typeArguments, lookupMode == SimpleNameLookupMode.InvocationTarget);
} else {
r = lookup.LookupType(t, identifier, typeArguments);
r = lookup.LookupType(t, identifier, typeArguments, parameterizeResultType);
}
if (!(r is UnknownMemberResolveResult)) // but do return AmbiguousMemberResolveResult
return r;
}
// look in current namespace definitions
for (UsingScope n = this.UsingScope; n != null; n = n.Parent) {
// first look for a namespace
@ -1620,7 +1643,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1620,7 +1643,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
ITypeDefinition def = context.GetTypeDefinition(n.NamespaceName, identifier, k, StringComparer.Ordinal);
if (def != null) {
IType result = def;
if (k != 0) {
if (parameterizeResultType) {
result = new ParameterizedType(def, typeArguments);
}
if (n.HasAlias(identifier))
@ -1654,10 +1677,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1654,10 +1677,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
def = context.GetTypeDefinition(ns.NamespaceName, identifier, k, StringComparer.Ordinal);
if (def != null) {
if (firstResult == null) {
if (k == 0)
firstResult = def;
else
if (parameterizeResultType)
firstResult = new ParameterizedType(def, typeArguments);
else
firstResult = def;
} else {
return new AmbiguousTypeResolveResult(firstResult);
}
@ -1727,7 +1750,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1727,7 +1750,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return ErrorResult;
}
if (target.Type == SharedTypes.Dynamic)
if (SharedTypes.Dynamic.Equals(target.Type))
return DynamicResult;
MemberLookup lookup = CreateMemberLookup();
@ -1811,7 +1834,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1811,7 +1834,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
cancellationToken.ThrowIfCancellationRequested();
if (target.Type == SharedTypes.Dynamic)
if (SharedTypes.Dynamic.Equals(target.Type))
return DynamicResult;
MethodGroupResolveResult mgrr = target as MethodGroupResolveResult;
@ -1921,7 +1944,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1921,7 +1944,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
} else {
// argument might be a lambda or delegate type, so we have to try to guess the delegate type
IType type = arguments[i].Type;
if (type == SharedTypes.Null || type == SharedTypes.UnknownType) {
if (SharedTypes.Null.Equals(type) || SharedTypes.UnknownType.Equals(type)) {
list.Add(new DefaultParameter(KnownTypeReference.Object, argumentNames[i]));
} else {
list.Add(new DefaultParameter(type, argumentNames[i]));
@ -1971,7 +1994,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -1971,7 +1994,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
{
cancellationToken.ThrowIfCancellationRequested();
if (target.Type == SharedTypes.Dynamic)
if (SharedTypes.Dynamic.Equals(target.Type))
return DynamicResult;
OverloadResolution or = new OverloadResolution(context, arguments, argumentNames, new IType[0]);
@ -2088,7 +2111,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2088,7 +2111,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
Conversions c = new Conversions(context);
bool isValid;
IType resultType;
if (trueExpression.Type == SharedTypes.Dynamic || falseExpression.Type == SharedTypes.Dynamic) {
if (SharedTypes.Dynamic.Equals(trueExpression.Type) || SharedTypes.Dynamic.Equals(falseExpression.Type)) {
resultType = SharedTypes.Dynamic;
isValid = true;
} else if (HasType(trueExpression) && HasType(falseExpression)) {
@ -2124,7 +2147,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -2124,7 +2147,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
bool HasType(ResolveResult r)
{
return r.Type != SharedTypes.UnknownType && r.Type != SharedTypes.Null;
return !(SharedTypes.UnknownType.Equals(r.Type) || SharedTypes.Null.Equals(r.Type));
}
#endregion

10
ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs

@ -191,7 +191,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -191,7 +191,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
bool NullLiteralConversion(IType fromType, IType toType)
{
// C# 4.0 spec: §6.1.5
return fromType == SharedTypes.Null && NullableType.IsNullable(toType);
return SharedTypes.Null.Equals(fromType) && NullableType.IsNullable(toType);
// This function only handles the conversion from the null literal to nullable value types,
// reference types are handled by ImplicitReferenceConversion instead.
}
@ -207,7 +207,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -207,7 +207,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return false;
// conversion from null literal is always possible
if (fromType == SharedTypes.Null)
if (SharedTypes.Null.Equals(fromType))
return true;
ArrayType fromArray = fromType as ArrayType;
@ -242,7 +242,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -242,7 +242,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
bool IsSubtypeOf(IType s, IType t)
{
// conversion to dynamic + object are always possible
if (t == SharedTypes.Dynamic || t.Equals(objectType))
if (t.Equals(SharedTypes.Dynamic) || t.Equals(objectType))
return true;
// let GetAllBaseTypes do the work for us
@ -305,7 +305,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -305,7 +305,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
bool ImplicitDynamicConversion(IType fromType, IType toType)
{
// C# 4.0 spec: §6.1.8
return fromType == SharedTypes.Dynamic;
return SharedTypes.Dynamic.Equals(fromType);
}
#endregion
@ -360,7 +360,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -360,7 +360,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
// C# 4.0 spec: §18.4 Pointer conversions
if (fromType is PointerType && toType is PointerType && toType.ReflectionName == "System.Void*")
return true;
if (fromType == SharedTypes.Null && toType is PointerType)
if (SharedTypes.Null.Equals(fromType) && toType is PointerType)
return true;
return false;
}

10
ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs

@ -107,7 +107,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -107,7 +107,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
#endregion
public ResolveResult LookupType(IType declaringType, string name, IList<IType> typeArguments)
public ResolveResult LookupType(IType declaringType, string name, IList<IType> typeArguments, bool parameterizeResultType = true)
{
int typeArgumentCount = typeArguments.Count;
Predicate<ITypeDefinition> typeFilter = delegate (ITypeDefinition d) {
@ -116,7 +116,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -116,7 +116,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
List<IType> types = declaringType.GetNestedTypes(context, typeFilter).ToList();
RemoveTypesHiddenByOtherTypes(types);
if (types.Count > 0)
return CreateTypeResolveResult(types[0], types.Count > 1, typeArguments);
return CreateTypeResolveResult(types[0], types.Count > 1, typeArguments, parameterizeResultType);
else
return new UnknownMemberResolveResult(declaringType, name, typeArguments);
}
@ -141,9 +141,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -141,9 +141,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
}
}
ResolveResult CreateTypeResolveResult(IType returnedType, bool isAmbiguous, IList<IType> typeArguments)
ResolveResult CreateTypeResolveResult(IType returnedType, bool isAmbiguous, IList<IType> typeArguments, bool parameterizeResultType)
{
if (typeArguments.Count > 0) {
if (parameterizeResultType && typeArguments.Count > 0) {
// parameterize the type if necessary
ITypeDefinition returnedTypeDef = returnedType as ITypeDefinition;
if (returnedTypeDef != null)
@ -247,7 +247,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -247,7 +247,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
if (types.Count > 0) {
bool isAmbiguous = !(types.Count == 1 && members.Count == 0);
return CreateTypeResolveResult(types[0], isAmbiguous, typeArguments);
return CreateTypeResolveResult(types[0], isAmbiguous, typeArguments, true);
}
if (members.Count == 0)
return new UnknownMemberResolveResult(type, name, typeArguments);

6
ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs

@ -885,13 +885,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -885,13 +885,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
return resolver.ResolveThisReference();
}
static readonly GetClassTypeReference systemType = new GetClassTypeReference("System", "Type", 0);
public override ResolveResult VisitTypeOfExpression(TypeOfExpression typeOfExpression, object data)
{
ScanChildren(typeOfExpression);
if (resolverEnabled)
return new ResolveResult(systemType.Resolve(resolver.Context));
return new ResolveResult(KnownTypeReference.Type.Resolve(resolver.Context));
else
return null;
}
@ -935,7 +933,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -935,7 +933,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver
resultType = SharedTypes.UnknownType;
break;
case UndocumentedExpressionType.RefType:
resultType = systemType;
resultType = KnownTypeReference.Type;
break;
case UndocumentedExpressionType.MakeRef:
resultType = typeof(TypedReference).ToTypeReference();

70
ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

@ -76,10 +76,10 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -76,10 +76,10 @@ namespace ICSharpCode.NRefactory.TypeSystem
throw new ArgumentNullException("assemblyDefinition");
ITypeResolveContext oldEarlyBindContext = this.EarlyBindContext;
try {
// Read assembly attributes
IList<IAttribute> assemblyAttributes = new List<IAttribute>();
foreach (var attr in assemblyDefinition.CustomAttributes) {
assemblyAttributes.Add(ReadAttribute(attr));
}
AddAttributes(assemblyDefinition, assemblyAttributes);
if (this.InterningProvider != null)
assemblyAttributes = this.InterningProvider.InternList(assemblyAttributes);
else
@ -357,13 +357,30 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -357,13 +357,30 @@ namespace ICSharpCode.NRefactory.TypeSystem
#endregion
#region Read Attributes
void AddAttributes(ICustomAttributeProvider customAttributeProvider, IEntity targetEntity)
#region Assembly Attributes
static readonly ITypeReference typeForwardedToAttributeTypeRef = typeof(TypeForwardedToAttribute).ToTypeReference();
void AddAttributes(AssemblyDefinition assembly, IList<IAttribute> outputList)
{
if (customAttributeProvider.HasCustomAttributes) {
AddCustomAttributes(customAttributeProvider.CustomAttributes, targetEntity.Attributes);
if (assembly.HasCustomAttributes) {
AddCustomAttributes(assembly.CustomAttributes, outputList);
}
// TypeForwardedToAttribute
foreach (ExportedType type in assembly.MainModule.ExportedTypes) {
if (type.IsForwarder) {
int typeParameterCount;
string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount);
var typeForwardedTo = new DefaultAttribute(typeForwardedToAttributeTypeRef, new[] { KnownTypeReference.Type });
var typeRef = new GetClassTypeReference(type.Namespace, name, typeParameterCount);
typeForwardedTo.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.Type, typeRef));
outputList.Add(typeForwardedTo);
}
}
}
#endregion
#region Parameter Attributes
static readonly IAttribute inAttribute = new DefaultAttribute(typeof(InAttribute).ToTypeReference(), null);
static readonly IAttribute outAttribute = new DefaultAttribute(typeof(OutAttribute).ToTypeReference(), null);
@ -379,7 +396,9 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -379,7 +396,9 @@ namespace ICSharpCode.NRefactory.TypeSystem
AddCustomAttributes(parameter.CustomAttributes, targetParameter.Attributes);
}
}
#endregion
#region Method Attributes
static readonly ITypeReference dllImportAttributeTypeRef = typeof(DllImportAttribute).ToTypeReference();
static readonly SimpleConstantValue trueValue = new SimpleConstantValue(KnownTypeReference.Boolean, true);
static readonly SimpleConstantValue falseValue = new SimpleConstantValue(KnownTypeReference.Boolean, true);
@ -506,18 +525,24 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -506,18 +525,24 @@ namespace ICSharpCode.NRefactory.TypeSystem
{
attribute.NamedArguments.Add(new KeyValuePair<string, IConstantValue>(name, value));
}
#endregion
#region Type Attributes
static readonly DefaultAttribute serializableAttribute = new DefaultAttribute(typeof(SerializableAttribute).ToTypeReference(), null);
static readonly DefaultAttribute comImportAttribute = new DefaultAttribute(typeof(ComImportAttribute).ToTypeReference(), null);
static readonly ITypeReference structLayoutAttributeTypeRef = typeof(StructLayoutAttribute).ToTypeReference();
static readonly ITypeReference layoutKindTypeRef = typeof(LayoutKind).ToTypeReference();
static readonly ITypeReference charSetTypeRef = typeof(CharSet).ToTypeReference();
void AddAttributes(TypeDefinition typeDefinition, ITypeDefinition targetEntity)
{
#region SerializableAttribute
// SerializableAttribute
if (typeDefinition.IsSerializable)
targetEntity.Attributes.Add(serializableAttribute);
#endregion
// ComImportAttribute
if (typeDefinition.IsImport)
targetEntity.Attributes.Add(comImportAttribute);
#region StructLayoutAttribute
LayoutKind layoutKind = LayoutKind.Auto;
@ -568,25 +593,25 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -568,25 +593,25 @@ namespace ICSharpCode.NRefactory.TypeSystem
AddCustomAttributes(typeDefinition.CustomAttributes, targetEntity.Attributes);
}
}
#endregion
#region Field Attributes
static readonly ITypeReference fieldOffsetAttributeTypeRef = typeof(FieldOffsetAttribute).ToTypeReference();
static readonly DefaultAttribute nonSerializedAttribute = new DefaultAttribute(typeof(NonSerializedAttribute).ToTypeReference(), null);
void AddAttributes(FieldDefinition fieldDefinition, IEntity targetEntity)
{
#region FieldOffsetAttribute
// FieldOffsetAttribute
if (fieldDefinition.HasLayoutInfo) {
DefaultAttribute fieldOffset = new DefaultAttribute(fieldOffsetAttributeTypeRef, new[] { KnownTypeReference.Int32 });
fieldOffset.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.Int32, fieldDefinition.Offset));
targetEntity.Attributes.Add(fieldOffset);
}
#endregion
#region NonSerializedAttribute
// NonSerializedAttribute
if (fieldDefinition.IsNotSerialized) {
targetEntity.Attributes.Add(nonSerializedAttribute);
}
#endregion
if (fieldDefinition.HasMarshalInfo) {
targetEntity.Attributes.Add(ConvertMarshalInfo(fieldDefinition.MarshalInfo));
@ -596,6 +621,25 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -596,6 +621,25 @@ namespace ICSharpCode.NRefactory.TypeSystem
AddCustomAttributes(fieldDefinition.CustomAttributes, targetEntity.Attributes);
}
}
#endregion
#region Event Attributes
void AddAttributes(EventDefinition eventDefinition, IEntity targetEntity)
{
if (eventDefinition.HasCustomAttributes) {
AddCustomAttributes(eventDefinition.CustomAttributes, targetEntity.Attributes);
}
}
#endregion
#region Property Attributes
void AddAttributes(PropertyDefinition propertyDefinition, IEntity targetEntity)
{
if (propertyDefinition.HasCustomAttributes) {
AddCustomAttributes(propertyDefinition.CustomAttributes, targetEntity.Attributes);
}
}
#endregion
#region MarshalAsAttribute (ConvertMarshalInfo)
static readonly ITypeReference marshalAsAttributeTypeRef = typeof(MarshalAsAttribute).ToTypeReference();
@ -610,6 +654,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -610,6 +654,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
}
#endregion
#region Custom Attributes (ReadAttribute)
void AddCustomAttributes(Mono.Collections.Generic.Collection<CustomAttribute> attributes, IList<IAttribute> targetCollection)
{
foreach (var cecilAttribute in attributes) {
@ -661,6 +706,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -661,6 +706,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
return a;
}
#endregion
#endregion
#region Read Constant Value
public IConstantValue ReadConstantValue(CustomAttributeArgument arg)

17
ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs

@ -99,6 +99,16 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -99,6 +99,16 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// <summary>
/// Gets whether the type is an open type (contains type parameters).
/// </summary>
/// <example>
/// <code>
/// class X&lt;T&gt; {
/// List&lt;T&gt; open;
/// X&lt;X&lt;T[]&gt;&gt; open;
/// X&lt;string&gt; closed;
/// int closed;
/// }
/// </code>
/// </example>
public static bool IsOpen(this IType type)
{
if (type == null)
@ -109,8 +119,13 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -109,8 +119,13 @@ namespace ICSharpCode.NRefactory.TypeSystem
}
/// <summary>
/// Gets whether the type is unbound.
/// Gets whether the type is unbound (is a generic type, but no type arguments were provided).
/// </summary>
/// <remarks>
/// In "<c>typeof(List&lt;Dictionary&lt;,&gt;&gt;)</c>", only the Dictionary is unbound, the List is considered
/// bound despite containing an unbound type.
/// This method returns false for partially parameterized types (<c>Dictionary&lt;string, &gt;</c>).
/// </remarks>
public static bool IsUnbound(this IType type)
{
if (type == null)

12
ICSharpCode.NRefactory/TypeSystem/IType.cs

@ -73,10 +73,18 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -73,10 +73,18 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// The filter is tested on the unparameterized types.</param>
/// <remarks>
/// If this type is parameterized, the nested type will also be parameterized.
/// Any additional type parameters on the nested type will be parameterized with the
/// corresponding ITypeParameter.
/// Any additional type parameters on the nested type will be parameterized with
/// <see cref="SharedType.UnboundTypeArgument"/>.
/// </remarks>
IEnumerable<IType> GetNestedTypes(ITypeResolveContext context, Predicate<ITypeDefinition> filter = null);
// Note that we cannot 'leak' the additional type parameter as we leak the normal type parameters, because
// the index might collide. For example,
// class Base<T> { class Nested<X> {} }
// class Derived<A, B> : Base<B> { }
//
// Derived<string, int>.GetNestedTypes() = Base+Nested<int, UnboundTypeArgument>
// Derived.GetNestedTypes() = Base+Nested<`1, >
// Here `1 refers to B, and there's no way to return X as it would collide with B.
/// <summary>
/// Gets all instance constructors for this type.

13
ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs

@ -87,6 +87,16 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -87,6 +87,16 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// </summary>
public static readonly ITypeReference Double = new GetClassTypeReference("System", "Double", 0);
/// <summary>
/// Gets a type reference pointing to the <c>decimal</c> type.
/// </summary>
public static readonly ITypeReference Decimal = new GetClassTypeReference("System", "Decimal", 0);
/// <summary>
/// Gets a type reference pointing to the <c>System.Type</c> type.
/// </summary>
public static readonly ITypeReference Type = new GetClassTypeReference("System", "Type", 0);
/// <summary>
/// Gets all known type references.
/// </summary>
@ -95,7 +105,8 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -95,7 +105,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
return new[] {
Void, Object, Boolean,
SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64,
String, Char, Single, Double
String, Char, Single, Double, Decimal,
Type
};
}
}

18
ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs

@ -176,14 +176,16 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -176,14 +176,16 @@ namespace ICSharpCode.NRefactory.TypeSystem
{
/*
class Base<T> {
class Nested {}
class Nested<X> {}
}
class Derived<A, B> : Base<B> {}
Derived<string,int>.GetNestedTypes() = { Base`1+Nested<int> }
Derived.GetNestedTypes() = { Base`1+Nested<B> }
Base<B>.GetNestedTypes() = { Base`1+Nested<B> }
Base.GetNestedTypes() = { Base`1+Nested<T2> } where T2 = copy of T in Base`1+Nested
Derived<string,int>.GetNestedTypes() = { Base`1+Nested<int, > }
Derived.GetNestedTypes() = { Base`1+Nested<`1, > }
Base<`1>.GetNestedTypes() = { Base`1+Nested<`1, > }
Base.GetNestedTypes() = { Base`1+Nested }
Empty type arguments are represented by SharedTypes.UnboundTypeArgument.
*/
Substitution substitution = new Substitution(typeArguments);
List<IType> types = genericType.GetNestedTypes(context, filter).ToList();
@ -193,10 +195,10 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -193,10 +195,10 @@ namespace ICSharpCode.NRefactory.TypeSystem
// (partially) parameterize the nested type definition
IType[] newTypeArgs = new IType[def.TypeParameterCount];
for (int j = 0; j < newTypeArgs.Length; j++) {
if (i < typeArguments.Length)
newTypeArgs[j] = typeArguments[i];
if (j < typeArguments.Length)
newTypeArgs[j] = typeArguments[j];
else
newTypeArgs[j] = def.TypeParameters[j];
newTypeArgs[j] = SharedTypes.UnboundTypeArgument;
}
types[i] = new ParameterizedType(def, newTypeArgs);
} else {

16
ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs

@ -23,6 +23,11 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -23,6 +23,11 @@ namespace ICSharpCode.NRefactory.TypeSystem
/// </summary>
public sealed class Dynamic {}
/// <summary>
/// A reflection class used to represent an unbound type argument.
/// </summary>
public sealed class UnboundTypeArgument {}
#region ITypeResolveContext.GetTypeDefinition(Type)
/// <summary>
/// Retrieves a type definition.
@ -78,10 +83,15 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -78,10 +83,15 @@ namespace ICSharpCode.NRefactory.TypeSystem
ITypeReference def = ToTypeReference(type.GetGenericTypeDefinition(), entity);
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], entity);
allUnbound &= args[i].Equals(SharedTypes.UnboundTypeArgument);
}
return new ParameterizedTypeReference(def, args);
if (allUnbound)
return def;
else
return new ParameterizedTypeReference(def, args);
} else if (type.IsArray) {
return new ArrayTypeReference(ToTypeReference(type.GetElementType(), entity), type.GetArrayRank());
} else if (type.IsPointer) {
@ -111,6 +121,8 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -111,6 +121,8 @@ namespace ICSharpCode.NRefactory.TypeSystem
return SharedTypes.Dynamic;
else if (type == typeof(Null))
return SharedTypes.Null;
else if (type == typeof(UnboundTypeArgument))
return SharedTypes.UnboundTypeArgument;
ITypeReference baseTypeRef = ToTypeReference(type.DeclaringType, entity);
int typeParameterCount;
string name = SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount);
@ -175,7 +187,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -175,7 +187,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
KnownTypeReference.UInt64,
KnownTypeReference.Single,
KnownTypeReference.Double,
new GetClassTypeReference("System", "Decimal", 0),
KnownTypeReference.Decimal,
new GetClassTypeReference("System", "DateTime", 0),
SharedTypes.UnknownType, // (TypeCode)17 has no enum value?
KnownTypeReference.String

29
ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs

@ -29,6 +29,13 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -29,6 +29,13 @@ namespace ICSharpCode.NRefactory.TypeSystem
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "It's immutable")]
public readonly static IType Dynamic = new DynamicType();
/// <summary>
/// A type used for unbound type arguments in partially parameterized types.
/// </summary>
/// <see cref="IType.GetNestedTypes"/>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "It's immutable")]
public readonly static IType UnboundTypeArgument = new UnboundType();
/*
* I'd like to define static instances for common types like
* void, int, etc.; but there are two problems with this:
@ -122,5 +129,27 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -122,5 +129,27 @@ namespace ICSharpCode.NRefactory.TypeSystem
return 31986112;
}
}
sealed class UnboundType : AbstractType
{
public override string Name {
get { return string.Empty; }
}
public override bool? IsReferenceType(ITypeResolveContext context)
{
return null;
}
public override bool Equals(IType other)
{
return other is UnboundType;
}
public override int GetHashCode()
{
return 151719123;
}
}
}
}

Loading…
Cancel
Save