public EditMigrationsWindow(EditMigrationsViewModel viewModel) { InitializeComponent(); DataContext = viewModel; }
/// <summary> /// Called when the Generate Migrations command is run /// </summary> /// <param name="sender">The sender.</param> /// <param name="e">The <see cref="EventArgs" /> instance containing the event data.</param> private void MigrationsCallback(object sender, EventArgs e) { IntPtr hierarchyPtr, selectionContainerPtr; uint projectItemId; IVsMultiItemSelect mis; IVsMonitorSelection monitorSelection = (IVsMonitorSelection)GetGlobalService(typeof(SVsShellMonitorSelection)); monitorSelection.GetCurrentSelection(out hierarchyPtr, out projectItemId, out mis, out selectionContainerPtr); IVsHierarchy hierarchy = Marshal.GetTypedObjectForIUnknown(hierarchyPtr, typeof(IVsHierarchy)) as IVsHierarchy; if (hierarchy == null) { FireError("F**k knows why but it is broken, sorry"); return; } object projObj; hierarchy.GetProperty(projectItemId, (int)__VSHPROPID.VSHPROPID_ExtObject, out projObj); ProjectItem projItem = projObj as ProjectItem; if (projItem == null) { FireError("The item you have selected is not playing nicely. Apologies"); return; } var project = projItem.ContainingProject; var migrations = new List<Migration>(); var allClasses = GetProjectItems(project.ProjectItems).Where(v => v.Name.Contains(".cs")); // check for .cs extension on each, foreach (var c in allClasses) { var eles = c.FileCodeModel; if (eles == null) continue; foreach (var ele in eles.CodeElements) { if (ele is EnvDTE.CodeNamespace) { var ns = ele as EnvDTE.CodeNamespace; // run through classes foreach (var property in ns.Members) { var member = property as CodeType; if (member == null) continue; // check all classes they derive from to see if any of them are migration classes, add them if so migrations.AddRange(from object b in member.Bases select b as CodeClass into bClass where bClass != null && bClass.Name == "DataMigrationImpl" select new Migration(member)); } } } } var model = projItem.FileCodeModel; if (model == null) { FireError("This class you have selected is weird and broken. Choose another one"); return; } var elements = model.CodeElements; var classes = new List<Model>(); // run through elements (they are done in a hierachy, so first we have using statements and the namespace) to find namespace foreach (var ele in elements) { if (ele is EnvDTE.CodeNamespace) { var ns = ele as EnvDTE.CodeNamespace; // run through classes foreach (var c in ns.Members) { var member = c as CodeType; if (member == null) continue; classes.Add(new Model() { Class = member, Name = member.Name }); } } } if (!classes.Any()) { FireError("No classes in the selected file!"); return; } var vm = new MigrationsViewModel(migrations, classes); var window = new MigrationsWindow(vm); var success = window.ShowDialog(); if (!success.GetValueOrDefault()) { return; } CodeType selectedClass = vm.SelectedClass.Class; if (selectedClass == null) { FireError("No class to generate migrations from!"); return; } // name of class var modelName = selectedClass.Name; // get code class var cc = selectedClass as CodeClass; // get all members of the class var members = cc.Members; bool contentPartRecord = false; foreach (var d in cc.Bases) { var dClass = d as CodeClass; if (dClass != null && dClass.Name == "ContentPartRecord") { contentPartRecord = true; } } var props = new List<MigrationItem>(); //iterate through to find properties foreach (var member in members) { var prop = member as CodeProperty; if (prop == null) continue; if (prop.Access != vsCMAccess.vsCMAccessPublic) continue; var type = prop.Type; var name = prop.Name; var fullName = type.AsFullName; var nullable = fullName.Contains(".Nullable<"); var sType = type.AsString.Replace("?", ""); var sName = name; // if model, add _Id for nhibernate if (fullName.Contains(".Models.") || fullName.Contains(".Records.")) { sName += "_Id"; sType = "int"; } var mi = new MigrationItem() { Name = name, SuggestedName = sName, Type = fullName, SuggestedType = sType, Nullable = nullable, Create = true, }; props.Add(mi); } var createMigrationFile = !String.IsNullOrEmpty(vm.NewMigration); if (!createMigrationFile) { if (vm.SelectedMigration == null) { FireError("Select a migration or choose a new one!"); return; } var mig = vm.SelectedMigration.CodeType; string path = (string)mig.ProjectItem.Properties.Item("FullPath").Value; string text = File.ReadAllText(path); var noTimesCreated = Regex.Matches(text, @"SchemaBuilder.Create\(""" + modelName + @""",").Count; var noTimesDropped = Regex.Matches(text, @"SchemaBuilder.DropTable\(""" + modelName + @"""\)").Count; bool created = noTimesCreated > noTimesDropped; if (noTimesCreated == 1 && noTimesDropped == 0) { foreach (var p in props.Where(p => text.Contains(p.Name))) { p.Create = false; } } if (created) { foreach (var p in props) { var name = p.Name; var noDrops = Regex.Matches(text, @".DropColumn\(""" + name).Count; var noOccurences = Regex.Matches(text, name).Count; if ((noOccurences - noDrops) > noDrops) p.Create = false; } } } // if a collection ignore foreach (var p in props) if (p.Type.Contains("System.Collection")) p.Create = false; var bmvm = new BuildMigrationsViewModel(props); var bmWindow = new BuildMigrationsWindow(bmvm); var bmSuccess = bmWindow.ShowDialog(); if (!bmSuccess.GetValueOrDefault()) { return; } var sb = new StringBuilder(); var createTable = "SchemaBuilder.CreateTable(\"" + modelName + "\", t => t"; sb.AppendLine(createTable); if (contentPartRecord) sb.AppendLine("\t.ContentPartRecord()"); foreach (var p in bmvm.Migrations.Where(z => z.Create)) { sb.AppendLine("\t" + ParseMigrationItem(p)); } sb.AppendLine(");"); var editViewModel = new EditMigrationsViewModel() { Migrations = sb.ToString() }; var editWindow = new EditMigrationsWindow(editViewModel); var emSuccess = editWindow.ShowDialog(); if (!emSuccess.GetValueOrDefault()) { return; } var migrationsCode = new StringBuilder(); using (StringReader reader = new StringReader(editViewModel.Migrations)) { string line; while ((line = reader.ReadLine()) != null) { migrationsCode.AppendLine(line.Insert(0, "\t\t\t")); } } if (!createMigrationFile) EditMigrations(vm.SelectedMigration.CodeType, migrationsCode.ToString()); else { var templates = Path.Combine(Path.GetDirectoryName(GetType().Assembly.Location), "OrchardTemplates"); var newMigration = project.ProjectItems.AddFromFileCopy(templates + "\\Migrationsxxx.cs"); Insert(newMigration.Properties.Item("FullPath").Value.ToString(), new[] { new KeyValuePair<string, string>("$module$", project.Name), new KeyValuePair<string, string>("$migrationName$", vm.NewMigration), new KeyValuePair<string, string>("$code$", migrationsCode.ToString()) }); var cs = vm.NewMigration.EndsWith(".cs") ? "" : ".cs"; newMigration.Name = vm.NewMigration + cs; } }