// Can be removed if https://github.com/dotnet/roslyn/issues/67 gets resolved // Modeled after Sandcastle implementation: http://tunnelvisionlabs.github.io/SHFB/docs-master/XMLCommentsGuide/html/86453FFB-B978-4A2A-9EB5-70E118CA8073.htm private void ProcessInheritDoc(XElement root, ISymbol currentSymbol, List <XElement> inheritDocElements, HashSet <string> inheritedSymbolCommentIds) { if (inheritDocElements.Count > 0) { // Gather the documents (first in the list takes precedence) List <ISymbol> inheritedSymbols = new List <ISymbol>(); foreach (XElement inheritDocElement in inheritDocElements) { // Remove from the parent inheritDocElement.Remove(); // Locate the appropriate symbol string inheritDocElementCref = inheritDocElement.Attribute("cref")?.Value; if (inheritDocElementCref == null && inheritedSymbolCommentIds.Add(currentSymbol.GetDocumentationCommentId())) { INamedTypeSymbol currentTypeSymbol = currentSymbol as INamedTypeSymbol; IMethodSymbol currentMethodSymbol = currentSymbol as IMethodSymbol; IPropertySymbol currentPropertySymbol = currentSymbol as IPropertySymbol; IEventSymbol currentEventSymbol = currentSymbol as IEventSymbol; if (currentTypeSymbol != null) { // Types and interfaces, inherit from all base types List <INamedTypeSymbol> baseTypeSymbols = AnalyzeSymbolVisitor.GetBaseTypes(currentTypeSymbol) .Where(x => inheritedSymbolCommentIds.Add(x.GetDocumentationCommentId())) .ToList(); if (baseTypeSymbols.Count > 0) { inheritedSymbols.AddRange(baseTypeSymbols); } // Then inherit from all interfaces List <INamedTypeSymbol> interfaceSymbols = currentTypeSymbol.AllInterfaces .Where(x => inheritedSymbolCommentIds.Add(x.GetDocumentationCommentId())) .ToList(); if (interfaceSymbols.Count > 0) { inheritedSymbols.AddRange(interfaceSymbols); } } else if (currentMethodSymbol != null && currentMethodSymbol.Name == currentMethodSymbol.ContainingType.Name) { // Constructor, check base type constructors for the same signature string signature = AnalyzeSymbolVisitor.GetFullName(currentMethodSymbol); signature = signature.Substring(signature.IndexOf('(')); foreach (INamedTypeSymbol baseTypeSymbol in AnalyzeSymbolVisitor.GetBaseTypes(currentMethodSymbol.ContainingType)) { foreach (IMethodSymbol constructorSymbol in baseTypeSymbol.Constructors.Where(x => !x.IsImplicitlyDeclared)) { string constructorSignature = AnalyzeSymbolVisitor.GetFullName(constructorSymbol); constructorSignature = constructorSignature.Substring(constructorSignature.IndexOf('(')); if (signature == constructorSignature && inheritedSymbolCommentIds.Add(constructorSymbol.GetDocumentationCommentId())) { inheritedSymbols.Add(constructorSymbol); } } } } else if (currentMethodSymbol != null) { PopulateInheritedMemberSymbols(currentMethodSymbol, x => x.OverriddenMethod, inheritedSymbolCommentIds, inheritedSymbols); } else if (currentPropertySymbol != null) { PopulateInheritedMemberSymbols(currentPropertySymbol, x => x.OverriddenProperty, inheritedSymbolCommentIds, inheritedSymbols); } else if (currentEventSymbol != null) { PopulateInheritedMemberSymbols(currentEventSymbol, x => x.OverriddenEvent, inheritedSymbolCommentIds, inheritedSymbols); } } else if (inheritDocElementCref != null) { // Explicit cref if (inheritedSymbolCommentIds.Add(inheritDocElementCref)) { ISymbol inheritedSymbol = DocumentationCommentId.GetFirstSymbolForDeclarationId(inheritDocElementCref, _compilation); if (inheritedSymbol != null) { inheritedSymbols.Add(inheritedSymbol); } } } } // Add the inherited comments foreach (ISymbol inheritedSymbol in inheritedSymbols) { string inheritedXml = inheritedSymbol.GetDocumentationCommentXml(expandIncludes: true); if (!string.IsNullOrEmpty(inheritedXml)) { XElement inheritedRoot = GetRootElement(inheritedXml); if (inheritedRoot != null) { // Inherit elements other than <inheritdoc> List <XElement> inheritedInheritDocElements = new List <XElement>(); foreach (XElement inheritedElement in inheritedRoot.Elements()) { if (inheritedElement.Name == "inheritdoc") { inheritedInheritDocElements.Add(inheritedElement); } else { string inheritedElementCref = inheritedElement.Attribute("cref")?.Value; string inheritedElementName = inheritedElement.Attribute("name")?.Value; bool inherit = true; foreach (XElement rootElement in root.Elements(inheritedElement.Name)) { if (inheritedElementCref == null && inheritedElementName == null) { // Don't inherit if the name is the same and there's no distinguishing attributes inherit = false; break; } if (inheritedElementCref != null && inheritedElementCref == rootElement.Attribute("cref")?.Value) { // Don't inherit if the cref attribute is the same inherit = false; break; } if (inheritedElementName != null && inheritedElementName == rootElement.Attribute("name")?.Value) { // Don't inherit if the name attribute is the same inherit = false; break; } } if (inherit) { root.Add(inheritedElement); } } } // Recursively inherit <inheritdoc> if (inheritedInheritDocElements.Count > 0) { ProcessInheritDoc(root, inheritedSymbol, inheritedInheritDocElements, inheritedSymbolCommentIds); } } } } } }
public SymbolDocumentValue(ISymbol symbol, AnalyzeSymbolVisitor visitor) { _symbol = symbol; _visitor = visitor; }
public SymbolDocumentValues(IEnumerable <ISymbol> symbols, AnalyzeSymbolVisitor visitor) { _symbols = symbols ?? Array.Empty <ISymbol>(); _visitor = visitor; }