Skip to content

Commit

Permalink
Merge pull request #2817 from BZngr/next
Browse files Browse the repository at this point in the history
Relocate accessible declarations tests to DeclarationFinderTests
  • Loading branch information
retailcoder committed Mar 11, 2017
2 parents c6cede0 + 4a36e12 commit f499deb
Show file tree
Hide file tree
Showing 8 changed files with 451 additions and 441 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ ClientBin/
*.[Pp]ublish.xml
*.pfx
*.publishsettings
*.playlist

# Monodevelop detritus
*.userprefs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ public AssignedByValParameterMakeLocalCopyQuickFix(Declaration target, Qualified
_target = target;
_dialogFactory = dialogFactory;
_parserState = parserState;
_forbiddenNames = GetIdentifierNamesAccessibleToProcedureContext();
_localCopyVariableName = ComputeSuggestedName();
_forbiddenNames = parserState.DeclarationFinder.GetDeclarationsWithIdentifiersToAvoid(target).Select(n => n.IdentifierName);
_localCopyVariableName = ComputeSuggestedName();
}

public override bool CanFixInModule { get { return false; } }
Expand Down Expand Up @@ -113,61 +113,5 @@ private string BuildLocalCopyAssignment()
return (_target.AsTypeDeclaration is ClassModuleDeclaration ? Tokens.Set + " " : string.Empty)
+ _localCopyVariableName + " = " + _target.IdentifierName;
}

private IEnumerable<string> GetIdentifierNamesAccessibleToProcedureContext()
{
return _parserState.AllUserDeclarations
.Where(candidateDeclaration =>
(
IsDeclarationInTheSameProcedure(candidateDeclaration, _target)
|| IsDeclarationInTheSameModule(candidateDeclaration, _target)
|| IsProjectGlobalDeclaration(candidateDeclaration, _target))
).Select(declaration => declaration.IdentifierName).Distinct();
}

private bool IsDeclarationInTheSameProcedure(Declaration candidateDeclaration, Declaration scopingDeclaration)
{
return candidateDeclaration.ParentScope == scopingDeclaration.ParentScope;
}

private bool IsDeclarationInTheSameModule(Declaration candidateDeclaration, Declaration scopingDeclaration)
{
return candidateDeclaration.ComponentName == scopingDeclaration.ComponentName
&& !IsDeclaredInMethodOrProperty(candidateDeclaration.ParentDeclaration.Context);
}

private bool IsProjectGlobalDeclaration(Declaration candidateDeclaration, Declaration scopingDeclaration)
{
return candidateDeclaration.ProjectName == scopingDeclaration.ProjectName
&& !(candidateDeclaration.ParentScopeDeclaration is ClassModuleDeclaration)
&& (candidateDeclaration.Accessibility == Accessibility.Public
|| ((candidateDeclaration.Accessibility == Accessibility.Implicit)
&& (candidateDeclaration.ParentScopeDeclaration is ProceduralModuleDeclaration)));
}

private bool IsDeclaredInMethodOrProperty(RuleContext procedureContext)
{
if (procedureContext is VBAParser.SubStmtContext)
{
return true;
}
else if (procedureContext is VBAParser.FunctionStmtContext)
{
return true;
}
else if (procedureContext is VBAParser.PropertyLetStmtContext)
{
return true;
}
else if (procedureContext is VBAParser.PropertyGetStmtContext)
{
return true;
}
else if (procedureContext is VBAParser.PropertySetStmtContext)
{
return true;
}
return false;
}
}
}
4 changes: 2 additions & 2 deletions RetailCoder.VBE/Refactorings/Rename/RenameRefactoring.cs
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,12 @@ public void Refactor(Declaration target)

private void Rename()
{
var declaration = _state.DeclarationFinder.GetDeclarationsAccessibleToScope(_model.Target, _model.Declarations)
var declaration = _state.DeclarationFinder.GetDeclarationsWithIdentifiersToAvoid(_model.Target)
.Where(d => d.IdentifierName.Equals(_model.NewName, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
if (declaration != null)
{
var message = string.Format(RubberduckUI.RenameDialog_ConflictingNames, _model.NewName,
declaration.IdentifierName);
declaration);
var rename = _messageBox.Show(message, RubberduckUI.RenameDialog_Caption, MessageBoxButtons.YesNo,
MessageBoxIcon.Exclamation);

Expand Down
138 changes: 109 additions & 29 deletions Rubberduck.Parsing/Symbols/DeclarationFinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -816,58 +816,138 @@ private ConcurrentBag<Declaration> FindEventHandlers(IEnumerable<Declaration> de
return new ConcurrentBag<Declaration>(handlers);
}

public IEnumerable<Declaration> GetDeclarationsAccessibleToScope(Declaration target, IEnumerable<Declaration> declarations)

public IEnumerable<Declaration> GetAccessibleDeclarations(Declaration target)
{
if (target == null) { return Enumerable.Empty<Declaration>(); }

var declarations = GetAllDeclarations();

//declarations based on Accessibility
var projectDeclaration = RetrieveDeclarationType(target, DeclarationType.Project);
var moduleDeclaration = GetModuleDeclaration(target);
return declarations
.Where(candidateDeclaration =>
(
IsDeclarationInTheSameProcedure(candidateDeclaration, target)
|| IsDeclarationChildOfTheScope(candidateDeclaration, target)
|| IsModuleLevelDeclarationOfTheScope(candidateDeclaration, target)
|| IsProjectGlobalDeclaration(candidateDeclaration, target)
)).Distinct();
.Where(callee => AccessibilityCheck.IsAccessible(projectDeclaration, moduleDeclaration, target.ParentDeclaration, callee)).ToList();
}

public IEnumerable<Declaration> GetDeclarationsWithIdentifiersToAvoid(Declaration target)
{
if (target == null) { return Enumerable.Empty<Declaration>(); }

var accessibleDeclarations = GetAccessibleDeclarations(target);

//todo: handle case where target is in a consuming module rather than the exposing module

//Filter accessible declarations to those that would result in name collisions or hiding
var possibleConflictDeclarations = accessibleDeclarations.Where(dec =>
IsInProceduralModule(dec)
|| IsDeclarationInSameModuleScope(dec, target)
|| IsDeclarationInSameProcedureScope(dec, target)
|| dec.DeclarationType == DeclarationType.Project
|| dec.DeclarationType == DeclarationType.ClassModule
|| dec.DeclarationType == DeclarationType.ProceduralModule
|| dec.DeclarationType == DeclarationType.UserForm
).ToList();

//Add local variables when the target is a method or property
if (IsMethodOrProperty(target))
{
var declarations = GetAllDeclarations();
var localVariableDeclarations = declarations.Where(dec => target == dec.ParentDeclaration).ToList();
possibleConflictDeclarations.AddRange(localVariableDeclarations.ToList());
}

return possibleConflictDeclarations;
}

private IEnumerable<Declaration> GetAllDeclarations()
{
List<Declaration> declarations = new List<Declaration>();
foreach (var Key in _declarationsByName.Keys)
{
ConcurrentBag<Declaration> theDeclarations;
_declarationsByName.TryGetValue(Key, out theDeclarations);
declarations.AddRange(theDeclarations);
}
return declarations;
}

private bool IsInProceduralModule(Declaration candidateDeclaration)
{
var candidateModuleDeclaration = GetModuleDeclaration(candidateDeclaration);
if (null == candidateModuleDeclaration) { return false; }

return (candidateModuleDeclaration.DeclarationType == DeclarationType.ProceduralModule);
}

private bool IsDeclarationInTheSameProcedure(Declaration candidateDeclaration, Declaration scopingDeclaration)
private bool IsDeclarationInSameProcedureScope(Declaration candidateDeclaration, Declaration scopingDeclaration)
{
return candidateDeclaration.ParentScope == scopingDeclaration.ParentScope;
}

private bool IsDeclarationChildOfTheScope(Declaration candidateDeclaration, Declaration scopingDeclaration)
private bool IsChildOfScopeMethodOrProperty(Declaration candidateDeclaration, Declaration scopingDeclaration)
{
return scopingDeclaration == candidateDeclaration.ParentDeclaration;
if (IsMethodOrProperty(scopingDeclaration))
{
return scopingDeclaration == candidateDeclaration.ParentDeclaration;
}
return false;
}

private bool IsModuleLevelDeclarationOfTheScope(Declaration candidateDeclaration, Declaration scopingDeclaration)
private bool IsDeclarationInSameModuleScope(Declaration candidateDeclaration, Declaration scopingDeclaration)
{
if (candidateDeclaration.ParentDeclaration == null)
if (candidateDeclaration.ParentDeclaration != null)
{
return false;
return candidateDeclaration.ComponentName == scopingDeclaration.ComponentName
&& (candidateDeclaration.ParentDeclaration.DeclarationType == DeclarationType.ClassModule
|| candidateDeclaration.ParentDeclaration.DeclarationType == DeclarationType.ProceduralModule);
}
return candidateDeclaration.ComponentName == scopingDeclaration.ComponentName
&& !IsDeclaredWithinMethodOrProperty(candidateDeclaration.ParentDeclaration.Context);
else
return false;
}

private bool IsProjectGlobalDeclaration(Declaration candidateDeclaration, Declaration scopingDeclaration)
private bool IsMethodOrProperty(Declaration declaration)
{
return candidateDeclaration.ProjectName == scopingDeclaration.ProjectName
&& !(candidateDeclaration.ParentScopeDeclaration is ClassModuleDeclaration)
&& (candidateDeclaration.Accessibility == Accessibility.Public
|| ((candidateDeclaration.Accessibility == Accessibility.Implicit)
&& (candidateDeclaration.ParentScopeDeclaration is ProceduralModuleDeclaration)));
if (declaration == null) { return false; }

return (declaration.DeclarationType == DeclarationType.PropertyGet)
|| (declaration.DeclarationType == DeclarationType.PropertySet)
|| (declaration.DeclarationType == DeclarationType.PropertyLet)
|| (declaration.DeclarationType == DeclarationType.Procedure)
|| (declaration.DeclarationType == DeclarationType.Function);
}

private bool IsDeclaredWithinMethodOrProperty(RuleContext procedureContextCandidate)
private Declaration GetModuleDeclaration(Declaration declaration)
{
if (procedureContextCandidate == null) { return false; }
var classDeclaration = RetrieveDeclarationType(declaration, DeclarationType.ClassModule);
if (null != classDeclaration)
{
return classDeclaration;
}
var moduleDeclaration = RetrieveDeclarationType(declaration, DeclarationType.ProceduralModule);
if (null != moduleDeclaration)
{
return moduleDeclaration;
}
return null;
}

private Declaration RetrieveDeclarationType(Declaration start, DeclarationType goalType)
{
if (start.DeclarationType == goalType) { return start; }

var next = start.ParentDeclaration;
for (var idx = 0; idx < 10; idx++)
{
if (next == null) { return null; }

return (procedureContextCandidate is VBAParser.SubStmtContext)
|| (procedureContextCandidate is VBAParser.FunctionStmtContext)
|| (procedureContextCandidate is VBAParser.PropertyLetStmtContext)
|| (procedureContextCandidate is VBAParser.PropertyGetStmtContext)
|| (procedureContextCandidate is VBAParser.PropertySetStmtContext);
if (next.DeclarationType == goalType)
{
return next;
}
next = next.ParentDeclaration;
}
return null;
}
}
}

0 comments on commit f499deb

Please sign in to comment.