Skip to content

Commit 5f86fa8

Browse files
committed
Added module to module reference handling to the ParseCoordinator.
1 parent 99ff37a commit 5f86fa8

File tree

4 files changed

+76
-22
lines changed

4 files changed

+76
-22
lines changed

Rubberduck.Parsing/Symbols/DeclarationFinder.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,12 @@ public IEnumerable<Declaration> Undeclared
141141

142142
public IEnumerable<Declaration> Members(Declaration module)
143143
{
144-
return _declarations[module.QualifiedName.QualifiedModuleName];
144+
return Members(module.QualifiedName.QualifiedModuleName);
145+
}
146+
147+
public IEnumerable<Declaration> Members(QualifiedModuleName module)
148+
{
149+
return _declarations[module];
145150
}
146151

147152
private IEnumerable<Declaration> _nonBaseAsType;

Rubberduck.Parsing/VBA/ModuleState.cs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ public class ModuleState
2121
public List<IAnnotation> Annotations { get; private set; }
2222
public SyntaxErrorException ModuleException { get; private set; }
2323
public IDictionary<Tuple<string, DeclarationType>, Attributes> ModuleAttributes { get; private set; }
24-
public HashSet<QualifiedModuleName> HasReferenceToModule { get; private set;}
25-
public ConcurrentDictionary<QualifiedModuleName, byte> IsReferencedByModule { get; private set; }
24+
public ConcurrentDictionary<QualifiedModuleName, byte> HasReferenceToModule { get; private set; }
25+
public HashSet<QualifiedModuleName> IsReferencedByModule { get; private set; }
2626

2727
public bool IsNew { get; private set; }
2828

@@ -46,8 +46,8 @@ public ModuleState(ConcurrentDictionary<Declaration, byte> declarations)
4646
Annotations = new List<IAnnotation>();
4747
ModuleException = null;
4848
ModuleAttributes = new Dictionary<Tuple<string, DeclarationType>, Attributes>();
49-
HasReferenceToModule = new HashSet<QualifiedModuleName>();
50-
IsReferencedByModule = new ConcurrentDictionary<QualifiedModuleName, byte>();
49+
HasReferenceToModule = new ConcurrentDictionary<QualifiedModuleName, byte>();
50+
IsReferencedByModule = new HashSet<QualifiedModuleName>();
5151

5252
IsNew = true;
5353
}
@@ -63,8 +63,8 @@ public ModuleState(ParserState state)
6363
Annotations = new List<IAnnotation>();
6464
ModuleException = null;
6565
ModuleAttributes = new Dictionary<Tuple<string, DeclarationType>, Attributes>();
66-
HasReferenceToModule = new HashSet<QualifiedModuleName>();
67-
IsReferencedByModule = new ConcurrentDictionary<QualifiedModuleName, byte>();
66+
HasReferenceToModule = new ConcurrentDictionary<QualifiedModuleName, byte>();
67+
IsReferencedByModule = new HashSet<QualifiedModuleName>();
6868

6969
IsNew = true;
7070
}
@@ -80,8 +80,8 @@ public ModuleState(SyntaxErrorException moduleException)
8080
Annotations = new List<IAnnotation>();
8181
ModuleException = moduleException;
8282
ModuleAttributes = new Dictionary<Tuple<string, DeclarationType>, Attributes>();
83-
HasReferenceToModule = new HashSet<QualifiedModuleName>();
84-
IsReferencedByModule = new ConcurrentDictionary<QualifiedModuleName, byte>();
83+
HasReferenceToModule = new ConcurrentDictionary<QualifiedModuleName, byte>();
84+
IsReferencedByModule = new HashSet<QualifiedModuleName>();
8585

8686
IsNew = true;
8787
}
@@ -97,8 +97,8 @@ public ModuleState(IDictionary<Tuple<string, DeclarationType>, Attributes> modul
9797
Annotations = new List<IAnnotation>();
9898
ModuleException = null;
9999
ModuleAttributes = moduleAttributes;
100-
HasReferenceToModule = new HashSet<QualifiedModuleName>();
101-
IsReferencedByModule = new ConcurrentDictionary<QualifiedModuleName, byte>();
100+
HasReferenceToModule = new ConcurrentDictionary<QualifiedModuleName, byte>();
101+
IsReferencedByModule = new HashSet<QualifiedModuleName>();
102102

103103
IsNew = true;
104104
}
@@ -154,12 +154,12 @@ public ModuleState SetModuleAttributes(IDictionary<Tuple<string, DeclarationType
154154

155155
public void RefreshHasReferenceToModule()
156156
{
157-
HasReferenceToModule = new HashSet<QualifiedModuleName>();
157+
HasReferenceToModule = new ConcurrentDictionary<QualifiedModuleName, byte>();
158158
}
159159

160160
public void RefreshIsReferencedByModule()
161161
{
162-
IsReferencedByModule = new ConcurrentDictionary<QualifiedModuleName, byte>();
162+
IsReferencedByModule = new HashSet<QualifiedModuleName>();
163163
}
164164

165165

Rubberduck.Parsing/VBA/ParseCoordinator.cs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -217,6 +217,8 @@ private void ExecuteCommonParseActivities(List<IVBComponent> toParse, Cancellati
217217
_projectDeclarations.Clear();
218218
State.ClearAllReferences();
219219

220+
ClearModuleToModuleReferences(toParse);
221+
220222
ParseComponents(toParse, token);
221223

222224
if (token.IsCancellationRequested || State.Status >= ParserState.Error)
@@ -268,6 +270,14 @@ private void SetModuleStates(List<IVBComponent> components, ParserState parserSt
268270
}
269271
}
270272

273+
private void ClearModuleToModuleReferences(List<IVBComponent> toClear)
274+
{
275+
foreach (var component in toClear)
276+
{
277+
State.ClearModuleToModuleReferencesFromModule(new QualifiedModuleName(component));
278+
}
279+
}
280+
271281
private void ParseComponents(List<IVBComponent> components, CancellationToken token)
272282
{
273283
token.ThrowIfCancellationRequested();
@@ -496,6 +506,10 @@ private void ResolveAllReferences(CancellationToken token)
496506

497507
token.ThrowIfCancellationRequested();
498508

509+
AddModuleToModuleReferences(State.DeclarationFinder, token);
510+
511+
token.ThrowIfCancellationRequested();
512+
499513
AddUndeclaredVariablesToDeclarations();
500514

501515
//This is here and not in the calling method because it has to happen before the ready state is reached.
@@ -555,6 +569,41 @@ private void ResolveReferences(DeclarationFinder finder, QualifiedModuleName qua
555569
}
556570
}
557571

572+
private void AddModuleToModuleReferences(DeclarationFinder finder, CancellationToken token)
573+
{
574+
var options = new ParallelOptions();
575+
options.CancellationToken = token;
576+
options.MaxDegreeOfParallelism = _maxDegreeOfReferenceResolverParallelism;
577+
try
578+
{
579+
Parallel.For(0, State.ParseTrees.Count, options,
580+
(index) => AddModuleToModuleReferences(finder, State.ParseTrees[index].Key)
581+
);
582+
}
583+
catch (AggregateException exception)
584+
{
585+
if (exception.Flatten().InnerExceptions.All(ex => ex is OperationCanceledException))
586+
{
587+
throw exception.InnerException; //This eliminates the stack trace, but for the cancellation, this is irrelevant.
588+
}
589+
State.SetStatusAndFireStateChanged(this, ParserState.ResolverError);
590+
throw;
591+
}
592+
}
593+
594+
private void AddModuleToModuleReferences(DeclarationFinder finder, QualifiedModuleName referencedModule)
595+
{
596+
var referencingModules = finder.Members(referencedModule)
597+
.SelectMany(declaration => declaration.References)
598+
.Select(reference => reference.QualifiedModuleName)
599+
.Distinct()
600+
.Where(referencingModule => !referencedModule.Equals(referencingModule));
601+
foreach (var referencingModule in referencingModules)
602+
{
603+
State.AddModuleToModuleReference(referencedModule, referencingModule);
604+
}
605+
}
606+
558607
private void AddUndeclaredVariablesToDeclarations()
559608
{
560609
var undeclared = State.DeclarationFinder.Undeclared.ToList();
@@ -651,6 +700,7 @@ private bool CleanUpRemovedComponents(List<IVBComponent> components)
651700
var componentRemoved = removedModuledecalrations.Any();
652701
foreach (var declaration in removedModuledecalrations)
653702
{
703+
State.ClearModuleToModuleReferencesFromModule(declaration.QualifiedName.QualifiedModuleName);
654704
State.ClearStateCache(declaration.QualifiedName.QualifiedModuleName);
655705
}
656706
return componentRemoved;

Rubberduck.Parsing/VBA/RubberduckParserState.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1098,12 +1098,12 @@ public void AddModuleToModuleReference(QualifiedModuleName referencedModule, Qua
10981098
{
10991099
return;
11001100
}
1101-
if (referencingModuleState.HasReferenceToModule.Contains(referencedModule))
1101+
if (referencedModuleState.IsReferencedByModule.Contains(referencingModule))
11021102
{
11031103
return;
11041104
}
1105-
referencedModuleState.IsReferencedByModule.AddOrUpdate(referencingModule, 1, (key,value) => value);
1106-
referencingModuleState.HasReferenceToModule.Add(referencedModule);
1105+
referencedModuleState.IsReferencedByModule.Add(referencingModule);
1106+
referencingModuleState.HasReferenceToModule.AddOrUpdate(referencedModule, 1, (key, value) => value);
11071107
}
11081108

11091109
public void ClearModuleToModuleReferencesFromModule(QualifiedModuleName referencingModule)
@@ -1115,14 +1115,13 @@ public void ClearModuleToModuleReferencesFromModule(QualifiedModuleName referenc
11151115
}
11161116

11171117
ModuleState referencedModuleState;
1118-
byte dummyOutValue;
1119-
foreach (var referencedModule in referencingModuleState.HasReferenceToModule)
1120-
{
1118+
foreach (var referencedModule in referencingModuleState.HasReferenceToModule.Keys)
1119+
{
11211120
if (!_moduleStates.TryGetValue(referencedModule,out referencedModuleState))
11221121
{
11231122
continue;
11241123
}
1125-
referencedModuleState.IsReferencedByModule.TryRemove(referencingModule,out dummyOutValue);
1124+
referencedModuleState.IsReferencedByModule.Remove(referencingModule);
11261125
}
11271126
referencingModuleState.RefreshHasReferenceToModule();
11281127
}
@@ -1134,7 +1133,7 @@ public HashSet<QualifiedModuleName> ModulesReferencedBy(QualifiedModuleName refe
11341133
{
11351134
return new HashSet<QualifiedModuleName>();
11361135
}
1137-
return new HashSet<QualifiedModuleName>(referencingModuleState.HasReferenceToModule);
1136+
return new HashSet<QualifiedModuleName>(referencingModuleState.HasReferenceToModule.Keys);
11381137
}
11391138

11401139
public HashSet<QualifiedModuleName> ModulesReferencing(QualifiedModuleName referencedModule)
@@ -1144,7 +1143,7 @@ public HashSet<QualifiedModuleName> ModulesReferencing(QualifiedModuleName refer
11441143
{
11451144
return new HashSet<QualifiedModuleName>();
11461145
}
1147-
return new HashSet<QualifiedModuleName>(referencedModuleState.IsReferencedByModule.Keys);
1146+
return new HashSet<QualifiedModuleName>(referencedModuleState.IsReferencedByModule);
11481147
}
11491148

11501149
private bool _isDisposed;

0 commit comments

Comments
 (0)