/// <summary> /// Used to analyze scriptbloct, functionmemberast or functiondefinitionast /// </summary> /// <param name="ast"></param> /// <returns></returns> public void AnalyzeImpl(Ast ast, VariableAnalysis outerAnalysis) { if (!(ast is ScriptBlockAst || ast is FunctionMemberAst || ast is FunctionDefinitionAst)) { return; } _variables = FindAllVariablesVisitor.Visit(ast); Init(); if (ast is FunctionMemberAst || ast is FunctionDefinitionAst) { IEnumerable<ParameterAst> parameters = FindParameters(ast, ast.GetType()); if (parameters != null) { ProcessParameters(parameters); } } else { ScriptBlockAst sbAst = ast as ScriptBlockAst; if (sbAst != null && sbAst.ParamBlock != null && sbAst.ParamBlock.Parameters != null) { ProcessParameters(sbAst.ParamBlock.Parameters); } } if (ast is FunctionMemberAst) { (ast as FunctionMemberAst).Body.Visit(this.Decorator); } else if (ast is FunctionDefinitionAst) { (ast as FunctionDefinitionAst).Body.Visit(this.Decorator); } else { ast.Visit(this.Decorator); } Ast parent = ast; while (parent.Parent != null) { parent = parent.Parent; } List<TypeDefinitionAst> classes = parent.FindAll(item => item is TypeDefinitionAst && (item as TypeDefinitionAst).IsClass, true) .Cast<TypeDefinitionAst>().ToList(); if (outerAnalysis != null) { // Initialize the variables from outside var outerDictionary = outerAnalysis.InternalVariablesDictionary; foreach (var details in outerDictionary.Values) { if (details.DefinedBlock != null) { var assignTarget = new AssignmentTarget(details.RealName, details.Type); assignTarget.Constant = details.Constant; if (!_variables.ContainsKey(assignTarget.Name)) { _variables.Add(assignTarget.Name, new VariableAnalysisDetails { Name = assignTarget.Name, RealName = assignTarget.Name, Type = assignTarget.Type }); } Entry.AddFirstAst(assignTarget); } } foreach (var key in _variables.Keys) { if (outerDictionary.ContainsKey(key)) { var outerItem = outerDictionary[key]; var innerItem = _variables[key]; innerItem.Constant = outerItem.Constant; innerItem.Name = outerItem.Name; innerItem.RealName = outerItem.RealName; innerItem.Type = outerItem.Type; } } } var dictionaries = Block.SparseSimpleConstants(_variables, Entry, classes); VariablesDictionary = dictionaries.Item1; InternalVariablesDictionary = new Dictionary<string, VariableAnalysisDetails>(StringComparer.OrdinalIgnoreCase); foreach (var KVP in dictionaries.Item2) { var analysis = KVP.Value; if (analysis == null) { continue; } if (!InternalVariablesDictionary.ContainsKey(analysis.RealName)) { InternalVariablesDictionary.Add(analysis.RealName, analysis); } else { InternalVariablesDictionary[analysis.RealName] = analysis; } } }
private void ProcessParameters(IEnumerable<ParameterAst> parameters) { foreach (var parameter in parameters) { var variablePath = parameter.Name.VariablePath; bool isSwitchOrMandatory = false; Type type = null; foreach (var paramAst in parameter.Attributes) { if (paramAst is TypeConstraintAst) { if (type == null) { type = paramAst.TypeName.GetReflectionType(); } if (paramAst.TypeName.GetReflectionType() == typeof(System.Management.Automation.SwitchParameter)) { isSwitchOrMandatory = true; } } else if (paramAst is AttributeAst) { var args = (paramAst as AttributeAst).NamedArguments; if (args != null) { foreach (NamedAttributeArgumentAst arg in args) { if (String.Equals(arg.ArgumentName, "mandatory", StringComparison.OrdinalIgnoreCase) && String.Equals(arg.Argument.Extent.Text, "$true", StringComparison.OrdinalIgnoreCase)) { isSwitchOrMandatory = true; } } } } } var varName = AssignmentTarget.GetUnaliasedVariableName(variablePath); var details = _variables[varName]; details.Type = type ?? details.Type ?? typeof(object); if (parameter.DefaultValue != null) { var assignTarget = new AssignmentTarget(varName, type); if (parameter.DefaultValue is ConstantExpressionAst) { assignTarget.Constant = (parameter.DefaultValue as ConstantExpressionAst).Value; assignTarget.Type = assignTarget.Constant == null ? typeof(object) : assignTarget.Constant.GetType(); } Entry.AddAst(assignTarget); } else if (isSwitchOrMandatory) { // Consider switch or mandatory parameter as already initialized Entry.AddAst(new AssignmentTarget(varName, type)); } else { VariableTarget varTarget = new VariableTarget(parameter.Name); varTarget.Type = details.Type; Entry.AddAst(varTarget); } } }