/// <summary> /// Create <see cref="NewFolding"/>s for the specified document. /// </summary> public IEnumerable <NewFolding> CreateNewFoldings(TextDocument document, XmlReader reader, out int firstErrorOffset) { Stack <XmlFoldStart> stack = new Stack <XmlFoldStart>(); List <NewFolding> foldMarkers = new List <NewFolding>(); try { while (reader.Read()) { switch (reader.NodeType) { case XmlNodeType.Element: if (!reader.IsEmptyElement) { XmlFoldStart newFoldStart = CreateElementFoldStart(document, reader); stack.Push(newFoldStart); } break; case XmlNodeType.EndElement: XmlFoldStart foldStart = stack.Pop(); CreateElementFold(document, foldMarkers, reader, foldStart); break; case XmlNodeType.Comment: CreateCommentFold(document, foldMarkers, reader); break; } } firstErrorOffset = -1; } catch (XmlException ex) { // ignore errors at invalid positions (prevent ArgumentOutOfRangeException) if (ex.LineNumber >= 1 && ex.LineNumber <= document.LineCount) { firstErrorOffset = document.GetOffset(ex.LineNumber, ex.LinePosition); } else { firstErrorOffset = 0; } } foldMarkers.Sort((a, b) => a.StartOffset.CompareTo(b.StartOffset)); return(foldMarkers); }
/// <summary> /// Creates an XmlFoldStart for the start tag of an element. /// </summary> XmlFoldStart CreateElementFoldStart(TextDocument document, XmlReader reader) { // Take off 1 from the offset returned // from the xml since it points to the start // of the element name and not the beginning // tag. //XmlFoldStart newFoldStart = new XmlFoldStart(reader.Prefix, reader.LocalName, reader.LineNumber - 1, reader.LinePosition - 2); XmlFoldStart newFoldStart = new XmlFoldStart(); IXmlLineInfo lineInfo = (IXmlLineInfo)reader; newFoldStart.StartLine = lineInfo.LineNumber; newFoldStart.StartOffset = document.GetOffset(newFoldStart.StartLine, lineInfo.LinePosition - 1); if (this.ShowAttributesWhenFolded && reader.HasAttributes) { newFoldStart.Name = String.Concat("<", reader.Name, " ", GetAttributeFoldText(reader), ">"); } else { newFoldStart.Name = String.Concat("<", reader.Name, ">"); } return(newFoldStart); }
/// <summary> /// Create an element fold if the start and end tag are on /// different lines. /// </summary> static void CreateElementFold(TextDocument document, List <NewFolding> foldMarkers, XmlReader reader, XmlFoldStart foldStart) { IXmlLineInfo lineInfo = (IXmlLineInfo)reader; int endLine = lineInfo.LineNumber; if (endLine > foldStart.StartLine) { int endCol = lineInfo.LinePosition + reader.Name.Length + 1; foldStart.EndOffset = document.GetOffset(endLine, endCol); foldMarkers.Add(foldStart); } }