提交 cf5702ec 编写于 作者: C CyrusNajmabadi

Merge pull request #8994 from CyrusNajmabadi/passCodeProviderStateInTests

Provide a way for 'code action' tests to pass data to their CodeFixProvider constructor.
上级 dd0e7741
......@@ -72,53 +72,59 @@ protected void ApplyOptionsToWorkspace(Workspace workspace, IDictionary<OptionKe
protected async Task TestMissingAsync(
string initialMarkup,
IDictionary<OptionKey, object> options = null,
string fixAllActionEquivalenceKey = null)
string fixAllActionEquivalenceKey = null,
object fixProviderData = null)
{
await TestMissingAsync(initialMarkup, parseOptions: null, options: options, fixAllActionEquivalenceKey: fixAllActionEquivalenceKey);
await TestMissingAsync(initialMarkup, parseOptions: GetScriptOptions(), options: options, fixAllActionEquivalenceKey: fixAllActionEquivalenceKey);
await TestMissingAsync(initialMarkup, parseOptions: null, options: options, fixAllActionEquivalenceKey: fixAllActionEquivalenceKey, fixProviderData: fixProviderData);
await TestMissingAsync(initialMarkup, parseOptions: GetScriptOptions(), options: options, fixAllActionEquivalenceKey: fixAllActionEquivalenceKey, fixProviderData: fixProviderData);
}
protected Task TestMissingAsync(
string initialMarkup,
ParseOptions parseOptions,
IDictionary<OptionKey, object> options = null,
string fixAllActionEquivalenceKey = null)
string fixAllActionEquivalenceKey = null,
object fixProviderData = null)
{
return TestMissingAsync(initialMarkup, parseOptions, compilationOptions: null, options: options, fixAllActionEquivalenceKey: fixAllActionEquivalenceKey);
return TestMissingAsync(initialMarkup, parseOptions, compilationOptions: null, options: options, fixAllActionEquivalenceKey: fixAllActionEquivalenceKey, fixProviderData: fixProviderData);
}
protected async Task TestMissingAsync(
string initialMarkup,
ParseOptions parseOptions, CompilationOptions compilationOptions,
IDictionary<OptionKey, object> options = null,
string fixAllActionEquivalenceKey = null)
string fixAllActionEquivalenceKey = null,
object fixProviderData = null)
{
using (var workspace = await CreateWorkspaceFromFileAsync(initialMarkup, parseOptions, compilationOptions))
{
ApplyOptionsToWorkspace(workspace, options);
var actions = await GetCodeActionsAsync(workspace, fixAllActionEquivalenceKey);
var actions = await GetCodeActionsAsync(workspace, fixAllActionEquivalenceKey, fixProviderData);
Assert.True(actions == null || actions.Count == 0);
}
}
protected async Task<IList<CodeAction>> GetCodeActionsAsync(TestWorkspace workspace, string fixAllActionEquivalenceKey)
protected async Task<IList<CodeAction>> GetCodeActionsAsync(
TestWorkspace workspace, string fixAllActionEquivalenceKey, object fixProviderData = null)
{
return MassageActions(await GetCodeActionsWorkerAsync(workspace, fixAllActionEquivalenceKey));
return MassageActions(await GetCodeActionsWorkerAsync(workspace, fixAllActionEquivalenceKey, fixProviderData));
}
protected abstract Task<IList<CodeAction>> GetCodeActionsWorkerAsync(TestWorkspace workspace, string fixAllActionEquivalenceKey);
protected abstract Task<IList<CodeAction>> GetCodeActionsWorkerAsync(
TestWorkspace workspace, string fixAllActionEquivalenceKey, object fixProviderData = null);
protected async Task TestSmartTagTextAsync(
string initialMarkup,
string displayText,
int index = 0,
ParseOptions parseOptions = null,
CompilationOptions compilationOptions = null)
CompilationOptions compilationOptions = null,
object fixProviderData = null)
{
using (var workspace = await CreateWorkspaceFromFileAsync(initialMarkup, parseOptions, compilationOptions))
{
var actions = await GetCodeActionsAsync(workspace, fixAllActionEquivalenceKey: null);
var actions = await GetCodeActionsAsync(workspace, fixAllActionEquivalenceKey: null, fixProviderData: fixProviderData);
Assert.Equal(displayText, actions.ElementAt(index).Title);
}
}
......@@ -157,10 +163,11 @@ protected async Task<IList<CodeAction>> GetCodeActionsAsync(TestWorkspace worksp
string initialMarkup, string expectedMarkup,
int index = 0, bool compareTokens = true,
IDictionary<OptionKey, object> options = null,
string fixAllActionEquivalenceKey = null)
string fixAllActionEquivalenceKey = null,
object fixProviderData = null)
{
await TestAsync(initialMarkup, expectedMarkup, null, index, compareTokens, options, fixAllActionEquivalenceKey);
await TestAsync(initialMarkup, expectedMarkup, GetScriptOptions(), index, compareTokens, options, fixAllActionEquivalenceKey);
await TestAsync(initialMarkup, expectedMarkup, null, index, compareTokens, options, fixAllActionEquivalenceKey, fixProviderData);
await TestAsync(initialMarkup, expectedMarkup, GetScriptOptions(), index, compareTokens, options, fixAllActionEquivalenceKey, fixProviderData);
}
protected Task TestAsync(
......@@ -168,9 +175,10 @@ protected async Task<IList<CodeAction>> GetCodeActionsAsync(TestWorkspace worksp
ParseOptions parseOptions,
int index = 0, bool compareTokens = true,
IDictionary<OptionKey, object> options = null,
string fixAllActionEquivalenceKey = null)
string fixAllActionEquivalenceKey = null,
object fixProviderData = null)
{
return TestAsync(initialMarkup, expectedMarkup, parseOptions, null, index, compareTokens, options, fixAllActionEquivalenceKey);
return TestAsync(initialMarkup, expectedMarkup, parseOptions, null, index, compareTokens, options, fixAllActionEquivalenceKey, fixProviderData);
}
protected async Task TestAsync(
......@@ -178,7 +186,8 @@ protected async Task<IList<CodeAction>> GetCodeActionsAsync(TestWorkspace worksp
ParseOptions parseOptions, CompilationOptions compilationOptions,
int index = 0, bool compareTokens = true,
IDictionary<OptionKey, object> options = null,
string fixAllActionEquivalenceKey = null)
string fixAllActionEquivalenceKey = null,
object fixProviderData = null)
{
string expected;
IDictionary<string, IList<TextSpan>> spanMap;
......@@ -194,7 +203,7 @@ protected async Task<IList<CodeAction>> GetCodeActionsAsync(TestWorkspace worksp
{
ApplyOptionsToWorkspace(workspace, options);
var actions = await GetCodeActionsAsync(workspace, fixAllActionEquivalenceKey);
var actions = await GetCodeActionsAsync(workspace, fixAllActionEquivalenceKey, fixProviderData);
await TestActionsAsync(
workspace, expected, index,
actions,
......@@ -323,11 +332,27 @@ protected static async Task<IEnumerable<CodeActionOperation>> VerifyInputsAndGet
TestWorkspace workspace,
IEnumerable<CodeActionOperation> operations)
{
var applyChangesOperation = operations.OfType<ApplyChangesOperation>().First();
var oldSolution = workspace.CurrentSolution;
var newSolution = applyChangesOperation.ChangedSolution;
Tuple<Solution, Solution> result = null;
foreach (var operation in operations)
{
if (operation is ApplyChangesOperation && result == null)
{
var oldSolution = workspace.CurrentSolution;
var newSolution = ((ApplyChangesOperation)operation).ChangedSolution;
result = Tuple.Create(oldSolution, newSolution);
}
else if (operation.ApplyDuringTests)
{
operation.Apply(workspace, CancellationToken.None);
}
}
return Tuple.Create(oldSolution, newSolution);
if (result == null)
{
throw new InvalidOperationException("No ApplyChangesOperation found");
}
return result;
}
protected virtual IList<CodeAction> MassageActions(IList<CodeAction> actions)
......
......@@ -25,7 +25,8 @@ public abstract class AbstractCodeActionTest : AbstractCodeActionOrUserDiagnosti
{
protected abstract object CreateCodeRefactoringProvider(Workspace workspace);
protected override async Task<IList<CodeAction>> GetCodeActionsWorkerAsync(TestWorkspace workspace, string fixAllActionEquivalenceKey)
protected override async Task<IList<CodeAction>> GetCodeActionsWorkerAsync(
TestWorkspace workspace, string fixAllActionEquivalenceKey, object fixProviderData)
{
return (await GetCodeRefactoringAsync(workspace))?.Actions?.ToList();
}
......
......@@ -25,14 +25,24 @@ public abstract class AbstractDiagnosticProviderBasedUserDiagnosticTest : Abstra
internal abstract Tuple<DiagnosticAnalyzer, CodeFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace);
private Tuple<DiagnosticAnalyzer, CodeFixProvider> GetOrCreateDiagnosticProviderAndFixer(Workspace workspace)
internal virtual Tuple<DiagnosticAnalyzer, CodeFixProvider> CreateDiagnosticProviderAndFixer(
Workspace workspace, object fixProviderData)
{
return _analyzerAndFixerMap.GetOrAdd(workspace, CreateDiagnosticProviderAndFixer);
return CreateDiagnosticProviderAndFixer(workspace);
}
internal async override Task<IEnumerable<Diagnostic>> GetDiagnosticsAsync(TestWorkspace workspace)
private Tuple<DiagnosticAnalyzer, CodeFixProvider> GetOrCreateDiagnosticProviderAndFixer(
Workspace workspace, object fixProviderData)
{
var providerAndFixer = GetOrCreateDiagnosticProviderAndFixer(workspace);
return fixProviderData == null
? _analyzerAndFixerMap.GetOrAdd(workspace, CreateDiagnosticProviderAndFixer)
: CreateDiagnosticProviderAndFixer(workspace, fixProviderData);
}
internal async override Task<IEnumerable<Diagnostic>> GetDiagnosticsAsync(
TestWorkspace workspace, object fixProviderData = null)
{
var providerAndFixer = GetOrCreateDiagnosticProviderAndFixer(workspace, fixProviderData);
var provider = providerAndFixer.Item1;
TextSpan span;
......@@ -42,9 +52,10 @@ internal async override Task<IEnumerable<Diagnostic>> GetDiagnosticsAsync(TestWo
return allDiagnostics;
}
internal override async Task<IEnumerable<Tuple<Diagnostic, CodeFixCollection>>> GetDiagnosticAndFixesAsync(TestWorkspace workspace, string fixAllActionId)
internal override async Task<IEnumerable<Tuple<Diagnostic, CodeFixCollection>>> GetDiagnosticAndFixesAsync(
TestWorkspace workspace, string fixAllActionId, object fixProviderData)
{
var providerAndFixer = GetOrCreateDiagnosticProviderAndFixer(workspace);
var providerAndFixer = GetOrCreateDiagnosticProviderAndFixer(workspace, fixProviderData);
var provider = providerAndFixer.Item1;
Document document;
......
......@@ -53,7 +53,8 @@ private ImmutableArray<Diagnostic> FilterDiagnostics(IEnumerable<Diagnostic> dia
return diagnostics.ToImmutableArray();
}
internal override async Task<IEnumerable<Diagnostic>> GetDiagnosticsAsync(TestWorkspace workspace)
internal override async Task<IEnumerable<Diagnostic>> GetDiagnosticsAsync(
TestWorkspace workspace, object fixProviderData)
{
var providerAndFixer = CreateDiagnosticProviderAndFixer(workspace);
......@@ -64,7 +65,8 @@ internal override async Task<IEnumerable<Diagnostic>> GetDiagnosticsAsync(TestWo
return FilterDiagnostics(diagnostics);
}
internal override async Task<IEnumerable<Tuple<Diagnostic, CodeFixCollection>>> GetDiagnosticAndFixesAsync(TestWorkspace workspace, string fixAllActionId)
internal override async Task<IEnumerable<Tuple<Diagnostic, CodeFixCollection>>> GetDiagnosticAndFixesAsync(
TestWorkspace workspace, string fixAllActionId, object fixProviderData)
{
var providerAndFixer = CreateDiagnosticProviderAndFixer(workspace);
......
......@@ -27,18 +27,21 @@ namespace Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics
{
public abstract class AbstractUserDiagnosticTest : AbstractCodeActionOrUserDiagnosticTest
{
internal abstract Task<IEnumerable<Tuple<Diagnostic, CodeFixCollection>>> GetDiagnosticAndFixesAsync(TestWorkspace workspace, string fixAllActionEquivalenceKey);
internal abstract Task<IEnumerable<Diagnostic>> GetDiagnosticsAsync(TestWorkspace workspace);
internal abstract Task<IEnumerable<Tuple<Diagnostic, CodeFixCollection>>> GetDiagnosticAndFixesAsync(
TestWorkspace workspace, string fixAllActionEquivalenceKey, object fixProviderData);
internal abstract Task<IEnumerable<Diagnostic>> GetDiagnosticsAsync(TestWorkspace workspace, object fixProviderData);
protected override async Task<IList<CodeAction>> GetCodeActionsWorkerAsync(TestWorkspace workspace, string fixAllActionEquivalenceKey)
protected override async Task<IList<CodeAction>> GetCodeActionsWorkerAsync(
TestWorkspace workspace, string fixAllActionEquivalenceKey, object fixProviderData)
{
var diagnostics = await GetDiagnosticAndFixAsync(workspace, fixAllActionEquivalenceKey);
var diagnostics = await GetDiagnosticAndFixAsync(workspace, fixAllActionEquivalenceKey, fixProviderData);
return diagnostics?.Item2?.Fixes.Select(f => f.Action).ToList();
}
internal async Task<Tuple<Diagnostic, CodeFixCollection>> GetDiagnosticAndFixAsync(TestWorkspace workspace, string fixAllActionEquivalenceKey = null)
internal async Task<Tuple<Diagnostic, CodeFixCollection>> GetDiagnosticAndFixAsync(
TestWorkspace workspace, string fixAllActionEquivalenceKey = null, object fixProviderData = null)
{
return (await GetDiagnosticAndFixesAsync(workspace, fixAllActionEquivalenceKey)).FirstOrDefault();
return (await GetDiagnosticAndFixesAsync(workspace, fixAllActionEquivalenceKey, fixProviderData)).FirstOrDefault();
}
protected Document GetDocumentAndSelectSpan(TestWorkspace workspace, out TextSpan span)
......@@ -224,11 +227,13 @@ protected async Task TestEquivalenceKeyAsync(string initialMarkup, string equiva
protected async Task TestActionCountInAllFixesAsync(
string initialMarkup,
int count,
ParseOptions parseOptions = null, CompilationOptions compilationOptions = null)
ParseOptions parseOptions = null,
CompilationOptions compilationOptions = null,
object fixProviderData = null)
{
using (var workspace = await CreateWorkspaceFromFileAsync(initialMarkup, parseOptions, compilationOptions))
{
var diagnosticAndFix = await GetDiagnosticAndFixesAsync(workspace, null);
var diagnosticAndFix = await GetDiagnosticAndFixesAsync(workspace, fixAllActionEquivalenceKey: null, fixProviderData: fixProviderData);
var diagnosticCount = diagnosticAndFix.Select(x => x.Item2.Fixes.Count()).Sum();
Assert.Equal(count, diagnosticCount);
......@@ -238,8 +243,11 @@ protected async Task TestEquivalenceKeyAsync(string initialMarkup, string equiva
protected async Task TestSpansAsync(
string initialMarkup, string expectedMarkup,
int index = 0,
ParseOptions parseOptions = null, CompilationOptions compilationOptions = null,
string diagnosticId = null, string fixAllActionEquivalenceId = null)
ParseOptions parseOptions = null,
CompilationOptions compilationOptions = null,
string diagnosticId = null,
string fixAllActionEquivalenceId = null,
object fixProviderData = null)
{
IList<TextSpan> spansList;
string unused;
......@@ -251,13 +259,13 @@ protected async Task TestEquivalenceKeyAsync(string initialMarkup, string equiva
ISet<TextSpan> actualTextSpans;
if (diagnosticId == null)
{
var diagnosticsAndFixes = await GetDiagnosticAndFixesAsync(workspace, fixAllActionEquivalenceId);
var diagnosticsAndFixes = await GetDiagnosticAndFixesAsync(workspace, fixAllActionEquivalenceId, fixProviderData);
var diagnostics = diagnosticsAndFixes.Select(t => t.Item1);
actualTextSpans = diagnostics.Select(d => d.Location.SourceSpan).ToSet();
}
else
{
var diagnostics = await GetDiagnosticsAsync(workspace);
var diagnostics = await GetDiagnosticsAsync(workspace, fixProviderData);
actualTextSpans = diagnostics.Where(d => d.Id == diagnosticId).Select(d => d.Location.SourceSpan).ToSet();
}
......@@ -437,7 +445,7 @@ protected async Task TestEquivalenceKeyAsync(string initialMarkup, string equiva
testState.TestProjectManagementService.SetDefaultNamespace(
defaultNamespace: defaultNamespace);
var diagnosticsAndFixes = await GetDiagnosticAndFixesAsync(testState.Workspace, null);
var diagnosticsAndFixes = await GetDiagnosticAndFixesAsync(testState.Workspace, fixAllActionEquivalenceKey: null, fixProviderData: null);
var generateTypeDiagFixes = diagnosticsAndFixes.SingleOrDefault(df => GenerateTypeTestState.FixIds.Contains(df.Item1.Id));
if (isMissing)
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Threading;
using System.Threading.Tasks;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeActions
{
......@@ -24,5 +26,12 @@ public virtual string Title
public virtual void Apply(Workspace workspace, CancellationToken cancellationToken)
{
}
/// <summary>
/// Operations may make all sorts of changes that may not be appropriate during testing
/// (like popping up UI). So, by default, we don't apply them unless the operation asks
/// for that to happen.
/// </summary>
internal virtual bool ApplyDuringTests => false;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册