public static async Task InsertMemberWithCursor(string operation, Projects.Project project, ITypeSymbol type, Location part, SyntaxNode newMember, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (operation == null)
            {
                throw new ArgumentNullException(nameof(operation));
            }
            if (project == null)
            {
                throw new ArgumentNullException(nameof(project));
            }
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }
            if (newMember == null)
            {
                throw new ArgumentNullException(nameof(newMember));
            }
            var doc = await IdeApp.Workbench.OpenDocument(part.SourceTree.FilePath, project, true);

            var textView = await doc.GetContentWhenAvailable <ITextView> (cancellationToken);

            await doc.DocumentContext.UpdateParseDocument();

            var document = doc.DocumentContext.AnalysisDocument;

            if (document == null)
            {
                LoggingService.LogError("Can't find document to insert member (fileName:" + part.SourceTree.FilePath + ")");
                return;
            }
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var typeDecl = (ClassDeclarationSyntax)root.FindNode(part.SourceSpan);

            // for some reason the reducer doesn't reduce this
            var systemVoid = newMember.DescendantNodesAndSelf().OfType <QualifiedNameSyntax> ().FirstOrDefault(ma => ma.ToString() == "System.Void");

            if (systemVoid != null)
            {
                newMember = newMember.ReplaceNode(systemVoid, SyntaxFactory.ParseTypeName("void"));
            }

            var newRoot = root.ReplaceNode(typeDecl, typeDecl.AddMembers((MemberDeclarationSyntax)newMember.WithAdditionalAnnotations(Simplifier.Annotation, Formatter.Annotation, insertedMemberAnnotation)));

            var projectOptions = await document.GetOptionsAsync(cancellationToken);

            document = document.WithSyntaxRoot(newRoot);
            document = await Formatter.FormatAsync(document, Formatter.Annotation, projectOptions, cancellationToken).ConfigureAwait(false);

            document = await Simplifier.ReduceAsync(document, Simplifier.Annotation, projectOptions, cancellationToken).ConfigureAwait(false);

            root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var node  = root.GetAnnotatedNodes(insertedMemberAnnotation).Single();
            var model = await doc.DocumentContext.AnalysisDocument.GetSemanticModelAsync(cancellationToken);

            Application.Invoke((o, args) => {
                var editor = doc.Editor;
                if (editor == null)
                {
                    // bypass the insertion point selection UI for the new editor
                    document.Project.Solution.Workspace.TryApplyChanges(document.Project.Solution);
                    var editorOperationsFactoryService = CompositionManager.Instance.GetExportedValue <IEditorOperationsFactoryService> ();
                    var editorOperations = editorOperationsFactoryService.GetEditorOperations(textView);
                    var point            = new Microsoft.VisualStudio.Text.VirtualSnapshotPoint(textView.TextSnapshot, node.SpanStart);
                    editorOperations.SelectAndMoveCaret(point, point, TextSelectionMode.Stream, EnsureSpanVisibleOptions.AlwaysCenter);
                    return;
                }

                var insertionPoints = InsertionPointService.GetInsertionPoints(
                    editor,
                    model,
                    type,
                    part.SourceSpan.Start
                    );
                var options = new InsertionModeOptions(
                    operation,
                    insertionPoints,
                    point => {
                    if (!point.Success)
                    {
                        return;
                    }
                    var text = node.ToString();
                    point.InsertionPoint.Insert(editor, doc.DocumentContext, text);
                }
                    );

                editor.StartInsertionMode(options);
            });
        }
예제 #2
0
        public static async Task InsertMemberWithCursor(string operation, Projects.Project project, ITypeSymbol type, Location part, SyntaxNode newMember, CancellationToken cancellationToken = default(CancellationToken))
        {
            if (operation == null)
            {
                throw new ArgumentNullException(nameof(operation));
            }
            if (project == null)
            {
                throw new ArgumentNullException(nameof(project));
            }
            if (type == null)
            {
                throw new ArgumentNullException(nameof(type));
            }
            if (newMember == null)
            {
                throw new ArgumentNullException(nameof(newMember));
            }
            var doc = await IdeApp.Workbench.OpenDocument(part.SourceTree.FilePath, project, true);

            await doc.UpdateParseDocument();

            var document = doc.AnalysisDocument;

            if (document == null)
            {
                LoggingService.LogError("Can't find document to insert member (fileName:" + part.SourceTree.FilePath + ")");
                return;
            }
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var typeDecl = (ClassDeclarationSyntax)root.FindNode(part.SourceSpan);

            // for some reason the reducer doesn't reduce this
            var systemVoid = newMember.DescendantNodesAndSelf().OfType <QualifiedNameSyntax> ().FirstOrDefault(ma => ma.ToString() == "System.Void");

            if (systemVoid != null)
            {
                newMember = newMember.ReplaceNode(systemVoid, SyntaxFactory.ParseTypeName("void"));
            }

            var newRoot = root.ReplaceNode(typeDecl, typeDecl.AddMembers((MemberDeclarationSyntax)newMember.WithAdditionalAnnotations(Simplifier.Annotation, Formatter.Annotation, insertedMemberAnnotation)));

            var policy         = project.Policies.Get <CSharpFormattingPolicy> ("text/x-csharp");
            var textPolicy     = project.Policies.Get <TextStylePolicy> ("text/x-csharp");
            var projectOptions = policy.CreateOptions(textPolicy);

            document = document.WithSyntaxRoot(newRoot);
            document = await Formatter.FormatAsync(document, Formatter.Annotation, projectOptions, cancellationToken).ConfigureAwait(false);

            document = await Simplifier.ReduceAsync(document, Simplifier.Annotation, projectOptions, cancellationToken).ConfigureAwait(false);

            root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var node = root.GetAnnotatedNodes(insertedMemberAnnotation).Single();

            Application.Invoke(async(o, args) => {
                var insertionPoints = InsertionPointService.GetInsertionPoints(
                    doc.Editor,
                    await doc.UpdateParseDocument(),
                    type,
                    part.SourceSpan.Start
                    );
                var options = new InsertionModeOptions(
                    operation,
                    insertionPoints,
                    point => {
                    if (!point.Success)
                    {
                        return;
                    }
                    var text = node.ToString();
                    point.InsertionPoint.Insert(doc.Editor, doc, text);
                }
                    );

                doc.Editor.StartInsertionMode(options);
            });
        }