Ejemplo n.º 1
0
 private static XElement N(
     string elementName, params XAttribute[] attributeList)
 => n.Element(elementName, attributeList);
Ejemplo n.º 2
0
        public static void ApplyBuiltinFixup(this XDocument document)
        {
            // add the gs namespace prefix

            document.Root.SetAttributeValue(XNamespace.Xmlns + "gs", gs.NamespaceName);

            // remove all elements marked as "skip", "moved-to" or "shadowed-by"
            // and functions/methods with varagrs. On OS X/homebrew, there are
            // aliases that end with _autoptr that need to be ignored too.

            var elementsToRemove = document.Descendants()
                                   .Where(d => d.Name != gi + "return-value" && d.Name != gi + "parameter")
                                   .Where(d => d.Attribute("skip").AsBool() ||
                                          d.Attribute("moved-to") != null ||
                                          d.Attribute("shadowed-by") != null ||
                                          d.IsCallableWithVarArgs() ||
                                          d.Attribute("name").AsString("").EndsWith("_autoptr", StringComparison.Ordinal))
                                   .ToList();

            foreach (var element in elementsToRemove)
            {
                element.Remove();
            }

            // add functions for GType getters

            var elementsWithGTypeGetter = document.Descendants()
                                          .Where(d => d.Attribute(glib + "get-type").AsString("intern") != "intern");

            foreach (var element in elementsWithGTypeGetter)
            {
                var functionElement = new XElement(
                    gi + "function",
                    new XAttribute("name", "_get_g_type"),
                    new XAttribute(c + "identifier", element.Attribute(glib + "get-type").Value),
                    new XAttribute(gs + "access-modifiers", "private"),
                    new XElement(
                        gi + "return-value",
                        new XElement(
                            gi + "type",
                            new XAttribute("name", "GType"))));
                element.Add(functionElement);
            }

            // rename all error_quark functions to get_error_quark so that they
            // become properties
            var errorQuarkElements = document.Descendants(gi + "function")
                                     .Where(d => d.Attribute("name").Value.EndsWith("error_quark", StringComparison.Ordinal));

            foreach (var element in errorQuarkElements)
            {
                if (element.Attribute("name").Value.StartsWith("get_", StringComparison.Ordinal))
                {
                    continue;
                }
                element.SetAttributeValue("name", "get_" + element.Attribute("name").Value);
            }

            // add value field to all alias elements

            var aliasElements = document.Descendants(gi + "alias");

            foreach (var element in aliasElements)
            {
                var valueFieldElement = new XElement(gi + "field",
                                                     new XAttribute("name", "value"),
                                                     new XAttribute(gs + "access-modifiers", "private"),
                                                     new XElement(element.Element(gi + "type")));
                element.Add(valueFieldElement);
            }

            // add error parameters for anything that throws

            var elementsThatThrow = document.Descendants()
                                    .Where(d => d.Attribute("throws") != null);

            foreach (var element in elementsThatThrow)
            {
                var errorElement = new XElement(gs + "error-parameter",
                                                new XAttribute("name", "error"),
                                                new XAttribute("direction", "out"),
                                                new XAttribute(gs + "managed-type", typeof(IntPtr).FullName),
                                                new XElement(gi + "doc", "return location for a #GError"),
                                                new XElement(gi + "type",
                                                             new XAttribute("name", "GLib.Error")));
                if (element.Element(gi + "parameters") == null)
                {
                    element.Add(new XElement(gi + "parameters"));
                }
                element.Element(gi + "parameters").Add(errorElement);
            }

            // create managed-name attributes

            foreach (var element in document.Descendants())
            {
                if (element.Attribute(gs + "managed-name") != null)
                {
                    continue;
                }

                if (element.Name == gi + "return-value")
                {
                    element.SetAttributeValue(gs + "managed-name", "ret");
                    continue;
                }
                var attr = element.Attribute("name");
                if (attr == null)
                {
                    continue;
                }
                var name = attr.Value;
                // replace name by shadows if it exists (i.e. drop _full suffix)
                var shadows = element.Attribute("shadows");
                if (shadows != null)
                {
                    name = shadows.Value;
                }

                // check various conditions where we might want camelCase
                var camelCase      = false;
                var accessModifier = element.Attribute(gs + "access-modifiers");
                if (accessModifier != null)
                {
                    camelCase = accessModifier.Value.Contains("private");
                }
                if (element.Name == gi + "parameter" || element.Name == gi + "instance-parameter" || element.Name == gs + "error-parameter")
                {
                    camelCase = true;
                }

                name = camelCase ? name.ToCamelCase() : name.ToPascalCase();

                // callbacks that are defined for a field tend to have name conflicts
                if (element.Name == gi + "field" && element.Element(gi + "callback") != null)
                {
                    // add "Impl" suffix to the field name
                    name += "Impl";
                }

                element.SetAttributeValue(gs + "managed-name", name);
            }

            // flag extension methods
            var elementNamesThatRequireExtensionMethods = new [] {
                gi + "enumeration",
                gi + "bitfield",
                gi + "interface",
            };
            var elementsThatRequireExtensionMethods = document.Descendants(gi + "method")
                                                      .Where(e => elementNamesThatRequireExtensionMethods.Contains(e.Parent.Name));

            foreach (var element in elementsThatRequireExtensionMethods)
            {
                element.SetAttributeValue(gs + "extension-method", "1");
            }

            // flag ref functions

            var elementsWithRefMethod = document.Descendants(gi + "method")
                                        .Where(d => d.Attribute("name").Value == "ref" &&
                                               !d.Element(gi + "parameters").Elements(gi + "parameter").Any());

            foreach (var element in elementsWithRefMethod)
            {
                element.SetAttributeValue(gs + "special-func", "ref");
                element.SetAttributeValue(gs + "access-modifiers", "public override");
                element.Element(gi + "return-value").SetAttributeValue("skip", "1");
            }

            // flag unref functions

            var elementsWithUnrefMethod = document.Descendants(gi + "method")
                                          .Where(d => d.Attribute("name").Value == "unref" &&
                                                 !d.Element(gi + "parameters").Elements(gi + "parameter").Any());

            foreach (var element in elementsWithUnrefMethod)
            {
                element.SetAttributeValue(gs + "special-func", "unref");
                element.SetAttributeValue(gs + "access-modifiers", "public override");
            }

            // flag free functions

            var elementsWithFreeMethod = document.Descendants(gi + "method")
                                         .Where(d => d.Attribute("name").Value == "free" &&
                                                !d.Element(gi + "parameters").Elements(gi + "parameter").Any());

            foreach (var element in elementsWithFreeMethod)
            {
                element.SetAttributeValue(gs + "special-func", "free");
                element.SetAttributeValue(gs + "access-modifiers", "protected override");
            }

            // flag equals functions

            var elementsWithEqualsFunction = document.Descendants(gi + "method")
                                             .Where(d => d.Attribute("name").Value == "equal" &&
                                                    d.Element(gi + "parameters").Elements(gi + "parameter").Count() == 1);

            foreach (var element in elementsWithEqualsFunction)
            {
                element.SetAttributeValue(gs + "special-func", "equal");
                element.SetAttributeValue(gs + "managed-name", "Equals");
            }

            // flag compare functions

            var elementsWithCompareFunction = document.Descendants(gi + "method")
                                              .Where(d => d.Attribute("name").Value == "compare" &&
                                                     d.Element(gi + "parameters").Elements(gi + "parameter").Count() == 1);

            foreach (var element in elementsWithCompareFunction)
            {
                element.SetAttributeValue(gs + "special-func", "compare");
                element.SetAttributeValue(gs + "managed-name", "CompareTo");
            }

            // flag hash functions

            var elementsWithHashFunction = document.Descendants(gi + "method")
                                           .Where(d => d.Attribute("name").Value == "hash" &&
                                                  !d.Element(gi + "parameters").Elements(gi + "parameter").Any() &&
                                                  d.Element(gi + "return-value").Element(gi + "type") != null &&
                                                  d.Element(gi + "return-value").Element(gi + "type").Attribute("name").Value == "guint");

            foreach (var element in elementsWithHashFunction)
            {
                element.SetAttributeValue(gs + "special-func", "hash");
                element.SetAttributeValue(gs + "access-modifiers", "public override");
                // set managed-name here so it don't get turned into a property getter
                element.SetAttributeValue(gs + "managed-name", "GetHashCode");
                // change return type to match .NET
                element.Element(gi + "return-value").Element(gi + "type").SetAttributeValue("name", "gint");
            }

            // flag to_string functions

            var elementsWithToStringFunction = document.Descendants(gi + "method")
                                               .Where(d => d.Attribute("name").Value == "to_string" &&
                                                      !d.Element(gi + "parameters").Elements(gi + "parameter").Any());

            foreach (var element in elementsWithToStringFunction)
            {
                element.SetAttributeValue(gs + "special-func", "to-string");
                element.SetAttributeValue(gs + "access-modifiers", "public override");
            }

            // flag reference-counted opaques

            var recordsThatAreRefCounted = document.Descendants(gi + "record")
                                           .Where(d => d.Elements(gi + "method").Any(m => m.Attribute(gs + "special-func").AsString() == "ref") &&
                                                  d.Elements(gi + "method").Any(m => m.Attribute(gs + "special-func").AsString() == "unref"));

            foreach (var element in recordsThatAreRefCounted)
            {
                element.SetAttributeValue(gs + "opaque", "ref-counted");
            }

            // flag owned opaques

            var recordsThatAreOwned = document.Descendants(gi + "record")
                                      .Where(d => d.Elements(gi + "method").Any(m => m.Attribute(gs + "special-func").AsString() == "free"));

            foreach (var element in recordsThatAreOwned)
            {
                element.SetAttributeValue(gs + "opaque", "owned");
            }

            // flag static opaques

            var recordsThatAreStatic = document.Descendants(gi + "record")
                                       .Where(d => d.Elements(gi + "constructor").Any(c => c.Attribute("name").AsString() == "new" &&
                                                                                      c.Element(gi + "return-value").Attribute("transfer-ownership").AsString() == "none"));

            foreach (var element in recordsThatAreStatic)
            {
                element.SetAttributeValue(gs + "opaque", "static");
            }

            // flag gtype-struct opaques

            var recordsThatAreGTypeStructs = document.Descendants(gi + "record")
                                             .Where(d => d.Attribute(glib + "is-gtype-struct-for") != null);

            foreach (var element in recordsThatAreGTypeStructs)
            {
                element.SetAttributeValue(gs + "opaque", "gtype-struct");
            }

            // move fields to internal struct in opaques

            var recordsThatAreOpaque = document.Descendants(gi + "record")
                                       .Where(d => d.Attribute(gs + "opaque") != null);

            foreach (var element in recordsThatAreOpaque)
            {
                var innerStruct = new XElement(gi + "record",
                                               new XAttribute("name", element.Attribute("name").Value + "Struct"),
                                               new XAttribute(gs + "managed-name", element.Attribute(gs + "managed-name").Value + "Struct"),
                                               new XAttribute(gs + "access-modifiers", "protected"));
                var fields = element.Elements(gi + "field").ToList();
                foreach (var field in fields)
                {
                    field.Remove();
                    innerStruct.Add(field);
                }
                element.AddFirst(innerStruct);
            }

            // remove fields from classes

            var classes = document.Descendants(gi + "class");

            foreach (var element in classes)
            {
                var fields = element.Elements(gi + "field").ToList();
                foreach (var field in fields)
                {
                    field.Remove();
                }
            }

            // add managed-type attribute (skipping existing managed-type attributes)

            var elementsWithManagedType = document.Descendants()
                                          .Where(d => ElementsThatReferenceAType.Contains(d.Name))
                                          .Where(d => d.Attribute(gs + "managed-type") == null);

            foreach (var element in elementsWithManagedType)
            {
                var managedType = element.GetManagedTypeName();
                element.SetAttributeValue(gs + "managed-type", managedType);
            }

            // add managed-parameters element

            var parameterElements = document.Descendants(gi + "parameters");

            foreach (var element in parameterElements)
            {
                var managedParamtersElement = new XElement(gs + "managed-parameters");
                foreach (var managedParameterElement in element.EnumerateManagedParameters())
                {
                    managedParamtersElement.Add(new XElement(managedParameterElement));
                }
                element.Parent.Add(managedParamtersElement);
            }

            // flag getters as properties

            var getters = document.Descendants()
                          .Where(d => (d.Name == gi + "function" || d.Name == gi + "method") &&
                                 !d.Attribute(gs + "extension-method").AsBool() &&
                                 !d.Attribute(gs + "pinvoke-only").AsBool() &&
                                 (d.Attribute("name").Value.StartsWith("get_", StringComparison.Ordinal) || d.Attribute("name").Value.StartsWith("is_", StringComparison.Ordinal)) &&
                                 (d.Element(gs + "managed-parameters") == null || !d.Element(gs + "managed-parameters").Elements(gi + "parameter").Any()));

            foreach (var element in getters)
            {
                var name = element.Attribute(gs + "managed-name").Value;
                if (element.Attribute("name").Value.StartsWith("get_", StringComparison.Ordinal))
                {
                    // drop the Get prefix, but not the Is
                    name = name.Substring(3);
                }
                element.SetAttributeValue(gs + "property", name);
                element.SetAttributeValue(gs + "managed-name", "get_" + name);
            }

            // flag setters as properties (if there is a matching getter only)

            var setters = document.Descendants()
                          .Where(d => (d.Name == gi + "function" || d.Name == gi + "method") &&
                                 !d.Attribute(gs + "pinvoke-only").AsBool() &&
                                 d.Attribute("name").Value.StartsWith("set_", StringComparison.Ordinal) &&
                                 d.Element(gs + "managed-parameters") != null &&
                                 d.Element(gs + "managed-parameters").Elements(gi + "parameter").Count() == 1);

            foreach (var element in setters)
            {
                var name = element.Attribute(gs + "managed-name").Value;
                // drop the Set prefix
                name = name.Substring(3);
                var matchingGetter = element.Parent.Elements(element.Name).SingleOrDefault(e => e.Attribute(gs + "property").AsString() == name);
                if (matchingGetter == null)
                {
                    // we don't want set-only properties
                    continue;
                }
                var getterReturnType    = matchingGetter.Element(gi + "return-value").Attribute(gs + "managed-type").Value;
                var setterParameterType = element.Element(gs + "managed-parameters").Element(gi + "parameter").Attribute(gs + "managed-type").Value;
                if (getterReturnType != setterParameterType)
                {
                    // this isn't the setter if the types don't match
                    continue;
                }
                element.SetAttributeValue(gs + "property", name);
                element.SetAttributeValue(gs + "managed-name", "set_" + name);
                // rename the parameter to "value" since that is what the set accessor in C# requires
                element.Element(gs + "managed-parameters").Element(gi + "parameter").SetAttributeValue(gs + "managed-name", "value");
            }
        }
Ejemplo n.º 3
0
 private static XElement N(
     string elementName, params XAttribute[] attributeList)
 {
     return(n.Element(elementName, attributeList));
 }