static int ReplaceInheritDocs(ICollection <AssemblyDocument> assemblyDocuments, ICollection <AssemblyDocument> allAssemblyDocuments, IDictionary <string, TypeDoc> typeDocByName, ICollection <string> sortedTypeNames, Action <LogLevel, string> logger) { int count = 0; foreach (var typeName in sortedTypeNames) { TypeDoc typeDoc = typeDocByName[typeName]; while (true) { var inheritDoc = typeDoc.rootElement.Descendants("inheritdoc").FirstOrDefault(); if (inheritDoc == null) { break; } var cref = inheritDoc.Attribute("cref")?.Value; string path = inheritDoc.Parent.GetPath(stop: typeDoc.rootElement); //inheritDoc.RemoveRecurseUp(stop: typeDoc.rootElement); inheritDoc.CleanRemove(); MergeChildElements(assemblyDocuments, allAssemblyDocuments, typeDocByName, typeName, typeDoc, cref: cref, path: path, logger: logger); if (path == null) { MergeMemberElements(assemblyDocuments, allAssemblyDocuments, typeDocByName, typeName, typeDoc, cref: cref, logger: logger); } count++; } foreach (var memberElement in typeDoc.memberElements.ToArray()) { while (true) { var inheritDoc = memberElement.Descendants("inheritdoc").FirstOrDefault(); if (inheritDoc == null) { break; } var cref = inheritDoc.Attribute("cref")?.Value; string path = inheritDoc.Parent.GetPath(stop: memberElement); //inheritDoc.RemoveRecurseUp(stop: memberElement); inheritDoc.CleanRemove(); MergeMemberElements(assemblyDocuments, allAssemblyDocuments, typeDocByName, typeName, typeDoc, cref: cref, memberElementName: MemberElementName.Parse(memberElement), path: path, logger: logger); count++; } } } return(count); }
// Compile assemblies into dictionary of types static IDictionary <string, TypeDoc> Compile(ICollection <AssemblyDocument> assemblyDocuments, string excludeTypesText, Action <LogLevel, string> logger) { var excludeTypes = string.IsNullOrWhiteSpace(excludeTypesText) ? null : excludeTypesText.Split(',').Select(x => x.Trim()).Select(x => x.EndsWith(".*") ? x.Replace(".*", "") : x).ToHashSet(); var result = new Dictionary <string, TypeDoc>(); foreach (var assemblyDocument in assemblyDocuments) { var memberElements = assemblyDocument.xDocument.Descendants("member"); foreach (var memberElement in memberElements) { var memberElementName = MemberElementName.Parse(memberElement); if (!assemblyDocument.typeDataByName.TryGetValue(memberElementName.typeName, out TypeData typeData)) { if (logger != null) { logger(LogLevel.Warn, $"Could not find type '{memberElementName.typeName}'"); } continue; } else if (excludeTypes != null && excludeTypes.Contains(memberElementName.typeName)) { if (logger != null) { logger(LogLevel.Info, $"Excluded type '{memberElementName.typeName}'"); } continue; } if (!result.TryGetValue(typeData.name, out TypeDoc typeDoc)) { var baseTypes = GetBaseTypeDatas(assemblyDocuments, typeData, logger); typeDoc = new TypeDoc(baseTypes); result[typeData.name] = typeDoc; } if (memberElementName.group == "T") { typeDoc.rootElement.Add(memberElement.Elements()); } else { typeDoc.memberElements.Add(memberElement); } } } return(result); }
static ICollection <TypeData> OverrideBaseTypeDatas(ICollection <AssemblyDocument> allAssemblyDocuments, TypeDoc typeDoc, MemberElementName crefMemberElementName, Action <LogLevel, string> logger) { ICollection <TypeData> baseTypes = null; if (crefMemberElementName != null) { foreach (var assemblyDocument in allAssemblyDocuments) { if (assemblyDocument.typeDataByName.TryGetValue(crefMemberElementName.typeName, out TypeData crefTypeData)) { baseTypes = new TypeData[] { crefTypeData }; break; } } } if (baseTypes == null) { baseTypes = typeDoc.baseTypeDatas; } return(baseTypes); }
static void MergeMemberElements(ICollection <AssemblyDocument> assemblyDocuments, ICollection <AssemblyDocument> allAssemblyDocuments, IDictionary <string, TypeDoc> typeDocByName, string typeName, TypeDoc typeDoc, string cref = null, MemberElementName memberElementName = null, string path = null, Action <LogLevel, string> logger = null) { if (logger != null) { logger(LogLevel.Trace, $"MergeMemberElements():typeName={typeName}"); } var crefMemberElementName = string.IsNullOrEmpty(cref) ? null : MemberElementName.Parse(cref); var baseTypeDatas = OverrideBaseTypeDatas(allAssemblyDocuments, typeDoc, crefMemberElementName, logger); var pathParts = path?.Split('/'); foreach (var baseTypeData in baseTypeDatas.Reverse()) { if (typeDocByName.TryGetValue(baseTypeData.name, out TypeDoc baseTypeDoc)) { foreach (var baseMemberElement in baseTypeDoc.memberElements) { var baseMemberElementName = MemberElementName.Parse(baseMemberElement); if (memberElementName == null || (crefMemberElementName != null && crefMemberElementName.Matches(baseMemberElementName)) || (baseMemberElementName.group == memberElementName.group && baseMemberElementName.memberName == memberElementName.memberName)) { var baseTargetElements = baseMemberElement.Select(pathParts); if (baseTargetElements != null && baseTargetElements.Count() > 0) { var newMemberElementName = new MemberElementName(baseMemberElementName.group, typeName, memberElementName != null ? memberElementName.memberName : baseMemberElementName.memberName); var newMemberElementNameText = newMemberElementName.ToString(); XElement matchingMemberElement = null; var matchingMemberElements = typeDoc.memberElements.Where(x => x.Attribute("name").Value == newMemberElementNameText); if (matchingMemberElements.Count() == 0) { matchingMemberElement = new XElement(baseMemberElement); matchingMemberElement.SetAttributeValue("name", newMemberElementNameText); typeDoc.memberElements.Add(matchingMemberElement); } else { var first = matchingMemberElements.First(); var matchingTargetElements = first.Select(pathParts); if (matchingTargetElements == null || matchingTargetElements.Count() == 0 || (matchingTargetElements.Count() == 1 && matchingTargetElements.Single().IsEmpty)) { matchingMemberElement = first; } if (matchingMemberElements.Count() > 1) { logger(LogLevel.Warn, $"Found multiple matching elements where name='{newMemberElementNameText}'"); } } if (matchingMemberElement != null) { matchingMemberElement.CopyFrom(baseMemberElement, pathParts); typeDoc.Changed = true; } } } } } } }
static void MergeChildElements(ICollection <AssemblyDocument> assemblyDocuments, ICollection <AssemblyDocument> allAssemblyDocuments, IDictionary <string, TypeDoc> typeDocByName, string typeName, TypeDoc typeDoc, string cref = null, string path = null, Action <LogLevel, string> logger = null) { if (logger != null) { logger(LogLevel.Trace, $"MergeChildElements():typeName={typeName}"); } var crefMemberElementName = string.IsNullOrEmpty(cref) ? null : MemberElementName.Parse(cref); var baseTypeDatas = OverrideBaseTypeDatas(allAssemblyDocuments, typeDoc, crefMemberElementName, logger); var pathParts = path?.Split('/'); foreach (var baseTypeData in baseTypeDatas.Reverse()) { if (typeDocByName.TryGetValue(baseTypeData.name, out TypeDoc baseTypeDoc)) { var baseTargetElements = baseTypeDoc.rootElement.Select(pathParts); if (baseTargetElements.Count() > 0) { typeDoc.rootElement.CopyFrom(baseTypeDoc.rootElement, pathParts); typeDoc.Changed = true; break; } } } }