/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/EditorFeatures/CSharpTest/EventHookup/EventHookupCommandHandlerTests.cs
1 227 строк
35 KB
Amadeusz Wieczorek
fix tests and add one test
05 дек 2025, 02:25
05 дек 2025, 02:25
55451a8
Код
Авторство
О чём код?
// 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. #nullable disable using System.Threading.Tasks; using System.Xml.Linq; using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics.NamingStyles; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.EventHookup; [UseExportProvider] [Trait(Traits.Feature, Traits.Features.EventHookup)] public sealed class EventHookupCommandHandlerTests { private readonly NamingStylesTestOptionSets _namingOptions = new(LanguageNames.CSharp); [WpfFact] public async Task HandlerName_EventInThisClass() { var markup = """ class C { event System.Action MyEvent; void M() { MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("C_MyEvent"); } [WpfFact] public async Task Handler_DismissSuggestionService() { var markup = """ class C { event System.Action MyEvent; void M() { MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("C_MyEvent"); testState.AssertSuggestionServiceWasDismissed(); } [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/20999")] public async Task HandlerName_EventInThisClass_CamelCaseRule() { var markup = """ class C { event System.Action MyEvent; void M() { MyEvent +$$ } } """; using var testState = new EventHookupTestState( EventHookupTestState.GetWorkspaceXml(markup), _namingOptions.MethodNamesAreCamelCase); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("c_MyEvent"); } [WpfFact] public async Task HandlerName_EventOnLocal() { var markup = """ class C { public event System.Action MyEvent; } class D { void M() { C local = new C(); local.MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("Local_MyEvent"); } [WpfFact] public async Task HandlerName_EventOnFieldOfObject() { var markup = """ class C { public event System.Action MyEvent; } class D { public C cfield = new C(); } class E { void Goo() { D local = new D(); local.cfield.MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("Cfield_MyEvent"); } [WpfFact] public async Task NoHookupOnIntegerPlusEquals() { var markup = """ class C { void Goo() { int x = 7; x +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertNotShowing(); // Make sure that sending the tab works correctly. Note the 4 spaces after the += testState.SendTab(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertCodeIs(""" class C { void Goo() { int x = 7; x += } } """); } [WpfFact] public async Task HandlerName_DefaultHandlerNameAlreadyExistsWithSameNonStaticState() { var markup = """ class C { public event System.Action MyEvent; void Goo() { MyEvent +$$ } private void C_MyEvent() { } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("C_MyEvent1"); } [WpfFact] public async Task HandlerName_DefaultHandlerNameAlreadyExistsWithDifferentStaticState() { var markup = """ class C { public event System.Action MyEvent; void Goo() { MyEvent +$$ } private static void C_MyEvent() { } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("C_MyEvent1"); } [WpfFact] public async Task HandlerName_DefaultHandlerNameAlreadyExistsAsField() { var markup = """ class C { event System.Action MyEvent; int C_MyEvent; void M(string[] args) { MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("C_MyEvent1"); } [WpfFact] public async Task HookupInLambdaInLocalDeclaration() { var markup = """ class C { public event System.Action MyEvent; void Goo() { Action a = () => MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("C_MyEvent"); } [WpfFact] public async Task TypingSpacesDoesNotDismiss() { var markup = """ class C { event System.Action MyEvent; void M() { MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("C_MyEvent"); testState.SendTypeChar(' '); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("C_MyEvent"); } [WpfFact] public async Task TypingLettersDismisses() { var markup = """ class C { event System.Action MyEvent; void M() { MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("C_MyEvent"); testState.SendTypeChar('d'); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertNotShowing(); } [WpfFact] public async Task TypingEqualsInSessionDismisses() { var markup = """ class C { event System.Action MyEvent; void M() { MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("C_MyEvent"); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertNotShowing(); } [WpfFact] public async Task CancelViaLeftKey() { var markup = """ class C { event System.Action MyEvent; void M() { MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("C_MyEvent"); testState.SendTypeChar(' '); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("C_MyEvent"); testState.SendLeftKey(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("C_MyEvent"); testState.SendLeftKey(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertNotShowing(); } [WpfFact] public async Task CancelViaBackspace() { var markup = """ class C { event System.Action MyEvent; void M() { MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("C_MyEvent"); testState.SendTypeChar(' '); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("C_MyEvent"); testState.SendBackspace(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertNotShowing(); } [WpfFact] public async Task EventHookupBeforeEventHookup() { var markup = """ class C { event System.Action MyEvent; void M() { MyEvent +$$ MyEvent += C_MyEvent; } private void C_MyEvent() { throw new System.NotImplementedException(); } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); testState.SendTab(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertCodeIs(""" class C { event System.Action MyEvent; void M() { MyEvent += C_MyEvent1; MyEvent += C_MyEvent; } private void C_MyEvent1() { throw new System.NotImplementedException(); } private void C_MyEvent() { throw new System.NotImplementedException(); } } """); } [WpfFact] public async Task EventHookupBeforeComment() { var markup = """ class C { event System.Action MyEvent; void M() { MyEvent +$$ // Awesome Comment! MyEvent += C_MyEvent; } private void C_MyEvent() { throw new System.NotImplementedException(); } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); testState.SendTab(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertCodeIs(""" class C { event System.Action MyEvent; void M() { MyEvent += C_MyEvent1; // Awesome Comment! MyEvent += C_MyEvent; } private void C_MyEvent1() { throw new System.NotImplementedException(); } private void C_MyEvent() { throw new System.NotImplementedException(); } } """); } [WpfFact] public async Task EventHookupInArgument() { var markup = """ class C { event System.Action MyEvent; void M() { Goo(() => MyEvent +$$) } private void Goo(Action a) { } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); testState.SendTab(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertCodeIs(""" class C { event System.Action MyEvent; void M() { Goo(() => MyEvent += C_MyEvent;) } private void C_MyEvent() { throw new System.NotImplementedException(); } private void Goo(Action a) { } } """); } [WpfFact] public async Task HookupInFieldDeclarationSingleLineLambda() { var markup = """ class C { static event System.Action MyEvent; System.Action A = () => MyEvent +$$ } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); testState.SendTab(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertCodeIs(""" class C { static event System.Action MyEvent; System.Action A = () => MyEvent += C_MyEvent; private static void C_MyEvent() { throw new System.NotImplementedException(); } } """); } [WpfFact] public async Task HookupInFieldDeclarationMultiLineLambda() { var markup = """ class C { static event System.Action MyEvent; System.Action A = () => { MyEvent +$$ }; } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); testState.SendTab(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertCodeIs(""" class C { static event System.Action MyEvent; System.Action A = () => { MyEvent += C_MyEvent; }; private static void C_MyEvent() { throw new System.NotImplementedException(); } } """); } [WpfFact] public async Task EventHookupInUnformattedPosition1() { var markup = """ class C { event System.Action MyEvent; void M() {MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); testState.SendTab(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertCodeIs(""" class C { event System.Action MyEvent; void M() { MyEvent += C_MyEvent; } private void C_MyEvent() { throw new System.NotImplementedException(); } } """); } [WpfFact] public async Task EventHookupInUnformattedPosition2() { var markup = """ class C { event System.Action MyEvent; void M() {MyEvent +$$ MyEvent += C_MyEvent; } private void C_MyEvent() { throw new System.NotImplementedException(); } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); for (var i = 0; i < 20; i++) { testState.SendTypeChar(' '); } testState.SendTab(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertCodeIs(""" class C { event System.Action MyEvent; void M() { MyEvent += C_MyEvent1; MyEvent += C_MyEvent; } private void C_MyEvent1() { throw new System.NotImplementedException(); } private void C_MyEvent() { throw new System.NotImplementedException(); } } """); } [WpfFact] public async Task SessionCancelledByCharacterBeforeEventHookupDeterminationCompleted() { var markup = """ class C { event System.Action MyEvent; void M() { MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SetEventHookupCheckMutex(); testState.SendTypeChar('='); testState.SendTypeChar('z'); testState.ReleaseEventHookupCheckMutex(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertNotShowing(); } [WpfFact] public async Task TabBeforeEventHookupDeterminationCompleted() { var markup = """ class C { event System.Action MyEvent; void M() { MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SetEventHookupCheckMutex(); testState.SendTypeChar('='); // tab releases the mutex testState.SendTab(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertNotShowing(); testState.AssertCodeIs(""" class C { event System.Action MyEvent; void M() { MyEvent += C_MyEvent; } private void C_MyEvent() { throw new System.NotImplementedException(); } } """); } [WpfFact] public async Task MoveCaretOutOfSpanBeforeEventHookupDeterminationCompleted() { var markup = """ class C { event System.Action MyEvent; void M() { MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SetEventHookupCheckMutex(); testState.SendTypeChar('='); testState.SendLeftKey(); testState.ReleaseEventHookupCheckMutex(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertNotShowing(); } [WpfFact] public async Task EnsureNameUniquenessInPartialClasses() { var markup = """ public partial class C { event System.Action MyEvent; public async Task Test() { MyEvent +$$ } } public partial class C { private void C_MyEvent() { throw new System.NotImplementedException(); } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("C_MyEvent1"); } [WpfFact] public async Task EnsureNameUniquenessAgainstBaseClasses() { var markup = """ class Base { protected int Console_CancelKeyPress; } class Program : Base { void Main(string[] args) { var goo = Console_CancelKeyPress + 23; System.Console.CancelKeyPress +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("Console_CancelKeyPress1"); } [WpfFact] public async Task EnsureNameUniquenessAgainstParameters() { var markup = """ class C { event System.Action MyEvent; void M(int C_MyEvent) { MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("C_MyEvent1"); } [WpfFact] public async Task DelegateInvokeMethodReturnsNonVoid() { var markup = """ class C { delegate int D(double d); event D MyEvent; void M() { MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); testState.SendTab(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertCodeIs(""" class C { delegate int D(double d); event D MyEvent; void M() { MyEvent += C_MyEvent; } private int C_MyEvent(double d) { throw new System.NotImplementedException(); } } """); } [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/553660")] public async Task PlusEqualsInsideComment() { var markup = """ class C { void M() { // +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); testState.SendTab(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertNotShowing(); } [WpfFact, WorkItem("http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/951664")] public async Task UseInvocationLocationTypeNameWhenEventIsMemberOfBaseType() { var markup = """ namespace Scenarios { public class DelegateTest_Generics_NonGenericClass { public delegate void D1<T>(); public event D1<string> E1; } } class TestClass_T1_S1_4 : Scenarios.DelegateTest_Generics_NonGenericClass { void Method() { E1 +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); testState.SendTab(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertCodeIs(""" namespace Scenarios { public class DelegateTest_Generics_NonGenericClass { public delegate void D1<T>(); public event D1<string> E1; } } class TestClass_T1_S1_4 : Scenarios.DelegateTest_Generics_NonGenericClass { void Method() { E1 += TestClass_T1_S1_4_E1; } private void TestClass_T1_S1_4_E1() { throw new System.NotImplementedException(); } } """); } [WpfFact] public async Task EventHookupWithQualifiedMethodAccess() { var markup = """ class C { event System.Action MyEvent; void M() { MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup, QualifyMethodAccessWithNotification(NotificationOption2.Error)); testState.SendTypeChar('='); testState.SendTab(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertCodeIs(""" class C { event System.Action MyEvent; void M() { MyEvent += this.C_MyEvent; } private void C_MyEvent() { throw new System.NotImplementedException(); } } """); } [WpfFact] public async Task EventHookupRemovesInaccessibleAttributes() { var workspaceXml = """ <Workspace> <Project Language="C#" AssemblyName="A" CommonReferences="true"> <Document>using System; public static class C { public static event DelegateType E; public delegate void DelegateType([ShouldBeRemovedInternalAttribute] object o); } internal class ShouldBeRemovedInternalAttribute : Attribute { }</Document> </Project> <Project Language="C#" CommonReferences="true"> <ProjectReference>A</ProjectReference> <Document>class D { void M() { C.E +$$ } }</Document> </Project> </Workspace> """; using var testState = new EventHookupTestState(XElement.Parse(workspaceXml), options: null); testState.SendTypeChar('='); testState.SendTab(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertCodeIs(""" class D { void M() { C.E += C_E; } private void C_E(object o) { throw new System.NotImplementedException(); } } """); } [WpfFact] public async Task EventHookupWithQualifiedMethodAccessAndNotificationOptionSilent() { // This validates the scenario where the user has stated that they prefer `this.` qualification but the // notification level is `Silent`, which means existing violations of the rule won't be flagged but newly // generated code will conform appropriately. var markup = """ class C { event System.Action MyEvent; void M() { MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup, QualifyMethodAccessWithNotification(NotificationOption2.Silent)); testState.SendTypeChar('='); testState.SendTab(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertCodeIs(""" class C { event System.Action MyEvent; void M() { MyEvent += this.C_MyEvent; } private void C_MyEvent() { throw new System.NotImplementedException(); } } """); } [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/58474")] public async Task EventHookupInTopLevelCode() { var markup = """ System.AppDomain.CurrentDomain.UnhandledException +$$ """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); testState.SendTab(); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertCodeIs(""" System.AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; void CurrentDomain_UnhandledException(object sender, System.UnhandledExceptionEventArgs e) { throw new System.NotImplementedException(); } """); } [WpfFact] public async Task EventHookupAtEndOfDocument() { var markup = """ System.AppDomain.CurrentDomain.UnhandledException +$$ """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("CurrentDomain_UnhandledException"); var expectedCode = """ System.AppDomain.CurrentDomain.UnhandledException += """; testState.AssertCodeIs(expectedCode); testState.SendTab(); await testState.WaitForAsynchronousOperationsAsync(); expectedCode = """ System.AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; void CurrentDomain_UnhandledException(object sender, System.UnhandledExceptionEventArgs e) { throw new System.NotImplementedException(); } """; testState.AssertCodeIs(expectedCode); } [WpfFact, WorkItem("https://github.com/dotnet/roslyn/issues/59935")] public async Task HandlerName_EventInGenericClass() { var markup = """ using System; class C { void M() { Generic<int>.MyEvent +$$ } } class Generic<T> { public static event EventHandler MyEvent; } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("Generic_MyEvent"); } [WpfFact] public async Task HandlerName_GlobalAlias01() { var markup = """ using System; class C { void M() { global::D.MyEvent +$$ } } class D { public static event EventHandler MyEvent; } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("D_MyEvent"); } [WpfFact] public async Task HandlerName_GlobalAlias02() { var markup = """ using System; class C { void M() { global::Generic<int>.MyEvent +$$ } } class Generic<T> { public static event EventHandler MyEvent; } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("Generic_MyEvent"); } [WpfFact] public async Task HandlerName_GlobalAlias03() { var markup = """ class Program { void Main(string[] args) { global::System.Console.CancelKeyPress +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("Console_CancelKeyPress"); } [WpfFact] public async Task HandlerName_InvocationExpression() { var markup = """ using System; class C { public event EventHandler MyEvent; public static C CreateC() { return new C(); } public void M2() { CreateC().MyEvent +$$ } } """; using var testState = EventHookupTestState.CreateTestState(markup); testState.SendTypeChar('='); await testState.WaitForAsynchronousOperationsAsync(); testState.AssertShowing("C_MyEvent"); } private static OptionsCollection QualifyMethodAccessWithNotification(NotificationOption2 notification) => new(LanguageNames.CSharp) { { CodeStyleOptions2.QualifyMethodAccess, true, notification } }; }