From b648951f54f4ff071c385ba4d55d515a706d73e7 Mon Sep 17 00:00:00 2001 From: Eusebiu Marcu Date: Sun, 23 Jan 2011 14:06:00 +0200 Subject: [PATCH] Using CodeDom to generate metadata files. Add Option dialog for expand references --- data/resources/StringResources.resx | 9 + .../Project/ICSharpCode.SharpDevelop.addin | 3 + .../Project/ICSharpCode.SharpDevelop.csproj | 5 + .../Src/Editor/Commands/GoToDefinition.cs | 115 ++++- .../IDEOptions/SharpDevelopUIOptions.xaml | 15 + .../IDEOptions/SharpDevelopUIOptions.xaml.cs | 21 + .../TreeNodes/InnerExpand/MemberNodes.cs | 10 - .../TreeNodes/InnerExpand/TypeNodes.cs | 10 - .../ProjectBrowser/TreeNodes/ReferenceNode.cs | 5 + .../DecompilerService/DecompilerService.cs | 431 ++++++++++++------ 10 files changed, 452 insertions(+), 172 deletions(-) create mode 100644 src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/SharpDevelopUIOptions.xaml create mode 100644 src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/SharpDevelopUIOptions.xaml.cs diff --git a/data/resources/StringResources.resx b/data/resources/StringResources.resx index eb50836d0f..787a4f0294 100644 --- a/data/resources/StringResources.resx +++ b/data/resources/StringResources.resx @@ -2596,6 +2596,15 @@ Do you want to add the new file to the project ${CurrentProjectName}? UI language set to: + + Sharp Develop UI options + + + Sharp Develop UI options + + + Expand project references (reflect references) + Select your preferred &ambience: diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin b/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin index adc724bd04..d84f7dcd14 100755 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.addin @@ -1079,6 +1079,9 @@ + diff --git a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj index a7b0e82314..d67ff7ad0a 100644 --- a/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj +++ b/src/Main/Base/Project/ICSharpCode.SharpDevelop.csproj @@ -247,6 +247,10 @@ SelectCulturePanel.xaml Code + + SharpDevelopUIOptions.xaml + Code + WebProjectOptionsPanel.xaml @@ -823,6 +827,7 @@ + diff --git a/src/Main/Base/Project/Src/Editor/Commands/GoToDefinition.cs b/src/Main/Base/Project/Src/Editor/Commands/GoToDefinition.cs index 36bd84c516..d78ce8f624 100644 --- a/src/Main/Base/Project/Src/Editor/Commands/GoToDefinition.cs +++ b/src/Main/Base/Project/Src/Editor/Commands/GoToDefinition.cs @@ -1,10 +1,13 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) -using ICSharpCode.SharpDevelop.Dom; using System; +using System.IO; using ICSharpCode.Core; +using ICSharpCode.SharpDevelop.Dom; using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.SharpDevelop.Project; +using Mono.Cecil; namespace ICSharpCode.SharpDevelop.Editor.Commands { @@ -15,15 +18,111 @@ namespace ICSharpCode.SharpDevelop.Editor.Commands if (symbol == null) return; FilePosition pos = symbol.GetDefinitionPosition(); - if (pos.IsEmpty) + if (pos.IsEmpty) { + new GoToDecompiledDefinition().Run(symbol); + } else { + try { + if (pos.Position.IsEmpty) + FileService.OpenFile(pos.FileName); + else + FileService.JumpToFilePosition(pos.FileName, pos.Line, pos.Column); + } catch (Exception ex) { + MessageService.ShowException(ex, "Error jumping to '" + pos.FileName + "'."); + } + } + } + } + + public class GoToDecompiledDefinition : AbstractMenuCommand + { + /// + /// Don't use this method; throws NotImplementedException. + /// + public override void Run() + { + throw new NotImplementedException(); + } + + public void Run(ResolveResult symbol) + { + if (ProjectService.CurrentProject == null) return; - try { - if (pos.Position.IsEmpty) - FileService.OpenFile(pos.FileName); + string filePath = null; + if (symbol is MemberResolveResult) { + var s = (MemberResolveResult)symbol; + DecompilerService.ReadMetadata(s.ResolvedMember.DeclaringType, out filePath); + if (string.IsNullOrEmpty(filePath)) + return; + + // jump to definition + var info = ParserService.ParseFile(filePath); + int line = 0, col = 0; + foreach(var c in info.CompilationUnit.Classes) { + if (s.ResolvedMember.EntityType == EntityType.Event) { + foreach (var ev in c.Events) { + if (s.ResolvedMember.FullyQualifiedName == ev.FullyQualifiedName && + s.ResolvedMember.ReturnType.FullyQualifiedName == ev.ReturnType.FullyQualifiedName) { + col = ev.Region.BeginColumn; + line = ev.Region.BeginLine; + } + } + + if (col > 0 || line > 0) + break; + } + + if (s.ResolvedMember.EntityType == EntityType.Method) { + + foreach(var m1 in s.ResolvedMember.DeclaringType.Methods) { + if (s.ResolvedMember.ReturnType.FullyQualifiedName != m1.ReturnType.FullyQualifiedName || + s.ResolvedMember.FullyQualifiedName != m1.FullyQualifiedName) continue; + + foreach (var m in c.Methods) { + if (m1.FullyQualifiedName == m.FullyQualifiedName && + m1.ReturnType.FullyQualifiedName == m1.ReturnType.FullyQualifiedName && + m1.Parameters.Count == m.Parameters.Count) { + + col = m.Region.BeginColumn; + line = m.Region.BeginLine; + break; + } + } + + if (col > 0 || line > 0) + break; + } + + if (col > 0 || line > 0) + break; + } + + if (s.ResolvedMember.EntityType == EntityType.Property) { + foreach (var p in c.Properties) { + if (s.ResolvedMember.FullyQualifiedName == p.FullyQualifiedName && + s.ResolvedMember.ReturnType.FullyQualifiedName == p.ReturnType.FullyQualifiedName) { + col = p.Region.BeginColumn; + line = p.Region.BeginLine; + break; + } + } + + if (col > 0 || line > 0) + break; + } + } + + if (col > 0 || line > 0) + FileService.JumpToFilePosition(filePath, line, col); else - FileService.JumpToFilePosition(pos.FileName, pos.Line, pos.Column); - } catch (Exception ex) { - MessageService.ShowException(ex, "Error jumping to '" + pos.FileName + "'."); + FileService.OpenFile(filePath); + } + + if (symbol is TypeResolveResult) { + var s = (TypeResolveResult)symbol; + DecompilerService.ReadMetadata(s.ResolvedClass, out filePath); + + if (!string.IsNullOrEmpty(filePath)) + FileService.OpenFile(filePath); } } } diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/SharpDevelopUIOptions.xaml b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/SharpDevelopUIOptions.xaml new file mode 100644 index 0000000000..61efd58c9f --- /dev/null +++ b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/SharpDevelopUIOptions.xaml @@ -0,0 +1,15 @@ + + + + + + + \ No newline at end of file diff --git a/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/SharpDevelopUIOptions.xaml.cs b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/SharpDevelopUIOptions.xaml.cs new file mode 100644 index 0000000000..42ef53ac1a --- /dev/null +++ b/src/Main/Base/Project/Src/Gui/Dialogs/OptionPanels/IDEOptions/SharpDevelopUIOptions.xaml.cs @@ -0,0 +1,21 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +using System; +using System.Windows.Controls; +using ICSharpCode.Core; + +namespace ICSharpCode.SharpDevelop.Gui.OptionPanels +{ + public partial class SharpDevelopUIOptions : OptionPanel + { + public SharpDevelopUIOptions() + { + InitializeComponent(); + } + + public static bool ExpandReferences { + get { return PropertyService.Get("ExpandReferences", false); } + set { PropertyService.Set("ExpandReferences", value); } + } + } +} \ No newline at end of file diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/MemberNodes.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/MemberNodes.cs index 6fe62668eb..b90c86c7de 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/MemberNodes.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/MemberNodes.cs @@ -2,7 +2,6 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; using Mono.Cecil; -using Services.DecompilerService; namespace ICSharpCode.SharpDevelop.Project.InnerExpand { @@ -18,15 +17,6 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand Text = name; } - public override void ActivateItem() - { - string filePath = null; - DecompilerService.ReadMetadata(type, out filePath); - FileService.OpenFile(filePath); - - base.ActivateItem(); - } - public override object AcceptVisitor(ProjectBrowserTreeNodeVisitor visitor, object data) { return visitor.Visit(this, data); diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/TypeNodes.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/TypeNodes.cs index 1af6bf497f..4d348b1bd6 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/TypeNodes.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/InnerExpand/TypeNodes.cs @@ -3,7 +3,6 @@ using System; using System.Text; using Mono.Cecil; -using Services.DecompilerService; namespace ICSharpCode.SharpDevelop.Project.InnerExpand { @@ -61,15 +60,6 @@ namespace ICSharpCode.SharpDevelop.Project.InnerExpand } } - public override void ActivateItem() - { - string filePath = null; - DecompilerService.ReadMetadata(type, out filePath); - FileService.OpenFile(filePath); - - base.ActivateItem(); - } - public override object AcceptVisitor(ProjectBrowserTreeNodeVisitor visitor, object data) { return visitor.Visit(this, data); diff --git a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/ReferenceNode.cs b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/ReferenceNode.cs index 7d1a81c40e..ed8b085902 100644 --- a/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/ReferenceNode.cs +++ b/src/Main/Base/Project/Src/Gui/Pads/ProjectBrowser/TreeNodes/ReferenceNode.cs @@ -5,6 +5,8 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; + +using ICSharpCode.SharpDevelop.Gui.OptionPanels; using ICSharpCode.SharpDevelop.Project.InnerExpand; using Mono.Cecil; @@ -38,6 +40,9 @@ namespace ICSharpCode.SharpDevelop.Project public void ShowNamespaces(bool forceRefresh = false) { + if (!SharpDevelopUIOptions.ExpandReferences) + return; + if (namespaces.Count > 0 && !forceRefresh) return; diff --git a/src/Main/Base/Project/Src/Services/DecompilerService/DecompilerService.cs b/src/Main/Base/Project/Src/Services/DecompilerService/DecompilerService.cs index 6e1d208ede..8ccafc8077 100644 --- a/src/Main/Base/Project/Src/Services/DecompilerService/DecompilerService.cs +++ b/src/Main/Base/Project/Src/Services/DecompilerService/DecompilerService.cs @@ -2,156 +2,22 @@ // This code is distributed under the GNU LGPL (for details please see \doc\license.txt) using System; +using System.CodeDom; +using System.CodeDom.Compiler; +using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text; - +using System.Windows.Navigation; +using ICSharpCode.SharpDevelop.Dom; +using ICSharpCode.SharpDevelop.Gui; +using ICSharpCode.SharpDevelop.Project; using Mono.Cecil; -namespace Services.DecompilerService +namespace ICSharpCode.SharpDevelop { public static class DecompilerService { - public static void ReadMetadata(TypeDefinition type, out string filePath) - { - if (type == null) - { - filePath = null; - return; - } - - StringBuilder sb = new StringBuilder(); - - sb.Append("using System;"); - - sb.Append(Environment.NewLine); - sb.Append(Environment.NewLine); - - sb.Append("namespace " + type.Namespace); - sb.Append(Environment.NewLine); - sb.Append("{"); - sb.Append(Environment.NewLine); - - // attributes - if (type.HasCustomAttributes) { - foreach (var attr in type.CustomAttributes) { - sb.Append("\t["); - sb.Append(attr.AttributeType.Name); - sb.Append("]"); - sb.Append(Environment.NewLine); - } - } - - // main definition - sb.Append("\tpublic "); - - if (type.IsValueType) - sb.Append("struct "); - else - if (type.IsEnum) - sb.Append("enum "); - else { - if (type.IsClass) { - if (type.IsAbstract) - sb.Append("abstract "); - if (type.IsSealed) - sb.Append("sealed "); - sb.Append("class "); - } - - if (type.IsInterface) - sb.Append("interface "); - } - - sb.Append(type.Name); - - // inheritance - if (type.BaseType != null) { - sb.Append(" : "); - sb.Append(type.BaseType.Name); - } - - sb.Append(Environment.NewLine); - sb.Append("\t{"); - sb.Append(Environment.NewLine); - - if (type.HasEvents) { - sb.Append("\t");sb.Append("\t");sb.Append("// Public Events"); - sb.Append(Environment.NewLine); - - foreach (var ev in type.Events) { - sb.Append("\t");sb.Append("\t"); - sb.Append("public event ");sb.Append(ev.EventType.FullName);sb.Append(" ");sb.Append(ev.Name); - sb.Append(Environment.NewLine); - sb.Append(Environment.NewLine); - } - } - - if (type.HasProperties) { - sb.Append("\t");sb.Append("\t");sb.Append("// Public Properties"); - sb.Append(Environment.NewLine); - - foreach (var property in type.Properties) { - - if (property.GetMethod != null && !property.GetMethod.IsPublic && - property.SetMethod != null && !property.SetMethod.IsPublic) - continue; - - sb.Append("\t");sb.Append("\t"); - sb.Append("public ");sb.Append(property.PropertyType.FullName);sb.Append(" ");sb.Append(property.Name); - sb.Append(" {"); - if (property.GetMethod != null && property.GetMethod.IsPublic) - sb.Append(" get;"); - if (property.SetMethod != null && property.SetMethod.IsPublic) - sb.Append(" set;"); - sb.Append(" }"); - sb.Append(Environment.NewLine); - sb.Append(Environment.NewLine); - } - } - - if (type.HasMethods) { - sb.Append("\t");sb.Append("\t");sb.Append("// Public Methods"); - sb.Append(Environment.NewLine); - - foreach (var method in type.Methods) { - - if (method.IsPrivate) continue; - - if (method.Name.StartsWith("get_") || method.Name.StartsWith("set_")) continue; - - sb.Append("\t");sb.Append("\t"); - sb.Append("public "); - if (method.IsStatic) - sb.Append("static "); - - if (!method.IsConstructor) { - sb.Append(method.ReturnType.FullName);sb.Append(" ");sb.Append(method.Name); - } else { - sb.Append(type.Name); - } - - sb.Append(GetParameters(method)); - - sb.Append(";"); - sb.Append(Environment.NewLine); - sb.Append(Environment.NewLine); - } - } - - sb.Append("\t}"); - sb.Append(Environment.NewLine); - sb.Append("}"); - - // temp file - string tempFolder = Path.GetTempPath(); - string file = type.Name + ".temp.cs"; - filePath = Path.Combine(tempFolder, file); - - using (StreamWriter sr = new StreamWriter(filePath)) { - sr.Write(sb.ToString()); - } - } - public static string GetParameters(MethodDefinition method) { StringBuilder sb = new StringBuilder(); @@ -182,5 +48,282 @@ namespace Services.DecompilerService return sb.ToString(); } + + public static void ReadMetadata(IClass c, out string filePath) + { + CodeCompileUnit compileUnit = new CodeCompileUnit(); + + // add namespace + CodeNamespace generatedNamespace = new CodeNamespace(c.Namespace); + generatedNamespace.Imports.Add(new CodeNamespaceImport("System")); + compileUnit.Namespaces.Add(generatedNamespace); + + // add type + var targetClass = new CodeTypeDeclaration(c.Name); + + // write attributes + AddAttributes(c, targetClass); + + // write class definition + if (c.IsPublic) targetClass.TypeAttributes |= System.Reflection.TypeAttributes.Public; + if (c.IsSealed) targetClass.TypeAttributes |= System.Reflection.TypeAttributes.Sealed; + // static class limitation - c.IsStatic: https://connect.microsoft.com/VisualStudio/feedback/details/93653/codedom-unable-to-generate-static-events-and-classes + targetClass.IsPartial = c.IsPartial; + + switch (c.ClassType) { + case ClassType.Class: + targetClass.IsClass = true; + break; + case ClassType.Enum: + targetClass.IsEnum = true; + break; + case ClassType.Interface: + targetClass.IsInterface = true; + break; + case ClassType.Struct: + targetClass.IsStruct = true; + break; + } + + // generics + foreach (var typeParameter in c.TypeParameters) { + var tp = new CodeTypeParameter(typeParameter.Name); + foreach (var con in typeParameter.Constraints) { + tp.Constraints.Add(con.Name); + } + targetClass.TypeParameters.Add(tp); + } + + // base types + foreach (var basetype in c.BaseTypes) { + if (basetype.FullyQualifiedName.Equals("System.Object", StringComparison.OrdinalIgnoreCase)) + continue; + var baseType = AddGenericBaseTypes(basetype); + targetClass.BaseTypes.Add(baseType); + } + + // field members + foreach (var f in c.Fields) { + if (!f.IsPublic && !f.IsProtected) continue; + + CodeMemberField field = new CodeMemberField() { Name = f.Name, + Attributes = MemberAttributes.Public }; + AddDefinition(f, field); + AddAttributes(f, field); + AddDocumentation(f, field); + + field.Type = new CodeTypeReference(f.ReturnType.FullyQualifiedName); + targetClass.Members.Add(field); + } + + // event members + foreach (var e in c.Events) { + if (!e.IsPublic && !e.IsProtected) continue; + CodeMemberEvent ev = new CodeMemberEvent() { Name = e.Name, + Attributes = MemberAttributes.Public, + Type = new CodeTypeReference(e.ReturnType.FullyQualifiedName) }; + AddDefinition(e, ev); + AddDocumentation(e, ev); + + targetClass.Members.Add(ev); + } + + // properties + foreach (var property in c.Properties) { + if (!property.IsPublic && !property.IsProtected) continue; + CodeMemberProperty p = new CodeMemberProperty() { + Name = property.Name, + Attributes = MemberAttributes.Public, + Type = new CodeTypeReference(property.ReturnType.FullyQualifiedName), + HasGet = property.CanGet, + HasSet = property.CanSet + }; + + AddAttributes(property, p); + AddDefinition(property, p); + AddDocumentation(property, p); + + if (property.IsIndexer) { + p.Parameters.Add(new CodeParameterDeclarationExpression("System.Int32", "index")); + } + targetClass.Members.Add(p); + } + + // methods and constructors + foreach (var method in c.Methods) { + if (!method.IsPublic && !method.IsProtected) continue; + + if (method.IsConstructor) { + CodeConstructor constructor = new CodeConstructor() { Name = c.Name, + Attributes = MemberAttributes.Public }; + AddAttributes(method, constructor); + AddDefinition(method, constructor); + AddParameters(method, constructor); + AddDocumentation(method, constructor); + + targetClass.Members.Add(constructor); + } else { + CodeMemberMethod m = new CodeMemberMethod() { + Name = method.Name, + Attributes = MemberAttributes.Public, + ReturnType = new CodeTypeReference(method.ReturnType.FullyQualifiedName), + }; + + AddAttributes(method, m); + AddDefinition(method, m); + AddParameters(method, m); + AddDocumentation(method, m); + + targetClass.Members.Add(m); + } + } + + // delegates + foreach (var inner in c.InnerClasses) { + if (inner.ClassType == ClassType.Delegate) { + IMethod invoker = inner.Methods.Where(method => method.Name == "Invoke").FirstOrDefault(); + CodeTypeDelegate del = new CodeTypeDelegate(inner.Name) { + Attributes = MemberAttributes.Public, + ReturnType = new CodeTypeReference(invoker.ReturnType.FullyQualifiedName) + }; + + AddDocumentation(invoker, del); + + foreach (var p in invoker.Parameters) + del.Parameters.Add(new CodeParameterDeclarationExpression(p.ReturnType.FullyQualifiedName, p.Name)); + + targetClass.Members.Add(del); + } + } + + // add class + generatedNamespace.Types.Add(targetClass); + filePath = WriteTempFile(c.Name, compileUnit); + } + + static CodeTypeReference AddGenericBaseTypes(IReturnType basetype) + { + string type = basetype.FullyQualifiedName; + CodeTypeReference baseType = new CodeTypeReference(type); + if (basetype.IsConstructedReturnType) + { + var constructed = basetype as ConstructedReturnType; + int i = 0; + foreach (var typearg in constructed.TypeArguments) { + baseType.TypeArguments.Add(new CodeTypeReference(typearg.Name, CodeTypeReferenceOptions.GenericTypeParameter)); + + if (typearg is ConstructedReturnType) { + CodeTypeReference baseType1 = new CodeTypeReference(typearg.FullyQualifiedName); + baseType1.TypeArguments.Add(AddGenericBaseTypes(typearg)); + baseType.TypeArguments[i].TypeArguments.Add(baseType1); + } + ++i; + } + } + + return baseType; + } + + static void AddParameters(IMethod method, CodeMemberMethod m) + { + foreach (var p in method.Parameters) { + string returnType = p.ReturnType.FullyQualifiedName; + + var par = new CodeParameterDeclarationExpression(returnType, p.Name); + + if (p.ReturnType.IsConstructedReturnType) + { + CodeTypeReference baseType = new CodeTypeReference(returnType); + var c = p.ReturnType as ConstructedReturnType; + foreach (var typearg in c.TypeArguments) { + baseType.TypeArguments.Add(new CodeTypeReference(typearg.Name, CodeTypeReferenceOptions.GenericTypeParameter)); + } + + par.Type = baseType; + } + + if (p.IsRef) + par.Direction = FieldDirection.Ref; + if (p.IsOut) + par.Direction = FieldDirection.Out; + if (p.IsParams) + par.CustomAttributes.Add(new CodeAttributeDeclaration(new CodeTypeReference(typeof(System.ParamArrayAttribute)))); + // TODO: if (p.IsOptional) + + m.Parameters.Add(par); + } + } + + static void AddDocumentation(IEntity entity, CodeTypeMember member) + { + if (string.IsNullOrEmpty(entity.Documentation) || string.IsNullOrEmpty(entity.Documentation.Trim())) + return; + + member.Comments.Add(new CodeCommentStatement(entity.Documentation.Replace(" ", string.Empty), true)); + } + + static void AddDefinition(IEntity entity, CodeTypeMember member) + { + if (entity.IsProtected) + member.Attributes = MemberAttributes.Family; + + if (entity.IsStatic) + member.Attributes |= MemberAttributes.Static; + if (entity.IsNew) + member.Attributes |= MemberAttributes.New; + if (entity.IsOverride) + member.Attributes |= MemberAttributes.Override; + if (entity.IsAbstract) + member.Attributes |= MemberAttributes.Abstract; + if (entity.IsVirtual) + member.Attributes |= MemberAttributes.Final; + if (entity.IsConst) + member.Attributes |= MemberAttributes.Const; + } + + static void AddAttributes(IEntity entity, CodeTypeMember member) + { + // write attributes + foreach (var attr in entity.Attributes) { + + List list = new List(); + for (int i = 0; i < attr.PositionalArguments.Count; i++) { + if (!(attr.PositionalArguments[i] is IReturnType)) + list.Add(new CodeAttributeArgument(new CodePrimitiveExpression(attr.PositionalArguments[i]))); + } + + if (list.Count == 0) { + member.CustomAttributes.Add( + new CodeAttributeDeclaration(attr.AttributeType.FullyQualifiedName)); + } else { + member.CustomAttributes.Add( + new CodeAttributeDeclaration(attr.AttributeType.FullyQualifiedName, list.ToArray())); + } + } + } + + static string WriteTempFile(string fileName, CodeCompileUnit compileUnit) + { + // temp file + string tempFolder = Path.GetTempPath(); + string file = fileName + ".temp.cs"; + string filePath = Path.Combine(tempFolder, file); + + if (File.Exists(filePath)) + File.Delete(filePath); + + // write file + using (var sw = new StreamWriter(filePath, false)) + { + ProjectService + .CurrentProject + .LanguageProperties + .CodeDomProvider.GenerateCodeFromCompileUnit( + compileUnit, + sw, + new CodeGeneratorOptions()); + } + return filePath; + } } -} +} \ No newline at end of file