private static IScriptExtent GetExtentFromConstant(string value, IScriptExtent source)
        {
            string startLine        = null;
            int    newLineCount     = 1;
            int    positionInColumn = 1;
            int    lastNewLineIndex = -1;

            for (int i = 0; i < value.Length; i++)
            {
                switch (value[i])
                {
                case '\n':
                    if (startLine == null)
                    {
                        startLine = value.Substring(0, i + 1);
                    }

                    lastNewLineIndex = i;
                    newLineCount++;
                    positionInColumn = 1;
                    break;

                case '\r':
                    break;

                default:
                    positionInColumn++;
                    break;
                }
            }

            if (startLine == null)
            {
                startLine = value;
            }

            IScriptPosition oldStart   = source.StartScriptPosition;
            string          fullScript = oldStart.GetFullScript();

            string endLine =
                lastNewLineIndex > -1
                    ? value.Substring(lastNewLineIndex + 1, value.Length - lastNewLineIndex)
                    : value;

            var start = new ScriptPosition(
                oldStart.File,
                1,
                1,
                startLine,
                fullScript);

            var end = new ScriptPosition(
                oldStart.File,
                newLineCount,
                positionInColumn,
                endLine,
                fullScript);

            return(new ScriptExtent(start, end));
        }
Exemplo n.º 2
0
        public static Ast GetContainingAstOfPosition(Ast fullAst, IScriptPosition position)
        {
            var visitor = new FindAstFromPositionVisitor(position);

            fullAst.Visit(visitor);
            return(visitor.GetAst());
        }
Exemplo n.º 3
0
 internal CompletionAnalysis(Ast ast, Token[] tokens, IScriptPosition cursorPosition, Hashtable options)
 {
     this._ast            = ast;
     this._tokens         = tokens;
     this._cursorPosition = cursorPosition;
     this._options        = options;
 }
Exemplo n.º 4
0
        private StatementAst CreateProcessedMessage(IScriptPosition position, ConsoleColor dashColor, Type astType)
        {
            ExpressionAst traceInvocation = InvokeMember(
                isStatic: true,
                Type(typeof(SequencePointTracer)),
                nameof(SequencePointTracer.TraceExpression),
                Variable("Host"),
                Member(Type(typeof(ConsoleColor)), dashColor.ToString(), isStatic: true),
                Type(astType),
                Variable(StackVariable),
                Constant(position.LineNumber),
                Constant(position.ColumnNumber),
                Index(
                    Array(
                        Pipeline(
                            CommandExpression(
                                ArrayLiteral(Variable(TempVariable))))),
                    Constant(0)),
                Variable("false"));

            return(Pipeline(CommandExpression(traceInvocation)));
            // var prefix = Add(CreateDashString(), String("< {0}"));
            // var message = Format(prefix, Variable(TempVariable));
            // return Pipeline(
            //     Command(
            //         WriteHost,
            //         message,
            //         CommandParameter("ForegroundColor"),
            //         String(dashColor.ToString())));
        }
Exemplo n.º 5
0
 internal CompletionAnalysis(Ast ast, Token[] tokens, IScriptPosition cursorPosition, Hashtable options)
 {
     _ast = ast;
     _tokens = tokens;
     _cursorPosition = cursorPosition;
     _options = options;
 }
Exemplo n.º 6
0
        private static Tuple <string, int, int> GetInputAndCursorFromAst(IScriptPosition cursorPosition)
        {
            string line = cursorPosition.Line;
            int    num  = cursorPosition.ColumnNumber - 1;
            int    num2 = cursorPosition.Offset - num;

            return(Tuple.Create <string, int, int>(line.Substring(0, num), num, num2));
        }
Exemplo n.º 7
0
        private static Collection <CompletionResult> GetCompletions(
            Ast ast,
            IReadOnlyList <Token> tokens,
            IScriptPosition cursorPosition,
            Hashtable options,
            out bool clobberCompletions)
        {
            KeywordResult?result = GetCurrentKeyword(ast, tokens, cursorPosition);

            Token lastToken = result?.Frame.ParentContext?.LastToken;

            if (lastToken is null)
            {
                clobberCompletions = false;
                return(null);
            }

            KeywordResult keyword = result.Value;

            switch (lastToken.Kind)
            {
            case TokenKind.NewLine:
            case TokenKind.Semi:
            case TokenKind.Pipe:
            case TokenKind.LParen:
            case TokenKind.LCurly:
            case TokenKind.AtParen:
            case TokenKind.DollarParen:
                clobberCompletions = false;
                return(CompleteKeywords(keyword));

            case TokenKind.Identifier:
            case TokenKind.Command:
                if (keyword.Frame.ParentContext.HasCommandAtPosition(cursorPosition))
                {
                    clobberCompletions = false;
                    return(CompleteKeywords(keyword));
                }

                clobberCompletions = true;
                return(CompleteParameters(keyword, cursorPosition));

            case TokenKind.Generic:
                if (lastToken.Extent.EndOffset == cursorPosition.Offset)
                {
                    clobberCompletions = true;
                    return(CompleteParameters(keyword, cursorPosition));
                }
                break;

            case TokenKind.Parameter:
                clobberCompletions = true;
                return(CompleteParameters(keyword, cursorPosition));
            }

            clobberCompletions = false;
            return(null);
        }
Exemplo n.º 8
0
        public static KeywordContext BuildFromInput(
            Ast ast,
            IReadOnlyList <Token> tokens,
            IScriptPosition cursorPosition)
        {
            // Now find the AST we're in
            CompletionPositionContext positionContext = GetEffectiveScriptPosition(cursorPosition, tokens);

            Ast containingAst = FindAstFromPositionVisitor.GetContainingAstOfPosition(ast, positionContext.LastNonNewlineToken.Extent.EndScriptPosition);

            if (containingAst is null)
            {
                return(null);
            }

            // Find the command AST that we're in
            CommandAst containingCommandAst = GetFirstParentCommandAst(containingAst);

            var context = new KeywordContext
            {
                ContainingAst        = containingAst,
                ContainingCommandAst = containingCommandAst,
                FullAst                = ast,
                LastTokenIndex         = positionContext.LastTokenIndex,
                LastToken              = positionContext.LastToken,
                LastNonNewlineToken    = positionContext.LastNonNewlineToken,
                EffectivePositionToken = positionContext.EffectivePositionToken,
                Tokens   = tokens,
                Position = cursorPosition
            };

            // Build a list of the keyword ASTs we're in going up
            Ast currAst     = containingAst;
            var commandAsts = new List <CommandAst>();

            do
            {
                if (currAst is CommandAst commandAst)
                {
                    commandAsts.Add(commandAst);
                }

                currAst = currAst.Parent;
            } while (currAst != null);

            // Then build the context list going back down
            var keywordStack = new List <KeywordContextFrame>(commandAsts.Count);
            int frameIndex   = 0;

            for (int i = commandAsts.Count - 1; i >= 0; i--)
            {
                keywordStack.Add(new KeywordContextFrame(context, frameIndex, commandAsts[i]));
                frameIndex++;
            }
            context.KeywordStack = keywordStack;

            return(context);
        }
Exemplo n.º 9
0
        private static CommandCompletion CompleteInputImpl(Ast ast, Token[] tokens, IScriptPosition positionOfCursor, Hashtable options)
        {
            PowerShell powershell        = PowerShell.Create(RunspaceMode.CurrentRunspace);
            int        replacementIndex  = -1;
            int        replacementLength = -1;
            List <CompletionResult> list = null;

            if (NeedToInvokeLegacyTabExpansion(powershell))
            {
                Tuple <string, int, int> inputAndCursorFromAst = GetInputAndCursorFromAst(positionOfCursor);
                list              = InvokeLegacyTabExpansion(powershell, inputAndCursorFromAst.Item1, inputAndCursorFromAst.Item2, false, out replacementIndex, out replacementLength);
                replacementIndex += inputAndCursorFromAst.Item3;
            }
            if ((list == null) || (list.Count == 0))
            {
                ExecutionContext executionContextFromTLS = LocalPipeline.GetExecutionContextFromTLS();
                MutableTuple     tuple2 = null;
                foreach (CallStackFrame frame in executionContextFromTLS.Debugger.GetCallStack())
                {
                    dynamic obj2  = PSObject.AsPSObject(frame);
                    var     site1 = CallSite <Func <CallSite, object, bool> > .Create(Binder.UnaryOperation(CSharpBinderFlags.None, ExpressionType.IsTrue, typeof(CommandCompletion), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }));

                    if (site1.Target(site1, obj2.Command.Equals("TabExpansion2", StringComparison.OrdinalIgnoreCase)))
                    {
                        tuple2 = frame.FunctionContext._localsTuple;
                        break;
                    }
                }
                SessionStateScope currentScope = null;
                if (tuple2 != null)
                {
                    currentScope = executionContextFromTLS.EngineSessionState.CurrentScope;
                    SessionStateScope parent = executionContextFromTLS.EngineSessionState.CurrentScope;
                    while ((parent != null) && (parent.LocalsTuple != tuple2))
                    {
                        parent = parent.Parent;
                    }
                    if (parent != null)
                    {
                        executionContextFromTLS.EngineSessionState.CurrentScope = parent.Parent;
                    }
                }
                try
                {
                    list = new CompletionAnalysis(ast, tokens, positionOfCursor, options).GetResults(powershell, out replacementIndex, out replacementLength);
                }
                finally
                {
                    if (currentScope != null)
                    {
                        executionContextFromTLS.EngineSessionState.CurrentScope = currentScope;
                    }
                }
            }
            return(new CommandCompletion(new Collection <CompletionResult>(list ?? EmptyCompletionResult), -1, replacementIndex, replacementLength));
        }
Exemplo n.º 10
0
        /// <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 =
#if NanoServer
                type.GetMethod(
                    "CloneWithNewOffset",
                    BindingFlags.Instance | BindingFlags.NonPublic);
#else
                type.GetMethod(
                    "CloneWithNewOffset",
                    BindingFlags.Instance | BindingFlags.NonPublic,
                    null,
                    new[] { typeof(int) }, null);
#endif

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

            Logger.Write(
                LogLevel.Verbose,
                string.Format(
                    "Getting completions at offset {0} (line: {1}, column: {2})",
                    fileOffset,
                    cursorPosition.LineNumber,
                    cursorPosition.ColumnNumber));

            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);
        }
Exemplo n.º 11
0
        private static CompletionPositionContext GetEffectiveScriptPosition(
            IScriptPosition cursorPosition,
            IReadOnlyList <Token> tokens)
        {
            // Go backward through the tokens to determine if we're positioned where a new command should be
            Token lastToken      = null;
            int   lastTokenIndex = -1;

            for (int i = tokens.Count - 1; i >= 0; i--)
            {
                Token currToken = tokens[i];

                if (currToken.Extent.EndScriptPosition.LineNumber < cursorPosition.LineNumber ||
                    (currToken.Extent.EndScriptPosition.LineNumber == cursorPosition.LineNumber &&
                     currToken.Extent.EndScriptPosition.ColumnNumber <= cursorPosition.ColumnNumber))
                {
                    if (lastToken == null)
                    {
                        lastTokenIndex = i;
                        lastToken      = currToken;
                        break;
                    }
                }
            }

            if (lastToken.Kind != TokenKind.NewLine)
            {
                return(new CompletionPositionContext(lastToken, lastToken, lastToken, lastTokenIndex));
            }

            // Go through and find the first token before us that isn't a newline.
            // When the cursor is at the end of an open scriptblock
            // it falls beyond that scriptblock's extent,
            // meaning we must backtrack to find the real context for a completion
            Token lastNonNewlineToken  = null;
            Token firstEndNewlineToken = lastToken;

            for (int i = lastTokenIndex; i >= 0; i--)
            {
                Token currToken = tokens[i];
                if (currToken.Kind != TokenKind.NewLine)
                {
                    lastNonNewlineToken = currToken;
                    break;
                }

                // This becomes the last token we saw moving backward
                // So when we see a non-newline token, this is the one just after that
                firstEndNewlineToken = currToken;
            }

            return(new CompletionPositionContext(lastToken, lastNonNewlineToken, firstEndNewlineToken, lastTokenIndex));
        }
Exemplo n.º 12
0
        public static Tuple <Ast, Token[], IScriptPosition> MapStringInputToParsedInput(string input, int cursorIndex)
        {
            Token[]      tokenArray;
            ParseError[] errorArray;
            if (cursorIndex > input.Length)
            {
                throw PSTraceSource.NewArgumentException("cursorIndex");
            }
            ScriptBlockAst  ast      = Parser.ParseInput(input, out tokenArray, out errorArray);
            IScriptPosition position = ((InternalScriptPosition)ast.Extent.StartScriptPosition).CloneWithNewOffset(cursorIndex);

            return(Tuple.Create <Ast, Token[], IScriptPosition>(ast, tokenArray, position));
        }
Exemplo n.º 13
0
 internal static string BriefMessage(IScriptPosition position)
 {
     StringBuilder builder = new StringBuilder(position.Line);
     if (position.ColumnNumber > builder.Length)
     {
         builder.Append(" <<<< ");
     }
     else
     {
         builder.Insert(position.ColumnNumber - 1, " >>>> ");
     }
     return StringUtil.Format(ParserStrings.TraceScriptLineMessage, position.LineNumber, builder.ToString());
 }
Exemplo n.º 14
0
        /// <summary>
        /// Return a message that looks like:
        ///     12+ $x + &lt;&lt;&lt;&lt; $b
        /// </summary>
        internal static string BriefMessage(IScriptPosition position)
        {
            StringBuilder message = new StringBuilder(position.Line);

            if (position.ColumnNumber > message.Length)
            {
                message.Append(" <<<< ");
            }
            else
            {
                message.Insert(position.ColumnNumber - 1, " >>>> ");
            }
            return(StringUtil.Format(ParserStrings.TraceScriptLineMessage, position.LineNumber, message.ToString()));
        }
Exemplo n.º 15
0
 public static CommandCompletion CompleteInput(Ast ast, Token[] tokens, IScriptPosition positionOfCursor, Hashtable options)
 {
     if (ast == null)
     {
         throw PSTraceSource.NewArgumentNullException("ast");
     }
     if (tokens == null)
     {
         throw PSTraceSource.NewArgumentNullException("tokens");
     }
     if (positionOfCursor == null)
     {
         throw PSTraceSource.NewArgumentNullException("positionOfCursor");
     }
     return(CompleteInputImpl(ast, tokens, positionOfCursor, options));
 }
Exemplo n.º 16
0
        /// <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;
        }
Exemplo n.º 17
0
        /// <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="executionService">
        /// The PowerShellContext to use for gathering completions.
        /// </param>
        /// <param name="logger">An ILogger implementation used for writing log messages.</param>
        /// <param name="cancellationToken">
        /// A CancellationToken to cancel completion requests.
        /// </param>
        /// <returns>
        /// A CommandCompletion instance that contains completions for the
        /// symbol at the given offset.
        /// </returns>
        public static async Task <CommandCompletion> GetCompletionsAsync(
            Ast scriptAst,
            Token[] currentTokens,
            int fileOffset,
            IInternalPowerShellExecutionService executionService,
            ILogger logger,
            CancellationToken cancellationToken)
        {
            IScriptPosition cursorPosition = s_clonePositionWithNewOffset(scriptAst.Extent.StartScriptPosition, fileOffset);

            logger.LogTrace(
                string.Format(
                    "Getting completions at offset {0} (line: {1}, column: {2})",
                    fileOffset,
                    cursorPosition.LineNumber,
                    cursorPosition.ColumnNumber));

            Stopwatch stopwatch = new();

            CommandCompletion commandCompletion = null;
            await executionService.ExecuteDelegateAsync(
                representation : "CompleteInput",
                new ExecutionOptions { Priority = ExecutionPriority.Next },
                (pwsh, _) =>
            {
                stopwatch.Start();
                commandCompletion = CommandCompletion.CompleteInput(
                    scriptAst,
                    currentTokens,
                    cursorPosition,
                    options: null,
                    powershell: pwsh);
            },
                cancellationToken)
            .ConfigureAwait(false);

            stopwatch.Stop();
            logger.LogTrace($"IntelliSense completed in {stopwatch.ElapsedMilliseconds}ms.");

            return(commandCompletion);
        }
Exemplo n.º 18
0
        private static Collection <CompletionResult> CompleteParameters(
            KeywordResult keyword,
            IScriptPosition cursorPosition)
        {
            if (keyword.Schema.ShouldUseDefaultParameterCompletions)
            {
                return(null);
            }

            // If we're still on the last token, we need to look further back
            Token lastToken = keyword.Frame.ParentContext.LastToken;

            if (cursorPosition.Offset == lastToken.Extent.EndOffset)
            {
                lastToken = keyword.Frame.ParentContext.Tokens[keyword.Frame.ParentContext.LastTokenIndex - 1];
            }

            return(lastToken.Kind == TokenKind.Parameter
                ? CompleteParameterValues(keyword, lastToken)
                : CompleteParameterNames(keyword));
        }
Exemplo n.º 19
0
        /// <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);
        }
Exemplo n.º 20
0
        internal CompletionContext CreateCompletionContext(ExecutionContext executionContext)
        {
            Func <Token, bool> predicate         = null;
            Func <Token, bool> func2             = null;
            Token           token                = null;
            IScriptPosition positionForAstSearch = this._cursorPosition;
            bool            flag   = false;
            Token           token2 = this._tokens.LastOrDefault <Token>(t => IsCursorWithinOrJustAfterExtent(this._cursorPosition, t.Extent) && IsInterestingToken(t));

            if (token2 == null)
            {
                if (predicate == null)
                {
                    predicate = t => IsCursorBeforeExtent(this._cursorPosition, t.Extent) && IsInterestingToken(t);
                }
                token = this._tokens.LastOrDefault <Token>(predicate);
                if (token != null)
                {
                    positionForAstSearch = token.Extent.EndScriptPosition;
                    flag = true;
                }
            }
            else
            {
                StringExpandableToken token3 = token2 as StringExpandableToken;
                if ((token3 != null) && (token3.NestedTokens != null))
                {
                    if (func2 == null)
                    {
                        func2 = t => IsCursorWithinOrJustAfterExtent(this._cursorPosition, t.Extent) && IsInterestingToken(t);
                    }
                    token2 = token3.NestedTokens.LastOrDefault <Token>(func2) ?? token3;
                }
            }
            IEnumerable <Ast> source = AstSearcher.FindAll(this._ast, ast => IsCursorWithinOrJustAfterExtent(positionForAstSearch, ast.Extent), true);

            return(new CompletionContext {
                TokenAtCursor = token2, TokenBeforeCursor = token, CursorPosition = this._cursorPosition, RelatedAsts = source.ToList <Ast>(), Options = this._options, ExecutionContext = executionContext, ReplacementIndex = flag ? this._cursorPosition.Offset : 0
            });
        }
Exemplo n.º 21
0
 public static CommandCompletion CompleteInput(Ast ast, Token[] tokens, IScriptPosition cursorPosition, Hashtable options, PowerShell powershell)
 {
     if (ast == null)
     {
         throw PSTraceSource.NewArgumentNullException("ast");
     }
     if (tokens == null)
     {
         throw PSTraceSource.NewArgumentNullException("tokens");
     }
     if (cursorPosition == null)
     {
         throw PSTraceSource.NewArgumentNullException("cursorPosition");
     }
     if (powershell == null)
     {
         throw PSTraceSource.NewArgumentNullException("powershell");
     }
     if (!powershell.IsChild)
     {
         RemoteRunspace remoteRunspace = powershell.Runspace as RemoteRunspace;
         if (remoteRunspace != null)
         {
             CheckScriptCallOnRemoteRunspace(remoteRunspace);
             if (remoteRunspace.GetCapabilities().Equals(RunspaceCapability.Default))
             {
                 int num;
                 int num2;
                 powershell.Commands.Clear();
                 Tuple <string, int, int> inputAndCursorFromAst = GetInputAndCursorFromAst(cursorPosition);
                 return(new CommandCompletion(new Collection <CompletionResult>(InvokeLegacyTabExpansion(powershell, inputAndCursorFromAst.Item1, inputAndCursorFromAst.Item2, true, out num, out num2) ?? EmptyCompletionResult), -1, num + inputAndCursorFromAst.Item3, num2));
             }
             string text   = ast.Extent.Text;
             int    offset = ((InternalScriptPosition)cursorPosition).Offset;
             return(CallScriptWithStringParameterSet(text, offset, options, powershell));
         }
     }
     return(CallScriptWithAstParameterSet(ast, tokens, cursorPosition, options, powershell));
 }
Exemplo n.º 22
0
        /// <summary>
        /// Add ARM DSL completions to the front of the completion result collection.
        /// May clobber other results if DSL completions are determined to be of low relevance.
        /// </summary>
        /// <param name="completion">The existing command completion object.</param>
        /// <param name="ast">The AST of the whole input as parsed.</param>
        /// <param name="tokens">The tokens of the whole input as parsed.</param>
        /// <param name="cursorPosition">The position of the cursor within the input.</param>
        /// <param name="options">A completion options hashtable. This is currently ignored.</param>
        public static void PrependDslCompletions(
            CommandCompletion completion,
            Ast ast,
            IReadOnlyList <Token> tokens,
            IScriptPosition cursorPosition,
            Hashtable options)
        {
            Collection <CompletionResult> completionResults = GetCompletions(ast, tokens, cursorPosition, options, out bool clobberCompletions);

            if (completionResults == null)
            {
                return;
            }

            if (completion.ReplacementIndex < 0)
            {
                completion.ReplacementIndex = cursorPosition.Offset;
            }

            if (completion.ReplacementLength < 0)
            {
                completion.ReplacementLength = 0;
            }

            if (clobberCompletions ||
                completion.CompletionMatches == null ||
                completion.CompletionMatches.Count == 0)
            {
                completion.CompletionMatches = completionResults;
            }
            else
            {
                foreach (CompletionResult existingCompletion in completion.CompletionMatches)
                {
                    completionResults.Add(existingCompletion);
                }
                completion.CompletionMatches = completionResults;
            }
        }
Exemplo n.º 23
0
        internal static TypeName FindTypeNameToComplete(ITypeName type, IScriptPosition cursor)
        {
            TypeName name = type as TypeName;

            if (name != null)
            {
                if ((cursor.Offset > type.Extent.StartOffset) && (cursor.Offset <= type.Extent.EndOffset))
                {
                    return(name);
                }
                return(null);
            }
            GenericTypeName name2 = type as GenericTypeName;

            if (name2 != null)
            {
                name = FindTypeNameToComplete(name2.TypeName, cursor);
                if (name != null)
                {
                    return(name);
                }
                foreach (ITypeName name3 in name2.GenericArguments)
                {
                    name = FindTypeNameToComplete(name3, cursor);
                    if (name != null)
                    {
                        return(name);
                    }
                }
                return(null);
            }
            ArrayTypeName name4 = type as ArrayTypeName;

            if (name4 == null)
            {
                return(null);
            }
            return((TypeName)(FindTypeNameToComplete(name4.ElementType, cursor) ?? null));
        }
Exemplo n.º 24
0
 internal static TypeName FindTypeNameToComplete(ITypeName type, IScriptPosition cursor)
 {
     TypeName name = type as TypeName;
     if (name != null)
     {
         if ((cursor.Offset > type.Extent.StartOffset) && (cursor.Offset <= type.Extent.EndOffset))
         {
             return name;
         }
         return null;
     }
     GenericTypeName name2 = type as GenericTypeName;
     if (name2 != null)
     {
         name = FindTypeNameToComplete(name2.TypeName, cursor);
         if (name != null)
         {
             return name;
         }
         foreach (ITypeName name3 in name2.GenericArguments)
         {
             name = FindTypeNameToComplete(name3, cursor);
             if (name != null)
             {
                 return name;
             }
         }
         return null;
     }
     ArrayTypeName name4 = type as ArrayTypeName;
     if (name4 == null)
     {
         return null;
     }
     return (TypeName) (FindTypeNameToComplete(name4.ElementType, cursor) ?? null);
 }
Exemplo n.º 25
0
 private static Ast GetLastAstAtCursor(ScriptBlockAst scriptBlockAst, IScriptPosition cursorPosition)
 {
     return AstSearcher.FindAll(scriptBlockAst, ast => IsCursorRightAfterExtent(cursorPosition, ast.Extent), true).LastOrDefault<Ast>();
 }
Exemplo n.º 26
0
 private static bool IsCursorBeforeExtent(IScriptPosition cursor, IScriptExtent extent)
 {
     return (extent.EndOffset < cursor.Offset);
 }
Exemplo n.º 27
0
 private static bool PositionIsEqual(IScriptPosition position1, IScriptPosition position2)
 {
     return(position1.ColumnNumber == position2.ColumnNumber &&
            position1.LineNumber == position2.LineNumber &&
            position1.File == position2.File);
 }
Exemplo n.º 28
0
 private static bool IsCursorWithinOrJustAfterExtent(IScriptPosition cursor, IScriptExtent extent)
 {
     return((cursor.Offset > extent.StartOffset) && (cursor.Offset <= extent.EndOffset));
 }
Exemplo n.º 29
0
 private static bool IsCursorBeforeExtent(IScriptPosition cursor, IScriptExtent extent)
 {
     return(extent.EndOffset < cursor.Offset);
 }
Exemplo n.º 30
0
        /// <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="powerShellContext">
        /// The PowerShellContext to use for gathering completions.
        /// </param>
        /// <param name="logger">An ILogger implementation used for writing log messages.</param>
        /// <param name="cancellationToken">
        /// A CancellationToken to cancel completion requests.
        /// </param>
        /// <returns>
        /// A CommandCompletion instance that contains completions for the
        /// symbol at the given offset.
        /// </returns>
        static public async Task <CommandCompletion> GetCompletions(
            Ast scriptAst,
            Token[] currentTokens,
            int fileOffset,
            PowerShellContext powerShellContext,
            ILogger logger,
            CancellationToken cancellationToken)
        {
            var type   = scriptAst.Extent.StartScriptPosition.GetType();
            var method =
#if CoreCLR
                type.GetMethod(
                    "CloneWithNewOffset",
                    BindingFlags.Instance | BindingFlags.NonPublic);
#else
                type.GetMethod(
                    "CloneWithNewOffset",
                    BindingFlags.Instance | BindingFlags.NonPublic,
                    null,
                    new[] { typeof(int) }, null);
#endif

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

            logger.Write(
                LogLevel.Verbose,
                string.Format(
                    "Getting completions at offset {0} (line: {1}, column: {2})",
                    fileOffset,
                    cursorPosition.LineNumber,
                    cursorPosition.ColumnNumber));

            CommandCompletion commandCompletion = null;
            if (powerShellContext.IsDebuggerStopped)
            {
                PSCommand command = new PSCommand();
                command.AddCommand("TabExpansion2");
                command.AddParameter("Ast", scriptAst);
                command.AddParameter("Tokens", currentTokens);
                command.AddParameter("PositionOfCursor", cursorPosition);
                command.AddParameter("Options", null);

                PSObject outputObject =
                    (await powerShellContext.ExecuteCommand <PSObject>(command, false, false))
                    .FirstOrDefault();

                if (outputObject != null)
                {
                    ErrorRecord errorRecord = outputObject.BaseObject as ErrorRecord;
                    if (errorRecord != null)
                    {
                        logger.WriteException(
                            "Encountered an error while invoking TabExpansion2 in the debugger",
                            errorRecord.Exception);
                    }
                    else
                    {
                        commandCompletion = outputObject.BaseObject as CommandCompletion;
                    }
                }
            }
            else if (powerShellContext.CurrentRunspace.Runspace.RunspaceAvailability ==
                     RunspaceAvailability.Available)
            {
                using (RunspaceHandle runspaceHandle = await powerShellContext.GetRunspaceHandle(cancellationToken))
                    using (PowerShell powerShell = PowerShell.Create())
                    {
                        powerShell.Runspace = runspaceHandle.Runspace;

                        Stopwatch stopwatch = new Stopwatch();
                        stopwatch.Start();

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

                        stopwatch.Stop();

                        logger.Write(LogLevel.Verbose, $"IntelliSense completed in {stopwatch.ElapsedMilliseconds}ms.");
                    }
            }

            return(commandCompletion);
        }
Exemplo n.º 31
0
 private static bool IsCursorOutsideOfExtent(IScriptPosition cursor, IScriptExtent extent)
 {
     return cursor.Offset < extent.StartOffset || cursor.Offset > extent.EndOffset;
 }
Exemplo n.º 32
0
 /// <summary>
 /// Find the configuration statement contains current cursor
 /// </summary>
 /// <param name="cursorPosition"></param>
 /// <param name="ast"></param>
 /// <param name="keywordAst"></param>
 /// <returns></returns>
 private ConfigurationDefinitionAst GetAncestorConfigurationAstAndKeywordAst(
     IScriptPosition cursorPosition,
     Ast ast,
     out DynamicKeywordStatementAst keywordAst)
 {
     ConfigurationDefinitionAst configureAst = Ast.GetAncestorConfigurationDefinitionAstAndDynamicKeywordStatementAst(ast, out keywordAst);
     // Find the configuration statement contains current cursor
     // Note: cursorPosition.Offset < configureAst.Extent.EndOffset means cursor locates inside the configuration
     //       cursorPosition.Offset = configureAst.Extent.EndOffset means cursor locates at the end of the configuration
     while (configureAst != null && cursorPosition.Offset > configureAst.Extent.EndOffset)
     {
         configureAst = Ast.GetAncestorAst<ConfigurationDefinitionAst>(configureAst.Parent);
     }
     return configureAst;
 }
Exemplo n.º 33
0
 private static Ast GetLastAstAtCursor(ScriptBlockAst scriptBlockAst, IScriptPosition cursorPosition)
 {
     var asts = AstSearcher.FindAll(scriptBlockAst, ast => IsCursorRightAfterExtent(cursorPosition, ast.Extent), searchNestedScriptBlocks: true);
     return asts.LastOrDefault();
 }
Exemplo n.º 34
0
 private static bool IsCursorWithinOrJustAfterExtent(IScriptPosition cursor, IScriptExtent extent)
 {
     return cursor.Offset > extent.StartOffset && cursor.Offset <= extent.EndOffset;
 }
Exemplo n.º 35
0
        private static KeywordResult?GetCurrentKeyword(Ast ast, IReadOnlyList <Token> tokens, IScriptPosition cursorPosition)
        {
            KeywordContext context = KeywordContext.BuildFromInput(ast, tokens, cursorPosition);

            if (context is null)
            {
                return(null);
            }

            DslKeywordSchema    currentSchema = PSArmSchemaInformation.PSArmSchema;
            KeywordContextFrame currentFrame  = null;

            for (int i = 0; i < context.KeywordStack.Count; i++)
            {
                KeywordContextFrame frame = context.KeywordStack[i];

                string commandName = frame.CommandAst.GetCommandName();

                if (commandName is null)
                {
                    continue;
                }

                IReadOnlyDictionary <string, DslKeywordSchema> subschemas = currentSchema.GetInnerKeywords(currentFrame);

                if (subschemas is null ||
                    !subschemas.TryGetValue(commandName, out DslKeywordSchema subschema))
                {
                    continue;
                }

                currentSchema = subschema;
                currentFrame  = frame;
            }

            if (currentFrame is null || currentSchema is null)
            {
                return(null);
            }

            return(new KeywordResult(currentSchema, currentFrame));
        }
Exemplo n.º 36
0
 private static Ast GetLastAstAtCursor(ScriptBlockAst scriptBlockAst, IScriptPosition cursorPosition)
 {
     return(AstSearcher.FindAll(scriptBlockAst, ast => IsCursorRightAfterExtent(cursorPosition, ast.Extent), true).LastOrDefault <Ast>());
 }
Exemplo n.º 37
0
 private static CommandCompletion CallScriptWithAstParameterSet(Ast ast, Token[] tokens, IScriptPosition cursorPosition, Hashtable options, PowerShell powershell)
 {
     try
     {
         powershell.Commands.Clear();
         powershell.AddCommand("TabExpansion2").AddArgument(ast).AddArgument(tokens).AddArgument(cursorPosition).AddArgument(options);
         Collection <PSObject> collection = powershell.Invoke();
         if (collection == null)
         {
             return(EmptyCommandCompletion);
         }
         if (collection.Count == 1)
         {
             CommandCompletion completion = PSObject.Base(collection[0]) as CommandCompletion;
             if (completion != null)
             {
                 return(completion);
             }
         }
     }
     catch (Exception exception)
     {
         CommandProcessorBase.CheckForSevereException(exception);
     }
     finally
     {
         powershell.Commands.Clear();
     }
     return(EmptyCommandCompletion);
 }
Exemplo n.º 38
0
 private static bool IsCursorRightAfterExtent(IScriptPosition cursor, IScriptExtent extent)
 {
     return(cursor.Offset == extent.EndOffset);
 }
Exemplo n.º 39
0
 private static bool IsCursorRightAfterExtent(IScriptPosition cursor, IScriptExtent extent)
 {
     return (cursor.Offset == extent.EndOffset);
 }
Exemplo n.º 40
0
 private static bool IsCursorBeforeExtent(IScriptPosition cursor, IScriptExtent extent)
 {
     return cursor.Offset < extent.StartOffset;
 }
Exemplo n.º 41
0
 private static bool IsCursorAfterExtentAndInTheSameLine(IScriptPosition cursor, IScriptExtent extent)
 {
     return cursor.Offset >= extent.EndOffset && extent.EndLineNumber == cursor.LineNumber;
 }
Exemplo n.º 42
0
        internal static TypeName FindTypeNameToComplete(ITypeName type, IScriptPosition cursor)
        {
            var typeName = type as TypeName;
            if (typeName != null)
            {
                // If the cursor is at the start offset, it's not really inside, so return null.
                // If the cursor is at the end offset, it's not really inside, but it's just before the cursor,
                // we don want to complete it.
                return (cursor.Offset > type.Extent.StartOffset && cursor.Offset <= type.Extent.EndOffset)
                           ? typeName
                           : null;
            }

            var genericTypeName = type as GenericTypeName;
            if (genericTypeName != null)
            {
                typeName = FindTypeNameToComplete(genericTypeName.TypeName, cursor);
                if (typeName != null)
                    return typeName;
                foreach (var t in genericTypeName.GenericArguments)
                {
                    typeName = FindTypeNameToComplete(t, cursor);
                    if (typeName != null)
                        return typeName;
                }
                return null;
            }

            var arrayTypeName = type as ArrayTypeName;
            if (arrayTypeName != null)
            {
                return FindTypeNameToComplete(arrayTypeName.ElementType, cursor) ?? null;
            }

            return null;
        }
Exemplo n.º 43
0
 private static bool IsCursorAfterExtent(IScriptPosition cursor, IScriptExtent extent)
 {
     return extent.EndOffset < cursor.Offset;
 }
Exemplo n.º 44
0
        // TODO: BRING THIS BACK
        /// <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="powerShellContext">
        /// The PowerShellContext to use for gathering completions.
        /// </param>
        /// <param name="logger">An ILogger implementation used for writing log messages.</param>
        /// <param name="cancellationToken">
        /// A CancellationToken to cancel completion requests.
        /// </param>
        /// <returns>
        /// A CommandCompletion instance that contains completions for the
        /// symbol at the given offset.
        /// </returns>
        public static async Task <CommandCompletion> GetCompletionsAsync(
            Ast scriptAst,
            Token[] currentTokens,
            int fileOffset,
            PowerShellContextService powerShellContext,
            ILogger logger,
            CancellationToken cancellationToken)
        {
            if (!s_completionHandle.Wait(0))
            {
                return(null);
            }

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

                logger.LogTrace(
                    string.Format(
                        "Getting completions at offset {0} (line: {1}, column: {2})",
                        fileOffset,
                        cursorPosition.LineNumber,
                        cursorPosition.ColumnNumber));

                if (!powerShellContext.IsAvailable)
                {
                    return(null);
                }

                var stopwatch = new Stopwatch();

                // If the current runspace is out of process we can use
                // CommandCompletion.CompleteInput because PSReadLine won't be taking up the
                // main runspace.
                if (powerShellContext.IsCurrentRunspaceOutOfProcess())
                {
                    using (RunspaceHandle runspaceHandle = await powerShellContext.GetRunspaceHandleAsync(cancellationToken))
                        using (System.Management.Automation.PowerShell powerShell = System.Management.Automation.PowerShell.Create())
                        {
                            powerShell.Runspace = runspaceHandle.Runspace;
                            stopwatch.Start();
                            try
                            {
                                return(CommandCompletion.CompleteInput(
                                           scriptAst,
                                           currentTokens,
                                           cursorPosition,
                                           options: null,
                                           powershell: powerShell));
                            }
                            finally
                            {
                                stopwatch.Stop();
                                logger.LogTrace($"IntelliSense completed in {stopwatch.ElapsedMilliseconds}ms.");
                            }
                        }
                }

                CommandCompletion commandCompletion = null;
                await powerShellContext.InvokeOnPipelineThreadAsync(
                    pwsh =>
                {
                    stopwatch.Start();
                    commandCompletion = CommandCompletion.CompleteInput(
                        scriptAst,
                        currentTokens,
                        cursorPosition,
                        options: null,
                        powershell: pwsh);
                });

                stopwatch.Stop();
                logger.LogTrace($"IntelliSense completed in {stopwatch.ElapsedMilliseconds}ms.");

                return(commandCompletion);
            }
            finally
            {
                s_completionHandle.Release();
            }
        }
Exemplo n.º 45
0
        private Tuple<ExpressionAst, StatementAst> GetHashEntryContainsCursor(
            IScriptPosition cursor,
            HashtableAst hashTableAst,
            bool isCursorInString)
        {
            Tuple<ExpressionAst, StatementAst> keyValuePairWithCursor = null;
            foreach (var kvp in hashTableAst.KeyValuePairs)
            {
                if (IsCursorWithinOrJustAfterExtent(cursor, kvp.Item2.Extent))
                {
                    keyValuePairWithCursor = kvp;
                    break;
                }
                if (!isCursorInString)
                {
                    //
                    // Handle following case, cursor is after '=' but before next key value pair,
                    // next key value pair will be treated as kvp.Item2 of 'Ensure' key
                    //
                    //    configuration foo
                    //    {
                    //        File foo
                    //        {
                    //            DestinationPath = "\foo.txt"
                    //            Ensure = |
                    //            DependsOn =@("[User]x")
                    //        }
                    //    }
                    //
                    if (kvp.Item2.Extent.StartLineNumber > kvp.Item1.Extent.EndLineNumber &&
                        IsCursorAfterExtentAndInTheSameLine(cursor, kvp.Item1.Extent))
                    {
                        keyValuePairWithCursor = kvp;
                        break;
                    }

                    //
                    // If cursor is not within a string, then handle following two cases,
                    //
                    //  #1) cursor is after '=', in the same line of previous key value pair
                    //      configuration test{File testfile{DestinationPath='c:\test'; Ensure = |
                    //
                    //  #2) cursor is after '=', in the separate line of previous key value pair
                    //      configuration test{File testfile{DestinationPath='c:\test';
                    //        Ensure = |
                    //
                    if (!IsCursorBeforeExtent(cursor, kvp.Item1.Extent) &&
                        IsCursorAfterExtentAndInTheSameLine(cursor, kvp.Item2.Extent))
                    {
                        keyValuePairWithCursor = kvp;
                    }
                }
            }
            return keyValuePairWithCursor;
        }
Exemplo n.º 46
0
        /// <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;
        }
Exemplo n.º 47
0
        private void GetCommandCompletionParameters(int caretPosition, out Ast ast, out Token[] tokens, out IScriptPosition cursorPosition)
        {
            ITrackingSpan trackingSpan;
            _textView.TextBuffer.Properties.TryGetProperty(BufferProperties.Ast, out ast);
            _textView.TextBuffer.Properties.TryGetProperty(BufferProperties.Tokens, out tokens);
            _textView.TextBuffer.Properties.TryGetProperty(BufferProperties.SpanTokenized, out trackingSpan);

            // No ast or tokens available on the buffer. Re-tokenize.
            if (ast == null || tokens == null)
            {
                var trackingSpan2 = _textView.TextBuffer.CurrentSnapshot.CreateTrackingSpan(0, _textView.TextBuffer.CurrentSnapshot.Length, SpanTrackingMode.EdgeInclusive);
                var text = trackingSpan2.GetText(_textView.TextBuffer.CurrentSnapshot);
                ParseError[] array;
                ast = Tokenize(text, 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;
        }