/// <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 TextPosition(lineNumber, columnNumber); foreach (var m in codeMapping.MemberCodeMappings.OrderBy(a => a.ILRange.From)) { if (m.StartPosition <= loc && loc <= m.EndPosition) { return(m); } } var list = new List <SourceCodeMapping>(codeMapping.MemberCodeMappings.FindAll(a => a.StartPosition.Line <= lineNumber && lineNumber <= a.EndPosition.Line)); list.Sort((a, b) => { var d = GetDist(a.StartPosition, lineNumber, columnNumber).CompareTo(GetDist(b.StartPosition, lineNumber, columnNumber)); if (d != 0) { return(d); } return(a.ILRange.From.CompareTo(b.ILRange.From)); }); if (list.Count > 0) { return(list[0]); } return(null); } else { SourceCodeMapping map = null; foreach (var m in codeMapping.MemberCodeMappings) { if (lineNumber < m.StartPosition.Line || lineNumber > m.EndPosition.Line) { continue; } if (map == null || m.ILRange.From < map.ILRange.From) { map = m; } } return(map); } }
bool DebugGetSourceCodeMappingForSetNextStatement(ITextEditorUIContext uiContext, out string errMsg, out SourceCodeMapping mapping) { errMsg = string.Empty; mapping = null; if (ProcessState == DebuggerProcessState.Terminated) { errMsg = dnSpy_Debugger_Resources.Error_NotDebugging; return false; } if (ProcessState == DebuggerProcessState.Starting || ProcessState == DebuggerProcessState.Continuing || ProcessState == DebuggerProcessState.Running) { errMsg = dnSpy_Debugger_Resources.Error_CantSetNextStatementWhenNotStopped; return false; } if (uiContext == null) { uiContext = fileTabManager.ActiveTab.TryGetTextEditorUIContext(); if (uiContext == null) { errMsg = dnSpy_Debugger_Resources.Error_NoTabAvailableDecompileCurrentMethod; return false; } } CodeMappings cm; if (currentLocation == null || !DebugUtils.VerifyAndGetCurrentDebuggedMethod(uiContext, currentLocation.Value.SerializedDnToken, out cm)) { errMsg = dnSpy_Debugger_Resources.Error_NoDebugInfoAvailable; return false; } Debug.Assert(currentLocation != null); var location = uiContext.Location; var bps = cm.Find(location.Line, location.Column); if (bps.Count == 0) { errMsg = dnSpy_Debugger_Resources.Error_CantSetNextStatementHere; return false; } if (GetCurrentMethodILFrame() == null) { errMsg = dnSpy_Debugger_Resources.Error_CantSetNextStatementNoILFrame; return false; } foreach (var bp in bps) { var md = bp.Mapping.Method; if (currentLocation.Value.Function.Token != md.MDToken.Raw) continue; var serAsm = serializedDnModuleCreator.Create(md.Module); if (!serAsm.Equals(currentLocation.Value.SerializedDnToken.Module)) continue; mapping = bp; break; } if (mapping == null) { errMsg = dnSpy_Debugger_Resources.Error_CantSetNextStatementToAnotherMethod; return false; } return true; }