//FIXME: make this async so it doesn't block the UI void DetectXcodeChanges() { NSObjectProjectInfo pinfo = null; var typeSyncJobs = new List <SyncObjcBackJob> (); foreach (var f in trackedFiles.ToList()) { var xcwrite = File.GetLastWriteTime(f.Key); if (xcwrite <= f.Value) { continue; } if (f.Key.EndsWith(".h")) { var job = ReadTypeFromXcode(f.Key, ref pinfo); if (job != null) { typeSyncJobs.Add(job); } } //TODO: copy changed xibs back into the project } if (typeSyncJobs.Count > 0) { UpdateCliTypes(pinfo, typeSyncJobs); } }
//FIXME: error handling void UpdateCliTypes(NSObjectProjectInfo pinfo, List <SyncObjcBackJob> typeSyncJobs) { var provider = System.CodeDom.Compiler.CodeDomProvider.CreateProvider("C#"); var options = new System.CodeDom.Compiler.CodeGeneratorOptions(); var writer = MonoDevelop.DesignerSupport.CodeBehindWriter.CreateForProject( new MonoDevelop.Core.ProgressMonitoring.NullProgressMonitor(), dnp); //group all the types by designer file var designerFile = new Dictionary <string, List <NSObjectTypeInfo> > (); foreach (var job in typeSyncJobs) { List <NSObjectTypeInfo> types; if (!designerFile.TryGetValue(job.DesignerFile, out types)) { designerFile[job.DesignerFile] = types = new List <NSObjectTypeInfo> (); } types.Add(job.Type); } //add in other designer types that exist in the designer files foreach (var ut in pinfo.GetTypes()) { if (!ut.IsUserType) { continue; } var df = ut.GetDesignerFile(); List <NSObjectTypeInfo> types; if (df != null && designerFile.TryGetValue(df, out types)) { if (!types.Any(t => t.ObjCName == ut.ObjCName)) { types.Add(ut); } } } updatingProjectFiles = true; try { foreach (var df in designerFile) { var ccu = GenerateCompileUnit(provider, options, df.Key, df.Value); writer.Write(ccu, df.Key); } writer.WriteOpenFiles(); foreach (var job in typeSyncJobs) { pinfo.InsertUpdatedType(job.Type); trackedFiles[job.HFile] = File.GetLastWriteTime(job.HFile); } } finally { updatingProjectFiles = false; } }
//FIXME: report errors SyncObjcBackJob ReadTypeFromXcode(FilePath hFile, ref NSObjectProjectInfo pinfo) { var parsed = NSObjectInfoService.ParseHeader(hFile); if (pinfo == null) { pinfo = NSObjectInfoService.GetProjectInfo(dnp); } var objcType = pinfo.GetType(hFile.FileNameWithoutExtension); if (objcType == null) { Console.WriteLine("Missing objc type {0}", hFile.FileNameWithoutExtension); return(null); } if (parsed.ObjCName != objcType.ObjCName) { Console.WriteLine("Parsed type name {0} does not match original {1}", parsed.ObjCName, objcType.ObjCName); return(null); } if (!objcType.IsUserType) { Console.WriteLine("Parsed type {0} is not a user type", objcType); return(null); } //FIXME: fix data loss when there are multiple designer types in one designer file, like MT templates var designerFile = objcType.GetDesignerFile(); //FIXME: add a designer file if there are any designer outlets and actions if (designerFile == null) { return(null); } //FIXME: detect unresolved types parsed.MergeCliInfo(objcType); pinfo.ResolveTypes(parsed); return(new SyncObjcBackJob() { HFile = hFile, DesignerFile = designerFile, Type = parsed, }); }