Example #1
0
        public static void TestAssertingEndText(
            string sampleClassCode,
            TextSpan refactoringSiteTextSpan,
            Action <string> assertion,
            int refactoringNumber = 0)
        {
            TestAsertingRefactorings(
                sampleClassCode,
                refactoringSiteTextSpan,
                (workspace, document, proposedCodeRefactorings) =>
            {
                CodeAction refactoring        = proposedCodeRefactorings.ElementAt(refactoringNumber);
                CodeActionOperation operation = refactoring
                                                .GetOperationsAsync(CancellationToken.None)
                                                .Result
                                                .Single();

                operation.Apply(workspace, CancellationToken.None);

                Document newDocument = workspace.CurrentSolution.GetDocument(document.Id);

                SourceText newText = newDocument.GetTextAsync(CancellationToken.None).Result;

                string text = newText.ToString();

                assertion(text);
            });
        }
        /// <summary>
        /// Apply the inputted CodeAction to the inputted document.
        /// Meant to be used to apply codefixes.
        /// </summary>
        /// <param name="document">The Document to apply the fix on</param>
        /// <param name="codeAction">A CodeAction that will be applied to the Document.</param>
        /// <returns>A Document with the changes from the CodeAction</returns>
        private static async Task <Document> ApplyFix(Document document, CodeAction codeAction)
        {
            try
            {
                var operations = await codeAction.GetOperationsAsync(CancellationToken.None);

                var solution = operations.OfType <ApplyChangesOperation>().Single().ChangedSolution;
                return(solution.GetDocument(document.Id));
            }
            catch (AggregateException e)
            {
                if (e.InnerExceptions.Count <= 0)
                {
                    throw;
                }

                foreach (var ex in e.InnerExceptions)
                {
                    Console.WriteLine("Exception thrown during code fix: " + ex.Message);
                    Console.WriteLine(ex.StackTrace.ToString());
                }

                throw;
            }
        }
        protected override async Task <IEnumerable <CodeActionOperation> > ComputeOperationsAsync(CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            var previewDialogService = _workspace.Services.GetService <IPreviewDialogService>();

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

            var changedSolution = previewDialogService.PreviewChanges(
                EditorFeaturesResources.PreviewChanges,
                "vs.codefix.previewchanges",
                _originalCodeAction.Title,
                EditorFeaturesResources.PreviewChangesRootNodeText,
                CodeAnalysis.Glyph.OpenFolder,
                _changeSummary.NewSolution,
                _changeSummary.OldSolution,
                showCheckBoxes: false);

            if (changedSolution == null)
            {
                // User pressed the cancel button.
                return(null);
            }

            cancellationToken.ThrowIfCancellationRequested();
            return(await _originalCodeAction.GetOperationsAsync(cancellationToken).ConfigureAwait(false));
        }
                internal override async Task <ImmutableArray <CodeActionOperation> > GetOperationsCoreAsync(IProgressTracker progressTracker, CancellationToken cancellationToken)
                {
                    cancellationToken.ThrowIfCancellationRequested();
                    var previewDialogService = _workspace.Services.GetService <IPreviewDialogService>();

                    if (previewDialogService == null)
                    {
                        return(ImmutableArray <CodeActionOperation> .Empty);
                    }

                    var changedSolution = previewDialogService.PreviewChanges(
                        EditorFeaturesResources.Preview_Changes,
                        "vs.codefix.previewchanges",
                        _originalCodeAction.Title,
                        EditorFeaturesResources.Changes,
                        CodeAnalysis.Glyph.OpenFolder,
                        _changeSummary.NewSolution,
                        _changeSummary.OldSolution,
                        showCheckBoxes: false);

                    if (changedSolution == null)
                    {
                        // User pressed the cancel button.
                        return(ImmutableArray <CodeActionOperation> .Empty);
                    }

                    cancellationToken.ThrowIfCancellationRequested();
                    return(await _originalCodeAction.GetOperationsAsync(cancellationToken).ConfigureAwait(false));
                }
Example #5
0
        public static void CodeAction(CodeAction codeAction, Document document, string expectedCode)
        {
            var operations = codeAction.GetOperationsAsync(CancellationToken.None).GetAwaiter().GetResult().ToList();

            if (operations.Count == 0)
            {
                throw RoslynTestKitException.NoOperationForCodeAction(codeAction);
            }

            var workspace = document.Project.Solution.Workspace;

            foreach (var operation in operations)
            {
                operation.Apply(workspace, CancellationToken.None);
            }
            var newDocument = workspace.CurrentSolution.GetDocument(document.Id);

            var sourceText = newDocument.GetTextAsync(CancellationToken.None).GetAwaiter().GetResult();
            var actualCode = sourceText.ToString();

            if (actualCode != expectedCode)
            {
                DiffHelper.TryToReportDiffWithExternalTool(expectedCode, actualCode);
                var diff = DiffHelper.GenerateInlineDiff(expectedCode, actualCode);
                throw new  TransformedCodeDifferentThanExpectedException(actualCode, expectedCode, diff);
            }
        }
        /// <summary>
        /// Apply the inputted CodeAction to the inputted document.
        /// Meant to be used to apply codefixes.
        /// </summary>
        /// <param name="document">The Document to apply the fix on.</param>
        /// <param name="codeAction">A CodeAction that will be applied to the Document.</param>
        /// <returns>A Document with the changes from the CodeAction</returns>
        private static Document ApplyFix(Document document, CodeAction codeAction)
        {
            var operations = codeAction.GetOperationsAsync(CancellationToken.None).Result;
            var solution   = operations.OfType <ApplyChangesOperation>().Single().ChangedSolution;

            return(solution.GetDocument(document.Id));
        }
Example #7
0
        private async Task <Document> ConvertCodeActionToChangedDocument(CodeAction action, CancellationToken cancellationToken)
        {
            var operations = await action.GetOperationsAsync(cancellationToken).ConfigureAwait(false);

            if (operations == null)
            {
                return(document);
            }
            if (operations.Count() > 1)
            {
                Console.WriteLine($"{DiagnosticId} : Only single operation is supported. Operation count = {operations.Count()} : {document.FilePath}");
                return(document);
            }

            var applyOperation = operations.First() as ApplyChangesOperation;

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

            var changedDocument = applyOperation.ChangedSolution?.Projects?.First()?.GetDocument(document.Id);

            return(changedDocument != null ? changedDocument : document);
        }
        internal static async void RunAction(DocumentContext context, CodeAction action, CancellationToken cancellationToken)
        {
            var operations = await action.GetOperationsAsync(cancellationToken).ConfigureAwait(false);

            if (operations == null)
            {
                return;
            }
            foreach (var op in operations)
            {
                if (op == null)
                {
                    continue;
                }
                try {
                    op.Apply(context.RoslynWorkspace, cancellationToken);
                } catch (Exception e) {
                    LoggingService.LogError("Error while appyling operation : " + op, e);
                }
            }

            if ((bool)hasCodeActionsProperty.GetValue(action))
            {
                var result = (ImmutableArray <CodeAction>)getCodeActionsMethod.Invoke(action, null);
                foreach (var nested in result)
                {
                    RunAction(context, nested, cancellationToken);
                }
            }
        }
Example #9
0
        /// <summary>
        /// Apply the inputted CodeAction to the inputted document.
        /// Meant to be used to apply codefixes.
        /// </summary>
        /// <param name="document">The Document to apply the fix on</param>
        /// <param name="codeAction">A CodeAction that will be applied to the Document.</param>
        /// <returns>A Document with the changes from the CodeAction</returns>
        private Document ApplyFix(Document document, CodeAction codeAction)
        {
            ImmutableArray <CodeActionOperation> operations = codeAction.GetOperationsAsync(CancellationToken.None).Result;
            Solution solution = operations.OfType <ApplyChangesOperation>().Single().ChangedSolution;

            return(solution.GetDocument(document.Id));
        }
        internal static async Task RunAction(DocumentContext context, CodeAction action, CancellationToken cancellationToken)
        {
            var operations = await action.GetOperationsAsync(cancellationToken).ConfigureAwait(false);

            if (operations == null)
            {
                return;
            }

            foreach (var op in operations)
            {
                if (op == null)
                {
                    continue;
                }
                try {
                    op.Apply(context.RoslynWorkspace, cancellationToken);
                } catch (Exception e) {
                    LoggingService.LogError("Error while applying operation : " + op, e);
                }
            }

            foreach (var nested in action.NestedCodeActions)
            {
                await RunAction(context, nested, cancellationToken).ConfigureAwait(false);
            }
        }
Example #11
0
        private async Task <string> ExecuteTest(string sourceCode)
        {
            var(diagnostic, document, workspace) = await TestSetup.SetupAsync(sourceCode);

            var        codeFixProvider = new JsonAnalyzerCodeFixProvider();
            CodeAction codeAction      = null;

            if (!diagnostic.Any())
            {
                return((await document.GetTextAsync(CancellationToken.None)).ToString());
            }
            var context = new CodeFixContext(document, diagnostic[0], (action, _) =>
            {
                codeAction = action;
            }, CancellationToken.None);

            await codeFixProvider.RegisterCodeFixesAsync(context);

            if (codeAction == null)
            {
                throw new Exception("Code action was not registered");
            }

            var operations = await codeAction.GetOperationsAsync(CancellationToken.None);

            foreach (var operation in operations)
            {
                operation.Apply(workspace, CancellationToken.None);
            }

            var updateDocument = workspace.CurrentSolution.GetDocument(document.Id);
            var actual         = (await updateDocument !.GetTextAsync()).ToString();

            return(actual);
        }
Example #12
0
        protected void Test(
            string markup,
            string expected,
            int actionIndex    = 0,
            bool compareTokens = false)
        {
            if (!markup.Contains('\r'))
            {
                markup = markup.Replace("\n", "\r\n");
            }

            if (!expected.Contains('\r'))
            {
                expected = expected.Replace("\n", "\r\n");
            }

            MarkupTestFile.GetSpan(markup, out string code, out TextSpan span);

            Document document = CreateDocument(code);
            IEnumerable <CodeAction> actions = GetRefactoring(document, span);

            Assert.NotNull(actions);

            CodeAction action = actions.ElementAt(actionIndex);

            Assert.NotNull(action);

            ApplyChangesOperation edit = action.GetOperationsAsync(CancellationToken.None).Result.OfType <ApplyChangesOperation>().First();

            VerifyDocument(expected, compareTokens, edit.ChangedSolution.GetDocument(document.Id));
        }
Example #13
0
        public static void CodeAction(CodeAction codeAction, Document document, string expectedCode)
        {
            var operations = codeAction.GetOperationsAsync(CancellationToken.None).GetAwaiter().GetResult().ToList();

            if (operations.Count == 0)
            {
                throw RoslynTestKitException.NoOperationForCodeAction(codeAction);
            }

            if (operations.Count > 1)
            {
                throw RoslynTestKitException.MoreThanOneOperationForCodeAction(codeAction, operations);
            }

            var operation = operations.Single();
            var workspace = document.Project.Solution.Workspace;

            operation.Apply(workspace, CancellationToken.None);

            var newDocument = workspace.CurrentSolution.GetDocument(document.Id);

            var sourceText = newDocument.GetTextAsync(CancellationToken.None).GetAwaiter().GetResult();
            var text       = sourceText.ToString();

            if (text != expectedCode)
            {
                TryToReportDiff(expectedCode, text);
                throw new  TransformedCodeDifferentThanExpectedException(text, expectedCode);
            }
        }
Example #14
0
        private async Task TestFixAllAsync(int codepage, FixAllScope scope)
        {
            string[] testCode = new[] { "class Foo { }", "class Bar { }" };

            this.fileEncoding = Encoding.GetEncoding(codepage);

            // Create a project using the specified encoding
            Project project    = this.CreateProject(testCode);
            Project oldProject = project;

            Workspace workspace = project.Solution.Workspace;

            var codeFixer      = this.GetCSharpCodeFixProvider();
            var fixAllProvider = codeFixer.GetFixAllProvider();
            var diagnostics    = new List <Diagnostic>();
            var descriptor     = this.GetCSharpDiagnosticAnalyzers().First().SupportedDiagnostics.First();

            foreach (var document in project.Documents)
            {
                // Create a diagnostic for the document to fix
                var diagnostic = Diagnostic.Create(
                    descriptor,
                    Location.Create(await document.GetSyntaxTreeAsync().ConfigureAwait(false), TextSpan.FromBounds(0, 0)));
                diagnostics.Add(diagnostic);
            }

            FixAllContext fixAllContext = new FixAllContext(
                project.Documents.First(),
                codeFixer,
                scope,
                nameof(SA1412CodeFixProvider) + "." + this.fileEncoding.WebName,
                new[] { SA1412StoreFilesAsUtf8.DiagnosticId },
                TestDiagnosticProvider.Create(diagnostics.ToImmutableArray()),
                CancellationToken.None);

            CodeAction codeAction = await fixAllProvider.GetFixAsync(fixAllContext).ConfigureAwait(false);

            var operation = codeAction.GetOperationsAsync(CancellationToken.None).ConfigureAwait(false).GetAwaiter().GetResult()[0];

            operation.Apply(workspace, CancellationToken.None);

            // project should now have the "fixed document" in it.
            // Because of limitations in roslyn the fixed document should
            // have a different DocumentId then the broken document
            project = workspace.CurrentSolution.Projects.First();

            Assert.Equal(2, project.DocumentIds.Count);

            for (int i = 0; i < project.DocumentIds.Count; i++)
            {
                DocumentId documentId = project.DocumentIds[i];
                SourceText sourceText = await project.GetDocument(documentId).GetTextAsync().ConfigureAwait(false);

                Assert.Equal(testCode[i], sourceText.ToString());

                Assert.Equal(Encoding.UTF8, sourceText.Encoding);
                Assert.NotEqual(oldProject.DocumentIds[i], project.DocumentIds[i]);
            }
        }
Example #15
0
        /// <summary>
        /// Apply the inputted <see cref="CodeAction"/> to the inputted document.
        /// Meant to be used to apply code fixes.
        /// </summary>
        /// <param name="project">The <see cref="Project"/> to apply the fix on</param>
        /// <param name="codeAction">A <see cref="CodeAction"/> that will be applied to the
        /// <paramref name="project"/>.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> that the task will observe.</param>
        /// <returns>A <see cref="Project"/> with the changes from the <see cref="CodeAction"/>.</returns>
        private static async Task <Project> ApplyFixAsync(Project project, CodeAction codeAction, CancellationToken cancellationToken)
        {
            var operations = await codeAction.GetOperationsAsync(cancellationToken).ConfigureAwait(false);

            var solution = operations.OfType <ApplyChangesOperation>().Single().ChangedSolution;

            return(solution.GetProject(project.Id));
        }
Example #16
0
        public async Task <Document> ApplyRefactoring(Document originalDocument, CodeAction codeAction)
        {
            var operations = await codeAction.GetOperationsAsync(default(CancellationToken));

            var solution = operations.OfType <ApplyChangesOperation>().Single().ChangedSolution;

            return(solution.GetDocument(originalDocument.Id));
        }
        /// <summary>
        /// Apply the inputted CodeAction to the inputted document.
        /// Meant to be used to apply codefixes.
        /// </summary>
        /// <param name="document">The Document to apply the fix on</param>
        /// <param name="codeAction">A CodeAction that will be applied to the Document.</param>
        /// <returns>A Document with the changes from the CodeAction</returns>
        private static async Task <Document> ApplyFixAsync(Document document, CodeAction codeAction)
        {
            var operations = await codeAction.GetOperationsAsync(CancellationToken.None);

            var solution = operations.OfType <ApplyChangesOperation>().Single().ChangedSolution;

            return(solution.GetDocument(document.Id));
        }
Example #18
0
        public static async Task <Document> ApplyChanges(this Document document, CodeAction codeAction, CancellationToken cancellationToken = default)
        {
            var operations = await codeAction.GetOperationsAsync(cancellationToken);

            var solution = operations.OfType <ApplyChangesOperation>().Single().ChangedSolution;

            return(solution.GetDocument(document.Id));
        }
Example #19
0
        private static async Task ApplyActions(AdhocWorkspace workspace, CodeAction action, CancellationTokenSource cts)
        {
            var operations = await action.GetOperationsAsync(cts.Token);

            foreach (var operation in operations)
            {
                operation.Apply(workspace, cts.Token);
            }
        }
        private async Task ExecuteCodeAction(CodeAction codeAction)
        {
            var operations = await codeAction.GetOperationsAsync(CancellationToken.None).ConfigureAwait(true);

            foreach (var operation in operations)
            {
                operation.Apply(_roslynHost.GetDocument(_documentId).Project.Solution.Workspace, CancellationToken.None);
            }
        }
        public static async Task <Document> ApplyCodeAction(this Document document, CodeAction codeAction)
        {
            var operations = await codeAction.GetOperationsAsync(CancellationToken.None).ConfigureAwait(false);

            return(operations
                   .OfType <ApplyChangesOperation>()
                   .Single()
                   .ChangedSolution
                   .GetDocument(document.Id));
        }
Example #22
0
 protected Task <ImmutableArray <CodeActionOperation> > GetOperationsAsync(
     IProgressTracker progressTracker,
     CancellationToken cancellationToken
     )
 {
     return(Task.Run(
                () => CodeAction.GetOperationsAsync(progressTracker, cancellationToken),
                cancellationToken
                ));
 }
Example #23
0
 public static Document ApplyCodeAction(this Document document, CodeAction codeAction)
 {
     return(codeAction
            .GetOperationsAsync(CancellationToken.None)
            .Result
            .OfType <ApplyChangesOperation>()
            .Single()
            .ChangedSolution
            .GetDocument(document.Id));
 }
Example #24
0
        public static async Task <Document> ApplyCodeActionAsync(this Document document, CodeAction codeAction)
        {
            ImmutableArray <CodeActionOperation> operations = await codeAction.GetOperationsAsync(CancellationToken.None);

            return(operations
                   .OfType <ApplyChangesOperation>()
                   .Single()
                   .ChangedSolution
                   .GetDocument(document.Id));
        }
Example #25
0
        internal static Task <ImmutableArray <CodeActionOperation> > VerifyActionAndGetOperationsAsync(
            CodeAction action, TestParameters parameters)
        {
            Assert.NotNull(action);
            if (parameters.priority != null)
            {
                Assert.Equal(parameters.priority.Value, action.Priority);
            }

            return(action.GetOperationsAsync(CancellationToken.None));
        }
        internal static Task <ImmutableArray <CodeActionOperation> > VerifyActionAndGetOperationsAsync(
            CodeAction action, TestParameters parameters)
        {
            Assert.False(action is null, "No action was offered when one was expected.");

            if (parameters.priority != null)
            {
                Assert.Equal(parameters.priority.Value, action.Priority);
            }

            return(action.GetOperationsAsync(CancellationToken.None));
        }
Example #27
0
        internal async Task <ImmutableArray <CodeActionOperation> > GetOperationsAsync(CancellationToken cancellationToken = default(CancellationToken))
        {
            Diagnostic diagnostic = this.DiagnosticsToFix.First();
            Document   document   = this.Solution.GetDocument(diagnostic.Location.SourceTree);

            var diagnosticsProvider = TesterDiagnosticProvider.Create(this.DiagnosticsToFix);

            var context = new FixAllContext(document, this.CodeFixProvider, FixAllScope.Solution, this.CodeFixEquivalenceKey, this.DiagnosticsToFix.Select(x => x.Id), diagnosticsProvider, cancellationToken);

            CodeAction action = await this.FixAllProvider.GetFixAsync(context).ConfigureAwait(false);

            return(await action.GetOperationsAsync(cancellationToken).ConfigureAwait(false));
        }
        internal async Task <ImmutableArray <CodeActionOperation> > GetOperationsAsync(CancellationToken cancellationToken)
        {
            Diagnostic       diagnostic    = this.DocumentDiagnosticsToFix.Values.SelectMany(i => i.Values).Concat(this.ProjectDiagnosticsToFix.Values).First().First();
            Document         document      = this.Solution.GetDocument(diagnostic.Location.SourceTree);
            HashSet <string> diagnosticIds = new HashSet <string>(this.DocumentDiagnosticsToFix.Values.SelectMany(i => i.Values).Concat(this.ProjectDiagnosticsToFix.Values).SelectMany(i => i.Select(j => j.Id)));

            var diagnosticsProvider = new TesterDiagnosticProvider(this.DocumentDiagnosticsToFix, this.ProjectDiagnosticsToFix);

            var context = new FixAllContext(document, this.CodeFixProvider, FixAllScope.Solution, this.CodeFixEquivalenceKey, diagnosticIds, diagnosticsProvider, cancellationToken);

            CodeAction action = await this.FixAllProvider.GetFixAsync(context).ConfigureAwait(false);

            return(await action.GetOperationsAsync(cancellationToken).ConfigureAwait(false));
        }
Example #29
0
        private async Task <IEnumerable <CodeActionOperation> > GetFixAllOperationsAsync(CodeAction codeAction, FixAllContext fixAllContext)
        {
            // We have computed the fix all occurrences code fix.
            // Now fetch the new solution with applied fix and bring up the Preview changes dialog.

            var cancellationToken = fixAllContext.CancellationToken;
            var workspace         = fixAllContext.Project.Solution.Workspace;

            cancellationToken.ThrowIfCancellationRequested();
            var operations = await codeAction.GetOperationsAsync(cancellationToken).ConfigureAwait(false);

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

            cancellationToken.ThrowIfCancellationRequested();
            var newSolution = await codeAction.GetChangedSolutionInternalAsync(cancellationToken).ConfigureAwait(false);

            cancellationToken.ThrowIfCancellationRequested();
            using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesPreviewChanges, cancellationToken))
            {
                var previewService = workspace.Services.GetService <IPreviewDialogService>();
                var glyph          = fixAllContext.Project.Language == LanguageNames.CSharp ?
                                     Glyph.CSharpProject :
                                     Glyph.BasicProject;

                var changedSolution = previewService.PreviewChanges(
                    string.Format(EditorFeaturesResources.PreviewChangesOf, EditorFeaturesResources.FixAllOccurrences),
                    "vs.codefix.fixall",
                    codeAction.Title,
                    EditorFeaturesResources.FixAllOccurrences,
                    glyph,
                    newSolution,
                    fixAllContext.Project.Solution);

                if (changedSolution == null)
                {
                    // User clicked cancel.
                    FixAllLogger.LogPreviewChangesResult(applied: false);
                    return(null);
                }

                FixAllLogger.LogPreviewChangesResult(applied: true, allChangesApplied: changedSolution == newSolution);
                newSolution = changedSolution;
            }

            // Get a code action, with apply changes operation replaced with the newSolution.
            return(GetNewFixAllOperations(operations, newSolution, cancellationToken));
        }
        /// <summary>
        /// Apply the inputted <see cref="CodeAction"/> to the inputted document.
        /// Meant to be used to apply code fixes.
        /// </summary>
        /// <param name="project">The <see cref="Project"/> to apply the code action on.</param>
        /// <param name="codeAction">A <see cref="CodeAction"/> that will be applied to the
        /// <paramref name="project"/>.</param>
        /// <param name="verifier">The verifier to use for test assertions.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> that the task will observe.</param>
        /// <returns>A <see cref="Project"/> with the changes from the <see cref="CodeAction"/>.</returns>
        protected async Task <Project> ApplyCodeActionAsync(Project project, CodeAction codeAction, IVerifier verifier, CancellationToken cancellationToken)
        {
            var operations = await codeAction.GetOperationsAsync(cancellationToken).ConfigureAwait(false);

            var solution       = operations.OfType <ApplyChangesOperation>().Single().ChangedSolution;
            var changedProject = solution.GetProject(project.Id);

            if (changedProject != project)
            {
                project = await RecreateProjectDocumentsAsync(changedProject, verifier, cancellationToken).ConfigureAwait(false);
            }

            return(project);
        }