/// <summary> /// Gets source code mapping and metadata token based on type name and line number. /// </summary> /// <param name="codeMappings">Code mappings storage.</param> /// <param name="typeName">Member reference name.</param> /// <param name="lineNumber">Line number.</param> /// <param name="columnNumber">Column number or 0 for any column.</param> /// <returns></returns> public static SourceCodeMapping GetInstructionByLineNumber( this MemberMapping codeMapping, int lineNumber, int columnNumber) { if (codeMapping == null) { throw new ArgumentException("CodeMappings storage must be valid!"); } if (columnNumber != 0) { var loc = new TextLocation(lineNumber, columnNumber); foreach (var m in codeMapping.MemberCodeMappings.OrderBy(a => a.ILInstructionOffset.From)) { if (m.StartLocation <= loc && loc <= m.EndLocation) { return(m); } } var list = new List <SourceCodeMapping>(codeMapping.MemberCodeMappings.FindAll(a => a.StartLocation.Line <= lineNumber && lineNumber <= a.EndLocation.Line)); list.Sort((a, b) => { var d = GetDist(a.StartLocation, lineNumber, columnNumber).CompareTo(GetDist(b.StartLocation, lineNumber, columnNumber)); if (d != 0) { return(d); } return(a.ILInstructionOffset.From.CompareTo(b.ILInstructionOffset.From)); }); if (list.Count > 0) { return(list[0]); } return(null); } else { SourceCodeMapping map = null; foreach (var m in codeMapping.MemberCodeMappings) { if (lineNumber < m.StartLocation.Line || lineNumber > m.EndLocation.Line) { continue; } if (map == null || m.ILInstructionOffset.From < map.ILInstructionOffset.From) { map = m; } } return(map); } }
bool DebugGetSourceCodeMappingForSetNextStatement(DecompilerTextView textView, out string errMsg, out SourceCodeMapping mapping) { errMsg = string.Empty; mapping = null; if (ProcessState == DebuggerProcessState.Terminated) { errMsg = "We're not debugging"; return false; } if (ProcessState == DebuggerProcessState.Starting || ProcessState == DebuggerProcessState.Continuing || ProcessState == DebuggerProcessState.Running) { errMsg = "Can't set next statement when the process is running"; return false; } if (textView == null) { textView = MainWindow.Instance.ActiveTextView; if (textView == null) { errMsg = "No tab is available. Decompile the current method!"; return false; } } Dictionary<MethodKey, MemberMapping> cm; if (!VerifyAndGetCurrentDebuggedMethod(textView, out cm)) { errMsg = "No debug information found. Make sure that only the debugged method is selected in the treeview (press 'Alt+Num *' to go to current statement)"; return false; } var location = textView.TextEditor.TextArea.Caret.Location; var bps = SourceCodeMappingUtils.Find(cm, location.Line, location.Column); if (bps.Count == 0) { errMsg = "It's not possible to set the next statement here"; return false; } if (GetCurrentMethodILFrame() == null) { errMsg = "There's no IL frame"; return false; } if (currentLocation != null) { var currentKey = currentLocation.Value.MethodKey; foreach (var bp in bps) { var md = bp.MemberMapping.MethodDefinition; if (currentLocation.Value.Token != md.MDToken.Raw) continue; var serAsm = GetSerializedDnModuleWithAssembly(md); if (serAsm == null) continue; if (serAsm != currentLocation.Value.ModuleAssembly) continue; mapping = bp; break; } } if (mapping == null) { errMsg = "The next statement cannot be set to another method"; return false; } return true; }
public static bool DebugGetSourceCodeMappingForSetNextStatement(out string errMsg, out SourceCodeMapping mapping) { errMsg = string.Empty; mapping = null; if (DebuggerService.CurrentDebugger == null) { errMsg = "No debugger exists"; return false; } if (!DebuggerService.CurrentDebugger.IsDebugging) { errMsg = "We're not debugging"; return false; } if (DebuggerService.CurrentDebugger.IsProcessRunning) { errMsg = "Can't set next statement when the process is running"; return false; } var textView = MainWindow.Instance.ActiveTextView; if (textView == null) { errMsg = "No tab is available. Decompile the current method!"; return false; } Tuple<MethodKey, int, IMemberRef> info; MethodKey currentKey; Dictionary<MethodKey, MemberMapping> cm; if (!DebugUtils.VerifyAndGetCurrentDebuggedMethod(textView, out info, out currentKey, out cm)) { errMsg = "No debug information found. Make sure that only the debugged method is selected in the treeview (press 'Alt+Num *' to go to current statement)"; return false; } var location = textView.TextEditor.TextArea.Caret.Location; var bps = SourceCodeMappingUtils.Find(cm, location.Line, location.Column); if (bps.Count == 0) { errMsg = "It's not possible to set the next statement here"; return false; } // The method def could be different now if the debugged assembly was reloaded from disk // so use SigComparer and not object references to compare the methods. var flags = SigComparerOptions.CompareDeclaringTypes | SigComparerOptions.CompareAssemblyPublicKeyToken | SigComparerOptions.CompareAssemblyVersion | SigComparerOptions.CompareAssemblyLocale | SigComparerOptions.PrivateScopeIsComparable; foreach (var bp in bps) { if (new SigComparer(flags).Equals(bp.MemberMapping.MethodDefinition, info.Item3)) { mapping = bp; break; } } if (mapping == null) { errMsg = "The next statement cannot be set to another method"; return false; } return true; }
public void EndNode(AstNode node) { this.nodes.Pop(); if (this.highlightItems.Count > 0) { TextLocation startLocation = this.startLocations.Pop(); if (this.currentMapping != null) { var ranges = node.Annotation<List<ICSharpCode.Decompiler.ILAst.ILRange>>(); if ((ranges != null) && (ranges.Count > 0)) { foreach (var range in ranges) { SourceCodeMapping scm = null; //foreach (int offset in this.HighlightOffsets) foreach (HighlightItem item in this.highlightItems) { if ((item.Offset >= range.From) && (item.Offset <= range.To)) { if (this.CheckNode(node, item)) { if (scm == null) { int adjust = 0; if (node is ThrowStatement) { adjust = -(this.indent * tabSize + 2); } scm = new SourceCodeMapping() { ILInstructionOffset = range, StartLocation = startLocation, EndLocation = new TextLocation(this.CurrentLocation.Line, this.CurrentLocation.Column + adjust), MemberMapping = this.currentMapping }; } this.HighlightMapping[item.Offset].Add(scm); } } } this.currentMapping.MemberCodeMappings.Add(scm); } } } if (node.Annotation<MemberMapping>() != null) { this.currentMapping = this.memberMapping.Pop(); } } }