public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { object item = this.ClassAction(typeDefinitionAst.Name, typeDefinitionAst.Extent, this.GetCurrentNestingLevel(), this.GetCurrentParentObject()); foreach (MemberAst member in typeDefinitionAst.Members) { if (member is PropertyMemberAst) { this.ClassPropertyAction(member.Name, member.Extent, this.GetCurrentNestingLevel() + 1, item); } else if (member is FunctionMemberAst) { FunctionMemberAst functionMember = (FunctionMemberAst)member; object newParentObject; if (functionMember.IsConstructor) { newParentObject = this.ClassConstructorAction(member.Name, member.Extent, this.GetCurrentNestingLevel() + 1, item); } else { newParentObject = this.ClassMethodAction(member.Name, member.Extent, this.GetCurrentNestingLevel() + 1, item); } this.VisitChildren(functionMember.Body, newParentObject); } } return AstVisitAction.SkipChildren; }
/// <summary> /// Return the most deep typeDefinitionAst in the current context. /// </summary> /// <returns>TypeDefinitionAst or null, if currently not in type definition.</returns> public TypeDefinitionAst GetCurrentTypeDefinitionAst() { for (int i = _scopes.Count - 1; i >= 0; i--) { TypeDefinitionAst ast = _scopes[i]._ast as TypeDefinitionAst; if (ast != null) { return(ast); } } return(null); }
internal void AddType(Parser parser, TypeDefinitionAst typeDefinitionAst) { TypeLookupResult result; if (_typeTable.TryGetValue(typeDefinitionAst.Name, out result)) { if (result.ExternalNamespaces != null) { // override external type by the type defined in the current namespace result.ExternalNamespaces = null; result.Type = typeDefinitionAst; } else { parser.ReportError(typeDefinitionAst.Extent, () => ParserStrings.MemberAlreadyDefined, typeDefinitionAst.Name); } } else { _typeTable.Add(typeDefinitionAst.Name, new TypeLookupResult(typeDefinitionAst)); } }
/// <summary> /// Convert the cacheItem to a PSClassInfo object. /// For this, we call Get-Module -List with module name. /// </summary> /// <param name="classNameMatcher">Wildcard pattern matcher for comparing class name.</param> /// <param name="modulePath">Path to the module where the class is defined.</param> /// <returns>Converted PSClassInfo object.</returns> private PSClassInfo CachedItemToPSClassInfo(WildcardPattern classNameMatcher, string modulePath) { foreach (var module in GetPSModuleInfo(modulePath)) { var exportedTypes = module.GetExportedTypeDefinitions(); ScriptBlockAst ast = null; TypeDefinitionAst typeAst = null; if (!_useWildCards) { if (exportedTypes.TryGetValue(_className, out typeAst)) { ast = typeAst.Parent.Parent as ScriptBlockAst; if (ast != null) { return(ConvertToClassInfo(module, ast, typeAst)); } } } else { foreach (var exportedType in exportedTypes) { if (exportedType.Value != null && classNameMatcher.IsMatch(exportedType.Value.Name) && exportedType.Value.IsClass) { ast = exportedType.Value.Parent.Parent as ScriptBlockAst; if (ast != null) { return(ConvertToClassInfo(module, ast, exportedType.Value)); } } } } } return(null); }
internal Scope(TypeDefinitionAst typeDefinition) { _ast = typeDefinition; _scopeType = ScopeType.Type; _typeTable = new Dictionary <string, TypeLookupResult>(StringComparer.OrdinalIgnoreCase); _variableTable = new Dictionary <string, Ast>(StringComparer.OrdinalIgnoreCase); foreach (var member in typeDefinition.Members) { var propertyMember = member as PropertyMemberAst; if (propertyMember != null) { // Duplicate members are an error, but we catch that later after all types // have been resolved. We could report errors for properties here, but // we couldn't compare methods because overloads can't be compared until types // are resolved. if (!_variableTable.ContainsKey(propertyMember.Name)) { _variableTable.Add(propertyMember.Name, propertyMember); } } } }
internal Scope(TypeDefinitionAst typeDefinition) { _ast = typeDefinition; _scopeType = ScopeType.Type; _typeTable = new Dictionary<string, TypeLookupResult>(StringComparer.OrdinalIgnoreCase); _variableTable = new Dictionary<string, Ast>(StringComparer.OrdinalIgnoreCase); foreach (var member in typeDefinition.Members) { var propertyMember = member as PropertyMemberAst; if (propertyMember != null) { // Duplicate members are an error, but we catch that later after all types // have been resolved. We could report errors for properties here, but // we couldn't compare methods because overloads can't be compared until types // are resolved. if (!_variableTable.ContainsKey(propertyMember.Name)) { _variableTable.Add(propertyMember.Name, propertyMember); } } } }
internal void AddTypeFromUsingModule(Parser parser, TypeDefinitionAst typeDefinitionAst, PSModuleInfo moduleInfo) { TypeLookupResult result; if (_typeTable.TryGetValue(typeDefinitionAst.Name, out result)) { if (result.ExternalNamespaces != null) { // override external type by the type defined in the current namespace result.ExternalNamespaces.Add(moduleInfo.Name); } } else { var newLookupEntry = new TypeLookupResult(typeDefinitionAst) { ExternalNamespaces = new List <string>() }; newLookupEntry.ExternalNamespaces.Add(moduleInfo.Name); _typeTable.Add(typeDefinitionAst.Name, newLookupEntry); } string fullName = SymbolResolver.GetModuleQualifiedName(moduleInfo.Name, typeDefinitionAst.Name); if (_typeTable.TryGetValue(fullName, out result)) { parser.ReportError(typeDefinitionAst.Extent, nameof(ParserStrings.MemberAlreadyDefined), ParserStrings.MemberAlreadyDefined, fullName); } else { _typeTable.Add(fullName, new TypeLookupResult(typeDefinitionAst)); } }
public override object VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { _symbolResolver._symbolTable.LeaveScope(); return null; }
public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { _symbolTable.EnterScope(typeDefinitionAst); return AstVisitAction.Continue; }
/// <summary> /// Add Type from the different module to the symbol Table. /// </summary> /// <param name="typeDefinitionAst"></param> /// <param name="moduleInfo"></param> public void AddTypeFromUsingModule(TypeDefinitionAst typeDefinitionAst, PSModuleInfo moduleInfo) { _scopes[_scopes.Count - 1].AddTypeFromUsingModule(_parser, typeDefinitionAst, moduleInfo); }
internal void EnterScope(TypeDefinitionAst typeDefinition) { var scope = new Scope(typeDefinition); _scopes.Add(scope); AddTypesInScope(typeDefinition); }
/// <summary/> public virtual AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) => DefaultVisit(typeDefinitionAst);
public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { _symbolTable.EnterScope(typeDefinitionAst); return(AstVisitAction.Continue); }
/// <summary> /// Gets the line no for DSC Class Resource Get/Set/Test methods /// </summary> /// <param name="typeDefinitionAst"></param> /// <param name="methodsLinePosition"></param> private static bool GetResourceMethodsLineNumber(TypeDefinitionAst typeDefinitionAst, out Dictionary<string, int> methodsLinePosition) { const string getMethodName = "Get"; const string setMethodName = "Set"; const string testMethodName = "Test"; methodsLinePosition = new Dictionary<string, int>(); ; foreach (var member in typeDefinitionAst.Members) { var functionMemberAst = member as FunctionMemberAst; if (functionMemberAst != null) { if (functionMemberAst.Name.Equals(getMethodName, StringComparison.OrdinalIgnoreCase)) { methodsLinePosition[getMethodName] = functionMemberAst.NameExtent.StartLineNumber; } else if (functionMemberAst.Name.Equals(setMethodName, StringComparison.OrdinalIgnoreCase)) { methodsLinePosition[setMethodName] = functionMemberAst.NameExtent.StartLineNumber; } else if (functionMemberAst.Name.Equals(testMethodName, StringComparison.OrdinalIgnoreCase)) { methodsLinePosition[testMethodName] = functionMemberAst.NameExtent.StartLineNumber; } } } // All 3 methods (Get/Set/Test) position should be found. return (methodsLinePosition.Count == 3); }
private static void GenerateMofForAst(TypeDefinitionAst typeAst, StringBuilder sb, List<object> embeddedInstanceTypes) { var className = typeAst.Name; sb.AppendFormat(CultureInfo.InvariantCulture, "[ClassVersion(\"1.0.0\"), FriendlyName(\"{0}\")]\nclass {0}", className); if (typeAst.Attributes.Any(a => a.TypeName.GetReflectionAttributeType() == typeof(DscResourceAttribute))) { sb.Append(" : OMI_BaseResource"); } sb.Append("\n{\n"); ProcessMembers(sb, embeddedInstanceTypes, typeAst, className); Queue<object> bases = new Queue<object>(); foreach (var b in typeAst.BaseTypes) { bases.Enqueue(b); } while (bases.Count > 0) { var b = bases.Dequeue(); var tc = b as TypeConstraintAst; if (tc != null) { b = tc.TypeName.GetReflectionType(); if (b == null) { var td = tc.TypeName as TypeName; if (td != null && td._typeDefinitionAst != null) { ProcessMembers(sb, embeddedInstanceTypes, td._typeDefinitionAst, className); foreach (var b1 in td._typeDefinitionAst.BaseTypes) { bases.Enqueue(b1); } } continue; } } var type = b as Type; if (type != null) { ProcessMembers(type, sb, embeddedInstanceTypes, className); var t = type.GetTypeInfo().BaseType; if (t != null) { bases.Enqueue(t); } } } sb.Append("};"); }
internal static string GenerateMofForAst(TypeDefinitionAst typeAst) { var embeddedInstanceTypes = new List<object>(); var sb = new StringBuilder(); GenerateMofForAst(typeAst, sb, embeddedInstanceTypes); var visitedInstances = new List<object>(); visitedInstances.Add(typeAst); ProcessEmbeddedInstanceTypes(embeddedInstanceTypes, visitedInstances, sb); return sb.ToString(); }
internal DefineEnumHelper(Parser parser, ModuleBuilder module, TypeDefinitionAst enumDefinitionAst, string typeName) { _parser = parser; _enumDefinitionAst = enumDefinitionAst; _moduleBuilder = module; _typeName = typeName; }
/// <summary> /// Return base class type, never return null. /// </summary> /// <param name="parser"></param> /// <param name="typeDefinitionAst"></param> /// <param name="interfaces">return declared interfaces</param> /// <returns></returns> private Type GetBaseTypes(Parser parser, TypeDefinitionAst typeDefinitionAst, out List<Type> interfaces) { // Define base types and report errors. Type baseClass = null; interfaces = new List<Type>(); // Default base class is System.Object and it has a default ctor. _baseClassHasDefaultCtor = true; if (typeDefinitionAst.BaseTypes.Any()) { // base class var baseTypeAsts = typeDefinitionAst.BaseTypes; var firstBaseTypeAst = baseTypeAsts[0]; if (firstBaseTypeAst.TypeName.IsArray) { parser.ReportError(firstBaseTypeAst.Extent, () => ParserStrings.SubtypeArray, firstBaseTypeAst.TypeName.FullName); // fall to the default base type } else { baseClass = firstBaseTypeAst.TypeName.GetReflectionType(); if (baseClass == null) { parser.ReportError(firstBaseTypeAst.Extent, () => ParserStrings.TypeNotFound, firstBaseTypeAst.TypeName.FullName); // fall to the default base type } else { if (baseClass.GetTypeInfo().IsSealed) { parser.ReportError(firstBaseTypeAst.Extent, () => ParserStrings.SealedBaseClass, baseClass.Name); // ignore base type if it's sealed. baseClass = null; } else if (baseClass.GetTypeInfo().IsGenericType && !baseClass.IsConstructedGenericType) { parser.ReportError(firstBaseTypeAst.Extent, () => ParserStrings.SubtypeUnclosedGeneric, baseClass.Name); // ignore base type, we cannot inherit from unclosed generic. baseClass = null; } else if (baseClass.GetTypeInfo().IsInterface) { // First Ast can represent interface as well as BaseClass. interfaces.Add(baseClass); baseClass = null; } } } if (baseClass != null) { // All PS classes are TypeName instances. // For PS classes we cannot use reflection API, because type is not created yet. var baseTypeName = firstBaseTypeAst.TypeName as TypeName; if (baseTypeName != null) { _baseClassHasDefaultCtor = baseTypeName.HasDefaultCtor(); } else { _baseClassHasDefaultCtor = baseClass.HasDefaultCtor(); } } for (int i = 0; i < baseTypeAsts.Count; i++) { if (baseTypeAsts[i].TypeName.IsArray) { parser.ReportError(baseTypeAsts[i].Extent, () => ParserStrings.SubtypeArray, baseTypeAsts[i].TypeName.FullName); this.HasFatalErrors = true; } } for (int i = 1; i < baseTypeAsts.Count; i++) { if (baseTypeAsts[i].TypeName.IsArray) { parser.ReportError(baseTypeAsts[i].Extent, () => ParserStrings.SubtypeArray, baseTypeAsts[i].TypeName.FullName); } else { Type interfaceType = baseTypeAsts[i].TypeName.GetReflectionType(); if (interfaceType == null) { parser.ReportError(baseTypeAsts[i].Extent, () => ParserStrings.TypeNotFound, baseTypeAsts[i].TypeName.FullName); } else { if (interfaceType.GetTypeInfo().IsInterface) { interfaces.Add(interfaceType); } else { parser.ReportError(baseTypeAsts[i].Extent, () => ParserStrings.InterfaceNameExpected, interfaceType.Name); } } } } } return baseClass ?? typeof(object); }
public DefineTypeHelper(Parser parser, ModuleBuilder module, TypeDefinitionAst typeDefinitionAst, string typeName) { _moduleBuilder = module; _parser = parser; _typeDefinitionAst = typeDefinitionAst; List<Type> interfaces; var baseClass = this.GetBaseTypes(parser, typeDefinitionAst, out interfaces); _typeBuilder = module.DefineType(typeName, Reflection.TypeAttributes.Class | Reflection.TypeAttributes.Public, baseClass, interfaces.ToArray()); _staticHelpersTypeBuilder = module.DefineType(string.Format(CultureInfo.InvariantCulture, "{0}_<staticHelpers>", typeName), Reflection.TypeAttributes.Class); DefineCustomAttributes(_typeBuilder, typeDefinitionAst.Attributes, _parser, AttributeTargets.Class); _typeDefinitionAst.Type = _typeBuilder.AsType(); _fieldsToInitForMemberFunctions = new List<Tuple<string, object>>(); _definedMethods = new Dictionary<string, List<Tuple<FunctionMemberAst, Type[]>>>(StringComparer.OrdinalIgnoreCase); _definedProperties = new Dictionary<string, PropertyMemberAst>(StringComparer.OrdinalIgnoreCase); _sessionStateField = _typeBuilder.DefineField(SessionStateFieldName, typeof(SessionStateInternal), FieldAttributes.Private); _sessionStateKeeperField = _staticHelpersTypeBuilder.DefineField(s_sessionStateKeeperFieldName, typeof(SessionStateKeeper), FieldAttributes.Assembly | FieldAttributes.Static); }
public object VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { throw PSTraceSource.NewArgumentException(nameof(typeDefinitionAst)); }
public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst ast) { return(Check(ast)); }
private static void ProcessMembers(StringBuilder sb, List<object> embeddedInstanceTypes, TypeDefinitionAst typeDefinitionAst, string className) { foreach (var member in typeDefinitionAst.Members) { var property = member as PropertyMemberAst; if (property == null || property.IsStatic || property.Attributes.All(a => a.TypeName.GetReflectionAttributeType() != typeof(DscPropertyAttribute))) { continue; } var memberType = property.PropertyType == null ? typeof(object) : property.PropertyType.TypeName.GetReflectionType(); var attributes = new List<object>(); for (int i = 0; i < property.Attributes.Count; i++) { attributes.Add(property.Attributes[i].GetAttribute()); } string mofType; bool isArrayType; string embeddedInstanceType; string[] enumNames = null; if (memberType != null) { // TODO - validate type and name mofType = MapTypeToMofType(memberType, member.Name, className, out isArrayType, out embeddedInstanceType, embeddedInstanceTypes); if (memberType.GetTypeInfo().IsEnum) { enumNames = Enum.GetNames(memberType); } } else { // PropertyType can't be null, we used typeof(object) above in that case so we don't get here. mofType = MapTypeNameToMofType(property.PropertyType.TypeName, member.Name, className, out isArrayType, out embeddedInstanceType, embeddedInstanceTypes, ref enumNames); } string arrayAffix = isArrayType ? "[]" : String.Empty; sb.AppendFormat(CultureInfo.InvariantCulture, " {0}{1} {2}{3};\n", MapAttributesToMof(enumNames, attributes, embeddedInstanceType), mofType, member.Name, arrayAffix); } }
/// <summary> /// Check if it is a qualified DSC resource type /// </summary> /// <param name="parser"></param> /// <param name="typeDefinitionAst"></param> /// <param name="dscResourceAttributeAst"></param> internal static void CheckType(Parser parser, TypeDefinitionAst typeDefinitionAst, AttributeAst dscResourceAttributeAst) { bool hasSet = false; bool hasTest = false; bool hasGet = false; bool hasDefaultCtor = false; bool hasNonDefaultCtor = false; bool hasKey = false; Diagnostics.Assert(dscResourceAttributeAst != null, "CheckType called only for DSC resources. dscResourceAttributeAst must be non-null."); foreach (var member in typeDefinitionAst.Members) { var functionMemberAst = member as FunctionMemberAst; if (functionMemberAst != null) { CheckSet(functionMemberAst, ref hasSet); CheckGet(parser, functionMemberAst, ref hasGet); CheckTest(functionMemberAst, ref hasTest); if (functionMemberAst.IsConstructor && !functionMemberAst.IsStatic) { if (functionMemberAst.Parameters.Count == 0) { hasDefaultCtor = true; } else { hasNonDefaultCtor = true; } } } else { var propertyMemberAst = (PropertyMemberAst)member; CheckKey(parser, propertyMemberAst, ref hasKey); } } if (typeDefinitionAst.BaseTypes != null && (!hasSet || !hasGet || !hasTest || !hasKey)) { LookupRequiredMembers(parser, typeDefinitionAst, ref hasSet, ref hasGet, ref hasTest, ref hasKey); } var name = typeDefinitionAst.Name; if (!hasSet) { parser.ReportError(dscResourceAttributeAst.Extent, () => ParserStrings.DscResourceMissingSetMethod, name); } if (!hasGet) { parser.ReportError(dscResourceAttributeAst.Extent, () => ParserStrings.DscResourceMissingGetMethod, name); } if (!hasTest) { parser.ReportError(dscResourceAttributeAst.Extent, () => ParserStrings.DscResourceMissingTestMethod, name); } if (!hasDefaultCtor && hasNonDefaultCtor) { parser.ReportError(dscResourceAttributeAst.Extent, () => ParserStrings.DscResourceMissingDefaultConstructor, name); } if (!hasKey) { parser.ReportError(dscResourceAttributeAst.Extent, () => ParserStrings.DscResourceMissingKeyProperty, name); } }
private static string GetClassNameInAssembly(TypeDefinitionAst typeDefinitionAst) { // Only allocate a list if necessary - in the most common case, we don't need it. List<string> nameParts = null; var parent = typeDefinitionAst.Parent; while (parent.Parent != null) { if (parent is IParameterMetadataProvider) { nameParts = nameParts ?? new List<string>(); var fnDefn = parent.Parent as FunctionDefinitionAst; if (fnDefn != null) { parent = fnDefn; nameParts.Add(fnDefn.Name); } else { nameParts.Add("<" + parent.Extent.Text.GetHashCode().ToString("x", CultureInfo.InvariantCulture) + ">"); } } parent = parent.Parent; } if (nameParts == null) { return typeDefinitionAst.Name; } nameParts.Reverse(); nameParts.Add(typeDefinitionAst.Name); return string.Join(".", nameParts); }
/// <summary> /// Look up all the way up until find all the required members /// </summary> /// <param name="parser"></param> /// <param name="typeDefinitionAst">The type definition ast of the DSC resource type</param> /// <param name="hasSet">flag to indicate if the class contains Set method.</param> /// <param name="hasGet">flag to indicate if the class contains Get method.</param> /// <param name="hasTest">flag to indicate if the class contains Test method.</param> /// <param name="hasKey">flag to indicate if the class contains Key property.</param> private static void LookupRequiredMembers(Parser parser, TypeDefinitionAst typeDefinitionAst, ref bool hasSet, ref bool hasGet, ref bool hasTest, ref bool hasKey) { if (typeDefinitionAst == null) { return; } if (hasSet && hasGet && hasTest && hasKey) { return; } foreach (var baseType in typeDefinitionAst.BaseTypes) { var baseTypeName = baseType.TypeName as TypeName; if (baseTypeName == null) { continue; } TypeDefinitionAst baseTypeDefinitionAst = baseTypeName._typeDefinitionAst; if (baseTypeDefinitionAst == null || !baseTypeDefinitionAst.IsClass) { continue; } foreach (var member in baseTypeDefinitionAst.Members) { var functionMemberAst = member as FunctionMemberAst; if (functionMemberAst != null) { CheckSet(functionMemberAst, ref hasSet); CheckGet(parser, functionMemberAst, ref hasGet); CheckTest(functionMemberAst, ref hasTest); } else { var propertyMemberAst = (PropertyMemberAst)member; CheckKey(parser, propertyMemberAst, ref hasKey); } } if (baseTypeDefinitionAst.BaseTypes != null && (!hasSet || !hasGet || !hasTest || !hasKey)) { LookupRequiredMembers(parser, baseTypeDefinitionAst, ref hasSet, ref hasGet, ref hasTest, ref hasKey); } } }
internal void AddTypeFromUsingModule(Parser parser, TypeDefinitionAst typeDefinitionAst, PSModuleInfo moduleInfo) { TypeLookupResult result; if (_typeTable.TryGetValue(typeDefinitionAst.Name, out result)) { if (result.ExternalNamespaces != null) { // override external type by the type defined in the current namespace result.ExternalNamespaces.Add(moduleInfo.Name); } } else { var newLookupEntry = new TypeLookupResult(typeDefinitionAst) { ExternalNamespaces = new List<string>() }; newLookupEntry.ExternalNamespaces.Add(moduleInfo.Name); _typeTable.Add(typeDefinitionAst.Name, newLookupEntry); } string fullName = SymbolResolver.GetModuleQualifiedName(moduleInfo.Name, typeDefinitionAst.Name); if (_typeTable.TryGetValue(fullName, out result)) { parser.ReportError(typeDefinitionAst.Extent, () => ParserStrings.MemberAlreadyDefined, fullName); } else { _typeTable.Add(fullName, new TypeLookupResult(typeDefinitionAst)); } }
public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { AttributeAst dscResourceAttibuteAst = null; for (int i = 0; i < typeDefinitionAst.Attributes.Count; i++) { var attr = typeDefinitionAst.Attributes[i]; if (attr.TypeName.GetReflectionAttributeType() == typeof(DscResourceAttribute)) { dscResourceAttibuteAst = attr; break; } } if (dscResourceAttibuteAst != null) { DscResourceChecker.CheckType(_parser, typeDefinitionAst, dscResourceAttibuteAst); } return AstVisitAction.Continue; }
/// <summary> /// Add Type to the symbol Table. /// </summary> /// <param name="typeDefinitionAst"></param> public void AddType(TypeDefinitionAst typeDefinitionAst) { _scopes[_scopes.Count - 1].AddType(_parser, typeDefinitionAst); }
/// <summary/> public virtual AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { return AstVisitAction.Continue; }
public TypeLookupResult(TypeDefinitionAst type = null) { Type = type; }
/// <summary> /// This constructor is used when the type is defined in PowerShell. /// </summary> /// <param name="typeDefinitionAst">The type definition from the ast.</param> public PSTypeName(TypeDefinitionAst typeDefinitionAst) { if (typeDefinitionAst == null) { throw PSTraceSource.NewArgumentNullException("typeDefinitionAst"); } TypeDefinitionAst = typeDefinitionAst; Name = typeDefinitionAst.Name; }
// This is the main entry point for turning an AST into compiled code. internal void Compile(CompiledScriptBlockData scriptBlock, bool optimize) { var body = scriptBlock.Ast; Diagnostics.Assert(body is ScriptBlockAst || body is FunctionDefinitionAst || body is FunctionMemberAst || body is CompilerGeneratedMemberFunctionAst, "Caller to verify ast is correct type."); var ast = (Ast)body; Optimize = optimize; _compilingScriptCmdlet = scriptBlock.UsesCmdletBinding; var fileName = ast.Extent.File; if (fileName != null) { _debugSymbolDocument = Expression.SymbolDocument(fileName); } var details = VariableAnalysis.Analyze(body, !optimize, _compilingScriptCmdlet); LocalVariablesTupleType = details.Item1; var nameToIndexMap = details.Item2; if (!nameToIndexMap.TryGetValue(SpecialVariables.@switch, out _switchTupleIndex)) { _switchTupleIndex = VariableAnalysis.ForceDynamic; } if (!nameToIndexMap.TryGetValue(SpecialVariables.@foreach, out _foreachTupleIndex)) { _foreachTupleIndex = VariableAnalysis.ForceDynamic; } LocalVariablesParameter = Expression.Variable(LocalVariablesTupleType, "locals"); var functionMemberAst = ast as FunctionMemberAst; if (functionMemberAst != null) { CompilingMemberFunction = true; MemberFunctionReturnType = functionMemberAst.GetReturnType(); _memberFunctionType = (TypeDefinitionAst)functionMemberAst.Parent; SpecialMemberFunctionType = SpecialMemberFunctionType.None; if (functionMemberAst.Name.Equals(_memberFunctionType.Name, StringComparison.OrdinalIgnoreCase)) { // TODO: default argument support var parameters = ((IParameterMetadataProvider)functionMemberAst.Body).Parameters; if (parameters == null || parameters.Count == 0) { SpecialMemberFunctionType = functionMemberAst.IsStatic ? SpecialMemberFunctionType.StaticConstructor : SpecialMemberFunctionType.DefaultConstructor; } } } else { var generatedMemberFunctionAst = ast as CompilerGeneratedMemberFunctionAst; if (generatedMemberFunctionAst != null) { CompilingMemberFunction = true; SpecialMemberFunctionType = generatedMemberFunctionAst.Type; MemberFunctionReturnType = typeof(void); _memberFunctionType = generatedMemberFunctionAst.DefiningType; } } body.Body.Accept(this); if (_sequencePoints.Count == 0) { // Uncommon, but possible if a script is empty, or if it only defines functions. // In this case, add the entire body as a sequence point. Debugging won't stop // on this sequence point, but it makes it safe to access the CurrentPosition // property in FunctionContext (which can happen if there are exceptions // defining the functions.) _sequencePoints.Add(ast.Extent); } var compileInterpretChoice = (_stmtCount > 300) ? CompileInterpretChoice.NeverCompile : CompileInterpretChoice.CompileOnDemand; if (optimize) { scriptBlock.DynamicParamBlock = CompileTree(_dynamicParamBlockLambda, compileInterpretChoice); scriptBlock.BeginBlock = CompileTree(_beginBlockLambda, compileInterpretChoice); scriptBlock.ProcessBlock = CompileTree(_processBlockLambda, compileInterpretChoice); scriptBlock.EndBlock = CompileTree(_endBlockLambda, compileInterpretChoice); scriptBlock.LocalsMutableTupleType = LocalVariablesTupleType; scriptBlock.LocalsMutableTupleCreator = MutableTuple.TupleCreator(LocalVariablesTupleType); scriptBlock.NameToIndexMap = nameToIndexMap; } else { scriptBlock.UnoptimizedDynamicParamBlock = CompileTree(_dynamicParamBlockLambda, compileInterpretChoice); scriptBlock.UnoptimizedBeginBlock = CompileTree(_beginBlockLambda, compileInterpretChoice); scriptBlock.UnoptimizedProcessBlock = CompileTree(_processBlockLambda, compileInterpretChoice); scriptBlock.UnoptimizedEndBlock = CompileTree(_endBlockLambda, compileInterpretChoice); scriptBlock.UnoptimizedLocalsMutableTupleType = LocalVariablesTupleType; scriptBlock.UnoptimizedLocalsMutableTupleCreator = MutableTuple.TupleCreator(LocalVariablesTupleType); } // The sequence points are identical optimized or not. Regardless, we want to ensure // that the list is unique no matter when the property is accessed, so make sure it is set just once. if (scriptBlock.SequencePoints == null) { scriptBlock.SequencePoints = _sequencePoints.ToArray(); } }
/// <summary> /// Bake types and creates a dynamic assembly. /// This method should be called only for rootAsts (i.e. script file root ScriptBlockAst). /// </summary> /// <param name="rootForDefiningTypes"></param> /// <param name="typeAsts">non-empty array of TypeDefinitionAst</param> /// <returns>Assembly with defined types</returns> internal static Assembly DefinePowerShellTypes(Ast rootForDefiningTypes, TypeDefinitionAst[] typeAsts) { // TODO(sevoroby): this Diagnostic is conceptually right. // BUT It triggers, when we define type in an InitialSessionState and use it later in two different PowerShell instances. // Diagnostics.Assert(typeAsts[0].Type == null, "We must not call DefinePowerShellTypes twice for the same TypeDefinitionAsts"); if (typeAsts[0].Type != null) { // We treat Type as a mutable buffer field and wipe it here to start definitions from scratch. // I didn't find any real scenario when it can cause problems, except multi-threaded environment, which is rear and out-of-scope for now. // Potentially, we can fix it with Ast.Copy() and rewiring ITypeName references for the whole tree. foreach (var typeDefinitionAst in typeAsts) { typeDefinitionAst.Type = null; } } // This is a short term solution - all error messages produced by creating the types should happen // at parse time, not runtime. var parser = new Parser(); var assembly = TypeDefiner.DefineTypes(parser, rootForDefiningTypes, typeAsts); if (parser.ErrorList.Count > 0) { // wipe types, if there are any errors. foreach (var typeDefinitionAst in typeAsts) { typeDefinitionAst.Type = null; } throw new ParseException(parser.ErrorList.ToArray()); } return assembly; }
object ICustomAstVisitor2.VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) => ProcessRewriter(VisitTypeDefinition, typeDefinitionAst);
public object VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { return ExpressionCache.Empty; }
/// <summary/> public virtual object VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { return(null); }
public override object VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { _symbolResolver._symbolTable.LeaveScope(); return(null); }
public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { DiscoveredClasses.Add(typeDefinitionAst); return(_forCompletion ? AstVisitAction.Continue : AstVisitAction.SkipChildren); }
public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { DiscoveredClasses.Add(typeDefinitionAst); return _forCompletion ? AstVisitAction.Continue : AstVisitAction.SkipChildren; }
public object VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { return(false); }
public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { return(Visit(typeDefinitionAst)); }
public override StatementAst VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) => VisitStatement(base.VisitTypeDefinition(typeDefinitionAst));
internal static Assembly DefineTypes(Parser parser, Ast rootAst, TypeDefinitionAst[] typeDefinitions) { Diagnostics.Assert(rootAst.Parent == null, "Caller should only define types from the root ast"); var definedTypes = new HashSet<string>(StringComparer.OrdinalIgnoreCase); // First character is a special mark that allows us to cheaply ignore dynamic generated assemblies in ClrFacede.GetAssemblies() // Two replaces at the end are for not-allowed characters. They are replaced by similar-looking chars. string assemblyName = ClrFacade.FIRST_CHAR_PSASSEMBLY_MARK + (string.IsNullOrWhiteSpace(rootAst.Extent.File) ? "powershell" : rootAst.Extent.File .Replace('\\', (char)0x29f9) .Replace('/', (char)0x29f9) .Replace(':', (char)0x0589)); var assembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName(assemblyName), AssemblyBuilderAccess.RunAndCollect, GetAssemblyAttributeBuilders()); var module = assembly.DefineDynamicModule(assemblyName); var defineTypeHelpers = new List<DefineTypeHelper>(); var defineEnumHelpers = new List<DefineEnumHelper>(); foreach (var typeDefinitionAst in typeDefinitions) { var typeName = GetClassNameInAssembly(typeDefinitionAst); if (!definedTypes.Contains(typeName)) { definedTypes.Add(typeName); if ((typeDefinitionAst.TypeAttributes & TypeAttributes.Class) == TypeAttributes.Class) { defineTypeHelpers.Add(new DefineTypeHelper(parser, module, typeDefinitionAst, typeName)); } else if ((typeDefinitionAst.TypeAttributes & TypeAttributes.Enum) == TypeAttributes.Enum) { defineEnumHelpers.Add(new DefineEnumHelper(parser, module, typeDefinitionAst, typeName)); } } } // Define enums before classes so members of classes can use these enum types. defineEnumHelpers = DefineEnumHelper.Sort(defineEnumHelpers, parser); foreach (var helper in defineEnumHelpers) { helper.DefineEnum(); } foreach (var helper in defineTypeHelpers) { helper.DefineMembers(); } foreach (var helper in defineTypeHelpers) { Diagnostics.Assert(helper._typeDefinitionAst.Type.GetTypeInfo() is TypeBuilder, "Type should be the TypeBuilder"); bool runtimeTypeAssigned = false; if (!helper.HasFatalErrors) { try { var type = helper._typeBuilder.CreateTypeInfo().AsType(); helper._typeDefinitionAst.Type = type; runtimeTypeAssigned = true; var helperType = helper._staticHelpersTypeBuilder.CreateTypeInfo().AsType(); if (helper._fieldsToInitForMemberFunctions != null) { foreach (var tuple in helper._fieldsToInitForMemberFunctions) { helperType.GetField(tuple.Item1, BindingFlags.NonPublic | BindingFlags.Static) .SetValue(null, tuple.Item2); } } helperType.GetField(s_sessionStateKeeperFieldName, BindingFlags.NonPublic | BindingFlags.Static).SetValue(null, new SessionStateKeeper()); } catch (TypeLoadException e) { // This is a cheap way to get error messages about non-implemented abstract/interface methods (and maybe some other errors). // We use .NET API to perform this check during type creation. // // Presumably this catch could go away when we will not create Type at parse time. // Error checking should be moved/added to semantic checks. parser.ReportError(helper._typeDefinitionAst.Extent, () => ParserStrings.TypeCreationError, helper._typeBuilder.Name, e.Message); } } if (!runtimeTypeAssigned) { // Clean up ast helper._typeDefinitionAst.Type = null; } } return assembly; }
/// <summary/> public virtual AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { return(AstVisitAction.Continue); }
internal static Type GetTypeFromMemberExpressionAst(MemberExpressionAst memAst, VariableAnalysisDetails analysis, TypeDefinitionAst psClass) #endif { if (memAst != null && memAst.Expression is VariableExpressionAst && memAst.Member is StringConstantExpressionAst && !String.Equals((memAst.Expression as VariableExpressionAst).VariablePath.UserPath, "this", StringComparison.OrdinalIgnoreCase)) { string fieldName = (memAst.Member as StringConstantExpressionAst).Value; #if !PSV3 if (psClass == null && analysis.Constant == SpecialVars.ThisVariable) { psClass = AssignmentTarget.FindClassAncestor(memAst); } if (psClass != null) { Type typeFromClass = AssignmentTarget.GetTypeFromClass(psClass, memAst); { if (typeFromClass != null) { return typeFromClass; } } } #endif // If the type is not a ps class or there are some types of the same name. if (analysis != null && analysis.Type != null && analysis.Type != typeof(object) && analysis.Type != typeof(Unreached) && analysis.Type != typeof(Undetermined)) { if (memAst is InvokeMemberExpressionAst) { return AssignmentTarget.GetTypeFromInvokeMemberAst(analysis.Type, memAst as InvokeMemberExpressionAst, fieldName, false); } else { return AssignmentTarget.GetPropertyOrFieldTypeFromMemberExpressionAst(analysis.Type, fieldName); } } } return null; }
private PSClassInfo ConvertToClassInfo(PSModuleInfo module, ScriptBlockAst ast, TypeDefinitionAst statement) { PSClassInfo classInfo = new PSClassInfo(statement.Name); Dbg.Assert(statement.Name != null, "statement should have a name."); classInfo.Module = module; Collection <PSClassMemberInfo> properties = new Collection <PSClassMemberInfo>(); foreach (var member in statement.Members) { if (member is PropertyMemberAst propAst && !propAst.PropertyAttributes.HasFlag(PropertyAttributes.Hidden)) { Dbg.Assert(propAst.Name != null, "PropName cannot be null"); Dbg.Assert(propAst.PropertyType != null, "PropertyType cannot be null"); Dbg.Assert(propAst.PropertyType.TypeName != null, "Property TypeName cannot be null"); Dbg.Assert(propAst.Extent != null, "Property Extent cannot be null"); Dbg.Assert(propAst.Extent.Text != null, "Property ExtentText cannot be null"); PSClassMemberInfo classProperty = new PSClassMemberInfo(propAst.Name, propAst.PropertyType.TypeName.FullName, propAst.Extent.Text); properties.Add(classProperty); } } classInfo.UpdateMembers(properties); string mamlHelpFile = null; if (ast.GetHelpContent() != null) { mamlHelpFile = ast.GetHelpContent().MamlHelpFile; } if (!string.IsNullOrEmpty(mamlHelpFile)) { classInfo.HelpFile = mamlHelpFile; } return(classInfo); }
/// <summary> /// Get the type for memberexpressionast assuming that the variable is a class /// </summary> /// <param name="psClass"></param> /// <param name="memberExpressionAst"></param> /// <returns></returns> internal static Type GetTypeFromClass(TypeDefinitionAst psClass, MemberExpressionAst memberExpressionAst) { Type result = null; if (psClass != null) { MemberAst memAst = psClass.Members.FirstOrDefault(item => String.Equals(item.Name, (memberExpressionAst.Member as StringConstantExpressionAst).Value, StringComparison.OrdinalIgnoreCase)); if (memAst != null) { if (memAst is PropertyMemberAst) { result = (memAst as PropertyMemberAst).PropertyType.TypeName.GetReflectionType(); } else if (memAst is FunctionMemberAst) { result = (memAst as FunctionMemberAst).ReturnType.TypeName.GetReflectionType(); } } } return result; }
public object VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) { return(AutomationNull.Value); }
public override AstVisitAction VisitTypeDefinition(TypeDefinitionAst typeDefinitionAst) => VisitAst(typeDefinitionAst);