Skip to content

Commit 76a7275

Browse files
committed
if property is named after a type, usages of the type resolve as usages of the property - but type references resolve correctly. Excel crashes on exit for some reason.
1 parent 09035e3 commit 76a7275

File tree

3 files changed

+136
-63
lines changed

3 files changed

+136
-63
lines changed

RetailCoder.VBE/UI/RefactorMenu.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,10 @@ public void FindAllReferences()
179179
var selection = IDE.ActiveCodePane.GetSelection();
180180
var progress = new ParsingProgressPresenter();
181181
var result = progress.Parse(_parser, IDE.ActiveVBProject);
182+
if (result == null)
183+
{
184+
return; // bug/todo: something's definitely wrong, exception thrown in resolver code
185+
}
182186

183187
var declarations = result.Declarations.Items
184188
.Where(item => item.DeclarationType != DeclarationType.ModuleOption)

Rubberduck.Parsing/Symbols/Declaration.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,18 @@ public Declaration(QualifiedMemberName qualifiedName, string parentScope,
5050

5151
public void AddReference(IdentifierReference reference)
5252
{
53-
if (!_references.Select(r => r.Context).Contains(reference.Context))
53+
if (reference.Declaration.Context == reference.Context)
54+
{
55+
return;
56+
}
57+
58+
if (reference.Context.Parent != _context
59+
&& !_references.Select(r => r.Context).Contains(reference.Context)
60+
&& !_references.Any(r => r.QualifiedModuleName == reference.QualifiedModuleName
61+
&& r.Selection.StartLine == reference.Selection.StartLine
62+
&& r.Selection.EndLine == reference.Selection.EndLine
63+
&& r.Selection.StartColumn == reference.Selection.StartColumn
64+
&& r.Selection.EndColumn == reference.Selection.EndColumn))
5465
{
5566
_references.Add(reference);
5667
}

Rubberduck.Parsing/Symbols/IdentifierReferenceListener.cs

Lines changed: 120 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ public IdentifierReferenceListener(QualifiedModuleName qualifiedModuleName, Decl
3333
_moduleTypes = new HashSet<DeclarationType>(new[]
3434
{
3535
DeclarationType.Module,
36-
DeclarationType.Class
36+
DeclarationType.Class,
37+
DeclarationType.Project
3738
});
3839

3940
_memberTypes = new HashSet<DeclarationType>(new[]
@@ -154,7 +155,8 @@ public override void EnterWithStmt(VBAParser.WithStmtContext context)
154155
{
155156
// object variable is a built-in Collection class instance
156157
qualifier = _declarations.Items.Single(item => item.IsBuiltIn
157-
&& item.IdentifierName == collectionContext.GetText());
158+
&& item.IdentifierName == collectionContext.GetText()
159+
&& item.DeclarationType == DeclarationType.Class);
158160
reference = CreateReference(baseTypeContext, qualifier);
159161
}
160162
}
@@ -206,7 +208,7 @@ private Declaration ResolveType(VBAParser.ComplexTypeContext context)
206208
{
207209
return _declarations[identifier.GetText()].SingleOrDefault(item =>
208210
item.ProjectName == libraryName
209-
&& item.DeclarationType == DeclarationType.Class);
211+
&& _moduleTypes.Contains(item.DeclarationType));
210212
}
211213

212214
return null;
@@ -244,13 +246,15 @@ private Declaration ResolveType(Declaration parent)
244246
// look in current project first.
245247
var result = _declarations[parent.AsTypeName].SingleOrDefault(item =>
246248
_moduleTypes.Contains(item.DeclarationType)
247-
&& item.ProjectName == _currentScope.ProjectName);
249+
&& item.ProjectName == _currentScope.ProjectName
250+
&& _moduleTypes.Contains(item.DeclarationType));
248251

249252
if (result == null)
250253
{
251-
// look in all projects (including VbaStdLib library.
254+
// look in all projects (including VbaStdLib library).
252255
result = _declarations[parent.AsTypeName].SingleOrDefault(item =>
253-
_moduleTypes.Contains(item.DeclarationType));
256+
_moduleTypes.Contains(item.DeclarationType)
257+
&& _moduleTypes.Contains(item.DeclarationType));
254258
}
255259

256260
return result;
@@ -298,6 +302,17 @@ private Declaration Resolve(ParserRuleContext callSiteContext, Declaration local
298302
?? FindModuleScopeProcedure(identifierName, localScope, accessorType)
299303
?? FindProjectScopeDeclaration(identifierName);
300304

305+
if (callee == null)
306+
{
307+
// calls inside With block can still refer to identifiers in _currentScope
308+
localScope = _currentScope;
309+
identifierName = callSiteContext.GetText();
310+
callee = FindLocalScopeDeclaration(identifierName, localScope)
311+
?? FindModuleScopeDeclaration(identifierName, localScope)
312+
?? FindModuleScopeProcedure(identifierName, localScope, accessorType)
313+
?? FindProjectScopeDeclaration(identifierName);
314+
}
315+
301316
if (callee == null)
302317
{
303318
return null;
@@ -321,8 +336,6 @@ private Declaration Resolve(VBAParser.ICS_S_VariableOrProcedureCallContext conte
321336
return null;
322337
}
323338

324-
_isResolving = true;
325-
326339
var identifierContext = context.ambiguousIdentifier();
327340
var fieldCall = context.dictionaryCallStmt();
328341

@@ -360,8 +373,6 @@ private Declaration Resolve(VBAParser.ICS_S_ProcedureOrArrayCallContext context,
360373
return null;
361374
}
362375

363-
_isResolving = true;
364-
365376
var identifierContext = context.ambiguousIdentifier();
366377
var fieldCall = context.dictionaryCallStmt();
367378
// todo: understand WTF [baseType] is doing in that grammar rule...
@@ -376,8 +387,6 @@ private Declaration Resolve(VBAParser.ICS_S_MembersCallContext context, ContextA
376387
return null;
377388
}
378389

379-
_isResolving = true;
380-
381390
if (localScope == null)
382391
{
383392
localScope = _currentScope;
@@ -403,8 +412,6 @@ private Declaration Resolve(VBAParser.ICS_S_MembersCallContext context, ContextA
403412
return null;
404413
}
405414

406-
//var memberReference = CreateReference(member.Context, member);
407-
//member.AddReference(memberReference);
408415
parent = member;
409416
}
410417

@@ -417,24 +424,24 @@ private Declaration Resolve(VBAParser.ICS_S_MembersCallContext context, ContextA
417424
return Resolve(fieldCall, parent, hasExplicitLetStatement, isAssignmentTarget);
418425
}
419426

420-
private void Resolve(VBAParser.ICS_B_ProcedureCallContext context)
427+
private Declaration Resolve(VBAParser.ICS_B_ProcedureCallContext context)
421428
{
422429
if (context == null)
423430
{
424-
return;
431+
return null;
425432
}
426433

427-
_isResolving = true;
428-
429434
var identifierContext = context.certainIdentifier();
430435
var callee = Resolve(identifierContext, _currentScope);
431436
if (callee == null)
432437
{
433-
return;
438+
return null;
434439
}
435440

436441
var reference = CreateReference(identifierContext, callee);
437442
callee.AddReference(reference);
443+
444+
return callee;
438445
}
439446

440447
private Declaration Resolve(VBAParser.ImplicitCallStmt_InStmtContext callSiteContext, Declaration localScope, ContextAccessorType accessorType, bool hasExplicitLetStatement = false, bool isAssignmentTarget = false)
@@ -471,7 +478,8 @@ private Declaration FindLocalScopeDeclaration(string identifierName, Declaration
471478
}
472479

473480
var parent = _declarations[identifierName].SingleOrDefault(item =>
474-
item.ParentScope == localScope.Scope);
481+
item.ParentScope == localScope.Scope
482+
&& !_moduleTypes.Contains(item.DeclarationType));
475483
return parent;
476484
}
477485

@@ -490,7 +498,8 @@ private Declaration FindModuleScopeDeclaration(string identifierName, Declaratio
490498

491499
return _declarations[identifierName].SingleOrDefault(item =>
492500
item.ParentScope == localScope.ParentScope
493-
&& !item.DeclarationType.HasFlag(DeclarationType.Member));
501+
&& !item.DeclarationType.HasFlag(DeclarationType.Member)
502+
&& !_moduleTypes.Contains(item.DeclarationType));
494503
}
495504

496505
/// <summary>
@@ -529,8 +538,9 @@ private Declaration FindProjectScopeDeclaration(string identifierName)
529538
{
530539
// assume unqualified variable call, i.e. unique declaration.
531540
return _declarations[identifierName].SingleOrDefault(item =>
532-
item.Accessibility == Accessibility.Public
533-
|| item.Accessibility == Accessibility.Global);
541+
(item.Accessibility == Accessibility.Public
542+
|| item.Accessibility == Accessibility.Global
543+
|| item.DeclarationType == DeclarationType.Module));
534544
}
535545

536546
/// <summary>
@@ -551,29 +561,13 @@ private Declaration FindProjectScopeDeclaration(string identifierName, string mo
551561

552562
#region IVBAListener overrides
553563

554-
// avoid re-resolving identifiers
555-
private bool _isResolving;
556-
557564
public override void EnterICS_B_ProcedureCall(VBAParser.ICS_B_ProcedureCallContext context)
558565
{
559-
if (_isResolving)
560-
{
561-
return;
562-
}
563-
564566
Resolve(context);
565-
_isResolving = false;
566567
}
567568

568569
public override void EnterICS_B_MemberProcedureCall(VBAParser.ICS_B_MemberProcedureCallContext context)
569570
{
570-
if (_isResolving)
571-
{
572-
return;
573-
}
574-
575-
_isResolving = true;
576-
577571
var parentScope = Resolve(context.implicitCallStmt_InStmt(), _currentScope, ContextAccessorType.GetValueOrReference);
578572
var parentType = ResolveType(parentScope);
579573

@@ -600,47 +594,25 @@ public override void EnterICS_B_MemberProcedureCall(VBAParser.ICS_B_MemberProced
600594

601595
var fieldCall = context.dictionaryCallStmt();
602596
Resolve(fieldCall, member);
603-
604-
_isResolving = false;
605597
}
606598

607599
public override void EnterICS_S_VariableOrProcedureCall(VBAParser.ICS_S_VariableOrProcedureCallContext context)
608600
{
609-
if (_isResolving)
610-
{
611-
return;
612-
}
613-
614601
Resolve(context, _currentScope);
615602
}
616603

617604
public override void EnterICS_S_ProcedureOrArrayCall(VBAParser.ICS_S_ProcedureOrArrayCallContext context)
618605
{
619-
if (_isResolving)
620-
{
621-
return;
622-
}
623-
624606
Resolve(context, _currentScope);
625607
}
626608

627609
public override void EnterICS_S_MembersCall(VBAParser.ICS_S_MembersCallContext context)
628610
{
629-
if (_isResolving)
630-
{
631-
return;
632-
}
633-
634611
Resolve(context, _currentScope);
635612
}
636613

637614
public override void EnterICS_S_DictionaryCall(VBAParser.ICS_S_DictionaryCallContext context)
638615
{
639-
if (_isResolving)
640-
{
641-
return;
642-
}
643-
644616
Resolve(context, _currentScope);
645617
}
646618

@@ -674,7 +646,7 @@ public override void EnterAsTypeClause(VBAParser.AsTypeClauseContext context)
674646
var collection = baseType.COLLECTION();
675647
if (collection != null)
676648
{
677-
type = _declarations[collection.GetText()].SingleOrDefault(item => item.IsBuiltIn);
649+
type = _declarations[collection.GetText()].SingleOrDefault(item => item.IsBuiltIn && item.DeclarationType == DeclarationType.Class);
678650
reference = CreateReference(baseType, type);
679651
}
680652
}
@@ -695,6 +667,7 @@ public override void EnterForNextStmt(VBAParser.ForNextStmtContext context)
695667
var identifiers = context.ambiguousIdentifier();
696668
var identifier = Resolve(identifiers[0], _currentScope, ContextAccessorType.AssignValue);
697669

670+
// each iteration counts as an assignment
698671
var reference = CreateReference(identifiers[0], identifier, true);
699672
identifier.AddReference(reference);
700673

@@ -704,6 +677,91 @@ public override void EnterForNextStmt(VBAParser.ForNextStmtContext context)
704677
}
705678
}
706679

680+
public override void EnterForEachStmt(VBAParser.ForEachStmtContext context)
681+
{
682+
var identifiers = context.ambiguousIdentifier();
683+
var identifier = Resolve(identifiers[0], _currentScope);
684+
685+
// each iteration counts as an assignment
686+
var reference = CreateReference(identifiers[0], identifier, true);
687+
identifier.AddReference(reference);
688+
689+
if (identifiers.Count > 1)
690+
{
691+
identifier.AddReference(CreateReference(identifiers[1], identifier));
692+
}
693+
}
694+
695+
public override void EnterImplementsStmt(VBAParser.ImplementsStmtContext context)
696+
{
697+
var identifierContext = context.ambiguousIdentifier();
698+
var identifier = Resolve(identifierContext, _currentScope);
699+
identifier.AddReference(CreateReference(identifierContext, identifier));
700+
}
701+
702+
public override void EnterRaiseEventStmt(VBAParser.RaiseEventStmtContext context)
703+
{
704+
var identifierContext = context.ambiguousIdentifier();
705+
var identifier = Resolve(identifierContext, _currentScope);
706+
identifier.AddReference(CreateReference(identifierContext, identifier));
707+
}
708+
709+
public override void EnterResumeStmt(VBAParser.ResumeStmtContext context)
710+
{
711+
var identifierContext = context.ambiguousIdentifier();
712+
var identifier = Resolve(identifierContext, _currentScope);
713+
identifier.AddReference(CreateReference(identifierContext, identifier));
714+
}
715+
716+
public override void EnterFileNumber(VBAParser.FileNumberContext context)
717+
{
718+
var identifierContext = context.ambiguousIdentifier();
719+
if (identifierContext == null)
720+
{
721+
return;
722+
}
723+
var identifier = Resolve(identifierContext, _currentScope);
724+
identifier.AddReference(CreateReference(identifierContext, identifier));
725+
}
726+
727+
public override void EnterArgDefaultValue(VBAParser.ArgDefaultValueContext context)
728+
{
729+
var identifierContext = context.ambiguousIdentifier();
730+
if (identifierContext == null)
731+
{
732+
return;
733+
}
734+
var identifier = Resolve(identifierContext, _currentScope);
735+
identifier.AddReference(CreateReference(identifierContext, identifier));
736+
}
737+
738+
public override void EnterFieldLength(VBAParser.FieldLengthContext context)
739+
{
740+
var identifierContext = context.ambiguousIdentifier();
741+
if (identifierContext == null)
742+
{
743+
return;
744+
}
745+
var identifier = Resolve(identifierContext, _currentScope);
746+
identifier.AddReference(CreateReference(identifierContext, identifier));
747+
}
748+
749+
public override void EnterVsAssign(VBAParser.VsAssignContext context)
750+
{
751+
// named parameter reference must be scoped to called procedure
752+
var callee = FindParentCall(context);
753+
Resolve(context.implicitCallStmt_InStmt(), callee);
754+
}
755+
756+
private Declaration FindParentCall(VBAParser.VsAssignContext context)
757+
{
758+
var calleeContext = context.Parent.Parent.Parent;
759+
return Resolve(calleeContext as VBAParser.ICS_B_ProcedureCallContext)
760+
?? Resolve(calleeContext as VBAParser.ICS_S_VariableOrProcedureCallContext, _currentScope)
761+
?? Resolve(calleeContext as VBAParser.ICS_S_ProcedureOrArrayCallContext, _currentScope)
762+
?? Resolve(calleeContext as VBAParser.ICS_S_MembersCallContext, _currentScope);
763+
}
764+
707765
#endregion
708766

709767
private IdentifierReference CreateReference(ParserRuleContext callSiteContext, Declaration callee, bool isAssignmentTarget = false, bool hasExplicitLetStatement = false)

0 commit comments

Comments
 (0)