// Copyright (c) 2010-2013 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.Collections.Generic; using System.Linq; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { /// /// References an entity by its type and name. /// This class can be used to refer to all members except for constructors and explicit interface implementations. /// /// /// Resolving a DefaultMemberReference requires a context that provides enough information for resolving the declaring type reference /// and the parameter types references. /// [Serializable] public sealed class DefaultMemberReference : IMemberReference, ISupportsInterning { readonly SymbolKind symbolKind; readonly ITypeReference typeReference; readonly string name; readonly int typeParameterCount; readonly IList parameterTypes; public DefaultMemberReference(SymbolKind symbolKind, ITypeReference typeReference, string name, int typeParameterCount = 0, IList parameterTypes = null) { if (typeReference == null) throw new ArgumentNullException("typeReference"); if (name == null) throw new ArgumentNullException("name"); if (typeParameterCount != 0 && symbolKind != SymbolKind.Method) throw new ArgumentException("Type parameter count > 0 is only supported for methods."); this.symbolKind = symbolKind; this.typeReference = typeReference; this.name = name; this.typeParameterCount = typeParameterCount; this.parameterTypes = parameterTypes ?? EmptyList.Instance; } public ITypeReference DeclaringTypeReference { get { return typeReference; } } public IMember Resolve(ITypeResolveContext context) { IType type = typeReference.Resolve(context); IEnumerable members; if (symbolKind == SymbolKind.Accessor) { members = type.GetAccessors( m => m.Name == name && !m.IsExplicitInterfaceImplementation, GetMemberOptions.IgnoreInheritedMembers); } else if (symbolKind == SymbolKind.Method) { members = type.GetMethods( m => m.Name == name && m.SymbolKind == SymbolKind.Method && m.TypeParameters.Count == typeParameterCount && !m.IsExplicitInterfaceImplementation, GetMemberOptions.IgnoreInheritedMembers); } else { members = type.GetMembers( m => m.Name == name && m.SymbolKind == symbolKind && !m.IsExplicitInterfaceImplementation, GetMemberOptions.IgnoreInheritedMembers); } var resolvedParameterTypes = parameterTypes.Resolve(context); foreach (IMember member in members) { IParameterizedMember parameterizedMember = member as IParameterizedMember; if (parameterizedMember == null) { if (parameterTypes.Count == 0) return member; } else if (parameterTypes.Count == parameterizedMember.Parameters.Count) { bool signatureMatches = true; for (int i = 0; i < parameterTypes.Count; i++) { IType type1 = DummyTypeParameter.NormalizeAllTypeParameters(resolvedParameterTypes[i]); IType type2 = DummyTypeParameter.NormalizeAllTypeParameters(parameterizedMember.Parameters[i].Type); if (!type1.Equals(type2)) { signatureMatches = false; break; } } if (signatureMatches) return member; } } return null; } ISymbol ISymbolReference.Resolve(ITypeResolveContext context) { return ((IMemberReference)this).Resolve(context); } int ISupportsInterning.GetHashCodeForInterning() { return (int)symbolKind ^ typeReference.GetHashCode() ^ name.GetHashCode() ^ parameterTypes.GetHashCode(); } bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { DefaultMemberReference o = other as DefaultMemberReference; return o != null && symbolKind == o.symbolKind && typeReference == o.typeReference && name == o.name && parameterTypes == o.parameterTypes; } } }