提交 62ea5142 编写于 作者: R Ravi Chande

Implement ISuggestedActionsSource2

上级 b8afd807
......@@ -75,7 +75,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0"/>
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0"/>
</dependentAssembly>
<!-- Even though all of our references are to Dev15 binaries we are still pulling in BasicUndo
......
......@@ -83,7 +83,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0"/>
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0"/>
</dependentAssembly>
<!-- Even though all of our references are to Dev15 binaries we are still pulling in BasicUndo
......
......@@ -75,7 +75,7 @@
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0"/>
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.VisualStudio.Validation" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
......
......@@ -41,7 +41,7 @@
<MicrosoftDiaSymReaderPortablePdbVersion>1.3.0</MicrosoftDiaSymReaderPortablePdbVersion>
<MicrosoftDotNetIBCMerge>4.7.2-alpha-00001</MicrosoftDotNetIBCMerge>
<MicrosoftIdentityModelClientsActiveDirectoryVersion>3.13.8</MicrosoftIdentityModelClientsActiveDirectoryVersion>
<MicrosoftInternalPerformanceCodeMarkersDesignTimeVersion>15.0.26507-alpha</MicrosoftInternalPerformanceCodeMarkersDesignTimeVersion>
<MicrosoftInternalPerformanceCodeMarkersDesignTimeVersion>15.0.26606-alpha</MicrosoftInternalPerformanceCodeMarkersDesignTimeVersion>
<MicrosoftInternalVisualStudioShellInterop140DesignTimeVersion>14.3.25407-alpha</MicrosoftInternalVisualStudioShellInterop140DesignTimeVersion>
<MicrosoftMetadataVisualizerVersion>1.0.0-beta1-61531-03</MicrosoftMetadataVisualizerVersion>
<MicrosoftMSXMLVersion>8.0.0.0-alpha</MicrosoftMSXMLVersion>
......@@ -60,35 +60,35 @@
<MicrosoftNetSdkVersion>2.0.0-alpha-20170405-2</MicrosoftNetSdkVersion>
<MicrosoftNuGetBuildTasksVersion>0.1.0</MicrosoftNuGetBuildTasksVersion>
<MicrosoftPortableTargetsVersion>0.1.2-dev</MicrosoftPortableTargetsVersion>
<MicrosoftServiceHubClientVersion>1.1.18-rc-g92b2150dd1</MicrosoftServiceHubClientVersion>
<MicrosoftServiceHubClientVersion>1.1.31-rc</MicrosoftServiceHubClientVersion>
<MicrosoftTplDataflowVersion>4.5.24</MicrosoftTplDataflowVersion>
<MicrosoftVisualBasicVersion>10.1.0</MicrosoftVisualBasicVersion>
<MicrosoftVisualStudioCallHierarchyPackageDefinitionsVersion>15.0.26507-alpha</MicrosoftVisualStudioCallHierarchyPackageDefinitionsVersion>
<MicrosoftVisualStudioCodeAnalysisSdkUIVersion>15.0.26507-alpha</MicrosoftVisualStudioCodeAnalysisSdkUIVersion>
<MicrosoftVisualStudioComponentModelHostVersion>15.0.26507-alpha</MicrosoftVisualStudioComponentModelHostVersion>
<MicrosoftVisualStudioCallHierarchyPackageDefinitionsVersion>15.0.26606-alpha</MicrosoftVisualStudioCallHierarchyPackageDefinitionsVersion>
<MicrosoftVisualStudioCodeAnalysisSdkUIVersion>15.0.26606-alpha</MicrosoftVisualStudioCodeAnalysisSdkUIVersion>
<MicrosoftVisualStudioComponentModelHostVersion>15.0.26606-alpha</MicrosoftVisualStudioComponentModelHostVersion>
<MicrosoftVisualStudioCompositionVersion>15.0.66-rc</MicrosoftVisualStudioCompositionVersion>
<MicrosoftVisualStudioCoreUtilityVersion>15.0.26507-alpha</MicrosoftVisualStudioCoreUtilityVersion>
<MicrosoftVisualStudioCoreUtilityVersion>15.0.26606-alpha</MicrosoftVisualStudioCoreUtilityVersion>
<MicrosoftVisualStudioDebuggerEngineVersion>15.0.26201-gamma</MicrosoftVisualStudioDebuggerEngineVersion>
<MicrosoftVisualStudioDebuggerMetadataVersion>15.0.26201-gamma</MicrosoftVisualStudioDebuggerMetadataVersion>
<MicrosoftVisualStudioDebuggerInterop100Version>10.0.30319</MicrosoftVisualStudioDebuggerInterop100Version>
<MicrosoftVisualStudioDesignerInterfacesVersion>1.1.4322</MicrosoftVisualStudioDesignerInterfacesVersion>
<MicrosoftVisualStudioDiagnosticsPerformanceProviderVersion>15.0.26507-alpha</MicrosoftVisualStudioDiagnosticsPerformanceProviderVersion>
<MicrosoftVisualStudioEditorVersion>15.0.26507-alpha</MicrosoftVisualStudioEditorVersion>
<MicrosoftVisualStudioGraphModelVersion>15.0.26507-alpha</MicrosoftVisualStudioGraphModelVersion>
<MicrosoftVisualStudioImageCatalogVersion>15.0.26507-alpha</MicrosoftVisualStudioImageCatalogVersion>
<MicrosoftVisualStudioImagingVersion>15.0.26507-alpha</MicrosoftVisualStudioImagingVersion>
<MicrosoftVisualStudioDiagnosticsPerformanceProviderVersion>15.0.26606-alpha</MicrosoftVisualStudioDiagnosticsPerformanceProviderVersion>
<MicrosoftVisualStudioEditorVersion>15.0.26606-alpha</MicrosoftVisualStudioEditorVersion>
<MicrosoftVisualStudioGraphModelVersion>15.0.26606-alpha</MicrosoftVisualStudioGraphModelVersion>
<MicrosoftVisualStudioImageCatalogVersion>15.0.26606-alpha</MicrosoftVisualStudioImageCatalogVersion>
<MicrosoftVisualStudioImagingVersion>15.0.26606-alpha</MicrosoftVisualStudioImagingVersion>
<MicrosoftVisualStudioImagingInterop140DesignTimeVersion>14.3.25407</MicrosoftVisualStudioImagingInterop140DesignTimeVersion>
<MicrosoftVisualStudioInteractiveWindowVersion>2.0.0-rc3-61304-01</MicrosoftVisualStudioInteractiveWindowVersion>
<MicrosoftVisualStudioLanguageCallHierarchyVersion>15.0.26507-alpha</MicrosoftVisualStudioLanguageCallHierarchyVersion>
<MicrosoftVisualStudioLanguageIntellisenseVersion>15.0.26507-alpha</MicrosoftVisualStudioLanguageIntellisenseVersion>
<MicrosoftVisualStudioLanguageNavigateToInterfacesVersion>15.0.26507-alpha</MicrosoftVisualStudioLanguageNavigateToInterfacesVersion>
<MicrosoftVisualStudioLanguageStandardClassificationVersion>15.0.26507-alpha</MicrosoftVisualStudioLanguageStandardClassificationVersion>
<MicrosoftVisualStudioLanguageCallHierarchyVersion>15.0.26606-alpha</MicrosoftVisualStudioLanguageCallHierarchyVersion>
<MicrosoftVisualStudioLanguageIntellisenseVersion>15.0.26606-alpha</MicrosoftVisualStudioLanguageIntellisenseVersion>
<MicrosoftVisualStudioLanguageNavigateToInterfacesVersion>15.0.26606-alpha</MicrosoftVisualStudioLanguageNavigateToInterfacesVersion>
<MicrosoftVisualStudioLanguageStandardClassificationVersion>15.0.26606-alpha</MicrosoftVisualStudioLanguageStandardClassificationVersion>
<MicrosoftVisualStudioOLEInteropVersion>7.10.6070</MicrosoftVisualStudioOLEInteropVersion>
<MicrosoftVisualStudioPlatformVSEditorVersion>15.0.26507-alpha</MicrosoftVisualStudioPlatformVSEditorVersion>
<MicrosoftVisualStudioPlatformVSEditorInteropVersion>15.0.26507-alpha</MicrosoftVisualStudioPlatformVSEditorInteropVersion>
<MicrosoftVisualStudioProgressionCodeSchemaVersion>15.0.26507-alpha</MicrosoftVisualStudioProgressionCodeSchemaVersion>
<MicrosoftVisualStudioProgressionCommonVersion>15.0.26507-alpha</MicrosoftVisualStudioProgressionCommonVersion>
<MicrosoftVisualStudioProgressionInterfacesVersion>15.0.26507-alpha</MicrosoftVisualStudioProgressionInterfacesVersion>
<MicrosoftVisualStudioPlatformVSEditorVersion>15.0.26606-alpha</MicrosoftVisualStudioPlatformVSEditorVersion>
<MicrosoftVisualStudioPlatformVSEditorInteropVersion>15.0.26606-alpha</MicrosoftVisualStudioPlatformVSEditorInteropVersion>
<MicrosoftVisualStudioProgressionCodeSchemaVersion>15.0.26606-alpha</MicrosoftVisualStudioProgressionCodeSchemaVersion>
<MicrosoftVisualStudioProgressionCommonVersion>15.0.26606-alpha</MicrosoftVisualStudioProgressionCommonVersion>
<MicrosoftVisualStudioProgressionInterfacesVersion>15.0.26606-alpha</MicrosoftVisualStudioProgressionInterfacesVersion>
<MicrosoftVisualStudioProjectSystemVersion>15.3.178-pre-g209fb07c2e</MicrosoftVisualStudioProjectSystemVersion>
<MicrosoftVisualStudioQualityToolsUnitTestFrameworkVersion>10.0.0.0-alpha</MicrosoftVisualStudioQualityToolsUnitTestFrameworkVersion>
<MicrosoftVisualStudioRemoteControlVersion>14.0.249-master2E2DC10C</MicrosoftVisualStudioRemoteControlVersion>
......@@ -96,32 +96,33 @@
<MicrosoftVisualStudioSetupConfigurationNativex86Version>1.3.269-rc</MicrosoftVisualStudioSetupConfigurationNativex86Version>
<MicrosoftVisualStudioSettings140Version>14.3.25407</MicrosoftVisualStudioSettings140Version>
<MicrosoftVisualStudioShell140Version>14.3.25407</MicrosoftVisualStudioShell140Version>
<MicrosoftVisualStudioShell150Version>15.0.26507-alpha</MicrosoftVisualStudioShell150Version>
<MicrosoftVisualStudioShellDesignVersion>15.0.26507-alpha</MicrosoftVisualStudioShellDesignVersion>
<MicrosoftVisualStudioShellFrameworkVersion>15.0.26507-alpha</MicrosoftVisualStudioShellFrameworkVersion>
<MicrosoftVisualStudioShellImmutable100Version>15.0.26507-alpha</MicrosoftVisualStudioShellImmutable100Version>
<MicrosoftVisualStudioShell150Version>15.0.26606-alpha</MicrosoftVisualStudioShell150Version>
<MicrosoftVisualStudioShellDesignVersion>15.0.26606-alpha</MicrosoftVisualStudioShellDesignVersion>
<MicrosoftVisualStudioShellInterop153DesignTimeVersion>15.0.26606-alpha</MicrosoftVisualStudioShellInterop153DesignTimeVersion>
<MicrosoftVisualStudioShellFrameworkVersion>15.0.26606-alpha</MicrosoftVisualStudioShellFrameworkVersion>
<MicrosoftVisualStudioShellImmutable100Version>15.0.26606-alpha</MicrosoftVisualStudioShellImmutable100Version>
<MicrosoftVisualStudioShellImmutable110Version>15.0.25413-Preview5</MicrosoftVisualStudioShellImmutable110Version>
<MicrosoftVisualStudioShellInteropVersion>7.10.6071</MicrosoftVisualStudioShellInteropVersion>
<MicrosoftVisualStudioShellInterop100Version>10.0.30319</MicrosoftVisualStudioShellInterop100Version>
<MicrosoftVisualStudioShellInterop110Version>11.0.61030</MicrosoftVisualStudioShellInterop110Version>
<MicrosoftVisualStudioShellInterop121DesignTimeVersion>12.1.30328</MicrosoftVisualStudioShellInterop121DesignTimeVersion>
<MicrosoftVisualStudioShellInterop140DesignTimeVersion>14.3.25407</MicrosoftVisualStudioShellInterop140DesignTimeVersion>
<MicrosoftVisualStudioShellInterop150DesignTimeVersion>15.0.26507-alpha</MicrosoftVisualStudioShellInterop150DesignTimeVersion>
<MicrosoftVisualStudioShellInterop150DesignTimeVersion>15.0.26606-alpha</MicrosoftVisualStudioShellInterop150DesignTimeVersion>
<MicrosoftVisualStudioShellInterop80Version>8.0.50727</MicrosoftVisualStudioShellInterop80Version>
<MicrosoftVisualStudioShellInterop90Version>9.0.30729</MicrosoftVisualStudioShellInterop90Version>
<MicrosoftVisualStudioTelemetryVersion>15.0.26507-alpha</MicrosoftVisualStudioTelemetryVersion>
<MicrosoftVisualStudioTelemetryVersion>15.0.26606-alpha</MicrosoftVisualStudioTelemetryVersion>
<MicrosoftVisualStudioTemplateWizardInterfaceVersion>8.0.0.0-alpha</MicrosoftVisualStudioTemplateWizardInterfaceVersion>
<MicrosoftVisualStudioTextDataVersion>15.0.26507-alpha</MicrosoftVisualStudioTextDataVersion>
<MicrosoftVisualStudioTextInternalVersion>15.0.26507-alpha</MicrosoftVisualStudioTextInternalVersion>
<MicrosoftVisualStudioTextLogicVersion>15.0.26507-alpha</MicrosoftVisualStudioTextLogicVersion>
<MicrosoftVisualStudioTextUIVersion>15.0.26507-alpha</MicrosoftVisualStudioTextUIVersion>
<MicrosoftVisualStudioTextUIWpfVersion>15.0.26507-alpha</MicrosoftVisualStudioTextUIWpfVersion>
<MicrosoftVisualStudioTextDataVersion>15.0.26606-alpha</MicrosoftVisualStudioTextDataVersion>
<MicrosoftVisualStudioTextInternalVersion>15.0.26606-alpha</MicrosoftVisualStudioTextInternalVersion>
<MicrosoftVisualStudioTextLogicVersion>15.0.26606-alpha</MicrosoftVisualStudioTextLogicVersion>
<MicrosoftVisualStudioTextUIVersion>15.0.26606-alpha</MicrosoftVisualStudioTextUIVersion>
<MicrosoftVisualStudioTextUIWpfVersion>15.0.26606-alpha</MicrosoftVisualStudioTextUIWpfVersion>
<MicrosoftVisualStudioTextManagerInteropVersion>7.10.6070</MicrosoftVisualStudioTextManagerInteropVersion>
<MicrosoftVisualStudioTextManagerInterop100Version>10.0.30319</MicrosoftVisualStudioTextManagerInterop100Version>
<MicrosoftVisualStudioTextManagerInterop120Version>12.0.30110</MicrosoftVisualStudioTextManagerInterop120Version>
<MicrosoftVisualStudioTextManagerInterop121DesignTimeVersion>12.1.30328</MicrosoftVisualStudioTextManagerInterop121DesignTimeVersion>
<MicrosoftVisualStudioThreadingVersion>15.3.20</MicrosoftVisualStudioThreadingVersion>
<MicrosoftVisualStudioUtilitiesVersion>15.0.26507-alpha</MicrosoftVisualStudioUtilitiesVersion>
<MicrosoftVisualStudioUtilitiesVersion>15.0.26606-alpha</MicrosoftVisualStudioUtilitiesVersion>
<MicrosoftVisualStudioValidationVersion>15.3.15</MicrosoftVisualStudioValidationVersion>
<MicrosoftVisualStudioVsInteractiveWindowVersion>2.0.0-rc3-61304-01</MicrosoftVisualStudioVsInteractiveWindowVersion>
<MicrosoftWin32PrimitivesVersion>4.3.0</MicrosoftWin32PrimitivesVersion>
......@@ -130,7 +131,7 @@
<MoqVersion>4.2.1402.2112</MoqVersion>
<NerdbankFullDuplexStreamVersion>1.0.1</NerdbankFullDuplexStreamVersion>
<NETStandardLibraryVersion>1.6.1</NETStandardLibraryVersion>
<NewtonsoftJsonVersion>8.0.3</NewtonsoftJsonVersion>
<NewtonsoftJsonVersion>9.0.1</NewtonsoftJsonVersion>
<NuGetCommandLineVersion>2.8.5</NuGetCommandLineVersion>
<NuGetCommandLineXPlatVersion>3.5.0-beta2-1484</NuGetCommandLineXPlatVersion>
<NuGetVisualStudioVersion>4.0.0-rc-2048</NuGetVisualStudioVersion>
......@@ -145,7 +146,7 @@
<RoslynToolsMicrosoftVSIXExpInstallerVersion>0.4.0-beta</RoslynToolsMicrosoftVSIXExpInstallerVersion>
<RoslynToolsReferenceAssembliesVersion>0.1.1</RoslynToolsReferenceAssembliesVersion>
<RoslynMicrosoftVisualStudioExtensionManagerVersion>0.0.4</RoslynMicrosoftVisualStudioExtensionManagerVersion>
<StreamJsonRpcVersion>1.0.2-rc</StreamJsonRpcVersion>
<StreamJsonRpcVersion>1.1.73</StreamJsonRpcVersion>
<SystemAppContextVersion>4.3.0</SystemAppContextVersion>
<SystemCollectionsVersion>4.3.0</SystemCollectionsVersion>
<SystemCollectionsConcurrentVersion>4.3.0</SystemCollectionsConcurrentVersion>
......@@ -228,4 +229,4 @@
<xunitrunnervisualstudioVersion>2.2.0-beta4-build1194</xunitrunnervisualstudioVersion>
</PropertyGroup>
</Project>
</Project>
\ No newline at end of file
......@@ -170,7 +170,10 @@
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Utilities">
<Version>$(MicrosoftVisualStudioUtilitiesVersion)</Version>
</PackageReference>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Shell.Interop.15.3.DesignTime">
<Version>$(MicrosoftVisualStudioShellInterop153DesignTimeVersion)</Version>
</PackageReference>
</ItemGroup>
<Import Project="..\..\..\build\Targets\Imports.targets" />
</Project>
......@@ -73,7 +73,7 @@ internal partial class CodeFixService : ForegroundThreadAffinitizedObject, ICode
_fixAllProviderMap = ImmutableDictionary<object, FixAllProviderInfo>.Empty;
}
public async Task<FirstDiagnosticResult> GetFirstDiagnosticWithFixAsync(
public async Task<FirstDiagnosticResult> GetMostSevereFixableDiagnostic(
Document document, TextSpan range, CancellationToken cancellationToken)
{
if (document == null || !document.IsOpen())
......@@ -83,32 +83,61 @@ internal partial class CodeFixService : ForegroundThreadAffinitizedObject, ICode
using (var diagnostics = SharedPools.Default<List<DiagnosticData>>().GetPooledObject())
{
var fullResult = await _diagnosticService.TryAppendDiagnosticsForSpanAsync(document, range, diagnostics.Object, cancellationToken: cancellationToken).ConfigureAwait(false);
foreach (var diagnostic in diagnostics.Object)
using (var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
{
cancellationToken.ThrowIfCancellationRequested();
if (!range.IntersectsWith(diagnostic.TextSpan))
{
continue;
}
var linkedToken = linkedTokenSource.Token;
// This flag is used by SuggestedActionsSource to track what solution is was
// last able to get "full results" for.
var isFullResult = await _diagnosticService.TryAppendDiagnosticsForSpanAsync(
document, range, diagnostics.Object, cancellationToken: linkedToken).ConfigureAwait(false);
var errorDiagnostics = diagnostics.Object.Where(d => d.Severity == DiagnosticSeverity.Error);
var otherDiagnostics = diagnostics.Object.Where(d => d.Severity != DiagnosticSeverity.Error);
// Kick off a task that will determine there's an Error Diagnostic with a fixer
var errorDiagnosticsTask = Task.Run(
() => GetFirstDiagnosticWithFixAsync(document, errorDiagnostics, range, linkedToken),
linkedToken);
// Kick off a task that will determine if any non-Error Diagnostic has a fixer
var otherDiagnosticsTask = Task.Run(
() => GetFirstDiagnosticWithFixAsync(document, otherDiagnostics, range, linkedToken),
linkedToken);
// If the error diagnostics task happens to complete with a non-null result before
// the other diagnostics task, we can cancel the other task.
var diagnostic = await errorDiagnosticsTask.ConfigureAwait(false)
?? await otherDiagnosticsTask.ConfigureAwait(false);
linkedTokenSource.Cancel();
return new FirstDiagnosticResult(partialResult: !isFullResult,
hasFix: diagnostic != null,
diagnostic: diagnostic);
}
}
}
// REVIEW: 2 possible designs.
// 1. find the first fix and then return right away. if the lightbulb is actually expanded, find all fixes for the line synchronously. or
// 2. kick off a task that finds all fixes for the given range here but return once we find the first one.
// at the same time, let the task to run to finish. if the lightbulb is expanded, we just simply use the task to get all fixes.
//
// first approach is simpler, so I will implement that first. if the first approach turns out to be not good enough, then
// I will try the second approach which will be more complex but quicker
var hasFix = await ContainsAnyFix(document, diagnostic, cancellationToken).ConfigureAwait(false);
if (hasFix)
{
return new FirstDiagnosticResult(!fullResult, hasFix, diagnostic);
}
private async Task<DiagnosticData> GetFirstDiagnosticWithFixAsync(
Document document,
IEnumerable<DiagnosticData> severityGroup,
TextSpan range,
CancellationToken cancellationToken)
{
foreach (var diagnostic in severityGroup)
{
if (!range.IntersectsWith(diagnostic.TextSpan))
{
continue;
}
return new FirstDiagnosticResult(!fullResult, false, default(DiagnosticData));
if (await ContainsAnyFixAsync(document, diagnostic, cancellationToken).ConfigureAwait(false))
{
return diagnostic;
}
}
return null;
}
public async Task<ImmutableArray<CodeFixCollection>> GetFixesAsync(Document document, TextSpan range, bool includeSuppressionFixes, CancellationToken cancellationToken)
......@@ -142,7 +171,7 @@ public async Task<ImmutableArray<CodeFixCollection>> GetFixesAsync(Document docu
foreach (var spanAndDiagnostic in aggregatedDiagnostics)
{
await AppendFixesAsync(
document, spanAndDiagnostic.Key, spanAndDiagnostic.Value,
document, spanAndDiagnostic.Key, spanAndDiagnostic.Value,
result, cancellationToken).ConfigureAwait(false);
}
......@@ -176,7 +205,7 @@ public async Task<ImmutableArray<CodeFixCollection>> GetFixesAsync(Document docu
foreach (var spanAndDiagnostic in aggregatedDiagnostics)
{
await AppendSuppressionsAsync(
document, spanAndDiagnostic.Key, spanAndDiagnostic.Value,
document, spanAndDiagnostic.Key, spanAndDiagnostic.Value,
result, cancellationToken).ConfigureAwait(false);
}
}
......@@ -267,7 +296,7 @@ public async Task<ImmutableArray<CodeFixCollection>> GetFixesAsync(Document docu
}
private async Task AppendSuppressionsAsync(
Document document, TextSpan span, IEnumerable<DiagnosticData> diagnostics,
Document document, TextSpan span, IEnumerable<DiagnosticData> diagnostics,
ArrayBuilder<CodeFixCollection> result, CancellationToken cancellationToken)
{
if (!_suppressionProvidersMap.TryGetValue(document.Project.Language, out var lazySuppressionProvider) || lazySuppressionProvider.Value == null)
......@@ -276,10 +305,10 @@ public async Task<ImmutableArray<CodeFixCollection>> GetFixesAsync(Document docu
}
await AppendFixesOrSuppressionsAsync(
document, span, diagnostics, result, lazySuppressionProvider.Value,
document, span, diagnostics, result, lazySuppressionProvider.Value,
hasFix: d => lazySuppressionProvider.Value.CanBeSuppressedOrUnsuppressed(d),
getFixes: dxs => lazySuppressionProvider.Value.GetSuppressionsAsync(
document, span, dxs, cancellationToken),
document, span, dxs, cancellationToken),
cancellationToken: cancellationToken).ConfigureAwait(false);
}
......@@ -293,7 +322,7 @@ public async Task<ImmutableArray<CodeFixCollection>> GetFixesAsync(Document docu
Func<ImmutableArray<Diagnostic>, Task<ImmutableArray<CodeFix>>> getFixes,
CancellationToken cancellationToken)
{
var allDiagnostics =
var allDiagnostics =
await diagnosticsWithSameSpan.OrderByDescending(d => d.Severity)
.ToDiagnosticsAsync(document.Project, cancellationToken).ConfigureAwait(false);
var diagnostics = allDiagnostics.WhereAsArray(hasFix);
......@@ -372,7 +401,7 @@ private async Task<IEnumerable<Diagnostic>> GetProjectDiagnosticsAsync(Project p
}
}
private async Task<bool> ContainsAnyFix(
private async Task<bool> ContainsAnyFixAsync(
Document document, DiagnosticData diagnostic, CancellationToken cancellationToken)
{
var workspaceFixers = ImmutableArray<CodeFixProvider>.Empty;
......@@ -387,7 +416,7 @@ private async Task<IEnumerable<Diagnostic>> GetProjectDiagnosticsAsync(Project p
}
Lazy<ISuppressionFixProvider> lazySuppressionProvider = null;
var hasSuppressionFixer =
var hasSuppressionFixer =
_suppressionProvidersMap.TryGetValue(document.Project.Language, out lazySuppressionProvider) &&
lazySuppressionProvider.Value != null;
......
......@@ -10,9 +10,8 @@ namespace Microsoft.CodeAnalysis.CodeFixes
{
internal interface ICodeFixService
{
Task<FirstDiagnosticResult> GetFirstDiagnosticWithFixAsync(Document document, TextSpan textSpan, CancellationToken cancellationToken);
Task<ImmutableArray<CodeFixCollection>> GetFixesAsync(Document document, TextSpan textSpan, bool includeSuppressionFixes, CancellationToken cancellationToken);
CodeFixProvider GetSuppressionFixer(string language, IEnumerable<string> diagnosticIds);
Task<FirstDiagnosticResult> GetMostSevereFixableDiagnostic(Document document, TextSpan range, CancellationToken cancellationToken);
}
}
......@@ -24,14 +24,17 @@
using Microsoft.VisualStudio.Text.Editor;
using Roslyn.Utilities;
using CodeFixGroupKey = System.Tuple<Microsoft.CodeAnalysis.Diagnostics.DiagnosticData, Microsoft.CodeAnalysis.CodeActions.CodeActionPriority>;
namespace Microsoft.CodeAnalysis.Editor.Implementation.Suggestions
{
using CodeFixGroupKey = Tuple<DiagnosticData, CodeActionPriority>;
internal partial class SuggestedActionsSourceProvider
{
private class SuggestedActionsSource : ForegroundThreadAffinitizedObject, ISuggestedActionsSource
private class SuggestedActionsSource : ForegroundThreadAffinitizedObject, ISuggestedActionsSource2
{
private readonly ISuggestedActionCategoryRegistryService _suggestedActionCategoryRegistry;
// state that will be only reset when source is disposed.
private SuggestedActionsSourceProvider _owner;
private ITextView _textView;
......@@ -44,12 +47,17 @@ private class SuggestedActionsSource : ForegroundThreadAffinitizedObject, ISugge
public event EventHandler<EventArgs> SuggestedActionsChanged;
public SuggestedActionsSource(SuggestedActionsSourceProvider owner, ITextView textView, ITextBuffer textBuffer)
public SuggestedActionsSource(
SuggestedActionsSourceProvider owner,
ITextView textView,
ITextBuffer textBuffer,
ISuggestedActionCategoryRegistryService suggestedActionCategoryRegistry)
{
_owner = owner;
_textView = textView;
_textView.Closed += OnTextViewClosed;
_subjectBuffer = textBuffer;
_suggestedActionCategoryRegistry = suggestedActionCategoryRegistry;
_registration = Workspace.GetWorkspaceRegistration(textBuffer.AsTextContainer());
_lastSolutionVersionReported = InvalidSolutionVersion;
......@@ -221,7 +229,7 @@ private SuggestedActionSet FilterActionSetByTitle(SuggestedActionSet set, HashSe
{
return actions.Count == 0
? null
: new SuggestedActionSet(actions.ToImmutable(), set.Title, set.Priority, set.ApplicableToSpan);
: new SuggestedActionSet(set.CategoryName, actions.ToImmutable(), set.Title, set.Priority, set.ApplicableToSpan);
}
finally
{
......@@ -261,7 +269,11 @@ private SuggestedActionSet InlineActions(SuggestedActionSet actionSet)
}
return new SuggestedActionSet(
newActions.ToImmutableAndFree(), actionSet.Title, actionSet.Priority, actionSet.ApplicableToSpan);
actionSet.CategoryName,
newActions.ToImmutableAndFree(),
actionSet.Title,
actionSet.Priority,
actionSet.ApplicableToSpan);
}
private ImmutableArray<SuggestedActionSet> GetCodeFixes(
......@@ -529,13 +541,29 @@ private CodeRefactoring FilterOnUIThread(CodeRefactoring refactoring, Workspace
// diagnostic from things like build shouldn't reach here since we don't support LB for those diagnostics
Contract.Requires(diag.Item1.HasTextSpan);
sets.Add(new SuggestedActionSet(group, priority, diag.Item1.TextSpan.ToSpan()));
var category = GetFixCategory(diag.Item1.Severity);
sets.Add(new SuggestedActionSet(category, group, priority: priority, applicableToSpan: diag.Item1.TextSpan.ToSpan()));
}
}
return sets.ToImmutableAndFree();
}
private static string GetFixCategory(DiagnosticSeverity severity)
{
switch (severity)
{
case DiagnosticSeverity.Hidden:
case DiagnosticSeverity.Info:
case DiagnosticSeverity.Warning:
return PredefinedSuggestedActionCategoryNames.CodeFix;
case DiagnosticSeverity.Error:
return PredefinedSuggestedActionCategoryNames.ErrorFix;
default:
throw ExceptionUtilities.Unreachable;
};
}
private static SuggestedActionSetPriority GetSuggestedActionSetPriority(CodeActionPriority key)
{
switch (key)
......@@ -619,87 +647,81 @@ private static SuggestedActionSetPriority GetSuggestedActionSetPriority(CodeActi
}
return new SuggestedActionSet(
PredefinedSuggestedActionCategoryNames.Refactoring,
refactoringSuggestedActions.ToImmutableAndFree(),
SuggestedActionSetPriority.Low,
applicableSpan);
priority: SuggestedActionSetPriority.Low,
applicableToSpan: applicableSpan);
}
public async Task<bool> HasSuggestedActionsAsync(
public Task<bool> HasSuggestedActionsAsync(
ISuggestedActionCategorySet requestedActionCategories,
SnapshotSpan range,
CancellationToken cancellationToken)
{
var provider = _owner;
// We implement GetSuggestedActionCategoriesAsync so this should not be called
throw new NotImplementedException($"We implement {nameof(GetSuggestedActionCategoriesAsync)}. This should not be called.");
}
if (IsDisposed)
private async Task<TextSpan?> GetSpanAsync(SnapshotSpan range)
{
// First, ensure that the snapshot we're being asked about is for an actual
// roslyn document. This can fail, for example, in projection scenarios where
// we are called with a range snapshot that refers to the projection buffer
// and not the actual roslyn code that is being projected into it.
var document = range.Snapshot.GetOpenDocumentInCurrentContextWithChanges();
if (document == null)
{
// We've already been disposed. No point in continuing.
return false;
return null;
}
using (var asyncToken = _owner.OperationListener.BeginAsyncOperation("HasSuggestedActionsAsync"))
{
// First, ensure that the snapshot we're being asked about is for an actual
// roslyn document. This can fail, for example, in projection scenarios where
// we are called with a range snapshot that refers to the projection buffer
// and not the actual roslyn code that is being projected into it.
var document = range.Snapshot.GetOpenDocumentInCurrentContextWithChanges();
if (document == null)
{
return false;
}
// Next, before we do any async work, acquire the user's selection, directly grabbing
// it from the UI thread if htat's what we're on. That way we don't have any reentrancy
// blocking concerns if VS wants to block on this call (for example, if the user
// explicitly invokes the 'show smart tag' command).
//
// This work must happen on the UI thread as it needs to access the _textView's mutable
// state.
//
// Note: we may be called in one of two VS scenarios:
// 1) User has moved caret to a new line. In this case VS will call into us in the
// bg to see if we have any suggested actions for this line. In order to figure
// this out, we need to see what selectoin the user has (for refactorings), which
// necessitates going back to the fg.
//
// 2) User moves to a line and immediately hits ctrl-dot. In this case, on the UI
// thread VS will kick us off and then immediately block to get the results so
// that they can expand the lightbulb. In this case we cannot do BG work first,
// then call back into the UI thread to try to get the user selection. This will
// deadlock as the UI thread is blocked on us.
//
// There are two solution to '2'. Either introduce reentrancy (which we really don't
// like to do), or just ensure that we acquire and get the users selection up front.
// This means that when we're called from the UI therad, we never try to go back to the
// UI thread.
TextSpan? selection = null;
if (IsForeground())
{
selection = TryGetCodeRefactoringSelection(range);
}
else
// Next, before we do any async work, acquire the user's selection, directly grabbing
// it from the UI thread if htat's what we're on. That way we don't have any reentrancy
// blocking concerns if VS wants to block on this call (for example, if the user
// explicitly invokes the 'show smart tag' command).
//
// This work must happen on the UI thread as it needs to access the _textView's mutable
// state.
//
// Note: we may be called in one of two VS scenarios:
// 1) User has moved caret to a new line. In this case VS will call into us in the
// bg to see if we have any suggested actions for this line. In order to figure
// this out, we need to see what selectoin the user has (for refactorings), which
// necessitates going back to the fg.
//
// 2) User moves to a line and immediately hits ctrl-dot. In this case, on the UI
// thread VS will kick us off and then immediately block to get the results so
// that they can expand the lightbulb. In this case we cannot do BG work first,
// then call back into the UI thread to try to get the user selection. This will
// deadlock as the UI thread is blocked on us.
//
// There are two solution to '2'. Either introduce reentrancy (which we really don't
// like to do), or just ensure that we acquire and get the users selection up front.
// This means that when we're called from the UI therad, we never try to go back to the
// UI thread.
TextSpan? selection = null;
if (IsForeground())
{
selection = TryGetCodeRefactoringSelection(range);
}
else
{
await InvokeBelowInputPriority(() =>
{
await InvokeBelowInputPriority(() =>
// Make sure we were not disposed between kicking off this work and getting
// to this point.
if (IsDisposed)
{
// Make sure we were not disposed between kicking off this work and getting
// to this point.
if (IsDisposed)
{
return;
}
selection = TryGetCodeRefactoringSelection(range);
}).ConfigureAwait(false);
}
return;
}
return
await HasFixesAsync(provider, document, range, cancellationToken).ConfigureAwait(false) ||
await HasRefactoringsAsync(provider, document, selection, cancellationToken).ConfigureAwait(false);
selection = TryGetCodeRefactoringSelection(range);
}).ConfigureAwait(false);
}
return selection;
}
private async Task<bool> HasFixesAsync(
private async Task<string> GetFixLevelAsync(
SuggestedActionsSourceProvider provider,
Document document,
SnapshotSpan range,
......@@ -712,28 +734,28 @@ private static SuggestedActionSetPriority GetSuggestedActionSetPriority(CodeActi
supportsFeatureService.SupportsCodeFixes(document))
{
var result = await Task.Run(
() => provider._codeFixService.GetFirstDiagnosticWithFixAsync(
() => provider._codeFixService.GetMostSevereFixableDiagnostic(
document, range.Span.ToTextSpan(), cancellationToken),
cancellationToken).ConfigureAwait(false);
if (result.HasFix)
{
Logger.Log(FunctionId.SuggestedActions_HasSuggestedActionsAsync);
return true;
return GetFixCategory(result.Diagnostic.Severity);
}
if (result.PartialResult)
{
// reset solution version number so that we can raise suggested action changed event
Volatile.Write(ref _lastSolutionVersionReported, InvalidSolutionVersion);
return false;
return null;
}
}
return false;
return null;
}
private async Task<bool> HasRefactoringsAsync(
private async Task<string> TryGetRefactoringSuggestedActionCategoryAsync(
SuggestedActionsSourceProvider provider,
Document document,
TextSpan? selection,
......@@ -743,7 +765,7 @@ private static SuggestedActionSetPriority GetSuggestedActionSetPriority(CodeActi
{
// this is here to fail test and see why it is failed.
Trace.WriteLine("given range is not current");
return false;
return null;
}
var workspace = document.Project.Solution.Workspace;
......@@ -753,13 +775,16 @@ private static SuggestedActionSetPriority GetSuggestedActionSetPriority(CodeActi
provider._codeRefactoringService != null &&
supportsFeatureService.SupportsRefactorings(document))
{
return await Task.Run(
if (await Task.Run(
() => provider._codeRefactoringService.HasRefactoringsAsync(
document, selection.Value, cancellationToken),
cancellationToken).ConfigureAwait(false);
cancellationToken).ConfigureAwait(false))
{
return PredefinedSuggestedActionCategoryNames.Refactoring;
}
}
return false;
return null;
}
private TextSpan? TryGetCodeRefactoringSelection(SnapshotSpan range)
......@@ -860,6 +885,40 @@ private void OnSuggestedActionsChanged(Workspace currentWorkspace, DocumentId cu
Volatile.Write(ref _lastSolutionVersionReported, solutionVersion);
}
public async Task<ISuggestedActionCategorySet> GetSuggestedActionCategoriesAsync(ISuggestedActionCategorySet requestedActionCategories, SnapshotSpan range, CancellationToken cancellationToken)
{
var provider = _owner;
using (var asyncToken = _owner.OperationListener.BeginAsyncOperation(nameof(GetSuggestedActionCategoriesAsync)))
{
var selection = await GetSpanAsync(range).ConfigureAwait(false);
if (selection != null)
{
var document = range.Snapshot.GetOpenDocumentInCurrentContextWithChanges();
using (var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken))
{
var linkedToken = linkedTokenSource.Token;
var errorTask = Task.Run(
() => GetFixLevelAsync(provider, document, range, linkedToken), linkedToken);
var refactoringTask = Task.Run(
() => TryGetRefactoringSuggestedActionCategoryAsync(provider, document, selection, linkedToken),
linkedToken);
// If we happen to get the result of the error task before the refactoring task,
// and that result is non-null, we can just cancel the refactoring task.
var result = await errorTask.ConfigureAwait(false) ?? await refactoringTask.ConfigureAwait(false);
linkedTokenSource.Cancel();
return result == null
? null
: _suggestedActionCategoryRegistry.CreateSuggestedActionCategorySet(result);
}
}
}
return null;
}
}
}
}
\ No newline at end of file
......@@ -35,6 +35,7 @@ internal partial class SuggestedActionsSourceProvider : ISuggestedActionsSourceP
private readonly ICodeRefactoringService _codeRefactoringService;
private readonly IDiagnosticAnalyzerService _diagnosticService;
private readonly ICodeFixService _codeFixService;
private readonly ISuggestedActionCategoryRegistryService _suggestedActionCategoryRegistry;
public readonly ICodeActionEditHandlerService EditHandler;
public readonly IAsynchronousOperationListener OperationListener;
......@@ -50,6 +51,7 @@ internal partial class SuggestedActionsSourceProvider : ISuggestedActionsSourceP
ICodeFixService codeFixService,
ICodeActionEditHandlerService editHandler,
IWaitIndicator waitIndicator,
ISuggestedActionCategoryRegistryService suggestedActionCategoryRegistry,
[ImportMany] IEnumerable<Lazy<IAsynchronousOperationListener, FeatureMetadata>> asyncListeners,
[ImportMany] IEnumerable<Lazy<IImageMonikerService, OrderableMetadata>> imageMonikerServices,
[ImportMany] IEnumerable<Lazy<ISuggestedActionCallback>> actionCallbacks)
......@@ -57,6 +59,7 @@ internal partial class SuggestedActionsSourceProvider : ISuggestedActionsSourceP
_codeRefactoringService = codeRefactoringService;
_diagnosticService = diagnosticService;
_codeFixService = codeFixService;
_suggestedActionCategoryRegistry = suggestedActionCategoryRegistry;
ActionCallbacks = actionCallbacks.ToImmutableArray();
EditHandler = editHandler;
WaitIndicator = waitIndicator;
......@@ -70,7 +73,7 @@ public ISuggestedActionsSource CreateSuggestedActionsSource(ITextView textView,
Contract.ThrowIfNull(textView);
Contract.ThrowIfNull(textBuffer);
return new SuggestedActionsSource(this, textView, textBuffer);
return new SuggestedActionsSource(this, textView, textBuffer, _suggestedActionCategoryRegistry);
}
}
}
\ No newline at end of file
......@@ -46,7 +46,7 @@ public async Task TestGetFirstDiagnosticWithFixAsync()
var reference = new MockAnalyzerReference();
var project = workspace.CurrentSolution.Projects.Single().AddAnalyzerReference(reference);
var document = project.Documents.Single();
var unused = await fixService.GetFirstDiagnosticWithFixAsync(document, TextSpan.FromBounds(0, 0), cancellationToken: CancellationToken.None);
var unused = await fixService.GetMostSevereFixableDiagnostic(document, TextSpan.FromBounds(0, 0), cancellationToken: CancellationToken.None);
var fixer1 = fixers.Single().Value as MockFixer;
var fixer2 = reference.Fixer as MockFixer;
......@@ -127,7 +127,7 @@ public async Task GetFirstDiagnosticWithFixAsync(CodeFixProvider codefix)
using (var workspace = tuple.Item1)
{
GetDocumentAndExtensionManager(tuple.Item2, workspace, out var document, out var extensionManager);
var unused = await tuple.Item3.GetFirstDiagnosticWithFixAsync(document, TextSpan.FromBounds(0, 0), cancellationToken: CancellationToken.None);
var unused = await tuple.Item3.GetMostSevereFixableDiagnostic(document, TextSpan.FromBounds(0, 0), cancellationToken: CancellationToken.None);
Assert.True(extensionManager.IsDisabled(codefix));
Assert.False(extensionManager.IsIgnored(codefix));
}
......
......@@ -15,7 +15,17 @@ public static DisposableTextView CreateDisposableTextView(this ITextEditorFactor
public static DisposableTextView CreateDisposableTextView(this ITextEditorFactoryService textEditorFactory, ITextBuffer buffer)
{
return new DisposableTextView(textEditorFactory.CreateTextView(buffer));
// Every default role but outlining. Starting in 15.2, the editor
// OutliningManager imports JoinableTaskContext in a way that's
// difficult to satisfy in our unit tests. Since we don't directly
// depend on it, just disable it
var roles = textEditorFactory.CreateTextViewRoleSet(PredefinedTextViewRoles.Analyzable,
PredefinedTextViewRoles.Document,
PredefinedTextViewRoles.Editable,
PredefinedTextViewRoles.Interactive,
PredefinedTextViewRoles.Zoomable);
return new DisposableTextView(textEditorFactory.CreateTextView(buffer, roles));
}
}
......
......@@ -203,7 +203,18 @@ public IWpfTextView GetTextView()
WpfTestCase.RequireWpfFact($"Creates an IWpfTextView through {nameof(TestHostDocument)}.{nameof(GetTextView)}");
_textView = _exportProvider.GetExportedValue<ITextEditorFactoryService>().CreateTextView(this.TextBuffer);
var factory = _exportProvider.GetExportedValue<ITextEditorFactoryService>();
// Every default role but outlining. Starting in 15.2, the editor
// OutliningManager imports JoinableTaskContext in a way that's
// difficult to satisfy in our unit tests. Since we don't directly
// depend on it, just disable it
var roles = factory.CreateTextViewRoleSet(PredefinedTextViewRoles.Analyzable,
PredefinedTextViewRoles.Document,
PredefinedTextViewRoles.Editable,
PredefinedTextViewRoles.Interactive,
PredefinedTextViewRoles.Zoomable);
_textView = factory.CreateTextView(this.TextBuffer, roles);
if (this.CursorPosition.HasValue)
{
_textView.Caret.MoveTo(new SnapshotPoint(_textView.TextSnapshot, CursorPosition.Value));
......
......@@ -20,6 +20,7 @@ Microsoft.VisualStudio.Utilities.dll
Microsoft.VisualStudio.Platform.VSEditor.dll
Microsoft.VisualStudio.Platform.VSEditor.Interop.dll
Microsoft.VisualStudio.Shell.Interop.15.0.DesignTime.dll
Microsoft.VisualStudio.Shell.Interop.15.3.DesignTime.dll
Microsoft.Internal.Performance.CodeMarkers.DesignTime.dll
PackageAndDeploy\Microsoft.VisualStudio.Shell.Framework.dll
PackageAndDeploy\Microsoft.VisualStudio.Shell.15.0.dll
......
......@@ -345,6 +345,9 @@
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Shell.Interop.15.0.DesignTime">
<Version>$(MicrosoftVisualStudioShellInterop150DesignTimeVersion)</Version>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Shell.Interop.15.3.DesignTime">
<Version>$(MicrosoftVisualStudioShellInterop153DesignTimeVersion)</Version>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Shell.15.0">
<Version>$(MicrosoftVisualStudioShell150Version)</Version>
......
......@@ -126,6 +126,15 @@
<PackageReference Include="Microsoft.VisualStudio.Diagnostics.PerformanceProvider">
<Version>$(MicrosoftVisualStudioDiagnosticsPerformanceProviderVersion)</Version>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Shell.Interop.15.3.DesignTime">
<Version>$(MicrosoftVisualStudioShellInterop153DesignTimeVersion)</Version>
</PackageReference>
<PackageReference Include="StreamJsonRPC">
<Version>$(StreamJsonRPCVersion)</Version>
</PackageReference>
<PackageReference Include="Microsoft.VisualStudio.Threading">
<Version>$(MicrosoftVisualStudioThreadingVersion)</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<PublicAPI Include="PublicAPI.Shipped.txt" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册