public void TestWritingIncludeGuard()
        {
            var writer = new CHeaderFileWriter()
            {
                IncludeGuard = "test"
            };

            using (var stream = new MemoryStream())
            {
                writer.WriteHeaderFile(new CSourceFile(), stream);
                var bytes = stream.ToArray();
                var str   = Encoding.ASCII.GetString(bytes);

                Assert.That(str, Is.Not.Null.And.EqualTo("#ifndef test\r\n#define test\r\n\r\n\r\n#endif\r\n"));
            }
        }
        public void TestWritingHeaderComment()
        {
            var writer = new CHeaderFileWriter()
            {
                HeaderComment = "test"
            };

            using (var stream = new MemoryStream())
            {
                writer.WriteHeaderFile(new CSourceFile(), stream);
                var bytes = stream.ToArray();
                var str   = Encoding.ASCII.GetString(bytes);

                Assert.That(str, Is.Not.Null.And.EqualTo("test\r\n\r\n"));
            }
        }
        /// <summary>
        /// Writer the parsed source file to the output file
        /// </summary>
        /// <param name="showIncludeGuard">Whether to surround the header file in an include guard</param>
        /// <param name="codeWriter">The code writer object</param>
        /// <param name="headerFileName">The name of the header file to produce</param>
        /// <param name="c">The parse source file</param>
        private static void WriteToHeaderFile(bool showIncludeGuard, CHeaderFileWriter codeWriter, string headerFileName, CSourceFile c)
        {
            if (showIncludeGuard)
            {
                codeWriter.IncludeGuard = new Regex(@"[^A-Z0-9_]").Replace(string.Format("__{0}__",
                                                                                         Path.GetFileName(headerFileName).ToUpperInvariant()), "_");
            }
            else
            {
                codeWriter.IncludeGuard = null;
            }

            using (var stream = File.Open(headerFileName, FileMode.Create))
            {
                codeWriter.WriteHeaderFile(c, stream);
            }
        }
        /// <summary>
        /// Parse a C file and write a header files from the parsed contents.
        /// </summary>
        /// <param name="sourceFileName">The source file to parse</param>
        /// <param name="headerFileName">The header file to write</param>
        /// <param name="codeWriter">Code writer object</param>
        /// <param name="showIncludeGuard">Whether to surround the header file in an include guard</param>
        /// <param name="projectItem">The project item corresponding to the source file</param>
        /// <returns></returns>
        private bool ParseItem(string sourceFileName, string headerFileName,
                               CHeaderFileWriter codeWriter, bool showIncludeGuard, ProjectItem projectItem)
        {
            var containingProject = projectItem.ContainingProject;
            var existingItem      = containingProject.FindExistingItem(headerFileName);

            if (existingItem != null)
            {
                var message = string.Format("File {0} already exists, would you like to re-generate the header file?", headerFileName);
                var result  = this.dlgService.ShowYesNoCancelDialog(message,
                                                                    "File Exists");
                if (result == System.Windows.MessageBoxResult.No)
                {
                    return(true);
                }
                else if (result == System.Windows.MessageBoxResult.Cancel)
                {
                    return(false);
                }
            }

            if (existingItem != null)
            {
                CheckOutFile(ApplicationObject.SourceControl, headerFileName);
            }

            var c = this.ParseSourceFile(sourceFileName);

            WriteToHeaderFile(showIncludeGuard, codeWriter, headerFileName, c);

            // Add File to Project
            if (existingItem == null)
            {
                containingProject.ProjectItems.AddFromFile(headerFileName);
                if (!containingProject.Saved)
                {
                    containingProject.Save();
                }
            }

            return(true);
        }
        /// <summary>
        /// Generate C header files for a list of project items.
        /// </summary>
        /// <param name="projectItems">A list of project items.</param>
        private void ProcessFiles(IReadOnlyCollection <ProjectItem> projectItems)
        {
            bool showIncludeGuard;
            bool autoSaveFiles;
            var  codeWriter = new CHeaderFileWriter();

            // Add Options
            using (var options = GetDialogPage(typeof(CSourceFileOptions)) as CSourceFileOptions)
            {
                codeWriter.HeaderComment          = SetHeaderComment(options.HeaderComment);
                codeWriter.IncludeStaticFunctions = options.IncludeStaticFunctions;
                codeWriter.IncludeExternFunctions = options.IncludeExternFunctions;
                showIncludeGuard = options.ShowIncludeGuard;
                autoSaveFiles    = options.AutoSaveFiles;
            }

            // Initialize viewmodel to keep track of progress
            using (var progressVM = new ProgressViewModel
            {
                Minimum = 0.0,
                Maximum = 1.0,
                Message = "Starting...",
                ProgressValue = 0.0
            })
            {
                this.ShowProgressDialog(progressVM);

                int i = 0;
                foreach (var projectItem in projectItems)
                {
                    if (projectItem.Document != null && !projectItem.Document.Saved && autoSaveFiles)
                    {
                        projectItem.Document.Save();
                    }

                    string file      = projectItem.FileNames[0];
                    string itemToAdd = GetItemFileName(file);
                    bool   error     = false;

                    try
                    {
                        // Parse the file
                        log.Info("Processing {0}/{1}: {2}", ++i, projectItems.Count, file);
                        progressVM.Message = string.Format("{0}/{1}: Processing {2}", i, projectItems.Count, file);
                        if (!ParseItem(file, itemToAdd, codeWriter, showIncludeGuard, projectItem))
                        {
                            break;
                        }
                        progressVM.ProgressValue = Convert.ToDouble(i);
                    }
                    catch (ParserException tex)
                    {
                        // Go to file/line where the error occurred and display a dialog with the error message.
                        var window = ApplicationObject.ItemOperations.OpenFile(file);
                        window.Activate();
                        if (tex.LineNumber > 0)
                        {
                            var textSelection = window.Selection as TextSelection;
                            if (textSelection != null)
                            {
                                textSelection.GotoLine(tex.LineNumber, true);
                            }
                        }
                        log.Error(string.Format("Failed to parse file: {0}", file), tex);
                        this.ShowExceptionDialog(tex, string.Format("Failed to parse file: {0}", file));
                        error = true;
                    }
                    catch (Exception ex)
                    {
                        // Show a dialog with a less-than-helpful exception message.
                        log.Error(string.Format("Unknown error while parsing file: {0}", file), ex);
                        this.ShowExceptionDialog(ex, string.Format("Unknown exception while parsing: {0}", file));
                        error = true;
                    }
                    finally
                    {
                        // Log the result of the parse operation.
                        var messageBuilder = new System.Text.StringBuilder();
                        messageBuilder.AppendFormat("Completed processing file {0}/{1}: {2}.", i, projectItems.Count, file);
                        if (error)
                        {
                            messageBuilder.Append(" There were one or more errors detected during processing.");
                        }
                        else
                        {
                            messageBuilder.Append(" The operation was completed successfully.");
                        }
                        log.Info(messageBuilder.ToString());
                    }
                }
            }
        }