/// <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: if (reader.Value.TrimStart().StartsWith("#region")) { XmlFoldStart newFoldStartComment = CreateCommentRegionFoldStart(document, reader); stack.Push(newFoldStartComment); } else if (reader.Value.Trim().StartsWith("#endregion")) { XmlFoldStart foldStartComent = stack.Pop(); CreateCommentRegionFold(document, foldMarkers, reader, foldStartComent); } else { 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 CreateCommentRegionFoldStart(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 - 4); newFoldStart.Name = reader.Value.Replace("#region", ""); //if (this.ShowAttributesWhenFolded && reader.HasAttributes) //{ // newFoldStart.Name = String.Concat("<", reader.Name, " ", GetAttributeFoldText(reader), ">"); //} //else //{ // newFoldStart.Name = String.Concat("<", reader.Name, ">"); //} return(newFoldStart); }
/// <summary> /// Creates an XmlFoldStart for the start tag of an element. /// </summary> XmlFoldStart CreateCommentRegionFoldStart(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 - 4); newFoldStart.Name = reader.Value.Replace("#region", ""); 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); } }