/// <summary> /// Check if the open and close tags for an XML line should be on their own lines or not. /// </summary> /// <param name="line"></param> /// <param name="indentlevel"></param> /// <returns><c>true</c> if the tags should be split, otherwise <c>false</c>.</returns> private bool TagsOnOwnLine(CommentLineXml line, int indentlevel) { // Check for splitting all root level tags. if (Settings.Default.Formatting_CommentXmlSplitAllTags && indentlevel <= 1) { return(true); } // Split if there is more than one child line. if (line.Lines.Count > 1) { return(true); } // Split if there is literal content (eg. a code tag). if (line.Content != null) { return(true); } // Split if this is a summary tag and option to split is set. if (Settings.Default.Formatting_CommentXmlSplitSummaryTagToMultipleLines && string.Equals(line.TagName, "summary", StringComparison.OrdinalIgnoreCase)) { return(true); } // Always split on StyleCop SA1633 copyright tag. if (Settings.Default.Formatting_CommentXmlSplitSummaryTagToMultipleLines && string.Equals(line.TagName, "copyright", StringComparison.OrdinalIgnoreCase)) { return(true); } return(false); }
public static string Format(string text, CodeCommentOptions options) { var xml = XElement.Parse(string.Format("<doc>{0}</doc>", text)); var line = new CommentLineXml(xml, options); var regex = CodeCommentHelper.GetCommentRegex("CSharp", false); var formatter = new CommentFormatter(line, string.Empty, options, regex); return formatter.ToString(); }
public static string Format(string text, string prefix) { var xml = XElement.Parse($"<doc>{text}</doc>"); var line = new CommentLineXml(xml); var regex = CodeCommentHelper.GetCommentRegex(CodeLanguage.CSharp, !string.IsNullOrEmpty(prefix)); var formatter = new CommentFormatter(line, prefix, 4, regex); return formatter.ToString(); }
/// <summary> /// Helper function to generate the preview in the options menu. /// </summary> public static string FormatXml(string text, CodeCommentOptions options) { var xml = XElement.Parse(string.Format("<doc>{0}</doc>", text)); var line = new CommentLineXml(xml, options); var regex = CodeCommentHelper.GetCommentRegex("CSharp", false); var formatter = new CommentFormatter(line, "///", options, regex); return(formatter.ToString()); }
/// <summary> /// Helper function to generate the preview in the options menu. /// </summary> public static string FormatXml(string text) { var xml = XElement.Parse($"<doc>{text}</doc>"); var line = new CommentLineXml(xml); var regex = CodeCommentHelper.GetCommentRegex(CodeLanguage.CSharp, false); var formatter = new CommentFormatter(line, "///", 4, regex); return(formatter.ToString()); }
/// <summary> /// Helper function to generate the preview in the options menu. /// </summary> public static string FormatXml(string text) { var xml = XElement.Parse($"<doc>{text}</doc>"); var line = new CommentLineXml(xml); var regex = CodeCommentHelper.GetCommentRegex(CodeLanguage.CSharp, false); var formatter = new CommentFormatter(line, "///", 4, regex); return formatter.ToString(); }
/// <summary> /// Formats the comment. /// </summary> public TextPoint Format() { if (!IsValid) { throw new InvalidOperationException("Cannot format comment, the comment is not valid."); } var originalText = _startPoint.GetText(_endPoint); var matches = _commentLineRegex.Matches(originalText).OfType <Match>().ToArray(); var commentOptions = new CommentOptions { Prefix = matches.First(m => m.Success).Groups["prefix"].Value ?? string.Empty, Regex = CodeCommentHelper.GetCommentRegex(_document.GetCodeLanguage(), false) }; // Concatenate the comment lines without comment prefixes and see if the resulting bit // can be parsed as XML. ICommentLine line = null; var lineTexts = matches.Select(m => m.Groups["line"].Value).ToArray(); var commentText = string.Join(Environment.NewLine, lineTexts); if (commentText.Contains('<')) { try { var xml = XElement.Parse($"<doc>{commentText}</doc>"); line = new CommentLineXml(xml); } catch (System.Xml.XmlException) { // If XML cannot be parsed, comment will be handled as a normal text comment. } } if (line == null) { line = new CommentLine(commentText); } var formatter = new CommentFormatter( line, _formatterOptions, commentOptions); if (!formatter.Equals(originalText)) { var cursor = StartPoint.CreateEditPoint(); cursor.Delete(EndPoint); cursor.Insert(formatter.ToString()); _endPoint = cursor.CreateEditPoint(); } return(EndPoint); }
private static void AlignParamTags(CommentLineXml xml) { var paramPhrases = xml.Lines.OfType <CommentLineXml>().Where(p => string.Equals(p.TagName, "param", StringComparison.OrdinalIgnoreCase)); if (paramPhrases.Count() > 1) { // If param tags are broken into seperate lines there is nothing to align. var paramSplit = paramPhrases.First().TagOptions.Split.HasFlag(XmlTagNewLine.AfterOpen); if (!paramSplit) { var longestParam = paramPhrases.Max(p => p.OpenTag.Length); foreach (var phrase in paramPhrases) { phrase.OpenTag = phrase.OpenTag.PadRight(longestParam); } } } }
/// <returns><c>true</c> if line fitted on single line, <c>false</c> if it wrapped on multiple lines.</returns> private bool ParseXml(CommentLineXml line, int indentLevel = 0) { // All XML lines start on a new line. if (!_isFirstWord) { NewLine(indentLevel); } Append(line.OpenTag); // If this is the StyleCop SA1633 header <copyright> tag, the content should ALWAYS be // indented. So if no indenting is set, fake it. This is done by adding the indenting to // the comment prefix, otherwise it would indent recursively. var isCopyrightTag = indentLevel == 0 && string.Equals(line.TagName, "copyright", StringComparison.OrdinalIgnoreCase); if (isCopyrightTag && Settings.Default.Formatting_CommentXmlValueIndent < 1) { _commentPrefixLength += CodeCommentHelper.CopyrightExtraIndent; _commentPrefix += string.Empty.PadLeft(CodeCommentHelper.CopyrightExtraIndent); } // Increase the indent level. indentLevel++; bool tagOnOwnLine = TagsOnOwnLine(line, indentLevel); if (tagOnOwnLine) { NewLine(indentLevel); } // If the literal content of an XML tag is set, output that content without formatting. if (line.Content != null) { var codeLines = Regex.Split(line.Content.Trim('\r', '\n'), "\n"); for (int i = 0; i < codeLines.Length; i++) { Append(codeLines[i].TrimEnd()); // Append newline for all except the last line. if (i + 1 < codeLines.Length) { NewLine(indentLevel); } } } else { // Loop and parse all content lines, with a little hacky solution for allowing // the parser to know the XML tag length. var xmlTagLength = tagOnOwnLine ? 0 : WordLength(line.OpenTag) + WordLength(line.Closetag); foreach (var l in line.Lines) { // Parse function returns true if it had to wrap lines. If so, we need to // force a newline before the closing tag. tagOnOwnLine |= Parse(l, indentLevel, xmlTagLength); } } indentLevel--; // Undo the indenting hack done for copyright tags. if (isCopyrightTag && Settings.Default.Formatting_CommentXmlValueIndent < 1) { _commentPrefixLength -= CodeCommentHelper.CopyrightExtraIndent; _commentPrefix = _commentPrefix.Substring(0, _commentPrefixLength); } // If opening tag was on own line, do the same for the closing tag. if (tagOnOwnLine && !_isFirstWord) { NewLine(indentLevel); } Append(line.Closetag); return(tagOnOwnLine); }
/// <returns> /// Returns <c>true</c> if the line requests a break afterwards (did not fit on a single /// line), otherwise <c>false</c>. /// </returns> private bool ParseXml(CommentLineXml line, int indentLevel = 0) { // All XML lines start on a new line. if (!_isFirstWord) { NewLine(); } Indent(indentLevel); Append(line.OpenTag); // Self closing tags have no content, skip all further logic and just output. var tagOnOwnLine = TagsOnOwnLine(line, indentLevel); if (line.IsSelfClosing) { if (tagOnOwnLine) { NewLine(); return(false); } return(true); } // If this is the StyleCop SA1633 header <copyright> tag, the content should ALWAYS be // indented. So if no indenting is set, fake it. This is done by adding the indenting to // the comment prefix, otherwise it would indent recursively. var isCopyrightTag = indentLevel == 0 && string.Equals(line.TagName, "copyright", StringComparison.OrdinalIgnoreCase); if (isCopyrightTag && Settings.Default.Formatting_CommentXmlValueIndent < 1) { _commentPrefixLength += CodeCommentHelper.CopyrightExtraIndent; _commentOptions.Prefix += string.Empty.PadLeft(CodeCommentHelper.CopyrightExtraIndent); } // Increase the indent level. indentLevel++; var isLiteralContent = !string.IsNullOrEmpty(line.Content); // If true the tag should be alone on it's own line. tagOnOwnLine |= isLiteralContent; // If the literal content of an XML tag is set, output that content without formatting. if (isLiteralContent) { var literals = line.Content.Trim('\r', '\n').TrimEnd('\r', '\n', '\t', ' ').Split('\n'); for (int i = 0; i < literals.Length; i++) { NewLine(true); Append(literals[i].TrimEnd()); } } else { // If the tag has any child lines and should be on it's own line, put another break. if (tagOnOwnLine && line.Lines.Count > 0) { NewLine(); } // Loop and parse all content lines, with a little hacky solution for allowing the // parser to know the XML tag length. var xmlTagLength = tagOnOwnLine ? 0 : WordLength(line.OpenTag) + WordLength(line.CloseTag); var needBreakBefore = false; foreach (var l in line.Lines) { if (needBreakBefore) { NewLine(); } // Parse function returns true if it had to wrap lines. If so, we need to force a // newline before the closing tag. needBreakBefore = Parse(l, indentLevel, xmlTagLength); tagOnOwnLine |= needBreakBefore; } } indentLevel--; // Undo the indenting hack done for copyright tags. if (isCopyrightTag && Settings.Default.Formatting_CommentXmlValueIndent < 1) { _commentPrefixLength -= CodeCommentHelper.CopyrightExtraIndent; _commentOptions.Prefix = _commentOptions.Prefix.Substring(0, _commentPrefixLength); } // If opening tag was on own line, do the same for the closing tag. if (tagOnOwnLine && !_isFirstWord) { NewLine(); Indent(indentLevel); } else if (Settings.Default.Formatting_CommentXmlSpaceTags) { Append(CodeCommentHelper.Spacer); } Append(line.CloseTag); return(tagOnOwnLine || CommentLineXml.SingleLineElementNames.Contains(line.TagName, StringComparer.OrdinalIgnoreCase)); }
/// <returns> /// Returns <c>true</c> if the line requests a break afterwards (did not fit on a single /// line), otherwise <c>false</c>. /// </returns> private bool FormatXml(CommentLineXml xml) { var isLiteralContent = !string.IsNullOrEmpty(xml.Content); var split = xml.TagOptions.Split; if (isLiteralContent) { // Tags containing literal content with multiple with should always be on their own line. if (xml.Content.Contains('\n')) { split = XmlTagNewLine.Always; } } else if ((split == XmlTagNewLine.Default || split == XmlTagNewLine.Content) && xml.Lines.Count > 1) { // Split always if there is more than one child line. split = XmlTagNewLine.Always; } if (split.HasFlag(XmlTagNewLine.BeforeOpen) && !_isFirstWord) { NewLine(); } Append(xml.TagOptions.KeepTogether ? CodeCommentHelper.FakeToSpace(xml.OpenTag) : xml.OpenTag); // Self closing tags have no content, skip all further logic and just output. if (xml.IsSelfClosing) { if (split.HasFlag(XmlTagNewLine.AfterClose)) { if (!xml.IsLast) { NewLine(); } return(false); } return(true); } if (split.HasFlag(XmlTagNewLine.AfterOpen)) { NewLine(); } // Increase the indenting. _indentAmount += xml.TagOptions.Indent; if (isLiteralContent) { // If the literal content of an XML tag is set, output that content without formatting. var literals = xml.Content.Trim('\r', '\n').TrimEnd('\r', '\n', '\t', ' ').Split('\n'); for (int i = 0; i < literals.Length; i++) { if (i > 0) { NewLine(true); } Append(literals[i].TrimEnd(), true); } } else { // Else output the child lines. var xmlTagLength = WordLength(xml.OpenTag) + WordLength(xml.CloseTag) + (xml.TagOptions.SpaceContent ? 2 : 0); foreach (var line in xml.Lines) { if (!Format(line, xmlTagLength, xml.TagOptions.SpaceContent)) { split |= XmlTagNewLine.BeforeClose | XmlTagNewLine.AfterClose; } } } // Remove the indenting. _indentAmount -= xml.TagOptions.Indent; // If opening tag was on own line, do the same for the closing tag. if (split.HasFlag(XmlTagNewLine.BeforeClose)) { NewLine(); } else if (xml.TagOptions.SpaceContent) { Append(CodeCommentHelper.Spacer); } Append(xml.CloseTag); if (split.HasFlag(XmlTagNewLine.AfterClose)) { //if (!xml.IsLast) { NewLine(); } return(false); } return(true); }
/// <summary> /// Formats the comment. /// </summary> /// <param name="options">The options to be used for formatting.</param> public TextPoint Format(CodeCommentOptions options) { if (!IsValid) { throw new InvalidOperationException("Cannot format comment, the comment is not valid."); } var originalText = _startPoint.GetText(_endPoint); var matches = _commentLineRegex.Matches(originalText).OfType<Match>().ToArray(); var commentPrefix = matches.First(m => m.Success).Groups["prefix"].Value; // Concatenate the comment lines without comment prefixes and see if the resulting bit // can be parsed as XML. ICommentLine line = null; var lineTexts = matches.Select(m => m.Groups["line"].Value).ToArray(); var commentText = string.Join(Environment.NewLine, lineTexts); if (commentText.Contains('<')) { try { var xml = XElement.Parse(string.Format("<doc>{0}</doc>", commentText)); line = new CommentLineXml(xml, options); } catch (System.Xml.XmlException) { // If XML cannot be parsed, comment will be handled as a normal text comment. } } if (line == null) { line = new CommentLine(commentText); } var formatter = new CommentFormatter( line, commentPrefix, options, CodeCommentHelper.GetCommentRegex(_document.Language, false)); if (!formatter.Equals(originalText)) { var cursor = StartPoint.CreateEditPoint(); cursor.Delete(EndPoint); cursor.Insert(formatter.ToString()); _endPoint = cursor.CreateEditPoint(); } return EndPoint; }
/// <summary> /// Helper function to generate the preview in the options menu. /// </summary> public static string FormatXml(string text) { var xml = XElement.Parse(string.Format("<doc>{0}</doc>", text)); var line = new CommentLineXml(xml); var regex = CodeCommentHelper.GetCommentRegex("CSharp", false); var formatter = new CommentFormatter(line, "///", 4, regex); return formatter.ToString(); }