예제 #1
0
        /* Function: Start
         *
         * Dependencies:
         *
         *		- <Config.Manager> must be started before using the rest of the class.
         */
        public bool Start(Errors.ErrorList errors)
        {
            EngineInstance.AddStartupWatcher(this);

            SQLite.API.Result sqliteResult = SQLite.API.Initialize();

            if (sqliteResult != SQLite.API.Result.OK)
            {
                throw new SQLite.Exceptions.UnexpectedResult("Could not initialize SQLite.", sqliteResult);
            }

            Path databaseFile = EngineInstance.Config.WorkingDataFolder + "/CodeDB.nd";

            connection = new SQLite.Connection();
            bool success = false;

            if (!EngineInstance.HasIssues(StartupIssues.NeedToStartFresh |
                                          StartupIssues.FileIDsInvalidated |
                                          StartupIssues.CodeIDsInvalidated |
                                          StartupIssues.CommentIDsInvalidated))
            {
                try
                {
                    connection.Open(databaseFile, false);

                    Version version = GetVersion();

                    if (BinaryFile.IsCompatible(version, Engine.Instance.Version, "2.0.2") == true)
                    {
                        LoadSystemVariables();
                        success = true;
                    }
                }
                catch { }
            }

            if (!success)
            {
                connection.Dispose();

                if (System.IO.File.Exists(databaseFile))
                {
                    System.IO.File.Delete(databaseFile);
                }

                connection.Open(databaseFile, true);
                CreateDatabase();

                EngineInstance.AddStartupIssues(StartupIssues.CodeIDsInvalidated |
                                                StartupIssues.CommentIDsInvalidated |
                                                StartupIssues.NeedToReparseAllFiles,
                                                dontNotify: this);
            }

            started = true;
            return(true);
        }
예제 #2
0
        /* Function: Start
         */
        public bool Start(ErrorList errorList)
        {
            StartupIssues newStartupIssues = StartupIssues.None;


            // Load SearchIndex.nd

            bool hasBinaryFile;

            if (!EngineInstance.HasIssues(StartupIssues.NeedToStartFresh |
                                          StartupIssues.CommentIDsInvalidated |
                                          StartupIssues.CodeIDsInvalidated |
                                          StartupIssues.CommentIDsInvalidated))
            {
                SearchIndex_nd binaryFileParser = new SearchIndex_nd();
                hasBinaryFile = binaryFileParser.Load(Target.WorkingDataFolder + "/SearchIndex.nd", out prefixTopicIDs);
            }
            else
            {
                prefixTopicIDs = new StringTable <NumberSet>(KeySettingsForPrefixes);
                hasBinaryFile  = false;
            }

            if (!hasBinaryFile)
            {
                // If we don't have the binary file we need to reparse all the source files to rebuild the index.  However, setting NeedToReparseAllFiles
                // isn't enough because it will reparse those files, send them to CodeDB, and then CodeDB won't send topic updates if the underlying
                // content hasn't changed.  So f**k it, blow it all up and start over.
                newStartupIssues |= StartupIssues.NeedToStartFresh;
            }


            // Add watchers

            EngineInstance.CodeDB.AddChangeWatcher(this);
            EngineInstance.AddStartupWatcher(this);


            if (newStartupIssues != StartupIssues.None)
            {
                EngineInstance.AddStartupIssues(newStartupIssues, dontNotify: this);
            }

            started = true;
            return(true);
        }
예제 #3
0
        public override bool Start(Errors.ErrorList errorList)
        {
            int           errors           = errorList.Count;
            StartupIssues newStartupIssues = StartupIssues.None;


            //
            // Validate the output folder.
            //

            if (System.IO.Directory.Exists(config.Folder) == false)
            {
                errorList.Add(Locale.Get("NaturalDocs.Engine", "Error.FolderDoesntExist(type, name)", "output", config.Folder));
                return(false);
            }


            //
            // Load and validate the styles, including any inherited styles.
            //

            string    styleName   = config.ProjectInfo.StyleName;
            Style_txt styleParser = new Style_txt();

            if (styleName == null)
            {
                style = EngineInstance.Styles.LoadStyle("Default", errorList, Config.PropertySource.SystemDefault);
            }

            else if (EngineInstance.Styles.StyleExists(styleName))
            {
                style = EngineInstance.Styles.LoadStyle(styleName, errorList, config.ProjectInfo.StyleNamePropertyLocation);
            }

            // Check if it's an empty folder we want to generate a default Style.txt for
            else if (System.IO.Directory.Exists(EngineInstance.Config.ProjectConfigFolder + '/' + styleName) &&
                     !System.IO.File.Exists(EngineInstance.Config.ProjectConfigFolder + '/' + styleName + "/Style.txt"))
            {
                style = new Styles.Advanced(EngineInstance.Config.ProjectConfigFolder + '/' + styleName + "/Style.txt");

                // Inherit Default so everything still works before it's filled out.
                style.AddInheritedStyle("Default", Config.PropertySource.SystemGenerated);

                if (!styleParser.Save((Styles.Advanced)style, errorList, false))
                {
                    return(false);
                }

                // Now we have to reload it so it loads the inherited style as well.
                style = EngineInstance.Styles.LoadStyle(styleName, errorList, config.ProjectInfo.StyleNamePropertyLocation);
            }

            else
            {
                errorList.Add(Locale.Get("NaturalDocs.Engine", "Style.txt.CantFindStyle(name)", styleName),
                              config.ProjectInfo.StyleNamePropertyLocation);
                return(false);
            }

            stylesWithInheritance = style.BuildInheritanceList();


            //
            // Load Config.nd
            //

            Config_nd             binaryConfigParser = new Config_nd();
            List <Style>          previousStyles;
            List <FileSourceInfo> previousFileSourceInfoList;
            bool hasBinaryConfigFile = false;

            if (!EngineInstance.HasIssues(StartupIssues.NeedToStartFresh))
            {
                hasBinaryConfigFile = binaryConfigParser.Load(WorkingDataFolder + "/Config.nd", out previousStyles, out previousFileSourceInfoList);
            }
            else             // start fresh
            {
                previousStyles             = new List <Style>();
                previousFileSourceInfoList = new List <FileSourceInfo>();
            }


            //
            // Compare to the previous list of styles.
            //

            bool inPurgingOperation = false;

            if (!hasBinaryConfigFile)
            {
                // If we don't have the binary config file we have to purge every style folder because some of them may no longer be in
                // use and we won't know which.
                PurgeAllStyleFolders(ref inPurgingOperation);

                newStartupIssues |= StartupIssues.NeedToReparseStyleFiles;
            }

            else             // (hasBinaryConfigFile)
            {
                // Purge the style folders for any no longer in use.

                foreach (var previousStyle in previousStyles)
                {
                    bool stillExists = false;

                    foreach (var currentStyle in stylesWithInheritance)
                    {
                        if (currentStyle.IsSameFundamentalStyle(previousStyle))
                        {
                            stillExists = true;
                            break;
                        }
                    }

                    if (!stillExists)
                    {
                        PurgeStyleFolder(previousStyle.Name, ref inPurgingOperation);
                    }
                }

                // Reparse styles on anything new.  If a style is new we can't assume all its files are going to be sent to the
                // IChangeWatcher functions because another output target may have been using it, and thus they are already in
                // Files.Manager.

                foreach (var currentStyle in stylesWithInheritance)
                {
                    bool foundMatch = false;

                    foreach (var previousStyle in previousStyles)
                    {
                        if (previousStyle.IsSameFundamentalStyle(currentStyle))
                        {
                            foundMatch = true;
                            break;
                        }
                    }

                    if (!foundMatch)
                    {
                        newStartupIssues |= StartupIssues.NeedToReparseStyleFiles;
                        break;
                    }
                }
            }


            //
            // Compare to the previous list of FileSources.
            //

            if (!hasBinaryConfigFile)
            {
                // If we don't have the binary config file we need to rebuild all the output because we don't know which FileSource was
                // previously set to which number, which determines which output folder they use, like /files vs /files2.
                newStartupIssues |= StartupIssues.NeedToRebuildAllOutput;

                // This also means we have to purge every source or image output folder because we won't know which changed or are
                // no longer in use.
                PurgeAllSourceAndImageFolders(ref inPurgingOperation);
            }

            else              // (hasBinaryConfigFile)
            {
                bool hasDeletions = false;
                bool hasAdditions = false;


                // Purge the output folders of any deleted FileSources

                foreach (var previousFileSourceInfo in previousFileSourceInfoList)
                {
                    bool stillExists = false;

                    foreach (var fileSource in EngineInstance.Files.FileSources)
                    {
                        if (previousFileSourceInfo.IsSameFundamentalFileSource(fileSource))
                        {
                            stillExists = true;
                            break;
                        }
                    }

                    if (!stillExists)
                    {
                        hasDeletions = true;
                        Path outputFolder;

                        if (previousFileSourceInfo.Type == InputType.Source)
                        {
                            outputFolder = Paths.SourceFile.OutputFolder(OutputFolder, previousFileSourceInfo.Number);
                        }
                        else if (previousFileSourceInfo.Type == InputType.Image)
                        {
                            outputFolder = Paths.Image.OutputFolder(OutputFolder, previousFileSourceInfo.Number, previousFileSourceInfo.Type);
                        }
                        else
                        {
                            throw new NotImplementedException();
                        }

                        PurgeFolder(outputFolder, ref inPurgingOperation);
                    }
                }


                // Check if any FileSources were added

                foreach (var fileSource in EngineInstance.Files.FileSources)
                {
                    if (fileSource.Type == InputType.Source || fileSource.Type == InputType.Image)
                    {
                        bool foundMatch = false;

                        foreach (var previousFileSourceInfo in previousFileSourceInfoList)
                        {
                            if (previousFileSourceInfo.IsSameFundamentalFileSource(fileSource))
                            {
                                foundMatch = true;
                                break;
                            }
                        }

                        if (!foundMatch)
                        {
                            hasAdditions = true;
                            break;
                        }
                    }
                }


                // If there were both additions and deletions, force a rebuild.  This covers if a FileSource was simply moved from one
                // number to another, in which case the rebuild is required to populate the new folder.  This also covers if a folder
                // FileSource is replaced by one for its parent folder, in which case a rebuild is required to recreate the output for the
                // files in the child folder.

                if (hasAdditions && hasDeletions)
                {
                    newStartupIssues |= StartupIssues.NeedToRebuildAllOutput;
                }
            }


            //
            // Load BuildState.nd
            //

            BuildState_nd buildStateParser        = new BuildState_nd();
            bool          hasBinaryBuildStateFile = false;

            if (!EngineInstance.HasIssues(StartupIssues.NeedToStartFresh |
                                          StartupIssues.FileIDsInvalidated |
                                          StartupIssues.CodeIDsInvalidated |
                                          StartupIssues.CommentIDsInvalidated))
            {
                hasBinaryBuildStateFile = buildStateParser.Load(WorkingDataFolder + "/BuildState.nd", out buildState, out unprocessedChanges);
            }
            else             // start fresh
            {
                buildState         = new BuildState();
                unprocessedChanges = new UnprocessedChanges();
            }

            if (!hasBinaryBuildStateFile)
            {
                // If we don't have a build state file we need to reparse all the source files because we need to know sourceFilesWithContent
                // and classesWithContent.  We also need to rebuild all the output because we don't know if there was anything left in
                // sourceFilesToRebuild from the last run.  But those two flags actually aren't enough, because it will reparse those files, send
                // them to CodeDB, and then CodeDB won't send topic updates if the underlying content hasn't changed.  We'd actually need
                // to add all files and classes to UnprocessedChanges, but the Files module isn't started yet.  So f**k it, blow it all up and start
                // over.
                newStartupIssues |= StartupIssues.NeedToStartFresh;

                // Purge everything so no stray files are left behind from the previous build.
                PurgeAllSourceAndImageFolders(ref inPurgingOperation);
                PurgeAllClassFolders(ref inPurgingOperation);
                PurgeAllDatabaseFolders(ref inPurgingOperation);
                PurgeAllStyleFolders(ref inPurgingOperation);
                PurgeAllMenuFolders(ref inPurgingOperation);
                PurgeAllSearchIndexFolders(ref inPurgingOperation);
            }


            //
            // We're done with anything that could purge.
            //

            FinishedPurging(ref inPurgingOperation);


            //
            // Resave the Style.txt-based styles.
            //

            foreach (var style in stylesWithInheritance)
            {
                if (style is Styles.Advanced)
                {
                    var  advancedStyle = style as Styles.Advanced;
                    bool isSystemStyle = EngineInstance.Config.SystemStyleFolder.Contains(advancedStyle.ConfigFile);

                    // No error on save for system styles.
                    styleParser.Save(advancedStyle, errorList, noErrorOnFail: isSystemStyle);
                }
            }


            //
            // Save Config.nd.
            //

            if (!System.IO.Directory.Exists(WorkingDataFolder))
            {
                System.IO.Directory.CreateDirectory(WorkingDataFolder);
            }

            List <FileSourceInfo> fileSourceInfoList = new List <FileSourceInfo>();

            foreach (var fileSource in EngineInstance.Files.FileSources)
            {
                if (fileSource.Type == Files.InputType.Source || fileSource.Type == Files.InputType.Image)
                {
                    FileSourceInfo fileSourceInfo = new FileSourceInfo();
                    fileSourceInfo.CopyFrom(fileSource);
                    fileSourceInfoList.Add(fileSourceInfo);
                }
                ;
            }

            binaryConfigParser.Save(WorkingDataFolder + "/Config.nd", stylesWithInheritance, fileSourceInfoList);


            //
            // Always rebuild the scaffolding since they're quick.  If you ever make this differential, remember that FramePage depends
            // on the project name and other information.
            //

            unprocessedChanges.AddFramePage();
            unprocessedChanges.AddMainStyleFiles();


            //
            // Load up unprocessedChanges if we're rebuilding
            //

            if (EngineInstance.HasIssues(StartupIssues.NeedToRebuildAllOutput) ||
                (newStartupIssues & StartupIssues.NeedToRebuildAllOutput) != 0)
            {
                unprocessedChanges.AddSourceFiles(buildState.sourceFilesWithContent);
                unprocessedChanges.AddClasses(buildState.classesWithContent);
                unprocessedChanges.AddImageFiles(buildState.usedImageFiles);

                newStartupIssues |= StartupIssues.NeedToReparseStyleFiles;

                unprocessedChanges.AddMainStyleFiles();
                unprocessedChanges.AddMainSearchFiles();
                unprocessedChanges.AddFramePage();
                unprocessedChanges.AddMenu();

                // We'll handle search prefixes after starting SearchIndex
            }


            //
            // Create the search index, watch other modules, and apply new StartupIssues
            //

            searchIndex = new SearchIndex.Manager(this);

            EngineInstance.CodeDB.AddChangeWatcher(this);
            EngineInstance.Files.AddChangeWatcher(this);
            searchIndex.AddChangeWatcher(this);
            EngineInstance.AddStartupWatcher(this);

            if (newStartupIssues != StartupIssues.None)
            {
                EngineInstance.AddStartupIssues(newStartupIssues, dontNotify: this);
            }

            searchIndex.Start(errorList);


            //
            // If we're rebuilding everything, add the search index prefixes now that that's started
            //

            if (EngineInstance.HasIssues(StartupIssues.NeedToRebuildAllOutput))
            {
                var usedPrefixes = searchIndex.UsedPrefixes();

                foreach (var searchPrefix in usedPrefixes)
                {
                    unprocessedChanges.AddSearchPrefix(searchPrefix);
                }
            }


            return(errors == errorList.Count);
        }
예제 #4
0
		private static bool BuildDocumentation (ErrorList errorList)
			{
			ShowConsoleHeader();

			bool rebuildAllOutputFromCommandLine = EngineInstance.Config.RebuildAllOutput;
			bool reparseEverythingFromCommandLine = EngineInstance.Config.ReparseEverything;

			EngineInstance.AddStartupWatcher(new EngineStartupWatcher());


			executionTimer.Start("Engine Startup");
			
			if (EngineInstance.Start(errorList, commandLineConfig) == true)
				{
				executionTimer.End("Engine Startup");


				// File Search
						
				executionTimer.Start("Finding Source Files");

				using ( StatusManagers.FileSearch statusManager = new StatusManagers.FileSearch() )
					{
					statusManager.Start();
							
					Multithread("File Adder", EngineInstance.Files.WorkOnAddingAllFiles);
							
					statusManager.End();
					}
							
				EngineInstance.Files.DeleteFilesNotInFileSources( Engine.Delegates.NeverCancel );
							
				executionTimer.End("Finding Source Files");

						
				// Rebuild notice

				string alternateStartMessage = null;
						
				if (reparseEverythingFromCommandLine || rebuildAllOutputFromCommandLine)
					{  alternateStartMessage = "Status.RebuildEverythingByRequest";  }
				else if (EngineInstance.Config.ReparseEverything && EngineInstance.Config.RebuildAllOutput)
					{  alternateStartMessage = "Status.RebuildEverythingAutomatically";  }
							
							
				// Parsing
						
				executionTimer.Start("Parsing Source Files");

				using ( StatusManagers.Parsing statusManager = new StatusManagers.Parsing(alternateStartMessage) )
					{
					statusManager.Start();
					totalFileChanges = statusManager.TotalFilesToProcess;

					Multithread("Parser", EngineInstance.Files.WorkOnProcessingChanges);							
							
					statusManager.End();
					}
							
				executionTimer.End("Parsing Source Files");

							
				// Resolving
						
				executionTimer.Start("Resolving Links");

				using ( StatusManagers.ResolvingLinks statusManager = new StatusManagers.ResolvingLinks() )
					{
					statusManager.Start();

					Multithread("Resolver", EngineInstance.Links.WorkOnResolvingLinks);
							
					statusManager.End();
					}
							
				executionTimer.End("Resolving Links");

							
				// Building
						
				executionTimer.Start("Building Output");

				using ( StatusManagers.Building statusManager = new StatusManagers.Building() )
					{
					statusManager.Start();

					Multithread("Builder", EngineInstance.Output.WorkOnUpdatingOutput);
					Multithread("Finalizer", EngineInstance.Output.WorkOnFinalizingOutput);							
							
					statusManager.End();
					}
							
				executionTimer.End("Building Output");

							
				// End
						
				EngineInstance.Cleanup(Delegates.NeverCancel);
						
				ShowConsoleFooter(true);
				return true;
				}

			else // engine did not start correctly
				{  
				executionTimer.End("Engine Startup");

				ShowConsoleFooter(false);
				return false;
				}
			}
예제 #5
0
        private static bool BuildDocumentation(ErrorList errorList)
        {
            ShowConsoleHeader();

            EngineInstance.AddStartupWatcher(new EngineStartupWatcher());


            executionTimer.Start("Engine Startup");

            if (EngineInstance.Start(errorList, commandLineConfig) == true)
            {
                executionTimer.End("Engine Startup");


                // File Search

                executionTimer.Start("Finding Source Files");

                var adderProcess = EngineInstance.Files.CreateAdderProcess();

                using (StatusManagers.FileSearch statusManager = new StatusManagers.FileSearch(adderProcess))
                {
                    statusManager.Start();

                    Multithread("File Adder", adderProcess.WorkOnAddingAllFiles);

                    statusManager.End();
                }

                EngineInstance.Files.DeleteFilesNotReAdded(Engine.Delegates.NeverCancel);
                adderProcess.Dispose();

                executionTimer.End("Finding Source Files");


                // Rebuild notice

                string alternativeStartMessage = null;

                if (EngineInstance.Config.UserWantsEverythingRebuilt ||
                    EngineInstance.Config.UserWantsOutputRebuilt)
                {
                    alternativeStartMessage = "Status.RebuildEverythingByRequest";
                }
                else if (EngineInstance.HasIssues(StartupIssues.NeedToStartFresh |
                                                  StartupIssues.NeedToReparseAllFiles |
                                                  StartupIssues.NeedToRebuildAllOutput))
                {
                    alternativeStartMessage = "Status.RebuildEverythingAutomatically";
                }


                // Parsing

                executionTimer.Start("Parsing Source Files");

                var changeProcessor = EngineInstance.Files.CreateChangeProcessor();

                using (StatusManagers.Parsing statusManager = new StatusManagers.Parsing(changeProcessor, alternativeStartMessage))
                {
                    statusManager.Start();
                    totalFileChanges = statusManager.TotalFilesToProcess;

                    Multithread("Parser", changeProcessor.WorkOnProcessingChanges);

                    statusManager.End();
                }

                changeProcessor.Dispose();

                executionTimer.End("Parsing Source Files");


                // Resolving

                executionTimer.Start("Resolving Links");

                var resolverProcess = EngineInstance.Links.CreateResolverProcess();

                using (StatusManagers.ResolvingLinks statusManager = new StatusManagers.ResolvingLinks(resolverProcess))
                {
                    statusManager.Start();

                    Multithread("Resolver", resolverProcess.WorkOnResolvingLinks);

                    statusManager.End();
                }

                resolverProcess.Dispose();

                executionTimer.End("Resolving Links");


                // Building

                executionTimer.Start("Building Output");

                var builderProcess = EngineInstance.Output.CreateBuilderProcess();

                using (StatusManagers.Building statusManager = new StatusManagers.Building(builderProcess))
                {
                    statusManager.Start();

                    Multithread("Builder", builderProcess.WorkOnUpdatingOutput);
                    Multithread("Finalizer", builderProcess.WorkOnFinalizingOutput);

                    statusManager.End();
                }

                builderProcess.Dispose();

                executionTimer.End("Building Output");


                // End

                EngineInstance.Cleanup(Delegates.NeverCancel);

                ShowConsoleFooter(true);
                return(true);
            }

            else             // engine did not start correctly
            {
                executionTimer.End("Engine Startup");

                ShowConsoleFooter(false);
                return(false);
            }
        }