@@ -96,27 +96,59 @@ class Modifiable extends Declaration, @modifiable {
96
96
/** Holds if this declaration is `async`. */
97
97
predicate isAsync ( ) { this .hasModifier ( "async" ) }
98
98
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
+
99
106
/**
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.
102
116
*/
103
117
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 ( )
106
131
}
107
132
108
133
/**
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.
111
142
*/
112
143
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 ( )
115
147
}
116
148
117
149
/**
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 .
120
152
*/
121
153
predicate isEffectivelyPublic ( ) { not isEffectivelyPrivate ( ) and not isEffectivelyInternal ( ) }
122
154
}
@@ -159,6 +191,11 @@ class Virtualizable extends Member, @virtualizable {
159
191
implementsExplicitInterface ( )
160
192
}
161
193
194
+ override predicate isPrivate ( ) {
195
+ super .isPrivate ( ) and
196
+ not implementsExplicitInterface ( )
197
+ }
198
+
162
199
/**
163
200
* Gets any interface this member explicitly implements; this only applies
164
201
* to members that can be declared on an interface, i.e. methods, properties,
0 commit comments