Skip to content

Commit 17ed14d

Browse files
committed
[generator] do not generate identical methods to previously generated ones.
There are classes that implement more than one interfaces that share an identical methods (which share the same name and the same JNI signature). For example, java.nio.AsynchronousFileChannel implements Closeable and AsynchronousChannel, both of which contain `close()` method. Only one `Close()` should be generated for that class.
1 parent 689c752 commit 17ed14d

16 files changed

+415
-3
lines changed

tools/generator/ClassGen.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -313,9 +313,7 @@ public override ClassGen BaseGen {
313313
void GenerateAbstractMembers (StreamWriter sw, string indent, CodeGenerationOptions opt)
314314
{
315315
foreach (InterfaceGen gen in GetAllDerivedInterfaces ())
316-
// FIXME: this is an ugly workaround for bug in generator that generates extraneous member.
317-
if (FullName != "Android.Views.Animations.BaseInterpolator" || gen.FullName != "Android.Views.Animations.IInterpolator")
318-
gen.GenerateAbstractMembers (this, sw, indent, opt);
316+
gen.GenerateAbstractMembers (this, sw, indent, opt);
319317
}
320318

321319
void GenMethods (StreamWriter sw, string indent, CodeGenerationOptions opt)
@@ -339,6 +337,7 @@ void GenMethods (StreamWriter sw, string indent, CodeGenerationOptions opt)
339337
m.GenerateAbstractDeclaration (sw, indent, opt, null, this);
340338
else
341339
m.Generate (sw, indent, opt, this, true);
340+
opt.ContextGeneratedMethods.Add (m);
342341
m.IsVirtual = virt;
343342
}
344343

@@ -371,6 +370,8 @@ void GenProperties (StreamWriter sw, string indent, CodeGenerationOptions opt)
371370
public override void Generate (StreamWriter sw, string indent, CodeGenerationOptions opt, GenerationInfo gen_info)
372371
{
373372
opt.ContextTypes.Push (this);
373+
opt.ContextGeneratedMethods = new List<Method> ();
374+
374375
gen_info.TypeRegistrations.Add (new KeyValuePair<string, string>(RawJniName, AssemblyQualifiedName));
375376
bool is_enum = base_symbol != null && base_symbol.FullName == "Java.Lang.Enum";
376377
if (is_enum)
@@ -497,6 +498,9 @@ public override void Generate (StreamWriter sw, string indent, CodeGenerationOpt
497498
sw.WriteLine ();
498499
GenerateInvoker (sw, indent, opt);
499500
}
501+
502+
opt.ContextGeneratedMethods.Clear ();
503+
500504
opt.ContextTypes.Pop ();
501505
}
502506

tools/generator/CodeGenerator.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@ public class CodeGenerationOptions
560560
public Stack<GenBase> ContextTypes {
561561
get { return context_types; }
562562
}
563+
public List<Method> ContextGeneratedMethods { get; set; } = new List<Method> ();
563564
public GenBase ContextType {
564565
get { return context_types.Any () ? context_types.Peek () : null; }
565566
}

tools/generator/InterfaceGen.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,8 @@ public void GenerateAbstractMembers (ClassGen gen, StreamWriter sw, string inden
620620
foreach (Method m in Methods.Where (m => !m.IsInterfaceDefaultMethod && !m.IsStatic)) {
621621
bool mapped = false;
622622
string sig = m.GetSignature ();
623+
if (opt.ContextGeneratedMethods.Any (_ => _.Name == m.Name && _.JniSignature == m.JniSignature))
624+
continue;
623625
for (var cls = gen; cls != null; cls = cls.BaseGen)
624626
if (cls.ContainsMethod (m, false) || cls != gen && gen.ExplicitlyImplementedInterfaceMethods.Contains (sig)) {
625627
mapped = true;
@@ -631,6 +633,7 @@ public void GenerateAbstractMembers (ClassGen gen, StreamWriter sw, string inden
631633
m.GenerateExplicitInterfaceImplementation (sw, indent, opt, this);
632634
else
633635
m.GenerateAbstractDeclaration (sw, indent, opt, this, gen);
636+
opt.ContextGeneratedMethods.Add (m);
634637
}
635638
foreach (Property prop in Properties) {
636639
if (gen.ContainsProperty (prop.Name, false))
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using System;
2+
using NUnit.Framework;
3+
4+
namespace generatortests
5+
{
6+
[TestFixture]
7+
public class InterfaceMethodsConflict : BaseGeneratorTest
8+
{
9+
[Test]
10+
public void GeneratedOK ()
11+
{
12+
RunAllTargets (
13+
outputRelativePath: "InterfaceMethodsConflict",
14+
apiDescriptionFile: "expected/InterfaceMethodsConflict/InterfaceMethodsConflict.xml",
15+
expectedRelativePath: "InterfaceMethodsConflict");
16+
}
17+
}
18+
}
19+
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<api>
3+
<package name="xamarin.test">
4+
<class abstract="false" deprecated="not deprecated" final="false" name="Object" static="false" visibility="public">
5+
</class>
6+
</package>
7+
<package name="xamarin.test">
8+
<interface abstract="true" deprecated="not deprecated" final="false" name="I1" static="false" visibility="public">
9+
<method abstract="true" deprecated="not deprecated" final="false" name="close" native="false" return="void" static="false" synchronized="false" visibility="public">
10+
</method>
11+
</interface>
12+
<interface abstract="true" deprecated="not deprecated" final="false" name="I2" static="false" visibility="public">
13+
<method abstract="true" deprecated="not deprecated" final="false" name="close" native="false" return="void" static="false" synchronized="false" visibility="public">
14+
</method>
15+
</interface>
16+
<class abstract="true" deprecated="not deprecated" extends="java.lang.Object" extends-generic-aware="java.lang.Object"
17+
final="false" name="SomeObject" static="false" visibility="public">
18+
<implements name="xamarin.test.I1" name-generic-aware="xamarin.test.I1" />
19+
<implements name="xamarin.test.I2" name-generic-aware="xamarin.test.I2" />
20+
</class>
21+
</package>
22+
</api>
23+
24+
25+
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
2+
3+
4+

tools/generator/Tests/expected.targets

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,12 @@
495495
<Content Include='expected.ji\TestInterface\Test.ME.TestInterfaceImplementation.cs'>
496496
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
497497
</Content>
498+
<Content Include='expected.ji\InterfaceMethodsConflict\InterfaceMethodsConflict.xml'>
499+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
500+
</Content>
501+
<Content Include='expected.ji\InterfaceMethodsConflict\Xamarin.Test.SomeObject.cs'>
502+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
503+
</Content>
498504
<Content Include='expected\GenericArguments\GenericArguments.xml'>
499505
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
500506
</Content>
@@ -615,5 +621,11 @@
615621
<Content Include='expected\TestInterface\Test.ME.TestInterfaceImplementation.cs'>
616622
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
617623
</Content>
624+
<Content Include='expected\InterfaceMethodsConflict\InterfaceMethodsConflict.xml'>
625+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
626+
</Content>
627+
<Content Include='expected\InterfaceMethodsConflict\Xamarin.Test.SomeObject.cs'>
628+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
629+
</Content>
618630
</ItemGroup>
619631
</Project>
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<api>
3+
<package name="java.lang">
4+
<class abstract="false" deprecated="not deprecated" final="false" name="Object" static="false" visibility="public">
5+
</class>
6+
</package>
7+
<package name="xamarin.test">
8+
<interface abstract="true" deprecated="not deprecated" final="false" name="I1" static="false" visibility="public">
9+
<method abstract="true" deprecated="not deprecated" final="false" name="close" native="false" return="void" static="false" synchronized="false" visibility="public">
10+
</method>
11+
</interface>
12+
<interface abstract="true" deprecated="not deprecated" final="false" name="I2" static="false" visibility="public">
13+
<method abstract="true" deprecated="not deprecated" final="false" name="close" native="false" return="void" static="false" synchronized="false" visibility="public">
14+
</method>
15+
</interface>
16+
<class abstract="false" deprecated="not deprecated" extends="java.lang.Object" extends-generic-aware="java.lang.Object"
17+
final="false" name="SomeObject" static="false" visibility="public">
18+
<implements name="xamarin.test.I1" name-generic-aware="xamarin.test.I1" />
19+
<implements name="xamarin.test.I2" name-generic-aware="xamarin.test.I2" />
20+
</class>
21+
<class abstract="true" deprecated="not deprecated" extends="java.lang.Object" extends-generic-aware="java.lang.Object"
22+
final="false" name="SomeObject2" static="false" visibility="public">
23+
<implements name="xamarin.test.I1" name-generic-aware="xamarin.test.I1" />
24+
<implements name="xamarin.test.I2" name-generic-aware="xamarin.test.I2" />
25+
</class>
26+
</package>
27+
</api>
28+
29+
30+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Android.Runtime;
4+
5+
namespace Java.Interop {
6+
7+
partial class __TypeRegistrations {
8+
9+
public static void RegisterPackages ()
10+
{
11+
#if MONODROID_TIMING
12+
var start = DateTime.Now;
13+
Android.Util.Log.Info ("MonoDroid-Timing", "RegisterPackages start: " + (start - new DateTime (1970, 1, 1)).TotalMilliseconds);
14+
#endif // def MONODROID_TIMING
15+
Java.Interop.TypeManager.RegisterPackages (
16+
new string[]{
17+
},
18+
new Converter<string, Type>[]{
19+
});
20+
#if MONODROID_TIMING
21+
var end = DateTime.Now;
22+
Android.Util.Log.Info ("MonoDroid-Timing", "RegisterPackages time: " + (end - new DateTime (1970, 1, 1)).TotalMilliseconds + " [elapsed: " + (end - start).TotalMilliseconds + " ms]");
23+
#endif // def MONODROID_TIMING
24+
}
25+
26+
static Type Lookup (string[] mappings, string javaType)
27+
{
28+
string managedType = Java.Interop.TypeManager.LookupTypeMapping (mappings, javaType);
29+
if (managedType == null)
30+
return null;
31+
return Type.GetType (managedType);
32+
}
33+
}
34+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Android.Runtime;
4+
5+
namespace Java.Lang {
6+
7+
// Metadata.xml XPath class reference: path="/api/package[@name='java.lang']/class[@name='Object']"
8+
[global::Android.Runtime.Register ("java/lang/Object", DoNotGenerateAcw=true)]
9+
public partial class Object {
10+
11+
}
12+
}

0 commit comments

Comments
 (0)