예제 #1
0
        /// <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);
            }
        }