// Take either an XML type declaration or a type.dotident element, and return the associated // TypeDeclaration instance if it is declared somewhere in the XML, null otherwise public static TypeDeclaration New(XElement elem, Container <Declaration> super, TypeScriptDefContext context) { // If the argument passed is an XML type declaration, we don't search // in the XML and directly return the associated instance if (TypeDeclaration.GetClass(elem) != null) { return(TypeDeclaration.GetInstance(elem, super, context)); } string[] name = elem.Attribute("text").Value.Split('.'); XElement parent; TypeDeclaration typeDeclaration = null; do { // We check if there is a declaration in the current namespace parent = elem.Ancestors().FirstOrDefault(e => TypeDeclaration.IsTypeDeclarationContainer(e)); if (parent != null) { typeDeclaration = TypeDeclaration.New(name, parent, super, context); elem = parent; } } // If not, we check in the parent namespace, and if not in the parent of the parent, // and so on until we reach the root namespace while (typeDeclaration == null && parent != null); return(typeDeclaration); }
// Parse and add content to this namespace public void AddContent(XElement content, TypeScriptDefContext context) { #if LOG_VERBOSE context.Logger.WriteMessage("AddContent: '" + this.Name + "'"); #endif foreach (XElement elem in content.Elements()) { switch (elem.Name.LocalName) { case "import": this.Imports.Add(new Import(elem)); break; case "namespace": this.AddChildNamespace(elem, context); // We don't add it directly because maybe the namespace already exists break; // Variable directly in the namespace case "variable": this.StaticClass.Properties.Add(new Property(elem, this.StaticClass, context) { Static = true }); break; // Function directly in the namespace case "function": this.StaticClass.Methods.Add(new Method(elem, this.StaticClass, context) { Static = true }); break; case "enum": this.Declarations.Add(TypeDeclaration.New(elem, this, context)); break; case "interface": this.Declarations.Add(TypeDeclaration.New(elem, this, context)); break; case "class": this.Declarations.Add(TypeDeclaration.New(elem, this, context)); break; } } }
// This is simply boring XML parsing, should've used deserialization but at this time I was a noob sorry public GlobalProgram(XDocument doc, string name, TypeScriptDefContext context) : this(context) { this.Name = name; var Child = doc.Root.Elements(); string[] path = name.Split('.'); this.StaticClass.Name = path.Last() + "Class"; foreach (XElement elem in Child) { switch (elem.Name.LocalName) { case "import": this.Imports.Add(new Import(elem)); break; case "namespace": this.AddChildNamespace(elem, context); // We don't add it directly because maybe the namespace already exists break; // Variable directly in the namespace case "variable": this.StaticClass.Properties.Add(new Property(elem, this.StaticClass, context) { Static = true }); break; // Function directly in the namespace case "function": this.StaticClass.Methods.Add(new Method(elem, this.StaticClass, context) { Static = true }); break; case "interface": this.Declarations.Add(TypeDeclaration.New(elem, this, context)); break; case "class": this.Declarations.Add(TypeDeclaration.New(elem, this, context)); break; } } }
// Check if a given type name is declared somewhere in a given XML subtree, // and return the associated TypeDeclaration instance if it is, null otherwise private static TypeDeclaration New(string[] name, XElement root, Container <Declaration> super, TypeScriptDefContext context) { // We create a list of the elements we're going to inspect var elems = new List <XElement>(); // First we inspect the root itself (except if it is the global namespace) if (root.Name.LocalName != "start") { elems.Add(root); } // If there is no declaration directly in the root, we inspect its children IEnumerable <XElement> children; // We need to handle the special case of namespace elements, // which do not hold their declarations as direct children if (root.Name.LocalName == "namespace") { children = root.Element("namespacecontent").Elements(); } else { children = root.Elements(); } elems.AddRange(children); // Then for each element in the list foreach (XElement e in elems) { // First we make sure that it correponds either to a TypeDeclaration or a Container<TypeDeclaration> Type typeDeclarationClass = TypeDeclaration.GetClass(e); bool isTypeDeclarationContainer = TypeDeclaration.IsTypeDeclarationContainer(e); if (typeDeclarationClass != null || isTypeDeclarationContainer) { // The element identifier must be at most as long as the type name string[] ident = Tool.GetIdent(e).Split('.'); if (ident.Length <= name.Length) { // If the hole identifier matches the beginning of the name int match = ident.ToList().FirstMismatchIndex(name.ToList()); if (match == ident.Length) { // Either the beginning is actually the type (local) name... if (name.Length == 1) { // ...and if the element is associated with a TypeDeclaration class, // it means we have found a valid declaration, so we return an instance of said class if (typeDeclarationClass != null) { return(TypeDeclaration.GetInstance(e, super, context)); } } // Or the beginning is just the name of an ancestor container... else if (isTypeDeclarationContainer) { // ...and therefore we call the method recursively on the element var res = TypeDeclaration.New(name.Skip(match).ToArray(), e, super, context); // If we found a valid declaration during the recursive call, we return it if (res != null) { return(res); } // Otherwise there might be another container with the same name, so we keep searching. // For example it is possible that class a.b does not contain the declaration, // while namespace a.b, which is going to be merged with class a.b by the compiler, does contain it. } } } } } // If there is no element containing a declaration, we return null return(null); }