Skip to content

Commit dd426b1

Browse files
committed
Introduce a field on the COM synchronizer for references affected by priority changes
In case the priorities of references change the variable shadowing potentially changes for all references in between. So we need this information to force the corresponding references to be resolved again, even if there is no other reason.
1 parent 3ba395a commit dd426b1

File tree

4 files changed

+63
-41
lines changed

4 files changed

+63
-41
lines changed

Rubberduck.Parsing/VBA/ComReferenceLoading/COMReferenceSynchronizerBase.cs

Lines changed: 55 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ public abstract class COMReferenceSynchronizerBase : ICOMReferenceSynchronizer,
2525
private readonly IReferencedDeclarationsCollector _referencedDeclarationsCollector;
2626

2727
private readonly List<QualifiedModuleName> _unloadedCOMReferences = new List<QualifiedModuleName>();
28-
private readonly List<(string projectId, string referencedProjectId, int newPriority, int oldPriority)> _referencesWithChangedPriority = new List<(string projectId, string referencedProjectId, int newPriority, int oldPriority)>();
28+
private readonly List<(string projectId, string referencedProjectId)> _referencesAffectedByPriorityChanges = new List<(string projectId, string referencedProjectId)>();
2929

3030
private readonly Dictionary<(string identifierName, string fullPath), string> _projectIdsByFilePathAndProjectName = new Dictionary<(string identifierName, string fullPath), string>();
3131

@@ -59,7 +59,8 @@ protected COMReferenceSynchronizerBase(RubberduckParserState state, IParserState
5959

6060

6161
public bool LastSyncOfCOMReferencesLoadedReferences { get; private set; }
62-
public IEnumerable<QualifiedModuleName> COMReferencesUnloadedUnloadedInLastSync => _unloadedCOMReferences;
62+
public IEnumerable<QualifiedModuleName> COMReferencesUnloadedInLastSync => _unloadedCOMReferences;
63+
public IEnumerable<(string projectId, string referencedProjectId)> COMReferencesAffectedByPriorityChangesInLastSync => _referencesAffectedByPriorityChanges;
6364

6465
private readonly IDictionary<string, ReferencePriorityMap> _projectReferences = new Dictionary<string, ReferencePriorityMap>();
6566
public IReadOnlyCollection<ReferencePriorityMap> ProjectReferences => _projectReferences.Values.AsReadOnly();
@@ -77,7 +78,7 @@ public void SyncComReferences(CancellationToken token)
7778

7879
LastSyncOfCOMReferencesLoadedReferences = false;
7980
_unloadedCOMReferences.Clear();
80-
_referencesWithChangedPriority.Clear();
81+
_referencesAffectedByPriorityChanges.Clear();
8182
RefreshReferencedByProjectId();
8283

8384
var unmapped = new ConcurrentBag<ReferenceInfo>();
@@ -91,31 +92,55 @@ public void SyncComReferences(CancellationToken token)
9192
LoadReferences(referencesToLoad, unmapped, token);
9293
}
9394

94-
DetermineReferencesWithChangedPriorities(_projectReferences, oldProjectReferences);
95+
DetermineReferencesAffectedByPriorityChanges(_projectReferences, oldProjectReferences);
96+
UnloadNoLongerExistingReferences(_projectReferences, oldProjectReferences);
9597

98+
parsingStageTimer.Stop();
99+
parsingStageTimer.Log("Loaded and unloaded referenced libraries in {0}ms.");
100+
}
101+
102+
private void UnloadNoLongerExistingReferences(IDictionary<string, ReferencePriorityMap> newProjectReferences, IDictionary<string, ReferencePriorityMap> oldProjectReferences)
103+
{
96104
var noLongerReferencedProjectIds = oldProjectReferences.Keys
97-
.Where(projectId => !_projectReferences.ContainsKey(projectId))
105+
.Where(projectId => !newProjectReferences.ContainsKey(projectId))
98106
.ToList();
99107

100108
foreach (var referencedProjectId in noLongerReferencedProjectIds)
101109
{
102110
UnloadComReference(referencedProjectId);
103111
}
112+
}
104113

105-
parsingStageTimer.Stop();
106-
parsingStageTimer.Log("Loaded and unloaded referenced libraries in {0}ms.");
114+
private void DetermineReferencesAffectedByPriorityChanges(IDictionary<string, ReferencePriorityMap> newProjectReferences, IDictionary<string, ReferencePriorityMap> oldProjectReferences)
115+
{
116+
var referencePriorityChanges = ReferencePriorityChanges(newProjectReferences, oldProjectReferences);
117+
118+
foreach (var oldMap in oldProjectReferences.Values)
119+
{
120+
foreach (var projectId in referencePriorityChanges.Keys)
121+
{
122+
if (oldMap.TryGetValue(projectId, out var priority)
123+
&& referencePriorityChanges[projectId]
124+
.Any(tpl => (tpl.oldPriority <= priority && tpl.newPriority >= priority)
125+
|| (tpl.oldPriority >= priority && tpl.newPriority <= priority)))
126+
{
127+
_referencesAffectedByPriorityChanges.Add((projectId, oldMap.ReferencedProjectId));
128+
}
129+
}
130+
}
107131
}
108132

109-
private void DetermineReferencesWithChangedPriorities(IDictionary<string, ReferencePriorityMap> newProjectReferences, IDictionary<string, ReferencePriorityMap> oldProjectReferences)
133+
private static IDictionary<string, List<(int newPriority, int oldPriority)>> ReferencePriorityChanges(IDictionary<string, ReferencePriorityMap> newProjectReferences, IDictionary<string, ReferencePriorityMap> oldProjectReferences)
110134
{
135+
var referencePriorityChanges = new Dictionary<string, List<(int newPriority, int oldPriority)>>();
111136
foreach (var referencedProjectId in oldProjectReferences.Keys)
112137
{
113138
var oldMap = oldProjectReferences[referencedProjectId];
114139
if (!newProjectReferences.TryGetValue(referencedProjectId, out var newMap))
115140
{
116141
foreach (var projectId in oldMap.Keys)
117142
{
118-
_referencesWithChangedPriority.Add((projectId, referencedProjectId, int.MaxValue, oldMap[projectId]));
143+
AddPriorityChangeToDictionary(projectId, int.MaxValue, oldMap[projectId], referencePriorityChanges);
119144
}
120145
}
121146
else
@@ -130,17 +155,15 @@ private void DetermineReferencesWithChangedPriorities(IDictionary<string, Refere
130155

131156
if (newPriority != oldPriority)
132157
{
133-
_referencesWithChangedPriority.Add((projectId, referencedProjectId, newPriority,
134-
oldMap[projectId]));
158+
AddPriorityChangeToDictionary(projectId, newPriority, oldMap[projectId], referencePriorityChanges);
135159
}
136160
}
137161

138162
foreach (var projectId in newMap.Keys)
139163
{
140164
if (!oldMap.ContainsKey(projectId))
141165
{
142-
_referencesWithChangedPriority.Add(
143-
(projectId, referencedProjectId, newMap[projectId], int.MaxValue));
166+
AddPriorityChangeToDictionary(projectId, newMap[projectId], int.MaxValue, referencePriorityChanges);
144167
}
145168
}
146169
}
@@ -156,9 +179,27 @@ private void DetermineReferencesWithChangedPriorities(IDictionary<string, Refere
156179
var newMap = newProjectReferences[referencedProjectId];
157180
foreach (var projectId in newMap.Keys)
158181
{
159-
_referencesWithChangedPriority.Add((projectId, referencedProjectId, newMap[projectId], int.MaxValue));
182+
AddPriorityChangeToDictionary(projectId, newMap[projectId], int.MaxValue, referencePriorityChanges);
160183
}
161184
}
185+
186+
return referencePriorityChanges;
187+
}
188+
189+
private static void AddPriorityChangeToDictionary(
190+
string projectId,
191+
int newPriority,
192+
int oldPriority,
193+
IDictionary<string, List<(int newPriority, int oldPriority)>> dict)
194+
{
195+
if (dict.TryGetValue(projectId, out var changeList))
196+
{
197+
changeList.Add((newPriority, oldPriority));
198+
}
199+
else
200+
{
201+
dict.Add(projectId, new List<(int newPriority, int oldPriority)> { (newPriority, oldPriority) });
202+
}
162203
}
163204

164205
private Dictionary<string, List<ReferenceInfo>> ReferencedByProjectId()

Rubberduck.Parsing/VBA/ComReferenceLoading/ICOMReferenceSynchronizer.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ namespace Rubberduck.Parsing.VBA.ComReferenceLoading
77
public interface ICOMReferenceSynchronizer
88
{
99
bool LastSyncOfCOMReferencesLoadedReferences { get; }
10-
IEnumerable<QualifiedModuleName> COMReferencesUnloadedUnloadedInLastSync { get; }
10+
IEnumerable<QualifiedModuleName> COMReferencesUnloadedInLastSync { get; }
11+
IEnumerable<(string projectId, string referencedProjectId)> COMReferencesAffectedByPriorityChangesInLastSync { get; }
1112

1213
void SyncComReferences(CancellationToken token);
1314
}

Rubberduck.Parsing/VBA/ParseCoordinator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -224,9 +224,9 @@ private void ExecuteCommonParseActivities(IReadOnlyCollection<QualifiedModuleNam
224224
token.ThrowIfCancellationRequested();
225225

226226
_parsingStageService.SyncComReferences(token);
227-
if (_parsingStageService.LastSyncOfCOMReferencesLoadedReferences || _parsingStageService.COMReferencesUnloadedUnloadedInLastSync.Any())
227+
if (_parsingStageService.LastSyncOfCOMReferencesLoadedReferences || _parsingStageService.COMReferencesUnloadedInLastSync.Any())
228228
{
229-
var unloadedReferences = _parsingStageService.COMReferencesUnloadedUnloadedInLastSync;
229+
var unloadedReferences = _parsingStageService.COMReferencesUnloadedInLastSync;
230230
var additionalModulesToBeReresolved = OtherModulesReferencingAnyNotToBeParsed(unloadedReferences.ToHashSet().AsReadOnly(), toParse);
231231
toReresolveReferences.UnionWith(additionalModulesToBeReresolved);
232232
_parserStateManager.SetModuleStates(additionalModulesToBeReresolved, ParserState.ResolvingReferences, token);

Rubberduck.Parsing/VBA/ParsingStageService.cs

Lines changed: 4 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -52,30 +52,10 @@ public ParsingStageService(
5252
_referenceResolver = referenceResolver;
5353
}
5454

55-
56-
public bool LastLoadOfBuiltInDeclarationsLoadedDeclarations
57-
{
58-
get
59-
{
60-
return _builtInDeclarationLoader.LastLoadOfBuiltInDeclarationsLoadedDeclarations;
61-
}
62-
}
63-
64-
public bool LastSyncOfCOMReferencesLoadedReferences
65-
{
66-
get
67-
{
68-
return _comSynchronizer.LastSyncOfCOMReferencesLoadedReferences;
69-
}
70-
}
71-
72-
public IEnumerable<QualifiedModuleName> COMReferencesUnloadedUnloadedInLastSync
73-
{
74-
get
75-
{
76-
return _comSynchronizer.COMReferencesUnloadedUnloadedInLastSync;
77-
}
78-
}
55+
public bool LastLoadOfBuiltInDeclarationsLoadedDeclarations => _builtInDeclarationLoader.LastLoadOfBuiltInDeclarationsLoadedDeclarations;
56+
public bool LastSyncOfCOMReferencesLoadedReferences => _comSynchronizer.LastSyncOfCOMReferencesLoadedReferences;
57+
public IEnumerable<QualifiedModuleName> COMReferencesUnloadedInLastSync => _comSynchronizer.COMReferencesUnloadedInLastSync;
58+
public IEnumerable<(string projectId, string referencedProjectId)>COMReferencesAffectedByPriorityChangesInLastSync =>_comSynchronizer.COMReferencesAffectedByPriorityChangesInLastSync;
7959

8060
public void LoadBuitInDeclarations()
8161
{

0 commit comments

Comments
 (0)