Skip to content

Commit

Permalink
[generator] Use custom delegates instead of Func/Action.
Browse files Browse the repository at this point in the history
  • Loading branch information
jpobst committed Apr 24, 2020
1 parent ce8dc40 commit dec7404
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 21 deletions.
50 changes: 47 additions & 3 deletions tools/generator/CodeGenerationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;

using System.Text;
using Java.Interop.Tools.JavaCallableWrappers;

using Xamarin.Android.Binder;
Expand Down Expand Up @@ -44,6 +44,9 @@ internal CodeGenerator CreateCodeGenerator (TextWriter writer)

public SymbolTable SymbolTable { get; } = new SymbolTable ();

readonly SortedSet<string> jni_marshal_delegates = new SortedSet<string> ();
readonly object jni_marshal_delegates_lock = new object ();

public bool UseGlobal { get; set; }
public bool IgnoreNonPublicType { get; set; }
public string AssemblyName { get; set; }
Expand Down Expand Up @@ -129,9 +132,10 @@ public string GetNullForgiveness (Parameter symbol)
return string.Empty;
}

string GetNullable (string s)
string GetNullable(string s)
{
switch (s) {
switch (s)
{
case "void":
case "int":
//case "int[]":
Expand All @@ -156,6 +160,46 @@ string GetNullable (string s)
return NullableOperator;
}

// Encoding format:
// - Type name prefix: _JniMarshal_PP
// - Parameter types, using JNI encoding, e.g. Z is boolean, I is int, etc. Exception: Reference types, normally encoded as L…;, are instead just L.
// - Another _.
// - Return type, encoded as with parameters. A void return type is V.
internal string GetJniMarshalDelegate (Method method)
{
var sb = new StringBuilder ("_JniMarshal_PP");

foreach (var p in method.Parameters)
sb.Append (GetJniTypeCode (p.Symbol));

sb.Append ("_");

sb.Append (method.IsVoid ? "V" : GetJniTypeCode (method.RetVal.Symbol));

var result = sb.ToString ();

lock (jni_marshal_delegates_lock)
jni_marshal_delegates.Add (result);

return result;
}

string GetJniTypeCode (ISymbol symbol)
{
var jni_name = symbol.JniName;

if (jni_name.StartsWith ("L") || jni_name.StartsWith ("["))
return "L";

return symbol.JniName;
}

internal IEnumerable<string> GetJniMarshalDelegates ()
{
lock (jni_marshal_delegates_lock)
return jni_marshal_delegates;
}

public string GetOutputName (string s)
{
if (s == "System.Void")
Expand Down
4 changes: 2 additions & 2 deletions tools/generator/CodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -187,12 +187,12 @@ static void Run (CodeGeneratorOptions options, DirectoryAssemblyResolver resolve
if (mapping_file != null)
GenerateMappingReportFile (gens, mapping_file);

new NamespaceMapping (gens).Generate (opt, gen_info);

foreach (IGeneratable gen in gens)
if (gen.IsGeneratable)
gen.Generate (opt, gen_info);

new NamespaceMapping (gens).Generate (opt, gen_info);


ClassGen.GenerateTypeRegistrations (opt, gen_info);
ClassGen.GenerateEnumList (gen_info);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1090,7 +1090,7 @@ public virtual void WriteMethodCallback (Method method, string indent, GenBase t
{
var is_private = method.IsInterfaceDefaultMethod ? "private " : string.Empty;

string delegate_type = method.GetDelegateType ();
string delegate_type = method.GetDelegateType (opt);
writer.WriteLine ("{0}{2}static Delegate{3} {1};", indent, method.EscapedCallbackName, is_private, opt.NullableOperator);
writer.WriteLine ("#pragma warning disable 0169");
if (method.Deprecated != null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -128,15 +128,7 @@ internal string GetAdapterName (CodeGenerationOptions opt, string adapter)
// Connectors for DIM are defined on the interface, not the implementing type
public string GetConnectorNameFull (CodeGenerationOptions opt) => ConnectorName + (opt.SupportDefaultInterfaceMethods && IsInterfaceDefaultMethod ? $":{DeclaringType.FullName}, " + (AssemblyName ?? opt.AssemblyName) : string.Empty);

internal string GetDelegateType ()
{
var parms = Parameters.DelegateTypeParams;

if (IsVoid)
return $"Action<IntPtr, IntPtr{parms}>";
else
return $"Func<IntPtr, IntPtr{parms}, {RetVal.NativeType}>";
}
internal string GetDelegateType (CodeGenerationOptions opt) => opt.GetJniMarshalDelegate (this);

public string GetMetadataXPathReference (GenBase declaringType) =>
$"{declaringType.MetadataXPathReference}/method[@name='{JavaName}'{Parameters.GetMethodXPathPredicate ()}]";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,54 @@ public NamespaceMapping (IEnumerable<GenBase> gens)
public void Generate (CodeGenerationOptions opt, GenerationInfo gen_info)
{
using (var sw = gen_info.OpenStream (opt.GetFileName ("__NamespaceMapping__"))) {
sw.WriteLine ("using System;");
sw.WriteLine ();

foreach (var p in mappings)
sw.WriteLine ("[assembly:global::Android.Runtime.NamespaceMapping (Java = \"{0}\", Managed=\"{1}\")]",
p.Key, p.Value);

sw.WriteLine ();

// delegate bool _JniMarshal_PPL_Z (IntPtr jnienv, IntPtr klass, IntPtr a);
foreach (var jni in opt.GetJniMarshalDelegates ())
sw.WriteLine ($"delegate {FromJniType (jni[jni.Length - 1])} {jni} (IntPtr jnienv, IntPtr klass{GetDelegateParameters (jni)});");
}
}

string GetDelegateParameters (string jni)
{
var parameters = new List<string> ();

jni = jni.Substring ("_JniMarshal_PP".Length);

var index = 0;

while (jni[index] != '_') {
parameters.Add ($"{FromJniType (jni [index])} p{index}");
index++;
}

if (parameters.Count == 0)
return string.Empty;

return ", " + string.Join (", ", parameters);
}

string FromJniType (char c)
{
switch (c) {
case 'B': return "sbyte";
case 'C': return "char";
case 'D': return "double";
case 'F': return "float";
case 'I': return "int";
case 'J': return "long";
case 'S': return "short";
case 'Z': return "bool";
case 'V': return "void";
default:
return "IntPtr"; ;
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions tools/generator/generator.csproj
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net472;netcoreapp3.1</TargetFrameworks>
<TargetFramework>net472</TargetFramework>
<OutputType>Exe</OutputType>
<DefineConstants>$(DefineConstants);GENERATOR;HAVE_CECIL;JCW_ONLY_TYPE_NAMES</DefineConstants>
<LangVersion>8.0</LangVersion>
</PropertyGroup>

<PropertyGroup>
Expand Down Expand Up @@ -35,6 +36,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\Xamarin.SourceWriter\Xamarin.SourceWriter.csproj" />
<ProjectReference Include="..\..\src\Xamarin.Android.Tools.AnnotationSupport\Xamarin.Android.Tools.AnnotationSupport.csproj" />
<ProjectReference Include="..\..\src\Xamarin.Android.Tools.ApiXmlAdjuster\Xamarin.Android.Tools.ApiXmlAdjuster.csproj" />
<ProjectReference Include="..\..\src\Java.Interop.Tools.Diagnostics\Java.Interop.Tools.Diagnostics.csproj" />
Expand Down
21 changes: 17 additions & 4 deletions tools/generator/generator.sln
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2012
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "generator", "generator.csproj", "{D14A1B5C-2060-4930-92BE-F7190256C735}"
# Visual Studio Version 16
VisualStudioVersion = 16.0.30013.7
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "generator", "generator.csproj", "{D14A1B5C-2060-4930-92BE-F7190256C735}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "generator-Tests", "..\..\tests\generator-Tests\generator-Tests.csproj", "{4EEAB1A7-99C1-4302-9C18-01A7B481409B}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "generator-Tests", "..\..\tests\generator-Tests\generator-Tests.csproj", "{4EEAB1A7-99C1-4302-9C18-01A7B481409B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Xamarin.SourceWriter", "..\..\src\Xamarin.SourceWriter\Xamarin.SourceWriter.csproj", "{FD3882A4-2661-47C6-9C37-18FAFE5F7991}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -19,5 +22,15 @@ Global
{4EEAB1A7-99C1-4302-9C18-01A7B481409B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4EEAB1A7-99C1-4302-9C18-01A7B481409B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4EEAB1A7-99C1-4302-9C18-01A7B481409B}.Release|Any CPU.Build.0 = Release|Any CPU
{FD3882A4-2661-47C6-9C37-18FAFE5F7991}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FD3882A4-2661-47C6-9C37-18FAFE5F7991}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FD3882A4-2661-47C6-9C37-18FAFE5F7991}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FD3882A4-2661-47C6-9C37-18FAFE5F7991}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EEBC7E77-8FA5-4C2C-8FFD-08F6CD0A5330}
EndGlobalSection
EndGlobal

0 comments on commit dec7404

Please sign in to comment.