diff --git a/src/CodeStyle/Core/Tests/UnitTestUtilities/Microsoft.CodeAnalysis.CodeStyle.UnitTestUtilities.csproj b/src/CodeStyle/Core/Tests/UnitTestUtilities/Microsoft.CodeAnalysis.CodeStyle.UnitTestUtilities.csproj index 69807d0f912fa..3a5c8ce8f9c94 100644 --- a/src/CodeStyle/Core/Tests/UnitTestUtilities/Microsoft.CodeAnalysis.CodeStyle.UnitTestUtilities.csproj +++ b/src/CodeStyle/Core/Tests/UnitTestUtilities/Microsoft.CodeAnalysis.CodeStyle.UnitTestUtilities.csproj @@ -24,7 +24,7 @@ - + diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SemanticSnippetCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SemanticSnippetCompletionProviderTests.cs new file mode 100644 index 0000000000000..83eb82f956ba1 --- /dev/null +++ b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/SemanticSnippetCompletionProviderTests.cs @@ -0,0 +1,81 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.Completion.CompletionProviders.Snippets; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders; + +[Trait(Traits.Feature, Traits.Features.Completion)] +public sealed class SemanticSnippetCompletionProviderTests : AbstractCSharpCompletionProviderTests +{ + public SemanticSnippetCompletionProviderTests() + { + ShowNewSnippetExperience = true; + } + + internal override Type GetCompletionProviderType() + => typeof(CSharpSnippetCompletionProvider); + + [WpfFact] + public async Task InsertConsoleSnippetWithInvocationBeforeAndAfterCursorTest() + { + var markupBeforeCommit = """ + class Program + { + public void Method() + { + Wr$$Blah + } + } + """; + + var expectedCodeAfterCommit = """ + using System; + + class Program + { + public void Method() + { + Console.WriteLine($$); + } + } + """; + + await VerifyCustomCommitProviderAsync(markupBeforeCommit, "cw", expectedCodeAfterCommit); + } + + [WpfFact] + public async Task InsertConsoleSnippetWithInvocationUnderscoreBeforeAndAfterCursorTest() + { + var markupBeforeCommit = + """ + class Program + { + public void Method() + { + _Wr$$Blah_ + } + } + """; + + var expectedCodeAfterCommit = + """ + using System; + + class Program + { + public void Method() + { + Console.WriteLine($$); + } + } + """; + await VerifyCustomCommitProviderAsync(markupBeforeCommit, "cw", expectedCodeAfterCommit); + } +} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/AbstractCSharpAutoPropertyCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/AbstractCSharpAutoPropertyCompletionProviderTests.cs deleted file mode 100644 index 9d689789446a6..0000000000000 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/AbstractCSharpAutoPropertyCompletionProviderTests.cs +++ /dev/null @@ -1,172 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Test.Utilities; -using Microsoft.CodeAnalysis.Testing; -using Roslyn.Test.Utilities; -using Xunit; - -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; - -public abstract class AbstractCSharpAutoPropertyCompletionProviderTests : AbstractCSharpSnippetCompletionProviderTests -{ - protected abstract string GetDefaultPropertyBlockText(); - - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] - public async Task MissingInNamespace() - { - await VerifyPropertyAbsenceAsync(""" - namespace Namespace - { - $$ - } - """); - } - - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] - public async Task MissingInFilescopedNamespace() - { - await VerifyPropertyAbsenceAsync(""" - namespace Namespace; - - $$ - """); - } - - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] - public async Task MissingInTopLevelContext() - { - await VerifyPropertyAbsenceAsync(""" - System.Console.WriteLine(); - $$ - """); - } - - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] - public async Task InsertSnippetInClass() - { - await VerifyDefaultPropertyAsync(""" - class MyClass - { - $$ - } - """); - } - - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] - public async Task InsertSnippetInRecord() - { - await VerifyDefaultPropertyAsync(""" - record MyRecord - { - $$ - } - """); - } - - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] - public async Task InsertSnippetInStruct() - { - await VerifyDefaultPropertyAsync(""" - struct MyStruct - { - $$ - } - """); - } - - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] - public abstract Task InsertSnippetInReadonlyStruct(); - - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] - public abstract Task InsertSnippetInReadonlyStruct_ReadonlyModifierInOtherPartialDeclaration(); - - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] - public abstract Task InsertSnippetInReadonlyStruct_ReadonlyModifierInOtherPartialDeclaration_MissingPartialModifier(); - - // This case might produce non-default results for different snippets (e.g. no `set` accessor in 'propg' snippet), - // so it is tested separately for all of them - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] - public abstract Task InsertSnippetInInterface(); - - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] - public async Task InsertSnippetNaming() - { - await VerifyDefaultPropertyAsync(""" - class MyClass - { - public int MyProperty { get; set; } - $$ - } - """, "MyProperty1"); - } - - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] - public async Task MissingInEnum() - { - await VerifyPropertyAbsenceAsync(""" - enum MyEnum - { - $$ - } - """); - } - - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] - public async Task MissingInMethod() - { - await VerifyPropertyAbsenceAsync(""" - class Program - { - public void Method() - { - $$ - } - } - """); - } - - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] - public async Task MissingInConstructor() - { - await VerifyPropertyAbsenceAsync(""" - class Program - { - public Program() - { - $$ - } - } - """); - } - - [WpfTheory, Trait(Traits.Feature, Traits.Features.Completion)] - [InlineData("public")] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - [InlineData("protected internal")] - public async Task AfterAccessibilityModifier(string modifier) - { - await VerifyPropertyAsync($$""" - class Program - { - {{modifier}} $$ - } - """, $"int MyProperty {GetDefaultPropertyBlockText()}"); - } - - private Task VerifyPropertyAbsenceAsync(string markup) => VerifyItemIsAbsentAsync(markup, ItemToCommit); - - protected async Task VerifyPropertyAsync(string markup, string propertyText) - { - TestFileMarkupParser.GetPosition(markup, out var code, out var position); - var expectedCode = code.Insert(position, propertyText + "$$"); - await VerifyCustomCommitProviderAsync(markup, ItemToCommit, expectedCode); - } - - protected Task VerifyDefaultPropertyAsync(string markup, string propertyName = "MyProperty") - => VerifyPropertyAsync(markup, $"public int {propertyName} {GetDefaultPropertyBlockText()}"); -} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/AbstractCSharpSnippetCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/AbstractCSharpSnippetCompletionProviderTests.cs deleted file mode 100644 index 64fe0106bb973..0000000000000 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/AbstractCSharpSnippetCompletionProviderTests.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using Microsoft.CodeAnalysis.CSharp.Completion.CompletionProviders.Snippets; - -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; - -public abstract class AbstractCSharpSnippetCompletionProviderTests : AbstractCSharpCompletionProviderTests -{ - protected abstract string ItemToCommit { get; } - - protected AbstractCSharpSnippetCompletionProviderTests() - { - ShowNewSnippetExperience = true; - } - - internal override Type GetCompletionProviderType() - => typeof(CSharpSnippetCompletionProvider); -} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpClassSnippetCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpClassSnippetCompletionProviderTests.cs deleted file mode 100644 index 4af897017458a..0000000000000 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpClassSnippetCompletionProviderTests.cs +++ /dev/null @@ -1,547 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Test.Utilities; -using Roslyn.Test.Utilities; -using Xunit; - -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; - -[Trait(Traits.Feature, Traits.Features.Completion)] -public class CSharpClassSnippetCompletionProviderTests : AbstractCSharpSnippetCompletionProviderTests -{ - protected override string ItemToCommit => "class"; - - [WpfFact] - public async Task InsertClassSnippetInNamespaceTest() - { - var markupBeforeCommit = - """ - namespace Namespace - { - $$ - } - """; - - var expectedCodeAfterCommit = - """ - namespace Namespace - { - class MyClass - { - $$ - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertClassSnippetInFileScopedNamespaceTest() - { - var markupBeforeCommit = - """ - namespace Namespace; - - $$ - """; - - var expectedCodeAfterCommit = - """ - namespace Namespace; - - class MyClass - { - $$ - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertClassSnippetTest() - { - var markupBeforeCommit = -@"$$"; - - var expectedCodeAfterCommit = - """ - class MyClass - { - $$ - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertClassTopLevelSnippetTest() - { - var markupBeforeCommit = - """ - System.Console.WriteLine(); - $$ - """; - - var expectedCodeAfterCommit = - """ - System.Console.WriteLine(); - class MyClass - { - $$ - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertClassSnippetInClassTest() - { - var markupBeforeCommit = - """ - class MyClass - { - $$ - } - """; - - var expectedCodeAfterCommit = - """ - class MyClass - { - class MyClass1 - { - $$ - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertClassSnippetInRecordTest() - { - var markupBeforeCommit = - """ - record MyRecord - { - $$ - } - """; - - var expectedCodeAfterCommit = - """ - record MyRecord - { - class MyClass - { - $$ - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertClassSnippetInStructTest() - { - var markupBeforeCommit = - """ - struct MyStruct - { - $$ - } - """; - - var expectedCodeAfterCommit = - """ - struct MyStruct - { - class MyClass - { - $$ - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertClassSnippetInInterfaceTest() - { - var markupBeforeCommit = - """ - interface MyInterface - { - $$ - } - """; - - var expectedCodeAfterCommit = - """ - interface MyInterface - { - class MyClass - { - $$ - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertClassSnippetWithModifiersTest() - { - var markupBeforeCommit = - $@" - - - -$$ - - -root = true - -[*] -# IDE0008: Use explicit type -dotnet_style_require_accessibility_modifiers = always - - -"; - var expectedCodeAfterCommit = - $@" -public class MyClass -{{ - $$ -}} -"; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task NoClassSnippetInEnumTest() - { - var markupBeforeCommit = - """ - enum MyEnum - { - $$ - } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoClassSnippetInMethodTest() - { - var markupBeforeCommit = - """ - class Program - { - public void Method() - { - $$ - } - } - """; - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoClassSnippetInConstructorTest() - { - var markupBeforeCommit = - """ - class Program - { - public Program() - { - $$ - } - } - """; - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfTheory] - [InlineData("public")] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - [InlineData("protected internal")] - public async Task AfterAccessibilityModifier(string modifier) - { - var markupBeforeCommit = $"{modifier} $$"; - - var expectedCodeAfterCommit = $$""" - {{modifier}} class MyClass - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("public")] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - [InlineData("protected internal")] - public async Task AfterAccessibilityModifier_RequireAccessibilityModifiers(string modifier) - { - var markupBeforeCommit = $$""" - - - {{modifier}} $$ - - root = true - - [*] - # IDE0008: Use explicit type - dotnet_style_require_accessibility_modifiers = always - - - - """; - - var expectedCodeAfterCommit = $$""" - {{modifier}} class MyClass - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("abstract")] - [InlineData("sealed")] - [InlineData("static")] - [InlineData("unsafe")] - public async Task InsertClassSnippetAfterValidModifiersTest(string modifier) - { - var markupBeforeCommit = $"{modifier} $$"; - - var expectedCodeAfterCommit = $$""" - {{modifier}} class MyClass - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("ref")] - [InlineData("readonly")] - public async Task NoClassSnippetAfterInvalidModifiersTest(string modifier) - { - var markupBeforeCommit = $"{modifier} $$"; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfTheory, WorkItem("https://github.com/dotnet/roslyn/issues/69600")] - [InlineData("public")] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - [InlineData("protected internal")] - public async Task NoAdditionalAccessibilityModifiersIfAfterPartialKeywordTest(string modifier) - { - var markupBeforeCommit = $$""" - - - {{modifier}} partial $$ - - root = true - - [*] - # IDE0008: Use explicit type - dotnet_style_require_accessibility_modifiers = always - - - - """; - - var expectedCodeAfterCommit = $$""" - {{modifier}} partial class MyClass - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/69600")] - public async Task EnsureCorrectModifierOrderAfterPartialKeywordTest() - { - var markupBeforeCommit = """ - - - partial $$ - - root = true - - [*] - # IDE0008: Use explicit type - dotnet_style_require_accessibility_modifiers = always - - - - """; - - var expectedCodeAfterCommit = """ - public partial class MyClass - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/69600")] - public async Task EnsureCorrectModifierOrderAfterPartialKeywordTest_InvalidPreferredModifiersList() - { - var markupBeforeCommit = """ - - - partial $$ - - [*] - dotnet_style_require_accessibility_modifiers = always - - csharp_preferred_modifier_order = invalid! - - - - """; - - var expectedCodeAfterCommit = """ - public partial class MyClass - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task EnsureCorrectModifierOrderFromOptionsTest_PublicModifierBeforeAllOthers() - { - var markupBeforeCommit = """ - - - sealed unsafe $$ - - [*] - dotnet_style_require_accessibility_modifiers = always - - csharp_preferred_modifier_order = public,sealed,unsafe - - - - """; - - var expectedCodeAfterCommit = """ - public sealed unsafe class MyClass - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task EnsureCorrectModifierOrderFromOptionsTest_PublicModifierBeforeAllOthers_NotAllModifiersInTheList() - { - var markupBeforeCommit = """ - - - sealed unsafe $$ - - [*] - dotnet_style_require_accessibility_modifiers = always - - csharp_preferred_modifier_order = public,sealed - - - - """; - - var expectedCodeAfterCommit = """ - public sealed unsafe class MyClass - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task EnsureCorrectModifierOrderFromOptionsTest_PublicModifierBetweenOthers() - { - var markupBeforeCommit = """ - - - sealed unsafe $$ - - [*] - dotnet_style_require_accessibility_modifiers = always - - csharp_preferred_modifier_order = sealed,public,unsafe - - - - """; - - var expectedCodeAfterCommit = """ - sealed public unsafe class MyClass - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task EnsureCorrectModifierOrderFromOptionsTest_PublicModifierAfterAllOthers() - { - var markupBeforeCommit = """ - - - sealed unsafe $$ - - [*] - dotnet_style_require_accessibility_modifiers = always - - csharp_preferred_modifier_order = sealed,unsafe,public - - - - """; - - var expectedCodeAfterCommit = """ - sealed unsafe public class MyClass - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } -} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpConsoleSnippetCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpConsoleSnippetCompletionProviderTests.cs deleted file mode 100644 index 43a98dac711ff..0000000000000 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpConsoleSnippetCompletionProviderTests.cs +++ /dev/null @@ -1,584 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Test.Utilities; -using Roslyn.Test.Utilities; -using Xunit; - -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; - -[Trait(Traits.Feature, Traits.Features.Completion)] -public class CSharpConsoleSnippetCompletionProviderTests : AbstractCSharpSnippetCompletionProviderTests -{ - protected override string ItemToCommit => "cw"; - - [WpfFact] - public async Task InsertConsoleSnippetInMethodTest() - { - var markupBeforeCommit = - """ - class Program - { - public void Method() - { - Wr$$ - } - } - """; - - var expectedCodeAfterCommit = - """ - using System; - - class Program - { - public void Method() - { - Console.WriteLine($$); - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertNormalConsoleSnippetInAsyncContextTest() - { - var markupBeforeCommit = - """ - class Program - { - public async Task MethodAsync() - { - Wr$$ - } - } - """; - - var expectedCodeAfterCommit = - """ - using System; - - class Program - { - public async Task MethodAsync() - { - Console.WriteLine($$); - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertConsoleSnippetGlobalTest() - { - var markupBeforeCommit = - """ - $$ - class Program - { - public async Task MethodAsync() - { - } - } - """; - - var expectedCodeAfterCommit = - """ - using System; - - Console.WriteLine($$); - class Program - { - public async Task MethodAsync() - { - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task NoConsoleSnippetInBlockNamespaceTest() - { - var markupBeforeCommit = - """ - namespace Namespace - { - $$ - class Program - { - public async Task MethodAsync() - { - } - } - } - """; - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoConsoleSnippetInFileScopedNamespaceTest() - { - var markupBeforeCommit = - """ - namespace Namespace; - $$ - class Program - { - public async Task MethodAsync() - { - } - } - """; - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task InsertConsoleSnippetInConstructorTest() - { - var markupBeforeCommit = - """ - class Program - { - public Program() - { - var x = 5; - $$ - } - } - """; - - var expectedCodeAfterCommit = - """ - using System; - - class Program - { - public Program() - { - var x = 5; - Console.WriteLine($$); - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertConsoleSnippetInLocalFunctionTest() - { - var markupBeforeCommit = - """ - class Program - { - public void Method() - { - var x = 5; - void LocalMethod() - { - $$ - } - } - } - """; - - var expectedCodeAfterCommit = - """ - using System; - - class Program - { - public void Method() - { - var x = 5; - void LocalMethod() - { - Console.WriteLine($$); - } - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertConsoleSnippetInAnonymousFunctionTest() - { - var markupBeforeCommit = - """ - public delegate void Print(int value); - - static void Main(string[] args) - { - Print print = delegate(int val) { - $$ - }; - - } - """; - - var expectedCodeAfterCommit = - """ - using System; - - public delegate void Print(int value); - - static void Main(string[] args) - { - Print print = delegate(int val) { - Console.WriteLine($$); - }; - - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertConsoleSnippetInParenthesizedLambdaExpressionTest() - { - var markupBeforeCommit = - """ - Func testForEquality = (x, y) => - { - $$ - return x == y; - }; - """; - - var expectedCodeAfterCommit = - """ - using System; - - Func testForEquality = (x, y) => - { - Console.WriteLine($$); - return x == y; - }; - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task NoConsoleSnippetInSwitchExpression() - { - var markupBeforeCommit = - """ - class Program - { - public void Method() - { - var operation = 2; - - var result = operation switch - { - $$ - 1 => "Case 1", - 2 => "Case 2", - 3 => "Case 3", - 4 => "Case 4", - }; - } - } - """; - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoConsoleSnippetInSingleLambdaExpression() - { - var markupBeforeCommit = - """ - class Program - { - public void Method() - { - Func f = x => $$; - } - } - """; - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoConsoleSnippetInStringTest() - { - var markupBeforeCommit = - """ - class Program - { - public void Method() - { - var str = "$$"; - } - } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoConsoleSnippetInObjectInitializerTest() - { - var markupBeforeCommit = - """ - class Program - { - public void Method() - { - var str = new Test($$); - } - } - - class Test - { - private string val; - - public Test(string val) - { - this.val = val; - } - } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoConsoleSnippetInParameterListTest() - { - var markupBeforeCommit = - """ - class Program - { - public void Method(int x, $$) - { - } - } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoConsoleSnippetInRecordDeclarationTest() - { - var markupBeforeCommit = - """ - public record Person - { - $$ - public string FirstName { get; init; } = default!; - public string LastName { get; init; } = default!; - }; - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoConsoleSnippetInVariableDeclarationTest() - { - var markupBeforeCommit = - """ - class Program - { - public void Method() - { - var x = $$ - } - } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task InsertConsoleSnippetWithInvocationBeforeAndAfterCursorTest() - { - var markupBeforeCommit = - """ - class Program - { - public void Method() - { - Wr$$Blah - } - } - """; - - var expectedCodeAfterCommit = - """ - using System; - - class Program - { - public void Method() - { - Console.WriteLine($$); - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertConsoleSnippetWithInvocationUnderscoreBeforeAndAfterCursorTest() - { - var markupBeforeCommit = - """ - class Program - { - public void Method() - { - _Wr$$Blah_ - } - } - """; - - var expectedCodeAfterCommit = - """ - using System; - - class Program - { - public void Method() - { - Console.WriteLine($$); - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - /// - /// We want to fix this case and insert the fully qualified namespace - /// in a future fix. - /// - [WpfFact] - public async Task InsertConsoleSnippetWithPropertyNamedConsoleTest() - { - var markupBeforeCommit = - """ - class Program - { - public int Console { get; set; } - - public void Method() - { - $$ - } - } - """; - - var expectedCodeAfterCommit = - """ - using System; - - class Program - { - public int Console { get; set; } - - public void Method() - { - Console.WriteLine($$); - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/72266")] - public async Task InsertConsoleSnippetInVoidReturningLambdaTest1() - { - var markupBeforeCommit = """ - using System; - - M(() => $$); - - void M(Action a) - { - } - """; - - var expectedCodeAfterCommit = """ - using System; - - M(() => Console.WriteLine($$)); - - void M(Action a) - { - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/72266")] - public async Task InsertConsoleSnippetInVoidReturningLambdaTest2() - { - var markupBeforeCommit = """ - using System; - - Action action = () => $$ - """; - - var expectedCodeAfterCommit = """ - using System; - - Action action = () => Console.WriteLine($$) - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/72266")] - public async Task InsertConsoleSnippetInVoidReturningLambdaTest_TypeInference() - { - var markupBeforeCommit = """ - using System; - - var action = () => $$ - """; - - var expectedCodeAfterCommit = """ - using System; - - var action = () => Console.WriteLine($$) - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/72266")] - public async Task NoConsoleSnippetInNonVoidReturningLambdaTest1() - { - var markupBeforeCommit = """ - using System; - - M(() => $$); - - void M(Func f) - { - } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/72266")] - public async Task NoConsoleSnippetInNonVoidReturningLambdaTest2() - { - var markupBeforeCommit = """ - using System; - - Func f = () => $$ - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } -} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpDoSnippetCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpDoSnippetCompletionProviderTests.cs deleted file mode 100644 index e1ae704c239b1..0000000000000 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpDoSnippetCompletionProviderTests.cs +++ /dev/null @@ -1,709 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Test.Utilities; -using Roslyn.Test.Utilities; -using Xunit; - -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; - -[Trait(Traits.Feature, Traits.Features.Completion)] -public class CSharpDoSnippetCompletionProviderTests : AbstractCSharpSnippetCompletionProviderTests -{ - protected override string ItemToCommit => "do"; - - [WpfFact] - public async Task InsertSnippetInMethodTest() - { - var markupBeforeCommit = """ - class Program - { - public void Method() - { - $$ - } - } - """; - - var expectedCodeAfterCommit = """ - class Program - { - public void Method() - { - do - { - $$ - } - while (true); - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertSnippetInGlobalContextTest() - { - var markupBeforeCommit = """ - Ins$$ - """; - - var expectedCodeAfterCommit = """ - do - { - $$ - } - while (true); - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task NoSnippetInBlockNamespaceTest() - { - var markupBeforeCommit = """ - namespace Namespace - { - $$ - class Program - { - public async Task MethodAsync() - { - } - } - } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoSnippetInFileScopedNamespaceTest() - { - var markupBeforeCommit = """ - namespace Namespace; - $$ - class Program - { - public async Task MethodAsync() - { - } - } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task InsertSnippetInConstructorTest() - { - var markupBeforeCommit = """ - class Program - { - public Program() - { - var x = 5; - $$ - } - } - """; - - var expectedCodeAfterCommit = """ - class Program - { - public Program() - { - var x = 5; - do - { - $$ - } - while (true); - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertSnippetInLocalFunctionTest() - { - var markupBeforeCommit = """ - class Program - { - public void Method() - { - var x = 5; - void LocalMethod() - { - $$ - } - } - } - """; - - var expectedCodeAfterCommit = """ - class Program - { - public void Method() - { - var x = 5; - void LocalMethod() - { - do - { - $$ - } - while (true); - } - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertSnippetInAnonymousFunctionTest() - { - var markupBeforeCommit = """ - public delegate void Print(int value); - - static void Main(string[] args) - { - Print print = delegate(int val) { - $$ - }; - - } - """; - - var expectedCodeAfterCommit = """ - public delegate void Print(int value); - - static void Main(string[] args) - { - Print print = delegate(int val) { - do - { - $$ - } - while (true); - }; - - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertSnippetInParenthesizedLambdaExpressionTest() - { - var markupBeforeCommit = """ - Func testForEquality = (x, y) => - { - $$ - return x == y; - }; - """; - - var expectedCodeAfterCommit = """ - Func testForEquality = (x, y) => - { - do - { - $$ - } - while (true); - return x == y; - }; - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task NoSnippetInSwitchExpression() - { - var markupBeforeCommit = """ - class Program - { - public void Method() - { - var operation = 2; - - var result = operation switch - { - $$ - 1 => "Case 1", - 2 => "Case 2", - 3 => "Case 3", - 4 => "Case 4", - }; - } - } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoSnippetInSingleLambdaExpression() - { - var markupBeforeCommit = """ - class Program - { - public void Method() - { - Func f = x => $$; - } - } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoSnippetInStringTest() - { - var markupBeforeCommit = """ - class Program - { - public void Method() - { - var str = "$$"; - } - } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoSnippetInObjectInitializerTest() - { - var markupBeforeCommit = """ - class Program - { - public void Method() - { - var str = new Test($$); - } - } - - class Test - { - private string val; - - public Test(string val) - { - this.val = val; - } - } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoSnippetInParameterListTest() - { - var markupBeforeCommit = """ - class Program - { - public void Method(int x, $$) - { - } - } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoSnippetInRecordDeclarationTest() - { - var markupBeforeCommit = """ - public record Person - { - $$ - public string FirstName { get; init; } = default!; - public string LastName { get; init; } = default!; - }; - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoSnippetInVariableDeclarationTest() - { - var markupBeforeCommit = """ - class Program - { - public void Method() - { - var x = $$ - } - } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task InsertSnippetWithInvocationBeforeAndAfterCursorTest() - { - var markupBeforeCommit = """ - class Program - { - public void Method() - { - Wr$$Blah - } - } - """; - - var expectedCodeAfterCommit = """ - class Program - { - public void Method() - { - do - { - $$ - } - while (true); - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertSnippetWithInvocationUnderscoreBeforeAndAfterCursorTest() - { - var markupBeforeCommit = """ - class Program - { - public void Method() - { - _Wr$$Blah_ - } - } - """; - - var expectedCodeAfterCommit = """ - class Program - { - public void Method() - { - do - { - $$ - } - while (true); - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertInlineSnippetForCorrectTypeTest() - { - var markupBeforeCommit = """ - class Program - { - void M(bool arg) - { - arg.$$ - } - } - """; - - var expectedCodeAfterCommit = """ - class Program - { - void M(bool arg) - { - do - { - $$ - } - while (arg); - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task NoInlineSnippetForIncorrectTypeTest() - { - var markupBeforeCommit = """ - class Program - { - void M(int arg) - { - arg.$$ - } - } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoInlineSnippetWhenNotDirectlyExpressionStatementTest() - { - var markupBeforeCommit = """ - class Program - { - void M(bool arg) - { - System.Console.WriteLine(arg.$$); - } - } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfTheory] - [InlineData("// comment")] - [InlineData("/* comment */")] - [InlineData("#region test")] - public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInMethodTest1(string trivia) - { - var markupBeforeCommit = $$""" - class Program - { - void M(bool arg) - { - {{trivia}} - arg.$$ - } - } - """; - - var expectedCodeAfterCommit = $$""" - class Program - { - void M(bool arg) - { - {{trivia}} - do - { - $$ - } - while (arg); - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("#if true")] - [InlineData("#pragma warning disable CS0108")] - [InlineData("#nullable enable")] - public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInMethodTest2(string trivia) - { - var markupBeforeCommit = $$""" - class Program - { - void M(bool arg) - { - {{trivia}} - arg.$$ - } - } - """; - - var expectedCodeAfterCommit = $$""" - class Program - { - void M(bool arg) - { - {{trivia}} - do - { - $$ - } - while (arg); - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("// comment")] - [InlineData("/* comment */")] - public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInGlobalStatementTest1(string trivia) - { - var markupBeforeCommit = $$""" - {{trivia}} - true.$$ - """; - - var expectedCodeAfterCommit = $$""" - {{trivia}} - do - { - $$ - } - while (true); - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("#region test")] - [InlineData("#if true")] - [InlineData("#pragma warning disable CS0108")] - [InlineData("#nullable enable")] - public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInGlobalStatementTest2(string trivia) - { - var markupBeforeCommit = $$""" - {{trivia}} - true.$$ - """; - - var expectedCodeAfterCommit = $$""" - - {{trivia}} - do - { - $$ - } - while (true); - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] - public async Task InsertInlineSnippetWhenDottingBeforeContextualKeywordTest1() - { - var markupBeforeCommit = """ - using System.Collections.Generic; - - class C - { - void M(bool flag) - { - flag.$$ - var a = 0; - } - } - """; - - var expectedCodeAfterCommit = """ - using System.Collections.Generic; - - class C - { - void M(bool flag) - { - do - { - $$ - } - while (flag); - var a = 0; - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] - public async Task InsertInlineSnippetWhenDottingBeforeContextualKeywordTest2() - { - var markupBeforeCommit = """ - using System.Collections.Generic; - - class C - { - void M(bool flag, Task t) - { - flag.$$ - await t; - } - } - """; - - var expectedCodeAfterCommit = $$""" - using System.Collections.Generic; - - class C - { - void M(bool flag, Task t) - { - do - { - $$ - } - while (flag); - await t; - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] - [InlineData("Task")] - [InlineData("Task")] - [InlineData("System.Threading.Tasks.Task")] - public async Task InsertInlineSnippetWhenDottingBeforeNameSyntaxTest(string nameSyntax) - { - var markupBeforeCommit = $$""" - using System.Collections.Generic; - - class C - { - void M(bool flag) - { - flag.$$ - {{nameSyntax}} t = null; - } - } - """; - - var expectedCodeAfterCommit = $$""" - using System.Collections.Generic; - - class C - { - void M(bool flag) - { - do - { - $$ - } - while (flag); - {{nameSyntax}} t = null; - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } -} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpEnumSnippetCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpEnumSnippetCompletionProviderTests.cs deleted file mode 100644 index 98e1635773035..0000000000000 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpEnumSnippetCompletionProviderTests.cs +++ /dev/null @@ -1,285 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Threading.Tasks; -using Roslyn.Test.Utilities; -using Xunit; - -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; - -public class CSharpEnumSnippetCompletionProviderTests : AbstractCSharpSnippetCompletionProviderTests -{ - protected override string ItemToCommit => "enum"; - - [WpfFact] - public async Task InsertEnumSnippetInNamespaceTest() - { - await VerifyCustomCommitProviderAsync(""" - namespace Namespace - { - $$ - } - """, ItemToCommit, """ - namespace Namespace - { - enum MyEnum - { - $$ - } - } - """); - } - - [WpfFact] - public async Task InsertEnumSnippetInFileScopedNamespaceTest() - { - await VerifyCustomCommitProviderAsync(""" - namespace Namespace; - - $$ - """, ItemToCommit, """ - namespace Namespace; - - enum MyEnum - { - $$ - } - """); - } - - [WpfFact] - public async Task InsertEnumSnippetTest() - { - await VerifyCustomCommitProviderAsync(""" - $$ - """, ItemToCommit, """ - enum MyEnum - { - $$ - } - """); - } - - [WpfFact] - public async Task InsertEnumTopLevelSnippetTest() - { - await VerifyCustomCommitProviderAsync(""" - System.Console.WriteLine(); - $$ - """, ItemToCommit, """ - System.Console.WriteLine(); - enum MyEnum - { - $$ - } - """); - } - - [WpfFact] - public async Task InsertEnumSnippetInClassTest() - { - await VerifyCustomCommitProviderAsync(""" - class MyClass - { - $$ - } - """, ItemToCommit, """ - class MyClass - { - enum MyEnum - { - $$ - } - } - """); - } - - [WpfFact] - public async Task InsertEnumSnippetInRecordTest() - { - await VerifyCustomCommitProviderAsync(""" - record MyRecord - { - $$ - } - """, ItemToCommit, """ - record MyRecord - { - enum MyEnum - { - $$ - } - } - """); - } - - [WpfFact] - public async Task InsertEnumSnippetInStructTest() - { - await VerifyCustomCommitProviderAsync(""" - struct MyStruct - { - $$ - } - """, ItemToCommit, """ - struct MyStruct - { - enum MyEnum - { - $$ - } - } - """); - } - - [WpfFact] - public async Task InsertEnumSnippetInInterfaceTest() - { - await VerifyCustomCommitProviderAsync(""" - interface MyInterface - { - $$ - } - """, ItemToCommit, """ - interface MyInterface - { - enum MyEnum - { - $$ - } - } - """); - } - - [WpfFact] - public async Task InsertEnumSnippetWithModifiersTest() - { - await VerifyCustomCommitProviderAsync(""" - - - $$ - - root = true - - [*] - # IDE0008: Use explicit type - dotnet_style_require_accessibility_modifiers = always - - - - """, ItemToCommit, """ - public enum MyEnum - { - $$ - } - """); - } - - [WpfFact] - public async Task NoEnumSnippetInEnumTest() - { - await VerifyItemIsAbsentAsync(""" - enum MyEnum - { - $$ - } - """, ItemToCommit); - } - - [WpfFact] - public async Task NoEnumSnippetInMethodTest() - { - await VerifyItemIsAbsentAsync(""" - class Program - { - public void Method() - { - $$ - } - } - """, ItemToCommit); - } - - [WpfFact] - public async Task NoEnumSnippetInConstructorTest() - { - await VerifyItemIsAbsentAsync(""" - class Program - { - public Program() - { - $$ - } - } - """, ItemToCommit); - } - - [WpfTheory] - [InlineData("public")] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - [InlineData("protected internal")] - public async Task AfterAccessibilityModifier(string modifier) - { - var markupBeforeCommit = $"{modifier} $$"; - - var expectedCodeAfterCommit = $$""" - {{modifier}} enum MyEnum - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("public")] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - [InlineData("protected internal")] - public async Task AfterAccessibilityModifier_RequireAccessibilityModifiers(string modifier) - { - var markupBeforeCommit = $$""" - - - {{modifier}} $$ - - root = true - - [*] - # IDE0008: Use explicit type - dotnet_style_require_accessibility_modifiers = always - - - - """; - - var expectedCodeAfterCommit = $$""" - {{modifier}} enum MyEnum - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("abstract")] - [InlineData("partial")] - [InlineData("sealed")] - [InlineData("static")] - [InlineData("ref")] - [InlineData("readonly")] - [InlineData("unsafe")] - public async Task NoEnumSnippetAfterInvalidModifiersTest(string modifier) - { - var markupBeforeCommit = $"{modifier} $$"; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } -} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpForSnippetCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpForSnippetCompletionProviderTests.cs deleted file mode 100644 index e8a806a99f557..0000000000000 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpForSnippetCompletionProviderTests.cs +++ /dev/null @@ -1,1281 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Test.Utilities; -using Roslyn.Test.Utilities; -using Xunit; - -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; - -[Trait(Traits.Feature, Traits.Features.Completion)] -public class CSharpForSnippetCompletionProviderTests : AbstractCSharpSnippetCompletionProviderTests -{ - protected override string ItemToCommit => "for"; - - [WpfFact] - public async Task InsertForSnippetInMethodTest() - { - await VerifyCustomCommitProviderAsync(""" - class Program - { - public void Method() - { - $$ - } - } - """, ItemToCommit, """ - class Program - { - public void Method() - { - for (int i = 0; i < length; i++) - { - $$ - } - } - } - """); - } - - [WpfFact] - public async Task InsertForSnippetInMethodUsedIncrementorTest() - { - await VerifyCustomCommitProviderAsync(""" - class Program - { - public void Method() - { - int i; - $$ - } - } - """, ItemToCommit, """ - class Program - { - public void Method() - { - int i; - for (int j = 0; j < length; j++) - { - $$ - } - } - } - """); - } - - [WpfFact] - public async Task InsertForSnippetInMethodUsedIncrementorsTest() - { - await VerifyCustomCommitProviderAsync(""" - class Program - { - public void Method() - { - int i, j, k; - $$ - } - } - """, ItemToCommit, """ - class Program - { - public void Method() - { - int i, j, k; - for (int i1 = 0; i1 < length; i1++) - { - $$ - } - } - } - """); - } - - [WpfFact] - public async Task InsertForSnippetInGlobalContextTest() - { - await VerifyCustomCommitProviderAsync(""" - $$ - """, ItemToCommit, """ - for (int i = 0; i < length; i++) - { - $$ - } - """); - } - - [WpfFact] - public async Task InsertForSnippetInConstructorTest() - { - await VerifyCustomCommitProviderAsync(""" - class Program - { - public Program() - { - $$ - } - } - """, ItemToCommit, """ - class Program - { - public Program() - { - for (int i = 0; i < length; i++) - { - $$ - } - } - } - """); - } - - [WpfFact] - public async Task InsertForSnippetInLocalFunctionTest() - { - // TODO: fix this test when bug with simplifier failing to find correct node is fixed - await VerifyCustomCommitProviderAsync(""" - class Program - { - public void Method() - { - void LocalFunction() - { - $$ - } - } - } - """, ItemToCommit, """ - class Program - { - public void Method() - { - void LocalFunction() - { - for (global::System.Int32 i = 0; i < length; i++) - { - $$ - } - } - } - } - """); - } - - [WpfFact] - public async Task InsertForSnippetInAnonymousFunctionTest() - { - // TODO: fix this test when bug with simplifier failing to find correct node is fixed - await VerifyCustomCommitProviderAsync(""" - class Program - { - public void Method() - { - var action = delegate() - { - $$ - }; - } - } - """, ItemToCommit, """ - class Program - { - public void Method() - { - var action = delegate() - { - for (global::System.Int32 i = 0; i < length; i++) - { - $$ - } - }; - } - } - """); - } - - [WpfFact] - public async Task InsertForSnippetInParenthesizedLambdaExpressionTest() - { - // TODO: fix this test when bug with simplifier failing to find correct node is fixed - await VerifyCustomCommitProviderAsync(""" - class Program - { - public void Method() - { - var action = () => - { - $$ - }; - } - } - """, ItemToCommit, """ - class Program - { - public void Method() - { - var action = () => - { - for (global::System.Int32 i = 0; i < length; i++) - { - $$ - } - }; - } - } - """); - } - - [WpfFact] - public async Task ProduceVarWithSpecificCodeStyleTest() - { - await VerifyCustomCommitProviderAsync(""" - - - class Program - { - public void Method() - { - $$ - } - } - - root = true - - [*] - # IDE0008: Use explicit type - csharp_style_var_for_built_in_types = true - - - - """, ItemToCommit, """ - class Program - { - public void Method() - { - for (var i = 0; i < length; i++) - { - $$ - } - } - } - """); - } - - [WpfTheory] - [MemberData(nameof(IntegerTypes))] - public async Task InsertInlineForSnippetInMethodTest(string inlineExpressionType) - { - await VerifyCustomCommitProviderAsync($$""" - class Program - { - public void Method({{inlineExpressionType}} l) - { - l.$$ - } - } - """, ItemToCommit, $$""" - class Program - { - public void Method({{inlineExpressionType}} l) - { - for ({{inlineExpressionType}} i = 0; i < l; i++) - { - $$ - } - } - } - """); - } - - [WpfTheory] - [MemberData(nameof(IntegerTypes))] - public async Task InsertInlineForSnippetInGlobalContextTest(string inlineExpressionType) - { - await VerifyCustomCommitProviderAsync($$""" - {{inlineExpressionType}} l; - l.$$ - """, ItemToCommit, $$""" - {{inlineExpressionType}} l; - for ({{inlineExpressionType}} i = 0; i < l; i++) - { - $$ - } - """); - } - - [WpfTheory] - [MemberData(nameof(NotIntegerTypes))] - public async Task NoInlineForSnippetForIncorrectTypeInMethodTest(string inlineExpressionType) - { - var markup = $$""" - class Program - { - public void Method({{inlineExpressionType}} l) - { - l.$$ - } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfTheory] - [MemberData(nameof(NotIntegerTypes))] - public async Task NoInlineForSnippetForIncorrectTypeInGlobalContextTest(string inlineExpressionType) - { - var markup = $$""" - {{inlineExpressionType}} l; - l.$$ - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfFact] - public async Task ProduceVarWithSpecificCodeStyleForInlineSnippetTest() - { - await VerifyCustomCommitProviderAsync(""" - - - class Program - { - public void Method(int l) - { - l.$$ - } - } - - root = true - - [*] - # IDE0008: Use explicit type - csharp_style_var_for_built_in_types = true - - - - """, ItemToCommit, """ - class Program - { - public void Method(int l) - { - for (var i = 0; i < l; i++) - { - $$ - } - } - } - """); - } - - [WpfFact] - public async Task NoInlineForSnippetNotDirectlyExpressionStatementTest() - { - var markup = """ - class Program - { - public void Method(int l) - { - System.Console.WriteLine(l.$$); - } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfTheory] - [InlineData("// comment")] - [InlineData("/* comment */")] - [InlineData("#region test")] - public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInMethodTest1(string trivia) - { - var markupBeforeCommit = $$""" - class Program - { - void M(int len) - { - {{trivia}} - len.$$ - } - } - """; - - var expectedCodeAfterCommit = $$""" - class Program - { - void M(int len) - { - {{trivia}} - for (int i = 0; i < len; i++) - { - $$ - } - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("#if true")] - [InlineData("#pragma warning disable CS0108")] - [InlineData("#nullable enable")] - public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInMethodTest2(string trivia) - { - var markupBeforeCommit = $$""" - class Program - { - void M(int len) - { - {{trivia}} - len.$$ - } - } - """; - - var expectedCodeAfterCommit = $$""" - class Program - { - void M(int len) - { - {{trivia}} - for (int i = 0; i < len; i++) - { - $$ - } - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("// comment")] - [InlineData("/* comment */")] - public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInGlobalStatementTest1(string trivia) - { - var markupBeforeCommit = $$""" - {{trivia}} - 10.$$ - """; - - var expectedCodeAfterCommit = $$""" - {{trivia}} - for (int i = 0; i < 10; i++) - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("#region test")] - [InlineData("#if true")] - [InlineData("#pragma warning disable CS0108")] - [InlineData("#nullable enable")] - public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInGlobalStatementTest2(string trivia) - { - var markupBeforeCommit = $$""" - {{trivia}} - 10.$$ - """; - - var expectedCodeAfterCommit = $$""" - - {{trivia}} - for (int i = 0; i < 10; i++) - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] - [MemberData(nameof(IntegerTypes))] - public async Task InsertInlineForSnippetWhenDottingBeforeContextualKeywordTest1(string intType) - { - var markupBeforeCommit = $$""" - using System.Collections.Generic; - - class C - { - void M({{intType}} @int) - { - @int.$$ - var a = 0; - } - } - """; - - var expectedCodeAfterCommit = $$""" - using System.Collections.Generic; - - class C - { - void M({{intType}} @int) - { - for ({{intType}} i = 0; i < @int; i++) - { - $$ - } - var a = 0; - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] - [MemberData(nameof(IntegerTypes))] - public async Task InsertInlineForSnippetWhenDottingBeforeContextualKeywordTest2(string intType) - { - var markupBeforeCommit = $$""" - using System.Collections.Generic; - - class C - { - void M({{intType}} @int, Task t) - { - @int.$$ - await t; - } - } - """; - - var expectedCodeAfterCommit = $$""" - using System.Collections.Generic; - - class C - { - void M({{intType}} @int, Task t) - { - for ({{intType}} i = 0; i < @int; i++) - { - $$ - } - await t; - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] - [InlineData("Task")] - [InlineData("Task")] - [InlineData("System.Threading.Tasks.Task")] - public async Task InsertInlineForSnippetWhenDottingBeforeNameSyntaxTest(string nameSyntax) - { - var markupBeforeCommit = $$""" - using System.Collections.Generic; - - class C - { - void M(int @int) - { - @int.$$ - {{nameSyntax}} t = null; - } - } - """; - - var expectedCodeAfterCommit = $$""" - using System.Collections.Generic; - - class C - { - void M(int @int) - { - for (int i = 0; i < @int; i++) - { - $$ - } - {{nameSyntax}} t = null; - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("int[]")] - [InlineData("Span")] - [InlineData("ReadOnlySpan")] - [InlineData("ImmutableArray")] - public async Task InsertInlineForSnippetForCommonTypesWithLengthPropertyTest(string type) - { - var markupBeforeCommit = $$""" - - - using System; - using System.Collections.Generic; - using System.Collections.Immutable; - - public class C - { - void M({{type.Replace("<", "<").Replace(">", ">")}} type) - { - type.$$ - } - } - - - """; - - var expectedCodeAfterCommit = $$""" - using System; - using System.Collections.Generic; - using System.Collections.Immutable; - - public class C - { - void M({{type}} type) - { - for (int i = 0; i < type.Length; i++) - { - $$ - } - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("public")] - [InlineData("internal")] - [InlineData("protected internal")] - public async Task InsertInlineForSnippetForTypeWithAccessibleLengthPropertyTest(string lengthPropertyAccessibility) - { - var markupBeforeCommit = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - {{lengthPropertyAccessibility}} int Length { get; } - } - """; - - var expectedCodeAfterCommit = $$""" - class C - { - void M(MyType type) - { - for (int i = 0; i < type.Length; i++) - { - $$ - } - } - } - - public class MyType - { - {{lengthPropertyAccessibility}} int Length { get; } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("")] - [InlineData("internal")] - [InlineData("protected internal")] - public async Task InsertInlineForSnippetForTypeWithAccessibleLengthPropertyGetterTest(string getterAccessibility) - { - var markupBeforeCommit = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public int Length { {{getterAccessibility}} get; } - } - """; - - var expectedCodeAfterCommit = $$""" - class C - { - void M(MyType type) - { - for (int i = 0; i < type.Length; i++) - { - $$ - } - } - } - - public class MyType - { - public int Length { {{getterAccessibility}} get; } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [MemberData(nameof(IntegerTypes))] - public async Task InsertInlineForSnippetForTypesWithLengthPropertyOfDifferentIntegerTypesTest(string integerType) - { - var markupBeforeCommit = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public {{integerType}} Length { get; } - } - """; - - var expectedCodeAfterCommit = $$""" - class C - { - void M(MyType type) - { - for ({{integerType}} i = 0; i < type.Length; i++) - { - $$ - } - } - } - - public class MyType - { - public {{integerType}} Length { get; } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertInlineForSnippetForTypeWithLengthPropertyInBaseClassTest() - { - var markupBeforeCommit = """ - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType : MyTypeBase - { - } - - public class MyTypeBase - { - public int Length { get; } - } - """; - - var expectedCodeAfterCommit = """ - class C - { - void M(MyType type) - { - for (int i = 0; i < type.Length; i++) - { - $$ - } - } - } - - public class MyType : MyTypeBase - { - } - - public class MyTypeBase - { - public int Length { get; } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task NoInlineForSnippetWhenLengthPropertyHasNoGetterTest() - { - var markup = """ - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public int Length { set { } } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfTheory] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - public async Task NoInlineForSnippetForInaccessibleLengthPropertyTest(string lengthPropertyAccessibility) - { - var markup = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - {{lengthPropertyAccessibility}} int Length { get; } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfTheory] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - public async Task NoInlineForSnippetForInaccessibleLengthPropertyGetterTest(string getterAccessibility) - { - var markup = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public int Length { {{getterAccessibility}} get; } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfTheory] - [MemberData(nameof(NotIntegerTypes))] - public async Task NoInlineForSnippetForLengthPropertyOfIncorrectTypeTest(string notIntegerType) - { - var markup = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public {{notIntegerType}} Length { get; } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfTheory] - [InlineData("List")] - [InlineData("HashSet")] - [InlineData("Dictionary")] - [InlineData("ImmutableList")] - public async Task InsertInlineForSnippetForCommonTypesWithCountPropertyTest(string type) - { - var markupBeforeCommit = $$""" - - - using System; - using System.Collections.Generic; - using System.Collections.Immutable; - - public class C - { - void M({{type.Replace("<", "<").Replace(">", ">")}} type) - { - type.$$ - } - } - - - """; - - var expectedCodeAfterCommit = $$""" - using System; - using System.Collections.Generic; - using System.Collections.Immutable; - - public class C - { - void M({{type}} type) - { - for (int i = 0; i < type.Count; i++) - { - $$ - } - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("public")] - [InlineData("internal")] - [InlineData("protected internal")] - public async Task InsertInlineForSnippetForTypeWithAccessibleCountPropertyTest(string countPropertyAccessibility) - { - var markupBeforeCommit = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - {{countPropertyAccessibility}} int Count { get; } - } - """; - - var expectedCodeAfterCommit = $$""" - class C - { - void M(MyType type) - { - for (int i = 0; i < type.Count; i++) - { - $$ - } - } - } - - public class MyType - { - {{countPropertyAccessibility}} int Count { get; } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("")] - [InlineData("internal")] - [InlineData("protected internal")] - public async Task InsertInlineForSnippetForTypeWithAccessibleCountPropertyGetterTest(string getterAccessibility) - { - var markupBeforeCommit = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public int Count { {{getterAccessibility}} get; } - } - """; - - var expectedCodeAfterCommit = $$""" - class C - { - void M(MyType type) - { - for (int i = 0; i < type.Count; i++) - { - $$ - } - } - } - - public class MyType - { - public int Count { {{getterAccessibility}} get; } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [MemberData(nameof(IntegerTypes))] - public async Task InsertInlineForSnippetForTypesWithCountPropertyOfDifferentIntegerTypesTest(string integerType) - { - var markupBeforeCommit = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public {{integerType}} Count { get; } - } - """; - - var expectedCodeAfterCommit = $$""" - class C - { - void M(MyType type) - { - for ({{integerType}} i = 0; i < type.Count; i++) - { - $$ - } - } - } - - public class MyType - { - public {{integerType}} Count { get; } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertInlineForSnippetForTypeWithCountPropertyInBaseClassTest() - { - var markupBeforeCommit = """ - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType : MyTypeBase - { - } - - public class MyTypeBase - { - public int Count { get; } - } - """; - - var expectedCodeAfterCommit = """ - class C - { - void M(MyType type) - { - for (int i = 0; i < type.Count; i++) - { - $$ - } - } - } - - public class MyType : MyTypeBase - { - } - - public class MyTypeBase - { - public int Count { get; } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task NoInlineForSnippetWhenCountPropertyHasNoGetterTest() - { - var markup = """ - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public int Count { set { } } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfTheory] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - public async Task NoInlineForSnippetForInaccessibleCountPropertyTest(string countPropertyAccessibility) - { - var markup = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - {{countPropertyAccessibility}} int Count { get; } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfTheory] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - public async Task NoInlineForSnippetForInaccessibleCountPropertyGetterTest(string getterAccessibility) - { - var markup = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public int Count { {{getterAccessibility}} get; } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfTheory] - [MemberData(nameof(NotIntegerTypes))] - public async Task NoInlineForSnippetForCountPropertyOfIncorrectTypeTest(string notIntegerType) - { - var markup = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public {{notIntegerType}} Count { get; } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfFact] - public async Task NoInlineForSnippetForTypeWithBothLengthAndCountPropertyTest() - { - var markup = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public int Length { get; } - public int Count { get; } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - public static IEnumerable IntegerTypes - { - get - { - return - [ - ["byte"], - ["sbyte"], - ["short"], - ["ushort"], - ["int"], - ["uint"], - ["long"], - ["ulong"], - ["nint"], - ["nuint"] - ]; - } - } - - public static IEnumerable NotIntegerTypes - { - get - { - return - [ - ["string"], - ["System.DateTime"], - ["System.Action"] - ]; - } - } -} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpForrSnippetCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpForrSnippetCompletionProviderTests.cs deleted file mode 100644 index 4e8d250141331..0000000000000 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpForrSnippetCompletionProviderTests.cs +++ /dev/null @@ -1,1283 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Collections.Generic; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Test.Utilities; -using Roslyn.Test.Utilities; -using Xunit; - -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; - -[Trait(Traits.Feature, Traits.Features.Completion)] -public class CSharpForrSnippetCompletionProviderTests : AbstractCSharpSnippetCompletionProviderTests -{ - protected override string ItemToCommit => "forr"; - - [WpfFact] - public async Task InsertForrSnippetInMethodTest() - { - await VerifyCustomCommitProviderAsync(""" - class Program - { - public void Method() - { - $$ - } - } - """, ItemToCommit, """ - class Program - { - public void Method() - { - for (int i = length - 1; i >= 0; i--) - { - $$ - } - } - } - """); - } - - [WpfFact] - public async Task InsertForrSnippetInMethodUsedIncrementorTest() - { - await VerifyCustomCommitProviderAsync(""" - class Program - { - public void Method() - { - int i; - $$ - } - } - """, ItemToCommit, """ - class Program - { - public void Method() - { - int i; - for (int j = length - 1; j >= 0; j--) - { - $$ - } - } - } - """); - } - - [WpfFact] - public async Task InsertForrSnippetInMethodUsedIncrementorsTest() - { - await VerifyCustomCommitProviderAsync(""" - class Program - { - public void Method() - { - int i, j, k; - $$ - } - } - """, ItemToCommit, """ - class Program - { - public void Method() - { - int i, j, k; - for (int i1 = length - 1; i1 >= 0; i1--) - { - $$ - } - } - } - """); - } - - [WpfFact] - public async Task InsertForrSnippetInGlobalContextTest() - { - await VerifyCustomCommitProviderAsync(""" - $$ - """, ItemToCommit, """ - for (int i = length - 1; i >= 0; i--) - { - $$ - } - """); - } - - [WpfFact] - public async Task InsertForrSnippetInConstructorTest() - { - await VerifyCustomCommitProviderAsync(""" - class Program - { - public Program() - { - $$ - } - } - """, ItemToCommit, """ - class Program - { - public Program() - { - for (int i = length - 1; i >= 0; i--) - { - $$ - } - } - } - """); - } - - [WpfFact] - public async Task InsertForrSnippetInLocalFunctionTest() - { - // TODO: fix this test when bug with simplifier failing to find correct node is fixed - await VerifyCustomCommitProviderAsync(""" - class Program - { - public void Method() - { - void LocalFunction() - { - $$ - } - } - } - """, ItemToCommit, """ - class Program - { - public void Method() - { - void LocalFunction() - { - for (global::System.Int32 i = (length) - (1); i >= 0; i--) - { - $$ - } - } - } - } - """); - } - - [WpfFact] - public async Task InsertForrSnippetInAnonymousFunctionTest() - { - // TODO: fix this test when bug with simplifier failing to find correct node is fixed - await VerifyCustomCommitProviderAsync(""" - class Program - { - public void Method() - { - var action = delegate() - { - $$ - }; - } - } - """, ItemToCommit, """ - class Program - { - public void Method() - { - var action = delegate() - { - for (global::System.Int32 i = (length) - (1); i >= 0; i--) - { - $$ - } - }; - } - } - """); - } - - [WpfFact] - public async Task InsertForrSnippetInParenthesizedLambdaExpressionTest() - { - // TODO: fix this test when bug with simplifier failing to find correct node is fixed - await VerifyCustomCommitProviderAsync(""" - class Program - { - public void Method() - { - var action = () => - { - $$ - }; - } - } - """, ItemToCommit, """ - class Program - { - public void Method() - { - var action = () => - { - for (global::System.Int32 i = (length) - (1); i >= 0; i--) - { - $$ - } - }; - } - } - """); - } - - [WpfFact] - public async Task TryToProduceVarWithSpecificCodeStyleTest() - { - // In non-inline reversed for snippet type of expression `length - 1` is unknown, - // so it cannot be simplified to `var`. Therefore having explicit `int` type here is expected - await VerifyCustomCommitProviderAsync(""" - - - class Program - { - public void Method() - { - $$ - } - } - - root = true - - [*] - # IDE0008: Use explicit type - csharp_style_var_for_built_in_types = true - - - - """, ItemToCommit, """ - class Program - { - public void Method() - { - for (int i = length - 1; i >= 0; i--) - { - $$ - } - } - } - """); - } - - [WpfTheory] - [MemberData(nameof(IntegerTypes))] - public async Task InsertInlineForrSnippetInMethodTest(string inlineExpressionType) - { - await VerifyCustomCommitProviderAsync($$""" - class Program - { - public void Method({{inlineExpressionType}} l) - { - l.$$ - } - } - """, ItemToCommit, $$""" - class Program - { - public void Method({{inlineExpressionType}} l) - { - for ({{inlineExpressionType}} i = l - 1; i >= 0; i--) - { - $$ - } - } - } - """); - } - - [WpfTheory] - [MemberData(nameof(IntegerTypes))] - public async Task InsertInlineForrSnippetInGlobalContextTest(string inlineExpressionType) - { - await VerifyCustomCommitProviderAsync($$""" - {{inlineExpressionType}} l; - l.$$ - """, ItemToCommit, $$""" - {{inlineExpressionType}} l; - for ({{inlineExpressionType}} i = l - 1; i >= 0; i--) - { - $$ - } - """); - } - - [WpfTheory] - [MemberData(nameof(NotIntegerTypes))] - public async Task NoInlineForrSnippetForIncorrectTypeInMethodTest(string inlineExpressionType) - { - var markup = $$""" - class Program - { - public void Method({{inlineExpressionType}} l) - { - l.$$ - } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfTheory] - [MemberData(nameof(NotIntegerTypes))] - public async Task NoInlineForrSnippetForIncorrectTypeInGlobalContextTest(string inlineExpressionType) - { - var markup = $$""" - {{inlineExpressionType}} l; - l.$$ - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfFact] - public async Task ProduceVarWithSpecificCodeStyleForInlineSnippetTest() - { - await VerifyCustomCommitProviderAsync(""" - - - class Program - { - public void Method(int l) - { - l.$$ - } - } - - root = true - - [*] - # IDE0008: Use explicit type - csharp_style_var_for_built_in_types = true - - - - """, ItemToCommit, """ - class Program - { - public void Method(int l) - { - for (var i = l - 1; i >= 0; i--) - { - $$ - } - } - } - """); - } - - [WpfFact] - public async Task NoInlineForrSnippetNotDirectlyExpressionStatementTest() - { - var markup = """ - class Program - { - public void Method(int l) - { - System.Console.WriteLine(l.$$); - } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfTheory] - [InlineData("// comment")] - [InlineData("/* comment */")] - [InlineData("#region test")] - public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInMethodTest1(string trivia) - { - var markupBeforeCommit = $$""" - class Program - { - void M(int len) - { - {{trivia}} - len.$$ - } - } - """; - - var expectedCodeAfterCommit = $$""" - class Program - { - void M(int len) - { - {{trivia}} - for (int i = len - 1; i >= 0; i--) - { - $$ - } - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("#if true")] - [InlineData("#pragma warning disable CS0108")] - [InlineData("#nullable enable")] - public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInMethodTest2(string trivia) - { - var markupBeforeCommit = $$""" - class Program - { - void M(int len) - { - {{trivia}} - len.$$ - } - } - """; - - var expectedCodeAfterCommit = $$""" - class Program - { - void M(int len) - { - {{trivia}} - for (int i = len - 1; i >= 0; i--) - { - $$ - } - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("// comment")] - [InlineData("/* comment */")] - public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInGlobalStatementTest1(string trivia) - { - var markupBeforeCommit = $$""" - {{trivia}} - 10.$$ - """; - - var expectedCodeAfterCommit = $$""" - {{trivia}} - for (int i = 10 - 1; i >= 0; i--) - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("#region test")] - [InlineData("#if true")] - [InlineData("#pragma warning disable CS0108")] - [InlineData("#nullable enable")] - public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInGlobalStatementTest2(string trivia) - { - var markupBeforeCommit = $$""" - {{trivia}} - 10.$$ - """; - - var expectedCodeAfterCommit = $$""" - - {{trivia}} - for (int i = 10 - 1; i >= 0; i--) - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] - [MemberData(nameof(IntegerTypes))] - public async Task InsertInlineForrSnippetWhenDottingBeforeContextualKeywordTest1(string intType) - { - var markupBeforeCommit = $$""" - using System.Collections.Generic; - - class C - { - void M({{intType}} @int) - { - @int.$$ - var a = 0; - } - } - """; - - var expectedCodeAfterCommit = $$""" - using System.Collections.Generic; - - class C - { - void M({{intType}} @int) - { - for ({{intType}} i = @int - 1; i >= 0; i--) - { - $$ - } - var a = 0; - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] - [MemberData(nameof(IntegerTypes))] - public async Task InsertInlineForrSnippetWhenDottingBeforeContextualKeywordTest2(string intType) - { - var markupBeforeCommit = $$""" - using System.Collections.Generic; - - class C - { - void M({{intType}} @int, Task t) - { - @int.$$ - await t; - } - } - """; - - var expectedCodeAfterCommit = $$""" - using System.Collections.Generic; - - class C - { - void M({{intType}} @int, Task t) - { - for ({{intType}} i = @int - 1; i >= 0; i--) - { - $$ - } - await t; - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] - [InlineData("Task")] - [InlineData("Task")] - [InlineData("System.Threading.Tasks.Task")] - public async Task InsertInlineForrSnippetWhenDottingBeforeNameSyntaxTest(string nameSyntax) - { - var markupBeforeCommit = $$""" - using System.Collections.Generic; - - class C - { - void M(int @int) - { - @int.$$ - {{nameSyntax}} t = null; - } - } - """; - - var expectedCodeAfterCommit = $$""" - using System.Collections.Generic; - - class C - { - void M(int @int) - { - for (int i = @int - 1; i >= 0; i--) - { - $$ - } - {{nameSyntax}} t = null; - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("int[]")] - [InlineData("Span")] - [InlineData("ReadOnlySpan")] - [InlineData("ImmutableArray")] - public async Task InsertInlineForrSnippetForCommonTypesWithLengthPropertyTest(string type) - { - var markupBeforeCommit = $$""" - - - using System; - using System.Collections.Generic; - using System.Collections.Immutable; - - public class C - { - void M({{type.Replace("<", "<").Replace(">", ">")}} type) - { - type.$$ - } - } - - - """; - - var expectedCodeAfterCommit = $$""" - using System; - using System.Collections.Generic; - using System.Collections.Immutable; - - public class C - { - void M({{type}} type) - { - for (int i = type.Length - 1; i >= 0; i--) - { - $$ - } - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("public")] - [InlineData("internal")] - [InlineData("protected internal")] - public async Task InsertInlineForrSnippetForTypeWithAccessibleLengthPropertyTest(string lengthPropertyAccessibility) - { - var markupBeforeCommit = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - {{lengthPropertyAccessibility}} int Length { get; } - } - """; - - var expectedCodeAfterCommit = $$""" - class C - { - void M(MyType type) - { - for (int i = type.Length - 1; i >= 0; i--) - { - $$ - } - } - } - - public class MyType - { - {{lengthPropertyAccessibility}} int Length { get; } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("")] - [InlineData("internal")] - [InlineData("protected internal")] - public async Task InsertInlineForrSnippetForTypeWithAccessibleLengthPropertyGetterTest(string getterAccessibility) - { - var markupBeforeCommit = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public int Length { {{getterAccessibility}} get; } - } - """; - - var expectedCodeAfterCommit = $$""" - class C - { - void M(MyType type) - { - for (int i = type.Length - 1; i >= 0; i--) - { - $$ - } - } - } - - public class MyType - { - public int Length { {{getterAccessibility}} get; } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [MemberData(nameof(IntegerTypes))] - public async Task InsertInlineForrSnippetForTypesWithLengthPropertyOfDifferentIntegerTypesTest(string integerType) - { - var markupBeforeCommit = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public {{integerType}} Length { get; } - } - """; - - var expectedCodeAfterCommit = $$""" - class C - { - void M(MyType type) - { - for ({{integerType}} i = type.Length - 1; i >= 0; i--) - { - $$ - } - } - } - - public class MyType - { - public {{integerType}} Length { get; } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertInlineForrSnippetForTypeWithLengthPropertyInBaseClassTest() - { - var markupBeforeCommit = """ - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType : MyTypeBase - { - } - - public class MyTypeBase - { - public int Length { get; } - } - """; - - var expectedCodeAfterCommit = """ - class C - { - void M(MyType type) - { - for (int i = type.Length - 1; i >= 0; i--) - { - $$ - } - } - } - - public class MyType : MyTypeBase - { - } - - public class MyTypeBase - { - public int Length { get; } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task NoInlineForrSnippetWhenLengthPropertyHasNoGetterTest() - { - var markup = """ - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public int Length { set { } } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfTheory] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - public async Task NoInlineForrSnippetForInaccessibleLengthPropertyTest(string lengthPropertyAccessibility) - { - var markup = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - {{lengthPropertyAccessibility}} int Length { get; } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfTheory] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - public async Task NoInlineForrSnippetForInaccessibleLengthPropertyGetterTest(string getterAccessibility) - { - var markup = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public int Length { {{getterAccessibility}} get; } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfTheory] - [MemberData(nameof(NotIntegerTypes))] - public async Task NoInlineForrSnippetForLengthPropertyOfIncorrectTypeTest(string notIntegerType) - { - var markup = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public {{notIntegerType}} Length { get; } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfTheory] - [InlineData("List")] - [InlineData("HashSet")] - [InlineData("Dictionary")] - [InlineData("ImmutableList")] - public async Task InsertInlineForrSnippetForCommonTypesWithCountPropertyTest(string type) - { - var markupBeforeCommit = $$""" - - - using System; - using System.Collections.Generic; - using System.Collections.Immutable; - - public class C - { - void M({{type.Replace("<", "<").Replace(">", ">")}} type) - { - type.$$ - } - } - - - """; - - var expectedCodeAfterCommit = $$""" - using System; - using System.Collections.Generic; - using System.Collections.Immutable; - - public class C - { - void M({{type}} type) - { - for (int i = type.Count - 1; i >= 0; i--) - { - $$ - } - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("public")] - [InlineData("internal")] - [InlineData("protected internal")] - public async Task InsertInlineForrSnippetForTypeWithAccessibleCountPropertyTest(string countPropertyAccessibility) - { - var markupBeforeCommit = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - {{countPropertyAccessibility}} int Count { get; } - } - """; - - var expectedCodeAfterCommit = $$""" - class C - { - void M(MyType type) - { - for (int i = type.Count - 1; i >= 0; i--) - { - $$ - } - } - } - - public class MyType - { - {{countPropertyAccessibility}} int Count { get; } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("")] - [InlineData("internal")] - [InlineData("protected internal")] - public async Task InsertInlineForrSnippetForTypeWithAccessibleCountPropertyGetterTest(string getterAccessibility) - { - var markupBeforeCommit = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public int Count { {{getterAccessibility}} get; } - } - """; - - var expectedCodeAfterCommit = $$""" - class C - { - void M(MyType type) - { - for (int i = type.Count - 1; i >= 0; i--) - { - $$ - } - } - } - - public class MyType - { - public int Count { {{getterAccessibility}} get; } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [MemberData(nameof(IntegerTypes))] - public async Task InsertInlineForrSnippetForTypesWithCountPropertyOfDifferentIntegerTypesTest(string integerType) - { - var markupBeforeCommit = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public {{integerType}} Count { get; } - } - """; - - var expectedCodeAfterCommit = $$""" - class C - { - void M(MyType type) - { - for ({{integerType}} i = type.Count - 1; i >= 0; i--) - { - $$ - } - } - } - - public class MyType - { - public {{integerType}} Count { get; } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertInlineForrSnippetForTypeWithCountPropertyInBaseClassTest() - { - var markupBeforeCommit = """ - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType : MyTypeBase - { - } - - public class MyTypeBase - { - public int Count { get; } - } - """; - - var expectedCodeAfterCommit = """ - class C - { - void M(MyType type) - { - for (int i = type.Count - 1; i >= 0; i--) - { - $$ - } - } - } - - public class MyType : MyTypeBase - { - } - - public class MyTypeBase - { - public int Count { get; } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task NoInlineForrSnippetWhenCountPropertyHasNoGetterTest() - { - var markup = """ - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public int Count { set { } } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfTheory] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - public async Task NoInlineForrSnippetForInaccessibleCountPropertyTest(string countPropertyAccessibility) - { - var markup = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - {{countPropertyAccessibility}} int Count { get; } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfTheory] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - public async Task NoInlineForrSnippetForInaccessibleCountPropertyGetterTest(string getterAccessibility) - { - var markup = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public int Count { {{getterAccessibility}} get; } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfTheory] - [MemberData(nameof(NotIntegerTypes))] - public async Task NoInlineForrSnippetForCountPropertyOfIncorrectTypeTest(string notIntegerType) - { - var markup = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public {{notIntegerType}} Count { get; } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - [WpfFact] - public async Task NoInlineForrSnippetForTypeWithBothLengthAndCountPropertyTest() - { - var markup = $$""" - class C - { - void M(MyType type) - { - type.$$ - } - } - - public class MyType - { - public int Length { get; } - public int Count { get; } - } - """; - - await VerifyItemIsAbsentAsync(markup, ItemToCommit); - } - - public static IEnumerable IntegerTypes - { - get - { - return - [ - ["byte"], - ["sbyte"], - ["short"], - ["ushort"], - ["int"], - ["uint"], - ["long"], - ["ulong"], - ["nint"], - ["nuint"] - ]; - } - } - - public static IEnumerable NotIntegerTypes - { - get - { - return - [ - ["string"], - ["System.DateTime"], - ["System.Action"] - ]; - } - } -} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpIfSnippetCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpIfSnippetCompletionProviderTests.cs deleted file mode 100644 index 4b1021190adc4..0000000000000 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpIfSnippetCompletionProviderTests.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; - -public class CSharpIfSnippetCompletionProviderTests : AbstractCSharpConditionalBlockSnippetCompletionProviderTests -{ - protected override string ItemToCommit => "if"; -} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpInterfaceSnippetCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpInterfaceSnippetCompletionProviderTests.cs deleted file mode 100644 index 046e72a7a43f2..0000000000000 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpInterfaceSnippetCompletionProviderTests.cs +++ /dev/null @@ -1,412 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Test.Utilities; -using Roslyn.Test.Utilities; -using Xunit; - -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; - -[Trait(Traits.Feature, Traits.Features.Completion)] -public class CSharpInterfaceSnippetCompletionProviderTests : AbstractCSharpSnippetCompletionProviderTests -{ - protected override string ItemToCommit => "interface"; - - [WpfFact] - public async Task InsertInterfaceSnippetInNamespaceTest() - { - var markupBeforeCommit = - """ - namespace Namespace - { - $$ - } - """; - - var expectedCodeAfterCommit = - """ - namespace Namespace - { - interface MyInterface - { - $$ - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertInterfaceSnippetInFileScopedNamespaceTest() - { - var markupBeforeCommit = - """ - namespace Namespace; - - $$ - """; - - var expectedCodeAfterCommit = - """ - namespace Namespace; - - interface MyInterface - { - $$ - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertInterfaceSnippetTest() - { - var markupBeforeCommit = -@"$$"; - - var expectedCodeAfterCommit = - """ - interface MyInterface - { - $$ - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertInterfaceTopLevelSnippetTest() - { - var markupBeforeCommit = - """ - System.Console.WriteLine(); - $$ - """; - - var expectedCodeAfterCommit = - """ - System.Console.WriteLine(); - interface MyInterface - { - $$ - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertInterfaceSnippetInClassTest() - { - var markupBeforeCommit = - """ - class MyClass - { - $$ - } - """; - - var expectedCodeAfterCommit = - """ - class MyClass - { - interface MyInterface - { - $$ - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertInterfaceSnippetInRecordTest() - { - var markupBeforeCommit = - """ - record MyRecord - { - $$ - } - """; - - var expectedCodeAfterCommit = - """ - record MyRecord - { - interface MyInterface - { - $$ - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertInterfaceSnippetInStructTest() - { - var markupBeforeCommit = - """ - struct MyStruct - { - $$ - } - """; - - var expectedCodeAfterCommit = - """ - struct MyStruct - { - interface MyInterface - { - $$ - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertInterfaceSnippetInInterfaceTest() - { - var markupBeforeCommit = - """ - interface MyInterface - { - $$ - } - """; - - var expectedCodeAfterCommit = - """ - interface MyInterface - { - interface MyInterface1 - { - $$ - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertInterfaceSnippetWithModifiersTest() - { - var markupBeforeCommit = - $@" - - - -$$ - - -root = true - -[*] -# IDE0008: Use explicit type -dotnet_style_require_accessibility_modifiers = always - - -"; - var expectedCodeAfterCommit = - $@" -public interface MyInterface -{{ - $$ -}} -"; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task NoInterfaceSnippetInEnumTest() - { - var markupBeforeCommit = - """ - enum MyEnum - { - $$ - } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoInteraceSnippetInMethodTest() - { - var markupBeforeCommit = - """ - class Program - { - public void Method() - { - $$ - } - } - """; - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoInterfaceSnippetInConstructorTest() - { - var markupBeforeCommit = - """ - class Program - { - public Program() - { - $$ - } - } - """; - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfTheory] - [InlineData("public")] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - [InlineData("protected internal")] - public async Task AfterAccessibilityModifier(string modifier) - { - var markupBeforeCommit = $"{modifier} $$"; - - var expectedCodeAfterCommit = $$""" - {{modifier}} interface MyInterface - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("public")] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - [InlineData("protected internal")] - public async Task AfterAccessibilityModifier_RequireAccessibilityModifiers(string modifier) - { - var markupBeforeCommit = $$""" - - - {{modifier}} $$ - - root = true - - [*] - # IDE0008: Use explicit type - dotnet_style_require_accessibility_modifiers = always - - - - """; - - var expectedCodeAfterCommit = $$""" - {{modifier}} interface MyInterface - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("unsafe")] - public async Task InsertInterfaceSnippetAfterValidModifiersTest(string modifier) - { - var markupBeforeCommit = $"{modifier} $$"; - - var expectedCodeAfterCommit = $$""" - {{modifier}} interface MyInterface - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("abstract")] - [InlineData("sealed")] - [InlineData("static")] - [InlineData("ref")] - [InlineData("readonly")] - public async Task NoInterfaceSnippetAfterInvalidModifiersTest(string modifier) - { - var markupBeforeCommit = $"{modifier} $$"; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfTheory, WorkItem("https://github.com/dotnet/roslyn/issues/69600")] - [InlineData("public")] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - [InlineData("protected internal")] - public async Task NoAdditionalAccessibilityModifiersIfAfterPartialKeywordTest(string modifier) - { - var markupBeforeCommit = $$""" - - - {{modifier}} partial $$ - - root = true - - [*] - # IDE0008: Use explicit type - dotnet_style_require_accessibility_modifiers = always - - - - """; - - var expectedCodeAfterCommit = $$""" - {{modifier}} partial interface MyInterface - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/69600")] - public async Task EnsureCorrectModifierOrderAfterPartialKeywordTest() - { - var markupBeforeCommit = """ - - - partial $$ - - root = true - - [*] - # IDE0008: Use explicit type - dotnet_style_require_accessibility_modifiers = always - - - - """; - - var expectedCodeAfterCommit = """ - public partial interface MyInterface - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } -} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpStructSnippetCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpStructSnippetCompletionProviderTests.cs deleted file mode 100644 index f09a3bc6e900e..0000000000000 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpStructSnippetCompletionProviderTests.cs +++ /dev/null @@ -1,558 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Test.Utilities; -using Roslyn.Test.Utilities; -using Xunit; - -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; - -[Trait(Traits.Feature, Traits.Features.Completion)] -public class CSharpStructSnippetCompletionProviderTests : AbstractCSharpSnippetCompletionProviderTests -{ - protected override string ItemToCommit => "struct"; - - [WpfFact] - public async Task InsertStructSnippetInNamespaceTest() - { - var markupBeforeCommit = - """ - namespace Namespace - { - $$ - } - """; - - var expectedCodeAfterCommit = - """ - namespace Namespace - { - struct MyStruct - { - $$ - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertStructSnippetInFileScopedNamespaceTest() - { - var markupBeforeCommit = - """ - namespace Namespace; - - $$ - """; - - var expectedCodeAfterCommit = - """ - namespace Namespace; - - struct MyStruct - { - $$ - } - """ -; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertStructSnippetTest() - { - var markupBeforeCommit = -@"$$"; - - var expectedCodeAfterCommit = - """ - struct MyStruct - { - $$ - } - """ -; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertStructTopLevelSnippetTest() - { - var markupBeforeCommit = - """ - System.Console.WriteLine(); - $$ - """; - - var expectedCodeAfterCommit = - """ - System.Console.WriteLine(); - struct MyStruct - { - $$ - } - """ -; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertStructSnippetInClassTest() - { - var markupBeforeCommit = - """ - struct MyClass - { - $$ - } - """ -; - - var expectedCodeAfterCommit = - """ - struct MyClass - { - struct MyStruct - { - $$ - } - } - """ -; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertStructSnippetInRecordTest() - { - var markupBeforeCommit = - """ - record MyRecord - { - $$ - } - """; - - var expectedCodeAfterCommit = - """ - record MyRecord - { - struct MyStruct - { - $$ - } - } - """ -; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertStructSnippetInStructTest() - { - var markupBeforeCommit = - """ - struct MyStruct - { - $$ - } - """; - - var expectedCodeAfterCommit = - """ - struct MyStruct - { - struct MyStruct1 - { - $$ - } - } - """ -; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertStructSnippetInInterfaceTest() - { - var markupBeforeCommit = - """ - interface MyInterface - { - $$ - } - """; - - var expectedCodeAfterCommit = - """ - interface MyInterface - { - struct MyStruct - { - $$ - } - } - """ -; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertStructSnippetWithModifiersTest() - { - var markupBeforeCommit = - $@" - - - -$$ - - -root = true - -[*] -# IDE0008: Use explicit type -dotnet_style_require_accessibility_modifiers = always - - -"; - var expectedCodeAfterCommit = - $@" -public struct MyStruct -{{ - $$ -}} -"; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task NoStructSnippetInEnumTest() - { - var markupBeforeCommit = - """ - enum MyEnum - { - $$ - } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoStructSnippetInMethodTest() - { - var markupBeforeCommit = - """ - struct Program - { - public void Method() - { - $$ - } - } - """ -; - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfFact] - public async Task NoStructSnippetInConstructorTest() - { - var markupBeforeCommit = - """ - struct Program - { - public Program() - { - $$ - } - } - """ -; - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfTheory] - [InlineData("public")] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - [InlineData("protected internal")] - public async Task AfterAccessibilityModifier(string modifier) - { - var markupBeforeCommit = $"{modifier} $$"; - - var expectedCodeAfterCommit = $$""" - {{modifier}} struct MyStruct - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("public")] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - [InlineData("protected internal")] - public async Task AfterAccessibilityModifier_RequireAccessibilityModifiers(string modifier) - { - var markupBeforeCommit = $$""" - - - {{modifier}} $$ - - root = true - - [*] - # IDE0008: Use explicit type - dotnet_style_require_accessibility_modifiers = always - - - - """; - - var expectedCodeAfterCommit = $$""" - {{modifier}} struct MyStruct - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("ref")] - [InlineData("readonly")] - [InlineData("unsafe")] - public async Task InsertStructSnippetAfterValidModifiersTest(string modifier) - { - var markupBeforeCommit = $"{modifier} $$"; - - var expectedCodeAfterCommit = $$""" - {{modifier}} struct MyStruct - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfTheory] - [InlineData("abstract")] - [InlineData("sealed")] - [InlineData("static")] - public async Task NoStructSnippetAfterInvalidModifiersTest(string modifier) - { - var markupBeforeCommit = $"{modifier} $$"; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); - } - - [WpfTheory, WorkItem("https://github.com/dotnet/roslyn/issues/69600")] - [InlineData("public")] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - [InlineData("protected internal")] - public async Task NoAdditionalAccessibilityModifiersIfAfterPartialKeywordTest(string modifier) - { - var markupBeforeCommit = $$""" - - - {{modifier}} partial $$ - - root = true - - [*] - # IDE0008: Use explicit type - dotnet_style_require_accessibility_modifiers = always - - - - """; - - var expectedCodeAfterCommit = $$""" - {{modifier}} partial struct MyStruct - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/69600")] - public async Task EnsureCorrectModifierOrderAfterPartialKeywordTest() - { - var markupBeforeCommit = """ - - - partial $$ - - root = true - - [*] - # IDE0008: Use explicit type - dotnet_style_require_accessibility_modifiers = always - - - - """; - - var expectedCodeAfterCommit = """ - public partial struct MyStruct - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/69600")] - public async Task EnsureCorrectModifierOrderAfterPartialKeywordTest_InvalidPreferredModifiersList() - { - var markupBeforeCommit = """ - - - partial $$ - - [*] - dotnet_style_require_accessibility_modifiers = always - - csharp_preferred_modifier_order = invalid! - - - - """; - - var expectedCodeAfterCommit = """ - public partial struct MyStruct - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task EnsureCorrectModifierOrderFromOptionsTest_PublicModifierBeforeAllOthers() - { - var markupBeforeCommit = """ - - - readonly ref $$ - - [*] - dotnet_style_require_accessibility_modifiers = always - - csharp_preferred_modifier_order = public,readonly,ref - - - - """; - - var expectedCodeAfterCommit = """ - public readonly ref struct MyStruct - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task EnsureCorrectModifierOrderFromOptionsTest_PublicModifierBeforeAllOthers_NotAllModifiersInTheList() - { - var markupBeforeCommit = """ - - - readonly ref $$ - - [*] - dotnet_style_require_accessibility_modifiers = always - - csharp_preferred_modifier_order = public,readonly - - - - """; - - var expectedCodeAfterCommit = """ - public readonly ref struct MyStruct - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task EnsureCorrectModifierOrderFromOptionsTest_PublicModifierBetweenOthers() - { - var markupBeforeCommit = """ - - - readonly ref $$ - - [*] - dotnet_style_require_accessibility_modifiers = always - - csharp_preferred_modifier_order = readonly,public,ref - - - - """; - - var expectedCodeAfterCommit = """ - readonly public ref struct MyStruct - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task EnsureCorrectModifierOrderFromOptionsTest_PublicModifierAfterAllOthers() - { - var markupBeforeCommit = """ - - - readonly ref $$ - - [*] - dotnet_style_require_accessibility_modifiers = always - - csharp_preferred_modifier_order = readonly,ref,public - - - - """; - - var expectedCodeAfterCommit = """ - readonly ref public struct MyStruct - { - $$ - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } -} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpWhileSnippetCompletionProviderTests.cs b/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpWhileSnippetCompletionProviderTests.cs deleted file mode 100644 index e22eaa9e5df21..0000000000000 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpWhileSnippetCompletionProviderTests.cs +++ /dev/null @@ -1,10 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; - -public class CSharpWhileSnippetCompletionProviderTests : AbstractCSharpConditionalBlockSnippetCompletionProviderTests -{ - protected override string ItemToCommit => "while"; -} diff --git a/src/Features/CSharp/Portable/Snippets/AbstractCSharpTypeSnippetProvider.cs b/src/Features/CSharp/Portable/Snippets/AbstractCSharpTypeSnippetProvider.cs index af4945b17c570..322ae299d7923 100644 --- a/src/Features/CSharp/Portable/Snippets/AbstractCSharpTypeSnippetProvider.cs +++ b/src/Features/CSharp/Portable/Snippets/AbstractCSharpTypeSnippetProvider.cs @@ -27,6 +27,8 @@ internal abstract class AbstractCSharpTypeSnippetProvider ValidModifiers { get; } + protected virtual bool CanBePartial => true; + protected override bool IsValidSnippetLocationCore(SnippetContext context, CancellationToken cancellationToken) { var syntaxContext = (CSharpSyntaxContext)context.SyntaxContext; @@ -36,7 +38,7 @@ protected override bool IsValidSnippetLocationCore(SnippetContext context, Cance syntaxContext.IsTypeDeclarationContext( validModifiers: ValidModifiers, validTypeDeclarations: SyntaxKindSet.ClassInterfaceStructRecordTypeDeclarations, - canBePartial: true, + canBePartial: CanBePartial, cancellationToken: cancellationToken); } diff --git a/src/Features/CSharp/Portable/Snippets/CSharpEnumSnippetProvider.cs b/src/Features/CSharp/Portable/Snippets/CSharpEnumSnippetProvider.cs index 1ffa575749b5a..84ad261a5de86 100644 --- a/src/Features/CSharp/Portable/Snippets/CSharpEnumSnippetProvider.cs +++ b/src/Features/CSharp/Portable/Snippets/CSharpEnumSnippetProvider.cs @@ -37,6 +37,8 @@ internal sealed class CSharpEnumSnippetProvider() : AbstractCSharpTypeSnippetPro protected override ISet ValidModifiers => s_validModifiers; + protected override bool CanBePartial => false; + protected override async Task GenerateTypeDeclarationAsync(Document document, int position, CancellationToken cancellationToken) { var generator = SyntaxGenerator.GetGenerator(document); diff --git a/src/Features/CSharpTest/Snippets/AbstractCSharpAutoPropertySnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/AbstractCSharpAutoPropertySnippetProviderTests.cs new file mode 100644 index 0000000000000..8dbe4ef2d7abb --- /dev/null +++ b/src/Features/CSharpTest/Snippets/AbstractCSharpAutoPropertySnippetProviderTests.cs @@ -0,0 +1,167 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Diagnostics.CodeAnalysis; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.CodeAnalysis.Testing; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; + +[Trait(Traits.Feature, Traits.Features.Snippets)] +public abstract class AbstractCSharpAutoPropertySnippetProviderTests : AbstractCSharpSnippetProviderTests +{ + protected abstract string DefaultPropertyBlockText { get; } + + [Fact] + public async Task NoSnippetInBlockNamespaceTest() + { + await VerifySnippetIsAbsentAsync(""" + namespace Namespace + { + $$ + } + """); + } + + [Fact] + public async Task NoSnippetInFileScopedNamespaceTest() + { + await VerifySnippetIsAbsentAsync(""" + namespace Namespace + + $$ + """); + } + + [Fact] + public async Task NoSnippetInTopLevelContextTest() + { + await VerifySnippetIsAbsentAsync(""" + System.Console.WriteLine(); + $$ + """); + } + + [Fact] + public async Task InsertSnippetInClassTest() + { + await VerifyDefaultPropertyAsync(""" + class MyClass + { + $$ + } + """); + } + + [Fact] + public async Task InsertSnippetInRecordTest() + { + await VerifyDefaultPropertyAsync(""" + record MyRecord + { + $$ + } + """); + } + + [Fact] + public async Task InsertSnippetInStructTest() + { + await VerifyDefaultPropertyAsync(""" + struct MyStruct + { + $$ + } + """); + } + + [Fact] + public abstract Task InsertSnippetInReadonlyStructTest(); + + [Fact] + public abstract Task InsertSnippetInReadonlyStructTest_ReadonlyModifierInOtherPartialDeclaration(); + + [Fact] + public abstract Task InsertSnippetInReadonlyStructTest_ReadonlyModifierInOtherPartialDeclaration_MissingPartialModifier(); + + // This case might produce non-default results for different snippets (e.g. no `set` accessor in 'propg' snippet), + // so it is tested separately for all of them + [Fact] + public abstract Task InsertSnippetInInterfaceTest(); + + [Fact] + public async Task InsertSnippetNamingTest() + { + await VerifyDefaultPropertyAsync(""" + class MyClass + { + public int MyProperty { get; set; } + $$ + } + """, "MyProperty1"); + } + + [Fact] + public async Task NoSnippetInEnumTest() + { + await VerifySnippetIsAbsentAsync(""" + enum MyEnum + { + $$ + } + """); + } + + [Fact] + public async Task NoSnippetInMethodTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public void Method() + { + $$ + } + } + """); + } + + [Fact] + public async Task NoSnippetInConstructorTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public Program() + { + $$ + } + } + """); + } + + [Theory] + [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))] + public async Task InsertSnippetAfterAccessibilityModifierTest(string modifier) + { + await VerifyPropertyAsync($$""" + class Program + { + {{modifier}} $$ + } + """, $$"""{|0:int|} {|1:MyProperty|} {{DefaultPropertyBlockText}}"""); + } + + protected async Task VerifyPropertyAsync([StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string markup, string propertyMarkup) + { + TestFileMarkupParser.GetPosition(markup, out var code, out var position); + var expectedCode = code.Insert(position, propertyMarkup + "$$"); + await VerifySnippetAsync(markup, expectedCode); + } + + protected Task VerifyDefaultPropertyAsync([StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string markup, string propertyName = "MyProperty") + => VerifyPropertyAsync(markup, $$"""public {|0:int|} {|1:{{propertyName}}|} {{DefaultPropertyBlockText}}"""); +} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/AbstractCSharpConditionalBlockSnippetCompletionProviderTests.cs b/src/Features/CSharpTest/Snippets/AbstractCSharpConditionalBlockSnippetProviderTests.cs similarity index 51% rename from src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/AbstractCSharpConditionalBlockSnippetCompletionProviderTests.cs rename to src/Features/CSharpTest/Snippets/AbstractCSharpConditionalBlockSnippetProviderTests.cs index 7831a0e46ece3..3b46139dd4bbe 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/AbstractCSharpConditionalBlockSnippetCompletionProviderTests.cs +++ b/src/Features/CSharpTest/Snippets/AbstractCSharpConditionalBlockSnippetProviderTests.cs @@ -7,15 +7,15 @@ using Roslyn.Test.Utilities; using Xunit; -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; -[Trait(Traits.Feature, Traits.Features.Completion)] -public abstract class AbstractCSharpConditionalBlockSnippetCompletionProviderTests : AbstractCSharpSnippetCompletionProviderTests +[Trait(Traits.Feature, Traits.Features.Snippets)] +public abstract class AbstractCSharpConditionalBlockSnippetProviderTests : AbstractCSharpSnippetProviderTests { - [WpfFact] + [Fact] public async Task InsertSnippetInMethodTest() { - var markupBeforeCommit = """ + await VerifySnippetAsync(""" class Program { public void Method() @@ -23,81 +23,58 @@ public void Method() $$ } } - """; - - var expectedCodeAfterCommit = $$""" + """, $$""" class Program { public void Method() { - {{ItemToCommit}} (true) + {{SnippetIdentifier}} ({|0:true|}) { $$ } } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertSnippetInGlobalContextTest() { - var markupBeforeCommit = """ - Ins$$ - """; - - var expectedCodeAfterCommit = $$""" - {{ItemToCommit}} (true) + await VerifySnippetAsync(""" + $$ + """, $$""" + {{SnippetIdentifier}} ({|0:true|}) { $$ } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task NoSnippetInBlockNamespaceTest() { - var markupBeforeCommit = """ + await VerifySnippetIsAbsentAsync(""" namespace Namespace { $$ - class Program - { - public async Task MethodAsync() - { - } - } } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task NoSnippetInFileScopedNamespaceTest() { - var markupBeforeCommit = """ + await VerifySnippetIsAbsentAsync(""" namespace Namespace; - $$ - class Program - { - public async Task MethodAsync() - { - } - } - """; - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + $$ + """); } - [WpfFact] + [Fact] public async Task InsertSnippetInConstructorTest() { - var markupBeforeCommit = """ + await VerifySnippetAsync(""" class Program { public Program() @@ -106,29 +83,25 @@ public Program() $$ } } - """; - - var expectedCodeAfterCommit = $$""" + """, $$""" class Program { public Program() { var x = 5; - {{ItemToCommit}} (true) + {{SnippetIdentifier}} ({|0:true|}) { $$ } } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertSnippetInLocalFunctionTest() { - var markupBeforeCommit = """ + await VerifySnippetAsync(""" class Program { public void Method() @@ -140,9 +113,7 @@ void LocalMethod() } } } - """; - - var expectedCodeAfterCommit = $$""" + """, $$""" class Program { public void Method() @@ -150,86 +121,82 @@ public void Method() var x = 5; void LocalMethod() { - {{ItemToCommit}} (true) + {{SnippetIdentifier}} ({|0:true|}) { $$ } } } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertSnippetInAnonymousFunctionTest() { - var markupBeforeCommit = """ + await VerifySnippetAsync(""" public delegate void Print(int value); static void Main(string[] args) { - Print print = delegate(int val) { + Print print = delegate(int val) + { $$ }; } - """; - - var expectedCodeAfterCommit = $$""" + """, $$""" public delegate void Print(int value); static void Main(string[] args) { - Print print = delegate(int val) { - {{ItemToCommit}} (true) + Print print = delegate(int val) + { + {{SnippetIdentifier}} ({|0:true|}) { $$ } }; } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertSnippetInParenthesizedLambdaExpressionTest() { - var markupBeforeCommit = """ + await VerifySnippetAsync(""" + using System; + Func testForEquality = (x, y) => { $$ return x == y; }; - """; + """, $$""" + using System; - var expectedCodeAfterCommit = $$""" Func testForEquality = (x, y) => { - {{ItemToCommit}} (true) + {{SnippetIdentifier}} ({|0:true|}) { $$ } return x == y; }; - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task NoSnippetInSwitchExpression() { - var markupBeforeCommit = """ + await VerifySnippetIsAbsentAsync(""" class Program { public void Method() { - var operation = 2; - + var operation = 2; + var result = operation switch { $$ @@ -240,31 +207,29 @@ public void Method() }; } } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task NoSnippetInSingleLambdaExpression() { - var markupBeforeCommit = """ + await VerifySnippetIsAbsentAsync(""" + using System; + class Program { public void Method() { - Func f = x => $$; + Func f = x => $$; } } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task NoSnippetInStringTest() { - var markupBeforeCommit = """ + await VerifySnippetIsAbsentAsync(""" class Program { public void Method() @@ -272,71 +237,60 @@ public void Method() var str = "$$"; } } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfFact] - public async Task NoSnippetInObjectInitializerTest() + [Fact] + public async Task NoSnippetInConstructorArgumentsTest() { - var markupBeforeCommit = """ + await VerifySnippetIsAbsentAsync(""" class Program { public void Method() { - var str = new Test($$); + var test = new Test($$); } } class Test { - private string val; - public Test(string val) { - this.val = val; } } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task NoSnippetInParameterListTest() { - var markupBeforeCommit = """ + await VerifySnippetIsAbsentAsync(""" class Program { public void Method(int x, $$) { } } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task NoSnippetInRecordDeclarationTest() { - var markupBeforeCommit = """ + await VerifySnippetIsAbsentAsync(""" public record Person { $$ - public string FirstName { get; init; } = default!; - public string LastName { get; init; } = default!; + public string FirstName { get; init; } + public string LastName { get; init; } }; - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task NoSnippetInVariableDeclarationTest() { - var markupBeforeCommit = """ + await VerifySnippetIsAbsentAsync(""" class Program { public void Method() @@ -344,73 +298,13 @@ public void Method() var x = $$ } } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfFact] - public async Task InsertSnippetWithInvocationBeforeAndAfterCursorTest() - { - var markupBeforeCommit = """ - class Program - { - public void Method() - { - Wr$$Blah - } - } - """; - - var expectedCodeAfterCommit = $$""" - class Program - { - public void Method() - { - {{ItemToCommit}} (true) - { - $$ - } - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] - public async Task InsertSnippetWithInvocationUnderscoreBeforeAndAfterCursorTest() - { - var markupBeforeCommit = """ - class Program - { - public void Method() - { - _Wr$$Blah_ - } - } - """; - - var expectedCodeAfterCommit = $$""" - class Program - { - public void Method() - { - {{ItemToCommit}} (true) - { - $$ - } - } - } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); - } - - [WpfFact] + [Fact] public async Task InsertInlineSnippetForCorrectTypeTest() { - var markupBeforeCommit = """ + await VerifySnippetAsync(""" class Program { void M(bool arg) @@ -418,28 +312,24 @@ void M(bool arg) arg.$$ } } - """; - - var expectedCodeAfterCommit = $$""" + """, $$""" class Program { void M(bool arg) { - {{ItemToCommit}} (arg) + {{SnippetIdentifier}} (arg) { $$ } } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task NoInlineSnippetForIncorrectTypeTest() { - var markupBeforeCommit = """ + await VerifySnippetIsAbsentAsync(""" class Program { void M(int arg) @@ -447,15 +337,13 @@ void M(int arg) arg.$$ } } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task NoInlineSnippetWhenNotDirectlyExpressionStatementTest() { - var markupBeforeCommit = """ + await VerifySnippetIsAbsentAsync(""" class Program { void M(bool arg) @@ -463,18 +351,16 @@ void M(bool arg) System.Console.WriteLine(arg.$$); } } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfTheory] + [Theory] [InlineData("// comment")] [InlineData("/* comment */")] [InlineData("#region test")] public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInMethodTest1(string trivia) { - var markupBeforeCommit = $$""" + await VerifySnippetAsync($$""" class Program { void M(bool arg) @@ -483,32 +369,28 @@ void M(bool arg) arg.$$ } } - """; - - var expectedCodeAfterCommit = $$""" + """, $$""" class Program { void M(bool arg) { {{trivia}} - {{ItemToCommit}} (arg) + {{SnippetIdentifier}} (arg) { $$ } } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfTheory] + [Theory] [InlineData("#if true")] [InlineData("#pragma warning disable CS0108")] [InlineData("#nullable enable")] public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInMethodTest2(string trivia) { - var markupBeforeCommit = $$""" + await VerifySnippetAsync($$""" class Program { void M(bool arg) @@ -517,76 +399,62 @@ void M(bool arg) arg.$$ } } - """; - - var expectedCodeAfterCommit = $$""" + """, $$""" class Program { void M(bool arg) { {{trivia}} - {{ItemToCommit}} (arg) + {{SnippetIdentifier}} (arg) { $$ } } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfTheory] + [Theory] [InlineData("// comment")] [InlineData("/* comment */")] public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInGlobalStatementTest1(string trivia) { - var markupBeforeCommit = $$""" - {{trivia}} + await VerifySnippetAsync($""" + {trivia} true.$$ - """; - - var expectedCodeAfterCommit = $$""" + """, $$""" {{trivia}} - {{ItemToCommit}} (true) + {{SnippetIdentifier}} (true) { $$ } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfTheory] + [Theory] [InlineData("#region test")] [InlineData("#if true")] [InlineData("#pragma warning disable CS0108")] [InlineData("#nullable enable")] public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInGlobalStatementTest2(string trivia) { - var markupBeforeCommit = $$""" - {{trivia}} + await VerifySnippetAsync($""" + {trivia} true.$$ - """; - - var expectedCodeAfterCommit = $$""" + """, $$""" {{trivia}} - {{ItemToCommit}} (true) + {{SnippetIdentifier}} (true) { $$ } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] public async Task InsertInlineSnippetWhenDottingBeforeContextualKeywordTest1() { - var markupBeforeCommit = """ - using System.Collections.Generic; - + await VerifySnippetAsync(""" class C { void M(bool flag) @@ -595,70 +463,56 @@ void M(bool flag) var a = 0; } } - """; - - var expectedCodeAfterCommit = $$""" - using System.Collections.Generic; - + """, $$""" class C { void M(bool flag) { - {{ItemToCommit}} (flag) + {{SnippetIdentifier}} (flag) { $$ } var a = 0; } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] public async Task InsertInlineSnippetWhenDottingBeforeContextualKeywordTest2() { - var markupBeforeCommit = """ - using System.Collections.Generic; - + await VerifySnippetAsync(""" class C { - void M(bool flag, Task t) + async void M(bool flag, Task t) { flag.$$ await t; } } - """; - - var expectedCodeAfterCommit = $$""" - using System.Collections.Generic; - + """, $$""" class C { - void M(bool flag, Task t) + async void M(bool flag, Task t) { - {{ItemToCommit}} (flag) + {{SnippetIdentifier}} (flag) { $$ } await t; } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfTheory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] + [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] [InlineData("Task")] [InlineData("Task")] [InlineData("System.Threading.Tasks.Task")] public async Task InsertInlineSnippetWhenDottingBeforeNameSyntaxTest(string nameSyntax) { - var markupBeforeCommit = $$""" - using System.Collections.Generic; + await VerifySnippetAsync($$""" + using System.Threading.Tasks; class C { @@ -668,24 +522,20 @@ void M(bool flag) {{nameSyntax}} t = null; } } - """; - - var expectedCodeAfterCommit = $$""" - using System.Collections.Generic; + """, $$""" + using System.Threading.Tasks; class C { void M(bool flag) { - {{ItemToCommit}} (flag) + {{SnippetIdentifier}} (flag) { $$ } {{nameSyntax}} t = null; } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } } diff --git a/src/Features/CSharpTest/Snippets/AbstractCSharpSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/AbstractCSharpSnippetProviderTests.cs new file mode 100644 index 0000000000000..ac9ebbccf4424 --- /dev/null +++ b/src/Features/CSharpTest/Snippets/AbstractCSharpSnippetProviderTests.cs @@ -0,0 +1,12 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Microsoft.CodeAnalysis.Test.Utilities.Snippets; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; + +public abstract class AbstractCSharpSnippetProviderTests : AbstractSnippetProviderTests +{ + protected sealed override string LanguageName => LanguageNames.CSharp; +} diff --git a/src/Features/CSharpTest/Snippets/CSharpClassSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpClassSnippetProviderTests.cs new file mode 100644 index 0000000000000..605189a8b6fea --- /dev/null +++ b/src/Features/CSharpTest/Snippets/CSharpClassSnippetProviderTests.cs @@ -0,0 +1,419 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; + +[Trait(Traits.Feature, Traits.Features.Snippets)] +public sealed class CSharpClassSnippetProviderTests : AbstractCSharpSnippetProviderTests +{ + protected override string SnippetIdentifier => "class"; + + [Fact] + public async Task InsertClassSnippetInBlockNamespaceTest() + { + await VerifySnippetAsync(""" + namespace Namespace + { + $$ + } + """, """ + namespace Namespace + { + class {|0:MyClass|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertClassSnippetInFileScopedNamespaceTest() + { + await VerifySnippetAsync(""" + namespace Namespace; + + $$ + """, """ + namespace Namespace; + + class {|0:MyClass|} + { + $$ + } + """); + } + + [Fact] + public async Task InsertClassSnippetTest() + { + await VerifySnippetAsync(""" + $$ + """, """ + class {|0:MyClass|} + { + $$ + } + """); + } + + [Fact] + public async Task InsertClassTopLevelSnippetTest() + { + await VerifySnippetAsync(""" + System.Console.WriteLine(); + $$ + """, """ + System.Console.WriteLine(); + class {|0:MyClass|} + { + $$ + } + """); + } + + [Fact] + public async Task InsertClassSnippetInClassTest() + { + await VerifySnippetAsync(""" + class MyClass + { + $$ + } + """, """ + class MyClass + { + class {|0:MyClass1|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertClassSnippetInRecordTest() + { + await VerifySnippetAsync(""" + record MyRecord + { + $$ + } + """, """ + record MyRecord + { + class {|0:MyClass|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertClassSnippetInStructTest() + { + await VerifySnippetAsync(""" + struct MyStruct + { + $$ + } + """, """ + struct MyStruct + { + class {|0:MyClass|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertClassSnippetInInterfaceTest() + { + await VerifySnippetAsync(""" + interface MyInterface + { + $$ + } + """, """ + interface MyInterface + { + class {|0:MyClass|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertClassSnippetWithModifiersTest() + { + await VerifySnippetAsync(""" + $$ + """, """ + public class {|0:MyClass|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + """); + } + + [Fact] + public async Task NoClassSnippetInEnumTest() + { + await VerifySnippetIsAbsentAsync(""" + enum MyEnum + { + $$ + } + """); + } + + [Fact] + public async Task NoClassSnippetInMethodTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public void Method() + { + $$ + } + } + """); + } + + [Fact] + public async Task NoClassSnippetInConstructorTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public Program() + { + $$ + } + } + """); + } + + [Theory] + [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))] + public async Task InsertClassSnippetAfterAccessibilityModifier(string modifier) + { + await VerifySnippetAsync($""" + {modifier} $$ + """, $$""" + {{modifier}} class {|0:MyClass|} + { + $$ + } + """); + } + + [Theory] + [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))] + public async Task InsertClassSnippetAfterAccessibilityModifier_RequireAccessibilityModifiers(string modifier) + { + await VerifySnippetAsync($""" + {modifier} $$ + """, $$""" + {{modifier}} class {|0:MyClass|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + """); + } + + [Theory] + [InlineData("abstract")] + [InlineData("sealed")] + [InlineData("static")] + [InlineData("unsafe")] + public async Task InsertClassSnippetAfterValidModifiersTest(string modifier) + { + await VerifySnippetAsync($""" + {modifier} $$ + """, $$""" + {{modifier}} class {|0:MyClass|} + { + $$ + } + """); + } + + [Theory] + [InlineData("ref")] + [InlineData("readonly")] + public async Task NoClassSnippetAfterInvalidModifiersTest(string modifier) + { + await VerifySnippetIsAbsentAsync($""" + {modifier} $$ + """); + } + + [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/69600")] + [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))] + public async Task NoAdditionalAccessibilityModifiersIfAfterPartialKeywordTest(string modifier) + { + await VerifySnippetAsync($""" + {modifier} partial $$ + """, $$""" + {{modifier}} partial class {|0:MyClass|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69600")] + public async Task EnsureCorrectModifierOrderAfterPartialKeywordTest() + { + await VerifySnippetAsync(""" + partial $$ + """, """ + public partial class {|0:MyClass|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69600")] + public async Task EnsureCorrectModifierOrderAfterPartialKeywordTest_InvalidPreferredModifiersList() + { + await VerifySnippetAsync(""" + partial $$ + """, """ + public partial class {|0:MyClass|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + + csharp_preferred_modifier_order = invalid! + """); + } + + [Fact] + public async Task EnsureCorrectModifierOrderFromOptionsTest_PublicModifierBeforeAllOthers() + { + await VerifySnippetAsync(""" + sealed unsafe $$ + """, """ + public sealed unsafe class {|0:MyClass|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + + csharp_preferred_modifier_order = public,sealed,unsafe + """); + } + + [Fact] + public async Task EnsureCorrectModifierOrderFromOptionsTest_PublicModifierBeforeAllOthers_NotAllModifiersInTheList() + { + await VerifySnippetAsync(""" + sealed unsafe $$ + """, """ + public sealed unsafe class {|0:MyClass|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + + csharp_preferred_modifier_order = public,sealed + """); + } + + [Fact] + public async Task EnsureCorrectModifierOrderFromOptionsTest_PublicModifierBetweenOthers() + { + await VerifySnippetAsync(""" + sealed unsafe $$ + """, """ + sealed public unsafe class {|0:MyClass|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + + csharp_preferred_modifier_order = sealed,public,unsafe + """); + } + + [Fact] + public async Task EnsureCorrectModifierOrderFromOptionsTest_PublicModifierAfterAllOthers() + { + await VerifySnippetAsync(""" + sealed unsafe $$ + """, """ + sealed unsafe public class {|0:MyClass|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + + csharp_preferred_modifier_order = sealed,unsafe,public + """); + } +} diff --git a/src/Features/CSharpTest/Snippets/CSharpConsoleSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpConsoleSnippetProviderTests.cs new file mode 100644 index 0000000000000..a62d6aa39cfef --- /dev/null +++ b/src/Features/CSharpTest/Snippets/CSharpConsoleSnippetProviderTests.cs @@ -0,0 +1,414 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; + +[Trait(Traits.Feature, Traits.Features.Snippets)] +public sealed class CSharpConsoleSnippetProviderTests : AbstractCSharpSnippetProviderTests +{ + protected override string SnippetIdentifier => "cw"; + + [Fact] + public async Task InsertConsoleSnippetInMethodTest() + { + await VerifySnippetAsync(""" + class Program + { + public void Method() + { + $$ + } + } + """, """ + using System; + + class Program + { + public void Method() + { + Console.WriteLine($$); + } + } + """); + } + + [Fact] + public async Task InsertNormalConsoleSnippetInAsyncContextTest() + { + await VerifySnippetAsync(""" + using System.Threading.Tasks; + + class Program + { + public async Task MethodAsync() + { + $$ + } + } + """, """ + using System; + using System.Threading.Tasks; + + class Program + { + public async Task MethodAsync() + { + Console.WriteLine($$); + } + } + """); + } + + [Fact] + public async Task InsertConsoleSnippetInGlobalContextTest() + { + await VerifySnippetAsync(""" + $$ + """, """ + using System; + + Console.WriteLine($$); + """); + } + + [Fact] + public async Task NoConsoleSnippetInBlockNamespaceTest() + { + await VerifySnippetIsAbsentAsync(""" + namespace Namespace + { + $$ + } + """); + } + + [Fact] + public async Task NoConsoleSnippetInFileScopedNamespaceTest() + { + await VerifySnippetIsAbsentAsync(""" + namespace Namespace; + + $$ + """); + } + + [Fact] + public async Task InsertConsoleSnippetInConstructorTest() + { + await VerifySnippetAsync(""" + class Program + { + public Program() + { + var x = 5; + $$ + } + } + """, """ + using System; + + class Program + { + public Program() + { + var x = 5; + Console.WriteLine($$); + } + } + """); + } + + [Fact] + public async Task InsertConsoleSnippetInLocalFunctionTest() + { + await VerifySnippetAsync(""" + class Program + { + public void Method() + { + var x = 5; + void LocalMethod() + { + $$ + } + } + } + """, """ + using System; + + class Program + { + public void Method() + { + var x = 5; + void LocalMethod() + { + Console.WriteLine($$); + } + } + } + """); + } + + [Fact] + public async Task InsertConsoleSnippetInAnonymousFunctionTest() + { + await VerifySnippetAsync(""" + public delegate void Print(int value); + + static void Main(string[] args) + { + Print print = delegate(int val) + { + $$ + }; + + } + """, """ + using System; + + public delegate void Print(int value); + + static void Main(string[] args) + { + Print print = delegate(int val) + { + Console.WriteLine($$); + }; + + } + """); + } + + [Fact] + public async Task InsertConsoleSnippetInParenthesizedLambdaExpressionTest() + { + await VerifySnippetAsync(""" + using System; + + Func testForEquality = (x, y) => + { + $$ + return x == y; + }; + """, """ + using System; + + Func testForEquality = (x, y) => + { + Console.WriteLine($$); + return x == y; + }; + """); + } + + [Fact] + public async Task NoConsoleSnippetInSwitchExpressionTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public void Method() + { + var operation = 2; + + var result = operation switch + { + $$ + 1 => "Case 1", + 2 => "Case 2", + 3 => "Case 3", + 4 => "Case 4", + }; + } + } + """); + } + + [Fact] + public async Task NoConsoleSnippetInStringTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public void Method() + { + var str = "$$"; + } + } + """); + } + + [Fact] + public async Task NoConsoleSnippetInConstructorArgumentsTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public void Method() + { + var test = new Test($$); + } + } + + class Test + { + public Test(string val) + { + } + } + """); + } + + [Fact] + public async Task NoConsoleSnippetInParameterListTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public void Method(int x, $$) + { + } + } + """); + } + + [Fact] + public async Task NoConsoleSnippetInRecordDeclarationTest() + { + await VerifySnippetIsAbsentAsync(""" + public record Person + { + $$ + public string FirstName { get; init; } + public string LastName { get; init; } + }; + """); + } + + [Fact] + public async Task NoConsoleSnippetInVariableDeclarationTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public void Method() + { + var x = $$ + } + } + """); + } + + /// + /// We want to fix this case and insert the fully qualified namespace + /// in a future fix. + /// + [Fact] + public async Task InsertConsoleSnippetWithPropertyNamedConsoleTest() + { + await VerifySnippetAsync(""" + class Program + { + public int Console { get; set; } + + public void Method() + { + $$ + } + } + """, """ + using System; + + class Program + { + public int Console { get; set; } + + public void Method() + { + Console.WriteLine($$); + } + } + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72266")] + public async Task InsertConsoleSnippetInVoidReturningLambdaTest1() + { + await VerifySnippetAsync(""" + using System; + + M(() => $$); + + void M(Action a) + { + } + """, """ + using System; + + M(() => Console.WriteLine($$)); + + void M(Action a) + { + } + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72266")] + public async Task InsertConsoleSnippetInVoidReturningLambdaTest2() + { + await VerifySnippetAsync(""" + using System; + + Action action = () => $$ + """, """ + using System; + + Action action = () => Console.WriteLine($$) + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72266")] + public async Task InsertConsoleSnippetInVoidReturningLambdaTest_TypeInference() + { + await VerifySnippetAsync(""" + using System; + + var action = () => $$ + """, """ + using System; + + var action = () => Console.WriteLine($$) + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72266")] + public async Task NoConsoleSnippetInNonVoidReturningLambdaTest1() + { + await VerifySnippetIsAbsentAsync(""" + using System; + + M(() => $$); + + void M(Func f) + { + } + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/72266")] + public async Task NoConsoleSnippetInNonVoidReturningLambdaTest2() + { + await VerifySnippetIsAbsentAsync(""" + using System; + + Func f = () => $$ + """); + } +} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpConstructorSnippetCompletionProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpConstructorSnippetProviderTests.cs similarity index 57% rename from src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpConstructorSnippetCompletionProviderTests.cs rename to src/Features/CSharpTest/Snippets/CSharpConstructorSnippetProviderTests.cs index ba82dd751d67d..e5cc0a8775b09 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpConstructorSnippetCompletionProviderTests.cs +++ b/src/Features/CSharpTest/Snippets/CSharpConstructorSnippetProviderTests.cs @@ -7,65 +7,52 @@ using Roslyn.Test.Utilities; using Xunit; -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; -[Trait(Traits.Feature, Traits.Features.Completion)] -public class CSharpConstructorSnippetCompletionProviderTests : AbstractCSharpSnippetCompletionProviderTests +[Trait(Traits.Feature, Traits.Features.Snippets)] +public sealed class CSharpConstructorSnippetProviderTests : AbstractCSharpSnippetProviderTests { - protected override string ItemToCommit => "ctor"; + protected override string SnippetIdentifier => "ctor"; - [WpfFact] + [Fact] public async Task ConstructorSnippetMissingInNamespace() { - var markupBeforeCommit = - """ + await VerifySnippetIsAbsentAsync(""" namespace Namespace { $$ } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task ConstructorSnippetMissingInFileScopedNamespace() { - var markupBeforeCommit = - """ + await VerifySnippetIsAbsentAsync(""" namespace Namespace; $$ - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task ConstructorSnippetMissingInTopLevelContext() { - var markupBeforeCommit = - """ + await VerifySnippetIsAbsentAsync(""" System.Console.WriteLine(); $$ - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task InsertConstructorSnippetInClassTest() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" class MyClass { $$ } - """; - - var expectedCodeAfterCommit = - """ + """, """ class MyClass { public MyClass() @@ -73,23 +60,18 @@ public MyClass() $$ } } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertConstructorSnippetInAbstractClassTest() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" abstract class MyClass { $$ } - """; - - var expectedCodeAfterCommit = - """ + """, """ abstract class MyClass { protected MyClass() @@ -97,15 +79,13 @@ protected MyClass() $$ } } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertConstructorSnippetInAbstractClassTest_AbstractModifierInOtherPartialDeclaration() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" partial class MyClass { $$ @@ -114,10 +94,7 @@ partial class MyClass abstract partial class MyClass { } - """; - - var expectedCodeAfterCommit = - """ + """, """ partial class MyClass { protected MyClass() @@ -129,15 +106,13 @@ protected MyClass() abstract partial class MyClass { } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertConstructorSnippetInNestedAbstractClassTest() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" class MyClass { abstract class NestedClass @@ -145,10 +120,7 @@ abstract class NestedClass $$ } } - """; - - var expectedCodeAfterCommit = - """ + """, """ class MyClass { abstract class NestedClass @@ -159,23 +131,18 @@ protected NestedClass() } } } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertConstructorSnippetInStructTest() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" struct MyStruct { $$ } - """; - - var expectedCodeAfterCommit = - """ + """, """ struct MyStruct { public MyStruct() @@ -183,23 +150,18 @@ public MyStruct() $$ } } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertConstructorSnippetInRecordTest() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" record MyRecord { $$ } - """; - - var expectedCodeAfterCommit = - """ + """, """ record MyRecord { public MyRecord() @@ -207,29 +169,24 @@ public MyRecord() $$ } } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task ConstructorSnippetMissingInInterface() { - var markupBeforeCommit = - """ + await VerifySnippetIsAbsentAsync(""" interface MyInterface { $$ } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task InsertConstructorSnippetInNestedClassTest() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" class MyClass { class MyClass1 @@ -237,10 +194,7 @@ class MyClass1 $$ } } - """; - - var expectedCodeAfterCommit = - """ + """, """ class MyClass { class MyClass1 @@ -251,28 +205,20 @@ public MyClass1() } } } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfTheory] - [InlineData("public")] - [InlineData("private")] - [InlineData("protected")] - [InlineData("internal")] - [InlineData("private protected")] - [InlineData("protected internal")] + [Theory] [InlineData("static")] + [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))] public async Task InsertConstructorSnippetAfterValidModifiersTest(string modifiers) { - var markupBeforeCommit = $$""" + await VerifySnippetAsync($$""" class MyClass { {{modifiers}} $$ } - """; - - var expectedCodeAfterCommit = $$""" + """, $$""" class MyClass { {{modifiers}} MyClass() @@ -280,12 +226,10 @@ class MyClass $$ } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfTheory] + [Theory] [InlineData("abstract")] [InlineData("sealed")] [InlineData("virtual")] @@ -295,47 +239,36 @@ class MyClass [InlineData("file")] public async Task ConstructorSnippetMissingAfterInvalidModifierTest(string modifier) { - var markupBeforeCommit = $$""" + await VerifySnippetIsAbsentAsync($$""" class MyClass { {{modifier}} $$ } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfTheory] - [InlineData("public")] - [InlineData("private")] - [InlineData("protected")] - [InlineData("internal")] - [InlineData("private protected")] - [InlineData("protected internal")] + [Theory] + [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))] public async Task ConstructorSnippetMissingAfterBothAccessibilityModifierAndStaticKeywordTest(string accessibilityModifier) { - var markupBeforeCommit = $$""" + await VerifySnippetIsAbsentAsync($$""" class MyClass { {{accessibilityModifier}} static $$ } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task InsertConstructorSnippetAfterAccessibilityModifierBeforeOtherMemberTest() { - var markupBeforeCommit = """ + await VerifySnippetAsync(""" class C { private $$ readonly int Value = 3; } - """; - - var expectedCodeAfterCommit = """ + """, """ class C { private C() @@ -344,23 +277,19 @@ private C() } readonly int Value = 3; } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertConstructorSnippetBetweenAccessibilityModifiersBeforeOtherMemberTest() { - var markupBeforeCommit = """ + await VerifySnippetAsync(""" class C { protected $$ internal int Value = 3; } - """; - - var expectedCodeAfterCommit = """ + """, """ class C { protected C() @@ -369,23 +298,19 @@ protected C() } internal int Value = 3; } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertConstructorSnippetAfterAccessibilityModifierBeforeOtherStaticMemberTest() { - var markupBeforeCommit = """ + await VerifySnippetAsync(""" class C { internal $$ static int Value = 3; } - """; - - var expectedCodeAfterCommit = """ + """, """ class C { internal C() @@ -394,15 +319,13 @@ internal C() } static int Value = 3; } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/68176")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68176")] public async Task InsertCorrectConstructorSnippetInNestedTypeTest_CtorBeforeNestedType() { - var markupBeforeCommit = """ + await VerifySnippetAsync(""" class Outer { $$ @@ -410,9 +333,7 @@ class Inner { } } - """; - - var expectedCodeAfterCommit = """ + """, """ class Outer { public Outer() @@ -423,15 +344,13 @@ class Inner { } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/68176")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/68176")] public async Task InsertCorrectConstructorSnippetInNestedTypeTest_CtorAfterNestedType() { - var markupBeforeCommit = """ + await VerifySnippetAsync(""" class Outer { class Inner @@ -439,9 +358,7 @@ class Inner } $$ } - """; - - var expectedCodeAfterCommit = """ + """, """ class Outer { class Inner @@ -452,8 +369,6 @@ public Outer() $$ } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } } diff --git a/src/Features/CSharpTest/Snippets/CSharpDoSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpDoSnippetProviderTests.cs new file mode 100644 index 0000000000000..69d1e4ca499b0 --- /dev/null +++ b/src/Features/CSharpTest/Snippets/CSharpDoSnippetProviderTests.cs @@ -0,0 +1,557 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; + +[Trait(Traits.Feature, Traits.Features.Snippets)] +public sealed class CSharpDoSnippetProviderTests : AbstractCSharpSnippetProviderTests +{ + protected override string SnippetIdentifier => "do"; + + [Fact] + public async Task InsertDoSnippetInMethodTest() + { + await VerifySnippetAsync(""" + class Program + { + public void Method() + { + $$ + } + } + """, """ + class Program + { + public void Method() + { + do + { + $$ + } + while ({|0:true|}); + } + } + """); + } + + [Fact] + public async Task InsertDoSnippetInGlobalContextTest() + { + await VerifySnippetAsync(""" + $$ + """, """ + do + { + $$ + } + while ({|0:true|}); + """); + } + + [Fact] + public async Task NoDoSnippetInBlockNamespaceTest() + { + await VerifySnippetIsAbsentAsync(""" + namespace Namespace + { + $$ + } + """); + } + + [Fact] + public async Task NoDoSnippetInFileScopedNamespaceTest() + { + await VerifySnippetIsAbsentAsync(""" + namespace Namespace; + + $$ + """); + } + + [Fact] + public async Task InsertDoSnippetInConstructorTest() + { + await VerifySnippetAsync(""" + class Program + { + public Program() + { + var x = 5; + $$ + } + } + """, """ + class Program + { + public Program() + { + var x = 5; + do + { + $$ + } + while ({|0:true|}); + } + } + """); + } + + [Fact] + public async Task InsertDoSnippetInLocalFunctionTest() + { + await VerifySnippetAsync(""" + class Program + { + public void Method() + { + var x = 5; + void LocalMethod() + { + $$ + } + } + } + """, """ + class Program + { + public void Method() + { + var x = 5; + void LocalMethod() + { + do + { + $$ + } + while ({|0:true|}); + } + } + } + """); + } + + [Fact] + public async Task InsertDoSnippetInAnonymousFunctionTest() + { + await VerifySnippetAsync(""" + public delegate void Print(int value); + + static void Main(string[] args) + { + Print print = delegate(int val) + { + $$ + }; + + } + """, """ + public delegate void Print(int value); + + static void Main(string[] args) + { + Print print = delegate(int val) + { + do + { + $$ + } + while ({|0:true|}); + }; + + } + """); + } + + [Fact] + public async Task InsertDoSnippetInParenthesizedLambdaExpressionTest() + { + await VerifySnippetAsync(""" + using System; + + Func testForEquality = (x, y) => + { + $$ + return x == y; + }; + """, """ + using System; + + Func testForEquality = (x, y) => + { + do + { + $$ + } + while ({|0:true|}); + return x == y; + }; + """); + } + + [Fact] + public async Task NoDoSnippetInSwitchExpression() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public void Method() + { + var operation = 2; + + var result = operation switch + { + $$ + 1 => "Case 1", + 2 => "Case 2", + 3 => "Case 3", + 4 => "Case 4", + }; + } + } + """); + } + + [Fact] + public async Task NoDoSnippetInSingleLambdaExpression() + { + await VerifySnippetIsAbsentAsync(""" + using System; + + class Program + { + public void Method() + { + Func f = x => $$; + } + } + """); + } + + [Fact] + public async Task NoDoSnippetInStringTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public void Method() + { + var str = "$$"; + } + } + """); + } + + [Fact] + public async Task NoDoSnippetInConstructorArgumentsTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public void Method() + { + var test = new Test($$); + } + } + + class Test + { + public Test(string val) + { + } + } + """); + } + + [Fact] + public async Task NoDoSnippetInParameterListTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public void Method(int x, $$) + { + } + } + """); + } + + [Fact] + public async Task NoDoSnippetInRecordDeclarationTest() + { + await VerifySnippetIsAbsentAsync(""" + public record Person + { + $$ + public string FirstName { get; init; } + public string LastName { get; init; } + }; + """); + } + + [Fact] + public async Task NoDoSnippetInVariableDeclarationTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public void Method() + { + var x = $$ + } + } + """); + } + + [Fact] + public async Task InsertInlineDoSnippetForCorrectTypeTest() + { + await VerifySnippetAsync(""" + class Program + { + void M(bool arg) + { + arg.$$ + } + } + """, """ + class Program + { + void M(bool arg) + { + do + { + $$ + } + while (arg); + } + } + """); + } + + [Fact] + public async Task NoInlineDoSnippetForIncorrectTypeTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + void M(int arg) + { + arg.$$ + } + } + """); + } + + [Fact] + public async Task NoInlineDoSnippetWhenNotDirectlyExpressionStatementTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + void M(bool arg) + { + System.Console.WriteLine(arg.$$); + } + } + """); + } + + [Theory] + [InlineData("// comment")] + [InlineData("/* comment */")] + [InlineData("#region test")] + public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInMethodTest1(string trivia) + { + await VerifySnippetAsync($$""" + class Program + { + void M(bool arg) + { + {{trivia}} + arg.$$ + } + } + """, $$""" + class Program + { + void M(bool arg) + { + {{trivia}} + do + { + $$ + } + while (arg); + } + } + """); + } + + [Theory] + [InlineData("#if true")] + [InlineData("#pragma warning disable CS0108")] + [InlineData("#nullable enable")] + public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInMethodTest2(string trivia) + { + await VerifySnippetAsync($$""" + class Program + { + void M(bool arg) + { + {{trivia}} + arg.$$ + } + } + """, $$""" + class Program + { + void M(bool arg) + { + {{trivia}} + do + { + $$ + } + while (arg); + } + } + """); + } + + [Theory] + [InlineData("// comment")] + [InlineData("/* comment */")] + public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInGlobalStatementTest1(string trivia) + { + await VerifySnippetAsync($""" + {trivia} + true.$$ + """, $$""" + {{trivia}} + do + { + $$ + } + while (true); + """); + } + + [Theory] + [InlineData("#region test")] + [InlineData("#if true")] + [InlineData("#pragma warning disable CS0108")] + [InlineData("#nullable enable")] + public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInGlobalStatementTest2(string trivia) + { + await VerifySnippetAsync($""" + {trivia} + true.$$ + """, $$""" + + {{trivia}} + do + { + $$ + } + while (true); + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] + public async Task InsertInlineSnippetWhenDottingBeforeContextualKeywordTest1() + { + await VerifySnippetAsync(""" + class C + { + void M(bool flag) + { + flag.$$ + var a = 0; + } + } + """, """ + class C + { + void M(bool flag) + { + do + { + $$ + } + while (flag); + var a = 0; + } + } + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] + public async Task InsertInlineSnippetWhenDottingBeforeContextualKeywordTest2() + { + await VerifySnippetAsync(""" + class C + { + async void M(bool flag, Task t) + { + flag.$$ + await t; + } + } + """, """ + class C + { + async void M(bool flag, Task t) + { + do + { + $$ + } + while (flag); + await t; + } + } + """); + } + + [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] + [InlineData("Task")] + [InlineData("Task")] + [InlineData("System.Threading.Tasks.Task")] + public async Task InsertInlineSnippetWhenDottingBeforeNameSyntaxTest(string nameSyntax) + { + await VerifySnippetAsync($$""" + using System.Threading.Tasks; + + class C + { + void M(bool flag) + { + flag.$$ + {{nameSyntax}} t = null; + } + } + """, $$""" + using System.Threading.Tasks; + + class C + { + void M(bool flag) + { + do + { + $$ + } + while (flag); + {{nameSyntax}} t = null; + } + } + """); + } +} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpElseSnippetCompletionProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpElseSnippetProviderTests.cs similarity index 61% rename from src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpElseSnippetCompletionProviderTests.cs rename to src/Features/CSharpTest/Snippets/CSharpElseSnippetProviderTests.cs index 9092a961c772e..6dbd4f8352b6d 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpElseSnippetCompletionProviderTests.cs +++ b/src/Features/CSharpTest/Snippets/CSharpElseSnippetProviderTests.cs @@ -4,21 +4,19 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Test.Utilities; -using Roslyn.Test.Utilities; using Xunit; -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; -[Trait(Traits.Feature, Traits.Features.Completion)] -public class CSharpElseSnippetCompletionProviderTests : AbstractCSharpSnippetCompletionProviderTests +[Trait(Traits.Feature, Traits.Features.Snippets)] +public sealed class CSharpElseSnippetProviderTests : AbstractCSharpSnippetProviderTests { - protected override string ItemToCommit => "else"; + protected override string SnippetIdentifier => "else"; - [WpfFact] + [Fact] public async Task InsertElseSnippetInMethodTest() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" class Program { public void Method() @@ -29,10 +27,7 @@ public void Method() $$ } } - """; - - var expectedCodeAfterCommit = - """ + """, """ class Program { public void Method() @@ -46,15 +41,13 @@ public void Method() } } } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task NoElseSnippetInMethodWithoutIfStatementTest() { - var markupBeforeCommit = - """ + await VerifySnippetIsAbsentAsync(""" class Program { public void Method() @@ -62,29 +55,18 @@ public void Method() $$ } } - """; - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task InsertElseSnippetGlobalTest() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" if (true) { } $$ - class Program - { - public async Task MethodAsync() - { - } - } - """; - - var expectedCodeAfterCommit = - """ + """, """ if (true) { } @@ -92,63 +74,39 @@ public async Task MethodAsync() { $$ } - class Program - { - public async Task MethodAsync() - { - } - } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task NoElseSnippetInBlockNamespaceTest() { - var markupBeforeCommit = - """ + await VerifySnippetIsAbsentAsync(""" namespace Namespace { if (true) { } $$ - class Program - { - public async Task MethodAsync() - { - } - } } - """; - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task NoElseSnippetInFileScopedNamespaceTest() { - var markupBeforeCommit = - """ + await VerifySnippetIsAbsentAsync(""" namespace Namespace; if (true) { } $$ - class Program - { - public async Task MethodAsync() - { - } - } - """; - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task InsertElseSnippetInConstructorTest() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" class Program { public Program() @@ -159,10 +117,7 @@ public Program() $$ } } - """; - - var expectedCodeAfterCommit = - """ + """, """ class Program { public Program() @@ -176,15 +131,13 @@ public Program() } } } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertElseSnippetInLocalFunctionTest() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" class Program { public void Method() @@ -200,10 +153,7 @@ void LocalMethod() } } } - """; - - var expectedCodeAfterCommit = - """ + """, """ class Program { public void Method() @@ -222,15 +172,13 @@ void LocalMethod() } } } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertElseSnippetSingleLineIfWithBlockTest() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" class Program { public void Method() @@ -239,10 +187,7 @@ public void Method() $$ } } - """; - - var expectedCodeAfterCommit = - """ + """, """ class Program { public void Method() @@ -254,16 +199,15 @@ public void Method() } } } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertElseSnippetSingleLineIfTest() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" using System; + class Program { public void Method() @@ -272,11 +216,9 @@ public void Method() $$ } } - """; - - var expectedCodeAfterCommit = - """ + """, """ using System; + class Program { public void Method() @@ -288,15 +230,13 @@ public void Method() } } } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertElseSnippetNestedIfTest() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" class Program { public void Method() @@ -310,10 +250,7 @@ public void Method() $$ } } - """; - - var expectedCodeAfterCommit = - """ + """, """ class Program { public void Method() @@ -330,7 +267,6 @@ public void Method() } } } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } } diff --git a/src/Features/CSharpTest/Snippets/CSharpEnumSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpEnumSnippetProviderTests.cs new file mode 100644 index 0000000000000..dc880015a72b4 --- /dev/null +++ b/src/Features/CSharpTest/Snippets/CSharpEnumSnippetProviderTests.cs @@ -0,0 +1,262 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; + +[Trait(Traits.Feature, Traits.Features.Snippets)] +public sealed class CSharpEnumSnippetProviderTests : AbstractCSharpSnippetProviderTests +{ + protected override string SnippetIdentifier => "enum"; + + [Fact] + public async Task InsertEnumSnippetInBlockNamespaceTest() + { + await VerifySnippetAsync(""" + namespace Namespace + { + $$ + } + """, """ + namespace Namespace + { + enum {|0:MyEnum|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertEnumSnippetInFileScopedNamespaceTest() + { + await VerifySnippetAsync(""" + namespace Namespace; + + $$ + """, """ + namespace Namespace; + + enum {|0:MyEnum|} + { + $$ + } + """); + } + + [Fact] + public async Task InsertEnumSnippetTest() + { + await VerifySnippetAsync(""" + $$ + """, """ + enum {|0:MyEnum|} + { + $$ + } + """); + } + + [Fact] + public async Task InsertEnumTopLevelSnippetTest() + { + await VerifySnippetAsync(""" + System.Console.WriteLine(); + $$ + """, """ + System.Console.WriteLine(); + enum {|0:MyEnum|} + { + $$ + } + """); + } + + [Fact] + public async Task InsertEnumSnippetInClassTest() + { + await VerifySnippetAsync(""" + class MyClass + { + $$ + } + """, """ + class MyClass + { + enum {|0:MyEnum|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertEnumSnippetInRecordTest() + { + await VerifySnippetAsync(""" + record MyRecord + { + $$ + } + """, """ + record MyRecord + { + enum {|0:MyEnum|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertEnumSnippetInStructTest() + { + await VerifySnippetAsync(""" + struct MyStruct + { + $$ + } + """, """ + struct MyStruct + { + enum {|0:MyEnum|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertEnumSnippetInInterfaceTest() + { + await VerifySnippetAsync(""" + interface MyInterface + { + $$ + } + """, """ + interface MyInterface + { + enum {|0:MyEnum|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertEnumSnippetWithModifiersTest() + { + await VerifySnippetAsync(""" + $$ + """, """ + public enum {|0:MyEnum|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + """); + } + + [Fact] + public async Task NoEnumSnippetInEnumTest() + { + await VerifySnippetIsAbsentAsync(""" + enum MyEnum + { + $$ + } + """); + } + + [Fact] + public async Task NoEnumSnippetInMethodTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public void Method() + { + $$ + } + } + """); + } + + [Fact] + public async Task NoEnumSnippetInConstructorTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public Program() + { + $$ + } + } + """); + } + + [Theory] + [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))] + public async Task InsertEnumSnippetAfterAccessibilityModifier(string modifier) + { + await VerifySnippetAsync($""" + {modifier} $$ + """, $$""" + {{modifier}} enum {|0:MyEnum|} + { + $$ + } + """); + } + + [Theory] + [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))] + public async Task InsertEnumSnippetAfterAccessibilityModifier_RequireAccessibilityModifiers(string modifier) + { + await VerifySnippetAsync($""" + {modifier} $$ + """, $$""" + {{modifier}} enum {|0:MyEnum|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + """); + } + + [Theory] + [InlineData("abstract")] + [InlineData("partial")] + [InlineData("sealed")] + [InlineData("static")] + [InlineData("ref")] + [InlineData("readonly")] + [InlineData("unsafe")] + public async Task NoEnumSnippetAfterInvalidModifiersTest(string modifier) + { + await VerifySnippetIsAbsentAsync($""" + {modifier} $$ + """); + } +} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpForEachSnippetCompletionProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpForEachSnippetProviderTests.cs similarity index 53% rename from src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpForEachSnippetCompletionProviderTests.cs rename to src/Features/CSharpTest/Snippets/CSharpForEachSnippetProviderTests.cs index c9cc0eaf2f4c9..c803a34b7b6e1 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpForEachSnippetCompletionProviderTests.cs +++ b/src/Features/CSharpTest/Snippets/CSharpForEachSnippetProviderTests.cs @@ -4,101 +4,86 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.CodeAnalysis.Testing; using Roslyn.Test.Utilities; using Xunit; -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; -[Trait(Traits.Feature, Traits.Features.Completion)] -public class CSharpForEachSnippetCompletionProviderTests : AbstractCSharpSnippetCompletionProviderTests +[Trait(Traits.Feature, Traits.Features.Snippets)] +public sealed class CSharpForEachSnippetProviderTests : AbstractCSharpSnippetProviderTests { - protected override string ItemToCommit => "foreach"; + protected override string SnippetIdentifier => "foreach"; - [WpfFact] + [Fact] public async Task InsertForEachSnippetInMethodTest() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" class Program { public void Method() { - Ins$$ + $$ } } - """; - - var expectedCodeAfterCommit = - """ + """, """ class Program { public void Method() { - foreach (var item in collection) + foreach (var {|0:item|} in {|1:collection|}) { $$ } } } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertForEachSnippetInMethodItemUsedTest() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" class Program { public void Method() { var item = 5; - Ins$$ + $$ } } - """; - - var expectedCodeAfterCommit = - """ + """, """ class Program { public void Method() { var item = 5; - foreach (var item1 in collection) + foreach (var {|0:item1|} in {|1:collection|}) { $$ } } } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertForEachSnippetInGlobalContextTest() { - var markupBeforeCommit = - """ - Ins$$ - """; - - var expectedCodeAfterCommit = - """ - foreach (var item in collection) + await VerifySnippetAsync(""" + $$ + """, """ + foreach (var {|0:item|} in {|1:collection|}) { $$ } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertForEachSnippetInConstructorTest() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" class Program { public Program() @@ -106,30 +91,24 @@ public Program() $$ } } - """; - - var expectedCodeAfterCommit = - """ + """, """ class Program { public Program() { - foreach (var item in collection) + foreach (var {|0:item|} in {|1:collection|}) { $$ } } } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertForEachSnippetWithCollectionTest() { - var markupBeforeCommit = - """ - using System; + await VerifySnippetAsync(""" using System.Collections.Generic; class Program @@ -140,11 +119,7 @@ public Program() $$ } } - """; - - var expectedCodeAfterCommit = - """ - using System; + """, """ using System.Collections.Generic; class Program @@ -152,21 +127,19 @@ class Program public Program() { var list = new List { 1, 2, 3 }; - foreach (var item in list) + foreach (var {|0:item|} in {|1:list|}) { $$ } } } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertForEachSnippetInLocalFunctionTest() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" class Program { public void Method() @@ -178,10 +151,7 @@ void LocalMethod() } } } - """; - - var expectedCodeAfterCommit = - """ + """, """ class Program { public void Method() @@ -189,100 +159,71 @@ public void Method() var x = 5; void LocalMethod() { - foreach (var item in collection) + foreach (var {|0:item|} in {|1:collection|}) { $$ } } } } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task InsertForEachSnippetInAnonymousFunctionTest() { - var markupBeforeCommit = - """ + await VerifySnippetAsync(""" public delegate void Print(int value); + static void Main(string[] args) { - Print print = delegate(int val) { + Print print = delegate(int val) + { $$ }; } - """; - - var expectedCodeAfterCommit = - """ + """, """ public delegate void Print(int value); + static void Main(string[] args) { - Print print = delegate(int val) { - foreach (var item in args) + Print print = delegate(int val) + { + foreach (var {|0:item|} in {|1:args|}) { $$ } }; } - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] - public async Task InsertForEachSnippetInParenthesizedLambdaExpressionRegularTest() + [Fact] + public async Task InsertForEachSnippetInParenthesizedLambdaExpressionTest() { - var markupBeforeCommit = - """ - Func testForEquality = (x, y) => - { - $$ - return x == y; - }; - """; - - var expectedCodeAfterCommit = - """ - Func testForEquality = (x, y) => - { - foreach (var item in args) - { - $$ - } - return x == y; - }; - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit, sourceCodeKind: SourceCodeKind.Regular); - } + await VerifySnippetAsync(""" + using System; - [WpfFact] - public async Task InsertForEachSnippetInParenthesizedLambdaExpressionScriptTest() - { - var markupBeforeCommit = - """ Func testForEquality = (x, y) => { $$ return x == y; }; - """; + """, """ + using System; - var expectedCodeAfterCommit = - """ Func testForEquality = (x, y) => { - foreach (var item in collection) + foreach (var {|0:item|} in {|1:args|}) { $$ } return x == y; }; - """; - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit, sourceCodeKind: SourceCodeKind.Script); + """); } - [WpfTheory] + [Theory] [InlineData("List")] [InlineData("int[]")] [InlineData("IEnumerable")] @@ -290,9 +231,9 @@ public async Task InsertForEachSnippetInParenthesizedLambdaExpressionScriptTest( [InlineData("IEnumerable")] public async Task InsertInlineForEachSnippetForCorrectTypeTest(string collectionType) { - var markupBeforeCommit = $$""" - using System.Collections.Generic; + await VerifySnippetAsync($$""" using System.Collections; + using System.Collections.Generic; class C { @@ -301,31 +242,27 @@ void M({{collectionType}} enumerable) enumerable.$$ } } - """; - - var expectedCodeAfterCommit = $$""" - using System.Collections.Generic; + """, $$""" using System.Collections; + using System.Collections.Generic; class C { void M({{collectionType}} enumerable) { - foreach (var item in enumerable) + foreach (var {|0:item|} in enumerable) { $$ } } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact] + [Fact] public async Task NoInlineForEachSnippetForIncorrectTypeTest() { - var markupBeforeCommit = """ + await VerifySnippetIsAbsentAsync(""" class Program { void M(int arg) @@ -333,15 +270,13 @@ void M(int arg) arg.$$ } } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task NoInlineForEachSnippetWhenNotDirectlyExpressionStatementTest() { - var markupBeforeCommit = """ + await VerifySnippetIsAbsentAsync(""" using System; using System.Collections.Generic; @@ -352,18 +287,16 @@ void M(List list) Console.WriteLine(list.$$); } } - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + """); } - [WpfTheory] + [Theory] [InlineData("// comment")] [InlineData("/* comment */")] [InlineData("#region test")] public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInMethodTest1(string trivia) { - var markupBeforeCommit = $$""" + await VerifySnippetAsync($$""" class Program { void M(int[] arr) @@ -372,32 +305,28 @@ void M(int[] arr) arr.$$ } } - """; - - var expectedCodeAfterCommit = $$""" + """, $$""" class Program { void M(int[] arr) { {{trivia}} - foreach (var item in arr) + foreach (var {|0:item|} in arr) { $$ } } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfTheory] + [Theory] [InlineData("#if true")] [InlineData("#pragma warning disable CS0108")] [InlineData("#nullable enable")] public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInMethodTest2(string trivia) { - var markupBeforeCommit = $$""" + await VerifySnippetAsync($$""" class Program { void M(int[] arr) @@ -406,165 +335,128 @@ void M(int[] arr) arr.$$ } } - """; - - var expectedCodeAfterCommit = $$""" + """, $$""" class Program { void M(int[] arr) { {{trivia}} - foreach (var item in arr) + foreach (var {|0:item|} in arr) { $$ } } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfTheory] + [Theory] [InlineData("// comment")] [InlineData("/* comment */")] public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInGlobalStatementTest1(string trivia) { - var markupBeforeCommit = $$""" + await VerifySnippetAsync($$""" {{trivia}} (new int[10]).$$ - """; - - var expectedCodeAfterCommit = $$""" + """, $$""" {{trivia}} - foreach (var item in new int[10]) + foreach (var {|0:item|} in new int[10]) { $$ } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfTheory] + [Theory] [InlineData("#region test")] [InlineData("#if true")] [InlineData("#pragma warning disable CS0108")] [InlineData("#nullable enable")] public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInGlobalStatementTest2(string trivia) { - var markupBeforeCommit = $$""" + await VerifySnippetAsync($$""" {{trivia}} (new int[10]).$$ - """; - - var expectedCodeAfterCommit = $$""" + """, $$""" {{trivia}} - foreach (var item in new int[10]) + foreach (var {|0:item|} in new int[10]) { $$ } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfTheory] + [Theory] [InlineData("")] [InlineData("async ")] public async Task InsertForEachSnippetAfterSingleAwaitKeywordInMethodBodyTest(string asyncKeyword) { - var markupBeforeCommit = $$""" - - - class C + await VerifySnippetAsync($$""" + class C { {{asyncKeyword}}void M() { await $$ } - } - - - """; - - var expectedCodeAfterCommit = $$""" + } + """, $$""" class C { {{asyncKeyword}}void M() { - await foreach (var item in collection) + await foreach (var {|0:item|} in {|1:collection|}) { $$ } } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """, + referenceAssemblies: ReferenceAssemblies.Net.Net70); } - [WpfFact] + [Fact] public async Task InsertForEachSnippetAfterSingleAwaitKeywordInGlobalStatementTest() { - var markupBeforeCommit = """ - - - await $$ - - - """; - - var expectedCodeAfterCommit = """ - await foreach (var item in collection) + await VerifySnippetAsync(""" + await $$ + """, """ + await foreach (var {|0:item|} in {|1:collection|}) { $$ } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """, + referenceAssemblies: ReferenceAssemblies.Net.Net70); } - [WpfFact] + [Fact] public async Task NoForEachStatementAfterAwaitKeywordWhenWontResultInStatementTest() { - var markupBeforeCommit = """ - - - var result = await $$ - - - """; - - await VerifyItemIsAbsentAsync(markupBeforeCommit, ItemToCommit); + await VerifySnippetIsAbsentAsync(""" + var result = await $$ + """, + referenceAssemblies: ReferenceAssemblies.Net.Net70); } - [WpfTheory] + [Theory] [InlineData("")] [InlineData("async ")] public async Task PreferAsyncEnumerableVariableInScopeForAwaitForEachTest(string asyncKeyword) { - var markupBeforeCommit = $$""" - - - using System.Collections.Generic; + await VerifySnippetAsync($$""" + using System.Collections.Generic; class C { {{asyncKeyword}}void M() { - IEnumerable<int> enumerable; - IAsyncEnumerable<int> asyncEnumerable; + IEnumerable enumerable; + IAsyncEnumerable asyncEnumerable; await $$ } - } - - - """; - - var expectedCodeAfterCommit = $$""" + } + """, $$""" using System.Collections.Generic; class C @@ -574,60 +466,52 @@ class C IEnumerable enumerable; IAsyncEnumerable asyncEnumerable; - await foreach (var item in asyncEnumerable) + await foreach (var {|0:item|} in {|1:asyncEnumerable|}) { $$ } } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """, + referenceAssemblies: ReferenceAssemblies.Net.Net70); } - [WpfTheory] + [Theory] [InlineData("")] [InlineData("async ")] public async Task InsertAwaitForEachSnippetForPostfixAsyncEnumerableTest(string asyncKeyword) { - var markupBeforeCommit = $$""" - - - using System.Collections.Generic; + await VerifySnippetAsync($$""" + using System.Collections.Generic; class C { - {{asyncKeyword}}void M(IAsyncEnumerable<int> asyncEnumerable) + {{asyncKeyword}}void M(IAsyncEnumerable asyncEnumerable) { asyncEnumerable.$$ } - } - - - """; - - var expectedCodeAfterCommit = $$""" + } + """, $$""" using System.Collections.Generic; class C { {{asyncKeyword}}void M(IAsyncEnumerable asyncEnumerable) { - await foreach (var item in asyncEnumerable) + await foreach (var {|0:item|} in asyncEnumerable) { $$ } } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """, + referenceAssemblies: ReferenceAssemblies.Net.Net70); } - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] public async Task InsertInlineForEachSnippetWhenDottingBeforeContextualKeywordTest1() { - var markupBeforeCommit = """ + await VerifySnippetAsync(""" using System.Collections.Generic; class C @@ -638,69 +522,64 @@ void M(IEnumerable ints) var a = 0; } } - """; - - var expectedCodeAfterCommit = """ + """, """ using System.Collections.Generic; class C { void M(IEnumerable ints) { - foreach (var item in ints) + foreach (var {|0:item|} in ints) { $$ } var a = 0; } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] public async Task InsertInlineForEachSnippetWhenDottingBeforeContextualKeywordTest2() { - var markupBeforeCommit = """ + await VerifySnippetAsync(""" + using System.Threading.Tasks; using System.Collections.Generic; class C { - void M(IEnumerable ints, Task t) + async void M(IEnumerable ints, Task t) { ints.$$ await t; } } - """; - - var expectedCodeAfterCommit = """ + """, """ + using System.Threading.Tasks; using System.Collections.Generic; class C { - void M(IEnumerable ints, Task t) + async void M(IEnumerable ints, Task t) { - foreach (var item in ints) + foreach (var {|0:item|} in ints) { $$ } await t; } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfTheory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] + [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] [InlineData("Task")] [InlineData("Task")] [InlineData("System.Threading.Tasks.Task")] public async Task InsertInlineForEachSnippetWhenDottingBeforeNameSyntaxTest(string nameSyntax) { - var markupBeforeCommit = $$""" + await VerifySnippetAsync($$""" + using System.Threading.Tasks; using System.Collections.Generic; class C @@ -711,144 +590,124 @@ void M(IEnumerable ints) {{nameSyntax}} t = null; } } - """; - - var expectedCodeAfterCommit = $$""" + """, $$""" + using System.Threading.Tasks; using System.Collections.Generic; class C { void M(IEnumerable ints) { - foreach (var item in ints) + foreach (var {|0:item|} in ints) { $$ } {{nameSyntax}} t = null; } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """); } - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] public async Task InsertInlineAwaitForEachSnippetWhenDottingBeforeContextualKeywordTest1() { - var markupBeforeCommit = """ - - - using System.Collections.Generic; + await VerifySnippetAsync(""" + using System.Collections.Generic; class C { - void M(IAsyncEnumerable<int> asyncInts) + void M(IAsyncEnumerable asyncInts) { asyncInts.$$ var a = 0; } - } - - - """; - - var expectedCodeAfterCommit = """ + } + """, """ using System.Collections.Generic; class C { void M(IAsyncEnumerable asyncInts) { - await foreach (var item in asyncInts) + await foreach (var {|0:item|} in asyncInts) { $$ } var a = 0; } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """, + referenceAssemblies: ReferenceAssemblies.Net.Net70); } - [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] public async Task InsertInlineAwaitForEachSnippetWhenDottingBeforeContextualKeywordTest2() { - var markupBeforeCommit = """ - - - using System.Collections.Generic; + await VerifySnippetAsync(""" + using System.Threading.Tasks; + using System.Collections.Generic; class C { - void M(IAsyncEnumerable<int> asyncInts, Task t) + async void M(IAsyncEnumerable asyncInts, Task t) { asyncInts.$$ await t; } - } - - - """; - - var expectedCodeAfterCommit = """ + } + """, """ + using System.Threading.Tasks; using System.Collections.Generic; class C { - void M(IAsyncEnumerable asyncInts, Task t) + async void M(IAsyncEnumerable asyncInts, Task t) { - await foreach (var item in asyncInts) + await foreach (var {|0:item|} in asyncInts) { $$ } await t; } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """, + referenceAssemblies: ReferenceAssemblies.Net.Net70); } - [WpfTheory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] + [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] [InlineData("Task")] [InlineData("Task")] [InlineData("System.Threading.Tasks.Task")] public async Task InsertInlineAwaitForEachSnippetWhenDottingBeforeNameSyntaxTest(string nameSyntax) { - var markupBeforeCommit = $$""" - - - using System.Collections.Generic; + await VerifySnippetAsync($$""" + using System.Threading.Tasks; + using System.Collections.Generic; class C { - void M(IAsyncEnumerable<int> asyncInts) + void M(IAsyncEnumerable asyncInts) { asyncInts.$$ - {{nameSyntax.Replace("<", "<").Replace(">", ">")}} t = null; + {{nameSyntax}} t = null; } - } - - - """; - - var expectedCodeAfterCommit = $$""" + } + """, $$""" + using System.Threading.Tasks; using System.Collections.Generic; class C { void M(IAsyncEnumerable asyncInts) { - await foreach (var item in asyncInts) + await foreach (var {|0:item|} in asyncInts) { $$ } {{nameSyntax}} t = null; } } - """; - - await VerifyCustomCommitProviderAsync(markupBeforeCommit, ItemToCommit, expectedCodeAfterCommit); + """, + referenceAssemblies: ReferenceAssemblies.Net.Net70); } } diff --git a/src/Features/CSharpTest/Snippets/CSharpForSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpForSnippetProviderTests.cs new file mode 100644 index 0000000000000..8e219314bd621 --- /dev/null +++ b/src/Features/CSharpTest/Snippets/CSharpForSnippetProviderTests.cs @@ -0,0 +1,878 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.CodeAnalysis.Testing; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; + +[Trait(Traits.Feature, Traits.Features.Snippets)] +public sealed class CSharpForSnippetProviderTests : AbstractCSharpSnippetProviderTests +{ + protected override string SnippetIdentifier => "for"; + + [Fact] + public async Task InsertForSnippetInMethodTest() + { + await VerifySnippetAsync(""" + class Program + { + public void Method() + { + $$ + } + } + """, """ + class Program + { + public void Method() + { + for (int {|0:i|} = 0; {|0:i|} < {|1:length|}; {|0:i|}++) + { + $$ + } + } + } + """); + } + + [Fact] + public async Task InsertForSnippetInMethodUsedIncrementorTest() + { + await VerifySnippetAsync(""" + class Program + { + public void Method() + { + int i; + $$ + } + } + """, """ + class Program + { + public void Method() + { + int i; + for (int {|0:j|} = 0; {|0:j|} < {|1:length|}; {|0:j|}++) + { + $$ + } + } + } + """); + } + + [Fact] + public async Task InsertForSnippetInMethodUsedIncrementorsTest() + { + await VerifySnippetAsync(""" + class Program + { + public void Method() + { + int i, j, k; + $$ + } + } + """, """ + class Program + { + public void Method() + { + int i, j, k; + for (int {|0:i1|} = 0; {|0:i1|} < {|1:length|}; {|0:i1|}++) + { + $$ + } + } + } + """); + } + + [Fact] + public async Task InsertForSnippetInGlobalContextTest() + { + await VerifySnippetAsync(""" + $$ + """, """ + for (int {|0:i|} = 0; {|0:i|} < {|1:length|}; {|0:i|}++) + { + $$ + } + """); + } + + [Fact] + public async Task InsertForSnippetInConstructorTest() + { + await VerifySnippetAsync(""" + class Program + { + public Program() + { + $$ + } + } + """, """ + class Program + { + public Program() + { + for (int {|0:i|} = 0; {|0:i|} < {|1:length|}; {|0:i|}++) + { + $$ + } + } + } + """); + } + + [Fact] + public async Task InsertForSnippetInLocalFunctionTest() + { + // TODO: fix this test when bug with simplifier failing to find correct node is fixed + await VerifySnippetAsync(""" + class Program + { + public void Method() + { + void LocalFunction() + { + $$ + } + } + } + """, """ + class Program + { + public void Method() + { + void LocalFunction() + { + for (global::System.Int32 {|0:i|} = 0; {|0:i|} < {|1:length|}; {|0:i|}++) + { + $$ + } + } + } + } + """); + } + + [Fact] + public async Task InsertForSnippetInAnonymousFunctionTest() + { + // TODO: fix this test when bug with simplifier failing to find correct node is fixed + await VerifySnippetAsync(""" + class Program + { + public void Method() + { + var action = delegate() + { + $$ + }; + } + } + """, """ + class Program + { + public void Method() + { + var action = delegate() + { + for (global::System.Int32 {|0:i|} = 0; {|0:i|} < {|1:length|}; {|0:i|}++) + { + $$ + } + }; + } + } + """); + } + + [Fact] + public async Task InsertForSnippetInParenthesizedLambdaExpressionTest() + { + // TODO: fix this test when bug with simplifier failing to find correct node is fixed + await VerifySnippetAsync(""" + class Program + { + public void Method() + { + var action = () => + { + $$ + }; + } + } + """, """ + class Program + { + public void Method() + { + var action = () => + { + for (global::System.Int32 {|0:i|} = 0; {|0:i|} < {|1:length|}; {|0:i|}++) + { + $$ + } + }; + } + } + """); + } + + [Fact] + public async Task ProduceVarWithSpecificCodeStyleTest() + { + await VerifySnippetAsync(""" + class Program + { + public void Method() + { + $$ + } + } + """, """ + class Program + { + public void Method() + { + for (var {|0:i|} = 0; {|0:i|} < {|1:length|}; {|0:i|}++) + { + $$ + } + } + } + """, + editorconfig: """ + root = true + + [*] + csharp_style_var_for_built_in_types = true + """); + } + + [Theory] + [MemberData(nameof(CommonSnippetTestData.IntegerTypes), MemberType = typeof(CommonSnippetTestData))] + public async Task InsertInlineForSnippetInMethodTest(string inlineExpressionType) + { + await VerifySnippetAsync($$""" + class Program + { + public void Method({{inlineExpressionType}} l) + { + l.$$ + } + } + """, $$""" + class Program + { + public void Method({{inlineExpressionType}} l) + { + for ({{inlineExpressionType}} {|0:i|} = 0; {|0:i|} < l; {|0:i|}++) + { + $$ + } + } + } + """); + } + + [Theory] + [MemberData(nameof(CommonSnippetTestData.IntegerTypes), MemberType = typeof(CommonSnippetTestData))] + public async Task InsertInlineForSnippetInGlobalContextTest(string inlineExpressionType) + { + await VerifySnippetAsync($$""" + {{inlineExpressionType}} l; + l.$$ + """, $$""" + {{inlineExpressionType}} l; + for ({{inlineExpressionType}} {|0:i|} = 0; {|0:i|} < l; {|0:i|}++) + { + $$ + } + """); + } + + [Theory] + [MemberData(nameof(CommonSnippetTestData.NotIntegerTypesWithoutLengthOrCountProperty), MemberType = typeof(CommonSnippetTestData))] + public async Task NoInlineForSnippetForIncorrectTypeInMethodTest(string inlineExpressionType) + { + await VerifySnippetIsAbsentAsync($$""" + class Program + { + public void Method({{inlineExpressionType}} l) + { + l.$$ + } + } + """); + } + + [Theory] + [MemberData(nameof(CommonSnippetTestData.NotIntegerTypesWithoutLengthOrCountProperty), MemberType = typeof(CommonSnippetTestData))] + public async Task NoInlineForSnippetForIncorrectTypeInGlobalContextTest(string inlineExpressionType) + { + await VerifySnippetIsAbsentAsync($$""" + {{inlineExpressionType}} l; + l.$$ + """); + } + + [Fact] + public async Task ProduceVarWithSpecificCodeStyleForInlineSnippetTest() + { + await VerifySnippetAsync(""" + class Program + { + public void Method(int l) + { + l.$$ + } + } + """, """ + class Program + { + public void Method(int l) + { + for (var {|0:i|} = 0; {|0:i|} < l; {|0:i|}++) + { + $$ + } + } + } + """, + editorconfig: """ + root = true + + [*] + csharp_style_var_for_built_in_types = true + """); + } + + [Fact] + public async Task NoInlineForSnippetNotDirectlyExpressionStatementTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public void Method(int l) + { + System.Console.WriteLine(l.$$); + } + } + """); + } + + [Theory] + [InlineData("// comment")] + [InlineData("/* comment */")] + [InlineData("#region test")] + public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInMethodTest1(string trivia) + { + await VerifySnippetAsync($$""" + class Program + { + void M(int len) + { + {{trivia}} + len.$$ + } + } + """, $$""" + class Program + { + void M(int len) + { + {{trivia}} + for (int {|0:i|} = 0; {|0:i|} < len; {|0:i|}++) + { + $$ + } + } + } + """); + } + + [Theory] + [InlineData("#if true")] + [InlineData("#pragma warning disable CS0108")] + [InlineData("#nullable enable")] + public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInMethodTest2(string trivia) + { + await VerifySnippetAsync($$""" + class Program + { + void M(int len) + { + {{trivia}} + len.$$ + } + } + """, $$""" + class Program + { + void M(int len) + { + {{trivia}} + for (int {|0:i|} = 0; {|0:i|} < len; {|0:i|}++) + { + $$ + } + } + } + """); + } + + [Theory] + [InlineData("// comment")] + [InlineData("/* comment */")] + public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInGlobalStatementTest1(string trivia) + { + await VerifySnippetAsync($$""" + {{trivia}} + 10.$$ + """, $$""" + {{trivia}} + for (int {|0:i|} = 0; {|0:i|} < 10; {|0:i|}++) + { + $$ + } + """); + } + + [Theory] + [InlineData("#region test")] + [InlineData("#if true")] + [InlineData("#pragma warning disable CS0108")] + [InlineData("#nullable enable")] + public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInGlobalStatementTest2(string trivia) + { + await VerifySnippetAsync($$""" + {{trivia}} + 10.$$ + """, $$""" + + {{trivia}} + for (int {|0:i|} = 0; {|0:i|} < 10; {|0:i|}++) + { + $$ + } + """); + } + + [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] + [MemberData(nameof(CommonSnippetTestData.IntegerTypes), MemberType = typeof(CommonSnippetTestData))] + public async Task InsertInlineForSnippetWhenDottingBeforeContextualKeywordTest1(string intType) + { + await VerifySnippetAsync($$""" + using System.Collections.Generic; + + class C + { + void M({{intType}} @int) + { + @int.$$ + var a = 0; + } + } + """, $$""" + using System.Collections.Generic; + + class C + { + void M({{intType}} @int) + { + for ({{intType}} {|0:i|} = 0; {|0:i|} < @int; {|0:i|}++) + { + $$ + } + var a = 0; + } + } + """); + } + + [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] + [MemberData(nameof(CommonSnippetTestData.IntegerTypes), MemberType = typeof(CommonSnippetTestData))] + public async Task InsertInlineForSnippetWhenDottingBeforeContextualKeywordTest2(string intType) + { + await VerifySnippetAsync($$""" + using System.Collections.Generic; + + class C + { + async void M({{intType}} @int, Task t) + { + @int.$$ + await t; + } + } + """, $$""" + using System.Collections.Generic; + + class C + { + async void M({{intType}} @int, Task t) + { + for ({{intType}} {|0:i|} = 0; {|0:i|} < @int; {|0:i|}++) + { + $$ + } + await t; + } + } + """); + } + + [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] + [InlineData("Task")] + [InlineData("Task")] + [InlineData("System.Threading.Tasks.Task")] + public async Task InsertInlineForSnippetWhenDottingBeforeNameSyntaxTest(string nameSyntax) + { + await VerifySnippetAsync($$""" + using System.Threading.Tasks; + using System.Collections.Generic; + + class C + { + void M(int @int) + { + @int.$$ + {{nameSyntax}} t = null; + } + } + """, $$""" + using System.Threading.Tasks; + using System.Collections.Generic; + + class C + { + void M(int @int) + { + for (int {|0:i|} = 0; {|0:i|} < @int; {|0:i|}++) + { + $$ + } + {{nameSyntax}} t = null; + } + } + """); + } + + [Theory] + [InlineData("int[]", "Length")] + [InlineData("Span", "Length")] + [InlineData("ReadOnlySpan", "Length")] + [InlineData("ImmutableArray", "Length")] + [InlineData("List", "Count")] + [InlineData("HashSet", "Count")] + [InlineData("Dictionary", "Count")] + [InlineData("ImmutableList", "Count")] + public async Task InsertInlineForSnippetForCommonTypesWithLengthOrCountPropertyTest(string type, string propertyName) + { + await VerifySnippetAsync($$""" + using System; + using System.Collections.Generic; + using System.Collections.Immutable; + + public class C + { + void M({{type}} type) + { + type.$$ + } + } + """, $$""" + using System; + using System.Collections.Generic; + using System.Collections.Immutable; + + public class C + { + void M({{type}} type) + { + for (int {|0:i|} = 0; {|0:i|} < type.{{propertyName}}; {|0:i|}++) + { + $$ + } + } + } + """, + referenceAssemblies: ReferenceAssemblies.Net.Net80); + } + + [Theory] + [CombinatorialData] + public async Task InsertInlineForSnippetForTypeWithAccessibleLengthOrCountPropertyTest( + [CombinatorialValues("public", "internal", "protected internal")] string propertyAccessibility, + [CombinatorialValues("Length", "Count")] string propertyName) + { + await VerifySnippetAsync($$""" + class C + { + void M(MyType type) + { + type.$$ + } + } + + public class MyType + { + {{propertyAccessibility}} int {{propertyName}} { get; } + } + """, $$""" + class C + { + void M(MyType type) + { + for (int {|0:i|} = 0; {|0:i|} < type.{{propertyName}}; {|0:i|}++) + { + $$ + } + } + } + + public class MyType + { + {{propertyAccessibility}} int {{propertyName}} { get; } + } + """); + } + + [Theory] + [CombinatorialData] + public async Task InsertInlineForSnippetForTypeWithAccessibleLengthOrCountPropertyGetterTest( + [CombinatorialValues("", "internal", "protected internal")] string getterAccessibility, + [CombinatorialValues("Length", "Count")] string propertyName) + { + await VerifySnippetAsync($$""" + class C + { + void M(MyType type) + { + type.$$ + } + } + + public class MyType + { + public int {{propertyName}} { {{getterAccessibility}} get; } + } + """, $$""" + class C + { + void M(MyType type) + { + for (int {|0:i|} = 0; {|0:i|} < type.{{propertyName}}; {|0:i|}++) + { + $$ + } + } + } + + public class MyType + { + public int {{propertyName}} { {{getterAccessibility}} get; } + } + """); + } + + [Theory] + [CombinatorialData] + public async Task InsertInlineForSnippetForTypesWithLengthOrCountPropertyOfDifferentIntegerTypesTest( + [CombinatorialValues("byte", "sbyte", "short", "ushort", "int", "uint", "long", "ulong", "nint", "nuint")] string integerType, + [CombinatorialValues("Length", "Count")] string propertyName) + { + await VerifySnippetAsync($$""" + class C + { + void M(MyType type) + { + type.$$ + } + } + + public class MyType + { + public {{integerType}} {{propertyName}} { get; } + } + """, $$""" + class C + { + void M(MyType type) + { + for ({{integerType}} {|0:i|} = 0; {|0:i|} < type.{{propertyName}}; {|0:i|}++) + { + $$ + } + } + } + + public class MyType + { + public {{integerType}} {{propertyName}} { get; } + } + """); + } + + [Theory] + [InlineData("Length")] + [InlineData("Count")] + public async Task InsertInlineForSnippetForTypeWithLengthOrCountPropertyInBaseClassTest(string propertyName) + { + await VerifySnippetAsync($$""" + class C + { + void M(MyType type) + { + type.$$ + } + } + + public class MyType : MyTypeBase + { + } + + public class MyTypeBase + { + public int {{propertyName}} { get; } + } + """, $$""" + class C + { + void M(MyType type) + { + for (int {|0:i|} = 0; {|0:i|} < type.{{propertyName}}; {|0:i|}++) + { + $$ + } + } + } + + public class MyType : MyTypeBase + { + } + + public class MyTypeBase + { + public int {{propertyName}} { get; } + } + """); + } + + [Theory] + [InlineData("Length")] + [InlineData("Count")] + public async Task NoInlineForSnippetWhenLengthOrCountPropertyHasNoGetterTest(string propertyName) + { + await VerifySnippetIsAbsentAsync($$""" + class C + { + void M(MyType type) + { + type.$$ + } + } + + public class MyType + { + public int {{propertyName}} { set { } } + } + """); + } + + [Theory] + [CombinatorialData] + public async Task NoInlineForSnippetForInaccessibleLengthPropertyTest( + [CombinatorialValues("private", "protected", "private protected")] string propertyAccessibility, + [CombinatorialValues("Length", "Count")] string propertyName) + { + await VerifySnippetIsAbsentAsync($$""" + class C + { + void M(MyType type) + { + type.$$ + } + } + + public class MyType + { + {{propertyAccessibility}} int {{propertyName}} { get; } + } + """); + } + + [Theory] + [CombinatorialData] + public async Task NoInlineForSnippetForInaccessibleLengthOrCountPropertyGetterTest( + [CombinatorialValues("private", "protected", "private protected")] string getterAccessibility, + [CombinatorialValues("Length", "Count")] string propertyName) + { + await VerifySnippetIsAbsentAsync($$""" + class C + { + void M(MyType type) + { + type.$$ + } + } + + public class MyType + { + public int {{propertyName}} { {{getterAccessibility}} get; } + } + """); + } + + [Theory] + [CombinatorialData] + public async Task NoInlineForSnippetForLengthPropertyOfIncorrectTypeTest( + [CombinatorialValues("object", "string", "System.DateTime", "System.Action")] string notIntegerType, + [CombinatorialValues("Length", "Count")] string propertyName) + { + await VerifySnippetIsAbsentAsync($$""" + class C + { + void M(MyType type) + { + type.$$ + } + } + + public class MyType + { + public {{notIntegerType}} {{propertyName}} { get; } + } + """); + } + + [Fact] + public async Task NoInlineForSnippetForTypeWithBothLengthAndCountPropertyTest() + { + await VerifySnippetIsAbsentAsync(""" + class C + { + void M(MyType type) + { + type.$$ + } + } + + public class MyType + { + public int Length { get; } + public int Count { get; } + } + """); + } +} diff --git a/src/Features/CSharpTest/Snippets/CSharpIfSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpIfSnippetProviderTests.cs new file mode 100644 index 0000000000000..038ab754902f9 --- /dev/null +++ b/src/Features/CSharpTest/Snippets/CSharpIfSnippetProviderTests.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; + +public sealed class CSharpIfSnippetProviderTests : AbstractCSharpConditionalBlockSnippetProviderTests +{ + protected override string SnippetIdentifier => "if"; +} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpSimSnippetCompletionProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpIntMainSnippetProviderTests.cs similarity index 57% rename from src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpSimSnippetCompletionProviderTests.cs rename to src/Features/CSharpTest/Snippets/CSharpIntMainSnippetProviderTests.cs index 7854b75169561..55b046b1ae38e 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpSimSnippetCompletionProviderTests.cs +++ b/src/Features/CSharpTest/Snippets/CSharpIntMainSnippetProviderTests.cs @@ -4,46 +4,46 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Test.Utilities; -using Roslyn.Test.Utilities; using Xunit; -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; -public class CSharpSimSnippetCompletionProviderTests : AbstractCSharpSnippetCompletionProviderTests +[Trait(Traits.Feature, Traits.Features.Snippets)] +public sealed class CSharpIntMainSnippetProviderTests : AbstractCSharpSnippetProviderTests { - protected override string ItemToCommit => "sim"; + protected override string SnippetIdentifier => "sim"; - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] - public async Task TestMissingInNamespace() + [Fact] + public async Task TestMissingInBlockNamespace() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" namespace Test { $$ } - """, ItemToCommit); + """); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact] public async Task TestMissingInFileScopedNamespace() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" namespace Test; $$ - """, ItemToCommit); + """); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact] public async Task TestMissingInTopLevelContext() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" System.Console.WriteLine(); $$ - """, ItemToCommit); + """); } - [WpfTheory, Trait(Traits.Feature, Traits.Features.Completion)] + [Theory] [InlineData("class")] [InlineData("struct")] [InlineData("interface")] @@ -52,12 +52,12 @@ await VerifyItemIsAbsentAsync(""" [InlineData("record struct")] public async Task TestInsertSnippetInType(string type) { - await VerifyCustomCommitProviderAsync($$""" + await VerifySnippetAsync($$""" {{type}} Program { $$ } - """, ItemToCommit, $$""" + """, $$""" {{type}} Program { static int Main(string[] args) @@ -69,21 +69,21 @@ static int Main(string[] args) """); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact] public async Task TestMissingInEnum() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" enum MyEnum { $$ } - """, ItemToCommit); + """); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact] public async Task TestMissingInMethod() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" class Program { void M() @@ -91,13 +91,13 @@ void M() $$ } } - """, ItemToCommit); + """); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact] public async Task TestMissingInConstructor() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" class Program { public Program() @@ -105,23 +105,19 @@ public Program() $$ } } - """, ItemToCommit); + """); } - [WpfTheory, Trait(Traits.Feature, Traits.Features.Completion)] - [InlineData("public")] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - [InlineData("protected internal")] + [Theory] + [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))] public async Task TestInsertSnippetAfterAccessibilityModifier(string modifier) { - await VerifyCustomCommitProviderAsync($$""" + await VerifySnippetAsync($$""" class Program { {{modifier}} $$ } - """, ItemToCommit, $$""" + """, $$""" class Program { {{modifier}} static int Main(string[] args) @@ -133,7 +129,7 @@ class Program """); } - [WpfTheory, Trait(Traits.Feature, Traits.Features.Completion)] + [Theory] [InlineData("static")] [InlineData("virtual")] [InlineData("abstract")] @@ -141,37 +137,37 @@ class Program [InlineData("file")] public async Task TestMissingAfterIncorrectModifiers(string modifier) { - await VerifyItemIsAbsentAsync($$""" + await VerifySnippetIsAbsentAsync($$""" class Program { {{modifier}} $$ } - """, ItemToCommit); + """); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact] public async Task TestMissingIfAnotherMemberWithNameMainExists() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" class Program { public int Main => 0; $$ } - """, ItemToCommit); + """); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact] public async Task TestMissingIfTopLevelStatementsArePresent() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" System.Console.WriteLine(); class Program { $$ } - """, ItemToCommit); + """); } } diff --git a/src/Features/CSharpTest/Snippets/CSharpInterfaceSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpInterfaceSnippetProviderTests.cs new file mode 100644 index 0000000000000..d7f11f78611cc --- /dev/null +++ b/src/Features/CSharpTest/Snippets/CSharpInterfaceSnippetProviderTests.cs @@ -0,0 +1,314 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; + +[Trait(Traits.Feature, Traits.Features.Snippets)] +public sealed class CSharpInterfaceSnippetProviderTests : AbstractCSharpSnippetProviderTests +{ + protected override string SnippetIdentifier => "interface"; + + [Fact] + public async Task InsertInterfaceSnippetInBlockNamespaceTest() + { + await VerifySnippetAsync(""" + namespace Namespace + { + $$ + } + """, """ + namespace Namespace + { + interface {|0:MyInterface|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertInterfaceSnippetInFileScopedNamespaceTest() + { + await VerifySnippetAsync(""" + namespace Namespace; + + $$ + """, """ + namespace Namespace; + + interface {|0:MyInterface|} + { + $$ + } + """); + } + + [Fact] + public async Task InsertInterfaceSnippetTest() + { + await VerifySnippetAsync(""" + $$ + """, """ + interface {|0:MyInterface|} + { + $$ + } + """); + } + + [Fact] + public async Task InsertInterfaceTopLevelSnippetTest() + { + await VerifySnippetAsync(""" + System.Console.WriteLine(); + $$ + """, """ + System.Console.WriteLine(); + interface {|0:MyInterface|} + { + $$ + } + """); + } + + [Fact] + public async Task InsertInterfaceSnippetInClassTest() + { + await VerifySnippetAsync(""" + class MyClass + { + $$ + } + """, """ + class MyClass + { + interface {|0:MyInterface|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertInterfaceSnippetInRecordTest() + { + await VerifySnippetAsync(""" + record MyRecord + { + $$ + } + """, """ + record MyRecord + { + interface {|0:MyInterface|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertInterfaceSnippetInStructTest() + { + await VerifySnippetAsync(""" + struct MyStruct + { + $$ + } + """, """ + struct MyStruct + { + interface {|0:MyInterface|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertInterfaceSnippetInInterfaceTest() + { + await VerifySnippetAsync(""" + interface MyInterface + { + $$ + } + """, """ + interface MyInterface + { + interface {|0:MyInterface1|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertInterfaceSnippetWithModifiersTest() + { + await VerifySnippetAsync(""" + $$ + """, """ + public interface {|0:MyInterface|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + """); + } + + [Fact] + public async Task NoInterfaceSnippetInEnumTest() + { + await VerifySnippetIsAbsentAsync(""" + enum MyEnum + { + $$ + } + """); + } + + [Fact] + public async Task NoInterfaceSnippetInMethodTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public void Method() + { + $$ + } + } + """); + } + + [Fact] + public async Task NoInterfaceSnippetInConstructorTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public Program() + { + $$ + } + } + """); + } + + [Theory] + [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))] + public async Task InsertInterfaceSnippetAfterAccessibilityModifier(string modifier) + { + await VerifySnippetAsync($""" + {modifier} $$ + """, $$""" + {{modifier}} interface {|0:MyInterface|} + { + $$ + } + """); + } + + [Theory] + [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))] + public async Task InsertInterfaceSnippetAfterAccessibilityModifier_RequireAccessibilityModifiers(string modifier) + { + await VerifySnippetAsync($""" + {modifier} $$ + """, $$""" + {{modifier}} interface {|0:MyInterface|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + """); + } + + [Theory] + [InlineData("unsafe")] + public async Task InsertInterfaceSnippetAfterValidModifiersTest(string modifier) + { + await VerifySnippetAsync($""" + {modifier} $$ + """, $$""" + {{modifier}} interface {|0:MyInterface|} + { + $$ + } + """); + } + + [Theory] + [InlineData("abstract")] + [InlineData("sealed")] + [InlineData("static")] + [InlineData("ref")] + [InlineData("readonly")] + public async Task NoInterfaceSnippetAfterInvalidModifiersTest(string modifier) + { + await VerifySnippetIsAbsentAsync($""" + {modifier} $$ + """); + } + + [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/69600")] + [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))] + public async Task NoAdditionalAccessibilityModifiersIfAfterPartialKeywordTest(string modifier) + { + await VerifySnippetAsync($""" + {modifier} partial $$ + """, $$""" + {{modifier}} partial interface {|0:MyInterface|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69600")] + public async Task EnsureCorrectModifierOrderAfterPartialKeywordTest() + { + await VerifySnippetAsync(""" + partial $$ + """, """ + public partial interface {|0:MyInterface|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + """); + } +} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpLockSnippetCompletionProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpLockSnippetProviderTests.cs similarity index 72% rename from src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpLockSnippetCompletionProviderTests.cs rename to src/Features/CSharpTest/Snippets/CSharpLockSnippetProviderTests.cs index e98f868689a89..41e9169b6b948 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpLockSnippetCompletionProviderTests.cs +++ b/src/Features/CSharpTest/Snippets/CSharpLockSnippetProviderTests.cs @@ -4,20 +4,19 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Test.Utilities; -using Roslyn.Test.Utilities; using Xunit; -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; -[Trait(Traits.Feature, Traits.Features.Completion)] -public class CSharpLockSnippetCompletionProviderTests : AbstractCSharpSnippetCompletionProviderTests +[Trait(Traits.Feature, Traits.Features.Snippets)] +public sealed class CSharpLockSnippetProviderTests : AbstractCSharpSnippetProviderTests { - protected override string ItemToCommit => "lock"; + protected override string SnippetIdentifier => "lock"; - [WpfFact] + [Fact] public async Task InsertLockSnippetInMethodTest() { - await VerifyCustomCommitProviderAsync(""" + await VerifySnippetAsync(""" class Program { public void Method() @@ -25,12 +24,12 @@ public void Method() $$ } } - """, ItemToCommit, """ + """, """ class Program { public void Method() { - lock (this) + lock ({|0:this|}) { $$ } @@ -39,43 +38,43 @@ public void Method() """); } - [WpfFact] + [Fact] public async Task InsertLockSnippetInGlobalContextTest() { - await VerifyCustomCommitProviderAsync(""" + await VerifySnippetAsync(""" $$ - """, ItemToCommit, """ - lock (this) + """, """ + lock ({|0:this|}) { $$ } """); } - [WpfFact] + [Fact] public async Task NoLockSnippetInBlockNamespaceTest() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" namespace Namespace { $$ } - """, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task NoLockSnippetInFileScopedNamespaceTest() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" namespace Namespace; $$ - """, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task InsertLockSnippetInConstructorTest() { - await VerifyCustomCommitProviderAsync(""" + await VerifySnippetAsync(""" class Program { public Program() @@ -83,12 +82,12 @@ public Program() $$ } } - """, ItemToCommit, """ + """, """ class Program { public Program() { - lock (this) + lock ({|0:this|}) { $$ } @@ -97,21 +96,21 @@ public Program() """); } - [WpfFact] + [Fact] public async Task NoLockSnippetInTypeBodyTest() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" class Program { $$ } - """, ItemToCommit); + """); } - [WpfFact] + [Fact] public async Task InsertLockSnippetInLocalFunctionTest() { - await VerifyCustomCommitProviderAsync(""" + await VerifySnippetAsync(""" class Program { public void Method() @@ -122,14 +121,14 @@ void LocalFunction() } } } - """, ItemToCommit, """ + """, """ class Program { public void Method() { void LocalFunction() { - lock (this) + lock ({|0:this|}) { $$ } @@ -139,10 +138,10 @@ void LocalFunction() """); } - [WpfFact] + [Fact] public async Task InsertLockSnippetInAnonymousFunctionTest() { - await VerifyCustomCommitProviderAsync(""" + await VerifySnippetAsync(""" class Program { public void Method() @@ -153,14 +152,14 @@ public void Method() }; } } - """, ItemToCommit, """ + """, """ class Program { public void Method() { var action = delegate() { - lock (this) + lock ({|0:this|}) { $$ } @@ -170,10 +169,10 @@ public void Method() """); } - [WpfFact] + [Fact] public async Task InsertLockSnippetInParenthesizedLambdaExpressionTest() { - await VerifyCustomCommitProviderAsync(""" + await VerifySnippetAsync(""" class Program { public void Method() @@ -184,14 +183,14 @@ public void Method() }; } } - """, ItemToCommit, """ + """, """ class Program { public void Method() { var action = () => { - lock (this) + lock ({|0:this|}) { $$ } diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpPropSnippetCompletionProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpPropSnippetProviderTests.cs similarity index 63% rename from src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpPropSnippetCompletionProviderTests.cs rename to src/Features/CSharpTest/Snippets/CSharpPropSnippetProviderTests.cs index 67596503fcc10..903f9d6a2b942 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpPropSnippetCompletionProviderTests.cs +++ b/src/Features/CSharpTest/Snippets/CSharpPropSnippetProviderTests.cs @@ -4,16 +4,15 @@ using System.Threading.Tasks; -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; -public class CSharpPropSnippetCompletionProviderTests : AbstractCSharpAutoPropertyCompletionProviderTests +public sealed class CSharpPropSnippetProviderTests : AbstractCSharpAutoPropertySnippetProviderTests { - protected override string ItemToCommit => "prop"; + protected override string SnippetIdentifier => "prop"; - protected override string GetDefaultPropertyBlockText() - => "{ get; set; }"; + protected override string DefaultPropertyBlockText => "{ get; set; }"; - public override async Task InsertSnippetInReadonlyStruct() + public override async Task InsertSnippetInReadonlyStructTest() { // Ensure we don't generate redundant `set` accessor when executed in readonly struct await VerifyPropertyAsync(""" @@ -21,10 +20,10 @@ readonly struct MyStruct { $$ } - """, "public int MyProperty { get; }"); + """, "public {|0:int|} {|1:MyProperty|} { get; }"); } - public override async Task InsertSnippetInReadonlyStruct_ReadonlyModifierInOtherPartialDeclaration() + public override async Task InsertSnippetInReadonlyStructTest_ReadonlyModifierInOtherPartialDeclaration() { // Ensure we don't generate redundant `set` accessor when executed in readonly struct await VerifyPropertyAsync(""" @@ -36,10 +35,10 @@ partial struct MyStruct readonly partial struct MyStruct { } - """, "public int MyProperty { get; }"); + """, "public {|0:int|} {|1:MyProperty|} { get; }"); } - public override async Task InsertSnippetInReadonlyStruct_ReadonlyModifierInOtherPartialDeclaration_MissingPartialModifier() + public override async Task InsertSnippetInReadonlyStructTest_ReadonlyModifierInOtherPartialDeclaration_MissingPartialModifier() { // Even though there is no `partial` modifier on the first declaration // compiler still treats the whole type as partial since it is more likely that @@ -54,10 +53,10 @@ struct MyStruct readonly partial struct MyStruct { } - """, "public int MyProperty { get; }"); + """, "public {|0:int|} {|1:MyProperty|} { get; }"); } - public override async Task InsertSnippetInInterface() + public override async Task InsertSnippetInInterfaceTest() { await VerifyDefaultPropertyAsync(""" interface MyInterface diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpPropgSnippetCompletionProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpPropgSnippetProviderTests.cs similarity index 62% rename from src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpPropgSnippetCompletionProviderTests.cs rename to src/Features/CSharpTest/Snippets/CSharpPropgSnippetProviderTests.cs index 0e6802bd9df30..d4413d32e9bc5 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpPropgSnippetCompletionProviderTests.cs +++ b/src/Features/CSharpTest/Snippets/CSharpPropgSnippetProviderTests.cs @@ -4,16 +4,15 @@ using System.Threading.Tasks; -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; -public class CSharpPropgSnippetCompletionProviderTests : AbstractCSharpAutoPropertyCompletionProviderTests +public sealed class CSharpPropgSnippetProviderTests : AbstractCSharpAutoPropertySnippetProviderTests { - protected override string ItemToCommit => "propg"; + protected override string SnippetIdentifier => "propg"; - protected override string GetDefaultPropertyBlockText() - => "{ get; private set; }"; + protected override string DefaultPropertyBlockText => "{ get; private set; }"; - public override async Task InsertSnippetInReadonlyStruct() + public override async Task InsertSnippetInReadonlyStructTest() { // Ensure we don't generate redundant `set` accessor when executed in readonly struct await VerifyPropertyAsync(""" @@ -21,10 +20,10 @@ readonly struct MyStruct { $$ } - """, "public int MyProperty { get; }"); + """, "public {|0:int|} {|1:MyProperty|} { get; }"); } - public override async Task InsertSnippetInReadonlyStruct_ReadonlyModifierInOtherPartialDeclaration() + public override async Task InsertSnippetInReadonlyStructTest_ReadonlyModifierInOtherPartialDeclaration() { // Ensure we don't generate redundant `set` accessor when executed in readonly struct await VerifyPropertyAsync(""" @@ -36,10 +35,10 @@ partial struct MyStruct readonly partial struct MyStruct { } - """, "public int MyProperty { get; }"); + """, "public {|0:int|} {|1:MyProperty|} { get; }"); } - public override async Task InsertSnippetInReadonlyStruct_ReadonlyModifierInOtherPartialDeclaration_MissingPartialModifier() + public override async Task InsertSnippetInReadonlyStructTest_ReadonlyModifierInOtherPartialDeclaration_MissingPartialModifier() { // Even though there is no `partial` modifier on the first declaration // compiler still treats the whole type as partial since it is more likely that @@ -54,10 +53,10 @@ struct MyStruct readonly partial struct MyStruct { } - """, "public int MyProperty { get; }"); + """, "public {|0:int|} {|1:MyProperty|} { get; }"); } - public override async Task InsertSnippetInInterface() + public override async Task InsertSnippetInInterfaceTest() { // Ensure we don't generate redundant `set` accessor when executed in interface await VerifyPropertyAsync(""" @@ -65,6 +64,6 @@ interface MyInterface { $$ } - """, "public int MyProperty { get; }"); + """, "public {|0:int|} {|1:MyProperty|} { get; }"); } } diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpPropiSnippetCompletionProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpPropiSnippetProviderTests.cs similarity index 59% rename from src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpPropiSnippetCompletionProviderTests.cs rename to src/Features/CSharpTest/Snippets/CSharpPropiSnippetProviderTests.cs index 5a2d0250db204..880dcf3a70927 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpPropiSnippetCompletionProviderTests.cs +++ b/src/Features/CSharpTest/Snippets/CSharpPropiSnippetProviderTests.cs @@ -4,16 +4,15 @@ using System.Threading.Tasks; -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; -public class CSharpPropiSnippetCompletionProviderTests : AbstractCSharpAutoPropertyCompletionProviderTests +public sealed class CSharpPropiSnippetProviderTests : AbstractCSharpAutoPropertySnippetProviderTests { - protected override string ItemToCommit => "propi"; + protected override string SnippetIdentifier => "propi"; - protected override string GetDefaultPropertyBlockText() - => "{ get; init; }"; + protected override string DefaultPropertyBlockText => "{ get; init; }"; - public override async Task InsertSnippetInReadonlyStruct() + public override async Task InsertSnippetInReadonlyStructTest() { await VerifyDefaultPropertyAsync(""" readonly struct MyStruct @@ -23,7 +22,7 @@ readonly struct MyStruct """); } - public override async Task InsertSnippetInReadonlyStruct_ReadonlyModifierInOtherPartialDeclaration() + public override async Task InsertSnippetInReadonlyStructTest_ReadonlyModifierInOtherPartialDeclaration() { await VerifyDefaultPropertyAsync(""" partial struct MyStruct @@ -37,7 +36,7 @@ readonly partial struct MyStruct """); } - public override async Task InsertSnippetInReadonlyStruct_ReadonlyModifierInOtherPartialDeclaration_MissingPartialModifier() + public override async Task InsertSnippetInReadonlyStructTest_ReadonlyModifierInOtherPartialDeclaration_MissingPartialModifier() { await VerifyDefaultPropertyAsync(""" struct MyStruct @@ -51,7 +50,7 @@ readonly partial struct MyStruct """); } - public override async Task InsertSnippetInInterface() + public override async Task InsertSnippetInInterfaceTest() { await VerifyDefaultPropertyAsync(""" interface MyInterface diff --git a/src/Features/CSharpTest/Snippets/CSharpReversedForSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpReversedForSnippetProviderTests.cs new file mode 100644 index 0000000000000..375214bf81ddc --- /dev/null +++ b/src/Features/CSharpTest/Snippets/CSharpReversedForSnippetProviderTests.cs @@ -0,0 +1,880 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Test.Utilities; +using Microsoft.CodeAnalysis.Testing; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; + +[Trait(Traits.Feature, Traits.Features.Snippets)] +public sealed class CSharpReversedForSnippetProviderTests : AbstractCSharpSnippetProviderTests +{ + protected override string SnippetIdentifier => "forr"; + + [Fact] + public async Task InsertReversedForSnippetInMethodTest() + { + await VerifySnippetAsync(""" + class Program + { + public void Method() + { + $$ + } + } + """, """ + class Program + { + public void Method() + { + for (int {|0:i|} = {|1:length|} - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + } + } + """); + } + + [Fact] + public async Task InsertReversedForSnippetInMethodUsedIncrementorTest() + { + await VerifySnippetAsync(""" + class Program + { + public void Method() + { + int i; + $$ + } + } + """, """ + class Program + { + public void Method() + { + int i; + for (int {|0:j|} = {|1:length|} - 1; {|0:j|} >= 0; {|0:j|}--) + { + $$ + } + } + } + """); + } + + [Fact] + public async Task InsertReversedForSnippetInMethodUsedIncrementorsTest() + { + await VerifySnippetAsync(""" + class Program + { + public void Method() + { + int i, j, k; + $$ + } + } + """, """ + class Program + { + public void Method() + { + int i, j, k; + for (int {|0:i1|} = {|1:length|} - 1; {|0:i1|} >= 0; {|0:i1|}--) + { + $$ + } + } + } + """); + } + + [Fact] + public async Task InsertReversedForSnippetInGlobalContextTest() + { + await VerifySnippetAsync(""" + $$ + """, """ + for (int {|0:i|} = {|1:length|} - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + """); + } + + [Fact] + public async Task InsertReversedForSnippetInConstructorTest() + { + await VerifySnippetAsync(""" + class Program + { + public Program() + { + $$ + } + } + """, """ + class Program + { + public Program() + { + for (int {|0:i|} = {|1:length|} - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + } + } + """); + } + + [Fact] + public async Task InsertReversedForSnippetInLocalFunctionTest() + { + // TODO: fix this test when bug with simplifier failing to find correct node is fixed + await VerifySnippetAsync(""" + class Program + { + public void Method() + { + void LocalFunction() + { + $$ + } + } + } + """, """ + class Program + { + public void Method() + { + void LocalFunction() + { + for (global::System.Int32 {|0:i|} = {|1:(length)|} - (1); {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + } + } + } + """); + } + + [Fact] + public async Task InsertReversedForSnippetInAnonymousFunctionTest() + { + // TODO: fix this test when bug with simplifier failing to find correct node is fixed + await VerifySnippetAsync(""" + class Program + { + public void Method() + { + var action = delegate() + { + $$ + }; + } + } + """, """ + class Program + { + public void Method() + { + var action = delegate() + { + for (global::System.Int32 {|0:i|} = {|1:(length)|} - (1); {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + }; + } + } + """); + } + + [Fact] + public async Task InsertReversedForSnippetInParenthesizedLambdaExpressionTest() + { + // TODO: fix this test when bug with simplifier failing to find correct node is fixed + await VerifySnippetAsync(""" + class Program + { + public void Method() + { + var action = () => + { + $$ + }; + } + } + """, """ + class Program + { + public void Method() + { + var action = () => + { + for (global::System.Int32 {|0:i|} = {|1:(length)|} - (1); {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + }; + } + } + """); + } + + [Fact] + public async Task TryToProduceVarWithSpecificCodeStyleTest() + { + // In non-inline reversed for snippet type of expression `length - 1` is unknown, + // so it cannot be simplified to `var`. Therefore having explicit `int` type here is expected + await VerifySnippetAsync(""" + class Program + { + public void Method() + { + $$ + } + } + """, """ + class Program + { + public void Method() + { + for (int {|0:i|} = {|1:length|} - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + } + } + """, + editorconfig: """ + root = true + + [*] + csharp_style_var_for_built_in_types = true + """); + } + + [Theory] + [MemberData(nameof(CommonSnippetTestData.IntegerTypes), MemberType = typeof(CommonSnippetTestData))] + public async Task InsertInlineReversedForSnippetInMethodTest(string inlineExpressionType) + { + await VerifySnippetAsync($$""" + class Program + { + public void Method({{inlineExpressionType}} l) + { + l.$$ + } + } + """, $$""" + class Program + { + public void Method({{inlineExpressionType}} l) + { + for ({{inlineExpressionType}} {|0:i|} = l - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + } + } + """); + } + + [Theory] + [MemberData(nameof(CommonSnippetTestData.IntegerTypes), MemberType = typeof(CommonSnippetTestData))] + public async Task InsertInlineReversedForSnippetInGlobalContextTest(string inlineExpressionType) + { + await VerifySnippetAsync($$""" + {{inlineExpressionType}} l; + l.$$ + """, $$""" + {{inlineExpressionType}} l; + for ({{inlineExpressionType}} {|0:i|} = l - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + """); + } + + [Theory] + [MemberData(nameof(CommonSnippetTestData.NotIntegerTypesWithoutLengthOrCountProperty), MemberType = typeof(CommonSnippetTestData))] + public async Task NoInlineReversedForSnippetForIncorrectTypeInMethodTest(string inlineExpressionType) + { + await VerifySnippetIsAbsentAsync($$""" + class Program + { + public void Method({{inlineExpressionType}} l) + { + l.$$ + } + } + """); + } + + [Theory] + [MemberData(nameof(CommonSnippetTestData.NotIntegerTypesWithoutLengthOrCountProperty), MemberType = typeof(CommonSnippetTestData))] + public async Task NoInlineReversedForSnippetForIncorrectTypeInGlobalContextTest(string inlineExpressionType) + { + await VerifySnippetIsAbsentAsync($$""" + {{inlineExpressionType}} l; + l.$$ + """); + } + + [Fact] + public async Task ProduceVarWithSpecificCodeStyleForInlineSnippetTest() + { + await VerifySnippetAsync(""" + class Program + { + public void Method(int l) + { + l.$$ + } + } + """, """ + class Program + { + public void Method(int l) + { + for (var {|0:i|} = l - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + } + } + """, + editorconfig: """ + root = true + + [*] + csharp_style_var_for_built_in_types = true + """); + } + + [Fact] + public async Task NoInlineReversedForSnippetNotDirectlyExpressionStatementTest() + { + await VerifySnippetIsAbsentAsync(""" + class Program + { + public void Method(int l) + { + System.Console.WriteLine(l.$$); + } + } + """); + } + + [Theory] + [InlineData("// comment")] + [InlineData("/* comment */")] + [InlineData("#region test")] + public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInMethodTest1(string trivia) + { + await VerifySnippetAsync($$""" + class Program + { + void M(int len) + { + {{trivia}} + len.$$ + } + } + """, $$""" + class Program + { + void M(int len) + { + {{trivia}} + for (int {|0:i|} = len - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + } + } + """); + } + + [Theory] + [InlineData("#if true")] + [InlineData("#pragma warning disable CS0108")] + [InlineData("#nullable enable")] + public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInMethodTest2(string trivia) + { + await VerifySnippetAsync($$""" + class Program + { + void M(int len) + { + {{trivia}} + len.$$ + } + } + """, $$""" + class Program + { + void M(int len) + { + {{trivia}} + for (int {|0:i|} = len - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + } + } + """); + } + + [Theory] + [InlineData("// comment")] + [InlineData("/* comment */")] + public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInGlobalStatementTest1(string trivia) + { + await VerifySnippetAsync($$""" + {{trivia}} + 10.$$ + """, $$""" + {{trivia}} + for (int {|0:i|} = 10 - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + """); + } + + [Theory] + [InlineData("#region test")] + [InlineData("#if true")] + [InlineData("#pragma warning disable CS0108")] + [InlineData("#nullable enable")] + public async Task CorrectlyDealWithLeadingTriviaInInlineSnippetInGlobalStatementTest2(string trivia) + { + await VerifySnippetAsync($$""" + {{trivia}} + 10.$$ + """, $$""" + + {{trivia}} + for (int {|0:i|} = 10 - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + """); + } + + [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] + [MemberData(nameof(CommonSnippetTestData.IntegerTypes), MemberType = typeof(CommonSnippetTestData))] + public async Task InsertInlineReversedForSnippetWhenDottingBeforeContextualKeywordTest1(string intType) + { + await VerifySnippetAsync($$""" + using System.Collections.Generic; + + class C + { + void M({{intType}} @int) + { + @int.$$ + var a = 0; + } + } + """, $$""" + using System.Collections.Generic; + + class C + { + void M({{intType}} @int) + { + for ({{intType}} {|0:i|} = @int - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + var a = 0; + } + } + """); + } + + [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] + [MemberData(nameof(CommonSnippetTestData.IntegerTypes), MemberType = typeof(CommonSnippetTestData))] + public async Task InsertInlineReversedForSnippetWhenDottingBeforeContextualKeywordTest2(string intType) + { + await VerifySnippetAsync($$""" + using System.Collections.Generic; + + class C + { + async void M({{intType}} @int, Task t) + { + @int.$$ + await t; + } + } + """, $$""" + using System.Collections.Generic; + + class C + { + async void M({{intType}} @int, Task t) + { + for ({{intType}} {|0:i|} = @int - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + await t; + } + } + """); + } + + [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/69598")] + [InlineData("Task")] + [InlineData("Task")] + [InlineData("System.Threading.Tasks.Task")] + public async Task InsertInlineReversedForSnippetWhenDottingBeforeNameSyntaxTest(string nameSyntax) + { + await VerifySnippetAsync($$""" + using System.Threading.Tasks; + using System.Collections.Generic; + + class C + { + void M(int @int) + { + @int.$$ + {{nameSyntax}} t = null; + } + } + """, $$""" + using System.Threading.Tasks; + using System.Collections.Generic; + + class C + { + void M(int @int) + { + for (int {|0:i|} = @int - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + {{nameSyntax}} t = null; + } + } + """); + } + + [Theory] + [InlineData("int[]", "Length")] + [InlineData("Span", "Length")] + [InlineData("ReadOnlySpan", "Length")] + [InlineData("ImmutableArray", "Length")] + [InlineData("List", "Count")] + [InlineData("HashSet", "Count")] + [InlineData("Dictionary", "Count")] + [InlineData("ImmutableList", "Count")] + public async Task InsertInlineReversedForSnippetForCommonTypesWithLengthOrCountPropertyTest(string type, string propertyName) + { + await VerifySnippetAsync($$""" + using System; + using System.Collections.Generic; + using System.Collections.Immutable; + + public class C + { + void M({{type}} type) + { + type.$$ + } + } + """, $$""" + using System; + using System.Collections.Generic; + using System.Collections.Immutable; + + public class C + { + void M({{type}} type) + { + for (int {|0:i|} = type.{{propertyName}} - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + } + } + """, + referenceAssemblies: ReferenceAssemblies.Net.Net80); + } + + [Theory] + [CombinatorialData] + public async Task InsertInlineReversedForSnippetForTypeWithAccessibleLengthOrCountPropertyTest( + [CombinatorialValues("public", "internal", "protected internal")] string propertyAccessibility, + [CombinatorialValues("Length", "Count")] string propertyName) + { + await VerifySnippetAsync($$""" + class C + { + void M(MyType type) + { + type.$$ + } + } + + public class MyType + { + {{propertyAccessibility}} int {{propertyName}} { get; } + } + """, $$""" + class C + { + void M(MyType type) + { + for (int {|0:i|} = type.{{propertyName}} - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + } + } + + public class MyType + { + {{propertyAccessibility}} int {{propertyName}} { get; } + } + """); + } + + [Theory] + [CombinatorialData] + public async Task InsertInlineReversedForSnippetForTypeWithAccessibleLengthOrCountPropertyGetterTest( + [CombinatorialValues("", "internal", "protected internal")] string getterAccessibility, + [CombinatorialValues("Length", "Count")] string propertyName) + { + await VerifySnippetAsync($$""" + class C + { + void M(MyType type) + { + type.$$ + } + } + + public class MyType + { + public int {{propertyName}} { {{getterAccessibility}} get; } + } + """, $$""" + class C + { + void M(MyType type) + { + for (int {|0:i|} = type.{{propertyName}} - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + } + } + + public class MyType + { + public int {{propertyName}} { {{getterAccessibility}} get; } + } + """); + } + + [Theory] + [CombinatorialData] + public async Task InsertInlineReversedForSnippetForTypesWithLengthOrCountPropertyOfDifferentIntegerTypesTest( + [CombinatorialValues("byte", "sbyte", "short", "ushort", "int", "uint", "long", "ulong", "nint", "nuint")] string integerType, + [CombinatorialValues("Length", "Count")] string propertyName) + { + await VerifySnippetAsync($$""" + class C + { + void M(MyType type) + { + type.$$ + } + } + + public class MyType + { + public {{integerType}} {{propertyName}} { get; } + } + """, $$""" + class C + { + void M(MyType type) + { + for ({{integerType}} {|0:i|} = type.{{propertyName}} - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + } + } + + public class MyType + { + public {{integerType}} {{propertyName}} { get; } + } + """); + } + + [Theory] + [InlineData("Length")] + [InlineData("Count")] + public async Task InsertInlineReversedForSnippetForTypeWithLengthOrCountPropertyInBaseClassTest(string propertyName) + { + await VerifySnippetAsync($$""" + class C + { + void M(MyType type) + { + type.$$ + } + } + + public class MyType : MyTypeBase + { + } + + public class MyTypeBase + { + public int {{propertyName}} { get; } + } + """, $$""" + class C + { + void M(MyType type) + { + for (int {|0:i|} = type.{{propertyName}} - 1; {|0:i|} >= 0; {|0:i|}--) + { + $$ + } + } + } + + public class MyType : MyTypeBase + { + } + + public class MyTypeBase + { + public int {{propertyName}} { get; } + } + """); + } + + [Theory] + [InlineData("Length")] + [InlineData("Count")] + public async Task NoInlineReversedForSnippetWhenLengthOrCountPropertyHasNoGetterTest(string propertyName) + { + await VerifySnippetIsAbsentAsync($$""" + class C + { + void M(MyType type) + { + type.$$ + } + } + + public class MyType + { + public int {{propertyName}} { set { } } + } + """); + } + + [Theory] + [CombinatorialData] + public async Task NoInlineReversedForSnippetForInaccessibleLengthPropertyTest( + [CombinatorialValues("private", "protected", "private protected")] string propertyAccessibility, + [CombinatorialValues("Length", "Count")] string propertyName) + { + await VerifySnippetIsAbsentAsync($$""" + class C + { + void M(MyType type) + { + type.$$ + } + } + + public class MyType + { + {{propertyAccessibility}} int {{propertyName}} { get; } + } + """); + } + + [Theory] + [CombinatorialData] + public async Task NoInlineReversedForSnippetForInaccessibleLengthOrCountPropertyGetterTest( + [CombinatorialValues("private", "protected", "private protected")] string getterAccessibility, + [CombinatorialValues("Length", "Count")] string propertyName) + { + await VerifySnippetIsAbsentAsync($$""" + class C + { + void M(MyType type) + { + type.$$ + } + } + + public class MyType + { + public int {{propertyName}} { {{getterAccessibility}} get; } + } + """); + } + + [Theory] + [CombinatorialData] + public async Task NoInlineReversedForSnippetForLengthPropertyOfIncorrectTypeTest( + [CombinatorialValues("object", "string", "System.DateTime", "System.Action")] string notIntegerType, + [CombinatorialValues("Length", "Count")] string propertyName) + { + await VerifySnippetIsAbsentAsync($$""" + class C + { + void M(MyType type) + { + type.$$ + } + } + + public class MyType + { + public {{notIntegerType}} {{propertyName}} { get; } + } + """); + } + + [Fact] + public async Task NoInlineReversedForSnippetForTypeWithBothLengthAndCountPropertyTest() + { + await VerifySnippetIsAbsentAsync(""" + class C + { + void M(MyType type) + { + type.$$ + } + } + + public class MyType + { + public int Length { get; } + public int Count { get; } + } + """); + } +} diff --git a/src/Features/CSharpTest/Snippets/CSharpStructSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpStructSnippetProviderTests.cs new file mode 100644 index 0000000000000..39200d76aeefc --- /dev/null +++ b/src/Features/CSharpTest/Snippets/CSharpStructSnippetProviderTests.cs @@ -0,0 +1,419 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Test.Utilities; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; + +[Trait(Traits.Feature, Traits.Features.Snippets)] +public sealed class CSharpStructSnippetProviderTests : AbstractCSharpSnippetProviderTests +{ + protected override string SnippetIdentifier => "struct"; + + [Fact] + public async Task InsertStructSnippetInBlockNamespaceTest() + { + await VerifySnippetAsync(""" + namespace Namespace + { + $$ + } + """, """ + namespace Namespace + { + struct {|0:MyStruct|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertStructSnippetInFileScopedNamespaceTest() + { + await VerifySnippetAsync(""" + namespace Namespace; + + $$ + """, """ + namespace Namespace; + + struct {|0:MyStruct|} + { + $$ + } + """); + } + + [Fact] + public async Task InsertStructSnippetTest() + { + await VerifySnippetAsync(""" + $$ + """, """ + struct {|0:MyStruct|} + { + $$ + } + """); + } + + [Fact] + public async Task InsertStructTopLevelSnippetTest() + { + await VerifySnippetAsync(""" + System.Console.WriteLine(); + $$ + """, """ + System.Console.WriteLine(); + struct {|0:MyStruct|} + { + $$ + } + """); + } + + [Fact] + public async Task InsertStructSnippetInClassTest() + { + await VerifySnippetAsync(""" + class MyClass + { + $$ + } + """, """ + class MyClass + { + struct {|0:MyStruct|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertStructSnippetInRecordTest() + { + await VerifySnippetAsync(""" + record MyRecord + { + $$ + } + """, """ + record MyRecord + { + struct {|0:MyStruct|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertStructSnippetInStructTest() + { + await VerifySnippetAsync(""" + struct MyStruct + { + $$ + } + """, """ + struct MyStruct + { + struct {|0:MyStruct1|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertStructSnippetInInterfaceTest() + { + await VerifySnippetAsync(""" + interface MyInterface + { + $$ + } + """, """ + interface MyInterface + { + struct {|0:MyStruct|} + { + $$ + } + } + """); + } + + [Fact] + public async Task InsertStructSnippetWithModifiersTest() + { + await VerifySnippetAsync(""" + $$ + """, """ + public struct {|0:MyStruct|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + """); + } + + [Fact] + public async Task NoStructSnippetInEnumTest() + { + await VerifySnippetIsAbsentAsync(""" + enum MyEnum + { + $$ + } + """); + } + + [Fact] + public async Task NoStructSnippetInMethodTest() + { + await VerifySnippetIsAbsentAsync(""" + struct Program + { + public void Method() + { + $$ + } + } + """); + } + + [Fact] + public async Task NoStructSnippetInConstructorTest() + { + await VerifySnippetIsAbsentAsync(""" + struct Program + { + public Program() + { + $$ + } + } + """); + } + + [Theory] + [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))] + public async Task InsertStructSnippetAfterAccessibilityModifier(string modifier) + { + await VerifySnippetAsync($""" + {modifier} $$ + """, $$""" + {{modifier}} struct {|0:MyStruct|} + { + $$ + } + """); + } + + [Theory] + [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))] + public async Task InsertStructSnippetAfterAccessibilityModifier_RequireAccessibilityModifiers(string modifier) + { + await VerifySnippetAsync($""" + {modifier} $$ + """, $$""" + {{modifier}} struct {|0:MyStruct|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + """); + } + + [Theory] + [InlineData("ref")] + [InlineData("readonly")] + [InlineData("unsafe")] + public async Task InsertStructSnippetAfterValidModifiersTest(string modifier) + { + await VerifySnippetAsync($""" + {modifier} $$ + """, $$""" + {{modifier}} struct {|0:MyStruct|} + { + $$ + } + """); + } + + [Theory] + [InlineData("abstract")] + [InlineData("sealed")] + [InlineData("static")] + public async Task NoStructSnippetAfterInvalidModifiersTest(string modifier) + { + await VerifySnippetIsAbsentAsync($""" + {modifier} $$ + """); + } + + [Theory, WorkItem("https://github.com/dotnet/roslyn/issues/69600")] + [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))] + public async Task NoAdditionalAccessibilityModifiersIfAfterPartialKeywordTest(string modifier) + { + await VerifySnippetAsync($""" + {modifier} partial $$ + """, $$""" + {{modifier}} partial struct {|0:MyStruct|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69600")] + public async Task EnsureCorrectModifierOrderAfterPartialKeywordTest() + { + await VerifySnippetAsync(""" + partial $$ + """, """ + public partial struct {|0:MyStruct|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + """); + } + + [Fact, WorkItem("https://github.com/dotnet/roslyn/issues/69600")] + public async Task EnsureCorrectModifierOrderAfterPartialKeywordTest_InvalidPreferredModifiersList() + { + await VerifySnippetAsync(""" + partial $$ + """, """ + public partial struct {|0:MyStruct|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + + csharp_preferred_modifier_order = invalid! + """); + } + + [Fact] + public async Task EnsureCorrectModifierOrderFromOptionsTest_PublicModifierBeforeAllOthers() + { + await VerifySnippetAsync(""" + readonly ref $$ + """, """ + public readonly ref struct {|0:MyStruct|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + + csharp_preferred_modifier_order = public,readonly,ref + """); + } + + [Fact] + public async Task EnsureCorrectModifierOrderFromOptionsTest_PublicModifierBeforeAllOthers_NotAllModifiersInTheList() + { + await VerifySnippetAsync(""" + readonly ref $$ + """, """ + public readonly ref struct {|0:MyStruct|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + + csharp_preferred_modifier_order = public,readonly + """); + } + + [Fact] + public async Task EnsureCorrectModifierOrderFromOptionsTest_PublicModifierBetweenOthers() + { + await VerifySnippetAsync(""" + readonly ref $$ + """, """ + readonly public ref struct {|0:MyStruct|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + + csharp_preferred_modifier_order = readonly,public,ref + """); + } + + [Fact] + public async Task EnsureCorrectModifierOrderFromOptionsTest_PublicModifierAfterAllOthers() + { + await VerifySnippetAsync(""" + readonly ref $$ + """, """ + readonly ref public struct {|0:MyStruct|} + { + $$ + } + """, + editorconfig: """ + root = true + + [*] + dotnet_style_require_accessibility_modifiers = always + + csharp_preferred_modifier_order = readonly,ref,public + """); + } +} diff --git a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpSvmSnippetCompletionProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpVoidMainSnippetProviderTests.cs similarity index 57% rename from src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpSvmSnippetCompletionProviderTests.cs rename to src/Features/CSharpTest/Snippets/CSharpVoidMainSnippetProviderTests.cs index 2c87172c08f06..1303b298e4f97 100644 --- a/src/EditorFeatures/CSharpTest/Completion/CompletionProviders/Snippets/CSharpSvmSnippetCompletionProviderTests.cs +++ b/src/Features/CSharpTest/Snippets/CSharpVoidMainSnippetProviderTests.cs @@ -4,46 +4,46 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.Test.Utilities; -using Roslyn.Test.Utilities; using Xunit; -namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders.Snippets; +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; -public class CSharpSvmSnippetCompletionProviderTests : AbstractCSharpSnippetCompletionProviderTests +[Trait(Traits.Feature, Traits.Features.Snippets)] +public sealed class CSharpVoidMainSnippetProviderTests : AbstractCSharpSnippetProviderTests { - protected override string ItemToCommit => "svm"; + protected override string SnippetIdentifier => "svm"; - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] - public async Task TestMissingInNamespace() + [Fact] + public async Task TestMissingInBlockNamespace() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" namespace Test { $$ } - """, ItemToCommit); + """); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact] public async Task TestMissingInFileScopedNamespace() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" namespace Test; $$ - """, ItemToCommit); + """); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact] public async Task TestMissingInTopLevelContext() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" System.Console.WriteLine(); $$ - """, ItemToCommit); + """); } - [WpfTheory, Trait(Traits.Feature, Traits.Features.Completion)] + [Theory] [InlineData("class")] [InlineData("struct")] [InlineData("interface")] @@ -52,12 +52,12 @@ await VerifyItemIsAbsentAsync(""" [InlineData("record struct")] public async Task TestInsertSnippetInType(string type) { - await VerifyCustomCommitProviderAsync($$""" + await VerifySnippetAsync($$""" {{type}} Program { $$ } - """, ItemToCommit, $$""" + """, $$""" {{type}} Program { static void Main(string[] args) @@ -68,21 +68,21 @@ static void Main(string[] args) """); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact] public async Task TestMissingInEnum() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" enum MyEnum { $$ } - """, ItemToCommit); + """); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact] public async Task TestMissingInMethod() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" class Program { void M() @@ -90,13 +90,13 @@ void M() $$ } } - """, ItemToCommit); + """); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact] public async Task TestMissingInConstructor() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" class Program { public Program() @@ -104,23 +104,19 @@ public Program() $$ } } - """, ItemToCommit); + """); } - [WpfTheory, Trait(Traits.Feature, Traits.Features.Completion)] - [InlineData("public")] - [InlineData("private")] - [InlineData("protected")] - [InlineData("private protected")] - [InlineData("protected internal")] + [Theory] + [MemberData(nameof(CommonSnippetTestData.AllAccessibilityModifiers), MemberType = typeof(CommonSnippetTestData))] public async Task TestInsertSnippetAfterAccessibilityModifier(string modifier) { - await VerifyCustomCommitProviderAsync($$""" + await VerifySnippetAsync($$""" class Program { {{modifier}} $$ } - """, ItemToCommit, $$""" + """, $$""" class Program { {{modifier}} static void Main(string[] args) @@ -131,7 +127,7 @@ class Program """); } - [WpfTheory, Trait(Traits.Feature, Traits.Features.Completion)] + [Theory] [InlineData("static")] [InlineData("virtual")] [InlineData("abstract")] @@ -139,37 +135,37 @@ class Program [InlineData("file")] public async Task TestMissingAfterIncorrectModifiers(string modifier) { - await VerifyItemIsAbsentAsync($$""" + await VerifySnippetIsAbsentAsync($$""" class Program { {{modifier}} $$ } - """, ItemToCommit); + """); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact] public async Task TestMissingIfAnotherMemberWithNameMainExists() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" class Program { public int Main => 0; $$ } - """, ItemToCommit); + """); } - [WpfFact, Trait(Traits.Feature, Traits.Features.Completion)] + [Fact] public async Task TestMissingIfTopLevelStatementsArePresent() { - await VerifyItemIsAbsentAsync(""" + await VerifySnippetIsAbsentAsync(""" System.Console.WriteLine(); class Program { $$ } - """, ItemToCommit); + """); } } diff --git a/src/Features/CSharpTest/Snippets/CSharpWhileSnippetProviderTests.cs b/src/Features/CSharpTest/Snippets/CSharpWhileSnippetProviderTests.cs new file mode 100644 index 0000000000000..7d175ed42f969 --- /dev/null +++ b/src/Features/CSharpTest/Snippets/CSharpWhileSnippetProviderTests.cs @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; + +public sealed class CSharpWhileSnippetProviderTests : AbstractCSharpConditionalBlockSnippetProviderTests +{ + protected override string SnippetIdentifier => "while"; +} diff --git a/src/Features/CSharpTest/Snippets/CommonSnippetTestData.cs b/src/Features/CSharpTest/Snippets/CommonSnippetTestData.cs new file mode 100644 index 0000000000000..95585d2385a45 --- /dev/null +++ b/src/Features/CSharpTest/Snippets/CommonSnippetTestData.cs @@ -0,0 +1,41 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Xunit; + +namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Snippets; + +public static class CommonSnippetTestData +{ + public static TheoryData IntegerTypes => new() + { + "byte", + "sbyte", + "short", + "ushort", + "int", + "uint", + "long", + "ulong", + "nint", + "nuint", + }; + + public static TheoryData NotIntegerTypesWithoutLengthOrCountProperty => new() + { + "object", + "System.DateTime", + "System.Action", + }; + + public static TheoryData AllAccessibilityModifiers => new() + { + "public", + "private", + "protected", + "internal", + "private protected", + "protected internal", + }; +} diff --git a/src/Features/Core/Portable/Snippets/AbstractSnippetService.cs b/src/Features/Core/Portable/Snippets/AbstractSnippetService.cs index 8ee61c89eb4bc..69439dbed076c 100644 --- a/src/Features/Core/Portable/Snippets/AbstractSnippetService.cs +++ b/src/Features/Core/Portable/Snippets/AbstractSnippetService.cs @@ -39,7 +39,8 @@ public ISnippetProvider GetSnippetProvider(string snippetIdentifier) public ImmutableArray GetSnippets(SnippetContext context, CancellationToken cancellationToken) { using var _ = ArrayBuilder.GetInstance(out var arrayBuilder); - foreach (var provider in GetSnippetProviders(context.Document)) + EnsureSnippetsLoaded(context.Document.Project.Language); + foreach (var provider in _snippetProviders) { if (provider.IsValidSnippetLocation(context, cancellationToken)) arrayBuilder.Add(new(provider.Identifier, provider.Description, provider.AdditionalFilterTexts)); @@ -48,14 +49,14 @@ public ImmutableArray GetSnippets(SnippetContext context, Cancellat return arrayBuilder.ToImmutableAndClear(); } - private ImmutableArray GetSnippetProviders(Document document) + internal void EnsureSnippetsLoaded(string language) { lock (_snippetProvidersLock) { if (_snippetProviders.IsDefault) { using var _ = ArrayBuilder.GetInstance(out var arrayBuilder); - foreach (var provider in _lazySnippetProviders.Where(p => p.Metadata.Language == document.Project.Language)) + foreach (var provider in _lazySnippetProviders.Where(p => p.Metadata.Language == language)) { var providerData = provider.Value; Debug.Assert(!_identifierToProviderMap.TryGetValue(providerData.Identifier, out var _)); @@ -66,7 +67,5 @@ private ImmutableArray GetSnippetProviders(Document document) _snippetProviders = arrayBuilder.ToImmutable(); } } - - return _snippetProviders; } } diff --git a/src/Features/Core/Portable/Snippets/SnippetPlaceholder.cs b/src/Features/Core/Portable/Snippets/SnippetPlaceholder.cs index 5ac97d650be43..be91e76766823 100644 --- a/src/Features/Core/Portable/Snippets/SnippetPlaceholder.cs +++ b/src/Features/Core/Portable/Snippets/SnippetPlaceholder.cs @@ -48,4 +48,10 @@ public SnippetPlaceholder(string text, int startingPosition) : this(text, [startingPosition]) { } + + public void Deconstruct(out string text, out ImmutableArray startingPositions) + { + text = Text; + startingPositions = StartingPositions; + } } diff --git a/src/Features/TestUtilities/Snippets/AbstractSnippetProviderTests.cs b/src/Features/TestUtilities/Snippets/AbstractSnippetProviderTests.cs new file mode 100644 index 0000000000000..838958b955dd1 --- /dev/null +++ b/src/Features/TestUtilities/Snippets/AbstractSnippetProviderTests.cs @@ -0,0 +1,139 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery; +using Microsoft.CodeAnalysis.Snippets; +using Microsoft.CodeAnalysis.Testing; +using Microsoft.CodeAnalysis.Text; +using Xunit; + +namespace Microsoft.CodeAnalysis.Test.Utilities.Snippets; + +[UseExportProvider] +public abstract class AbstractSnippetProviderTests +{ + protected abstract string SnippetIdentifier { get; } + + protected abstract string LanguageName { get; } + + protected async Task VerifySnippetAsync( + [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string markupBeforeCommit, + [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string markupAfterCommit, + string? editorconfig = null, + ReferenceAssemblies? referenceAssemblies = null) + { + using var workspace = new TestWorkspace(FeaturesTestCompositions.Features); + + referenceAssemblies ??= ReferenceAssemblies.Default; + var metadataReferences = await referenceAssemblies.ResolveAsync(LanguageName, CancellationToken.None); + var project = workspace.CurrentSolution. + AddProject("TestProject", "TestAssembly", LanguageName) + .WithMetadataReferences(metadataReferences); + + TestFileMarkupParser.GetPosition(markupBeforeCommit, out markupBeforeCommit, out var snippetRequestPosition); + var document = project.AddDocument("TestDocument", markupBeforeCommit, filePath: "/TestDocument"); + + if (editorconfig is not null) + { + var editorConfigDoc = document.Project.AddAnalyzerConfigDocument(".editorconfig", SourceText.From(editorconfig), filePath: "/.editorconfig"); + document = editorConfigDoc.Project.GetDocument(document.Id)!; + } + + var snippetServiceInterface = document.GetRequiredLanguageService(); + var snippetService = Assert.IsAssignableFrom(snippetServiceInterface); + + snippetService.EnsureSnippetsLoaded(LanguageName); + var snippetProvider = snippetService.GetSnippetProvider(SnippetIdentifier); + + var syntaxContextService = document.GetRequiredLanguageService(); + var semanticModel = await document.GetRequiredSemanticModelAsync(CancellationToken.None); + var syntaxContext = syntaxContextService.CreateContext(document, semanticModel, snippetRequestPosition, CancellationToken.None); + + var snippetContext = new SnippetContext(syntaxContext); + var isValidSnippetLocation = snippetProvider.IsValidSnippetLocation(snippetContext, CancellationToken.None); + Assert.True(isValidSnippetLocation, "Snippet is unexpectedly invalid on a given position"); + + var snippetChange = await snippetProvider.GetSnippetChangeAsync(document, snippetRequestPosition, CancellationToken.None); + var documentSourceText = await document.GetTextAsync(); + var documentTextAfterSnippet = documentSourceText.WithChanges(snippetChange.TextChanges); + + TestFileMarkupParser.GetPositionAndSpans(markupAfterCommit, out markupAfterCommit, out int finalCaretPosition, out ImmutableDictionary> placeholderLocations); + Assert.Equal(markupAfterCommit, documentTextAfterSnippet.ToString()); + + var placeholderLocationsArray = new ImmutableArray[placeholderLocations.Count]; + var snippetPlaceholders = snippetChange.Placeholders; + Assert.Equal(placeholderLocationsArray.Length, snippetPlaceholders.Length); + + foreach (var placeholderLocationPair in placeholderLocations) + { + if (!int.TryParse(placeholderLocationPair.Key, out var locationIndex)) + { + Assert.True(false, "Expected placeholder locations contains span with invalid annotation"); + return; + } + + placeholderLocationsArray[locationIndex] = placeholderLocationPair.Value; + } + + for (var i = 0; i < placeholderLocationsArray.Length; i++) + { + if (placeholderLocationsArray[i].IsDefault) + { + Assert.True(false, $"Placeholder location for index {i} was not specified"); + } + } + + for (var i = 0; i < snippetPlaceholders.Length; i++) + { + var expectedSpans = placeholderLocationsArray[i]; + var (placeholderText, placeholderPositions) = snippetPlaceholders[i]; + + Assert.Equal(expectedSpans.Length, placeholderPositions.Length); + + for (var j = 0; j < placeholderPositions.Length; j++) + { + var expectedSpan = expectedSpans[j]; + Assert.Contains(expectedSpan.Start, placeholderPositions); + Assert.Equal(documentTextAfterSnippet.ToString(expectedSpan), placeholderText); + } + } + + Assert.Equal(finalCaretPosition, snippetChange.FinalCaretPosition); + } + + protected async Task VerifySnippetIsAbsentAsync( + [StringSyntax(PredefinedEmbeddedLanguageNames.CSharpTest)] string markup, + ReferenceAssemblies? referenceAssemblies = null) + { + using var workspace = new TestWorkspace(FeaturesTestCompositions.Features); + + referenceAssemblies ??= ReferenceAssemblies.Default; + var metadataReferences = await referenceAssemblies.ResolveAsync(LanguageName, CancellationToken.None); + var project = workspace.CurrentSolution. + AddProject("TestProject", "TestAssembly", LanguageName) + .WithMetadataReferences(metadataReferences); + + TestFileMarkupParser.GetPosition(markup, out markup, out var snippetRequestPosition); + var document = project.AddDocument("TestDocument", markup); + + var snippetServiceInterface = document.GetRequiredLanguageService(); + var snippetService = Assert.IsAssignableFrom(snippetServiceInterface); + + snippetService.EnsureSnippetsLoaded(LanguageName); + var snippetProvider = snippetService.GetSnippetProvider(SnippetIdentifier); + + var syntaxContextService = document.GetRequiredLanguageService(); + var semanticModel = await document.GetRequiredSemanticModelAsync(CancellationToken.None); + var syntaxContext = syntaxContextService.CreateContext(document, semanticModel, snippetRequestPosition, CancellationToken.None); + + var snippetContext = new SnippetContext(syntaxContext); + var isValidSnippetLocation = snippetProvider.IsValidSnippetLocation(snippetContext, CancellationToken.None); + Assert.False(isValidSnippetLocation, "Snippet is unexpectedly valid on a given position"); + } +} diff --git a/src/Features/DiagnosticsTestUtilities/Utilities/StringSyntaxAttribute.cs b/src/Features/TestUtilities/Utilities/StringSyntaxAttribute.cs similarity index 89% rename from src/Features/DiagnosticsTestUtilities/Utilities/StringSyntaxAttribute.cs rename to src/Features/TestUtilities/Utilities/StringSyntaxAttribute.cs index 4c54aa7019884..9e06c3e595612 100644 --- a/src/Features/DiagnosticsTestUtilities/Utilities/StringSyntaxAttribute.cs +++ b/src/Features/TestUtilities/Utilities/StringSyntaxAttribute.cs @@ -7,7 +7,7 @@ namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] - public sealed class StringSyntaxAttribute : Attribute + internal sealed class StringSyntaxAttribute : Attribute { public StringSyntaxAttribute(string syntax) => Syntax = syntax; public string Syntax { get; }