public override IEnumerable <CompletionResult> CompleteArgument(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters) { return(CommenceMetadata.Categories.Where(s => s.ToLower().StartsWith(wordToComplete.ToLower())) .Select(s => new CompletionResult(base.MapString(s)))); }
public ParameterSet(CommandAst commandAst, IAzContext azContext = null) { Validation.CheckArgument(commandAst, $"{nameof(commandAst)} cannot be null."); _commandAst = commandAst; _azContext = azContext; var parameters = new List <Parameter>(); CommandParameterAst param = null; Ast arg = null; // positional parameters must be before named parameters. // This loop will convert them to named parameters. // Loop through all the parameters. The first element of CommandElements is the command name, so skip it. bool hasSeenNamedParameter = false; bool hasSeenIncompleteParameter = false; for (var i = 1; i < commandAst.CommandElements.Count(); ++i) { var elem = commandAst.CommandElements[i]; if (elem is CommandParameterAst p) { if (hasSeenIncompleteParameter) { throw new CommandLineException("'-' is in the middle of the parameter list."); } hasSeenNamedParameter = true; AddNamedParameter(param, arg); // In case there is a switch parameter, we store the parameter name/value and add them when we see the next pair. param = p; arg = null; } else if (AzPredictorConstants.ParameterIndicator == elem?.ToString().Trim().FirstOrDefault()) { // We have an incomplete command line such as // `New-AzResourceGroup -Name ResourceGroup01 -Location WestUS -` // We'll ignore the incomplete parameter. AddNamedParameter(param, arg); param = null; arg = null; hasSeenIncompleteParameter = true; } else { if (hasSeenIncompleteParameter || (hasSeenNamedParameter && param == null)) { throw new CommandLineException("Positional parameters must be before named parameters."); } if (param == null) { // This is a positional parameter. var pair = BoundParameters.First((pair) => pair.Value.Value == elem); var parameterName = pair.Key; var parameterValue = CommandLineUtilities.EscapePredictionText(pair.Value.Value.ToString()); parameters.Add(new Parameter(parameterName, parameterValue, true)); BoundParameters.Remove(pair); // Remove it so that we can match another parameter with the same value. } else { arg = elem; AddNamedParameter(param, arg); param = null; arg = null; } } } Validation.CheckInvariant <CommandLineException>((param != null) || (arg == null)); AddNamedParameter(param, arg); Parameters = parameters; void AddNamedParameter(CommandParameterAst parameter, Ast parameterValue) { if (parameter != null) { var value = parameterValue?.ToString(); if (value == null) { value = parameter.Argument?.ToString(); } if (value != null) { value = CommandLineUtilities.UnescapePredictionText(value); } parameters.Add(new Parameter(parameter.ParameterName, value, false)); } } }
private static ArmResourceName GetResourceNameFromAst(CommandAst commandAst) { string @namespace = null; string type = null; string apiVersion = null; var expectedParameter = ResourceKeywordParameter.None; foreach (CommandElementAst commandElement in commandAst.CommandElements) { if (expectedParameter != ResourceKeywordParameter.None && commandElement is CommandParameterAst parameterAst) { if (parameterAst.ParameterName.Is(nameof(NewPSArmResourceCommand.Namespace))) { if (parameterAst.Argument != null) { @namespace = (parameterAst.Argument as StringConstantExpressionAst)?.Value; } else { expectedParameter = ResourceKeywordParameter.Namespace; } continue; } if (parameterAst.ParameterName.Is(nameof(NewPSArmResourceCommand.Type))) { if (parameterAst.Argument != null) { type = (parameterAst.Argument as StringConstantExpressionAst)?.Value; } else { expectedParameter = ResourceKeywordParameter.Type; } continue; } if (parameterAst.ParameterName.Is(nameof(NewPSArmResourceCommand.ApiVersion))) { if (parameterAst.Argument != null) { apiVersion = (parameterAst.Argument as StringConstantExpressionAst)?.Value; } else { expectedParameter = ResourceKeywordParameter.ApiVersion; } continue; } } switch (expectedParameter) { case ResourceKeywordParameter.Namespace: @namespace = (commandElement as StringConstantExpressionAst)?.Value; break; case ResourceKeywordParameter.Type: type = (commandElement as StringConstantExpressionAst)?.Value; break; case ResourceKeywordParameter.ApiVersion: apiVersion = (commandElement as StringConstantExpressionAst)?.Value; break; } expectedParameter = ResourceKeywordParameter.None; } return(new ArmResourceName(@namespace, type, apiVersion)); }
private bool HasRequiredParameters(CommandAst commandAst) { var bindResult = BindParameters(commandAst); return(HasNameParameter(commandAst, bindResult) && HasBodyParameter(commandAst, bindResult)); }
/// <inheritdoc/> public override void RecordHistory(CommandAst history) { History = history; }
public IEnumerable <CompletionResult> CompleteArgument(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters) { var organizer = new SnippetOrganizer(SnippyOptions.Instance.Value, FileAssociations.Instance.Value); var languages = organizer.GetUniqueLanguages(); return(string.IsNullOrEmpty(wordToComplete) ? languages.Select(x => new CompletionResult(x)) : languages.Where(x => x.StartsWith(wordToComplete)).Select(x => new CompletionResult(x))); }
// This method does parameter binding for a very limited set of scenarios, specifically // for New-Alias, Set-Alias, Import-Module, and Export-ModuleMember. It might not even // correctly handle these cmdlets if new parameters are added. // // It also only populates the bound parameters for a limited set of parameters needed // for module analysis. private static Hashtable DoPsuedoParameterBinding(CommandAst commandAst, string commandName) { var result = new Hashtable(StringComparer.OrdinalIgnoreCase); var parameterBindingInfo = s_parameterBindingInfoTable[commandName].parameterInfo; int positionsBound = 0; for (int i = 1; i < commandAst.CommandElements.Count; i++) { var element = commandAst.CommandElements[i]; var specifiedParameter = element as CommandParameterAst; if (specifiedParameter != null) { bool boundParameter = false; var specifiedParamName = specifiedParameter.ParameterName; foreach (var parameterInfo in parameterBindingInfo) { if (parameterInfo.name.StartsWith(specifiedParamName, StringComparison.OrdinalIgnoreCase)) { if (parameterInfo.position != -1) { positionsBound |= 1 << parameterInfo.position; } var argumentAst = specifiedParameter.Argument; if (argumentAst == null) { argumentAst = commandAst.CommandElements[i] as ExpressionAst; if (argumentAst != null) { i += 1; } } if (argumentAst != null) { boundParameter = true; result[parameterInfo.name] = GetSafeValueVisitor.GetSafeValue(argumentAst, null, GetSafeValueVisitor.SafeValueContext.ModuleAnalysis); } break; } } if (boundParameter || specifiedParameter.Argument != null) { continue; } if (!"PassThru".StartsWith(specifiedParamName, StringComparison.OrdinalIgnoreCase) && !"Force".StartsWith(specifiedParamName, StringComparison.OrdinalIgnoreCase) && !"Confirm".StartsWith(specifiedParamName, StringComparison.OrdinalIgnoreCase) && !"Global".StartsWith(specifiedParamName, StringComparison.OrdinalIgnoreCase) && !"AsCustomObject".StartsWith(specifiedParamName, StringComparison.OrdinalIgnoreCase) && !"Verbose".StartsWith(specifiedParamName, StringComparison.OrdinalIgnoreCase) && !"Debug".StartsWith(specifiedParamName, StringComparison.OrdinalIgnoreCase) && !"DisableNameChecking".StartsWith(specifiedParamName, StringComparison.OrdinalIgnoreCase) && !"NoClobber".StartsWith(specifiedParamName, StringComparison.OrdinalIgnoreCase)) { // Named parameter, skip the argument (except for specific switch parameters i += 1; } } else { // Positional argument, find which position we want to bind int pos = 0; for (; pos < 10; pos++) { if ((positionsBound & (1 << pos)) == 0) { break; } } positionsBound |= 1 << pos; // Now see if we care (we probably do, but if the user did something odd, like specify too many, then we don't really) foreach (var parameterInfo in parameterBindingInfo) { if (parameterInfo.position == pos) { result[parameterInfo.name] = GetSafeValueVisitor.GetSafeValue( commandAst.CommandElements[i], null, GetSafeValueVisitor.SafeValueContext.ModuleAnalysis); } } } } return(result); }
public IEnumerable <CompletionResult> CompleteArgument(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters) { return(PrivilegeHelper.ALL_PRIVILEGES .Concat(Lsa.ALL_RIGHTS.Keys) .Where(p => p.StartsWith(wordToComplete, true, CultureInfo.InvariantCulture)) .Select(p => ProcessPrivilege(p))); }
public override AstVisitAction VisitCommand(CommandAst ast) { return(Check(ast)); }
public IEnumerable <CompletionResult> CompleteArgument(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters) { var wc = new WildcardPattern(wordToComplete + "*", WildcardOptions.IgnoreCase); return(GetPSMembers().Concat(GetTypeMembers() ?? Array.Empty <string>()) .Where(i => wc.IsMatch(i)) .Select(i => CreateCompletionResult(i))); }
/// <summary> /// Convert a CommandAst known to represent a Pester command and a reference to the scriptfile /// it is in into symbol representing a Pester call for code lens /// </summary> /// <param name="scriptFile">the scriptfile the Pester call occurs in</param> /// <param name="pesterCommandAst">the CommandAst representing the Pester call</param> /// <returns>a symbol representing the Pester call containing metadata for CodeLens to use</returns> private static PesterSymbolReference ConvertPesterAstToSymbolReference(ScriptFile scriptFile, CommandAst pesterCommandAst) { string testLine = scriptFile.GetLine(pesterCommandAst.Extent.StartLineNumber); PesterCommandType?commandName = PesterSymbolReference.GetCommandType(pesterCommandAst.GetCommandName()); if (commandName == null) { return(null); } // Search for a name for the test // If the test has more than one argument for names, we set it to null string testName = null; bool alreadySawName = false; for (int i = 1; i < pesterCommandAst.CommandElements.Count; i++) { CommandElementAst currentCommandElement = pesterCommandAst.CommandElements[i]; // Check for an explicit "-Name" parameter if (currentCommandElement is CommandParameterAst parameterAst) { i++; if (parameterAst.ParameterName == "Name" && i < pesterCommandAst.CommandElements.Count) { testName = alreadySawName ? null : (pesterCommandAst.CommandElements[i] as StringConstantExpressionAst)?.Value; alreadySawName = true; } continue; } // Otherwise, if an argument is given with no parameter, we assume it's the name // If we've already seen a name, we set the name to null if (pesterCommandAst.CommandElements[i] is StringConstantExpressionAst testNameStrAst) { testName = alreadySawName ? null : testNameStrAst.Value; alreadySawName = true; } } return(new PesterSymbolReference( scriptFile, commandName.Value, testLine, testName, pesterCommandAst.Extent )); }
/// <summary> /// Returns completion results for experimental feature names used as arguments to experimental feature cmdlets. /// </summary> /// <param name="commandName">The command name.</param> /// <param name="parameterName">The parameter name.</param> /// <param name="wordToComplete">The word to complete.</param> /// <param name="commandAst">The command AST.</param> /// <param name="fakeBoundParameters">The fake bound parameters.</param> /// <returns>List of Completion Results.</returns> public IEnumerable <CompletionResult> CompleteArgument(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters) { if (fakeBoundParameters == null) { throw PSTraceSource.NewArgumentNullException(nameof(fakeBoundParameters)); } var commandInfo = new CmdletInfo("Get-ExperimentalFeature", typeof(GetExperimentalFeatureCommand)); var ps = System.Management.Automation.PowerShell.Create(RunspaceMode.CurrentRunspace) .AddCommand(commandInfo) .AddParameter("Name", wordToComplete + "*"); HashSet <string> names = new HashSet <string>(); var results = ps.Invoke <ExperimentalFeature>(); foreach (var result in results) { names.Add(result.Name); } return(names.OrderBy(name => name).Select(name => new CompletionResult(name, name, CompletionResultType.Text, name))); }
public object VisitCommand(CommandAst commandAst) => null;
/// <summary> /// Iterate over command elements to extract local parameter values. /// /// Store these values by a key /// consisting of the suffix of the command + the parameter name. There are some exceptions, e.g. /// credential, location, where the parameter name itself is the key. /// /// For example, New-AzResourceGroup -Name Hello -Location 'EastUS' will store into local parameters: /// ResourceGroupName => Hello /// Location => 'EastUS' /// </summary> /// <param name="command">The command ast element</param> /// <remarks> /// This doesn't support positional parameter. /// </remarks> private void ExtractLocalParameters(CommandAst command) { // Azure PowerShell command is in the form of {Verb}-Az{Noun}, e.g. New-AzResource. // We need to extract the noun to construct the parameter name. var commandName = command.GetCommandName(); var commandNoun = ParameterValuePredictor.GetAzCommandNoun(commandName)?.ToLower(); if (commandNoun == null) { return; } Dictionary <string, string> commandNounMap = null; _commandParamToResourceMap?.TryGetValue(commandNoun, out commandNounMap); for (int i = 1; i < command.CommandElements.Count;) { if (command.CommandElements[i] is CommandParameterAst parameterAst) { var parameterName = parameterAst.ParameterName.ToLower(); string parameterValue = null; // In the form of "-Name:Value" if (parameterAst.Argument != null) { parameterValue = parameterAst.Argument.ToString(); ++i; } else if (i + 1 < command.CommandElements.Count) { // We don't support positional parameter. // The next element is either // 1. The value of this parameter name. // 2. This parameter is a switch parameter which doesn't have a value. The next element is a parameter. var nextElement = command.CommandElements[i + 1]; if (nextElement is CommandParameterAst) { ++i; continue; } parameterValue = command.CommandElements[i + 1].ToString(); i += 2; } var parameterKey = parameterName; if (commandNounMap != null) { if (commandNounMap.TryGetValue(parameterName, out var mappedValue)) { parameterKey = mappedValue; } } _cancellationTokenSource?.Cancel(); _cancellationTokenSource = new CancellationTokenSource(); Task.Run(() => { this._localParameterValues.AddOrUpdate(parameterKey, parameterValue, (k, v) => parameterValue); if (_cancellationTokenSource.IsCancellationRequested) { throw new OperationCanceledException(); } String localParameterValuesJson = JsonSerializer.Serialize <ConcurrentDictionary <string, string> >(_localParameterValues, JsonUtilities.DefaultSerializerOptions); _mutex.WaitOne(); try { System.IO.File.WriteAllText(_paramValueHistoryFilePath, localParameterValuesJson); } finally { _mutex.ReleaseMutex(); } }); } } }
/// <summary> /// Condition on the parameter that must be satisfied for the error to be raised. /// </summary> /// <param name="CmdAst"></param> /// <param name="CeAst"></param> /// <returns></returns> public override bool ParameterCondition(CommandAst CmdAst, CommandElementAst CeAst) { return(CeAst is CommandParameterAst && String.Equals((CeAst as CommandParameterAst).ParameterName, "AsPlainText", StringComparison.OrdinalIgnoreCase)); }
/// <summary> /// Return true if mandatory parameters are used OR the cmdlet does not exist /// </summary> /// <param name="cmdAst"></param> /// <returns></returns> private bool MandatoryParameterExists(CommandAst cmdAst) { CommandInfo cmdInfo = null; List <ParameterMetadata> mandParams = new List <ParameterMetadata>(); IEnumerable <CommandElementAst> ceAsts = null; bool returnValue = false; #region Predicates // Predicate to find ParameterAsts. Func <CommandElementAst, bool> foundParamASTs = delegate(CommandElementAst ceAst) { if (ceAst is CommandParameterAst) { return(true); } return(false); }; #endregion #region Compares parameter list and mandatory parameter list. cmdInfo = Helper.Instance.GetCommandInfoLegacy(cmdAst.GetCommandName()); if (cmdInfo == null || (cmdInfo.CommandType != System.Management.Automation.CommandTypes.Cmdlet)) { return(true); } // ignores if splatted variable is used if (Helper.Instance.HasSplattedVariable(cmdAst)) { return(true); } // Gets parameters from command elements. ceAsts = cmdAst.CommandElements.Where <CommandElementAst>(foundParamASTs); // Gets mandatory parameters from cmdlet. // If cannot find any mandatory parameter, it's not necessary to do a further check for current cmdlet. try { int noOfParamSets = cmdInfo.ParameterSets.Count; foreach (ParameterMetadata pm in cmdInfo.Parameters.Values) { int count = 0; if (pm.Attributes.Count < noOfParamSets) { continue; } foreach (Attribute attr in pm.Attributes) { if (!(attr is ParameterAttribute)) { continue; } if (((ParameterAttribute)attr).Mandatory) { count += 1; } } if (count >= noOfParamSets) { mandParams.Add(pm); } } } catch (Exception) { // For cases like cmd.exe. Also for runtime exception return(true); } if (mandParams.Count() == 0 || Helper.Instance.PositionalParameterUsed(cmdAst)) { returnValue = true; } else { // Compares parameter list and mandatory parameter list. foreach (CommandElementAst ceAst in ceAsts) { CommandParameterAst cpAst = (CommandParameterAst)ceAst; if (mandParams.Count <ParameterMetadata>(item => item.Name.Equals(cpAst.ParameterName, StringComparison.OrdinalIgnoreCase)) > 0) { returnValue = true; break; } } } #endregion return(returnValue); }
/// <summary> /// Determines if the command is a document definition. /// </summary> private bool IsDefinition(CommandAst commandAst) { return(_Comparer.Equals(commandAst.GetCommandName(), DOCUMENT_KEYWORD)); }
/// <inheritdoc/> /// <remarks> /// Tries to get the suggestions for the user input from the command history. If that doesn't find /// <paramref name="suggestionCount"/> suggestions, it'll fallback to find the suggestion regardless of command history. /// </remarks> public virtual CommandLineSuggestion GetSuggestion(PredictionContext context, int suggestionCount, int maxAllowedCommandDuplicate, CancellationToken cancellationToken) { Validation.CheckArgument(context, $"{nameof(context)} cannot be null"); Validation.CheckArgument <ArgumentOutOfRangeException>(suggestionCount > 0, $"{nameof(suggestionCount)} must be larger than 0."); Validation.CheckArgument <ArgumentOutOfRangeException>(maxAllowedCommandDuplicate > 0, $"{nameof(maxAllowedCommandDuplicate)} must be larger than 0."); var relatedAsts = context.RelatedAsts; CommandAst commandAst = null; for (var i = relatedAsts.Count - 1; i >= 0; --i) { if (relatedAsts[i] is CommandAst c) { commandAst = c; break; } } if (commandAst == null) { return(null); } var commandName = commandAst.GetCommandName(); if (string.IsNullOrWhiteSpace(commandName)) { return(null); } ParameterSet inputParameterSet = null; try { inputParameterSet = new ParameterSet(commandAst, _azContext); } catch when(!IsRecognizedCommand(commandName)) { // We only ignore the exception when the command name is not supported. // We want to collect the telemetry about the exception how common it is for the format we don't support. return(null); } cancellationToken.ThrowIfCancellationRequested(); // We want to show a survey/feedback cmdlet at the end of the suggestion list. We try to find one less // suggestions to make room for that cmdlet and avoid too much computation. // But if only one suggestion is requested, we don't replace it with the survey cmdlets. var suggestionFromPredictorCount = (suggestionCount == 1) ? 1 : (suggestionCount - 1); var rawUserInput = context.InputAst.ToString(); var presentCommands = new Dictionary <string, int>(); var commandBasedPredictor = _commandBasedPredictor; var commandToRequestPrediction = _commandToRequestPrediction; var result = commandBasedPredictor?.Item2?.GetSuggestion(commandName, inputParameterSet, rawUserInput, presentCommands, suggestionFromPredictorCount, maxAllowedCommandDuplicate, cancellationToken); if ((result != null) && (result.Count > 0)) { var suggestionSource = SuggestionSource.PreviousCommand; if (string.Equals(commandToRequestPrediction, commandBasedPredictor?.Item1, StringComparison.Ordinal)) { suggestionSource = SuggestionSource.CurrentCommand; } for (var i = 0; i < result.Count; ++i) { result.UpdateSuggestionSource(i, suggestionSource); } } if ((result == null) || (result.Count < suggestionFromPredictorCount)) { var fallbackPredictor = _fallbackPredictor; var suggestionCountToRequest = (result == null) ? suggestionFromPredictorCount : suggestionFromPredictorCount - result.Count; var resultsFromFallback = fallbackPredictor?.GetSuggestion(commandName, inputParameterSet, rawUserInput, presentCommands, suggestionCountToRequest, maxAllowedCommandDuplicate, cancellationToken); if ((result == null) && (resultsFromFallback != null)) { result = resultsFromFallback; for (var i = 0; i < result.Count; ++i) { result.UpdateSuggestionSource(i, SuggestionSource.StaticCommands); } } else if ((resultsFromFallback != null) && (resultsFromFallback.Count > 0)) { for (var i = 0; i < resultsFromFallback.Count; ++i) { result.AddSuggestion(resultsFromFallback.PredictiveSuggestions[i], resultsFromFallback.SourceTexts[i], SuggestionSource.StaticCommands); } } } if (suggestionCount > 1) { // Add the survey/feedback cmdlet at the end if the user isn't typing it. bool isSurveyCmdletFound = false; if (result != null) { foreach (var predictiveCommand in result.SourceTexts) { if (string.Equals(predictiveCommand, _surveyCmdlets[_azContext.Cohort].Command, StringComparison.Ordinal)) { isSurveyCmdletFound = true; break; } } } else { result = new CommandLineSuggestion(); } if (!isSurveyCmdletFound) { var toAddCmdlet = _surveyCmdlets[_azContext.Cohort].Command; var toAddDescription = _surveyCmdlets[_azContext.Cohort].Description; result.AddSuggestion(new PredictiveSuggestion($"{toAddCmdlet} # {toAddDescription}", toAddCmdlet), toAddCmdlet, SuggestionSource.StaticCommands); } } return(result); }
// Visit one the other variations: // - Dotting scripts // - Setting aliases // - Importing modules // - Exporting module members public override AstVisitAction VisitCommand(CommandAst commandAst) { string commandName = commandAst.GetCommandName() ?? GetSafeValueVisitor.GetSafeValue(commandAst.CommandElements[0], null, GetSafeValueVisitor.SafeValueContext.ModuleAnalysis) as string; if (commandName == null) { return(AstVisitAction.SkipChildren); } // They are trying to dot a script if (commandAst.InvocationOperator == TokenKind.Dot) { // . Foo-Bar4.ps1 // . $psScriptRoot\Foo-Bar.ps1 -Bing Baz // . ""$psScriptRoot\Support Files\Foo-Bar2.ps1"" -Bing Baz // . '$psScriptRoot\Support Files\Foo-Bar3.ps1' -Bing Baz DiscoveredModules.Add( new RequiredModuleInfo { Name = commandName, CommandsToPostFilter = new List <string>() }); ModuleIntrinsics.Tracer.WriteLine("Module dots {0}", commandName); } // They are setting an alias. if (string.Equals(commandName, "New-Alias", StringComparison.OrdinalIgnoreCase) || string.Equals(commandName, "Microsoft.PowerShell.Utility\\New-Alias", StringComparison.OrdinalIgnoreCase) || string.Equals(commandName, "Set-Alias", StringComparison.OrdinalIgnoreCase) || string.Equals(commandName, "Microsoft.PowerShell.Utility\\Set-Alias", StringComparison.OrdinalIgnoreCase) || string.Equals(commandName, "nal", StringComparison.OrdinalIgnoreCase) || string.Equals(commandName, "sal", StringComparison.OrdinalIgnoreCase)) { // Set-Alias Foo-Bar5 Foo-Bar // Set-Alias -Name Foo-Bar6 -Value Foo-Bar // sal Foo-Bar7 Foo-Bar // sal -Value Foo-Bar -Name Foo-Bar8 var boundParameters = DoPsuedoParameterBinding(commandAst, commandName); var name = boundParameters["Name"] as string; if (!string.IsNullOrEmpty(name)) { var value = boundParameters["Value"] as string; if (!string.IsNullOrEmpty(value)) { // These aren't stored in DiscoveredExports, as they are only // exported after the user calls Export-ModuleMember. DiscoveredAliases[name] = value; ModuleIntrinsics.Tracer.WriteLine("Module defines alias: {0} = {1}", name, value); } } return(AstVisitAction.SkipChildren); } // They are importing a module if (string.Equals(commandName, "Import-Module", StringComparison.OrdinalIgnoreCase) || string.Equals(commandName, "ipmo", StringComparison.OrdinalIgnoreCase)) { // Import-Module Module1 // Import-Module Module2 -Function Foo-Module2*, Foo-Module2Second* -Cmdlet Foo-Module2Cmdlet,Foo-Module2Cmdlet* // Import-Module Module3 -Function Foo-Module3Command1, Foo-Module3Command2 // Import-Module Module4, // Module5 // Import-Module -Name Module6, // Module7 -Global var boundParameters = DoPsuedoParameterBinding(commandAst, commandName); List <string> commandsToPostFilter = new List <string>(); Action <string> onEachCommand = importedCommandName => commandsToPostFilter.Add(importedCommandName); // Process any exports from the module that we determine from // the -Function, -Cmdlet, or -Alias parameters ProcessCmdletArguments(boundParameters["Function"], onEachCommand); ProcessCmdletArguments(boundParameters["Cmdlet"], onEachCommand); ProcessCmdletArguments(boundParameters["Alias"], onEachCommand); // Now, go through all of the discovered modules on Import-Module // and register them for deeper investigation. Action <string> onEachModule = moduleName => { ModuleIntrinsics.Tracer.WriteLine("Discovered module import: {0}", moduleName); DiscoveredModules.Add( new RequiredModuleInfo { Name = moduleName, CommandsToPostFilter = commandsToPostFilter }); }; ProcessCmdletArguments(boundParameters["Name"], onEachModule); return(AstVisitAction.SkipChildren); } // They are exporting a module member if (string.Equals(commandName, "Export-ModuleMember", StringComparison.OrdinalIgnoreCase) || string.Equals(commandName, "Microsoft.PowerShell.Core\\Export-ModuleMember", StringComparison.OrdinalIgnoreCase) || string.Equals(commandName, "$script:ExportModuleMember", StringComparison.OrdinalIgnoreCase)) { // Export-ModuleMember * // Export-ModuleMember Exported-UnNamedModuleMember // Export-ModuleMember -Function Exported-FunctionModuleMember1, Exported-FunctionModuleMember2 -Cmdlet Exported-CmdletModuleMember ` // -Alias Exported-AliasModuleMember // & $script:ExportModuleMember -Function (...) var boundParameters = DoPsuedoParameterBinding(commandAst, commandName); Action <string> onEachFunction = exportedCommandName => { DiscoveredCommandFilters.Add(exportedCommandName); ModuleIntrinsics.Tracer.WriteLine("Discovered explicit export: {0}", exportedCommandName); // If the export doesn't contain wildcards, then add it to the // discovered commands as well. It is likely that they created // the command dynamically if ((!WildcardPattern.ContainsWildcardCharacters(exportedCommandName)) && (!DiscoveredExports.Contains(exportedCommandName))) { DiscoveredExports.Add(exportedCommandName); } }; ProcessCmdletArguments(boundParameters["Function"], onEachFunction); ProcessCmdletArguments(boundParameters["Cmdlet"], onEachFunction); Action <string> onEachAlias = exportedAlias => { DiscoveredCommandFilters.Add(exportedAlias); // If the export doesn't contain wildcards, then add it to the // discovered commands as well. It is likely that they created // the command dynamically if (!WildcardPattern.ContainsWildcardCharacters(exportedAlias)) { DiscoveredAliases[exportedAlias] = null; } }; ProcessCmdletArguments(boundParameters["Alias"], onEachAlias); return(AstVisitAction.SkipChildren); } // They are exporting a module member using our advanced 'public' function // that we've presented in many demos if ((string.Equals(commandName, "public", StringComparison.OrdinalIgnoreCase)) && (commandAst.CommandElements.Count > 2)) { // public function Publicly-ExportedFunction // public alias Publicly-ExportedAlias string publicCommandName = commandAst.CommandElements[2].ToString().Trim(); DiscoveredExports.Add(publicCommandName); DiscoveredCommandFilters.Add(publicCommandName); } return(AstVisitAction.SkipChildren); }
/// <inheritdoc/> public virtual void RecordHistory(CommandAst history) { Validation.CheckArgument(history, $"{nameof(history)} cannot be null."); _parameterValuePredictor.ProcessHistoryCommand(history); }
/// <summary> /// Determines if the command is a rule definition. /// </summary> private bool IsRule(CommandAst commandAst) { return(_Comparer.Equals(commandAst.GetCommandName(), RULE_KEYWORD)); }
/// <summary> /// GetError: Retrieves the error message. /// </summary> /// <returns></returns> public abstract string GetError(string FileName, CommandAst CmdAst);
private void ConvertCommand(CommandAst commandAst, bool isTrustedInput) { // First need command name. var commandName = GetCommandName(commandAst.CommandElements[0], isTrustedInput); var command = new Command(commandName, isScript: false, useLocalScope: _createLocalScope); // Handle redirections, if any (there can really be just 0 or 1). if (commandAst.Redirections.Count > 0) { Diagnostics.Assert(commandAst.Redirections.Count == 1, "only 1 kind of redirection is supported"); Diagnostics.Assert(commandAst.Redirections[0] is MergingRedirectionAst, "unexpected redirection type"); PipelineResultTypes toType = PipelineResultTypes.Output; PipelineResultTypes fromType; switch (commandAst.Redirections[0].FromStream) { case RedirectionStream.Error: fromType = PipelineResultTypes.Error; break; case RedirectionStream.Warning: fromType = PipelineResultTypes.Warning; break; case RedirectionStream.Verbose: fromType = PipelineResultTypes.Verbose; break; case RedirectionStream.Debug: fromType = PipelineResultTypes.Debug; break; case RedirectionStream.Information: fromType = PipelineResultTypes.Information; break; case RedirectionStream.All: fromType = PipelineResultTypes.All; break; default: // Default to Error->Output to be compatible with V2. fromType = PipelineResultTypes.Error; break; } command.MergeMyResults(fromType, toType); } _powershell.AddCommand(command); // Now the parameters and arguments. foreach (var ast in commandAst.CommandElements.Skip(1)) { var exprAst = ast as ExpressionAst; if (exprAst != null) { VariableExpressionAst variableAst = null; var usingExprAst = ast as UsingExpressionAst; if (usingExprAst != null) { string usingAstKey = PsUtils.GetUsingExpressionKey(usingExprAst); object usingValue = _usingValueMap[usingAstKey]; variableAst = usingExprAst.SubExpression as VariableExpressionAst; if (variableAst != null && variableAst.Splatted) { // Support the splatting of a dictionary var parameters = usingValue as System.Collections.IDictionary; if (parameters != null) { _powershell.AddParameters(parameters); } else { // Support the splatting of an array var arguments = usingValue as System.Collections.IEnumerable; if (arguments != null) { foreach (Object argument in arguments) { _powershell.AddArgument(argument); } } else { // Splat the object directly. _powershell.AddArgument(usingValue); } } } else { _powershell.AddArgument(usingValue); } continue; } variableAst = ast as VariableExpressionAst; if (variableAst != null && variableAst.Splatted) { GetSplattedVariable(variableAst); } else { var constantExprAst = ast as ConstantExpressionAst; object argument; if (constantExprAst != null && LanguagePrimitives.IsNumeric(LanguagePrimitives.GetTypeCode(constantExprAst.StaticType))) { var commandArgumentText = constantExprAst.Extent.Text; argument = constantExprAst.Value; if (!commandArgumentText.Equals(constantExprAst.Value.ToString(), StringComparison.Ordinal)) { // The wrapped number will actually return a PSObject which could end holding a reference to // a typetable, making the object runspace specific. We should find a better way to avoid // any possibility of sharing problems, though this is unlikely to cause problems. argument = ParserOps.WrappedNumber(argument, commandArgumentText); } } else { if (!isTrustedInput) { try { argument = GetSafeValueVisitor.GetSafeValue(exprAst, _context, GetSafeValueVisitor.SafeValueContext.GetPowerShell); } catch (System.Exception) { throw new ScriptBlockToPowerShellNotSupportedException( "CantConvertWithDynamicExpression", null, AutomationExceptions.CantConvertWithDynamicExpression, exprAst.Extent.Text); } } else { argument = GetExpressionValue(exprAst, isTrustedInput); } } _powershell.AddArgument(argument); } } else { AddParameter((CommandParameterAst)ast, isTrustedInput); } } }
/// <summary> /// Condition on the cmdlet that must be satisfied for the error to be raised /// </summary> /// <param name="CmdAst"></param> /// <returns></returns> public abstract bool CommandCondition(CommandAst CmdAst);
/// <summary> /// Implementations CompleteArgument function of the <see cref="IArgumentCompleter"/>. /// </summary> public IEnumerable <CompletionResult> CompleteArgument(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters) { IEnumerable <string> names = GetEnvironments().Where(env => env.ToLower().StartsWith(wordToComplete.ToLower())); foreach (string name in names) { yield return(new CompletionResult(name, name, CompletionResultType.ParameterValue, name)); } }
/// <summary> /// Condition on the parameter that must be satisfied for the error to be raised. /// </summary> /// <param name="CmdAst"></param> /// <param name="CeAst"></param> /// <returns></returns> public abstract bool ParameterCondition(CommandAst CmdAst, CommandElementAst CeAst);
/// <summary> /// CompleteArgument. /// </summary> public IEnumerable <CompletionResult> CompleteArgument(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters) { var wordToCompletePattern = WildcardPattern.Get(string.IsNullOrWhiteSpace(wordToComplete) ? "*" : wordToComplete + "*", WildcardOptions.IgnoreCase); foreach (var edition in Utils.AllowedEditionValues) { if (wordToCompletePattern.IsMatch(edition)) { yield return(new CompletionResult(edition, edition, CompletionResultType.Text, edition)); } } }
/// <summary> /// Condition on the cmdlet that must be satisfied for the error to be raised /// </summary> /// <param name="CmdAst"></param> /// <returns></returns> public override bool CommandCondition(CommandAst CmdAst) { return(true); }
/// <summary> /// Offers the names of types loaded into the session for argument completion. /// </summary> public IEnumerable <CompletionResult> CompleteArgument(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters) { var wc = new WildcardPattern(wordToComplete?.Trim("\"'()[]".ToCharArray()) + "*", WildcardOptions.IgnoreCase); var types = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(a => a.GetTypes()) .Where(t => t.IsPublic) .Select(t => (t.FullName, t.Name)) .Where(n => wc.IsMatch(n.Name) || wc.IsMatch(n.FullName)); foreach (var(FullName, Name) in types) { string safeOutput = FullName.Contains(" ") ? "'" + CodeGeneration.EscapeSingleQuotedStringContent(FullName) + "'" : FullName; yield return(new CompletionResult(safeOutput, FullName, CompletionResultType.Type, FullName)); } }
/// <summary> /// Offers argument completion for IPv4 address values. /// </summary> /// <param name="commandName">Unused</param> /// <param name="parameterName">Unused</param> /// <param name="wordToComplete">IP addresses will be matched against any value in this string. /// The closer to the intended IP address, the more accurate the argument completion results will be.</param> /// <param name="commandAst">Unused</param> /// <param name="fakeBoundParameters">Unused</param> /// <returns></returns> public IEnumerable <CompletionResult> CompleteArgument(string commandName, string parameterName, string wordToComplete, CommandAst commandAst, IDictionary fakeBoundParameters) { wordToComplete += "*"; string[]? octetStrings = wordToComplete?.Split('.'); if (octetStrings?.Length > 4) { yield break; } IEnumerable <byte>[] ranges = new IEnumerable <byte> [4]; for (int i = 0; i < 4; i++) { string?octetString = octetStrings?.Length > i ? octetStrings[i] : null; ranges[i] = CompleteOctet(octetString); } decimal returned = 0; foreach (byte firstOctet in ranges[0]) { foreach (byte secondOctet in ranges[1]) { foreach (byte thirdOctet in ranges[2]) { foreach (byte fourthOctet in ranges[3]) { var ip = new IPAddress(new[] { firstOctet, secondOctet, thirdOctet, fourthOctet }).ToString(); yield return(new CompletionResult(ip, ip, CompletionResultType.ParameterValue, ip)); if (returned++ > MaximumReturnCount) { yield break; } } } } } }