예제 #1
0
 private static void ToClassificationInfo(Token token, int start, int length, ICollection<ClassificationInfo> classificationInfo)
 {
     if (token != null && length > 0)
     {
         classificationInfo.Add(new ClassificationInfo(start, length, GetClassificationType(token)));
     }
 }
예제 #2
0
        private static List <System.Management.Automation.Language.Token> GetCommentBlock(System.Management.Automation.Language.Token[] tokens, ref int startIndex)
        {
            List <System.Management.Automation.Language.Token> list = new List <System.Management.Automation.Language.Token>();
            int num = 0x7fffffff;

            for (int i = startIndex; i < tokens.Length; i++)
            {
                System.Management.Automation.Language.Token item = tokens[i];
                if (item.Extent.StartLineNumber > num)
                {
                    startIndex = i;
                    return(list);
                }
                if (item.Kind == TokenKind.Comment)
                {
                    list.Add(item);
                    num = item.Extent.EndLineNumber + 1;
                }
                else if (item.Kind != TokenKind.NewLine)
                {
                    startIndex = i;
                    return(list);
                }
            }
            return(list);
        }
예제 #3
0
 internal ErrorStatementAst(IScriptExtent extent, Token kind, IEnumerable<KeyValuePair<string, Tuple<Token, Ast>>> flags, IEnumerable<Ast> conditions, IEnumerable<Ast> bodies) : base(extent)
 {
     if (kind == null)
     {
         throw PSTraceSource.NewArgumentNullException("kind");
     }
     this.Kind = kind;
     if ((flags != null) && flags.Any<KeyValuePair<string, Tuple<Token, Ast>>>())
     {
         this.Flags = new Dictionary<string, Tuple<Token, Ast>>(StringComparer.OrdinalIgnoreCase);
         foreach (KeyValuePair<string, Tuple<Token, Ast>> pair in flags)
         {
             if (!this.Flags.ContainsKey(pair.Key))
             {
                 this.Flags.Add(pair.Key, pair.Value);
                 if (pair.Value.Item2 != null)
                 {
                     base.SetParent(pair.Value.Item2);
                 }
             }
         }
     }
     if ((conditions != null) && conditions.Any<Ast>())
     {
         this.Conditions = new ReadOnlyCollection<Ast>(conditions.ToArray<Ast>());
         base.SetParents(conditions);
     }
     if ((bodies != null) && bodies.Any<Ast>())
     {
         this.Bodies = new ReadOnlyCollection<Ast>(bodies.ToArray<Ast>());
         base.SetParents(bodies);
     }
 }
예제 #4
0
 internal CompletionAnalysis(Ast ast, Token[] tokens, IScriptPosition cursorPosition, Hashtable options)
 {
     _ast = ast;
     _tokens = tokens;
     _cursorPosition = cursorPosition;
     _options = options;
 }
        private static List<string> GetSingleAstRequiredModules(Ast ast, Token[] tokens)
        {
            List<string> modules = new List<string>();
            List<string> resources = new List<string>();
            var imports = tokens.Where(token =>
                    String.Compare(token.Text, "Import-DscResource", StringComparison.OrdinalIgnoreCase) == 0);

            //
            // Create a function with the same name as Import-DscResource keyword and use powershell
            // argument function binding to emulate Import-DscResource argument binding.
            //
            InitialSessionState initialSessionState = InitialSessionState.Create();
            SessionStateFunctionEntry importDscResourcefunctionEntry = new SessionStateFunctionEntry(
                "Import-DscResource", @"param($Name, $ModuleName)
                if ($ModuleName) 
                {
                    foreach ($m in $ModuleName) { $global:modules.Add($m) }
                } else {
                    foreach ($n in $Name) { $global:resources.Add($n) }
                }
            ");
            initialSessionState.Commands.Add(importDscResourcefunctionEntry);
            initialSessionState.LanguageMode = PSLanguageMode.RestrictedLanguage;
            var moduleVarEntry = new SessionStateVariableEntry("modules", modules, "");
            var resourcesVarEntry = new SessionStateVariableEntry("resources", resources, "");
            initialSessionState.Variables.Add(moduleVarEntry);
            initialSessionState.Variables.Add(resourcesVarEntry);

            using (System.Management.Automation.PowerShell powerShell = System.Management.Automation.PowerShell.Create(initialSessionState))
            {
                foreach (var import in imports)
                {
                    int startOffset = import.Extent.StartOffset;
                    var asts = ast.FindAll(a => IsCandidateForImportDscResourceAst(a, startOffset), true);
                    int longestLen = -1;
                    Ast longestCandidate = null;
                    foreach (var candidatAst in asts)
                    {
                        int curLen = candidatAst.Extent.EndOffset - candidatAst.Extent.StartOffset;
                        if (curLen > longestLen)
                        {
                            longestCandidate = candidatAst;
                            longestLen = curLen;
                        }
                    }
                    // longestCandidate should contain AST for import-dscresource, like "Import-DSCResource -Module x -Name y".
                    if (longestCandidate != null)
                    {
                        string importText = longestCandidate.Extent.Text;
                        // We invoke-command "importText" here. Script injection is prevented:
                        // We checked that file represents a valid AST without errors.
                        powerShell.AddScript(importText);
                        powerShell.Invoke();
                        powerShell.Commands.Clear();
                    }
                }
            }
            modules.AddRange(resources.Select(GetModuleNameForDscResource));
            return modules;
        }
예제 #6
0
        private static List <System.Management.Automation.Language.Token> GetPrecedingCommentBlock(System.Management.Automation.Language.Token[] tokens, int tokenIndex, int proximity)
        {
            List <System.Management.Automation.Language.Token> list = new List <System.Management.Automation.Language.Token>();
            int num = tokens[tokenIndex].Extent.StartLineNumber - proximity;

            for (int i = tokenIndex - 1; i >= 0; i--)
            {
                System.Management.Automation.Language.Token item = tokens[i];
                if (item.Extent.EndLineNumber < num)
                {
                    break;
                }
                if (item.Kind == TokenKind.Comment)
                {
                    list.Add(item);
                    num = item.Extent.StartLineNumber - 1;
                }
                else if (item.Kind != TokenKind.NewLine)
                {
                    break;
                }
            }
            list.Reverse();
            return(list);
        }
예제 #7
0
        /// <summary>
        /// Retrieve completion suggestions
        /// </summary>
        /// <param name="completionWord">Word to complete</param>
        /// <param name="content">Script that we're working with</param>
        /// <param name="lineContent">Content of the current line</param>
        /// <param name="line">Line object from AvaloneEdit</param>
        /// <param name="runbookToken">Token containing the name of the runbook (if not runbook, null)</param>
        /// <param name="position">Caret offset</param>
        /// <param name="triggerChar">Not used</param>
        /// <param name="triggerTag">Counter</param>
        public void GetCompletionData(string completionWord, string content, string lineContent, DocumentLine line, Token runbookToken, int position, char? triggerChar, long triggerTag)
        {
            if (_requestTrigger != 0 && triggerTag <= _requestTrigger)
                return;

            DismissGetCompletionResults();
            ProcessCompletion(content, triggerChar, completionWord, runbookToken, position, triggerTag);
        }
예제 #8
0
 /// <summary>
 /// Get the state of the buffer - the ast, tokens, errors, and position of the cursor
 /// </summary>
 public static void GetBufferState(out Ast ast, out Token[] tokens, out ParseError[] parseErrors, out int cursor)
 {
     _singleton.ParseInput();
     ast = _singleton._ast;
     tokens = _singleton._tokens;
     parseErrors = _singleton._parseErrors;
     cursor = _singleton._current;
 }
 internal ExpandableStringExpressionAst(Token token, string value, string formatString, IEnumerable<ExpressionAst> nestedExpressions) : base(token.Extent)
 {
     this.FormatExpression = formatString;
     this.Value = value;
     this.StringConstantType = StringConstantExpressionAst.MapTokenKindToStringContantKind(token);
     this.NestedExpressions = new ReadOnlyCollection<ExpressionAst>(nestedExpressions.ToArray<ExpressionAst>());
     base.SetParents((IEnumerable<Ast>) this.NestedExpressions);
 }
예제 #10
0
        /// <summary>
        ///     Gets called when the window looses focus. If the inspector window is open, we want to close it at this point.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnLostFocus(object sender, RoutedEventArgs e)
        {
            if (_objectInspector == null)
                return;

            _objectInspector?.Close();
            _currentToken = null;
        }
예제 #11
0
        private void AddSpanForToken(Token token, int spanStart, List<ClassificationInfo> classificationInfo)
        {
            var stringExpandableToken = token as StringExpandableToken;
            if (stringExpandableToken != null && stringExpandableToken.NestedTokens != null)
            {
                AddSpansForStringToken(stringExpandableToken, spanStart, classificationInfo);
            }

            ToClassificationInfo(token, token.Extent.StartOffset + spanStart, token.Extent.EndOffset - token.Extent.StartOffset, classificationInfo);
        }
예제 #12
0
파일: Parser.cs 프로젝트: dfinke/powershell
        /// <summary>
        /// Parse input from the specified file.
        /// </summary>
        /// <param name="fileName">The name of the file to parse.</param>
        /// <param name="tokens">Returns the tokens from parsing the script.</param>
        /// <param name="errors">Returns errors, if any, discovered while parsing the script.</param>
        /// <returns>The <see cref="ScriptBlockAst"/> that represents the input script file.</returns>
        public static ScriptBlockAst ParseFile(string fileName, out Token[] tokens, out ParseError[] errors)
        {
            const string scriptSchemaExtension = ".schema.psm1";
            var parseDscResource = false;
            // If the file has the 'schema.psm1' extension, then it is a 'DSC module file' however we don't actually load the
            // module at parse time so we can't use the normal mechanisms to bind the module name for configuration commands.
            // As an alternative, we extract the base name of the module file and use that as the module name for any keywords exported by this file.
            var parser = new Parser();
            if (!string.IsNullOrEmpty(fileName) && fileName.Length > scriptSchemaExtension.Length && fileName.EndsWith(scriptSchemaExtension, StringComparison.OrdinalIgnoreCase))
            {
                parser._keywordModuleName = Path.GetFileName(fileName.Substring(0, fileName.Length - scriptSchemaExtension.Length));
                parseDscResource = true;
            }

            string scriptContents;
            try
            {
                var esi = new ExternalScriptInfo(fileName, fileName);
                scriptContents = esi.ScriptContents;
            }
            catch (Exception e)
            {
                var emptyExtent = new EmptyScriptExtent();
                var errorMsg = string.Format(CultureInfo.CurrentCulture, ParserStrings.FileReadError, e.Message);
                errors = new[] { new ParseError(emptyExtent, "FileReadError", errorMsg) };
                tokens = Utils.EmptyArray<Token>();
                return new ScriptBlockAst(emptyExtent, null, new StatementBlockAst(emptyExtent, null, null), false);
            }

            var tokenList = new List<Token>();
            ScriptBlockAst result;
            try
            {
                if (!parseDscResource)
                {
                    DynamicKeyword.Push();
                }
                result = parser.Parse(fileName, scriptContents, tokenList, out errors, ParseMode.Default);
            }
            catch (Exception e)
            {
                throw new ParseException(ParserStrings.UnrecoverableParserError, e);
            }
            finally
            {
                if (!parseDscResource)
                {
                    DynamicKeyword.Pop();
                }
            }

            tokens = tokenList.ToArray();
            return result;
        }
예제 #13
0
 internal ErrorStatementAst(IScriptExtent extent, Token kind, IEnumerable<Ast> nestedAsts = null) : base(extent)
 {
     if (kind == null)
     {
         throw PSTraceSource.NewArgumentNullException("kind");
     }
     this.Kind = kind;
     if ((nestedAsts != null) && nestedAsts.Any<Ast>())
     {
         this.NestedAst = new ReadOnlyCollection<Ast>(nestedAsts.ToArray<Ast>());
         base.SetParents(this.NestedAst);
     }
 }
예제 #14
0
파일: PSToken.cs 프로젝트: 40a/PowerShell
 internal PSToken(Token token)
 {
     Type = GetPSTokenType(token);
     _extent = token.Extent;
     if (token is StringToken)
     {
         _content = ((StringToken)token).Value;
     }
     else if (token is VariableToken)
     {
         _content = ((VariableToken)token).VariablePath.ToString();
     }
 }
예제 #15
0
 public BlockStatementAst(IScriptExtent extent, Token kind, StatementBlockAst body) : base(extent)
 {
     if ((kind == null) || (body == null))
     {
         throw PSTraceSource.NewArgumentNullException((kind == null) ? "kind" : "body");
     }
     if ((kind.Kind != TokenKind.Sequence) && (kind.Kind != TokenKind.Parallel))
     {
         throw PSTraceSource.NewArgumentException("kind");
     }
     this.Kind = kind;
     this.Body = body;
     base.SetParent(body);
 }
        /// <summary>
        /// Get the abstract syntax tree, tokens and the cursor position.
        /// </summary>
        /// <param name="script">The active script.</param>
        /// <param name="caretPosition">The caret position.</param>
        /// <param name="ast">The AST to get.</param>
        /// <param name="tokens">The tokens to get.</param>
        /// <param name="cursorPosition">The cursor position to get.</param>
        public static void GetCommandCompletionParameters(string script, int caretPosition, out Ast ast, out Token[] tokens, out IScriptPosition cursorPosition)
        {
            ParseError[] array;
            ast = Tokenize(script, out tokens, out array);
            if (ast != null)
            {
                //HACK: Clone with a new offset using private method... 
                var type = ast.Extent.StartScriptPosition.GetType();
                var method = type.GetMethod("CloneWithNewOffset",
                                            BindingFlags.Instance | BindingFlags.NonPublic,
                                            null,
                                            new[] { typeof(int) }, null);

                cursorPosition = (IScriptPosition)method.Invoke(ast.Extent.StartScriptPosition, new object[] { caretPosition });
                return;
            }
            cursorPosition = null;
        }
예제 #17
0
파일: PSToken.cs 프로젝트: 40a/PowerShell
 /// <summary>
 /// Map a V3 token to a V2 PSTokenType
 /// </summary>
 /// <param name="token">The V3 token</param>
 /// <returns>The V2 PSTokenType</returns>
 public static PSTokenType GetPSTokenType(Token token)
 {
     if ((token.TokenFlags & TokenFlags.CommandName) != 0)
     {
         return PSTokenType.Command;
     }
     if ((token.TokenFlags & TokenFlags.MemberName) != 0)
     {
         return PSTokenType.Member;
     }
     if ((token.TokenFlags & TokenFlags.AttributeName) != 0)
     {
         return PSTokenType.Attribute;
     }
     if ((token.TokenFlags & TokenFlags.TypeName) != 0)
     {
         return PSTokenType.Type;
     }
     return s_tokenKindMapping[(int)token.Kind];
 }
예제 #18
0
        internal static System.Management.Automation.Language.StringConstantType MapTokenKindToStringContantKind(Token token)
        {
            switch (token.Kind)
            {
                case TokenKind.Generic:
                    return System.Management.Automation.Language.StringConstantType.BareWord;

                case TokenKind.StringLiteral:
                    return System.Management.Automation.Language.StringConstantType.SingleQuoted;

                case TokenKind.StringExpandable:
                    return System.Management.Automation.Language.StringConstantType.DoubleQuoted;

                case TokenKind.HereStringLiteral:
                    return System.Management.Automation.Language.StringConstantType.SingleQuotedHereString;

                case TokenKind.HereStringExpandable:
                    return System.Management.Automation.Language.StringConstantType.DoubleQuotedHereString;
            }
            throw PSTraceSource.NewInvalidOperationException();
        }
        /// <summary>
        /// Gets completions for the symbol found in the Ast at 
        /// the given file offset.
        /// </summary>
        /// <param name="scriptAst">
        /// The Ast which will be traversed to find a completable symbol.
        /// </param>
        /// <param name="currentTokens">
        /// The array of tokens corresponding to the scriptAst parameter.
        /// </param>
        /// <param name="fileOffset">
        /// The 1-based file offset at which a symbol will be located.
        /// </param>
        /// <param name="runspace">
        /// The Runspace to use for gathering completions.
        /// </param>
        /// <returns>
        /// A CommandCompletion instance that contains completions for the
        /// symbol at the given offset.
        /// </returns>
        static public CommandCompletion GetCompletions(
            Ast scriptAst, 
            Token[] currentTokens, 
            int fileOffset,
            Runspace runspace)
        {
            var type = scriptAst.Extent.StartScriptPosition.GetType();
            var method = 
                type.GetMethod(
                    "CloneWithNewOffset",
                    BindingFlags.Instance | BindingFlags.NonPublic,
                    null,
                    new[] { typeof(int) }, null);

            IScriptPosition cursorPosition = 
                (IScriptPosition)method.Invoke(
                    scriptAst.Extent.StartScriptPosition, 
                    new object[] { fileOffset });

            CommandCompletion commandCompletion = null;
            if (runspace.RunspaceAvailability == RunspaceAvailability.Available)
            {
                using (System.Management.Automation.PowerShell powerShell = 
                        System.Management.Automation.PowerShell.Create())
                {
                    powerShell.Runspace = runspace;

                    commandCompletion = 
                        CommandCompletion.CompleteInput(
                            scriptAst, 
                            currentTokens, 
                            cursorPosition, 
                            null, 
                            powerShell); 
                }
            }

            return commandCompletion;
        }
예제 #20
0
 private static bool CompleteAgainstStatementFlags(Ast scriptAst, Ast lastAst, Token token, out TokenKind kind)
 {
     Func<Ast, bool> predicate = null;
     kind = TokenKind.Unknown;
     ErrorStatementAst ast = lastAst as ErrorStatementAst;
     if (((ast != null) && (ast.Kind != null)) && (ast.Kind.Kind == TokenKind.Switch))
     {
         kind = TokenKind.Switch;
         return true;
     }
     ScriptBlockAst ast2 = scriptAst as ScriptBlockAst;
     if (((token != null) && (token.Kind == TokenKind.Minus)) && (ast2 != null))
     {
         Tuple<Token, Ast> tuple;
         if (predicate == null)
         {
             predicate = a => IsCursorBeforeExtent(token.Extent.StartScriptPosition, a.Extent);
         }
         Ast parent = AstSearcher.FindAll(ast2, predicate, true).LastOrDefault<Ast>();
         ast = null;
         while (parent != null)
         {
             ast = parent as ErrorStatementAst;
             if (ast != null)
             {
                 break;
             }
             parent = parent.Parent;
         }
         if ((((ast != null) && (ast.Kind != null)) && ((ast.Kind.Kind == TokenKind.Switch) && (ast.Flags != null))) && (ast.Flags.TryGetValue("--%", out tuple) && IsTokenTheSame(tuple.Item1, token)))
         {
             kind = TokenKind.Switch;
             return true;
         }
     }
     return false;
 }
예제 #21
0
 private static bool CompleteAgainstSwitchFile(Ast lastAst, Token tokenBeforeCursor)
 {
     Tuple<Token, Ast> tuple;
     ErrorStatementAst ast = lastAst as ErrorStatementAst;
     if ((((ast != null) && (ast.Flags != null)) && ((ast.Kind != null) && (tokenBeforeCursor != null))) && (ast.Kind.Kind.Equals(TokenKind.Switch) && ast.Flags.TryGetValue("file", out tuple)))
     {
         return (tuple.Item1.Extent.EndOffset == tokenBeforeCursor.Extent.EndOffset);
     }
     if (!(lastAst.Parent is CommandExpressionAst))
     {
         return false;
     }
     PipelineAst parent = lastAst.Parent.Parent as PipelineAst;
     if (parent == null)
     {
         return false;
     }
     ast = parent.Parent as ErrorStatementAst;
     if (((ast == null) || (ast.Kind == null)) || (ast.Flags == null))
     {
         return false;
     }
     return ((ast.Kind.Kind.Equals(TokenKind.Switch) && ast.Flags.TryGetValue("file", out tuple)) && (tuple.Item2 == parent));
 }
예제 #22
0
 public static IEnumerable<DiagnosticRecord> Analyze(ScriptBlockAst scriptBlock, Token[] tokens)
 {
     return ScriptAnalyzer.Instance.AnalyzeSyntaxTree(scriptBlock, tokens, string.Empty);
 }
 /// <summary>
 /// Tokonize the script and get the needed data.
 /// </summary>
 /// <param name="script">The active script.</param>
 /// <param name="tokens">The tokens to get.</param>
 /// <param name="errors">The parse errors to get.</param>
 /// <returns></returns>
 public static Ast Tokenize(string script, out Token[] tokens, out ParseError[] errors)
 {
     Ast result;
     try
     {
         Ast ast = System.Management.Automation.Language.Parser.ParseInput(script, out tokens, out errors);
         result = ast;
     }
     catch (RuntimeException ex)
     {
         var parseError = new ParseError(null, ex.ErrorRecord.FullyQualifiedErrorId, ex.Message);
         errors = new[] { parseError };
         tokens = new Token[0];
         result = null;
     }
     return result;
 }
예제 #24
0
        private void ReallyRender()
        {
            var text = ParseInput();

            int statusLineCount = GetStatusLineCount();
            int j = _initialX + (_bufferWidth * Options.ExtraPromptLineCount);
            var backgroundColor = _initialBackgroundColor;
            var foregroundColor = _initialForegroundColor;
            bool afterLastToken = false;
            int totalBytes = j;
            int bufferWidth = _console.BufferWidth;

            var tokenStack = new Stack<SavedTokenState>();
            tokenStack.Push(new SavedTokenState
            {
                Tokens = _tokens,
                Index = 0,
                BackgroundColor = _initialBackgroundColor,
                ForegroundColor = _initialForegroundColor
            });

            int bufferLineCount;

            try
            {
                _console.StartRender();

                bufferLineCount = ConvertOffsetToCoordinates(text.Length).Y - _initialY + 1 + statusLineCount;
                if (_consoleBuffer.Length != bufferLineCount * bufferWidth)
                {
                    var newBuffer = new CHAR_INFO[bufferLineCount * bufferWidth];
                    Array.Copy(_consoleBuffer, newBuffer, _initialX + (Options.ExtraPromptLineCount * _bufferWidth));
                    if (_consoleBuffer.Length > bufferLineCount * bufferWidth)
                    {
                        int consoleBufferOffset = ConvertOffsetToConsoleBufferOffset(text.Length, _initialX + (Options.ExtraPromptLineCount * _bufferWidth));
                        // Need to erase the extra lines that we won't draw again
                        for (int i = consoleBufferOffset; i < _consoleBuffer.Length; i++)
                        {
                            _consoleBuffer[i] = _space;
                        }
                        _console.WriteBufferLines(_consoleBuffer, ref _initialY);
                    }
                    _consoleBuffer = newBuffer;
                }

                for (int i = 0; i < text.Length; i++)
                {
                    totalBytes = totalBytes % bufferWidth;
                    if (!afterLastToken)
                    {
                        // Figure out the color of the character - if it's in a token,
                        // use the tokens color otherwise use the initial color.
                        var state = tokenStack.Peek();
                        var token = state.Tokens[state.Index];
                        if (i == token.Extent.EndOffset)
                        {
                            if (token == state.Tokens[state.Tokens.Length - 1])
                            {
                                tokenStack.Pop();
                                if (tokenStack.Count == 0)
                                {
                                    afterLastToken = true;
                                    token = null;
                                    foregroundColor = _initialForegroundColor;
                                    backgroundColor = _initialBackgroundColor;
                                }
                                else
                                {
                                    state = tokenStack.Peek();
                                }
                            }

                            if (!afterLastToken)
                            {
                                foregroundColor = state.ForegroundColor;
                                backgroundColor = state.BackgroundColor;

                                token = state.Tokens[++state.Index];
                            }
                        }

                        if (!afterLastToken && i == token.Extent.StartOffset)
                        {
                            GetTokenColors(token, out foregroundColor, out backgroundColor);

                            var stringToken = token as StringExpandableToken;
                            if (stringToken != null)
                            {
                                // We might have nested tokens.
                                if (stringToken.NestedTokens != null && stringToken.NestedTokens.Any())
                                {
                                    var tokens = new Token[stringToken.NestedTokens.Count + 1];
                                    stringToken.NestedTokens.CopyTo(tokens, 0);
                                    // NestedTokens doesn't have an "EOS" token, so we use
                                    // the string literal token for that purpose.
                                    tokens[tokens.Length - 1] = stringToken;

                                    tokenStack.Push(new SavedTokenState
                                    {
                                        Tokens = tokens,
                                        Index = 0,
                                        BackgroundColor = backgroundColor,
                                        ForegroundColor = foregroundColor
                                    });

                                    if (i == tokens[0].Extent.StartOffset)
                                    {
                                        GetTokenColors(tokens[0], out foregroundColor, out backgroundColor);
                                    }
                                }
                            }
                        }
                    }

                    var charToRender = text[i];
                    if (charToRender == '\n')
                    {
                        while ((j % bufferWidth) != 0)
                        {
                            _consoleBuffer[j++] = _space;
                        }

                        for (int k = 0; k < Options.ContinuationPrompt.Length; k++, j++)
                        {
                            _consoleBuffer[j].UnicodeChar = Options.ContinuationPrompt[k];
                            _consoleBuffer[j].ForegroundColor = Options.ContinuationPromptForegroundColor;
                            _consoleBuffer[j].BackgroundColor = Options.ContinuationPromptBackgroundColor;
                        }
                    }
                    else
                    {
                        int size = LengthInBufferCells(charToRender);
                        totalBytes += size;

                        //if there is no enough space for the character at the edge, fill in spaces at the end and
                        //put the character to next line.
                        int filling = totalBytes > bufferWidth ? (totalBytes - bufferWidth) % size : 0;
                        for (int f = 0; f < filling; f++)
                        {
                            _consoleBuffer[j++] = _space;
                            totalBytes++;
                        }

                        if (char.IsControl(charToRender))
                        {
                            _consoleBuffer[j].UnicodeChar = '^';
                            MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor);
                            _consoleBuffer[j].UnicodeChar = (char)('@' + charToRender);
                            MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor);

                        }
                        else if (size > 1)
                        {
                            _consoleBuffer[j].UnicodeChar = charToRender;
                            _consoleBuffer[j].Attributes = (ushort)(_consoleBuffer[j].Attributes |
                                                           (uint)CHAR_INFO_Attributes.COMMON_LVB_LEADING_BYTE);
                            MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor);
                            _consoleBuffer[j].UnicodeChar = charToRender;
                            _consoleBuffer[j].Attributes = (ushort)(_consoleBuffer[j].Attributes |
                                                           (uint)CHAR_INFO_Attributes.COMMON_LVB_TRAILING_BYTE);
                            MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor);
                        }
                        else
                        {
                            _consoleBuffer[j].UnicodeChar = charToRender;
                            MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor);
                        }
                    }
                }
            }
            finally
            {
                _console.EndRender();
            }

            for (; j < (_consoleBuffer.Length - (statusLineCount * _bufferWidth)); j++)
            {
                _consoleBuffer[j] = _space;
            }

            if (_statusLinePrompt != null)
            {
                foregroundColor = _statusIsErrorMessage ? Options.ErrorForegroundColor : _console.ForegroundColor;
                backgroundColor = _statusIsErrorMessage ? Options.ErrorBackgroundColor : _console.BackgroundColor;

                for (int i = 0; i < _statusLinePrompt.Length; i++, j++)
                {
                    _consoleBuffer[j].UnicodeChar = _statusLinePrompt[i];
                    _consoleBuffer[j].ForegroundColor = foregroundColor;
                    _consoleBuffer[j].BackgroundColor = backgroundColor;
                }
                for (int i = 0; i < _statusBuffer.Length; i++, j++)
                {
                    _consoleBuffer[j].UnicodeChar = _statusBuffer[i];
                    _consoleBuffer[j].ForegroundColor = foregroundColor;
                    _consoleBuffer[j].BackgroundColor = backgroundColor;
                }

                for (; j < _consoleBuffer.Length; j++)
                {
                    _consoleBuffer[j] = _space;
                }
            }

            bool rendered = false;
            if (_parseErrors.Length > 0)
            {
                int promptChar = _initialX - 1 + (_bufferWidth * Options.ExtraPromptLineCount);

                while (promptChar >= 0)
                {
                    var c = (char)_consoleBuffer[promptChar].UnicodeChar;
                    if (char.IsWhiteSpace(c))
                    {
                        promptChar -= 1;
                        continue;
                    }

                    ConsoleColor prevColor = _consoleBuffer[promptChar].ForegroundColor;
                    _consoleBuffer[promptChar].ForegroundColor = ConsoleColor.Red;
                    _console.WriteBufferLines(_consoleBuffer, ref _initialY);
                    rendered = true;
                    _consoleBuffer[promptChar].ForegroundColor = prevColor;
                    break;
                }
            }

            if (!rendered)
            {
                _console.WriteBufferLines(_consoleBuffer, ref _initialY);
            }

            PlaceCursor();

            if ((_initialY + bufferLineCount) > (_console.WindowTop + _console.WindowHeight))
            {
                _console.WindowTop = _initialY + bufferLineCount - _console.WindowHeight;
            }

            _lastRenderTime.Restart();
        }
예제 #25
0
        private void ReallyRender()
        {
            _renderForDemoNeeded = false;

            var text = ParseInput();

            int statusLineCount = GetStatusLineCount();
            int bufferLineCount = ConvertOffsetToCoordinates(text.Length).Y - _initialY + 1 + _demoWindowLineCount + statusLineCount;
            int bufferWidth = Console.BufferWidth;
            if (_consoleBuffer.Length != bufferLineCount * bufferWidth)
            {
                var newBuffer = new CHAR_INFO[bufferLineCount * bufferWidth];
                Array.Copy(_consoleBuffer, newBuffer, _initialX + (Options.ExtraPromptLineCount * _bufferWidth));
                if (_consoleBuffer.Length > bufferLineCount * bufferWidth)
                {
                    // Need to erase the extra lines that we won't draw again
                    for (int i = bufferLineCount * bufferWidth; i < _consoleBuffer.Length; i++)
                    {
                        _consoleBuffer[i] = _space;
                    }
                    WriteBufferLines(_consoleBuffer, ref _initialY);
                }
                _consoleBuffer = newBuffer;
            }

            var tokenStack = new Stack<SavedTokenState>();
            tokenStack.Push(new SavedTokenState
            {
                Tokens          = _tokens,
                Index           = 0,
                BackgroundColor = _initialBackgroundColor,
                ForegroundColor = _initialForegroundColor
            });

            int j               = _initialX + (_bufferWidth * Options.ExtraPromptLineCount);
            var backgroundColor = _initialBackgroundColor;
            var foregroundColor = _initialForegroundColor;

            for (int i = 0; i < text.Length; i++)
            {
                // Figure out the color of the character - if it's in a token,
                // use the tokens color otherwise use the initial color.
                var state = tokenStack.Peek();
                var token = state.Tokens[state.Index];
                if (i == token.Extent.EndOffset)
                {
                    if (token == state.Tokens[state.Tokens.Length - 1])
                    {
                        tokenStack.Pop();
                        state = tokenStack.Peek();
                    }
                    foregroundColor = state.ForegroundColor;
                    backgroundColor = state.BackgroundColor;

                    token = state.Tokens[++state.Index];
                }

                if (i == token.Extent.StartOffset)
                {
                    GetTokenColors(token, out foregroundColor, out backgroundColor);

                    var stringToken = token as StringExpandableToken;
                    if (stringToken != null)
                    {
                        // We might have nested tokens.
                        if (stringToken.NestedTokens != null && stringToken.NestedTokens.Any())
                        {
                            var tokens = new Token[stringToken.NestedTokens.Count + 1];
                            stringToken.NestedTokens.CopyTo(tokens, 0);
                            // NestedTokens doesn't have an "EOS" token, so we use
                            // the string literal token for that purpose.
                            tokens[tokens.Length - 1] = stringToken;

                            tokenStack.Push(new SavedTokenState
                            {
                                Tokens          = tokens,
                                Index           = 0,
                                BackgroundColor = backgroundColor,
                                ForegroundColor = foregroundColor
                            });
                        }
                    }
                }

                if (text[i] == '\n')
                {
                    while ((j % bufferWidth) != 0)
                    {
                        _consoleBuffer[j++] = _space;
                    }

                    for (int k = 0; k < Options.ContinuationPrompt.Length; k++, j++)
                    {
                        _consoleBuffer[j].UnicodeChar = Options.ContinuationPrompt[k];
                        _consoleBuffer[j].ForegroundColor = Options.ContinuationPromptForegroundColor;
                        _consoleBuffer[j].BackgroundColor = Options.ContinuationPromptBackgroundColor;
                    }
                }
                else if (char.IsControl(text[i]))
                {
                    _consoleBuffer[j].UnicodeChar = '^';
                    MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor);
                    _consoleBuffer[j].UnicodeChar = (char)('@' + text[i]);
                    MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor);
                }
                else
                {
                    _consoleBuffer[j].UnicodeChar = text[i];
                    MaybeEmphasize(ref _consoleBuffer[j++], i, foregroundColor, backgroundColor);
                }
            }

            for (; j < (_consoleBuffer.Length - ((statusLineCount + _demoWindowLineCount) * _bufferWidth)); j++)
            {
                _consoleBuffer[j] = _space;
            }

            if (_statusLinePrompt != null)
            {
                for (int i = 0; i < _statusLinePrompt.Length; i++, j++)
                {
                    _consoleBuffer[j].UnicodeChar = _statusLinePrompt[i];
                    _consoleBuffer[j].ForegroundColor = Console.ForegroundColor;
                    _consoleBuffer[j].BackgroundColor = Console.BackgroundColor;
                }
                for (int i = 0; i < _statusBuffer.Length; i++, j++)
                {
                    _consoleBuffer[j].UnicodeChar = _statusBuffer[i];
                    _consoleBuffer[j].ForegroundColor = Console.ForegroundColor;
                    _consoleBuffer[j].BackgroundColor = Console.BackgroundColor;
                }

                for (; j < (_consoleBuffer.Length - (_demoWindowLineCount * _bufferWidth)); j++)
                {
                    _consoleBuffer[j] = _space;
                }
            }

            if (_demoMode)
            {
                RenderDemoWindow(j);
            }

            bool rendered = false;
            if (_parseErrors.Length > 0)
            {
                int promptChar = _initialX - 1 + (_bufferWidth * Options.ExtraPromptLineCount);

                while (promptChar >= 0)
                {
                    if (char.IsSymbol((char)_consoleBuffer[promptChar].UnicodeChar))
                    {
                        ConsoleColor prevColor = _consoleBuffer[promptChar].ForegroundColor;
                        _consoleBuffer[promptChar].ForegroundColor = ConsoleColor.Red;
                        WriteBufferLines(_consoleBuffer, ref _initialY);
                        rendered = true;
                        _consoleBuffer[promptChar].ForegroundColor = prevColor;
                        break;
                    }
                    promptChar -= 1;
                }
            }

            if (!rendered)
            {
                WriteBufferLines(_consoleBuffer, ref _initialY);
            }

            PlaceCursor();

            if ((_initialY + bufferLineCount + (_demoMode ? 1 : 0)) > (Console.WindowTop + Console.WindowHeight))
            {
                Console.WindowTop = _initialY + bufferLineCount + (_demoMode ? 1 : 0) - Console.WindowHeight;
            }

            _lastRenderTime.Restart();
        }
예제 #26
0
        private static bool IsTokenTheSame(Token x, Token y)
        {
            if (x.Kind == y.Kind && x.TokenFlags == y.TokenFlags &&
                x.Extent.StartLineNumber == y.Extent.StartLineNumber &&
                x.Extent.StartColumnNumber == y.Extent.StartColumnNumber &&
                x.Extent.EndLineNumber == y.Extent.EndLineNumber &&
                x.Extent.EndColumnNumber == y.Extent.EndColumnNumber)
            {
                return true;
            }

            return false;
        }
예제 #27
0
        private static bool CompleteAgainstStatementFlags(Ast scriptAst, Ast lastAst, Token token, out TokenKind kind)
        {
            kind = TokenKind.Unknown;

            // Handle "switch -f<tab>"
            var errorStatement = lastAst as ErrorStatementAst;
            if (errorStatement != null && errorStatement.Kind != null)
            {
                switch (errorStatement.Kind.Kind)
                {
                    case TokenKind.Switch:
                        kind = TokenKind.Switch;
                        return true;
                    default:
                        break;
                }
            }

            // Handle "switch -<tab>". Skip cases like "switch ($a) {} -<tab> "
            var scriptBlockAst = scriptAst as ScriptBlockAst;
            if (token != null && token.Kind == TokenKind.Minus && scriptBlockAst != null)
            {
                var asts = AstSearcher.FindAll(scriptBlockAst, ast => IsCursorAfterExtent(token.Extent.StartScriptPosition, ast.Extent), searchNestedScriptBlocks: true);

                Ast last = asts.LastOrDefault();
                errorStatement = null;

                while (last != null)
                {
                    errorStatement = last as ErrorStatementAst;
                    if (errorStatement != null) { break; }
                    last = last.Parent;
                }

                if (errorStatement != null && errorStatement.Kind != null)
                {
                    switch (errorStatement.Kind.Kind)
                    {
                        case TokenKind.Switch:

                            Tuple<Token, Ast> value;
                            if (errorStatement.Flags != null && errorStatement.Flags.TryGetValue(Parser.VERBATIM_ARGUMENT, out value))
                            {
                                if (IsTokenTheSame(value.Item1, token))
                                {
                                    kind = TokenKind.Switch;
                                    return true;
                                }
                            }
                            break;

                        default:
                            break;
                    }
                }
            }

            return false;
        }
예제 #28
0
 /// <summary>
 /// Split the text in the comment token into multiple lines, appending commentLines.
 /// </summary>
 /// <param name="comment">A single line or multiline comment token</param>
 /// <param name="commentLines"></param>
 private static void CollectCommentText(Token comment, List<string> commentLines)
 {
     string text = comment.Text;
     CollectCommentText(text, commentLines);
 }
예제 #29
0
 private static void CollectCommentText(System.Management.Automation.Language.Token comment, List <string> commentLines)
 {
     CollectCommentText(comment.Text, commentLines);
 }
예제 #30
0
        private void GetTokenColors(Token token, out ConsoleColor foregroundColor, out ConsoleColor backgroundColor)
        {
            switch (token.Kind)
            {
            case TokenKind.Comment:
                foregroundColor = _options.CommentForegroundColor;
                backgroundColor = _options.CommentBackgroundColor;
                return;

            case TokenKind.Parameter:
                foregroundColor = _options.ParameterForegroundColor;
                backgroundColor = _options.ParameterBackgroundColor;
                return;

            case TokenKind.Variable:
            case TokenKind.SplattedVariable:
                foregroundColor = _options.VariableForegroundColor;
                backgroundColor = _options.VariableBackgroundColor;
                return;

            case TokenKind.StringExpandable:
            case TokenKind.StringLiteral:
            case TokenKind.HereStringExpandable:
            case TokenKind.HereStringLiteral:
                foregroundColor = _options.StringForegroundColor;
                backgroundColor = _options.StringBackgroundColor;
                return;

            case TokenKind.Number:
                foregroundColor = _options.NumberForegroundColor;
                backgroundColor = _options.NumberBackgroundColor;
                return;
            }

            if ((token.TokenFlags & TokenFlags.CommandName) != 0)
            {
                foregroundColor = _options.CommandForegroundColor;
                backgroundColor = _options.CommandBackgroundColor;
                return;
            }

            if ((token.TokenFlags & TokenFlags.Keyword) != 0)
            {
                foregroundColor = _options.KeywordForegroundColor;
                backgroundColor = _options.KeywordBackgroundColor;
                return;
            }

            if ((token.TokenFlags & (TokenFlags.BinaryOperator | TokenFlags.UnaryOperator | TokenFlags.AssignmentOperator)) != 0)
            {
                foregroundColor = _options.OperatorForegroundColor;
                backgroundColor = _options.OperatorBackgroundColor;
                return;
            }

            if ((token.TokenFlags & TokenFlags.TypeName) != 0)
            {
                foregroundColor = _options.TypeForegroundColor;
                backgroundColor = _options.TypeBackgroundColor;
                return;
            }

            if ((token.TokenFlags & TokenFlags.MemberName) != 0)
            {
                foregroundColor = _options.MemberForegroundColor;
                backgroundColor = _options.MemberBackgroundColor;
                return;
            }

            foregroundColor = _options.DefaultTokenForegroundColor;
            backgroundColor = _options.DefaultTokenBackgroundColor;
        }
예제 #31
0
파일: Words.cs 프로젝트: joonro/PSReadLine
 static bool OffsetWithinToken(int offset, Token token)
 {
     return offset < token.Extent.EndOffset && offset >= token.Extent.StartOffset;
 }
예제 #32
0
 private static bool IsInterestingToken(Token token)
 {
     return token.Kind != TokenKind.NewLine && token.Kind != TokenKind.EndOfInput;
 }
        private static List<string> GetRequiredModulesFromAst(Ast ast, Token[] tokens)
        {
            List<string> modules = new List<string>();

            // We use System.Management.Automation.Language.Parser to extract required modules from ast, 
            // but format of ast is a bit tricky and have changed in time.
            //
            // There are two place where 'Import-DscResource' keyword can appear:
            // 1) 
            // Configuration Foo {
            //   Import-DscResource ....  # outside node
            //   Node Bar {...}
            // }
            // 2)
            // Configuration Foo {
            //   Node Bar {
            //     Import-DscResource .... # inside node
            //     ...
            //   }
            // }
            // 
            // The old version of System.Management.Automation.Language.Parser produces slightly different AST for the first case.
            // In new version, Configuration corresponds to ConfigurationDefinitionAst.
            // In old version is's a generic CommandAst with specific commandElements which capture top-level Imports (case 1).
            // In new version all imports correspond to their own CommandAsts, same for case 2 in old version. 

            // Old version, case 1:
            IEnumerable<CommandAst> legacyConfigurationAsts = ast.FindAll(IsLegacyAstConfiguration, true).Select(x => (CommandAst)x);
            foreach (var legacyConfigurationAst in legacyConfigurationAsts)
            {
                // Note: these two sequences are translated to same AST:
                //
                // Import-DscResource -Module xComputerManagement; Import-DscResource -Name xComputer
                // Import-DscResource -Module xComputerManagement -Name xComputer
                //
                // We cannot distinguish different imports => cannot ignore resource names for imports with specified modules.
                // So we process everything: ModuleDefinition and ResourceDefinition.

                // Example: Import-DscResource -Module xPSDesiredStateConfiguration
                modules.AddRange(GetLegacyTopLevelParametersFromAst(legacyConfigurationAst, "ModuleDefinition"));
                // Example: Import-DscResource -Name MSFT_xComputer
                modules.AddRange(GetLegacyTopLevelParametersFromAst(legacyConfigurationAst, "ResourceDefinition").Select(GetModuleNameForDscResource));    
            }
            
            // Both cases in new version and 2nd case in old version:
            modules.AddRange(GetSingleAstRequiredModules(ast, tokens));

            return modules.Distinct().ToList();
        }