Exemplo n.º 1
0
 public void OnUpdatePrefix(string prefix, CodeDB.EventAccessor accessor)
 {
     lock (accessLock)
     {
         buildState.SearchPrefixesToRebuild.Add(prefix);
     }
 }
Exemplo n.º 2
0
        // Group: CodeDB.IChangeWatcher Functions
        // __________________________________________________________________________


        public void OnAddTopic(Topic topic, CodeDB.EventAccessor eventAccessor)
        {
            // If this topic defines a class, it's possible it's now the best definition and thus we have to update the class prototypes
            // of all its parents.  We don't have to worry about updating children because that will be taken care of by OnLinkChange
            // since there would be a class parent link pointing to it.

            IDObjects.NumberSet parentClassIDs     = null;
            IDObjects.NumberSet parentClassFileIDs = null;

            if (topic.DefinesClass)
            {
                eventAccessor.GetInfoOnClassParents(topic.ClassID, out parentClassIDs, out parentClassFileIDs);
            }

            lock (accessLock)
            {
                buildState.SourceFilesToRebuild.Add(topic.FileID);

                if (topic.ClassID != 0)
                {
                    buildState.ClassFilesToRebuild.Add(topic.ClassID);
                }

                if (parentClassIDs != null)
                {
                    buildState.ClassFilesToRebuild.Add(parentClassIDs);
                }
                if (parentClassFileIDs != null)
                {
                    buildState.SourceFilesToRebuild.Add(parentClassFileIDs);
                }
            }
        }
Exemplo n.º 3
0
        public void OnDeleteTopic(Topic topic, IDObjects.NumberSet linksAffected, CodeDB.EventAccessor eventAccessor)
        {
            // We'll wait for OnChangeLinkTarget to handle linksAffected

            IDObjects.NumberSet parentClassIDs     = null;
            IDObjects.NumberSet parentClassFileIDs = null;

            if (topic.DefinesClass)
            {
                eventAccessor.GetInfoOnClassParents(topic.ClassID, out parentClassIDs, out parentClassFileIDs);
            }

            lock (accessLock)
            {
                buildState.SourceFilesToRebuild.Add(topic.FileID);

                if (topic.ClassID != 0)
                {
                    buildState.ClassFilesToRebuild.Add(topic.ClassID);
                }

                if (parentClassIDs != null)
                {
                    buildState.ClassFilesToRebuild.Add(parentClassIDs);
                }
                if (parentClassFileIDs != null)
                {
                    buildState.SourceFilesToRebuild.Add(parentClassFileIDs);
                }
            }
        }
Exemplo n.º 4
0
        public void OnDeleteTopic(Topic topic, IDObjects.NumberSet linksAffected, CodeDB.EventAccessor eventAccessor)
        {
            // We'll wait for OnChangeLinkTarget to handle linksAffected

            IDObjects.NumberSet parentClassIDs     = null;
            IDObjects.NumberSet parentClassFileIDs = null;

            if (topic.DefinesClass)
            {
                eventAccessor.GetInfoOnClassParents(topic.ClassID, out parentClassIDs, out parentClassFileIDs);
            }

            unprocessedChanges.Lock();
            try
            {
                unprocessedChanges.AddSourceFile(topic.FileID);

                if (topic.ClassID != 0)
                {
                    unprocessedChanges.AddClass(topic.ClassID);
                }

                if (parentClassIDs != null)
                {
                    unprocessedChanges.AddClasses(parentClassIDs);
                }
                if (parentClassFileIDs != null)
                {
                    unprocessedChanges.AddSourceFiles(parentClassFileIDs);
                }
            }
            finally
            { unprocessedChanges.Unlock(); }
        }
Exemplo n.º 5
0
        public void OnDeleteTopic(Topic topic, CodeDB.EventAccessor eventAccessor)
        {
            IDObjects.NumberSet parentClassIDs     = null;
            IDObjects.NumberSet parentClassFileIDs = null;

            if (topic.DefinesClass)
            {
                eventAccessor.GetInfoOnClassParents(topic.ClassID, out parentClassIDs, out parentClassFileIDs);
            }

            lock (accessLock)
            {
                buildState.SourceFilesToRebuild.Add(topic.FileID);

                if (topic.ClassID != 0)
                {
                    buildState.ClassFilesToRebuild.Add(topic.ClassID);
                }

                if (parentClassIDs != null)
                {
                    buildState.ClassFilesToRebuild.Add(parentClassIDs);
                }
                if (parentClassFileIDs != null)
                {
                    buildState.SourceFilesToRebuild.Add(parentClassFileIDs);
                }
            }
        }
Exemplo n.º 6
0
 public void OnDeletePrefix(string prefix, CodeDB.EventAccessor accessor)
 {
     lock (accessLock)
     {
         buildState.NeedToBuildSearchPrefixIndex = true;
         buildState.SearchPrefixesToRebuild.Add(prefix);
     }
 }
Exemplo n.º 7
0
        public void OnDeleteImageLink(ImageLink imageLink, CodeDB.EventAccessor eventAccessor)
        {
            // We don't have to force any HTML to be rebuilt here.  This can only happen if the containing topic was
            // changed so we can rely on the topic code to handle that.

            // However, this could change whether the image file is used or unused, so we have to add it to the list.
            if (imageLink.TargetFileID != 0)
            {
                unprocessedChanges.AddImageFileUseCheck(imageLink.TargetFileID);
            }
        }
Exemplo n.º 8
0
        public void OnAddLink(Link link, CodeDB.EventAccessor eventAccessor)
        {
            // If a class parent link was added we have to rebuild all source files that define that class as the class prototype
            // may have changed.
            IDObjects.NumberSet filesThatDefineClass = null;

            if (link.Type == LinkType.ClassParent)
            {
                filesThatDefineClass = eventAccessor.GetFileIDsThatDefineClassID(link.ClassID);

                // If it's resolved we have to rebuild all source files that define the target as well so its children get updated.
                if (link.TargetClassID != 0)
                {
                    IDObjects.NumberSet filesThatDefineTarget = eventAccessor.GetFileIDsThatDefineClassID(link.TargetClassID);

                    if (filesThatDefineClass == null)
                    {
                        filesThatDefineClass = filesThatDefineTarget;
                    }
                    else if (filesThatDefineTarget != null)
                    {
                        filesThatDefineClass.Add(filesThatDefineTarget);
                    }
                }
            }

            unprocessedChanges.Lock();
            try
            {
                // Even if it's not a class parent link we still need to rebuild the source and class files that contain it.  We can't
                // rely on the topic events picking it up because it's possible to change links without changing topics.  How?  By
                // changing a using statement, which causes all the links to change.
                unprocessedChanges.AddSourceFile(link.FileID);

                if (link.ClassID != 0)
                {
                    unprocessedChanges.AddClass(link.ClassID);
                }

                if (link.Type == LinkType.ClassParent && link.TargetClassID != 0)
                {
                    unprocessedChanges.AddClass(link.TargetClassID);
                }

                if (filesThatDefineClass != null)
                {
                    unprocessedChanges.AddSourceFiles(filesThatDefineClass);
                }
            }
            finally
            { unprocessedChanges.Unlock(); }
        }
Exemplo n.º 9
0
        public void OnDeleteLink(Link link, CodeDB.EventAccessor eventAccessor)
        {
            IDObjects.NumberSet filesThatDefineClass = null;

            if (link.Type == LinkType.ClassParent)
            {
                filesThatDefineClass = eventAccessor.GetFileIDsThatDefineClassID(link.ClassID);

                if (link.TargetClassID != 0)
                {
                    IDObjects.NumberSet filesThatDefineTarget = eventAccessor.GetFileIDsThatDefineClassID(link.TargetClassID);

                    if (filesThatDefineClass == null)
                    {
                        filesThatDefineClass = filesThatDefineTarget;
                    }
                    else if (filesThatDefineTarget != null)
                    {
                        filesThatDefineClass.Add(filesThatDefineTarget);
                    }
                }
            }

            unprocessedChanges.Lock();
            try
            {
                unprocessedChanges.AddSourceFile(link.FileID);

                if (link.ClassID != 0)
                {
                    unprocessedChanges.AddClass(link.ClassID);
                }

                if (link.Type == LinkType.ClassParent && link.TargetClassID != 0)
                {
                    unprocessedChanges.AddClass(link.TargetClassID);
                }

                if (filesThatDefineClass != null)
                {
                    unprocessedChanges.AddSourceFiles(filesThatDefineClass);
                }
            }
            finally
            { unprocessedChanges.Unlock(); }
        }
Exemplo n.º 10
0
        public void OnDeleteTopic(Topic topic, IDObjects.NumberSet linksAffected, CodeDB.EventAccessor eventAccessor)
        {
            if (!IncludeInIndex(topic))
            {
                return;
            }

            TopicEntry entry = new TopicEntry(topic, this);

            accessLock.EnterWriteLock();

            try
            {
                foreach (string keyword in entry.Keywords)
                {
                    string prefix    = KeywordPrefix(keyword);
                    var    numberSet = prefixTopicIDs[prefix];

                    if (numberSet != null)
                    {
                        numberSet.Remove(topic.TopicID);

                        if (numberSet.IsEmpty)
                        {
                            prefixTopicIDs.Remove(prefix);

                            foreach (var changeWatcher in changeWatchers)
                            {
                                changeWatcher.OnDeletePrefix(prefix, eventAccessor);
                            }
                        }
                        else
                        {
                            foreach (var changeWatcher in changeWatchers)
                            {
                                changeWatcher.OnUpdatePrefix(prefix, eventAccessor);
                            }
                        }
                    }
                }
            }
            finally
            { accessLock.ExitWriteLock(); }
        }
Exemplo n.º 11
0
        public void OnDeleteLink(Link link, CodeDB.EventAccessor eventAccessor)
        {
            IDObjects.NumberSet filesThatDefineClass = null;

            if (link.Type == LinkType.ClassParent)
            {
                filesThatDefineClass = eventAccessor.GetFileIDsThatDefineClassID(link.ClassID);

                if (link.TargetClassID != 0)
                {
                    IDObjects.NumberSet filesThatDefineTarget = eventAccessor.GetFileIDsThatDefineClassID(link.TargetClassID);

                    if (filesThatDefineClass == null)
                    {
                        filesThatDefineClass = filesThatDefineTarget;
                    }
                    else if (filesThatDefineTarget != null)
                    {
                        filesThatDefineClass.Add(filesThatDefineTarget);
                    }
                }
            }

            lock (accessLock)
            {
                buildState.SourceFilesToRebuild.Add(link.FileID);

                if (link.ClassID != 0)
                {
                    buildState.ClassFilesToRebuild.Add(link.ClassID);
                }

                if (link.Type == LinkType.ClassParent && link.TargetClassID != 0)
                {
                    buildState.ClassFilesToRebuild.Add(link.TargetClassID);
                }

                if (filesThatDefineClass != null)
                {
                    buildState.SourceFilesToRebuild.Add(filesThatDefineClass);
                }
            }
        }
Exemplo n.º 12
0
        // Group: CodeDB.IChangeWatcher Functions
        // __________________________________________________________________________


        public void OnAddTopic(Topic topic, CodeDB.EventAccessor eventAccessor)
        {
            if (!IncludeInIndex(topic))
            {
                return;
            }

            TopicEntry entry = new TopicEntry(topic, this);

            accessLock.EnterWriteLock();

            try
            {
                foreach (string keyword in entry.Keywords)
                {
                    string prefix   = KeywordPrefix(keyword);
                    var    topicIDs = prefixTopicIDs[prefix];

                    if (topicIDs == null)
                    {
                        topicIDs = new IDObjects.NumberSet();
                        topicIDs.Add(topic.TopicID);
                        prefixTopicIDs[prefix] = topicIDs;

                        foreach (var changeWatcher in changeWatchers)
                        {
                            changeWatcher.OnAddPrefix(prefix, eventAccessor);
                        }
                    }
                    else
                    {
                        topicIDs.Add(topic.TopicID);

                        foreach (var changeWatcher in changeWatchers)
                        {
                            changeWatcher.OnUpdatePrefix(prefix, eventAccessor);
                        }
                    }
                }
            }
            finally
            { accessLock.ExitWriteLock(); }
        }
Exemplo n.º 13
0
        public void OnChangeLinkTarget(Link link, int oldTargetTopicID, int oldTargetClassID, CodeDB.EventAccessor eventAccessor)
        {
            IDObjects.NumberSet filesThatDefineClass = null;

            if (link.Type == LinkType.ClassParent)
            {
                filesThatDefineClass = eventAccessor.GetFileIDsThatDefineClassID(link.ClassID);

                if (link.TargetClassID != 0)
                {
                    IDObjects.NumberSet filesThatDefineTarget = eventAccessor.GetFileIDsThatDefineClassID(link.TargetClassID);

                    if (filesThatDefineClass == null)
                    {
                        filesThatDefineClass = filesThatDefineTarget;
                    }
                    else if (filesThatDefineTarget != null)
                    {
                        filesThatDefineClass.Add(filesThatDefineTarget);
                    }
                }

                if (oldTargetClassID != 0)
                {
                    IDObjects.NumberSet filesThatDefineOldTarget = eventAccessor.GetFileIDsThatDefineClassID(oldTargetClassID);

                    if (filesThatDefineClass == null)
                    {
                        filesThatDefineClass = filesThatDefineOldTarget;
                    }
                    else if (filesThatDefineOldTarget != null)
                    {
                        filesThatDefineClass.Add(filesThatDefineOldTarget);
                    }
                }
            }

            lock (accessLock)
            {
                buildState.SourceFilesToRebuild.Add(link.FileID);

                if (link.ClassID != 0)
                {
                    buildState.ClassFilesToRebuild.Add(link.ClassID);
                }

                if (link.Type == LinkType.ClassParent)
                {
                    if (link.TargetClassID != 0)
                    {
                        buildState.ClassFilesToRebuild.Add(link.TargetClassID);
                    }
                    if (oldTargetClassID != 0)
                    {
                        buildState.ClassFilesToRebuild.Add(oldTargetClassID);
                    }
                }

                if (filesThatDefineClass != null)
                {
                    buildState.SourceFilesToRebuild.Add(filesThatDefineClass);
                }
            }

            // If this is a Natural Docs link, see if it appears in the summary for any topics.  This would mean that it appears in
            // these topics' tooltips, so we have to find any links to these topics and rebuild the files those links appear in.

            // Why do we have to do this if links aren't added to tooltips?  Because how it's resolved can affect it's appearance.
            // It will show up as "link" versus "<link>" if it's resolved or not, and "a at b" versus "a" depending on if it resolves to
            // the topic "a at b" or the topic "b".

            // Why don't we do this for type links?  Because unlike Natural Docs links, type links don't change in appearance
            // based on whether they're resolved or not.  Therefore the logic that we don't have to worry about it because links
            // don't appear in tooltips holds true.

            if (link.Type == LinkType.NaturalDocs)
            {
                IDObjects.NumberSet fileIDs, classIDs;
                eventAccessor.GetInfoOnLinksToTopicsWithNDLinkInSummary(link, out fileIDs, out classIDs);

                if (fileIDs != null || classIDs != null)
                {
                    lock (accessLock)
                    {
                        if (fileIDs != null)
                        {
                            buildState.SourceFilesToRebuild.Add(fileIDs);
                        }
                        if (classIDs != null)
                        {
                            buildState.ClassFilesToRebuild.Add(classIDs);
                        }
                    }
                }
            }
        }
Exemplo n.º 14
0
 public void OnDeleteImageLink(ImageLink imageLink, CodeDB.EventAccessor eventAccessor)
 {
     unprocessedChanges.DeleteImageLink(imageLink);
 }
Exemplo n.º 15
0
        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);
                        }
                    }
                }
            }
        }
Exemplo n.º 16
0
        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();
            }
        }
Exemplo n.º 17
0
 public void OnDeletePrefix(string prefix, CodeDB.EventAccessor accessor)
 {
     unprocessedChanges.AddMainSearchFiles();
     unprocessedChanges.AddSearchPrefix(prefix);
 }
Exemplo n.º 18
0
 public void OnChangeLinkTarget(Link link, int oldTargetTopicID, int oldTargetClassID, CodeDB.EventAccessor eventAccessor)
 {
     // We don't care about links.
 }
Exemplo n.º 19
0
 public void OnUpdatePrefix(string prefix, CodeDB.EventAccessor accessor)
 {
     unprocessedChanges.AddSearchPrefix(prefix);
 }
Exemplo n.º 20
0
 public void OnChangeImageLinkTarget(ImageLink imageLink, int oldTargetFileID, CodeDB.EventAccessor eventAccessor)
 {
     // We're going to be the one causing this event, not responding to it.  No other code should be changing link definitions.
 }
Exemplo n.º 21
0
 public void OnChangeImageLinkTarget(ImageLink imageLink, int oldTargetFileID, CodeDB.EventAccessor eventAccessor)
 {
     // xxx placeholder
 }
Exemplo n.º 22
0
 public void OnDeleteLink(Link link, CodeDB.EventAccessor eventAccessor)
 {
     // We don't care about links.
 }
Exemplo n.º 23
0
 public void OnChangeImageLinkTarget(ImageLink imageLink, int oldTargetFileID, CodeDB.EventAccessor eventAccessor)
 {
     // We don't care about image links.
 }
Exemplo n.º 24
0
 public void OnDeleteImageLink(ImageLink imageLink, CodeDB.EventAccessor eventAccessor)
 {
     // We don't care about image links.
 }
Exemplo n.º 25
0
 public void OnDeleteImageLink(ImageLink imageLink, CodeDB.EventAccessor eventAccessor)
 {
     // xxx placeholder
 }
Exemplo n.º 26
0
        public void OnChangeImageLinkTarget(ImageLink imageLink, int oldTargetFileID, CodeDB.EventAccessor eventAccessor)
        {
            // Here we have to rebuild the HTML containing the link because this could happen without the containing
            // topic changing, such as if an image file was deleted or a new one served as a better target.

            unprocessedChanges.AddSourceFile(imageLink.FileID);
            unprocessedChanges.AddClass(imageLink.ClassID);


            // We also have to check both image files because they could have changed between used and unused.

            if (imageLink.TargetFileID != 0)
            {
                unprocessedChanges.AddImageFileUseCheck(imageLink.TargetFileID);
            }
            if (oldTargetFileID != 0)
            {
                unprocessedChanges.AddImageFileUseCheck(oldTargetFileID);
            }


            // We also have to see if it appears in the summary for any topics.  This would mean that it appears in these topics'
            // tooltips, so we have to find any links to these topics and rebuild the files those links appear in.

            // Why do we have to do this if links aren't added to tooltips?  Because how it's resolved can affect it's appearance.
            // It will show up as "(see diagram)" versus "(see images/diagram.jpg)" if it's resolved or not.

            IDObjects.NumberSet fileIDs, classIDs;
            eventAccessor.GetInfoOnLinksToTopicsWithImageLinkInSummary(imageLink, out fileIDs, out classIDs);

            if (fileIDs != null)
            {
                unprocessedChanges.AddSourceFiles(fileIDs);
            }
            if (classIDs != null)
            {
                unprocessedChanges.AddClasses(classIDs);
            }
        }