/// <summary> /// Create data in the CodeMappings and DecompiledMemberReferences. /// </summary> /// <param name="token">Token of the current method.</param> /// <param name="member">Current member (MethodDefinition, PropertyDefinition, EventDefinition).</param> /// <remarks>The token is used in CodeMappings; member (and its token) is used in DecompiledMemberReferences.</remarks> protected virtual void CreateCodeMappings(int token, MemberReference member) { this.CodeMappings.Add(token, new List<MemberMapping>()); int t = member.MetadataToken.ToInt32(); if (!this.DecompiledMemberReferences.ContainsKey(t)) this.DecompiledMemberReferences.Add(t, member); }
/// <summary> /// Gets the source code and type name from metadata token and offset. /// </summary> /// <param name="codeMappings">Code mappings storage.</param> /// <param name="token">Metadata token.</param> /// <param name="ilOffset">IL offset.</param> /// <param name="typeName">Type definition.</param> /// <param name="line">Line number.</param> /// <remarks>It is possible to exist to different types from different assemblies with the same metadata token.</remarks> public static bool GetInstructionByTokenAndOffset( this List<MemberMapping> codeMappings, int token, int ilOffset, out MemberReference member, out int line) { member = null; line = 0; if (codeMappings == null) throw new ArgumentException("CodeMappings storage must be valid!"); var mapping = codeMappings.FirstOrDefault(m => m.MetadataToken == token); if (mapping == null) return false; var codeMapping = mapping.MemberCodeMappings.FirstOrDefault( cm => cm.ILInstructionOffset.From <= ilOffset && ilOffset <= cm.ILInstructionOffset.To - 1); if (codeMapping == null) { codeMapping = mapping.MemberCodeMappings.FirstOrDefault(cm => cm.ILInstructionOffset.From > ilOffset); if (codeMapping == null) { codeMapping = mapping.MemberCodeMappings.LastOrDefault(); if (codeMapping == null) return false; } } member = mapping.MemberReference; line = codeMapping.SourceCodeLine; return true; }
/// <summary> /// Create code mapping for a method. /// </summary> /// <param name="method">Method to create the mapping for.</param> /// <param name="codeMappings">Source code mapping storage.</param> /// <param name="actualMemberReference">The actual member reference.</param> internal static MemberMapping CreateCodeMapping( this MethodDefinition member, List<MemberMapping> codeMappings, MemberReference actualMemberReference = null) { if (member == null || !member.HasBody) return null; if (codeMappings == null) return null; // create IL/CSharp code mappings - used in debugger MemberMapping currentMemberMapping = null; if (codeMappings.Any(map => map.MetadataToken == member.MetadataToken.ToInt32())) { currentMemberMapping = new MemberMapping() { MetadataToken = member.MetadataToken.ToInt32(), MemberCodeMappings = new List<SourceCodeMapping>(), MemberReference = actualMemberReference ?? member, CodeSize = member.Body.CodeSize }; codeMappings.Add(currentMemberMapping); } return currentMemberMapping; }
public void AddMemberReference (MemberReference member) { MemberReferences [member.token.RID - 1] = member; }
public static TypeReference SubstituteTypeArgs(TypeReference type, MemberReference member) { if (type is TypeSpecification) { ArrayType arrayType = type as ArrayType; if (arrayType != null) { TypeReference elementType = SubstituteTypeArgs(arrayType.ElementType, member); if (elementType != arrayType.ElementType) { return new ArrayType(elementType, arrayType.Dimensions); } else { return type; } } ByReferenceType refType = type as ByReferenceType; if (refType != null) { TypeReference elementType = SubstituteTypeArgs(refType.ElementType, member); return elementType != refType.ElementType ? new ByReferenceType(elementType) : type; } GenericInstanceType giType = type as GenericInstanceType; if (giType != null) { GenericInstanceType newType = new GenericInstanceType(giType.ElementType); bool isChanged = false; for (int i = 0; i < giType.GenericArguments.Count; i++) { newType.GenericArguments.Add(SubstituteTypeArgs(giType.GenericArguments[i], member)); isChanged |= newType.GenericArguments[i] != giType.GenericArguments[i]; } return isChanged ? newType : type; } OptionalModifierType optmodType = type as OptionalModifierType; if (optmodType != null) { TypeReference elementType = SubstituteTypeArgs(optmodType.ElementType, member); return elementType != optmodType.ElementType ? new OptionalModifierType(optmodType.ModifierType, elementType) : type; } RequiredModifierType reqmodType = type as RequiredModifierType; if (reqmodType != null) { TypeReference elementType = SubstituteTypeArgs(reqmodType.ElementType, member); return elementType != reqmodType.ElementType ? new RequiredModifierType(reqmodType.ModifierType, elementType) : type; } PointerType ptrType = type as PointerType; if (ptrType != null) { TypeReference elementType = SubstituteTypeArgs(ptrType.ElementType, member); return elementType != ptrType.ElementType ? new PointerType(elementType) : type; } } GenericParameter gp = type as GenericParameter; if (gp != null) { if (gp.Owner.GenericParameterType == GenericParameterType.Method) { return ((GenericInstanceMethod)member).GenericArguments[gp.Position]; } else { if (member.DeclaringType is ArrayType) { return ((ArrayType)member.DeclaringType).ElementType; } else { return ((GenericInstanceType)member.DeclaringType).GenericArguments[gp.Position]; } } } return type; }
public ResolutionException (MemberReference member) : base ("Failed to resolve " + member.FullName) { this.member = member; }