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 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); }