Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
0d5cc6b
Introduced option not to eval parser state on module state change and…
MDoerner Jan 30, 2017
32f9af9
Introduced cancellation on reparse in the tests.
MDoerner Jan 30, 2017
a488500
Merge remote-tracking branch 'upstream/next' into ReworkParseCoordina…
MDoerner Jan 30, 2017
2db6457
In ExtractInterface the ImplementInterface refactoring kicks in after…
MDoerner Jan 30, 2017
71886b2
Fixed bugs I introduced in the coordination of parse tasks.
MDoerner Jan 31, 2017
22ec3a4
removed superfluous variable definition
MDoerner Jan 31, 2017
420f920
Merge pull request #2605 from MDoerner/ReworkParseCoordinatorPart1Bugfix
retailcoder Jan 31, 2017
6dac808
Merge branch 'ReworkParseCoordinatorPart1Bugfix' into ReworkParseCoor…
MDoerner Jan 31, 2017
1ec0d9d
Added catching the OperationCanceledExceptions.
MDoerner Jan 31, 2017
1bed4e7
Revert back to starting the implement interface refactoring only at t…
MDoerner Jan 31, 2017
45d429f
Merge branch 'next' into ReworkParseCoordinatorPart2
MDoerner Jan 31, 2017
233bb27
Merge branch 'next' into ReworkParseCoordinatorPart2
MDoerner Jan 31, 2017
265b67e
Merge pull request #2606 from MDoerner/ReworkParseCoordinatorPart2
retailcoder Jan 31, 2017
4474634
Add more thread safety to DeclarationFinder.
comintern Feb 1, 2017
932637f
Merge branch 'next' of https://github.com/comintern/Rubberduck.git
comintern Feb 1, 2017
84e1ff4
Merge branch 'next' into next
comintern Feb 1, 2017
e51187b
Merge pull request #2607 from comintern/next
retailcoder Feb 1, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ public void Refactor()
pane.Selection = oldSelection.Value.Selection;
}
}

_state.OnParseRequested(this);
}

public void Refactor(QualifiedSelection target)
Expand Down
112 changes: 65 additions & 47 deletions Rubberduck.Parsing/Symbols/DeclarationFinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace Rubberduck.Parsing.Symbols
internal static class DictionaryExtensions
{
public static IEnumerable<TValue> AllValues<TKey, TValue>(
this IDictionary<TKey, TValue[]> source)
this ConcurrentDictionary<TKey, ConcurrentBag<TValue>> source)
{
return source.SelectMany(item => item.Value).ToList();
}
Expand All @@ -26,6 +26,11 @@ public static IEnumerable<TValue> AllValues<TKey, TValue>(
{
return source.SelectMany(item => item.Value).ToList();
}

public static ConcurrentDictionary<TKey, ConcurrentBag<TValue>> ToConcurrentDictionary<TKey, TValue>(this IEnumerable<IGrouping<TKey, TValue>> source)
{
return new ConcurrentDictionary<TKey, ConcurrentBag<TValue>>(source.Select(x => new KeyValuePair<TKey, ConcurrentBag<TValue>>(x.Key, new ConcurrentBag<TValue>(x))));
}
}

public class DeclarationFinder
Expand All @@ -35,14 +40,14 @@ public class DeclarationFinder

private readonly IHostApplication _hostApp;
private readonly AnnotationService _annotationService;
private readonly ConcurrentDictionary<string, Declaration[]> _declarationsByName;
private readonly ConcurrentDictionary<QualifiedModuleName, Declaration[]> _declarations;
private readonly ConcurrentDictionary<QualifiedMemberName, IList<Declaration>> _undeclared;
private readonly ConcurrentDictionary<string, ConcurrentBag<Declaration>> _declarationsByName;
private readonly ConcurrentDictionary<QualifiedModuleName, ConcurrentBag<Declaration>> _declarations;
private readonly ConcurrentDictionary<QualifiedMemberName, ConcurrentBag<Declaration>> _undeclared;
private readonly ConcurrentBag<UnboundMemberDeclaration> _unresolved;
private readonly ConcurrentDictionary<QualifiedModuleName, IAnnotation[]> _annotations;
private readonly ConcurrentDictionary<Declaration, Declaration[]> _parametersByParent;
private readonly ConcurrentDictionary<DeclarationType, Declaration[]> _userDeclarationsByType;
private readonly ConcurrentDictionary<QualifiedModuleName, ConcurrentBag<IAnnotation>> _annotations;
private readonly ConcurrentDictionary<Declaration, ConcurrentBag<Declaration>> _parametersByParent;
private readonly ConcurrentDictionary<DeclarationType, ConcurrentBag<Declaration>> _userDeclarationsByType;

private readonly Lazy<ConcurrentDictionary<Declaration, Declaration[]>> _handlersByWithEventsField;
private readonly Lazy<ConcurrentDictionary<VBAParser.ImplementsStmtContext, Declaration[]>> _membersByImplementsContext;
private readonly Lazy<ConcurrentDictionary<Declaration, Declaration[]>> _interfaceMembers;
Expand All @@ -52,26 +57,16 @@ public class DeclarationFinder
public DeclarationFinder(IReadOnlyList<Declaration> declarations, IEnumerable<IAnnotation> annotations, IHostApplication hostApp = null)
{
_hostApp = hostApp;
_annotations = new ConcurrentDictionary<QualifiedModuleName, IAnnotation[]>(annotations.GroupBy(node => node.QualifiedSelection.QualifiedName)
.ToDictionary(grouping => grouping.Key, grouping => grouping.ToArray()));
_declarations = new ConcurrentDictionary<QualifiedModuleName, Declaration[]>(declarations.GroupBy(item => item.QualifiedName.QualifiedModuleName)
.ToDictionary(grouping => grouping.Key, grouping => grouping.ToArray()));

_declarationsByName = new ConcurrentDictionary<string, Declaration[]>(
declarations.GroupBy(declaration => new { IdentifierName = declaration.IdentifierName.ToLowerInvariant() })
.ToDictionary(grouping => grouping.Key.IdentifierName, grouping => grouping.ToArray(), NameComparer));
_parametersByParent = new ConcurrentDictionary<Declaration, Declaration[]>(
declarations.Where(declaration => declaration.DeclarationType == DeclarationType.Parameter)
.GroupBy(declaration => declaration.ParentDeclaration)
.ToDictionary(grouping => grouping.Key, grouping => grouping.ToArray()));
_userDeclarationsByType = new ConcurrentDictionary<DeclarationType, Declaration[]>(
declarations.Where(declaration => !declaration.IsBuiltIn)
.GroupBy(declaration => declaration.DeclarationType)
.ToDictionary(grouping => grouping.Key, grouping => grouping.ToArray()));
_annotations = annotations.GroupBy(node => node.QualifiedSelection.QualifiedName).ToConcurrentDictionary();
_declarations = declarations.GroupBy(item => item.QualifiedName.QualifiedModuleName).ToConcurrentDictionary();
_declarationsByName = declarations.GroupBy(declaration => declaration.IdentifierName.ToLowerInvariant()).ToConcurrentDictionary();
_parametersByParent = declarations.Where(declaration => declaration.DeclarationType == DeclarationType.Parameter)
.GroupBy(declaration => declaration.ParentDeclaration).ToConcurrentDictionary();
_userDeclarationsByType = declarations.Where(declaration => !declaration.IsBuiltIn).GroupBy(declaration => declaration.DeclarationType).ToConcurrentDictionary();
_builtinEvents = new Lazy<ConcurrentBag<Declaration>>(() => FindBuiltInEventHandlers(declarations));

_projects = _projects = declarations.Where(d => d.DeclarationType == DeclarationType.Project).ToList();
_classes = _declarations.AllValues().Where(d => d.DeclarationType == DeclarationType.ClassModule).ToList();
_projects = _projects = new Lazy<ConcurrentBag<Declaration>>(() => new ConcurrentBag<Declaration>(declarations.Where(d => d.DeclarationType == DeclarationType.Project)));
_classes = new Lazy<ConcurrentBag<Declaration>>(() => new ConcurrentBag<Declaration>(declarations.Where(d => d.DeclarationType == DeclarationType.ClassModule)));

var withEventsFields = UserDeclarations(DeclarationType.Variable).Where(item => item.IsWithEvents).ToArray();
var events = withEventsFields.Select(field =>
Expand All @@ -95,7 +90,7 @@ public DeclarationFinder(IReadOnlyList<Declaration> declarations, IEnumerable<IA
.ToDictionary(item => item.WithEventsField, item => item.Handlers.ToArray())
));

_undeclared = new ConcurrentDictionary<QualifiedMemberName, IList<Declaration>>(new Dictionary<QualifiedMemberName, IList<Declaration>>());
_undeclared = new ConcurrentDictionary<QualifiedMemberName, ConcurrentBag<Declaration>>(new Dictionary<QualifiedMemberName, ConcurrentBag<Declaration>>());
_unresolved = new ConcurrentBag<UnboundMemberDeclaration>(new List<UnboundMemberDeclaration>());
_annotationService = new AnnotationService(this);

Expand All @@ -111,7 +106,7 @@ public DeclarationFinder(IReadOnlyList<Declaration> declarations, IEnumerable<IA
});

_interfaceMembers = new Lazy<ConcurrentDictionary<Declaration, Declaration[]>>(() =>
new ConcurrentDictionary<Declaration, Declaration[]>(interfaceMembers.ToDictionary(item => item.InterfaceModule, item => item.InterfaceMembers.ToArray())));
new ConcurrentDictionary<Declaration, Declaration[]>(interfaceMembers.ToDictionary(item => item.InterfaceModule, item => item.InterfaceMembers.ToArray())));

var implementingNames = new Lazy<IEnumerable<string>>(() => implementsInstructions.SelectMany(item =>
_declarations[item.IdentifierReference.Declaration.QualifiedName.QualifiedModuleName]
Expand Down Expand Up @@ -158,21 +153,40 @@ public IEnumerable<Declaration> FindBuiltinEventHandlers()
}
}

private readonly IEnumerable<Declaration> _classes;
public IEnumerable<Declaration> Classes { get { return _classes; } }
private readonly Lazy<ConcurrentBag<Declaration>> _classes;

public IEnumerable<Declaration> Classes
{
get
{
lock (ThreadLock)
{
return _classes.Value;
}
}
}

private readonly Lazy<ConcurrentBag<Declaration>> _projects;

private readonly IEnumerable<Declaration> _projects;
public IEnumerable<Declaration> Projects { get { return _projects; } }
public IEnumerable<Declaration> Projects
{
get
{
lock (ThreadLock)
{
return _projects.Value;
}
}
}

public IEnumerable<Declaration> UserDeclarations(DeclarationType type)
{
Declaration[] result;
ConcurrentBag<Declaration> result;
if (!_userDeclarationsByType.TryGetValue(type, out result))
{
result = _userDeclarationsByType
result = new ConcurrentBag<Declaration>(_userDeclarationsByType
.Where(item => item.Key.HasFlag(type))
.SelectMany(item => item.Value)
.ToArray();
.SelectMany(item => item.Value));
}
return result;
}
Expand Down Expand Up @@ -218,7 +232,7 @@ public Declaration FindParameter(Declaration procedure, string parameterName)

public IEnumerable<Declaration> FindMemberMatches(Declaration parent, string memberName)
{
Declaration[] children;
ConcurrentBag<Declaration> children;
if (_declarations.TryGetValue(parent.QualifiedName.QualifiedModuleName, out children))
{
return children.Where(item => item.DeclarationType.HasFlag(DeclarationType.Member)
Expand All @@ -230,7 +244,7 @@ public IEnumerable<Declaration> FindMemberMatches(Declaration parent, string mem

public IEnumerable<IAnnotation> FindAnnotations(QualifiedModuleName module)
{
IAnnotation[] result;
ConcurrentBag<IAnnotation> result;
return _annotations.TryGetValue(module, out result) ? result : Enumerable.Empty<IAnnotation>();
}

Expand Down Expand Up @@ -264,7 +278,7 @@ public Declaration FindLabel(Declaration procedure, string label)
public IEnumerable<Declaration> MatchName(string name)
{
var normalizedName = ToNormalizedName(name);
Declaration[] result;
ConcurrentBag<Declaration> result;
return _declarationsByName.TryGetValue(normalizedName, out result)
? result
: Enumerable.Empty<Declaration>();
Expand Down Expand Up @@ -305,7 +319,7 @@ public Declaration FindStdModule(string name, Declaration parent = null, bool in
{
var matches = MatchName(name);
result = matches.SingleOrDefault(declaration => declaration.DeclarationType.HasFlag(DeclarationType.ProceduralModule)
&& (parent == null || parent.Equals(declaration.ParentDeclaration))
&& (parent.Equals(declaration.ParentDeclaration))
&& (includeBuiltIn || !declaration.IsBuiltIn));
}
catch (InvalidOperationException exception)
Expand All @@ -324,7 +338,7 @@ public Declaration FindClassModule(string name, Declaration parent = null, bool
{
var matches = MatchName(name);
result = matches.SingleOrDefault(declaration => declaration.DeclarationType.HasFlag(DeclarationType.ClassModule)
&& (parent == null || parent.Equals(declaration.ParentDeclaration))
&& (parent.Equals(declaration.ParentDeclaration))
&& (includeBuiltIn || !declaration.IsBuiltIn));
}
catch (InvalidOperationException exception)
Expand Down Expand Up @@ -481,18 +495,22 @@ public Declaration OnUndeclaredVariable(Declaration enclosingProcedure, string i
var hasUndeclared = _undeclared.ContainsKey(enclosingProcedure.QualifiedName);
if (hasUndeclared)
{
var inScopeUndeclared = _undeclared[enclosingProcedure.QualifiedName].FirstOrDefault(d => d.IdentifierName == identifierName);
ConcurrentBag<Declaration> undeclared;
while (!_undeclared.TryGetValue(enclosingProcedure.QualifiedName, out undeclared))
{
_undeclared.TryGetValue(enclosingProcedure.QualifiedName, out undeclared);
}
var inScopeUndeclared = undeclared.FirstOrDefault(d => d.IdentifierName == identifierName);
if (inScopeUndeclared != null)
{
return inScopeUndeclared;
}
_undeclared[enclosingProcedure.QualifiedName].Add(undeclaredLocal);
undeclared.Add(undeclaredLocal);
}
else
{
_undeclared[enclosingProcedure.QualifiedName] = new List<Declaration> { undeclaredLocal };
_undeclared.TryAdd(enclosingProcedure.QualifiedName, new ConcurrentBag<Declaration> { undeclaredLocal });
}

return undeclaredLocal;
}

Expand Down Expand Up @@ -524,14 +542,14 @@ public Declaration OnBracketedExpression(string expression, ParserRuleContext co

var qualifiedName = hostApp.QualifiedName.QualifiedModuleName.QualifyMemberName(expression);

IList<Declaration> undeclared;
ConcurrentBag<Declaration> undeclared;
if (_undeclared.TryGetValue(qualifiedName, out undeclared))
{
return undeclared.SingleOrDefault();
}

var item = new Declaration(qualifiedName, hostApp, hostApp, Tokens.Variant, string.Empty, false, false, Accessibility.Global, DeclarationType.BracketedExpression, context, context.GetSelection(), false, null);
_undeclared.TryAdd(qualifiedName, new List<Declaration> { item });
_undeclared.TryAdd(qualifiedName, new ConcurrentBag<Declaration> { item });
return item;
}

Expand Down
10 changes: 8 additions & 2 deletions Rubberduck.Parsing/VBA/ComponentParseTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,15 @@ public void Start(CancellationToken token)
Cause = exception
});
}
catch (OperationCanceledException)
catch (OperationCanceledException exception)
{
// no results to be used, so no results "returned"
//We return this, so that the calling code knows that the operation actually has been cancelled.
var failedHandler = ParseFailure;
if (failedHandler != null)
failedHandler.Invoke(this, new ParseFailureArgs
{
Cause = exception
});
}
}

Expand Down
Loading