diff --git a/Backend/Utils/Helper.cs b/Backend/Utils/Helper.cs index 3c0f2047..43d53039 100644 --- a/Backend/Utils/Helper.cs +++ b/Backend/Utils/Helper.cs @@ -6,6 +6,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using Model; namespace Backend.Utils { diff --git a/CCIProvider/TypeExtractor.cs b/CCIProvider/TypeExtractor.cs index 19e64dda..b0b31929 100644 --- a/CCIProvider/TypeExtractor.cs +++ b/CCIProvider/TypeExtractor.cs @@ -810,7 +810,22 @@ private void ExtractGenericTypeParameters(IGenericDefinition definingType, Cci.I var index = (ushort)i; var name = parameterdef.Name.Value; var typeKind = GetGenericParameterTypeKind(parameterdef); - var parameter = new GenericParameter(GenericParameterKind.Type, index, name, typeKind); + var variance = GenericParameterVariance.NONE; + switch (parameterdef.Variance) + { + case Cci.TypeParameterVariance.Contravariant: + variance = GenericParameterVariance.CONTRAVARIANT; + break; + case Cci.TypeParameterVariance.Covariant: + variance = GenericParameterVariance.COVARIANT; + break; + } + + var parameter = new GenericParameter(GenericParameterKind.Type, index, name, typeKind) + { + Variance = variance, + DefaultConstructorConstraint = parameterdef.MustHaveDefaultConstructor + }; ExtractAttributes(parameter.Attributes, parameterdef.Attributes); @@ -818,7 +833,8 @@ private void ExtractGenericTypeParameters(IGenericDefinition definingType, Cci.I definingType.GenericParameters.Add(parameter); defGenericContext.TypeParameters.Add(parameter); - } + parameter.Constraints.AddRange(parameterdef.Constraints.Select(cciTypeRef => ExtractType(cciTypeRef))); + } } private static IList GetAllGenericTypeParameters(Cci.ITypeDefinition typedef) diff --git a/MetadataProvider/AssemblyExtractor.cs b/MetadataProvider/AssemblyExtractor.cs index 66787d90..5c40ca80 100644 --- a/MetadataProvider/AssemblyExtractor.cs +++ b/MetadataProvider/AssemblyExtractor.cs @@ -13,75 +13,6 @@ namespace MetadataProvider { internal class AssemblyExtractor { - #region FakeArrayType - - private struct FakeArrayType : IBasicType - { - public ArrayType Type { get; private set; } - - public FakeArrayType(ArrayType type) - { - this.Type = type; - } - - public IAssemblyReference ContainingAssembly - { - get { return null; } - } - - public string ContainingNamespace - { - get { return string.Empty; } - } - - public string Name - { - get { return "FakeArray"; } - } - - public string GenericName - { - get { return this.Name; } - } - - public IList GenericArguments - { - get { return null; } - } - - public IBasicType GenericType - { - get { return null; } - } - - public TypeDefinition ResolvedType - { - get { return null; } - } - - public TypeKind TypeKind - { - get { return TypeKind.ReferenceType; } - } - - public ISet Attributes - { - get { return null; } - } - - public int GenericParameterCount - { - get { return 0; } - } - - public IBasicType ContainingType - { - get { return null; } - } - } - - #endregion - private IDictionary definedTypes; private IDictionary definedMethods; private IDictionary definedFields; @@ -97,6 +28,7 @@ public IBasicType ContainingType private TypeDefinition currentType; private MethodDefinition currentMethod; private IDictionary currentMethodLocalVariablesNames; + private readonly CustomAttributeTypeProvider customAttributeTypeProvider; public AssemblyExtractor(Host host, SRPE.PEReader reader, SRM.MetadataReaderProvider pdbProvider = null) { @@ -109,6 +41,7 @@ public AssemblyExtractor(Host host, SRPE.PEReader reader, SRM.MetadataReaderProv this.defGenericContext = new GenericContext(); this.refGenericContext = new GenericContext(); this.signatureTypeProvider = new SignatureTypeProvider(this); + this.customAttributeTypeProvider = new CustomAttributeTypeProvider(signatureTypeProvider); if (pdbProvider != null) { @@ -129,7 +62,17 @@ public TypeDefinition GetDefinedType(SRM.TypeDefinitionHandle handle) var name = metadata.GetString(typedef.Name); name = GetGenericName(name); - result = new TypeDefinition(name); + result = new TypeDefinition(name) + { + ContainingAssembly = assembly, + ContainingNamespace = new Namespace(metadata.GetString(typedef.Namespace)) + }; + + foreach (var genericParameterHandle in typedef.GetGenericParameters()) + { + ExtractGenericParameter(GenericParameterKind.Type, result, genericParameterHandle); + } + definedTypes.Add(handle, result); } @@ -148,6 +91,11 @@ public MethodDefinition GetDefinedMethod(SRM.MethodDefinitionHandle handle) name = GetGenericName(name); result = new MethodDefinition(name, null); + foreach (var genericParameterHandle in methoddef.GetGenericParameters()) + { + ExtractGenericParameter(GenericParameterKind.Method, result, genericParameterHandle); + } + definedMethods.Add(handle, result); } @@ -175,13 +123,25 @@ public Assembly Extract() { var assemblydef = metadata.GetAssemblyDefinition(); var name = metadata.GetString(assemblydef.Name); - assembly = new Assembly(name); + assembly = new Assembly(name) + { + Version = assemblydef.Version, + Culture = metadata.GetString(assemblydef.Culture), + PublicKey = metadata.GetBlobBytes(assemblydef.PublicKey) + }; + + ExtractAttributes(assembly, assemblydef.GetCustomAttributes()); foreach (var handle in metadata.AssemblyReferences) { var referencedef = metadata.GetAssemblyReference(handle); name = metadata.GetString(referencedef.Name); - var reference = new AssemblyReference(name); + var reference = new AssemblyReference(name) + { + Version = referencedef.Version, + Culture = metadata.GetString(referencedef.Culture), + PublicKey = metadata.GetBlobBytes(referencedef.PublicKeyOrToken) + }; assembly.References.Add(reference); } @@ -248,9 +208,9 @@ private void ExtractType(SRM.TypeDefinitionHandle typedefHandle) type.ContainingNamespace = currentNamespace; currentType = type; - foreach (var handle in typedef.GetGenericParameters()) + foreach (var genericParameter in type.GenericParameters) { - ExtractGenericParameter(GenericParameterKind.Type, type, handle); + defGenericContext.TypeParameters.Add(genericParameter); } ExtractBaseType(typedef.BaseType); @@ -275,17 +235,25 @@ private void ExtractType(SRM.TypeDefinitionHandle typedefHandle) type.UnderlayingType = valueField.Type as IBasicType; } + var methodOverrides = MethodOverridesOf(typedef); foreach (var handle in typedef.GetMethods()) { - ExtractMethod(handle); + ExtractMethod(handle, methodOverrides); } defGenericContext.TypeParameters.Clear(); + + foreach (var handle in typedef.GetProperties()) + { + ExtractProperty(handle); + } foreach (var handle in typedef.GetNestedTypes()) { ExtractType(handle); } + + ExtractAttributes(type, typedef.GetCustomAttributes()); currentType = currentType.ContainingType; } @@ -439,27 +407,39 @@ private void ExtractGenericParameter(GenericParameterKind parameterKind, IGeneri typeKind = TypeKind.ValueType; } - var name = metadata.GetString(genericParameterdef.Name); - var genericParameter = new GenericParameter(parameterKind, (ushort)genericParameterdef.Index, name, typeKind) - { - GenericContainer = genericContainer - }; - - if (parameterKind == GenericParameterKind.Type) + var variance = GenericParameterVariance.NONE; + if (genericParameterdef.Attributes.HasFlag(SR.GenericParameterAttributes.Contravariant)) { - defGenericContext.TypeParameters.Add(genericParameter); + variance = GenericParameterVariance.CONTRAVARIANT; } - else if (parameterKind == GenericParameterKind.Method) + + if (genericParameterdef.Attributes.HasFlag(SR.GenericParameterAttributes.Covariant)) { - defGenericContext.MethodParameters.Add(genericParameter); + variance = GenericParameterVariance.COVARIANT; } - else + + var name = metadata.GetString(genericParameterdef.Name); + var genericParameter = new GenericParameter(parameterKind, (ushort)genericParameterdef.Index, name, typeKind) { - throw parameterKind.ToUnknownValueException(); - } + GenericContainer = genericContainer, + Variance = variance, + DefaultConstructorConstraint = genericParameterdef.Attributes.HasFlag(SR.GenericParameterAttributes.DefaultConstructorConstraint) + }; genericContainer.GenericParameters.Add(genericParameter); - } + var typeConstraints = genericParameterdef.GetConstraints().Select( + constraint => + { + refGenericContext.MethodParameters.Clear(); + refGenericContext.TypeParameters.Clear(); + CreateGenericParameterReferences(parameterKind, genericContainer.GenericParameterCount); + var constraints = signatureTypeProvider.GetTypeFromHandle(metadata, refGenericContext, + metadata.GetGenericParameterConstraint(constraint).Type); + BindGenericParameterReferences(parameterKind, genericContainer); + return constraints; + }); + genericParameter.Constraints.AddRange(typeConstraints); + } private void ExtractField(SRM.FieldDefinitionHandle handle) { @@ -471,6 +451,8 @@ private void ExtractField(SRM.FieldDefinitionHandle handle) field.IsStatic = fielddef.Attributes.HasFlag(SR.FieldAttributes.Static); field.Visibility = GetVisibilityKind(fielddef.Attributes); field.Value = ExtractFieldDefaultValue(fielddef); + + ExtractAttributes(field, fielddef.GetCustomAttributes()); currentType.Fields.Add(field); } @@ -495,8 +477,28 @@ private Constant ExtractFieldDefaultValue(SRM.FieldDefinition fielddef) return result; } + + private void ExtractProperty(SRM.PropertyDefinitionHandle handle) + { + var propertyDef = metadata.GetPropertyDefinition(handle); + var name = metadata.GetString(propertyDef.Name); + CreateGenericParameterReferences(GenericParameterKind.Type, currentType.GenericParameters.Count); + var signature = propertyDef.DecodeSignature(signatureTypeProvider, refGenericContext); + var getter = propertyDef.GetAccessors().Getter; + var setter = propertyDef.GetAccessors().Setter; + var property = new PropertyDefinition(name, signature.ReturnType) + { + Getter = !getter.IsNil ? GetDefinedMethod(getter) : default, + Setter = !setter.IsNil ? GetDefinedMethod(setter) : default, + ContainingType = currentType, + IsStatic = !signature.Header.IsInstance + }; + currentType.PropertyDefinitions.Add(property); + BindGenericParameterReferences(GenericParameterKind.Type, currentType); + ExtractAttributes(property, propertyDef.GetCustomAttributes()); + } - private void ExtractMethod(SRM.MethodDefinitionHandle methoddefHandle) + private void ExtractMethod(SRM.MethodDefinitionHandle methoddefHandle, IList methodOverrides) { var methoddef = metadata.GetMethodDefinition(methoddefHandle); var method = GetDefinedMethod(methoddefHandle); @@ -512,9 +514,9 @@ private void ExtractMethod(SRM.MethodDefinitionHandle methoddefHandle) currentType.Methods.Add(method); currentMethod = method; - foreach (var handle in methoddef.GetGenericParameters()) + foreach (var genericParameter in method.GenericParameters) { - ExtractGenericParameter(GenericParameterKind.Method, method, handle); + defGenericContext.MethodParameters.Add(genericParameter); } var signature = methoddef.DecodeSignature(signatureTypeProvider, defGenericContext); @@ -527,6 +529,14 @@ private void ExtractMethod(SRM.MethodDefinitionHandle methoddefHandle) ExtractLocalVariablesNames(methoddefHandle); ExtractMethodBody(methoddef.RelativeVirtualAddress); + + var methodOverride = methodOverrides.FirstOrDefault(m => method.MatchSignature(m.newMethodImplementation)); + if (methodOverride != null) + { + method.OverridenMethod = methodOverride.overridenMethod; + } + + ExtractAttributes(method, methoddef.GetCustomAttributes()); defGenericContext.MethodParameters.Clear(); currentMethod = null; @@ -632,7 +642,10 @@ private void ExtractParameters(IList parameters) type = signatureTypeProvider.GetByReferenceType(type); } - var v = new LocalVariable("this", true) { Type = type }; + var v = new LocalVariable("this", true) + { + Type = type + }; parameters.Add(v); } @@ -964,10 +977,16 @@ private IInstruction ExtractInstruction(ILInstruction operation) break; case SRM.ILOpCode.Ldfld: + instruction = ProcessLoadField(operation, false); + break; case SRM.ILOpCode.Ldsfld: + instruction = ProcessLoadField(operation, true); + break; case SRM.ILOpCode.Ldflda: + instruction = ProcessLoadField(operation, false); + break; case SRM.ILOpCode.Ldsflda: - instruction = ProcessLoadField(operation); + instruction = ProcessLoadField(operation, true); break; case SRM.ILOpCode.Ldftn: @@ -1082,8 +1101,10 @@ private IInstruction ExtractInstruction(ILInstruction operation) break; case SRM.ILOpCode.Stfld: + instruction = ProcessStoreField(operation, false); + break; case SRM.ILOpCode.Stsfld: - instruction = ProcessStoreField(operation); + instruction = ProcessStoreField(operation, true); break; case SRM.ILOpCode.Stind_i: @@ -1260,21 +1281,30 @@ private IFieldReference GetFieldReference(SRM.MemberReference member) BindGenericParameterReferences(GenericParameterKind.Type, containingType); return field; } + + private IMethodReference GetMethodReference(SRM.MemberReference member) => + GetMethodReference(member.Name, member.Parent, member.DecodeMethodSignature); - private IMethodReference GetMethodReference(SRM.MemberReference member) + private IMethodReference GetMethodReference(SRM.MethodDefinition methodDefinition) => + GetMethodReference(methodDefinition.Name, methodDefinition.GetDeclaringType(), methodDefinition.DecodeSignature); + + private IMethodReference GetMethodReference( + SRM.StringHandle methodName, + SRM.EntityHandle parent, + Func> decodeSignature) { - var name = metadata.GetString(member.Name); - var type = signatureTypeProvider.GetTypeFromHandle(metadata, defGenericContext, member.Parent); + var name = metadata.GetString(methodName); + var type = signatureTypeProvider.GetTypeFromHandle(metadata, defGenericContext, parent); if (type is ArrayType) { - type = new FakeArrayType(type as ArrayType); + type = new ArrayTypeWrapper(type as ArrayType); } var containingType = (IBasicType)type; CreateGenericParameterReferences(GenericParameterKind.Type, containingType.GenericParameterCount); - var signature = member.DecodeMethodSignature(signatureTypeProvider, refGenericContext); + var signature = decodeSignature(signatureTypeProvider, refGenericContext); var method = new MethodReference(name, signature.ReturnType) { @@ -1400,7 +1430,7 @@ private IInstruction ProcessSwitch(ILInstruction op) return instruction; } - private IInstruction ProcessCreateArray(ILInstruction op, ArrayType arrayType = null, bool withLowerBounds = false) + private CreateArrayInstruction ProcessCreateArray(ILInstruction op, ArrayType arrayType = null, bool withLowerBounds = false) { if (arrayType == null) { @@ -1413,13 +1443,13 @@ private IInstruction ProcessCreateArray(ILInstruction op, ArrayType arrayType = return instruction; } - private IInstruction ProcessLoadArrayElement(ILInstruction op, ArrayType arrayType, LoadArrayElementOperation operation) + private LoadArrayElementInstruction ProcessLoadArrayElement(ILInstruction op, LoadArrayElementOperation operation, ArrayType arrayType = null) { var instruction = new LoadArrayElementInstruction(op.Offset, operation, arrayType); return instruction; } - private IInstruction ProcessStoreArrayElement(ILInstruction op, ArrayType arrayType) + private StoreArrayElementInstruction ProcessStoreArrayElement(ILInstruction op, ArrayType arrayType = null) { var instruction = new StoreArrayElementInstruction(op.Offset, arrayType); return instruction; @@ -1430,12 +1460,13 @@ private IInstruction ProcessCreateObject(ILInstruction op) var method = GetOperand(op); IInstruction instruction; - if (method.ContainingType is FakeArrayType) + if (method.ContainingType is ArrayTypeWrapper) { - var arrayType = (FakeArrayType)method.ContainingType; + var arrayType = (ArrayTypeWrapper)method.ContainingType; var withLowerBounds = method.Parameters.Count > arrayType.Type.Rank; - - instruction = ProcessCreateArray(op, arrayType.Type, withLowerBounds); + var createArrayInstruction = ProcessCreateArray(op, arrayType.Type, withLowerBounds); + createArrayInstruction.Constructor = method; + instruction = createArrayInstruction; } else { @@ -1450,19 +1481,22 @@ private IInstruction ProcessMethodCall(ILInstruction op) var method = GetOperand(op); IInstruction instruction; - if (method.ContainingType is FakeArrayType) + if (method.ContainingType is ArrayTypeWrapper) { - var arrayType = (FakeArrayType)method.ContainingType; + var arrayType = (ArrayTypeWrapper)method.ContainingType; if (method.Name == "Set") { - instruction = ProcessStoreArrayElement(op, arrayType.Type); + var storeArrayElementInstruction = ProcessStoreArrayElement(op, arrayType.Type); + storeArrayElementInstruction.Method = method; + instruction = storeArrayElementInstruction; } else { var operation = OperationHelper.ToLoadArrayElementOperation(method.Name); - - instruction = ProcessLoadArrayElement(op, arrayType.Type, operation); + var loadArrayElementInstruction = ProcessLoadArrayElement(op, operation, arrayType.Type); + loadArrayElementInstruction.Method = method; + instruction = loadArrayElementInstruction; } } else @@ -1564,11 +1598,12 @@ private IInstruction ProcessLoadIndirect(ILInstruction op) return instruction; } - private IInstruction ProcessLoadField(ILInstruction op) + private IInstruction ProcessLoadField(ILInstruction op, bool isStatic) { var operation = OperationHelper.ToLoadFieldOperation(op.Opcode); var field = GetOperand(op); + SetFieldStaticProperty(field, isStatic); var instruction = new LoadFieldInstruction(op.Offset, operation, field); return instruction; } @@ -1608,10 +1643,11 @@ private IInstruction ProcessStoreLocal(ILInstruction op) return instruction; } - private IInstruction ProcessStoreField(ILInstruction op) + private IInstruction ProcessStoreField(ILInstruction op, bool isStatic) { var field = GetOperand(op); - + + SetFieldStaticProperty(field, isStatic); var instruction = new StoreFieldInstruction(op.Offset, field); return instruction; } @@ -1635,11 +1671,7 @@ private IInstruction ProcessConversion(ILInstruction op) var unsigned = OperationHelper.OperandsAreUnsigned(op.Opcode); var type = GetOperand(op); - if (operation == ConvertOperation.Box && type.TypeKind == TypeKind.ValueType) - { - type = PlatformTypes.Object; - } - else if (operation == ConvertOperation.Conv) + if (operation == ConvertOperation.Conv) { type = OperationHelper.GetOperationType(op.Opcode); } @@ -1655,7 +1687,7 @@ private IInstruction ProcessConversion(ILInstruction op) private static string GetGenericName(string name) { var start = name.LastIndexOf('`'); - + if (start > -1) { name = name.Remove(start); @@ -1663,5 +1695,109 @@ private static string GetGenericName(string name) return name; } + + private void ExtractAttributes(IMetadataReference owner, SRM.CustomAttributeHandleCollection customAttributeHandleCollection) + { + foreach (var customAttributeHandle in customAttributeHandleCollection) + { + var customAttribute = metadata.GetCustomAttribute(customAttributeHandle); + var attribute = new CustomAttribute + { + Constructor = GetMethodReference(customAttribute.Constructor), + }; + var arguments = customAttribute.DecodeValue(customAttributeTypeProvider); + + foreach (var fixedArgument in arguments.FixedArguments) + { + attribute.Arguments.Add(new Constant(fixedArgument.Value) + { + Type = fixedArgument.Type + }); + } + + // TODO named arguments + + owner.Attributes.Add(attribute); + } + } + + // Metadata static indicator for FieldReferences (!signatureHeader.IsInstance) appears to be incorrect when read. + // So field isStatic is ensured with the field operation kind (ex: stsfld => static, ldfld => not static) + private static void SetFieldStaticProperty(IFieldReference field, bool isStatic) + { + switch (field) + { + case FieldReference fieldReference: + { + fieldReference.IsStatic = isStatic; + break; + } + case FieldDefinition fieldDefinition: + { + fieldDefinition.IsStatic = isStatic; + break; + } + default: throw new Exception("case not handled"); + + } + } + + private IList MethodOverridesOf(SRM.TypeDefinition typedef) => + typedef + .GetMethodImplementations() + .Select(handle => metadata.GetMethodImplementation(handle)) + .Select(methodImplementation => + { + IMethodReference newMethodImplementation; + switch (methodImplementation.MethodBody.Kind) + { + case SRM.HandleKind.MethodDefinition: + { + newMethodImplementation = GetMethodReference((SRM.MethodDefinitionHandle) methodImplementation.MethodBody); + break; + } + case SRM.HandleKind.MemberReference: + { + newMethodImplementation = GetMethodReference((SRM.MemberReferenceHandle) methodImplementation.MethodBody); + break; + } + default: + throw new Exception("Unexpected handle kind"); + } + + IMethodReference overridenMethod; + switch (methodImplementation.MethodDeclaration.Kind) + { + case SRM.HandleKind.MethodDefinition: + { + overridenMethod = GetMethodReference( + metadata.GetMethodDefinition((SRM.MethodDefinitionHandle) methodImplementation.MethodDeclaration)); + break; + } + case SRM.HandleKind.MemberReference: + { + overridenMethod = GetMethodReference( + metadata.GetMemberReference((SRM.MemberReferenceHandle) methodImplementation.MethodDeclaration)); + break; + } + default: + throw new Exception("Unexpected handle kind"); + } + + return new MethodOverride(newMethodImplementation, overridenMethod); + }) + .ToList(); + } + + internal class MethodOverride + { + public readonly IMethodReference newMethodImplementation; + public readonly IMethodReference overridenMethod; + + public MethodOverride(IMethodReference newMethodImplementation, IMethodReference overridenMethod) + { + this.newMethodImplementation = newMethodImplementation; + this.overridenMethod = overridenMethod; + } } } \ No newline at end of file diff --git a/MetadataProvider/CustomAttributeTypeProvider.cs b/MetadataProvider/CustomAttributeTypeProvider.cs new file mode 100644 index 00000000..f196ad56 --- /dev/null +++ b/MetadataProvider/CustomAttributeTypeProvider.cs @@ -0,0 +1,33 @@ +using System.Reflection.Metadata; +using Model.Types; + +namespace MetadataProvider +{ + internal class CustomAttributeTypeProvider : ICustomAttributeTypeProvider + { + private readonly SignatureTypeProvider signatureTypeProvider; + + public CustomAttributeTypeProvider(SignatureTypeProvider signatureTypeProvider) + { + this.signatureTypeProvider = signatureTypeProvider; + } + + public IType GetPrimitiveType(PrimitiveTypeCode typeCode) => signatureTypeProvider.GetPrimitiveType(typeCode); + + public IType GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind) => + signatureTypeProvider.GetTypeFromDefinition(reader, handle, rawTypeKind); + + public IType GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind) => + signatureTypeProvider.GetTypeFromReference(reader, handle, rawTypeKind); + + public IType GetSZArrayType(IType elementType) => signatureTypeProvider.GetSZArrayType(elementType); + + public IType GetSystemType() => PlatformTypes.Type; + + public bool IsSystemType(IType type) => PlatformTypes.Type.Equals(type); + + public IType GetTypeFromSerializedName(string name) => new BasicType(name); + + public PrimitiveTypeCode GetUnderlyingEnumType(IType type) => PrimitiveTypeCode.Int32; + } +} \ No newline at end of file diff --git a/MetadataProvider/MetadataProvider.csproj b/MetadataProvider/MetadataProvider.csproj index 18c1c3a2..2f6ca308 100644 --- a/MetadataProvider/MetadataProvider.csproj +++ b/MetadataProvider/MetadataProvider.csproj @@ -49,6 +49,7 @@ + diff --git a/MetadataProvider/SignatureTypeProvider.cs b/MetadataProvider/SignatureTypeProvider.cs index 9ce7a48e..a17fdc13 100644 --- a/MetadataProvider/SignatureTypeProvider.cs +++ b/MetadataProvider/SignatureTypeProvider.cs @@ -75,7 +75,10 @@ public virtual IType GetTypeFromReference(SRM.MetadataReader reader, SRM.TypeRef var assemblyHandle = (SRM.AssemblyReferenceHandle)typeref.ResolutionScope; var assembly = reader.GetAssemblyReference(assemblyHandle); name = reader.GetString(assembly.Name); - type.ContainingAssembly = new AssemblyReference(name); + type.ContainingAssembly = new AssemblyReference(name) + { + Version = assembly.Version + }; break; } diff --git a/Model/Assembly.cs b/Model/Assembly.cs index 454bae9e..9a52ebae 100644 --- a/Model/Assembly.cs +++ b/Model/Assembly.cs @@ -9,18 +9,25 @@ namespace Model { - public interface IAssemblyReference + public interface IAssemblyReference : IMetadataReference { string Name { get; } + Version Version { get; } + string Culture { get; } + byte[] PublicKey { get; } } public class AssemblyReference : IAssemblyReference { public string Name { get; private set; } - + public Version Version { get; set; } + public string Culture { get; set; } + public byte[] PublicKey { get; set; } + public ISet Attributes { get; private set; } public AssemblyReference(string name) { this.Name = name; + this.Attributes = new HashSet(); } public override string ToString() @@ -49,11 +56,15 @@ public class Assembly : IAssemblyReference public string Name { get; private set; } public IList References { get; private set; } public Namespace RootNamespace { get; set; } - + public Version Version { get; set; } + public string Culture { get; set; } + public byte[] PublicKey { get; set; } + public ISet Attributes { get; private set; } public Assembly(string name) { this.Name = name; this.References = new List(); + this.Attributes = new HashSet(); } public bool MatchReference(IAssemblyReference reference) diff --git a/Model/Bytecode/Instructions.cs b/Model/Bytecode/Instructions.cs index bb12534e..8cf7d27a 100644 --- a/Model/Bytecode/Instructions.cs +++ b/Model/Bytecode/Instructions.cs @@ -245,6 +245,8 @@ public class CreateArrayInstruction : Instruction public ArrayType Type { get; set; } public bool WithLowerBound { get; set; } + public IMethodReference Constructor { get; set; } + public CreateArrayInstruction(uint label, ArrayType type) : base(label) { @@ -266,6 +268,8 @@ public override string ToString() public class LoadArrayElementInstruction : Instruction { public LoadArrayElementOperation Operation { get; set; } + + public IMethodReference Method { get; set; } public ArrayType Array { get; set; } public LoadArrayElementInstruction(uint label, LoadArrayElementOperation operation, ArrayType array) @@ -290,6 +294,8 @@ public override string ToString() public class StoreArrayElementInstruction : Instruction { public ArrayType Array { get; set; } + + public IMethodReference Method { get; set; } public StoreArrayElementInstruction(uint label, ArrayType array) : base(label) diff --git a/Model/Extensions.cs b/Model/Extensions.cs index 8ba54658..ad6be5c7 100644 --- a/Model/Extensions.cs +++ b/Model/Extensions.cs @@ -246,7 +246,7 @@ public static BasicType Instantiate(this IBasicType type, IEnumerable gen ContainingAssembly = type.ContainingAssembly, ContainingNamespace = type.ContainingNamespace, ContainingType = type.ContainingType, - GenericParameterCount = type.GenericParameterCount, + GenericParameterCount = genericArguments.Count(), GenericType = type }; @@ -361,6 +361,53 @@ public static bool IsDelegate(this IType type) return result; } + public static bool MatchSignature(this IMethodReference method, IMethodReference anotherMethod) + { + var result = method.Name == anotherMethod.Name && + method.IsStatic == anotherMethod.IsStatic && + method.GenericParameterCount == anotherMethod.GenericParameterCount && + method.ReturnType.Equals(anotherMethod.ReturnType) && + method.MatchParameters(anotherMethod); + return result; + } + + public static bool MatchParameters(this IMethodReference method, IMethodReference anotherMethod) + { + var result = false; + + if (method.Parameters.Count == anotherMethod.Parameters.Count) + { + result = true; + + for (var i = 0; i < method.Parameters.Count && result; ++i) + { + var parameterdef = method.Parameters[i]; + var parameterref = anotherMethod.Parameters[i]; + + result = parameterdef.MatchReference(parameterref); + } + } + + return result; + } + + public static bool MatchReference(this IMethodParameterReference parameter, IMethodParameterReference anotherParameter) + { + var result = false; + + if (anotherParameter is MethodParameter) + { + result = parameter.Equals(anotherParameter); + } + else + { + result = parameter.Kind == anotherParameter.Kind && + parameter.Type.Equals(anotherParameter.Type); + } + + return result; + } + #region Control-flow helper methods public static bool IsBranch(this IInstruction instruction, out IList targets) diff --git a/Model/Types/TypeDefinitions.cs b/Model/Types/TypeDefinitions.cs index 27062ea7..5678eb23 100644 --- a/Model/Types/TypeDefinitions.cs +++ b/Model/Types/TypeDefinitions.cs @@ -242,23 +242,6 @@ public bool HasDefaultValue get { return this.DefaultValue != null; } } - public bool MatchReference(IMethodParameterReference parameter) - { - var result = false; - - if (parameter is MethodParameter) - { - result = this.Equals(parameter); - } - else - { - result = this.Kind == parameter.Kind && - this.Type.Equals(parameter.Type); - } - - return result; - } - public override string ToString() { string kind; @@ -397,7 +380,66 @@ public override bool Equals(object obj) return result; } } + public class PropertyDefinition : ITypeMemberDefinition, IMetadataReference + { + public PropertyDefinition(string name, IType propType) + { + PropertyType = propType; + Name = name; + Attributes = new HashSet(); + } + + public ISet Attributes { get; private set; } + public IType PropertyType { get; set; } + public string Name { get; set; } + public MethodDefinition Getter { get; set; } + public MethodDefinition Setter { get; set; } + public TypeDefinition ContainingType { get; set; } + IBasicType ITypeMemberReference.ContainingType + { + get { return this.ContainingType; } + } + public bool IsStatic { get; set; } + public bool MatchReference(ITypeMemberReference member) + { + if (member is PropertyDefinition) + return member.Equals(this); + return false; + } + public override bool Equals(object obj) + { + if (obj is PropertyDefinition propertyDef) + { + bool hasSetter = (propertyDef.Setter != null) == (this.Setter != null); + bool hasGetter = (propertyDef.Getter != null) == (this.Getter != null); + return propertyDef.Name.Equals(this.Name) && + propertyDef.PropertyType.Equals(this.PropertyType) && + hasSetter && hasGetter && + (propertyDef.Getter == null || propertyDef.Getter.Equals(this.Getter)) && + (propertyDef.Setter == null || propertyDef.Setter.Equals(this.Setter)) && + (propertyDef.ContainingType.Equals(this.ContainingType)); + } + return false; + } + public override string ToString() + { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.AppendLine("Property definition"); + stringBuilder.AppendLine(String.Format("Name: {0}", Name)); + stringBuilder.AppendLine(String.Format("Property type: {0}", PropertyType)); + stringBuilder.AppendLine(String.Format("Containing type: {0}", ContainingType)); + if (Getter != null) + stringBuilder.AppendLine(String.Format("Getter: {0}", Getter.ToSignatureString())); + if (Setter != null) + stringBuilder.AppendLine(String.Format("Setter: {0}", Setter.ToSignatureString())); + return stringBuilder.ToString(); + } + public override int GetHashCode() + { + return this.Name.GetHashCode(); + } + } public class MethodDefinition : ITypeMemberDefinition, IMethodReference, IGenericDefinition { public VisibilityKind Visibility { get; set; } @@ -413,7 +455,8 @@ public class MethodDefinition : ITypeMemberDefinition, IMethodReference, IGeneri public bool IsConstructor { get; set; } public bool IsExternal { get; set; } public MethodBody Body { get; set; } - + public IMethodReference OverridenMethod { get; set; } + public MethodDefinition(string name, IType returnType) { this.Name = name; @@ -510,36 +553,6 @@ public bool MatchReference(ITypeMemberReference member) return result; } - public bool MatchSignature(IMethodReference method) - { - var result = this.Name == method.Name && - this.IsStatic == method.IsStatic && - this.GenericParameters.Count == method.GenericParameterCount && - this.ReturnType.Equals(method.ReturnType) && - this.MatchParameters(method); - return result; - } - - public bool MatchParameters(IMethodReference method) - { - var result = false; - - if (this.Parameters.Count == method.Parameters.Count) - { - result = true; - - for (var i = 0; i < this.Parameters.Count && result; ++i) - { - var parameterdef = this.Parameters[i]; - var parameterref = method.Parameters[i]; - - result = parameterdef.MatchReference(parameterref); - } - } - - return result; - } - public string ToSignatureString() { var result = new StringBuilder(); @@ -623,6 +636,9 @@ public class TypeDefinition : IBasicType, IGenericDefinition, ITypeMemberDefinit public IList Methods { get; private set; } public IList Types { get; private set; } public IBasicType UnderlayingType { get; set; } + public ISet PropertyDefinitions { get; private set; } + + public int GenericParameterCount => GenericParameters.Count; public TypeDefinition(string name, TypeKind typeKind = TypeKind.Unknown, TypeDefinitionKind kind = TypeDefinitionKind.Unknown) { @@ -635,6 +651,7 @@ public TypeDefinition(string name, TypeKind typeKind = TypeKind.Unknown, TypeDef this.Fields = new List(); this.Methods = new List(); this.Types = new List(); + this.PropertyDefinitions = new HashSet(); } public string GenericName @@ -676,11 +693,6 @@ IBasicType ITypeMemberReference.ContainingType #region IGenericReference members - int IGenericReference.GenericParameterCount - { - get { return this.GenericParameters.Count; } - } - #endregion #region IBasicType members diff --git a/Model/Types/Types.cs b/Model/Types/Types.cs index 0d6934db..bfcf835a 100644 --- a/Model/Types/Types.cs +++ b/Model/Types/Types.cs @@ -81,6 +81,8 @@ public static class PlatformTypes public static readonly BasicType Task = New("mscorlib", "System.Threading.Tasks", "Task", TypeKind.ReferenceType); public static readonly BasicType GenericTask = New("mscorlib", "System.Threading.Tasks", "Task", TypeKind.ReferenceType, 1); + + public static readonly BasicType Type = New("mscorlib", "System", "Type", TypeKind.ReferenceType); public static void Resolve(Host host) { @@ -535,11 +537,21 @@ private static string GetName(GenericParameterKind kind, ushort index) return string.Format("{0}{1}", prefix, index); } } + + public enum GenericParameterVariance + { + COVARIANT, + CONTRAVARIANT, + NONE + } public class GenericParameter : IGenericParameterReference { public ISet Attributes { get; private set; } - public TypeKind TypeKind { get; set; } + public ISet Constraints { get; private set; } + public bool DefaultConstructorConstraint { get; set; } + public GenericParameterVariance Variance { get; set; } + public TypeKind TypeKind { get; set; } public IGenericDefinition GenericContainer { get; set; } public GenericParameterKind Kind { get; set; } public ushort Index { get; set; } @@ -552,7 +564,8 @@ public GenericParameter(GenericParameterKind kind, ushort index, string name, Ty this.Name = name; this.TypeKind = typeKind; this.Attributes = new HashSet(); - } + this.Constraints = new HashSet(); + } #region IGenericParameterReference members @@ -732,4 +745,88 @@ public override bool Equals(object obj) return result; } } + + #region ArrayTypeWrapper + + public struct ArrayTypeWrapper : IBasicType + { + public ArrayType Type { get; } + + public ArrayTypeWrapper(ArrayType type) + { + this.Type = type; + } + + public IAssemblyReference ContainingAssembly + { + get { return null; } + } + + public string ContainingNamespace + { + get { return string.Empty; } + } + + public string Name + { + get { return "ArrayTypeWrapper"; } + } + + public string GenericName + { + get { return this.Name; } + } + + public IList GenericArguments + { + get { return null; } + } + + public IBasicType GenericType + { + get { return null; } + } + + public TypeDefinition ResolvedType + { + get { return null; } + } + + public TypeKind TypeKind + { + get { return TypeKind.ReferenceType; } + } + + public ISet Attributes + { + get { return null; } + } + + public int GenericParameterCount + { + get { return GenericParameterCountOf(Type); } + } + + public IBasicType ContainingType + { + get { return null; } + } + + private int GenericParameterCountOf(IType type) + { + switch (Type.ElementsType) + { + case IGenericParameterReference genericParameterReference: + return genericParameterReference.GenericContainer.GenericParameterCount; + case ArrayType arrayType: + return GenericParameterCountOf(arrayType.ElementsType); + case PointerType pointerType: + return GenericParameterCountOf(pointerType.TargetType); + default: + return 0; + } + } + } + + #endregion }