/// <summary> /// This function is the callback used to execute the command when the menu item is clicked. /// See the constructor to see how the menu item is associated with this function using /// OleMenuCommandService service and MenuCommand class. /// </summary> /// <param name="sender">Event sender.</param> /// <param name="e">Event args.</param> private void MenuItemCallback(object sender, EventArgs e) { ThreadHelper.ThrowIfNotOnUIThread(); try { _statusBar.SetText(""); var dnSpyPath = ReadDnSpyPath()?.Trim(new [] { '\r', '\n', ' ', '\'', '\"' }); if (string.IsNullOrWhiteSpace(dnSpyPath)) { MessageBox.Show("Set dnSpy path in options first!", "[GoToDnSpy] Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (!File.Exists(dnSpyPath)) { MessageBox.Show($"File '{dnSpyPath}' not exists!", "[GoToDnSpy] Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } var textView = GetTextView(); if (textView == null) { _statusBar.SetText("Can't get text view, please open the file and execute the function while a document window is active."); return; } SnapshotPoint caretPosition = textView.Caret.Position.BufferPosition; Microsoft.CodeAnalysis.Document document = caretPosition.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) { _statusBar.SetText("Execute the function while a document window is active."); return; } SyntaxNode rootSyntaxNode = ThreadHelper.JoinableTaskFactory.Run(() => document.GetSyntaxRootAsync()); SyntaxToken st = rootSyntaxNode.FindToken(caretPosition); SemanticModel semanticModel = ThreadHelper.JoinableTaskFactory.Run(() => document.GetSemanticModelAsync()); ISymbol symbol = null; var parentKind = st.Parent.Kind(); if (st.Kind() == SyntaxKind.IdentifierToken && ( parentKind == SyntaxKind.PropertyDeclaration || parentKind == SyntaxKind.FieldDeclaration || parentKind == SyntaxKind.MethodDeclaration || parentKind == SyntaxKind.NamespaceDeclaration || parentKind == SyntaxKind.DestructorDeclaration || parentKind == SyntaxKind.ConstructorDeclaration || parentKind == SyntaxKind.OperatorDeclaration || parentKind == SyntaxKind.ConversionOperatorDeclaration || parentKind == SyntaxKind.EnumDeclaration || parentKind == SyntaxKind.EnumMemberDeclaration || parentKind == SyntaxKind.ClassDeclaration || parentKind == SyntaxKind.EventDeclaration || parentKind == SyntaxKind.EventFieldDeclaration || parentKind == SyntaxKind.InterfaceDeclaration || parentKind == SyntaxKind.StructDeclaration || parentKind == SyntaxKind.DelegateDeclaration || parentKind == SyntaxKind.IndexerDeclaration || parentKind == SyntaxKind.VariableDeclarator )) { symbol = semanticModel.LookupSymbols(caretPosition.Position, name: st.Text).FirstOrDefault(); } else { SymbolInfo si = semanticModel.GetSymbolInfo(st.Parent); symbol = si.Symbol ?? (si.GetType().GetProperty("CandidateSymbols").GetValue(si) as IEnumerable <ISymbol>)?.FirstOrDefault(); } TryPreprocessLocal(ref symbol); string memberName = null; MemberType memberType = 0; // todo: view SLaks.Ref12.Services.RoslynSymbolResolver if (symbol == null || ( (!TryHandleAsType(symbol, out INamedTypeSymbol typeSymbol)) && (!TryHandleAsMember(symbol, out typeSymbol, out memberName, out memberType)) )) { var msg = $"{st.Text} is not a valid identifier. token: {st.ToString()}, Kind: {st.Kind()}"; _statusBar.SetText(msg); Debug.WriteLine(msg); return; } string typeNamespace = GetFullNamespace(typeSymbol); string typeName = typeNamespace + "." + typeSymbol.MetadataName; string asmDef = GetAssemblyDefinition(typeSymbol.ContainingAssembly); string asmPath = GetAssemblyPath(semanticModel, asmDef); if (string.IsNullOrWhiteSpace(asmPath)) { _statusBar.SetText($"Assembly '{asmDef}' with type {typeName} not found;"); return; } else if (!File.Exists(asmPath)) { MessageBox.Show($"Try build project first;\nAssembly '{asmDef}' with type {typeName} not found, path:\n{asmPath}", "[GoToDnSpy] Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } System.Diagnostics.Process.Start(dnSpyPath, BuildDnSpyArguments(asmPath, typeName, memberName, memberType)); } catch (Exception ex) { _statusBar.SetText(ex.Message.ToString()); MessageBox.Show($"Some error in GoToDnSpy extensiton.\n Please take screenshot and create issue on github with this error\n{ex.ToString()}", "[GoToDnSpy] Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } }