private bool ApplyShowOnlyProjectsWithMultipleSolutionsFilter(VsProject project) { return(!ShowOnlyProjectsWithMultipleSolutions || _projectSolutionUsages[project].Count > 1); }
private bool ApplySolutionFilter(VsProject project) { return(!IsSolutionFilterEnabled || SolutionFilter == null || SolutionFilter.Projects.Contains(project)); }
/// <summary> /// Get latest JObject for package identity /// </summary> /// <param name="repo"></param> /// <param name="identity"></param> /// <param name="allowPrerelease"></param> /// <returns></returns> public static List <JObject> GetLastestJObjectsForPackage(SourceRepository repo, JObject jObject, VsProject project, bool allowPrerelease, int skip, int take, bool takeAllVersions) { List <JObject> jObjects = new List <JObject>(); string id = jObject.Value <string>(Properties.PackageId); string version = jObject.Value <string>(Properties.Version); NuGetVersion nVersion = GetNuGetVersionFromString(version); if (!takeAllVersions) { string latestVersion = GetLastestVersionForPackage(repo, id, project.GetSupportedFrameworks(), allowPrerelease, nVersion, false); if (latestVersion != null) { NuGetVersion laVersion = GetNuGetVersionFromString(latestVersion); if (laVersion > nVersion) { Task <JObject> task = repo.GetPackageMetadata(id, laVersion); JObject latestJObject = task.Result; jObjects.Add(latestJObject); } } } else { JObject package = GetJObjectForPackageId(repo, id, project.GetSupportedFrameworks(), allowPrerelease, skip, take); IEnumerable <NuGetVersion> versionList = GetAllVersionsForPackageId(package).OrderByDescending(v => v); // Work around a bug in repo.Search(), where prerelease versions are not filtered out. if (!allowPrerelease) { versionList = versionList.Where(p => p > nVersion && p.IsPrerelease == false); } else { versionList = versionList.Where(p => p > nVersion); } foreach (NuGetVersion updateVersion in versionList) { JObject updateObject = GetPackageByIdAndVersion(repo, id, updateVersion.ToNormalizedString(), allowPrerelease); jObjects.Add(updateObject); } } return(jObjects); }
private bool ApplyShowOnlyProjectsWithNuGetPackagesFilter(VsProject project) { return(!ShowOnlyProjectsWithNuGetPackages || project.NuGetReferences.Any()); }
/// <summary> /// Migrates the site.master layout files from the source WebForms project into the \Shared folder /// in the Blazor target application project. /// </summary> /// <param name="webFormSiteMasterFiles">The flattened list of WebForms project objects/files</param> /// <param name="blazorServerProject">The target Blazor project object</param> /// <returns></returns> /// private async Task ConvertAspxPage(VsDocument sourcePage, VsProject targetProject, VsProjectFolder targetPagesFolder, VsCSharpSource sourceCodeBehind = null) private async Task <string> ConvertLayoutFiles(IEnumerable <VsModel> webFormSiteMasterFiles, VsProject blazorServerProject) { string headerData = null; //put the files in the target project var targetFolder = await blazorServerProject.CheckAddFolder("Shared"); try { foreach (var layoutFile in webFormSiteMasterFiles) { //We don't want to touch/migrate any of the *.designer files if (layoutFile.Name.ToLower().Contains("designer")) { continue; } String targetFileName = layoutFile.Name.Replace(".", ""); //Get any existing children in the targetFolder that match. var existingBlazorMatches = await targetFolder.GetChildrenAsync(true, false); var docMatches = existingBlazorMatches.Where(p => p.Name.ToLower().Contains(targetFileName.ToLower())).Cast <VsDocument>(); foreach (VsDocument matchFile in docMatches) { //delete each matched file in the target folder. await matchFile.DeleteAsync(); } //work on just the Site.Master file which is basically a specialized *.aspx file. if (!layoutFile.Name.ToLower().Contains(".cs")) { var docObj = layoutFile as VsDocument; var textFromResult = await docObj.GetDocumentContentAsStringAsync(); //grab the <%Page element from the source and pull it from the text. Its meta data anyway and just screws up the conversion down the line. var pageHeaderData = System.Text.RegularExpressions.Regex.Match(textFromResult, @"<%@\s*[^%>]*(.*?)\s*%>").Value; if (pageHeaderData.Length > 0) { textFromResult = Regex.Replace(textFromResult, @"<%@\s*[^%>]*(.*?)\s*%>", string.Empty); } //Swap ASP.NET string tokens for Razor syntax (<%, <%@, <%:, <%#:, etc var targetText = RemoveASPNETSyntax(textFromResult); //Convert Site.Master file into razor syntax, specifically the asp:controls that might be used there. var conversionData = await ReplaceAspControls(targetText); //Drop the pageHeaderData into the Dictionary for later processing by any downstream T4 factories conversionData.Add("HeaderData", pageHeaderData); //Setup Page directives, using statements etc var targetWithMeta = await SetRazorPageDirectives(targetFileName, conversionData); VsDocument success = await _visualStudioActions.ProjectFolderActions.AddDocumentAsync(targetFolder, $"{targetFileName}.razor", targetWithMeta); //Updating the dialog await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Information, $"The file {targetFileName}.razor was copied to {targetFolder.Name}."); } //Get sibling/named code-behind file //1. Get the children of this *.aspx file //2. Grab the doc that has the same name with a ".cs" extension on the end of it if (layoutFile.Name.Contains(".cs")) { targetFileName = layoutFile.Name.Replace(".cs", ""); targetFileName = targetFileName.Replace(".", ""); var sourceObj = layoutFile as VsCSharpSource; var codeSource = sourceObj.SourceCode; var metaDataDictionary = new Dictionary <string, string>(); metaDataDictionary.Add("Namespace", $"{blazorServerProject.Name}.Pages"); //Setup Page directives, using statements etc //var targetWithMeta = await SetRazorPageDirectives(targetFileName, conversionData); CsModelStore modelStore = new CsModelStore(); modelStore.SetModel(codeSource.Classes.FirstOrDefault()); var codebehind = await _visualStudioActions.ProjectFolderActions.AddDocumentAsync(targetFolder, $"{targetFileName}.razor.cs", Templates.PageCodeBehind.GenerateSource(modelStore, metaDataDictionary)); // Updating the dialog await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Information, $"The file {targetFileName}.razor.cs was copied to {targetFolder.Name}."); } } } catch (Exception unhandledError) { await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Error, $"The following unhandled error occured while trying to migrate the layout files. '{unhandledError.Message}'"); } return(headerData); }
private void Deploy(DebugPort port) { Debug.Assert(port != null && !port.IsLocalPort); VsPackage.MessageCentre.InternalErrorMsg(DiagnosticStrings.StartDeployAssemblies); CorDebugProcess process = null; bool fDeviceFound = false; VsPackage.MessageCentre.DeploymentMsg(DiagnosticStrings.StartingDeviceDeployment); for (int retries = 0; retries < 60; retries++) { VsPackage.MessageCentre.DeploymentMsg(String.Format(DiagnosticStrings.Iteration, port.Name, DeployDeviceName, retries)); try { process = GetDeviceProcess(); if (process != null) { switch (port.PortFilter) { case PortFilter.Serial: case PortFilter.Usb: case PortFilter.TcpIp: //test the connection. This doesn't tell you if the connection will fail during the AttachToEngine, //but it's a pretty good guess. VsPackage.MessageCentre.DeploymentMsg(String.Format(DiagnosticStrings.OpeningPort, process.PortDefinition.Port)); fDeviceFound = process.PortDefinition.TryToOpen(); if (!fDeviceFound) { VsPackage.MessageCentre.DeploymentMsg(String.Format(DiagnosticStrings.PortNotFound, process.PortDefinition.Port)); } break; default: SetDeployFailure(string.Format("Device {0} has an unsupported/unexpected port type", this.DeployDeviceDescription)); return; } if (fDeviceFound) { break; } } } catch (IOException) { } Thread.Sleep(500); } if (!fDeviceFound || process == null) { SetDeployFailure(string.Format("Device not found or cannot be opened - {0}", this.DeployDeviceDescription)); return; } VsPackage.MessageCentre.DeploymentMsg(DiagnosticStrings.AttachingEngine); Engine engine = process.AttachToEngine(); if (engine == null) { VsPackage.MessageCentre.DeploymentMsg(DiagnosticStrings.CannotAttachEngine); SetDeployFailure(string.Format(DiagnosticStrings.UnableToCommunicate, this.DeployDeviceDescription)); return; } VsPackage.MessageCentre.DeploymentMsg(DiagnosticStrings.EngineAttached); try { VsPackage.MessageCentre.DeploymentMsg(DiagnosticStrings.QueryingDeviceAssemblies); ArrayList assemblies = new ArrayList(); Hashtable systemAssemblies = new Hashtable(); //Ensure Assemblies are loaded if (process.IsDeviceInInitializeState()) { engine.ResumeExecution(); Thread.Sleep(200); while (process.IsDeviceInInitializeState()) { VsPackage.MessageCentre.DeploymentMsg(DiagnosticStrings.WaitingInitialize); //need to break out of this or timeout or something? Thread.Sleep(200); } } WireProtocol.Commands.Debugging_Resolve_Assembly[] assms = engine.ResolveAllAssemblies(); // find out which are the system assemblies // we will insert each system assemblies in a hash table where the value will be the assembly version foreach (Debugging_Resolve_Assembly resolvedAssembly in assms) { VsPackage.MessageCentre.DeploymentMsg(String.Format(DiagnosticStrings.FoundAssembly, resolvedAssembly.m_reply.Name, resolvedAssembly.m_reply.m_version.ToString())); if ((resolvedAssembly.m_reply.m_flags & Debugging_Resolve_Assembly.Reply.c_Deployed) == 0) { systemAssemblies[resolvedAssembly.m_reply.Name.ToLower()] = resolvedAssembly.m_reply.m_version; } } string[] pes = m_project.GetDependencies(true, true, engine.IsTargetBigEndian); string[] dlls = m_project.GetDependencies(true, false, engine.IsTargetBigEndian); Debug.Assert(pes.Length == dlls.Length); // now we will re-deploy all system assemblies for (int i = 0; i < pes.Length; ++i) { string assemblyPath = pes[i]; string dllPath = dlls[i]; //is this a system assembly? string fileName = Path.ChangeExtension(Path.GetFileName(assemblyPath), null).ToLower(); bool fDeployNewVersion = true; if (systemAssemblies.ContainsKey(fileName)) { // get the version of the assembly on the device Debugging_Resolve_Assembly.Version deviceVer = (WireProtocol.Commands.Debugging_Resolve_Assembly.Version)systemAssemblies[fileName]; // get the version of the assembly of the project // We need to load the bytes for the assembly because other Load methods can override the path // with gac or recently used paths. This is the only way we control the exact assembly that is loaded. byte[] asmData = null; using (FileStream sr = new FileStream(dllPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { asmData = new byte[sr.Length]; sr.Read(asmData, 0, (int)sr.Length); } System.Reflection.Assembly assm = Assembly.Load(asmData); Version deployVer = assm.GetName().Version; // compare versions strictly, and deploy whatever assembly does not match the version on the device if (VsProject.TargetFrameworkExactMatch(deviceVer, deployVer)) { fDeployNewVersion = false; } else { //////////////////////////////////////////////// // !!! SPECIAL CASE !!! // // // // MSCORLIB cannot be deployed more than once // //////////////////////////////////////////////// if (assm.GetName().Name.ToLower().Contains("mscorlib")) { string message = string.Format("Cannot deploy the base assembly '{9}', or any of his satellite assemblies, to device - {0} twice. Assembly '{9}' on the device has version {1}.{2}.{3}.{4}, while the program is trying to deploy version {5}.{6}.{7}.{8} ", this.DeployDeviceDescription, deviceVer.iMajorVersion, deviceVer.iMinorVersion, deviceVer.iBuildNumber, deviceVer.iRevisionNumber, deployVer.Major, deployVer.Minor, deployVer.Build, deployVer.Revision, assm.GetName().Name); VsPackage.MessageCentre.DeploymentMsg(message); SetDeployFailure(message); return; } } } // append the assembly whose version does not match, or that still is not on the device, to the blob to deploy if (fDeployNewVersion) { using (FileStream fs = File.Open(assemblyPath, FileMode.Open, FileAccess.Read)) { VsPackage.MessageCentre.DeploymentMsg(String.Format(DiagnosticStrings.AddingPEtoBundle, assemblyPath)); long length = (fs.Length + 3) / 4 * 4; byte[] buf = new byte[length]; fs.Read(buf, 0, (int)fs.Length); assemblies.Add(buf); } } } VsPackage.MessageCentre.DeploymentMsg("Attempting deployment..."); if (!engine.Deployment_Execute(assemblies, false, VsPackage.MessageCentre.DeploymentMsg)) { VsPackage.MessageCentre.DeploymentMsg(DiagnosticStrings.DeployFailed); SetDeployFailure(); return; } } finally { process.DetachFromEngine(); } }
/// <summary> /// Process the ok button click event. /// </summary> /// <param name="sender">Hosting user control.</param> /// <param name="e">We dont use the routing args with this implementation.</param> private void ButtonOk_Click(object sender, RoutedEventArgs e) { //Loading the selected projects from the dialog VsProject webformProject = ComboboxWebFormsProject.SelectedItem as VsProject; VsProject blazorProject = ComboboxBlazorProject.SelectedItem as VsProject; //Checking that a source webforms project has been selected. if (webformProject == null) { MessageBox.Show("You must select a Webforms Project before continuing."); return; } //Checking to make sure a target blazor project has been selected. if (blazorProject == null) { MessageBox.Show("You must have a Blazor Project selected before continuing."); return; } //Checking to make sure the same project was not selected. if (webformProject.Name == blazorProject.Name) { MessageBox.Show("The web forms project and the blazor project cannot be the same."); return; } bool migrationStepsSelected = false; migrationStepsSelected = CheckBoxMigrateAspxPages.IsChecked.GetResult() | CheckBoxMigrateBundling.IsChecked.GetResult() | CheckBoxMigrateConfiguration.IsChecked.GetResult() | CheckBoxMigrateHttpModules.IsChecked.GetResult() | CheckBoxMigrateLogic.IsChecked.GetResult() | CheckBoxMigrateStaticFiles.IsChecked.GetResult() | CheckBoxStartupProcess.IsChecked.GetResult(); if (!migrationStepsSelected) { MessageBox.Show("You have to select a migration step in order to continue."); return; } try { var migrationSteps = new MigrationSteps(CheckBoxStartupProcess.IsChecked.GetResult(), CheckBoxMigrateHttpModules.IsChecked.GetResult(), CheckBoxMigrateStaticFiles.IsChecked.GetResult(), CheckBoxMigrateBundling.IsChecked.GetResult(), CheckBoxMigrateAspxPages.IsChecked.GetResult(), CheckBoxMigrateConfiguration.IsChecked.GetResult(), CheckBoxMigrateLogic.IsChecked.GetResult()); //Creating an empty observable collection. This will be updated during the execution of the migration process. StepStatus = new ObservableCollection <MigrationStepStatus>(); //Updating the dialog to not accept input while the migration is processing ButtonOk.Content = "Processing"; ButtonOk.IsEnabled = false; ButtonCancel.IsEnabled = false; //Creating the migration process logic. Notice that we pass in a copy of the visual studio actions that code factory uses for visual studio automation. //In addition we pass a reference to the dialog itself. //We have implemented an interface on the dialog that allows the background thread to call into this dialog and update the migration status. var migrationProcess = new WebFormToBlazorServerMigration(_visualStudioActions, this); //Updating the UI to begin the migration process. SetupStatusForMigration(migrationSteps); //Starting the migration process on a background thread and letting the dialog keep processing UI updates. Task.Run(() => migrationProcess.StartMigration(webformProject, blazorProject, migrationSteps)); } catch (Exception unhandledError) { //Displaying the error that was not managed during the migration process. MessageBox.Show($"The following unhandled error occured while performing the setup operations. '{unhandledError.Message}'", "Unhandled Setup Error", MessageBoxButton.OK, MessageBoxImage.Error); } }
/// <summary> /// This step is used to locate any code artifacts within the Web Forms application that inherit from HttpApplication in order to alter /// any of the default behavior of IIS. Any code found will be copied and moved into the end of the blazor target projects Startup.cs file definition. /// </summary> /// <param name="webFormProjectData">Pre cached project data about the web forms project.</param> /// <param name="webFormProject">The web forms project that we are migrating data from.</param> /// <param name="blazorServerProject">The blazor server project this is being migrated to.</param> private async Task MigrateStartupAsync(IReadOnlyList <VsModel> webFormProjectData, VsProject webFormProject, VsProject blazorServerProject) { try { //Informing the dialog the migration step has started. await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.Startup, MigrationStatusEnum.Running); //Find class(es) that inherit HttpApplication var startupClasses = webFormProjectData.GetClassesThatInheritBase("HttpApplication"); if (!startupClasses.Any()) { //No startup classes were found updating the hosting dialog to inform the user there was nothing to convert in the startup process. await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.Startup, MessageTypeEnum.Information, $"No classes were found in {webFormProject.Name} that inherit from 'HttpApplication'"); await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.Startup, MigrationStatusEnum.Passed); return; } var blazorStartupClass = await blazorServerProject.FindClassAsync("Startup", false); if (blazorStartupClass == null) { //No startup class was found in the blazor server project. Cannot update the startup class. Informing the user and failing the step await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.Startup, MessageTypeEnum.Warning, $"The target project {blazorServerProject.Name} does not have definition for a Startup class ('public class Startup')."); await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.Startup, MigrationStatusEnum.Failed); return; } //Get the methods //Copy them into the blazorStartupClass commented out. foreach (var source in startupClasses) { //loading the class data var sourceClass = source.Classes.FirstOrDefault(); //If no class was found continue the process. if (sourceClass == null) { continue; } //double loop - I do not like this and it needs to be refactored. foreach (var method in sourceClass.Methods) { await blazorStartupClass.AddToEndAsync(blazorStartupClass.SourceFiles.First(), $"\r\n/*{method.FormatCSharpDeclarationSyntax()}\r\n{{ { await method.GetBodySyntaxAsync()} \r\n}}*/"); await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.Startup, MessageTypeEnum.Information, $"Class: {sourceClass.Name} Method: {method.Name} has been copied into the Startup.cs class commented out. Please refactor manually."); } } //All items process updating the status of the step has passed. await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.Startup, MigrationStatusEnum.Passed); } catch (Exception unhandledError) { //Dumping the exception that occured directly into the status so the user can see what happened. await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.Startup, MessageTypeEnum.Error, $"The following unhandled error occured. '{unhandledError.Message}'"); //Updating the status that the step failed await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.Startup, MigrationStatusEnum.Failed); } }
/// <summary> /// Get Installed Package References for a single project /// </summary> /// <returns></returns> protected IEnumerable<InstalledPackageReference> GetInstalledReferences(VsProject proj) { IEnumerable<InstalledPackageReference> refs = Enumerable.Empty<InstalledPackageReference>(); InstalledPackagesList installedList = proj.InstalledPackages; if (installedList != null) { refs = installedList.GetInstalledPackages(); } return refs; }
/// <summary> /// Get Installed Package References a single project with specified packageId /// </summary> /// <returns></returns> protected InstalledPackageReference GetInstalledReference(VsProject proj, string Id) { InstalledPackageReference packageRef = null; InstalledPackagesList installedList = proj.InstalledPackages; if (installedList != null) { packageRef = installedList.GetInstalledPackage(Id); } return packageRef; }
private IEnumerable<PowerShellPreviewResult> AddToPowerShellPreviewResult(List<PowerShellPreviewResult> list, PreviewResult result, PowerShellPackageAction action, VsProject proj) { IEnumerable<PackageIdentity> identities = null; IEnumerable<UpdatePreviewResult> updates = null; switch (action) { case PowerShellPackageAction.Install: { identities = result.Added; break; } case PowerShellPackageAction.Uninstall: { identities = result.Deleted; break; } case PowerShellPackageAction.Update: { updates = result.Updated; break; } } if (identities != null) { foreach (PackageIdentity identity in identities) { PowerShellPreviewResult previewRes = new PowerShellPreviewResult(); previewRes.Id = identity.Id; previewRes.Action = string.Format("{0} ({1})", action.ToString(), identity.Version.ToNormalizedString()); list.Add(previewRes); previewRes.ProjectName = proj.Name; } } if (updates != null) { foreach (UpdatePreviewResult updateResult in updates) { PowerShellPreviewResult previewRes = new PowerShellPreviewResult(); previewRes.Id = updateResult.Old.Id; previewRes.Action = string.Format("{0} ({1} => {2})", action.ToString(), updateResult.Old.Version.ToNormalizedString(), updateResult.New.Version.ToNormalizedString()); list.Add(previewRes); previewRes.ProjectName = proj.Name; } } return list; }
private IEnumerable<PowerShellPreviewResult> ConvertToPowerShellPreviewResult(PreviewResult result, VsProject proj) { List<PowerShellPreviewResult> psResults = new List<PowerShellPreviewResult>(); AddToPowerShellPreviewResult(psResults, result, PowerShellPackageAction.Install, proj); AddToPowerShellPreviewResult(psResults, result, PowerShellPackageAction.Uninstall, proj); AddToPowerShellPreviewResult(psResults, result, PowerShellPackageAction.Update, proj); return psResults; }
private void LogPreviewResult(PreviewResult result, VsProject proj) { IEnumerable<PowerShellPreviewResult> psResults = ConvertToPowerShellPreviewResult(result, proj); WriteObject(psResults); }
/// <summary> /// Get latest update for package identity /// </summary> /// <param name="repo"></param> /// <param name="identity"></param> /// <param name="allowPrerelease"></param> /// <returns></returns> public static PackageIdentity GetLastestUpdateForPackage(SourceRepository repo, PackageIdentity identity, VsProject project, bool allowPrerelease, bool isSafe) { string latestVersion = GetLastestVersionForPackage(repo, identity.Id, project.GetSupportedFrameworks(), allowPrerelease, identity.Version, isSafe); PackageIdentity latestIdentity = null; if (latestVersion != null) { latestIdentity = new PackageIdentity(identity.Id, NuGetVersion.Parse(latestVersion)); } return latestIdentity; }
private void AddProjectVertex(VsProject project, BidirectionalGraph <object, IEdge <object> > graph, List <VsProject> projectsInGraph) { projectsInGraph.Add(project); graph.AddVertex(project); }
public async Task MigrateAspxFiles(IReadOnlyList <VsModel> webFormProjectData, VsProject webFormProject, VsProject blazorServerProject) { try { //Informing the dialog the migration step has started. await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.AspxPages, MigrationStatusEnum.Running); //Getting all the aspx & ascx files in the project. var aspxFiles = webFormProjectData.Where(p => p.ModelType == VisualStudioModelType.Document && (p.Name.EndsWith(".aspx") || p.Name.EndsWith(".ascx"))).Cast <VsDocument>(); if (!aspxFiles.Any()) { await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Warning, "No Aspx files were found in the web forms project. This step is finished."); await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.AspxPages, MigrationStatusEnum.Passed); return; } //Migrate over the site.master layout pages. var layoutFiles = webFormProjectData.Where(p => p.Name.ToLower().Contains(".master")); var success = await ConvertLayoutFiles(layoutFiles, blazorServerProject); //Calling into the CodeFactory project system and getting all the direct children of the project. var blazorRootModels = await blazorServerProject.GetChildrenAsync(false); //Getting the pages folder from the blazor project. var blazorPagesFolder = blazorRootModels.FirstOrDefault(m => m.ModelType == VisualStudioModelType.ProjectFolder & m.Name.ToLower().Equals("pages")) as VsProjectFolder; //If the pages folder was not found fail this step and return. if (blazorPagesFolder == null) { await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Error, "No pages folder was found in the blazor project, cannot continue the aspx file conversion."); await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.AspxPages, MigrationStatusEnum.Failed); return; } //Call the CodeFactory project system to get all the current children of the pages project folder. var pagesFolderModels = await blazorPagesFolder.GetChildrenAsync(true); //Filtering out everything but documents. var pages = pagesFolderModels.Where(m => m.ModelType == VisualStudioModelType.Document) .Cast <VsDocument>(); int collect = 0; //Processing each aspx file. foreach (VsDocument aspxFile in aspxFiles) { collect++; //Getting the formatted names that will be used in migrating the ASPX file and its code behind to the blazor project. string targetFileNameNoExtension = Path.GetFileNameWithoutExtension(aspxFile.Path); string aspxCodeBehindFileName = $"{targetFileNameNoExtension}.aspx.cs"; string ascxCodeBehindFileName = $"{targetFileNameNoExtension}.axcs.cs"; string razorPageFileName = $"{targetFileNameNoExtension}.razor"; string razorPageCodeBehindFileName = $"{targetFileNameNoExtension}.razor.cs"; //Searching for an existing razor page. We will delete razor pages and recreate them. var currentRazorPage = pages.FirstOrDefault(p => p.Path.ToLower().EndsWith(razorPageFileName.ToLower())); if (currentRazorPage != null) { //Razor page was found removing the razor page. bool removedPage = await currentRazorPage.DeleteAsync(); if (removedPage) { await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Information, $"Removed the razor page {razorPageFileName}"); var currentRazorPageCodeBehind = pages.FirstOrDefault(p => p.Path.ToLower().EndsWith(razorPageCodeBehindFileName.ToLower())); if (currentRazorPageCodeBehind != null) { if (File.Exists(currentRazorPageCodeBehind.Path)) { bool removedCodeBehind = await currentRazorPageCodeBehind.DeleteAsync(); if (removedCodeBehind) { await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Information, $"Removed the razor page code behind file {razorPageCodeBehindFileName}"); } else { await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Error, $"Could not remove the razor page code behind file {razorPageCodeBehindFileName}.The target ASPX file will not be migrated."); continue; } } } } else { await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Error, $"Could not remove the razor page {razorPageFileName}.The target ASPX file will not be migrated."); continue; } } VsCSharpSource CodeBehindSource = null; if (aspxFile.Path.Contains("ascx")) { //Getting the code behind file that supports the current aspx page. CodeBehindSource = webFormProjectData .Where(m => m.ModelType == VisualStudioModelType.CSharpSource).Cast <VsCSharpSource>() .FirstOrDefault(s => s.SourceCode.SourceDocument.ToLower().EndsWith(ascxCodeBehindFileName.ToLower())) as VsCSharpSource; } //Getting the code behind file that supports the current aspx page. CodeBehindSource = webFormProjectData .Where(m => m.ModelType == VisualStudioModelType.CSharpSource).Cast <VsCSharpSource>() .FirstOrDefault(s => s.SourceCode.SourceDocument.ToLower().EndsWith(aspxCodeBehindFileName.ToLower())) as VsCSharpSource; //Converting the aspx page and the code behind file if it was found. await ConvertAspxPage(aspxFile, blazorServerProject, blazorPagesFolder, CodeBehindSource); if (collect == 4) { GC.Collect(); collect = 0; } } //Completed the migration step informing the dialog. await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.AspxPages, MigrationStatusEnum.Passed); } catch (Exception unhandledError) { //Dumping the exception that occured directly into the status so the user can see what happened. await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Error, $"The following unhandled error occured. '{unhandledError.Message}'"); //Updating the status that the step failed await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.AspxPages, MigrationStatusEnum.Failed); } }
/// <summary> /// Gets a list of all classes in the project that qualify for transient dependency injection registration. /// </summary> /// <param name="project">Target project to register.</param> /// <param name="rejectedClassNames">The class names that are not allowed for dependency injection.</param> /// <param name="rejectedBaseClasses">The base classes not allowed for dependency injection.</param> /// <param name="targetInterfaceTypeForRegistration">The interfaces of a target type to use for registration, this includes inheriting the target type.</param> /// <returns></returns> public static async Task <IEnumerable <DependencyInjectionRegistrationInformation> > GetTransientClassesAsync(VsProject project, IEnumerable <string> rejectedClassNames = null, IEnumerable <ModelLookupData> rejectedBaseClasses = null, IEnumerable <ModelLookupData> targetInterfaceTypeForRegistration = null) { var result = new List <DependencyInjectionRegistrationInformation>(); if (project == null) { return(result); } if (!project.HasChildren) { return(result); } var projectChildren = await project.GetChildrenAsync(true, true); var csSourceCodeDocuments = projectChildren .Where(m => m.ModelType == VisualStudioModelType.CSharpSource) .Cast <VsCSharpSource>(); foreach (var csSourceCodeDocument in csSourceCodeDocuments) { var sourceCode = csSourceCodeDocument.SourceCode; if (sourceCode == null) { continue; } if (!sourceCode.Classes.Any()) { continue; } var classes = sourceCode.Classes; foreach (var csClass in classes) { var registration = IsTransientClass(csClass, rejectedClassNames, rejectedBaseClasses, targetInterfaceTypeForRegistration); if (registration == null) { continue; } if (!result.Any(r => (r.ClassData?.Namespace == registration.ClassData?.Namespace && r.ClassData?.Name == registration.ClassData?.Name))) { result.Add(registration); } } //result.AddRange(classes.Select(csClass => IsTransientClass(csClass, rejectedClassNames, // rejectedBaseClasses, targetInterfaceTypeForRegistration)).Where(diInfo => diInfo != null)); } return(result); }
/// <summary> /// Helper method that converts Aspx Pages to Blazor pages. /// </summary> /// <param name="sourcePage">The source aspx page to be converted.</param> /// <param name="targetProject">The target blazor project to write to.</param> /// <param name="targetPagesFolder">The target visual studio project folder the converted aspx will be added to.</param> /// <param name="sourceCodeBehind">Optional parameter that provides the code behind file for the aspx page to be converted also.</param> /// <returns>Flag used to determine if the conversion was successful.</returns> private async Task ConvertAspxPage(VsDocument sourcePage, VsProject targetProject, VsProjectFolder targetPagesFolder, VsCSharpSource sourceCodeBehind = null, VsDocument sourceDocCodeBehind = null) { try { //Getting the content from the source document. var pageContent = await sourcePage.GetDocumentContentAsStringAsync(); //File.ReadAllText(result.Path); //grab the <%Page element from the source and pull it from the text. Its meta data anyway and just screws up the conversion down the line. var pageHeaderData = System.Text.RegularExpressions.Regex.Match(pageContent, @"<%@\s*[^%>]*(.*?)\s*%>").Value; if (pageHeaderData.Length > 0) { pageContent = Regex.Replace(pageContent, @"<%@\s*[^%>]*(.*?)\s*%>", string.Empty); } //Swap ASP.NET string tokens for Razor syntax (<%, <%@, <%:, <%#:, etc var targetText = RemoveASPNETSyntax(pageContent); //Convert ASP.NET into Razor syntax. **This actually presumes that any controls like <asp:ListView.. //will have an equivalent Razor component in place called <ListView.. etc var conversionData = await ReplaceAspControls(targetText); //Drop the pageHeaderData into the Dictionary for later processing by any downstream T4 factories conversionData.Add("HeaderData", pageHeaderData); //Getting the source code from the code behind file provided. var codeSource = sourceCodeBehind?.SourceCode; if ((codeSource == null) && (sourceDocCodeBehind != null)) { codeSource = await sourceDocCodeBehind.GetCSharpSourceModelAsync(); } //put the files in the target project String targetFileName = Path.GetFileNameWithoutExtension(sourcePage.Path); conversionData.Add("Namespace", $"{targetProject.DefaultNamespace}.Pages"); //Setup Page directives, using statements etc var targetWithMeta = await SetRazorPageDirectives(targetFileName, conversionData); //Adding the converted content from the aspx page to the new razor page. VsDocument success = await targetPagesFolder.AddDocumentAsync($"{targetFileName}.razor", targetWithMeta); if (success != null) { //Updating the dialog with the status the aspx page has been converted. await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Information, $"Converted the aspx page to a razor page, added razor page {targetFileName}.razor"); //If we have the source code from the original aspx page add it to the razor pages folder. if (codeSource != null) { //Creating a CodeFactory model store this will be used to pass data to a T4 factory. CsModelStore modelStore = new CsModelStore(); //Adding the current class from the code behind into the model store for processing. modelStore.SetModel(codeSource.Classes.FirstOrDefault()); //Processing the T4 factory and loading the source code. var codeBehindFormattedSourceCode = Templates.PageCodeBehind.GenerateSource(modelStore, conversionData); //Calling the CodeFactory project system and adding a new code behind file and injecting the formatted code into the file. var codeBehind = await targetPagesFolder.AddDocumentAsync($"{targetFileName}.razor.cs", codeBehindFormattedSourceCode); if (codeBehind != null) { //Updating the dialog with the status the aspx page code behind has been converted. await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Information, $"Converted the aspx page code behind file to a razor page code behind file, added code behind file {targetFileName}.razor.cs"); } else { //Updating the dialog with the status the aspx page code behind failed await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Error, $"Failed the conversion of the aspx page code behind file to a razor page code behind file {targetFileName}.razor.cs"); } } } else { //Updating the dialog with the status the aspx page failed conversion. await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Error, $"Failed the conversion of the aspx page {targetFileName}.razor. Will not convert the code behind file."); } } catch (Exception unhandledError) { await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Error, $"The following unhandled error occured while trying to convert the aspx page. '{unhandledError.Message}'"); } }
/// <summary> /// Create a new registration class from scratch /// </summary> /// <param name="sourceProject">The source project to build the new registration class for.</param> /// <param name="className">The name of the class that is used for service registration. This will be set to the constant <see cref="NetConstants.DefaultDependencyInjectionClassName"/> this can be overwritten with a custom class name.</param> /// <param name="automatedRegistrationMethodName">The name of the automatic transient class registration method. This will be set to the constant <see cref="NetConstants.DefaultAutomaticTransientClassRegistrationMethodName"/> this can be overwritten with a custom method name. </param> /// <returns>Fully formatted source code for registration class.</returns> public static string BuildNewRegistrationClass(VsProject sourceProject, string className = NetConstants.DefaultDependencyInjectionClassName, string automatedRegistrationMethodName = NetConstants.DefaultAutomaticTransientClassRegistrationMethodName) { if (sourceProject == null) { return(null); } if (!sourceProject.IsLoaded) { return(null); } string defaultNamespace = sourceProject.DefaultNamespace; if (string.IsNullOrEmpty(defaultNamespace)) { return(null); } CodeFactory.SourceFormatter classFormatter = new CodeFactory.SourceFormatter(); classFormatter.AppendCodeLine(0, "using System;"); classFormatter.AppendCodeLine(0, "using System.Collections.Generic;"); classFormatter.AppendCodeLine(0, "using Microsoft.Extensions.Configuration;"); classFormatter.AppendCodeLine(0, "using Microsoft.Extensions.DependencyInjection;"); classFormatter.AppendCodeLine(0, $"namespace {defaultNamespace}"); classFormatter.AppendCodeLine(0, "{"); classFormatter.AppendCodeLine(1, "/// <summary>"); classFormatter.AppendCodeLine(1, $"/// Responsible for dependency inject of services for the library <see cref=\"{sourceProject.Name}\"/>"); classFormatter.AppendCodeLine(1, "/// </summary>"); classFormatter.AppendCodeLine(1, $"public static class {className}"); classFormatter.AppendCodeLine(1, "{"); classFormatter.AppendCodeLine(2, "/// <summary>"); classFormatter.AppendCodeLine(2, "/// Flag that determines if registration has already been performed on the library"); classFormatter.AppendCodeLine(2, "/// </summary>"); classFormatter.AppendCodeLine(2, "public static bool ServicesRegistered { get; private set; }"); classFormatter.AppendCodeLine(0); classFormatter.AppendCodeLine(2, "/// <summary>"); classFormatter.AppendCodeLine(2, "/// Register the dependency injection service that are supported by this library and triggers registration for other libraries referenced by this library."); classFormatter.AppendCodeLine(2, "/// </summary>"); classFormatter.AppendCodeLine(2, "/// <param name=\"serviceCollection\">The service collection that dependency injection uses.</param>"); classFormatter.AppendCodeLine(2, "/// <param name=\"configuration\">The hosting systems configuration.</param>"); classFormatter.AppendCodeLine(2, "public static void RegisterServices(IServiceCollection serviceCollection, IConfiguration configuration)"); classFormatter.AppendCodeLine(2, "{"); classFormatter.AppendCodeLine(3, "//If services have already been registered do no process service registration. This protects from duplicate registration."); classFormatter.AppendCodeLine(3, "if (ServicesRegistered) return;"); classFormatter.AppendCodeLine(0); classFormatter.AppendCodeLine(3, "//Call down stream libraries and have them complete their registration."); classFormatter.AppendCodeLine(3, "RegisterDependentServices(serviceCollection, configuration);"); classFormatter.AppendCodeLine(0); classFormatter.AppendCodeLine(3, "//Process all manually managed registrations for this library."); classFormatter.AppendCodeLine(3, "ManualRegistrationServices(serviceCollection, configuration);"); classFormatter.AppendCodeLine(0); classFormatter.AppendCodeLine(3, "//Process all automatically discovered services for registration."); classFormatter.AppendCodeLine(3, $"{automatedRegistrationMethodName}(serviceCollection);"); classFormatter.AppendCodeLine(0); classFormatter.AppendCodeLine(3, "//Update the registration status."); classFormatter.AppendCodeLine(3, "ServicesRegistered = true;"); classFormatter.AppendCodeLine(2, "}"); classFormatter.AppendCodeLine(0); classFormatter.AppendCodeLine(2, "/// <summary>"); classFormatter.AppendCodeLine(2, "/// Register dependency injection services for child libraries referenced by this library."); classFormatter.AppendCodeLine(2, "/// </summary>"); classFormatter.AppendCodeLine(2, "/// <param name=\"serviceCollection\">The service collection that dependency injection uses.</param>"); classFormatter.AppendCodeLine(2, "/// <param name=\"configuration\">The hosting systems configuration.</param>"); classFormatter.AppendCodeLine(2, "private static void RegisterDependentServices(IServiceCollection serviceCollection, IConfiguration configuration)"); classFormatter.AppendCodeLine(2, "{"); classFormatter.AppendCodeLine(3, "//Todo: Register services from other libraries directly referenced by this library."); classFormatter.AppendCodeLine(2, "}"); classFormatter.AppendCodeLine(0); classFormatter.AppendCodeLine(2, "/// <summary>"); classFormatter.AppendCodeLine(2, "/// Register services with the service collection manually. This is where manual singleton objects and complex service registration is managed."); classFormatter.AppendCodeLine(2, "/// </summary>"); classFormatter.AppendCodeLine(2, "/// <param name=\"serviceCollection\">The service collection that dependency injection uses.</param>"); classFormatter.AppendCodeLine(2, "/// <param name=\"configuration\">The hosting systems configuration.</param>"); classFormatter.AppendCodeLine(2, "private static void ManualRegistrationServices(IServiceCollection serviceCollection, IConfiguration configuration)"); classFormatter.AppendCodeLine(2, "{"); classFormatter.AppendCodeLine(3, "//TODO: manually add singleton and manually managed registrations here."); classFormatter.AppendCodeLine(2, "}"); classFormatter.AppendCodeLine(0); classFormatter.AppendCodeLine(2, "/// <summary>"); classFormatter.AppendCodeLine(2, "/// Automated registration of classes using transient registration."); classFormatter.AppendCodeLine(2, "/// </summary>"); classFormatter.AppendCodeLine(2, "/// <param name=\"serviceCollection\">The service collection to register services.</param>"); classFormatter.AppendCodeLine(2, $"private static void {automatedRegistrationMethodName}(IServiceCollection serviceCollection)"); classFormatter.AppendCodeLine(2, "{"); classFormatter.AppendCodeLine(3, "//Will be updated through code automation do not change or add to this method by hand."); classFormatter.AppendCodeLine(2, "}"); classFormatter.AppendCodeLine(1, "}"); classFormatter.AppendCodeLine(0, "}"); return(classFormatter.ReturnSource()); }
/// <summary> /// Starts the migration process from webforms project to a blazor server project. /// </summary> /// <param name="webFormsProject">Source project to read data from.</param> /// <param name="blazorServerProject">Target server blazor project to inject into.</param> /// <param name="steps">The migration steps that are to be run.</param> public async Task StartMigration(VsProject webFormsProject, VsProject blazorServerProject, MigrationSteps steps) { try { //bounds checking that migration steps were provided. if (steps == null) { await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.MigrationProcess, MigrationStatusEnum.Failed); await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.MigrationProcess, MessageTypeEnum.Error, "Could not determine which migration steps are to be perform migration aborted."); await _statusTracking.UpdateMigrationFinishedAsync(); return; } //Bounds checking that the web forms project was provided. if (webFormsProject == null) { await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.MigrationProcess, MigrationStatusEnum.Failed); await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.MigrationProcess, MessageTypeEnum.Error, "Internal error occured, no web forms project was provided the migration was aborted."); await _statusTracking.UpdateMigrationFinishedAsync(); return; } //Bounds checking if the blazor server project was provided. if (blazorServerProject == null) { await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.MigrationProcess, MigrationStatusEnum.Failed); await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.MigrationProcess, MessageTypeEnum.Error, "Internal error occured, no blazor server project was provided the migration was aborted."); await _statusTracking.UpdateMigrationFinishedAsync(); return; } //Starting the migration process by caching the web forms project data await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.MigrationProcess, MigrationStatusEnum.Running); await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.MigrationProcess, MessageTypeEnum.Information, "Please wait loading the data from the web forms project..."); //Loading the visual studio models from the webFormsProject. //This is a resource intensive task we only need to do this once since we are never updating the web forms project. //We will cache this data and pass it on to all parts of the migration process //var filePath = new DirectoryInfo(webFormsProject.Path).FullName; var webFormProjectData = await webFormsProject.LoadAllProjectData(false); //Confirming the web forms data has been cached if (webFormProjectData.Any()) { await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.MigrationProcess, MigrationStatusEnum.Passed); await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.MigrationProcess, MessageTypeEnum.Information, "Web forms data has been cached, migration beginning."); } else { await _statusTracking.UpdateStepStatusAsync(MigrationStepEnum.MigrationProcess, MigrationStatusEnum.Failed); await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.MigrationProcess, MessageTypeEnum.Error, "Failed to load the web forms project data, cannot continue the migration process."); await _statusTracking.UpdateMigrationFinishedAsync(); return; } //Running the migration steps in sequential order if (steps.Startup) { await MigrateStartupAsync(webFormProjectData, webFormsProject, blazorServerProject); } if (steps.HttpModules) { await MigrateHttpModulesAsync(webFormProjectData, webFormsProject, blazorServerProject); } if (steps.StaticFiles) { await MigrateStaticFiles(webFormProjectData, webFormsProject, blazorServerProject); } if (steps.Bundling) { await MigrateBundling(webFormProjectData, webFormsProject, blazorServerProject); } if (steps.AspxPages) { await MigrateAspxFiles(webFormProjectData, webFormsProject, blazorServerProject); } if (steps.Configuration) { await MigrateConfig(webFormProjectData, webFormsProject, blazorServerProject); } if (steps.AppLogic) { await MigrateLogic(webFormProjectData, webFormsProject, blazorServerProject); } } catch (Exception unhandledError) { //Updating the dialog with the unhandled error that occured. await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.MigrationProcess, MessageTypeEnum.Error, $"The migration process had an unhandled error, the migration process is aborting. The following error occured. '{unhandledError.Message}'"); } finally { //Informing the hosting dialog the migration has finished. await _statusTracking.UpdateMigrationFinishedAsync(); } }
/// <summary> /// Searches the root of a project for the dependency injection registration class. If it is not found will generate a new service registration class. /// </summary> /// <param name="source">The source project to load the registration class from.</param> /// <param name="className">The name of the class that is used for service registration. This will be set to the constant <see cref="NetConstants.DefaultDependencyInjectionClassName"/> this can be overwritten with a custom class name.</param> /// <param name="automatedRegistrationMethodName">The name of the automatic transient class registration method. This will be set to the constant <see cref="NetConstants.DefaultAutomaticTransientClassRegistrationMethodName"/> this can be overwritten with a custom method name. </param> /// <returns>The source code model for the registration class.</returns> public static async Task <CsSource> GetRegistrationClassAsync(VsProject source, string className = NetConstants.DefaultDependencyInjectionClassName, string automatedRegistrationMethodName = NetConstants.DefaultAutomaticTransientClassRegistrationMethodName) { if (source == null) { throw new ArgumentNullException(nameof(source)); } if (!source.IsLoaded) { throw new CodeFactoryException("Project model was not loaded cannot load or create the registration class."); } if (string.IsNullOrEmpty(className)) { throw new ArgumentNullException(nameof(className)); } var projectFiles = await source.GetChildrenAsync(false, true); CsSource registrationSource = null; try { //Searching the projects root directory code files for the registration class if (projectFiles.Any()) { registrationSource = projectFiles.Where(f => f.ModelType == VisualStudioModelType.CSharpSource) .Cast <VsCSharpSource>().FirstOrDefault(s => s.SourceCode.Classes.Any(c => c.Name == className)) ?.SourceCode; } //If no registration source code file was found then create a new registration class from scratch. if (registrationSource == null) { var registrationClassCode = BuildNewRegistrationClass(source, className, automatedRegistrationMethodName); if (registrationClassCode == null) { throw new CodeFactoryException("Could not generate the dependency injection registration source code"); } string registrationClassFileName = $"{className}.cs"; var document = await source.AddDocumentAsync(registrationClassFileName, registrationClassCode); registrationSource = await document.GetCSharpSourceModelAsync(); } if (registrationSource == null) { throw new CodeFactoryException("Cannot load the source code for the registration class."); } } catch (CodeFactoryException) { throw; } catch (Exception unhandledException) { throw new CodeFactoryException("An error occured while loading the registration class source code, cannot continue.", unhandledException); } return(registrationSource); }
/// <summary> /// Get latest update for package identity /// </summary> /// <param name="repo"></param> /// <param name="identity"></param> /// <param name="allowPrerelease"></param> /// <returns></returns> public static PackageIdentity GetLastestUpdateForPackage(SourceRepository repo, PackageIdentity identity, VsProject project, bool allowPrerelease, bool isSafe) { string latestVersion = GetLastestVersionForPackage(repo, identity.Id, project.GetSupportedFrameworks(), allowPrerelease, identity.Version, isSafe); PackageIdentity latestIdentity = null; if (latestVersion != null) { latestIdentity = new PackageIdentity(identity.Id, NuGetVersion.Parse(latestVersion)); } return(latestIdentity); }
/// <summary> /// Handles the generation or update of a project wide dependency injection class and automatic registration of classes. /// </summary> /// <param name="source">The target project to add or update dependency injection in.</param> /// <param name="className">The name of the class that is used for service registration. This will be set to the constant <see cref="NetConstants.DefaultDependencyInjectionClassName"/> this can be overwritten with a custom class name.</param> /// <param name="automatedRegistrationMethodName">The name of the automatic transient class registration method. This will be set to the constant <see cref="NetConstants.DefaultAutomaticTransientClassRegistrationMethodName"/> this can be overwritten with a custom method name. </param> /// <param name="rejectedClassNames">Optional parameter that determines if the class name matches the name in the list it cannot be used for registration.</param> /// <param name="rejectedBaseClasses">Optional parameter that determines if the class inherits the target base class it cannot be used for registration.</param> /// <param name="targetInterfaceTypeForRegistration">Optional parameter that will determine which interface will be used for registration, This will be the interface itself or anything that inherits the interface.</param> public static async Task ProjectBuildDependencyInjectionAsync(VsProject source, string className = NetConstants.DefaultDependencyInjectionClassName, string automatedRegistrationMethodName = NetConstants.DefaultAutomaticTransientClassRegistrationMethodName, IEnumerable <string> rejectedClassNames = null, IEnumerable <ModelLookupData> rejectedBaseClasses = null, IEnumerable <ModelLookupData> targetInterfaceTypeForRegistration = null) { try { var registrationSourceCode = await GetRegistrationClassAsync(source, className, automatedRegistrationMethodName); if (registrationSourceCode == null) { throw new CodeFactoryException("Could load or create the dependency injection code."); } if (!registrationSourceCode.IsLoaded) { throw new CodeFactoryException("Could load or create the dependency injection code."); } var registrationClasses = await GetTransientClassesAsync(source, rejectedClassNames, rejectedBaseClasses, targetInterfaceTypeForRegistration); foreach (var diInfo in registrationClasses) { var targetNamespace = diInfo?.ClassData.Namespace; if (string.IsNullOrEmpty(targetNamespace)) { continue; } registrationSourceCode = await registrationSourceCode.AddUsingStatementAsync(targetNamespace); } var manager = registrationSourceCode.LoadNamespaceManager(source.DefaultNamespace); var methodSource = BuildTransientInjectionMethod(registrationClasses, false, true, automatedRegistrationMethodName, "serviceCollection", manager); if (string.IsNullOrEmpty(methodSource)) { throw new CodeFactoryException("Failed to create the automatic transient method"); } var registrationClass = registrationSourceCode.Classes.FirstOrDefault(c => c.Name == className); if (registrationClass == null) { throw new CodeFactoryException("Could not load the dependency injection class"); } var autoRegistrationMethod = registrationClass.Methods.FirstOrDefault(m => m.Name == automatedRegistrationMethodName); if (autoRegistrationMethod != null) { await autoRegistrationMethod.ReplaceAsync(methodSource); } else { await registrationClass.AddToEndAsync(methodSource); } } catch (CodeFactoryException) { throw; } catch (Exception unhandledError) { throw new CodeFactoryException( "Could not generate the registration class, an unhandled error occured, see exception for details.", unhandledError); } }
private void ProcessProject(List <ListBoxItemData> allFiles, ref int totalLines, ref int totalItems, ref long totalSize, VsSolutionProjectPart each, string projectPath, VsProject proj) { foreach (string file in proj.IncludedFiles) { string filename = projectPath + "\\" + file; FileInfo info = new FileInfo(filename); bool alreadyIndexed = false; foreach (ListBoxItemData lbid in allFiles) { if (lbid.Path + "\\" + lbid.Name == info.FullName) { alreadyIndexed = true; lbid.Project += ", " + each.Name; break; } } if (!alreadyIndexed) { int lines = File.ReadAllLines(filename).Length; ListBoxItemData lbid = new ListBoxItemData(info.Name, info.DirectoryName, info.LastWriteTime, FileType(filename), IOHelpers.FormatFileSize(info.Length), lines, each.Name); totalLines += lines; totalItems++; totalSize += info.Length; allFiles.Add(lbid); } } foreach (VsProject project in proj.IncludedProjects) { ProcessProject(allFiles, ref totalLines, ref totalItems, ref totalSize, each, projectPath, project); } }
public ShowProjectMessage(VsProject project) { Project = project; }
private bool ApplyShowOnlyProjectsWithoutSolutionFilter(VsProject project) { return(!ShowOnlyProjectsWithoutSolution || _projectSolutionUsages[project].Count == 0); }
public IntellisenseFilter(VsProject project) { m_project = project; }
private bool ApplyProjectReferenceFilter(VsProject project) { return(!IsProjectReferenceFilterEnabled || ProjectReferenceFilter == null || project.ProjectReferences.Any(r => r.Path == ProjectReferenceFilter.Path)); }
public int Generate(string wszInputFilePath, string bstrInputFileContents, string wszDefaultNamespace, IntPtr[] rgbOutputFileContents, out uint pcbOutput, IVsGeneratorProgress pGenerateProgress) { try { bool oldVsProject = site.GetType().IsCOMObject; InputFileContents = bstrInputFileContents; InputFilePath = wszInputFilePath; _codeGeneratorProgress = pGenerateProgress; _newFileNames.Clear(); int iFound = 0; uint itemId = 0; EnvDTE.ProjectItem item; Microsoft.VisualStudio.Shell.Interop.VSDOCUMENTPRIORITY[] pdwPriority = new Microsoft.VisualStudio.Shell.Interop.VSDOCUMENTPRIORITY[1]; // obtain a reference to the current project as an IVsProject type //Microsoft.VisualStudio.Shell.Interop.IVsProject VsProject = VsHelper.ToVsProject(_project); Microsoft.VisualStudio.Shell.Interop.IVsProject VsProject; if (oldVsProject) { VsProject = VsHelper.ToVsProject(_project); } else { VsProject = VsHelper.ToNewVsProject(_project, (Microsoft.VisualStudio.OLE.Interop.IServiceProvider)_project.DTE); } // this locates, and returns a handle to our source file, as a ProjectItem VsProject.IsDocumentInProject(InputFilePath, out iFound, pdwPriority, out itemId); // if our source file was found in the project (which it should have been) if (iFound != 0 && itemId != 0) { VsProject.GetItemContext(itemId, out Microsoft.VisualStudio.OLE.Interop.IServiceProvider oleSp); if (oleSp != null) { var sp = new ServiceProvider(oleSp); // convert our handle to a ProjectItem item = sp.GetService(typeof(EnvDTE.ProjectItem)) as EnvDTE.ProjectItem; } else { throw new ApplicationException("Unable to retrieve Visual Studio ProjectItem"); } } else { throw new ApplicationException("Unable to retrieve Visual Studio ProjectItem"); } var generatePath = Path.GetDirectoryName(wszInputFilePath); var configPath = Path.Combine(generatePath, "gen.config"); var genTypes = (from line in File.ReadAllLines(configPath) where !line.StartsWith("//", StringComparison.Ordinal) where !string.IsNullOrWhiteSpace(line) select line).ToArray(); var siFileName = Path.GetFileName(wszInputFilePath); Debug.WriteLine("Start Custom Tool."); int lineCount = bstrInputFileContents.Split('\n').Length; byte[] bytes = Encoding.UTF8.GetBytes(lineCount.ToString() + " LOC"); int length = bytes.Length; rgbOutputFileContents[0] = Marshal.AllocCoTaskMem(length); Marshal.Copy(bytes, 0, rgbOutputFileContents[0], length); pcbOutput = (uint)length; // Use ProcessStartInfo class. var startInfo = new ProcessStartInfo { FileName = "java.exe", UseShellExecute = false, RedirectStandardOutput = true, CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden, WorkingDirectory = Path.GetDirectoryName(_project.FullName) }; bool isfirst = true; var args = new StringBuilder(); foreach (var type in genTypes) { if (isfirst) { args.Append($"-jar \"{type}\" \"{wszInputFilePath}\""); isfirst = false; } else { if (!String.IsNullOrEmpty(type) && !type.StartsWith("//")) { var genComps = type.Split(); if (genComps.Length == 1) { args.Append($" -o \"{generatePath}\" {type}"); } else { args.Append(" -o \"" + generatePath + type.Substring(type.IndexOf(" ")).Trim() + "\" " + genComps[0]); Directory.CreateDirectory(generatePath + type.Substring(type.IndexOf(" ")).Trim()); } } } } startInfo.Arguments = args.ToString(); try { // Start the process with the info we specified. // Call WaitForExit and then the using-statement will close. using (var exeProcess = Process.Start(startInfo)) { exeProcess.WaitForExit(); //var output = ""; //while (!exeProcess.StandardOutput.EndOfStream) //{ // output += exeProcess.StandardOutput.ReadLine() + "\n"; //} var sb = new StringBuilder(); while (!exeProcess.StandardOutput.EndOfStream) { sb.AppendLine(exeProcess.StandardOutput.ReadLine()); } var output = sb.ToString(); bool start = false; foreach (var oline in Regex.Split(output, "\r\n|\r|\n")) { if (genTypes.Contains(oline) || genTypes.Any(x => x.StartsWith(oline))) { start = true; } if (start) { if (!string.IsNullOrEmpty(oline) && !oline.Trim().StartsWith("(") && !genTypes.Contains(oline)) { _newFileNames.Add(oline.Substring(oline.IndexOf(":") + 2).Trim()); } } } if (output.Contains("ParseException")) { var exception = output.Substring(output.IndexOf("ParseException")); exception = exception.Substring(0, exception.IndexOf('\n')); uint line = uint.Parse(exception.Split(new string[] { " line " }, StringSplitOptions.None)[1].Split(',')[0]) - 1; uint column = uint.Parse(exception.Split(new string[] { " column " }, StringSplitOptions.None)[1].Split('.')[0]) - 1; GeneratorError(4, output.Replace("\n", " "), line, column); foreach (EnvDTE.ProjectItem childItem in item.ProjectItems) { childItem.Delete(); } return(VSConstants.E_FAIL); } else if (output.Contains("bbd.jportal.TokenMgrError")) { var exception = output.Substring(output.IndexOf("bbd.jportal.TokenMgrError")); exception = exception.Substring(0, exception.IndexOf('\n')); uint line = uint.Parse(exception.Split(new string[] { " line " }, StringSplitOptions.None)[1].Split(',')[0]) - 1; uint column = uint.Parse(exception.Split(new string[] { " column " }, StringSplitOptions.None)[1].Split('.')[0]) - 1; GeneratorError(4, output.Replace("\n", " "), line, column); foreach (EnvDTE.ProjectItem childItem in item.ProjectItems) { childItem.Delete(); } return(VSConstants.E_FAIL); } } } catch (Exception ex) { pcbOutput = 0; GeneratorError(4, ex.ToString(), 0, 0); File.WriteAllText("sifilegenerator.log", "Si file generation failed for: " + Directory.GetCurrentDirectory() + "\r\n"); File.AppendAllText("sifilegenerator.log", ex.Message + "\n\n" + ex.StackTrace + "\n\n" + ex.InnerException); File.AppendAllText("sifilegenerator.log", Environment.NewLine + "-----------------------------------------------------------------------------" + Environment.NewLine); return(VSConstants.E_FAIL); } foreach (var pfile in _newFileNames.ToList()) { try { if (File.Exists(pfile) && Directory.GetParent(pfile).FullName == generatePath) { EnvDTE.ProjectItem itm = item.ProjectItems.AddFromFile(pfile); } else { _newFileNames.Remove(pfile); } } catch (COMException) { } } /* * Here you may wish to perform some addition logic * such as, setting a custom tool for the target file if it * is intented to perform its own generation process. * Or, set the target file as an 'Embedded Resource' so that * it is embedded into the final Assembly. * * EnvDTE.Property prop = itm.Properties.Item("CustomTool"); * //// set to embedded resource * itm.Properties.Item("BuildAction").Value = 3; * if (String.IsNullOrEmpty((string)prop.Value) || !String.Equals((string)prop.Value, typeof(AnotherCustomTool).Name)) * { * prop.Value = typeof(AnotherCustomTool).Name; * } */ // perform some clean-up, making sure we delete any old (stale) target-files foreach (EnvDTE.ProjectItem childItem in item.ProjectItems) { if (!_newFileNames.Select(x => x.Substring(x.LastIndexOf("\\") + 1)).Contains(childItem.Name)) { // then delete it childItem.Delete(); } } // generate our summary content for our 'single' file byte[] summaryData = GenerateSummaryContent(); if (summaryData == null) { rgbOutputFileContents[0] = IntPtr.Zero; pcbOutput = 0; } else { // return our summary data, so that Visual Studio may write it to disk. rgbOutputFileContents[0] = Marshal.AllocCoTaskMem(summaryData.Length); Marshal.Copy(summaryData, 0, rgbOutputFileContents[0], summaryData.Length); pcbOutput = (uint)summaryData.Length; } } catch (Exception e) { pcbOutput = 0; GeneratorError(4, e.ToString(), 0, 0); var errorPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), "SiFileGenerator"); if (!Directory.Exists(errorPath)) { Directory.CreateDirectory(errorPath); } var filePath = Path.Combine(errorPath, "Error.txt"); using (var writer = new StreamWriter(filePath, true)) { writer.WriteLine(e); writer.WriteLine(Environment.NewLine + "-----------------------------------------------------------------------------" + Environment.NewLine); } return(VSConstants.E_FAIL); } return(VSConstants.S_OK); }
private bool ApplyNuGetPackageFilter(VsProject project) { return(!IsNuGetPackageFilterEnabled || NuGetPackageFilter == null || project.NuGetReferences.Any(n => n.Name == NuGetPackageFilter.Name && n.Version == NuGetPackageFilter.Version)); }
public ScriptParser(string path, VsProject project) { _path = path; _project = project; }
/// <summary> /// Get latest JObject for package identity /// </summary> /// <param name="repo"></param> /// <param name="identity"></param> /// <param name="allowPrerelease"></param> /// <returns></returns> public static List<JObject> GetLastestJObjectsForPackage(SourceRepository repo, JObject jObject, VsProject project, bool allowPrerelease, int skip, int take, bool takeAllVersions) { List<JObject> jObjects = new List<JObject>(); string id = jObject.Value<string>(Properties.PackageId); string version = jObject.Value<string>(Properties.Version); NuGetVersion nVersion = GetNuGetVersionFromString(version); if (!takeAllVersions) { string latestVersion = GetLastestVersionForPackage(repo, id, project.GetSupportedFrameworks(), allowPrerelease, nVersion, false); if (latestVersion != null) { NuGetVersion laVersion = GetNuGetVersionFromString(latestVersion); if (laVersion > nVersion) { Task<JObject> task = repo.GetPackageMetadata(id, laVersion); JObject latestJObject = task.Result; jObjects.Add(latestJObject); } } } else { JObject package = GetJObjectForPackageId(repo, id, project.GetSupportedFrameworks(), allowPrerelease, skip, take); IEnumerable<NuGetVersion> versionList = GetAllVersionsForPackageId(package).OrderByDescending(v => v); // Work around a bug in repo.Search(), where prerelease versions are not filtered out. if (!allowPrerelease) { versionList = versionList.Where(p => p > nVersion && p.IsPrerelease == false); } else { versionList = versionList.Where(p => p > nVersion); } foreach (NuGetVersion updateVersion in versionList) { JObject updateObject = GetPackageByIdAndVersion(repo, id, updateVersion.ToNormalizedString(), allowPrerelease); jObjects.Add(updateObject); } } return jObjects; }
public async Task MigrateSingleASPXFile(VsDocument aspxSourcefile, VsProject blazorServerProject) { try { //VsCSharpSource aspxCodeBehindFile //Getting the formatted names that will be used in migrating the ASPX file and its code behind to the blazor project. string targetFileNameNoExtension = Path.GetFileNameWithoutExtension(aspxSourcefile.Path); string aspxCodeBehindFileName = $"{targetFileNameNoExtension}.aspx.cs"; string razorPageFileName = $"{targetFileNameNoExtension}.razor"; string razorPageCodeBehindFileName = $"{targetFileNameNoExtension}.razor.cs"; //Calling into the CodeFactory project system and getting all the direct children of the project. var blazorRootModels = await blazorServerProject.GetChildrenAsync(false); //Getting the pages folder from the blazor project. var blazorPagesFolder = blazorRootModels.FirstOrDefault(m => m.ModelType == VisualStudioModelType.ProjectFolder & m.Name.ToLower().Equals("pages")) as VsProjectFolder; //If the pages folder was not found fail this step and return. if (blazorPagesFolder == null) { await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Error, "No pages folder was found in the blazor project, cannot continue the aspx file conversion."); return; } //Call the CodeFactory project system to get all the current children of the pages project folder. var pagesFolderModels = await blazorPagesFolder.GetChildrenAsync(true); //Filtering out everything but documents. var pages = pagesFolderModels.Where(m => m.ModelType == VisualStudioModelType.Document) .Cast <VsDocument>(); //Searching for an existing razor page. We will delete razor pages and recreate them. var currentRazorPage = pages.FirstOrDefault(p => p.Path.ToLower().EndsWith(razorPageFileName.ToLower())); if (currentRazorPage != null) { //Razor page was found removing the razor page. bool removedPage = await currentRazorPage.DeleteAsync(); if (removedPage) { await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Information, $"Removed the razor page {razorPageFileName}"); var currentRazorPageCodeBehind = pages.FirstOrDefault(p => p.Path.ToLower().EndsWith(razorPageCodeBehindFileName.ToLower())); if (currentRazorPageCodeBehind != null) { if (File.Exists(currentRazorPageCodeBehind.Path)) { bool removedCodeBehind = await currentRazorPageCodeBehind.DeleteAsync(); if (removedCodeBehind) { await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Information, $"Removed the razor page code behind file {razorPageCodeBehindFileName}"); } else { await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Error, $"Could not remove the razor page code behind file {razorPageCodeBehindFileName}.The target ASPX file will not be migrated."); return; } } } } else { await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Error, $"Could not remove the razor page {razorPageFileName}.The target ASPX file will not be migrated."); return; } } var aspxChildren = await aspxSourcefile.GetChildrenAsync(true); var codeBehindFile = aspxChildren .Where(c => (c.IsSourceCode == true) && (c.SourceType == SourceCodeType.CSharp)).FirstOrDefault(); //Converting the aspx page and the code behind file if it was found. await ConvertAspxPage(aspxSourcefile, blazorServerProject, blazorPagesFolder, null, codeBehindFile); await _statusTracking.UpdateMigrationFinishedAsync(); } catch (Exception unhandledError) { //Dumping the exception that occured directly into the status so the user can see what happened. await _statusTracking.UpdateCurrentStatusAsync(MigrationStepEnum.AspxPages, MessageTypeEnum.Error, $"The following unhandled error occured. '{unhandledError.Message}'"); } }