Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions src/rgen/Microsoft.Macios.Bindings.Analyzer/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 39 additions & 0 deletions src/rgen/Microsoft.Macios.Bindings.Analyzer/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -599,4 +599,43 @@
<value>Wrong 'this' parameter in category method</value>
</data>

<!-- RBI0045 -->

<data name="RBI0045Description" xml:space="preserve">
<value>Categories do not support events.</value>
</data>
<data name="RBI0045MessageFormat" xml:space="preserve">
<value>Category '{0}' has events (found {1}), but events are not supported on categories</value>
<comment>{0} is the name of the category, {1} the number of events</comment>
</data>
<data name="RBI0045Title" xml:space="preserve">
<value>Events are not supported on categories</value>
</data>

<!-- RBI0046 -->

<data name="RBI0046Description" xml:space="preserve">
<value>Categories do not support constructors.</value>
</data>
<data name="RBI0046MessageFormat" xml:space="preserve">
<value>Category '{0}' has constructors (found {1}), but constructors are not supported on categories</value>
<comment>{0} is the name of the category, {1} the number of constructors</comment>
</data>
<data name="RBI0046Title" xml:space="preserve">
<value>Constructors are not supported on categories</value>
</data>

<!-- RBI0047 -->

<data name="RBI0047Description" xml:space="preserve">
<value>Categories do not support properties.</value>
</data>
<data name="RBI0047MessageFormat" xml:space="preserve">
<value>Category '{0}' has properties (found {1}), but properties are not supported on categories</value>
<comment>{0} is the name of the category, {1} the number of properties</comment>
</data>
<data name="RBI0047Title" xml:space="preserve">
<value>Properties are not supported on categories</value>
</data>

</root>
55 changes: 50 additions & 5 deletions src/rgen/Microsoft.Macios.Bindings.Analyzer/RgenDiagnostics.cs
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,7 @@ public static class RgenDiagnostics {
);

/// <summary>
/// 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.
/// </summary>
internal static readonly DiagnosticDescriptor RBI0040 = new (
"RBI0040",
Expand All @@ -618,7 +618,7 @@ public static class RgenDiagnostics {
);

/// <summary>
/// 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.
/// </summary>
internal static readonly DiagnosticDescriptor RBI0041 = new (
"RBI0041",
Expand All @@ -633,7 +633,7 @@ public static class RgenDiagnostics {
);

/// <summary>
/// Disgnostic descriptor for when a category method is not partial
/// Diagnostic descriptor for when a category method is not partial
/// </summary>
internal static readonly DiagnosticDescriptor RBI0042 = new (
"RBI0042",
Expand All @@ -648,7 +648,7 @@ public static class RgenDiagnostics {
);

/// <summary>
/// Disgnostic descriptor for when a category method is not and extension
/// Diagnostic descriptor for when a category method is not and extension
/// </summary>
internal static readonly DiagnosticDescriptor RBI0043 = new (
"RBI0043",
Expand All @@ -663,7 +663,7 @@ public static class RgenDiagnostics {
);

/// <summary>
/// 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
/// </summary>
internal static readonly DiagnosticDescriptor RBI0044 = new (
"RBI0044",
Expand All @@ -676,4 +676,49 @@ public static class RgenDiagnostics {
description: new LocalizableResourceString (nameof (Resources.RBI0044Description), Resources.ResourceManager,
typeof (Resources))
);

/// <summary>
/// Diagnostic descriptor for when a category contains an event.
/// </summary>
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))
);

/// <summary>
/// Diagnostic descriptor for when a category contains an constructor.
/// </summary>
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))
);

/// <summary>
/// Diagnostic descriptor for when a category contains an constructor.
/// </summary>
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))
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -70,6 +69,48 @@ bool ValidMethods (Binding binding, RootContext context,
return diagnostics.Length == 0;
}

/// <summary>
/// Validates that categories do not contain unsupported members such as events, constructors, or properties.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

/// </summary>
/// <param name="binding">The category binding to validate.</param>
/// <param name="context">The root context for validation.</param>
/// <param name="diagnostics">When this method returns, contains diagnostics for any unsupported members; otherwise, an empty array.</param>
/// <param name="location">The code location to be used for the diagnostics.</param>
/// <returns><c>true</c> if no unsupported members are present; otherwise, <c>false</c>.</returns>
bool ValidMembers (Binding binding, RootContext context,
out ImmutableArray<Diagnostic> diagnostics, Location? location = null)
{
var builder = ImmutableArray.CreateBuilder<Diagnostic> ();

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;
}


/// <summary>
/// Initializes a new instance of the <see cref="CategoryValidator"/> class.
/// </summary>
Expand All @@ -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);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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<Category> (typeof (NSObject))]
public partial class TestClass{

[Export<Constructor> (""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<Category> (typeof (NSObject))]
public partial class TestClass{

[SupportedOSPlatform (""ios"")]
[SupportedOSPlatform (""tvos"")]
[SupportedOSPlatform (""macos"")]
[SupportedOSPlatform (""maccatalyst13.1"")]
[Export<Property> (""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 ();
Expand Down
Loading