From 58e8e158d08c3b9eccb6ce355bcec9d22d4c8f51 Mon Sep 17 00:00:00 2001 From: Max Doerner Date: Sun, 19 Jan 2020 20:09:17 +0100 Subject: [PATCH] Generate distinct unresolved variable declarations in Get Set and Let --- .../DeclarationCaching/DeclarationFinder.cs | 19 ++--- RubberduckTests/Grammar/ResolverTests.cs | 72 +++++++++++++++++++ 2 files changed, 83 insertions(+), 8 deletions(-) diff --git a/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs b/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs index 0d198a3fab..bf5ad33983 100644 --- a/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs +++ b/Rubberduck.Parsing/VBA/DeclarationCaching/DeclarationFinder.cs @@ -30,7 +30,7 @@ public class DeclarationFinder private readonly IReadOnlyDictionary _failedResolutionStores; private readonly ConcurrentDictionary _newFailedResolutionStores; - private readonly ConcurrentDictionary> _newUndeclared; + private readonly ConcurrentDictionary<(QualifiedMemberName memberName, DeclarationType declarationType), ConcurrentBag> _newUndeclared; private IDictionary<(QualifiedModuleName module, int annotatedLine), List> _annotations; private IDictionary> _parametersByParent; @@ -78,7 +78,7 @@ private static QualifiedSelection GetGroupingKey(Declaration declaration) _failedResolutionStores = failedResolutionStores; _newFailedResolutionStores = new ConcurrentDictionary(); - _newUndeclared = new ConcurrentDictionary>(); + _newUndeclared = new ConcurrentDictionary<(QualifiedMemberName memberName, DeclarationType declarationType), ConcurrentBag>(); var collectionConstructionActions = CollectionConstructionActions(declarations, annotations); ExecuteCollectionConstructionActions(collectionConstructionActions); @@ -986,13 +986,14 @@ public Declaration OnUndeclaredVariable(Declaration enclosingProcedure, string i null, !isReDimVariable); - var hasUndeclared = _newUndeclared.ContainsKey(enclosingProcedure.QualifiedName); + var enclosingScope = (enclosingProcedure.QualifiedName, enclosingProcedure.DeclarationType); + var hasUndeclared = _newUndeclared.ContainsKey(enclosingScope); if (hasUndeclared) { ConcurrentBag undeclared; - while (!_newUndeclared.TryGetValue(enclosingProcedure.QualifiedName, out undeclared)) + while (!_newUndeclared.TryGetValue(enclosingScope, out undeclared)) { - _newUndeclared.TryGetValue(enclosingProcedure.QualifiedName, out undeclared); + _newUndeclared.TryGetValue(enclosingScope, out undeclared); } var inScopeUndeclared = undeclared.FirstOrDefault(d => d.IdentifierName == identifierName); if (inScopeUndeclared != null) @@ -1003,7 +1004,7 @@ public Declaration OnUndeclaredVariable(Declaration enclosingProcedure, string i } else { - _newUndeclared.TryAdd(enclosingProcedure.QualifiedName, new ConcurrentBag { undeclaredLocal }); + _newUndeclared.TryAdd(enclosingScope, new ConcurrentBag { undeclaredLocal }); } return undeclaredLocal; } @@ -1067,14 +1068,16 @@ public Declaration OnBracketedExpression(string expression, ParserRuleContext co Debug.Assert(hostApp != null, "Host application project can't be null. Make sure VBA standard library is included if host is unknown."); var qualifiedName = hostApp.QualifiedName.QualifiedModuleName.QualifyMemberName(expression); + var declarationType = DeclarationType.BracketedExpression; + var undeclaredScope = (qualifiedName, declarationType); - if (_newUndeclared.TryGetValue(qualifiedName, out var undeclared)) + if (_newUndeclared.TryGetValue(undeclaredScope, out var undeclared)) { return undeclared.SingleOrDefault(); } var item = new Declaration(qualifiedName, hostApp, hostApp, Tokens.Variant, string.Empty, false, false, Accessibility.Global, DeclarationType.BracketedExpression, context, null, context.GetSelection(), true, null); - _newUndeclared.TryAdd(qualifiedName, new ConcurrentBag { item }); + _newUndeclared.TryAdd(undeclaredScope, new ConcurrentBag { item }); return item; } diff --git a/RubberduckTests/Grammar/ResolverTests.cs b/RubberduckTests/Grammar/ResolverTests.cs index 98b5ef0684..93ffc0b61a 100644 --- a/RubberduckTests/Grammar/ResolverTests.cs +++ b/RubberduckTests/Grammar/ResolverTests.cs @@ -7300,5 +7300,77 @@ End Function Assert.AreEqual(expectedReferenceText, enumMemberReference.IdentifierName); } } + + [Category("Grammar")] + [Category("Resolver")] + [Test] + public void OneUndeclaredVariablePerMemberAndUndeclaredIdentifier_DifferentMemberName() + { + var moduleCode = @" +Private Sub Foo + bar = 42 + 23 + bar = bar + bar + bar = bar * bar + fooBar = 42 +End Sub + +Private Sub DoSomething + bar = 42 + 23 + bar = bar + bar + bar = bar * bar + fooBaz = 42 +End Sub +"; + + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(moduleCode, out _); + + using (var state = Resolve(vbe.Object)) + { + var finder = state.DeclarationFinder; + var module = finder.UserDeclarations(DeclarationType.ProceduralModule) + .Single(); + var undeclared = finder.Members(module.QualifiedModuleName) + .Where(declaration => declaration.IsUndeclared) + .ToList(); + + Assert.AreEqual(4, undeclared.Count); + } + } + + [Category("Grammar")] + [Category("Resolver")] + [Test] + public void OneUndeclaredVariablePerMemberAndUndeclaredIdentifier_DifferentDeclarationType() + { + var moduleCode = @" +Private Property Get Foo() As Variant + bar = 42 + 23 + bar = bar + bar + bar = bar * bar + fooBar = 42 +End Property + +Private Property Let Foo(arg As Variant) + bar = 42 + 23 + bar = bar + bar + bar = bar * bar + fooBaz = 42 +End Property +"; + + var vbe = MockVbeBuilder.BuildFromSingleStandardModule(moduleCode, out _); + + using (var state = Resolve(vbe.Object)) + { + var finder = state.DeclarationFinder; + var module = finder.UserDeclarations(DeclarationType.ProceduralModule) + .Single(); + var undeclared = finder.Members(module.QualifiedModuleName) + .Where(declaration => declaration.IsUndeclared) + .ToList(); + + Assert.AreEqual(4, undeclared.Count); + } + } } }