diff --git a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj index 7a5b18af60..7a4084067a 100644 --- a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj +++ b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj @@ -178,6 +178,10 @@ + + + + diff --git a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs index fc08d0b2c2..e6d55860ca 100644 --- a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs +++ b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs @@ -617,9 +617,8 @@ namespace ICSharpCode.NRefactory.TypeSystem { if (parameter == null) throw new ArgumentNullException("parameter"); - DefaultParameter p = new DefaultParameter(); - p.Name = parameter.Name; - p.Type = ReadTypeReference(parameter.ParameterType, typeAttributes: parameter, entity: parentMember); + var type = ReadTypeReference(parameter.ParameterType, typeAttributes: parameter, entity: parentMember); + DefaultParameter p = new DefaultParameter(type, parameter.Name); if (parameter.HasCustomAttributes) AddAttributes(parameter, p.Attributes); diff --git a/ICSharpCode.NRefactory/TypeSystem/ConstructedType.cs b/ICSharpCode.NRefactory/TypeSystem/ConstructedType.cs index b089fe8894..140a1eae1f 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ConstructedType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ConstructedType.cs @@ -23,6 +23,29 @@ namespace ICSharpCode.NRefactory.TypeSystem /// public class ConstructedType : Immutable, IType { + sealed class Substitution : TypeVisitor + { + readonly IType[] typeArguments; + + public Substitution(IType[] typeArguments) + { + this.typeArguments = typeArguments; + } + + public override IType VisitTypeParameter(ITypeParameter type) + { + int index = type.Index; + if (type.ParentClass != null) { + if (index >= 0 && index < typeArguments.Length) + return typeArguments[index]; + else + return SharedTypes.UnknownType; + } else { + return base.VisitTypeParameter(type); + } + } + } + readonly ITypeDefinition genericType; readonly IType[] typeArguments; @@ -118,7 +141,8 @@ namespace ICSharpCode.NRefactory.TypeSystem public IEnumerable GetBaseTypes(ITypeResolveContext context) { - throw new NotImplementedException(); + Substitution substitution = new Substitution(typeArguments); + return genericType.GetBaseTypes(context).Select(t => t.AcceptVisitor(substitution)); } public IList GetNestedTypes(ITypeResolveContext context) @@ -128,22 +152,54 @@ namespace ICSharpCode.NRefactory.TypeSystem public IList GetMethods(ITypeResolveContext context) { - throw new NotImplementedException(); + Substitution substitution = new Substitution(typeArguments); + IList methods = genericType.GetMethods(context); + for (int i = 0; i < methods.Count; i++) { + SpecializedMethod m = new SpecializedMethod(methods[i]); + m.SetDeclaringType(this); + m.SubstituteTypes(context, substitution); + methods[i] = m; + } + return methods; } public IList GetProperties(ITypeResolveContext context) { - throw new NotImplementedException(); + Substitution substitution = new Substitution(typeArguments); + IList properties = genericType.GetProperties(context); + for (int i = 0; i < properties.Count; i++) { + SpecializedProperty p = new SpecializedProperty(properties[i]); + p.SetDeclaringType(this); + p.SubstituteTypes(context, substitution); + properties[i] = p; + } + return properties; } public IList GetFields(ITypeResolveContext context) { - throw new NotImplementedException(); + Substitution substitution = new Substitution(typeArguments); + IList fields = genericType.GetFields(context); + for (int i = 0; i < fields.Count; i++) { + SpecializedField f = new SpecializedField(fields[i]); + f.SetDeclaringType(this); + f.ReturnType = f.ReturnType.Resolve(context).AcceptVisitor(substitution); + fields[i] = f; + } + return fields; } public IList GetEvents(ITypeResolveContext context) { - throw new NotImplementedException(); + Substitution substitution = new Substitution(typeArguments); + IList events = genericType.GetEvents(context); + for (int i = 0; i < events.Count; i++) { + SpecializedEvent e = new SpecializedEvent(events[i]); + e.SetDeclaringType(this); + e.ReturnType = e.ReturnType.Resolve(context).AcceptVisitor(substitution); + events[i] = e; + } + return events; } public override bool Equals(object obj) diff --git a/ICSharpCode.NRefactory/TypeSystem/IMember.cs b/ICSharpCode.NRefactory/TypeSystem/IMember.cs index 0c64a6c76a..f5e120ce07 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IMember.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IMember.cs @@ -27,11 +27,11 @@ namespace ICSharpCode.NRefactory.TypeSystem IType DeclaringType { get; } /// - /// Gets the generic member this member is based on. - /// Returns null if this is not a specialized member. + /// Gets the original member definition for this member. + /// Returns this if this is not a specialized member. /// Specialized members are the result of overload resolution with type substitution. /// - IMember GenericMember { get; } + IMember MemberDefinition { get; } /// /// Gets the return type of this member. @@ -81,8 +81,9 @@ namespace ICSharpCode.NRefactory.TypeSystem } } - IMember IMember.GenericMember { + IMember IMember.MemberDefinition { get { + Contract.Ensures(Contract.Result() != null); return null; } } diff --git a/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs b/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs index 7406c101c2..3faff4ae0a 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs @@ -28,21 +28,25 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Gets all methods that can be called on this return type. /// + /// A new mutable list IList GetMethods(ITypeResolveContext context); /// /// Gets all properties that can be called on this return type. /// + /// A new mutable list IList GetProperties(ITypeResolveContext context); /// /// Gets all fields that can be called on this return type. /// + /// A new mutable list IList GetFields(ITypeResolveContext context); /// /// Gets all events that can be called on this return type. /// + /// A new mutable list IList GetEvents(ITypeResolveContext context); } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs index 43ee6f2b10..97aef7d680 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs @@ -51,7 +51,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation this.name = name; } - /* do we really need copy constructor (for specialized members?) + /// + /// Copy constructor + /// protected AbstractMember(IMember member) { if (member == null) @@ -64,6 +66,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation this.bodyRegion = member.BodyRegion; this.name = member.Name; this.accessibility = member.Accessibility; + this.entityType = member.EntityType; this.IsSealed = member.IsSealed; this.IsAbstract = member.IsAbstract; this.IsShadowing = member.IsShadowing; @@ -73,14 +76,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation this.IsStatic = member.IsStatic; } - static IList CopyList(IList inputList) + protected static IList CopyList(IList inputList) { if (inputList.Count == 0) return null; else return new List(inputList); } - */ public ITypeDefinition DeclaringTypeDefinition { get { return declaringTypeDefinition; } @@ -90,8 +92,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return declaringTypeDefinition; } } - public virtual IMember GenericMember { - get { return null; } + public virtual IMember MemberDefinition { + get { return this; } } public ITypeReference ReturnType { diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultEvent.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultEvent.cs index 880a2695fb..38cf3467ce 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultEvent.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultEvent.cs @@ -23,6 +23,20 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation { } + /// + /// Copy constructor + /// + protected DefaultEvent(IEvent ev) + : base(ev) + { + this.CanAdd = ev.CanAdd; + this.addAccessibility = ev.AddAccessibility; + this.CanRemove = ev.CanRemove; + this.removeAccessibility = ev.RemoveAccessibility; + this.CanInvoke = ev.CanInvoke; + this.invokeAccessibility = ev.InvokeAccessibility; + } + public bool CanAdd { get { return flags[FlagCanAdd]; } set { diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs index 361f14f073..9e811e8df7 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs @@ -27,6 +27,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation { } + protected DefaultField(IField f) : base(f) + { + this.constantValue = f.ConstantValue; + this.IsReadOnly = f.IsReadOnly; + this.IsVolatile = f.IsVolatile; + } + public bool IsConst { get { return constantValue != null; } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs index 17243d0756..b77904f3d3 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs @@ -31,6 +31,17 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation { } + /// + /// Copy constructor + /// + protected DefaultMethod(IMethod method) : base(method) + { + returnTypeAttributes = CopyList(returnTypeAttributes); + typeParameters = CopyList(typeParameters); + parameters = CopyList(parameters); + this.IsExtensionMethod = method.IsExtensionMethod; + } + public IList ReturnTypeAttributes { get { if (returnTypeAttributes == null) diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs index e9304a80fe..377684a7c9 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs @@ -20,6 +20,31 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation DomRegion region; byte flags; + public DefaultParameter(ITypeReference type, string name) + { + if (type == null) + throw new ArgumentNullException("type"); + if (name == null) + throw new ArgumentNullException("name"); + this.type = type; + this.name = name; + } + + /// + /// Copy constructor + /// + public DefaultParameter(IParameter p) + { + this.name = p.Name; + this.type = p.Type; + this.attributes = p.Attributes; + this.defaultValue = p.DefaultValue; + this.region = p.Region; + this.IsRef = p.IsRef; + this.IsOut = p.IsOut; + this.IsParams = p.IsParams; + } + protected override void FreezeInternal() { type.Freeze(); diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultProperty.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultProperty.cs index 855df24da4..8e85a924c6 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultProperty.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultProperty.cs @@ -30,6 +30,16 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation { } + protected DefaultProperty(IProperty p) : base(p) + { + this.getterAccessibility = p.GetterAccessibility; + this.setterAccessibility = p.SetterAccessibility; + this.parameters = CopyList(p.Parameters); + this.IsIndexer = p.IsIndexer; + this.CanGet = p.CanGet; + this.CanSet = p.CanSet; + } + public bool IsIndexer { get { return flags[FlagIsIndexer]; } set { diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs new file mode 100644 index 0000000000..6c2fdbe105 --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs @@ -0,0 +1,36 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Represents a specialized IEvent (e.g. after type substitution). + /// + public class SpecializedEvent : DefaultEvent + { + readonly IMember memberDefinition; + IType declaringType; + + public SpecializedEvent(IEvent e) : base(e) + { + this.memberDefinition = e.MemberDefinition; + this.declaringType = e.DeclaringType; + } + + public override IType DeclaringType { + get { return declaringType; } + } + + public void SetDeclaringType(IType declaringType) + { + CheckBeforeMutation(); + this.declaringType = declaringType; + } + + public override IMember MemberDefinition { + get { return memberDefinition; } + } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs new file mode 100644 index 0000000000..ccdf9d5044 --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs @@ -0,0 +1,36 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Represents a specialized IField (e.g. after type substitution). + /// + public class SpecializedField : DefaultField + { + readonly IMember memberDefinition; + IType declaringType; + + public SpecializedField(IField f) : base(f) + { + this.memberDefinition = f.MemberDefinition; + this.declaringType = f.DeclaringType; + } + + public override IType DeclaringType { + get { return declaringType; } + } + + public void SetDeclaringType(IType declaringType) + { + CheckBeforeMutation(); + this.declaringType = declaringType; + } + + public override IMember MemberDefinition { + get { return memberDefinition; } + } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs new file mode 100644 index 0000000000..99717ee193 --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs @@ -0,0 +1,51 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Represents a specialized IMethod (e.g. after type substitution). + /// + public class SpecializedMethod : DefaultMethod + { + readonly IMember memberDefinition; + IType declaringType; + + public SpecializedMethod(IMethod m) : base(m) + { + this.memberDefinition = m.MemberDefinition; + this.declaringType = m.DeclaringType; + } + + public override IType DeclaringType { + get { return declaringType; } + } + + public void SetDeclaringType(IType declaringType) + { + CheckBeforeMutation(); + this.declaringType = declaringType; + } + + public override IMember MemberDefinition { + get { return memberDefinition; } + } + + /// + /// Performts type substitution in parameter types and in the return type. + /// + public void SubstituteTypes(ITypeResolveContext context, TypeVisitor substitution) + { + this.ReturnType = this.ReturnType.Resolve(context).AcceptVisitor(substitution); + var p = this.Parameters; + for (int i = 0; i < p.Count; i++) { + IType newType = p[i].Type.Resolve(context).AcceptVisitor(substitution); + if (newType != p[i].Type) { + p[i] = new DefaultParameter(p[i]) { Type = newType }; + } + } + } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs new file mode 100644 index 0000000000..59c9a7c009 --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs @@ -0,0 +1,51 @@ +// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Represents a specialized IProperty (e.g. after type substitution). + /// + public class SpecializedProperty : DefaultProperty + { + readonly IMember memberDefinition; + IType declaringType; + + public SpecializedProperty(IProperty p) : base(p) + { + this.memberDefinition = p.MemberDefinition; + this.declaringType = p.DeclaringType; + } + + public override IType DeclaringType { + get { return declaringType; } + } + + public void SetDeclaringType(IType declaringType) + { + CheckBeforeMutation(); + this.declaringType = declaringType; + } + + public override IMember MemberDefinition { + get { return memberDefinition; } + } + + /// + /// Performts type substitution in parameter types and in the return type. + /// + public void SubstituteTypes(ITypeResolveContext context, TypeVisitor substitution) + { + this.ReturnType = this.ReturnType.Resolve(context).AcceptVisitor(substitution); + var p = this.Parameters; + for (int i = 0; i < p.Count; i++) { + IType newType = p[i].Type.Resolve(context).AcceptVisitor(substitution); + if (newType != p[i].Type) { + p[i] = new DefaultParameter(p[i]) { Type = newType }; + } + } + } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/TypeVisitor.cs b/ICSharpCode.NRefactory/TypeSystem/TypeVisitor.cs index 774cfda4f8..af8ae4ca8f 100644 --- a/ICSharpCode.NRefactory/TypeSystem/TypeVisitor.cs +++ b/ICSharpCode.NRefactory/TypeSystem/TypeVisitor.cs @@ -6,7 +6,7 @@ using System; namespace ICSharpCode.NRefactory.TypeSystem { /// - /// Description of ITypeVisitor. + /// Base class for the visitor pattern on . /// public abstract class TypeVisitor {