Beispiel #1
0
        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);
            }
        }
Beispiel #2
0
        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);
            }
        }
Beispiel #5
0
        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);
            }
        }
Beispiel #6
0
        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);
        }
Beispiel #7
0
            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));
        }
Beispiel #9
0
        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);
        }