public void Generate(string dest) { if (dest == null) { throw new ArgumentNullException(nameof(dest)); } Directory.CreateDirectory(dest); this.SourceFiles = new List <string>(); foreach (var eocObjectClass in EocObjectClassMap.Values) { eocObjectClass.ParseCode(); } foreach (var eocStaticClass in EocStaticClassMap.Values) { eocStaticClass.ParseCode(); } foreach (var eocObjectClass in EocObjectClassMap.Values) { eocObjectClass.Optimize(); } foreach (var eocStaticClass in EocStaticClassMap.Values) { eocStaticClass.Optimize(); } //分析依赖图 foreach (var x in EocConstantMap.Values) { x?.AnalyzeDependencies(DependencyGraph); } foreach (var x in EocStructMap.Values) { x.AnalyzeDependencies(DependencyGraph); } foreach (var x in EocGlobalVariableMap.Values) { x.AnalyzeDependencies(DependencyGraph); } foreach (var x in EocDllDeclareMap.Values) { x.AnalyzeDependencies(DependencyGraph); } foreach (var x in EocObjectClassMap.Values) { x.AnalyzeDependencies(DependencyGraph); } foreach (var x in EocStaticClassMap.Values) { x.AnalyzeDependencies(DependencyGraph); } if (EocDllExportMap != null) { foreach (var x in EocDllExportMap.Values) { x.AnalyzeDependencies(DependencyGraph); } } if (Source.InitEcSectionInfo != null) { DependencyGraph.AddVerticesAndEdgeRange(Source.InitEcSectionInfo.InitMethod.Select(x => new Edge <string>("[Root]", GetCppMethodName(x)))); } if (Source.Code.MainMethod != 0) { DependencyGraph.AddVerticesAndEdge(new Edge <string>("[Root]", GetCppMethodName(Source.Code.MainMethod))); } else { DependencyGraph.AddVerticesAndEdge(new Edge <string>("[Root]", "e::user::cmd::EocUser__启动子程序")); } //生成依赖列表 this.Dependencies = new HashSet <string>(); GraphUtils.AnalyzeDependencies(DependencyGraph, "[Root]", this.Dependencies); //删除未使用代码 EocConstantMap = EocConstantMap.FilterSortedDictionary(x => Dependencies.Contains(x.Value?.RefId)); EocStructMap = EocStructMap.FilterSortedDictionary(x => Dependencies.Contains(x.Value.RefId)); EocGlobalVariableMap = EocGlobalVariableMap.FilterSortedDictionary(x => Dependencies.Contains(x.Value.RefId)); EocDllDeclareMap = EocDllDeclareMap.FilterSortedDictionary(x => Dependencies.Contains(x.Value.RefId)); EocObjectClassMap = EocObjectClassMap.FilterSortedDictionary(x => Dependencies.Contains(x.Value.RefId)); foreach (var x in EocObjectClassMap.Values) { x.RemoveUnusedCode(Dependencies); } foreach (var x in EocStaticClassMap.Values) { x.RemoveUnusedCode(Dependencies); } EocStaticClassMap = EocStaticClassMap.FilterSortedDictionary(x => x.Value.Method.Count != 0); //依赖信息 File.WriteAllText(Path.Combine(dest, "Dependencies.txt"), string.Join("\r\n", this.Dependencies), Encoding.UTF8); File.WriteAllBytes(Path.Combine(dest, "DependencyGraph.gv"), Encoding.UTF8.GetBytes(GraphUtils.WriteGraphvizScript(DependencyGraph, "DependencyGraph"))); string fileName; //常量 using (var writer = NewCodeFileByCppName(dest, ConstantNamespace, "h")) EocConstant.Define(this, writer, EocConstantMap); using (var writer = NewCodeFileByCppName(dest, ConstantNamespace, "cpp")) EocConstant.Implement(this, writer, EocConstantMap); //声明自定义数据类型(结构/对象类) using (var writer = NewCodeFileByCppName(dest, TypeNamespace, "h")) { DefineAllTypes(writer); } //实现 对象类 foreach (var item in EocObjectClassMap.Values) { using (var writer = NewCodeFileByCppName(dest, item.CppName, "cpp")) item.ImplementRawObjectClass(writer); } //静态类 foreach (var item in EocStaticClassMap.Values) { using (var writer = NewCodeFileByCppName(dest, item.CppName, "h")) item.Define(writer); using (var writer = NewCodeFileByCppName(dest, item.CppName, "cpp")) item.Implement(writer); } //全局变量 using (var writer = NewCodeFileByCppName(dest, GlobalNamespace, "h")) EocGlobalVariable.Define(this, writer, EocGlobalVariableMap); using (var writer = NewCodeFileByCppName(dest, GlobalNamespace, "cpp")) EocGlobalVariable.Implement(this, writer, EocGlobalVariableMap); //DLL using (var writer = NewCodeFileByCppName(dest, DllNamespace, "h")) EocDll.Define(this, writer, EocDllDeclareMap); using (var writer = NewCodeFileByCppName(dest, DllNamespace, "cpp")) EocDll.Implement(this, writer, EocDllDeclareMap); //预编译头 using (var writer = NewCodeFileByCppName(dest, "stdafx", "h")) MakeStandardHeader(writer); //程序入口 using (var writer = NewCodeFileByCppName(dest, "entry", "cpp")) MakeProgramEntry(writer); //Dll导出 if (EocDllExportMap != null) { using (var writer = NewCodeFileByCppName(dest, "dll_export", "cpp")) EocDllExport.Implement(this, writer, EocDllExportMap); fileName = Path.Combine(dest, "dll_export.def"); using (var writer = new StreamWriter(File.Create(fileName), Encoding.UTF8)) { EocDllExport.MakeDef(this, writer, EocDllExportMap); } } //CMake项目配置文件 fileName = Path.Combine(dest, "CMakeLists.txt"); using (var writer = new StreamWriter(File.Create(fileName), Encoding.UTF8)) MakeCMakeLists(writer); //VSCode配置文件 fileName = Path.Combine(dest, ".vscode", "settings.json"); Directory.CreateDirectory(Path.GetDirectoryName(fileName)); using (var writer = new StreamWriter(File.Create(fileName), Encoding.UTF8)) MakeVSCodeSettings(writer); }
public ProjectConverter(EProjectFile.EProjectFile source, EocProjectType projectType = EocProjectType.Console, string projectNamespace = "e::user", ILoggerWithContext logger = null) { this.Logger = logger ?? new NullLoggerWithContext(); if (source == null) { throw new ArgumentNullException(nameof(source)); } this.IdToNameMap = new IdToNameMap(source.Code, source.Resource, source.LosableSection); this.MethodIdMap = source.Code.Methods.ToDictionary(x => x.Id); this.MethodIdToClassMap = new Dictionary <int, ClassInfo>(); foreach (var item in source.Code.Classes) { Array.ForEach(item.Method, x => MethodIdToClassMap.Add(x, item)); } projectNamespace = projectNamespace ?? "e::user"; this.ProjectNamespace = projectNamespace; this.TypeNamespace = projectNamespace + "::type"; this.CmdNamespace = projectNamespace + "::cmd"; this.DllNamespace = projectNamespace + "::dll"; this.ConstantNamespace = projectNamespace + "::constant"; this.GlobalNamespace = projectNamespace + "::global"; this.Source = source; this.Libs = source.Code.Libraries.Select( x => { try { return(LibInfo.Load(x)); } catch (Exception ex) { Logger.Warn("加载fne信息失败,请检查易语言环境,支持库:{0},异常信息:{1}", x.Name, ex); return(null); } }).ToArray(); this.EocLibs = source.Code.Libraries.Select( x => { try { return(EocLibInfo.Load(x)); } catch (Exception ex) { Logger.Warn("加载eoc库信息失败,请检查eoc环境,支持库:{0},异常信息:{1}", x.Name, ex); return(null); } }).ToArray(); LibCmdToDeclaringTypeMap = Libs.Select(lib => { var r = new Dictionary <int, int>(); for (int i = 0; i < lib?.DataType?.Length; i++) { if (lib.DataType[i].Method != null) { Array.ForEach(lib.DataType[i].Method, x => r[x] = i); } } return(r); }).ToList().AsReadOnly(); this.EocHelperLibId = Array.FindIndex(source.Code.Libraries, x => x.FileName.ToLower() == "EocHelper".ToLower()); this.DataTypeId_IntPtr = this.EocHelperLibId == -1 ? -1 : EplSystemId.MakeLibDataTypeId((short)this.EocHelperLibId, 0); this.ProjectType = projectType; this.EocConstantMap = EocConstant.Translate(this, Source.Resource.Constants); this.EocStructMap = EocStruct.Translate(this, Source.Code.Structs); this.EocGlobalVariableMap = EocGlobalVariable.Translate(this, Source.Code.GlobalVariables); this.EocDllDeclareMap = EocDll.Translate(this, Source.Code.DllDeclares); this.EocObjectClassMap = EocObjectClass.Translate(this, Source.Code.Classes.Where(x => EplSystemId.GetType(x.Id) == EplSystemId.Type_Class)); this.EocStaticClassMap = EocStaticClass.Translate(this, Source.Code.Classes.Where(x => EplSystemId.GetType(x.Id) != EplSystemId.Type_Class)); this.EocMemberMap = this.EocObjectClassMap.Values.SelectMany(x => x.MemberInfoMap) .Concat(this.EocStaticClassMap.Values.SelectMany(x => x.MemberInfoMap)) .Concat(this.EocStructMap.Values.SelectMany(x => x.MemberInfoMap)) .ToSortedDictionary(); this.EocMethodMap = this.EocObjectClassMap.Values.SelectMany(x => x.Method) .Concat(this.EocStaticClassMap.Values.SelectMany(x => x.Method)) .ToSortedDictionary(); if (ProjectType == EocProjectType.Dll) { this.EocDllExportMap = EocDllExport.Translate(this, Source.Code.Methods.Where(x => x.IsStatic && x.Public).Select(x => x.Id)); } }