private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken token)
        {
            var sourceText = await document.GetTextAsync(token).ConfigureAwait(false);

            var startIndex = sourceText.Lines.IndexOf(diagnostic.Location.SourceSpan.Start);
            int endIndex = startIndex;

            for (var i = startIndex + 1; i < sourceText.Lines.Count; i++)
            {
                if (!string.IsNullOrWhiteSpace(sourceText.Lines[i].ToString()))
                {
                    endIndex = i - 1;
                    break;
                }
            }

            if (endIndex >= (startIndex + 1))
            {
                var replaceSpan = TextSpan.FromBounds(sourceText.Lines[startIndex + 1].SpanIncludingLineBreak.Start, sourceText.Lines[endIndex].SpanIncludingLineBreak.End);
                var newSourceText = sourceText.Replace(replaceSpan, string.Empty);
                return document.WithText(newSourceText);
            }

            return document;
        }
        private static async Task<Document> GetTransformedDocumentAsync(Document document, Location location, CancellationToken cancellationToken)
        {
            var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
            var sourceSpan = location.SourceSpan;

            return document.WithText(text.WithChanges(GetTextChange(text, sourceSpan)));
        }
        private bool TryGetDocumentWithFullyQualifiedTypeName(Document document, out TextSpan updatedTextSpan, out Document documentWithFullyQualifiedTypeName)
        {
            documentWithFullyQualifiedTypeName = null;
            updatedTextSpan = default(TextSpan);

            var surfaceBufferFieldSpan = new VsTextSpan[1];
            if (snippetExpansionClient.ExpansionSession.GetFieldSpan(_fieldName, surfaceBufferFieldSpan) != VSConstants.S_OK)
            {
                return false;
            }

            SnapshotSpan subjectBufferFieldSpan;
            if (!snippetExpansionClient.TryGetSubjectBufferSpan(surfaceBufferFieldSpan[0], out subjectBufferFieldSpan))
            {
                return false;
            }

            var originalTextSpan = new TextSpan(subjectBufferFieldSpan.Start, subjectBufferFieldSpan.Length);
            updatedTextSpan = new TextSpan(subjectBufferFieldSpan.Start, _fullyQualifiedName.Length);

            var textChange = new TextChange(originalTextSpan, _fullyQualifiedName);
            var newText = document.GetTextAsync(CancellationToken.None).WaitAndGetResult(CancellationToken.None).WithChanges(textChange);

            documentWithFullyQualifiedTypeName = document.WithText(newText);
            return true;
        }
        private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
        {
            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
            var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            TextChange textChange = new TextChange(new TextSpan(diagnostic.Location.SourceSpan.Start, 1), string.Empty);
            return document.WithText(text.WithChanges(textChange));
        }
        private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken token)
        {
            var newLine = document.Project.Solution.Workspace.Options.GetOption(FormattingOptions.NewLine, LanguageNames.CSharp);

            var sourceText = await document.GetTextAsync(token).ConfigureAwait(false);
            var textChange = new TextChange(diagnostic.Location.SourceSpan, newLine);

            return document.WithText(sourceText.WithChanges(textChange));
        }
 private async Task<Document> ReplaceWithUtcNowAsync(Document document, TextSpan span, CancellationToken cancellationToken)
 {
     var text = await document.GetTextAsync();
     var repl = "DateTime.UtcNow";
     if (Regex.Replace(text.GetSubText(span).ToString(),@"\s+",string.Empty) == "System.DateTime.Now")
         repl = "System.DateTime.UtcNow";
     var newtext = text.Replace(span, repl);
     return document.WithText(newtext);
 }
 private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
 {
     var indentationOptions = IndentationOptions.FromDocument(document);
     SourceText sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
     return document.WithText(sourceText.WithChanges(FixDiagnostic(indentationOptions, sourceText, diagnostic)));
 }
 /// <summary>
 /// Fixes the whitespace at the end of a document.
 /// </summary>
 /// <param name="document">The document to be changed.</param>
 /// <param name="diagnostic">The diagnostic to fix.</param>
 /// <param name="newlineAtEndOfFile">A <see cref="EndOfFileHandling"/> value indicating the desired behavior.</param>
 /// <param name="cancellationToken">The cancellation token associated with the fix action.</param>
 /// <returns>The transformed document.</returns>
 private static async Task<Document> FixEndOfFileAsync(Document document, Diagnostic diagnostic, EndOfFileHandling newlineAtEndOfFile, CancellationToken cancellationToken)
 {
     var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
     string replacement = newlineAtEndOfFile == EndOfFileHandling.Omit ? string.Empty : "\r\n";
     return document.WithText(text.WithChanges(new TextChange(diagnostic.Location.SourceSpan, replacement)));
 }
        private static async Task<Document> GetSingleAnalyzerDocumentAsync(ImmutableArray<DiagnosticAnalyzer> analyzers, CodeFixProvider codeFixProvider, int? codeFixIndex, Document document, int maxNumberOfIterations, CancellationToken cancellationToken)
        {
            var previousDiagnostics = ImmutableArray.Create<Diagnostic>();

            bool done;
            do
            {
                var analyzerDiagnostics = await GetSortedDiagnosticsFromDocumentsAsync(analyzers, new[] { document }, cancellationToken).ConfigureAwait(false);
                if (analyzerDiagnostics.Length == 0)
                {
                    break;
                }

                if (!AreDiagnosticsDifferent(analyzerDiagnostics, previousDiagnostics))
                {
                    break;
                }

                if (--maxNumberOfIterations < 0)
                {
                    Assert.True(false, "The upper limit for the number of code fix iterations was exceeded");
                }

                previousDiagnostics = analyzerDiagnostics;

                done = true;
                for (var i = 0; i < analyzerDiagnostics.Length; i++)
                {
                    var actions = new List<CodeAction>();
                    var context = new CodeFixContext(document, analyzerDiagnostics[i], (a, d) => actions.Add(a), cancellationToken);
                    await codeFixProvider.RegisterCodeFixesAsync(context).ConfigureAwait(false);

                    if (actions.Count > 0)
                    {
                        var fixedDocument = await ApplyFixAsync(document, actions.ElementAt(codeFixIndex.GetValueOrDefault(0)), cancellationToken).ConfigureAwait(false);
                        if (fixedDocument != document)
                        {
                            done = false;
                            var newText = await fixedDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);

                            // workaround for issue #936 - force re-parsing to get the same sort of syntax tree as the original document.
                            document = document.WithText(newText);
                            break;
                        }
                    }
                }
            }
            while (!done);

            return document;
        }
        private Document DeleteMember(Document document, SyntaxNode node)
        {
            var text = document.GetTextAsync(CancellationToken.None)
                               .WaitAndGetResult_CodeModel(CancellationToken.None);

            // We want to delete all the leading trivia from the node back to,
            // but not including:
            //  * the first preprocessor directive
            //  - or -
            //  * the first comment after a white-space only line
            // We also want to delete all the trailing trivia

            var deletionEnd = node.FullSpan.End;

            var deletionStart = node.SpanStart;

            int contiguousEndOfLines = 0;
            foreach (var trivia in node.GetLeadingTrivia().Reverse())
            {
                if (trivia.IsDirective)
                {
                    break;
                }

                if (trivia.Kind() == SyntaxKind.EndOfLineTrivia)
                {
                    if (contiguousEndOfLines > 0)
                    {
                        break;
                    }
                    else
                    {
                        contiguousEndOfLines++;
                    }
                }
                else if (trivia.Kind() != SyntaxKind.WhitespaceTrivia)
                {
                    contiguousEndOfLines = 0;
                }

                deletionStart = trivia.FullSpan.Start;
            }

            text = text.Replace(TextSpan.FromBounds(deletionStart, deletionEnd), string.Empty);

            return document.WithText(text);
        }
Example #11
0
        private static Document ForkNewDocument(CopyData copyData, Document document, TextSpan span)
        {
            // here we assume paste data is what is copied before.
            // we will check this assumption when things are actually pasted.
            var newText = document.GetTextAsync().Result.ToString().Remove(span.Start, span.Length).Insert(span.Start, copyData.Text);

            // fork solution
            return document.WithText(SourceText.From(newText));
        }
 private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
 {
     var settings = SettingsHelper.GetStyleCopSettings(document.Project.AnalyzerOptions, cancellationToken);
     SourceText sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
     return document.WithText(sourceText.WithChanges(FixDiagnostic(settings.Indentation, sourceText, diagnostic)));
 }
Example #13
0
        private void ApplyDocumentToBuffer(Document document, SpanChange spanSource, out SourceTextContainer container, out Document documentBackedByTextBuffer)
        {
            var contentTypeService = document.Project.LanguageServices.GetService<IContentTypeLanguageService>();
            var contentType = contentTypeService.GetDefaultContentType();

            TextView.TextBuffer.ChangeContentType(contentType, null);

            var documentText = document.GetTextAsync().Result.ToString();
            SpanToShow = spanSource.GetSpan();

            using (var edit = TextView.TextBuffer.CreateEdit())
            {
                edit.Replace(new Span(0, TextView.TextBuffer.CurrentSnapshot.Length), documentText);
                edit.Apply();
            }

            container = TextView.TextBuffer.AsTextContainer();
            documentBackedByTextBuffer = document.WithText(container.CurrentText);
        }
        protected override bool TryGetSimplifiedTypeNameInCaseContext(Document document, string fullyQualifiedTypeName, string firstEnumMemberName, int startPosition, int endPosition, CancellationToken cancellationToken, out string simplifiedTypeName)
        {
            simplifiedTypeName = string.Empty;
            var typeAnnotation = new SyntaxAnnotation();

            var str = "case " + fullyQualifiedTypeName + "." + firstEnumMemberName + ":" + Environment.NewLine + " break;";
            var textChange = new TextChange(new TextSpan(startPosition, endPosition - startPosition), str);
            var typeSpanToAnnotate = new TextSpan(startPosition + "case ".Length, fullyQualifiedTypeName.Length);

            var textWithCaseAdded = document.GetTextAsync(cancellationToken).WaitAndGetResult(cancellationToken).WithChanges(textChange);
            var documentWithCaseAdded = document.WithText(textWithCaseAdded);

            var syntaxRoot = documentWithCaseAdded.GetSyntaxRootSynchronously(cancellationToken);
            var nodeToReplace = syntaxRoot.DescendantNodes().FirstOrDefault(n => n.Span == typeSpanToAnnotate);

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

            var updatedRoot = syntaxRoot.ReplaceNode(nodeToReplace, nodeToReplace.WithAdditionalAnnotations(typeAnnotation, Simplifier.Annotation));
            var documentWithAnnotations = documentWithCaseAdded.WithSyntaxRoot(updatedRoot);

            var simplifiedDocument = Simplifier.ReduceAsync(documentWithAnnotations, cancellationToken: cancellationToken).Result;
            simplifiedTypeName = simplifiedDocument.GetSyntaxRootSynchronously(cancellationToken).GetAnnotatedNodesAndTokens(typeAnnotation).Single().ToString();
            return true;
        }
 private static async Task<Document> RemoveSemicolonTextAsync(Document document, SyntaxToken token, CancellationToken cancellationToken)
 {
     SourceText sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
     TextLine line = sourceText.Lines.GetLineFromPosition(token.SpanStart);
     if (sourceText.ToString(line.Span).Trim() == token.Text)
     {
         // remove the line containing the semicolon token
         TextChange textChange = new TextChange(line.SpanIncludingLineBreak, string.Empty);
         return document.WithText(sourceText.WithChanges(textChange));
     }
     else
     {
         // remove just the semicolon
         TextChange textChange = new TextChange(token.Span, string.Empty);
         return document.WithText(sourceText.WithChanges(textChange));
     }
 }
 /// <summary>
 /// Removes trailing whitespace.
 /// </summary>
 /// <param name="document">The document to be changed.</param>
 /// <param name="diagnostic">The diagnostic to fix.</param>
 /// <param name="cancellationToken">The cancellation token associated with the fix action.</param>
 /// <returns>The transformed document.</returns>
 private static async Task<Document> RemoveWhitespaceAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
 {
     var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
     return document.WithText(text.WithChanges(new TextChange(diagnostic.Location.SourceSpan, string.Empty)));
 }
        private Document Delete(Document document, AttributeSyntax node)
        {
            var attributeList = node.FirstAncestorOrSelf<AttributeListSyntax>();

            // If we don't have anything left, then just delete the whole attribute list.
            if (attributeList.Attributes.Count == 1)
            {
                var text = document.GetTextAsync(CancellationToken.None)
                                   .WaitAndGetResult_CodeModel(CancellationToken.None);

                // Note that we want to keep all leading trivia and delete all trailing trivia.
                var deletionStart = attributeList.SpanStart;
                var deletionEnd = attributeList.FullSpan.End;

                text = text.Replace(TextSpan.FromBounds(deletionStart, deletionEnd), string.Empty);

                return document.WithText(text);
            }
            else
            {
                var newAttributeList = attributeList.RemoveNode(node, SyntaxRemoveOptions.KeepNoTrivia);

                return document.ReplaceNodeAsync(attributeList, newAttributeList, CancellationToken.None)
                               .WaitAndGetResult_CodeModel(CancellationToken.None);
            }
        }
        private static async Task<Document> RemoveSemicolonTextAsync(Document document, SyntaxToken token, CancellationToken cancellationToken)
        {
            TextChange textChange;

            SourceText sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
            TextLine line = sourceText.Lines.GetLineFromPosition(token.SpanStart);
            if (sourceText.ToString(line.Span).Trim() == token.Text)
            {
                // remove the line containing the semicolon token
                textChange = new TextChange(line.SpanIncludingLineBreak, string.Empty);
                return document.WithText(sourceText.WithChanges(textChange));
            }

            TextSpan spanToRemove;
            var whitespaceIndex = TriviaHelper.IndexOfTrailingWhitespace(token.LeadingTrivia);
            if (whitespaceIndex >= 0)
            {
                spanToRemove = TextSpan.FromBounds(token.LeadingTrivia[whitespaceIndex].Span.Start, token.Span.End);
            }
            else
            {
                var previousToken = token.GetPreviousToken();
                whitespaceIndex = TriviaHelper.IndexOfTrailingWhitespace(previousToken.TrailingTrivia);
                if (whitespaceIndex >= 0)
                {
                    spanToRemove = TextSpan.FromBounds(previousToken.TrailingTrivia[whitespaceIndex].Span.Start, token.Span.End);
                }
                else
                {
                    spanToRemove = token.Span;
                }
            }

            textChange = new TextChange(spanToRemove, string.Empty);
            return document.WithText(sourceText.WithChanges(textChange));
        }
        private static async Task<Document> GetFixAllAnalyzerAsync(FixAllScope scope, ImmutableArray<DiagnosticAnalyzer> analyzers, CodeFixProvider codeFixProvider, int? codeFixIndex, Document document, int numberOfIterations, CancellationToken cancellationToken)
        {
            int expectedNumberOfIterations = numberOfIterations;
            if (numberOfIterations < 0)
            {
                numberOfIterations = -numberOfIterations;
            }

            var previousDiagnostics = ImmutableArray.Create<Diagnostic>();

            var fixAllProvider = codeFixProvider.GetFixAllProvider();

            if (fixAllProvider == null)
            {
                return null;
            }

            bool done;
            do
            {
                var analyzerDiagnostics = await GetSortedDiagnosticsFromDocumentsAsync(analyzers, new[] { document }, cancellationToken).ConfigureAwait(false);
                if (analyzerDiagnostics.Length == 0)
                {
                    break;
                }

                if (!AreDiagnosticsDifferent(analyzerDiagnostics, previousDiagnostics))
                {
                    break;
                }

                if (--numberOfIterations < 0)
                {
                    Assert.True(false, "The upper limit for the number of fix all iterations was exceeded");
                }

                string equivalenceKey = null;
                foreach (var diagnostic in analyzerDiagnostics)
                {
                    if (!codeFixProvider.FixableDiagnosticIds.Contains(diagnostic.Id))
                    {
                        // do not pass unsupported diagnostics to a code fix provider
                        continue;
                    }

                    var actions = new List<CodeAction>();
                    var context = new CodeFixContext(document, diagnostic, (a, d) => actions.Add(a), cancellationToken);
                    await codeFixProvider.RegisterCodeFixesAsync(context).ConfigureAwait(false);
                    if (actions.Count > (codeFixIndex ?? 0))
                    {
                        equivalenceKey = actions[codeFixIndex ?? 0].EquivalenceKey;
                        break;
                    }
                }

                previousDiagnostics = analyzerDiagnostics;

                done = true;

                FixAllContext.DiagnosticProvider fixAllDiagnosticProvider = TestDiagnosticProvider.Create(analyzerDiagnostics);

                IEnumerable<string> analyzerDiagnosticIds = analyzers.SelectMany(x => x.SupportedDiagnostics).Select(x => x.Id);
                IEnumerable<string> compilerDiagnosticIds = codeFixProvider.FixableDiagnosticIds.Where(x => x.StartsWith("CS", StringComparison.Ordinal));
                IEnumerable<string> disabledDiagnosticIds = document.Project.CompilationOptions.SpecificDiagnosticOptions.Where(x => x.Value == ReportDiagnostic.Suppress).Select(x => x.Key);
                IEnumerable<string> relevantIds = analyzerDiagnosticIds.Concat(compilerDiagnosticIds).Except(disabledDiagnosticIds).Distinct();
                FixAllContext fixAllContext = new FixAllContext(document, codeFixProvider, scope, equivalenceKey, relevantIds, fixAllDiagnosticProvider, cancellationToken);

                CodeAction action = await fixAllProvider.GetFixAsync(fixAllContext).ConfigureAwait(false);
                if (action == null)
                {
                    return document;
                }

                var fixedDocument = await ApplyFixAsync(document, action, cancellationToken).ConfigureAwait(false);
                if (fixedDocument != document)
                {
                    done = false;
                    var newText = await fixedDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);

                    // workaround for issue #936 - force re-parsing to get the same sort of syntax tree as the original document.
                    document = document.WithText(newText);
                }
            }
            while (!done);

            if (expectedNumberOfIterations >= 0)
            {
                Assert.Equal($"{expectedNumberOfIterations} iterations", $"{expectedNumberOfIterations - numberOfIterations} iterations");
            }

            return document;
        }
 private static async Task<Document> GetTransformedDocumentAsync(Document document, Diagnostic diagnostic, CancellationToken cancellationToken)
 {
     var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
     var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
     return document.WithText(text.WithChanges(GetTextChange(root, text, diagnostic)));
 }
        private static async Task<Document> GetFixAllAnalyzerAsync(FixAllScope scope, ImmutableArray<DiagnosticAnalyzer> analyzers, CodeFixProvider codeFixProvider, int? codeFixIndex, Document document, int maxNumberOfIterations, CancellationToken cancellationToken)
        {
            var previousDiagnostics = ImmutableArray.Create<Diagnostic>();

            var fixAllProvider = codeFixProvider.GetFixAllProvider();

            if (fixAllProvider == null)
            {
                return null;
            }

            bool done;
            do
            {
                var analyzerDiagnostics = await GetSortedDiagnosticsFromDocumentsAsync(analyzers, new[] { document }, cancellationToken).ConfigureAwait(false);
                if (analyzerDiagnostics.Length == 0)
                {
                    break;
                }

                if (!AreDiagnosticsDifferent(analyzerDiagnostics, previousDiagnostics))
                {
                    break;
                }

                if (--maxNumberOfIterations < 0)
                {
                    Assert.True(false, "The upper limit for the number of fix all iterations was exceeded");
                }

                string equivalenceKey = null;
                foreach (var diagnostic in analyzerDiagnostics)
                {
                    var actions = new List<CodeAction>();
                    var context = new CodeFixContext(document, diagnostic, (a, d) => actions.Add(a), cancellationToken);
                    await codeFixProvider.RegisterCodeFixesAsync(context).ConfigureAwait(false);
                    if (actions.Count > (codeFixIndex ?? 0))
                    {
                        equivalenceKey = actions[codeFixIndex ?? 0].EquivalenceKey;
                        break;
                    }
                }

                previousDiagnostics = analyzerDiagnostics;

                done = true;

                FixAllContext.DiagnosticProvider fixAllDiagnosticProvider = TestDiagnosticProvider.Create(analyzerDiagnostics);

                FixAllContext fixAllContext = new FixAllContext(document, codeFixProvider, scope, equivalenceKey, codeFixProvider.FixableDiagnosticIds, fixAllDiagnosticProvider, cancellationToken);

                CodeAction action = await fixAllProvider.GetFixAsync(fixAllContext).ConfigureAwait(false);
                if (action == null)
                {
                    return document;
                }

                var fixedDocument = await ApplyFixAsync(document, action, cancellationToken).ConfigureAwait(false);
                if (fixedDocument != document)
                {
                    done = false;
                    var newText = await fixedDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);

                    // workaround for issue #936 - force re-parsing to get the same sort of syntax tree as the original document.
                    document = document.WithText(newText);
                }
            }
            while (!done);

            return document;
        }
 private static async Task<Document> RecreateDocumentAsync(Document document, CancellationToken cancellationToken)
 {
     var newText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
     newText = newText.WithChanges(new TextChange(new TextSpan(0, 0), " "));
     newText = newText.WithChanges(new TextChange(new TextSpan(0, 1), string.Empty));
     return document.WithText(newText);
 }