Skip to content

Commit

Permalink
[bgen] Generate Obsolete + EditorBrowsable attributes in a few more c…
Browse files Browse the repository at this point in the history
…ases.

* Forward [Obsolete] from api definition interfaces.
* Generate [EditorBrowsable] whenever an api definition member as either
  [EditorBrowsable] or [Obsolete].
  • Loading branch information
rolfbjarne committed Aug 27, 2024
1 parent c90fc43 commit ea30774
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 16 deletions.
1 change: 0 additions & 1 deletion src/bgen/Enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,6 @@ void GenerateEnum (Type type)
sb.Append ("]");
print (sb.ToString ());
}
PrintObsoleteAttributes (type);
CopyNativeName (type);

var unique_constants = new HashSet<string> ();
Expand Down
51 changes: 36 additions & 15 deletions src/bgen/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3866,18 +3866,47 @@ bool DoesPropertyNeedDirtyCheck (PropertyInfo pi, ExportAttribute ea)
}
}

void PrintObsoleteAttributes (ICustomAttributeProvider provider, bool already_has_editor_browsable_attribute = false)
void PrintObsoleteAttributes (ICustomAttributeProvider provider)
{
var obsoleteAttributes = AttributeManager.GetCustomAttributes<ObsoleteAttribute> (provider);

foreach (var oa in obsoleteAttributes) {
print ("[Obsolete (\"{0}\", {1})]", oa.Message, oa.IsError ? "true" : "false");
}

if (!already_has_editor_browsable_attribute && obsoleteAttributes.Any ())
var printEditorBrowsableAttribute = TryGetPrintEditorBrowsableAttribute (provider, out var editorBrowsableAttribute);
if (!printEditorBrowsableAttribute && obsoleteAttributes.Any ()) {
printEditorBrowsableAttribute = true;
editorBrowsableAttribute = "[EditorBrowsable (EditorBrowsableState.Never)]";
}
if (printEditorBrowsableAttribute)
print ("[EditorBrowsable (EditorBrowsableState.Never)]");
}

bool TryGetPrintEditorBrowsableAttribute (ICustomAttributeProvider provider, out string attribute)
{
attribute = string.Empty;
foreach (var ea in AttributeManager.GetCustomAttributes<EditorBrowsableAttribute> (provider)) {
switch (ea.State) {
case EditorBrowsableState.Always:
attribute = "[EditorBrowsable (EditorBrowsableState.Always)]";
break;
case EditorBrowsableState.Never:
attribute = "[EditorBrowsable (EditorBrowsableState.Never)]";
break;
case EditorBrowsableState.Advanced:
attribute = "[EditorBrowsable (EditorBrowsableState.Advanced)]";
break;
default:
attribute = $"[EditorBrowsable (EditorBrowsableState.{ea.State})]";
break;
}
return true;
}

return false;
}

void PrintPropertyAttributes (PropertyInfo pi, Type type, bool skipTypeInjection = false)
{
var minfo = new MemberInformation (this, this, pi, type);
Expand Down Expand Up @@ -4418,21 +4447,11 @@ void GenerateAsyncMethod (MemberInformation original_minfo, AsyncMethodKind asyn
void PrintMethodAttributes (MemberInformation minfo)
{
MethodInfo mi = minfo.Method;
var editor_browsable_attribute = false;

foreach (var sa in AttributeManager.GetCustomAttributes<ThreadSafeAttribute> (mi))
print (sa.Safe ? "[ThreadSafe]" : "[ThreadSafe (false)]");

foreach (var ea in AttributeManager.GetCustomAttributes<EditorBrowsableAttribute> (mi)) {
if (ea.State == EditorBrowsableState.Always) {
print ("[EditorBrowsable]");
} else {
print ("[EditorBrowsable (EditorBrowsableState.{0})]", ea.State);
}
editor_browsable_attribute = true;
}

PrintObsoleteAttributes (mi, editor_browsable_attribute);
PrintObsoleteAttributes (mi);

if (minfo.is_return_release)
print ("[return: ReleaseAttribute ()]");
Expand Down Expand Up @@ -5507,7 +5526,7 @@ public void PrintBindAsAttribute (ICustomAttributeProvider mi, StringBuilder sb
// Not adding the experimental attribute is bad (it would mean that an API
// we meant to be experimental ended up being released as stable), so it's
// opt-out instead of opt-in.
public void PrintAttributes (ICustomAttributeProvider mi, bool platform = false, bool preserve = false, bool advice = false, bool notImplemented = false, bool bindAs = false, bool requiresSuper = false, Type inlinedType = null, bool experimental = true)
public void PrintAttributes (ICustomAttributeProvider mi, bool platform = false, bool preserve = false, bool advice = false, bool notImplemented = false, bool bindAs = false, bool requiresSuper = false, Type inlinedType = null, bool experimental = true, bool obsolete = false)
{
if (platform)
PrintPlatformAttributes (mi as MemberInfo, inlinedType);
Expand All @@ -5523,6 +5542,8 @@ public void PrintAttributes (ICustomAttributeProvider mi, bool platform = false,
PrintRequiresSuperAttribute (mi);
if (experimental)
PrintExperimentalAttribute (mi);
if (obsolete)
PrintObsoleteAttributes (mi);
}

public void PrintExperimentalAttribute (ICustomAttributeProvider mi)
Expand Down Expand Up @@ -5754,7 +5775,7 @@ public void Generate (Type type)
print ("[Model]");
}

PrintAttributes (type, platform: true, preserve: true, advice: true);
PrintAttributes (type, platform: true, preserve: true, advice: true, obsolete: true);

if (type.IsEnum) {
GenerateEnum (type);
Expand Down
18 changes: 18 additions & 0 deletions tests/generator/BGenTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,24 @@ public void NSCopyingNullability (Profile profile)
bgen.AssertNoWarnings ();
}

[Test]
[TestCase (Profile.iOS)]
public void EditorBrowsable (Profile profile)
{
var bgen = BuildFile (profile, false, true, "tests/editor-browsable.cs");
var types = bgen.ApiAssembly.MainModule.Types;

var hasEditorBrowsableAttribute = new Func<ICustomAttributeProvider, bool> ((ICustomAttributeProvider provider) =>
{
return provider.CustomAttributes.Any (v => v.AttributeType.Name == "EditorBrowsableAttribute");
});

var strongEnumType = types.Single (v => v.Name == "StrongEnum");
Assert.IsTrue (hasEditorBrowsableAttribute (strongEnumType), "StrongEnumType");
var objcClassType = types.Single (v => v.Name == "ObjCClass");
Assert.IsTrue (hasEditorBrowsableAttribute (objcClassType), "ObjCClass");
}

static string RenderArgument (CustomAttributeArgument arg)
{
var td = arg.Type.Resolve ();
Expand Down
19 changes: 19 additions & 0 deletions tests/generator/tests/editor-browsable.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;
using System.ComponentModel;

using Foundation;

namespace EditorBrowsable {
[EditorBrowsable (EditorBrowsableState.Never)]
enum StrongEnum {
[Field ("AField", "__Internal")]
A,
}

[EditorBrowsable (EditorBrowsableState.Never)]
[BaseType (typeof (NSObject))]
interface ObjCClass {
[Export ("strongEnumField")]
StrongEnum StrongEnumField { get; set; }
}
}

0 comments on commit ea30774

Please sign in to comment.