// CONSIDER: could add a depth count and just not rewrite below that depth. private XNode[] Rewrite(XNode node, string currentXmlFilePath, CSharpSyntaxNode originatingSyntax) { _cancellationToken.ThrowIfCancellationRequested(); string commentMessage = null; if (node.NodeType == XmlNodeType.Element) { XElement element = (XElement)node; if (ElementNameIs(element, DocumentationCommentXmlNames.IncludeElementName)) { XNode[] rewritten = RewriteIncludeElement(element, currentXmlFilePath, originatingSyntax, out commentMessage); if (rewritten != null) { return rewritten; } } } XContainer container = node as XContainer; if (container == null) { Debug.Assert(commentMessage == null, "How did we get an error comment for a non-container?"); return new XNode[] { node.Copy(copyAttributeAnnotations: false) }; } IEnumerable<XNode> oldNodes = container.Nodes(); // Do this after grabbing the nodes, so we don't see copies of them. container = container.Copy(copyAttributeAnnotations: false); // WARN: don't use node after this point - use container since it's already been copied. if (oldNodes != null) { XNode[] rewritten = RewriteMany(oldNodes.ToArray(), currentXmlFilePath, originatingSyntax); container.ReplaceNodes(rewritten); } // NOTE: we may modify the values of cref attributes, so don't do this until AFTER we've // made a copy. Also, we only care if we're included text - otherwise we've already // processed the cref. if (container.NodeType == XmlNodeType.Element && originatingSyntax != null) { XElement element = (XElement)container; foreach (XAttribute attribute in element.Attributes()) { if (AttributeNameIs(attribute, DocumentationCommentXmlNames.CrefAttributeName)) { BindAndReplaceCref(attribute, originatingSyntax); } else if (AttributeNameIs(attribute, DocumentationCommentXmlNames.NameAttributeName)) { if (ElementNameIs(element, DocumentationCommentXmlNames.ParameterElementName) || ElementNameIs(element, DocumentationCommentXmlNames.ParameterReferenceElementName)) { BindName(attribute, originatingSyntax, isParameter: true); } else if (ElementNameIs(element, DocumentationCommentXmlNames.TypeParameterElementName) || ElementNameIs(element, DocumentationCommentXmlNames.TypeParameterReferenceElementName)) { BindName(attribute, originatingSyntax, isParameter: false); } } } } if (commentMessage == null) { return new XNode[] { container }; // Already copied. } else { XComment failureComment = new XComment(commentMessage); return new XNode[] { failureComment, container }; // Already copied. } }