/* Function: GetBodyLinks * Goes through the body of the passed <Topic> and adds any Natural Docs and image links it finds in the <NDMarkup> * to <LinkSet> and <ImageLinkSet>. */ protected void GetBodyLinks(Topic topic, ref LinkSet linkSet, ref ImageLinkSet imageLinkSet) { if (topic.Body == null) { return; } NDMarkup.Iterator iterator = new NDMarkup.Iterator(topic.Body); // Doing two passes of GoToFirstTag is probably faster than iterating through each element if (iterator.GoToFirstTag("<link type=\"naturaldocs\"")) { do { Link link = new Link(); // ignore LinkID link.Type = LinkType.NaturalDocs; link.Text = iterator.Property("originaltext"); link.Context = topic.BodyContext; // ignore contextID link.FileID = topic.FileID; link.ClassString = topic.ClassString; // ignore classID link.LanguageID = topic.LanguageID; // ignore EndingSymbol // ignore TargetTopicID // ignore TargetScore linkSet.Add(link); }while (iterator.GoToNextTag("<link type=\"naturaldocs\"")); } iterator = new NDMarkup.Iterator(topic.Body); if (iterator.GoToFirstTag("<image")) { do { ImageLink imageLink = new ImageLink(); // ignore ImageLinkID imageLink.OriginalText = iterator.Property("originaltext"); imageLink.Path = new Path(iterator.Property("target")); // ignore FileName, generated from Path imageLink.FileID = topic.FileID; imageLink.ClassString = topic.ClassString; // ignore classID // ignore TargetFileID // ignore TargetScore imageLinkSet.Add(imageLink); }while (iterator.GoToNextTag("<image")); } }
/* Function: ProcessNewOrChangedSourceFile * Takes a new or changed <File>, parses it, and updates <CodeDB.Manager> with its contents. The <CodeDB.Accessor> * should NOT already hold a lock. */ protected ProcessFileResult ProcessNewOrChangedSourceFile(File file, Engine.CodeDB.Accessor codeDBAccessor, CancelDelegate cancelDelegate) { try { var language = EngineInstance.Languages.FromFileName(file.FileName); IList <Topic> topics = null; LinkSet links = null; ImageLinkSet imageLinks = null; // Parse the file var parseResult = language.Parser.Parse(file.FileName, file.ID, cancelDelegate, out topics, out links); if (parseResult == Parser.ParseResult.Cancelled) { return(ProcessFileResult.Cancelled); } else if (parseResult == Parser.ParseResult.CantAccessFile) { return(ProcessFileResult.CantAccessFile); } else if (parseResult == Parser.ParseResult.FileDoesntExist) { return(ProcessFileResult.FileDoesntExist); } // Extract links from the bodies and prototypes if (topics != null && topics.Count > 0) { imageLinks = new ImageLinkSet(); foreach (Topic topic in topics) { GetLinks(topic, ref links, ref imageLinks); if (cancelDelegate()) { return(ProcessFileResult.Cancelled); } } } // Update the database codeDBAccessor.GetReadPossibleWriteLock(); try { if (topics != null && topics.Count > 0) { codeDBAccessor.UpdateTopicsInFile(file.ID, topics, cancelDelegate); } else { codeDBAccessor.DeleteTopicsInFile(file.ID, cancelDelegate); } if (links != null && links.Count > 0) { codeDBAccessor.UpdateLinksInFile(file.ID, links, cancelDelegate); } else { codeDBAccessor.DeleteLinksInFile(file.ID, cancelDelegate); } if (imageLinks != null && imageLinks.Count > 0) { codeDBAccessor.UpdateImageLinksInFile(file.ID, imageLinks, cancelDelegate); } else { codeDBAccessor.DeleteImageLinksInFile(file.ID, cancelDelegate); } // Need this check in case CodeDB quit early because of the cancel delegate. if (cancelDelegate()) { return(ProcessFileResult.Cancelled); } } finally { codeDBAccessor.ReleaseLock(); } return(ProcessFileResult.Success); } catch (Exception e) { try { e.AddNaturalDocsTask("Parsing file " + file.FileName); } catch { } throw; } }
// Group: Topic Functions // __________________________________________________________________________ /* Function: GetLinks * Goes through the body and prototype of the passed <Topic> and adds any Natural Docs and image links it finds in the * <NDMarkup> to <LinkSet> and <ImageLinkSet>. */ protected void GetLinks(Topic topic, ref LinkSet linkSet, ref ImageLinkSet imageLinkSet) { GetBodyLinks(topic, ref linkSet, ref imageLinkSet); GetPrototypeLinks(topic, ref linkSet); }
/* Function: ProcessChangedFile * Takes a changed <File>, parses it, and updates <CodeDB.Manager> with its contents. It returns the result code that * should be passed to <ReleaseClaimedFile()> if the file was retrieved with <ClaimChangedFile()>. The <CodeDB.Accessor> * should NOT already hold a lock. */ public ReleaseClaimedFileReason ProcessChangedFile(File file, Engine.CodeDB.Accessor codeDBAccessor, CancelDelegate cancelDelegate) { // Process source files if (file.Type == FileType.Source) { try { var language = EngineInstance.Languages.FromFileName(file.FileName); IList <Topic> topics = null; LinkSet links = null; ImageLinkSet imageLinks = null; var parseResult = language.Parse(file.FileName, file.ID, cancelDelegate, out topics, out links); if (parseResult == Language.ParseResult.FileDoesntExist) { return(ReleaseClaimedFileReason.FileDoesntExist); } else if (parseResult == Language.ParseResult.CantAccessFile) { return(ReleaseClaimedFileReason.CantAccessFile); } else if (parseResult == Language.ParseResult.Cancelled) { return(ReleaseClaimedFileReason.CancelledProcessing); } // Parse the topic bodies for Natural Docs links and image links. Parse the prototypes for type links. if (topics != null && topics.Count > 0) { imageLinks = new ImageLinkSet(); foreach (Topic topic in topics) { if (topic.Body != null) { ExtractBodyLinks(topic, links, imageLinks); if (cancelDelegate()) { return(ReleaseClaimedFileReason.CancelledProcessing); } } // We want to extract type links even for prototypes in the class hierarchy because the HTML output falls back to // regular prototypes if there's no class prototype. Also, if there's parameter lists in the description the HTML // generator will require type links to exist regardless of what type of prototype it creates. For example, this // SystemVerilog interface: // // // Interface: myInterface // // // // Parameters: // // PARAMNAME - description // // interface myInterface #(parameter PARAMNAME = 8) (input reset, clk); // // The HTML generation for the Parameters section will expect a type link to exist for PARAMNAME. // if (topic.Prototype != null ) { ExtractTypeLinks(topic, links); if (cancelDelegate()) { return(ReleaseClaimedFileReason.CancelledProcessing); } } } } // Update the database codeDBAccessor.GetReadPossibleWriteLock(); try { if (topics != null && topics.Count > 0) { codeDBAccessor.UpdateTopicsInFile(file.ID, topics, cancelDelegate); } else { codeDBAccessor.DeleteTopicsInFile(file.ID, cancelDelegate); } if (links != null && links.Count > 0) { codeDBAccessor.UpdateLinksInFile(file.ID, links, cancelDelegate); } else { codeDBAccessor.DeleteLinksInFile(file.ID, cancelDelegate); } if (imageLinks != null && imageLinks.Count > 0) { codeDBAccessor.UpdateImageLinksInFile(file.ID, imageLinks, cancelDelegate); } else { codeDBAccessor.DeleteImageLinksInFile(file.ID, cancelDelegate); } } finally { codeDBAccessor.ReleaseLock(); } // Need this final check in case CodeDB quit with a cancellation. if (cancelDelegate()) { return(ReleaseClaimedFileReason.CancelledProcessing); } return(ReleaseClaimedFileReason.SuccessfullyProcessed); } catch (Exception e) { try { e.AddNaturalDocsTask("Parsing File: " + file.FileName); } catch { } throw; } } // Process style and image files else { // These are only processed by output builders. They're not in CodeDB so we don't need to do anything here. return(ReleaseClaimedFileReason.SuccessfullyProcessed); } }