static bool DoMethodsMatch(MethodBase mi, MemberDoc mDoc) { string miName = TypeUtils.ReplacePlus(mi.Name); if (miName != mDoc.Name.MemberName) { return(false); } int genericArgsCount = 0; if (mi.IsGenericMethod) { genericArgsCount = mi.GetGenericArguments().Length; } if (mDoc.GenericParameterCount != genericArgsCount) { return(false); } if (!TypeUtils.DoParametersMatch(mi.GetParameters(), mDoc.Arguments ?? EmptyStr)) { return(false); } if ((mDoc.Name.MemberName == "op_Explicit" || mDoc.Name.MemberName == "op_Implicit") && ((MethodInfo)mi).ReturnType.FullName != mDoc.Returns ) { return(false); } return(true); }
//returns: null if not member public static MemberDoc ParseMember(XElement e) { string s = e.Attribute("name").Value; var type = GetType(s[0]); if (type == MemberType.NotMember) return null; s = s.Substring(2); var ret = new MemberDoc { DocInfo = e, Type = type, FullDescription = s }; int nameEndIndex = s.Length - 1; //индекс последнего элемента имени int par1Index = s.IndexOf('('); if (0 <= par1Index) { int par2Index = s.Length - 1; if (s[par2Index] != ')') { par2Index = s.IndexOf(")~"); if (par2Index == -1) throw new Exception(ErrMsg + ret.FullDescription); int retVal = par2Index + 2; ret.Returns = s.Substring(retVal, s.Length - retVal); } ret.ArgumentsTxt = s.Substring(par1Index + 1, par2Index-par1Index-1);//s.Substring(par1Index + 1, s.Length - par1Index - 2); nameEndIndex = par1Index - 1; } ret.Name = ParseUtils.ParseName(s, nameEndIndex); ret.Arguments = ParseUtils.SplitArgumentList(ret.ArgumentsTxt); ret.FixNames(); return ret; }
static bool DoPropertiesMatch(PropertyInfo mi, MemberDoc mDoc) { string miName = TypeUtils.ReplacePlus(mi.Name); if (miName != mDoc.Name.MemberName) { return(false); } if (!TypeUtils.DoParametersMatch(mi.GetIndexParameters(), mDoc.Arguments ?? EmptyStr)) { return(false); } return(true); }
//Если попадаются members у которых включающий их класс не был объявлен в XML документации, то создается класс, но у него не будет заполнено RawNode static TypeDoc[] ParseMembers(XElement members) { Dictionary <string, TypeDoc> types = members .XPathSelectElements("member[starts-with(@name,\"T:\")]") .Select(TypeDoc.Parse) .Where(t => !t.FullName.Contains("XamlGeneratedNamespace")) .ToDictionary(_ => _.FullName); foreach (var node in members.XPathSelectElements("member[not(starts-with(@name,\"T:\"))]")) { var member = MemberDoc.ParseMember(node); if (member != null) { TypeDoc type; if (types.TryGetValue(member.Name.FullClassName, out type)) { type.Members.Add(member); } else { type = new TypeDoc { FullName = member.Name.FullClassName }; type.Members.Add(member); if (!type.FullName.Contains("XamlGeneratedNamespace")) { types.Add(type.FullName, type); } } } else { //ToDo: сделать обработку типов(редкие,неиспользуемые) 'N'-namespace, '!' - error } } return(types .Select(_ => _.Value) .ToArray()); }
//returns: null if not member public static MemberDoc ParseMember(XElement e) { string s = e.Attribute("name").Value; var type = GetType(s[0]); if (type == MemberType.NotMember) { return(null); } s = s.Substring(2); var ret = new MemberDoc { DocInfo = e, Type = type, FullDescription = s }; int nameEndIndex = s.Length - 1; //индекс последнего элемента имени int par1Index = s.IndexOf('('); if (0 <= par1Index) { int par2Index = s.Length - 1; if (s[par2Index] != ')') { par2Index = s.IndexOf(")~"); if (par2Index == -1) { throw new Exception(ErrMsg + ret.FullDescription); } int retVal = par2Index + 2; ret.Returns = s.Substring(retVal, s.Length - retVal); } ret.ArgumentsTxt = s.Substring(par1Index + 1, par2Index - par1Index - 1); //s.Substring(par1Index + 1, s.Length - par1Index - 2); nameEndIndex = par1Index - 1; } ret.Name = ParseUtils.ParseName(s, nameEndIndex); ret.Arguments = ParseUtils.SplitArgumentList(ret.ArgumentsTxt); ret.FixNames(); return(ret); }
/// <summary> /// /// </summary> /// <param name="asm"></param> /// <param name="findOptions"> Опции указывающие какие типы и члены собирать</param> /// <param name="unboundTypes">Массив типов из XML документации, которые не смогли привязаться к данным из Reflection</param> /// <param name="unboundMembers">Массив members из XML документации, которые не смогли привязаться к данным из Reflection</param> public void MergeWithReflection(Assembly asm, FindOptions findOptions, out TypeDoc[] unboundTypes, out MemberDoc[] unboundMembers) { var docTypes=Types.ToDictionary(_ => _.FullName); foreach (var type in asm.GetTypes()) { if(!type.IsVisible && !findOptions.InternalClasses) continue; string name = type.FullName.Replace('+', '.'); //Для nested классов type.FullName дает Class1+Class2, а по XML Class1.Class2 - невозможно отличить nested класс от namespace TypeDoc docT; if (docTypes.TryGetValue(name, out docT)) { if(docT.ReflectionType!=null) throw new Exception("multiple types on single node"); docT.ReflectionType = type; } else if (findOptions.UndocumentedClasses) { docT = new TypeDoc { FullName = name , ReflectionType = type}; if (!docT.FullName.Contains("XamlGeneratedNamespace")) docTypes.Add(docT.FullName, docT); } } if (findOptions.UndocumentedClasses) Types = docTypes.Select(_ => _.Value).ToArray(); unboundTypes = Types.Where(_ => _.ReflectionType == null).ToArray(); if (unboundTypes.Length > 0) Types = Types.Where(_ => _.ReflectionType != null).ToArray(); var unbound = new List<MemberDoc>(); foreach (var type in Types) unbound.AddRange(type.MergeMembersWithReflection(!findOptions.UndocumentedMembers, findOptions.PrivateMembers)); unboundMembers = unbound.ToArray(); }