diff --git a/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs b/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs index 912e4ccc9..a55e1edc9 100644 --- a/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs +++ b/ICSharpCode.Decompiler/Ast/TextOutputFormatter.cs @@ -132,28 +132,14 @@ namespace ICSharpCode.Decompiler.Ast var n = node.Ancestors.FirstOrDefault(a => a.Annotation() != null); if (n != default(AstType)) { MemberMapping mapping = n.Annotation(); -// var map = mapping.MemberCodeMappings.Find(s => s.SourceCodeLine == output.CurrentLine); - + + // add all ranges foreach (var range in ranges) { -// // check if the range is in previous mapping -// var prevmap = mapping.MemberCodeMappings.Find(m => m.ILInstructionOffset.From <= range.From && -// m.ILInstructionOffset.To >= range.To); -// -// if (prevmap != null) -// continue; -// -// if (map == null) { - mapping.MemberCodeMappings.Add(/*map = */new SourceCodeMapping { - ILInstructionOffset = range, - SourceCodeLine = output.CurrentLine, - MemberMapping = mapping - }); -// } else { -// if (map.ILInstructionOffset.From > range.From) -// map.ILInstructionOffset.From = range.From; -// if (map.ILInstructionOffset.To < range.To) -// map.ILInstructionOffset.To = range.To; -// } + mapping.MemberCodeMappings.Add(new SourceCodeMapping { + ILInstructionOffset = range, + SourceCodeLine = output.CurrentLine, + MemberMapping = mapping + }); } } } diff --git a/ICSharpCode.Decompiler/CodeMappings.cs b/ICSharpCode.Decompiler/CodeMappings.cs index 9c09ec797..672ab151b 100644 --- a/ICSharpCode.Decompiler/CodeMappings.cs +++ b/ICSharpCode.Decompiler/CodeMappings.cs @@ -46,26 +46,56 @@ namespace ICSharpCode.Decompiler public int[] ToArray() { var resultList = new List(); - resultList.Add(ILInstructionOffset.From); - resultList.Add(ILInstructionOffset.To); - var list = MemberMapping.MemberCodeMappings.ConvertAll(s => new ILRange { From = s.ILInstructionOffset.From, To = s.ILInstructionOffset.To }); + // add list for the current source code line + var currentList = MemberMapping.MemberCodeMappings.FindAll(m => m.SourceCodeLine == this.SourceCodeLine); + foreach (var element in currentList.Distinct(new SourceCodeMappingComparer())) { + resultList.Add(element.ILInstructionOffset.From); + resultList.Add(element.ILInstructionOffset.To); + } - var invertedList = ILRange.Invert(list, MemberMapping.CodeSize); + // add inverted + var invertedList = MemberMapping.GetInvertedList(); if (invertedList != null && invertedList.Count() > 0) { foreach (var range in invertedList) { resultList.Add(range.From); resultList.Add(range.To); - } + } } - // remove last gap - step on the last line - if (resultList[resultList.Count - 1] == MemberMapping.CodeSize) { - resultList.RemoveAt(resultList.Count - 1); - resultList.RemoveAt(resultList.Count - 1); + return resultList.ToArray(); + } + + sealed class SourceCodeMappingComparer : IEqualityComparer + { + public bool Equals(SourceCodeMapping x, SourceCodeMapping y) + { + //Check whether the compared objects reference the same data. + if (Object.ReferenceEquals(x, y)) return true; + + //Check whether any of the compared objects is null. + if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null)) + return false; + + return x.ILInstructionOffset.From == y.ILInstructionOffset.From && + x.ILInstructionOffset.To == y.ILInstructionOffset.To && + x.SourceCodeLine == y.SourceCodeLine; } - return resultList.ToArray(); + public int GetHashCode(SourceCodeMapping map) + { + //Check whether the object is null + if (Object.ReferenceEquals(map, null)) return 0; + + //Get hash code for the ILInstructionOffset field if it is not null. + int hashRange = map.ILInstructionOffset == null ? 0 : map.ILInstructionOffset.GetHashCode(); + + //Get hash code for the SourceCodeLine field. + int hashLine = map.SourceCodeLine.GetHashCode(); + + //Calculate the hash code for the product. + return hashRange ^ hashLine; + } } } @@ -93,6 +123,18 @@ namespace ICSharpCode.Decompiler /// Gets or sets the source code mappings. /// public List MemberCodeMappings { get; set; } + + /// + /// Gets the inverted IL Ranges.
+ /// E.g.: for (0-9, 11-14, 14-18, 21-25) => (9-11,18-21). + ///
+ /// IL Range inverted list. + public IEnumerable GetInvertedList() + { + var list = MemberCodeMappings.ConvertAll( + s => new ILRange { From = s.ILInstructionOffset.From, To = s.ILInstructionOffset.To }); + return ILRange.Invert(list, CodeSize); + } } public static class CodeMappings