@@ -96,27 +96,59 @@ class Modifiable extends Declaration, @modifiable {
9696 /** Holds if this declaration is `async`. */
9797 predicate isAsync ( ) { this .hasModifier ( "async" ) }
9898
99+ private predicate isReallyPrivate ( ) {
100+ this .isPrivate ( ) and
101+ not this .isProtected ( ) and
102+ // Rare case when a member is defined with the same name in multiple assemblies with different visibility
103+ not this .isPublic ( )
104+ }
105+
99106 /**
100- * Holds if this declaration is effectively `private` (either directly or
101- * because one of the enclosing types is `private`).
107+ * Holds if this declaration is effectively `private`. A declaration is considered
108+ * effectively `private` if it can only be referenced from
109+ * - the declaring and its nested types, similarly to `private` declarations, and
110+ * - the enclosing types.
111+ *
112+ * Note that explicit interface implementations are also considered effectively
113+ * `private` if the implemented interface is itself effectively `private`. Finally,
114+ * `private protected` members are not considered effectively `private`, because
115+ * they can be overriden within the declaring assembly.
102116 */
103117 predicate isEffectivelyPrivate ( ) {
104- this .isPrivate ( ) or
105- this .getDeclaringType + ( ) .isPrivate ( )
118+ this .isReallyPrivate ( ) or
119+ this .getDeclaringType + ( ) .( Modifiable ) .isReallyPrivate ( ) or
120+ this .( Virtualizable ) .getExplicitlyImplementedInterface ( ) .isEffectivelyPrivate ( )
121+ }
122+
123+ private predicate isReallyInternal ( ) {
124+ (
125+ this .isInternal ( ) and not this .isProtected ( )
126+ or
127+ this .isPrivate ( ) and this .isProtected ( )
128+ ) and
129+ // Rare case when a member is defined with the same name in multiple assemblies with different visibility
130+ not this .isPublic ( )
106131 }
107132
108133 /**
109- * Holds if this declaration is effectively `internal` (either directly or
110- * because one of the enclosing types is `internal`).
134+ * Holds if this declaration is effectively `internal`. A declaration is considered
135+ * effectively `internal` if it can only be referenced from the declaring assembly.
136+ *
137+ * Note that friend assemblies declared in `InternalsVisibleToAttribute` are not
138+ * considered. Explicit interface implementations are also considered effectively
139+ * `internal` if the implemented interface is itself effectively `internal`. Finally,
140+ * `internal protected` members are not considered effectively `internal`, because
141+ * they can be overriden outside the declaring assembly.
111142 */
112143 predicate isEffectivelyInternal ( ) {
113- this .isInternal ( ) or
114- this .getDeclaringType + ( ) .isInternal ( )
144+ this .isReallyInternal ( ) or
145+ this .getDeclaringType + ( ) .( Modifiable ) .isReallyInternal ( ) or
146+ this .( Virtualizable ) .getExplicitlyImplementedInterface ( ) .isEffectivelyInternal ( )
115147 }
116148
117149 /**
118- * Holds if this declaration is effectively `public`, because it
119- * and all enclosing types are `public` .
150+ * Holds if this declaration is effectively `public`, meaning that it can be
151+ * referenced outside the declaring assembly .
120152 */
121153 predicate isEffectivelyPublic ( ) { not isEffectivelyPrivate ( ) and not isEffectivelyInternal ( ) }
122154}
@@ -159,6 +191,11 @@ class Virtualizable extends Member, @virtualizable {
159191 implementsExplicitInterface ( )
160192 }
161193
194+ override predicate isPrivate ( ) {
195+ super .isPrivate ( ) and
196+ not implementsExplicitInterface ( )
197+ }
198+
162199 /**
163200 * Gets any interface this member explicitly implements; this only applies
164201 * to members that can be declared on an interface, i.e. methods, properties,
0 commit comments