diff --git a/src/rgen/Microsoft.Macios.Bindings.Analyzer/Resources.Designer.cs b/src/rgen/Microsoft.Macios.Bindings.Analyzer/Resources.Designer.cs index db8da0cbd3cd..5854f1a7568c 100644 --- a/src/rgen/Microsoft.Macios.Bindings.Analyzer/Resources.Designer.cs +++ b/src/rgen/Microsoft.Macios.Bindings.Analyzer/Resources.Designer.cs @@ -1271,5 +1271,86 @@ internal static string RBI0044Title { return ResourceManager.GetString("RBI0044Title", resourceCulture); } } + + /// + /// Looks up a localized string similar to Categories do not support events.. + /// + internal static string RBI0045Description { + get { + return ResourceManager.GetString("RBI0045Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Category '{0}' has events (found {1}), but events are not supported on categories. + /// + internal static string RBI0045MessageFormat { + get { + return ResourceManager.GetString("RBI0045MessageFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Events are not supported on categories. + /// + internal static string RBI0045Title { + get { + return ResourceManager.GetString("RBI0045Title", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Categories do not support constructors.. + /// + internal static string RBI0046Description { + get { + return ResourceManager.GetString("RBI0046Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Category '{0}' has constructors (found {1}), but constructors are not supported on categories. + /// + internal static string RBI0046MessageFormat { + get { + return ResourceManager.GetString("RBI0046MessageFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Constructors are not supported on categories. + /// + internal static string RBI0046Title { + get { + return ResourceManager.GetString("RBI0046Title", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Categories do not support properties.. + /// + internal static string RBI0047Description { + get { + return ResourceManager.GetString("RBI0047Description", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Category '{0}' has properties (found {1}), but properties are not supported on categories. + /// + internal static string RBI0047MessageFormat { + get { + return ResourceManager.GetString("RBI0047MessageFormat", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Properties are not supported on categories. + /// + internal static string RBI0047Title { + get { + return ResourceManager.GetString("RBI0047Title", resourceCulture); + } + } } } diff --git a/src/rgen/Microsoft.Macios.Bindings.Analyzer/Resources.resx b/src/rgen/Microsoft.Macios.Bindings.Analyzer/Resources.resx index 6c5d4621edcd..55f3b4c605d1 100644 --- a/src/rgen/Microsoft.Macios.Bindings.Analyzer/Resources.resx +++ b/src/rgen/Microsoft.Macios.Bindings.Analyzer/Resources.resx @@ -599,4 +599,43 @@ Wrong 'this' parameter in category method + + + + Categories do not support events. + + + Category '{0}' has events (found {1}), but events are not supported on categories + {0} is the name of the category, {1} the number of events + + + Events are not supported on categories + + + + + + Categories do not support constructors. + + + Category '{0}' has constructors (found {1}), but constructors are not supported on categories + {0} is the name of the category, {1} the number of constructors + + + Constructors are not supported on categories + + + + + + Categories do not support properties. + + + Category '{0}' has properties (found {1}), but properties are not supported on categories + {0} is the name of the category, {1} the number of properties + + + Properties are not supported on categories + + diff --git a/src/rgen/Microsoft.Macios.Bindings.Analyzer/RgenDiagnostics.cs b/src/rgen/Microsoft.Macios.Bindings.Analyzer/RgenDiagnostics.cs index a286c132a77e..a8c95d30851f 100644 --- a/src/rgen/Microsoft.Macios.Bindings.Analyzer/RgenDiagnostics.cs +++ b/src/rgen/Microsoft.Macios.Bindings.Analyzer/RgenDiagnostics.cs @@ -603,7 +603,7 @@ public static class RgenDiagnostics { ); /// - /// Disgnostic descriptor for when a method marked as async has does not provide a return type or return type name. + /// Diagnostic descriptor for when a method marked as async has does not provide a return type or return type name. /// internal static readonly DiagnosticDescriptor RBI0040 = new ( "RBI0040", @@ -618,7 +618,7 @@ public static class RgenDiagnostics { ); /// - /// Disgnostic descriptor for when a class inherits from UIView and is missing the initWithFrame: constructor. + /// Diagnostic descriptor for when a class inherits from UIView and is missing the initWithFrame: constructor. /// internal static readonly DiagnosticDescriptor RBI0041 = new ( "RBI0041", @@ -633,7 +633,7 @@ public static class RgenDiagnostics { ); /// - /// Disgnostic descriptor for when a category method is not partial + /// Diagnostic descriptor for when a category method is not partial /// internal static readonly DiagnosticDescriptor RBI0042 = new ( "RBI0042", @@ -648,7 +648,7 @@ public static class RgenDiagnostics { ); /// - /// Disgnostic descriptor for when a category method is not and extension + /// Diagnostic descriptor for when a category method is not and extension /// internal static readonly DiagnosticDescriptor RBI0043 = new ( "RBI0043", @@ -663,7 +663,7 @@ public static class RgenDiagnostics { ); /// - /// Disgnostic descriptor for when a category method is not and extension of the category's target type + /// Diagnostic descriptor for when a category method is not and extension of the category's target type /// internal static readonly DiagnosticDescriptor RBI0044 = new ( "RBI0044", @@ -676,4 +676,49 @@ public static class RgenDiagnostics { description: new LocalizableResourceString (nameof (Resources.RBI0044Description), Resources.ResourceManager, typeof (Resources)) ); + + /// + /// Diagnostic descriptor for when a category contains an event. + /// + internal static readonly DiagnosticDescriptor RBI0045 = new ( + "RBI0045", + new LocalizableResourceString (nameof (Resources.RBI0045Title), Resources.ResourceManager, typeof (Resources)), + new LocalizableResourceString (nameof (Resources.RBI0045MessageFormat), Resources.ResourceManager, + typeof (Resources)), + "Usage", + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: new LocalizableResourceString (nameof (Resources.RBI0045Description), Resources.ResourceManager, + typeof (Resources)) + ); + + /// + /// Diagnostic descriptor for when a category contains an constructor. + /// + internal static readonly DiagnosticDescriptor RBI0046 = new ( + "RBI0046", + new LocalizableResourceString (nameof (Resources.RBI0046Title), Resources.ResourceManager, typeof (Resources)), + new LocalizableResourceString (nameof (Resources.RBI0046MessageFormat), Resources.ResourceManager, + typeof (Resources)), + "Usage", + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: new LocalizableResourceString (nameof (Resources.RBI0046Description), Resources.ResourceManager, + typeof (Resources)) + ); + + /// + /// Diagnostic descriptor for when a category contains an constructor. + /// + internal static readonly DiagnosticDescriptor RBI0047 = new ( + "RBI0047", + new LocalizableResourceString (nameof (Resources.RBI0047Title), Resources.ResourceManager, typeof (Resources)), + new LocalizableResourceString (nameof (Resources.RBI0047MessageFormat), Resources.ResourceManager, + typeof (Resources)), + "Usage", + DiagnosticSeverity.Error, + isEnabledByDefault: true, + description: new LocalizableResourceString (nameof (Resources.RBI0047Description), Resources.ResourceManager, + typeof (Resources)) + ); } diff --git a/src/rgen/Microsoft.Macios.Bindings.Analyzer/Validators/CategoryValidator.cs b/src/rgen/Microsoft.Macios.Bindings.Analyzer/Validators/CategoryValidator.cs index f97d3509f87e..48499e959a25 100644 --- a/src/rgen/Microsoft.Macios.Bindings.Analyzer/Validators/CategoryValidator.cs +++ b/src/rgen/Microsoft.Macios.Bindings.Analyzer/Validators/CategoryValidator.cs @@ -3,7 +3,6 @@ using System.Collections.Immutable; using Microsoft.CodeAnalysis; -using Microsoft.Macios.Generator; using Microsoft.Macios.Generator.Attributes; using Microsoft.Macios.Generator.Context; using Microsoft.Macios.Generator.DataModel; @@ -70,6 +69,48 @@ bool ValidMethods (Binding binding, RootContext context, return diagnostics.Length == 0; } + /// + /// Validates that categories do not contain unsupported members such as events, constructors, or properties. + /// + /// The category binding to validate. + /// The root context for validation. + /// When this method returns, contains diagnostics for any unsupported members; otherwise, an empty array. + /// The code location to be used for the diagnostics. + /// true if no unsupported members are present; otherwise, false. + bool ValidMembers (Binding binding, RootContext context, + out ImmutableArray diagnostics, Location? location = null) + { + var builder = ImmutableArray.CreateBuilder (); + + if (binding.Events.Length > 0) { + builder.Add (Diagnostic.Create ( + RBI0045, // Categories cannot contain events. + location, + binding.Name, + binding.Events.Length)); + } + + if (binding.Constructors.Length > 0) { + builder.Add (Diagnostic.Create ( + RBI0046, // Categories cannot contain constructors. + location, + binding.Name, + binding.Constructors.Length)); + } + + if (binding.Properties.Length > 0) { + builder.Add (Diagnostic.Create ( + RBI0047, // Categories cannot contain properties. + location, + binding.Name, + binding.Properties.Length)); + } + + diagnostics = builder.ToImmutable (); + return diagnostics.Length == 0; + } + + /// /// Initializes a new instance of the class. /// @@ -81,5 +122,8 @@ public CategoryValidator () AddGlobalStrategy (RBI0004, IsStatic); // validate all methods in the category binding AddGlobalStrategy ([RBI0042, RBI0043, RBI0044], ValidMethods); + // make sure that we do not have constructors, properties, fields or events + AddGlobalStrategy ([RBI0045, RBI0046, RBI0047], ValidMembers); } + } diff --git a/tests/rgen/Microsoft.Macios.Bindings.Analyzer.Tests/CategoryAnalyzerTests.cs b/tests/rgen/Microsoft.Macios.Bindings.Analyzer.Tests/CategoryAnalyzerTests.cs index bafa3f91a0f2..fa168375e1c0 100644 --- a/tests/rgen/Microsoft.Macios.Bindings.Analyzer.Tests/CategoryAnalyzerTests.cs +++ b/tests/rgen/Microsoft.Macios.Bindings.Analyzer.Tests/CategoryAnalyzerTests.cs @@ -177,6 +177,73 @@ public static partial class TestClass{ DiagnosticSeverity.Error, "Extension method 'ValueForKey' in category 'TestClass' must have the first parameter type match the category's extended type 'Foundation.NSObject' found 'Foundation.NSValue'" ]; + + // category with constructors + yield return [ + @" +#pragma warning disable APL0003 + +using System; +using System.Runtime.Versioning; +using AVFoundation; +using CoreGraphics; +using Foundation; +using ObjCBindings; +using ObjCRuntime; +using nfloat = System.Runtime.InteropServices.NFloat; + +namespace TestNamespace; + +[SupportedOSPlatform (""macos"")] +[SupportedOSPlatform (""ios"")] +[SupportedOSPlatform (""tvos"")] +[SupportedOSPlatform (""maccatalyst13.1"")] +[BindingType (typeof (NSObject))] +public partial class TestClass{ + + [Export (""initWithScheme:host:path:"")] + public TestClass (string scheme, string host, string path); + +}", + "RBI0046", + DiagnosticSeverity.Error, + "Category 'TestClass' has constructors (found 1), but constructors are not supported on categories" + ]; + + // category with properties + yield return [ + @" +#pragma warning disable APL0003 + +using System; +using System.Runtime.Versioning; +using AVFoundation; +using CoreGraphics; +using Foundation; +using ObjCBindings; +using ObjCRuntime; +using nfloat = System.Runtime.InteropServices.NFloat; + +namespace TestNamespace; + +[SupportedOSPlatform (""macos"")] +[SupportedOSPlatform (""ios"")] +[SupportedOSPlatform (""tvos"")] +[SupportedOSPlatform (""maccatalyst13.1"")] +[BindingType (typeof (NSObject))] +public partial class TestClass{ + + [SupportedOSPlatform (""ios"")] + [SupportedOSPlatform (""tvos"")] + [SupportedOSPlatform (""macos"")] + [SupportedOSPlatform (""maccatalyst13.1"")] + [Export (""count"")] + public virtual partial nuint Count { get; set; } +}", + "RBI0047", + DiagnosticSeverity.Error, + "Category 'TestClass' has properties (found 1), but properties are not supported on categories" + ]; } IEnumerator IEnumerable.GetEnumerator () => GetEnumerator ();