public async static Task Run(MonoDevelop.Ide.Gui.Document doc)
        {
            if (!doc.Editor.IsSomethingSelected)
            {
                return;
            }
            var ad = doc.AnalysisDocument;

            if (ad == null || !await IsValid(doc))
            {
                return;
            }
            try {
                var selectionRange = doc.Editor.SelectionRange;
                var token          = default(CancellationToken);
                var selection      = new CSharpSelectionValidator(await SemanticDocument.CreateAsync(ad, token).ConfigureAwait(false), new TextSpan(selectionRange.Offset, selectionRange.Length), doc.GetOptionSet());
                var result         = await selection.GetValidSelectionAsync(token).ConfigureAwait(false);

                if (!result.ContainsValidContext)
                {
                    return;
                }
                var extractor        = new CSharpMethodExtractor((CSharpSelectionResult)result);
                var extractionResult = await extractor.ExtractMethodAsync(token).ConfigureAwait(false);

                var changes = await extractionResult.Document.GetTextChangesAsync(ad, token);

                using (var undo = doc.Editor.OpenUndoGroup()) {
                    foreach (var change in changes.OrderByDescending(ts => ts.Span.Start))
                    {
                        doc.Editor.ReplaceText(change.Span.Start, change.Span.Length, change.NewText);
                    }
                    // hack to remove the redundant private modifier.
                    if (doc.Editor.GetTextAt(extractionResult.MethodDeclarationNode.SpanStart, "private ".Length) == "private ")
                    {
                        doc.Editor.RemoveText(extractionResult.MethodDeclarationNode.SpanStart, "private ".Length);
                    }
                }
                await doc.UpdateParseDocument();

                var info = RefactoringSymbolInfo.GetSymbolInfoAsync(doc, extractionResult.InvocationNameToken.Span.Start).Result;
                var sym  = info.DeclaredSymbol ?? info.Symbol;
                if (sym != null)
                {
                    await new MonoDevelop.Refactoring.Rename.RenameRefactoring().Rename(sym);
                }
            }
            catch (Exception e) {
                LoggingService.LogError("Error while extracting method", e);
            }
        }
        public static async Task <bool> IsValid(MonoDevelop.Ide.Gui.Document doc, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (doc == null)
            {
                return(false);
            }
            if (doc.Editor == null || !doc.Editor.IsSomethingSelected)
            {
                return(false);
            }
            var ad = doc.AnalysisDocument;

            if (ad == null)
            {
                return(false);
            }
            var selectionRange = doc.Editor.SelectionRange;

            try {
                var selection = new CSharpSelectionValidator(await SemanticDocument.CreateAsync(ad, cancellationToken).ConfigureAwait(false), new TextSpan(selectionRange.Offset, selectionRange.Length), doc.GetOptionSet());
                var result    = await selection.GetValidSelectionAsync(cancellationToken).ConfigureAwait(false);

                return(result.ContainsValidContext);
            } catch (Exception) {
                return(false);
            }
        }