@@ -816,58 +816,138 @@ private ConcurrentBag<Declaration> FindEventHandlers(IEnumerable<Declaration> de
816
816
return new ConcurrentBag < Declaration > ( handlers ) ;
817
817
}
818
818
819
- public IEnumerable < Declaration > GetDeclarationsAccessibleToScope ( Declaration target , IEnumerable < Declaration > declarations )
819
+
820
+ public IEnumerable < Declaration > GetAccessibleDeclarations ( Declaration target )
820
821
{
821
822
if ( target == null ) { return Enumerable . Empty < Declaration > ( ) ; }
822
823
824
+ var declarations = GetAllDeclarations ( ) ;
825
+
826
+ //declarations based on Accessibility
827
+ var projectDeclaration = RetrieveDeclarationType ( target , DeclarationType . Project ) ;
828
+ var moduleDeclaration = GetModuleDeclaration ( target ) ;
823
829
return declarations
824
- . Where ( candidateDeclaration =>
825
- (
826
- IsDeclarationInTheSameProcedure ( candidateDeclaration , target )
827
- || IsDeclarationChildOfTheScope ( candidateDeclaration , target )
828
- || IsModuleLevelDeclarationOfTheScope ( candidateDeclaration , target )
829
- || IsProjectGlobalDeclaration ( candidateDeclaration , target )
830
- ) ) . Distinct ( ) ;
830
+ . Where ( callee => AccessibilityCheck . IsAccessible ( projectDeclaration , moduleDeclaration , target . ParentDeclaration , callee ) ) . ToList ( ) ;
831
+ }
832
+
833
+ public IEnumerable < Declaration > GetDeclarationsWithIdentifiersToAvoid ( Declaration target )
834
+ {
835
+ if ( target == null ) { return Enumerable . Empty < Declaration > ( ) ; }
836
+
837
+ var accessibleDeclarations = GetAccessibleDeclarations ( target ) ;
838
+
839
+ //todo: handle case where target is in a consuming module rather than the exposing module
840
+
841
+ //Filter accessible declarations to those that would result in name collisions or hiding
842
+ var possibleConflictDeclarations = accessibleDeclarations . Where ( dec =>
843
+ IsInProceduralModule ( dec )
844
+ || IsDeclarationInSameModuleScope ( dec , target )
845
+ || IsDeclarationInSameProcedureScope ( dec , target )
846
+ || dec . DeclarationType == DeclarationType . Project
847
+ || dec . DeclarationType == DeclarationType . ClassModule
848
+ || dec . DeclarationType == DeclarationType . ProceduralModule
849
+ || dec . DeclarationType == DeclarationType . UserForm
850
+ ) . ToList ( ) ;
851
+
852
+ //Add local variables when the target is a method or property
853
+ if ( IsMethodOrProperty ( target ) )
854
+ {
855
+ var declarations = GetAllDeclarations ( ) ;
856
+ var localVariableDeclarations = declarations . Where ( dec => target == dec . ParentDeclaration ) . ToList ( ) ;
857
+ possibleConflictDeclarations . AddRange ( localVariableDeclarations . ToList ( ) ) ;
858
+ }
859
+
860
+ return possibleConflictDeclarations ;
861
+ }
862
+
863
+ private IEnumerable < Declaration > GetAllDeclarations ( )
864
+ {
865
+ List < Declaration > declarations = new List < Declaration > ( ) ;
866
+ foreach ( var Key in _declarationsByName . Keys )
867
+ {
868
+ ConcurrentBag < Declaration > theDeclarations ;
869
+ _declarationsByName . TryGetValue ( Key , out theDeclarations ) ;
870
+ declarations . AddRange ( theDeclarations ) ;
871
+ }
872
+ return declarations ;
873
+ }
874
+
875
+ private bool IsInProceduralModule ( Declaration candidateDeclaration )
876
+ {
877
+ var candidateModuleDeclaration = GetModuleDeclaration ( candidateDeclaration ) ;
878
+ if ( null == candidateModuleDeclaration ) { return false ; }
879
+
880
+ return ( candidateModuleDeclaration . DeclarationType == DeclarationType . ProceduralModule ) ;
831
881
}
832
882
833
- private bool IsDeclarationInTheSameProcedure ( Declaration candidateDeclaration , Declaration scopingDeclaration )
883
+ private bool IsDeclarationInSameProcedureScope ( Declaration candidateDeclaration , Declaration scopingDeclaration )
834
884
{
835
885
return candidateDeclaration . ParentScope == scopingDeclaration . ParentScope ;
836
886
}
837
887
838
- private bool IsDeclarationChildOfTheScope ( Declaration candidateDeclaration , Declaration scopingDeclaration )
888
+ private bool IsChildOfScopeMethodOrProperty ( Declaration candidateDeclaration , Declaration scopingDeclaration )
839
889
{
840
- return scopingDeclaration == candidateDeclaration . ParentDeclaration ;
890
+ if ( IsMethodOrProperty ( scopingDeclaration ) )
891
+ {
892
+ return scopingDeclaration == candidateDeclaration . ParentDeclaration ;
893
+ }
894
+ return false ;
841
895
}
842
896
843
- private bool IsModuleLevelDeclarationOfTheScope ( Declaration candidateDeclaration , Declaration scopingDeclaration )
897
+ private bool IsDeclarationInSameModuleScope ( Declaration candidateDeclaration , Declaration scopingDeclaration )
844
898
{
845
- if ( candidateDeclaration . ParentDeclaration = = null )
899
+ if ( candidateDeclaration . ParentDeclaration ! = null )
846
900
{
847
- return false ;
901
+ return candidateDeclaration . ComponentName == scopingDeclaration . ComponentName
902
+ && ( candidateDeclaration . ParentDeclaration . DeclarationType == DeclarationType . ClassModule
903
+ || candidateDeclaration . ParentDeclaration . DeclarationType == DeclarationType . ProceduralModule ) ;
848
904
}
849
- return candidateDeclaration . ComponentName == scopingDeclaration . ComponentName
850
- && ! IsDeclaredWithinMethodOrProperty ( candidateDeclaration . ParentDeclaration . Context ) ;
905
+ else
906
+ return false ;
851
907
}
852
908
853
- private bool IsProjectGlobalDeclaration ( Declaration candidateDeclaration , Declaration scopingDeclaration )
909
+ private bool IsMethodOrProperty ( Declaration declaration )
854
910
{
855
- return candidateDeclaration . ProjectName == scopingDeclaration . ProjectName
856
- && ! ( candidateDeclaration . ParentScopeDeclaration is ClassModuleDeclaration )
857
- && ( candidateDeclaration . Accessibility == Accessibility . Public
858
- || ( ( candidateDeclaration . Accessibility == Accessibility . Implicit )
859
- && ( candidateDeclaration . ParentScopeDeclaration is ProceduralModuleDeclaration ) ) ) ;
911
+ if ( declaration == null ) { return false ; }
912
+
913
+ return ( declaration . DeclarationType == DeclarationType . PropertyGet )
914
+ || ( declaration . DeclarationType == DeclarationType . PropertySet )
915
+ || ( declaration . DeclarationType == DeclarationType . PropertyLet )
916
+ || ( declaration . DeclarationType == DeclarationType . Procedure )
917
+ || ( declaration . DeclarationType == DeclarationType . Function ) ;
860
918
}
861
919
862
- private bool IsDeclaredWithinMethodOrProperty ( RuleContext procedureContextCandidate )
920
+ private Declaration GetModuleDeclaration ( Declaration declaration )
863
921
{
864
- if ( procedureContextCandidate == null ) { return false ; }
922
+ var classDeclaration = RetrieveDeclarationType ( declaration , DeclarationType . ClassModule ) ;
923
+ if ( null != classDeclaration )
924
+ {
925
+ return classDeclaration ;
926
+ }
927
+ var moduleDeclaration = RetrieveDeclarationType ( declaration , DeclarationType . ProceduralModule ) ;
928
+ if ( null != moduleDeclaration )
929
+ {
930
+ return moduleDeclaration ;
931
+ }
932
+ return null ;
933
+ }
934
+
935
+ private Declaration RetrieveDeclarationType ( Declaration start , DeclarationType goalType )
936
+ {
937
+ if ( start . DeclarationType == goalType ) { return start ; }
938
+
939
+ var next = start . ParentDeclaration ;
940
+ for ( var idx = 0 ; idx < 10 ; idx ++ )
941
+ {
942
+ if ( next == null ) { return null ; }
865
943
866
- return ( procedureContextCandidate is VBAParser . SubStmtContext )
867
- || ( procedureContextCandidate is VBAParser . FunctionStmtContext )
868
- || ( procedureContextCandidate is VBAParser . PropertyLetStmtContext )
869
- || ( procedureContextCandidate is VBAParser . PropertyGetStmtContext )
870
- || ( procedureContextCandidate is VBAParser . PropertySetStmtContext ) ;
944
+ if ( next . DeclarationType == goalType )
945
+ {
946
+ return next ;
947
+ }
948
+ next = next . ParentDeclaration ;
949
+ }
950
+ return null ;
871
951
}
872
952
}
873
953
}
0 commit comments