示例#1
0
        /// <summary>
        ///   Tries to open a <see cref="ProjectItem" /> such that content modification operations are possible.
        /// </summary>
        /// <param name="item">The <see cref="ProjectItem" /> to be opened.</param>
        /// <param name="extension">
        ///   The <see cref="ILicenseHeaderExtension" /> instance used to access the currently configured
        ///   language definitions.
        /// </param>
        /// <returns>
        ///   Returns <see langword="true" /> if opening <paramref name="item" /> succeeded or was not necessary, otherwise
        ///   <see langword="false" />.
        /// </returns>
        public static bool TryOpenDocument(ProjectItem item, ILicenseHeaderExtension extension)
        {
            try
            {
                ThreadHelper.ThrowIfNotOnUIThread();

                // Opening files potentially having non-text content (.png, .snk) might result in a Visual Studio error "Some bytes have been replaced with the
                // Unicode substitution character while loading file ...". In order to avoid this, files with unknown extensions are not opened. However, in order
                // to keep such files eligible as Core input, still return true
                var languageForExtension = extension.LicenseHeaderReplacer.GetLanguageFromExtension(Path.GetExtension(item.FileNames[1]));
                if (languageForExtension == null)
                {
                    return(true);
                }

                item.Open(Constants.vsViewKindTextView);
                return(true);
            }
            catch (COMException)
            {
                return(false);
            }
            catch (IOException)
            {
                return(false);
            }
        }
示例#2
0
        /// <summary>
        ///   Adds the license header text for the specified extension to the given project item.
        /// </summary>
        /// <param name="item">Specifies the project item in which the license header text is to be inserted.</param>
        /// <param name="extension">Specifies the extension of the language whose content should be added to the project item.</param>
        /// <param name="calledByUser">Specifies whether this method was called explicitly by the user or by the program.</param>
        /// <returns></returns>
        public static async Task AddLicenseHeaderToItemAsync(
            this ProjectItem item,
            ILicenseHeaderExtension extension,
            bool calledByUser)
        {
            if (item == null || ProjectItemInspection.IsLicenseHeader(item))
            {
                return;
            }

            await extension.JoinableTaskFactory.SwitchToMainThreadAsync();

            var headers = LicenseHeaderFinder.GetHeaderDefinitionForItem(item);

            if (headers != null)
            {
                var content = item.GetContent(out var wasAlreadyOpen, extension);
                if (content == null)
                {
                    return;
                }

                var result = await extension.LicenseHeaderReplacer.RemoveOrReplaceHeader(
                    new LicenseHeaderContentInput (content, item.FileNames[1], headers, item.GetAdditionalProperties()));

                await CoreHelpers.HandleResultAsync(result, extension, wasAlreadyOpen, calledByUser);

                return;
            }

            if (calledByUser && LicenseHeaderDefinitionFileHelper.ShowQuestionForAddingLicenseHeaderFile(item.ContainingProject, extension.DefaultLicenseHeaderPageModel))
            {
                await AddLicenseHeaderToItemAsync(item, extension, true);
            }
        }
        public void TestNoLicenseHeaderFile()
        {
            ILicenseHeaderExtension extension   = MockRepository.GenerateStub <ILicenseHeaderExtension> ();
            ProjectItem             projectItem = MockRepository.GenerateMock <ProjectItem>();

            projectItem.Expect(x => x.Name).Return("projectItem.cs");

            ILinkedFileFilter     linkedFileFilter      = MockRepository.GenerateMock <ILinkedFileFilter> ();
            LicenseHeaderReplacer licenseHeaderReplacer = MockRepository.GenerateStrictMock <LicenseHeaderReplacer> (extension);

            linkedFileFilter.Expect(x => x.NoLicenseHeaderFile).Return(new List <ProjectItem> {
                projectItem
            });
            linkedFileFilter.Expect(x => x.ToBeProgressed).Return(new List <ProjectItem> ());
            linkedFileFilter.Expect(x => x.NotInSolution).Return(new List <ProjectItem> ());


            LinkedFileHandler linkedFileHandler = new LinkedFileHandler();

            linkedFileHandler.Handle(licenseHeaderReplacer, linkedFileFilter);

            string expectedMessage = string.Format(Resources.LinkedFileUpdateInformation, "projectItem.cs")
                                     .Replace(@"\n", "\n");

            Assert.AreEqual(expectedMessage, linkedFileHandler.Message);
        }
        public static void AddExistingLicenseHeaderDefinitionFile(ILicenseHeaderExtension serviceProvider)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            var project     = serviceProvider.GetSolutionExplorerItem() as Project;
            var projectItem = serviceProvider.GetSolutionExplorerItem() as ProjectItem;

            string fileName;

            if (project != null)
            {
                fileName = project.FileName;
            }
            else if (projectItem != null)
            {
                fileName = projectItem.Name;
            }
            else
            {
                return;
            }

            ProjectItems projectItems = null;

            if (project != null)
            {
                projectItems = project.ProjectItems;
            }
            else if (projectItem != null)
            {
                projectItems = projectItem.ProjectItems;
            }

            ExistingLicenseHeaderDefinitionFileAdder.AddDefinitionFileToOneProject(fileName, projectItems);
        }
        public static void AddNewLicenseHeaderDefinitionFile(ILicenseHeaderExtension serviceProvider)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            var page         = serviceProvider.DefaultLicenseHeaderPageModel;
            var solutionItem = serviceProvider.GetSolutionExplorerItem();
            var project      = solutionItem as Project;

            if (project == null)
            {
                if (solutionItem is ProjectItem projectItem)
                {
                    LicenseHeaderDefinitionFileHelper.AddLicenseHeaderDefinitionFile(projectItem, page);
                }
            }

            if (project == null)
            {
                return;
            }

            var licenseHeaderDefinitionFile = LicenseHeaderDefinitionFileHelper.AddHeaderDefinitionFile(project, page);

            licenseHeaderDefinitionFile.Open(Constants.vsViewKindCode).Activate();
        }
示例#6
0
 public AddLicenseHeaderToAllFilesInProjectHelper(
     CancellationToken cancellationToken,
     ILicenseHeaderExtension licenseHeaderExtension,
     BaseUpdateViewModel baseUpdateViewModel)
 {
     _cancellationToken      = cancellationToken;
     _licenseHeaderExtension = licenseHeaderExtension;
     _baseUpdateViewModel    = baseUpdateViewModel;
 }
示例#7
0
        /// <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}");
            }
        }
示例#8
0
        private static void ProcessSuccess(ReplacerSuccess replacerSuccess, ILicenseHeaderExtension extension, bool isOpen)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            if (!File.Exists(replacerSuccess.FilePath) || TrySetContent(replacerSuccess.FilePath, extension.Dte2.Solution, replacerSuccess.NewContent, isOpen, extension))
            {
                return;
            }

            s_log.Error($"Updating license header for file {replacerSuccess.FilePath} failed.");
            MessageBoxHelper.ShowError($"Updating license header for file {replacerSuccess.FilePath} failed.");
        }
示例#9
0
        /// <summary>
        ///   Processes the given <see cref="ReplacerResult{TSuccess,TError}" /> object, including handling errors that possibly
        ///   occurred.
        /// </summary>
        /// <param name="result">Specifies the replacer result. Indicates whether the specific operation succeeded or failed.</param>
        /// <param name="extension">
        ///   A <see cref="ILicenseHeaderExtension" /> instance used to access members exposed by the LHM
        ///   Extension Package.
        /// </param>
        /// <param name="isOpen">Specifies if the current file is currently open.</param>
        /// <param name="calledByUser">
        ///   Specifies whether this method was called explicitly by the user or implicitly by the
        ///   program.
        /// </param>
        public static async Task HandleResultAsync(
            ReplacerResult <ReplacerSuccess, ReplacerError <LicenseHeaderContentInput> > result,
            ILicenseHeaderExtension extension,
            bool isOpen,
            bool calledByUser)
        {
            if (result.IsSuccess)
            {
                await extension.JoinableTaskFactory.SwitchToMainThreadAsync();

                ProcessSuccess(result.Success, extension, isOpen);
                return;
            }

            if (!calledByUser)
            {
                return;
            }

            var error = result.Error;

            switch (error.Type)
            {
            case ReplacerErrorType.NonCommentText:
                error.Input.IgnoreNonCommentText = true;
                if (!MessageBoxHelper.AskYesNo(error.Description, Resources.Warning, true))
                {
                    return;
                }

                var resultIgnoringNonCommentText = await extension.LicenseHeaderReplacer.RemoveOrReplaceHeader(error.Input);

                if (resultIgnoringNonCommentText.IsSuccess)
                {
                    ProcessSuccess(resultIgnoringNonCommentText.Success, extension, isOpen);
                    return;
                }

                error = resultIgnoringNonCommentText.Error;
                ProcessError(error);
                break;

            case ReplacerErrorType.LanguageNotFound:
                return; // ignore such an error (i. e. do not propagate to user)

            case ReplacerErrorType.LicenseHeaderDocument:
                return; // ignore such an error (i. e. do not propagate to user)

            default:
                ProcessError(error);
                break;
            }
        }
      public void SetUp ()
      {
        _extensionMock = MockRepository.GenerateMock<ILicenseHeaderExtension> ();
        _optionsPage = MockRepository.GenerateMock<IOptionsPage>();
        _replacer = new LicenseHeaderReplacer (_extensionMock);
        _projectItem = MockRepository.GenerateMock<ProjectItem> ();
        _languagesPage = MockRepository.GenerateMock<ILanguagesPage>();
        _extensionMock.Expect (x => x.LanguagesPage).Return (_languagesPage);
        _extensionMock.Expect (x => x.OptionsPage).Return (_optionsPage);
        _optionsPage.Expect (x => x.UseRequiredKeywords).Return (true);
        _optionsPage.Expect (x => x.RequiredKeywords).Return ("");

        _projectItem.Stub(x => x.Open(Constants.vsViewKindTextView)).Return(MockRepository.GenerateMock<Window>());
      }
            public void SetUp()
            {
                _extensionMock = MockRepository.GenerateMock <ILicenseHeaderExtension>();
                _optionsPage   = MockRepository.GenerateMock <IOptionsPage>();
                _replacer      = new LicenseHeaderReplacer(_extensionMock);
                _projectItem   = MockRepository.GenerateMock <ProjectItem>();
                _languagesPage = MockRepository.GenerateMock <ILanguagesPage>();
                _extensionMock.Expect(x => x.LanguagesPage).Return(_languagesPage);
                _extensionMock.Expect(x => x.OptionsPage).Return(_optionsPage);
                _optionsPage.Expect(x => x.UseRequiredKeywords).Return(true);
                _optionsPage.Expect(x => x.RequiredKeywords).Return("");

                _projectItem.Stub(x => x.Open(Constants.vsViewKindTextView)).Return(MockRepository.GenerateMock <Window>());
            }
        private static async Task HandleLinkedFilesAndShowMessageBoxAsync(ILicenseHeaderExtension serviceProvider, IEnumerable <ProjectItem> linkedItems)
        {
            ILinkedFileFilter linkedFileFilter = new LinkedFileFilter(serviceProvider.Dte2.Solution);

            linkedFileFilter.Filter(linkedItems);

            var linkedFileHandler = new LinkedFileHandler(serviceProvider);
            await linkedFileHandler.HandleAsync(linkedFileFilter);

            if (linkedFileHandler.Message != string.Empty)
            {
                MessageBoxHelper.ShowMessage(linkedFileHandler.Message);
            }
        }
        public void TestNoProjectItems()
        {
            Solution solution = MockRepository.GenerateStub <Solution>();
            ILicenseHeaderExtension extension = MockRepository.GenerateStub <ILicenseHeaderExtension>();

            LinkedFileFilter      linkedFileFilter      = MockRepository.GenerateStrictMock <LinkedFileFilter>(solution);
            LicenseHeaderReplacer licenseHeaderReplacer = MockRepository.GenerateStrictMock <LicenseHeaderReplacer>(extension);

            LinkedFileHandler linkedFileHandler = new LinkedFileHandler();

            linkedFileHandler.Handle(licenseHeaderReplacer, linkedFileFilter);

            Assert.AreEqual(string.Empty, linkedFileHandler.Message);
        }
        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);
        }
 public LicenseHeaderReplacer(ILicenseHeaderExtension licenseHeaderExtension)
 {
     _licenseHeaderExtension = licenseHeaderExtension;
 }
示例#17
0
        /// <summary>
        ///   Returns the document content of the given project item that has the language of the given extension and returns it as
        ///   string.
        /// </summary>
        /// <param name="item">Specifies the project item whose specific content should be returned.</param>
        /// <param name="wasAlreadyOpen">Specifies whether the project item was already open before this method was called.</param>
        /// <param name="extension">Specifies the extension of the language whose content should be returned.</param>
        /// <returns></returns>
        public static string GetContent(this ProjectItem item, out bool wasAlreadyOpen, ILicenseHeaderExtension extension)
        {
            ThreadHelper.ThrowIfNotOnUIThread();

            wasAlreadyOpen = item.IsOpen();

            if (!wasAlreadyOpen && !CoreHelpers.TryOpenDocument(item, extension))
            {
                return(null);
            }

            // Referring to the comment in the TryOpenDocument method: files with unknown extensions that were precautiously not opened are still fed as input to the
            // Core - with empty content, though, as the Core will return ReplacerErrorType.LanguageNotFound anyway (i. e. content is not relevant, only the extension)
            // (returning false from TryOpenDocument or null from this method would mean skipping the file entirely, which we do not want since we want to be able to
            // react to a ReplacerErrorType.LanguageNotFound)
            var languageForExtension = extension.LicenseHeaderReplacer.GetLanguageFromExtension(Path.GetExtension(item.FileNames[1]));

            if (languageForExtension == null)
            {
                return("");
            }

            try
            {
                if (!(item.Document?.Object("TextDocument") is TextDocument textDocument))
                {
                    return(null);
                }

                var wasSaved = item.Document.Saved;
                var content  = textDocument.CreateEditPoint(textDocument.StartPoint).GetText(textDocument.EndPoint);

                CoreHelpers.SaveAndCloseIfNecessary(item, wasAlreadyOpen, wasSaved);

                return(content);
            }
            catch (Exception)
            {
                return(null);
            }
        }
示例#18
0
 public LicenseHeaderReplacer(ILicenseHeaderExtension licenseHeaderExtension)
 {
     _licenseHeaderExtension = licenseHeaderExtension;
 }
示例#19
0
 public AddLicenseHeaderToAllFilesInSolutionImplementation(ILicenseHeaderExtension licenseHeaderExtension)
 {
     _licenseHeaderExtension = licenseHeaderExtension;
 }
 public AddLicenseHeaderToAllFilesInFolderProjectImplementation(ILicenseHeaderExtension licenseHeaderExtension)
 {
     _licenseHeaderExtension = licenseHeaderExtension;
 }
 public LinkedFileHandler(ILicenseHeaderExtension licenseHeaderExtension)
 {
     _licenseHeaderExtension = licenseHeaderExtension;
     Message = string.Empty;
 }
示例#22
0
 public ButtonHandlerFactory(ILicenseHeaderExtension licenseHeadersPackage, LicenseHeaderReplacer licenseHeaderReplacer)
 {
     _licenseHeadersPackage = licenseHeadersPackage;
     _licenseHeaderReplacer = licenseHeaderReplacer;
 }
 public ButtonHandlerFactory(ILicenseHeaderExtension licenseHeadersPackage, LicenseHeaderReplacer licenseHeaderReplacer)
 {
   _licenseHeadersPackage = licenseHeadersPackage;
   _licenseHeaderReplacer = licenseHeaderReplacer;
 }
示例#24
0
        private static bool TrySetContent(string itemPath, Solution solution, string content, bool wasOpen, ILicenseHeaderExtension extension)
        {
            ThreadHelper.ThrowIfNotOnUIThread();
            var item = solution.FindProjectItem(itemPath);

            if (item == null)
            {
                return(false);
            }

            if (!wasOpen && !TryOpenDocument(item, extension))
            {
                return(false);
            }

            // returning false from this method would signify an error, which we do not want since this circumstance is expected to occur with unknown file extensions
            var languageForExtension = extension.LicenseHeaderReplacer.GetLanguageFromExtension(Path.GetExtension(item.FileNames[1]));

            if (languageForExtension == null)
            {
                return(true);
            }

            if (!(item.Document.Object("TextDocument") is TextDocument textDocument))
            {
                return(false);
            }

            var wasSaved = item.Document.Saved;

            textDocument.CreateEditPoint(textDocument.StartPoint).Delete(textDocument.EndPoint);
            textDocument.CreateEditPoint(textDocument.StartPoint).Insert(content);

            SaveAndCloseIfNecessary(item, wasOpen, wasSaved);

            return(true);
        }
 /// <summary>
 ///   Creates an instance of the type implementing the <see cref="IMenuItemButtonHandler" /> interface that fits the given
 ///   parameters.
 /// </summary>
 /// <param name="level">The level the <see cref="IMenuItemButtonHandler" /> instance to be created should operate on.</param>
 /// <param name="mode">
 ///   The license header insertion mode to be used by the <see cref="IMenuItemButtonHandler" /> instance
 ///   to be created.
 /// </param>
 /// <param name="licenseHeadersPackage">
 ///   The <see cref="ILicenseHeaderExtension" /> instance the
 ///   <see cref="IMenuItemButtonHandler" /> instance to be created may use for its operations.
 /// </param>
 /// <returns>
 ///   Returns a´n <see cref="IMenuItemButtonHandler" /> instance operating on the level specified by
 ///   <paramref name="level" /> and executing operations of the mode specified by <paramref name="mode" />.
 /// </returns>
 public static IMenuItemButtonHandler CreateHandler(MenuItemButtonLevel level, MenuItemButtonOperation mode, ILicenseHeaderExtension licenseHeadersPackage)
 {
     return(level switch
     {
         MenuItemButtonLevel.Solution => CreateSolutionHandler(licenseHeadersPackage, mode),
         MenuItemButtonLevel.Folder => CreateFolderHandler(licenseHeadersPackage, mode),
         MenuItemButtonLevel.Project => CreateProjectHandler(licenseHeadersPackage, mode),
         _ => throw new ArgumentOutOfRangeException(nameof(level), level, null)
     });
 public RemoveLicenseHeaderFromAllFilesInSolutionImplementation(ILicenseHeaderExtension licenseHeaderExtension)
 {
     _licenseHeaderExtension = licenseHeaderExtension;
 }