public string ToFullJavaName(TypeName javaType) { string java = javaType.ToJavaString (); string suffix = javaType.ArrayDimension > 0 ? " []" : ""; java = javaType.ArrayDimension > 0 ? java.Substring (0, java.Length - 3) : java; if (IsSupportedPrimitiveJavaType (java)) return java; foreach (var imp in unit.Imports) { int idx = java.IndexOf ('.'); string head = idx < 0 ? java : java.Substring (0, idx); if (imp.Identifiers.Length > 0 && head == imp.Identifiers.Last ()) return imp.ToJavaString () + (idx < 0 ? "" : java.Substring (idx)) + suffix; } // FIXME: implement lookup with wildcard import // not found. return (unit.Package != null ? unit.Package.ToJavaString () + '.' : null) + java + suffix; }
// java name could be ns-less, or even partial ("import foo.Bar;" + "Bar.Baz" => "foo.Bar.Baz") public string ToCSharp(TypeName javaType) { string java = javaType.ToJavaString (); string suffix = javaType.ArrayDimension > 0 ? " []" : ""; java = javaType.ArrayDimension > 0 ? java.Substring (0, java.Length - 3) : java; string cs; Func<string,string> filter = (ret) => ret == "sbyte []" ? "byte []" : ret; if (cache.TryGetValue (java, out cs)) return filter (cs + suffix); if (IsSupportedPrimitiveJavaType (java)) return filter ((java == "boolean" ? "bool" : java == "byte" ? "sbyte" : java) + suffix); var javaFullName = ToFullJavaName (javaType); javaFullName = javaFullName.Substring (0, javaFullName.Length - suffix.Length); if (database.RegisteredTypes.TryGetValue (javaFullName, out cs)) { //Console.WriteLine ("Found in lookup " + javaFullName + " / " + cs); cache [java] = cs; return filter (cs + suffix); } var p = parcelable_names.FirstOrDefault (pp => pp.ToJavaString () == javaFullName); if (p != null) { var decentNS = GetCSharpNamespace (p); var stupidNS = p.GetNamespace (); cache [java] = cs = (stupidNS != decentNS ? p.ToString ().Replace (stupidNS, decentNS) : p.ToString ()); //Console.WriteLine ("Found in parcelable lookup " + java + " / " + cs); return filter (cs + suffix); } string csns = javaFullName != java ? GetCSharpNamespace (javaType) : String.Empty; cache [java] = cs = csns + (string.IsNullOrEmpty (csns) ? "" : ".") + javaType.Identifiers.Last (); //Console.WriteLine ("NOT Found in lookup " + java + " / " + cs); return filter (cs + suffix); }
public string ToCSharpNamespace(TypeName package) { string dummy, javapkg = package != null ? package.ToJavaString () : String.Empty; return package == null ? String.Empty : database.NamespaceMappings.TryGetValue (javapkg, out dummy) ? dummy : package.ToString (); }
public string GetCSharpNamespace(TypeName name) { string dummy, javapkg = name != null ? name.GetPackage () : String.Empty; return database.NamespaceMappings.TryGetValue (javapkg, out dummy) ? dummy : name.GetNamespace (); }
public bool IsParcelable(TypeName type) { var jn = ToFullJavaName (type); jn = type.ArrayDimension > 0 ? jn.Substring (0, jn.Length - 3) : jn; foreach (var p in parcelable_names) if (p.ToJavaString () == jn) return true; return false; }
string GetReadStatements(TypeName type, string parcel, string arg) { string csname = name_cache.ToCSharp (type); switch (csname) { case "String []": return String.Format ("{1}.ReadStringArray ({0});", arg, parcel); case "bool []": return String.Format ("{1}.ReadBooleanArray ({0});", arg, parcel); // FIXME: I'm not sure if aidl should support byte... case "byte []": return String.Format ("{1}.ReadByteArray ({0});", arg, parcel); case "char []": return String.Format ("{1}.ReadCharArray ({0});", arg, parcel); case "int []": return String.Format ("{1}.ReadIntArray ({0});", arg, parcel); case "long []": return String.Format ("{1}.ReadLongArray ({0});", arg, parcel); case "float []": return String.Format ("{1}.ReadFloatArray ({0});", arg, parcel); case "double []": return String.Format ("{1}.ReadDoubleArray ({0});", arg, parcel); case "Android.OS.IParcelable": return String.Format ("{0} = {1}.ReadInt () != 0 ? ({2}) global::Android.OS.Bundle.Creator.CreateFromParcel ({1}) : null;", arg, parcel, ToOutputTypeName (csname)); // FIXME: are JavaList for List and JavaDictionary for Map always appropriate? case "List": case "Android.Runtime.JavaList": if (type.GenericArguments != null) { switch (name_cache.ToCSharp (type.GenericArguments.First ())) { case "String": case "Java.Lang.ICharSequence": return String.Format ("{1}.ReadStringList ((global::System.Collections.Generic.IList<string>) {0});", arg, parcel); case "Android.OS.IBinder": return String.Format ("{1}.ReadBinderList ((global::System.Collections.Generic.IList<global::Android.OS.IBinder>) {0});", arg, parcel); default: return String.Format ("{1}.ReadTypedList ({0}, {2}.Creator);", arg, parcel, ToOutputTypeName (name_cache.ToCSharp (type.GenericArguments [0]))); } } return String.Format ("{0} = {1}.ReadList ();", arg, parcel); case "Map": case "Android.Runtime.JavaDictionary": return String.Format ("{0} = {1}.ReadMap ();", arg, parcel); case "Android.OS.IBinder": return String.Format ("{0} = {1}.ReadStrongBinder ();", arg, parcel); case "Android.OS.IBinder []": return String.Format ("{1}.ReadBinderArray ({0});", arg, parcel); default: if (name_cache.IsParcelable (type)) { if (type.ArrayDimension > 0) // ParcelableCreator return String.Format ("{1}.ReadTypedArray ({0}, {2}.Creator);", arg, parcel, ToOutputTypeName (csname.Substring (0, csname.Length - 3))); else return String.Format ("if ({1}.ReadInt () != 0) {0}.ReadFromParcel ({1});", arg, parcel); } else if (type.ArrayDimension > 0) throw new NotSupportedException (String.Format ("AIDL does not support reading this array type: {0}", type)); else // interfaces return String.Format ("{0} = {2}Stub.AsInterface ({1}.ReadStrongBinder ());", arg, parcel, ToOutputTypeName (csname)); } }
string GetWriteStatements(TypeName type, string parcel, string arg, string parcelableWriteFlags) { string csname = name_cache.ToCSharp (type); switch (csname) { case "String": return parcel + ".WriteString (" + arg + ");"; case "String []": return parcel + ".WriteStringArray (" + arg + ");"; case "bool": return parcel + ".WriteInt (" + arg + " ? 1 : 0);"; case "bool []": return parcel + ".WriteBooleanArray (" + arg + ");"; // FIXME: I'm not sure if aidl should support byte... case "sbyte": return parcel + ".WriteByte (" + arg + ");"; case "byte []": return String.Format ("{1}.WriteByteArray ({0});", arg, parcel); case "char": return parcel + ".WriteInt ((int) " + arg + ");"; case "char []": return parcel + ".WriteCharArray (" + arg + ");"; case "int": return parcel + ".WriteInt (" + arg + ");"; case "int []": return parcel + ".WriteIntArray (" + arg + ");"; case "long": return parcel + ".WriteLong (" + arg + ");"; case "long []": return parcel + ".WriteLongArray (" + arg + ");"; case "float": return parcel + ".WriteFloat (" + arg + ");"; case "float []": return parcel + ".WriteFloatArray (" + arg + ");"; case "double": return parcel + ".WriteDouble (" + arg + ");"; case "double []": return parcel + ".WriteDoubleArray (" + arg + ");"; // FIXME: are JavaList for List and JavaDictionary for Map always appropriate? case "List": case "Android.Runtime.JavaList": if (type.GenericArguments != null) { switch (name_cache.ToCSharp (type.GenericArguments.First ())) { case "String": case "Java.Lang.ICharSequence": return String.Format ("{1}.WriteStringList ((global::System.Collections.Generic.IList<string>) {0});", arg, parcel); case "Android.OS.IBinder": return String.Format ("{1}.WriteBinderList ((global::System.Collections.Generic.IList<global::Android.OS.IBinder>) {0});", arg, parcel); default: return String.Format ("{1}.WriteTypedList ({0});", arg, parcel, ToOutputTypeName (name_cache.ToCSharp (type.GenericArguments [0]))); } } return String.Format ("{1}.WriteList ({0});", arg, parcel); case "Map": case "Android.Runtime.JavaDictionary": return String.Format ("{1}.WriteMap ({0});", arg, parcel); case "Android.OS.Bundle": case "Android.OS.IParcelable": return String.Format ("if ({0} != null) {{ {1}.WriteInt (1); {0}.WriteToParcel ({1}, {2}); }} else {1}.WriteInt (0);", arg, parcel, parcelableWriteFlags); case "Android.OS.IBinder": return String.Format ("{1}.WriteStrongBinder ({0});", arg, parcel); case "Android.OS.IBinder []": return String.Format ("{1}.WriteBinderArray ({0});", arg, parcel); case "Java.Lang.ICharSequence": return String.Format ("if ({0} != null) {{ {1}.WriteInt (1); global::Android.Text.TextUtils.WriteToParcel ({0}, {1}, {2}); }} else {1}.WriteInt (0);", arg, parcel, parcelableWriteFlags); default: // interfaces if (name_cache.IsParcelable (type)) { if (type.ArrayDimension > 0) return String.Format ("{1}.WriteTypedArray ({0}, {2});", arg, parcel, parcelableWriteFlags); else return String.Format ("if ({0} != null) {{ {1}.WriteInt (1); {0}.WriteToParcel ({1}, {2}); }} else {1}.WriteInt (0);", arg, parcel, parcelableWriteFlags); } else if (type.ArrayDimension > 0) throw new NotSupportedException (String.Format ("AIDL does not support writing this array type: {0}", type)); else return String.Format ("{1}.WriteStrongBinder (((({0} != null)) ? ({0}.AsBinder ()) : (null)));", arg, parcel); } }
string GetCreateStatements(TypeName type, string parcel, string arg) { string csname = name_cache.ToCSharp (type); switch (csname) { case "String": return String.Format ("{0} = {1}.ReadString ();", arg, parcel); case "String []": return String.Format ("{0} = {1}.CreateStringArray (); {1}.ReadStringArray ({0});", arg, parcel); case "bool": return String.Format ("{0} = {1}.ReadInt () != 0;", arg, parcel); case "bool []": return String.Format ("{0} = {1}.CreateBooleanArray (); {1}.ReadBooleanArray ({0});", arg, parcel); // FIXME: I'm not sure if aidl should support byte... case "sbyte": return String.Format ("{0} = {1}.ReadByte ();", arg, parcel); case "byte []": return String.Format ("{0} = {1}.CreateByteArray (); {1}.ReadByteArray ({0});", arg, parcel); case "char": return String.Format ("{0} = (char) {1}.ReadInt ();", arg, parcel); case "char []": return String.Format ("{0} = {1}.CreateCharArray (); {1}.ReadCharArray ({0});", arg, parcel); case "int": return String.Format ("{0} = {1}.ReadInt ();", arg, parcel); case "int []": return String.Format ("{0} = {1}.CreateIntArray (); {1}.ReadIntArray ({0});", arg, parcel); case "long": return String.Format ("{0} = {1}.ReadLong ();", arg, parcel); case "long []": return String.Format ("{0} = {1}.CreateLongArray (); {1}.ReadLongArray ({0});", arg, parcel); case "float": return String.Format ("{0} = {1}.ReadFloat ();", arg, parcel); case "float []": return String.Format ("{0} = {1}.CreateFloatArray (); {1}.ReadFloatArray ({0});", arg, parcel); case "double": return String.Format ("{0} = {1}.ReadDouble ();", arg, parcel); case "double []": return String.Format ("{0} = {1}.CreateDoubleArray (); {1}.ReadDoubleArray ({0});", arg, parcel); // FIXME: are JavaList for List and JavaDictionary for Map always appropriate? case "List": case "Android.Runtime.JavaList": if (type.GenericArguments != null) { switch (name_cache.ToCSharp (type.GenericArguments.First ())) { case "String": case "Java.Lang.ICharSequence": return String.Format ("{0} = (global::Android.Runtime.JavaList) {1}.CreateStringArrayList ();", arg, parcel); case "Android.OS.IBinder": return String.Format ("{0} = (global::Android.Runtime.JavaList) {1}.CreateBinderArrayList ();", arg, parcel); default: return String.Format ("{0} = (global::Android.Runtime.JavaList) {1}.CreateTypedArrayList ({2}.Creator);", arg, parcel, ToOutputTypeName (name_cache.ToCSharp (type.GenericArguments [0]))); } } return String.Format ("{0} = (global::Android.Runtime.JavaList) {1}.ReadArrayList ((global::Java.Lang.ClassLoader) null);", arg, parcel); case "Map": case "Android.Runtime.JavaDictionary": return String.Format ("{0} = {1}.ReadHashMap ();", arg, parcel); case "Android.OS.IParcelable": return String.Format ("{0} = {1}.ReadInt () != 0 ? ({2}) global::Android.OS.Bundle.Creator.CreateFromParcel ({1}) : null;", arg, parcel, ToOutputTypeName (csname)); case "Android.OS.IBinder": return String.Format ("{0} = {1}.ReadStrongBinder ();", arg, parcel); case "Android.OS.IBinder []": return String.Format ("{0} = {1}.CreateBinderArray ();", arg, parcel); case "Java.Lang.ICharSequence": return String.Format ("{0} = {1}.ReadInt () != 0 ? (global::Java.Lang.ICharSequence) global::Android.Text.TextUtils.CharSequenceCreator.CreateFromParcel ({1}) : null;", arg, parcel); default: if (name_cache.IsParcelable (type)) { if (type.ArrayDimension > 0) // ParcelableCreator return String.Format ("{0} = global::System.Array.ConvertAll<global::Java.Lang.Object,{2}> ({1}.CreateTypedArray ({2}.Creator), __input => ({2}) __input);", arg, parcel, ToOutputTypeName (csname.Substring (0, csname.Length - 3))); else return String.Format ("{0} = {1}.ReadInt () != 0 ? ({2}) global::Android.OS.Bundle.Creator.CreateFromParcel ({1}) : null;", arg, parcel, ToOutputTypeName (csname)); } else if (type.ArrayDimension > 0) throw new NotSupportedException (String.Format ("AIDL does not support creating this array type: {0}", type)); else // interfaces return String.Format ("{0} = {2}Stub.AsInterface ({1}.ReadStrongBinder ());", arg, parcel, ToOutputTypeName (csname)); } }
// FIXME: should this be used? string GetCreatorName(TypeName type) { string csname = name_cache.ToCSharp (type); switch (csname) { case "String": case "Java.Lang.ICharSequence": return "Android.OS.Parcel.StringCreator"; case "List": case "Android.Runtime.JavaList": return "Android.OS.Parcel.ArrayListCreator"; default: if (name_cache.IsParcelable (type)) return csname + ".Creator"; return String.Empty; } }
public CompilationUnit(TypeName package, TypeName [] imports, ITypeDeclaration [] types) { Package = package; Imports = imports; Types = types; }
public TypeName(string [] identifiers, TypeName [] genericArguments) { if (identifiers == null) throw new ArgumentNullException ("identifiers"); if (identifiers.Any (i => i == null)) throw new ArgumentException ("'identifiers' contain one or more null values: {0}", String.Concat (identifiers)); if (genericArguments != null && genericArguments.Any (g => g == null)) throw new ArgumentException (String.Format ("With {0} elementType, 'genericArguments' contain one or more null values", String.Concat (".", identifiers))); this.Identifiers = identifiers; this.GenericArguments = genericArguments; }
public Parcelable(TypeName name) { Name = name; }
public Argument(string modifier, TypeName type, string name) { Modifier = modifier; Type = type; Name = name; }
public Method(string modifier, TypeName returnType, string name, Argument [] args) { Modifier = modifier; ReturnType = returnType; JavaName = name; Name = Util.ToPascalCase (name); Arguments = args ?? new Argument [0]; }