private async Task <bool> NavigateThroughInterfaceImplementationsAsync(Document currentDocument, ISymbol selectedSymbol, SnapshotPoint currentPosition) { if (_interfaceNavigationState != null) { // check if count is greater than 2 if (_interfaceNavigationState.SymbolsToVisit.Count() > 1) { // check if user didn't move elsewhere if (selectedSymbol.ToString() == _interfaceNavigationState.SymbolsToVisit.First().ToString()) { _interfaceNavigationState.SymbolsToVisit.RemoveAt(0); return(TryGoToDefinition(currentDocument.Project, _interfaceNavigationState.SymbolsToVisit.First())); } else { _interfaceNavigationState = null; } } else if (_interfaceNavigationState.SymbolsToVisit.Count() == 1) { if (selectedSymbol.ToString() == _interfaceNavigationState.SymbolsToVisit.First().ToString()) { return(await GotoPositionAsync(currentDocument, _interfaceNavigationState.NavigateToPositionAtTheEnd)); } } } return(false); }
public async Task <bool> GoToImplementationAsync() { var wpfTextView = await GetWpfTextViewAsync(); var currentPosition = wpfTextView.Caret.Position.BufferPosition; var document = currentPosition.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) { // no document found => we can't help return(false); } var semanticModel = await document.GetSemanticModelAsync(); // find symbol at caret position var selectedSymbol = await SymbolFinder.FindSymbolAtPositionAsync(semanticModel, currentPosition.Position, document.Project.Solution.Workspace); if (selectedSymbol == null) { // no symbol selected => we can't help return(false); } if (await NavigateThroughInterfaceImplementationsAsync(document, selectedSymbol, currentPosition)) { return(true); } _interfaceNavigationState = null; // search implementation only if method or property symbol if (selectedSymbol is IMethodSymbol || selectedSymbol is IPropertySymbol) { try { // prio 1: we're assuming it's an interface method/property => find implementations var implSymbols = await SymbolFinder.FindImplementationsAsync(selectedSymbol, document.Project.Solution); if (implSymbols.Any()) { var symbolsToVisit = new List <ISymbol>(); symbolsToVisit.Add(selectedSymbol); symbolsToVisit.AddRange(implSymbols); _interfaceNavigationState = new NavigationState { SymbolsToVisit = symbolsToVisit, NavigateToPositionAtTheEnd = currentPosition }; return(await TryGoToDefinitionOrNavigateBackwardAsync(document, selectedSymbol, currentPosition)); } // prio 2: we assume that it is an implementation of an interface method/property // we will jump betweem each implementation var interfaceSymbols = await SymbolFinder.FindImplementedInterfaceMembersAsync(selectedSymbol, document.Project.Solution); if (interfaceSymbols.Count() > 0) { var implInterfaceSymbols = new List <ISymbol>(); foreach (var interfaceSymbol in interfaceSymbols) { implInterfaceSymbols.AddRange(await SymbolFinder.FindImplementationsAsync(interfaceSymbol, document.Project.Solution)); } if (implInterfaceSymbols.Any()) { NavigateTo(implInterfaceSymbols, document.Project, selectedSymbol); return(true); } } // prio 3: we assume override or abstract var overrideSymbols = await SymbolFinder.FindOverridesAsync(selectedSymbol, document.Project.Solution); if (overrideSymbols.Any()) { NavigateTo(overrideSymbols, document.Project, selectedSymbol); return(true); } } catch (System.Exception ex) { ShowMessageBox($"{ex.Message}:\n{ex.StackTrace}"); } } // default behaviour: Go to definition as F12 or NavigateBackward Ctrl + - return(await TryGoToDefinitionOrNavigateBackwardAsync(document, selectedSymbol, currentPosition)); }