Skip to content

Commit d76b104

Browse files
committed
[Xamarin.Android.Build.Tasks] Add MSBuild support for DIM.
1 parent 97f345a commit d76b104

File tree

12 files changed

+267
-2
lines changed

12 files changed

+267
-2
lines changed

src/Xamarin.Android.Build.Tasks/Tasks/Generator.cs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ public class BindingsGenerator : AndroidToolTask
4545
[Required]
4646
public string MonoAndroidFrameworkDirectories { get; set; }
4747

48+
public string LangVersion { get; set; }
49+
50+
public bool EnableInterfaceMembersPreview { get; set; }
51+
4852
public ITaskItem[] TransformFiles { get; set; }
4953
public ITaskItem[] ReferencedManagedLibraries { get; set; }
5054
public ITaskItem[] AnnotationsZipFiles { get; set; }
@@ -131,6 +135,9 @@ protected override string GenerateCommandLineCommands ()
131135
if (UseShortFileNames)
132136
cmd.AppendSwitch ("--use-short-file-names");
133137

138+
if (EnableInterfaceMembersPreview && SupportsCSharp8)
139+
cmd.AppendSwitch ("--lang-features=interface-constants,default-interface-methods");
140+
134141
return cmd.ToString ();
135142
}
136143

@@ -142,5 +149,27 @@ protected override string GenerateFullPathToTool ()
142149
{
143150
return Path.Combine (ToolPath, ToolExe);
144151
}
152+
153+
bool SupportsCSharp8 {
154+
get {
155+
// These are the values that pre-date C# 8. We assume any
156+
// new value we encounter is something that supports it.
157+
switch (LangVersion) {
158+
case "7.3":
159+
case "7.2":
160+
case "7.1":
161+
case "7":
162+
case "6":
163+
case "5":
164+
case "4":
165+
case "3":
166+
case "ISO-2":
167+
case "ISO-1":
168+
return false;
169+
}
170+
171+
return true;
172+
}
173+
}
145174
}
146175
}

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,5 +510,63 @@ public void DesignTimeBuild (string classParser)
510510
}
511511
}
512512
}
513+
514+
[Test]
515+
[TestCaseSource (nameof (ClassParseOptions))]
516+
public void BindDefaultInterfaceMethods (string classParser)
517+
{
518+
var proj = new XamarinAndroidBindingProject {
519+
IsRelease = true,
520+
};
521+
522+
// The sources for the .jar is in the jar itself.
523+
string classesJarBase64 = @"
524+
UEsDBBQACAgIANWk6UwAAAAAAAAAAAAAAAAJAAQATUVUQS1JTkYv/soAAAMAUEsHCAAAAAACAAAAAAA
525+
AAFBLAwQUAAgICADVpOlMAAAAAAAAAAAAAAAAFAAAAE1FVEEtSU5GL01BTklGRVNULk1G803My0xLLS
526+
7RDUstKs7Mz7NSMNQz4OVyLkpNLElN0XWqBAlY6BnEG5obKmj4FyUm56QqOOcXFeQXJZYA1WvycvFyA
527+
QBQSwcIFGFrLUQAAABFAAAAUEsDBAoAAAgAAK2k6UwAAAAAAAAAAAAAAAAEAAAAY29tL1BLAwQKAAAI
528+
AACtpOlMAAAAAAAAAAAAAAAADAAAAGNvbS94YW1hcmluL1BLAwQKAAAIAACwpOlMAAAAAAAAAAAAAAA
529+
AEQAAAGNvbS94YW1hcmluL3Rlc3QvUEsDBBQACAgIAJmk6UwAAAAAAAAAAAAAAAAuAAAAY29tL3hhbW
530+
FyaW4vdGVzdC9EZWZhdWx0SW50ZXJmYWNlTWV0aG9kcy5jbGFzc3WOvU7DMBSFjxsnKeWnXUE8QLrgh
531+
ScAhBSJnwHE7qQ3JVUSC8dGFc/EwsrAA/BQiOuqLKnw8Pn4+LuWv38+vwCcY5biKMVUIKqMYWbzXEBe
532+
mgUJTG/qju58W5B91EXDTbIkd6HtX3jj0G+DzPL5E28v3q8FJg/G25Ku6zB1ekWV9o3LO0e20iXdkns
533+
2i/5spV+1QFaaVq11q23dKUe9U//4ArMwoRrdLdV9saLSJQICI4QVc4ogmTGfThBugFH0zuR/MpNNE7
534+
x015NDL3C868VDL2XuYbL1joMTjI+BNpYC+/xcaA820uEvUEsHCIw1aijpAAAAhQEAAFBLAwQUAAgIC
535+
ACYpOlMAAAAAAAAAAAAAAAAHAAAAERlZmF1bHRJbnRlcmZhY2VNZXRob2RzLmphdmF1zLEOwiAQBuCd
536+
p7hRl0Zd2YyLgw9xwlGJFCocTWPTdxdSHarxxv///utR3bElUKFrRuwwWt8wJZZC9PnqrALrmaJBRXA
537+
ig9nx+RNciG9BJzEJKKeXtnowIcBmCxNE4hw97CTMP6glPmJcuf1f91y5w7cbgtWQ3rCOBnSZymJhNX
538+
nkPJYnUsziBVBLBwgzfz2miQAAAPUAAABQSwECFAAUAAgICADVpOlMAAAAAAIAAAAAAAAACQAEAAAAA
539+
AAAAAAAAAAAAAAATUVUQS1JTkYv/soAAFBLAQIUABQACAgIANWk6UwUYWstRAAAAEUAAAAUAAAAAAAA
540+
AAAAAAAAAD0AAABNRVRBLUlORi9NQU5JRkVTVC5NRlBLAQIKAAoAAAgAAK2k6UwAAAAAAAAAAAAAAAA
541+
EAAAAAAAAAAAAAAAAAMMAAABjb20vUEsBAgoACgAACAAAraTpTAAAAAAAAAAAAAAAAAwAAAAAAAAAAA
542+
AAAAAA5QAAAGNvbS94YW1hcmluL1BLAQIKAAoAAAgAALCk6UwAAAAAAAAAAAAAAAARAAAAAAAAAAAAA
543+
AAAAA8BAABjb20veGFtYXJpbi90ZXN0L1BLAQIUABQACAgIAJmk6UyMNWoo6QAAAIUBAAAuAAAAAAAA
544+
AAAAAAAAAD4BAABjb20veGFtYXJpbi90ZXN0L0RlZmF1bHRJbnRlcmZhY2VNZXRob2RzLmNsYXNzUEs
545+
BAhQAFAAICAgAmKTpTDN/PaaJAAAA9QAAABwAAAAAAAAAAAAAAAAAgwIAAERlZmF1bHRJbnRlcmZhY2
546+
VNZXRob2RzLmphdmFQSwUGAAAAAAcABwDOAQAAVgMAAAAA
547+
";
548+
proj.Jars.Add (new AndroidItem.EmbeddedJar ("dim.jar") {
549+
BinaryContent = () => Convert.FromBase64String (classesJarBase64)
550+
});
551+
552+
proj.AndroidClassParser = classParser;
553+
554+
proj.SetProperty ("EnableInterfaceMembersPreview", "True");
555+
proj.SetProperty ("LangVersion", "preview");
556+
557+
using (var b = CreateDllBuilder (Path.Combine ("temp", TestName), false, false)) {
558+
proj.NuGetRestore (b.ProjectDirectory);
559+
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");
560+
561+
string asmpath = Path.GetFullPath (Path.Combine (Path.GetDirectoryName (new Uri (GetType ().Assembly.CodeBase).LocalPath), b.ProjectDirectory, b.Output.OutputPath, (proj.AssemblyName ?? proj.ProjectName) + ".dll"));
562+
Assert.IsTrue (File.Exists (asmpath), "assembly does not exist");
563+
564+
var cs = b.Output.GetIntermediaryAsText (Path.Combine ("generated", "src", "Com.Xamarin.Test.IDefaultInterfaceMethods.cs"));
565+
Assert.IsTrue (cs.Contains ("int Quux ();"), "Quux not generated.");
566+
Assert.IsTrue (cs.Contains ("virtual unsafe int Foo ()"), "Foo not generated.");
567+
Assert.IsTrue (cs.Contains ("virtual unsafe int Bar {"), "Bar not generated.");
568+
Assert.IsTrue (cs.Contains ("set {"), "(Baz) setter not generated.");
569+
}
570+
}
513571
}
514572
}

src/Xamarin.Android.Build.Tasks/Xamarin.Android.Bindings.targets

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -494,6 +494,8 @@ Copyright (C) 2012 Xamarin Inc. All rights reserved.
494494
ToolPath="$(MonoAndroidToolsDirectory)"
495495
ToolExe="$(BindingsGeneratorToolExe)"
496496
UseShortFileNames="$(UseShortGeneratorFileNames)"
497+
LangVersion="$(LangVersion)"
498+
EnableInterfaceMembersPreview="$(EnableInterfaceMembersPreview)"
497499
/>
498500

499501
<!-- Write a flag so we won't redo this target if nothing changed -->
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
using System;
2+
using Com.Xamarin.Android;
3+
using Java.Lang;
4+
using NUnit.Framework;
5+
6+
namespace Xamarin.Android.JcwGenTests
7+
{
8+
[TestFixture]
9+
public class DimTest
10+
{
11+
[Test]
12+
public void TestDefaultInterfaceMethods ()
13+
{
14+
var empty = new EmptyOverrideClass ();
15+
var iface = empty as IDefaultMethodsInterface;
16+
17+
Assert.AreEqual (0, iface.Foo ());
18+
Assert.AreEqual (2, iface.Bar);
19+
Assert.DoesNotThrow (() => iface.Bar = 5);
20+
21+
Assert.AreEqual (0, iface.InvokeFoo ());
22+
23+
Assert.Throws<UnsupportedOperationException> (() => iface.ToImplement ());
24+
}
25+
26+
[Test]
27+
public void TestOverriddenDefaultInterfaceMethods ()
28+
{
29+
var over = new ImplementedOverrideClass ();
30+
var iface = over as IDefaultMethodsInterface;
31+
32+
Assert.AreEqual (6, over.Foo ());
33+
Assert.AreEqual (100, over.Bar);
34+
Assert.DoesNotThrow (() => over.Bar = 5);
35+
36+
Assert.AreEqual (6, iface.InvokeFoo ());
37+
}
38+
39+
[Test]
40+
public void TestManagedEmptyDefaultInterfaceMethods ()
41+
{
42+
// Test using empty C# implementing interface
43+
var empty = new ManagedEmptyDefault ();
44+
var iface = empty as IDefaultMethodsInterface;
45+
46+
Assert.AreEqual (0, iface.Foo ());
47+
48+
Assert.AreEqual (0, iface.InvokeFoo ());
49+
}
50+
51+
[Test]
52+
public void TestManagedOverriddenDefaultInterfaceMethods ()
53+
{
54+
// Test using method overridden in C#
55+
var over = new ManagedOverrideDefault ();
56+
var iface = over as IDefaultMethodsInterface;
57+
58+
Assert.AreEqual (15, over.Foo ());
59+
Assert.AreEqual (15, iface.Foo ());
60+
61+
Assert.AreEqual (15, iface.InvokeFoo ());
62+
}
63+
64+
[Test]
65+
public void TestStaticMethods ()
66+
{
67+
Assert.AreEqual (10, IStaticMethodsInterface.Foo ());
68+
69+
Assert.AreEqual (3, IStaticMethodsInterface.Value);
70+
Assert.DoesNotThrow (() => IStaticMethodsInterface.Value = 5);
71+
}
72+
73+
[Test]
74+
public void TestChainedDefaultInterfaceMethods ()
75+
{
76+
var over = new ImplementedChainOverrideClass ();
77+
var iface = over as IDefaultMethodsInterface;
78+
79+
Assert.AreEqual (6, over.Foo ());
80+
Assert.AreEqual (100, over.Bar);
81+
Assert.DoesNotThrow (() => over.Bar = 5);
82+
83+
Assert.AreEqual (6, iface.InvokeFoo ());
84+
}
85+
86+
class ManagedEmptyDefault : Java.Lang.Object, IDefaultMethodsInterface
87+
{
88+
}
89+
90+
class ManagedOverrideDefault : Java.Lang.Object, IDefaultMethodsInterface
91+
{
92+
public int Foo () => 15;
93+
}
94+
}
95+
}

tests/CodeGen-Binding/Xamarin.Android.JcwGen-Tests/Properties/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0" package="Xamarin.Android.JcwGen_Tests">
3-
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="22" />
3+
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="28" />
44
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
55
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
66
<application android:label="Xamarin.Android.JcwGen-Tests">

tests/CodeGen-Binding/Xamarin.Android.JcwGen-Tests/Xamarin.Android.JcwGen-Tests.csproj

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,10 @@
1717
<AssemblyName>Xamarin.Android.JcwGen-Tests</AssemblyName>
1818
<AndroidManifest>Properties\AndroidManifest.xml</AndroidManifest>
1919
<AndroidSupportedAbis>armeabi-v7a;x86</AndroidSupportedAbis>
20-
<TargetFrameworkVersion>v8.1</TargetFrameworkVersion>
20+
<TargetFrameworkVersion>v9.0</TargetFrameworkVersion>
2121
<AndroidUseSharedRuntime>false</AndroidUseSharedRuntime>
2222
<AndroidUseLatestPlatformSdk>true</AndroidUseLatestPlatformSdk>
23+
<LangVersion>preview</LangVersion>
2324
</PropertyGroup>
2425
<Import Project="..\..\..\Configuration.props" />
2526
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
@@ -51,6 +52,7 @@
5152
</ItemGroup>
5253
<ItemGroup>
5354
<Compile Include="BindingTests.cs" />
55+
<Compile Include="DimBindingTests.cs" />
5456
<Compile Include="ExceptionTests.cs" />
5557
<Compile Include="MainActivity.cs" />
5658
<Compile Include="TestInstrumentation.cs" />

tests/CodeGen-Binding/Xamarin.Android.McwGen-Tests/Xamarin.Android.McwGen-Tests.csproj

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
<AssemblyName>Xamarin.Android.McwGen-Tests</AssemblyName>
1515
<AndroidUseLatestPlatformSdk>False</AndroidUseLatestPlatformSdk>
1616
<AndroidClassParser>class-parse</AndroidClassParser>
17+
<_JavacSourceVersion>1.8</_JavacSourceVersion>
18+
<_JavacTargetVersion>1.8</_JavacTargetVersion>
19+
<TargetFrameworkVersion>v9.0</TargetFrameworkVersion>
20+
<LangVersion>preview</LangVersion>
21+
<EnableInterfaceMembersPreview>True</EnableInterfaceMembersPreview>
1722
</PropertyGroup>
1823
<Import Project="..\..\..\Configuration.props" />
1924
<PropertyGroup>
@@ -113,6 +118,21 @@
113118
<TestJarEntry Include="java\com\xamarin\android\Bxc37706Throwable.java">
114119
<OutputFile>Jars/xamarin-test.jar</OutputFile>
115120
</TestJarEntry>
121+
<TestJarEntry Include="java\com\xamarin\android\DefaultMethodsInterface.java">
122+
<OutputFile>Jars/xamarin-test.jar</OutputFile>
123+
</TestJarEntry>
124+
<TestJarEntry Include="java\com\xamarin\android\EmptyOverrideClass.java">
125+
<OutputFile>Jars/xamarin-test.jar</OutputFile>
126+
</TestJarEntry>
127+
<TestJarEntry Include="java\com\xamarin\android\ImplementedOverrideClass.java">
128+
<OutputFile>Jars/xamarin-test.jar</OutputFile>
129+
</TestJarEntry>
130+
<TestJarEntry Include="java\com\xamarin\android\ImplementedChainOverrideClass.java">
131+
<OutputFile>Jars/xamarin-test.jar</OutputFile>
132+
</TestJarEntry>
133+
<TestJarEntry Include="java\com\xamarin\android\StaticMethodsInterface.java">
134+
<OutputFile>Jars/xamarin-test.jar</OutputFile>
135+
</TestJarEntry>
116136
</ItemGroup>
117137
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.Bindings.targets" />
118138
<Import Project="..\..\..\build-tools\scripts\Jar.targets" />
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.xamarin.android;
2+
3+
public interface DefaultMethodsInterface
4+
{
5+
default int foo () { return 0; }
6+
default int getBar () { return 2; }
7+
default void setBar (int value) { }
8+
default int toImplement () { throw new UnsupportedOperationException (); }
9+
default int invokeFoo () { return foo (); }
10+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package com.xamarin.android;
2+
3+
public class EmptyOverrideClass implements DefaultMethodsInterface
4+
{
5+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package com.xamarin.android;
2+
3+
public class ImplementedChainOverrideClass extends EmptyOverrideClass
4+
{
5+
@Override
6+
public int foo () {
7+
return 6;
8+
}
9+
10+
@Override
11+
public int getBar () {
12+
return 100;
13+
}
14+
15+
@Override
16+
public void setBar (int value) {
17+
}
18+
}

0 commit comments

Comments
 (0)