Beispiel #1
0
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var document          = context.Document;
            var textSpan          = context.Span;
            var cancellationToken = context.CancellationToken;

            // NOTE(DustinCa): Not supported in REPL for now.
            if (document.SourceCodeKind == SourceCodeKind.Interactive)
            {
                return;
            }

            if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles)
            {
                return;
            }

            var service = document.GetLanguageService <IGenerateDefaultConstructorsService>();
            var result  = await service.GenerateDefaultConstructorsAsync(document, textSpan, cancellationToken).ConfigureAwait(false);

            if (!result.ContainsChanges)
            {
                return;
            }

            var actions = result.GetCodeRefactoring(cancellationToken).Actions;

            context.RegisterRefactorings(actions);
        }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var document          = context.Document;
            var textSpan          = context.Span;
            var cancellationToken = context.CancellationToken;

            // TODO: https://github.com/dotnet/roslyn/issues/5778
            // Not supported in REPL for now.
            if (document.Project.IsSubmission)
            {
                return;
            }

            if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles)
            {
                return;
            }

            var service = document.GetLanguageService <IGenerateDefaultConstructorsService>();
            var actions = await service.GenerateDefaultConstructorsAsync(document, textSpan, cancellationToken).ConfigureAwait(false);

            if (!actions.IsDefault)
            {
                context.RegisterRefactorings(actions);
            }
        }
Beispiel #3
0
        public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var service = context.Document.GetLanguageService <AbstractEncapsulateFieldService>();
            var actions = await service.GetEncapsulateFieldCodeActionsAsync(context.Document, context.Span, context.CancellationToken).ConfigureAwait(false);

            context.RegisterRefactorings(actions);
        }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            // Don't bother if there isn't a selection
            var(document, textSpan, cancellationToken) = context;
            if (textSpan.IsEmpty)
            {
                return;
            }

            var workspace = document.Project.Solution.Workspace;

            if (workspace.Kind == WorkspaceKind.MiscellaneousFiles)
            {
                return;
            }

            var activeInlineRenameSession = workspace.Services.GetService <ICodeRefactoringHelpersService>().ActiveInlineRenameSession;

            if (activeInlineRenameSession)
            {
                return;
            }

            if (cancellationToken.IsCancellationRequested)
            {
                return;
            }

            var actions = await GetCodeActionsAsync(document, textSpan, cancellationToken : cancellationToken).ConfigureAwait(false);

            context.RegisterRefactorings(actions);
        }
Beispiel #5
0
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var document          = context.Document;
            var textSpan          = context.Span;
            var cancellationToken = context.CancellationToken;

            var workspace = document.Project.Solution.Workspace;

            if (workspace.Kind == WorkspaceKind.MiscellaneousFiles)
            {
                return;
            }

            if (document.IsGeneratedCode())
            {
                return;
            }

            var service = document.GetLanguageService <IMoveTypeService>();
            var actions = await service.GetRefactoringAsync(document, textSpan, cancellationToken).ConfigureAwait(false);

            if (!actions.IsDefault)
            {
                context.RegisterRefactorings(actions);
            }
        }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var document          = context.Document;
            var textSpan          = context.Span;
            var cancellationToken = context.CancellationToken;

            if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles)
            {
                return;
            }
            var model = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            if (model.IsFromGeneratedCode(cancellationToken))
            {
                return;
            }
            var result = await service.IntroduceVariableAsync(document, textSpan, cancellationToken).ConfigureAwait(false);

            if (!result.ContainsChanges)
            {
                return;
            }

            var actions = result.GetCodeRefactoring(cancellationToken).Actions;

            context.RegisterRefactorings(actions);
        }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var document = context.Document;
            var textSpan = context.Span;
            var cancellationToken = context.CancellationToken;

            // TODO: https://github.com/dotnet/roslyn/issues/5778
            // Not supported in REPL for now.
            if (document.Project.IsSubmission)
            {
                return;
            }

            if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles)
            {
                return;
            }

            var service = document.GetLanguageService<IGenerateDefaultConstructorsService>();
            var actions = await service.GenerateDefaultConstructorsAsync(document, textSpan, cancellationToken).ConfigureAwait(false);
            if (!actions.IsDefault)
            {
                context.RegisterRefactorings(actions);
            }
        }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var document = context.Document;
            var textSpan = context.Span;
            var cancellationToken = context.CancellationToken;

            var workspace = document.Project.Solution.Workspace;
            if (workspace.Kind == WorkspaceKind.MiscellaneousFiles)
            {
                return;
            }

            var generatedCodeRecognitionService = workspace.Services.GetService<IGeneratedCodeRecognitionService>();
            if (generatedCodeRecognitionService.IsGeneratedCode(document))
            {
                return;
            }

            var service = document.GetLanguageService<IMoveTypeService>();
            var actions = await service.GetRefactoringAsync(document, textSpan, cancellationToken).ConfigureAwait(false);
            if (!actions.IsDefault)
            {
                context.RegisterRefactorings(actions);
            }
        }
Beispiel #9
0
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var moveToNamespaceService = context.Document.GetLanguageService <IMoveToNamespaceService>();
            var actions = await moveToNamespaceService.GetCodeActionsAsync(context.Document, context.Span, context.CancellationToken).ConfigureAwait(false);

            context.RegisterRefactorings(actions);
        }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var document          = context.Document;
            var textSpan          = context.Span;
            var cancellationToken = context.CancellationToken;

            var state = await State.CreateAsync(this, document, textSpan, cancellationToken).ConfigureAwait(false);

            if (state == null)
            {
                return;
            }

            // No move file action if rootnamespace isn't a prefix of current declared namespace
            if (state.RelativeDeclaredNamespace != null)
            {
                context.RegisterRefactorings(MoveFileCodeAction.Create(state));
            }

            // No change namespace action if we can't construct a valid namespace from rootnamespace and folder names.
            if (state.TargetNamespace != null)
            {
                var service = document.GetLanguageService <IChangeNamespaceService>();
                var solutionChangeAction = new SolutionChangeAction(ChangeNamespaceActionTitle(state), token => service.ChangeNamespaceAsync(state.Solution, state.DocumentIds, state.DeclaredNamespace, state.TargetNamespace, token));
                context.RegisterRefactoring(solutionChangeAction);
            }
        }
Beispiel #11
0
        private async Task ComputeRefactoringsAsync(
            CodeRefactoringContext context,
            TOptionKind option,
            bool analyzerActive
            )
        {
            var(document, span, cancellationToken) = context;

            var computationTask = analyzerActive
                ? ComputeOpposingRefactoringsWhenAnalyzerActiveAsync(
                document,
                span,
                option,
                cancellationToken
                )
                : ComputeAllRefactoringsWhenAnalyzerInactiveAsync(
                document,
                span,
                cancellationToken
                );

            var codeActions = await computationTask.ConfigureAwait(false);

            context.RegisterRefactorings(codeActions);
        }
        public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var(document, textSpan, cancellationToken) = context;
            var service = document.GetLanguageService <AbstractExtractInterfaceService>();
            var actions = await service.GetExtractInterfaceCodeActionAsync(document, textSpan, cancellationToken).ConfigureAwait(false);

            context.RegisterRefactorings(actions);
        }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var document          = context.Document;
            var textSpan          = context.Span;
            var cancellationToken = context.CancellationToken;

            var state = await State.CreateAsync(this, document, textSpan, cancellationToken).ConfigureAwait(false);

            if (state == null)
            {
                return;
            }

            // No move file action if rootnamespace isn't a prefix of current declared namespace
            if (state.RelativeDeclaredNamespace != null)
            {
                // These code actions try to move file to a new location based on declared namespace
                // and the default namespace of the project. The new location is a list of folders
                // determined by the relateive part of the declared namespace compare to the default namespace.
                //
                // For example, if he default namespace is `A.B.C`, file path is
                // "[project root dir]\Class1.cs" and declared namespace in the file is
                // `A.B.C.D.E`, then this action will move the file to [project root dir]\D\E\Class1.cs". .
                //
                // We also try to use existing folders as target if possible, using the same example above,
                // if folder "[project root dir]\D.E\" already exist, we will also offer to move file to
                // "[project root dir]\D.E\Class1.cs".
                context.RegisterRefactorings(MoveFileCodeAction.Create(state));
            }

            // No change namespace action if we can't construct a valid namespace from rootnamespace and folder names.
            if (state.TargetNamespace != null)
            {
                // This code action tries to change the name of the namespace declaration to
                // match the folder hierarchy of the document. The new namespace is constructed
                // by concatenating the default namespace of the project and all the folders in
                // the file path up to the project root.
                //
                // For example, if he default namespace is `A.B.C`, file path is
                // "[project root dir]\D\E\F\Class1.cs" and declared namespace in the file is
                // `Foo.Bar.Baz`, then this action will change the namespace declaration
                // to `A.B.C.D.E.F`.
                //
                // Note that it also handles the case where the target namespace or declared namespace
                // is global namespace, i.e. default namespace is "" and the file is located at project
                // root directory, and no namespace declaration in the document, respectively.

                var service = document.GetLanguageService <IChangeNamespaceService>();

                var solutionChangeAction = new ChangeNamespaceCodeAction(
                    state.TargetNamespace.Length == 0
                        ? FeaturesResources.Change_to_global_namespace
                        : string.Format(FeaturesResources.Change_namespace_to_0, state.TargetNamespace),
                    token => service.ChangeNamespaceAsync(document, state.Container, state.TargetNamespace, token));

                context.RegisterRefactoring(solutionChangeAction);
            }
        }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var position          = context.Span.Start;
            var document          = context.Document;
            var cancellationToken = context.CancellationToken;

            var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var refactoringHelperService = document.GetLanguageService <IRefactoringHelpersService>();

            var parameterNode = await refactoringHelperService.TryGetSelectedNodeAsync <TParameterSyntax>(document, context.Span, cancellationToken).ConfigureAwait(false);

            if (parameterNode == null)
            {
                return;
            }

            var functionDeclaration = parameterNode.FirstAncestorOrSelf <SyntaxNode>(IsFunctionDeclaration);

            if (functionDeclaration == null)
            {
                return;
            }

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            // we can't just call GetDeclaredSymbol on functionDeclaration because it could an anonymous function,
            // so first we have to get the parameter symbol and then its containing method symbol
            var parameter = (IParameterSymbol)semanticModel.GetDeclaredSymbol(parameterNode, cancellationToken);

            if (parameter == null || parameter.Name == "")
            {
                return;
            }

            var method = (IMethodSymbol)parameter.ContainingSymbol;

            if (method.IsAbstract ||
                method.IsExtern ||
                method.PartialImplementationPart != null ||
                method.ContainingType.TypeKind == TypeKind.Interface)
            {
                return;
            }

            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

            if (CanOfferRefactoring(functionDeclaration, semanticModel, syntaxFacts, cancellationToken, out var blockStatementOpt))
            {
                // Ok.  Looks like a reasonable parameter to analyze.  Defer to subclass to
                // actually determine if there are any viable refactorings here.
                context.RegisterRefactorings(await GetRefactoringsAsync(
                                                 document, parameter, functionDeclaration, method, blockStatementOpt, cancellationToken).ConfigureAwait(false));
            }
        }
        public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            if (context.Span.IsEmpty)
            {
                var service = context.Document.GetLanguageService <AbstractChangeSignatureService>();
                var actions = await service.GetChangeSignatureCodeActionAsync(context.Document, context.Span, context.CancellationToken).ConfigureAwait(false);

                context.RegisterRefactorings(actions);
            }
        }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var(document, span, cancellationToken) = context;
            if (!span.IsEmpty)
            {
                return;
            }

            var position = span.Start;
            var root     = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var token = root.FindToken(position);

            var configOptions = await document.GetAnalyzerConfigOptionsAsync(cancellationToken).ConfigureAwait(false);

            var options = GetWrappingOptions(configOptions, context.Options);

            foreach (var node in token.GetRequiredParent().AncestorsAndSelf())
            {
                var containsSyntaxError = node.GetDiagnostics().Any(d => d.Severity == DiagnosticSeverity.Error);

                // Check if any wrapper can handle this node.  If so, then we're done, otherwise
                // keep walking up.
                foreach (var wrapper in _wrappers)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    var computer = await wrapper.TryCreateComputerAsync(
                        document, position, node, options, containsSyntaxError, cancellationToken).ConfigureAwait(false);

                    if (computer == null)
                    {
                        continue;
                    }

                    var actions = await computer.GetTopLevelCodeActionsAsync().ConfigureAwait(false);

                    if (actions.IsDefaultOrEmpty)
                    {
                        continue;
                    }

                    context.RegisterRefactorings(actions);
                    return;
                }

                // if we hit a syntax error and the computer couldn't handle it, then bail out.  Don't want to format if
                // we don't really understand what's going on.
                if (containsSyntaxError)
                {
                    return;
                }
            }
        }
Beispiel #17
0
        private async Task HandleNonSelectionAsync(CodeRefactoringContext context)
        {
            var document          = context.Document;
            var textSpan          = context.Span;
            var cancellationToken = context.CancellationToken;

            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();
            var sourceText  = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            // We offer the refactoring when the user is either on the header of a class/struct,
            // or if they're between any members of a class/struct and are on a blank line.
            if (!syntaxFacts.IsOnTypeHeader(root, textSpan.Start) &&
                !syntaxFacts.IsBetweenTypeMembers(sourceText, root, textSpan.Start))
            {
                return;
            }

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            // Only supported on classes/structs.
            var containingType = GetEnclosingNamedType(semanticModel, root, textSpan.Start, cancellationToken);

            if (containingType?.TypeKind != TypeKind.Class && containingType?.TypeKind != TypeKind.Struct)
            {
                return;
            }

            // No overrides in static classes.
            if (containingType.IsStatic)
            {
                return;
            }

            // Find all the possible instance fields/properties.  If there are any, then
            // show a dialog to the user to select the ones they want.
            var viableMembers = containingType.GetMembers().WhereAsArray(IsViableInstanceFieldOrProperty);

            if (viableMembers.Length == 0)
            {
                return;
            }

            GetExistingMemberInfo(
                containingType, out var hasEquals, out var hasGetHashCode);

            var actions = CreateActions(
                document, textSpan, containingType, viableMembers,
                hasEquals, hasGetHashCode,
                withDialog: true);

            context.RegisterRefactorings(actions);
        }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var document          = context.Document;
            var textSpan          = context.Span;
            var cancellationToken = context.CancellationToken;

            var service = document.GetLanguageService <ISyncNamespaceService>();
            var actions = await service.GetRefactoringsAsync(document, textSpan, cancellationToken).ConfigureAwait(false);

            context.RegisterRefactorings(actions);
        }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var(document, textSpan, cancellationToken) = context;
            if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles)
            {
                return;
            }

            var actions = await AddConstructorParametersFromMembersAsync(document, textSpan, cancellationToken).ConfigureAwait(false);

            context.RegisterRefactorings(actions);
        }
Beispiel #20
0
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var span = context.Span;

            if (!span.IsEmpty)
            {
                return;
            }

            var position          = span.Start;
            var document          = context.Document;
            var cancellationToken = context.CancellationToken;

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var token = root.FindToken(position);

            foreach (var node in token.Parent.AncestorsAndSelf())
            {
                // Make sure we don't have any syntax errors here.  Don't want to format if we don't
                // really understand what's going on.
                if (node.GetDiagnostics().Any(d => d.Severity == DiagnosticSeverity.Error))
                {
                    return;
                }

                // Check if any wrapper can handle this node.  If so, then we're done, otherwise
                // keep walking up.
                foreach (var wrapper in _wrappers)
                {
                    cancellationToken.ThrowIfCancellationRequested();

                    var computer = await wrapper.TryCreateComputerAsync(
                        document, position, node, cancellationToken).ConfigureAwait(false);

                    if (computer == null)
                    {
                        continue;
                    }

                    var actions = await computer.GetTopLevelCodeActionsAsync().ConfigureAwait(false);

                    if (actions.IsDefaultOrEmpty)
                    {
                        continue;
                    }

                    context.RegisterRefactorings(actions);
                    return;
                }
            }
        }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var document          = context.Document;
            var textSpan          = context.Span;
            var cancellationToken = context.CancellationToken;

            if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles)
            {
                return;
            }

            var actions = await this.GenerateConstructorFromMembersAsync(document, textSpan, cancellationToken).ConfigureAwait(false);

            context.RegisterRefactorings(actions);
        }
Beispiel #22
0
        private static async Task ComputeRefactoringsAsync(
            CodeRefactoringContext context, ExpressionBodyPreference option, bool analyzerActive)
        {
            var document          = context.Document;
            var span              = context.Span;
            var cancellationToken = context.CancellationToken;

            var computationTask = analyzerActive
                ? ComputeOpposingRefactoringsWhenAnalyzerActiveAsync(document, span, option, cancellationToken)
                : ComputeAllRefactoringsWhenAnalyzerInactiveAsync(document, span, cancellationToken);

            var codeActions = await computationTask.ConfigureAwait(false);

            context.RegisterRefactorings(codeActions);
        }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var document          = context.Document;
            var textSpan          = context.Span;
            var cancellationToken = context.CancellationToken;

            if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles)
            {
                return;
            }

            var service = document.GetLanguageService <IIntroduceVariableService>();
            var actions = await service.IntroduceVariableAsync(document, textSpan, cancellationToken).ConfigureAwait(false);

            context.RegisterRefactorings(actions);
        }
Beispiel #24
0
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var (document, textSpan, cancellationToken) = context;
            if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles)
            {
                return;
            }

            var actions = await GenerateEqualsAndGetHashCodeFromMembersAsync(document, textSpan, cancellationToken).ConfigureAwait(false);
            context.RegisterRefactorings(actions);

            if (actions.IsDefaultOrEmpty && textSpan.IsEmpty)
            {
                await HandleNonSelectionAsync(context).ConfigureAwait(false);
            }
        }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var document = context.Document;
            var textSpan = context.Span;
            var cancellationToken = context.CancellationToken;

            if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles)
            {
                return;
            }

            var service = document.GetLanguageService<IGenerateEqualsAndGetHashCodeService>();
            var actions = await service.GenerateEqualsAndGetHashCodeAsync(document, textSpan, cancellationToken).ConfigureAwait(false);
            if (!actions.IsDefault)
            {
                context.RegisterRefactorings(actions);
            }
        }
Beispiel #26
0
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var document          = context.Document;
            var textSpan          = context.Span;
            var cancellationToken = context.CancellationToken;

            if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles)
            {
                return;
            }

            var actions = await this.GenerateConstructorFromMembersAsync(
                document, textSpan, addNullChecks : false, cancellationToken : cancellationToken).ConfigureAwait(false);

            context.RegisterRefactorings(actions);

            if (actions.IsDefaultOrEmpty && textSpan.IsEmpty)
            {
                await HandleNonSelectionAsync(context).ConfigureAwait(false);
            }
        }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var document          = context.Document;
            var textSpan          = context.Span;
            var cancellationToken = context.CancellationToken;

            if (document.Project.Solution.Workspace.Kind == WorkspaceKind.MiscellaneousFiles)
            {
                return;
            }

            var service = document.GetLanguageService <IGenerateEqualsAndGetHashCodeService>();
            var result  = await service.GenerateEqualsAndGetHashCodeAsync(document, textSpan, cancellationToken).ConfigureAwait(false);

            if (!result.ContainsChanges)
            {
                return;
            }

            var actions = result.GetCodeRefactoring(cancellationToken).Actions;

            context.RegisterRefactorings(actions);
        }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var position          = context.Span.Start;
            var document          = context.Document;
            var cancellationToken = context.CancellationToken;

            var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var token         = root.FindToken(position);
            var parameterNode = GetParameterNode(token, position);

            if (parameterNode == null)
            {
                return;
            }

            // Only offered when there isn't a selection, or the selection exactly selects
            // a parameter name.
            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

            if (!context.Span.IsEmpty)
            {
                var parameterName = syntaxFacts.GetNameOfParameter(parameterNode);
                if (parameterName == null || parameterName.Value.Span != context.Span)
                {
                    return;
                }
            }

            var functionDeclaration = parameterNode.FirstAncestorOrSelf <SyntaxNode>(IsFunctionDeclaration);

            if (functionDeclaration == null)
            {
                return;
            }

            var parameterDefault = syntaxFacts.GetDefaultOfParameter(parameterNode);

            // Don't offer inside the "=initializer" of a parameter
            if (parameterDefault?.Span.Contains(position) == true)
            {
                return;
            }

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            // we can't just call GetDeclaredSymbol on functionDeclaration because it could an anonymous function,
            // so first we have to get the parameter symbol and then its containing method symbol
            var parameter = (IParameterSymbol)semanticModel.GetDeclaredSymbol(parameterNode, cancellationToken);

            if (parameter == null || parameter.Name == "")
            {
                return;
            }

            var method = (IMethodSymbol)parameter.ContainingSymbol;

            if (method.IsAbstract ||
                method.IsExtern ||
                method.PartialImplementationPart != null ||
                method.ContainingType.TypeKind == TypeKind.Interface)
            {
                return;
            }

            if (CanOfferRefactoring(functionDeclaration, semanticModel, syntaxFacts, cancellationToken, out var blockStatementOpt))
            {
                // Ok.  Looks like a reasonable parameter to analyze.  Defer to subclass to
                // actually determine if there are any viable refactorings here.
                context.RegisterRefactorings(await GetRefactoringsAsync(
                                                 document, parameter, functionDeclaration, method, blockStatementOpt, cancellationToken).ConfigureAwait(false));
            }
        }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            // Only offered when there isn't a selection.
            if (context.Span.Length > 0)
            {
                return;
            }

            var position          = context.Span.Start;
            var document          = context.Document;
            var cancellationToken = context.CancellationToken;

            var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var token = root.FindToken(position);

            var parameterNode = GetParameterNode(token, position);

            if (parameterNode == null)
            {
                return;
            }

            var functionDeclaration = parameterNode.FirstAncestorOrSelf <SyntaxNode>(IsFunctionDeclaration);

            if (functionDeclaration == null)
            {
                return;
            }

            var syntaxFacts      = document.GetLanguageService <ISyntaxFactsService>();
            var parameterDefault = syntaxFacts.GetDefaultOfParameter(parameterNode);

            // Don't offer inside the "=initializer" of a parameter
            if (parameterDefault?.Span.Contains(position) == true)
            {
                return;
            }

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            // we can't just call GetDeclaredSymbol on functionDeclaration because it could an anonymous function,
            // so first we have to get the parameter symbol and then its containing method symbol
            var parameter = (IParameterSymbol)semanticModel.GetDeclaredSymbol(parameterNode, cancellationToken);

            if (parameter == null || parameter.Name == "")
            {
                return;
            }

            var method = (IMethodSymbol)parameter.ContainingSymbol;

            if (method.IsAbstract ||
                method.IsExtern ||
                method.PartialImplementationPart != null ||
                method.ContainingType.TypeKind == TypeKind.Interface)
            {
                return;
            }

            // We support initializing parameters, even when the containing member doesn't have a
            // body. This is useful for when the user is typing a new constructor and hasn't written
            // the body yet.
            var blockStatementOpt = GetBlockOperation(functionDeclaration, semanticModel, cancellationToken);

            // Ok.  Looks like a reasonable parameter to analyze.  Defer to subclass to
            // actually determine if there are any viable refactorings here.
            context.RegisterRefactorings(await GetRefactoringsAsync(
                                             document, parameter, functionDeclaration, method, blockStatementOpt, cancellationToken).ConfigureAwait(false));
        }
        private async Task HandleNonSelectionAsync(CodeRefactoringContext context)
        {
            var document          = context.Document;
            var textSpan          = context.Span;
            var cancellationToken = context.CancellationToken;

            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();
            var sourceText  = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            // We offer the refactoring when the user is either on the header of a class/struct,
            // or if they're between any members of a class/struct and are on a blank line.
            if (!syntaxFacts.IsOnTypeHeader(root, textSpan.Start) &&
                !syntaxFacts.IsBetweenTypeMembers(sourceText, root, textSpan.Start))
            {
                return;
            }

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            // Only supported on classes/structs.
            var containingType = GetEnclosingNamedType(semanticModel, root, textSpan.Start, cancellationToken);

            if (containingType?.TypeKind != TypeKind.Class && containingType?.TypeKind != TypeKind.Struct)
            {
                return;
            }

            // No overrides in static classes.
            if (containingType.IsStatic)
            {
                return;
            }

            // Find all the possible instance fields/properties.  If there are any, then
            // show a dialog to the user to select the ones they want.
            var viableMembers = containingType.GetMembers().WhereAsArray(IsViableInstanceFieldOrProperty);

            if (viableMembers.Length == 0)
            {
                return;
            }

            GetExistingMemberInfo(
                containingType, out var hasEquals, out var hasGetHashCode);

            var pickMembersOptions = ArrayBuilder <PickMembersOption> .GetInstance();

            var equatableTypeOpt = semanticModel.Compilation.GetTypeByMetadataName(typeof(IEquatable <>).FullName);

            if (equatableTypeOpt != null)
            {
                var constructedType = equatableTypeOpt.Construct(containingType);
                if (!containingType.AllInterfaces.Contains(constructedType))
                {
                    var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

                    var value = options.GetOption(GenerateEqualsAndGetHashCodeFromMembersOptions.ImplementIEquatable);

                    var displayName = constructedType.ToDisplayString(new SymbolDisplayFormat(
                                                                          typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameOnly,
                                                                          genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters));

                    pickMembersOptions.Add(new PickMembersOption(
                                               ImplementIEquatableId,
                                               string.Format(FeaturesResources.Implement_0, displayName),
                                               value));
                }
            }

            if (!HasOperators(containingType))
            {
                var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);

                var value = options.GetOption(GenerateEqualsAndGetHashCodeFromMembersOptions.GenerateOperators);
                pickMembersOptions.Add(new PickMembersOption(
                                           GenerateOperatorsId,
                                           FeaturesResources.Generate_operators,
                                           value));
            }

            var actions = CreateActions(
                document, textSpan, containingType,
                viableMembers, pickMembersOptions.ToImmutableAndFree(),
                hasEquals, hasGetHashCode,
                withDialog: true);

            context.RegisterRefactorings(actions);
        }
Beispiel #31
0
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var(document, textSpan, cancellationToken) = context;
            var position   = context.Span.Start;
            var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var token             = root.FindToken(position);
            var selectedParameter = await context.TryGetRelevantNodeAsync <TParameterSyntax>().ConfigureAwait(false);

            if (selectedParameter == null)
            {
                return;
            }

            var functionDeclaration = selectedParameter.FirstAncestorOrSelf <SyntaxNode>(IsFunctionDeclaration);

            if (functionDeclaration is null)
            {
                return;
            }

            var generator      = SyntaxGenerator.GetGenerator(document);
            var parameterNodes = generator.GetParameters(functionDeclaration);
            var semanticModel  = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var syntaxFacts = document.GetLanguageService <ISyntaxFactsService>();

            // Only offered when there isn't a selection, or the selection exactly selects a parameter name.
            if (!context.Span.IsEmpty)
            {
                var parameterName = syntaxFacts.GetNameOfParameter(selectedParameter);
                if (parameterName == null || parameterName.Value.Span != context.Span)
                {
                    return;
                }
            }

            var parameterDefault = syntaxFacts.GetDefaultOfParameter(selectedParameter);

            // Don't offer inside the "=initializer" of a parameter
            if (parameterDefault?.Span.Contains(position) == true)
            {
                return;
            }

            // we can't just call GetDeclaredSymbol on functionDeclaration because it could an anonymous function,
            // so first we have to get the parameter symbol and then its containing method symbol
            if (!TryGetParameterSymbol(selectedParameter, semanticModel, out var parameter, cancellationToken))
            {
                return;
            }

            var methodSymbol = (IMethodSymbol)parameter.ContainingSymbol;

            if (methodSymbol.IsAbstract ||
                methodSymbol.IsExtern ||
                methodSymbol.PartialImplementationPart != null ||
                methodSymbol.ContainingType.TypeKind == TypeKind.Interface)
            {
                return;
            }

            if (CanOfferRefactoring(functionDeclaration, semanticModel, syntaxFacts, cancellationToken, out var blockStatementOpt))
            {
                // Ok.  Looks like the selected parameter could be refactored. Defer to subclass to
                // actually determine if there are any viable refactorings here.
                context.RegisterRefactorings(await GetRefactoringsForSingleParameterAsync(
                                                 document, parameter, functionDeclaration, methodSymbol, blockStatementOpt, cancellationToken).ConfigureAwait(false));
            }

            // List with parameterNodes that pass all checks
            var listOfPotentiallyValidParametersNodes = ArrayBuilder <SyntaxNode> .GetInstance();

            foreach (var parameterNode in parameterNodes)
            {
                if (!TryGetParameterSymbol(parameterNode, semanticModel, out parameter, cancellationToken))
                {
                    return;
                }

                // Update the list of valid parameter nodes
                listOfPotentiallyValidParametersNodes.Add(parameterNode);
            }

            if (listOfPotentiallyValidParametersNodes.Count > 1)
            {
                // Looks like we can offer a refactoring for more than one parameter. Defer to subclass to
                // actually determine if there are any viable refactorings here.
                context.RegisterRefactorings(await GetRefactoringsForAllParametersAsync(
                                                 document, functionDeclaration, methodSymbol, blockStatementOpt, listOfPotentiallyValidParametersNodes.ToImmutableAndFree(), position, cancellationToken).ConfigureAwait(false));
            }
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var(document, textSpan, cancellationToken) = context;

            // TODO: One could try to retrieve TParameterList and then filter out parameters that intersect with
            // textSpan and use that as `parameterNodes`, where `selectedParameter` would be the first one.

            var selectedParameter = await context.TryGetRelevantNodeAsync <TParameterSyntax>().ConfigureAwait(false);

            if (selectedParameter == null)
            {
                return;
            }

            var functionDeclaration = selectedParameter.FirstAncestorOrSelf(_isFunctionDeclarationFunc);

            if (functionDeclaration is null)
            {
                return;
            }

            var generator      = SyntaxGenerator.GetGenerator(document);
            var parameterNodes = generator.GetParameters(functionDeclaration);
            var semanticModel  = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var syntaxFacts = document.GetRequiredLanguageService <ISyntaxFactsService>();

            // we can't just call GetDeclaredSymbol on functionDeclaration because it could an anonymous function,
            // so first we have to get the parameter symbol and then its containing method symbol
            if (!TryGetParameterSymbol(selectedParameter, semanticModel, out var parameter, cancellationToken))
            {
                return;
            }

            var methodSymbol = (IMethodSymbol)parameter.ContainingSymbol;

            if (methodSymbol.IsAbstract ||
                methodSymbol.IsExtern ||
                methodSymbol.PartialImplementationPart != null ||
                methodSymbol.ContainingType.TypeKind == TypeKind.Interface)
            {
                return;
            }

            if (CanOfferRefactoring(functionDeclaration, semanticModel, syntaxFacts, cancellationToken, out var blockStatementOpt))
            {
                // Ok.  Looks like the selected parameter could be refactored. Defer to subclass to
                // actually determine if there are any viable refactorings here.
                var refactorings = await GetRefactoringsForSingleParameterAsync(
                    document, parameter, functionDeclaration, methodSymbol, blockStatementOpt, cancellationToken).ConfigureAwait(false);

                context.RegisterRefactorings(refactorings, context.Span);
            }

            // List with parameterNodes that pass all checks
            using var _ = ArrayBuilder <SyntaxNode> .GetInstance(out var listOfPotentiallyValidParametersNodes);

            foreach (var parameterNode in parameterNodes)
            {
                if (!TryGetParameterSymbol(parameterNode, semanticModel, out parameter, cancellationToken))
                {
                    return;
                }

                // Update the list of valid parameter nodes
                listOfPotentiallyValidParametersNodes.Add(parameterNode);
            }

            if (listOfPotentiallyValidParametersNodes.Count > 1)
            {
                // Looks like we can offer a refactoring for more than one parameter. Defer to subclass to
                // actually determine if there are any viable refactorings here.
                var refactorings = await GetRefactoringsForAllParametersAsync(
                    document, functionDeclaration, methodSymbol, blockStatementOpt,
                    listOfPotentiallyValidParametersNodes.ToImmutable(), selectedParameter.Span, cancellationToken).ConfigureAwait(false);

                context.RegisterRefactorings(refactorings, context.Span);
            }

            return;
        public override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            // Only offered when there isn't a selection.
            if (context.Span.Length > 0)
            {
                return;
            }

            var position          = context.Span.Start;
            var document          = context.Document;
            var cancellationToken = context.CancellationToken;

            var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var token = root.FindToken(position);

            var parameterNode = GetParameterNode(token, position);

            if (parameterNode == null)
            {
                return;
            }

            var containingMember = parameterNode.FirstAncestorOrSelf <TMemberDeclarationSyntax>();

            if (containingMember == null)
            {
                return;
            }

            var syntaxFacts      = document.GetLanguageService <ISyntaxFactsService>();
            var parameterDefault = syntaxFacts.GetDefaultOfParameter(parameterNode);

            // Don't offer inside the "=initializer" of a parameter
            if (parameterDefault?.Span.Contains(position) == true)
            {
                return;
            }

            var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);

            var method = (IMethodSymbol)semanticModel.GetDeclaredSymbol(containingMember, cancellationToken);

            if (method.IsAbstract ||
                method.IsExtern ||
                method.PartialImplementationPart != null ||
                method.ContainingType.TypeKind == TypeKind.Interface)
            {
                return;
            }

            var parameter = (IParameterSymbol)semanticModel.GetDeclaredSymbol(parameterNode, cancellationToken);

            if (!method.Parameters.Contains(parameter))
            {
                return;
            }

            if (parameter.Name == "")
            {
                return;
            }

            // Only offered on method-like things that have a body (i.e. non-interface/non-abstract).
            var bodyOpt = GetBody(containingMember);

            // We support initializing parameters, even when the containing member doesn't have a
            // body. This is useful for when the user is typing a new constructor and hasn't written
            // the body yet.
            var blockStatementOpt = default(IBlockOperation);

            if (bodyOpt != null)
            {
                blockStatementOpt = semanticModel.GetOperation(bodyOpt, cancellationToken) as IBlockOperation;
                if (blockStatementOpt == null)
                {
                    return;
                }
            }

            // Ok.  Looks like a reasonable parameter to analyze.  Defer to subclass to
            // actually determine if there are any viable refactorings here.
            context.RegisterRefactorings(await GetRefactoringsAsync(
                                             document, parameter, containingMember, blockStatementOpt, cancellationToken).ConfigureAwait(false));
        }
 public sealed override async Task ComputeRefactoringsAsync(CodeRefactoringContext context)
 {
     var service = context.Document.GetLanguageService<AbstractEncapsulateFieldService>();
     var actions = await service.GetEncapsulateFieldCodeActionsAsync(context.Document, context.Span, context.CancellationToken).ConfigureAwait(false);
     context.RegisterRefactorings(actions);
 }