Ejemplo n.º 1
0
        /// <summary>
        /// Create a <see cref="Comment"/> with the specified text content.
        /// </summary>
        public Comment(string text, CommentFlags flags)
        {
            Text          = text;
            _commentFlags = flags;

            // Default to same line for EOL comments, and separate line for regular comments
            SetNewLines(flags.HasFlag(CommentFlags.EOL) ? 0 : 1);
        }
Ejemplo n.º 2
0
 protected internal void SetCommentFlag(CommentFlags flag, bool value)
 {
     if (value)
     {
         _commentFlags |= flag;
     }
     else
     {
         _commentFlags &= ~flag;
     }
 }
Ejemplo n.º 3
0
        // NOTE: No parse-points are installed for comments - instead, the parser calls the
        //       parsing constructor directly based upon the token type.  This is because we
        //       want to treat entire comments as individual tokens to preserve whitespace.

        /// <summary>
        /// Parse a <see cref="Comment"/>.
        /// </summary>
        public Comment(Parser parser, CodeObject parent)
            : base(parser, parent)
        {
            Token token = parser.Token;

            _prefixSpaceCount = (token.LeadingWhitespace.Length < byte.MaxValue ? (byte)token.LeadingWhitespace.Length : byte.MaxValue);
            string text = token.Text;
            int    start;
            bool   noSpaceAfterDelimiter;

            // Parse a standard '//' comment
            if (text.StartsWith(ParseToken))
            {
                // Keep track of whether or not all '//' are followed by a space
                start = ParseToken.Length;
                noSpaceAfterDelimiter = (start < text.Length && text[start] != ' ');
                _text = text.Substring(start).TrimEnd();

                if (!IsFirstOnLine)
                {
                    // The comment occurred after another token on the same line - it's an EOL comment
                    _commentFlags |= CommentFlags.EOL;
                    parser.NextToken(true);
                }
                else
                {
                    // The comment was on a line by itself - combine with following lines if they're also comments,
                    // and they're compatible - not Doc or block comments, same # of prefix spaces, no special prefix.
                    while (true)
                    {
                        int nextLine = token.LineNumber + 1;
                        token = parser.NextToken(true);
                        if ((token != null) && token.IsComment && token.Text.StartsWith(ParseToken) &&
                            (token.LineNumber == nextLine) && (token.LeadingWhitespace.Length == _prefixSpaceCount) &&
                            (string.IsNullOrEmpty(_text) || CheckForSpecialComment(token.Text.Substring(ParseToken.Length)) == CommentFlags.None))
                        {
                            text  = parser.TokenText;
                            start = ParseToken.Length;
                            if (start < text.Length && text[start] != ' ')
                            {
                                noSpaceAfterDelimiter = true;
                            }
                            _text += "\n" + text.Substring(start).TrimEnd();
                        }
                        else
                        {
                            break;
                        }
                    }

                    // If the comment was left-justified, set the format flag as such so that it will be displayed
                    // at the left margin regardless of the current level of code indentation.
                    if (_prefixSpaceCount == 0)
                    {
                        _formatFlags |= FormatFlags.NoIndentation;
                    }
                }
            }
            else
            {
                // Parse a '/* ... */' block comment
                IsBlock = true;
                noSpaceAfterDelimiter = false;
                bool formatted = true;

                // The parser will pass through everything between the delimiters, so we have to deal with
                // that here by breaking it up into lines, stripping leading spaces and asterisks, and then
                // putting them back together.
                string[] lines = text.Split('\n');
                for (int i = 0; i < lines.Length; ++i)
                {
                    string line        = lines[i];
                    bool   hasBlockEnd = (i == lines.Length - 1 && line.EndsWith(ParseTokenBlockEnd));
                    if (i == 0)
                    {
                        start = ParseTokenBlockStart.Length;
                    }
                    else
                    {
                        // Skip leading spaces on subsequent lines up to the indent of the first line
                        start = Math.Min(_prefixSpaceCount, StringUtil.CharCount(line, ' ', 0));

                        // Special format handling: Skip a leading "*"
                        if (start < line.Length && line[start] == '*' && !(hasBlockEnd && start == line.Length - 2))
                        {
                            ++start;
                        }
                        else if (start < line.Length - 1)
                        {
                            // Special format handling: Skip " *" or "\" if followed by '*' and on the last line (if not part of the ending "*/"),
                            // or "//" (and NOT "///"), or "  " (if followed by a non-space).
                            if ((line[start] == ' ' && line[start + 1] == '*') || (line[start] == '\\' && line[start + 1] == '*' && i == lines.Length - 1))
                            {
                                if (!(hasBlockEnd && start == line.Length - 3))
                                {
                                    start += 2;
                                }
                            }
                            else if ((line[start] == '/' && line[start + 1] == '/' && (start == line.Length - 2 || line[start + 2] != '/')) ||
                                     (line[start] == ' ' && line[start + 1] == ' ' && (start == line.Length - 2 || line[start + 2] != ' ')))
                            {
                                start    += 2;
                                formatted = false;
                            }
                            else
                            {
                                formatted = false;
                            }
                        }
                    }
                    if (start < line.Length && line[start] != ' ')
                    {
                        noSpaceAfterDelimiter = true;
                    }
                    int length = line.Length - start;
                    if (hasBlockEnd)
                    {
                        length -= ParseTokenBlockEnd.Length;
                    }
                    _text += (i == 0 ? "" : "\n") + line.Substring(start, length).TrimEnd();
                }

                if (!formatted)
                {
                    _commentFlags |= CommentFlags.Raw;
                }

                Token nextToken = parser.NextToken(true);

                // If the comment occurred after another token on the same line AND it's a single line block
                // comment AND it's the last token on the line - it's an inline EOL comment.
                if (!IsFirstOnLine && lines.Length == 1 && nextToken.IsFirstOnLine)
                {
                    _commentFlags |= CommentFlags.EOL;
                }
            }

            // If any line is missing a space after the delimiter, then set the special flag indicating that no
            // spaces should be displayed.  Otherwise, remove one column of spaces and add it back when displayed.
            if (noSpaceAfterDelimiter)
            {
                NoSpaceAfterDelimiter = true;
            }
            else
            {
                RemoveSpaces(1);
            }

            SetSpecialFlags();
        }
Ejemplo n.º 4
0
 protected internal void SetSpecialFlags()
 {
     _commentFlags |= CheckForSpecialComment(_text);
 }