public async Task WriteDto_ExistingSolution_StudentDTORewriteShouldReuseBaseMapper()
        {
            var msWorkspace = MSBuildWorkspace.Create();
            var solution    = msWorkspace.OpenSolutionAsync(this.TestSolution.FullName).Result;

            solution = solution.GetIsolatedSolution();

            var roleDoc = solution.Projects
                          .SelectMany(p => p.Documents)
                          .Where(p => p.Name == "Role.cs")
                          .FirstOrDefault();

            var existingDto = solution.Projects
                              .SelectMany(p => p.Documents)
                              .Where(p => p.Name == "RoleDTO.cs")
                              .FirstOrDefault();

            var dtoLocation = solution.GetMostLikelyDtoLocation();
            var vm          = await PropertySelectorViewModel.Create(roleDoc, "RoleDTO", dtoLocation, existingDto);

            Assert.IsTrue(vm.EntityModel.ReuseBaseEntityMapper);
        }
Beispiel #2
0
        public async Task WriteDto_ExistingSolution_ScenarioCustomDtoName()
        {
            var msWorkspace = MSBuildWorkspace.Create();
            var solution    = msWorkspace.OpenSolutionAsync(this.TestSolution.FullName).Result;

            solution = solution.GetIsolatedSolution();

            var personClassDoc = solution.Projects
                                 .SelectMany(p => p.Documents)
                                 .Where(p => p.Name == "Person.cs")
                                 .FirstOrDefault();

            var dtoLocation = solution.GetMostLikelyDtoLocation();
            var vm          = await PropertySelectorViewModel.Create(personClassDoc, "PersonCustomDTO", dtoLocation);

            var modifiedSolution = await solution.WriteDto(dtoLocation, vm.GetMetadata(), true, false);

            Assert.IsNotNull(modifiedSolution);

            var changeSet = modifiedSolution.GetChanges(solution);

            Assert.AreEqual(1, changeSet.GetProjectChanges().Count());

            var projectChanges = changeSet.GetProjectChanges().Single();

            Assert.AreEqual(2, projectChanges.GetAddedDocuments().Count());

            var addedDocs = projectChanges.GetAddedDocuments()
                            .Select(p => modifiedSolution.GetProject(p.ProjectId).GetDocument(p))
                            .ToList();

            Assert.IsTrue(addedDocs.Any(p => p.Name == "PersonCustomDTO.cs"));
            Assert.IsTrue(addedDocs.Any(p => p.Name == "MapperBase.cs"));

            var personDtoSource = addedDocs.Where(p => p.Name == "PersonCustomDTO.cs").Single().GetTextAsync().Result.ToString();

            Assert.IsFalse(personDtoSource.Contains("PersonDTO"));
        }
        /// <summary>
        /// This function is the callback used to execute the command when the menu item is clicked.
        /// See the constructor to see how the menu item is associated with this function using
        /// OleMenuCommandService service and MenuCommand class.
        /// </summary>
        /// <param name="sender">Event sender.</param>
        /// <param name="e">Event args.</param>
        private async void MenuItemCallback(object sender, EventArgs e)
        {
            try
            {
                var componentModel = (IComponentModel)Microsoft.VisualStudio.Shell.Package.GetGlobalService(typeof(SComponentModel));
                var workspace      = componentModel.GetService <VisualStudioWorkspace>();

                var selectedItem = this.GetSelectedSolutionExplorerItem();
                Microsoft.CodeAnalysis.Document doc = null;

                if (selectedItem != null && selectedItem.Name != null && !selectedItem.Name.EndsWith(".cs"))
                {
                    VsShellUtilities.ShowMessageBox(this.package, "Generate DTO action can only be invoked on CSharp files.", "Error",
                                                    OLEMSGICON.OLEMSGICON_WARNING,
                                                    OLEMSGBUTTON.OLEMSGBUTTON_OK,
                                                    OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);

                    return;
                }

                if (selectedItem?.Document != null)
                {
                    doc = workspace.CurrentSolution.GetDocumentByFilePath(selectedItem.Document.FullName);
                }
                else if (selectedItem != null)
                {
                    var file        = selectedItem.Name;
                    var projectName = selectedItem.ContainingProject.Name;

                    var docs = workspace.CurrentSolution.Projects
                               .Where(p => p.Name == projectName)
                               .SelectMany(p => p.Documents)
                               .Where(d => d.Name == file)
                               .ToList();

                    if (docs.Count == 0)
                    {
                        VsShellUtilities.ShowMessageBox(this.package, "Shitty exception - cannot get current selected solution item :/// . Try opening desired document, and then activating this command.", "Error",
                                                        OLEMSGICON.OLEMSGICON_WARNING,
                                                        OLEMSGBUTTON.OLEMSGBUTTON_OK,
                                                        OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
                    }

                    if (docs.Count > 1)
                    {
                        VsShellUtilities.ShowMessageBox(this.package, "Multiple documents with same name exist - cannot get current selected solution item. Try opening desired document, and then activating this command.", "Error",
                                                        OLEMSGICON.OLEMSGICON_WARNING,
                                                        OLEMSGBUTTON.OLEMSGBUTTON_OK,
                                                        OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
                    }

                    doc = docs.FirstOrDefault();
                }
                else
                {
                    VsShellUtilities.ShowMessageBox(this.package, "Shitty exception - cannot get current selected solution item :/// . Try opening desired document, and then activating this command.", "Error",
                                                    OLEMSGICON.OLEMSGICON_WARNING,
                                                    OLEMSGBUTTON.OLEMSGBUTTON_OK,
                                                    OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);

                    return;
                }
                var possibleProjects = doc.GetPossibleProjects();

                var vmBasic = BasicOptionsViewModel.Create(possibleProjects, doc.Name.Replace(".cs", ""), doc.Project.Solution.GetMostLikelyDtoLocation());
                var shouldProceed = new BasicOptionsWindow {
                    DataContext = vmBasic
                }.ShowModal();

                if (shouldProceed != true)
                {
                    return;
                }

                var existingDoc = doc.Project.Solution.GetDocumentByLocation(vmBasic.DtoLocation, vmBasic.DtoName);
                if (existingDoc != null)
                {
                    var result = VsShellUtilities.ShowMessageBox(this.package, "There is already a DTO class in the specified location. Press OK if you would like to regenerate it, or cancel to choose different name.", "Warninig - regenerate DTO?",
                                                                 OLEMSGICON.OLEMSGICON_WARNING,
                                                                 OLEMSGBUTTON.OLEMSGBUTTON_OKCANCEL,
                                                                 OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);

                    if (result != 1)
                    {
                        return;
                    }
                }

                var vm = await PropertySelectorViewModel.Create(doc, vmBasic.DtoName, vmBasic.DtoLocation, existingDto : existingDoc);

                var isConfirmed = new PropertySelectorWindow()
                {
                    DataContext = vm
                }.ShowModal();

                if (isConfirmed == true)
                {
                    var modifiedSolution = await doc.Project.Solution.WriteDto(vm.DtoLocation, vm.EntityModel.ConvertToMetadata(), vm.GenerateMapper, vm.AddDataContract);

                    var ok = workspace.TryApplyChanges(modifiedSolution);

                    if (!ok)
                    {
                        VsShellUtilities.ShowMessageBox(this.package, "Unable to generate DTO. Please try again (could not apply changes).", "Error", OLEMSGICON.OLEMSGICON_WARNING, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
                    }
                }
            }
            catch (Exception ex)
            {
                try
                {
                    VsShellUtilities.ShowMessageBox(this.package, ex.Message, "An exception has occurred. Please c/p stack trace to project website (https://github.com/yohney/dto-generator), with brief description of the problem.",
                                                    OLEMSGICON.OLEMSGICON_WARNING,
                                                    OLEMSGBUTTON.OLEMSGBUTTON_OK,
                                                    OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);

                    var tmpFile = Path.GetTempFileName();

                    string stackTrace = "";

                    Exception tmp = ex;
                    while (tmp != null)
                    {
                        stackTrace += tmp.StackTrace;
                        stackTrace += "\n----------------------------\n\n";
                        tmp         = ex.InnerException;
                    }


                    File.WriteAllText(tmpFile, stackTrace);

                    VsShellUtilities.OpenBrowser("file:///" + tmpFile);
                }
                catch (Exception innerEx)
                {
                    VsShellUtilities.ShowMessageBox(this.package, innerEx.Message, "An exception has occurred. Unable to write stack trace to TEMP directory.",
                                                    OLEMSGICON.OLEMSGICON_WARNING,
                                                    OLEMSGBUTTON.OLEMSGBUTTON_OK,
                                                    OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
                }
            }
        }
        public static void ProcessCompositeForeigKey(this SerializableViewModel dest, bool RefTypeIsNullable, SerializableViewModelForeignKey destFk, IList <PropertySelectorViewModel> ForeigKeyParentProperties)
        {
            if (dest == null)
            {
                return;
            }
            if (dest.ForeignKeys == null)
            {
                return;
            }
            if (destFk == null)
            {
                return;
            }
            if (ForeigKeyParentProperties == null)
            {
                return;
            }
            List <SerializableViewModelForeignKey> locFrKs = new List <SerializableViewModelForeignKey>();
            bool locRefTypeIsNullable = false;

            string ForeignKeyNameChain = destFk.ForeignKeyNameChain;
            string ForeignKeyName      = destFk.ForeignKeyName;

            if (string.IsNullOrEmpty(ForeignKeyName))
            {
                return;
            }
            foreach (ClassFiledSelectorViewModel srcProp in ForeigKeyParentProperties)
            {
                if (srcProp.ForeigKeyParentProperties == null)
                {
                    continue;
                }
                if (srcProp.ForeigKeyParentProperties.Count < 1)
                {
                    continue;
                }
                PropertySelectorViewModel srcFkPrps = srcProp.ForeigKeyPPByForeignKN(ForeignKeyName);
                if (srcFkPrps == null)
                {
                    continue;
                }
                SerializableViewModelForeignKey svmFk = null;
                if (string.IsNullOrEmpty(ForeignKeyNameChain))
                {
                    svmFk =
                        dest.ForeignKeys.Where(
                            fk => string.IsNullOrEmpty(fk.ForeignKeyNameChain) &&
                            string.Equals(ForeignKeyName, fk.ForeignKeyName) &&
                            string.Equals(srcFkPrps.OriginalPropertyName, fk.DetailOriginalPropertyName)
                            ).FirstOrDefault();
                }
                else
                {
                    svmFk =
                        dest.ForeignKeys.Where(
                            fk => string.Equals(fk.ForeignKeyNameChain, ForeignKeyNameChain) &&
                            string.Equals(ForeignKeyName, fk.ForeignKeyName) &&
                            string.Equals(srcFkPrps.OriginalPropertyName, fk.DetailOriginalPropertyName)
                            ).FirstOrDefault();
                }
                if (svmFk != null)
                {
                    locRefTypeIsNullable = locRefTypeIsNullable || svmFk.RefTypeIsNullable;
                    locFrKs.Add(svmFk);
                    continue;
                }

                SerializableViewModelForeignKey dstFkp = new SerializableViewModelForeignKey()
                {
                    ForeignKeyName             = srcFkPrps.ForeignKeyName,
                    MasterOriginalPropertyName = srcFkPrps.OriginalPropertyName,
                    MasterPocoName             = srcFkPrps.PocoName,
                    MasterPocoFullName         = srcFkPrps.PocoFullName,
                    MasterTypeFullName         = srcFkPrps.TypeFullName,
                    MasterUnderlyingTypeName   = srcFkPrps.UnderlyingTypeName,
                    MasterTypeIsNullable       = srcFkPrps.TypeIsNullable,
                    RefTypeIsNullable          = srcFkPrps.TypeIsNullable || RefTypeIsNullable,

                    ForeignKeyNameChain        = ForeignKeyNameChain,
                    DetailOriginalPropertyName = srcProp.OriginalPropertyName,
                    DetailIsNullable           = srcProp.TypeIsNullable,
                    DetailTypeFullName         = srcProp.TypeFullName,
                    DetailUnderlyingTypeName   = srcProp.UnderlyingTypeName
                };
                dest.ForeignKeys.Add(dstFkp);
                locFrKs.Add(dstFkp);
                locRefTypeIsNullable = locRefTypeIsNullable || dstFkp.RefTypeIsNullable;
            }
            foreach (SerializableViewModelForeignKey srcProp in locFrKs)
            {
                srcProp.RefTypeIsNullable = locRefTypeIsNullable;
            }
        }