public XmlClassGen(XElement pkg, XElement elem) : base(new XmlGenBaseSupport(pkg, elem)) //FIXME: should not be xml specific { is_abstract = elem.XGetAttribute("abstract") == "true"; is_final = elem.XGetAttribute("final") == "true"; base_type = elem.XGetAttribute("extends"); foreach (var child in elem.Elements()) { switch (child.Name.LocalName) { case "implements": string iname = child.XGetAttribute("name-generic-aware"); iname = iname.Length > 0 ? iname : child.XGetAttribute("name"); AddInterface(iname); break; case "method": var synthetic = child.XGetAttribute("synthetic") == "true"; var finalizer = child.XGetAttribute("name") == "finalize" && child.XGetAttribute("jni-signature") == "()V"; if (!(synthetic || finalizer)) { AddMethod(new XmlMethod(this, child)); } break; case "constructor": Ctors.Add(new XmlCtor(this, child)); break; case "field": AddField(new XmlField(child)); break; case "typeParameters": break; // handled at GenBaseSupport default: Report.Warning(0, Report.WarningClassGen + 1, "unexpected class child {0}.", child.Name); break; } } }
public static ClassGen CreateClass(XElement pkg, XElement elem) { var klass = new ClassGen(CreateGenBaseSupport(pkg, elem, false)) { BaseType = elem.XGetAttribute("extends"), FromXml = true, IsAbstract = elem.XGetAttribute("abstract") == "true", IsFinal = elem.XGetAttribute("final") == "true" }; foreach (var child in elem.Elements()) { switch (child.Name.LocalName) { case "implements": var iname = child.XGetAttribute("name-generic-aware"); iname = iname.Length > 0 ? iname : child.XGetAttribute("name"); klass.AddImplementedInterface(iname); break; case "method": klass.AddMethod(CreateMethod(klass, child)); break; case "constructor": klass.Ctors.Add(CreateCtor(klass, child)); break; case "field": klass.AddField(CreateField(child)); break; case "typeParameters": break; // handled at GenBaseSupport default: Report.Warning(0, Report.WarningClassGen + 1, "unexpected class child {0}.", child.Name); break; } } return(klass); }
public XmlCtor(GenBase declaringType, XmlElement elem) : base(declaringType, new XmlMethodBaseSupport(elem)) { name = elem.XGetAttribute("name"); int idx = name.LastIndexOf('.'); if (idx > 0) { name = name.Substring(idx + 1); } // If 'elem' is a constructor for a non-static nested type, then // the type of the containing class must be inserted as the first // argument nonStaticNestedType = idx > 0 && elem.ParentNode.Attributes ["static"].Value == "false"; if (nonStaticNestedType) { string declName = elem.ParentNode.Attributes ["name"].Value; string expectedEnclosingName = declName.Substring(0, idx); XmlElement enclosingType = GetPreviousClass(elem.ParentNode.PreviousSibling, expectedEnclosingName); if (enclosingType == null) { missing_enclosing_class = true; Report.Warning(0, Report.WarningCtor + 0, "For {0}, could not find enclosing type '{1}'.", name, expectedEnclosingName); } else { Parameters.AddFirst(Parameter.FromClassElement(enclosingType)); } } foreach (XmlNode child in elem.ChildNodes) { if (child.Name == "parameter") { Parameters.Add(Parameter.FromElement(child as XmlElement)); } } if (elem.HasAttribute("customAttributes")) { custom_attributes = elem.GetAttribute("customAttributes"); } }
public static InterfaceGen CreateInterface(XElement pkg, XElement elem, CodeGenerationOptions options) { var iface = new InterfaceGen(CreateGenBaseSupport(pkg, elem, true)) { ArgsType = elem.XGetAttribute("argsType"), HasManagedName = elem.Attribute("managedName") != null, NoAlternatives = elem.XGetAttribute("no-alternatives") == "true", // Only use an explicitly set XML attribute Unnest = elem.XGetAttribute("unnest") == "true" ? true : elem.XGetAttribute("unnest") == "false" ? false : !options.SupportNestedInterfaceTypes }; foreach (var child in elem.Elements()) { switch (child.Name.LocalName) { case "implements": string iname = child.XGetAttribute("name-generic-aware"); iname = iname.Length > 0 ? iname : child.XGetAttribute("name"); iface.AddImplementedInterface(iname); break; case "method": iface.AddMethod(CreateMethod(iface, child)); break; case "field": iface.AddField(CreateField(child)); break; case "typeParameters": break; // handled at GenBaseSupport default: Report.Warning(0, Report.WarningInterfaceGen + 0, "unexpected interface child {0}.", child); break; } } return(iface); }
public XmlInterfaceGen(XmlElement pkg, XmlElement elem) : base(new InterfaceXmlGenBaseSupport(pkg, elem)) { hasManagedName = elem.HasAttribute("managedName"); args_type = elem.XGetAttribute("argsType"); foreach (XmlNode node in elem.ChildNodes) { XmlElement child = node as XmlElement; if (child == null) { continue; } switch (node.Name) { case "implements": string iname = child.XGetAttribute("name-generic-aware"); iname = iname.Length > 0 ? iname : child.XGetAttribute("name"); AddInterface(iname); break; case "method": if (child.GetAttribute("synthetic") != "true") { AddMethod(new XmlMethod(this, child)); } break; case "field": AddField(new XmlField(child)); break; case "typeParameters": break; // handled at GenBaseSupport default: Report.Warning(0, Report.WarningInterfaceGen + 0, "unexpected interface child {0}.", node.Name); break; } } }
public bool Validate(CodeGenerationOptions opt, GenericParameterDefinitionList type_params) { symbol = SymbolTable.Lookup(TypeName, type_params); if (symbol == null || !symbol.Validate(opt, type_params)) { Report.Warning(0, Report.WarningField + 0, "unexpected field type {0} {1}.", TypeName, opt.ContextString); return(false); } setParameters = new ParameterList() { SetterParameter, }; if (!setParameters.Validate(opt, type_params)) { throw new NotSupportedException( string.Format("Unable to generate setter parameter list {0}", opt.ContextString)); } return(true); }
public static InterfaceGen CreateInterface(XElement pkg, XElement elem) { var iface = new InterfaceGen(CreateGenBaseSupport(pkg, elem, true)) { ArgsType = elem.XGetAttribute("argsType"), HasManagedName = elem.Attribute("managedName") != null }; foreach (var child in elem.Elements()) { switch (child.Name.LocalName) { case "implements": string iname = child.XGetAttribute("name-generic-aware"); iname = iname.Length > 0 ? iname : child.XGetAttribute("name"); iface.AddImplementedInterface(iname); break; case "method": iface.AddMethod(CreateMethod(iface, child)); break; case "field": iface.AddField(CreateField(child)); break; case "typeParameters": break; // handled at GenBaseSupport default: Report.Warning(0, Report.WarningInterfaceGen + 0, "unexpected interface child {0}.", child); break; } } return(iface); }
protected override bool OnValidate(CodeGenerationOptions opt, GenericParameterDefinitionList type_params) { if (validated) { return(is_valid); } validated = true; // Due to demand to validate in prior to validate ClassGen's BaseType, it is *not* done at // GenBase. if (TypeParameters != null && !TypeParameters.Validate(opt, type_params)) { return(false); } if (!base.OnValidate(opt, type_params) || iface_validation_failed || MethodValidationFailed) { if (iface_validation_failed) { Report.Warning(0, Report.WarningInterfaceGen + 2, "Invalidating {0} and all nested types because some of its interfaces were invalid.", FullName); } else if (MethodValidationFailed) { Report.Warning(0, Report.WarningInterfaceGen + 3, "Invalidating {0} and all nested types because some of its methods were invalid.", FullName); } foreach (GenBase nest in NestedTypes) { nest.Invalidate(); } is_valid = false; return(false); } return(true); }
protected virtual bool OnValidate(CodeGenerationOptions opt, GenericParameterDefinitionList type_params) { if (Name.Length > TypeNamePrefix.Length && (Name [TypeNamePrefix.Length] == '.' || Char.IsDigit(Name [TypeNamePrefix.Length]))) // see bug #5111 { return(false); } if (!support.ValidateNamespace()) { return(false); } List <GenBase> valid_nests = new List <GenBase> (); foreach (GenBase gen in nested_types) { if (gen.Validate(opt, TypeParameters)) { valid_nests.Add(gen); } } nested_types = valid_nests; AdjustNestedTypeFullName(this); foreach (string iface_name in iface_names) { ISymbol isym = SymbolTable.Lookup(iface_name); if (isym != null && isym.Validate(opt, TypeParameters)) { ifaces.Add(isym); } else { if (isym == null) { Report.Warning(0, Report.WarningGenBase + 0, "For type {0}, base interface {1} does not exist.", FullName, iface_name); } else { Report.Warning(0, Report.WarningGenBase + 0, "For type {0}, base interface {1} is invalid.", FullName, iface_name); } iface_validation_failed = true; } } List <Field> valid_fields = new List <Field> (); foreach (Field f in fields) { if (!f.Validate(opt, TypeParameters)) { continue; } valid_fields.Add(f); } fields = valid_fields; int method_cnt = methods.Count; methods = methods.Where(m => ValidateMethod(opt, m)).ToList(); method_validation_failed = method_cnt != methods.Count; foreach (Method m in methods) { if (m.IsVirtual) { has_virtual_methods = true; } if (m.Name == "HashCode" && m.Parameters.Count == 0) { m.IsOverride = true; m.Name = "GetHashCode"; } jni_sig_hash [m.JavaName + m.JniSignature] = m; if ((m.Name == "ToString" && m.Parameters.Count == 0) || (BaseSymbol != null && BaseSymbol.ContainsMethod(m, true))) { m.IsOverride = true; } } return(true); }
void Process(XDocument meta_doc, string apiLevelString, int productVersion) { int apiLevel = 0; int.TryParse(apiLevelString, out apiLevel); var metadataChildren = meta_doc.XPathSelectElements("/metadata/*"); string prev_path = null; XElement attr_last_cache = null; foreach (var metaitem in metadataChildren) { if (ShouldSkip(metaitem, apiLevel, productVersion)) { continue; } if (!ShouldApply(metaitem)) { continue; } string path = metaitem.XGetAttribute("path"); if (path != prev_path) { attr_last_cache = null; } prev_path = path; switch (metaitem.Name.LocalName) { case "remove-node": try { var nodes = api_doc.XPathSelectElements(path).ToArray(); if (nodes.Any()) { foreach (var node in nodes) { node.Remove(); } } else { // BG8A00 Report.Warning(0, Report.WarningApiFixup + 0, null, metaitem, "<remove-node path=\"{0}\"/> matched no nodes.", path); } } catch (XPathException e) { // BG4A01 Report.Error(Report.ErrorApiFixup + 1, e, metaitem, "Invalid XPath specification: {0}", path); } break; case "add-node": try { var nodes = api_doc.XPathSelectElements(path); bool matched = false; if (!nodes.Any()) { // BG8A01 Report.Warning(0, Report.WarningApiFixup + 1, null, metaitem, "<add-node path=\"{0}\"/> matched no nodes.", path); } else { foreach (var node in nodes) { node.Add(metaitem.Nodes()); } matched = true; } } catch (XPathException e) { // BG4A02 Report.Error(Report.ErrorApiFixup + 2, e, metaitem, "Invalid XPath specification: {0}", path); } break; case "change-node": try { var nodes = api_doc.XPathSelectElements(path); bool matched = false; foreach (var node in nodes) { var newChild = new XElement(metaitem.Value); newChild.Add(node.Attributes()); newChild.Add(node.Nodes()); node.ReplaceWith(newChild); matched = true; } if (!matched) { // BG8A03 Report.Warning(0, Report.WarningApiFixup + 3, null, metaitem, "<change-node-type path=\"{0}\"/> matched no nodes.", path); } } catch (XPathException e) { // BG4A03 Report.Error(Report.ErrorApiFixup + 3, e, metaitem, "Invalid XPath specification: {0}", path); } break; case "attr": try { string attr_name = metaitem.XGetAttribute("name"); if (string.IsNullOrEmpty(attr_name)) { // BG4A07 Report.Error(Report.ErrorApiFixup + 7, null, metaitem, "Target attribute name is not specified for path: {0}", path); } var nodes = attr_last_cache != null ? new XElement [] { attr_last_cache } : api_doc.XPathSelectElements(path); int attr_matched = 0; foreach (var n in nodes) { n.SetAttributeValue(attr_name, metaitem.Value); attr_matched++; } if (attr_matched == 0) { // BG8A04 Report.Warning(0, Report.WarningApiFixup + 4, null, metaitem, "<attr path=\"{0}\"/> matched no nodes.", path); } if (attr_matched != 1) { attr_last_cache = null; } } catch (XPathException e) { // BG4A04 Report.Error(Report.ErrorApiFixup + 4, e, metaitem, "Invalid XPath specification: {0}", path); } break; case "move-node": try { string parent = metaitem.Value; var parents = api_doc.XPathSelectElements(parent); bool matched = false; foreach (var parent_node in parents) { var nodes = parent_node.XPathSelectElements(path).ToArray(); foreach (var node in nodes) { node.Remove(); } parent_node.Add(nodes); matched = true; } if (!matched) { // BG8A05 Report.Warning(0, Report.WarningApiFixup + 5, null, metaitem, "<move-node path=\"{0}\"/> matched no nodes.", path); } } catch (XPathException e) { // BG4A05 Report.Error(Report.ErrorApiFixup + 5, e, metaitem, "Invalid XPath specification: {0}", path); } break; case "remove-attr": try { string name = metaitem.XGetAttribute("name"); var nodes = api_doc.XPathSelectElements(path); bool matched = false; foreach (var node in nodes) { node.RemoveAttributes(); matched = true; } if (!matched) { // BG8A06 Report.Warning(0, Report.WarningApiFixup + 6, null, metaitem, "<remove-attr path=\"{0}\"/> matched no nodes.", path); } } catch (XPathException e) { // BG4A06 Report.Error(Report.ErrorApiFixup + 6, e, metaitem, "Invalid XPath specification: {0}", path); } break; } } }
public void GenerateEventsOrPropertiesForListener(StreamWriter sw, string indent, CodeGenerationOptions opt, ClassGen target) { var methods = target.Methods.Concat(target.Properties.Where(p => p.Setter != null).Select(p => p.Setter)); var props = new HashSet <string> (); var refs = new HashSet <string> (); var eventMethods = methods.Where(m => m.IsListenerConnector && m.EventName != String.Empty && m.ListenerType == this).Distinct(); foreach (var method in eventMethods) { string name = method.CalculateEventName(target.ContainsName); if (String.IsNullOrEmpty(name)) { Report.Warning(0, Report.WarningInterfaceGen + 1, "empty event name in {0}.{1}.", FullName, method.Name); continue; } if (opt.GetSafeIdentifier(name) != name) { Report.Warning(0, Report.WarningInterfaceGen + 4, "event name for {0}.{1} is invalid. `eventName' or `argsType` can be used to assign a valid member name.", FullName, method.Name); continue; } var prop = target.Properties.FirstOrDefault(p => p.Setter == method); if (prop != null) { string setter = "__Set" + prop.Name; props.Add(prop.Name); refs.Add(setter); GenerateEventOrProperty(sw, indent, target, opt, name, setter, string.Format("__v => {0} = __v", prop.Name), string.Format("__v => {0} = null", prop.Name)); } else { refs.Add(method.Name); string rm = null; string remove; if (method.Name.StartsWith("Set")) { remove = string.Format("__v => {0} (null)", method.Name); } else if (method.Name.StartsWith("Add") && (rm = "Remove" + method.Name.Substring("Add".Length)) != null && methods.Where(m => m.Name == rm).Any()) { remove = string.Format("__v => {0} (__v)", rm); } else { remove = string.Format("__v => {{throw new NotSupportedException (\"Cannot unregister from {0}.{1}\");}}", FullName, method.Name); } GenerateEventOrProperty(sw, indent, target, opt, name, method.Name, method.Name, remove); } } foreach (var r in refs) { sw.WriteLine("{0}WeakReference weak_implementor_{1};", indent, r); } sw.WriteLine(); sw.WriteLine("{0}{1}Implementor __Create{2}Implementor ()", indent, opt.GetOutputName(FullName), Name); sw.WriteLine("{0}{{", indent); sw.WriteLine("{0}\treturn new {1}Implementor ({2});", indent, opt.GetOutputName(FullName), NeedsSender ? "this" : ""); sw.WriteLine("{0}}}", indent); }
List <GenBase> ParsePackage(XElement ns, Predicate <XElement> p) { List <GenBase> result = new List <GenBase> (); Dictionary <string, GenBase> nested = new Dictionary <string, GenBase> (); Dictionary <string, GenBase> by_name = new Dictionary <string, GenBase> (); foreach (var elem in ns.Elements()) { string name = elem.XGetAttribute("name"); GenBase gen = null; switch (elem.Name.LocalName) { case "class": if (elem.XGetAttribute("obfuscated") == "true") { continue; } gen = XmlApiImporter.CreateClass(ns, elem, opt); break; case "interface": if (elem.XGetAttribute("obfuscated") == "true") { continue; } gen = XmlApiImporter.CreateInterface(ns, elem, opt); break; default: Report.Warning(0, Report.WarningParser + 3, "Unexpected node in package element: {0}.", elem.Name); break; } if (gen == null) { continue; } int idx = name.IndexOf('<'); if (idx > 0) { name = name.Substring(0, idx); } by_name [name] = gen; if (name.IndexOf('.') > 0) { nested [name] = gen; } else { result.Add(gen); } } foreach (string name in nested.Keys) { string top_ancestor = name.Substring(0, name.IndexOf('.')); if (by_name.ContainsKey(top_ancestor)) { by_name [top_ancestor].AddNestedType(nested [name]); } else { Report.Warning(0, Report.WarningParser + 4, "top ancestor {0} not found for nested type {1}.", top_ancestor, nested [name].FullName); nested [name].Invalidate(); } } return(result); }
void Process(XmlDocument meta_doc, string apiLevelString, int productVersion) { XPathNavigator api_nav = api_doc.CreateNavigator(); XPathNavigator meta_nav = meta_doc.CreateNavigator(); int apiLevel = 0; int.TryParse(apiLevelString, out apiLevel); XPathNodeIterator metadata = meta_nav.Select("/metadata/*"); string prev_path = null; XPathNavigator attr_last_cache = null; while (metadata.MoveNext()) { var metanav = metadata.Current; if (ShouldSkip(metanav, apiLevel, productVersion)) { continue; } if (!ShouldApply(metanav)) { continue; } string path = metanav.XGetAttribute("path", ""); if (path != prev_path) { attr_last_cache = null; } prev_path = path; switch (metanav.LocalName) { case "remove-node": try { XPathNodeIterator api_iter = api_nav.Select(path); List <XmlElement> matches = new List <XmlElement> (); while (api_iter.MoveNext()) { matches.Add(((IHasXmlNode)api_iter.Current).GetNode() as XmlElement); } foreach (XmlElement api_node in matches) { api_node.ParentNode.RemoveChild(api_node); } if (matches.Count == 0) { // BG8A00 Report.Warning(0, Report.WarningApiFixup + 0, "<remove-node path=\"{0}\"/> matched no nodes.", path); } } catch (XPathException e) { // BG4A01 Report.Error(Report.ErrorApiFixup + 1, e, "Invalid XPath specification: {0}", path); } break; case "add-node": try { XPathNodeIterator api_iter = api_nav.Select(path); bool matched = false; while (api_iter.MoveNext()) { XmlElement api_node = ((IHasXmlNode)api_iter.Current).GetNode() as XmlElement; foreach (XmlNode child in ((IHasXmlNode)metanav).GetNode().ChildNodes) { api_node.AppendChild(api_doc.ImportNode(child, true)); } matched = true; } if (!matched) { // BG8A01 Report.Warning(0, Report.WarningApiFixup + 1, "<add-node path=\"{0}\"/> matched no nodes.", path); } } catch (XPathException e) { // BG4A02 Report.Error(Report.ErrorApiFixup + 2, e, "Invalid XPath specification: {0}", path); } break; case "change-node": try { XPathNodeIterator api_iter = api_nav.Select(path); bool matched = false; while (api_iter.MoveNext()) { XmlElement node = ((IHasXmlNode)api_iter.Current).GetNode() as XmlElement; XmlElement parent = node.ParentNode as XmlElement; XmlElement new_node = api_doc.CreateElement(metanav.Value); foreach (XmlNode child in node.ChildNodes) { new_node.AppendChild(child.Clone()); } foreach (XmlAttribute attribute in node.Attributes) { new_node.Attributes.Append((XmlAttribute)attribute.Clone()); } parent.ReplaceChild(new_node, node); matched = true; } if (!matched) { // BG8A03 Report.Warning(0, Report.WarningApiFixup + 3, "<change-node-type path=\"{0}\"/> matched no nodes.", path); } } catch (XPathException e) { // BG4A03 Report.Error(Report.ErrorApiFixup + 3, e, "Invalid XPath specification: {0}", path); } break; case "attr": try { string attr_name = metanav.XGetAttribute("name", ""); if (string.IsNullOrEmpty(attr_name)) { // BG4A07 Report.Error(Report.ErrorApiFixup + 7, "Target attribute name is not specified for path: {0}", path); } var nodes = attr_last_cache != null ? (IEnumerable <XPathNavigator>) new XPathNavigator [] { attr_last_cache } : api_nav.Select(path).OfType <XPathNavigator> (); int attr_matched = 0; foreach (var n in nodes) { XmlElement node = ((IHasXmlNode)n).GetNode() as XmlElement; node.SetAttribute(attr_name, metanav.Value); //attr_last_cache = n; attr_matched++; } if (attr_matched == 0) { // BG8A04 Report.Warning(0, Report.WarningApiFixup + 4, "<attr path=\"{0}\"/> matched no nodes.", path); } if (attr_matched != 1) { attr_last_cache = null; } } catch (XPathException e) { // BG4A04 Report.Error(Report.ErrorApiFixup + 4, e, "Invalid XPath specification: {0}", path); } break; case "move-node": try { XPathExpression expr = api_nav.Compile(path); string parent = metanav.Value; XPathNodeIterator parent_iter = api_nav.Select(parent); bool matched = false; while (parent_iter.MoveNext()) { XmlNode parent_node = ((IHasXmlNode)parent_iter.Current).GetNode(); XPathNodeIterator path_iter = parent_iter.Current.Clone().Select(expr); while (path_iter.MoveNext()) { XmlNode node = ((IHasXmlNode)path_iter.Current).GetNode(); parent_node.AppendChild(node.Clone()); node.ParentNode.RemoveChild(node); } matched = true; } if (!matched) { // BG8A05 Report.Warning(0, Report.WarningApiFixup + 5, "<move-node path=\"{0}\"/> matched no nodes.", path); } } catch (XPathException e) { // BG4A05 Report.Error(Report.ErrorApiFixup + 5, e, "Invalid XPath specification: {0}", path); } break; case "remove-attr": try { string name = metanav.XGetAttribute("name", ""); XPathNodeIterator api_iter = api_nav.Select(path); bool matched = false; while (api_iter.MoveNext()) { XmlElement node = ((IHasXmlNode)api_iter.Current).GetNode() as XmlElement; node.RemoveAttribute(name); matched = true; } if (!matched) { // BG8A06 Report.Warning(0, Report.WarningApiFixup + 6, "<remove-attr path=\"{0}\"/> matched no nodes.", path); } } catch (XPathException e) { // BG4A06 Report.Error(Report.ErrorApiFixup + 6, e, "Invalid XPath specification: {0}", path); } break; } } }