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())); }
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)); } } } } } }
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)); } } } } }