public FunctionDefinitionAst(IScriptExtent extent, bool isFilter, bool isWorkflow, string name, IEnumerable<ParameterAst> parameters, ScriptBlockAst body) : base(extent) { if (string.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentNullException("name"); } if (body == null) { throw PSTraceSource.NewArgumentNullException("body"); } if (isFilter && isWorkflow) { throw PSTraceSource.NewArgumentException("isFilter"); } this.IsFilter = isFilter; this.IsWorkflow = isWorkflow; this.Name = name; if ((parameters != null) && parameters.Any<ParameterAst>()) { this.Parameters = new ReadOnlyCollection<ParameterAst>(parameters.ToArray<ParameterAst>()); base.SetParents((IEnumerable<Ast>) this.Parameters); } this.Body = body; base.SetParent(body); }
/// <summary> /// Parse the runbook content /// </summary> /// <param name="content"></param> public void Parse(string content) { if (_tokens == null || _scriptBlock == null) IsDirty = true; if (!IsDirty) return; _scriptBlock = System.Management.Automation.Language.Parser.ParseInput(content, out _tokens, out _parseErrors); if (_parseErrors != null && _parseErrors.Length > 0) { _currentlyHasParseErrors = true; OnParseError?.Invoke(this, new ParseErrorEventArgs(_parseErrors)); } else if (_currentlyHasParseErrors) { _currentlyHasParseErrors = false; OnClearParseErrors?.Invoke(this, new EventArgs()); } // Analyze the code too if (SettingsService.CurrentSettings.EnableCodeAnalysis && !string.IsNullOrEmpty(content) && IsDirty) { Task.Run(() => { var records = AnalyzerService.Analyze(_scriptBlock, _tokens);//ScriptAnalyzer.Instance.AnalyzeSyntaxTree(_scriptBlock, _tokens, string.Empty); if (SettingsService.CurrentSettings.EnableCodeAnalysis) {// && (_cachedRecords == null || _cachedRecords.Count() != records.Count())) Execute.OnUIThread(() => { OnAnalysisCompleted?.Invoke(this, new AnalysisEventArgs(records)); }); } }); } }
internal Command(ScriptBlockAst scriptBlockAst, bool useLocalScope = false) : this() { this.ScriptBlockAst = scriptBlockAst; this.UseLocalScope = useLocalScope; IsScript = false; }
public static bool TryParsePartialInput(string input, out ScriptBlockAst scriptBlock, out string lastControlStmt) { scriptBlock = null; lastControlStmt = ""; var parseTree = Parse(input, true); if (parseTree.Status.Equals(ParseTreeStatus.Parsed)) { scriptBlock = new AstBuilder(Grammar, parseTree).BuildScriptBlockAst(parseTree.Root); return true; } // if we're here we only partially parsed, because Parse would have thrown on error var reversedTokens = parseTree.Tokens.Reverse<Token>(); foreach (var token in reversedTokens) { if (token.KeyTerm != null && ControlStatementKeywords.Contains(token.KeyTerm.Text, StringComparer.InvariantCultureIgnoreCase)) { lastControlStmt = token.KeyTerm.Text; break; } } return false; }
public ScriptBlockExpressionAst(IScriptExtent extent, ScriptBlockAst scriptBlock) : base(extent) { if (scriptBlock == null) { throw PSTraceSource.NewArgumentNullException("scriptBlock"); } this.ScriptBlock = scriptBlock; base.SetParent(scriptBlock); }
public FunctionDefinitionAst(IScriptExtent extent, bool isFilter, bool isWorkflow, string name, IEnumerable<ParameterAst> parameters, ScriptBlockAst body) : base(extent) { this.IsFilter = isFilter; this.IsWorkflow = isWorkflow; this.Name = name; this.Parameters = parameters.ToReadOnlyCollection(); this.Body = body; }
internal static void CheckAst(Parser parser, ScriptBlockAst ast) { SemanticChecks semanticChecker = new SemanticChecks(parser); semanticChecker._scopeStack.Push(ast); ast.InternalVisit(semanticChecker); semanticChecker._scopeStack.Pop(); Diagnostics.Assert(semanticChecker._memberScopeStack.Count == 0, "Unbalanced push/pop of member scope stack"); Diagnostics.Assert(semanticChecker._scopeStack.Count == 0, "Unbalanced push/pop of scope stack"); }
public System.Object VisitScriptBlock(System.Management.Automation.Language.ScriptBlockAst scriptBlockAst) { IScriptExtent mappedExtent = MapExtent(scriptBlockAst.Extent); ParamBlockAst mappedParamBlock = scriptBlockAst.ParamBlock == null ? null : (ParamBlockAst)VisitParamBlock(scriptBlockAst.ParamBlock); NamedBlockAst mappedBeginBlock = scriptBlockAst.BeginBlock == null ? null : (NamedBlockAst)VisitNamedBlock(scriptBlockAst.BeginBlock); NamedBlockAst mappedProcessBlock = scriptBlockAst.ProcessBlock == null ? null : (NamedBlockAst)VisitNamedBlock(scriptBlockAst.ProcessBlock); NamedBlockAst mappedEndBlock = scriptBlockAst.EndBlock == null ? null : (NamedBlockAst)VisitNamedBlock(scriptBlockAst.EndBlock); NamedBlockAst mappedDynamicParamBlock = scriptBlockAst.DynamicParamBlock == null ? null : (NamedBlockAst)VisitNamedBlock(scriptBlockAst.DynamicParamBlock); return(new ScriptBlockAst(mappedExtent, mappedParamBlock, mappedBeginBlock, mappedProcessBlock, mappedEndBlock, mappedDynamicParamBlock)); }
internal static void ResolveSymbols(Parser parser, ScriptBlockAst scriptBlockAst) { Diagnostics.Assert(scriptBlockAst.Parent == null, "Can only resolve starting from the root"); var usingState = scriptBlockAst.UsingStatements.Count > 0 ? new TypeResolutionState(TypeOps.GetNamespacesForTypeResolutionState(scriptBlockAst.UsingStatements), TypeResolutionState.emptyAssemblies) : TypeResolutionState.GetDefaultUsingState(null); var resolver = new SymbolResolver(parser, usingState); resolver._symbolTable.EnterScope(scriptBlockAst, ScopeType.ScriptBlock); scriptBlockAst.Visit(resolver); resolver._symbolTable.LeaveScope(); Diagnostics.Assert(resolver._symbolTable._scopes.Count == 0, "Somebody missed removing a scope"); }
internal static void DefineWorkflows(ExecutionContext context, ScriptBlockAst scriptBlockAst) { try { foreach (WorkflowInfo info in Utils.GetAstToWorkflowConverterAndEnsureWorkflowModuleLoaded(context).CompileWorkflows(scriptBlockAst, null)) { context.EngineSessionState.SetWorkflowRaw(info, context.EngineSessionState.CurrentScope.ScopeOrigin); } } catch (Exception exception) { CommandProcessorBase.CheckForSevereException(exception); RuntimeException exception2 = exception as RuntimeException; if (exception2 == null) { throw ExceptionHandlingOps.ConvertToRuntimeException(exception, scriptBlockAst.Extent); } InterpreterError.UpdateExceptionErrorRecordPosition(exception2, scriptBlockAst.Extent); throw; } }
public object VisitScriptBlock(ScriptBlockAst scriptBlockAst) { this._currentBlock = this._entryBlock; if (scriptBlockAst.DynamicParamBlock != null) { scriptBlockAst.DynamicParamBlock.Accept(this); } if (scriptBlockAst.BeginBlock != null) { scriptBlockAst.BeginBlock.Accept(this); } if (scriptBlockAst.ProcessBlock != null) { scriptBlockAst.ProcessBlock.Accept(this); } if (scriptBlockAst.EndBlock != null) { scriptBlockAst.EndBlock.Accept(this); } this._currentBlock.FlowsTo(this._exitBlock); return(null); }
public object VisitScriptBlock(ScriptBlockAst scriptBlockAst) { throw PSTraceSource.NewArgumentException("ast"); }
public override AstVisitAction VisitScriptBlock(ScriptBlockAst scriptBlockAst) { this.ReportError(scriptBlockAst, () => ParserStrings.ScriptBlockNotSupportedInDataSection, new object[0]); return(AstVisitAction.Continue); }
public override AstVisitAction VisitScriptBlock(ScriptBlockAst ast) { return(Check(ast)); }
public virtual AstVisitAction VisitScriptBlock(ScriptBlockAst scriptBlockAst) { return AstVisitAction.Continue; }
public static IEnumerable<DiagnosticRecord> Analyze(ScriptBlockAst scriptBlock, Token[] tokens) { return ScriptAnalyzer.Instance.AnalyzeSyntaxTree(scriptBlock, tokens, string.Empty); }
public object VisitScriptBlock(ScriptBlockAst scriptBlockAst) { var funcDefn = scriptBlockAst.Parent as FunctionDefinitionAst; var funcName = (funcDefn != null) ? funcDefn.Name : "<ScriptBlock>"; var rootForDefiningTypesAndUsings = scriptBlockAst.Find(ast => ast is TypeDefinitionAst || ast is UsingStatementAst, true) != null ? scriptBlockAst : null; if (scriptBlockAst.DynamicParamBlock != null) { _dynamicParamBlockLambda = CompileNamedBlock(scriptBlockAst.DynamicParamBlock, funcName + "<DynamicParam>", rootForDefiningTypesAndUsings); rootForDefiningTypesAndUsings = null; } // Skip param block - nothing to generate, defaults get generated when generating parameter metadata. if (scriptBlockAst.BeginBlock != null) { _beginBlockLambda = CompileNamedBlock(scriptBlockAst.BeginBlock, funcName + "<Begin>", rootForDefiningTypesAndUsings); rootForDefiningTypesAndUsings = null; } if (scriptBlockAst.ProcessBlock != null) { var processFuncName = funcName; if (!scriptBlockAst.ProcessBlock.Unnamed) { processFuncName = funcName + "<Process>"; } _processBlockLambda = CompileNamedBlock(scriptBlockAst.ProcessBlock, processFuncName, rootForDefiningTypesAndUsings); rootForDefiningTypesAndUsings = null; } if (scriptBlockAst.EndBlock != null) { if (!scriptBlockAst.EndBlock.Unnamed) { funcName = funcName + "<End>"; } _endBlockLambda = CompileNamedBlock(scriptBlockAst.EndBlock, funcName, rootForDefiningTypesAndUsings); } return null; }
public object VisitScriptBlock(ScriptBlockAst scriptBlockAst) { this._currentBlock = this._entryBlock; if (scriptBlockAst.DynamicParamBlock != null) { scriptBlockAst.DynamicParamBlock.Accept(this); } if (scriptBlockAst.BeginBlock != null) { scriptBlockAst.BeginBlock.Accept(this); } if (scriptBlockAst.ProcessBlock != null) { scriptBlockAst.ProcessBlock.Accept(this); } if (scriptBlockAst.EndBlock != null) { scriptBlockAst.EndBlock.Accept(this); } this._currentBlock.FlowsTo(this._exitBlock); return null; }
public override AstVisitAction VisitScriptBlock(ScriptBlockAst scriptBlockAst) { try { scriptBlockAst.EndBlock.Visit(this); } catch (ReturnException e) { _pipelineCommandRuntime.WriteObject(e.Value); } return AstVisitAction.SkipChildren; }
private static Ast GetLastAstAtCursor(ScriptBlockAst scriptBlockAst, IScriptPosition cursorPosition) { var asts = AstSearcher.FindAll(scriptBlockAst, ast => IsCursorRightAfterExtent(cursorPosition, ast.Extent), searchNestedScriptBlocks: true); return asts.LastOrDefault(); }
/// <summary> /// Analyzes a single script file. /// </summary> /// <param name="filePath">The path to the file ot analyze</param> private void AnalyzeFile(string filePath) { Token[] tokens = null; ParseError[] errors = null; ConcurrentBag<DiagnosticRecord> diagnostics = new ConcurrentBag<DiagnosticRecord>(); ConcurrentBag<SuppressedRecord> suppressed = new ConcurrentBag<SuppressedRecord>(); BlockingCollection<List<object>> verboseOrErrors = new BlockingCollection<List<object>>(); // Use a List of KVP rather than dictionary, since for a script containing inline functions with same signature, keys clash List<KeyValuePair<CommandInfo, IScriptExtent>> cmdInfoTable = new List<KeyValuePair<CommandInfo, IScriptExtent>>(); //Check wild card input for the Include/ExcludeRules and create regex match patterns includeRegexList = new List<Regex>(); excludeRegexList = new List<Regex>(); if (includeRule != null) { foreach (string rule in includeRule) { Regex includeRegex = new Regex(String.Format("^{0}$", Regex.Escape(rule).Replace(@"\*", ".*")), RegexOptions.IgnoreCase); includeRegexList.Add(includeRegex); } } if (excludeRule != null) { foreach (string rule in excludeRule) { Regex excludeRegex = new Regex(String.Format("^{0}$", Regex.Escape(rule).Replace(@"\*", ".*")), RegexOptions.IgnoreCase); excludeRegexList.Add(excludeRegex); } } //Parse the file if (File.Exists(filePath)) { ast = Parser.ParseFile(filePath, out tokens, out errors); } else { ThrowTerminatingError(new ErrorRecord(new FileNotFoundException(), string.Format(CultureInfo.CurrentCulture, Strings.InvalidPath, filePath), ErrorCategory.InvalidArgument, filePath)); } if (errors != null && errors.Length > 0) { foreach (ParseError error in errors) { string parseErrorMessage = String.Format(CultureInfo.CurrentCulture, Strings.ParserErrorFormat, error.Extent.File, error.Message.TrimEnd('.'), error.Extent.StartLineNumber, error.Extent.StartColumnNumber); WriteError(new ErrorRecord(new ParseException(parseErrorMessage), parseErrorMessage, ErrorCategory.ParserError, error.ErrorId)); } } if (errors.Length > 10) { string manyParseErrorMessage = String.Format(CultureInfo.CurrentCulture, Strings.ParserErrorMessage, System.IO.Path.GetFileName(filePath)); WriteError(new ErrorRecord(new ParseException(manyParseErrorMessage), manyParseErrorMessage, ErrorCategory.ParserError, filePath)); return; } ruleSuppressions = Helper.Instance.GetRuleSuppression(ast); foreach (List<RuleSuppression> ruleSuppressionsList in ruleSuppressions.Values) { foreach (RuleSuppression ruleSuppression in ruleSuppressionsList) { if (!String.IsNullOrWhiteSpace(ruleSuppression.Error)) { WriteError(new ErrorRecord(new ArgumentException(ruleSuppression.Error), ruleSuppression.Error, ErrorCategory.InvalidArgument, ruleSuppression)); } } } #region Run VariableAnalysis try { Helper.Instance.InitializeVariableAnalysis(ast); } catch { } #endregion Helper.Instance.Tokens = tokens; #region Run ScriptRules //Trim down to the leaf element of the filePath and pass it to Diagnostic Record string fileName = System.IO.Path.GetFileName(filePath); if (ScriptAnalyzer.Instance.ScriptRules != null) { var tasks = ScriptAnalyzer.Instance.ScriptRules.Select(scriptRule => Task.Factory.StartNew(() => { bool includeRegexMatch = false; bool excludeRegexMatch = false; foreach (Regex include in includeRegexList) { if (include.IsMatch(scriptRule.GetName())) { includeRegexMatch = true; break; } } foreach (Regex exclude in excludeRegexList) { if (exclude.IsMatch(scriptRule.GetName())) { excludeRegexMatch = true; break; } } if ((includeRule == null || includeRegexMatch) && (excludeRule == null || !excludeRegexMatch)) { List<object> result = new List<object>(); result.Add(string.Format(CultureInfo.CurrentCulture, Strings.VerboseRunningMessage, scriptRule.GetName())); // Ensure that any unhandled errors from Rules are converted to non-terminating errors // We want the Engine to continue functioning even if one or more Rules throws an exception try { var records = Helper.Instance.SuppressRule(scriptRule.GetName(), ruleSuppressions, scriptRule.AnalyzeScript(ast, ast.Extent.File).ToList()); foreach (var record in records.Item2) { diagnostics.Add(record); } foreach (var suppressedRec in records.Item1) { suppressed.Add(suppressedRec); } } catch (Exception scriptRuleException) { result.Add(new ErrorRecord(scriptRuleException, Strings.RuleErrorMessage, ErrorCategory.InvalidOperation, ast.Extent.File)); } verboseOrErrors.Add(result); } })); Task.Factory.ContinueWhenAll(tasks.ToArray(), t => verboseOrErrors.CompleteAdding()); while (!verboseOrErrors.IsCompleted) { List<object> data = null; try { data = verboseOrErrors.Take(); } catch (InvalidOperationException) { } if (data != null) { WriteVerbose(data[0] as string); if (data.Count == 2) { WriteError(data[1] as ErrorRecord); } } } } #endregion #region Run Token Rules if (ScriptAnalyzer.Instance.TokenRules != null) { foreach (ITokenRule tokenRule in ScriptAnalyzer.Instance.TokenRules) { bool includeRegexMatch = false; bool excludeRegexMatch = false; foreach (Regex include in includeRegexList) { if (include.IsMatch(tokenRule.GetName())) { includeRegexMatch = true; break; } } foreach (Regex exclude in excludeRegexList) { if (exclude.IsMatch(tokenRule.GetName())) { excludeRegexMatch = true; break; } } if ((includeRule == null || includeRegexMatch) && (excludeRule == null || !excludeRegexMatch)) { WriteVerbose(string.Format(CultureInfo.CurrentCulture, Strings.VerboseRunningMessage, tokenRule.GetName())); // Ensure that any unhandled errors from Rules are converted to non-terminating errors // We want the Engine to continue functioning even if one or more Rules throws an exception try { var records = Helper.Instance.SuppressRule(tokenRule.GetName(), ruleSuppressions, tokenRule.AnalyzeTokens(tokens, filePath).ToList()); foreach (var record in records.Item2) { diagnostics.Add(record); } foreach (var suppressedRec in records.Item1) { suppressed.Add(suppressedRec); } } catch (Exception tokenRuleException) { WriteError(new ErrorRecord(tokenRuleException, Strings.RuleErrorMessage, ErrorCategory.InvalidOperation, fileName)); } } } } #endregion #region DSC Resource Rules if (ScriptAnalyzer.Instance.DSCResourceRules != null) { // Invoke AnalyzeDSCClass only if the ast is a class based resource if (Helper.Instance.IsDscResourceClassBased(ast)) { // Run DSC Class rule foreach (IDSCResourceRule dscResourceRule in ScriptAnalyzer.Instance.DSCResourceRules) { bool includeRegexMatch = false; bool excludeRegexMatch = false; foreach (Regex include in includeRegexList) { if (include.IsMatch(dscResourceRule.GetName())) { includeRegexMatch = true; break; } } foreach (Regex exclude in excludeRegexList) { if (exclude.IsMatch(dscResourceRule.GetName())) { excludeRegexMatch = true; break; } } if ((includeRule == null || includeRegexMatch) && (excludeRule == null || excludeRegexMatch)) { WriteVerbose(string.Format(CultureInfo.CurrentCulture, Strings.VerboseRunningMessage, dscResourceRule.GetName())); // Ensure that any unhandled errors from Rules are converted to non-terminating errors // We want the Engine to continue functioning even if one or more Rules throws an exception try { var records = Helper.Instance.SuppressRule(dscResourceRule.GetName(), ruleSuppressions, dscResourceRule.AnalyzeDSCClass(ast, filePath).ToList()); foreach (var record in records.Item2) { diagnostics.Add(record); } foreach (var suppressedRec in records.Item1) { suppressed.Add(suppressedRec); } } catch (Exception dscResourceRuleException) { WriteError(new ErrorRecord(dscResourceRuleException, Strings.RuleErrorMessage, ErrorCategory.InvalidOperation, filePath)); } } } } // Check if the supplied artifact is indeed part of the DSC resource if (Helper.Instance.IsDscResourceModule(filePath)) { // Run all DSC Rules foreach (IDSCResourceRule dscResourceRule in ScriptAnalyzer.Instance.DSCResourceRules) { bool includeRegexMatch = false; bool excludeRegexMatch = false; foreach (Regex include in includeRegexList) { if (include.IsMatch(dscResourceRule.GetName())) { includeRegexMatch = true; break; } } foreach (Regex exclude in excludeRegexList) { if (exclude.IsMatch(dscResourceRule.GetName())) { excludeRegexMatch = true; } } if ((includeRule == null || includeRegexMatch) && (excludeRule == null || !excludeRegexMatch)) { WriteVerbose(string.Format(CultureInfo.CurrentCulture, Strings.VerboseRunningMessage, dscResourceRule.GetName())); // Ensure that any unhandled errors from Rules are converted to non-terminating errors // We want the Engine to continue functioning even if one or more Rules throws an exception try { var records = Helper.Instance.SuppressRule(dscResourceRule.GetName(), ruleSuppressions, dscResourceRule.AnalyzeDSCResource(ast, filePath).ToList()); foreach (var record in records.Item2) { diagnostics.Add(record); } foreach (var suppressedRec in records.Item1) { suppressed.Add(suppressedRec); } } catch (Exception dscResourceRuleException) { WriteError(new ErrorRecord(dscResourceRuleException, Strings.RuleErrorMessage, ErrorCategory.InvalidOperation, filePath)); } } } } } #endregion #region Run External Rules if (ScriptAnalyzer.Instance.ExternalRules != null) { List<ExternalRule> exRules = new List<ExternalRule>(); foreach (ExternalRule exRule in ScriptAnalyzer.Instance.ExternalRules) { if ((includeRule == null || includeRule.Contains(exRule.GetName(), StringComparer.OrdinalIgnoreCase)) && (excludeRule == null || !excludeRule.Contains(exRule.GetName(), StringComparer.OrdinalIgnoreCase))) { string ruleName = string.Format(CultureInfo.CurrentCulture, "{0}\\{1}", exRule.GetSourceName(), exRule.GetName()); WriteVerbose(string.Format(CultureInfo.CurrentCulture, Strings.VerboseRunningMessage, ruleName)); // Ensure that any unhandled errors from Rules are converted to non-terminating errors // We want the Engine to continue functioning even if one or more Rules throws an exception try { exRules.Add(exRule); } catch (Exception externalRuleException) { WriteError(new ErrorRecord(externalRuleException, Strings.RuleErrorMessage, ErrorCategory.InvalidOperation, fileName)); } } } foreach (var record in ScriptAnalyzer.Instance.GetExternalRecord(ast, tokens, exRules.ToArray(), this, fileName)) { diagnostics.Add(record); } } #endregion IEnumerable<DiagnosticRecord> diagnosticsList = diagnostics; if (severity != null) { var diagSeverity = severity.Select(item => Enum.Parse(typeof(DiagnosticSeverity), item, true)); diagnosticsList = diagnostics.Where(item => diagSeverity.Contains(item.Severity)); } //Output through loggers foreach (ILogger logger in ScriptAnalyzer.Instance.Loggers) { if (SuppressedOnly) { foreach (DiagnosticRecord suppressRecord in suppressed) { logger.LogObject(suppressRecord, this); } } else { foreach (DiagnosticRecord diagnostic in diagnosticsList) { logger.LogObject(diagnostic, this); } } } }
public override AstVisitAction VisitScriptBlock(ScriptBlockAst scriptBlockAst) { this.ReportError(scriptBlockAst, () => ParserStrings.ScriptBlockNotSupportedInDataSection, new object[0]); return AstVisitAction.Continue; }
public FunctionDefinitionAst(IScriptExtent extent, bool isFilter, bool isWorkflow, string name, IEnumerable <ParameterAst> parameters, ScriptBlockAst body) : base(extent) { if (string.IsNullOrEmpty(name)) { throw PSTraceSource.NewArgumentNullException("name"); } if (body == null) { throw PSTraceSource.NewArgumentNullException("body"); } if (isFilter && isWorkflow) { throw PSTraceSource.NewArgumentException("isFilter"); } this.IsFilter = isFilter; this.IsWorkflow = isWorkflow; this.Name = name; if ((parameters != null) && parameters.Any <ParameterAst>()) { this.Parameters = new ReadOnlyCollection <ParameterAst>(parameters.ToArray <ParameterAst>()); base.SetParents((IEnumerable <Ast>) this.Parameters); } this.Body = body; base.SetParent(body); }
private void GenerateTypesAndUsings(ScriptBlockAst rootForDefiningTypesAndUsings, List<Expression> exprs) { // We don't postpone load assemblies, import modules from 'using' to the moment, when enclosed scriptblock is executed. // We do loading, when root of the script is compiled. // This allow us to avoid creating 10 different classes in this situation: // 1..10 | % { class C {} } // But it's possible that we are loading something from the codepaths that we never execute. // If Parent of rootForDefiningTypesAndUsings is not null, then we already defined all types, when Visit a parent ScriptBlock if (rootForDefiningTypesAndUsings.Parent == null) { if (rootForDefiningTypesAndUsings.UsingStatements.Any()) { bool allUsingsAreNamespaces = rootForDefiningTypesAndUsings.UsingStatements.All(us => us.UsingStatementKind == UsingStatementKind.Namespace); GenerateLoadUsings(rootForDefiningTypesAndUsings.UsingStatements, allUsingsAreNamespaces, exprs); } TypeDefinitionAst[] typeAsts = rootForDefiningTypesAndUsings.FindAll(ast => ast is TypeDefinitionAst, true) .Cast<TypeDefinitionAst>() .ToArray(); if (typeAsts.Length > 0) { var assembly = DefinePowerShellTypes(rootForDefiningTypesAndUsings, typeAsts); exprs.Add(Expression.Call(CachedReflectionInfo.TypeOps_SetAssemblyDefiningPSTypes, _functionContext, Expression.Constant(assembly))); exprs.Add(Expression.Call(CachedReflectionInfo.TypeOps_InitPowerShellTypesAtRuntime, Expression.Constant(typeAsts))); } } Dictionary<string, TypeDefinitionAst> typesToAddToScope = rootForDefiningTypesAndUsings.FindAll(ast => ast is TypeDefinitionAst, false) .Cast<TypeDefinitionAst>() .ToDictionary(type => type.Name); if (typesToAddToScope.Count > 0) { exprs.Add(Expression.Call(CachedReflectionInfo.TypeOps_AddPowerShellTypesToTheScope, Expression.Constant(typesToAddToScope), _executionContextParameter)); } }
private Expression<Action<FunctionContext>> CompileSingleLambda(ReadOnlyCollection<StatementAst> statements, ReadOnlyCollection<TrapStatementAst> traps, string funcName, IScriptExtent entryExtent, IScriptExtent exitExtent, ScriptBlockAst rootForDefiningTypesAndUsings) { _currentFunctionName = funcName; _loopTargets.Clear(); _returnTarget = Expression.Label("returnTarget"); var exprs = new List<Expression>(); var temps = new List<ParameterExpression>(); GenerateFunctionProlog(exprs, temps, entryExtent); if (rootForDefiningTypesAndUsings != null) { GenerateTypesAndUsings(rootForDefiningTypesAndUsings, exprs); } var actualBodyExprs = new List<Expression>(); if (CompilingMemberFunction) { temps.Add(_returnPipe); } CompileStatementListWithTraps(statements, traps, actualBodyExprs, temps); exprs.AddRange(actualBodyExprs); // We always add the return label even if it's unused - that way it doesn't matter what the last // expression is in the body - the full body will always have void type. exprs.Add(Expression.Label(_returnTarget)); GenerateFunctionEpilog(exprs, exitExtent); temps.Add(LocalVariablesParameter); Expression body = Expression.Block(temps, exprs); // A return from a normal block is just that - a simple return (no exception). // A return from a trap turns into an exception because the trap is compiled into a different lambda, yet // the return from the trap must return from the function containing the trap. So we wrap the full // body of regular begin/process/end blocks with a try/catch so a return from the trap returns // to the right place. We can avoid also avoid generating the catch if we know there aren't any traps. if (!_compilingTrap && ((traps != null && traps.Count > 0) || statements.Any(stmt => AstSearcher.Contains(stmt, ast => ast is TrapStatementAst, searchNestedScriptBlocks: false)))) { body = Expression.Block( new[] { _executionContextParameter }, Expression.TryCatchFinally( body, Expression.Call( Expression.Field(_executionContextParameter, CachedReflectionInfo.ExecutionContext_Debugger), CachedReflectionInfo.Debugger_ExitScriptFunction), Expression.Catch(typeof(ReturnException), ExpressionCache.Empty))); } else { // Either no traps, or we're compiling a trap - either way don't catch the ReturnException. body = Expression.Block( new[] { _executionContextParameter }, Expression.TryFinally( body, Expression.Call( Expression.Field(_executionContextParameter, CachedReflectionInfo.ExecutionContext_Debugger), CachedReflectionInfo.Debugger_ExitScriptFunction))); } return Expression.Lambda<Action<FunctionContext>>(body, funcName, new[] { _functionContext }); }
public ScriptBlockExpressionAst(IScriptExtent extent, ScriptBlockAst scriptBlock) : base(extent) { this.ScriptBlock = scriptBlock; }
public override AstVisitAction VisitScriptBlock(ScriptBlockAst scriptBlockAst) { try { scriptBlockAst.EndBlock.Visit(this); } catch (ReturnException) { } return AstVisitAction.SkipChildren; }
/// <summary> /// Visit script block /// </summary> /// <param name="scriptBlockAst"></param> /// <returns></returns> public object VisitScriptBlock(ScriptBlockAst scriptBlockAst) { if (scriptBlockAst == null) return null; _currentBlock = _entryBlock; if (scriptBlockAst.DynamicParamBlock != null) { scriptBlockAst.DynamicParamBlock.Visit(this.Decorator); } if (scriptBlockAst.BeginBlock != null) { scriptBlockAst.BeginBlock.Visit(this.Decorator); } if (scriptBlockAst.ProcessBlock != null) { scriptBlockAst.ProcessBlock.Visit(this.Decorator); } if (scriptBlockAst.EndBlock != null) { scriptBlockAst.EndBlock.Visit(this.Decorator); } _currentBlock.FlowsTo(_exitBlock); return null; }
internal Command(ScriptBlockAst scriptBlockAst) : this() { this.ScriptBlockAst = scriptBlockAst; IsScript = false; }
/// <summary/> public virtual object VisitScriptBlock(ScriptBlockAst scriptBlockAst) { return _decorated.VisitScriptBlock(scriptBlockAst); }
/// <summary> /// Finds all references (not including aliases) in a script for the given symbol /// </summary> /// <param name="scriptAst">The abstract syntax tree of the given script</param> /// <param name="foundSymbol">The symbol that we are looking for referneces of</param> /// <param name="needsAliases">If this reference search needs aliases. /// This should always be false and used for occurence requests</param> /// <returns>A collection of SymbolReference objects that are refrences to the symbolRefrence /// not including aliases</returns> public static IEnumerable<SymbolReference> FindReferencesOfSymbol( ScriptBlockAst scriptAst, SymbolReference foundSymbol, bool needsAliases) { FindReferencesVisitor referencesVisitor = new FindReferencesVisitor(foundSymbol); scriptAst.Visit(referencesVisitor); return referencesVisitor.FoundReferences; }
public FunctionDefinitionAst(IScriptExtent extent, bool isFilter, bool isWorkflow, string name, IEnumerable <ParameterAst> parameters, ScriptBlockAst body) : base(extent) { this.IsFilter = isFilter; this.IsWorkflow = isWorkflow; this.Name = name; this.Parameters = parameters.ToReadOnlyCollection(); this.Body = body; }
internal static void CheckAst(Parser parser, ScriptBlockAst ast) { SemanticChecks visitor = new SemanticChecks(parser); ast.InternalVisit(visitor); }
public object VisitScriptBlock(ScriptBlockAst scriptBlockAst) { return(AutomationNull.Value); }
/// <summary/> public virtual object VisitScriptBlock(ScriptBlockAst scriptBlockAst) { return(null); }
internal static PowerShell Convert(ScriptBlockAst body, ReadOnlyCollection<ParameterAst> functionParameters, bool isTrustedInput, ExecutionContext context, Dictionary<string, object> variables, bool filterNonUsingVariables, bool? createLocalScope, object[] args) { ExecutionContext.CheckStackDepth(); if (args == null) { args = Utils.EmptyArray<object>(); } // Perform validations on the ScriptBlock. GetSimplePipeline can allow for more than one // pipeline if the first parameter is true, but Invoke-Command doesn't yet support multiple // pipelines in a PowerShell (it just grabs the last command directly.) The rest of this // code properly supports multiple pipelines, so it should just work to change the false to true // if/when Invoke-Command can support multiple pipelines. string errorId; string errorMsg; body.GetSimplePipeline(true, out errorId, out errorMsg); if (errorId != null) { throw new ScriptBlockToPowerShellNotSupportedException(errorId, null, errorMsg); } var checker = new ScriptBlockToPowerShellChecker { ScriptBeingConverted = body }; if (functionParameters != null) { foreach (var parameter in functionParameters) { parameter.InternalVisit(checker); } } body.InternalVisit(checker); // When the context is null (or they haven't supplied any variables), throw, but only if we really need the // context (basically, if we have some variable reference to resolve). if (context == null && (checker.HasUsingExpr || checker.UsesParameter) && (variables == null)) { throw new PSInvalidOperationException(AutomationExceptions.CantConvertScriptBlockWithNoContext); } try { var converter = new ScriptBlockToPowerShellConverter { _context = context, _createLocalScope = createLocalScope }; if (checker.HasUsingExpr) { converter._usingValueMap = GetUsingValues(body, isTrustedInput, context, variables, filterNonUsingVariables).Item1; } if (checker.UsesParameter) { // If any parameters are used, we create a new scope and bind the parameters. var newScope = context.EngineSessionState.NewScope(false); context.EngineSessionState.CurrentScope = newScope; context.EngineSessionState.CurrentScope.ScopeOrigin = CommandOrigin.Internal; var locals = MutableTuple.MakeTuple(Compiler.DottedLocalsTupleType, Compiler.DottedLocalsNameIndexMap); // Get the parameter metadata for the script block. // If 'functionParameters' is not null, then the ScriptBlockAst is actually the body of a FunctionDefinitionAst, and it doesn't have a ParamBlock. // If 'functionParameters' is null, then the ScriptBlockAst may have parameters defined in its ParamBlock. bool usesCmdletBinding = false; var parameters = functionParameters != null ? Compiler.GetParameterMetaData(functionParameters, true, ref usesCmdletBinding) : ((IParameterMetadataProvider)body).GetParameterMetadata(true, ref usesCmdletBinding); object[] remainingArgs = ScriptBlock.BindArgumentsForScriptblockInvoke( (RuntimeDefinedParameter[])parameters.Data, args, context, false, null, locals); locals.SetAutomaticVariable(AutomaticVariable.Args, remainingArgs, context); newScope.LocalsTuple = locals; } foreach (var pipeline in body.EndBlock.Statements.OfType<PipelineAst>()) { converter._powershell.AddStatement(); converter.ConvertPipeline(pipeline, isTrustedInput); } return converter._powershell; } finally { if (checker.UsesParameter) { context.EngineSessionState.RemoveScope(context.EngineSessionState.CurrentScope); } } }
public object VisitScriptBlock(ScriptBlockAst scriptBlockAst) { return false; }
/// <summary> /// Check if the given UsingExpression is in a different scope from the previous UsingExpression that we analyzed. /// </summary> /// <remarks> /// Note that the value of <paramref name="usingExpr"/> is retrieved by calling 'UsingExpressionAstSearcher.FindAllUsingExpressionExceptForWorkflow'. /// So <paramref name="usingExpr"/> is guaranteed not inside a workflow. /// </remarks> /// <param name="usingExpr">The UsingExpression to analyze</param> /// <param name="topLevelParent">The top level Ast, should be either ScriptBlockAst or FunctionDefinitionAst</param> /// <param name="sbClosestToPreviousUsingExpr">The ScriptBlockAst that represents the scope of the previously analyzed UsingExpressions</param> private static bool HasUsingExpressionsInDifferentScopes(UsingExpressionAst usingExpr, Ast topLevelParent, ref ScriptBlockAst sbClosestToPreviousUsingExpr) { Diagnostics.Assert(topLevelParent is ScriptBlockAst || topLevelParent is FunctionDefinitionAst, "the top level parent should be either a ScriptBlockAst or FunctionDefinitionAst"); // Scan up the parents of a UsingExpression to check if it's in a nested function/filter/ScriptBlock Ast current = usingExpr; do { current = current.Parent; var sbAst = current as ScriptBlockAst; if (sbAst != null) { // We find the closest parent ScriptBlockAst of the current UsingExpression, which represents the scope // that the current UsingExpression is in. if (sbClosestToPreviousUsingExpr == null) { // The current UsingExpression is the first one to be analyzed. sbClosestToPreviousUsingExpr = sbAst; return false; } if (sbAst == sbClosestToPreviousUsingExpr) { // The current UsingExpression is in the same scope as the previous UsingExpression we analyzed. return false; } // The current UsingExpression is in a different scope from the previous UsingExpression we analyzed. return true; } var funcAst = current as FunctionDefinitionAst; if (funcAst != null) { // The parent chain of the current UsingExpression reaches a FunctionDefinitionAst, then the UsingExpression // must be in 'Parameters' property of this FunctionDefinitionAst. // In this case, the 'Body' of this FunctionDefinitionAst represents the scope that the UsingExpression is in. if (sbClosestToPreviousUsingExpr == null) { // The current UsingExpression is the first one to be analyzed. sbClosestToPreviousUsingExpr = funcAst.Body; return false; } if (funcAst.Body == sbClosestToPreviousUsingExpr) { // The current UsingExpression is in the same scope as the previous UsingExpression we analyzed. return false; } // The current UsingExpression is in a different scope from the previous UsingExpression we analyzed. return true; } } while (current != topLevelParent); Diagnostics.Assert(false, "Unreachable Code. Top level parent is eitehr ScriptBlockAst or FunctionDefinitionAst, so it should return within the loop for sure."); // I don't think it's reachable, but if it happens, just assume there are UsingExpressions in different scopes. return true; }
public override AstVisitAction VisitScriptBlock(ScriptBlockAst scriptBlockAst) { try { scriptBlockAst.EndBlock.Visit(this); } catch (ReturnException e) { // if the exception was a return excpetion, also write the returnResult, if existing if (PSObject.Unwrap(e.Value) != null) { _pipelineCommandRuntime.WriteObject(e.Value, true); } } return AstVisitAction.SkipChildren; }
private Expression<Action<FunctionContext>> CompileNamedBlock(NamedBlockAst namedBlockAst, string funcName, ScriptBlockAst rootForDefiningTypes) { IScriptExtent entryExtent = null; IScriptExtent exitExtent = null; if (namedBlockAst.Unnamed) { // Get extent from the function or scriptblock expression parent, if any. var scriptBlock = (ScriptBlockAst)namedBlockAst.Parent; if (scriptBlock.Parent != null && scriptBlock.Extent is InternalScriptExtent) { // We must have curlies at the start/end. var scriptExtent = (InternalScriptExtent)scriptBlock.Extent; entryExtent = new InternalScriptExtent(scriptExtent.PositionHelper, scriptExtent.StartOffset, scriptExtent.StartOffset + 1); exitExtent = new InternalScriptExtent(scriptExtent.PositionHelper, scriptExtent.EndOffset - 1, scriptExtent.EndOffset); } } else { entryExtent = namedBlockAst.OpenCurlyExtent; exitExtent = namedBlockAst.CloseCurlyExtent; } return CompileSingleLambda(namedBlockAst.Statements, namedBlockAst.Traps, funcName, entryExtent, exitExtent, rootForDefiningTypes); }
/// <summary/> public virtual AstVisitAction VisitScriptBlock(ScriptBlockAst scriptBlockAst) { return(AstVisitAction.Continue); }
/// <summary/> public virtual AstVisitAction VisitScriptBlock(ScriptBlockAst scriptBlockAst) => DefaultVisit(scriptBlockAst);
public object VisitScriptBlock(ScriptBlockAst scriptBlockAst) { return(false); }