Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,18 +51,7 @@ public static Assembly Compile (Xamarin.Android.Binder.CodeGeneratorOptions opti
.ToArray ();

// Set up the assemblies we need to reference
var binDir = Path.GetDirectoryName (typeof (BaseGeneratorTest).Assembly.Location);
var facDir = GetFacadesPath ();

var referencePaths = new[]{
unitTestFrameworkAssemblyPath,
typeof(object).Assembly.Location,
typeof(Enumerable).Assembly.Location,
typeof(Uri).Assembly.Location,
Path.Combine (binDir, "Java.Interop.dll"),
Path.Combine (facDir, "netstandard.dll"),
Path.Combine (facDir, "System.Runtime.dll"),
};
var referencePaths = GetReferencePaths ();

var references = referencePaths.Select (p => MetadataReference.CreateFromFile (p)).ToArray ();

Expand All @@ -76,10 +65,43 @@ public static Assembly Compile (Xamarin.Android.Binder.CodeGeneratorOptions opti

Console.WriteLine ($"# Trying to compile: {testCommandLine}");

return Compile (Path.GetFileName (assemblyFileName), syntax_trees, references, out hasErrors, out output, allowWarnings);
}

public static Assembly CompileSources (IEnumerable<string> sources, out bool hasErrors, out string output)
{
var supportFiles = Directory.EnumerateFiles (Path.Combine (Path.GetDirectoryName (supportFilePath), "SupportFiles"),
"*.cs", SearchOption.AllDirectories);
var parseOptions = new CSharpParseOptions (preprocessorSymbols: new [] { "NET" });
var syntaxTrees = sources.Concat (supportFiles.Select (File.ReadAllText))
.Select (s => CSharpSyntaxTree.ParseText (s, parseOptions));
var references = GetReferencePaths ().Select (p => MetadataReference.CreateFromFile (p));

return Compile ("GeneratedCallbacks_" + Guid.NewGuid ().ToString ("N"), syntaxTrees, references, out hasErrors, out output, allowWarnings: true);
}

static string [] GetReferencePaths ()
{
var binDir = Path.GetDirectoryName (typeof (BaseGeneratorTest).Assembly.Location);
var facDir = GetFacadesPath ();
return new [] {
unitTestFrameworkAssemblyPath,
typeof (object).Assembly.Location,
typeof (Enumerable).Assembly.Location,
typeof (Uri).Assembly.Location,
Path.Combine (binDir, "Java.Interop.dll"),
Path.Combine (facDir, "netstandard.dll"),
Path.Combine (facDir, "System.Runtime.dll"),
};
}

static Assembly Compile (string assemblyName, IEnumerable<SyntaxTree> syntaxTrees, IEnumerable<MetadataReference> references,
out bool hasErrors, out string output, bool allowWarnings)
{
// Compile!
var compilation = CSharpCompilation.Create (
Path.GetFileName (assemblyFileName),
syntaxTrees: syntax_trees,
assemblyName,
syntaxTrees: syntaxTrees,
references: references,
options: new CSharpCompilationOptions (OutputKind.DynamicallyLinkedLibrary, allowUnsafe: true));

Expand Down

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions external/Java.Interop/tools/generator/CodeGenerationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,17 @@ public SymbolTable SymbolTable {
public bool UseObsoletedOSPlatformAttributes { get; set; }
public bool UseRestrictToAttributes { get; set; }
public bool FixObsoleteOverrides { get; set; }

// Experimental: emit each supported non-generic `n_*` binding callback as an
// [UnmanagedCallersOnly] method which forwards to a shared typed marshaling helper,
// and omit the `cb_*` delegate cache field and the `Get*Handler ()` connector method.
public bool UseUnmanagedCallersOnlyCallbacks { get; set; }

// Compact, deterministic names for the callback infrastructure emitted for
// UseUnmanagedCallersOnlyCallbacks. Shared so that a [Register] connector and the callback
// it names agree even when they are emitted by different source writers.
public generator.SourceWriters.CallbackNameAllocator CallbackNames { get; } = new generator.SourceWriters.CallbackNameAllocator ();

public bool RemoveConstSugar => BuildingCoreAssembly;

bool? buildingCoreAssembly;
Expand Down
1 change: 1 addition & 0 deletions external/Java.Interop/tools/generator/CodeGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ static void Run (CodeGeneratorOptions options, DirectoryAssemblyResolver resolve
UseObsoletedOSPlatformAttributes = options.UseObsoletedOSPlatformAttributes,
UseRestrictToAttributes = options.UseRestrictToAttributes,
FixObsoleteOverrides = options.FixObsoleteOverrides,
UseUnmanagedCallersOnlyCallbacks = options.UseUnmanagedCallersOnlyCallbacks,
};
var resolverCache = new TypeDefinitionCache ();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public CodeGeneratorOptions ()
public bool SupportNullableReferenceTypes { get; set; }
public bool UseRestrictToAttributes { get; set; }
public bool FixObsoleteOverrides { get; set;} = true;
public bool UseUnmanagedCallersOnlyCallbacks { get; set; }
public bool UseObsoletedOSPlatformAttributes { get; set; }

public XmldocStyle XmldocStyle { get; set; } = XmldocStyle.IntelliSense;
Expand Down Expand Up @@ -109,7 +110,7 @@ public static CodeGeneratorOptions Parse (string[] args)
"SDK Platform {VERSION}/API level.",
v => opts.ApiLevel = v },
{ "lang-features=",
"For internal use. (Flags: interface-constants,default-interface-methods,nested-interface-types,nullable-reference-types,obsoleted-platform-attributes,restrict-to-attributes,do-not-fix-obsolete-overrides)",
"For internal use. (Flags: interface-constants,default-interface-methods,nested-interface-types,nullable-reference-types,obsoleted-platform-attributes,restrict-to-attributes,do-not-fix-obsolete-overrides,unmanaged-callers-only-callbacks)",
v => {
opts.SupportInterfaceConstants = v?.Contains ("interface-constants") == true;
opts.SupportDefaultInterfaceMethods = v?.Contains ("default-interface-methods") == true;
Expand All @@ -118,6 +119,7 @@ public static CodeGeneratorOptions Parse (string[] args)
opts.UseObsoletedOSPlatformAttributes = v?.Contains ("obsoleted-platform-attributes") == true;
opts.UseRestrictToAttributes = v?.Contains ("restrict-to-attributes") == true;
opts.FixObsoleteOverrides = v?.Contains ("do-not-fix-obsolete-overrides") == false;
opts.UseUnmanagedCallersOnlyCallbacks = v?.Contains ("unmanaged-callers-only-callbacks") == true;
}},
{ "preserve-enums",
"For internal use.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ public void Generate (CodeGenerationOptions opt, GenerationInfo gen_info)
sw.WriteLine ();

if (opt.CodeGenerationTarget != CodeGenerationTarget.JavaInterop1) {
// Only the experimental format is marked: the absence of the attribute means
// JavaPeerCallbackFormatAttribute.ConnectorDelegates, so existing bindings and
// existing consumers are unaffected.
if (opt.UseUnmanagedCallersOnlyCallbacks) {
sw.WriteLine ("[assembly:global::Java.Interop.JavaPeerCallbackFormat (global::Java.Interop.JavaPeerCallbackFormatAttribute.UnmanagedCallersOnlyCallbacks)]");
sw.WriteLine ();
}

foreach (var p in mappings) {
sw.WriteLine ($"[assembly:global::Android.Runtime.NamespaceMapping (Java = \"{p.Key}\", Managed=\"{p.Value}\")]");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public BoundAbstractProperty (GenBase gen, Property property, CodeGenerationOpti

SourceWriterExtensions.AddSupportedOSPlatform (GetterAttributes, property.Getter, opt);

GetterAttributes.Add (new RegisterAttr (property.Getter.JavaName, property.Getter.JniSignature, property.Getter.GetConnectorNameFull (opt), additionalProperties: property.Getter.AdditionalAttributeString ()) {
GetterAttributes.Add (new RegisterAttr (property.Getter.JavaName, property.Getter.JniSignature, UnmanagedCallbackSupport.GetPropertyConnectorNameFull (gen, property, property.Getter, opt), additionalProperties: property.Getter.AdditionalAttributeString ()) {
MemberType = opt.CodeGenerationTarget != CodeGenerationTarget.JavaInterop1 ? null : (MemberTypes?) MemberTypes.Method,
});

Expand All @@ -63,7 +63,7 @@ public BoundAbstractProperty (GenBase gen, Property property, CodeGenerationOpti
SourceWriterExtensions.AddSupportedOSPlatform (SetterAttributes, property.Setter, opt);

SourceWriterExtensions.AddMethodCustomAttributes (SetterAttributes, property.Setter);
SetterAttributes.Add (new RegisterAttr (property.Setter.JavaName, property.Setter.JniSignature, property.Setter.GetConnectorNameFull (opt), additionalProperties: property.Setter.AdditionalAttributeString ()) {
SetterAttributes.Add (new RegisterAttr (property.Setter.JavaName, property.Setter.JniSignature, UnmanagedCallbackSupport.GetPropertyConnectorNameFull (gen, property, property.Setter, opt), additionalProperties: property.Setter.AdditionalAttributeString ()) {
MemberType = opt.CodeGenerationTarget != CodeGenerationTarget.JavaInterop1 ? null : (MemberTypes?) MemberTypes.Method,
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public BoundInterface (InterfaceGen iface, CodeGenerationOptions opt, CodeGenera

UsePriorityOrder = true;

// Renaming happens up front, before any member is written, so that every writer -- and
// in particular the callback name allocator, which snapshots a type's members the first
// time it is asked about one of them -- observes the final managed names.
FixupInvokerMethodNames (iface);

SetVisibility (iface.Visibility);

iface.JavadocInfo?.AddJavadocs (Comments);
Expand Down Expand Up @@ -223,13 +228,20 @@ void AddProperties (InterfaceGen iface, CodeGenerationOptions opt)
}
}

void AddMethods (InterfaceGen iface, CodeGenerationOptions opt)
// A method whose managed name would collide with the interface itself or with one of its
// properties is prefixed with "Invoke".
static void FixupInvokerMethodNames (InterfaceGen iface)
{
foreach (var m in iface.Methods.Where (m => !m.IsStatic && !m.IsInterfaceDefaultMethod)) {
if (m.Name == iface.Name || iface.ContainsProperty (m.Name, true))
m.Name = "Invoke" + m.Name;
}
}

Methods.Add (new BoundInterfaceMethodDeclaration (m, iface.AssemblyQualifiedName + "Invoker", opt));
void AddMethods (InterfaceGen iface, CodeGenerationOptions opt)
{
foreach (var m in iface.Methods.Where (m => !m.IsStatic && !m.IsInterfaceDefaultMethod)) {
Methods.Add (new BoundInterfaceMethodDeclaration (iface, m, iface.AssemblyQualifiedName + "Invoker", opt));
}

if (!opt.SupportDefaultInterfaceMethods)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public class BoundInterfaceMethodDeclaration : MethodWriter
readonly Method method;
readonly CodeGenerationOptions opt;

public BoundInterfaceMethodDeclaration (Method method, string adapter, CodeGenerationOptions opt)
public BoundInterfaceMethodDeclaration (GenBase iface, Method method, string adapter, CodeGenerationOptions opt)
{
this.method = method;
this.opt = opt;
Expand Down Expand Up @@ -44,7 +44,7 @@ public BoundInterfaceMethodDeclaration (Method method, string adapter, CodeGener

SourceWriterExtensions.AddSupportedOSPlatform (Attributes, method, opt);

Attributes.Add (new RegisterAttr (method.JavaName, method.JniSignature, method.ConnectorName + ":" + method.GetAdapterName (opt, adapter), additionalProperties: method.AdditionalAttributeString ()) {
Attributes.Add (new RegisterAttr (method.JavaName, method.JniSignature, UnmanagedCallbackSupport.GetConnectorName (iface, method, opt) + ":" + method.GetAdapterName (opt, adapter), additionalProperties: method.AdditionalAttributeString ()) {
MemberType = opt.CodeGenerationTarget != CodeGenerationTarget.JavaInterop1 ? null : (MemberTypes?) MemberTypes.Method,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public BoundInterfacePropertyDeclaration (GenBase gen, Property property, string

SourceWriterExtensions.AddSupportedOSPlatform (GetterAttributes, property.Getter, opt);

GetterAttributes.Add (new RegisterAttr (property.Getter.JavaName, property.Getter.JniSignature, property.Getter.ConnectorName + ":" + property.Getter.GetAdapterName (opt, adapter), additionalProperties: property.Getter.AdditionalAttributeString ()) {
GetterAttributes.Add (new RegisterAttr (property.Getter.JavaName, property.Getter.JniSignature, UnmanagedCallbackSupport.GetConnectorName (gen, property.Getter, opt) + ":" + property.Getter.GetAdapterName (opt, adapter), additionalProperties: property.Getter.AdditionalAttributeString ()) {
MemberType = opt.CodeGenerationTarget != CodeGenerationTarget.JavaInterop1 ? null : (MemberTypes?) MemberTypes.Method,
});
}
Expand All @@ -50,7 +50,7 @@ public BoundInterfacePropertyDeclaration (GenBase gen, Property property, string

SourceWriterExtensions.AddSupportedOSPlatform (SetterAttributes, property.Setter, opt);

SetterAttributes.Add (new RegisterAttr (property.Setter.JavaName, property.Setter.JniSignature, property.Setter.ConnectorName + ":" + property.Setter.GetAdapterName (opt, adapter), additionalProperties: property.Setter.AdditionalAttributeString ()) {
SetterAttributes.Add (new RegisterAttr (property.Setter.JavaName, property.Setter.JniSignature, UnmanagedCallbackSupport.GetConnectorName (gen, property.Setter, opt) + ":" + property.Setter.GetAdapterName (opt, adapter), additionalProperties: property.Setter.AdditionalAttributeString ()) {
MemberType = opt.CodeGenerationTarget != CodeGenerationTarget.JavaInterop1 ? null : (MemberTypes?) MemberTypes.Method,
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ public BoundMethod (GenBase type, Method method, CodeGenerationOptions opt, bool

SourceWriterExtensions.AddSupportedOSPlatform (Attributes, method, opt);

Attributes.Add (new RegisterAttr (method.JavaName, method.JniSignature, method.IsVirtual ? method.GetConnectorNameFull (opt) : string.Empty, additionalProperties: method.AdditionalAttributeString ()) {
Attributes.Add (new RegisterAttr (method.JavaName, method.JniSignature, method.IsVirtual ? UnmanagedCallbackSupport.GetConnectorNameFull (type, method, opt) : string.Empty, additionalProperties: method.AdditionalAttributeString ()) {
MemberType = opt.CodeGenerationTarget != CodeGenerationTarget.JavaInterop1 ? null : (MemberTypes?) MemberTypes.Method,
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public BoundMethodAbstractDeclaration (GenBase gen, Method method, CodeGeneratio
SourceWriterExtensions.AddSupportedOSPlatform (Attributes, method, opt);

if (opt.CodeGenerationTarget != CodeGenerationTarget.JavaInterop1) {
Attributes.Add (new RegisterAttr (method.JavaName, method.JniSignature, method.ConnectorName, additionalProperties: method.AdditionalAttributeString ()));
Attributes.Add (new RegisterAttr (method.JavaName, method.JniSignature, UnmanagedCallbackSupport.GetConnectorName (impl, method, opt), additionalProperties: method.AdditionalAttributeString ()));
}

SourceWriterExtensions.AddMethodCustomAttributes (Attributes, method);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public BoundProperty (GenBase gen, Property property, CodeGenerationOptions opt,
GetterComments.Add ($"// Metadata.xml XPath method reference: path=\"{gen.MetadataXPathReference}/method[@name='{property.Getter.JavaName}'{property.Getter.Parameters.GetMethodXPathPredicate ()}]\"");

if (opt.CodeGenerationTarget != CodeGenerationTarget.JavaInterop1) {
GetterAttributes.Add (new RegisterAttr (property.Getter.JavaName, property.Getter.JniSignature, property.Getter.IsVirtual ? property.Getter.GetConnectorNameFull (opt) : string.Empty, additionalProperties: property.Getter.AdditionalAttributeString ()));
GetterAttributes.Add (new RegisterAttr (property.Getter.JavaName, property.Getter.JniSignature, property.Getter.IsVirtual ? UnmanagedCallbackSupport.GetPropertyConnectorNameFull (gen, property, property.Getter, opt) : string.Empty, additionalProperties: property.Getter.AdditionalAttributeString ()));
}

SourceWriterExtensions.AddMethodBody (GetBody, property.Getter, opt);
Expand All @@ -112,7 +112,7 @@ public BoundProperty (GenBase gen, Property property, CodeGenerationOptions opt,

SourceWriterExtensions.AddMethodCustomAttributes (SetterAttributes, property.Setter);
if (opt.CodeGenerationTarget != CodeGenerationTarget.JavaInterop1) {
SetterAttributes.Add (new RegisterAttr (property.Setter.JavaName, property.Setter.JniSignature, property.Setter.IsVirtual ? property.Setter.GetConnectorNameFull (opt) : string.Empty, additionalProperties: property.Setter.AdditionalAttributeString ()));
SetterAttributes.Add (new RegisterAttr (property.Setter.JavaName, property.Setter.JniSignature, property.Setter.IsVirtual ? UnmanagedCallbackSupport.GetPropertyConnectorNameFull (gen, property, property.Setter, opt) : string.Empty, additionalProperties: property.Setter.AdditionalAttributeString ()));
}

var pname = property.Setter.Parameters [0].Name;
Expand Down
Loading
Loading