internal static async Task RenameIdentifierAccordingToTypeNameAsync(
            RefactoringContext context,
            ForEachStatementSyntax forEachStatement)
        {
            if (forEachStatement.Type != null &&
                forEachStatement.Identifier.Span.Contains(context.Span))
            {
                SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                string oldName = forEachStatement.Identifier.ValueText;

                ITypeSymbol typeSymbol = semanticModel.GetTypeInfo(forEachStatement.Type, context.CancellationToken).Type;

                if (typeSymbol?.IsErrorType() == false)
                {
                    string newName = SyntaxUtility.CreateIdentifier(
                        typeSymbol,
                        firstCharToLower: true);

                    if (!string.IsNullOrEmpty(newName) &&
                        !string.Equals(newName, oldName, StringComparison.Ordinal))
                    {
                        ISymbol symbol = semanticModel.GetDeclaredSymbol(forEachStatement, context.CancellationToken);

                        context.RegisterRefactoring(
                            $"Rename variable to '{newName}'",
                            cancellationToken => SymbolRenamer.RenameAsync(context.Document, symbol, newName, cancellationToken));
                    }
                }
            }
        }
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            VariableDeclaratorSyntax declarator = root
                                                  .FindNode(context.Span, getInnermostNodeForTie: true)?
                                                  .FirstAncestorOrSelf <VariableDeclaratorSyntax>();

            if (declarator == null)
            {
                return;
            }

            if (context.Document.SupportsSemanticModel)
            {
                SemanticModel semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);

                ISymbol symbol = semanticModel.GetDeclaredSymbol(declarator, context.CancellationToken);

                string newName = TextUtility.ToCamelCaseWithUnderscore(declarator.Identifier.ValueText);

                CodeAction codeAction = CodeAction.Create(
                    $"Rename field to '{newName}'",
                    cancellationToken => SymbolRenamer.RenameAsync(context.Document, symbol, newName, cancellationToken),
                    DiagnosticIdentifiers.RenamePrivateFieldAccordingToCamelCaseWithUnderscore);

                context.RegisterCodeFix(codeAction, context.Diagnostics);
            }
        }
    /// <summary>
    /// Renames symbols in a CSharp project so that they don't clash on case within the same named scope, attempting to rename the least public ones first.
    /// This is because C# is case sensitive but VB is case insensitive.
    /// </summary>
    /// <remarks>
    /// Cases in different named scopes should be dealt with by <seealso cref="DocumentExtensions.ExpandAsync"/>.
    /// For names scoped within a type member, see <seealso cref="SemanticModelSymbolSetExtensions.GetCsLocalSymbolsPerScope"/>.
    /// </remarks>
    public static async Task <Project> RenameClashingSymbolsAsync(Project project)
    {
        var compilation = await project.GetCompilationAsync();

        var memberRenames = SymbolRenamer.GetNamespacesAndTypesInAssembly(project, compilation)
                            .SelectMany(x => GetSymbolsWithNewNames(x, compilation));

        return(await SymbolRenamer.PerformRenamesAsync(project, memberRenames.ToList()));
    }
Beispiel #4
0
        public static async Task ComputeRefactoringsAsync(RefactoringContext context, ParameterSyntax parameter)
        {
            if (!context.IsAnyRefactoringEnabled(
                    RefactoringIdentifiers.AddParameterNameToParameter,
                    RefactoringIdentifiers.RenameParameterAccordingToTypeName))
            {
                return;
            }

            SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

            IParameterSymbol parameterSymbol = semanticModel.GetDeclaredSymbol(parameter, context.CancellationToken);

            if (parameterSymbol?.Type == null)
            {
                return;
            }

            if (parameter.Identifier.IsMissing)
            {
                if (context.IsRefactoringEnabled(RefactoringIdentifiers.AddParameterNameToParameter))
                {
                    TextSpan span = (parameter.Type != null)
                        ? TextSpan.FromBounds(parameter.Type.Span.End, parameter.Span.End)
                        : parameter.Span;

                    if (span.Contains(context.Span))
                    {
                        string name = SyntaxUtility.CreateIdentifier(parameterSymbol.Type, firstCharToLower: true);

                        if (!string.IsNullOrEmpty(name))
                        {
                            context.RegisterRefactoring(
                                $"Add parameter name '{name}'",
                                cancellationToken => AddParameterNameToParameterAsync(context.Document, parameter, name, cancellationToken));
                        }
                    }
                }
            }
            else if (context.IsRefactoringEnabled(RefactoringIdentifiers.RenameParameterAccordingToTypeName) &&
                     parameter.Identifier.Span.Contains(context.Span))
            {
                string name    = parameter.Identifier.ValueText;
                string newName = SyntaxUtility.CreateIdentifier(parameterSymbol.Type, firstCharToLower: true);

                if (!string.IsNullOrEmpty(newName) &&
                    !string.Equals(name, newName, StringComparison.Ordinal))
                {
                    ISymbol symbol = semanticModel.GetDeclaredSymbol(parameter, context.CancellationToken);

                    context.RegisterRefactoring(
                        $"Rename parameter to '{newName}'",
                        cancellationToken => SymbolRenamer.RenameAsync(context.Document, symbol, newName, cancellationToken));
                }
            }
        }
        private static IEnumerable <(ISymbol Original, string NewName)> GetUniqueNamesForSymbolSet(IEnumerable <ISymbol> symbols)
        {
            var membersByCaseInsensitiveName = symbols.ToLookup(SymbolRenamer.GetName, m => m, StringComparer.OrdinalIgnoreCase);
            var names = new HashSet <string>(membersByCaseInsensitiveName.Select(ms => ms.Key),
                                             StringComparer.OrdinalIgnoreCase);
            var symbolsWithNewNames = membersByCaseInsensitiveName.Where(ms => ms.Count() > 1)
                                      .SelectMany(symbolGroup => SymbolRenamer.GetSymbolsWithNewNames(symbolGroup.ToArray(), names, false));

            return(symbolsWithNewNames);
        }
    private static IEnumerable <(ISymbol Original, string NewName)> GetUniqueNamesForSymbolSet(IEnumerable <ISymbol> symbols)
    {
#pragma warning disable RS1024 // Compare symbols correctly - analyzer bug, I'm using a string not the default ambiguous comparer
        var membersByCaseInsensitiveName = symbols.ToLookup(SymbolRenamer.GetName, StringComparer.OrdinalIgnoreCase);
#pragma warning restore RS1024 // Compare symbols correctly
        var names = new HashSet <string>(membersByCaseInsensitiveName.Select(ms => ms.Key),
                                         StringComparer.OrdinalIgnoreCase);
        var symbolsWithNewNames = membersByCaseInsensitiveName.Where(ms => ms.Count() > 1)
                                  .SelectMany(symbolGroup => SymbolRenamer.GetSymbolsWithNewNames(symbolGroup.ToArray(), names, false));
        return(symbolsWithNewNames);
    }
    private static IEnumerable <(ISymbol Original, string NewName)> GetSymbolsWithNewNames(INamespaceOrTypeSymbol containerSymbol, Compilation compilation)
    {
        if (containerSymbol.IsNamespace)
        {
            return(Enumerable.Empty <(ISymbol Original, string NewName)>());
        }

        var members = containerSymbol.GetMembers()
                      .Where(m => m.Locations.Any(loc => loc.SourceTree != null && compilation.ContainsSyntaxTree(loc.SourceTree)))
                      .Where(s => containerSymbol.Name == s.Name || containerSymbol is INamedTypeSymbol nt && nt.IsEnumType() && SymbolRenamer.GetName(s).StartsWith(containerSymbol.Name, StringComparison.InvariantCulture));
        var symbolSet = containerSymbol.Yield().Concat(members).ToArray();

        return(SymbolRenamer.GetSymbolsWithNewNames(symbolSet, new HashSet <string>(symbolSet.Select(SymbolRenamer.GetName)), true));
    }
        private static async Task RenameFieldAccordingToPropertyNameAsync(
            RefactoringContext context,
            IdentifierNameSyntax identifierName)
        {
            if (!identifierName.IsQualified() ||
                identifierName.IsQualifiedWithThis())
            {
                PropertyDeclarationSyntax propertyDeclaration = identifierName.FirstAncestor <PropertyDeclarationSyntax>();

                if (propertyDeclaration != null)
                {
                    SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                    var fieldSymbol = semanticModel
                                      .GetSymbolInfo(identifierName, context.CancellationToken)
                                      .Symbol as IFieldSymbol;

                    if (fieldSymbol?.IsPrivate() == true)
                    {
                        IPropertySymbol propertySymbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, context.CancellationToken);

                        if (propertySymbol != null &&
                            fieldSymbol.IsStatic == propertySymbol.IsStatic &&
                            object.Equals(fieldSymbol.ContainingType, propertySymbol.ContainingType))
                        {
                            string newName = TextUtility.ToCamelCase(propertySymbol.Name, context.Settings.PrefixFieldIdentifierWithUnderscore);

                            if (!string.Equals(newName, fieldSymbol.Name, StringComparison.Ordinal))
                            {
                                string fieldName = identifierName.Identifier.ValueText;

                                context.RegisterRefactoring(
                                    $"Rename field to '{newName}'",
                                    cancellationToken =>
                                {
                                    return(SymbolRenamer.RenameAsync(
                                               context.Document,
                                               fieldSymbol,
                                               newName,
                                               cancellationToken));
                                });
                            }
                        }
                    }
                }
            }
        }
        private static async Task RegisterCodeFixAsync(
            CodeFixContext context,
            ClassDeclarationSyntax classDeclaration,
            Diagnostic diagnostic)
        {
            SemanticModel semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);

            ISymbol symbol = semanticModel.GetDeclaredSymbol(classDeclaration, context.CancellationToken);

            string newName = classDeclaration.Identifier.ValueText + GetSuffix(diagnostic);

            CodeAction codeAction = CodeAction.Create(
                $"Rename class to '{newName}'",
                cancellationToken => SymbolRenamer.RenameAsync(context.Document, symbol, newName, cancellationToken),
                DiagnosticIdentifiers.AddCodeFixProviderSuffix);

            context.RegisterCodeFix(codeAction, diagnostic);
        }
        private static async Task RenameVariableAccordingToTypeNameAsync(
            RefactoringContext context,
            VariableDeclarationSyntax variableDeclaration)
        {
            if (variableDeclaration.Type != null &&
                variableDeclaration.Parent?.IsKind(SyntaxKind.EventFieldDeclaration) == false &&
                variableDeclaration.Variables.Count == 1 &&
                variableDeclaration.Variables[0].Identifier.Span.Contains(context.Span))
            {
                SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                ISymbol symbol = semanticModel.GetDeclaredSymbol(variableDeclaration.Variables[0], context.CancellationToken);

                if (symbol != null)
                {
                    ITypeSymbol typeSymbol = semanticModel.GetTypeInfo(variableDeclaration.Type, context.CancellationToken).Type;

                    if (typeSymbol?.IsErrorType() == false)
                    {
                        string newName = SyntaxUtility.CreateIdentifier(
                            typeSymbol,
                            FirstCharToLower(symbol));

                        if (!string.IsNullOrEmpty(newName))
                        {
                            if (context.Settings.PrefixFieldIdentifierWithUnderscore &&
                                symbol.IsField() &&
                                symbol.IsPrivate() &&
                                !((IFieldSymbol)symbol).IsConst)
                            {
                                newName = TextUtility.ToCamelCaseWithUnderscore(newName);
                            }

                            if (!string.Equals(variableDeclaration.Variables[0].Identifier.ValueText, newName, StringComparison.Ordinal))
                            {
                                context.RegisterRefactoring(
                                    $"Rename {GetName(symbol)} to '{newName}'",
                                    cancellationToken => SymbolRenamer.RenameAsync(context.Document, symbol, newName, cancellationToken));
                            }
                        }
                    }
                }
            }
        }
Beispiel #11
0
        public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            SyntaxNode root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);

            MethodDeclarationSyntax methodDeclaration = root
                                                        .FindNode(context.Span, getInnermostNodeForTie: true)?
                                                        .FirstAncestorOrSelf <MethodDeclarationSyntax>();

            if (methodDeclaration != null &&
                context.Document.SupportsSemanticModel)
            {
                SemanticModel semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);

                IMethodSymbol methodSymbol = semanticModel.GetDeclaredSymbol(methodDeclaration, context.CancellationToken);

                if (methodSymbol != null)
                {
                    foreach (Diagnostic diagnostic in context.Diagnostics)
                    {
                        switch (diagnostic.Id)
                        {
                        case DiagnosticIdentifiers.AsynchronousMethodNameShouldEndWithAsync:
                        case DiagnosticIdentifiers.NonAsynchronousMethodNameShouldNotEndWithAsync:
                        {
                            string name    = methodDeclaration.Identifier.ValueText;
                            string newName = GetNewName(methodDeclaration, diagnostic);

                            CodeAction codeAction = CodeAction.Create(
                                $"Rename method to '{newName}'",
                                cancellationToken => SymbolRenamer.RenameAsync(context.Document, methodSymbol, newName, cancellationToken),
                                diagnostic.Id + EquivalenceKeySuffix);

                            context.RegisterCodeFix(codeAction, diagnostic);

                            break;
                        }
                        }
                    }
                }
            }
        }
        private static async Task RenameMethodAccoringToTypeNameAsync(
            RefactoringContext context,
            MethodDeclarationSyntax methodDeclaration)
        {
            if (context.IsRefactoringEnabled(RefactoringIdentifiers.RenameMethodAccordingToTypeName) &&
                context.SupportsSemanticModel &&
                methodDeclaration.ReturnType?.IsVoid() == false &&
                methodDeclaration.Identifier.Span.Contains(context.Span))
            {
                SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                IMethodSymbol methodSymbol = semanticModel.GetDeclaredSymbol(methodDeclaration, context.CancellationToken);

                ITypeSymbol typeSymbol = GetType(methodDeclaration.ReturnType, semanticModel, context.CancellationToken);

                if (typeSymbol != null)
                {
                    string newName = SyntaxUtility.CreateIdentifier(typeSymbol);

                    if (!string.IsNullOrEmpty(newName))
                    {
                        newName = "Get" + newName;

                        if (methodSymbol.IsAsync)
                        {
                            newName += "Async";
                        }

                        if (!string.Equals(newName, methodDeclaration.Identifier.ValueText, StringComparison.Ordinal))
                        {
                            context.RegisterRefactoring(
                                $"Rename method to '{newName}'",
                                cancellationToken => SymbolRenamer.RenameAsync(context.Document, methodSymbol, newName, cancellationToken));
                        }
                    }
                }
            }
        }
        public static async Task ComputeRefactoringsAsync(RefactoringContext context, PropertyDeclarationSyntax propertyDeclaration)
        {
            if (context.IsRefactoringEnabled(RefactoringIdentifiers.MarkMemberAsStatic) &&
                propertyDeclaration.Span.Contains(context.Span) &&
                MarkMemberAsStaticRefactoring.CanRefactor(propertyDeclaration))
            {
                context.RegisterRefactoring(
                    "Mark property as static",
                    cancellationToken => MarkMemberAsStaticRefactoring.RefactorAsync(context.Document, propertyDeclaration, cancellationToken));

                MarkAllMembersAsStaticRefactoring.RegisterRefactoring(context, (ClassDeclarationSyntax)propertyDeclaration.Parent);
            }

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.ReplacePropertyWithMethod) &&
                propertyDeclaration.HeaderSpan().Contains(context.Span) &&
                ReplacePropertyWithMethodRefactoring.CanRefactor(context, propertyDeclaration))
            {
                string propertyName = propertyDeclaration.Identifier.ValueText;

                string title = $"Replace '{propertyName}' with method";

                if (propertyDeclaration.AccessorList.Accessors.Count > 1)
                {
                    title += "s";
                }

                context.RegisterRefactoring(
                    title,
                    cancellationToken => ReplacePropertyWithMethodRefactoring.RefactorAsync(context.Document, propertyDeclaration, cancellationToken));
            }

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.UseExpressionBodiedMember) &&
                propertyDeclaration.AccessorList?.Span.Contains(context.Span) == true &&
                context.SupportsCSharp6 &&
                UseExpressionBodiedMemberRefactoring.CanRefactor(propertyDeclaration))
            {
                context.RegisterRefactoring(
                    "Use expression-bodied member",
                    cancellationToken => UseExpressionBodiedMemberRefactoring.RefactorAsync(context.Document, propertyDeclaration, cancellationToken));
            }

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.RemovePropertyInitializer) &&
                RemovePropertyInitializerRefactoring.CanRefactor(context, propertyDeclaration))
            {
                context.RegisterRefactoring(
                    "Remove property initializer",
                    cancellationToken => RemovePropertyInitializerRefactoring.RefactorAsync(context.Document, propertyDeclaration, cancellationToken));
            }

            if (context.SupportsSemanticModel)
            {
                if (context.IsAnyRefactoringEnabled(
                        RefactoringIdentifiers.ExpandProperty,
                        RefactoringIdentifiers.ExpandPropertyAndAddBackingField) &&
                    propertyDeclaration.Span.Contains(context.Span) &&
                    ExpandPropertyRefactoring.CanRefactor(propertyDeclaration))
                {
                    if (context.IsRefactoringEnabled(RefactoringIdentifiers.ExpandProperty))
                    {
                        context.RegisterRefactoring(
                            "Expand property",
                            cancellationToken => ExpandPropertyRefactoring.RefactorAsync(context.Document, propertyDeclaration, cancellationToken));
                    }

                    if (context.IsRefactoringEnabled(RefactoringIdentifiers.ExpandPropertyAndAddBackingField))
                    {
                        context.RegisterRefactoring(
                            "Expand property and add backing field",
                            cancellationToken => ExpandPropertyAndAddBackingFieldRefactoring.RefactorAsync(context.Document, propertyDeclaration, context.Settings.PrefixFieldIdentifierWithUnderscore, cancellationToken));
                    }
                }

                if (context.IsRefactoringEnabled(RefactoringIdentifiers.NotifyPropertyChanged) &&
                    await NotifyPropertyChangedRefactoring.CanRefactorAsync(context, propertyDeclaration).ConfigureAwait(false))
                {
                    context.RegisterRefactoring(
                        "Notify property changed",
                        cancellationToken =>
                    {
                        return(NotifyPropertyChangedRefactoring.RefactorAsync(
                                   context.Document,
                                   propertyDeclaration,
                                   context.SupportsCSharp6,
                                   cancellationToken));
                    });
                }
            }

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.MakeMemberAbstract) &&
                propertyDeclaration.HeaderSpan().Contains(context.Span) &&
                MakeMemberAbstractRefactoring.CanRefactor(propertyDeclaration))
            {
                context.RegisterRefactoring(
                    "Make property abstract",
                    cancellationToken => MakeMemberAbstractRefactoring.RefactorAsync(context.Document, propertyDeclaration, cancellationToken));
            }

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.CopyDocumentationCommentFromBaseMember) &&
                propertyDeclaration.HeaderSpan().Contains(context.Span))
            {
                await CopyDocumentationCommentFromBaseMemberRefactoring.ComputeRefactoringAsync(context, propertyDeclaration).ConfigureAwait(false);
            }

            if (context.IsRefactoringEnabled(RefactoringIdentifiers.RenamePropertyAccordingToTypeName) &&
                context.SupportsSemanticModel &&
                propertyDeclaration.Type != null &&
                propertyDeclaration.Identifier.Span.Contains(context.Span))
            {
                SemanticModel semanticModel = await context.GetSemanticModelAsync().ConfigureAwait(false);

                ITypeSymbol typeSymbol = semanticModel
                                         .GetTypeInfo(propertyDeclaration.Type, context.CancellationToken)
                                         .Type;

                if (typeSymbol?.IsErrorType() == false)
                {
                    string newName = SyntaxUtility.CreateIdentifier(typeSymbol);

                    if (!string.IsNullOrEmpty(newName))
                    {
                        newName = TextUtility.FirstCharToUpper(newName);

                        if (!string.Equals(newName, propertyDeclaration.Identifier.ValueText, StringComparison.Ordinal))
                        {
                            ISymbol symbol = semanticModel.GetDeclaredSymbol(propertyDeclaration, context.CancellationToken);

                            context.RegisterRefactoring(
                                $"Rename property to '{newName}'",
                                cancellationToken => SymbolRenamer.RenameAsync(context.Document, symbol, newName, cancellationToken));
                        }
                    }
                }
            }
        }