-
Notifications
You must be signed in to change notification settings - Fork 53
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[generator] Ensure consistent member visibility. [#367]
- Loading branch information
Showing
7 changed files
with
255 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
28 changes: 28 additions & 0 deletions
28
tools/generator/Java.Interop.Tools.Generator.Transformation/MethodVisibilityFixup.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace MonoDroid.Generation | ||
{ | ||
// Java allows a public member to override a protected member, but C# does not. | ||
// This Fixup makes the override member protected as well. | ||
static class MethodVisibilityFixup | ||
{ | ||
public static void Fixup (GenBase gen) | ||
{ | ||
foreach (var method in gen.GetAllMethods ()) { | ||
var base_method = method.GetBaseMethodDeclaration (); | ||
|
||
if (base_method == null) | ||
continue; | ||
|
||
if (method.Visibility == "public" && (base_method.Visibility == "protected" || base_method.Visibility == "protected internal")) { | ||
Report.Warning (0, Report.WarningInconsistentAccessbility, $"Setting {gen.FullName}.{method.Name} visibility to {base_method.Visibility} to match base method"); | ||
method.Visibility = base_method.Visibility; | ||
} | ||
} | ||
} | ||
} | ||
} |
176 changes: 176 additions & 0 deletions
176
tools/generator/Tests/Unit-Tests/MethodVisibilityFixupTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
using System; | ||
using MonoDroid.Generation; | ||
using NUnit.Framework; | ||
|
||
namespace generatortests | ||
{ | ||
[TestFixture] | ||
public class MethodVisibilityFixupTests | ||
{ | ||
CodeGenerationOptions opt; | ||
GenericParameterDefinitionList list; | ||
CodeGeneratorContext context; | ||
|
||
[SetUp] | ||
public void SetUp () | ||
{ | ||
opt = new CodeGenerationOptions (); | ||
list = new GenericParameterDefinitionList (); | ||
context = new CodeGeneratorContext (); | ||
} | ||
|
||
[Test] | ||
public void FixupBaseOverride () | ||
{ | ||
var base_class = new TestClass ("java.lang.Object", "com.mypackage.Foo"); | ||
var this_class = new TestClass ("com.mypackage.Foo", "com.mypackage.MyClass"); | ||
|
||
base_class.Methods.Add (SupportTypeBuilder.CreateMethod (base_class, "DoSomething", opt)); | ||
base_class.Methods [0].Visibility = "protected"; | ||
opt.SymbolTable.AddType (base_class); | ||
|
||
this_class.Methods.Add (SupportTypeBuilder.CreateMethod (this_class, "DoSomething", opt)); | ||
this_class.Methods [0].Visibility = "public"; | ||
this_class.Methods [0].IsOverride = true; | ||
opt.SymbolTable.AddType (this_class); | ||
|
||
base_class.Validate (opt, list, context); | ||
this_class.Validate (opt, list, context); | ||
|
||
MethodVisibilityFixup.Fixup (this_class); | ||
|
||
Assert.AreEqual ("protected", this_class.Methods [0].Visibility); | ||
} | ||
|
||
[Test] | ||
public void FixupRecursiveBaseOverride () | ||
{ | ||
// This throws a middle class into the inheritance tree that does | ||
// not override the method to ensure we look recursively | ||
var base_class = new TestClass ("java.lang.Object", "com.mypackage.Foo"); | ||
var middle_class = new TestClass ("com.mypackage.Foo", "com.mypackage.Middle"); | ||
var this_class = new TestClass ("com.mypackage.Middle", "com.mypackage.MyClass"); | ||
|
||
base_class.Methods.Add (SupportTypeBuilder.CreateMethod (base_class, "DoSomething", opt)); | ||
base_class.Methods [0].Visibility = "protected"; | ||
opt.SymbolTable.AddType (base_class); | ||
|
||
opt.SymbolTable.AddType (middle_class); | ||
|
||
this_class.Methods.Add (SupportTypeBuilder.CreateMethod (this_class, "DoSomething", opt)); | ||
this_class.Methods [0].Visibility = "public"; | ||
this_class.Methods [0].IsOverride = true; | ||
opt.SymbolTable.AddType (this_class); | ||
|
||
base_class.Validate (opt, list, context); | ||
this_class.Validate (opt, list, context); | ||
|
||
MethodVisibilityFixup.Fixup (this_class); | ||
|
||
Assert.AreEqual ("protected", this_class.Methods [0].Visibility); | ||
} | ||
|
||
[Test] | ||
public void FixupNestedBaseOverride () | ||
{ | ||
// This tests: | ||
// - MyClass: public override void DoSomething () | ||
// |- MiddleClass: public override void DoSomething () | ||
// |- BaseClass: protected virtual void DoSomething () | ||
var base_class = new TestClass ("java.lang.Object", "com.mypackage.Foo"); | ||
var middle_class = new TestClass ("com.mypackage.Foo", "com.mypackage.Middle"); | ||
var this_class = new TestClass ("com.mypackage.Middle", "com.mypackage.MyClass"); | ||
|
||
base_class.Methods.Add (SupportTypeBuilder.CreateMethod (base_class, "DoSomething", opt)); | ||
base_class.Methods [0].Visibility = "protected"; | ||
opt.SymbolTable.AddType (base_class); | ||
|
||
middle_class.Methods.Add (SupportTypeBuilder.CreateMethod (middle_class, "DoSomething", opt)); | ||
middle_class.Methods [0].Visibility = "public"; | ||
middle_class.Methods [0].IsOverride = true; | ||
opt.SymbolTable.AddType (middle_class); | ||
|
||
this_class.Methods.Add (SupportTypeBuilder.CreateMethod (this_class, "DoSomething", opt)); | ||
this_class.Methods [0].Visibility = "public"; | ||
this_class.Methods [0].IsOverride = true; | ||
opt.SymbolTable.AddType (this_class); | ||
|
||
base_class.Validate (opt, list, context); | ||
middle_class.Validate (opt, list, context); | ||
this_class.Validate (opt, list, context); | ||
|
||
MethodVisibilityFixup.Fixup (this_class); | ||
|
||
Assert.AreEqual ("protected", this_class.Methods [0].Visibility); | ||
} | ||
|
||
[Test] | ||
public void FixupBaseProtectedInternalOverride () | ||
{ | ||
var base_class = new TestClass ("java.lang.Object", "com.mypackage.Foo"); | ||
var this_class = new TestClass ("com.mypackage.Foo", "com.mypackage.MyClass"); | ||
|
||
base_class.Methods.Add (SupportTypeBuilder.CreateMethod (base_class, "DoSomething", opt)); | ||
base_class.Methods [0].Visibility = "protected internal"; | ||
opt.SymbolTable.AddType (base_class); | ||
|
||
this_class.Methods.Add (SupportTypeBuilder.CreateMethod (this_class, "DoSomething", opt)); | ||
this_class.Methods [0].Visibility = "public"; | ||
this_class.Methods [0].IsOverride = true; | ||
opt.SymbolTable.AddType (this_class); | ||
|
||
base_class.Validate (opt, list, context); | ||
this_class.Validate (opt, list, context); | ||
|
||
MethodVisibilityFixup.Fixup (this_class); | ||
|
||
Assert.AreEqual ("protected internal", this_class.Methods [0].Visibility); | ||
} | ||
|
||
[Test] | ||
public void IgnoreValidPublic () | ||
{ | ||
var base_class = new TestClass ("java.lang.Object", "com.mypackage.Foo"); | ||
var this_class = new TestClass ("com.mypackage.Foo", "com.mypackage.MyClass"); | ||
|
||
base_class.Methods.Add (SupportTypeBuilder.CreateMethod (base_class, "DoSomething", opt)); | ||
base_class.Methods [0].Visibility = "public"; | ||
opt.SymbolTable.AddType (base_class); | ||
|
||
this_class.Methods.Add (SupportTypeBuilder.CreateMethod (this_class, "DoSomething", opt)); | ||
this_class.Methods [0].Visibility = "public"; | ||
this_class.Methods [0].IsOverride = true; | ||
opt.SymbolTable.AddType (this_class); | ||
|
||
base_class.Validate (opt, list, context); | ||
this_class.Validate (opt, list, context); | ||
|
||
MethodVisibilityFixup.Fixup (this_class); | ||
|
||
Assert.AreEqual ("public", this_class.Methods [0].Visibility); | ||
} | ||
|
||
[Test] | ||
public void FixupPropertyBaseOverride () | ||
{ | ||
var base_class = new TestClass ("java.lang.Object", "com.mypackage.Foo"); | ||
var this_class = new TestClass ("com.mypackage.Foo", "com.mypackage.MyClass"); | ||
|
||
base_class.Properties.Add (SupportTypeBuilder.CreateProperty (base_class, "Count", "int", opt)); | ||
base_class.Properties [0].Getter.Visibility = "protected"; | ||
opt.SymbolTable.AddType (base_class); | ||
|
||
this_class.Properties.Add (SupportTypeBuilder.CreateProperty (this_class, "Count", "int", opt)); | ||
this_class.Properties [0].Getter.Visibility = "public"; | ||
this_class.Properties [0].Getter.IsOverride = true; | ||
opt.SymbolTable.AddType (this_class); | ||
|
||
base_class.Validate (opt, list, context); | ||
this_class.Validate (opt, list, context); | ||
|
||
MethodVisibilityFixup.Fixup (this_class); | ||
|
||
Assert.AreEqual ("protected", this_class.Properties [0].Getter.Visibility); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters