Skip to content

Commit

Permalink
Fix Add/inline using static directive (RR0014, RR0180) (#988)
Browse files Browse the repository at this point in the history
  • Loading branch information
josefpihrt committed Nov 15, 2022
1 parent f30b281 commit fe9ec66
Show file tree
Hide file tree
Showing 8 changed files with 249 additions and 38 deletions.
2 changes: 2 additions & 0 deletions ChangeLog.md
Expand Up @@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

- Fix ([RCS1080](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RCS1080.md)) when collection is derived from `List<T>` ([#986](https://github.com/josefpihrt/roslynator/pull/986).
- Fix retrieving of trusted platform assemblies - separator differs by OS ([#987](https://github.com/josefpihrt/roslynator/pull/987).
- Fix refactoring ([RR0014](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RR0014.md)) ([#988](https://github.com/josefpihrt/roslynator/pull/988).
- Fix refactoring ([RR0180](https://github.com/JosefPihrt/Roslynator/blob/main/docs/analyzers/RR0180.md)) ([#988](https://github.com/josefpihrt/roslynator/pull/988).

## [4.1.2] - 2022-10-31

Expand Down
Expand Up @@ -18,24 +18,36 @@ public static async Task ComputeRefactoringsAsync(RefactoringContext context, Me
if (memberAccess.Name?.IsMissing != false)
return;

memberAccess = GetTopmostMemberAccessExpression(memberAccess);
if (context.Span.IsBetweenSpans(memberAccess))
{
if (memberAccess.IsParentKind(SyntaxKind.SimpleMemberAccessExpression))
memberAccess = (MemberAccessExpressionSyntax)memberAccess.Parent;
}

if (!context.Span.IsBetweenSpans(memberAccess.Expression))
{
return;
}

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

var typeSymbol = semanticModel.GetSymbol(memberAccess.Expression, context.CancellationToken) as INamedTypeSymbol;

if (typeSymbol?.TypeKind != TypeKind.Class)
if (semanticModel.GetSymbol(memberAccess.Expression, context.CancellationToken) is not INamedTypeSymbol typeSymbol)
{
return;
}

if (!typeSymbol.IsStatic)
if (typeSymbol.TypeKind != TypeKind.Class
&& typeSymbol.TypeKind != TypeKind.Struct)
{
return;
}

if (!typeSymbol.DeclaredAccessibility.Is(Accessibility.Public, Accessibility.Internal))
return;

if (semanticModel.GetSymbol(memberAccess.Name, context.CancellationToken)?.IsStatic != true)
return;

if (CSharpUtility.IsStaticClassInScope(memberAccess, typeSymbol, semanticModel, context.CancellationToken))
return;

Expand Down
Expand Up @@ -56,7 +56,8 @@ internal static class InlineUsingStaticDirectiveRefactoring

foreach (SyntaxNode descendant in node.DescendantNodes())
{
if (!descendant.IsParentKind(SyntaxKind.SimpleMemberAccessExpression)
if ((!descendant.IsParentKind(SyntaxKind.SimpleMemberAccessExpression)
|| ((MemberAccessExpressionSyntax)descendant.Parent).Name != descendant)
&& (descendant is SimpleNameSyntax name))
{
ISymbol symbol = semanticModel.GetSymbol(name, cancellationToken);
Expand Down

This file was deleted.

This file was deleted.

Expand Up @@ -6,7 +6,7 @@

namespace Roslynator.CSharp.Refactorings.Tests
{
public class RR0014AddUsingDirectiveTests : AbstractCSharpRefactoringVerifier
public class RR0013AddUsingDirectiveTests : AbstractCSharpRefactoringVerifier
{
public override string RefactoringId { get; } = RefactoringIdentifiers.AddUsingDirective;

Expand Down
163 changes: 163 additions & 0 deletions src/Tests/Refactorings.Tests/RR0014AddUsingStaticDirectiveTests.cs
@@ -0,0 +1,163 @@
// Copyright (c) Josef Pihrt and Contributors. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.

using System.Threading.Tasks;
using Roslynator.Testing.CSharp;
using Xunit;

namespace Roslynator.CSharp.Refactorings.Tests
{
public class RR0014AddUsingStaticDirectiveTests : AbstractCSharpRefactoringVerifier
{
public override string RefactoringId { get; } = RefactoringIdentifiers.AddUsingStaticDirective;

[Fact, Trait(Traits.Refactoring, RefactoringIdentifiers.AddUsingStaticDirective)]
public async Task Test_Math_Max()
{
await VerifyRefactoringAsync(@"
using System;
class C
{
void M()
{
int max = [|Math|].Max(1, 2);
}
}
", @"
using System;
using static System.Math;
class C
{
void M()
{
int max = Max(1, 2);
}
}
", equivalenceKey: EquivalenceKey.Create(RefactoringId));
}

[Fact, Trait(Traits.Refactoring, RefactoringIdentifiers.AddUsingStaticDirective)]
public async Task Test_Math_Max2()
{
await VerifyRefactoringAsync(@"
class C
{
void M()
{
int max = [|System.Math|].Max(1, 2);
}
}
", @"using static System.Math;
class C
{
void M()
{
int max = Max(1, 2);
}
}
", equivalenceKey: EquivalenceKey.Create(RefactoringId));
}

[Fact, Trait(Traits.Refactoring, RefactoringIdentifiers.AddUsingStaticDirective)]
public async Task Test_Math_Max3()
{
await VerifyRefactoringAsync(@"
class C
{
void M()
{
int max = [|global::System.Math|].Max(1, 2);
}
}
", @"using static System.Math;
class C
{
void M()
{
int max = Max(1, 2);
}
}
", equivalenceKey: EquivalenceKey.Create(RefactoringId));
}

[Fact, Trait(Traits.Refactoring, RefactoringIdentifiers.AddUsingStaticDirective)]
public async Task Test_SimpleMemberAccessExpression()
{
await VerifyRefactoringAsync(@"
using System;
class C
{
void M()
{
var x = [|StringComparer|].CurrentCulture.GetHashCode();
}
}
", @"
using System;
using static System.StringComparer;
class C
{
void M()
{
var x = CurrentCulture.GetHashCode();
}
}
", equivalenceKey: EquivalenceKey.Create(RefactoringId));
}

[Fact, Trait(Traits.Refactoring, RefactoringIdentifiers.AddUsingStaticDirective)]
public async Task Test_SimpleMemberAccessExpression2()
{
await VerifyRefactoringAsync(@"
class C
{
void M()
{
var x = [|System.StringComparer|].CurrentCulture.GetHashCode();
}
}
", @"using static System.StringComparer;
class C
{
void M()
{
var x = CurrentCulture.GetHashCode();
}
}
", equivalenceKey: EquivalenceKey.Create(RefactoringId));
}

[Fact, Trait(Traits.Refactoring, RefactoringIdentifiers.AddUsingStaticDirective)]
public async Task Test_Struct()
{
await VerifyRefactoringAsync(@"
using System;
class C
{
void M()
{
var x = [|TimeSpan|].Zero;
}
}
", @"
using System;
using static System.TimeSpan;
class C
{
void M()
{
var x = Zero;
}
}
", equivalenceKey: EquivalenceKey.Create(RefactoringId));
}
}
}
Expand Up @@ -42,6 +42,70 @@ void M()
Enumerable.Empty<object>();
}
}
", equivalenceKey: EquivalenceKey.Create(RefactoringId));
}

[Fact, Trait(Traits.Refactoring, RefactoringIdentifiers.InlineUsingStaticDirective)]
public async Task Test2()
{
await VerifyRefactoringAsync(@"
using System;
using [||]static System.StringComparer;
class C
{
void M()
{
var a = CurrentCulture.GetHashCode();
var b = CurrentCulture;
var c = StringComparer.CurrentCulture;
var d = System.StringComparer.CurrentCulture;
var e = global::System.StringComparer.CurrentCulture;
}
}
", @"
using System;
class C
{
void M()
{
var a = StringComparer.CurrentCulture.GetHashCode();
var b = StringComparer.CurrentCulture;
var c = StringComparer.CurrentCulture;
var d = System.StringComparer.CurrentCulture;
var e = global::System.StringComparer.CurrentCulture;
}
}
", equivalenceKey: EquivalenceKey.Create(RefactoringId));
}

[Fact, Trait(Traits.Refactoring, RefactoringIdentifiers.InlineUsingStaticDirective)]
public async Task Test_Math_Max()
{
await VerifyRefactoringAsync(@"
using System;
using [||]static System.Math;
class C
{
void M()
{
var max = Max(1, 2);
var min = Min(1, 2);
}
}
", @"
using System;
class C
{
void M()
{
var max = Math.Max(1, 2);
var min = Math.Min(1, 2);
}
}
", equivalenceKey: EquivalenceKey.Create(RefactoringId));
}
}
Expand Down

0 comments on commit fe9ec66

Please sign in to comment.