/// <summary> /// Parses a .Net XML documentation type, method, or other member name. /// </summary> /// <param name="name"> /// <list> /// <item>Names starting with "T:" are parsed as Type names.</item> /// <item>Names starting with "M:" are parsed as Method names.</item> /// <item>Names starting with "F:" are parsed as Member names.</item> /// <item>Names starting with "P:" are parsed as Member names.</item> /// <item>Names starting with "E:" are parsed as Member names.</item> /// <item>All others are parsed as Member names.</item> /// </list> /// </param> public static DotNetQualifiedName FromVisualStudioXml(string name) { if (String.IsNullOrEmpty(name)) { return(new DotNetQualifiedName()); } if (name.Length < 2 || name[1] != ':') { return(MemberNameFromVisualStudioXml(name)); } switch (name[0]) { case 'T': return(DotNetQualifiedClassName.FromVisualStudioXml(name)); case 'M': return(DotNetQualifiedMethodName.FromVisualStudioXml(name)); case 'F': case 'P': case 'E': return(MemberNameFromVisualStudioXml(name)); default: return(MemberNameFromVisualStudioXml(name)); } }
/// <summary> /// Parses a .Net XML documentation type name or namespace name. /// </summary> /// <remarks> /// Does not differentiate between types and namespaces /// because a nested type will have other type names in its namespace path /// and there are no important diffences in parsing the two. /// </remarks> /// <example> /// <para> /// How .Net xml documentation formats generic types: /// Backtics are followed by integers, identifying generic types. /// </para> /// <para> /// Single backtics (such as `1) on a class declaration indicate a count of generic types for the class. /// For example, <![CDATA[MyGenericType<T,U,V>]]> is documented as <c>MyGenericType`3</c>. /// Anywhere else within this object's documentation that a single backtic appears, it indicates the zero-based index of the generic type in reference to the class declaration. /// For example, the constructor <![CDATA[MyGenericType(T,U,V)]]> is documented as <c>MyGenericType.#ctor(`0,`1,`2)</c>. /// </para> /// </example> /// <param name="name">Name may or may not start with "T:"</param> public new static DotNetQualifiedClassName FromVisualStudioXml(string name) { if (name.StartsWith("T:")) { name = name.Substring(2); } int divider = name.LastIndexOf('.'); string localName = name; string fullNamespace = null; if (divider != -1) { localName = name.Substring(divider + 1); fullNamespace = name.Substring(0, divider); } int classGenericTypeCount = 0; if (localName.Contains("`")) { Int32.TryParse(localName.Substring(localName.IndexOf('`') + 1), out classGenericTypeCount); localName = localName.Substring(0, localName.IndexOf('`')); } if (String.IsNullOrEmpty(fullNamespace)) { return(new DotNetQualifiedClassName(localName, classGenericTypeCount)); } return(new DotNetQualifiedClassName(localName, DotNetQualifiedClassName.FromVisualStudioXml(fullNamespace), classGenericTypeCount)); }
/// <summary> /// Parse .Net XML documentation for Type data. /// </summary> /// <param name="memberElement">Expects tag name "member".</param> /// <example><![CDATA[<member name="T:Namespace.Type"></member>]]></example> public static DotNetType FromVisualStudioXml(XElement memberElement) { DotNetQualifiedClassName name = DotNetQualifiedClassName.FromVisualStudioXml(memberElement.GetAttributeValue("name")); DotNetType type = new DotNetType(name); type.ParseVisualStudioXmlDocumentation(memberElement); return(type); }
/// <summary> /// Returns deep clone of qualified name. /// </summary> public new DotNetQualifiedClassName Clone() { DotNetQualifiedClassName clonedFullNamespace = null; if (FullNamespace != null) { clonedFullNamespace = FullClassNamespace.Clone(); } return(new DotNetQualifiedClassName(localName, clonedFullNamespace, GenericTypeCount)); }
/// <summary> /// Parses a .Net XML documentation member name. /// </summary> /// <remarks> /// There is no support for generic types here because .Net XMl documentation does not include member types, just the names. /// </remarks> /// <remarks> /// Does not parse method names; use DotNetQualifiedMethodName.FromVisualStudioXml(string) instead. /// </remarks> /// <example> /// Expected formats: /// - "F:NamespaceA.NamespaceB.MemberC" /// - "P:NamespaceA.NamespaceB.MemberC" /// - "E:NamespaceA.NamespaceB.MemberC" /// - "NamespaceA.NamespaceB.MemberC" /// - "NamespaceA.NamespaceB.InterfaceNamespace#Interface#MemberC" /// </example> /// <param name="name">Name may or may not start with /[FPE]:/</param> private static DotNetQualifiedName MemberNameFromVisualStudioXml(string name) { if (name.StartsWith("F:")) { name = name.Substring(2); } if (name.StartsWith("P:")) { name = name.Substring(2); } if (name.StartsWith("E:")) { name = name.Substring(2); } int divider = name.LastIndexOf('.'); string localName = name; string fullNamespace = null; if (divider != -1) { localName = name.Substring(divider + 1); fullNamespace = name.Substring(0, divider); } DotNetQualifiedName explicitInterface = null; if (localName.Contains("#")) { int lastIndex = localName.LastIndexOf("#"); string interfaceName = localName.Substring(0, lastIndex).Replace("#", "."); explicitInterface = DotNetQualifiedName.FromVisualStudioXml(interfaceName); localName = localName.Substring(lastIndex + 1); } if (String.IsNullOrEmpty(fullNamespace)) { return(new DotNetQualifiedName(localName, explicitInterface)); } return(new DotNetQualifiedName(localName, DotNetQualifiedClassName.FromVisualStudioXml(fullNamespace), explicitInterface)); }
/// <summary></summary> public DotNetType(DotNetQualifiedClassName name) : base(name) { Category = TypeCategory.Unknown; IsSealed = false; }
/// <summary> /// Constructors need to reference the actual name of their type so they display the right name with aliases. /// </summary> internal void SetClassName(DotNetQualifiedClassName className) { MethodName.SetClassName(className); }
/// <summary></summary> public DotNetQualifiedClassName(string localName, DotNetQualifiedClassName fullNamespace, int genericTypeCount = 0) : base(localName, fullNamespace, null) { GenericTypeCount = genericTypeCount; }
/// <summary> /// Insert a new namespace into its proper position, based on the current node as the root. /// </summary> public void Insert(DotNetQualifiedClassName name) { //first root if (this.Value == null && this.Children.Count == 0) { this.Value = name; return; } if (this.Value == null) //null root over multiple top-level namespaces { //this belongs below a child foreach (DotNetQualifiedClassNameTreeNode childNode in this.Children) { if (name.IsWithin(childNode.Value)) { childNode.Insert(name); return; } } //this is at the same level as children DotNetQualifiedClassNameTreeNode newNode = new DotNetQualifiedClassNameTreeNode(name); this.AddChild(newNode); //children that belong below the new node int index = 0; while (index < this.Children.Count) { if (this.Children[index].Value.IsWithin(name)) { this.TransferChildTo(this.Children[index], newNode); continue; } index++; } //all children are within new name if (this.Children.Count == 1) { newNode.TransferChildrenTo(this); this.Value = newNode.Value; this.Children.Remove(newNode); } } else //normal, full tree { if (this.Value.IsWithin(name)) //new root { DotNetQualifiedClassNameTreeNode rootTransfer = new DotNetQualifiedClassNameTreeNode(this.Value); this.TransferChildrenTo(rootTransfer); this.Value = name; this.AddChild(rootTransfer); return; } else if (name.IsWithin(this.Value)) //descendent of root { //belongs below a child foreach (DotNetQualifiedClassNameTreeNode childNode in this.Children) { if (name.IsWithin(childNode.Value)) { childNode.Insert(name); return; } } //belongs at same level as children DotNetQualifiedClassNameTreeNode newNode = new DotNetQualifiedClassNameTreeNode(name); this.AddChild(newNode); //children that belong below the new node int index = 0; while (index < this.Children.Count) { if (this.Children[index].Value.IsWithin(name)) { this.TransferChildTo(this.Children[index], newNode); continue; } index++; } } else //same level as root { DotNetQualifiedClassNameTreeNode rootTransfer = new DotNetQualifiedClassNameTreeNode(this.Value); this.TransferChildrenTo(rootTransfer); this.Value = null; this.AddChild(rootTransfer); DotNetQualifiedClassNameTreeNode newNode = new DotNetQualifiedClassNameTreeNode(name); this.AddChild(newNode); } } }
internal DotNetQualifiedClassNameTreeNode(DotNetQualifiedClassName value) { Value = value; Parent = null; Children = new List <DotNetQualifiedClassNameTreeNode>(); }