Esempio n. 1
0
        private static async Task <CodeAction> ExtractLocalFunctionAsync(Document document, TextSpan textSpan, ExtractMethodGenerationOptions extractOptions, CodeCleanupOptions cleanupOptions, CancellationToken cancellationToken)
        {
            var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

            if (!syntaxFacts.SupportsLocalFunctionDeclaration(syntaxTree.Options))
            {
                return(null);
            }

            var localFunctionResult = await ExtractMethodService.ExtractMethodAsync(
                document,
                textSpan,
                localFunction : true,
                extractOptions,
                cancellationToken).ConfigureAwait(false);

            Contract.ThrowIfNull(localFunctionResult);

            if (localFunctionResult.Succeeded || localFunctionResult.SucceededWithSuggestion)
            {
                var codeAction = CodeAction.Create(
                    FeaturesResources.Extract_local_function,
                    async c =>
                {
                    var(document, invocationNameToken) = await localFunctionResult.GetFormattedDocumentAsync(cleanupOptions, c).ConfigureAwait(false);
                    return(await AddRenameAnnotationAsync(document, invocationNameToken, c).ConfigureAwait(false));
                },
                    nameof(FeaturesResources.Extract_local_function));
                return(codeAction);
            }

            return(null);
        }
        private static ExtractMethodResult TryWithoutMakingValueTypesRef(
            Document document, NormalizedSnapshotSpanCollection spans, ExtractMethodResult result, CancellationToken cancellationToken)
        {
            OptionSet options = document.Project.Solution.Options;

            if (options.GetOption(ExtractMethodOptions.DontPutOutOrRefOnStruct, document.Project.Language) || !result.Reasons.IsSingle())
            {
                return(null);
            }

            var reason = result.Reasons.FirstOrDefault();
            var length = FeaturesResources.Asynchronous_method_cannot_have_ref_out_parameters_colon_bracket_0_bracket.IndexOf(':');

            if (reason != null && length > 0 && reason.IndexOf(FeaturesResources.Asynchronous_method_cannot_have_ref_out_parameters_colon_bracket_0_bracket.Substring(0, length), 0, length, StringComparison.Ordinal) >= 0)
            {
                options = options.WithChangedOption(ExtractMethodOptions.DontPutOutOrRefOnStruct, document.Project.Language, true);
                var newResult = ExtractMethodService.ExtractMethodAsync(
                    document, spans.Single().Span.ToTextSpan(), options, cancellationToken).WaitAndGetResult(cancellationToken);

                // retry succeeded, return new result
                if (newResult.Succeeded || newResult.SucceededWithSuggestion)
                {
                    return(newResult);
                }
            }

            return(null);
        }
Esempio n. 3
0
        private static async Task <CodeAction> ExtractMethodAsync(Document document, TextSpan textSpan, ExtractMethodGenerationOptions extractOptions, CodeCleanupOptions cleanupOptions, CancellationToken cancellationToken)
        {
            var result = await ExtractMethodService.ExtractMethodAsync(
                document,
                textSpan,
                localFunction : false,
                extractOptions,
                cancellationToken).ConfigureAwait(false);

            Contract.ThrowIfNull(result);

            if (!result.Succeeded && !result.SucceededWithSuggestion)
            {
                return(null);
            }

            return(CodeAction.Create(
                       FeaturesResources.Extract_method,
                       async c =>
            {
                var(document, invocationNameToken) = await result.GetFormattedDocumentAsync(cleanupOptions, c).ConfigureAwait(false);
                return await AddRenameAnnotationAsync(document, invocationNameToken, c).ConfigureAwait(false);
            },
                       nameof(FeaturesResources.Extract_method)));
        }
Esempio n. 4
0
        private async Task <Tuple <CodeAction, string> > GetCodeActionAsync(
            Document document,
            TextSpan textSpan,
            CancellationToken cancellationToken)
        {
            var result = await ExtractMethodService.ExtractMethodAsync(
                document,
                textSpan,
                cancellationToken : cancellationToken).ConfigureAwait(false);

            Contract.ThrowIfNull(result);

            if (result.Succeeded || result.SucceededWithSuggestion)
            {
                var documentOptions = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

                var description = documentOptions.GetOption(ExtractMethodOptions.AllowMovingDeclaration) ?
                                  FeaturesResources.Extract_Method_plus_Local : FeaturesResources.Extract_Method;

                var codeAction  = new MyCodeAction(description, (c) => AddRenameAnnotationAsync(result.Document, result.InvocationNameToken, c));
                var methodBlock = result.MethodDeclarationNode;

                return(Tuple.Create <CodeAction, string>(codeAction, methodBlock.ToString()));
            }

            return(null);
        }
        private async Task <CodeAction> ExtractLocalFunctionAsync(Document document, TextSpan textSpan, CancellationToken cancellationToken)
        {
            var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

            if (!syntaxFacts.SupportsLocalFunctionDeclaration(syntaxTree.Options))
            {
                return(null);
            }

            var localFunctionResult = await ExtractMethodService.ExtractMethodAsync(
                document,
                textSpan,
                localFunction : true,
                cancellationToken : cancellationToken).ConfigureAwait(false);

            Contract.ThrowIfNull(localFunctionResult);

            if (localFunctionResult.Succeeded || localFunctionResult.SucceededWithSuggestion)
            {
                var codeAction = new MyCodeAction(FeaturesResources.Extract_local_function, c => AddRenameAnnotationAsync(localFunctionResult.Document, localFunctionResult.InvocationNameToken, c));
                return(codeAction);
            }

            return(null);
        }
        private static async Task <CodeAction> ExtractMethodAsync(
            Document document,
            TextSpan textSpan,
            CancellationToken cancellationToken
            )
        {
            var result = await ExtractMethodService
                         .ExtractMethodAsync(
                document,
                textSpan,
                localFunction : false,
                cancellationToken : cancellationToken
                )
                         .ConfigureAwait(false);

            Contract.ThrowIfNull(result);

            if (!result.Succeeded && !result.SucceededWithSuggestion)
            {
                return(null);
            }

            return(new MyCodeAction(
                       FeaturesResources.Extract_method,
                       c => AddRenameAnnotationAsync(result.Document, result.InvocationNameToken, c)
                       ));
        }
Esempio n. 7
0
        private static ExtractMethodResult TryWithoutMakingValueTypesRef(
            Document document, NormalizedSnapshotSpanCollection spans, ExtractMethodResult result, ExtractMethodOptions options, CancellationToken cancellationToken)
        {
            if (options.DontPutOutOrRefOnStruct || !result.Reasons.IsSingle())
            {
                return(null);
            }

            var reason = result.Reasons.FirstOrDefault();
            var length = FeaturesResources.Asynchronous_method_cannot_have_ref_out_parameters_colon_bracket_0_bracket.IndexOf(':');

            if (reason != null && length > 0 && reason.IndexOf(FeaturesResources.Asynchronous_method_cannot_have_ref_out_parameters_colon_bracket_0_bracket.Substring(0, length), 0, length, StringComparison.Ordinal) >= 0)
            {
                var newResult = ExtractMethodService.ExtractMethodAsync(
                    document,
                    spans.Single().Span.ToTextSpan(),
                    localFunction: false,
                    options with {
                    DontPutOutOrRefOnStruct = true
                },
        private bool Execute(
            ITextBuffer textBuffer,
            ITextView view,
            CancellationToken cancellationToken)
        {
            var spans = view.Selection.GetSnapshotSpansOnBuffer(textBuffer);

            if (spans.Count(s => s.Length > 0) != 1)
            {
                return(false);
            }

            var document = textBuffer.CurrentSnapshot.GetOpenDocumentInCurrentContextWithChanges();

            if (document == null)
            {
                return(false);
            }

            var result = ExtractMethodService.ExtractMethodAsync(
                document, spans.Single().Span.ToTextSpan(), cancellationToken: cancellationToken).WaitAndGetResult(cancellationToken);

            Contract.ThrowIfNull(result);

            if (!result.Succeeded && !result.SucceededWithSuggestion)
            {
                // if it failed due to out/ref parameter in async method, try it with different option
                var newResult = TryWithoutMakingValueTypesRef(document, spans, result, cancellationToken);
                if (newResult != null)
                {
                    var notificationService = document.Project.Solution.Workspace.Services.GetService <INotificationService>();
                    if (notificationService != null)
                    {
                        if (!notificationService.ConfirmMessageBox(
                                EditorFeaturesResources.Extract_method_failed_with_following_reasons_colon + Environment.NewLine + Environment.NewLine +
                                string.Join(Environment.NewLine, result.Reasons) + Environment.NewLine + Environment.NewLine +
                                EditorFeaturesResources.We_can_fix_the_error_by_not_making_struct_out_ref_parameter_s_Do_you_want_to_proceed,
                                title: EditorFeaturesResources.Extract_Method,
                                severity: NotificationSeverity.Error))
                        {
                            // We handled the command, displayed a notification and did not produce code.
                            return(true);
                        }
                    }

                    // reset result
                    result = newResult;
                }
                else if (TryNotifyFailureToUser(document, result))
                {
                    // We handled the command, displayed a notification and did not produce code.
                    return(true);
                }
            }

            // apply the change to buffer
            // get method name token
            ApplyChangesToBuffer(result, textBuffer, cancellationToken);

            // start inline rename
            var methodNameAtInvocation  = result.InvocationNameToken;
            var snapshotAfterFormatting = textBuffer.CurrentSnapshot;
            var documentAfterFormatting = snapshotAfterFormatting.GetOpenDocumentInCurrentContextWithChanges();

            _renameService.StartInlineSession(documentAfterFormatting, methodNameAtInvocation.Span, cancellationToken);

            // select invocation span
            view.TryMoveCaretToAndEnsureVisible(new SnapshotPoint(snapshotAfterFormatting, methodNameAtInvocation.Span.End));
            view.SetSelection(
                methodNameAtInvocation.Span.ToSnapshotSpan(snapshotAfterFormatting));

            return(true);
        }
Esempio n. 9
0
        private bool Execute(
            ITextBuffer textBuffer,
            ITextView view,
            IUIThreadOperationContext waitContext)
        {
            var cancellationToken = waitContext.UserCancellationToken;

            var spans = view.Selection.GetSnapshotSpansOnBuffer(textBuffer);

            if (spans.Count(s => s.Length > 0) != 1)
            {
                return(false);
            }

            var document = textBuffer.CurrentSnapshot.GetFullyLoadedOpenDocumentInCurrentContextWithChanges(
                waitContext, _threadingContext);

            if (document == null)
            {
                return(false);
            }

            var options = ExtractMethodOptions.From(document.Project);
            var result  = ExtractMethodService.ExtractMethodAsync(
                document, spans.Single().Span.ToTextSpan(), localFunction: false, options, cancellationToken).WaitAndGetResult(cancellationToken);

            Contract.ThrowIfNull(result);

            if (!result.Succeeded && !result.SucceededWithSuggestion)
            {
                // if it failed due to out/ref parameter in async method, try it with different option
                var newResult = TryWithoutMakingValueTypesRef(document, spans, result, options, cancellationToken);
                if (newResult != null)
                {
                    var notificationService = document.Project.Solution.Workspace.Services.GetService <INotificationService>();
                    if (notificationService != null)
                    {
                        // We are about to show a modal UI dialog so we should take over the command execution
                        // wait context. That means the command system won't attempt to show its own wait dialog
                        // and also will take it into consideration when measuring command handling duration.
                        waitContext.TakeOwnership();
                        if (!notificationService.ConfirmMessageBox(
                                EditorFeaturesResources.Extract_method_encountered_the_following_issues + Environment.NewLine + Environment.NewLine +
                                string.Join(Environment.NewLine, result.Reasons) + Environment.NewLine + Environment.NewLine +
                                EditorFeaturesResources.We_can_fix_the_error_by_not_making_struct_out_ref_parameter_s_Do_you_want_to_proceed,
                                title: EditorFeaturesResources.Extract_Method,
                                severity: NotificationSeverity.Error))
                        {
                            // We handled the command, displayed a notification and did not produce code.
                            return(true);
                        }
                    }

                    // reset result
                    result = newResult;
                }
                else if (TryNotifyFailureToUser(document, result, waitContext))
                {
                    // We handled the command, displayed a notification and did not produce code.
                    return(true);
                }
            }

            // apply the change to buffer
            // get method name token
            ApplyChangesToBuffer(result, textBuffer, cancellationToken);

            // start inline rename
            var methodNameAtInvocation  = result.InvocationNameToken;
            var snapshotAfterFormatting = textBuffer.CurrentSnapshot;
            var documentAfterFormatting = snapshotAfterFormatting.GetOpenDocumentInCurrentContextWithChanges();

            _renameService.StartInlineSession(documentAfterFormatting, methodNameAtInvocation.Span, cancellationToken);

            // select invocation span
            view.TryMoveCaretToAndEnsureVisible(new SnapshotPoint(snapshotAfterFormatting, methodNameAtInvocation.Span.End));
            view.SetSelection(
                methodNameAtInvocation.Span.ToSnapshotSpan(snapshotAfterFormatting));

            return(true);
        }
Esempio n. 10
0
        public Document GetRefactoredDocument(CancellationToken cancellationToken)
        {
            lock (this) {
                var start = DateTime.Now;

                Utils.Trace(string.Format("Trying to extract method, span: {0}", this.textSpan));

                var localDocument = document;

                var extracted = ExtractMethodService.ExtractMethodAsync(localDocument, this.textSpan, new ExtractMethodOptions(true), cancellationToken).Result;

                Utils.TraceTime("Roslyn extract method", DateTime.Now - start);

                if (!extracted.Succeeded)
                {
                    Utils.Trace("Method Extraction failed!");
                    return(null);
                }
                Utils.Trace("Extract method: ok");

                var clock = DateTime.Now;

                var resultingTree = localDocument.GetSyntaxTree(cancellationToken).GetRoot(cancellationToken);

                var newMethodSyntax = extracted.MethodDeclarationNode as MethodDeclarationSyntax;
                if (newMethodSyntax == null)
                {
                    return(null);
                }

                var body = newMethodSyntax.Body;

                var compilationUnitDeclaration = resultingTree as CompilationUnitSyntax;
                if (compilationUnitDeclaration == null)
                {
                    return(null);
                }
                var oldTree = localDocument.GetSyntaxTree(cancellationToken);
                if (oldTree == null)
                {
                    return(null);
                }

                Utils.Trace("Got the original syntax tree");

                var oldRoot = oldTree.GetRoot() as SyntaxNode;

                // find the smallest containing statement (and the
                Utils.Trace("Searching for the statement containing the new call");
                StatementSyntax containingStatement = extracted.InvocationNameToken.Parent.FirstAncestorOrSelf <StatementSyntax>();
                if (containingStatement == null)
                {
                    Utils.Trace("No containing statement found. Aborting");
                    return(null);
                }
                Utils.Trace("Containing statement found");

                Utils.Trace("Searching for the right spots where to place the placeholder calls");

                var oldText = oldTree.GetText().ToString();
                var beforeRefactoringText = oldText.Substring(0, containingStatement.Span.Start - 1);
                var afterRefactoringText  = oldText.Substring(containingStatement.Span.Start + containingStatement.Span.Length);

                //var sub = oldText.Substring(containingStatement.Span.Start, containingStatement.Span.Length);
                var sub = oldText.Substring(this.textSpan.Start, this.textSpan.Length);

                Utils.Trace("Generating the Precondition marker");

                var actualParameters = "";
                var formalParameters = "";

                var ps = newMethodSyntax.ParameterList.Parameters;
                for (int i = 0, j = 0, n = ps.Count; i < n; i++)
                {
                    var p = ps[i];
                    {
                        var modifiers = "";

                        foreach (var modifier in p.Modifiers)
                        {
                            modifiers = modifiers + modifier.ValueText + " ";
                        }

                        // Avoid the refs when emitting the condition
                        if (!String.IsNullOrEmpty(modifiers))
                        {
                            if (0 < j)
                            {
                                actualParameters += ",";
                                formalParameters += ",";
                            }

                            var name = p.Identifier.ValueText;
                            actualParameters += name;
                            formalParameters += p.Type + " " + name;

                            j++;
                        }
                    }
                }

                // todo: just use invocation, but replace the method name with __PreconditionMarker!
                var preconditionMarker = "__PreconditionMarker(" + actualParameters + ");";

                Utils.Trace("Generating the Postcondition marker");

                var postconditionMarker = "__PostconditionMarker(" + (actualParameters.Length > 0 ? actualParameters : "");

                BinaryExpressionSyntax assignment = null;
                var invocationExpression          = extracted.InvocationNameToken.Parent.Parent as InvocationExpressionSyntax;
                if (invocationExpression != null)
                {
                    var expression = invocationExpression.Parent.FirstAncestorOrSelf <ExpressionSyntax>();
                    if (expression != null && expression.Kind == SyntaxKind.AssignExpression)
                    {
                        // TODO: what about += or local declarations? should they be included?
                        assignment = (BinaryExpressionSyntax)expression;
                    }
                }

                if (assignment == null) // then the extraction was at the statement level
                {
                    postconditionMarker += (actualParameters.Length > 0 ? "," : "") + "false";
                }
                else
                {
                    postconditionMarker += (actualParameters.Length > 0 ? "," : "") + assignment.Left.GetText() + ", true";
                }
                postconditionMarker += ");";

                Utils.Trace("Searching for the enclosing method");

                // now need to climb up to enclosing method so definitions of the markers can be inserted
                MethodDeclarationSyntax containingMethod = containingStatement.FirstAncestorOrSelf <MethodDeclarationSyntax>();
                if (containingMethod == null)
                {
                    Utils.Trace("No enclosing method found: Aborting");
                    return(null);
                }

                Utils.Trace("Enclosing method found");

                Utils.Trace("Computing string positions for dummy methods");

                cancellationToken.ThrowIfCancellationRequested();
                var beforeMethodText = oldText.Substring(0, containingMethod.Span.Start - 1);
                var inMethodBeforeRefactoringText = oldText.Substring(containingMethod.Span.Start, this.textSpan.Start - containingMethod.Span.Start);
                var remaining = oldText.Substring(this.textSpan.End);

                Utils.Trace("Adding dummy methods");

                var preconditionMarkerDef = "[Pure]\npublic static void __PreconditionMarker(" + formalParameters + "){}\n";

                // It is generic only if there is a parameter representing the return value
                var postconditionMarkerDef = assignment != null ?
                                             "[Pure]\npublic static void __PostconditionMarker<T>(" + formalParameters + (formalParameters.Length > 0 ? "," : "") + "T x,bool returnValue){}\n"
          :
                                             "[Pure]\npublic static void __PostconditionMarker(" + formalParameters + (formalParameters.Length > 0 ? "," : "") + " bool returnValue = false){}\n"
                ;

                var newProg = String.Format("{0}\n{1}\n{2}\n{3}\n{4}\n{5}\n{6}\n{7}",
                                            beforeMethodText, preconditionMarkerDef, postconditionMarkerDef,
                                            inMethodBeforeRefactoringText, preconditionMarker, sub, postconditionMarker,
                                            remaining);

                var newSolution = localDocument.Project.Solution.WithDocumentText(document.Id, SourceText.From(newProg));
                //var newSolution = localDocument.Project.Solution.UpdateDocument(document.Id, SourceText.From(newProg));
                localDocument = newSolution.GetDocument(document.Id);
                var newTree = localDocument.GetSyntaxTree();

                cancellationToken.ThrowIfCancellationRequested();

                Utils.Trace("Dumping annotated tree");

                Utils.DumpCSFile(@"AnnotatedTree.cs", newTree.GetText().ToString(), @"Program with marker explicits");

                var newRoot = (CompilationUnitSyntax)newTree.GetRoot();
                if (newRoot.ContainsDiagnostics)
                {
                    return(null);
                }

                Utils.Trace("Searching the extracted method");

                MethodDeclarationSyntax newExtractedMethod, originalMethod;
                newExtractedMethod = extracted.MethodDeclarationNode as MethodDeclarationSyntax;
                if (newExtractedMethod == null)
                {
                    Utils.Trace("Extracted method not found: aborting");
                    return(null);
                }

                Utils.Trace("Extracted method found");

                originalMethod = newExtractedMethod;


                // Getting the name of the method
                MethodDeclarationSyntax methodToAnalyze = containingStatement.FirstAncestorOrSelf <MethodDeclarationSyntax>();
                if (methodToAnalyze == null)
                {
                    Utils.Trace("Extractee method not found: aborting");

                    return(null);
                }
                Utils.Trace("Extractee method found.");

                Utils.TraceTime("Generating annotated tree", DateTime.Now - clock);
                clock = DateTime.Now; // reset the clock

                // now let Clousot see the rewritten unit

                cancellationToken.ThrowIfCancellationRequested();
                Utils.Trace("Running Clousot to extract <Ps, Qs>");

                newExtractedMethod = ExtractAndAddPsQs(ref cancellationToken, localDocument, newRoot, newExtractedMethod);

                Utils.TraceTime("Running Clousot to extract <Ps, Qs>", DateTime.Now - clock);
                clock = DateTime.Now;

                if (newExtractedMethod == null)
                {
                    Utils.Trace("Aborting: failed to infer <Ps, Qs>");

                    return(null);
                }

                Utils.Trace("Checking we have new contracts");

#if DEBUG || TRACE
                // If we added some contract
                if (newExtractedMethod == originalMethod)
                {
                    Utils.Trace("no new contract, but we continue to get the <Pm, Qm>");
                    //return null;
                }
#endif

                Utils.Trace("Creating a new tree");

                var refactoredTree = (SyntaxNode)extracted.Document.GetSyntaxRoot().ReplaceNode(originalMethod, Formatter.Annotation.AddAnnotationTo(newExtractedMethod));
                //(SyntaxNode)resultingTree.ReplaceNode(originalMethod, Formatter.Annotation.AddAnnotationTo(newExtractedMethod));

                cancellationToken.ThrowIfCancellationRequested();

                Utils.DumpCSFile(@"RefactoredProgram.cs", refactoredTree.ToFullString(), "Program with extracted contracts (Ps, Qs)");
                //Utils.DumpCSFile(@"RefactoredProgram.cs", refactoredTree.GetFullText(), "Program with extracted contracts (Ps, Qs)");

                var annotatedMethod = ExtractAndAddPmQm(ref cancellationToken, localDocument, refactoredTree, newExtractedMethod);

                if (annotatedMethod == null)
                {
                    Utils.Trace("Aborting: failed to annotate the method");
                    return(null);
                }

                Utils.TraceTime("Running Clousot to extract <Pm, Qm>", DateTime.Now - clock);

                if (annotatedMethod != newExtractedMethod)
                {
                    Utils.Trace("Found new contracts, updating the method");
                    Utils.TraceTime("Done!", DateTime.Now - start);

                    refactoredTree = (SyntaxNode)extracted.Document.GetSyntaxRoot().ReplaceNode(originalMethod, Formatter.Annotation.AddAnnotationTo(annotatedMethod));
                }
                Utils.TraceTime("Done!", DateTime.Now - start);

                return(localDocument.WithSyntaxRoot(refactoredTree));
                //return this.editFactory.CreateTreeTransformEdit(localDocument.Project.Solution, localDocument.GetSyntaxTree(), refactoredTree);
            }
        }
Esempio n. 11
0
        public Document GetRefactoredDocument_new(CancellationToken cancellationToken)
        {
            if (this.textSpan.IsEmpty)
            {
                return(null);
            }

            lock (this) {
                var start = DateTime.Now;

                Utils.Trace(string.Format("Trying to extract method, span: {0}", this.textSpan));

                var localDocument = this.document;

                var extracted = ExtractMethodService.ExtractMethodAsync(localDocument, this.textSpan, new ExtractMethodOptions(true), cancellationToken).Result;
                Utils.TraceTime("Roslyn extract method", DateTime.Now - start);
                if (!extracted.Succeeded)
                {
                    Utils.Trace("Method Extraction failed!");
                    return(null);
                }
                Utils.Trace("Extract method: ok");
                var clock = DateTime.Now;

                var root = extracted.Document.GetSyntaxRoot(cancellationToken);
                var closestEnclosingStatement = extracted.InvocationNameToken.Parent.FirstAncestorOrSelf <StatementSyntax>();
                if (closestEnclosingStatement == null)
                {
                    return(null);
                }

                var newMethod = extracted.MethodDeclarationNode as MethodDeclarationSyntax;
                if (newMethod == null)
                {
                    return(null);
                }
                var body = newMethod.Body;


                Utils.Trace("Generating the Precondition marker");

                var actualParameters = "";
                var formalParameters = "";

                var ps = newMethod.ParameterList.Parameters;
                for (int i = 0, j = 0, n = ps.Count; i < n; i++)
                {
                    var p = ps[i];
                    {
                        var modifiers = "";

                        foreach (var modifier in p.Modifiers)
                        {
                            modifiers = modifiers + modifier.ValueText + " ";
                        }

                        // Avoid the refs when emitting the condition
                        if (!String.IsNullOrEmpty(modifiers))
                        {
                            if (0 < j)
                            {
                                actualParameters += ",";
                                formalParameters += ",";
                            }

                            var name = p.Identifier.ValueText;
                            actualParameters += name;
                            formalParameters += p.Type + " " + name;

                            j++;
                        }
                    }
                }

                // todo: just use invocation, but replace the method name with __PreconditionMarker!
                var preconditionMarkerString = "__PreconditionMarker(" + actualParameters + ");";
                var preconditionMarker       = Formatter.Annotation.AddAnnotationTo(SyntaxFactory.ParseStatement(preconditionMarkerString));

                var postconditionMarker = Formatter.Annotation.AddAnnotationTo(SyntaxFactory.ParseStatement("Console.WriteLine(5);\n"));


                var b = SyntaxFactory.Block(preconditionMarker, closestEnclosingStatement, postconditionMarker);


                //var finalRoot = ((SyntaxNode)root).ReplaceNode(
                //     closestEnclosingStatement,
                //     b.WithAdditionalAnnotations(CodeActionAnnotations.CreateRenameAnnotation())
                //     );

                Utils.Trace("Adding dummy methods");

                var preconditionMarkerDefString = "[Pure]\npublic static void __PreconditionMarker(" + formalParameters + "){}\n";
                var preconditionMarkerDef       = SyntaxFactory.MethodDeclaration(null, new SyntaxTokenList(), SyntaxFactory.ParseTypeName("void"), null, SyntaxFactory.ParseToken("__PreconditionMarker"), null, SyntaxFactory.ParseParameterList("(" + formalParameters + ")"), null, SyntaxFactory.Block());

                var r1       = (SyntaxNode)root;
                var classDef = closestEnclosingStatement.FirstAncestorOrSelf <TypeDeclarationSyntax>();
                var r2       = new AddMarkerMethods(classDef, preconditionMarkerDef).Visit(r1);
                var r3       = r2.ReplaceNode(
                    closestEnclosingStatement,
                    b.WithAdditionalAnnotations(CodeActionAnnotations.CreateRenameAnnotation())
                    );
                return(this.document.WithSyntaxRoot(r3));


#if false
                var resultingTree = (SyntaxNode)extracted.MethodDeclarationNode;

                var newMethodIdentified = (SyntaxToken)extracted.InvocationNameToken;


                var oldTree = localDocument.GetSyntaxTree(cancellationToken);
                if (oldTree == null)
                {
                    return(null);
                }

                Utils.Trace("Got the original syntax tree");
                var oldRoot = oldTree.GetRoot(cancellationToken) as SyntaxNode;
#endif
            }
        }