private string GetCommandName(CommandElementAst commandNameAst, bool isTrustedInput) { var exprAst = commandNameAst as ExpressionAst; string commandName; if (exprAst != null) { var value = GetExpressionValue(exprAst, isTrustedInput); if (value == null) { ScriptBlockToPowerShellChecker.ThrowError( new ScriptBlockToPowerShellNotSupportedException( "CantConvertWithScriptBlockInvocation", null, AutomationExceptions.CantConvertWithScriptBlockInvocation), exprAst); } if (value is CommandInfo) { commandName = ((CommandInfo)value).Name; } else { commandName = value as string; } } else { // If this assertion fires, the command name is determined incorrectly. Diagnostics.Assert(commandNameAst is CommandParameterAst, "Unexpected element not handled correctly."); commandName = commandNameAst.Extent.Text; } if (string.IsNullOrWhiteSpace(commandName)) { // TODO: could use a better error here throw new ScriptBlockToPowerShellNotSupportedException( "CantConvertWithScriptBlockInvocation", null, AutomationExceptions.CantConvertWithScriptBlockInvocation); } return(commandName); }
/// <summary> /// Checks to see if the command invocation is a dot /// in order to find a dot sourced file /// </summary> /// <param name="commandAst">A CommandAst object in the script's AST</param> /// <returns>A decision to stop searching if the right commandAst was found, /// or a decision to continue if it wasn't found</returns> public override AstVisitAction VisitCommand(CommandAst commandAst) { CommandElementAst commandElementAst = commandAst.CommandElements[0]; if (commandAst.InvocationOperator.Equals(TokenKind.Dot)) { string path = commandElementAst switch { StringConstantExpressionAst stringConstantExpressionAst => stringConstantExpressionAst.Value, ExpandableStringExpressionAst expandableStringExpressionAst => GetPathFromExpandableStringExpression(expandableStringExpressionAst), _ => null, }; if (!string.IsNullOrWhiteSpace(path)) { DotSourcedFiles.Add(PathUtils.NormalizePathSeparators(path)); } } return(base.VisitCommand(commandAst)); }
/// <summary> /// Creates a Linq expression for a <see cref="CommandAst" /> representing /// the "with" command. /// </summary> /// <param name="commandAst">The AST to convert.</param> /// <param name="targetAst">The AST containing the target of the keyword.</param> /// <param name="bodyAst">The AST containing the body of the keyword.</param> /// <param name="visitor">The <see cref="CompileVisitor" /> requesting the expression.</param> /// <returns>An expression representing the command.</returns> protected override Expression ProcessObjectAndBody( CommandAst commandAst, CommandElementAst targetAst, ScriptBlockExpressionAst bodyAst, CompileVisitor visitor) { var disposeVar = Expression.Variable(typeof(IDisposable)); return(visitor.NewBlock(() => Expression.Block( typeof(void), new[] { disposeVar }, Expression.Assign( disposeVar, Expression.Convert( targetAst.Compile(visitor), typeof(IDisposable))), Expression.TryFinally( bodyAst.ScriptBlock.EndBlock.Compile(visitor), Expression.Call(disposeVar, ReflectionCache.IDisposable_Dispose))))); }
public static CommandAst As( this Ast source, AstType <CommandAst> targetType, string commandName, TokenKind invocationOperator, params CommandElementAst[] elements) { var extent = GetExtentFromConstant(commandName, source.Extent); var newElements = new CommandElementAst[elements.Length + 1]; for (int i = 0; i < elements.Length; i++) { newElements[i + 1] = elements[i]; } newElements[0] = source.As(StringConstantExpression, commandName); return(new CommandAst( extent, newElements, invocationOperator, Enumerable.Empty <RedirectionAst>())); }
CommandParameter ConvertCommandElementToCommandParameter(CommandElementAst commandElement) { if (commandElement is CommandParameterAst) { var commandParameterAst = commandElement as CommandParameterAst; return(new CommandParameter(commandParameterAst.ParameterName, commandParameterAst.Argument)); } else if (commandElement is StringConstantExpressionAst) { var stringConstantExpressionAst = commandElement as StringConstantExpressionAst; return(new CommandParameter(null, stringConstantExpressionAst.Value)); } else if (commandElement is ExpressionAst) { return(new CommandParameter(null, EvaluateAst(commandElement))); } else { throw new NotImplementedException(); } }
private ArmResourceName?GetResourceName() { if (CommandAst.CommandElements is null) { return(null); } string resourceNamespace = null; string type = null; string apiVersion = null; int expect = 0; for (int i = 0; i < CommandAst.CommandElements.Count; i++) { CommandElementAst element = CommandAst.CommandElements[i]; if (element is CommandParameterAst parameterAst) { expect = 0; if (parameterAst.ParameterName.Is(nameof(NewPSArmResourceCommand.Type))) { expect = 1; } else if (parameterAst.ParameterName.Is(nameof(NewPSArmResourceCommand.ApiVersion))) { expect = 2; } else if (parameterAst.ParameterName.Is(nameof(NewPSArmResourceCommand.Namespace))) { expect = 3; } continue; } switch (expect) { case 1: if (element is StringConstantExpressionAst typeStrExpr) { type = typeStrExpr.Value; } break; case 2: if (element is StringConstantExpressionAst apiVersionStrExpr) { apiVersion = apiVersionStrExpr.Value; } break; case 3: if (element is StringConstantExpressionAst providerStrExpr) { resourceNamespace = providerStrExpr.Value; } break; } expect = 0; } if (resourceNamespace is null && type is null && apiVersion is null) { return(null); } return(new ArmResourceName(resourceNamespace, type, apiVersion)); }
/// <summary> /// AnalyzeScript: Analyzes the ast to check that cmdlets have help. /// </summary> /// <param name="ast">The script's ast</param> /// <param name="fileName">The name of the script</param> /// <returns>A List of diagnostic results of this rule</returns> public IEnumerable <DiagnosticRecord> AnalyzeScript(Ast ast, string fileName) { if (ast == null) { throw new ArgumentNullException(Strings.NullAstErrorMessage); } DiagnosticRecords.Clear(); this.fileName = fileName; exportedFunctions = new HashSet <string>(StringComparer.OrdinalIgnoreCase); List <string> exportFunctionsCmdlet = Helper.Instance.CmdletNameAndAliases("export-modulemember"); // find functions exported IEnumerable <Ast> cmdAsts = ast.FindAll(item => item is CommandAst && exportFunctionsCmdlet.Contains((item as CommandAst).GetCommandName(), StringComparer.OrdinalIgnoreCase), true); CommandInfo exportMM = Helper.Instance.GetCommandInfo("export-modulemember", CommandTypes.Cmdlet); // switch parameters IEnumerable <ParameterMetadata> switchParams = (exportMM != null) ? exportMM.Parameters.Values.Where <ParameterMetadata>(pm => pm.SwitchParameter) : Enumerable.Empty <ParameterMetadata>(); if (exportMM == null) { return(DiagnosticRecords); } foreach (CommandAst cmdAst in cmdAsts) { if (cmdAst.CommandElements == null || cmdAst.CommandElements.Count < 2) { continue; } int i = 1; while (i < cmdAst.CommandElements.Count) { CommandElementAst ceAst = cmdAst.CommandElements[i]; ExpressionAst exprAst = null; if (ceAst is CommandParameterAst) { var paramAst = ceAst as CommandParameterAst; var param = exportMM.ResolveParameter(paramAst.ParameterName); if (param == null) { i += 1; continue; } if (string.Equals(param.Name, "function", StringComparison.OrdinalIgnoreCase)) { // checks for the case of -Function:"verb-nouns" if (paramAst.Argument != null) { exprAst = paramAst.Argument; } // checks for the case of -Function "verb-nouns" else if (i < cmdAst.CommandElements.Count - 1) { i += 1; exprAst = cmdAst.CommandElements[i] as ExpressionAst; } } // some other parameter. we just checks whether the one after this is positional else if (i < cmdAst.CommandElements.Count - 1) { // the next element is a parameter like -module so just move to that one if (cmdAst.CommandElements[i + 1] is CommandParameterAst) { i += 1; continue; } // not a switch parameter so the next element is definitely the argument to this parameter if (paramAst.Argument == null && !switchParams.Contains(param)) { // skips the next element i += 1; } i += 1; continue; } } else if (ceAst is ExpressionAst) { exprAst = ceAst as ExpressionAst; } if (exprAst != null) { // One string so just add this to the list if (exprAst is StringConstantExpressionAst) { exportedFunctions.Add((exprAst as StringConstantExpressionAst).Value); } // Array of the form "v-n", "v-n1" else if (exprAst is ArrayLiteralAst) { exportedFunctions.UnionWith(Helper.Instance.GetStringsFromArrayLiteral(exprAst as ArrayLiteralAst)); } // Array of the form @("v-n", "v-n1") else if (exprAst is ArrayExpressionAst) { ArrayExpressionAst arrExAst = exprAst as ArrayExpressionAst; if (arrExAst.SubExpression != null && arrExAst.SubExpression.Statements != null) { foreach (StatementAst stAst in arrExAst.SubExpression.Statements) { if (stAst is PipelineAst) { PipelineAst pipeAst = stAst as PipelineAst; if (pipeAst.PipelineElements != null) { foreach (CommandBaseAst cmdBaseAst in pipeAst.PipelineElements) { if (cmdBaseAst is CommandExpressionAst) { exportedFunctions.UnionWith(Helper.Instance.GetStringsFromArrayLiteral((cmdBaseAst as CommandExpressionAst).Expression as ArrayLiteralAst)); } } } } } } } } i += 1; } } ast.Visit(this); return(DiagnosticRecords); }
/// <summary> /// Creates a Linq expression for a <see cref="CommandAst" /> representing /// a custom command. /// </summary> /// <param name="commandAst">The AST to convert.</param> /// <param name="targetAst">The AST containing the target of the keyword.</param> /// <param name="bodyAst">The AST containing the body of the keyword.</param> /// <param name="visitor">The <see cref="CompileVisitor" /> requesting the expression.</param> /// <returns>An expression representing the command.</returns> protected abstract Expression ProcessObjectAndBody( CommandAst commandAst, CommandElementAst targetAst, ScriptBlockExpressionAst bodyAst, CompileVisitor visitor);
public static MemberExpressionAst Member(ExpressionAst expression, CommandElementAst member, bool isStatic = false) => Current.Member(expression, member, isStatic);
public static InvokeMemberExpressionAst InvokeMember( bool isStatic, ExpressionAst expression, CommandElementAst method, params ExpressionAst[] arguments) => Current.InvokeMember(isStatic, expression, method, arguments);
private List <CompletionResult> GetResultForString(CompletionContext completionContext, ref int replacementIndex, ref int replacementLength, bool isQuotedString) { if (isQuotedString) { return(null); } Token tokenAtCursor = completionContext.TokenAtCursor; Ast ast = completionContext.RelatedAsts.Last <Ast>(); List <CompletionResult> list = null; ExpandableStringExpressionAst ast2 = ast as ExpandableStringExpressionAst; StringConstantExpressionAst ast3 = ast as StringConstantExpressionAst; if ((ast3 != null) || (ast2 != null)) { string input = (ast3 != null) ? ast3.Value : ast2.Value; StringConstantType type = (ast3 != null) ? ast3.StringConstantType : ast2.StringConstantType; string str2 = null; if (type == StringConstantType.DoubleQuoted) { Match match = Regex.Match(input, @"(\$[\w\d]+\.[\w\d\*]*)$"); if (match.Success) { str2 = match.Groups[1].Value; } else if ((match = Regex.Match(input, @"(\[[\w\d\.]+\]::[\w\d\*]*)$")).Success) { str2 = match.Groups[1].Value; } } if (str2 != null) { int num3; int num4; int offset = tokenAtCursor.Extent.StartScriptPosition.Offset; int length = (this._cursorPosition.Offset - offset) - 1; if (length >= input.Length) { length = input.Length; } CompletionAnalysis analysis = new CompletionAnalysis(this._ast, this._tokens, this._cursorPosition, this._options); CompletionContext context = analysis.CreateCompletionContext(completionContext.ExecutionContext); context.Helper = completionContext.Helper; List <CompletionResult> list2 = analysis.GetResultHelper(context, out num3, out num4, true); if ((list2 != null) && (list2.Count > 0)) { list = new List <CompletionResult>(); replacementIndex = (offset + 1) + (length - str2.Length); replacementLength = str2.Length; string str3 = str2.Substring(0, num3); foreach (CompletionResult result in list2) { string completionText = str3 + result.CompletionText; if (result.ResultType.Equals(CompletionResultType.Property)) { completionText = TokenKind.DollarParen.Text() + completionText + TokenKind.RParen.Text(); } else if (result.ResultType.Equals(CompletionResultType.Method)) { completionText = TokenKind.DollarParen.Text() + completionText; } completionText = completionText + "\""; list.Add(new CompletionResult(completionText, result.ListItemText, result.ResultType, result.ToolTip)); } } return(list); } CommandElementAst stringAst = ast as CommandElementAst; string str5 = CompletionCompleters.ConcatenateStringPathArguments(stringAst, string.Empty, completionContext); if (str5 == null) { return(list); } completionContext.WordToComplete = str5; if ((ast.Parent is CommandAst) || (ast.Parent is CommandParameterAst)) { list = CompletionCompleters.CompleteCommandArgument(completionContext); replacementIndex = completionContext.ReplacementIndex; replacementLength = completionContext.ReplacementLength; return(list); } list = new List <CompletionResult>(CompletionCompleters.CompleteFilename(completionContext)); if (str5.IndexOf('-') != -1) { List <CompletionResult> collection = CompletionCompleters.CompleteCommand(completionContext); if ((collection != null) && (collection.Count > 0)) { list.AddRange(collection); } } } return(list); }
/// <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> /// 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);