Skip to content

Commit

Permalink
Update RenameToUpperCaseCodeFixProvider to support conflict resolution
Browse files Browse the repository at this point in the history
Fixes #437
  • Loading branch information
sharwell committed Nov 27, 2015
1 parent fe6e43c commit 206218e
Showing 1 changed file with 40 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ namespace StyleCop.Analyzers.NamingRules
[Shared]
internal class RenameToUpperCaseCodeFixProvider : CodeFixProvider
{
/// <summary>
/// During conflict resolution for fields, this suffix is tried before falling back to 1, 2, 3, etc...
/// </summary>
private const string Suffix = "Value";

/// <inheritdoc/>
Expand All @@ -52,7 +55,8 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
foreach (var diagnostic in context.Diagnostics)
{
var token = root.FindToken(diagnostic.Location.SourceSpan.Start);
var newName = char.ToUpper(token.ValueText[0]) + token.ValueText.Substring(1);
var baseName = char.ToUpper(token.ValueText[0]) + token.ValueText.Substring(1);
var newName = baseName;
var memberSyntax = this.GetParentTypeDeclaration(token);

if (memberSyntax is NamespaceDeclarationSyntax)
Expand All @@ -62,9 +66,9 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
IdentifierNameSyntax identifierSyntax = (IdentifierNameSyntax)token.Parent;

var newIdentifierSyntac = identifierSyntax.WithIdentifier(SyntaxFactory.Identifier(newName));
var newIdentifierSyntax = identifierSyntax.WithIdentifier(SyntaxFactory.Identifier(newName));

var newRoot = root.ReplaceNode(identifierSyntax, newIdentifierSyntac);
var newRoot = root.ReplaceNode(identifierSyntax, newIdentifierSyntax);
return Task.FromResult(context.Document.WithSyntaxRoot(newRoot));
};

Expand All @@ -79,59 +83,70 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
SemanticModel semanticModel = await document.GetSemanticModelAsync(context.CancellationToken).ConfigureAwait(false);

var typeDeclarationSymbol = semanticModel.GetDeclaredSymbol(memberSyntax);
if (typeDeclarationSymbol == null)
var declaredSymbol = semanticModel.GetDeclaredSymbol(memberSyntax);
if (declaredSymbol == null)
{
continue;
}

if (!this.IsValidNewMemberName(typeDeclarationSymbol, newName))
bool usedSuffix = false;
if (declaredSymbol.Kind == SymbolKind.Field && !IsValidNewMemberName(semanticModel, declaredSymbol, newName))
{
usedSuffix = true;
newName = newName + Suffix;
}

int index = 0;
while (!IsValidNewMemberName(semanticModel, declaredSymbol, newName))
{
usedSuffix = false;
index++;
newName = baseName + index;
}

context.RegisterCodeFix(
CodeAction.Create(
string.Format(NamingResources.RenameToCodeFix, newName),
cancellationToken => RenameHelper.RenameSymbolAsync(document, root, token, newName, cancellationToken),
nameof(RenameToUpperCaseCodeFixProvider) + "_" + diagnostic.Id),
nameof(RenameToUpperCaseCodeFixProvider) + "_" + diagnostic.Id + "_" + usedSuffix + "_" + index),
diagnostic);
}
}
}

private bool IsValidNewMemberName(ISymbol typeSymbol, string name)
private static bool IsValidNewMemberName(SemanticModel semanticModel, ISymbol symbol, string name)
{
if (typeSymbol == null)
{
throw new ArgumentNullException(nameof(typeSymbol));
}
else if (typeSymbol.Name == name)
var members = (symbol as INamedTypeSymbol)?.GetMembers(name);
if (members.HasValue && !members.Value.IsDefaultOrEmpty)
{
return false;
}

var members = (typeSymbol as INamedTypeSymbol)?.GetMembers(name);
if (members.HasValue && !members.Value.IsDefaultOrEmpty)
var containingSymbol = symbol.ContainingSymbol as INamespaceOrTypeSymbol;
if (containingSymbol == null)
{
return false;
return true;
}

var containingType = typeSymbol.ContainingSymbol as INamedTypeSymbol;
if (containingType != null)
if (containingSymbol.Kind == SymbolKind.Namespace)
{
// Make sure to use the compilation namespace so interfaces in referenced assemblies are considered
containingSymbol = semanticModel.Compilation.GetCompilationNamespace((INamespaceSymbol)containingSymbol);
}
else if (containingSymbol.Kind == SymbolKind.NamedType)
{
// The name can't be the same as the name of the containing type
if (containingType.Name == name)
if (containingSymbol.Name == name)
{
return false;
}
}

// The name can't be the same as the name of an other member of the same type
members = containingType.GetMembers(name);
if (!members.Value.IsDefaultOrEmpty)
{
return false;
}
// The name can't be the same as the name of an other member of the same type
members = containingSymbol.GetMembers(name);
if (!members.Value.IsDefaultOrEmpty)
{
return false;
}

return true;
Expand Down

0 comments on commit 206218e

Please sign in to comment.