public void OnUpdateTopic(Topic oldTopic, Topic newTopic, Topic.ChangeFlags changeFlags, EventAccessor eventAccessor) { }
public void OnUpdateTopic(Topic oldTopic, Topic newTopic, Topic.ChangeFlags changeFlags, CodeDB.EventAccessor eventAccessor) { // We don't care about line number changes. They don't affect the output. We also don't care about context // changes. They might affect links but if they do it will be handled in OnChangeLinkTarget(). changeFlags &= ~(Topic.ChangeFlags.CommentLineNumber | Topic.ChangeFlags.CodeLineNumber | Topic.ChangeFlags.PrototypeContext | Topic.ChangeFlags.BodyContext); if (changeFlags == 0) { return; } lock (accessLock) { buildState.SourceFilesToRebuild.Add(oldTopic.FileID); #if DEBUG if (newTopic.FileID != oldTopic.FileID) { throw new Exception("Called OnUpdateTopic() with topics that had different file IDs"); } #endif if (oldTopic.ClassID != 0) { buildState.ClassFilesToRebuild.Add(oldTopic.ClassID); } if (newTopic.ClassID != 0) { buildState.ClassFilesToRebuild.Add(newTopic.ClassID); } } // If the summary or prototype changed this means its tooltip changed. Rebuild any file that contains links // to this topic. if ((changeFlags & (Topic.ChangeFlags.Prototype | Topic.ChangeFlags.Summary | Topic.ChangeFlags.LanguageID | Topic.ChangeFlags.CommentTypeID)) != 0) { IDObjects.NumberSet linkFileIDs, linkClassIDs; eventAccessor.GetInfoOnLinksThatResolveToTopicID(oldTopic.TopicID, out linkFileIDs, out linkClassIDs); IDObjects.NumberSet oldParentClassIDs = null; IDObjects.NumberSet oldParentClassFileIDs = null; IDObjects.NumberSet newParentClassIDs = null; IDObjects.NumberSet newParentClassFileIDs = null; if (oldTopic.DefinesClass) { eventAccessor.GetInfoOnClassParents(oldTopic.ClassID, out oldParentClassIDs, out oldParentClassFileIDs); } if (newTopic.DefinesClass && (newTopic.ClassID != oldTopic.ClassID || oldTopic.DefinesClass == false)) { eventAccessor.GetInfoOnClassParents(newTopic.ClassID, out newParentClassIDs, out newParentClassFileIDs); } if (linkFileIDs != null || linkClassIDs != null || oldParentClassIDs != null || oldParentClassFileIDs != null || newParentClassIDs != null || newParentClassFileIDs != null) { lock (accessLock) { if (linkFileIDs != null) { buildState.SourceFilesToRebuild.Add(linkFileIDs); } if (linkClassIDs != null) { buildState.ClassFilesToRebuild.Add(linkClassIDs); } if (oldParentClassIDs != null) { buildState.ClassFilesToRebuild.Add(oldParentClassIDs); } if (oldParentClassFileIDs != null) { buildState.SourceFilesToRebuild.Add(oldParentClassFileIDs); } if (newParentClassIDs != null) { buildState.ClassFilesToRebuild.Add(newParentClassIDs); } if (newParentClassFileIDs != null) { buildState.SourceFilesToRebuild.Add(newParentClassFileIDs); } } } } }
public void OnUpdateTopic(Topic oldTopic, Topic newTopic, Topic.ChangeFlags changeFlags, CodeDB.EventAccessor eventAccessor) { #if DEBUG if (IncludeInIndex(newTopic) != IncludeInIndex(oldTopic)) { throw new Exception("SearchIndex incorrectly assumes IncludeInIndex() will be the same for both the old and new topics in OnUpdateTopic()."); } #endif if (!IncludeInIndex(newTopic)) { return; } if ((changeFlags & (Topic.ChangeFlags.Title | Topic.ChangeFlags.CommentTypeID | Topic.ChangeFlags.SymbolDefinitonNumber | Topic.ChangeFlags.Symbol | Topic.ChangeFlags.LanguageID | Topic.ChangeFlags.FileID | Topic.ChangeFlags.EffectiveAccessLevel | Topic.ChangeFlags.Class)) == 0) { return; } // We assume that if the topics are similar enough to use OnUpdateTopic() instead of OnAdd/RemoveTopic() then they'll generate the exact // same keyword list, and they'll even be in the same order. This allows for a nice optimization here, but test it in debug builds in case these // assumptions are wrong in the future. #if DEBUG if (newTopic.TopicID != oldTopic.TopicID) { throw new Exception("SearchIndex incorrectly assumes both the old and new topics in OnUpdateTopic() have the same topic IDs."); } TopicEntry newEntry = new TopicEntry(newTopic, this); TopicEntry oldEntry = new TopicEntry(oldTopic, this); if (newEntry.Keywords.Count != oldEntry.Keywords.Count) { throw new Exception("SearchIndex incorrectly assumes both the old and new topics in OnUpdateTopic() have the same keywords."); } for (int i = 0; i < newEntry.Keywords.Count; i++) { if (newEntry.Keywords[i] != oldEntry.Keywords[i]) { throw new Exception("SearchIndex incorrectly assumes both the old and new topics in OnUpdateTopic() have the same keywords."); } } #endif TopicEntry entry = new TopicEntry(newTopic, this); // We use upgradeable in case one of the change handlers needs to do something that requires a write lock. accessLock.EnterUpgradeableReadLock(); try { foreach (var keyword in entry.Keywords) { string prefix = KeywordPrefix(keyword); foreach (var changeWatcher in changeWatchers) { changeWatcher.OnUpdatePrefix(prefix, eventAccessor); } } } finally { // We don't have to test to see if it was upgraded because if it was the write lock should have been released // by the change handler and we should recursively be back to an upgradeable read lock. accessLock.ExitUpgradeableReadLock(); } }