/// <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 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); }