@@ -191,16 +191,59 @@ impl PlaceExpr {
191
191
& self . root_name
192
192
}
193
193
194
+ /// If the place expression has the form `<NAME>.<MEMBER>`
195
+ /// (meaning it *may* be an instance attribute),
196
+ /// return `Some(<MEMBER>)`. Else, return `None`.
197
+ ///
198
+ /// This method is internal to the semantic-index submodule.
199
+ /// It *only* checks that the AST structure of the `Place` is
200
+ /// correct. It does not check whether the `Place` actually occurred in
201
+ /// a method context, or whether the `<NAME>` actually refers to the first
202
+ /// parameter of the method (i.e. `self`). To answer those questions,
203
+ /// use [`Self::as_instance_attribute`].
204
+ pub ( super ) fn as_instance_attribute_candidate ( & self ) -> Option < & Name > {
205
+ if self . sub_segments . len ( ) == 1 {
206
+ self . sub_segments [ 0 ] . as_member ( )
207
+ } else {
208
+ None
209
+ }
210
+ }
211
+
212
+ /// Return `true` if the place expression has the form `<NAME>.<MEMBER>`,
213
+ /// indicating that it *may* be an instance attribute if we are in a method context.
214
+ ///
215
+ /// This method is internal to the semantic-index submodule.
216
+ /// It *only* checks that the AST structure of the `Place` is
217
+ /// correct. It does not check whether the `Place` actually occurred in
218
+ /// a method context, or whether the `<NAME>` actually refers to the first
219
+ /// parameter of the method (i.e. `self`). To answer those questions,
220
+ /// use [`Self::is_instance_attribute`].
221
+ pub ( super ) fn is_instance_attribute_candidate ( & self ) -> bool {
222
+ self . as_instance_attribute_candidate ( ) . is_some ( )
223
+ }
224
+
194
225
/// Does the place expression have the form `self.{name}` (`self` is the first parameter of the method)?
195
226
pub ( super ) fn is_instance_attribute_named ( & self , name : & str ) -> bool {
196
- self . is_instance_attribute ( )
197
- && self . sub_segments . len ( ) == 1
198
- && self . sub_segments [ 0 ] . as_member ( ) . unwrap ( ) . as_str ( ) == name
227
+ self . as_instance_attribute ( ) . map ( Name :: as_str) == Some ( name)
199
228
}
200
229
201
230
/// Is the place an instance attribute?
202
- pub fn is_instance_attribute ( & self ) -> bool {
203
- self . flags . contains ( PlaceFlags :: IS_INSTANCE_ATTRIBUTE )
231
+ pub ( crate ) fn is_instance_attribute ( & self ) -> bool {
232
+ let is_instance_attribute = self . flags . contains ( PlaceFlags :: IS_INSTANCE_ATTRIBUTE ) ;
233
+ if is_instance_attribute {
234
+ debug_assert ! ( self . is_instance_attribute_candidate( ) ) ;
235
+ }
236
+ is_instance_attribute
237
+ }
238
+
239
+ /// Return `Some(<ATTRIBUTE>)` if the place expression is an instance attribute.
240
+ pub ( crate ) fn as_instance_attribute ( & self ) -> Option < & Name > {
241
+ if self . is_instance_attribute ( ) {
242
+ debug_assert ! ( self . as_instance_attribute_candidate( ) . is_some( ) ) ;
243
+ self . as_instance_attribute_candidate ( )
244
+ } else {
245
+ None
246
+ }
204
247
}
205
248
206
249
/// Is the place used in its containing scope?
@@ -570,9 +613,9 @@ impl PlaceTable {
570
613
self . places ( ) . filter ( |place_expr| place_expr. is_name ( ) )
571
614
}
572
615
573
- pub fn instance_attributes ( & self ) -> impl Iterator < Item = & PlaceExpr > {
616
+ pub fn instance_attributes ( & self ) -> impl Iterator < Item = & Name > {
574
617
self . places ( )
575
- . filter ( |place_expr| place_expr. is_instance_attribute ( ) )
618
+ . filter_map ( |place_expr| place_expr. as_instance_attribute ( ) )
576
619
}
577
620
578
621
/// Returns the place named `name`.
0 commit comments