Skip to content

Commit a594e04

Browse files
authored
Merge pull request #1813 from Hosch250/parserIssues
Get Linq out of parser/parser state
2 parents 9a00e68 + d748e89 commit a594e04

File tree

2 files changed

+518
-121
lines changed

2 files changed

+518
-121
lines changed

Rubberduck.Parsing/VBA/RubberduckParser.cs

Lines changed: 142 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections.Concurrent;
33
using System.Collections.Generic;
4-
using System.Linq;
54
using System.Threading;
65
using System.Threading.Tasks;
76
using Antlr4.Runtime;
@@ -16,6 +15,7 @@
1615
using Rubberduck.VBEditor.Extensions;
1716
using System.IO;
1817
using NLog;
18+
// ReSharper disable LoopCanBeConvertedToQuery
1919

2020
namespace Rubberduck.Parsing.VBA
2121
{
@@ -86,31 +86,45 @@ private void ReparseRequested(object sender, ParseRequestEventArgs e)
8686
/// </summary>
8787
public void Parse()
8888
{
89-
if (!_state.Projects.Any())
89+
if (_state.Projects.Count == 0)
9090
{
9191
foreach (var project in _vbe.VBProjects.UnprotectedProjects())
9292
{
9393
_state.AddProject(project);
9494
}
9595
}
9696

97-
var projects = _state.Projects.ToList();
97+
var components = new List<VBComponent>();
98+
foreach (var project in _state.Projects)
99+
{
100+
foreach (VBComponent component in project.VBComponents)
101+
{
102+
components.Add(component);
103+
}
104+
}
98105

99-
var components = projects.SelectMany(p => p.VBComponents.Cast<VBComponent>()).ToList();
100-
SyncComReferences(projects);
106+
SyncComReferences(_state.Projects);
101107

102108
foreach (var component in components)
103109
{
104110
_state.SetModuleState(component, ParserState.Pending);
105111
}
106112

107113
// invalidation cleanup should go into ParseAsync?
108-
foreach (var invalidated in _componentAttributes.Keys.Except(components))
114+
foreach (var key in _componentAttributes.Keys)
115+
{
116+
if (!components.Contains(key))
117+
{
118+
_componentAttributes.Remove(key);
119+
}
120+
}
121+
122+
var parseTasks = new Task[components.Count];
123+
for (var i = 0; i < components.Count; i++)
109124
{
110-
_componentAttributes.Remove(invalidated);
125+
parseTasks[i] = ParseAsync(components[i], CancellationToken.None);
111126
}
112127

113-
var parseTasks = components.Select(vbComponent => ParseAsync(vbComponent, CancellationToken.None)).ToArray();
114128
Task.WaitAll(parseTasks);
115129

116130
if (_state.Status != ParserState.Error)
@@ -125,24 +139,42 @@ public void Parse()
125139
/// </summary>
126140
private void ParseAll()
127141
{
128-
if (!_state.Projects.Any())
142+
if (_state.Projects.Count == 0)
129143
{
130144
foreach (var project in _vbe.VBProjects.UnprotectedProjects())
131145
{
132146
_state.AddProject(project);
133147
}
134148
}
135149

136-
var projects = _state.Projects.ToList();
137-
var components = projects.SelectMany(p => p.VBComponents.Cast<VBComponent>()).ToList();
150+
var components = new List<VBComponent>();
151+
foreach (var project in _state.Projects)
152+
{
153+
foreach (VBComponent component in project.VBComponents)
154+
{
155+
components.Add(component);
156+
}
157+
}
138158

139-
var toParse = components.Where(c => _state.IsNewOrModified(c)).ToList();
140-
var unchanged = components.Where(c => !_state.IsNewOrModified(c)).ToList();
159+
var toParse = new List<VBComponent>();
160+
var unchanged = new List<VBComponent>();
141161

142-
SyncComReferences(projects);
143-
AddBuiltInDeclarations(projects);
162+
foreach (var component in components)
163+
{
164+
if (_state.IsNewOrModified(component))
165+
{
166+
toParse.Add(component);
167+
}
168+
else
169+
{
170+
unchanged.Add(component);
171+
}
172+
}
173+
174+
SyncComReferences(_state.Projects);
175+
AddBuiltInDeclarations(_state.Projects);
144176

145-
if (!toParse.Any())
177+
if (toParse.Count == 0)
146178
{
147179
State.SetStatusAndFireStateChanged(_state.Status);
148180
return;
@@ -161,17 +193,25 @@ private void ParseAll()
161193
_state.SetModuleState(component, ParserState.Ready);
162194
}
163195

164-
Debug.Assert(unchanged.All(component => _state.GetModuleState(component) == ParserState.Ready));
165-
Debug.Assert(toParse.All(component => _state.GetModuleState(component) == ParserState.Pending));
196+
//Debug.Assert(unchanged.All(component => _state.GetModuleState(component) == ParserState.Ready));
197+
//Debug.Assert(toParse.All(component => _state.GetModuleState(component) == ParserState.Pending));
166198
}
167199

168200
// invalidation cleanup should go into ParseAsync?
169-
foreach (var invalidated in _componentAttributes.Keys.Except(components))
201+
foreach (var key in _componentAttributes.Keys)
170202
{
171-
_componentAttributes.Remove(invalidated);
203+
if (!components.Contains(key))
204+
{
205+
_componentAttributes.Remove(key);
206+
}
207+
}
208+
209+
var parseTasks = new Task[components.Count];
210+
for (var i = 0; i < components.Count; i++)
211+
{
212+
parseTasks[i] = ParseAsync(components[i], CancellationToken.None);
172213
}
173214

174-
var parseTasks = toParse.Select(vbComponent => ParseAsync(vbComponent, CancellationToken.None)).ToArray();
175215
Task.WaitAll(parseTasks);
176216

177217
if (_state.Status != ParserState.Error)
@@ -184,12 +224,16 @@ private void ParseAll()
184224
private void AddBuiltInDeclarations(IReadOnlyList<VBProject> projects)
185225
{
186226
var finder = new DeclarationFinder(_state.AllDeclarations, new CommentNode[] { }, new IAnnotation[] { });
187-
if (finder.MatchName(Tokens.Err).Any(item => item.IsBuiltIn
188-
&& item.DeclarationType == DeclarationType.Variable
189-
&& item.Accessibility == Accessibility.Global))
227+
228+
foreach (var item in finder.MatchName(Tokens.Err))
190229
{
191-
return;
230+
if (item.IsBuiltIn && item.DeclarationType == DeclarationType.Variable &&
231+
item.Accessibility == Accessibility.Global)
232+
{
233+
return;
234+
}
192235
}
236+
193237
var vba = finder.FindProject("VBA");
194238
if (vba == null)
195239
{
@@ -213,21 +257,25 @@ private void AddBuiltInDeclarations(IReadOnlyList<VBProject> projects)
213257

214258
private string GetReferenceProjectId(Reference reference, IReadOnlyList<VBProject> projects)
215259
{
216-
var id = projects.FirstOrDefault(project =>
260+
VBProject project = null;
261+
foreach (var item in projects)
217262
{
218263
try
219264
{
220-
return project.FileName == reference.FullPath;
265+
if (item.FileName == reference.FullPath)
266+
{
267+
project = item;
268+
}
221269
}
222270
catch (IOException)
223271
{
224272
// Filename throws exception if unsaved.
225-
return false;
226273
}
227-
});
228-
if (id != null)
274+
}
275+
276+
if (project != null)
229277
{
230-
return QualifiedModuleName.GetProjectId(id);
278+
return QualifiedModuleName.GetProjectId(project);
231279
}
232280
return QualifiedModuleName.GetProjectId(reference);
233281
}
@@ -243,7 +291,16 @@ private void SyncComReferences(IReadOnlyList<VBProject> projects)
243291
{
244292
var reference = vbProject.References.Item(priority);
245293
var referencedProjectId = GetReferenceProjectId(reference, projects);
246-
var map = _projectReferences.SingleOrDefault(r => r.ReferencedProjectId == referencedProjectId);
294+
295+
ReferencePriorityMap map = null;
296+
foreach (var item in _projectReferences)
297+
{
298+
if (item.ReferencedProjectId == referencedProjectId)
299+
{
300+
map = map != null ? null : item;
301+
}
302+
}
303+
247304
if (map == null)
248305
{
249306
map = new ReferencePriorityMap(referencedProjectId) { { projectId, priority } };
@@ -267,9 +324,24 @@ private void SyncComReferences(IReadOnlyList<VBProject> projects)
267324
}
268325
}
269326

270-
var mappedIds = _projectReferences.Select(map => map.ReferencedProjectId);
271-
var unmapped = projects.SelectMany(project => project.References.Cast<Reference>())
272-
.Where(reference => !mappedIds.Contains(GetReferenceProjectId(reference, projects)));
327+
var mappedIds = new List<string>();
328+
foreach (var item in _projectReferences)
329+
{
330+
mappedIds.Add(item.ReferencedProjectId);
331+
}
332+
333+
var unmapped = new List<Reference>();
334+
foreach (var project in projects)
335+
{
336+
foreach (Reference item in project.References)
337+
{
338+
if (!mappedIds.Contains(GetReferenceProjectId(item, projects)))
339+
{
340+
unmapped.Add(item);
341+
}
342+
}
343+
}
344+
273345
foreach (var reference in unmapped)
274346
{
275347
UnloadComReference(reference, projects);
@@ -279,15 +351,24 @@ private void SyncComReferences(IReadOnlyList<VBProject> projects)
279351
private void UnloadComReference(Reference reference, IReadOnlyList<VBProject> projects)
280352
{
281353
var referencedProjectId = GetReferenceProjectId(reference, projects);
282-
var map = _projectReferences.SingleOrDefault(r => r.ReferencedProjectId == referencedProjectId);
354+
355+
ReferencePriorityMap map = null;
356+
foreach (var item in _projectReferences)
357+
{
358+
if (item.ReferencedProjectId == referencedProjectId)
359+
{
360+
map = map != null ? null : item;
361+
}
362+
}
363+
283364
if (map == null || !map.IsLoaded)
284365
{
285366
// we're removing a reference we weren't tracking? ...this shouldn't happen.
286367
Debug.Assert(false);
287368
return;
288369
}
289370
map.Remove(referencedProjectId);
290-
if (!map.Any())
371+
if (map.Count == 0)
291372
{
292373
_projectReferences.Remove(map);
293374
_state.RemoveBuiltInDeclarations(reference);
@@ -390,9 +471,20 @@ private void Resolve(CancellationToken token)
390471

391472
private void ResolveInternal(CancellationToken token)
392473
{
393-
var components = _state.Projects
394-
.Where(project => project.Protection == vbext_ProjectProtection.vbext_pp_none)
395-
.SelectMany(p => p.VBComponents.Cast<VBComponent>()).ToList();
474+
var components = new List<VBComponent>();
475+
foreach (var project in _state.Projects)
476+
{
477+
if (project.Protection == vbext_ProjectProtection.vbext_pp_locked)
478+
{
479+
continue;
480+
}
481+
482+
foreach (VBComponent component in project.VBComponents)
483+
{
484+
components.Add(component);
485+
}
486+
}
487+
396488
if (!_state.HasAllParseTrees(components))
397489
{
398490
return;
@@ -471,7 +563,16 @@ private Declaration CreateProjectDeclaration(QualifiedModuleName projectQualifie
471563
var qualifiedName = projectQualifiedName.QualifyMemberName(project.Name);
472564
var projectId = qualifiedName.QualifiedModuleName.ProjectId;
473565
var projectDeclaration = new ProjectDeclaration(qualifiedName, project.Name, isBuiltIn: false);
474-
var references = _projectReferences.Where(projectContainingReference => projectContainingReference.ContainsKey(projectId));
566+
567+
var references = new List<ReferencePriorityMap>();
568+
foreach (var item in _projectReferences)
569+
{
570+
if (item.ContainsKey(projectId))
571+
{
572+
references.Add(item);
573+
}
574+
}
575+
475576
foreach (var reference in references)
476577
{
477578
int priority = reference[projectId];

0 commit comments

Comments
 (0)