Skip to content

Commit 55968ab

Browse files
committed
Make parser/resolver more async
1 parent d748e89 commit 55968ab

File tree

1 file changed

+55
-12
lines changed

1 file changed

+55
-12
lines changed

Rubberduck.Parsing/VBA/RubberduckParser.cs

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -179,8 +179,7 @@ private void ParseAll()
179179
State.SetStatusAndFireStateChanged(_state.Status);
180180
return;
181181
}
182-
183-
182+
184183
lock (_state) // note, method is invoked from UI thread... really need the lock here?
185184
{
186185
foreach (var component in toParse)
@@ -192,9 +191,6 @@ private void ParseAll()
192191
// note: seting to 'Parsed' would include them in the resolver walk. 'Ready' excludes them.
193192
_state.SetModuleState(component, ParserState.Ready);
194193
}
195-
196-
//Debug.Assert(unchanged.All(component => _state.GetModuleState(component) == ParserState.Ready));
197-
//Debug.Assert(toParse.All(component => _state.GetModuleState(component) == ParserState.Pending));
198194
}
199195

200196
// invalidation cleanup should go into ParseAsync?
@@ -206,18 +202,65 @@ private void ParseAll()
206202
}
207203
}
208204

209-
var parseTasks = new Task[components.Count];
210-
for (var i = 0; i < components.Count; i++)
205+
_projectDeclarations.Clear();
206+
_state.ClearBuiltInReferences();
207+
208+
var parseTasks = new Task[toParse.Count];
209+
for (var i = 0; i < toParse.Count; i++)
211210
{
212-
parseTasks[i] = ParseAsync(components[i], CancellationToken.None);
211+
var index = i;
212+
parseTasks[i] = new Task(() =>
213+
{
214+
ParseAsync(toParse[index], CancellationToken.None).Wait();
215+
216+
if (_resolverTokenSource.IsCancellationRequested || _central.IsCancellationRequested)
217+
{
218+
return;
219+
}
220+
221+
if (_state.Status == ParserState.Error) { return; }
222+
223+
var qualifiedName = new QualifiedModuleName(toParse[index]);
224+
Logger.Debug("Module '{0}' {1}", qualifiedName.ComponentName,
225+
_state.IsNewOrModified(qualifiedName) ? "was modified" : "was NOT modified");
226+
227+
_state.SetModuleState(toParse[index], ParserState.Resolving);
228+
ResolveDeclarations(qualifiedName.Component,
229+
_state.ParseTrees.Find(s => s.Key == qualifiedName).Value);
230+
});
231+
232+
parseTasks[i].Start();
213233
}
214234

215235
Task.WaitAll(parseTasks);
236+
_state.SetStatusAndFireStateChanged(ParserState.ResolvedDeclarations);
216237

217-
if (_state.Status != ParserState.Error)
238+
if (_state.Status < ParserState.Error)
218239
{
219-
Logger.Trace("Starting resolver task");
220-
Resolve(_central.Token);
240+
ResolveReferencesAsync();
241+
}
242+
}
243+
244+
private void ResolveReferencesAsync()
245+
{
246+
var finder = new DeclarationFinder(_state.AllDeclarations, _state.AllComments, _state.AllAnnotations);
247+
var passes = new List<ICompilationPass>
248+
{
249+
// This pass has to come first because the type binding resolution depends on it.
250+
new ProjectReferencePass(finder),
251+
new TypeHierarchyPass(finder, new VBAExpressionParser()),
252+
new TypeAnnotationPass(finder, new VBAExpressionParser())
253+
};
254+
passes.ForEach(p => p.Execute());
255+
256+
foreach (var kvp in _state.ParseTrees)
257+
{
258+
if (_resolverTokenSource.IsCancellationRequested || _central.IsCancellationRequested)
259+
{
260+
return;
261+
}
262+
263+
Task.Run(() => ResolveReferences(finder, kvp.Key.Component, kvp.Value));
221264
}
222265
}
223266

@@ -584,7 +627,7 @@ private Declaration CreateProjectDeclaration(QualifiedModuleName projectQualifie
584627
private void ResolveReferences(DeclarationFinder finder, VBComponent component, IParseTree tree)
585628
{
586629
var state = _state.GetModuleState(component);
587-
if (_state.Status == ParserState.ResolverError || (state != ParserState.Parsed))
630+
if (state != ParserState.Resolving)
588631
{
589632
return;
590633
}

0 commit comments

Comments
 (0)