예제 #1
0
        static JavaTypeReference JavaTypeNameToReference(this JavaApi api, JavaTypeName tn, params JavaTypeParameters?[] contextTypeParameters)
        {
            var tp = contextTypeParameters.Where(tps => tps != null)
                     .SelectMany(tps => tps !.TypeParameters)
                     .FirstOrDefault(xp => xp.Name == tn.DottedName);

            if (tp != null)
            {
                return(new JavaTypeReference(tp, tn.ArrayPart));
            }
            if (tn.DottedName == JavaTypeReference.GenericWildcard.SpecialName)
            {
                return(new JavaTypeReference(tn.BoundsType, tn.GenericConstraints?.Select(gc => JavaTypeNameToReference(api, gc, contextTypeParameters)), tn.ArrayPart));
            }
            var primitive = JavaTypeReference.GetSpecialType(tn.DottedName);

            if (primitive != null)
            {
                return(tn.ArrayPart == null && tn.GenericConstraints == null ? primitive : new JavaTypeReference(primitive, tn.ArrayPart, tn.BoundsType, tn.GenericConstraints?.Select(gc => JavaTypeNameToReference(api, gc, contextTypeParameters))));
            }
            var type = api.FindNonGenericType(tn.FullNameNonGeneric);

            return(new JavaTypeReference(type,
                                         tn.GenericArguments != null ? tn.GenericArguments.Select(_ => api.JavaTypeNameToReference(_, contextTypeParameters)).ToArray() : null,
                                         tn.ArrayPart));
        }
 public static void MarkOverrides(this JavaApi api, HashSet <JavaClass> doneList)
 {
     foreach (var kls in api.Packages.SelectMany(p => p.Types).OfType <JavaClass> ())
     {
         kls.MarkOverrides(doneList);
     }
 }
예제 #3
0
 public static void FindDefects(this JavaApi api)
 {
     foreach (var type in api.Packages.SelectMany(p => p.Types).Where(t => !t.IsReferenceOnly))
     {
         type.FindDefects();
     }
 }
        public static JavaType FindNonGenericType(this JavaApi api, string?name)
        {
            var ret = FindPackages(api, name ?? "")
                      .SelectMany(p => p.Types)
                      .FirstOrDefault(t => name == (t.Parent?.Name != null ? t.Parent.Name + "." : "") + t.Name);

            if (ret == null)
            {
                ret = ManagedType.DummyManagedPackages
                      .SelectMany(p => p.Types)
                      .FirstOrDefault(t => t.FullName == name);
            }
            if (ret == null)
            {
                // We moved this type to "mono.android.app.IntentService" which makes this
                // type resolution fail if a user tries to reference it in Java.
                if (name == "android.app.IntentService")
                {
                    return(FindNonGenericType(api, "mono.android.app.IntentService"));
                }

                throw new JavaTypeResolutionException(string.Format("Type '{0}' was not found.", name));
            }

            return(ret);
        }
        public static void LoadReferences(this JavaApi api, GenBase [] gens)
        {
            JavaPackage pkg = null;

            foreach (var gen in gens.Where(_ => _.IsAcw))
            {
                pkg = api.Packages.FirstOrDefault(_ => _.Name == gen.PackageName);
                if (pkg == null)
                {
                    pkg = new JavaPackage(api)
                    {
                        Name = gen.PackageName
                    };
                    api.Packages.Add(pkg);
                }
                if (gen is InterfaceGen)
                {
                    var iface = new JavaInterface(pkg);
                    pkg.Types.Add(iface);
                    iface.Load(gen);
                }
                else if (gen is ClassGen)
                {
                    var kls = new JavaClass(pkg);
                    pkg.Types.Add(kls);
                    kls.Load(gen);
                }
                else
                {
                    throw new InvalidOperationException();
                }
            }
        }
 public static void WriteParameterNamesXml(this JavaApi api, string file)
 {
     using (var xw = XmlWriter.Create(file, new XmlWriterSettings {
         Indent = true
     }))
         WriteParameterNamesXml(api, xw);
 }
예제 #7
0
        public void Process(string inputXmlFile, GenBase [] gens, string outputXmlFile, int reportVerbosity)
        {
            switch (reportVerbosity)
            {
            case 0:
                break;

            case 1:
                Log.Verbosity = Log.LoggingLevel.Error;
                break;

            case 2:
                Log.Verbosity = Log.LoggingLevel.Warning;
                break;

            default:
                Log.Verbosity = Log.LoggingLevel.Debug;
                break;
            }
            var api = new JavaApi();

            api.LoadReferences(gens);
            api.Load(inputXmlFile);
            api.StripNonBindables();
            api.Resolve();
            api.CreateGenericInheritanceMapping();
            api.MarkOverrides();
            api.FindDefects();
            api.Save(outputXmlFile);
        }
 public static void CreateGenericInheritanceMapping(this JavaApi api)
 {
     foreach (var kls in api.Packages.SelectMany(p => p.Types).OfType <JavaClass> ())
     {
         kls.PrepareGenericInheritanceMapping();
     }
 }
예제 #9
0
 public static void Resolve(this JavaApi api)
 {
     while (true)
     {
         bool errors = false;
         foreach (var t in api.AllPackages.SelectMany(p => p.AllTypes).OfType <JavaClass> ().ToArray())
         {
             try {
                 t.Resolve();
             }
             catch (JavaTypeResolutionException ex) {
                 Log.LogError("Error while processing type '{0}': {1}", t, ex.Message);
                 errors = true;
                 t.Parent?.RemoveType(t);
             }
         }
         foreach (var t in api.AllPackages.SelectMany(p => p.AllTypes).OfType <JavaInterface> ().ToArray())
         {
             try {
                 t.Resolve();
             } catch (JavaTypeResolutionException ex) {
                 Log.LogError("Error while processing type '{0}': {1}", t, ex.Message);
                 errors = true;
                 t.Parent?.RemoveType(t);
             }
         }
         if (!errors)
         {
             break;
         }
     }
 }
        public static void Save(this JavaApi api, XmlWriter writer)
        {
            writer.WriteStartElement("api");

            foreach (var pkg in api.Packages)
            {
                if (!pkg.Types.Any(t => !t.IsReferenceOnly))
                {
                    continue;
                }
                writer.WriteStartElement("package");
                writer.WriteAttributeString("name", pkg.Name);
                foreach (var type in pkg.Types)
                {
                    if (type.IsReferenceOnly)
                    {
                        continue;                         // skip reference only types
                    }
                    if (type is JavaClass)
                    {
                        ((JavaClass)type).Save(writer);
                    }
                    else
                    {
                        ((JavaInterface)type).Save(writer);
                    }
                }
                writer.WriteFullEndElement();
            }
            writer.WriteFullEndElement();
        }
예제 #11
0
 public static void Save(this JavaApi api, string xmlfile)
 {
     using (var writer = XmlWriter.Create(xmlfile, new XmlWriterSettings()
     {
         Encoding = new UTF8Encoding(false, true),
         Indent = true,
         OmitXmlDeclaration = true,
     }))
         api.Save(writer);
 }
예제 #12
0
        public void Process(string inputXmlFile, GenBase [] gens, string outputXmlFile)
        {
            var api = new JavaApi();

            api.LoadReferences(gens);
            api.Load(inputXmlFile);
            api.Resolve();
            api.CreateGenericInheritanceMapping();
            api.MarkOverrides();
            api.FindDefects();
            api.Save(outputXmlFile);
        }
예제 #13
0
        public static JavaType FindNonGenericType(this JavaApi api, string name)
        {
            var ret = api.Packages
                      .SelectMany(p => p.Types)
                      .FirstOrDefault(t => name.StartsWith(t.Parent.Name, StringComparison.Ordinal) && name == t.Parent.Name + '.' + t.Name);

            if (ret == null)
            {
                throw new JavaTypeResolutionException(string.Format("Type '{0}' was not found.", name));
            }

            return(ret);
        }
 static void Resolve(this JavaTypeParameters tp, JavaApi api, params JavaTypeParameters [] additionalTypeParameters)
 {
     foreach (var t in tp.TypeParameters)
     {
         if (t.GenericConstraints != null)
         {
             foreach (var g in t.GenericConstraints.GenericConstraints)
             {
                 try { g.ResolvedType = api.Parse(g.Type, additionalTypeParameters); } catch (JavaTypeResolutionException ex) { Log.LogWarning("Warning: failed to resolve generic constraint: '{0}': {1}", g.Type, ex.Message); }
             }
         }
     }
 }
예제 #15
0
        public static void Main(string [] args)
        {
            var inputXmlFile  = args [0];
            var outputXmlFile = args [1];

            var api = new JavaApi();

            api.Load(inputXmlFile);
            api.Resolve();
            api.CreateGenericInheritanceMapping();
            api.MarkOverrides();
            api.FindDefects();
            api.Save(outputXmlFile);
        }
예제 #16
0
        public static void StripNonBindables(this JavaApi api)
        {
            var invalids = new List <JavaMember> ();

            foreach (var member in api.AllPackages.SelectMany(p => p.AllTypes)
                     .SelectMany(t => t.Members).Where(m => m.Name != null && m.Name.Contains('$')))
            {
                invalids.Add(member);
            }
            foreach (var invalid in invalids)
            {
                invalid.Parent?.Members.Remove(invalid);
            }
        }
        static IEnumerable <JavaPackage> FindPackages(JavaApi api, string name)
        {
            // Given a type name like "java.lang.Object", return packages that could
            // possibly contain the type so we don't search all packages, ie:
            // - java.lang
            // - java
            var package_names = new List <string> ();
            int index;

            while ((index = name.LastIndexOf('.')) >= 0)
            {
                name = name.Substring(0, index);
                package_names.Add(name);
            }

            return(api.Packages.Where(p => package_names.Contains(p.Name, StringComparer.Ordinal)).ToList());
        }
예제 #18
0
        public static JavaType FindNonGenericType(this JavaApi api, string?name)
        {
            // Given a type name like 'android.graphics.BitmapFactory.Options'
            // We're going to search for:
            // - Pkg: android.graphics.BitmapFactory  Type: Options
            // - Pkg: android.graphics                Type: BitmapFactory.Options
            // - Pkg: android                         Type: graphics.BitmapFactory.Options
            // etc.  We will short-circuit as soon as we find a match
            var index = name?.LastIndexOf('.') ?? -1;

            while (index > 0)
            {
                var ns        = name !.Substring(0, index);
                var type_name = name.Substring(index + 1);

                if (api.Packages.TryGetValue(ns, out var pkg))
                {
                    if (pkg.Types.TryGetValue(type_name, out var type))
                    {
                        return(type.First());
                    }
                }

                index = name.LastIndexOf('.', index - 1);
            }

            // See if it's purely a C# type
            var ret = ManagedType.DummyManagedPackages
                      .SelectMany(p => p.AllTypes)
                      .FirstOrDefault(t => t.FullName == name);

            if (ret == null)
            {
                // We moved this type to "mono.android.app.IntentService" which makes this
                // type resolution fail if a user tries to reference it in Java.
                if (name == "android.app.IntentService")
                {
                    return(FindNonGenericType(api, "mono.android.app.IntentService"));
                }

                throw new JavaTypeResolutionException(string.Format("Type '{0}' was not found.", name));
            }

            return(ret);
        }
        public static JavaType FindNonGenericType(this JavaApi api, string name)
        {
            var ret = FindPackages(api, name)
                      .SelectMany(p => p.Types)
                      .FirstOrDefault(t => name == t.Parent.Name + '.' + t.Name);

            if (ret == null)
            {
                ret = ManagedType.DummyManagedPackages
                      .SelectMany(p => p.Types)
                      .FirstOrDefault(t => t.FullName == name);
            }
            if (ret == null)
            {
                throw new JavaTypeResolutionException(string.Format("Type '{0}' was not found.", name));
            }
            return(ret);
        }
        public static void Load(this JavaApi api, XmlReader reader, bool isReferenceOnly)
        {
            reader.MoveToContent();
            if (reader.LocalName != "api")
            {
                throw XmlUtil.UnexpectedElementOrContent(null, reader, "api");
            }
            api.ExtendedApiSource = reader.GetAttribute("api-source");
            api.Platform          = reader.GetAttribute("platform");
            XmlUtil.CheckExtraneousAttributes("api", reader, "api-source", "platform");
            if (reader.IsEmptyElement)
            {
                reader.Read();
            }
            else
            {
                reader.Read();
                do
                {
                    reader.MoveToContent();
                    if (reader.NodeType == XmlNodeType.EndElement)
                    {
                        break;                         // </api>
                    }
                    if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "package")
                    {
                        throw XmlUtil.UnexpectedElementOrContent("api", reader, "package");
                    }

                    var name = reader.GetAttribute("name");

                    if (!api.Packages.TryGetValue(name, out var pkg))
                    {
                        pkg = new JavaPackage(api);
                        api.Packages.Add(name, pkg);
                    }

                    pkg.Load(reader, isReferenceOnly);
                } while (true);

                XmlUtil.VerifyEndElement(reader, "api");
                reader.Read();
            }
        }
예제 #21
0
 public static void Resolve(this JavaApi api)
 {
     while (true)
     {
         bool errors = false;
         foreach (var t in api.Packages.SelectMany(p => p.Types).OfType <JavaClass> ().ToArray())
         {
             try { t.Resolve(); } catch (JavaTypeResolutionException ex) { Console.Error.WriteLine(string.Format("Error while processing type '{0}': {1}", t, ex.Message)); errors = true; t.Parent.Types.Remove(t); }
         }
         foreach (var t in api.Packages.SelectMany(p => p.Types).OfType <JavaInterface> ().ToArray())
         {
             try { t.Resolve(); } catch (JavaTypeResolutionException ex) { Console.Error.WriteLine(string.Format("Error while processing type '{0}': {1}", t, ex.Message)); errors = true; t.Parent.Types.Remove(t); }
         }
         if (!errors)
         {
             break;
         }
     }
 }
예제 #22
0
        static JavaTypeReference JavaTypeNameToReference(this JavaApi api, JavaTypeName tn, params JavaTypeParameters [] contextTypeParameters)
        {
            var tp = contextTypeParameters.Where(tps => tps != null).SelectMany(tps => tps.TypeParameters).FirstOrDefault(_ => _.Name == tn.FullNameNonGeneric);

            if (tp != null)
            {
                return(new JavaTypeReference(tp, tn.ArrayPart));
            }
            var primitive = JavaTypeReference.GetSpecialType(tn.FullNameNonGeneric);

            if (primitive != null)
            {
                return(tn.ArrayPart == null ? primitive : new JavaTypeReference(primitive, tn.ArrayPart));
            }
            var type = api.FindNonGenericType(tn.FullNameNonGeneric);

            return(new JavaTypeReference(type,
                                         tn.GenericArguments != null ? tn.GenericArguments.Select(_ => api.JavaTypeNameToReference(_, contextTypeParameters)).ToArray() : null,
                                         tn.ArrayPart));
        }
        public static void Save(this JavaApi api, XmlWriter writer)
        {
            writer.WriteStartElement("api");
            if (api.Platform != null)
            {
                writer.WriteAttributeString("platform", api.Platform);
            }

            foreach (var pkg in api.AllPackages)
            {
                if (!pkg.AllTypes.Any(t => !t.IsReferenceOnly))
                {
                    continue;
                }
                writer.WriteStartElement("package");
                writer.WriteAttributeString("name", pkg.Name);
                if (!string.IsNullOrEmpty(pkg.JniName))
                {
                    writer.WriteAttributeString("jni-name", pkg.JniName);
                }
                foreach (var type in pkg.AllTypes)
                {
                    if (type.IsReferenceOnly)
                    {
                        continue;                         // skip reference only types
                    }
                    if (type is JavaClass)
                    {
                        ((JavaClass)type).Save(writer);
                    }
                    else
                    {
                        ((JavaInterface)type).Save(writer);
                    }
                }
                writer.WriteFullEndElement();
            }
            writer.WriteFullEndElement();
        }
        public static void WriteParameterNamesText(this JavaApi api, TextWriter writer)
        {
            Action <string, JavaTypeParameters> writeTypeParameters = (indent, tps) => {
                if (tps != null && tps.TypeParameters.Any())
                {
                    writer.Write($"{indent}<{string.Join (",", tps.TypeParameters.Select (p => p.Name))}>");
                }
            };

            foreach (var package in api.Packages)
            {
                writer.WriteLine();
                writer.WriteLine($"package {package.Name}");
                writer.WriteLine(";---------------------------------------");

                foreach (var type in package.Types)
                {
                    if (!type.Members.OfType <JavaMethodBase> ().Any(m => m.Parameters.Any()))
                    {
                        continue;                         // we care only about types that has any methods that have parameters.
                    }
                    writer.Write(type is JavaClass ? "  class " : "  interface ");
                    writer.Write(type.Name);
                    writeTypeParameters("", type.TypeParameters);
                    writer.WriteLine();

                    // we care only about methods that have parameters.
                    foreach (var mb in type.Members.OfType <JavaMethodBase> ().Where(m => m.Parameters.Any()))
                    {
                        writer.Write("   ");
                        writeTypeParameters(" ", mb.TypeParameters);
                        var name = mb is JavaConstructor ? "#ctor" : mb.Name;
                        // For possible generic instances in parameter type, we replace all ", " with "," to ease parsing.
                        writer.WriteLine($" {name}({string.Join (", ", mb.Parameters.Select (p => p.Type.Replace (", ", ",") + ' ' + p.Name))})");
                    }
                }
            }
        }
예제 #25
0
        public static void LoadReferences(this JavaApi api, CodeGenerationOptions opt, IEnumerable <GenBase> gens)
        {
            JavaPackage pkg = null;

            foreach (var gen in gens.Where(_ => _.IsAcw))
            {
                if (!api.Packages.TryGetValue(gen.PackageName, out pkg))
                {
                    pkg = new JavaPackage(api)
                    {
                        Name = gen.PackageName
                    };
                    api.Packages.Add(pkg.Name, pkg);
                }

                if (gen is InterfaceGen iface_gen)
                {
                    var iface = new JavaInterface(pkg);
                    iface.Load(iface_gen);

                    pkg.AddType(iface);
                }
                else if (gen is ClassGen class_gen)
                {
                    var kls = new JavaClass(pkg);
                    kls.Load(opt, class_gen);

                    pkg.AddType(kls);
                }
                else
                {
                    throw new InvalidOperationException();
                }
                api.LoadReferences(opt, gen.NestedTypes);
            }
        }
 public static void Load(this JavaApi api, string xmlfile)
 {
     using (var reader = XmlReader.Create(xmlfile))
         api.Load(reader, false);
 }
/*
 * The Text Format is:
 *
 * package {packagename}
 * ;---------------------------------------
 *   interface {interfacename}{optional_type_parameters} -or-
 *   class {classname}{optional_type_parameters}
 *     {optional_type_parameters}{methodname}({parameters})
 *
 * Anything after ; is treated as comment.
 *
 * optional_type_parameters: "" -or- "<A,B,C>" (no constraints allowed)
 * parameters: type1 p0, type2 p1 (pairs of {type} {name}, joined by ", ")
 *
 * It is with strict indentations. two spaces for types, four spaces for methods.
 *
 * Constructors are named as "#ctor".
 *
 * Commas are used by both parameter types and parameter separators,
 * but only parameter separators can be followed by a whitespace.
 * It is useful when writing text parsers for this format.
 *
 * Type names may contain whitespaces in case it is with generic constraints (e.g. "? extends FooBar"),
 * so when parsing a parameter type-name pair, the only trustworthy whitespace for tokenizing name is the *last* one.
 */

        public static void WriteParameterNamesText(this JavaApi api, string file)
        {
            using (var sw = new StreamWriter(file))
                WriteParameterNamesText(api, sw);
        }
 public static void MarkOverrides(this JavaApi api)
 {
     api.MarkOverrides(new HashSet <JavaClass> ());
 }
예제 #29
0
        public JavaPackage(JavaApi parent)
        {
            Parent = parent;

            Types = new List <JavaType> ();
        }
        public static void WriteParameterNamesXml(this JavaApi api, XmlWriter writer)
        {
            writer.WriteStartElement("parameter-names");

            Action <JavaTypeParameters> writeTypeParameters = tps => {
                if (tps != null && tps.TypeParameters.Any())
                {
                    writer.WriteStartElement("type-parameters");
                    foreach (var gt in tps.TypeParameters)
                    {
                        writer.WriteStartElement("type-parameter");
                        writer.WriteAttributeString("name", gt.Name);
                        // no need to supply constraints.
                        writer.WriteEndElement();
                    }
                    writer.WriteEndElement();
                }
            };

            foreach (var package in api.Packages)
            {
                writer.WriteStartElement("package");
                writer.WriteAttributeString("name", package.Name);

                foreach (var type in package.Types)
                {
                    if (!type.Members.OfType <JavaMethodBase> ().Any(m => m.Parameters.Any()))
                    {
                        continue;                         // we care only about types that has any methods that have parameters.
                    }
                    writer.WriteStartElement(type is JavaClass ? "class" : "interface");
                    writer.WriteAttributeString("name", type.Name);

                    writeTypeParameters(type.TypeParameters);

                    // we care only about methods that have parameters.
                    foreach (var mb in type.Members.OfType <JavaMethodBase> ().Where(m => m.Parameters.Any()))
                    {
                        if (mb is JavaConstructor)
                        {
                            writer.WriteStartElement("constructor");
                        }
                        else
                        {
                            writer.WriteStartElement("method");
                            writer.WriteAttributeString("name", mb.Name);
                        }

                        writeTypeParameters(mb.TypeParameters);

                        foreach (var para in mb.Parameters)
                        {
                            writer.WriteStartElement("parameter");
                            // For possible generic instances in parameter type, we replace all ", " with "," to ease parsing.
                            writer.WriteAttributeString("type", para.Type.Replace(", ", ","));
                            writer.WriteAttributeString("name", para.Name);
                            writer.WriteEndElement();
                        }

                        writer.WriteEndElement();
                    }

                    writer.WriteEndElement();
                }

                writer.WriteEndElement();
            }

            writer.WriteEndElement();
        }