Span?IDotNetSpanMap.ToSpan(ModuleId module, uint token, uint ilOffset) { if (toMethodDebugInfo == null) { toMethodDebugInfo = new Dictionary <ModuleTokenId, MethodDebugInfo>(methodDebugInfos.Count); foreach (var info in methodDebugInfos) { var tokenId = new ModuleTokenId(moduleIdProvider.Create(info.Method.Module), info.Method.MDToken); if (toMethodDebugInfo.TryGetValue(tokenId, out var otherInfo)) { if (info.Statements.Length < otherInfo.Statements.Length) { continue; } } toMethodDebugInfo[tokenId] = info; } } if (!toMethodDebugInfo.TryGetValue(new ModuleTokenId(module, token), out var info2)) { return(null); } var statement = info2.GetSourceStatementByCodeOffset(ilOffset); if (statement == null) { return(null); } var textSpan = statement.Value.TextSpan; return(new Span(textSpan.Start, textSpan.Length)); }
public static bool GoToIL(IModuleIdProvider moduleIdProvider, IDocumentTabService documentTabService, IDsDocument document, uint token, uint ilOffset, bool newTab) { if (document == null) return false; var method = document.ModuleDef.ResolveToken(token) as MethodDef; if (method == null) return false; var modId = moduleIdProvider.Create(method.Module); var key = new ModuleTokenId(modId, method.MDToken); bool found = documentTabService.DocumentTreeView.FindNode(method.Module) != null; if (found) { documentTabService.FollowReference(method, newTab, true, e => { Debug.Assert(e.Tab.UIContext is IDocumentViewer); if (e.Success && !e.HasMovedCaret) { MoveCaretTo(e.Tab.UIContext as IDocumentViewer, key, ilOffset); e.HasMovedCaret = true; } }); return true; } Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => { documentTabService.FollowReference(method, newTab, true, e => { Debug.Assert(e.Tab.UIContext is IDocumentViewer); if (e.Success && !e.HasMovedCaret) { MoveCaretTo(e.Tab.UIContext as IDocumentViewer, key, ilOffset); e.HasMovedCaret = true; } }); })); return true; }
public IEnumerable <ITagSpan <ITextMarkerTag> > GetTags(ActiveStatementTagger tagger, NormalizedSnapshotSpanCollection spans) { if (activeStatements.Count == 0 || spans.Count == 0) { yield break; } //TODO: This code shouldn't depend on IDocumentViewer var docViewer = tagger.TextView.TextBuffer.TryGetDocumentViewer(); if (docViewer == null) { yield break; } var methodDebugService = docViewer.TryGetMethodDebugService(); if (methodDebugService == null) { yield break; } var snapshot = spans[0].Snapshot; MethodDef method = null; List <uint> ilOffsets = null; foreach (var span in spans) { foreach (var info in methodDebugService.GetStatementsByTextSpan(span.Span)) { if (info.Method != method) { method = info.Method; var moduleTokenId = new ModuleTokenId(moduleIdProvider.Create(method.Module), method.MDToken); if (!activeStatements.TryGetValue(moduleTokenId, out ilOffsets)) { continue; } } else if (ilOffsets == null) { continue; } var textSpan = info.Statement.TextSpan; if (textSpan.End > snapshot.Length) { yield break; // Old data, but we'll get called again } var binSpan = info.Statement.BinSpan; foreach (uint ilOffset in ilOffsets) { if (ilOffset >= binSpan.Start && ilOffset < binSpan.End) { yield return(new TagSpan <ITextMarkerTag>(new SnapshotSpan(snapshot, textSpan.Start, textSpan.Length), activeStatementTextMarkerTag)); } } } } }
public IGlyphTextMethodMarker AddMarker(MethodDef method, uint ilOffset, ImageReference?glyphImage, string markerTypeName, string selectedMarkerTypeName, IClassificationType classificationType, int zIndex, object tag, IGlyphTextMarkerHandler handler, Func <ITextView, bool> textViewFilter) { if (method == null) { throw new ArgumentNullException(nameof(method)); } return(AddMarker(new ModuleTokenId(moduleIdProvider.Create(method.Module), method.MDToken), ilOffset, glyphImage, markerTypeName, selectedMarkerTypeName, classificationType, zIndex, tag, handler, textViewFilter)); }
public override IEnumerable <SnapshotSpan> GetFrameSpans(ITextView textView, NormalizedSnapshotSpanCollection spans) { if (activeStatements.Count == 0) { yield break; } var docViewer = textView.TextBuffer.TryGetDocumentViewer(); if (docViewer == null) { yield break; } var methodDebugService = docViewer.TryGetMethodDebugService(); if (methodDebugService == null) { yield break; } var snapshot = spans[0].Snapshot; MethodDef method = null; List <uint> ilOffsets = null; foreach (var span in spans) { foreach (var info in methodDebugService.GetStatementsByTextSpan(span.Span)) { if (info.Method != method) { method = info.Method; var moduleTokenId = new ModuleTokenId(moduleIdProvider.Create(method.Module), method.MDToken); if (!activeStatements.TryGetValue(moduleTokenId, out ilOffsets)) { continue; } } else if (ilOffsets == null) { continue; } var textSpan = info.Statement.TextSpan; if (textSpan.End > snapshot.Length) { yield break; // Old data, but we'll get called again } var ilSpan = info.Statement.ILSpan; foreach (uint ilOffset in ilOffsets) { if (ilOffset >= ilSpan.Start && ilOffset < ilSpan.End) { yield return(new SnapshotSpan(snapshot, textSpan.Start, textSpan.Length)); } } } } }
void DocumentTabService_FileCollectionChanged(object sender, NotifyDocumentCollectionChangedEventArgs e) { switch (e.Type) { case NotifyDocumentCollectionType.Clear: case NotifyDocumentCollectionType.Remove: var existing = new HashSet <ModuleId>(documentTabService.DocumentTreeView.GetAllModuleNodes().Select(a => moduleIdProvider.Create(a.Document.ModuleDef))); var removed = new HashSet <ModuleId>(e.Documents.Select(a => moduleIdProvider.Create(a.ModuleDef))); existing.Remove(new ModuleId()); removed.Remove(new ModuleId()); object orbArg = null; if (OnRemoveBreakpoints != null) { orbArg = OnRemoveBreakpoints(orbArg); } foreach (var ilbp in GetILCodeBreakpoints()) { // Don't auto-remove BPs in dynamic modules since they have no disk file. The // user must delete these him/herself. if (ilbp.MethodToken.Module.IsDynamic) { continue; } // If the file is still in the TV, don't delete anything. This can happen if // we've loaded an in-memory module and the node just got removed. if (existing.Contains(ilbp.MethodToken.Module)) { continue; } if (removed.Contains(ilbp.MethodToken.Module)) { Remove(ilbp); } } OnRemoveBreakpoints?.Invoke(orbArg); break; case NotifyDocumentCollectionType.Add: break; } }
IDsDocument LoadExisting(ModuleId moduleId) { foreach (var file in AllActiveDocuments) { var otherId = moduleIdProvider.Create(file.ModuleDef); if (otherId.Equals(moduleId)) { return(file); } } foreach (var file in AllDocuments) { var moduleIdFile = moduleIdProvider.Create(file.ModuleDef); if (moduleIdFile.Equals(moduleId)) { return(file); } } return(null); }
public MethodDebugService(IReadOnlyList <MethodDebugInfo> methodDebugInfos, ITextSnapshot snapshot, IModuleIdProvider moduleIdProvider) { if (methodDebugInfos == null) { throw new ArgumentNullException(nameof(methodDebugInfos)); } if (snapshot == null) { throw new ArgumentNullException(nameof(snapshot)); } if (moduleIdProvider == null) { throw new ArgumentNullException(nameof(moduleIdProvider)); } this.dict = new Dictionary <ModuleTokenId, MethodDebugInfo>(methodDebugInfos.Count); this.snapshot = snapshot; this.moduleIdProvider = moduleIdProvider; var modIdDict = new Dictionary <ModuleDef, ModuleId>(); foreach (var info in methodDebugInfos) { var module = info.Method.Module; if (module == null) { continue; } ModuleId moduleId; if (!modIdDict.TryGetValue(module, out moduleId)) { moduleId = moduleIdProvider.Create(module); modIdDict.Add(module, moduleId); } var key = new ModuleTokenId(moduleId, info.Method.MDToken); MethodDebugInfo oldDebugInfo; if (this.dict.TryGetValue(key, out oldDebugInfo)) { if (info.Statements.Length < oldDebugInfo.Statements.Length) { continue; } } this.dict[key] = info; } }
public static bool GoToIL(IModuleIdProvider moduleIdProvider, IDocumentTabService documentTabService, IDsDocument document, uint token, uint ilOffset, bool newTab) { if (document == null) { return(false); } var method = document.ModuleDef.ResolveToken(token) as MethodDef; if (method == null) { return(false); } var modId = moduleIdProvider.Create(method.Module); var key = new ModuleTokenId(modId, method.MDToken); bool found = documentTabService.DocumentTreeView.FindNode(method.Module) != null; if (found) { documentTabService.FollowReference(method, newTab, true, e => { Debug.Assert(e.Tab.UIContext is IDocumentViewer); if (e.Success && !e.HasMovedCaret) { MoveCaretTo(e.Tab.UIContext as IDocumentViewer, key, ilOffset); e.HasMovedCaret = true; } }); return(true); } Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() => { documentTabService.FollowReference(method, newTab, true, e => { Debug.Assert(e.Tab.UIContext is IDocumentViewer); if (e.Success && !e.HasMovedCaret) { MoveCaretTo(e.Tab.UIContext as IDocumentViewer, key, ilOffset); e.HasMovedCaret = true; } }); })); return(true); }
public MethodDebugInfoMethodOffsetSpanMap(IModuleIdProvider moduleIdProvider, ReadOnlyCollection <MethodDebugInfo> methodDebugInfos) { if (methodDebugInfos == null) { throw new ArgumentNullException(nameof(methodDebugInfos)); } this.moduleIdProvider = moduleIdProvider; toMethodDebugInfo = new Dictionary <ModuleTokenId, MethodDebugInfo>(methodDebugInfos.Count); foreach (var info in methodDebugInfos) { var token = new ModuleTokenId(moduleIdProvider.Create(info.Method.Module), info.Method.MDToken); MethodDebugInfo otherInfo; if (toMethodDebugInfo.TryGetValue(token, out otherInfo)) { if (info.Statements.Length < otherInfo.Statements.Length) { continue; } } toMethodDebugInfo[token] = info; } }
public override TextViewBookmarkLocationResult?CreateLocation(IDocumentTab tab, ITextView textView, VirtualSnapshotPoint position) { var documentViewer = tab.TryGetDocumentViewer(); if (documentViewer == null) { return(null); } // A bookmark should be set on the current line if possible, and the current position // isn't necessarily at the start of the line. int startPos = position.Position.GetContainingLine().Start.Position; foreach (var data in documentViewer.ReferenceCollection.FindFrom(startPos)) { if (!data.Data.IsDefinition) { continue; } var def = data.Data.Reference as IMemberDef; if (def == null) { continue; } var span = data.Span; var snapshot = textView.TextSnapshot; if (span.End > snapshot.Length) { return(null); } var moduleId = moduleIdProvider.Create(def.Module); var location = dotNetBookmarkLocationFactory.Value.CreateTokenLocation(moduleId, def.MDToken.Raw); return(new TextViewBookmarkLocationResult(location, new SnapshotSpan(snapshot, span))); } return(null); }
public override TextViewBookmarkLocationResult?CreateLocation(IDocumentTab tab, ITextView textView, VirtualSnapshotPoint position) { var documentViewer = tab.TryGetDocumentViewer(); if (documentViewer == null) { return(null); } var methodDebugService = documentViewer.GetMethodDebugService(); if (methodDebugService == null) { return(null); } // A bookmark should be set on the current line if possible, and the current position // isn't necessarily at the start of the line. var startPos = position.Position.GetContainingLine().Start; var methodStatements = methodDebugService.FindByTextPosition(startPos, FindByTextPositionOptions.None); if (methodStatements.Count == 0) { return(null); } var textSpan = methodStatements[0].Statement.TextSpan; var snapshot = textView.TextSnapshot; if (textSpan.End > snapshot.Length) { return(null); } var span = new VirtualSnapshotSpan(new SnapshotSpan(snapshot, new Span(textSpan.Start, textSpan.Length))); var statement = methodStatements[0]; var moduleId = moduleIdProvider.Create(statement.Method.Module); var location = dotNetBookmarkLocationFactory.Value.CreateMethodBodyLocation(moduleId, statement.Method.MDToken.Raw, statement.Statement.ILSpan.Start); return(new TextViewBookmarkLocationResult(location, span)); }
public override DbgTextViewBreakpointLocationResult?CreateLocation(IDocumentTab tab, ITextView textView, VirtualSnapshotPoint position) { var documentViewer = tab.TryGetDocumentViewer(); if (documentViewer == null) { return(null); } var methodDebugService = documentViewer.GetMethodDebugService(); if (methodDebugService == null) { return(null); } var methodStatements = methodDebugService.FindByTextPosition(position.Position, FindByTextPositionOptions.None); if (methodStatements.Count == 0) { return(null); } var textSpan = methodStatements[0].Statement.TextSpan; var snapshot = textView.TextSnapshot; if (textSpan.End > snapshot.Length) { return(null); } var span = new VirtualSnapshotSpan(new SnapshotSpan(snapshot, new Span(textSpan.Start, textSpan.Length))); var locations = new DbgCodeLocation[methodStatements.Count]; for (int i = 0; i < methodStatements.Count; i++) { var statement = methodStatements[i]; var moduleId = moduleIdProvider.Create(statement.Method.Module); locations[i] = dbgDotNetCodeLocationFactory.Value.Create(moduleId, statement.Method.MDToken.Raw, statement.Statement.ILSpan.Start); } return(new DbgTextViewBreakpointLocationResult(locations, span)); }