/// <summary> /// Adds a property to the given type which raises PropertyChange Notifications when the property is set. /// </summary> /// <param name="type">The type to add property to.</param> /// <param name="propertyType">Type of the property.</param> /// <param name="propertyName">Name of the property.</param> /// <returns>Added property.</returns> protected CodeMemberProperty AddPropertyWithChangeNotification(CodeTypeDeclaration type, CodeTypeReference propertyType, string propertyName) { // Declare a private property to be the backing field string backingFieldName = string.Format(CultureInfo.InvariantCulture, "backing{0}", propertyName); type.AddField(propertyType, backingFieldName); CodeMemberProperty propertyWithChangeNotifications = new CodeMemberProperty() { Name = propertyName, Type = propertyType, Attributes = MemberAttributes.Public }; CodeThisReferenceExpression thisReference = new CodeThisReferenceExpression(); // this will hold the reference to the backing field CodeFieldReferenceExpression backingFieldReference = new CodeFieldReferenceExpression(thisReference, backingFieldName); // add a getter which returns the backing field propertyWithChangeNotifications.GetStatements.Add(new CodeMethodReturnStatement(backingFieldReference)); // add a statement which sets the value of the backing field CodeAssignStatement setStatement = new CodeAssignStatement(backingFieldReference, new CodeArgumentReferenceExpression("value")); // This will call the RaisePropertyChanged method passing in the propertyName CodeMethodInvokeExpression invokePropertyChangeNotifier = new CodeMethodInvokeExpression(thisReference, "RaisePropertyChanged", new CodeExpression[] { new CodePrimitiveExpression(propertyName) }); propertyWithChangeNotifications.SetStatements.Add(setStatement); propertyWithChangeNotifications.SetStatements.Add(invokePropertyChangeNotifier); type.Members.Add(propertyWithChangeNotifications); return(propertyWithChangeNotifications); }
static void AddErrorHelpers(CodeTypeDeclaration type) { var minusOne = Expression.Primitive(-1); var errors = type.AddProperty <CompilerErrorCollection> ("Errors").AsProtected() .WithGetLazyInitialize( type.AddField <CompilerErrorCollection> ("errors"), init: Expression.New <CompilerErrorCollection> ()) .OnThis(); type.AddMethod("Error") .WithParameter <string> ("message", out var paramErrorMessage) .WithStatements( errors.InvokeMethod( "Add", Expression.New <CompilerError> (Expression.Null, minusOne, minusOne, Expression.Null, paramErrorMessage) )); type.AddMethod("Warning") .WithParameter("message", TypeReference.String, out var paramWarningMessage) .WithStatements( Statement.DeclareVariable <CompilerError> ("val", Expression.New <CompilerError> (Expression.Null, minusOne, minusOne, Expression.Null, paramWarningMessage), out var val), val.SetProperty("IsWarning", Expression.True), errors.InvokeMethod("Add", val).AsStatement() ); }
static void AddIndentHelpers(CodeTypeDeclaration type) { var zero = Expression.Primitive(0); type.AddPropertyGetOnly("CurrentIndent", type.AddField("currentIndent", TypeReference.String, init: Expression.StringEmpty) .WithReference(out var currentIndent)); type.AddProperty <Stack <int> > ("Indents").AsPrivate() .WithGetLazyInitialize( type.AddField <Stack <int> > ("indents"), Expression.New <Stack <int> > ()) .WithReference(out var indents); type.AddMethod("PopIndent").Returns <string> () .WithStatements( Statement.If(indents.Property("Count").IsEqualValue(zero), Then: Expression.StringEmpty.Return()), Statement.DeclareVariable <int> ("lastPos", currentIndent.Property("Length").Subtract(indents.InvokeMethod("Pop")), out var lastPosRef), Statement.DeclareVariable(TypeReference.String, "last", currentIndent.InvokeMethod("Substring", lastPosRef), out var lastRef), currentIndent.Assign(currentIndent.InvokeMethod("Substring", zero, lastPosRef)), lastRef.Return() ); type.AddMethod("PushIndent") .WithParameter("indent", TypeReference.String, out var paramIndent) .WithStatements( indents.InvokeMethod("Push", paramIndent.Property("Length")).AsStatement(), currentIndent.Assign(currentIndent.Add(paramIndent)) ); type.AddMethod("ClearIndent") .WithStatements( currentIndent.Assign(Expression.StringEmpty), indents.InvokeMethod("Clear").AsStatement() ); }
private void Create_SOContainer(CodeNamespace pNameSpace, CodeNamespaceImport[] arrDefaultUsing, CodeTypeDeclaration pType, CodeTypeDeclaration[] arrEnumType, out CodeTypeDeclaration pContainerType, out CodeMemberMethod pInitMethod) { string strContainerTypeName = pType.Name + "_Container"; pContainerType = new CodeTypeDeclaration(strContainerTypeName); pContainerType.AddBaseClass("UnityEngine.ScriptableObject"); pNameSpace.Imports.Clear(); pNameSpace.Imports.AddRange(arrDefaultUsing); pNameSpace.Imports.Add(new CodeNamespaceImport("System.Linq")); pNameSpace.Imports.Add(new CodeNamespaceImport("System.Collections.Generic")); pNameSpace.Types.Clear(); pNameSpace.Types.Add(pContainerType); pNameSpace.Types.AddRange(arrEnumType); pContainerType.AddField(new FieldTypeData(const_strFieldName_private_instance, strContainerTypeName), MemberAttributes.Private | MemberAttributes.Static); var pPublicInstanceProperty = pContainerType.AddProperty(new FieldTypeData(const_strFieldName_instance, strContainerTypeName), MemberAttributes.Public | MemberAttributes.Static); pPublicInstanceProperty.GetStatements.Add(new CodeSnippetStatement($" return {const_strFieldName_private_instance};")); pContainerType.AddField(new FieldTypeData(const_strFieldName_ListData, $"List<{pType.Name}>")); pInitMethod = Generate_InitMethod(pContainerType, pType.Name); }
private void Create_SO(CodeFileBuilder pCodeFileBuilder, CodeNamespace pNameSpace, CodeTypeDeclaration pType, TypeData pSaveData) { pType.AddBaseClass("UnityEngine.ScriptableObject"); pNameSpace.Types.Clear(); pNameSpace.Types.Add(pType); var listVirtualFieldOption = pSaveData.listFieldData.Where(pExportOption => pExportOption.bDeleteThisField_InCode == false && pExportOption.bIsVirtualField); foreach (var pVirtualField in listVirtualFieldOption) { pType.AddField(pVirtualField); } pCodeFileBuilder.Generate_CSharpCode(pNameSpace, $"{GetRelative_To_AbsolutePath(strExportPath)}/{pType.Name}"); }
static void GenerateProcessingHelpers(CodeTypeDeclaration type) { var builderFieldDef = type.AddField <StringBuilder> ("builder").WithReference(out var builder); var sessionFieldDef = type.AddField <IDictionary <string, object> > ("session"); type.AddPropertyGetSet("Session", sessionFieldDef).AsVirtual(); type.AddProperty <StringBuilder> ("GenerationEnvironment") .WithSet(builder) .WithGetLazyInitialize(builder, builderFieldDef.Type.New()); AddErrorHelpers(type); AddIndentHelpers(type); AddWriteHelpers(type); }
private void Create_SOContainer(CodeNamespace pNameSpace, CodeNamespaceImport[] arrDefaultUsing, CodeTypeDeclaration pType, CodeTypeDeclaration[] arrEnumType, out CodeTypeDeclaration pContainerType, out CodeMemberMethod pInitMethod) { pContainerType = new CodeTypeDeclaration(pType.Name + "_Container"); pContainerType.AddBaseClass("UnityEngine.ScriptableObject"); pNameSpace.Imports.Clear(); pNameSpace.Imports.AddRange(arrDefaultUsing); pNameSpace.Imports.Add(new CodeNamespaceImport("System.Linq")); pNameSpace.Imports.Add(new CodeNamespaceImport("System.Collections.Generic")); pNameSpace.Types.Clear(); pNameSpace.Types.Add(pContainerType); pNameSpace.Types.AddRange(arrEnumType); pContainerType.AddField(new FieldTypeData(const_strListData, $"List<{pType.Name}>")); pInitMethod = Generate_InitMethod(pContainerType, pType.Name); }
static void AddToStringHelper(CodeTypeDeclaration type, CodeDomProvider provider) { var helperClass = Declare.Class("ToStringInstanceHelper") .AsNestedPublic() .WithReference(out var helperClassType); helperClass.AddField <IFormatProvider> ("formatProvider", TypeReference <System.Globalization.CultureInfo> .Global.Property("InvariantCulture")) .WithReference(out var formatProvider); helperClass.AddProperty <IFormatProvider> ("FormatProvider") .WithGet(formatProvider) .WithSetIgnoresNull(formatProvider); helperClass.AddMethod("ToStringWithCulture") .Returns <string> () .WithParameter <object> ("objectToConvert", out var objectToConvert) .WithStatements( objectToConvert.ThrowIfNull(), Declare.Variable <Type> ("type", objectToConvert.InvokeMethod("GetType"), out var objType), Declare.Variable <Type> ("iConvertibleType", Expression.TypeOf <IConvertible> (), out var iConvertibleType), Statement.If(iConvertibleType.InvokeMethod("IsAssignableFrom", objType), Then: Statement.Return(objectToConvert.Cast <IConvertible> ().InvokeMethod("ToString", formatProvider))), Declare.Variable <System.Reflection.MethodInfo> ("methInfo", objType.InvokeMethod("GetMethod", Expression.Primitive("ToString"), Expression.Array <Type> (iConvertibleType)), out var methInfoLocalRef), Statement.If(methInfoLocalRef.IsNotNull(), Then: Statement.Return(Expression.Cast <string> ( methInfoLocalRef.InvokeMethod("Invoke", objectToConvert, Expression.Array <object> (formatProvider))))), Statement.Return(objectToConvert.InvokeMethod("ToString")) ); var helperFieldName = provider.CreateValidIdentifier("_toStringHelper"); type.AddPropertyGetOnly("ToStringHelper", type.AddField(helperFieldName, helperClassType, Expression.New(helperClassType))); type.AddMember(helperClass); }
static void ProcessType(Type type, CodeTypeDeclaration ctd) { foreach (FieldInfo field in type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic)) { ctd.AddField(ConvertType(field.FieldType), field.Name).Attributes = 0; } foreach (FieldInfo field in type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic)) { EasyProperty p = ctd.AddProperty(ConvertType(field.FieldType), GetPropertyName(field.Name)); p.Getter.Return(Easy.Var(field.Name)); CodeExpression ex; if (field.FieldType.IsValueType) { ex = new CodePropertySetValueReferenceExpression(); } else { ex = GetDefaultValue("value", field); } p.Setter.Assign(Easy.Var(field.Name), ex); if (typeof(INode).IsAssignableFrom(field.FieldType)) { if (typeof(INullable).IsAssignableFrom(field.FieldType)) { p.SetStatements.Add(new CodeSnippetStatement("\t\t\t\tif (!" + field.Name + ".IsNull) " + field.Name + ".Parent = this;")); } else { p.SetStatements.Add(new CodeSnippetStatement("\t\t\t\t" + field.Name + ".Parent = this;")); } } } foreach (ConstructorInfo ctor in type.GetConstructors(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)) { CodeConstructor c = new CodeConstructor(); if (type.IsAbstract) { c.Attributes = MemberAttributes.Family; } else { c.Attributes = MemberAttributes.Public; } ctd.Members.Add(c); ConstructorInfo baseCtor = GetBaseCtor(type); foreach (ParameterInfo param in ctor.GetParameters()) { c.Parameters.Add(new CodeParameterDeclarationExpression(ConvertType(param.ParameterType), param.Name)); if (baseCtor != null && Array.Exists(baseCtor.GetParameters(), delegate(ParameterInfo p) { return(param.Name == p.Name); })) { continue; } c.Statements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression(GetPropertyName(param.Name)), new CodeVariableReferenceExpression(param.Name))); } if (baseCtor != null) { foreach (ParameterInfo param in baseCtor.GetParameters()) { c.BaseConstructorArgs.Add(new CodeVariableReferenceExpression(param.Name)); } } // initialize fields that were not initialized by parameter foreach (FieldInfo field in type.GetFields(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.NonPublic)) { if (field.FieldType.IsValueType && field.FieldType != typeof(Location)) { continue; } if (Array.Exists(ctor.GetParameters(), delegate(ParameterInfo p) { return(field.Name == p.Name); })) { continue; } c.Statements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression(field.Name), GetDefaultValue(null, field))); } } }
static CodeTypeDeclaration CreateAstVisitorClass(List <Type> nodeTypes, bool transformer) { CodeTypeDeclaration td = new CodeTypeDeclaration(transformer ? "AbstractAstTransformer" : "AbstractAstVisitor"); td.TypeAttributes = TypeAttributes.Public | TypeAttributes.Abstract; td.BaseTypes.Add(new CodeTypeReference("IAstVisitor")); if (transformer) { string comment = "The AbstractAstTransformer will iterate through the whole AST,\n " + "just like the AbstractAstVisitor. However, the AbstractAstTransformer allows\n " + "you to modify the AST at the same time: It does not use 'foreach' internally,\n " + "so you can add members to collections of parents of the current node (but\n " + "you cannot insert or delete items as that will make the index used invalid).\n " + "You can use the methods ReplaceCurrentNode and RemoveCurrentNode to replace\n " + "or remove the current node, totally independent from the type of the parent node."; Easy.AddSummary(td, comment); CodeMemberField field = td.AddField(Easy.TypeRef("Stack", "INode"), "nodeStack"); field.InitExpression = Easy.New(field.Type); /* * CodeExpression nodeStack = Easy.Var("nodeStack"); * CodeMemberProperty p = new CodeMemberProperty(); * p.Name = "CurrentNode"; * p.Type = new CodeTypeReference("INode"); * p.Attributes = MemberAttributes.Public | MemberAttributes.Final; * p.GetStatements.Add(new CodeMethodReturnStatement(new CodeVariableReferenceExpression("currentNode"))); * p.SetStatements.Add(new CodeAssignStatement(new CodeVariableReferenceExpression("currentNode"), * new CodePropertySetValueReferenceExpression())); * td.Members.Add(p); */ EasyMethod m = td.AddMethod("ReplaceCurrentNode"); m.AddParameter(Easy.TypeRef("INode"), "newNode"); m.Statements.Add(Easy.Var("nodeStack").InvokeMethod("Pop")); m.Statements.Add(Easy.Var("nodeStack").InvokeMethod("Push", Easy.Var("newNode"))); m = td.AddMethod("RemoveCurrentNode"); m.Statements.Add(Easy.Var("nodeStack").InvokeMethod("Pop")); m.Statements.Add(Easy.Var("nodeStack").InvokeMethod("Push", Easy.Null)); } foreach (Type type in nodeTypes) { if (!type.IsAbstract) { EasyMethod m = td.AddMethod(typeof(object), VisitPrefix + type.Name); m.Attributes = MemberAttributes.Public; m.AddParameter(ConvertType(type), GetFieldName(type.Name)); m.AddParameter(typeof(object), "data"); List <CodeStatement> assertions = new List <CodeStatement>(); string varVariableName = GetFieldName(type.Name); CodeExpression var = Easy.Var(varVariableName); assertions.Add(AssertIsNotNull(var)); AddFieldVisitCode(m, type, var, assertions, transformer); if (type.GetCustomAttributes(typeof(HasChildrenAttribute), true).Length > 0) { if (transformer) { m.Statements.Add(new CodeSnippetStatement(CreateTransformerLoop(varVariableName + ".Children", "INode"))); m.Body.Return(Easy.Null); } else { m.Body.Return(var.InvokeMethod("AcceptChildren", Easy.This, Easy.Var("data"))); } } else { CodeExpressionStatement lastStatement = null; if (m.Statements.Count > 0) { lastStatement = m.Statements[m.Statements.Count - 1] as CodeExpressionStatement; } if (lastStatement != null) { m.Statements.RemoveAt(m.Statements.Count - 1); m.Body.Return(lastStatement.Expression); } else { m.Body.Return(Easy.Null); } } for (int i = 0; i < assertions.Count; i++) { m.Statements.Insert(i, assertions[i]); } } } return(td); }
public static CodeMemberField AddField(this CodeTypeDeclaration typeDecl, Type type, string name) { return(typeDecl.AddField(Easy.TypeRef(type), name)); }
public virtual CodeTypeDeclaration CreateClass(SettingsDocument setDoc) { CodeTypeDeclaration c = new CodeTypeDeclaration(setDoc.GeneratedClassName); c.AddAttribute(typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute)); c.AddAttribute(typeof(System.CodeDom.Compiler.GeneratedCodeAttribute), Easy.Prim(typeof(SettingsCodeGeneratorTool).FullName), Easy.Prim(typeof(SettingsCodeGeneratorTool).Assembly.GetName().Version.ToString())); c.TypeAttributes = TypeAttributes.NotPublic | TypeAttributes.Sealed; c.IsPartial = true; c.BaseTypes.Add(Easy.TypeRef(typeof(ApplicationSettingsBase))); CodeMemberField f = c.AddField(Easy.TypeRef(c), "defaultInstance"); f.Attributes = MemberAttributes.Private | MemberAttributes.Static; f.InitExpression = Easy.Type(typeof(ApplicationSettingsBase)) .InvokeMethod("Synchronized", Easy.New(Easy.TypeRef(c))) .CastTo(Easy.TypeRef(c)); var defaultProperty = c.AddProperty(f, "Default"); if (setDoc.UseMySettingsClassName) { c.AddAttribute(typeof(EditorBrowsableAttribute), Easy.Prim(EditorBrowsableState.Advanced)); AddAutoSaveLogic(c, defaultProperty); } foreach (SettingsEntry entry in setDoc.Entries) { Type entryType = entry.Type ?? typeof(string); SpecialSetting?specialSetting = null; foreach (SpecialTypeDescriptor desc in SpecialTypeDescriptor.Descriptors) { if (desc.type == entryType) { entryType = typeof(string); specialSetting = desc.specialSetting; break; } } EasyProperty p = c.AddProperty(entryType, entry.Name); if (entry.Scope == SettingScope.User) { p.AddAttribute(typeof(UserScopedSettingAttribute)); } else { p.AddAttribute(typeof(ApplicationScopedSettingAttribute)); } if (!string.IsNullOrEmpty(entry.Provider)) { p.AddAttribute(typeof(SettingsProviderAttribute), Easy.TypeOf(new CodeTypeReference(entry.Provider))); } if (!string.IsNullOrEmpty(entry.Description)) { p.AddAttribute(typeof(SettingsDescriptionAttribute), Easy.Prim(entry.Description)); Easy.AddSummary(p, entry.Description); } p.AddAttribute(typeof(DebuggerNonUserCodeAttribute)); if (specialSetting != null) { p.AddAttribute(typeof(SpecialSettingAttribute), Easy.Prim(specialSetting.Value)); } if (entry.GenerateDefaultValueInCode) { p.AddAttribute(typeof(DefaultSettingValueAttribute), Easy.Prim(entry.SerializedValue)); } if (entry.Scope == SettingScope.User && entry.Roaming) { p.AddAttribute(typeof(SettingsManageabilityAttribute), Easy.Prim(SettingsManageability.Roaming)); } p.Getter.Return(Easy.This.Index(Easy.Prim(entry.Name)).CastTo(entryType)); // p.GetStatements.Add(new CodeMethodReturnStatement( // new CodeCastExpression(new CodeTypeReference(entryType), // new CodeIndexerExpression(new CodeThisReferenceExpression(), // new CodePrimitiveExpression(entry.Name)) // ) // )); if (entry.Scope == SettingScope.User) { p.Setter.Assign(Easy.This.Index(Easy.Prim(entry.Name)), Easy.Value); } } return(c); }
static void GenerateHostProperty(CodeTypeDeclaration type, Type hostType) { hostType ??= typeof(ITextTemplatingEngineHost); type.AddPropertyGetSet("Host", type.AddField("hostValue", TypeReference.Global(hostType))); }