Skip to content
Merged
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
1 change: 1 addition & 0 deletions src/error.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
// BI1039 The selector {0} on type {1} is found multiple times with different argument length {2} : {3}.
// BI1040 The selector {0} on type {1} is found multiple times with different argument out states on argument {2}.
// BI1041 The selector {0} on type {1} is found multiple times with different argument types on argument {2} - {3} : {4}.
// BI1042 Missing '[Field (LibraryName=value)]' for {field_pi.Name} (e.g."__Internal")
// BI11xx warnings
// BI1101 Trying to use a string as a [Target]
// BI1102 Using the deprecated EventArgs for a delegate signature in {0}.{1}, please use DelegateName instead
Expand Down
5 changes: 3 additions & 2 deletions src/generator-enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using XamCore.Foundation;
using XamCore.ObjCRuntime;
Expand Down Expand Up @@ -96,8 +97,8 @@ void GenerateEnum (Type type)
library_name = library_name.Substring (ns.Prefix.Length + 1);

// there might not be any other fields in the framework
if (!libraries.Contains (library_name))
libraries.Add (library_name);
if (!libraries.ContainsKey (library_name))
libraries.Add (library_name, null);
}

if (error != null) {
Expand Down
62 changes: 51 additions & 11 deletions src/generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1485,7 +1485,7 @@ public partial class Generator : IMemberGatherer {
Dictionary<Type,TrampolineInfo> trampolines = new Dictionary<Type,TrampolineInfo> ();
Dictionary<Type,int> trampolines_generic_versions = new Dictionary<Type,int> ();
Dictionary<Type,Type> notification_event_arg_types = new Dictionary<Type,Type> ();
List <string> libraries = new List <string> ();
Dictionary<string, string> libraries = new Dictionary<string, string> (); // <LibraryName, libraryPath>

Copy link
Contributor

@mandel-macaque mandel-macaque May 5, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've got a small question about this. You are using a Tuple that contains the lib name and the lib path. Later in the code we have to use things such as:

// searching for the lib
if (!libraries.Any (l => l.Item1 == library_name)) {
    libraries.Add (new Tuple<string, string> (library_name, library_path));
}

// looping for the libs 
foreach (var library_info in libraries.OrderBy (v => v.Item1))

I'm wondering how many times (if ever) we have a LibraryName that is not unique. If that is guaranteed, that is, no library will have the same name as other, using a dictionary (the StringDictionary specialised collection) over a List <Tuple <string, string>> makes sense. Searching will be faster, we will have less linq operations (and we all know that is good ;) ) and makes things such as accessing the data cleaner removing things like:

var library_name = library_info.Item1; // Getting the info from the tuple for readability
var library_path = library_info.Item2;

List<Tuple<string, ParameterInfo[]>> async_result_types = new List<Tuple <string, ParameterInfo[]>> ();
HashSet<string> async_result_types_emitted = new HashSet<string> ();
Expand Down Expand Up @@ -3004,7 +3004,30 @@ void GenerateTrampolinesForQueue (TrampolineInfo [] queue)
print ("}} /* class {0} */", ti.NativeInvokerName);
}
}


// We need to check against the user using just UIKit (and friends) in the FieldAttribute
// so we need to reflect the libraries contained in our Constants class and do the mapping
// we will return the system library path if found
bool IsNotSystemLibrary (string library_name)
{
string library_path = null;
return TryGetLibraryPath (library_name, ref library_path);
}

bool TryGetLibraryPath (string library_name, ref string library_path)
{
var libSuffixedName = $"{library_name}Library";
var constType = typeof (
#if XAMCORE_2_0
XamCore.ObjCRuntime.Constants);
#else
XamCore.Constants);
#endif
var field = constType.GetFields (BindingFlags.Public | BindingFlags.Static).FirstOrDefault (f => f.Name == libSuffixedName);
library_path = (string) field?.GetValue (null);
return library_path == null;
}

void GenerateLibraryHandles ()
{
sw = GetOutputStream ("ObjCRuntime", "Libraries");
Expand All @@ -3013,10 +3036,14 @@ void GenerateLibraryHandles ()
print ("namespace {0} {{", ns.CoreObjCRuntime); indent++;
print ("[CompilerGenerated]");
print ("static partial class Libraries {"); indent++;
foreach (string library_name in libraries.OrderBy (v => v)) {
print ("static public class {0} {{", library_name); indent++;
foreach (var library_info in libraries.OrderBy (v => v.Key)) {
var library_name = library_info.Key;
var library_path = library_info.Value;
print ("static public class {0} {{", library_name.Replace (".", string.Empty)); indent++;
if (BindThirdPartyLibrary && library_name == "__Internal") {
print ("static public readonly IntPtr Handle = Dlfcn.dlopen (null, 0);");
} else if (BindThirdPartyLibrary && library_path != null && IsNotSystemLibrary (library_name)) {
print ($"static public readonly IntPtr Handle = Dlfcn.dlopen (\"{library_path}\", 0);");
} else {
print ("static public readonly IntPtr Handle = Dlfcn.dlopen (Constants.{0}Library, 0);", library_name);
}
Expand Down Expand Up @@ -6228,6 +6255,7 @@ public void Generate (Type type)
foreach (var field_pi in field_exports.OrderBy (f => f.Name)) {
var fieldAttr = (FieldAttribute) field_pi.GetCustomAttributes (typeof (FieldAttribute), true) [0];
string library_name;
string library_path = null;

if (fieldAttr.LibraryName != null){
// Remapped
Expand All @@ -6241,19 +6269,31 @@ public void Generate (Type type)
library_name = CoreServicesMap;
break;
}
}
} else {
// we get something in LibraryName from FieldAttribute so we asume
// it is a path to a library, so we save the path and change library name
// to a valid identifier if needed
library_path = library_name;
library_name = Path.GetFileName (library_name);
if (library_name.Contains ("."))
library_name = library_name.Replace (".", string.Empty);
}
} else if (BindThirdPartyLibrary) {
// User should provide a LibraryName
throw new BindingException (1042, true, $"Missing '[Field (LibraryName=value)]' for {field_pi.Name} (e.g.\"__Internal\")");
} else {
library_name = type.Namespace;
// note: not every binding namespace will start with ns.Prefix (e.g. MonoTouch.)
if (!String.IsNullOrEmpty (ns.Prefix) && library_name.StartsWith (ns.Prefix))
if (!String.IsNullOrEmpty (ns.Prefix) && library_name.StartsWith (ns.Prefix)) {
library_name = library_name.Substring (ns.Prefix.Length + 1);
library_name = library_name.Replace (".", string.Empty); // Remove dots from namespaces
}
}

if (!libraries.Contains (library_name)) {
libraries.Add (library_name);
}
if (!libraries.ContainsKey (library_name))
libraries.Add (library_name, library_path);

bool is_unified_internal = field_pi.IsUnifiedInternal ();

string fieldTypeName = FormatType (field_pi.DeclaringType, field_pi.PropertyType);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove extra lines to reduce diff.

// Value types we dont cache for now, to avoid Nullable<T>
if (!field_pi.PropertyType.IsValueType) {
Expand All @@ -6263,7 +6303,7 @@ public void Generate (Type type)
}

PrintPreserveAttribute (field_pi);
print ("[Field (\"{0}\", \"{1}\")]", fieldAttr.SymbolName, library_name);
print ("[Field (\"{0}\", \"{1}\")]", fieldAttr.SymbolName, library_path ?? library_name);
PrintPlatformAttributes (field_pi);
if (Generator.HasAttribute (field_pi, typeof (AdvancedAttribute))){
print ("[EditorBrowsable (EditorBrowsableState.Advanced)]");
Expand Down