private void ExecuteCommandWorker( PasteCommandArgs args, CommandExecutionContext executionContext, ITrackingSpan trackingSpan) { if (!args.SubjectBuffer.CanApplyChangeDocumentToWorkspace()) { return; } // Don't perform work if we're inside the interactive window if (args.TextView.IsNotSurfaceBufferOfTextView(args.SubjectBuffer)) { return; } // Applying the post-paste snapshot to the tracking span gives us the span of pasted text. var snapshotSpan = trackingSpan.GetSpan(args.SubjectBuffer.CurrentSnapshot); var textSpan = snapshotSpan.Span.ToTextSpan(); var sourceTextContainer = args.SubjectBuffer.AsTextContainer(); if (!Workspace.TryGetWorkspace(sourceTextContainer, out var workspace)) { return; } var document = sourceTextContainer.GetOpenDocumentInCurrentContext(); if (document is null) { return; } var options = new AddMissingImportsOptions( HideAdvancedMembers: document.Project.Solution.Options.GetOption(CompletionOptions.Metadata.HideAdvancedMembers, document.Project.Language)); using var _ = executionContext.OperationContext.AddScope(allowCancellation: true, DialogText); var cancellationToken = executionContext.OperationContext.UserCancellationToken; // We're going to log the same thing on success or failure since this blocks the UI thread. This measurement is // intended to tell us how long we're blocking the user from typing with this action. using var blockLogger = Logger.LogBlock(FunctionId.CommandHandler_Paste_ImportsOnPaste, KeyValueLogMessage.Create(LogType.UserAction), cancellationToken); var addMissingImportsService = document.GetRequiredLanguageService <IAddMissingImportsFeatureService>(); #pragma warning disable VSTHRD102 // Implement internal logic asynchronously var updatedDocument = _threadingContext.JoinableTaskFactory.Run(() => addMissingImportsService.AddMissingImportsAsync(document, textSpan, options, cancellationToken)); #pragma warning restore VSTHRD102 // Implement internal logic asynchronously if (updatedDocument is null) { return; } workspace.TryApplyChanges(updatedDocument.Project.Solution); }
private async Task <AddMissingImportsOptions> GetOptionsAsync(Document document, CancellationToken cancellationToken) { var cleanupOptions = await document.GetCodeCleanupOptionsAsync(_globalOptions, cancellationToken).ConfigureAwait(false); var options = new AddMissingImportsOptions( CleanupOptions: cleanupOptions, HideAdvancedMembers: _globalOptions.GetOption(CompletionOptionsStorage.HideAdvancedMembers, document.Project.Language)); return(options); }
private async Task ExecuteAsync(Document document, SnapshotSpan snapshotSpan, ITextView textView) { _threadingContext.ThrowIfNotOnUIThread(); var indicatorFactory = document.Project.Solution.Workspace.Services.GetRequiredService <IBackgroundWorkIndicatorFactory>(); using var backgroundWorkContext = indicatorFactory.Create( textView, snapshotSpan, DialogText, cancelOnEdit: true, cancelOnFocusLost: true); var cancellationToken = backgroundWorkContext.UserCancellationToken; // We're going to log the same thing on success or failure since this blocks the UI thread. This measurement is // intended to tell us how long we're blocking the user from typing with this action. using var blockLogger = Logger.LogBlock(FunctionId.CommandHandler_Paste_ImportsOnPaste, KeyValueLogMessage.Create(LogType.UserAction), cancellationToken); var addMissingImportsService = document.GetRequiredLanguageService <IAddMissingImportsFeatureService>(); var cleanupOptions = await document.GetCodeCleanupOptionsAsync(_globalOptions, cancellationToken).ConfigureAwait(false); var options = new AddMissingImportsOptions( CleanupOptions: cleanupOptions, HideAdvancedMembers: _globalOptions.GetOption(CompletionOptionsStorage.HideAdvancedMembers, document.Project.Language)); var textSpan = snapshotSpan.Span.ToTextSpan(); var updatedDocument = await addMissingImportsService.AddMissingImportsAsync(document, textSpan, options, cancellationToken).ConfigureAwait(false); if (updatedDocument is null) { return; } // Required to switch back to the UI thread to call TryApplyChanges await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); document.Project.Solution.Workspace.TryApplyChanges(updatedDocument.Project.Solution); }
/// <inheritdoc/> public async Task <AddMissingImportsAnalysisResult> AnalyzeAsync(Document document, TextSpan textSpan, AddMissingImportsOptions options, CancellationToken cancellationToken) { // Get the diagnostics that indicate a missing import. var addImportFeatureService = document.GetRequiredLanguageService <IAddImportFeatureService>(); var solution = document.Project.Solution; var symbolSearchService = solution.Workspace.Services.GetRequiredService <ISymbolSearchService>(); // Since we are not currently considering NuGet packages, pass an empty array var packageSources = ImmutableArray <PackageSource> .Empty; var addImportOptions = new AddImportOptions( SearchOptions: new() { SearchReferenceAssemblies = true, SearchNuGetPackages = false }, CleanupOptions: options.CleanupOptions, HideAdvancedMembers: options.HideAdvancedMembers); var unambiguousFixes = await addImportFeatureService.GetUniqueFixesAsync( document, textSpan, FixableDiagnosticIds, symbolSearchService, addImportOptions, packageSources, cancellationToken).ConfigureAwait(false); // We do not want to add project or framework references without the user's input, so filter those out. var usableFixes = unambiguousFixes.WhereAsArray(fixData => DoesNotAddReference(fixData, document.Project.Id)); return(new AddMissingImportsAnalysisResult(usableFixes)); }
/// <inheritdoc/> public async Task <Document> AddMissingImportsAsync(Document document, TextSpan textSpan, AddMissingImportsOptions options, CancellationToken cancellationToken) { var analysisResult = await AnalyzeAsync(document, textSpan, options, cancellationToken).ConfigureAwait(false); return(await AddMissingImportsAsync(document, analysisResult, options.CleanupOptions.FormattingOptions, cancellationToken).ConfigureAwait(false)); }