Exemplo n.º 1
0
        static CMakeDeclarationsFactory()
        {
            // Display subcommands for all commands that have them.
            IEnumerable <CMakeCommandId> triggers =
                CMakeSubcommandMethods.GetMemberSelectionTriggers();

            foreach (CMakeCommandId id in triggers)
            {
                _methods[id] = CreateSubcommandDeclarations;
            }
        }
Exemplo n.º 2
0
 /// <summary>
 /// Get a methods object containing the parameters for a given CMake command.
 /// </summary>
 /// <param name="id">The identifier of a CMake command.</param>
 /// <param name="subcommand">The name of a subcommand or null if none.</param>
 /// <returns>
 /// A methods object or null if there is no parameter information.
 /// </returns>
 public static Methods GetCommandParameters(CMakeCommandId id, string subcommand)
 {
     if (subcommand != null)
     {
         return(CMakeSubcommandMethods.GetSubcommandParameters(id, subcommand));
     }
     if (!_parameters.ContainsKey(id))
     {
         return(null);
     }
     return(new CMakeMethods(id));
 }
Exemplo n.º 3
0
        private static CMakeItemDeclarations CreateSubcommandDeclarations(
            CMakeCommandId id, ParseRequest req, Source source,
            List <string> priorParameters)
        {
            IEnumerable <string> subcommands = CMakeSubcommandMethods.GetSubcommands(id);

            if (subcommands == null)
            {
                return(null);
            }

            CMakeItemDeclarations decls = new CMakeItemDeclarations();

            decls.AddItems(subcommands, CMakeItemDeclarations.ItemType.Command);
            return(decls);
        }
Exemplo n.º 4
0
 public override string GetDataTipText(int line, int col, out TextSpan span)
 {
     CMakeParsing.TokenData tokenData;
     if (_lines != null &&
         CMakeParsing.ParseForToken(_lines, line, col, out tokenData) &&
         !tokenData.InParens)
     {
         if (tokenData.TokenInfo.Token == (int)CMakeToken.Keyword)
         {
             // Get a Quick Info tip for the command at the cursor.
             span = tokenData.TokenInfo.ToTextSpan(line);
             string         lineText  = _lines.ToList()[line];
             string         tokenText = lineText.ExtractToken(tokenData.TokenInfo);
             CMakeCommandId id        = CMakeKeywords.GetCommandId(tokenText);
             if (CMakeSubcommandMethods.HasSubcommands(id))
             {
                 // Parse to get the subcommand, if there is one.
                 CMakeParsing.ParameterInfoResult result =
                     CMakeParsing.ParseForParameterInfo(_lines, line, -1, true);
                 return(CMakeSubcommandMethods.GetSubcommandQuickInfoTip(id,
                                                                         result.SubcommandName));
             }
             return(CMakeMethods.GetCommandQuickInfoTip(id));
         }
         else if (tokenData.TokenInfo.Token == (int)CMakeToken.Identifier)
         {
             // Get a Quick Info tip for the function called at the cursor, if
             // there is one.
             string        lineText   = _lines.ToList()[line];
             string        tokenText  = lineText.ExtractToken(tokenData.TokenInfo);
             List <string> parameters = CMakeParsing.ParseForParameterNames(_lines,
                                                                            tokenText);
             if (parameters != null)
             {
                 span = tokenData.TokenInfo.ToTextSpan(line);
                 return(string.Format("{0}({1})", tokenText,
                                      string.Join(" ", parameters)));
             }
         }
     }
     span = new TextSpan();
     return(null);
 }
Exemplo n.º 5
0
        public void TestQuickInfoTips()
        {
            // Test ordinary commands.
            Assert.AreEqual("if(expression)",
                            CMakeMethods.GetCommandQuickInfoTip(CMakeCommandId.If));
            Assert.AreEqual("set(variable value)",
                            CMakeMethods.GetCommandQuickInfoTip(CMakeCommandId.Set));
            Assert.IsNull(CMakeMethods.GetCommandQuickInfoTip(
                              CMakeCommandId.AddCustomCommand));

            // Test subcommands.
            Assert.AreEqual("cmake_policy(PUSH)",
                            CMakeSubcommandMethods.GetSubcommandQuickInfoTip(
                                CMakeCommandId.CMakePolicy, "PUSH"));
            Assert.AreEqual("export(PACKAGE name)",
                            CMakeSubcommandMethods.GetSubcommandQuickInfoTip(
                                CMakeCommandId.Export, "PACKAGE"));
            Assert.AreEqual("file(READ filename variable)",
                            CMakeSubcommandMethods.GetSubcommandQuickInfoTip(
                                CMakeCommandId.File, "READ"));
            Assert.IsNull(CMakeSubcommandMethods.GetSubcommandQuickInfoTip(
                              CMakeCommandId.Install, "CODE"));
        }
Exemplo n.º 6
0
        public bool ScanTokenAndProvideInfoAboutIt(TokenInfo tokenInfo, ref int state)
        {
            if (_textFile)
            {
                // Don't perform syntax highlighting if the file is an ordinary text
                // file.
                return(false);
            }

            if (GetStringFlag(state) && _offset < _source.Length)
            {
                // If the line begins inside a string token, begin by scanning the rest
                // of the string.
                ScanString(tokenInfo, ref state, false);
                _scannedNonWhitespace = true;
                _lastWhitespace       = false;
                return(true);
            }
            bool bracketComment  = GetBracketCommentFlag(state);
            bool bracketArgument = GetBracketArgumentFlag(state);

            if ((bracketComment || bracketArgument) && _offset < _source.Length)
            {
                // If the line begins inside a bracket comment token, begin by scanning
                // the rest of the bracket comment.
                ScanBracketCommentOrArgument(tokenInfo, bracketComment, ref state);
                _lastWhitespace = true;
                return(true);
            }

            bool originalScannedNonWhitespace = _scannedNonWhitespace;
            bool originalLastWhitespace       = _lastWhitespace;
            int  originalVariableDepth        = GetVariableDepth(state);

            SetVariableDepth(ref state, 0);
            bool noSeparator = GetNoSeparatorFlag(state);

            SetNoSeparatorFlag(ref state, false);
            tokenInfo.Trigger = TokenTriggers.None;
            _lastWhitespace   = false;
            while (_offset < _source.Length)
            {
                if (char.IsWhiteSpace(_source[_offset]))
                {
                    // Scan a whitespace token.
                    tokenInfo.StartIndex = _offset;
                    while (_offset < _source.Length &&
                           char.IsWhiteSpace(_source[_offset]))
                    {
                        _offset++;
                    }
                    tokenInfo.EndIndex = _offset - 1;
                    tokenInfo.Color    = TokenColor.Text;
                    tokenInfo.Token    = (int)CMakeToken.WhiteSpace;
                    CMakeCommandId id = GetLastCommand(state);
                    if (InsideParens(state))
                    {
                        if (!noSeparator)
                        {
                            if (CMakeSubcommandMethods.HasSubcommands(id))
                            {
                                // The first whitespace token after a subcommand marks
                                // the beginning of the parameters.  The remaining
                                // whitespace parameters separate consecutive parameters.
                                if (GetSubcommandParmsFlag(state))
                                {
                                    if (GetNeedSubcommandFlag(state))
                                    {
                                        SetNeedSubcommandFlag(ref state, false);
                                        tokenInfo.Trigger = TokenTriggers.ParameterStart;
                                    }
                                    else if (!originalLastWhitespace)
                                    {
                                        tokenInfo.Trigger = TokenTriggers.ParameterNext;
                                    }
                                }
                            }
                            else if (id == CMakeCommandId.Unspecified ||
                                     GetSeparatorCount(state) > 0)
                            {
                                if (!originalLastWhitespace)
                                {
                                    SetSeparatorCount(ref state,
                                                      GetSeparatorCount(state) - 1);
                                    tokenInfo.Trigger = TokenTriggers.ParameterNext;
                                }
                            }
                        }
                        if (CMakeKeywords.TriggersMemberSelection(id) ||
                            CMakeKeywords.TriggersMemberSelectionOnWhiteSpace(id))
                        {
                            tokenInfo.Trigger |= TokenTriggers.MemberSelect;
                        }
                    }
                    SetNoSeparatorFlag(ref state, true);
                    _lastWhitespace = true;
                    return(true);
                }
                else if (_source[_offset] == '#')
                {
                    // Check if it's a bracket comment.  If so, handle it specially.
                    if (_offset + 1 < _source.Length && _source[_offset + 1] == '[')
                    {
                        int i = _offset + 2;
                        while (i < _source.Length && _source[i] == '=')
                        {
                            i++;
                        }
                        if (i < _source.Length && _source[i] == '[')
                        {
                            SetBracketCommentFlag(ref state, true);
                            ScanBracketCommentOrArgument(tokenInfo, true, ref state);
                            _lastWhitespace = true;
                            return(true);
                        }
                    }

                    // Scan a comment token.
                    tokenInfo.StartIndex = _offset;
                    int endPos = _source.IndexOf('\n', _offset);
                    if (endPos > _offset)
                    {
                        while (endPos < _source.Length - 1 &&
                               (_source[endPos + 1] == '\r' || _source[endPos + 1] == '\n'))
                        {
                            endPos++;
                        }
                    }
                    else
                    {
                        endPos = _source.Length - 1;
                    }
                    tokenInfo.EndIndex = endPos;
                    tokenInfo.Color    = TokenColor.Comment;
                    tokenInfo.Token    = (int)CMakeToken.Comment;
                    _offset            = endPos + 1;
                    SetNoSeparatorFlag(ref state, noSeparator);
                    return(true);
                }

                // If we haven't returned by this point, the token is something other
                // than whitespace.  Therefore, set the flag indicating that a
                // non-whitespace token has been scanned on the current line so that
                // any additional identifier characters at the end won't trigger member
                // selection.  If you add any additional token, ensure that you handle
                // them after this point.
                _scannedNonWhitespace = true;

                if (_source[_offset] == '"')
                {
                    // Scan a string token.
                    ScanString(tokenInfo, ref state, true);
                    return(true);
                }
                else if (_source[_offset] == '(')
                {
                    // Scan an opening parenthesis.
                    if (!InsideParens(state))
                    {
                        CMakeCommandId id = GetLastCommand(state);
                        if (CMakeKeywords.TriggersMemberSelection(id))
                        {
                            tokenInfo.Trigger |= TokenTriggers.MemberSelect;
                            SetNeedSubcommandFlag(ref state, true);
                            SetNoSeparatorFlag(ref state, true);
                        }
                        else
                        {
                            tokenInfo.Trigger |= TokenTriggers.ParameterStart;
                            SetNoSeparatorFlag(ref state, true);
                        }
                    }
                    IncParenDepth(ref state);
                    tokenInfo.StartIndex = _offset;
                    tokenInfo.EndIndex   = _offset;
                    tokenInfo.Color      = TokenColor.Text;
                    tokenInfo.Token      = (int)CMakeToken.OpenParen;
                    tokenInfo.Trigger   |= TokenTriggers.MatchBraces;
                    _offset++;
                    return(true);
                }
                else if (_source[_offset] == ')')
                {
                    // Scan a closing parenthesis.
                    DecParenDepth(ref state);
                    if (GetParenDepth(state) == 0)
                    {
                        SetLastCommand(ref state, CMakeCommandId.Unspecified);
                        SetSeparatorCount(ref state, 0);
                        tokenInfo.Trigger = TokenTriggers.ParameterEnd;
                    }
                    tokenInfo.StartIndex = _offset;
                    tokenInfo.EndIndex   = _offset;
                    tokenInfo.Color      = TokenColor.Text;
                    tokenInfo.Token      = (int)CMakeToken.CloseParen;
                    tokenInfo.Trigger   |= TokenTriggers.MatchBraces;
                    _offset++;
                    return(true);
                }
                else if (char.IsLetter(_source[_offset]) || _source[_offset] == '_' ||
                         (originalVariableDepth == 0 && _source[_offset] == '\\'))
                {
                    // Scan a keyword, identifier, or file name token.
                    bool isFileName = false;
                    bool isNumeric  = false;
                    tokenInfo.StartIndex = _offset;
                    if (_source[_offset] == '\\' && _offset != _source.Length - 1)
                    {
                        // If the identifier starts with an escape sequence, skip over it.
                        _offset++;
                        isFileName = true;
                    }
                    while (_offset < _source.Length - 1)
                    {
                        char ch = _source[_offset + 1];
                        if (ch == '-')
                        {
                            // Variable names may contain hyphens but function names
                            // can't.  There classify an identifier with a hyphen in it
                            // as a numeric identifier.
                            isNumeric = true;
                        }
                        else if (originalVariableDepth == 0 && ScanFileNameChar())
                        {
                            isFileName = true;
                        }
                        else if (!char.IsLetterOrDigit(ch) && ch != '_')
                        {
                            break;
                        }
                        _offset++;
                    }
                    tokenInfo.EndIndex = _offset;
                    _offset++;

                    CMakeCommandId id     = GetLastCommand(state);
                    string         substr = _source.ExtractToken(tokenInfo);
                    if (originalVariableDepth != 0)
                    {
                        // If we're inside curly braces following a dollar sign, treat
                        // the identifier as a variable.
                        tokenInfo.Color = TokenColor.Identifier;
                        tokenInfo.Token = (int)CMakeToken.Variable;
                        SetVariableDepth(ref state, originalVariableDepth);
                    }
                    else if ((id == CMakeCommandId.Set || id == CMakeCommandId.Unset) &&
                             substr.StartsWith("ENV{"))
                    {
                        // Inside a SET or UNSET command, ENV{ indicates an environment
                        // variable.  This token is case-sensitive.
                        SetVariableDepth(ref state, originalVariableDepth + 1);
                        tokenInfo.EndIndex = tokenInfo.StartIndex + 3;
                        tokenInfo.Color    = TokenColor.Identifier;
                        tokenInfo.Token    = (int)CMakeToken.VariableStartSetEnv;
                        _offset            = tokenInfo.EndIndex + 1;
                    }
                    else if (isNumeric)
                    {
                        tokenInfo.Color = TokenColor.Identifier;
                        tokenInfo.Token = (int)CMakeToken.NumericIdentifier;
                    }
                    else if (isFileName)
                    {
                        // If we found characters that aren't valid in an identifier,
                        // treat the token as a file name.
                        tokenInfo.Color = TokenColor.Identifier;
                        tokenInfo.Token = (int)CMakeToken.FileName;
                    }
                    else
                    {
                        // Check whether the string is a keyword or not.
                        string tokenText = _source.ExtractToken(tokenInfo);
                        bool   isKeyword = false;
                        if (!InsideParens(state))
                        {
                            isKeyword = CMakeKeywords.IsCommand(tokenText);
                            id        = CMakeKeywords.GetCommandId(tokenText);
                            SetLastCommand(ref state, id);
                            SetSeparatorCount(ref state,
                                              CMakeMethods.GetParameterCount(id));
                            int count = GetSeparatorCount(state);
                            if (count > 0)
                            {
                                SetSeparatorCount(ref state, count - 1);
                            }
                        }
                        else
                        {
                            isKeyword = CMakeKeywords.IsKeyword(id, tokenText);
                            if (isKeyword)
                            {
                                SetSubcommandParmsFlag(ref state,
                                                       CMakeSubcommandMethods.HasSubcommandParameters(
                                                           id, tokenText));
                            }
                        }
                        tokenInfo.Color = isKeyword ? TokenColor.Keyword :
                                          TokenColor.Identifier;
                        tokenInfo.Token = isKeyword ? (int)CMakeToken.Keyword :
                                          (int)CMakeToken.Identifier;
                    }
                    if (tokenInfo.StartIndex == tokenInfo.EndIndex)
                    {
                        if (!InsideParens(state) && !originalScannedNonWhitespace)
                        {
                            // Trigger member selection if we're not inside parentheses.
                            tokenInfo.Trigger |= TokenTriggers.MemberSelect;
                        }
                        else if (!originalScannedNonWhitespace || originalLastWhitespace)
                        {
                            // Always trigger member selection in response to certain
                            // commands.
                            if (CMakeKeywords.TriggersMemberSelection(id) ||
                                CMakeKeywords.TriggersMemberSelectionOnWhiteSpace(id))
                            {
                                tokenInfo.Trigger |= TokenTriggers.MemberSelect;
                            }
                        }
                    }
                    return(true);
                }
                else if (char.IsDigit(_source[_offset]) || _source[_offset] == '-')
                {
                    // Variable names can start with numbers or hyphens in CMake, but
                    // function names can't.  We'll call these tokens "numeric
                    // identifiers" here and treat them accordingly when parsing.
                    tokenInfo.StartIndex = _offset;
                    bool isFileName = false;
                    while (_offset < _source.Length - 1)
                    {
                        char ch = _source[_offset + 1];
                        if (originalVariableDepth == 0 && ScanFileNameChar())
                        {
                            isFileName = true;
                        }
                        else if (!char.IsLetterOrDigit(ch) && ch != '_')
                        {
                            break;
                        }
                        _offset++;
                    }
                    tokenInfo.EndIndex = _offset;
                    _offset++;
                    tokenInfo.Color = TokenColor.Identifier;
                    if (originalVariableDepth != 0)
                    {
                        tokenInfo.Token = (int)CMakeToken.Variable;
                        SetVariableDepth(ref state, originalVariableDepth);
                    }
                    else if (isFileName)
                    {
                        tokenInfo.Token = (int)CMakeToken.FileName;
                    }
                    else
                    {
                        tokenInfo.Token = (int)CMakeToken.NumericIdentifier;
                    }
                    return(true);
                }
                else if (_source[_offset] == '$')
                {
                    // Scan a variable start token.
                    CMakeToken varToken = _varTokenMap.FirstOrDefault(
                        x => _source.Substring(_offset).StartsWith(x.Value)).Key;
                    tokenInfo.StartIndex = _offset;
                    _offset++;
                    if (varToken != CMakeToken.Unspecified)
                    {
                        if (varToken != CMakeToken.GeneratorStart)
                        {
                            SetVariableDepth(ref state, originalVariableDepth + 1);
                        }
                        tokenInfo.Token   = (int)varToken;
                        tokenInfo.Trigger =
                            TokenTriggers.MemberSelect | TokenTriggers.MatchBraces;
                        _offset += _varTokenMap[varToken].Length - 1;
                    }
                    tokenInfo.EndIndex = _offset - 1;
                    tokenInfo.Color    = TokenColor.Identifier;
                    return(true);
                }
                else if (_source[_offset] == '}')
                {
                    // Scan a variable end token.
                    tokenInfo.StartIndex = _offset;
                    tokenInfo.EndIndex   = _offset;
                    tokenInfo.Color      = TokenColor.Identifier;
                    tokenInfo.Token      = (int)CMakeToken.VariableEnd;
                    tokenInfo.Trigger    = TokenTriggers.MatchBraces;
                    SetVariableDepth(ref state, originalVariableDepth > 0 ?
                                     originalVariableDepth - 1 : 0);
                    _offset++;
                    return(true);
                }
                else if (_source[_offset] == '>')
                {
                    // Scan a generator expression end token.
                    tokenInfo.StartIndex = _offset;
                    tokenInfo.EndIndex   = _offset;
                    tokenInfo.Color      = TokenColor.Identifier;
                    tokenInfo.Token      = (int)CMakeToken.GeneratorEnd;
                    tokenInfo.Trigger    = TokenTriggers.MatchBraces;
                    SetVariableDepth(ref state, originalVariableDepth > 0 ?
                                     originalVariableDepth - 1 : 0);
                    _offset++;
                    return(true);
                }
                else if (_source[_offset] == ':')
                {
                    // Scan a colon.
                    tokenInfo.StartIndex = _offset;
                    tokenInfo.EndIndex   = _offset;
                    tokenInfo.Color      = TokenColor.Identifier;
                    tokenInfo.Token      = (int)CMakeToken.Colon;
                    _offset++;
                    return(true);
                }
                else if (_source[_offset] == '[')
                {
                    // Scan a bracket argument, if it is one.
                    int i = _offset + 1;
                    while (i < _source.Length && _source[i] == '=')
                    {
                        i++;
                    }
                    if (i < _source.Length && _source[i] == '[')
                    {
                        SetBracketArgumentFlag(ref state, true);
                        ScanBracketCommentOrArgument(tokenInfo, false, ref state);
                        _lastWhitespace = false;
                        return(true);
                    }
                }
                _offset++;
            }
            return(false);
        }