public override async Task DoWorkAsync(CancellationToken cancellationToken, BaseUpdateViewModel viewModel, Solution solution) { if (solution == null) { return; } if (!(viewModel is SolutionUpdateViewModel updateViewModel)) { throw new ArgumentException($"Argument {nameof(viewModel)} must be of type {nameof(SolutionUpdateViewModel)}"); } await _licenseHeaderExtension.JoinableTaskFactory.SwitchToMainThreadAsync(); var allSolutionProjectsSearcher = new AllSolutionProjectsSearcher(); var projectsInSolution = allSolutionProjectsSearcher.GetAllProjects(solution); updateViewModel.ProcessedProjectCount = 0; updateViewModel.ProjectCount = projectsInSolution.Count; var removeAllLicenseHeadersCommand = new RemoveLicenseHeaderFromAllFilesInProjectHelper(cancellationToken, _licenseHeaderExtension, updateViewModel); foreach (var project in projectsInSolution) { await removeAllLicenseHeadersCommand.ExecuteAsync(project); await IncrementProjectCountAsync(updateViewModel).ConfigureAwait(true); } }
public AddLicenseHeaderToAllFilesInProjectHelper( CancellationToken cancellationToken, ILicenseHeaderExtension licenseHeaderExtension, BaseUpdateViewModel baseUpdateViewModel) { _cancellationToken = cancellationToken; _licenseHeaderExtension = licenseHeaderExtension; _baseUpdateViewModel = baseUpdateViewModel; }
/// <summary> /// Creates a replacer progress that represents the progress of updated files in folders and projects. /// </summary> /// <param name="viewModel"> /// Specifies the view model that contains the progress bar whose update progress should be /// visualized. /// </param> /// <param name="projectName">Specifies the name of the project that is updated.</param> /// <param name="fileOpenedStatus">Specifies what files are currently open in the current project.</param> /// <param name="cancellationToken"> /// Specifies the cancellation token that indicates if the current updating progress has /// been cancelled by the user. /// </param> public static IProgress <ReplacerProgressContentReport> CreateProgress( BaseUpdateViewModel viewModel, string projectName, IDictionary <string, bool> fileOpenedStatus, CancellationToken cancellationToken) { return(new ReplacerProgress <ReplacerProgressContentReport> ( report => OnProgressReportedAsync(report, viewModel, projectName, fileOpenedStatus, cancellationToken).FireAndForget())); }
/// <summary> /// Processes a range of <see cref="ReplacerResult{TSuccess,TError}" /> objects, including possible error handling. /// </summary> /// <param name="result">Specifies the replacer result. Indicates whether the specific operation succeeded or failed.</param> /// <param name="licenseHeaderExtension"> /// A <see cref="ILicenseHeaderExtension" /> instance used to access members exposed /// by the LHM Extension Package. /// </param> /// <param name="viewModel"> /// A <see cref="BaseUpdateViewModel" /> instance used to update progress indicator properties if a /// <see cref="LicenseHeaderReplacer" /> newly needs to be invoked. /// </param> /// <param name="projectName"> /// The name of the project the files updated by a <see cref="LicenseHeaderReplacer" /> operation /// belong to. /// </param> /// <param name="fileOpenedStatus"> /// Provides information on which files (full path, dictionary key) are currently opened /// (values). /// </param> /// <param name="cancellationToken"> /// A <see cref="CancellationToken" /> that can be used to cancel pending Core operations /// if they have not been started yet. /// </param> public static async Task HandleResultAsync( IEnumerable <ReplacerResult <ReplacerSuccess, ReplacerError <LicenseHeaderContentInput> > > result, ILicenseHeaderExtension licenseHeaderExtension, BaseUpdateViewModel viewModel, string projectName, IDictionary <string, bool> fileOpenedStatus, CancellationToken cancellationToken) { // collect NonCommentText-errors and ask if license header should still be inserted var errors = result.Where(replacerResult => !replacerResult.IsSuccess).Select(replacerResult => replacerResult.Error).ToList(); var nonCommentTextErrorsByExtension = errors.Where(x => x.Type == ReplacerErrorType.NonCommentText).GroupBy(x => Path.GetExtension(x.Input.DocumentPath)); var inputIgnoringNonCommentText = new List <LicenseHeaderContentInput>(); foreach (var extension in nonCommentTextErrorsByExtension) { var message = string.Format(Resources.Warning_InvalidLicenseHeader, extension.Key).ReplaceNewLines(); if (!MessageBoxHelper.AskYesNo(message, Resources.Warning, true)) { continue; } foreach (var failedFile in extension) { failedFile.Input.IgnoreNonCommentText = true; inputIgnoringNonCommentText.Add(failedFile.Input); } } // collect other errors and the ones that occurred while "force-inserting" headers with non-comment-text var overallErrors = errors.Where(x => x.Type != ReplacerErrorType.NonCommentText && x.Type != ReplacerErrorType.LicenseHeaderDocument).ToList(); if (inputIgnoringNonCommentText.Count > 0) { viewModel.FileCountCurrentProject = inputIgnoringNonCommentText.Count; var resultIgnoringNonCommentText = await licenseHeaderExtension.LicenseHeaderReplacer.RemoveOrReplaceHeader( inputIgnoringNonCommentText, CreateProgress (viewModel, projectName, fileOpenedStatus, cancellationToken), cancellationToken); overallErrors.AddRange(resultIgnoringNonCommentText.Where(replacerResult => !replacerResult.IsSuccess).Select(replacerResult => replacerResult.Error)); } // display all errors collected from "first attempt" and "force-insertion" if (overallErrors.Count == 0) { return; } MessageBoxHelper.ShowError($"{overallErrors.Count} unexpected errors have occurred. See output window or log file for more details"); foreach (var otherError in overallErrors) { s_log.Error($"File '{otherError.Input.DocumentPath}' failed: {otherError.Description}"); } }
public override async Task DoWorkAsync(CancellationToken cancellationToken, BaseUpdateViewModel viewModel) { await _licenseHeaderExtension.JoinableTaskFactory.SwitchToMainThreadAsync(); var obj = _licenseHeaderExtension.GetSolutionExplorerItem(); var removeAllLicenseHeadersCommand = new RemoveLicenseHeaderFromAllFilesInProjectHelper(cancellationToken, _licenseHeaderExtension, viewModel); await removeAllLicenseHeadersCommand.ExecuteAsync(obj); }
private static async Task HandleAddLicenseHeaderToAllFilesInProjectResultAsync( CancellationToken cancellationToken, ILicenseHeaderExtension serviceProvider, object obj, AddLicenseHeaderToAllFilesResult addResult, BaseUpdateViewModel baseUpdateViewModel) { await serviceProvider.JoinableTaskFactory.SwitchToMainThreadAsync(); var project = obj as Project; var projectItem = obj as ProjectItem; if (project == null && projectItem == null) { return; } var currentProject = project; if (projectItem != null) { currentProject = projectItem.ContainingProject; } if (addResult.NoHeaderFound) { // No license header found... var solutionSearcher = new AllSolutionProjectsSearcher(); var projects = solutionSearcher.GetAllProjects(serviceProvider.Dte2.Solution); if (projects.Any(projectInSolution => LicenseHeaderFinder.GetHeaderDefinitionForProjectWithoutFallback(projectInSolution) != null)) { baseUpdateViewModel.ProcessedFilesCountCurrentProject = 0; // If another project has a license header, offer to add a link to the existing one. if (MessageBoxHelper.AskYesNo(Resources.Question_AddExistingDefinitionFileToProject.ReplaceNewLines())) { ExistingLicenseHeaderDefinitionFileAdder.AddDefinitionFileToOneProject(currentProject.FileName, currentProject.ProjectItems); await AddLicenseHeaderToAllFilesAsync(cancellationToken, serviceProvider, baseUpdateViewModel); } } else { // If no project has a license header, offer to add one for the solution. if (MessageBoxHelper.AskYesNo(Resources.Question_AddNewLicenseHeaderDefinitionForSolution.ReplaceNewLines())) { AddNewSolutionLicenseHeaderDefinitionFileCommand.Instance.Invoke(serviceProvider.Dte2.Solution); } } } }
public static async Task AddLicenseHeaderToAllFilesAsync( CancellationToken cancellationToken, ILicenseHeaderExtension serviceProvider, BaseUpdateViewModel folderProjectUpdateViewModel) { await serviceProvider.JoinableTaskFactory.SwitchToMainThreadAsync(); var obj = serviceProvider.GetSolutionExplorerItem(); var addLicenseHeaderToAllFilesCommand = new AddLicenseHeaderToAllFilesInProjectHelper( cancellationToken, serviceProvider, folderProjectUpdateViewModel); var addLicenseHeaderToAllFilesResult = await addLicenseHeaderToAllFilesCommand.RemoveOrReplaceHeadersAsync(obj); await HandleLinkedFilesAndShowMessageBoxAsync(serviceProvider, addLicenseHeaderToAllFilesResult.LinkedItems); await HandleAddLicenseHeaderToAllFilesInProjectResultAsync( cancellationToken, serviceProvider, obj, addLicenseHeaderToAllFilesResult, folderProjectUpdateViewModel); }
private static async Task OnProgressReportedAsync( ReplacerProgressContentReport progress, BaseUpdateViewModel baseUpdateViewModel, string projectName, IDictionary <string, bool> fileOpenedStatus, CancellationToken cancellationToken) { await LicenseHeadersPackage.Instance.JoinableTaskFactory.SwitchToMainThreadAsync(); if (!cancellationToken.IsCancellationRequested) { var result = new ReplacerResult <ReplacerSuccess, ReplacerError <LicenseHeaderContentInput> > ( new ReplacerSuccess(progress.ProcessedFilePath, progress.ProcessFileNewContent)); if (fileOpenedStatus.TryGetValue(progress.ProcessedFilePath, out var wasOpen)) { await HandleResultAsync(result, LicenseHeadersPackage.Instance, wasOpen, false); } else { await HandleResultAsync(result, LicenseHeadersPackage.Instance, false, false); } } if (baseUpdateViewModel == null) { return; } baseUpdateViewModel.FileCountCurrentProject = progress.TotalFileCount; baseUpdateViewModel.ProcessedFilesCountCurrentProject = progress.ProcessedFileCount; if (baseUpdateViewModel is SolutionUpdateViewModel solutionUpdateViewModel) { solutionUpdateViewModel.CurrentProject = projectName; } }
public override async Task DoWorkAsync(CancellationToken cancellationToken, BaseUpdateViewModel viewModel) { await FolderProjectMenuHelper.AddLicenseHeaderToAllFilesAsync(cancellationToken, _licenseHeaderExtension, viewModel); }
public override Task DoWorkAsync(CancellationToken cancellationToken, BaseUpdateViewModel viewModel, Solution solution) { return(DoWorkAsync(cancellationToken, viewModel)); }
/// <summary> /// Carries out the work that the corresponding <see cref="IMenuItemButtonHandler" /> /// instance wants to delegate to this <see cref="MenuItemButtonHandlerImplementation" /> instance. /// </summary> /// <param name="cancellationToken">The token to monitor for cancellation requests</param> /// <param name="viewModel"> /// The view model this implementation needs to update in order to reflect process in the corresponding /// dialog window. /// </param> public abstract Task DoWorkAsync(CancellationToken cancellationToken, BaseUpdateViewModel viewModel);
/// <summary> /// Carries out the work that the corresponding <see cref="IMenuItemButtonHandler" /> instance wants to delegate to this /// <see cref="MenuItemButtonHandlerImplementation" /> instance. /// </summary> /// <param name="cancellationToken">The token to monitor for cancellation requests</param> /// <param name="viewModel"> /// The view model this implementation needs to update in order to reflect process in the corresponding /// dialog window. /// </param> /// <param name="solution">The <see cref="Solution" /> instance the work to be done is related with.</param> /// <param name="window"> /// The <see cref="System.Windows.Window" /> that is on top of the screen while the work to be done is /// being carried out. /// </param> /// <remarks> /// If not both a Solution and a Window are strictly required for the desired work to be done (even though one or both of /// them might even be /// present, i. e. could theoretically be supplied), use another overload, if possible. If this is not possible, a /// suitable /// overload that does not expect the superfluous parameters is called by the actual implementation. /// </remarks> public abstract Task DoWorkAsync(CancellationToken cancellationToken, BaseUpdateViewModel viewModel, Solution solution, Window window);
private async Task HandleButtonInternalAsync(object solutionObject, MenuItemButtonHandlerImplementation handler, BaseUpdateViewModel solutionUpdateViewModel) { await LicenseHeadersPackage.Instance.JoinableTaskFactory.SwitchToMainThreadAsync(); if (!(solutionObject is Solution solution)) { return; } _cancellationTokenSource = new CancellationTokenSource(); try { await handler.DoWorkAsync(_cancellationTokenSource.Token, solutionUpdateViewModel, solution, _dialog); } catch (OperationCanceledException) { await LicenseHeadersPackage.Instance.JoinableTaskFactory.SwitchToMainThreadAsync(); _dialog.Close(); } catch (Exception ex) { MessageBoxHelper.ShowMessage( $"The operation '{handler.Description}' failed with the exception '{ex.Message}'. See Visual Studio Output Window for Details."); s_log.Error($"The operation '{handler.Description}' failed.", ex); } await LicenseHeadersPackage.Instance.JoinableTaskFactory.SwitchToMainThreadAsync(); _dialog.Close(); }
private async Task IncrementProjectCountAsync(BaseUpdateViewModel viewModel) { await _licenseHeaderExtension.JoinableTaskFactory.SwitchToMainThreadAsync(); viewModel.ProcessedProjectCount++; }
public override Task DoWorkAsync(CancellationToken cancellationToken, BaseUpdateViewModel viewModel) { throw new NotSupportedException(UnsupportedOverload); }
public override async Task DoWorkAsync(CancellationToken cancellationToken, BaseUpdateViewModel viewModel, Solution solution, Window window) { if (solution == null) { return; } if (!(viewModel is SolutionUpdateViewModel updateViewModel)) { throw new ArgumentException($"Argument {nameof(viewModel)} must be of type {nameof(SolutionUpdateViewModel)}"); } await _licenseHeaderExtension.JoinableTaskFactory.SwitchToMainThreadAsync(); var solutionHeaderDefinitions = LicenseHeaderFinder.GetHeaderDefinitionForSolution(solution); var allSolutionProjectsSearcher = new AllSolutionProjectsSearcher(); var projectsInSolution = allSolutionProjectsSearcher.GetAllProjects(solution); var projectsWithoutLicenseHeaderFile = projectsInSolution .Where(project => LicenseHeaderFinder.GetHeaderDefinitionForProjectWithoutFallback(project) == null) .ToList(); var projectsWithLicenseHeaderFile = projectsInSolution .Where(project => LicenseHeaderFinder.GetHeaderDefinitionForProjectWithoutFallback(project) != null) .ToList(); if (solutionHeaderDefinitions != null || !projectsWithoutLicenseHeaderFile.Any()) { // Every project is covered either by a solution or project level license header definition, go ahead and add them. await AddLicenseHeaderToProjectsAsync(cancellationToken, projectsInSolution, updateViewModel); } else { // Some projects are not covered by a header. var someProjectsHaveDefinition = projectsWithLicenseHeaderFile.Count > 0; if (someProjectsHaveDefinition) { // Some projects have a header. Ask the user if they want to add an existing header to the uncovered projects. if (await DefinitionFilesShouldBeAddedAsync(projectsWithoutLicenseHeaderFile, window)) { ExistingLicenseHeaderDefinitionFileAdder.AddDefinitionFileToMultipleProjects(projectsWithoutLicenseHeaderFile); } await AddLicenseHeaderToProjectsAsync(cancellationToken, projectsInSolution, updateViewModel); } else { // No projects have definition. Ask the user if they want to add a solution level header definition. if (await MessageBoxHelper.AskYesNoAsync(window, Resources.Question_AddNewLicenseHeaderDefinitionForSolution.ReplaceNewLines()).ConfigureAwait(true)) { AddNewSolutionLicenseHeaderDefinitionFileCommand.Instance.Invoke(solution); // They want to go ahead and apply without editing. if (!await MessageBoxHelper.AskYesNoAsync(window, Resources.Question_StopForConfiguringDefinitionFilesSingleFile).ConfigureAwait(true)) { await AddLicenseHeaderToProjectsAsync(cancellationToken, projectsInSolution, updateViewModel); } } } } }