From c3db4cedb3097d499e63a00ff544b5cb36dd148f Mon Sep 17 00:00:00 2001 From: Neil Henderson Date: Mon, 28 Jun 2021 16:06:36 +1000 Subject: [PATCH] Fixes #456. VSTHRD010 now recognizes when struct members require the main thread. --- .../VSTHRD010MainThreadUsageAnalyzer.cs | 2 +- ...ading.MembersRequiringMainThread.mocks.txt | 1 + .../VSTHRD010MainThreadUsageAnalyzerTests.cs | 40 +++++++++++++++++++ 3 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/VSTHRD010MainThreadUsageAnalyzer.cs b/src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/VSTHRD010MainThreadUsageAnalyzer.cs index 4d69aba2c..6c2a6bdea 100644 --- a/src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/VSTHRD010MainThreadUsageAnalyzer.cs +++ b/src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/VSTHRD010MainThreadUsageAnalyzer.cs @@ -443,7 +443,7 @@ private bool AnalyzeMemberWithinContext(ITypeSymbol type, ISymbol? symbol, Synta throw new ArgumentNullException(nameof(type)); } - bool requiresUIThread = (type.TypeKind == TypeKind.Interface || type.TypeKind == TypeKind.Class) + bool requiresUIThread = (type.TypeKind == TypeKind.Interface || type.TypeKind == TypeKind.Class || type.TypeKind == TypeKind.Struct) && this.MembersRequiringMainThread.Contains(type, symbol); if (requiresUIThread) diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/AdditionalFiles/vs-threading.MembersRequiringMainThread.mocks.txt b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/AdditionalFiles/vs-threading.MembersRequiringMainThread.mocks.txt index 46cfd3576..51a33f56b 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/AdditionalFiles/vs-threading.MembersRequiringMainThread.mocks.txt +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/AdditionalFiles/vs-threading.MembersRequiringMainThread.mocks.txt @@ -1,4 +1,5 @@ [TestNS.*] +[TestNS.SomeStruct] ![TestNS.FreeThreadedType] ![TestNS2.FreeThreadedType] [TestNS2.*] diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD010MainThreadUsageAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD010MainThreadUsageAnalyzerTests.cs index 80636a126..c360069e5 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD010MainThreadUsageAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD010MainThreadUsageAnalyzerTests.cs @@ -1864,6 +1864,46 @@ async void SecondAsync() await Verify.VerifyAnalyzerAsync(test, expect); } + [Fact] + public async Task StructMembers() + { + var test = @" +namespace TestNS +{ + struct SomeStruct + { + public static void DoSomething() + { + } + + public string Name { get; set; } + } +} + +namespace Foo +{ + class MyProgram + { + static void Main() + { + TestNS.SomeStruct.DoSomething(); + + var st = new TestNS.SomeStruct(); + st.Name = ""TheValue""; + string val = st.Name; + } + } +} +"; + var expect = new DiagnosticResult[] + { + Verify.Diagnostic(DescriptorSync).WithSpan(20, 31, 20, 42).WithArguments("SomeStruct", "Test.VerifyOnUIThread"), + Verify.Diagnostic(DescriptorSync).WithSpan(23, 16, 23, 20).WithArguments("SomeStruct", "Test.VerifyOnUIThread"), + Verify.Diagnostic(DescriptorSync).WithSpan(24, 29, 24, 33).WithArguments("SomeStruct", "Test.VerifyOnUIThread"), + }; + await Verify.VerifyAnalyzerAsync(test, expect); + } + private static class CodeFixIndex { public const int SwitchToMainThreadAsync = 0;