private static void RefactoringSetup( TestWorkspace workspace, CodeRefactoringProvider provider, List <CodeAction> codeActions, out EditorLayerExtensionManager.ExtensionManager extensionManager, out VisualStudio.Text.ITextBuffer textBuffer ) { var document = GetDocument(workspace); textBuffer = workspace.GetTestDocument(document.Id).GetTextBuffer(); var span = document.GetSyntaxRootAsync().Result.Span; var context = new CodeRefactoringContext( document, span, (a) => codeActions.Add(a), CancellationToken.None ); provider.ComputeRefactoringsAsync(context).Wait(); var action = codeActions.Single(); extensionManager = document.Project.Solution.Workspace.Services.GetService <IExtensionManager>() as EditorLayerExtensionManager.ExtensionManager; }
private static async Task <CodeRefactoring> GetCodeRefactoringAsync( CodeRefactoringProvider provider, TestWorkspace workspace ) { var documentsWithSelections = workspace.Documents.Where( d => !d.IsLinkFile && d.SelectedSpans.Count == 1 ); Debug.Assert( documentsWithSelections.Count() == 1, "One document must have a single span annotation" ); var span = documentsWithSelections.Single().SelectedSpans.Single(); var actions = ArrayBuilder <(CodeAction, TextSpan?)> .GetInstance(); var document = workspace.CurrentSolution.GetDocument( documentsWithSelections.Single().Id ); var context = new CodeRefactoringContext( document, span, (a, t) => actions.Add((a, t)), isBlocking: false, CancellationToken.None ); await provider.ComputeRefactoringsAsync(context); var result = actions.Count > 0 ? new CodeRefactoring(provider, actions.ToImmutable()) : null; actions.Free(); return(result); }
public static void VerifyNoRefactoring( string source, TextSpan span, CodeRefactoringProvider refactoringProvider, string language, string equivalenceKey = null) { Document document = WorkspaceFactory.CreateDocument(source, language); DiagnosticVerifier.VerifyNoCompilerError(document); List <CodeAction> actions = null; var context = new CodeRefactoringContext( document, span, codeAction => { if (equivalenceKey == null || string.Equals(codeAction.EquivalenceKey, equivalenceKey, StringComparison.Ordinal)) { (actions ?? (actions = new List <CodeAction>())).Add(codeAction); } }, CancellationToken.None); refactoringProvider.ComputeRefactoringsAsync(context).Wait(); Assert.True(actions == null, $"Expected no code refactoring, actual: {actions?.Count ?? 0}"); }
internal static List <CodeAction> GetRefactoringActions(string language, CodeRefactoringProvider codeRefactoringProvider, string source, TextSpan span) { var document = CodeAnalysisHelper.CreateDocument(source, language); var actions = new List <CodeAction>(); var context = new CodeRefactoringContext(document, span, (a) => actions.Add(a), CancellationToken.None); codeRefactoringProvider.ComputeRefactoringsAsync(context).Wait(); return(actions); }
private IEnumerable <CodeAction> GetRefactoring(Document document, TextSpan span) { CodeRefactoringProvider provider = CreateCodeRefactoringProvider; List <CodeAction> actions = new List <CodeAction>(); CodeRefactoringContext context = new CodeRefactoringContext(document, span, (a) => actions.Add(a), CancellationToken.None); provider.ComputeRefactoringsAsync(context).Wait(); return(actions); }
private async Task<CodeRefactoring> GetCodeRefactoringAsync( CodeRefactoringProvider provider, TestWorkspace workspace) { var document = GetDocument(workspace); var span = workspace.Documents.Single(d => !d.IsLinkFile && d.SelectedSpans.Count == 1).SelectedSpans.Single(); var actions = new List<CodeAction>(); var context = new CodeRefactoringContext(document, span, (a) => actions.Add(a), CancellationToken.None); await provider.ComputeRefactoringsAsync(context); return actions.Count > 0 ? new CodeRefactoring(provider, actions) : null; }
private static ImmutableArray <CodeAction> GetCodeRefactorings(CodeRefactoringProvider provider, Document document, TextSpan span) { var builder = ImmutableArray.CreateBuilder <CodeAction>(); Action <CodeAction> registerRefactoring = a => builder.Add(a); var context = new CodeRefactoringContext(document, span, registerRefactoring, CancellationToken.None); provider.ComputeRefactoringsAsync(context).GetAwaiter().GetResult(); return(builder.ToImmutable()); }
private static CodeAction SingleAction(Document document, CodeRefactoringProvider refactoring, int position) { var context = new RefactoringContext(document, refactoring, position); var token = context.SyntaxRoot.FindToken(position); refactoring.ComputeRefactoringsAsync(context.CreateRefactoringContext(token.Span)).GetAwaiter().GetResult(); return(context.Actions.Count switch { 0 => SingleAction(context, token.Parent), 1 => context.Actions[0], _ => throw new NotSupportedException("More than one action available. Currently not supporting invoking action by index. We should add support for it."), });
public async Task InvokeAsync() { var codeActions = new List <CodeAction>(); Action <CodeAction> registerRefactoring = codeActions.Add; var context = new CodeRefactoringContext(document, span, registerRefactoring, CancellationToken.None); await provider.ComputeRefactoringsAsync(context).ConfigureAwait(false); var codeAction = codeActions.Single(); operations = await codeAction.GetOperationsAsync(CancellationToken.None).ConfigureAwait(false); }
private static IReadOnlyList <CodeAction> CodeActions(CodeRefactoringProvider refactoring, string testCode, TextSpan span, IEnumerable <MetadataReference> metadataReferences) { var sln = CodeFactory.CreateSolutionWithOneProject( testCode, CodeFactory.DefaultCompilationOptions(Array.Empty <DiagnosticAnalyzer>()), metadataReferences); var document = sln.Projects.Single().Documents.Single(); var actions = new List <CodeAction>(); var context = new CodeRefactoringContext(document, span, a => actions.Add(a), CancellationToken.None); refactoring.ComputeRefactoringsAsync(context).GetAwaiter().GetResult(); return(actions); }
private static IReadOnlyList <CodeAction> CodeActions(CodeRefactoringProvider refactoring, string testCode, int position, IEnumerable <MetadataReference> metadataReferences) { var sln = CodeFactory.CreateSolutionWithOneProject( testCode, CodeFactory.DefaultCompilationOptions(Array.Empty <DiagnosticAnalyzer>()), metadataReferences); var document = sln.Projects.Single().Documents.Single(); var context = new RefactoringContext(document, refactoring, position); var token = context.SyntaxRoot.FindToken(position); refactoring.ComputeRefactoringsAsync(context.CreateRefactoringContext(token.Span)).GetAwaiter().GetResult(); var node = token.Parent; while (node != null && node.SpanStart == position) { refactoring.ComputeRefactoringsAsync(context.CreateRefactoringContext(node.Span)).GetAwaiter().GetResult(); node = node.Parent; } return(context.Actions); }
private async Task <CodeRefactoring> GetCodeRefactoringAsync( CodeRefactoringProvider provider, TestWorkspace workspace) { var document = GetDocument(workspace); var span = workspace.Documents.Single(d => !d.IsLinkFile && d.SelectedSpans.Count == 1).SelectedSpans.Single(); var actions = ArrayBuilder <CodeAction> .GetInstance(); var context = new CodeRefactoringContext(document, span, actions.Add, CancellationToken.None); await provider.ComputeRefactoringsAsync(context); var result = actions.Count > 0 ? new CodeRefactoring(provider, actions.ToImmutable()) : null; actions.Free(); return(result); }
/// <summary> /// General verifier for refactorings. /// Creates a Document from the source string, then applies the relevant refactorings. /// Then gets the string after the refactoring is applied and compares it with the expected result. /// Note: If any refactoring causes new compiler diagnostics to show up, the test fails unless allowNewCompilerDiagnostics is set to true. /// </summary> /// <param name="language">The language the source code is in</param> /// <param name="codeRefactoringProvider">The refactoring to be applied to the code</param> /// <param name="oldSource">A class in the form of a string before the refactoring was applied to it</param> /// <param name="newSource">A class in the form of a string after the refactoring was applied to it</param> /// <param name="nodeToRefactor">A function that finds selected node for refactoring accepting the root node as an argument</param> /// <param name="codeRefactoringIndex">Index determining which refactoring to apply if there are multiple</param> /// <param name="allowNewCompilerDiagnostics">A bool controlling whether or not the test will fail if the refactoring introduces other warnings after being applied</param> private async Task VerifyRefactoringAsync(string language, CodeRefactoringProvider codeRefactoringProvider, string oldSource, string newSource, Func <SyntaxNode, SyntaxNode> nodeToRefactor, int?codeRefactoringIndex, bool allowNewCompilerDiagnostics) { var document = CreateDocument(oldSource, language); var compilerDiagnostics = (await GetCompilerDiagnosticsAsync(document).ConfigureAwait(false)).ToArray(); var actions = new List <CodeAction>(); var root = await document.GetSyntaxRootAsync().ConfigureAwait(false); var node = nodeToRefactor(root); var context = new CodeRefactoringContext(document, node.FullSpan, a => actions.Add(a), CancellationToken.None); await codeRefactoringProvider.ComputeRefactoringsAsync(context).ConfigureAwait(false); if (actions.Count > 0) { document = await ApplyCodeActionAsync(document, codeRefactoringIndex != null ?actions[(int)codeRefactoringIndex] : actions[0]).ConfigureAwait(false); var newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, await GetCompilerDiagnosticsAsync(document).ConfigureAwait(false)); //check if applying the code fix introduced any new compiler diagnostics if (!allowNewCompilerDiagnostics && newCompilerDiagnostics.Any()) { // Format and get the compiler diagnostics again so that the locations make sense in the output document = document.WithSyntaxRoot(Formatter.Format(await document.GetSyntaxRootAsync().ConfigureAwait(false), Formatter.Annotation, document.Project.Solution.Workspace)); newCompilerDiagnostics = GetNewDiagnostics(compilerDiagnostics, await GetCompilerDiagnosticsAsync(document).ConfigureAwait(false)); var newSyntaxRoot = await document.GetSyntaxRootAsync().ConfigureAwait(false); Assert.True(false, string.Format("Refactoring introduced new compiler diagnostics:\r\n{0}\r\n\r\nNew document:\r\n{1}\r\n", string.Join("\r\n", newCompilerDiagnostics.Select(d => d.ToString())), newSyntaxRoot.ToFullString())); } } //after applying all of the refactorings, compare the resulting string to the inputted one var actual = await GetStringFromDocumentAsync(document).ConfigureAwait(false); Assert.Equal(newSource, actual); }
internal static string GetRefactoringResult(string language, CodeRefactoringProvider codeRefactoringProvider, string oldSource, TextSpan span, string equivalenceKey) { var document = CodeAnalysisHelper.CreateDocument(oldSource, language); var actions = new List <CodeAction>(); var context = new CodeRefactoringContext(document, span, (a) => actions.Add(a), CancellationToken.None); codeRefactoringProvider.ComputeRefactoringsAsync(context).Wait(); if (equivalenceKey != null) { document = CodeAnalysisHelper.ApplyFix(document, actions.Single(n => n.EquivalenceKey == equivalenceKey)); } else { document = CodeAnalysisHelper.ApplyFix(document, actions[0]); } var newSource = CodeAnalysisHelper.GetStringFromDocument(document); return(newSource); }
private static Document VerifyRefactoring( Document document, TextSpan span, CodeRefactoringProvider refactoringProvider, string equivalenceKey, bool allowNewCompilerDiagnostics) { ImmutableArray <Diagnostic> compilerDiagnostics = document.GetCompilerDiagnostics(); DiagnosticVerifier.VerifyNoCompilerError(compilerDiagnostics); List <CodeAction> actions = null; var context = new CodeRefactoringContext( document, span, a => { if (equivalenceKey == null || string.Equals(a.EquivalenceKey, equivalenceKey, StringComparison.Ordinal)) { (actions ?? (actions = new List <CodeAction>())).Add(a); } }, CancellationToken.None); refactoringProvider.ComputeRefactoringsAsync(context).Wait(); Assert.True(actions != null, "No code refactoring has been registered."); document = document.ApplyCodeAction(actions[0]); if (!allowNewCompilerDiagnostics) { DiagnosticVerifier.VerifyNoNewCompilerDiagnostics(document, compilerDiagnostics); } return(document); }
/// <summary> /// General verifier for code refactorings. /// Creates a Document from the source string and applies the relevant code refactorings to the marked selection. /// Then gets the string after the code refactoring is applied and compares it with the expected result. /// </summary> /// <param name="language">The language the source code is in</param> /// <param name="codeRefactoringProvider">The code refactoring to be applied to the code</param> /// <param name="oldSource">A class in the form of a string with [| |] selection markings before the CodeRefactoring was applied to it</param> /// <param name="newSource">A class in the form of a string after the CodeRefactoring was applied to it</param> /// <param name="codeRefactoringTitle">Titel determining which CodeRefactoring to apply if there are multiple</param> private void VerifyRefactoring(string language, CodeRefactoringProvider codeRefactoringProvider, string oldSource, string newSource, string codeRefactoringTitle) { TextSpan span; if (!TryGetCodeAndSpanFromMarkup(oldSource, out oldSource, out span)) { throw new ArgumentException("There are no selection markings in the code", nameof(oldSource)); } var document = CreateDocument(oldSource, language); var actions = new List <CodeAction>(); var context = new CodeRefactoringContext(document, span, (a) => actions.Add(a), CancellationToken.None); codeRefactoringProvider.ComputeRefactoringsAsync(context).Wait(); if (actions.Any()) { if (codeRefactoringTitle != null) { CodeAction codeAction = actions.FirstOrDefault(x => x.Title == codeRefactoringTitle); if (codeAction != null) { document = ApplyCodeAction(document, codeAction); } } else { document = ApplyCodeAction(document, actions.First()); } } //after applying all of the code actions, compare the resulting string to the inputted one var actual = GetStringFromDocument(document); Assert.AreEqual(newSource, actual); }
static List <CodeAction> GetActions(CodeRefactoringProvider action, string input, out DiagnosticTestBase.TestWorkspace workspace, out Document doc, VisualBasicParseOptions parseOptions = null) { TextSpan selectedSpan; TextSpan markedSpan; string text = ParseText(input, out selectedSpan, out markedSpan); workspace = new DiagnosticTestBase.TestWorkspace(); var projectId = ProjectId.CreateNewId(); var documentId = DocumentId.CreateNewId(projectId); if (parseOptions == null) { parseOptions = new VisualBasicParseOptions( LanguageVersion.VisualBasic14, DocumentationMode.Diagnose | DocumentationMode.Parse, SourceCodeKind.Regular, ImmutableArray.Create( new KeyValuePair <string, object>("DEBUG", null), new KeyValuePair <string, object>("TEST", null)) ); } //workspace.Options.WithChangedOption(VisualBasicFormattingOptions.NewLinesForBracesInControlBlocks, false); workspace.Open(ProjectInfo.Create( projectId, VersionStamp.Create(), "TestProject", "TestProject", LanguageNames.VisualBasic, null, null, new VisualBasicCompilationOptions( OutputKind.DynamicallyLinkedLibrary, "", "", "Script", null, null, OptionStrict.Off, true, true, false, parseOptions ), parseOptions, new[] { DocumentInfo.Create( documentId, "a.cs", null, SourceCodeKind.Regular, TextLoader.From(TextAndVersion.Create(SourceText.From(text), VersionStamp.Create())) ) }, null, DiagnosticTestBase.DefaultMetadataReferences ) ); doc = workspace.CurrentSolution.GetProject(projectId).GetDocument(documentId); var actions = new List <CodeAction>(); var context = new CodeRefactoringContext(doc, selectedSpan, actions.Add, default(CancellationToken)); action.ComputeRefactoringsAsync(context).Wait(); if (markedSpan.Start > 0) { foreach (var nra in actions.OfType <NRefactoryCodeAction>()) { Assert.AreEqual(markedSpan, nra.TextSpan, "Activation span does not match."); } } return(actions); }
static List <CodeAction> GetActions(CodeRefactoringProvider action, string input, out CSharpDiagnosticTestBase.TestWorkspace workspace, out Document doc, CSharpParseOptions parseOptions = null) { TextSpan selectedSpan; TextSpan markedSpan; string text = ParseText(input, out selectedSpan, out markedSpan); workspace = new CSharpDiagnosticTestBase.TestWorkspace(); var projectId = ProjectId.CreateNewId(); var documentId = DocumentId.CreateNewId(projectId); if (parseOptions == null) { parseOptions = new CSharpParseOptions( LanguageVersion.CSharp6, DocumentationMode.Diagnose | DocumentationMode.Parse, SourceCodeKind.Regular, ImmutableArray.Create("DEBUG", "TEST") ); } workspace.Options = workspace.Options .WithChangedOption(CSharpFormattingOptions.NewLinesForBracesInControlBlocks, true) .WithChangedOption(SimplificationOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration, LanguageNames.CSharp, true) .WithChangedOption(SimplificationOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess, LanguageNames.CSharp, true); workspace.Open(ProjectInfo.Create( projectId, VersionStamp.Create(), "TestProject", "TestProject", LanguageNames.CSharp, null, null, new CSharpCompilationOptions( OutputKind.DynamicallyLinkedLibrary, false, "", "", "Script", null, OptimizationLevel.Debug, false, true ), parseOptions, new[] { DocumentInfo.Create( documentId, "a.cs", null, SourceCodeKind.Regular, TextLoader.From(TextAndVersion.Create(SourceText.From(text), VersionStamp.Create())) ) }, null, DiagnosticTestBase.DefaultMetadataReferences ) ); doc = workspace.CurrentSolution.GetProject(projectId).GetDocument(documentId); var actions = new List <CodeAction>(); var context = new CodeRefactoringContext(doc, selectedSpan, actions.Add, default(CancellationToken)); action.ComputeRefactoringsAsync(context).Wait(); if (markedSpan.Start > 0) { foreach (var nra in actions.OfType <NRefactoryCodeAction>()) { Assert.True(markedSpan == nra.TextSpan, "Activation span does not match."); } } return(actions); }
// Helpers/Refactoring private static async Task GetRefactoringActionsAsync(CodeRefactoringProvider refactorer, Document document, List <CodeAction> actions, CancellationToken cancellationToken) { var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false) ?? throw new Exception("Document is not found");; var context = new CodeRefactoringContext(document, root.FullSpan, action => actions.Add(action), cancellationToken); await refactorer.ComputeRefactoringsAsync(context).ConfigureAwait(false); }