From 5b70e999dab815952165d647aa55189e3c8b07a4 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 24 Jan 2019 11:34:56 -0800 Subject: [PATCH] Tweak bail out from unused member analyzer for struct layout types Current implementation bailed out in symbol start action, which caused both analysis and reporting to be skipped for unused members in a type with StructLayout attribute. New implementation bails out in symbol end action, so we only skip reporting not analysis. Fixes #32727 --- .../RemoveUnusedMembersTests.cs | 20 +++++++++++++++++++ ...ctRemoveUnusedMembersDiagnosticAnalyzer.cs | 14 ++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/RemoveUnusedMembers/RemoveUnusedMembersTests.cs b/src/EditorFeatures/CSharpTest/RemoveUnusedMembers/RemoveUnusedMembersTests.cs index eadde58597c..323392e3d21 100644 --- a/src/EditorFeatures/CSharpTest/RemoveUnusedMembers/RemoveUnusedMembersTests.cs +++ b/src/EditorFeatures/CSharpTest/RemoveUnusedMembers/RemoveUnusedMembersTests.cs @@ -2084,6 +2084,26 @@ class C }}"); } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)] + [WorkItem(32727, "https://github.com/dotnet/roslyn/issues/32727")] + public async Task NestedStructLayoutTypeWithReference() + { + await TestDiagnosticMissingAsync( +@"using System.Runtime.InteropServices; + +class Program +{ + private const int [|MAX_PATH|] = 260; + + [StructLayout(LayoutKind.Sequential)] + internal struct ProcessEntry32 + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)] + public string szExeFile; + } +}"); + } + [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedMembers)] public async Task FixAllFields_Document() { diff --git a/src/Features/Core/Portable/RemoveUnusedMembers/AbstractRemoveUnusedMembersDiagnosticAnalyzer.cs b/src/Features/Core/Portable/RemoveUnusedMembers/AbstractRemoveUnusedMembersDiagnosticAnalyzer.cs index 3eaa78bd6b2..aa28dbfc723 100644 --- a/src/Features/Core/Portable/RemoveUnusedMembers/AbstractRemoveUnusedMembersDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/RemoveUnusedMembers/AbstractRemoveUnusedMembersDiagnosticAnalyzer.cs @@ -154,13 +154,6 @@ private void RegisterActions(CompilationStartAnalysisContext compilationStartCon Action onSymbolUsageFound = OnSymbolUsage; compilationStartContext.RegisterSymbolStartAction(symbolStartContext => { - if (symbolStartContext.Symbol.GetAttributes().Any(a => a.AttributeClass == _structLayoutAttributeType)) - { - // Bail out for types with 'StructLayoutAttribute' as the ordering of the members is critical, - // and removal of unused members might break semantics. - return; - } - var hasInvalidOrDynamicOperation = false; symbolStartContext.RegisterOperationAction(AnalyzeMemberReferenceOperation, OperationKind.FieldReference, OperationKind.MethodReference, OperationKind.PropertyReference, OperationKind.EventReference); symbolStartContext.RegisterOperationAction(AnalyzeFieldInitializer, OperationKind.FieldInitializer); @@ -351,6 +344,13 @@ private void OnSymbolEnd(SymbolAnalysisContext symbolEndContext, bool hasInvalid return; } + if (symbolEndContext.Symbol.GetAttributes().Any(a => a.AttributeClass == _structLayoutAttributeType)) + { + // Bail out for types with 'StructLayoutAttribute' as the ordering of the members is critical, + // and removal of unused members might break semantics. + return; + } + // Report diagnostics for unused candidate members. var first = true; PooledHashSet symbolsReferencedInDocComments = null; -- GitLab