Browse Source

Add MetadataProperty.

pull/1198/head
Daniel Grunwald 7 years ago
parent
commit
bca3191169
  1. 2
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  2. 9
      ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedProperty.cs
  3. 32
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs
  4. 228
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs
  5. 6
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMember.cs
  6. 51
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs
  7. 12
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedProperty.cs
  8. 11
      ICSharpCode.Decompiler/TypeSystem/MetadataAssembly.cs

2
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -348,9 +348,11 @@ @@ -348,9 +348,11 @@
<Compile Include="TypeSystem\Implementation\MetadataMethod.cs" />
<Compile Include="TypeSystem\Implementation\MetadataNamespace.cs" />
<Compile Include="TypeSystem\Implementation\MetadataParameter.cs" />
<Compile Include="TypeSystem\Implementation\MetadataProperty.cs" />
<Compile Include="TypeSystem\Implementation\MetadataTypeDefinition.cs" />
<Compile Include="TypeSystem\Implementation\MetadataTypeParameter.cs" />
<Compile Include="TypeSystem\Implementation\MetadataTypeReference.cs" />
<Compile Include="TypeSystem\Implementation\SpecializedParameter.cs" />
<Compile Include="TypeSystem\MetadataAssembly.cs" />
<Compile Include="TypeSystem\ModifiedType.cs" />
<Compile Include="TypeSystem\Implementation\TypeSpecification.cs" />

9
ICSharpCode.Decompiler/TypeSystem/Implementation/DefaultResolvedProperty.cs

@ -86,14 +86,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -86,14 +86,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public override IMember Specialize(TypeParameterSubstitution substitution)
{
if (TypeParameterSubstitution.Identity.Equals(substitution)
|| DeclaringType.TypeParameterCount == 0)
{
return this;
}
if (substitution.MethodTypeArguments != null && substitution.MethodTypeArguments.Count > 0)
substitution = new TypeParameterSubstitution(substitution.ClassTypeArguments, EmptyList<IType>.Instance);
return new SpecializedProperty(this, substitution);
return SpecializedProperty.Create(this, substitution);
}
}
}

32
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs

@ -25,8 +25,6 @@ using System.Reflection.Metadata; @@ -25,8 +25,6 @@ using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Util;
@ -130,15 +128,23 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -130,15 +128,23 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
private void DecodeSignature()
{
var metadata = assembly.metadata;
var methodDef = metadata.GetMethodDefinition(handle);
var methodDef = assembly.metadata.GetMethodDefinition(handle);
var genericContext = new GenericContext(DeclaringType.TypeParameters, this.TypeParameters);
var signature = methodDef.DecodeSignature(assembly.TypeProvider, genericContext);
var (returnType, parameters) = DecodeSignature(assembly, this, signature, methodDef.GetParameters());
LazyInit.GetOrSet(ref this.returnType, returnType);
LazyInit.GetOrSet(ref this.parameters, parameters);
}
internal static (IType, IParameter[]) DecodeSignature(MetadataAssembly assembly, IParameterizedMember owner, MethodSignature<IType> signature, ParameterHandleCollection? parameterHandles)
{
var metadata = assembly.metadata;
int i = 0;
CustomAttributeHandleCollection? returnTypeAttributes = null;
IParameter[] parameters = new IParameter[signature.RequiredParameterCount
+ (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs ? 1 : 0)];
foreach (var parameterHandle in methodDef.GetParameters()) {
if (parameterHandles != null) {
foreach (var parameterHandle in parameterHandles) {
var par = metadata.GetParameter(parameterHandle);
if (par.SequenceNumber == 0) {
// "parameter" holds return type attributes
@ -146,28 +152,28 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -146,28 +152,28 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
} else if (par.SequenceNumber > 0 && i < signature.RequiredParameterCount) {
Debug.Assert(par.SequenceNumber - 1 == i);
var parameterType = ApplyAttributeTypeVisitor.ApplyAttributesToType(
signature.ParameterTypes[i], Compilation,
signature.ParameterTypes[i], assembly.Compilation,
par.GetCustomAttributes(), metadata, assembly.TypeSystemOptions);
parameters[i] = new MetadataParameter(assembly, this, parameterType, parameterHandle);
parameters[i] = new MetadataParameter(assembly, owner, parameterType, parameterHandle);
i++;
}
}
}
while (i < signature.RequiredParameterCount) {
var parameterType = ApplyAttributeTypeVisitor.ApplyAttributesToType(
signature.ParameterTypes[i], Compilation, null, metadata, assembly.TypeSystemOptions);
parameters[i] = new DefaultParameter(parameterType, name: string.Empty, owner: this,
signature.ParameterTypes[i], assembly.Compilation, null, metadata, assembly.TypeSystemOptions);
parameters[i] = new DefaultParameter(parameterType, name: string.Empty, owner,
isRef: parameterType.Kind == TypeKind.ByReference);
i++;
}
if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
parameters[i] = new DefaultParameter(SpecialType.ArgList, name: string.Empty, owner: this);
parameters[i] = new DefaultParameter(SpecialType.ArgList, name: string.Empty, owner);
i++;
}
Debug.Assert(i == parameters.Length);
var returnType = ApplyAttributeTypeVisitor.ApplyAttributesToType(signature.ReturnType,
Compilation, returnTypeAttributes, metadata, assembly.TypeSystemOptions);
LazyInit.GetOrSet(ref this.returnType, returnType);
LazyInit.GetOrSet(ref this.parameters, parameters);
assembly.Compilation, returnTypeAttributes, metadata, assembly.TypeSystemOptions);
return (returnType, parameters);
}
#endregion

228
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataProperty.cs

@ -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);
}
}
}

6
ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMember.cs

@ -302,11 +302,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -302,11 +302,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
for (int i = 0; i < parameters.Length; i++) {
var p = paramDefs[i];
IType newType = substitution(p.Type);
parameters[i] = new DefaultParameter(
newType, p.Name, this,
p.Attributes, p.IsRef, p.IsOut,
p.IsParams, p.IsOptional, p.ConstantValue
);
parameters[i] = new SpecializedParameter(p, newType, this);
}
return parameters;
}

51
ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedParameter.cs

@ -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;
}
}

12
ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedProperty.cs

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation
{
/// <summary>
@ -23,6 +25,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -23,6 +25,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
/// </summary>
public class SpecializedProperty : SpecializedParameterizedMember, IProperty
{
internal static IProperty Create(IProperty propertyDefinition, TypeParameterSubstitution substitution)
{
if (TypeParameterSubstitution.Identity.Equals(substitution) || propertyDefinition.DeclaringType.TypeParameterCount == 0) {
return propertyDefinition;
}
if (substitution.MethodTypeArguments != null && substitution.MethodTypeArguments.Count > 0)
substitution = new TypeParameterSubstitution(substitution.ClassTypeArguments, EmptyList<IType>.Instance);
return new SpecializedProperty(propertyDefinition, substitution);
}
readonly IProperty propertyDefinition;
public SpecializedProperty(IProperty propertyDefinition, TypeParameterSubstitution substitution)

11
ICSharpCode.Decompiler/TypeSystem/MetadataAssembly.cs

@ -50,6 +50,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -50,6 +50,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
readonly MetadataTypeDefinition[] typeDefs;
readonly MetadataField[] fieldDefs;
readonly MetadataMethod[] methodDefs;
readonly MetadataProperty[] propertyDefs;
internal MetadataAssembly(ICompilation compilation, Metadata.PEFile peFile, TypeSystemOptions options)
{
@ -75,6 +76,7 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -75,6 +76,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
this.typeDefs = new MetadataTypeDefinition[metadata.TypeDefinitions.Count + 1];
this.fieldDefs = new MetadataField[metadata.FieldDefinitions.Count + 1];
this.methodDefs = new MetadataMethod[metadata.MethodDefinitions.Count + 1];
this.propertyDefs = new MetadataProperty[metadata.PropertyDefinitions.Count + 1];
}
internal string GetString(StringHandle name)
@ -198,7 +200,14 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -198,7 +200,14 @@ namespace ICSharpCode.Decompiler.TypeSystem
public IProperty GetDefinition(PropertyDefinitionHandle handle)
{
throw new NotImplementedException();
int row = MetadataTokens.GetRowNumber(handle);
if (row >= methodDefs.Length)
return null;
var property = LazyInit.VolatileRead(ref propertyDefs[row]);
if (property != null || handle.IsNil)
return property;
property = new MetadataProperty(this, handle);
return LazyInit.GetOrSet(ref propertyDefs[row], property);
}
public IEvent GetDefinition(EventDefinitionHandle handle)

Loading…
Cancel
Save