Browse Source

CecilLoader: add support for ConstructedType

newNRvisualizers
Daniel Grunwald 15 years ago
parent
commit
0ca757fab0
  1. 18
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs
  2. 22
      ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs
  3. 176
      ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs
  4. 5
      ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs
  5. 34
      ICSharpCode.NRefactory/TypeSystem/Implementation/ConstructedType.cs
  6. 21
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs
  7. 20
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs
  8. 16
      ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs
  9. 8
      ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs

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

@ -2,6 +2,10 @@ @@ -2,6 +2,10 @@
// This code is distributed under MIT X11 license (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
[assembly: ICSharpCode.NRefactory.TypeSystem.TestCase.TypeTestAttribute(
42, typeof(System.Action<>), typeof(IDictionary<string, IList<NUnit.Framework.TestAttribute>>))]
namespace ICSharpCode.NRefactory.TypeSystem.TestCase
{
@ -9,4 +13,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase @@ -9,4 +13,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase
{
public void Method() {}
}
public class TypeTestAttribute : Attribute
{
public TypeTestAttribute(int a1, Type a2, Type a3) {}
}
public class DynamicTest
{
public List<dynamic> DynamicGenerics1(Action<object, dynamic[], object> param) { return null; }
public void DynamicGenerics2(Action<object, dynamic, object> param) { }
public void DynamicGenerics3(Action<int, dynamic, object> param) { }
public void DynamicGenerics4(Action<int[], dynamic, object> param) { }
public void DynamicGenerics5(Action<int*[], dynamic, object> param) { }
}
}

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

@ -41,7 +41,27 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -41,7 +41,27 @@ namespace ICSharpCode.NRefactory.TypeSystem
IMethod method = c.Methods.Single(m => m.Name == "Method");
Assert.AreEqual(typeof(SimplePublicClass).FullName + ".Method", method.FullName);
Assert.AreSame(c, method.DeclaringType);
Assert.AreEqual(Accessibility.Public, method.Accessibility);
Assert.AreEqual(EntityType.Method, method.EntityType);
Assert.IsFalse(method.IsVirtual);
Assert.IsFalse(method.IsStatic);
Assert.IsTrue(method.IsFrozen);
Assert.AreEqual(0, method.Parameters.Count);
Assert.AreEqual(0, method.Attributes.Count);
}
[Test]
[Ignore]
public void DynamicTypeInGenerics()
{
ITypeDefinition testClass = testCasePC.GetClass(typeof(DynamicTest).FullName, 0, StringComparer.Ordinal);
/*CSharpAmbience a = new CSharpAmbience();
a.ConversionFlags = ConversionFlags.ShowReturnType | ConversionFlags.ShowParameterList;
Assert.AreEqual("List<dynamic> DynamicGenerics1(Action<object, dynamic[], object>)", a.Convert(testClass.Methods.Single(me => me.Name == "DynamicGenerics1")));
Assert.AreEqual("void DynamicGenerics2(Action<object, dynamic, object>)", a.Convert(testClass.Methods.Single(me => me.Name == "DynamicGenerics2")));
Assert.AreEqual("void DynamicGenerics3(Action<int, dynamic, object>)", a.Convert(testClass.Methods.Single(me => me.Name == "DynamicGenerics3")));
Assert.AreEqual("void DynamicGenerics4(Action<int[], dynamic, object>)", a.Convert(testClass.Methods.Single(me => me.Name == "DynamicGenerics4")));
Assert.AreEqual("void DynamicGenerics5(Action<Int32*[], dynamic, object>)", a.Convert(testClass.Methods.Single(me => me.Name == "DynamicGenerics5")));*/
}
}
}

176
ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Runtime.CompilerServices;
using ICSharpCode.NRefactory.TypeSystem.Implementation;
using Mono.Cecil;
@ -40,7 +40,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -40,7 +40,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
ITypeResolveContext oldEarlyBindContext = this.EarlyBindContext;
try {
List<IAttribute> assemblyAttributes = new List<IAttribute>();
ReadAttributes(assemblyDefinition, assemblyAttributes);
AddAttributes(assemblyDefinition, assemblyAttributes);
TypeStorage typeStorage = new TypeStorage();
CecilProjectContent pc = new CecilProjectContent(typeStorage, assemblyDefinition.Name.FullName, assemblyAttributes.AsReadOnly());
@ -181,26 +181,23 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -181,26 +181,23 @@ namespace ICSharpCode.NRefactory.TypeSystem
return PointerTypeReference.Create(
CreateType(
(type as Mono.Cecil.PointerType).ElementType,
entity,
typeAttributes, ref typeIndex));
entity, typeAttributes, ref typeIndex));
} else if (type is Mono.Cecil.ArrayType) {
typeIndex++;
return ArrayTypeReference.Create(
CreateType(
(type as Mono.Cecil.ArrayType).ElementType,
entity,
typeAttributes, ref typeIndex),
entity, typeAttributes, ref typeIndex),
(type as Mono.Cecil.ArrayType).Rank);
} else if (type is GenericInstanceType) {
GenericInstanceType gType = (GenericInstanceType)type;
/*IReturnType baseType = CreateType(pc, member, gType.ElementType, attributeProvider, ref typeIndex);
IReturnType[] para = new IReturnType[gType.GenericArguments.Count];
ITypeReference baseType = CreateType(gType.ElementType, entity, typeAttributes, ref typeIndex);
ITypeReference[] para = new ITypeReference[gType.GenericArguments.Count];
for (int i = 0; i < para.Length; ++i) {
typeIndex++;
para[i] = CreateType(pc, member, gType.GenericArguments[i], attributeProvider, ref typeIndex);
para[i] = CreateType(gType.GenericArguments[i], entity, typeAttributes, ref typeIndex);
}
return new ConstructedReturnType(baseType, para);*/
throw new NotImplementedException();
return ConstructedType.Create(baseType, para);
} else if (type is GenericParameter) {
GenericParameter typeGP = type as GenericParameter;
if (typeGP.Owner is MethodDefinition) {
@ -303,7 +300,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -303,7 +300,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
#endregion
#region Read Attributes
void ReadAttributes(ICustomAttributeProvider attributeProvider, IList<IAttribute> outputList)
void AddAttributes(ICustomAttributeProvider attributeProvider, IList<IAttribute> outputList)
{
foreach (var cecilAttribute in attributeProvider.CustomAttributes) {
outputList.Add(ReadAttribute(cecilAttribute));
@ -422,7 +419,7 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -422,7 +419,7 @@ namespace ICSharpCode.NRefactory.TypeSystem
InitNestedTypes(loader); // nested types can be initialized only after generic parameters were created
if (typeDefinition.HasCustomAttributes) {
loader.ReadAttributes(typeDefinition, this.Attributes);
loader.AddAttributes(typeDefinition, this.Attributes);
}
// set base classes
@ -538,19 +535,168 @@ namespace ICSharpCode.NRefactory.TypeSystem @@ -538,19 +535,168 @@ namespace ICSharpCode.NRefactory.TypeSystem
void InitMembers(CecilLoader loader)
{
this.AddDefaultConstructorIfRequired = (this.ClassType == ClassType.Struct || this.ClassType == ClassType.Enum);
if (typeDefinition.HasMethods) {
foreach (MethodDefinition method in typeDefinition.Methods) {
this.Methods.Add(loader.ReadMethod(method, this));
if (loader.IsVisible(method.Attributes)) {
EntityType type = EntityType.Method;
if (method.IsSpecialName) {
if (method.IsConstructor)
type = EntityType.Constructor;
else if (method.Name.StartsWith("op_", StringComparison.Ordinal))
type = EntityType.Operator;
else
continue;
}
this.Methods.Add(loader.ReadMethod(method, this, type));
}
}
}
}
}
#endregion
IMethod ReadMethod(MethodDefinition method, ITypeDefinition parentType)
#region ReadMethod
IMethod ReadMethod(MethodDefinition method, ITypeDefinition parentType, EntityType methodType)
{
DefaultMethod m = new DefaultMethod(parentType, method.Name);
m.EntityType = methodType;
if (method.HasGenericParameters) {
throw new NotImplementedException();
/*foreach (GenericParameter g in method.GenericParameters) {
m.TypeParameters.Add(new DefaultTypeParameter(this, g.Name, g.Position));
}
int i = 0;
foreach (GenericParameter g in method.GenericParameters) {
AddConstraintsFromType(m.TypeParameters[i++], g);
}*/
}
if (method.IsConstructor)
m.ReturnType = parentType;
else
m.ReturnType = ReadTypeReference(method.ReturnType, typeAttributes: method, entity: m);
if (method.HasCustomAttributes) {
AddAttributes(method, m.Attributes);
}
if (parentType.ClassType == ClassType.Interface) {
// interface members don't have modifiers, but we want to handle them as "public abstract"
m.Accessibility = Accessibility.Public;
m.IsAbstract = true;
} else {
TranslateModifiers(method, m);
}
if (method.HasParameters) {
foreach (ParameterDefinition p in method.Parameters) {
m.Parameters.Add(ReadParameter(p, parentMember: m));
}
}
AddExplicitInterfaceImplementations(method, m);
// mark as extension method is the attribute is set
if (method.IsStatic && method.HasCustomAttributes) {
foreach (var attr in method.CustomAttributes) {
if (attr.AttributeType.FullName == typeof(ExtensionAttribute).FullName)
m.IsExtensionMethod = true;
}
}
return m;
}
bool IsVisible(MethodAttributes att)
{
att &= MethodAttributes.MemberAccessMask;
return IncludeInternalMembers
|| att == MethodAttributes.Public
|| att == MethodAttributes.Family
|| att == MethodAttributes.FamORAssem;
}
Accessibility GetAccessibility(MethodAttributes attr)
{
switch (attr & MethodAttributes.MemberAccessMask) {
case MethodAttributes.Private:
return Accessibility.Private;
case MethodAttributes.FamANDAssem:
return Accessibility.ProtectedAndInternal;
case MethodAttributes.Assem:
return Accessibility.Internal;
case MethodAttributes.Family:
return Accessibility.Protected;
case MethodAttributes.FamORAssem:
return Accessibility.ProtectedOrInternal;
default:
return Accessibility.Public;
}
}
void TranslateModifiers(MethodDefinition method, AbstractMember member)
{
member.Accessibility = GetAccessibility(method.Attributes);
if (method.IsAbstract)
member.IsAbstract = true;
else if (method.IsFinal)
member.IsSealed = true;
else if (method.IsVirtual)
member.IsVirtual = true;
}
#endregion
bool IsVisible(FieldAttributes att)
{
att &= FieldAttributes.FieldAccessMask;
return IncludeInternalMembers
|| att == FieldAttributes.Public
|| att == FieldAttributes.Family
|| att == FieldAttributes.FamORAssem;
}
#region ReadParameter
public IParameter ReadParameter(ParameterDefinition parameter, IParameterizedMember parentMember = null)
{
if (parameter == null)
throw new ArgumentNullException("parameter");
DefaultParameter p = new DefaultParameter();
p.Name = parameter.Name;
p.Type = ReadTypeReference(parameter.ParameterType, typeAttributes: parameter, entity: parentMember);
if (parameter.HasCustomAttributes)
AddAttributes(parameter, p.Attributes);
if (parameter.ParameterType is ByReferenceType) {
if (parameter.IsOut)
p.IsOut = true;
else
p.IsRef = true;
}
if (parameter.IsOptional) {
p.DefaultValue = ReadConstantValue(new CustomAttributeArgument(parameter.ParameterType, parameter.Constant));
}
if (parameter.ParameterType is Mono.Cecil.ArrayType) {
foreach (CustomAttribute att in parameter.CustomAttributes) {
if (att.AttributeType.FullName == typeof(ParamArrayAttribute).FullName) {
p.IsParams = true;
break;
}
}
}
return p;
}
#endregion
void AddExplicitInterfaceImplementations(MethodDefinition method, AbstractMember targetMember)
{
if (method.HasOverrides) {
throw new NotImplementedException();
}
}
}
}

5
ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs

@ -244,5 +244,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -244,5 +244,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
public virtual string DotNetName {
get { return this.DeclaringType.DotNetName + "." + this.Name; }
}
public override string ToString()
{
return "[" + EntityType + " " + DotNetName + ":" + ReturnType + "]";
}
}
}

34
ICSharpCode.NRefactory/TypeSystem/Implementation/ConstructedType.cs

@ -174,6 +174,25 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -174,6 +174,25 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
return hashCode;
}
public static ITypeReference Create(ITypeReference genericType, IEnumerable<ITypeReference> typeArguments)
{
if (genericType == null)
throw new ArgumentNullException("genericType");
if (typeArguments == null)
throw new ArgumentNullException("typeArguments");
ITypeReference[] typeArgs = typeArguments.ToArray();
if (genericType is ITypeDefinition && Array.TrueForAll(typeArgs, t => t is IType)) {
IType[] ta = new IType[typeArgs.Length];
for (int i = 0; i < ta.Length; i++) {
ta[i] = (IType)typeArgs[i];
}
return new ConstructedType((ITypeDefinition)genericType, ta);
} else {
return new ConstructedTypeReference(genericType, typeArgs);
}
}
}
/// <summary>
@ -226,5 +245,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -226,5 +245,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
}
return new ConstructedType(baseTypeDef, resolvedTypes);
}
public override string ToString()
{
StringBuilder b = new StringBuilder(genericType.ToString());
b.Append('[');
for (int i = 0; i < typeArguments.Length; i++) {
if (i > 0)
b.Append(',');
b.Append('[');
b.Append(typeArguments[i].ToString());
b.Append(']');
}
b.Append(']');
return b.ToString();
}
}
}

21
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs

@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
@ -73,5 +74,25 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -73,5 +74,25 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return parameters;
}
}
public override string ToString()
{
StringBuilder b = new StringBuilder("[");
b.Append(EntityType.ToString());
b.Append(' ');
b.Append(DeclaringType.Name);
b.Append('.');
b.Append(Name);
b.Append('(');
var p = this.Parameters;
for (int i = 0; i < p.Count; i++) {
if (i > 0) b.Append(", ");
b.Append(p[i].ToString());
}
b.Append("):");
b.Append(ReturnType.ToString());
b.Append(']');
return b.ToString();
}
}
}

20
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs

@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Text;
namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
@ -133,5 +134,24 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -133,5 +134,24 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
return p != null && type == p.type && attributes == p.attributes
&& defaultValue == p.defaultValue && region == p.region && flags == p.flags;
}
public override string ToString()
{
StringBuilder b = new StringBuilder();
if (IsRef)
b.Append("ref ");
if (IsOut)
b.Append("out ");
if (IsParams)
b.Append("params ");
b.Append(name);
b.Append(':');
b.Append(type.ToString());
if (defaultValue != null) {
b.Append(" = ");
b.Append(defaultValue.ToString());
}
return b.ToString();
}
}
}

16
ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs

@ -37,6 +37,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -37,6 +37,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
const ushort FlagAbstract = 0x0002;
const ushort FlagShadowing = 0x0004;
const ushort FlagSynthetic = 0x0008;
const ushort FlagAddDefaultConstructorIfRequired = 0x0010;
protected override void FreezeInternal()
{
@ -398,5 +399,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -398,5 +399,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
{
return DotNetName;
}
/// <summary>
/// Gets whether a default constructor should be added to this class if it is required.
/// Such automatic default constructors will not appear in ITypeDefinition.Methods, but will be present
/// in IType.GetMethods().
/// </summary>
/// <remarks>This way of creating the default constructor is necessary because
/// we cannot create it directly in the IClass - we need to consider partial classes.</remarks>
public bool AddDefaultConstructorIfRequired {
get { return flags[FlagAddDefaultConstructorIfRequired]; }
set {
CheckBeforeMutation();
flags[FlagAddDefaultConstructorIfRequired] = value;
}
}
}
}

8
ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs

@ -33,5 +33,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -33,5 +33,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation
else
return value;
}
public override string ToString()
{
if (value == null)
return "null";
else
return value.ToString();
}
}
}

Loading…
Cancel
Save