public bool ExecuteCommand(ExtractInterfaceCommandArgs args, CommandExecutionContext context) { using (context.OperationContext.AddScope(allowCancellation: true, EditorFeaturesResources.Extract_Interface)) { var subjectBuffer = args.SubjectBuffer; if (!IsAvailable(subjectBuffer, out var workspace)) { return(false); } var caretPoint = args.TextView.GetCaretPoint(subjectBuffer); if (!caretPoint.HasValue) { return(false); } var document = subjectBuffer.CurrentSnapshot.GetFullyLoadedOpenDocumentInCurrentContextWithChanges( context.OperationContext, _threadingContext); if (document == null) { return(false); } // We are about to show a modal UI dialog so we should take over the command execution // wait context. That means the command system won't attempt to show its own wait dialog // and also will take it into consideration when measuring command handling duration. context.OperationContext.TakeOwnership(); var extractInterfaceService = document.GetLanguageService <AbstractExtractInterfaceService>(); _threadingContext.JoinableTaskFactory.Run(async() => { var result = await extractInterfaceService.ExtractInterfaceAsync( document, caretPoint.Value.Position, _globalOptions.CreateProvider(), (errorMessage, severity) => workspace.Services.GetService <INotificationService>().SendNotification(errorMessage, severity: severity), CancellationToken.None).ConfigureAwait(false); if (result == null || !result.Succeeded) { return; } if (!document.Project.Solution.Workspace.TryApplyChanges(result.UpdatedSolution)) { // TODO: handle failure return; } var navigationService = workspace.Services.GetService <IDocumentNavigationService>(); await navigationService.TryNavigateToPositionAsync( _threadingContext, workspace, result.NavigationDocumentId, position: 0, CancellationToken.None).ConfigureAwait(false); }); return(true); } }
public async Task <ImmutableArray <IntentSource> > ComputeIntentsAsync(IntentRequestContext intentRequestContext, CancellationToken cancellationToken) { var currentDocument = intentRequestContext.CurrentSnapshotSpan.Snapshot.GetOpenDocumentInCurrentContextWithChanges(); if (currentDocument == null) { throw new ArgumentException("could not retrieve document for request snapshot"); } var languageName = currentDocument.Project.Language; if (!_lazyIntentProviders.TryGetValue((LanguageName: languageName, IntentName: intentRequestContext.IntentName), out var provider)) { Logger.Log(FunctionId.Intellicode_UnknownIntent, KeyValueLogMessage.Create(LogType.UserAction, m => { m["intent"] = intentRequestContext.IntentName; m["language"] = languageName; })); return(ImmutableArray <IntentSource> .Empty); } var currentText = await currentDocument.GetTextAsync(cancellationToken).ConfigureAwait(false); var originalDocument = currentDocument.WithText(currentText.WithChanges(intentRequestContext.PriorTextEdits)); var selectionTextSpan = intentRequestContext.PriorSelection; var results = await provider.Value.ComputeIntentAsync( originalDocument, selectionTextSpan, currentDocument, new IntentDataProvider( intentRequestContext.IntentData, _globalOptions.CreateProvider()), cancellationToken).ConfigureAwait(false); if (results.IsDefaultOrEmpty) { return(ImmutableArray <IntentSource> .Empty); } using var _ = ArrayBuilder <IntentSource> .GetInstance(out var convertedResults); foreach (var result in results) { var convertedIntent = await ConvertToIntelliCodeResultAsync(result, originalDocument, currentDocument, cancellationToken).ConfigureAwait(false); convertedResults.AddIfNotNull(convertedIntent); } return(convertedResults.ToImmutable()); }
public TestDiagnosticAnalyzerDriver(Workspace workspace, bool includeSuppressedDiagnostics = false) { var mefServices = (IMefHostExportProvider)workspace.Services.HostServices; Assert.IsType <MockDiagnosticUpdateSourceRegistrationService>(mefServices.GetExportedValue <IDiagnosticUpdateSourceRegistrationService>()); _diagnosticAnalyzerService = Assert.IsType <DiagnosticAnalyzerService>(mefServices.GetExportedValue <IDiagnosticAnalyzerService>()); GlobalOptions = mefServices.GetExportedValue <IGlobalOptionService>(); FallbackOptions = GlobalOptions.CreateProvider(); _diagnosticAnalyzerService.CreateIncrementalAnalyzer(workspace); _includeSuppressedDiagnostics = includeSuppressedDiagnostics; }
private bool ExecuteCommand(ITextView textView, ITextBuffer subjectBuffer, CommandExecutionContext context) { using (context.OperationContext.AddScope(allowCancellation: true, FeaturesResources.Change_signature)) { if (!IsAvailable(subjectBuffer, out var workspace)) { return(false); } var caretPoint = textView.GetCaretPoint(subjectBuffer); if (!caretPoint.HasValue) { return(false); } var document = subjectBuffer.CurrentSnapshot.GetFullyLoadedOpenDocumentInCurrentContextWithChanges( context.OperationContext, _threadingContext); if (document == null) { return(false); } var changeSignatureService = document.GetRequiredLanguageService <AbstractChangeSignatureService>(); var cancellationToken = context.OperationContext.UserCancellationToken; // TODO: Make asynchronous and avoid expensive semantic operations on UI thread: // https://github.com/dotnet/roslyn/issues/62135 // Async operation to determine the change signature var changeSignatureContext = changeSignatureService.GetChangeSignatureContextAsync( document, caretPoint.Value.Position, restrictToDeclarations: false, _globalOptions.CreateProvider(), cancellationToken).WaitAndGetResult(context.OperationContext.UserCancellationToken); // UI thread bound operation to show the change signature dialog. var changeSignatureOptions = AbstractChangeSignatureService.GetChangeSignatureOptions(changeSignatureContext); // Async operation to compute the new solution created from the specified options. var result = changeSignatureService.ChangeSignatureWithContextAsync(changeSignatureContext, changeSignatureOptions, cancellationToken).WaitAndGetResult(cancellationToken); // UI thread bound operation to show preview changes dialog / show error message, then apply the solution changes (if applicable). HandleResult(result, document.Project.Solution, workspace, context); return(true); } }
public async Task <ExtractInterfaceOptionsResult> GetExtractInterfaceOptionsAsync( ISyntaxFactsService syntaxFactsService, INotificationService notificationService, List <ISymbol> extractableMembers, string defaultInterfaceName, List <string> allTypeNames, string defaultNamespace, string generatedNameTypeParameterSuffix, string languageName, CancellationToken cancellationToken) { await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); var viewModel = new ExtractInterfaceDialogViewModel( syntaxFactsService, _glyphService, notificationService, defaultInterfaceName, extractableMembers, allTypeNames, defaultNamespace, generatedNameTypeParameterSuffix, languageName); var dialog = new ExtractInterfaceDialog(viewModel); var result = dialog.ShowModal(); if (result.HasValue && result.Value) { var includedMembers = viewModel.MemberContainers.Where(c => c.IsChecked).Select(c => c.Symbol); return(new ExtractInterfaceOptionsResult( isCancelled: false, includedMembers: includedMembers.AsImmutable(), interfaceName: viewModel.DestinationViewModel.TypeName.Trim(), fileName: viewModel.DestinationViewModel.FileName.Trim(), location: GetLocation(viewModel.DestinationViewModel.Destination), _globalOptions.CreateProvider())); } else { return(ExtractInterfaceOptionsResult.Cancelled); } }
private async Task ExecuteAsync( EncapsulateFieldCommandArgs args, Document initialDocument, SnapshotSpan span) { _threadingContext.ThrowIfNotOnUIThread(); var subjectBuffer = args.SubjectBuffer; var workspace = initialDocument.Project.Solution.Workspace; var indicatorFactory = workspace.Services.GetRequiredService <IBackgroundWorkIndicatorFactory>(); using var context = indicatorFactory.Create( args.TextView, span, EditorFeaturesResources.Computing_Encapsulate_Field_information, cancelOnEdit: true, cancelOnFocusLost: true); var cancellationToken = context.UserCancellationToken; var document = await subjectBuffer.CurrentSnapshot.GetFullyLoadedOpenDocumentInCurrentContextWithChangesAsync(context).ConfigureAwait(false); Contract.ThrowIfNull(document); var service = document.GetRequiredLanguageService <AbstractEncapsulateFieldService>(); var result = await service.EncapsulateFieldsInSpanAsync( document, span.Span.ToTextSpan(), _globalOptions.CreateProvider(), useDefaultBehavior : true, cancellationToken).ConfigureAwait(false); if (result == null) { await _threadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken); // We are about to show a modal UI dialog so we should take over the command execution // wait context. That means the command system won't attempt to show its own wait dialog // and also will take it into consideration when measuring command handling duration. context.TakeOwnership(); var notificationService = workspace.Services.GetRequiredService <INotificationService>(); notificationService.SendNotification(EditorFeaturesResources.Please_select_the_definition_of_the_field_to_encapsulate, severity: NotificationSeverity.Error); return; } await ApplyChangeAsync(subjectBuffer, document, result, cancellationToken).ConfigureAwait(false); }
private async Task <string> DetermineIfEventHookupAndGetHandlerNameAsync(Document document, int position, CancellationToken cancellationToken) { _threadingContext.ThrowIfNotOnBackgroundThread(); // For test purposes only! if (TESTSessionHookupMutex != null) { TESTSessionHookupMutex.WaitOne(); TESTSessionHookupMutex.ReleaseMutex(); } using (Logger.LogBlock(FunctionId.EventHookup_Determine_If_Event_Hookup, cancellationToken)) { var plusEqualsToken = await GetPlusEqualsTokenInsideAddAssignExpressionAsync(document, position, cancellationToken).ConfigureAwait(false); if (plusEqualsToken == null) { return(null); } var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var eventSymbol = GetEventSymbol(semanticModel, plusEqualsToken.Value, cancellationToken); if (eventSymbol == null) { return(null); } var namingRule = await document.GetApplicableNamingRuleAsync( new SymbolKindOrTypeKind(MethodKind.Ordinary), new DeclarationModifiers(isStatic : plusEqualsToken.Value.Parent.IsInStaticContext()), Accessibility.Private, _globalOptions.CreateProvider(), cancellationToken).ConfigureAwait(false); return(GetEventHandlerName( eventSymbol, plusEqualsToken.Value, semanticModel, document.GetLanguageService <ISyntaxFactsService>(), namingRule)); } }
private async Task <IInlineRenameInfo> GetRenameInfoAsync( IEnumerable <IRefactorNotifyService> refactorNotifyServices, Document document, SyntaxToken triggerToken, CancellationToken cancellationToken) { var syntaxFacts = document.GetRequiredLanguageService <ISyntaxFactsService>(); if (syntaxFacts.IsReservedOrContextualKeyword(triggerToken)) { return(new FailureInlineRenameInfo(EditorFeaturesResources.You_must_rename_an_identifier)); } var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); var semanticFacts = document.GetRequiredLanguageService <ISemanticFactsService>(); var tokenRenameInfo = RenameUtilities.GetTokenRenameInfo(semanticFacts, semanticModel, triggerToken, cancellationToken); // Rename was invoked on a member group reference in a nameof expression. // Trigger the rename on any of the candidate symbols but force the // RenameOverloads option to be on. var triggerSymbol = tokenRenameInfo.HasSymbols ? tokenRenameInfo.Symbols.First() : null; if (triggerSymbol == null) { return(new FailureInlineRenameInfo(EditorFeaturesResources.You_cannot_rename_this_element)); } // see https://github.com/dotnet/roslyn/issues/10898 // we are disabling rename for tuple fields for now // 1) compiler does not return correct location information in these symbols // 2) renaming tuple fields seems a complex enough thing to require some design if (triggerSymbol.ContainingType?.IsTupleType == true) { return(new FailureInlineRenameInfo(EditorFeaturesResources.You_cannot_rename_this_element)); } // If rename is invoked on a member group reference in a nameof expression, then the // RenameOverloads option should be forced on. var forceRenameOverloads = tokenRenameInfo.IsMemberGroup; var symbol = await RenameUtilities.TryGetRenamableSymbolAsync(document, triggerToken.SpanStart, cancellationToken : cancellationToken).ConfigureAwait(false); if (symbol == null) { return(new FailureInlineRenameInfo(EditorFeaturesResources.You_cannot_rename_this_element)); } if (symbol.Kind == SymbolKind.Alias && symbol.IsExtern) { return(new FailureInlineRenameInfo(EditorFeaturesResources.You_cannot_rename_this_element)); } // Cannot rename constructors in VB. TODO: this logic should be in the VB subclass of this type. var workspace = document.Project.Solution.Workspace; if (symbol.Kind == SymbolKind.NamedType && symbol.Language == LanguageNames.VisualBasic && triggerToken.ToString().Equals("New", StringComparison.OrdinalIgnoreCase)) { var originalSymbol = await SymbolFinder.FindSymbolAtPositionAsync( semanticModel, triggerToken.SpanStart, workspace, cancellationToken : cancellationToken).ConfigureAwait(false); if (originalSymbol != null && originalSymbol.IsConstructor()) { return(new FailureInlineRenameInfo(EditorFeaturesResources.You_cannot_rename_this_element)); } } if (CheckLanguageSpecificIssues(semanticModel, symbol, triggerToken, out var langError)) { return(new FailureInlineRenameInfo(langError)); } // we allow implicit locals and parameters of Event handlers if (symbol.IsImplicitlyDeclared && symbol.Kind != SymbolKind.Local && !(symbol.Kind == SymbolKind.Parameter && symbol.ContainingSymbol.Kind == SymbolKind.Method && symbol.ContainingType != null && symbol.ContainingType.IsDelegateType() && symbol.ContainingType.AssociatedSymbol != null)) { // We enable the parameter in RaiseEvent, if the Event is declared with a signature. If the Event is declared as a // delegate type, we do not have a connection between the delegate type and the event. // this prevents a rename in this case :(. return(new FailureInlineRenameInfo(EditorFeaturesResources.You_cannot_rename_this_element)); } if (symbol.Kind == SymbolKind.Property && symbol.ContainingType.IsAnonymousType) { return(new FailureInlineRenameInfo(EditorFeaturesResources.Renaming_anonymous_type_members_is_not_yet_supported)); } if (symbol.IsErrorType()) { return(new FailureInlineRenameInfo(EditorFeaturesResources.Please_resolve_errors_in_your_code_before_renaming_this_element)); } if (symbol.Kind == SymbolKind.Method && ((IMethodSymbol)symbol).MethodKind == MethodKind.UserDefinedOperator) { return(new FailureInlineRenameInfo(EditorFeaturesResources.You_cannot_rename_operators)); } var symbolLocations = symbol.Locations; // Does our symbol exist in an unchangeable location? var documentSpans = ArrayBuilder <DocumentSpan> .GetInstance(); foreach (var location in symbolLocations) { if (location.IsInMetadata) { return(new FailureInlineRenameInfo(EditorFeaturesResources.You_cannot_rename_elements_that_are_defined_in_metadata)); } else if (location.IsInSource) { var solution = document.Project.Solution; var sourceDocument = solution.GetRequiredDocument(location.SourceTree); if (sourceDocument is SourceGeneratedDocument) { // The file is generated so we can't go editing it (for now) return(new FailureInlineRenameInfo(EditorFeaturesResources.You_cannot_rename_this_element)); } if (document.Project.IsSubmission) { var projectIdOfLocation = sourceDocument.Project.Id; if (solution.Projects.Any(p => p.IsSubmission && p.ProjectReferences.Any(r => r.ProjectId == projectIdOfLocation))) { return(new FailureInlineRenameInfo(EditorFeaturesResources.You_cannot_rename_elements_from_previous_submissions)); } } else { // We eventually need to return the symbol locations, so we must convert each location to a DocumentSpan since our return type is language-agnostic. documentSpans.Add(new DocumentSpan(sourceDocument, location.SourceSpan)); } } else { return(new FailureInlineRenameInfo(EditorFeaturesResources.You_cannot_rename_this_element)); } } var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false); var triggerText = sourceText.ToString(triggerToken.Span); var fallbackOptions = _globalOptions.CreateProvider(); return(new SymbolInlineRenameInfo( refactorNotifyServices, document, triggerToken.Span, triggerText, symbol, forceRenameOverloads, documentSpans.ToImmutableAndFree(), fallbackOptions, cancellationToken)); }
private bool Execute(EncapsulateFieldCommandArgs args, IUIThreadOperationScope waitScope) { using var token = _listener.BeginAsyncOperation("EncapsulateField"); var cancellationToken = waitScope.Context.UserCancellationToken; var document = args.SubjectBuffer.CurrentSnapshot.GetFullyLoadedOpenDocumentInCurrentContextWithChanges( waitScope.Context, _threadingContext); if (document == null) { return(false); } var spans = args.TextView.Selection.GetSnapshotSpansOnBuffer(args.SubjectBuffer); var service = document.GetLanguageService <AbstractEncapsulateFieldService>(); var result = service.EncapsulateFieldsInSpanAsync(document, spans.First().Span.ToTextSpan(), _globalOptions.CreateProvider(), useDefaultBehavior: true, cancellationToken).WaitAndGetResult(cancellationToken); // We are about to show a modal UI dialog so we should take over the command execution // wait context. That means the command system won't attempt to show its own wait dialog // and also will take it into consideration when measuring command handling duration. waitScope.Context.TakeOwnership(); var workspace = document.Project.Solution.Workspace; if (result == null) { var notificationService = workspace.Services.GetService <INotificationService>(); notificationService.SendNotification(EditorFeaturesResources.Please_select_the_definition_of_the_field_to_encapsulate, severity: NotificationSeverity.Error); return(false); } waitScope.AllowCancellation = false; cancellationToken = waitScope.Context.UserCancellationToken; var finalSolution = result.GetSolutionAsync(cancellationToken).WaitAndGetResult(cancellationToken); var previewService = workspace.Services.GetService <IPreviewDialogService>(); if (previewService != null) { finalSolution = previewService.PreviewChanges( string.Format(EditorFeaturesResources.Preview_Changes_0, EditorFeaturesResources.Encapsulate_Field), "vs.csharp.refactoring.preview", EditorFeaturesResources.Encapsulate_Field_colon, result.Name, result.Glyph, finalSolution, document.Project.Solution); } if (finalSolution == null) { // User clicked cancel. return(true); } using (var undoTransaction = _undoManager.GetTextBufferUndoManager(args.SubjectBuffer).TextBufferUndoHistory.CreateTransaction(EditorFeaturesResources.Encapsulate_Field)) { if (!workspace.TryApplyChanges(finalSolution)) { undoTransaction.Cancel(); return(false); } undoTransaction.Complete(); } return(true); }