Example #1
0
        /// <summary>
        /// Creates the XML open tag string for an XElement.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="options">The comment options used to contruct the tag.</param>
        /// <param name="allowSelfClosing">Whether to allow a self-closing tag or not.</param>
        /// <returns>The XML open tag. In case of an element without value, the tag is self-closing.</returns>
        internal static string CreateXmlOpenTag(System.Xml.Linq.XElement element, CodeCommentOptions options, bool allowSelfClosing = true)
        {
            var builder = new System.Text.StringBuilder();
            builder.Append("<");
            var name = element.Name.LocalName;
            builder.Append(options.XmlTagsToLowerCase ? name.ToLowerInvariant() : name);

            if (element.HasAttributes)
            {
                foreach (var attr in element.Attributes())
                {
                    builder.Append(CodeCommentHelper.Spacer);
                    builder.Append(attr.ToString());
                }
            }

            if (element.IsEmpty && allowSelfClosing)
            {
                if (options.XmlSpaceSingleTags)
                {
                    builder.Append(CodeCommentHelper.Spacer);
                }

                builder.Append("/");
            }

            builder.Append(">");

            var result = builder.ToString();

            return options.XmlKeepTagsTogether ? SpaceToFake(result) : result;
        }
        /// <summary>
        /// Loads the settings.
        /// </summary>
        public override void LoadSettings()
        {
            _options = new CodeCommentOptions(Settings.Default, 4);

            RaisePropertyChangedForAllOptionsProperties();
            UpdatePreviewText();
        }
Example #3
0
        /// <summary>
        /// Reformat all comments between the specified start and end point. Comments that start
        /// within the range, even if they overlap the end are included.
        /// </summary>
        /// <param name="textDocument">The text document.</param>
        /// <param name="start">The start point.</param>
        /// <param name="end">The end point.</param>
        public bool FormatComments(TextDocument textDocument, EditPoint start, EditPoint end)
        {
            var options = new CodeCommentOptions(Settings.Default, _package, textDocument);

            bool foundComments = false;

            while (start.Line <= end.Line)
            {
                if (CodeCommentHelper.IsCommentLine(start))
                {
                    var comment = new CodeComment(start);
                    if (comment.IsValid)
                    {
                        comment.Format(options);
                        foundComments = true;
                    }

                    if (comment.EndPoint != null)
                    {
                        start = comment.EndPoint.CreateEditPoint();
                    }
                }

                if (start.Line == textDocument.EndPoint.Line)
                {
                    break;
                }

                start.LineDown();
                start.StartOfLine();
            }

            return foundComments;
        }
 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();
 }
Example #5
0
        /// <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());
        }
Example #6
0
        public CommentFormatter(ICommentLine line, string commentPrefix, CodeCommentOptions options, Regex regex)
        {
            _builder         = new StringBuilder();
            _currentPosition = 0;
            _options         = options;
            _regex           = regex;
            _isFirstWord     = true;

            // Handle optionally empty prefix.
            if (!string.IsNullOrWhiteSpace(commentPrefix))
            {
                _commentPrefix       = commentPrefix + CodeCommentHelper.Spacer;
                _commentPrefixLength = WordLength(_commentPrefix);
            }
            else
            {
                _commentPrefix       = string.Empty;
                _commentPrefixLength = 0;
            }

            // Special handling for the root XML line, it should not output it's surrounding xml
            // tags, only it's child lines.
            var xml = line as CommentLineXml;

            if (xml != null)
            {
                // On the content of the root, fix the optional alignment of param tags. This is
                // not important if all tags will be broken onto seperate lines anyway.
                if (!options.XmlSplitAllTags && options.XmlAlignParamTags)
                {
                    var paramPhrases = xml.Lines.OfType <CommentLineXml>().Where(p => string.Equals(p.TagName, "param", StringComparison.OrdinalIgnoreCase));
                    if (paramPhrases.Count() > 1)
                    {
                        var longestParam = paramPhrases.Max(p => p.OpenTag.Length);
                        foreach (var phrase in paramPhrases)
                        {
                            phrase.OpenTag = phrase.OpenTag.PadRight(longestParam);
                        }
                    }
                }

                // Process all the lines inside the root XML line.
                foreach (var l in xml.Lines)
                {
                    NewLine();
                    Parse(l);
                }
            }
            else
            {
                // Normal comment line has no child-lines and can be processed normally.
                NewLine();
                Parse(line);
            }
        }
Example #7
0
        /// <summary>
        /// Creates the XML close tag string for an XElement.
        /// </summary>
        /// <param name="element">The element.</param>
        /// <param name="options">The comment options used to contruct the tag.</param>
        /// <param name="allowSelfClosing">Whether to allow a self-closing tag or not.</param>
        /// <returns>
        /// The XML close tag, or <c>null</c> if the element has no value and is a self-closing tag. If self-closing tags are not allowed, a close tag is retrned regardless.
        /// </returns>
        internal static string CreateXmlCloseTag(System.Xml.Linq.XElement element, CodeCommentOptions options, bool allowSelfClosing = true)
        {
            if (element.IsEmpty && allowSelfClosing)
            {
                return null;
            }

            var name = element.Name.LocalName;

            var result = string.Format("</{0}>", options.XmlTagsToLowerCase ? name.ToLowerInvariant() : name);

            return options.XmlKeepTagsTogether ? SpaceToFake(result) : result;
        }
Example #8
0
        /// <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);
        }
Example #9
0
        public CommentLineXml(XElement xml, CodeCommentOptions options)
            : base(null)
        {
            TagName = xml.Name.LocalName;

            // Tags that are forced to be their own line should never be self closing. This prevents
            // empty tags from getting collapsed.
            OpenTag  = CodeCommentHelper.CreateXmlOpenTag(xml, options, false);
            Closetag = CodeCommentHelper.CreateXmlCloseTag(xml, options, false);

            Lines = new List <ICommentLine>();

            _innerText = new StringBuilder();
            ParseChildNodes(xml, options);
            CloseInnerText();
        }
Example #10
0
        public CommentLineXml(XElement xml, CodeCommentOptions options)
            : base(null)
        {
            TagName = xml.Name.LocalName;

            // Tags that are forced to be their own line should never be self closing. This prevents
            // empty tags from getting collapsed.
            OpenTag = CodeCommentHelper.CreateXmlOpenTag(xml, options);
            Closetag = CodeCommentHelper.CreateXmlCloseTag(xml, options);

            Lines = new List<ICommentLine>();

            _innerText = new StringBuilder();
            ParseChildNodes(xml, options);
            CloseInnerText();
        }
Example #11
0
        /// <summary>
        /// Loads the settings.
        /// </summary>
        public override void LoadSettings()
        {
            _options = new CodeCommentOptions(4);

            UpdatePreviewText();
        }
 public static void AssertEqualAfterFormat(string input, CodeCommentOptions options)
 {
     AssertEqualAfterFormat(input, input, options);
 }
Example #13
0
        /// <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;
        }
 public static void AssertEqualAfterFormat(string input, string expected, CodeCommentOptions options)
 {
     var result = Format(input, options);
     Assert.AreEqual(expected, result);
 }
Example #15
0
        private void ParseChildNodes(XElement xml, CodeCommentOptions options)
        {
            if (string.Equals(TagName, "code", StringComparison.OrdinalIgnoreCase))
            {
                // Content of code element should be read literally and preserve whitespace.
                using (var reader = xml.CreateReader())
                {
                    reader.MoveToContent();
                    Content = reader.ReadInnerXml();
                }
            }
            else
            {
                // Loop and parse all child nodes.
                var node = xml.FirstNode;
                while (node != null)
                {
                    // If the node is a sub-element, it needs to be handled seperately.
                    if (node.NodeType == XmlNodeType.Element)
                    {
                        var e = (XElement)node;

                        // All root level elements and certain special sub elements always need to
                        // be on their own line.
                        if (e.Parent == null || e.Parent.Parent == null || NewLineElementNames.Contains(e.Name.LocalName, StringComparer.OrdinalIgnoreCase))
                        {
                            CloseInnerText();
                            Lines.Add(new CommentLineXml(e, options));
                        }
                        else
                        {
                            // If the tag is not forced to be on it's own line, append it to the
                            // current content as string.
                            _innerText.Append(CodeCommentHelper.CreateXmlOpenTag(e, options));

                            if (!e.IsEmpty)
                            {
                                if (options.XmlSpaceTagContent)
                                {
                                    _innerText.Append(CodeCommentHelper.Spacer);
                                }

                                ParseChildNodes(e, options);

                                _innerText.Append(CodeCommentHelper.CreateXmlCloseTag(e, options));
                            }

                            _innerText.Append(CodeCommentHelper.Spacer);
                        }
                    }
                    else
                    {
                        // Always trim trailing
                        var value = node.ToString().TrimEnd(CodeCommentHelper.Spacer);

                        // If the parent is an element, trim the starting spaces.
                        if (node.PreviousNode == null && node.Parent.NodeType == XmlNodeType.Element && !options.XmlSpaceTagContent)
                        {
                            value = value.TrimStart(CodeCommentHelper.Spacer);
                        }

                        _innerText.Append(value);

                        // Add spacing after (almost) each word.
                        if (node.NextNode != null || node.Parent.NodeType != XmlNodeType.Element || options.XmlSpaceTagContent)
                        {
                            _innerText.Append(CodeCommentHelper.Spacer);
                        }
                    }

                    node = node.NextNode;
                }
            }
        }
Example #16
0
        private void ParseChildNodes(XElement xml, CodeCommentOptions options)
        {
            if (string.Equals(TagName, "code", StringComparison.OrdinalIgnoreCase))
            {
                // Content of code element should be read literally and preserve whitespace.
                using (var reader = xml.CreateReader())
                {
                    reader.MoveToContent();
                    Content = reader.ReadInnerXml();
                }
            }
            else
            {
                // Loop and parse all child nodes.
                var node = xml.FirstNode;
                while (node != null)
                {
                    // If the node is a sub-element, it needs to be handled seperately.
                    if (node.NodeType == XmlNodeType.Element)
                    {
                        var e = (XElement)node;

                        // All root level elements and certain special sub elements always need to
                        // be on their own line.
                        if (e.Parent == null || e.Parent.Parent == null || NewLineElementNames.Contains(e.Name.LocalName, StringComparer.OrdinalIgnoreCase))
                        {
                            CloseInnerText();
                            Lines.Add(new CommentLineXml(e, options));
                        }
                        else
                        {
                            // If the tag is not forced to be on it's own line, append it to the
                            // current content as string.
                            _innerText.Append(CodeCommentHelper.CreateXmlOpenTag(e, options));

                            if (!e.IsEmpty)
                            {
                                if (options.XmlSpaceTagContent)
                                {
                                    _innerText.Append(CodeCommentHelper.Spacer);
                                }

                                ParseChildNodes(e, options);

                                _innerText.Append(CodeCommentHelper.CreateXmlCloseTag(e, options));
                            }

                        }
                    }
                    else
                    {
                        // Always trim trailing
                        var value = node.ToString().TrimEnd(CodeCommentHelper.Spacer);

                        // If the parent is an element, trim the starting spaces.
                        if (node.PreviousNode == null && node.Parent.NodeType == XmlNodeType.Element && !options.XmlSpaceTagContent)
                        {
                            value = value.TrimStart(CodeCommentHelper.Spacer);
                        }

                        // If the previous node was an XML element, put a space before the text
                        // unless the first character is interpunction.
                        if (node.PreviousNode != null && node.PreviousNode.NodeType == XmlNodeType.Element)
                        {
                            if (!StartsWithInterpunction(value))
                            {
                                _innerText.Append(CodeCommentHelper.Spacer);
                            }
                        }

                        _innerText.Append(value);

                        // Add spacing after (almost) each word.
                        if (node.NextNode != null || node.Parent.NodeType != XmlNodeType.Element || options.XmlSpaceTagContent)
                        {
                            _innerText.Append(CodeCommentHelper.Spacer);
                        }
                    }

                    node = node.NextNode;
                }
            }
        }
 public static string Format(IEnumerable<string> text, CodeCommentOptions options)
 {
     return Format(string.Join(Environment.NewLine, text), options);
 }