protected override void CommandCallback(object sender, EventArgs e) { IWpfTextView textView = ServiceProvider.GetWpfTextView(); if (textView == null) { return; } BqlFormatter formatter = CreateFormatter(textView); SnapshotPoint caretPosition = textView.Caret.Position.BufferPosition; Document document = caretPosition.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) { return; } (SyntaxNode syntaxRoot, SemanticModel semanticModel) = ThreadHelper.JoinableTaskFactory.Run( async() => (await document.GetSyntaxRootAsync(), await document.GetSemanticModelAsync())); if (syntaxRoot == null || semanticModel == null) { return; } SyntaxNode formattedRoot; if (textView.Selection.IsActive && !textView.Selection.IsEmpty) // if has selection { // Find all nodes within the span and format them var selectionSpan = TextSpan.FromBounds(textView.Selection.Start.Position, textView.Selection.End.Position); SyntaxNode topNode = syntaxRoot.FindNode(selectionSpan); // can, return top node that intersects with selectionSpan, so we need SpanWalker here if (topNode == null) { return; // nothing to format (e.g. selection contains only trivia) } var spanWalker = new SpanWalker(selectionSpan); spanWalker.Visit(topNode); if (spanWalker.NodesWithinSpan.Count == 0) { return; } formattedRoot = syntaxRoot.ReplaceNodes(spanWalker.NodesWithinSpan, (o, r) => formatter.Format(o, semanticModel)); } else { formattedRoot = formatter.Format(syntaxRoot, semanticModel); } if (!textView.TextBuffer.EditInProgress) { var formattedDocument = document.WithSyntaxRoot(formattedRoot); ApplyChanges(document, formattedDocument); } }
private async System.Threading.Tasks.Task CommandCallbackAsync() { await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); IWpfTextView textView = await ServiceProvider.GetWpfTextViewAsync(); if (textView == null || Package.DisposalToken.IsCancellationRequested) { return; } SnapshotPoint caretPosition = textView.Caret.Position.BufferPosition; Document document = caretPosition.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (document == null) { return; } await TaskScheduler.Default; //Go to background thread BqlFormatter formatter = BqlFormatter.FromTextView(textView); SyntaxNode syntaxRoot = await document.GetSyntaxRootAsync(); SemanticModel semanticModel = await document.GetSemanticModelAsync(); if (syntaxRoot == null || semanticModel == null) { return; } bool isPlatformReferenced = semanticModel.Compilation.GetTypeByMetadataName(TypeFullNames.PXGraph) != null; if (!isPlatformReferenced) { return; } SyntaxNode formattedRoot; if (textView.Selection.IsActive && !textView.Selection.IsEmpty) // if has selection { // Find all nodes within the span and format them var selectionSpan = TextSpan.FromBounds(textView.Selection.Start.Position, textView.Selection.End.Position); SyntaxNode topNode = syntaxRoot.FindNode(selectionSpan); // can, return top node that intersects with selectionSpan, so we need SpanWalker here if (topNode == null) { return; // nothing to format (e.g. selection contains only trivia) } var spanWalker = new SpanWalker(selectionSpan); spanWalker.Visit(topNode); if (spanWalker.NodesWithinSpan.Count == 0) { return; } formattedRoot = syntaxRoot.ReplaceNodes(spanWalker.NodesWithinSpan, (oldNode, replacementNode) => formatter.Format(oldNode, semanticModel) ?? replacementNode); } else { formattedRoot = formatter.Format(syntaxRoot, semanticModel) ?? syntaxRoot; } await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(); // Return to UI thread if (!textView.TextBuffer.EditInProgress && formattedRoot != syntaxRoot) { var formattedDocument = document.WithSyntaxRoot(formattedRoot); ApplyChanges(document, formattedDocument); } }