コード例 #1
0
ファイル: CommentFormatter.cs プロジェクト: waodng/VSIX
        /// <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 (!string.IsNullOrEmpty(line.Content))
            {
                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);
        }
コード例 #2
0
        /// <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);
        }
コード例 #3
0
ファイル: CommentFormatter.cs プロジェクト: waodng/VSIX
        /// <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 (!tagOnOwnLine && Settings.Default.Formatting_CommentXmlSpaceTags)
            {
                Append(CodeCommentHelper.Spacer);
            }

            // 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));
        }