mirror of https://github.com/icsharpcode/ILSpy.git
24 changed files with 0 additions and 2062 deletions
@ -1,36 +0,0 @@ |
|||||||
// 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 ICSharpCode.Decompiler.Semantics; |
|
||||||
|
|
||||||
namespace ICSharpCode.Decompiler.TypeSystem |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Represents an unresolved constant value.
|
|
||||||
/// </summary>
|
|
||||||
public interface IConstantValue |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Resolves the value of this constant.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="context">Context where the constant value will be used.</param>
|
|
||||||
/// <returns>Resolve result representing the constant value.
|
|
||||||
/// This method never returns null; in case of errors, an ErrorResolveResult will be returned.</returns>
|
|
||||||
ResolveResult Resolve(ITypeResolveContext context); |
|
||||||
} |
|
||||||
} |
|
@ -1,85 +0,0 @@ |
|||||||
// 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; |
|
||||||
|
|
||||||
namespace ICSharpCode.Decompiler.TypeSystem.Implementation |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Implementation of <see cref="IEntity"/> that resolves an unresolved entity.
|
|
||||||
/// </summary>
|
|
||||||
public abstract class AbstractResolvedEntity : IEntity |
|
||||||
{ |
|
||||||
protected readonly IUnresolvedEntity unresolved; |
|
||||||
protected readonly ITypeResolveContext parentContext; |
|
||||||
|
|
||||||
protected AbstractResolvedEntity(IUnresolvedEntity unresolved, ITypeResolveContext parentContext) |
|
||||||
{ |
|
||||||
if (unresolved == null) |
|
||||||
throw new ArgumentNullException("unresolved"); |
|
||||||
if (parentContext == null) |
|
||||||
throw new ArgumentNullException("parentContext"); |
|
||||||
this.unresolved = unresolved; |
|
||||||
this.parentContext = parentContext; |
|
||||||
this.Attributes = unresolved.Attributes.CreateResolvedAttributes(parentContext); |
|
||||||
} |
|
||||||
|
|
||||||
public System.Reflection.Metadata.EntityHandle MetadataToken => unresolved.MetadataToken; |
|
||||||
|
|
||||||
public SymbolKind SymbolKind { |
|
||||||
get { return unresolved.SymbolKind; } |
|
||||||
} |
|
||||||
|
|
||||||
public ITypeDefinition DeclaringTypeDefinition { |
|
||||||
get { return parentContext.CurrentTypeDefinition; } |
|
||||||
} |
|
||||||
|
|
||||||
public virtual IType DeclaringType { |
|
||||||
get { return parentContext.CurrentTypeDefinition; } |
|
||||||
} |
|
||||||
|
|
||||||
public IAssembly ParentAssembly { |
|
||||||
get { return parentContext.CurrentAssembly; } |
|
||||||
} |
|
||||||
|
|
||||||
public IReadOnlyList<IAttribute> Attributes { get; protected set; } |
|
||||||
IEnumerable<IAttribute> IEntity.GetAttributes() => Attributes; |
|
||||||
|
|
||||||
public bool IsStatic { get { return unresolved.IsStatic; } } |
|
||||||
public bool IsAbstract { get { return unresolved.IsAbstract; } } |
|
||||||
public bool IsSealed { get { return unresolved.IsSealed; } } |
|
||||||
public bool IsShadowing { get { return unresolved.IsShadowing; } } |
|
||||||
|
|
||||||
public ICompilation Compilation { |
|
||||||
get { return parentContext.Compilation; } |
|
||||||
} |
|
||||||
|
|
||||||
public string FullName { get { return unresolved.FullName; } } |
|
||||||
public string Name { get { return unresolved.Name; } } |
|
||||||
public string ReflectionName { get { return unresolved.ReflectionName; } } |
|
||||||
public string Namespace { get { return unresolved.Namespace; } } |
|
||||||
|
|
||||||
public virtual Accessibility Accessibility { get { return unresolved.Accessibility; } } |
|
||||||
|
|
||||||
public override string ToString() |
|
||||||
{ |
|
||||||
return "[" + this.SymbolKind.ToString() + " " + this.ReflectionName + "]"; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,138 +0,0 @@ |
|||||||
// 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.Collections.Generic; |
|
||||||
using System.Linq; |
|
||||||
using ICSharpCode.Decompiler.Util; |
|
||||||
|
|
||||||
namespace ICSharpCode.Decompiler.TypeSystem.Implementation |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Implementation of <see cref="IMember"/> that resolves an unresolved member.
|
|
||||||
/// </summary>
|
|
||||||
public abstract class AbstractResolvedMember : AbstractResolvedEntity, IMember |
|
||||||
{ |
|
||||||
protected new readonly IUnresolvedMember unresolved; |
|
||||||
protected readonly ITypeResolveContext context; |
|
||||||
volatile IType returnType; |
|
||||||
IReadOnlyList<IMember> implementedInterfaceMembers; |
|
||||||
|
|
||||||
protected AbstractResolvedMember(IUnresolvedMember unresolved, ITypeResolveContext parentContext) |
|
||||||
: base(unresolved, parentContext) |
|
||||||
{ |
|
||||||
this.unresolved = unresolved; |
|
||||||
this.context = parentContext.WithCurrentMember(this); |
|
||||||
} |
|
||||||
|
|
||||||
IMember IMember.MemberDefinition { |
|
||||||
get { return this; } |
|
||||||
} |
|
||||||
|
|
||||||
public IType ReturnType { |
|
||||||
get { |
|
||||||
return this.returnType ?? (this.returnType = unresolved.ReturnType.Resolve(context)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public IUnresolvedMember UnresolvedMember { |
|
||||||
get { return unresolved; } |
|
||||||
} |
|
||||||
|
|
||||||
public IEnumerable<IMember> ExplicitlyImplementedInterfaceMembers { |
|
||||||
get { |
|
||||||
IReadOnlyList<IMember> result = LazyInit.VolatileRead(ref this.implementedInterfaceMembers); |
|
||||||
if (result != null) { |
|
||||||
return result; |
|
||||||
} else { |
|
||||||
return LazyInit.GetOrSet(ref implementedInterfaceMembers, FindImplementedInterfaceMembers()); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
IReadOnlyList<IMember> FindImplementedInterfaceMembers() |
|
||||||
{ |
|
||||||
if (unresolved.IsExplicitInterfaceImplementation) { |
|
||||||
List<IMember> result = new List<IMember>(); |
|
||||||
foreach (var memberReference in unresolved.ExplicitInterfaceImplementations) { |
|
||||||
IMember member = memberReference.Resolve(context); |
|
||||||
if (member != null) |
|
||||||
result.Add(member); |
|
||||||
} |
|
||||||
return result.ToArray(); |
|
||||||
} else if (unresolved.IsStatic || unresolved.Accessibility != Accessibility.Public || DeclaringTypeDefinition == null || DeclaringTypeDefinition.Kind == TypeKind.Interface) { |
|
||||||
return EmptyList<IMember>.Instance; |
|
||||||
} else { |
|
||||||
// TODO: implement interface member mappings correctly
|
|
||||||
var result = InheritanceHelper.GetBaseMembers(this, true) |
|
||||||
.Where(m => m.DeclaringTypeDefinition != null && m.DeclaringTypeDefinition.Kind == TypeKind.Interface) |
|
||||||
.ToArray(); |
|
||||||
|
|
||||||
IEnumerable<IMember> otherMembers = DeclaringTypeDefinition.Members; |
|
||||||
if (SymbolKind == SymbolKind.Accessor) |
|
||||||
otherMembers = DeclaringTypeDefinition.GetAccessors(options: GetMemberOptions.IgnoreInheritedMembers); |
|
||||||
result = result.Where(item => !otherMembers.Any(m => m.IsExplicitInterfaceImplementation && m.ExplicitlyImplementedInterfaceMembers.Contains(item))).ToArray(); |
|
||||||
|
|
||||||
return result; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public bool IsExplicitInterfaceImplementation { |
|
||||||
get { return unresolved.IsExplicitInterfaceImplementation; } |
|
||||||
} |
|
||||||
|
|
||||||
public bool IsVirtual { |
|
||||||
get { return unresolved.IsVirtual; } |
|
||||||
} |
|
||||||
|
|
||||||
public bool IsOverride { |
|
||||||
get { return unresolved.IsOverride; } |
|
||||||
} |
|
||||||
|
|
||||||
public bool IsOverridable { |
|
||||||
get { return unresolved.IsOverridable; } |
|
||||||
} |
|
||||||
|
|
||||||
public TypeParameterSubstitution Substitution { |
|
||||||
get { return TypeParameterSubstitution.Identity; } |
|
||||||
} |
|
||||||
|
|
||||||
public virtual bool Equals(IMember obj, TypeVisitor typeNormalization) |
|
||||||
{ |
|
||||||
return Equals(obj); |
|
||||||
} |
|
||||||
|
|
||||||
public abstract IMember Specialize(TypeParameterSubstitution substitution); |
|
||||||
|
|
||||||
internal IMethod GetAccessor(ref IMethod accessorField, IUnresolvedMethod unresolvedAccessor) |
|
||||||
{ |
|
||||||
if (unresolvedAccessor == null) |
|
||||||
return null; |
|
||||||
IMethod result = LazyInit.VolatileRead(ref accessorField); |
|
||||||
if (result != null) { |
|
||||||
return result; |
|
||||||
} else { |
|
||||||
return LazyInit.GetOrSet(ref accessorField, CreateResolvedAccessor(unresolvedAccessor)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected virtual IMethod CreateResolvedAccessor(IUnresolvedMethod unresolvedAccessor) |
|
||||||
{ |
|
||||||
return (IMethod)unresolvedAccessor.CreateResolved(context); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,252 +0,0 @@ |
|||||||
// 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.Text; |
|
||||||
using ICSharpCode.Decompiler.Util; |
|
||||||
|
|
||||||
namespace ICSharpCode.Decompiler.TypeSystem.Implementation |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Base class for <see cref="IUnresolvedEntity"/> implementations.
|
|
||||||
/// </summary>
|
|
||||||
[Serializable] |
|
||||||
public abstract class AbstractUnresolvedEntity : IUnresolvedEntity, IFreezable |
|
||||||
{ |
|
||||||
// possible optimizations to reduce the memory usage of AbstractUnresolvedEntity:
|
|
||||||
// - store regions in more compact form (e.g. assume both file names are identical; use ushort for columns)
|
|
||||||
|
|
||||||
IUnresolvedTypeDefinition declaringTypeDefinition; |
|
||||||
|
|
||||||
string name = string.Empty; |
|
||||||
IList<IUnresolvedAttribute> attributes; |
|
||||||
System.Reflection.Metadata.EntityHandle metadataToken; |
|
||||||
|
|
||||||
// 1 byte per enum + 2 bytes for flags
|
|
||||||
SymbolKind symbolKind; |
|
||||||
Accessibility accessibility; |
|
||||||
internal BitVector16 flags; |
|
||||||
|
|
||||||
// flags for AbstractUnresolvedEntity:
|
|
||||||
internal const ushort FlagFrozen = 0x0001; |
|
||||||
internal const ushort FlagSealed = 0x0002; |
|
||||||
internal const ushort FlagAbstract = 0x0004; |
|
||||||
internal const ushort FlagShadowing = 0x0008; |
|
||||||
//internal const ushort FlagSynthetic = 0x0010;
|
|
||||||
internal const ushort FlagStatic = 0x0020; |
|
||||||
// flags for DefaultUnresolvedTypeDefinition/LazyCecilTypeDefinition
|
|
||||||
internal const ushort FlagAddDefaultConstructorIfRequired = 0x0040; |
|
||||||
internal const ushort FlagHasExtensionMethods = 0x0080; |
|
||||||
internal const ushort FlagHasNoExtensionMethods = 0x0100; |
|
||||||
internal const ushort FlagPartialTypeDefinition = 0x0200; |
|
||||||
// flags for AbstractUnresolvedMember:
|
|
||||||
internal const ushort FlagExplicitInterfaceImplementation = 0x0040; |
|
||||||
internal const ushort FlagVirtual = 0x0080; |
|
||||||
internal const ushort FlagOverride = 0x0100; |
|
||||||
// flags for DefaultField:
|
|
||||||
internal const ushort FlagFieldIsReadOnly = 0x1000; |
|
||||||
internal const ushort FlagFieldIsVolatile = 0x2000; |
|
||||||
internal const ushort FlagFieldIsFixedSize = 0x4000; |
|
||||||
// flags for DefaultMethod:
|
|
||||||
internal const ushort FlagExtensionMethod = 0x1000; |
|
||||||
internal const ushort FlagPartialMethod = 0x2000; |
|
||||||
internal const ushort FlagHasBody = 0x4000; |
|
||||||
internal const ushort FlagAsyncMethod = 0x8000; |
|
||||||
|
|
||||||
public bool IsFrozen { |
|
||||||
get { return flags[FlagFrozen]; } |
|
||||||
} |
|
||||||
|
|
||||||
public void Freeze() |
|
||||||
{ |
|
||||||
if (!flags[FlagFrozen]) { |
|
||||||
FreezeInternal(); |
|
||||||
flags[FlagFrozen] = true; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
protected virtual void FreezeInternal() |
|
||||||
{ |
|
||||||
attributes = FreezableHelper.FreezeListAndElements(attributes); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Uses the specified interning provider to intern
|
|
||||||
/// strings and lists in this entity.
|
|
||||||
/// This method does not test arbitrary objects to see if they implement ISupportsInterning;
|
|
||||||
/// instead we assume that those are interned immediately when they are created (before they are added to this entity).
|
|
||||||
/// </summary>
|
|
||||||
public virtual void ApplyInterningProvider(InterningProvider provider) |
|
||||||
{ |
|
||||||
if (provider == null) |
|
||||||
throw new ArgumentNullException("provider"); |
|
||||||
ThrowIfFrozen(); |
|
||||||
name = provider.Intern(name); |
|
||||||
attributes = provider.InternList(attributes); |
|
||||||
} |
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Creates a shallow clone of this entity.
|
|
||||||
/// Collections (e.g. a type's member list) will be cloned as well, but the elements
|
|
||||||
/// of said list will not be.
|
|
||||||
/// If this instance is frozen, the clone will be unfrozen.
|
|
||||||
/// </summary>
|
|
||||||
public virtual object Clone() |
|
||||||
{ |
|
||||||
var copy = (AbstractUnresolvedEntity)MemberwiseClone(); |
|
||||||
copy.flags[FlagFrozen] = false; |
|
||||||
if (attributes != null) |
|
||||||
copy.attributes = new List<IUnresolvedAttribute>(attributes); |
|
||||||
return copy; |
|
||||||
} |
|
||||||
|
|
||||||
protected void ThrowIfFrozen() |
|
||||||
{ |
|
||||||
FreezableHelper.ThrowIfFrozen(this); |
|
||||||
} |
|
||||||
|
|
||||||
public System.Reflection.Metadata.EntityHandle MetadataToken { |
|
||||||
get { return metadataToken; } |
|
||||||
set { |
|
||||||
ThrowIfFrozen(); |
|
||||||
metadataToken = value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public SymbolKind SymbolKind { |
|
||||||
get { return symbolKind; } |
|
||||||
set { |
|
||||||
ThrowIfFrozen(); |
|
||||||
symbolKind = value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public IUnresolvedTypeDefinition DeclaringTypeDefinition { |
|
||||||
get { return declaringTypeDefinition; } |
|
||||||
set { |
|
||||||
ThrowIfFrozen(); |
|
||||||
declaringTypeDefinition = value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public IList<IUnresolvedAttribute> Attributes { |
|
||||||
get { |
|
||||||
if (attributes == null) |
|
||||||
attributes = new List<IUnresolvedAttribute>(); |
|
||||||
return attributes; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public string Name { |
|
||||||
get { return name; } |
|
||||||
set { |
|
||||||
if (value == null) |
|
||||||
throw new ArgumentNullException("value"); |
|
||||||
ThrowIfFrozen(); |
|
||||||
name = value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public virtual string FullName { |
|
||||||
get { |
|
||||||
if (declaringTypeDefinition != null) |
|
||||||
return declaringTypeDefinition.FullName + "." + name; |
|
||||||
else if (!string.IsNullOrEmpty(this.Namespace)) |
|
||||||
return this.Namespace + "." + name; |
|
||||||
else |
|
||||||
return name; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public virtual string Namespace { |
|
||||||
get { |
|
||||||
if (declaringTypeDefinition != null) |
|
||||||
return declaringTypeDefinition.Namespace; |
|
||||||
else |
|
||||||
return string.Empty; |
|
||||||
} |
|
||||||
set { |
|
||||||
throw new NotSupportedException(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public virtual string ReflectionName { |
|
||||||
get { |
|
||||||
if (declaringTypeDefinition != null) |
|
||||||
return declaringTypeDefinition.ReflectionName + "." + name; |
|
||||||
else |
|
||||||
return name; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public Accessibility Accessibility { |
|
||||||
get { return accessibility; } |
|
||||||
set { |
|
||||||
ThrowIfFrozen(); |
|
||||||
accessibility = value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public bool IsStatic { |
|
||||||
get { return flags[FlagStatic]; } |
|
||||||
set { |
|
||||||
ThrowIfFrozen(); |
|
||||||
flags[FlagStatic] = value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public bool IsAbstract { |
|
||||||
get { return flags[FlagAbstract]; } |
|
||||||
set { |
|
||||||
ThrowIfFrozen(); |
|
||||||
flags[FlagAbstract] = value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public bool IsSealed { |
|
||||||
get { return flags[FlagSealed]; } |
|
||||||
set { |
|
||||||
ThrowIfFrozen(); |
|
||||||
flags[FlagSealed] = value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public bool IsShadowing { |
|
||||||
get { return flags[FlagShadowing]; } |
|
||||||
set { |
|
||||||
ThrowIfFrozen(); |
|
||||||
flags[FlagShadowing] = value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public override string ToString() |
|
||||||
{ |
|
||||||
StringBuilder b = new StringBuilder("["); |
|
||||||
b.Append(GetType().Name); |
|
||||||
b.Append(' '); |
|
||||||
if (this.DeclaringTypeDefinition != null) { |
|
||||||
b.Append(this.DeclaringTypeDefinition.Name); |
|
||||||
b.Append('.'); |
|
||||||
} |
|
||||||
b.Append(this.Name); |
|
||||||
b.Append(']'); |
|
||||||
return b.ToString(); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,268 +0,0 @@ |
|||||||
// 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; |
|
||||||
using ICSharpCode.Decompiler.Util; |
|
||||||
|
|
||||||
namespace ICSharpCode.Decompiler.TypeSystem.Implementation |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Base class for <see cref="IUnresolvedMember"/> implementations.
|
|
||||||
/// </summary>
|
|
||||||
[Serializable] |
|
||||||
public abstract class AbstractUnresolvedMember : AbstractUnresolvedEntity, IUnresolvedMember |
|
||||||
{ |
|
||||||
ITypeReference returnType = SpecialType.UnknownType; |
|
||||||
IList<IMemberReference> interfaceImplementations; |
|
||||||
|
|
||||||
public override void ApplyInterningProvider(InterningProvider provider) |
|
||||||
{ |
|
||||||
base.ApplyInterningProvider(provider); |
|
||||||
interfaceImplementations = provider.InternList(interfaceImplementations); |
|
||||||
} |
|
||||||
|
|
||||||
protected override void FreezeInternal() |
|
||||||
{ |
|
||||||
base.FreezeInternal(); |
|
||||||
interfaceImplementations = FreezableHelper.FreezeList(interfaceImplementations); |
|
||||||
} |
|
||||||
|
|
||||||
public override object Clone() |
|
||||||
{ |
|
||||||
var copy = (AbstractUnresolvedMember)base.Clone(); |
|
||||||
if (interfaceImplementations != null) |
|
||||||
copy.interfaceImplementations = new List<IMemberReference>(interfaceImplementations); |
|
||||||
return copy; |
|
||||||
} |
|
||||||
|
|
||||||
/* |
|
||||||
[Serializable] |
|
||||||
internal new class RareFields : AbstractUnresolvedEntity.RareFields |
|
||||||
{ |
|
||||||
internal IList<IMemberReference> interfaceImplementations; |
|
||||||
|
|
||||||
public override void ApplyInterningProvider(IInterningProvider provider) |
|
||||||
{ |
|
||||||
base.ApplyInterningProvider(provider); |
|
||||||
interfaceImplementations = provider.InternList(interfaceImplementations); |
|
||||||
} |
|
||||||
|
|
||||||
protected internal override void FreezeInternal() |
|
||||||
{ |
|
||||||
interfaceImplementations = FreezableHelper.FreezeListAndElements(interfaceImplementations); |
|
||||||
base.FreezeInternal(); |
|
||||||
} |
|
||||||
|
|
||||||
override Clone(){} |
|
||||||
} |
|
||||||
|
|
||||||
internal override AbstractUnresolvedEntity.RareFields WriteRareFields() |
|
||||||
{ |
|
||||||
ThrowIfFrozen(); |
|
||||||
if (rareFields == null) rareFields = new RareFields(); |
|
||||||
return rareFields; |
|
||||||
}*/ |
|
||||||
|
|
||||||
public ITypeReference ReturnType { |
|
||||||
get { return returnType; } |
|
||||||
set { |
|
||||||
if (value == null) |
|
||||||
throw new ArgumentNullException("value"); |
|
||||||
ThrowIfFrozen(); |
|
||||||
returnType = value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public bool IsExplicitInterfaceImplementation { |
|
||||||
get { return flags[FlagExplicitInterfaceImplementation]; } |
|
||||||
set { |
|
||||||
ThrowIfFrozen(); |
|
||||||
flags[FlagExplicitInterfaceImplementation] = value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public IList<IMemberReference> ExplicitInterfaceImplementations { |
|
||||||
get { |
|
||||||
/* |
|
||||||
RareFields rareFields = (RareFields)this.rareFields; |
|
||||||
if (rareFields == null || rareFields.interfaceImplementations == null) { |
|
||||||
rareFields = (RareFields)WriteRareFields(); |
|
||||||
return rareFields.interfaceImplementations = new List<IMemberReference>(); |
|
||||||
} |
|
||||||
return rareFields.interfaceImplementations; |
|
||||||
*/ |
|
||||||
if (interfaceImplementations == null) |
|
||||||
interfaceImplementations = new List<IMemberReference>(); |
|
||||||
return interfaceImplementations; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public bool IsVirtual { |
|
||||||
get { return flags[FlagVirtual]; } |
|
||||||
set { |
|
||||||
ThrowIfFrozen(); |
|
||||||
flags[FlagVirtual] = value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public bool IsOverride { |
|
||||||
get { return flags[FlagOverride]; } |
|
||||||
set { |
|
||||||
ThrowIfFrozen(); |
|
||||||
flags[FlagOverride] = value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public bool IsOverridable { |
|
||||||
get { |
|
||||||
// override or virtual or abstract but not sealed
|
|
||||||
return (flags.Data & (FlagOverride | FlagVirtual | FlagAbstract)) != 0 && !this.IsSealed; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
ITypeReference IMemberReference.DeclaringTypeReference { |
|
||||||
get { return this.DeclaringTypeDefinition; } |
|
||||||
} |
|
||||||
|
|
||||||
#region Resolve
|
|
||||||
public abstract IMember CreateResolved(ITypeResolveContext context); |
|
||||||
|
|
||||||
public virtual IMember Resolve(ITypeResolveContext context) |
|
||||||
{ |
|
||||||
ITypeReference interfaceTypeReference = null; |
|
||||||
if (this.IsExplicitInterfaceImplementation && this.ExplicitInterfaceImplementations.Count == 1) |
|
||||||
interfaceTypeReference = this.ExplicitInterfaceImplementations[0].DeclaringTypeReference; |
|
||||||
return Resolve(ExtendContextForType(context, this.DeclaringTypeDefinition), this.SymbolKind, this.Name, interfaceTypeReference); |
|
||||||
} |
|
||||||
|
|
||||||
protected static ITypeResolveContext ExtendContextForType(ITypeResolveContext assemblyContext, IUnresolvedTypeDefinition typeDef) |
|
||||||
{ |
|
||||||
if (typeDef == null) |
|
||||||
return assemblyContext; |
|
||||||
ITypeResolveContext parentContext; |
|
||||||
if (typeDef.DeclaringTypeDefinition != null) |
|
||||||
parentContext = ExtendContextForType(assemblyContext, typeDef.DeclaringTypeDefinition); |
|
||||||
else |
|
||||||
parentContext = assemblyContext; |
|
||||||
ITypeDefinition resolvedTypeDef = typeDef.Resolve(assemblyContext).GetDefinition(); |
|
||||||
return typeDef.CreateResolveContext(parentContext).WithCurrentTypeDefinition(resolvedTypeDef); |
|
||||||
} |
|
||||||
|
|
||||||
public static IMember Resolve(ITypeResolveContext context, |
|
||||||
SymbolKind symbolKind, |
|
||||||
string name, |
|
||||||
ITypeReference explicitInterfaceTypeReference = null, |
|
||||||
IList<string> typeParameterNames = null, |
|
||||||
IList<ITypeReference> parameterTypeReferences = null) |
|
||||||
{ |
|
||||||
if (context.CurrentTypeDefinition == null) |
|
||||||
return null; |
|
||||||
if (parameterTypeReferences == null) |
|
||||||
parameterTypeReferences = EmptyList<ITypeReference>.Instance; |
|
||||||
if (typeParameterNames == null || typeParameterNames.Count == 0) { |
|
||||||
// non-generic member
|
|
||||||
// In this case, we can simply resolve the parameter types in the given context
|
|
||||||
var parameterTypes = parameterTypeReferences.Resolve(context); |
|
||||||
if (explicitInterfaceTypeReference == null) { |
|
||||||
foreach (IMember member in context.CurrentTypeDefinition.Members) { |
|
||||||
if (member.IsExplicitInterfaceImplementation) |
|
||||||
continue; |
|
||||||
if (IsNonGenericMatch(member, symbolKind, name, parameterTypes)) |
|
||||||
return member; |
|
||||||
} |
|
||||||
} else { |
|
||||||
IType explicitInterfaceType = explicitInterfaceTypeReference.Resolve(context); |
|
||||||
foreach (IMember member in context.CurrentTypeDefinition.Members) { |
|
||||||
if (!member.IsExplicitInterfaceImplementation) |
|
||||||
continue; |
|
||||||
var interfaceMembers = member.ExplicitlyImplementedInterfaceMembers.ToList(); |
|
||||||
if (interfaceMembers.Count != 1) |
|
||||||
continue; |
|
||||||
if (IsNonGenericMatch(member, symbolKind, name, parameterTypes)) { |
|
||||||
if (explicitInterfaceType.Equals(interfaceMembers[0].DeclaringType)) |
|
||||||
return member; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} else { |
|
||||||
// generic member
|
|
||||||
// In this case, we must specify the correct context for resolving the parameter types
|
|
||||||
foreach (IMethod method in context.CurrentTypeDefinition.Methods) { |
|
||||||
if (method.SymbolKind != symbolKind) |
|
||||||
continue; |
|
||||||
if (method.Name != name) |
|
||||||
continue; |
|
||||||
if (method.Parameters.Count != parameterTypeReferences.Count) |
|
||||||
continue; |
|
||||||
// Compare type parameter count and names:
|
|
||||||
if (!typeParameterNames.SequenceEqual(method.TypeParameters.Select(tp => tp.Name))) |
|
||||||
continue; |
|
||||||
// Once we know the type parameter names are fitting, we can resolve the
|
|
||||||
// type references in the context of the method:
|
|
||||||
var contextForMethod = context.WithCurrentMember(method); |
|
||||||
var parameterTypes = parameterTypeReferences.Resolve(contextForMethod); |
|
||||||
if (!IsParameterTypeMatch(method, parameterTypes)) |
|
||||||
continue; |
|
||||||
if (explicitInterfaceTypeReference == null) { |
|
||||||
if (!method.IsExplicitInterfaceImplementation) |
|
||||||
return method; |
|
||||||
} else if (method.IsExplicitInterfaceImplementation && method.ExplicitlyImplementedInterfaceMembers.Count() == 1) { |
|
||||||
IType explicitInterfaceType = explicitInterfaceTypeReference.Resolve(contextForMethod); |
|
||||||
if (explicitInterfaceType.Equals(method.ExplicitlyImplementedInterfaceMembers.First().DeclaringType)) |
|
||||||
return method; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
static bool IsNonGenericMatch(IMember member, SymbolKind symbolKind, string name, IReadOnlyList<IType> parameterTypes) |
|
||||||
{ |
|
||||||
if (member.SymbolKind != symbolKind) |
|
||||||
return false; |
|
||||||
if (member.Name != name) |
|
||||||
return false; |
|
||||||
IMethod method = member as IMethod; |
|
||||||
if (method != null && method.TypeParameters.Count > 0) |
|
||||||
return false; |
|
||||||
return IsParameterTypeMatch(member, parameterTypes); |
|
||||||
} |
|
||||||
|
|
||||||
static bool IsParameterTypeMatch(IMember member, IReadOnlyList<IType> parameterTypes) |
|
||||||
{ |
|
||||||
IParameterizedMember parameterizedMember = member as IParameterizedMember; |
|
||||||
if (parameterizedMember == null) { |
|
||||||
return parameterTypes.Count == 0; |
|
||||||
} else if (parameterTypes.Count == parameterizedMember.Parameters.Count) { |
|
||||||
for (int i = 0; i < parameterTypes.Count; i++) { |
|
||||||
IType type1 = parameterTypes[i]; |
|
||||||
IType type2 = parameterizedMember.Parameters[i].Type; |
|
||||||
if (!type1.Equals(type2)) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
return true; |
|
||||||
} else { |
|
||||||
return false; |
|
||||||
} |
|
||||||
} |
|
||||||
#endregion
|
|
||||||
} |
|
||||||
} |
|
@ -1,51 +0,0 @@ |
|||||||
// 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; |
|
||||||
|
|
||||||
namespace ICSharpCode.Decompiler.TypeSystem.Implementation |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Given a reference to an accessor, returns the accessor's owner.
|
|
||||||
/// </summary>
|
|
||||||
[Serializable] |
|
||||||
sealed class AccessorOwnerMemberReference : IMemberReference |
|
||||||
{ |
|
||||||
readonly IMemberReference accessorReference; |
|
||||||
|
|
||||||
public AccessorOwnerMemberReference(IMemberReference accessorReference) |
|
||||||
{ |
|
||||||
if (accessorReference == null) |
|
||||||
throw new ArgumentNullException("accessorReference"); |
|
||||||
this.accessorReference = accessorReference; |
|
||||||
} |
|
||||||
|
|
||||||
public ITypeReference DeclaringTypeReference { |
|
||||||
get { return accessorReference.DeclaringTypeReference; } |
|
||||||
} |
|
||||||
|
|
||||||
public IMember Resolve(ITypeResolveContext context) |
|
||||||
{ |
|
||||||
IMethod method = accessorReference.Resolve(context) as IMethod; |
|
||||||
if (method != null) |
|
||||||
return method.AccessorOwner; |
|
||||||
else |
|
||||||
return null; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,399 +0,0 @@ |
|||||||
//
|
|
||||||
// BlobReader.cs
|
|
||||||
//
|
|
||||||
// Author:
|
|
||||||
// Daniel Grunwald <daniel@danielgrunwald.de>
|
|
||||||
//
|
|
||||||
// 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 ICSharpCode.Decompiler.Semantics; |
|
||||||
|
|
||||||
namespace ICSharpCode.Decompiler.TypeSystem.Implementation |
|
||||||
{ |
|
||||||
sealed class BlobReader |
|
||||||
{ |
|
||||||
internal static int GetBlobHashCode(byte[] blob) |
|
||||||
{ |
|
||||||
unchecked { |
|
||||||
int hash = 0; |
|
||||||
foreach (byte b in blob) { |
|
||||||
hash *= 257; |
|
||||||
hash += b; |
|
||||||
} |
|
||||||
return hash; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
internal static bool BlobEquals(byte[] a, byte[] b) |
|
||||||
{ |
|
||||||
if (a.Length != b.Length) |
|
||||||
return false; |
|
||||||
for (int i = 0; i < a.Length; i++) { |
|
||||||
if (a[i] != b[i]) |
|
||||||
return false; |
|
||||||
} |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
byte[] buffer; |
|
||||||
int position; |
|
||||||
readonly IAssembly currentResolvedAssembly; |
|
||||||
|
|
||||||
public BlobReader(byte[] buffer, IAssembly currentResolvedAssembly) |
|
||||||
{ |
|
||||||
if (buffer == null) |
|
||||||
throw new ArgumentNullException("buffer"); |
|
||||||
this.buffer = buffer; |
|
||||||
this.currentResolvedAssembly = currentResolvedAssembly; |
|
||||||
} |
|
||||||
|
|
||||||
public byte ReadByte() |
|
||||||
{ |
|
||||||
return buffer[position++]; |
|
||||||
} |
|
||||||
|
|
||||||
public sbyte ReadSByte() |
|
||||||
{ |
|
||||||
unchecked { |
|
||||||
return(sbyte) ReadByte(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public byte[] ReadBytes(int length) |
|
||||||
{ |
|
||||||
var bytes = new byte[length]; |
|
||||||
Buffer.BlockCopy(buffer, position, bytes, 0, length); |
|
||||||
position += length; |
|
||||||
return bytes; |
|
||||||
} |
|
||||||
|
|
||||||
public ushort ReadUInt16() |
|
||||||
{ |
|
||||||
unchecked { |
|
||||||
ushort value =(ushort)(buffer[position] |
|
||||||
|(buffer[position + 1] << 8)); |
|
||||||
position += 2; |
|
||||||
return value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public short ReadInt16() |
|
||||||
{ |
|
||||||
unchecked { |
|
||||||
return(short) ReadUInt16(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public uint ReadUInt32() |
|
||||||
{ |
|
||||||
unchecked { |
|
||||||
uint value =(uint)(buffer[position] |
|
||||||
|(buffer[position + 1] << 8) |
|
||||||
|(buffer[position + 2] << 16) |
|
||||||
|(buffer[position + 3] << 24)); |
|
||||||
position += 4; |
|
||||||
return value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public int ReadInt32() |
|
||||||
{ |
|
||||||
unchecked { |
|
||||||
return(int) ReadUInt32(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public ulong ReadUInt64() |
|
||||||
{ |
|
||||||
unchecked { |
|
||||||
uint low = ReadUInt32(); |
|
||||||
uint high = ReadUInt32(); |
|
||||||
|
|
||||||
return(((ulong) high) << 32) | low; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public long ReadInt64() |
|
||||||
{ |
|
||||||
unchecked { |
|
||||||
return(long) ReadUInt64(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public uint ReadCompressedUInt32() |
|
||||||
{ |
|
||||||
unchecked { |
|
||||||
byte first = ReadByte(); |
|
||||||
if((first & 0x80) == 0) |
|
||||||
return first; |
|
||||||
|
|
||||||
if((first & 0x40) == 0) |
|
||||||
return((uint)(first & ~0x80) << 8) |
|
||||||
| ReadByte(); |
|
||||||
|
|
||||||
return((uint)(first & ~0xc0) << 24) |
|
||||||
|(uint) ReadByte() << 16 |
|
||||||
|(uint) ReadByte() << 8 |
|
||||||
| ReadByte(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public float ReadSingle() |
|
||||||
{ |
|
||||||
unchecked { |
|
||||||
if(!BitConverter.IsLittleEndian) { |
|
||||||
var bytes = ReadBytes(4); |
|
||||||
Array.Reverse(bytes); |
|
||||||
return BitConverter.ToSingle(bytes, 0); |
|
||||||
} |
|
||||||
|
|
||||||
float value = BitConverter.ToSingle(buffer, position); |
|
||||||
position += 4; |
|
||||||
return value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public double ReadDouble() |
|
||||||
{ |
|
||||||
unchecked { |
|
||||||
if(!BitConverter.IsLittleEndian) { |
|
||||||
var bytes = ReadBytes(8); |
|
||||||
Array.Reverse(bytes); |
|
||||||
return BitConverter.ToDouble(bytes, 0); |
|
||||||
} |
|
||||||
|
|
||||||
double value = BitConverter.ToDouble(buffer, position); |
|
||||||
position += 8; |
|
||||||
return value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public ResolveResult ReadFixedArg(IType argType) |
|
||||||
{ |
|
||||||
if (argType.Kind == TypeKind.Array) { |
|
||||||
if (((ArrayType)argType).Dimensions != 1) { |
|
||||||
// Only single-dimensional arrays are supported
|
|
||||||
return ErrorResolveResult.UnknownError; |
|
||||||
} |
|
||||||
IType elementType = ((ArrayType)argType).ElementType; |
|
||||||
uint numElem = ReadUInt32(); |
|
||||||
if (numElem == 0xffffffff) { |
|
||||||
// null reference
|
|
||||||
return new ConstantResolveResult(argType, null); |
|
||||||
} else { |
|
||||||
ResolveResult[] elements = new ResolveResult[numElem]; |
|
||||||
for (int i = 0; i < elements.Length; i++) { |
|
||||||
elements[i] = ReadElem(elementType); |
|
||||||
// Stop decoding when encountering an error:
|
|
||||||
if (elements[i].IsError) |
|
||||||
return ErrorResolveResult.UnknownError; |
|
||||||
} |
|
||||||
IType int32 = currentResolvedAssembly.Compilation.FindType(KnownTypeCode.Int32); |
|
||||||
ResolveResult[] sizeArgs = { new ConstantResolveResult(int32, elements.Length) }; |
|
||||||
return new ArrayCreateResolveResult(argType, sizeArgs, elements); |
|
||||||
} |
|
||||||
} else { |
|
||||||
return ReadElem(argType); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public ResolveResult ReadElem(IType elementType) |
|
||||||
{ |
|
||||||
ITypeDefinition underlyingType; |
|
||||||
if (elementType.Kind == TypeKind.Enum) { |
|
||||||
underlyingType = elementType.GetDefinition().EnumUnderlyingType.GetDefinition(); |
|
||||||
} else { |
|
||||||
underlyingType = elementType.GetDefinition(); |
|
||||||
} |
|
||||||
if (underlyingType == null) |
|
||||||
return ErrorResolveResult.UnknownError; |
|
||||||
KnownTypeCode typeCode = underlyingType.KnownTypeCode; |
|
||||||
if (typeCode == KnownTypeCode.Object) { |
|
||||||
// boxed value type
|
|
||||||
IType boxedTyped = ReadCustomAttributeFieldOrPropType(); |
|
||||||
ResolveResult elem = ReadFixedArg(boxedTyped); |
|
||||||
if (elem.IsCompileTimeConstant && elem.ConstantValue == null) |
|
||||||
return new ConstantResolveResult(elementType, null); |
|
||||||
else |
|
||||||
return new ConversionResolveResult(elementType, elem, Conversion.BoxingConversion); |
|
||||||
} else if (typeCode == KnownTypeCode.Type) { |
|
||||||
var type = ReadType(); |
|
||||||
if (type != null) { |
|
||||||
return new TypeOfResolveResult(underlyingType, type); |
|
||||||
} else { |
|
||||||
return new ConstantResolveResult(underlyingType, null); |
|
||||||
} |
|
||||||
} else { |
|
||||||
return new ConstantResolveResult(elementType, ReadElemValue(typeCode)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
object ReadElemValue(KnownTypeCode typeCode) |
|
||||||
{ |
|
||||||
switch (typeCode) { |
|
||||||
case KnownTypeCode.Boolean: |
|
||||||
return ReadByte() != 0; |
|
||||||
case KnownTypeCode.Char: |
|
||||||
return (char)ReadUInt16(); |
|
||||||
case KnownTypeCode.SByte: |
|
||||||
return ReadSByte(); |
|
||||||
case KnownTypeCode.Byte: |
|
||||||
return ReadByte(); |
|
||||||
case KnownTypeCode.Int16: |
|
||||||
return ReadInt16(); |
|
||||||
case KnownTypeCode.UInt16: |
|
||||||
return ReadUInt16(); |
|
||||||
case KnownTypeCode.Int32: |
|
||||||
return ReadInt32(); |
|
||||||
case KnownTypeCode.UInt32: |
|
||||||
return ReadUInt32(); |
|
||||||
case KnownTypeCode.Int64: |
|
||||||
return ReadInt64(); |
|
||||||
case KnownTypeCode.UInt64: |
|
||||||
return ReadUInt64(); |
|
||||||
case KnownTypeCode.Single: |
|
||||||
return ReadSingle(); |
|
||||||
case KnownTypeCode.Double: |
|
||||||
return ReadDouble(); |
|
||||||
case KnownTypeCode.String: |
|
||||||
return ReadSerString(); |
|
||||||
default: |
|
||||||
throw new NotSupportedException(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public string ReadSerString () |
|
||||||
{ |
|
||||||
if (buffer [position] == 0xff) { |
|
||||||
position++; |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
int length = (int) ReadCompressedUInt32(); |
|
||||||
if (length == 0) |
|
||||||
return string.Empty; |
|
||||||
|
|
||||||
string @string = System.Text.Encoding.UTF8.GetString( |
|
||||||
buffer, position, |
|
||||||
buffer [position + length - 1] == 0 ? length - 1 : length); |
|
||||||
|
|
||||||
position += length; |
|
||||||
return @string; |
|
||||||
} |
|
||||||
|
|
||||||
public KeyValuePair<IMember, ResolveResult> ReadNamedArg(IType attributeType) |
|
||||||
{ |
|
||||||
SymbolKind memberType; |
|
||||||
var b = ReadByte(); |
|
||||||
switch (b) { |
|
||||||
case 0x53: |
|
||||||
memberType = SymbolKind.Field; |
|
||||||
break; |
|
||||||
case 0x54: |
|
||||||
memberType = SymbolKind.Property; |
|
||||||
break; |
|
||||||
default: |
|
||||||
throw new NotSupportedException(string.Format("Custom member type 0x{0:x} is not supported.", b)); |
|
||||||
} |
|
||||||
IType type = ReadCustomAttributeFieldOrPropType(); |
|
||||||
string name = ReadSerString(); |
|
||||||
ResolveResult val = ReadFixedArg(type); |
|
||||||
IMember member = null; |
|
||||||
// Use last matching member, as GetMembers() returns members from base types first.
|
|
||||||
foreach (IMember m in attributeType.GetMembers(m => m.SymbolKind == memberType && m.Name == name)) { |
|
||||||
if (m.ReturnType.Equals(type)) |
|
||||||
member = m; |
|
||||||
} |
|
||||||
return new KeyValuePair<IMember, ResolveResult>(member, val); |
|
||||||
} |
|
||||||
|
|
||||||
IType ReadCustomAttributeFieldOrPropType() |
|
||||||
{ |
|
||||||
ICompilation compilation = currentResolvedAssembly.Compilation; |
|
||||||
var b = ReadByte(); |
|
||||||
switch (b) { |
|
||||||
case 0x02: |
|
||||||
return compilation.FindType(KnownTypeCode.Boolean); |
|
||||||
case 0x03: |
|
||||||
return compilation.FindType(KnownTypeCode.Char); |
|
||||||
case 0x04: |
|
||||||
return compilation.FindType(KnownTypeCode.SByte); |
|
||||||
case 0x05: |
|
||||||
return compilation.FindType(KnownTypeCode.Byte); |
|
||||||
case 0x06: |
|
||||||
return compilation.FindType(KnownTypeCode.Int16); |
|
||||||
case 0x07: |
|
||||||
return compilation.FindType(KnownTypeCode.UInt16); |
|
||||||
case 0x08: |
|
||||||
return compilation.FindType(KnownTypeCode.Int32); |
|
||||||
case 0x09: |
|
||||||
return compilation.FindType(KnownTypeCode.UInt32); |
|
||||||
case 0x0a: |
|
||||||
return compilation.FindType(KnownTypeCode.Int64); |
|
||||||
case 0x0b: |
|
||||||
return compilation.FindType(KnownTypeCode.UInt64); |
|
||||||
case 0x0c: |
|
||||||
return compilation.FindType(KnownTypeCode.Single); |
|
||||||
case 0x0d: |
|
||||||
return compilation.FindType(KnownTypeCode.Double); |
|
||||||
case 0x0e: |
|
||||||
return compilation.FindType(KnownTypeCode.String); |
|
||||||
case 0x1d: |
|
||||||
return new ArrayType(compilation, ReadCustomAttributeFieldOrPropType()); |
|
||||||
case 0x50: |
|
||||||
return compilation.FindType(KnownTypeCode.Type); |
|
||||||
case 0x51: // boxed value type
|
|
||||||
return compilation.FindType(KnownTypeCode.Object); |
|
||||||
case 0x55: // enum
|
|
||||||
var type = ReadType(); |
|
||||||
if (type == null) { |
|
||||||
throw new NotSupportedException("Enum type should not be null."); |
|
||||||
} |
|
||||||
return type; |
|
||||||
default: |
|
||||||
throw new NotSupportedException(string.Format("Custom attribute type 0x{0:x} is not supported.", b)); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
IType ReadType() |
|
||||||
{ |
|
||||||
string typeName = ReadSerString(); |
|
||||||
if (typeName == null) { |
|
||||||
return null; |
|
||||||
} |
|
||||||
ITypeReference typeReference = ReflectionHelper.ParseReflectionName(typeName); |
|
||||||
IType typeInCurrentAssembly = typeReference.Resolve(new SimpleTypeResolveContext(currentResolvedAssembly)); |
|
||||||
if (typeInCurrentAssembly.Kind != TypeKind.Unknown) |
|
||||||
return typeInCurrentAssembly; |
|
||||||
|
|
||||||
// look for the type in mscorlib
|
|
||||||
ITypeDefinition systemObject = currentResolvedAssembly.Compilation.FindType(KnownTypeCode.Object).GetDefinition(); |
|
||||||
if (systemObject != null) { |
|
||||||
return typeReference.Resolve(new SimpleTypeResolveContext(systemObject.ParentAssembly)); |
|
||||||
} else { |
|
||||||
// couldn't find corlib - return the unknown IType for the current assembly
|
|
||||||
return typeInCurrentAssembly; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,115 +0,0 @@ |
|||||||
// 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 ICSharpCode.Decompiler.Util; |
|
||||||
|
|
||||||
namespace ICSharpCode.Decompiler.TypeSystem.Implementation |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// 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.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// Resolving a DefaultMemberReference requires a context that provides enough information for resolving the declaring type reference
|
|
||||||
/// and the parameter types references.
|
|
||||||
/// </remarks>
|
|
||||||
[Serializable] |
|
||||||
public sealed class DefaultMemberReference : IMemberReference, ISupportsInterning |
|
||||||
{ |
|
||||||
readonly SymbolKind symbolKind; |
|
||||||
readonly ITypeReference typeReference; |
|
||||||
readonly string name; |
|
||||||
readonly int typeParameterCount; |
|
||||||
readonly IList<ITypeReference> parameterTypes; |
|
||||||
|
|
||||||
public DefaultMemberReference(SymbolKind symbolKind, ITypeReference typeReference, string name, int typeParameterCount = 0, IList<ITypeReference> 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<ITypeReference>.Instance; |
|
||||||
} |
|
||||||
|
|
||||||
public ITypeReference DeclaringTypeReference { |
|
||||||
get { return typeReference; } |
|
||||||
} |
|
||||||
|
|
||||||
static readonly NormalizeTypeVisitor normalizeTypeVisitor = new NormalizeTypeVisitor(); |
|
||||||
|
|
||||||
public IMember Resolve(ITypeResolveContext context) |
|
||||||
{ |
|
||||||
IType type = typeReference.Resolve(context); |
|
||||||
IEnumerable<IMember> 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 = resolvedParameterTypes[i].AcceptVisitor(normalizeTypeVisitor); |
|
||||||
IType type2 = parameterizedMember.Parameters[i].Type.AcceptVisitor(normalizeTypeVisitor); |
|
||||||
if (!type1.Equals(type2)) { |
|
||||||
signatureMatches = false; |
|
||||||
break; |
|
||||||
} |
|
||||||
} |
|
||||||
if (signatureMatches) |
|
||||||
return member; |
|
||||||
} |
|
||||||
} |
|
||||||
return null; |
|
||||||
} |
|
||||||
|
|
||||||
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; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,69 +0,0 @@ |
|||||||
// 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 ICSharpCode.Decompiler.Semantics; |
|
||||||
|
|
||||||
namespace ICSharpCode.Decompiler.TypeSystem.Implementation |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// A simple constant value that is independent of the resolve context.
|
|
||||||
/// </summary>
|
|
||||||
[Serializable] |
|
||||||
public sealed class SimpleConstantValue : IConstantValue, ISupportsInterning |
|
||||||
{ |
|
||||||
readonly ITypeReference type; |
|
||||||
readonly object value; |
|
||||||
|
|
||||||
public SimpleConstantValue(ITypeReference type, object value) |
|
||||||
{ |
|
||||||
if (type == null) |
|
||||||
throw new ArgumentNullException("type"); |
|
||||||
this.type = type; |
|
||||||
this.value = value; |
|
||||||
} |
|
||||||
|
|
||||||
public ResolveResult Resolve(ITypeResolveContext context) |
|
||||||
{ |
|
||||||
return new ConstantResolveResult(type.Resolve(context), value); |
|
||||||
} |
|
||||||
|
|
||||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1308:NormalizeStringsToUppercase", |
|
||||||
Justification = "The C# keyword is lower case")] |
|
||||||
public override string ToString() |
|
||||||
{ |
|
||||||
if (value == null) |
|
||||||
return "null"; |
|
||||||
else if (value is bool) |
|
||||||
return value.ToString().ToLowerInvariant(); |
|
||||||
else |
|
||||||
return value.ToString(); |
|
||||||
} |
|
||||||
|
|
||||||
int ISupportsInterning.GetHashCodeForInterning() |
|
||||||
{ |
|
||||||
return type.GetHashCode() ^ (value != null ? value.GetHashCode() : 0); |
|
||||||
} |
|
||||||
|
|
||||||
bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) |
|
||||||
{ |
|
||||||
SimpleConstantValue scv = other as SimpleConstantValue; |
|
||||||
return scv != null && type == scv.type && value == scv.value; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
@ -1,140 +0,0 @@ |
|||||||
// 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.Collections; |
|
||||||
using System.Collections.Generic; |
|
||||||
using System.Collections.ObjectModel; |
|
||||||
using System.Runtime.CompilerServices; |
|
||||||
using ICSharpCode.Decompiler.Util; |
|
||||||
|
|
||||||
namespace ICSharpCode.Decompiler.TypeSystem.Implementation |
|
||||||
{ |
|
||||||
/// <summary>
|
|
||||||
/// Simple interning provider.
|
|
||||||
/// </summary>
|
|
||||||
public sealed class SimpleInterningProvider : InterningProvider |
|
||||||
{ |
|
||||||
sealed class InterningComparer : IEqualityComparer<ISupportsInterning> |
|
||||||
{ |
|
||||||
public bool Equals(ISupportsInterning x, ISupportsInterning y) |
|
||||||
{ |
|
||||||
return x.EqualsForInterning(y); |
|
||||||
} |
|
||||||
|
|
||||||
public int GetHashCode(ISupportsInterning obj) |
|
||||||
{ |
|
||||||
return obj.GetHashCodeForInterning(); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
sealed class ListComparer : IEqualityComparer<IEnumerable> |
|
||||||
{ |
|
||||||
public bool Equals(IEnumerable a, IEnumerable b) |
|
||||||
{ |
|
||||||
if (a.GetType() != b.GetType()) |
|
||||||
return false; |
|
||||||
IEnumerator e1 = a.GetEnumerator(); |
|
||||||
IEnumerator e2 = b.GetEnumerator(); |
|
||||||
while (e1.MoveNext()) { |
|
||||||
// e1 has more elements than e2; or elements are different
|
|
||||||
if (!e2.MoveNext() || e1.Current != e2.Current) |
|
||||||
return false; |
|
||||||
} |
|
||||||
if (e2.MoveNext()) // e2 has more elements than e1
|
|
||||||
return false; |
|
||||||
// No need to dispose e1/e2: non-generic IEnumerator doesn't implement IDisposable,
|
|
||||||
// and the underlying enumerator will likely be a List<T>.Enumerator which has an empty Dispose() method.
|
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
public int GetHashCode(IEnumerable obj) |
|
||||||
{ |
|
||||||
int hashCode = obj.GetType().GetHashCode(); |
|
||||||
unchecked { |
|
||||||
foreach (object o in obj) { |
|
||||||
hashCode *= 27; |
|
||||||
hashCode += RuntimeHelpers.GetHashCode(o); |
|
||||||
} |
|
||||||
} |
|
||||||
return hashCode; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
Dictionary<object, object> byValueDict = new Dictionary<object, object>(); |
|
||||||
Dictionary<ISupportsInterning, ISupportsInterning> supportsInternDict = new Dictionary<ISupportsInterning, ISupportsInterning>(new InterningComparer()); |
|
||||||
Dictionary<IEnumerable, IEnumerable> listDict = new Dictionary<IEnumerable, IEnumerable>(new ListComparer()); |
|
||||||
|
|
||||||
public override ISupportsInterning Intern(ISupportsInterning obj) |
|
||||||
{ |
|
||||||
if (obj == null) |
|
||||||
return null; |
|
||||||
|
|
||||||
// ensure objects are frozen when we put them into the dictionary
|
|
||||||
// note that Freeze may change the hash code of the object
|
|
||||||
FreezableHelper.Freeze(obj); |
|
||||||
|
|
||||||
ISupportsInterning output; |
|
||||||
if (supportsInternDict.TryGetValue(obj, out output)) { |
|
||||||
return output; |
|
||||||
} else { |
|
||||||
supportsInternDict.Add(obj, obj); |
|
||||||
return obj; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
public override string Intern(string text) |
|
||||||
{ |
|
||||||
if (text == null) |
|
||||||
return null; |
|
||||||
|
|
||||||
object output; |
|
||||||
if (byValueDict.TryGetValue(text, out output)) |
|
||||||
return (string)output; |
|
||||||
else |
|
||||||
return text; |
|
||||||
} |
|
||||||
|
|
||||||
public override object InternValue(object obj) |
|
||||||
{ |
|
||||||
if (obj == null) |
|
||||||
return null; |
|
||||||
|
|
||||||
object output; |
|
||||||
if (byValueDict.TryGetValue(obj, out output)) |
|
||||||
return output; |
|
||||||
else |
|
||||||
return obj; |
|
||||||
} |
|
||||||
|
|
||||||
public override IList<T> InternList<T>(IList<T> list) |
|
||||||
{ |
|
||||||
if (list == null) |
|
||||||
return null; |
|
||||||
if (list.Count == 0) |
|
||||||
return EmptyList<T>.Instance; |
|
||||||
if (!list.IsReadOnly) |
|
||||||
list = new ReadOnlyCollection<T>(list); |
|
||||||
IEnumerable output; |
|
||||||
if (listDict.TryGetValue(list, out output)) |
|
||||||
list = (IList<T>)output; |
|
||||||
else |
|
||||||
listDict.Add(list, list); |
|
||||||
return list; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
Loading…
Reference in new issue