diff --git a/src/System.Windows.Forms.Analyzers.CSharp/src/System/Windows/Forms/CSharp/Analyzers/MissingPropertySerializationConfiguration/MissingPropertySerializationConfigurationAnalyzer.cs b/src/System.Windows.Forms.Analyzers.CSharp/src/System/Windows/Forms/CSharp/Analyzers/MissingPropertySerializationConfiguration/MissingPropertySerializationConfigurationAnalyzer.cs index 52a79db8897..c8fe53bcd58 100644 --- a/src/System.Windows.Forms.Analyzers.CSharp/src/System/Windows/Forms/CSharp/Analyzers/MissingPropertySerializationConfiguration/MissingPropertySerializationConfigurationAnalyzer.cs +++ b/src/System.Windows.Forms.Analyzers.CSharp/src/System/Windows/Forms/CSharp/Analyzers/MissingPropertySerializationConfiguration/MissingPropertySerializationConfigurationAnalyzer.cs @@ -12,8 +12,10 @@ namespace System.Windows.Forms.CSharp.Analyzers.MissingPropertySerializationConf [DiagnosticAnalyzer(LanguageNames.CSharp)] public class MissingPropertySerializationConfigurationAnalyzer : DiagnosticAnalyzer { - public override ImmutableArray SupportedDiagnostics - => [CSharpDiagnosticDescriptors.s_missingPropertySerializationConfiguration]; + private const string SystemComponentModelName = "System.ComponentModel"; + + public override ImmutableArray SupportedDiagnostics => + [CSharpDiagnosticDescriptors.s_missingPropertySerializationConfiguration]; public override void Initialize(AnalysisContext context) { @@ -24,26 +26,53 @@ public override void Initialize(AnalysisContext context) private static void AnalyzeSymbol(SymbolAnalysisContext context) { - // We analyze only properties. - var propertySymbol = (IPropertySymbol)context.Symbol; + // We never flag a property named Site of type of ISite + if (context.Symbol is not IPropertySymbol propertySymbol + || propertySymbol.IsStatic) + { + return; + } - // Does the property belong to a class which derives from Component? - if (propertySymbol.ContainingType is null - || !propertySymbol - .ContainingType - .AllInterfaces - .Any(i => i.Name == nameof(IComponent))) + // A property of System.ComponentModel.ISite we never flag. + if (propertySymbol.Type.Name == nameof(ISite) + && propertySymbol.Type.ContainingNamespace.ToString() == SystemComponentModelName) { return; } - // Is the property read/write and at least internal? - if (propertySymbol.SetMethod is null + // Is the property read/write and at least internal and doesn't have a private setter? + if (propertySymbol.SetMethod is not IMethodSymbol propertySetter + || propertySetter.DeclaredAccessibility == Accessibility.Private || propertySymbol.DeclaredAccessibility < Accessibility.Internal) { return; } + // Skip overridden properties since the base property should already + // have the appropriate serialization configuration + if (propertySymbol.IsOverride) + { + return; + } + + // If the property is part of any interface named IComponent, we're out. + if (propertySymbol.ContainingType.Name == nameof(IComponent)) + { + return; + } + + // Does the property belong to a class which implements the System.ComponentModel.IComponent interface? + if (propertySymbol.ContainingType is null + || !propertySymbol + .ContainingType + .AllInterfaces + .Any(i => i.Name == nameof(IComponent) && + i.ContainingNamespace is not null && + i.ContainingNamespace.ToString() == SystemComponentModelName)) + { + return; + } + // Is the property attributed with DesignerSerializationVisibility or DefaultValue? if (propertySymbol.GetAttributes() .Any(a => a?.AttributeClass?.Name is (nameof(DesignerSerializationVisibilityAttribute)) diff --git a/src/System.Windows.Forms.Analyzers.VisualBasic/src/Analyzers/MissingPropertySerializationConfiguration/MissingPropertySerializationConfigurationDiagnosticAnalyzer.vb b/src/System.Windows.Forms.Analyzers.VisualBasic/src/Analyzers/MissingPropertySerializationConfiguration/MissingPropertySerializationConfigurationDiagnosticAnalyzer.vb index c5ff05bf0d2..45399be3ae0 100644 --- a/src/System.Windows.Forms.Analyzers.VisualBasic/src/Analyzers/MissingPropertySerializationConfiguration/MissingPropertySerializationConfigurationDiagnosticAnalyzer.vb +++ b/src/System.Windows.Forms.Analyzers.VisualBasic/src/Analyzers/MissingPropertySerializationConfiguration/MissingPropertySerializationConfigurationDiagnosticAnalyzer.vb @@ -12,6 +12,8 @@ Namespace Global.System.Windows.Forms.VisualBasic.Analyzers.MissingPropertySeria Public Class MissingPropertySerializationConfigurationAnalyzer Inherits DiagnosticAnalyzer + Private Const SystemComponentModelName As String = "System.ComponentModel" + Public Overrides ReadOnly Property SupportedDiagnostics As ImmutableArray(Of DiagnosticDescriptor) Get Return ImmutableArray.Create(s_missingPropertySerializationConfiguration) @@ -28,22 +30,46 @@ Namespace Global.System.Windows.Forms.VisualBasic.Analyzers.MissingPropertySeria ' We analyze only properties. Dim propertySymbol As IPropertySymbol = TryCast(context.Symbol, IPropertySymbol) + If propertySymbol Is Nothing Then Return End If - ' Does the property belong to a class which derives from Component? - If propertySymbol.ContainingType Is Nothing OrElse - Not propertySymbol.ContainingType.AllInterfaces.Any( - Function(i) i.Name = NameOf(IComponent)) Then + ' A property of System.ComponentModel.ISite we never flag. + If propertySymbol.Type.Name = NameOf(ISite) AndAlso + propertySymbol.Type.ContainingNamespace.ToString() = SystemComponentModelName Then + Return + End If + + ' If the property is part of any interface named IComponent, we're out. + If propertySymbol.ContainingType.Name = NameOf(IComponent) Then + Return + End If + ' Skip static properties since they are not serialized by the designer + If propertySymbol.IsStatic Then Return End If - ' Is the property read/write and at least internal? + ' Is the property read/write, at least internal, and doesn't have a private setter? If propertySymbol.SetMethod Is Nothing OrElse + propertySymbol.SetMethod.DeclaredAccessibility = Accessibility.Private OrElse propertySymbol.DeclaredAccessibility < Accessibility.Internal Then + Return + End If + + ' Skip overridden properties since the base property should already + ' have the appropriate serialization configuration + If propertySymbol.IsOverride Then + Return + End If + ' Does the property belong to a class which implements the System.ComponentModel.IComponent interface? + If propertySymbol.ContainingType Is Nothing OrElse + Not propertySymbol.ContainingType.AllInterfaces.Any( + Function(i) i.Name = NameOf(IComponent) AndAlso + i.ContainingNamespace IsNot Nothing AndAlso + i.ContainingNamespace.ToString() = SystemComponentModelName) Then Return End If