//public SymbolDetails GetSymbolDetails()

        #endregion

        #region Private Fields

        /// <summary>
        /// Gets all aliases found in the runspace
        /// </summary>
        private async Task GetAliases()
        {
            if (!this.areAliasesLoaded)
            {
                RunspaceHandle runspaceHandle = await this.powerShellContext.GetRunspaceHandle();

                CommandInvocationIntrinsics invokeCommand = runspaceHandle.Runspace.SessionStateProxy.InvokeCommand;
                IEnumerable <CommandInfo>   aliases       = invokeCommand.GetCommands("*", CommandTypes.Alias, true);

                runspaceHandle.Dispose();

                foreach (AliasInfo aliasInfo in aliases)
                {
                    if (!CmdletToAliasDictionary.ContainsKey(aliasInfo.Definition))
                    {
                        CmdletToAliasDictionary.Add(aliasInfo.Definition, new List <String>()
                        {
                            aliasInfo.Name
                        });
                    }
                    else
                    {
                        CmdletToAliasDictionary[aliasInfo.Definition].Add(aliasInfo.Name);
                    }

                    AliasToCmdletDictionary.Add(aliasInfo.Name, aliasInfo.Definition);
                }

                this.areAliasesLoaded = true;
            }
        }
        /// <summary>
        /// Gets completions for a statement contained in the given
        /// script file at the specified line and column position.
        /// </summary>
        /// <param name="scriptFile">
        /// The script file in which completions will be gathered.
        /// </param>
        /// <param name="lineNumber">
        /// The 1-based line number at which completions will be gathered.
        /// </param>
        /// <param name="columnNumber">
        /// The 1-based column number at which completions will be gathered.
        /// </param>
        /// <returns>
        /// A CommandCompletion instance completions for the identified statement.
        /// </returns>
        public async Task <CompletionResults> GetCompletionsInFile(
            ScriptFile scriptFile,
            int lineNumber,
            int columnNumber)
        {
            Validate.IsNotNull("scriptFile", scriptFile);

            // Get the offset at the specified position.  This method
            // will also validate the given position.
            int fileOffset =
                scriptFile.GetOffsetAtPosition(
                    lineNumber,
                    columnNumber);

            RunspaceHandle runspaceHandle =
                await this.powerShellContext.GetRunspaceHandle();

            CompletionResults completionResults =
                AstOperations.GetCompletions(
                    scriptFile.ScriptAst,
                    scriptFile.ScriptTokens,
                    fileOffset,
                    runspaceHandle.Runspace);

            runspaceHandle.Dispose();

            // save state of most recent completion
            mostRecentCompletions   = completionResults;
            mostRecentRequestFile   = scriptFile.Id;
            mostRecentRequestLine   = lineNumber;
            mostRecentRequestOffest = columnNumber;

            return(completionResults);
        }
        /// <summary>
        /// Finds the details of the symbol at the given script file location.
        /// </summary>
        /// <param name="scriptFile">The ScriptFile in which the symbol can be located.</param>
        /// <param name="lineNumber">The line number at which the symbol can be located.</param>
        /// <param name="columnNumber">The column number at which the symbol can be located.</param>
        /// <returns></returns>
        public async Task <SymbolDetails> FindSymbolDetailsAtLocation(
            ScriptFile scriptFile,
            int lineNumber,
            int columnNumber)
        {
            SymbolDetails   symbolDetails   = null;
            SymbolReference symbolReference =
                AstOperations.FindSymbolAtPosition(
                    scriptFile.ScriptAst,
                    lineNumber,
                    columnNumber);

            if (symbolReference != null)
            {
                RunspaceHandle runspaceHandle =
                    await this.powerShellContext.GetRunspaceHandle();

                symbolReference.FilePath = scriptFile.FilePath;
                symbolDetails            = new SymbolDetails(symbolReference, runspaceHandle.Runspace);

                runspaceHandle.Dispose();
            }
            else
            {
                // TODO #21: Return Result<T>
                return(null);
            }

            return(symbolDetails);
        }
        /// <summary>
        /// Finds the details of the symbol at the given script file location.
        /// </summary>
        /// <param name="scriptFile">The ScriptFile in which the symbol can be located.</param>
        /// <param name="lineNumber">The line number at which the symbol can be located.</param>
        /// <param name="columnNumber">The column number at which the symbol can be located.</param>
        /// <returns></returns>
        public async Task <SymbolDetails> FindSymbolDetailsAtLocation(
            ScriptFile scriptFile,
            int lineNumber,
            int columnNumber)
        {
            SymbolDetails   symbolDetails   = null;
            SymbolReference symbolReference =
                AstOperations.FindSymbolAtPosition(
                    scriptFile.ScriptAst,
                    lineNumber,
                    columnNumber);

            if (symbolReference != null)
            {
                // Request a runspace handle with a short timeout
                RunspaceHandle runspaceHandle =
                    await this.powerShellContext.GetRunspaceHandle(
                        new CancellationTokenSource(DefaultWaitTimeoutMilliseconds).Token);

                symbolReference.FilePath = scriptFile.FilePath;
                symbolDetails            = new SymbolDetails(symbolReference, runspaceHandle.Runspace);

                runspaceHandle.Dispose();
            }
            else
            {
                // TODO #21: Return Result<T>
                return(null);
            }

            return(symbolDetails);
        }
Пример #5
0
        /// <summary>
        /// Gets completions for a statement contained in the given
        /// script file at the specified line and column position.
        /// </summary>
        /// <param name="scriptFile">
        /// The script file in which completions will be gathered.
        /// </param>
        /// <param name="lineNumber">
        /// The 1-based line number at which completions will be gathered.
        /// </param>
        /// <param name="columnNumber">
        /// The 1-based column number at which completions will be gathered.
        /// </param>
        /// <returns>
        /// A CommandCompletion instance completions for the identified statement.
        /// </returns>
        public async Task <CompletionResults> GetCompletionsInFile(
            ScriptFile scriptFile,
            int lineNumber,
            int columnNumber)
        {
            Validate.IsNotNull("scriptFile", scriptFile);

            // Get the offset at the specified position.  This method
            // will also validate the given position.
            int fileOffset =
                scriptFile.GetOffsetAtPosition(
                    lineNumber,
                    columnNumber);

            RunspaceHandle runspaceHandle =
                await this.powerShellContext.GetRunspaceHandle(
                    new CancellationTokenSource(DefaultWaitTimeoutMilliseconds).Token);

            CommandCompletion commandCompletion =
                AstOperations.GetCompletions(
                    scriptFile.ScriptAst,
                    scriptFile.ScriptTokens,
                    fileOffset,
                    runspaceHandle.Runspace);

            runspaceHandle.Dispose();

            if (commandCompletion != null)
            {
                try
                {
                    CompletionResults completionResults =
                        CompletionResults.Create(
                            scriptFile,
                            commandCompletion);

                    // save state of most recent completion
                    mostRecentCompletions   = completionResults;
                    mostRecentRequestFile   = scriptFile.Id;
                    mostRecentRequestLine   = lineNumber;
                    mostRecentRequestOffest = columnNumber;

                    return(completionResults);
                }
                catch (ArgumentException e)
                {
                    // Bad completion results could return an invalid
                    // replacement range, catch that here
                    Logger.Write(
                        LogLevel.Error,
                        $"Caught exception while trying to create CompletionResults:\n\n{e.ToString()}");
                }
            }

            // If all else fails, return empty results
            return(new CompletionResults());
        }
Пример #6
0
        /// <summary>
        /// Gets all aliases found in the runspace
        /// </summary>
        private async Task GetAliases()
        {
            if (_areAliasesLoaded)
            {
                return;
            }

            try
            {
                RunspaceHandle runspaceHandle =
                    await _powerShellContext.GetRunspaceHandle(
                        new CancellationTokenSource(DefaultWaitTimeoutMilliseconds).Token);

                CommandInvocationIntrinsics invokeCommand = runspaceHandle.Runspace.SessionStateProxy.InvokeCommand;
                IEnumerable <CommandInfo>   aliases       = invokeCommand.GetCommands("*", CommandTypes.Alias, true);

                runspaceHandle.Dispose();

                foreach (AliasInfo aliasInfo in aliases)
                {
                    if (!_cmdletToAliasDictionary.ContainsKey(aliasInfo.Definition))
                    {
                        _cmdletToAliasDictionary.Add(aliasInfo.Definition, new List <String> {
                            aliasInfo.Name
                        });
                    }
                    else
                    {
                        _cmdletToAliasDictionary[aliasInfo.Definition].Add(aliasInfo.Name);
                    }

                    _aliasToCmdletDictionary.Add(aliasInfo.Name, aliasInfo.Definition);
                }

                _areAliasesLoaded = true;
            }
            catch (PSNotSupportedException e)
            {
                _logger.Write(
                    LogLevel.Warning,
                    $"Caught PSNotSupportedException while attempting to get aliases from remote session:\n\n{e.ToString()}");

                // Prevent the aliases from being fetched again - no point if the remote doesn't support InvokeCommand.
                _areAliasesLoaded = true;
            }
            catch (TaskCanceledException)
            {
                // The wait for a RunspaceHandle has timed out, skip aliases for now
            }
        }
        /// <summary>
        /// Gets completions for a statement contained in the given
        /// script file at the specified line and column position.
        /// </summary>
        /// <param name="scriptFile">
        /// The script file in which completions will be gathered.
        /// </param>
        /// <param name="lineNumber">
        /// The 1-based line number at which completions will be gathered.
        /// </param>
        /// <param name="columnNumber">
        /// The 1-based column number at which completions will be gathered.
        /// </param>
        /// <returns>
        /// A CommandCompletion instance completions for the identified statement.
        /// </returns>
        public async Task <CompletionResults> GetCompletionsInFile(
            ScriptFile scriptFile,
            int lineNumber,
            int columnNumber)
        {
            Validate.IsNotNull("scriptFile", scriptFile);

            // Get the offset at the specified position.  This method
            // will also validate the given position.
            int fileOffset =
                scriptFile.GetOffsetAtPosition(
                    lineNumber,
                    columnNumber);

            RunspaceHandle runspaceHandle =
                await this.powerShellContext.GetRunspaceHandle(
                    new CancellationTokenSource(DefaultWaitTimeoutMilliseconds).Token);

            CommandCompletion commandCompletion =
                AstOperations.GetCompletions(
                    scriptFile.ScriptAst,
                    scriptFile.ScriptTokens,
                    fileOffset,
                    runspaceHandle.Runspace);

            runspaceHandle.Dispose();

            if (commandCompletion != null)
            {
                CompletionResults completionResults =
                    CompletionResults.Create(
                        scriptFile,
                        commandCompletion);

                // save state of most recent completion
                mostRecentCompletions   = completionResults;
                mostRecentRequestFile   = scriptFile.Id;
                mostRecentRequestLine   = lineNumber;
                mostRecentRequestOffest = columnNumber;

                return(completionResults);
            }
            else
            {
                return(new CompletionResults());
            }
        }
        /// <summary>
        /// Gets all aliases found in the runspace
        /// </summary>
        private async Task GetAliases()
        {
            if (!this.areAliasesLoaded)
            {
                try
                {
                    RunspaceHandle runspaceHandle =
                        await this.powerShellContext.GetRunspaceHandle(
                            new CancellationTokenSource(DefaultWaitTimeoutMilliseconds).Token);

                    CommandInvocationIntrinsics invokeCommand = runspaceHandle.Runspace.SessionStateProxy.InvokeCommand;
                    IEnumerable <CommandInfo>   aliases       = invokeCommand.GetCommands("*", CommandTypes.Alias, true);

                    runspaceHandle.Dispose();

                    foreach (AliasInfo aliasInfo in aliases)
                    {
                        if (!CmdletToAliasDictionary.ContainsKey(aliasInfo.Definition))
                        {
                            CmdletToAliasDictionary.Add(aliasInfo.Definition, new List <String>()
                            {
                                aliasInfo.Name
                            });
                        }
                        else
                        {
                            CmdletToAliasDictionary[aliasInfo.Definition].Add(aliasInfo.Name);
                        }

                        AliasToCmdletDictionary.Add(aliasInfo.Name, aliasInfo.Definition);
                    }

                    this.areAliasesLoaded = true;
                }
                catch (TaskCanceledException)
                {
                    // The wait for a RunspaceHandle has timed out, skip aliases for now
                }
            }
        }
        /// <summary>
        /// Executes a PSCommand against the session's runspace and returns
        /// a collection of results of the expected type.
        /// </summary>
        /// <typeparam name="TResult">The expected result type.</typeparam>
        /// <param name="psCommand">The PSCommand to be executed.</param>
        /// <param name="sendOutputToHost">
        /// If true, causes any output written during command execution to be written to the host.
        /// </param>
        /// <param name="sendErrorToHost">
        /// If true, causes any errors encountered during command execution to be written to the host.
        /// </param>
        /// <returns>
        /// An awaitable Task which will provide results once the command
        /// execution completes.
        /// </returns>
        public async Task <IEnumerable <TResult> > ExecuteCommand <TResult>(
            PSCommand psCommand,
            bool sendOutputToHost = false,
            bool sendErrorToHost  = true)
        {
            RunspaceHandle        runspaceHandle  = null;
            IEnumerable <TResult> executionResult = null;

            // If the debugger is active and the caller isn't on the pipeline
            // thread, send the command over to that thread to be executed.
            if (Thread.CurrentThread.ManagedThreadId != this.pipelineThreadId &&
                this.pipelineExecutionTask != null)
            {
                Logger.Write(LogLevel.Verbose, "Passing command execution to pipeline thread.");

                PipelineExecutionRequest <TResult> executionRequest =
                    new PipelineExecutionRequest <TResult>(
                        this, psCommand, sendOutputToHost);

                // Send the pipeline execution request to the pipeline thread
                this.pipelineResultTask = new TaskCompletionSource <IPipelineExecutionRequest>();
                this.pipelineExecutionTask.SetResult(executionRequest);

                await this.pipelineResultTask.Task;
                return(executionRequest.Results);
            }
            else
            {
                try
                {
                    // Instruct PowerShell to send output and errors to the host
                    if (sendOutputToHost)
                    {
                        psCommand.Commands[0].MergeMyResults(
                            PipelineResultTypes.Error,
                            PipelineResultTypes.Output);

                        psCommand.Commands.Add(
                            this.GetOutputCommand(
                                endOfStatement: false));
                    }

                    if (this.currentRunspace.RunspaceAvailability == RunspaceAvailability.AvailableForNestedCommand ||
                        this.debuggerStoppedTask != null)
                    {
                        Logger.Write(
                            LogLevel.Verbose,
                            string.Format(
                                "Attempting to execute nested pipeline command(s):\r\n\r\n{0}",
                                GetStringForPSCommand(psCommand)));

                        executionResult =
                            this.ExecuteCommandInDebugger <TResult>(
                                psCommand,
                                sendOutputToHost);
                    }
                    else
                    {
                        Logger.Write(
                            LogLevel.Verbose,
                            string.Format(
                                "Attempting to execute command(s):\r\n\r\n{0}",
                                GetStringForPSCommand(psCommand)));

                        // Set the runspace
                        runspaceHandle = await this.GetRunspaceHandle();

                        if (runspaceHandle.Runspace.RunspaceAvailability != RunspaceAvailability.AvailableForNestedCommand)
                        {
                            this.powerShell.Runspace = runspaceHandle.Runspace;
                        }

                        // Invoke the pipeline on a background thread
                        // TODO: Use built-in async invocation!
                        executionResult =
                            await Task.Factory.StartNew <IEnumerable <TResult> >(
                                () =>
                        {
                            this.powerShell.Commands    = psCommand;
                            Collection <TResult> result = this.powerShell.Invoke <TResult>();
                            return(result);
                        },
                                CancellationToken.None, // Might need a cancellation token
                                TaskCreationOptions.None,
                                TaskScheduler.Default
                                );

                        if (this.powerShell.HadErrors)
                        {
                            string errorMessage = "Execution completed with errors:\r\n\r\n";

                            foreach (var error in this.powerShell.Streams.Error)
                            {
                                errorMessage += error.ToString() + "\r\n";
                            }

                            Logger.Write(LogLevel.Error, errorMessage);
                        }
                        else
                        {
                            Logger.Write(
                                LogLevel.Verbose,
                                "Execution completed successfully.");
                        }

                        return(executionResult);
                    }
                }
                catch (RuntimeException e)
                {
                    Logger.Write(
                        LogLevel.Error,
                        "Runtime exception occurred while executing command:\r\n\r\n" + e.ToString());

                    if (sendErrorToHost)
                    {
                        // Write the error to the host
                        this.WriteExceptionToHost(e);
                    }
                }
                finally
                {
                    // Get the new prompt before releasing the runspace handle
                    if (sendOutputToHost)
                    {
                        // Write the prompt
                        if (runspaceHandle != null)
                        {
                            this.WritePromptWithRunspace(runspaceHandle.Runspace);
                        }
                        else
                        {
                            this.WritePromptWithNestedPipeline();
                        }
                    }

                    // Dispose of the execution context
                    if (runspaceHandle != null)
                    {
                        runspaceHandle.Dispose();
                    }
                }
            }

            return(executionResult);
        }