mirror of https://github.com/icsharpcode/ILSpy.git
8 changed files with 333 additions and 36 deletions
@ -0,0 +1,228 @@
@@ -0,0 +1,228 @@
|
||||
// Copyright (c) 2018 Daniel Grunwald
|
||||
//
|
||||
// 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.Diagnostics; |
||||
using System.Linq; |
||||
using System.Reflection; |
||||
using System.Reflection.Metadata; |
||||
using System.Reflection.Metadata.Ecma335; |
||||
using System.Runtime.CompilerServices; |
||||
using System.Runtime.InteropServices; |
||||
using ICSharpCode.Decompiler.Semantics; |
||||
using ICSharpCode.Decompiler.Util; |
||||
|
||||
namespace ICSharpCode.Decompiler.TypeSystem.Implementation |
||||
{ |
||||
sealed class MetadataProperty : IProperty |
||||
{ |
||||
const Accessibility InvalidAccessibility = (Accessibility)0xff; |
||||
|
||||
readonly MetadataAssembly assembly; |
||||
readonly PropertyDefinitionHandle propertyHandle; |
||||
readonly MethodDefinitionHandle getterHandle; |
||||
readonly MethodDefinitionHandle setterHandle; |
||||
|
||||
// lazy-loaded:
|
||||
string name; |
||||
IAttribute[] customAttributes; |
||||
volatile Accessibility cachedAccessiblity = InvalidAccessibility; |
||||
IParameter[] parameters; |
||||
IType returnType; |
||||
|
||||
internal MetadataProperty(MetadataAssembly assembly, PropertyDefinitionHandle handle) |
||||
{ |
||||
Debug.Assert(assembly != null); |
||||
Debug.Assert(!handle.IsNil); |
||||
this.assembly = assembly; |
||||
this.propertyHandle = handle; |
||||
|
||||
var metadata = assembly.metadata; |
||||
var prop = metadata.GetPropertyDefinition(handle); |
||||
var accessors = prop.GetAccessors(); |
||||
getterHandle = accessors.Getter; |
||||
setterHandle = accessors.Setter; |
||||
} |
||||
|
||||
public EntityHandle MetadataToken => propertyHandle; |
||||
|
||||
public string Name { |
||||
get { |
||||
string name = LazyInit.VolatileRead(ref this.name); |
||||
if (name != null) |
||||
return name; |
||||
var metadata = assembly.metadata; |
||||
var propertyDef = metadata.GetPropertyDefinition(propertyHandle); |
||||
return LazyInit.GetOrSet(ref this.name, metadata.GetString(propertyDef.Name)); |
||||
} |
||||
} |
||||
|
||||
public bool CanGet => !getterHandle.IsNil; |
||||
public bool CanSet => !setterHandle.IsNil; |
||||
|
||||
public IMethod Getter => assembly.GetDefinition(getterHandle); |
||||
public IMethod Setter => assembly.GetDefinition(setterHandle); |
||||
|
||||
public bool IsIndexer => SymbolKind == SymbolKind.Indexer; |
||||
public SymbolKind SymbolKind => throw new NotImplementedException(); |
||||
|
||||
#region Signature (ReturnType + Parameters)
|
||||
public IReadOnlyList<IParameter> Parameters { |
||||
get { |
||||
var parameters = LazyInit.VolatileRead(ref this.parameters); |
||||
if (parameters != null) |
||||
return parameters; |
||||
DecodeSignature(); |
||||
return this.parameters; |
||||
} |
||||
} |
||||
|
||||
public IType ReturnType { |
||||
get { |
||||
var returnType = LazyInit.VolatileRead(ref this.returnType); |
||||
if (returnType != null) |
||||
return returnType; |
||||
DecodeSignature(); |
||||
return this.returnType; |
||||
} |
||||
} |
||||
|
||||
private void DecodeSignature() |
||||
{ |
||||
var propertyDef = assembly.metadata.GetPropertyDefinition(propertyHandle); |
||||
var genericContext = new GenericContext(DeclaringType.TypeParameters); |
||||
var signature = propertyDef.DecodeSignature(assembly.TypeProvider, genericContext); |
||||
ParameterHandleCollection? parameterHandles; |
||||
if (!getterHandle.IsNil) |
||||
parameterHandles = assembly.metadata.GetMethodDefinition(getterHandle).GetParameters(); |
||||
else if (!setterHandle.IsNil) |
||||
parameterHandles = assembly.metadata.GetMethodDefinition(setterHandle).GetParameters(); |
||||
else |
||||
parameterHandles = null; |
||||
var (returnType, parameters) = MetadataMethod.DecodeSignature(assembly, this, signature, parameterHandles); |
||||
LazyInit.GetOrSet(ref this.returnType, returnType); |
||||
LazyInit.GetOrSet(ref this.parameters, parameters); |
||||
} |
||||
#endregion
|
||||
|
||||
public IReadOnlyList<IMember> ImplementedInterfaceMembers => throw new NotImplementedException(); |
||||
|
||||
public bool IsExplicitInterfaceImplementation => throw new NotImplementedException(); |
||||
|
||||
public ITypeDefinition DeclaringTypeDefinition => (Getter ?? Setter)?.DeclaringTypeDefinition; |
||||
public IType DeclaringType => (Getter ?? Setter)?.DeclaringType; |
||||
IMember IMember.MemberDefinition => this; |
||||
TypeParameterSubstitution IMember.Substitution => TypeParameterSubstitution.Identity; |
||||
|
||||
#region Attributes
|
||||
public IReadOnlyList<IAttribute> Attributes { |
||||
get { |
||||
var attr = LazyInit.VolatileRead(ref this.customAttributes); |
||||
if (attr != null) |
||||
return attr; |
||||
return LazyInit.GetOrSet(ref this.customAttributes, DecodeAttributes()); |
||||
} |
||||
} |
||||
|
||||
IAttribute[] DecodeAttributes() |
||||
{ |
||||
var b = new AttributeListBuilder(assembly); |
||||
var metadata = assembly.metadata; |
||||
var propertyDef = metadata.GetPropertyDefinition(propertyHandle); |
||||
b.Add(propertyDef.GetCustomAttributes()); |
||||
return b.Build(); |
||||
} |
||||
#endregion
|
||||
|
||||
#region Accessibility
|
||||
public Accessibility Accessibility { |
||||
get { |
||||
var acc = cachedAccessiblity; |
||||
if (acc == InvalidAccessibility) |
||||
return cachedAccessiblity = ComputeAccessibility(); |
||||
else |
||||
return acc; |
||||
} |
||||
} |
||||
|
||||
Accessibility ComputeAccessibility() |
||||
{ |
||||
if (IsOverride && (getterHandle.IsNil || setterHandle.IsNil)) { |
||||
foreach (var baseMember in InheritanceHelper.GetBaseMembers(this, includeImplementedInterfaces: false)) { |
||||
if (!baseMember.IsOverride) |
||||
return baseMember.Accessibility; |
||||
} |
||||
} |
||||
return MergePropertyAccessibility( |
||||
this.Getter?.Accessibility ?? Accessibility.None, |
||||
this.Setter?.Accessibility ?? Accessibility.None); |
||||
} |
||||
|
||||
static internal Accessibility MergePropertyAccessibility(Accessibility left, Accessibility right) |
||||
{ |
||||
if (left == Accessibility.Public || right == Accessibility.Public) |
||||
return Accessibility.Public; |
||||
|
||||
if (left == Accessibility.ProtectedOrInternal || right == Accessibility.ProtectedOrInternal) |
||||
return Accessibility.ProtectedOrInternal; |
||||
|
||||
if (left == Accessibility.Protected && right == Accessibility.Internal || |
||||
left == Accessibility.Internal && right == Accessibility.Protected) |
||||
return Accessibility.ProtectedOrInternal; |
||||
|
||||
if (left == Accessibility.Protected || right == Accessibility.Protected) |
||||
return Accessibility.Protected; |
||||
|
||||
if (left == Accessibility.Internal || right == Accessibility.Internal) |
||||
return Accessibility.Internal; |
||||
|
||||
if (left == Accessibility.ProtectedAndInternal || right == Accessibility.ProtectedAndInternal) |
||||
return Accessibility.ProtectedAndInternal; |
||||
|
||||
return left; |
||||
} |
||||
#endregion
|
||||
|
||||
public bool IsStatic => (Getter ?? Setter)?.IsStatic ?? false; |
||||
public bool IsAbstract => (Getter ?? Setter)?.IsAbstract ?? false; |
||||
public bool IsSealed => (Getter ?? Setter)?.IsSealed ?? false; |
||||
public bool IsVirtual => (Getter ?? Setter)?.IsVirtual ?? false; |
||||
public bool IsOverride => (Getter ?? Setter)?.IsOverride ?? false; |
||||
public bool IsOverridable => (Getter ?? Setter)?.IsOverridable ?? false; |
||||
|
||||
bool IEntity.IsShadowing => (Getter ?? Setter)?.IsShadowing ?? false; |
||||
|
||||
public IAssembly ParentAssembly => assembly; |
||||
public ICompilation Compilation => assembly.Compilation; |
||||
|
||||
public string FullName => $"{DeclaringType?.FullName}.{Name}"; |
||||
public string ReflectionName => $"{DeclaringType?.ReflectionName}.{Name}"; |
||||
public string Namespace => DeclaringType?.Namespace ?? string.Empty; |
||||
|
||||
bool IMember.Equals(IMember obj, TypeVisitor typeNormalization) |
||||
{ |
||||
return this == obj; |
||||
} |
||||
|
||||
public IMember Specialize(TypeParameterSubstitution substitution) |
||||
{ |
||||
return SpecializedProperty.Create(this, substitution); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,51 @@
@@ -0,0 +1,51 @@
|
||||
// Copyright (c) 2018 Daniel Grunwald
|
||||
//
|
||||
// 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.Diagnostics; |
||||
|
||||
namespace ICSharpCode.Decompiler.TypeSystem.Implementation |
||||
{ |
||||
sealed class SpecializedParameter : IParameter |
||||
{ |
||||
readonly IParameter baseParameter; |
||||
readonly IType newType; |
||||
readonly IParameterizedMember newOwner; |
||||
|
||||
public SpecializedParameter(IParameter baseParameter, IType newType, IParameterizedMember newOwner) |
||||
{ |
||||
Debug.Assert(baseParameter != null && newType != null); |
||||
this.baseParameter = baseParameter; |
||||
this.newType = newType; |
||||
this.newOwner = newOwner; |
||||
} |
||||
|
||||
IReadOnlyList<IAttribute> IParameter.Attributes => baseParameter.Attributes; |
||||
bool IParameter.IsRef => baseParameter.IsRef; |
||||
bool IParameter.IsOut => baseParameter.IsOptional; |
||||
bool IParameter.IsParams => baseParameter.IsParams; |
||||
bool IParameter.IsOptional => baseParameter.IsOptional; |
||||
IParameterizedMember IParameter.Owner => newOwner; |
||||
string IVariable.Name => baseParameter.Name; |
||||
string ISymbol.Name => baseParameter.Name; |
||||
IType IVariable.Type => newType; |
||||
bool IVariable.IsConst => baseParameter.IsConst; |
||||
object IVariable.ConstantValue => baseParameter.ConstantValue; |
||||
SymbolKind ISymbol.SymbolKind => SymbolKind.Parameter; |
||||
} |
||||
} |
Loading…
Reference in new issue