Skip to content

Commit

Permalink
Merge pull request #51536 from sharwell/constants-2
Browse files Browse the repository at this point in the history
Update 'Add DebuggerDisplay' refactoring to support constant interpolated strings
  • Loading branch information
sharwell authored Mar 1, 2021
2 parents 425c739 + ac2c7e4 commit 29459c3
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 109 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,23 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

#nullable disable

using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp.AddDebuggerDisplay;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Testing;
using Xunit;
using VerifyCS = Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions.CSharpCodeRefactoringVerifier<
Microsoft.CodeAnalysis.CSharp.AddDebuggerDisplay.CSharpAddDebuggerDisplayCodeRefactoringProvider>;

namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.AddDebuggerDisplay
{
[Trait(Traits.Feature, Traits.Features.CodeActionsAddDebuggerDisplay)]
public sealed class AddDebuggerDisplayTests : AbstractCSharpCodeActionTest
public sealed class AddDebuggerDisplayTests
{
protected override CodeRefactoringProvider CreateCodeRefactoringProvider(Workspace workspace, TestParameters parameters)
=> new CSharpAddDebuggerDisplayCodeRefactoringProvider();

[Fact]
public async Task OfferedOnEmptyClass()
{
await TestInRegularAndScriptAsync(@"
await VerifyCS.VerifyRefactoringAsync(@"
[||]class C
{
}", @"
Expand All @@ -38,11 +34,39 @@ private string GetDebuggerDisplay()
}");
}

[Fact]
public async Task SupportsConstantInterpolatedStrings()
{
var code = @"
[||]class C
{
}";
var fixedCode = @"
using System.Diagnostics;
[DebuggerDisplay($""{{{nameof(GetDebuggerDisplay)}(),nq}}"")]
class C
{
private string GetDebuggerDisplay()
{
return ToString();
}
}";

await new VerifyCS.Test()
{
LanguageVersion = LanguageVersion.Preview,
TestCode = code,
FixedCode = fixedCode,
}.RunAsync();
}

[Fact]
public async Task OfferedOnEmptyRecord()
{
await TestInRegularAndScriptAsync(@"
[||]record C;", @"
var code = @"
[||]record C;";
var fixedCode = @"
using System.Diagnostics;
[DebuggerDisplay(""{"" + nameof(GetDebuggerDisplay) + ""(),nq}"")]
Expand All @@ -52,13 +76,21 @@ private string GetDebuggerDisplay()
{
return ToString();
}
}");
}";

await new VerifyCS.Test()
{
LanguageVersion = LanguageVersion.CSharp9,
ReferenceAssemblies = ReferenceAssemblies.Net.Net50,
TestCode = code,
FixedCode = fixedCode,
}.RunAsync();
}

[Fact]
public async Task OfferedOnEmptyStruct()
{
await TestInRegularAndScriptAsync(@"
await VerifyCS.VerifyRefactoringAsync(@"
[||]struct Foo
{
}", @"
Expand All @@ -77,52 +109,62 @@ private string GetDebuggerDisplay()
[Fact]
public async Task NotOfferedOnStaticClass()
{
await TestMissingInRegularAndScriptAsync(@"
var code = @"
[||]static class Foo
{
}");
}";

await VerifyCS.VerifyRefactoringAsync(code, code);
}

[Fact]
public async Task NotOfferedOnInterfaceWithToString()
{
await TestMissingInRegularAndScriptAsync(@"
var code = @"
[||]interface IFoo
{
string ToString();
}");
}";

await VerifyCS.VerifyRefactoringAsync(code, code);
}

[Fact]
public async Task NotOfferedOnEnum()
{
await TestMissingInRegularAndScriptAsync(@"
var code = @"
[||]enum Foo
{
}");
}";

await VerifyCS.VerifyRefactoringAsync(code, code);
}

[Fact]
public async Task NotOfferedOnDelegate()
{
await TestMissingInRegularAndScriptAsync(@"
[||]delegate void Foo();");
var code = @"
[||]delegate void Foo();";

await VerifyCS.VerifyRefactoringAsync(code, code);
}

[Fact]
public async Task NotOfferedOnUnrelatedClassMembers()
{
await TestMissingInRegularAndScriptAsync(@"
var code = @"
class C
{
[||]public int Foo { get; }
}");
}";

await VerifyCS.VerifyRefactoringAsync(code, code);
}

[Fact]
public async Task OfferedOnToString()
{
await TestInRegularAndScriptAsync(@"
await VerifyCS.VerifyRefactoringAsync(@"
class C
{
public override string [||]ToString() => ""Foo"";
Expand All @@ -144,7 +186,7 @@ private string GetDebuggerDisplay()
[Fact]
public async Task OfferedOnShadowingToString()
{
await TestInRegularAndScriptAsync(@"
await VerifyCS.VerifyRefactoringAsync(@"
class A
{
public new string [||]ToString() => ""Foo"";
Expand All @@ -166,7 +208,7 @@ private string GetDebuggerDisplay()
[Fact]
public async Task NotOfferedOnWrongOverloadOfToString()
{
await TestMissingInRegularAndScriptAsync(@"
var code = @"
class A
{
public virtual string ToString(int bar = 0) => ""Foo"";
Expand All @@ -175,13 +217,15 @@ class A
class B : A
{
public override string [||]ToString(int bar = 0) => ""Bar"";
}");
}";

await VerifyCS.VerifyRefactoringAsync(code, code);
}

[Fact]
public async Task OfferedOnExistingDebuggerDisplayMethod()
{
await TestInRegularAndScriptAsync(@"
await VerifyCS.VerifyRefactoringAsync(@"
class C
{
private string [||]GetDebuggerDisplay() => ""Foo"";
Expand All @@ -198,17 +242,19 @@ class C
[Fact]
public async Task NotOfferedOnWrongOverloadOfDebuggerDisplayMethod()
{
await TestMissingInRegularAndScriptAsync(@"
var code = @"
class A
{
private string [||]GetDebuggerDisplay(int bar = 0) => ""Foo"";
}");
}";

await VerifyCS.VerifyRefactoringAsync(code, code);
}

[Fact]
public async Task NamespaceImportIsNotDuplicated()
{
await TestInRegularAndScriptAsync(@"
await VerifyCS.VerifyRefactoringAsync(@"
using System.Diagnostics;
[||]class C
Expand All @@ -229,7 +275,7 @@ private string GetDebuggerDisplay()
[Fact]
public async Task NamespaceImportIsSorted()
{
await TestInRegularAndScriptAsync(@"
await VerifyCS.VerifyRefactoringAsync(@"
using System.Xml;
[||]class C
Expand All @@ -251,34 +297,38 @@ private string GetDebuggerDisplay()
[Fact]
public async Task NotOfferedWhenAlreadySpecified()
{
await TestMissingInRegularAndScriptAsync(@"
var code = @"
[System.Diagnostics.DebuggerDisplay(""Foo"")]
[||]class C
{
}");
}";

await VerifyCS.VerifyRefactoringAsync(code, code);
}

[Fact]
public async Task NotOfferedWhenAlreadySpecifiedWithSuffix()
{
await TestMissingInRegularAndScriptAsync(@"
var code = @"
[System.Diagnostics.DebuggerDisplayAttribute(""Foo"")]
[||]class C
{
}");
}";

await VerifyCS.VerifyRefactoringAsync(code, code);
}

[Fact]
public async Task OfferedWhenAttributeWithTheSameNameIsSpecified()
{
await TestInRegularAndScriptAsync(@"
[BrokenCode.DebuggerDisplay(""Foo"")]
await VerifyCS.VerifyRefactoringAsync(@"
[{|CS0246:BrokenCode|}.DebuggerDisplay(""Foo"")]
[||]class C
{
}", @"
using System.Diagnostics;
[BrokenCode.DebuggerDisplay(""Foo"")]
[{|CS0246:BrokenCode|}.DebuggerDisplay(""Foo"")]
[DebuggerDisplay(""{"" + nameof(GetDebuggerDisplay) + ""(),nq}"")]
[||]class C
{
Expand All @@ -292,14 +342,14 @@ private string GetDebuggerDisplay()
[Fact]
public async Task OfferedWhenAttributeWithTheSameNameIsSpecifiedWithSuffix()
{
await TestInRegularAndScriptAsync(@"
[BrokenCode.DebuggerDisplayAttribute(""Foo"")]
await VerifyCS.VerifyRefactoringAsync(@"
[{|CS0246:BrokenCode|}.DebuggerDisplayAttribute(""Foo"")]
[||]class C
{
}", @"
using System.Diagnostics;
[BrokenCode.DebuggerDisplayAttribute(""Foo"")]
[{|CS0246:BrokenCode|}.DebuggerDisplayAttribute(""Foo"")]
[DebuggerDisplay(""{"" + nameof(GetDebuggerDisplay) + ""(),nq}"")]
[||]class C
{
Expand All @@ -313,19 +363,21 @@ private string GetDebuggerDisplay()
[Fact]
public async Task AliasedTypeIsRecognized()
{
await TestMissingInRegularAndScriptAsync(@"
var code = @"
using DD = System.Diagnostics.DebuggerDisplayAttribute;
[DD(""Foo"")]
[||]class C
{
}");
}";

await VerifyCS.VerifyRefactoringAsync(code, code);
}

[Fact]
public async Task OfferedWhenBaseClassHasDebuggerDisplay()
{
await TestInRegularAndScriptAsync(@"
await VerifyCS.VerifyRefactoringAsync(@"
using System.Diagnostics;
[DebuggerDisplay(""Foo"")]
Expand Down Expand Up @@ -356,7 +408,7 @@ private string GetDebuggerDisplay()
[Fact]
public async Task ExistingDebuggerDisplayMethodIsUsedEvenWhenPublicStaticNonString()
{
await TestInRegularAndScriptAsync(@"
await VerifyCS.VerifyRefactoringAsync(@"
[||]class C
{
public static object GetDebuggerDisplay() => ""Foo"";
Expand All @@ -373,7 +425,7 @@ class C
[Fact]
public async Task ExistingDebuggerDisplayMethodWithParameterIsNotUsed()
{
await TestInRegularAndScriptAsync(@"
await VerifyCS.VerifyRefactoringAsync(@"
[||]class C
{
private string GetDebuggerDisplay(int foo = 0) => foo.ToString();
Expand Down
Loading

0 comments on commit 29459c3

Please sign in to comment.