Skip to content

Commit 47201c4

Browse files
authored
[generator] Change protected members in final class to private (#569)
When generating `Mono.Android.dll` for API-29/v10.0, we get ~12 warnings that we are declaring a new `protected` member within a `sealed` class, e.g.: warning CS0628: 'HttpHost.Hostname': new protected member declared in sealed class There are (at least) three plausible ways to address this warning: 1. Use `Metadata` to change the visibility of these members. 2. Update `generator` so that it doesn't emit the members at all. 3. Update `generator` so the visibility of the members is `private`. The problem with (1) is that if the Java type ever changes in the future to be *non*-`final` -- meaning `protected` members would "make sense" -- the members will remain changed, and will continue until some manual review occurs, which is unlikely to happen. (2) is appealing -- no members at all means smaller bindings -- but means that the members cannot be used from additional `partial` class declarations. (3) allows the members to be used from `partial` classes, if desired, while ensuring that if the type changes to become non-`final` in the future, visibility will "automatically" remain `protected`. Update `generator` so that `protected` members within `final` types are instead bound as `private` members, thus avoiding the CS0628.
1 parent c5815fb commit 47201c4

File tree

4 files changed

+108
-0
lines changed

4 files changed

+108
-0
lines changed
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
using System;
2+
using System.Linq;
3+
using System.Xml.Linq;
4+
using Java.Interop.Tools.Generator.Transformation;
5+
using MonoDroid.Generation;
6+
using NUnit.Framework;
7+
8+
namespace generatortests
9+
{
10+
[TestFixture]
11+
public class SealedProtectedFixupsTests
12+
{
13+
private CodeGenerationOptions options = new CodeGenerationOptions ();
14+
15+
[Test]
16+
public void FixProtectedMethod ()
17+
{
18+
var klass = CreateSealedClass ();
19+
20+
var method = SupportTypeBuilder.CreateMethod (klass, "ToString", options);
21+
22+
klass.Methods.Add (method);
23+
24+
method.Visibility = "protected";
25+
method.IsOverride = false;
26+
27+
SealedProtectedFixups.Fixup (new [] { (GenBase)klass }.ToList ());
28+
29+
Assert.AreEqual ("private", method.Visibility);
30+
}
31+
32+
[Test]
33+
public void FixProtectedProperty ()
34+
{
35+
var klass = CreateSealedClass ();
36+
37+
var method = SupportTypeBuilder.CreateProperty (klass, "Handle", "int", options);
38+
39+
klass.Properties.Add (method);
40+
41+
method.Getter.Visibility = "protected";
42+
method.Getter.IsOverride = false;
43+
44+
method.Setter.Visibility = "protected";
45+
method.Setter.IsOverride = false;
46+
47+
SealedProtectedFixups.Fixup (new [] { (GenBase) klass }.ToList ());
48+
49+
Assert.AreEqual ("private", method.Getter.Visibility);
50+
Assert.AreEqual ("private", method.Setter.Visibility);
51+
}
52+
53+
[Test]
54+
public void FixProtectedField ()
55+
{
56+
var klass = CreateSealedClass ();
57+
58+
var field = new Field {
59+
Name = "MyConstant",
60+
TypeName = "int",
61+
Visibility = "protected"
62+
};
63+
64+
klass.Fields.Add (field);
65+
66+
SealedProtectedFixups.Fixup (new [] { (GenBase) klass }.ToList ());
67+
68+
Assert.AreEqual ("private", field.Visibility);
69+
}
70+
71+
private ClassGen CreateSealedClass ()
72+
{
73+
var klass = SupportTypeBuilder.CreateClass ("my.example.class", options);
74+
klass.IsFinal = true;
75+
return klass;
76+
}
77+
}
78+
}

tools/generator/CodeGenerator.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,8 @@ static void Run (CodeGeneratorOptions options, DirectoryAssemblyResolver resolve
172172
foreach (GenBase gen in gens)
173173
gen.FixupExplicitImplementation ();
174174

175+
SealedProtectedFixups.Fixup (gens);
176+
175177
GenerateAnnotationAttributes (gens, annotations_zips);
176178

177179
//SymbolTable.Dump ();
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using MonoDroid.Generation;
5+
6+
namespace Java.Interop.Tools.Generator.Transformation
7+
{
8+
public static class SealedProtectedFixups
9+
{
10+
public static void Fixup (List<GenBase> gens)
11+
{
12+
foreach (var c in gens.OfType<ClassGen> ().Where (c => c.IsFinal)) {
13+
foreach (var m in c.Methods.Where (m => m.Visibility == "protected" && !m.IsOverride))
14+
m.Visibility = "private";
15+
16+
foreach (var p in c.Properties.Where (p => p.Getter?.Visibility == "protected" && !p.Getter.IsOverride))
17+
p.Getter.Visibility = "private";
18+
19+
foreach (var p in c.Properties.Where (p => p.Setter?.Visibility == "protected" && !p.Setter.IsOverride))
20+
p.Setter.Visibility = "private";
21+
22+
foreach (var p in c.Fields.Where (f => f.Visibility == "protected"))
23+
p.Visibility = "private";
24+
}
25+
}
26+
}
27+
}

tools/generator/generator.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@
104104
<Compile Include="Java.Interop.Tools.Generator.ObjectModel\NamespaceMapping.cs" />
105105
<Compile Include="Java.Interop.Tools.Generator.ObjectModel\Parameter.cs" />
106106
<Compile Include="Java.Interop.Tools.Generator.ObjectModel\ParameterList.cs" />
107+
<Compile Include="Java.Interop.Tools.Generator.Transformation\SealedProtectedFixups.cs" />
107108
<Compile Include="Java.Interop.Tools.Generator.Transformation\KotlinFixups.cs" />
108109
<Compile Include="Java.Interop.Tools.Generator.Transformation\Parser.cs" />
109110
<Compile Include="Utilities\AncestorDescendantCache.cs" />

0 commit comments

Comments
 (0)