@@ -123,6 +123,8 @@ module Input3 implements InputSig3 {
123123 predicate cacheRevRef ( ) {
124124 ( exists ( resolveFieldAccess ( _) ) implies any ( ) )
125125 or
126+ ( exists ( resolveAccessorAccess ( _) ) implies any ( ) )
127+ or
126128 ( exists ( resolveCallTarget ( _) ) implies any ( ) )
127129 }
128130
@@ -252,24 +254,55 @@ module Input3 implements InputSig3 {
252254 override Location getLocation ( ) { result = decl .getLocation ( ) }
253255 }
254256
255- class Field extends AstVariableDeclaration {
257+ final class Field = FieldImpl ;
258+
259+ abstract private class FieldImpl extends DeclarationImpl {
260+ abstract AstNode getAstNode ( ) ;
261+ }
262+
263+ private class VariableDeclarationField extends FieldImpl , AstVariableDeclaration {
256264 ClassLikeDeclaration cls ;
257265
258- Field ( ) { decl = cls .getAMember ( ) }
266+ VariableDeclarationField ( ) { decl = cls .getAMember ( ) }
267+
268+ override AstNode getAstNode ( ) { result = this .getDecl ( ) }
259269
260270 override TypeMention getDeclaringType ( ) { result = getClassLikeDeclarationTypeMention ( cls ) }
261271 }
262272
263- private class EnumField_ extends Field {
273+ private class EnumField_ extends VariableDeclarationField {
264274 override EnumField decl ;
265275
266276 override TypeMention getType ( ) { result = decl .getEnum ( ) .getNameNode ( ) }
267277 }
268278
279+ private class AccessorField extends FieldImpl , Callable {
280+ private AccessorDeclaration accessor ;
281+
282+ AccessorField ( ) { accessor = this .getCallable ( ) }
283+
284+ override TypeMention getType ( ) { result = accessor .getType ( ) }
285+
286+ override AstNode getAstNode ( ) { result = accessor }
287+ }
288+
269289 abstract class FieldAccess extends Expr {
270290 abstract Expr getReceiver ( ) ;
271291
272- abstract Field getField ( ) ;
292+ abstract Field getFieldImpl ( ) ;
293+
294+ Field getField ( ) {
295+ result = this .getFieldImpl ( ) and
296+ (
297+ result instanceof VariableDeclaration
298+ or
299+ hasIncomingValue ( this , _) and
300+ result .getAstNode ( ) instanceof SetterDeclaration
301+ or
302+ hasResultValue ( this ) and
303+ result .getAstNode ( ) instanceof GetterDeclaration
304+ )
305+ }
273306 }
274307
275308 pragma [ nomagic]
@@ -296,14 +329,14 @@ module Input3 implements InputSig3 {
296329 name = this .getMemberName ( )
297330 }
298331
299- override Field getField ( ) {
332+ override Field getFieldImpl ( ) {
300333 // mutual recursion; resolving qualified fields requires resolving types and vice versa
301334 result = lookupInstanceMember ( this )
302335 or
303336 // also mutual recursion
304337 exists ( TupleType tuple , string name |
305338 this .isTupleProjection ( tuple , name ) and
306- result .getDecl ( ) = tuple .getField ( name )
339+ result .getAstNode ( ) = tuple .getField ( name )
307340 )
308341 or
309342 // no mutual recursion; can be resolved directly with static name binding
@@ -322,7 +355,19 @@ module Input3 implements InputSig3 {
322355 private class UnqualifiedMemberAccessFieldAccess extends FieldAccess , UnqualifiedMemberAccess {
323356 override Expr getReceiver ( ) { none ( ) }
324357
325- override Field getField ( ) { result .getNameNode ( ) = this .getTarget ( ) }
358+ override Field getFieldImpl ( ) { result .getNameNode ( ) = this .getTarget ( ) }
359+ }
360+
361+ private class LocalAccessorFieldAccess extends FieldAccess , LocalNameAccess {
362+ AccessorDeclaration target ;
363+
364+ LocalAccessorFieldAccess ( ) {
365+ target = getStaticBindingTargetFromIdentifier ( this ) .getDeclaration ( )
366+ }
367+
368+ override Expr getReceiver ( ) { none ( ) }
369+
370+ override Field getFieldImpl ( ) { result .getAstNode ( ) = target }
326371 }
327372
328373 Type inferFieldAccessReceiverType ( FieldAccess fa , TypePath path ) {
@@ -506,17 +551,21 @@ module Input3 implements InputSig3 {
506551 }
507552
508553 Callable getTargetImpl ( boolean isFunctionExprInvoke ) {
509- // mutual recursion; call with explicit receiver: `obj.foo(42)`
510- result = lookupInstanceMember ( this .getCallee ( ) ) and
511- isFunctionExprInvoke = false
512- or
513- // mutual recursion; call to a function expression: `callback(42)`
514- result .asCallable ( ) = this .getInvokeTarget ( _) and
515- isFunctionExprInvoke = true
516- or
517- // no mutual recursion; can be resolved directly with static name binding
518- result = this .getTargetViaStaticNameBinding ( ) and
519- isFunctionExprInvoke = false
554+ (
555+ // mutual recursion; call with explicit receiver: `obj.foo(42)`
556+ result = lookupInstanceMember ( this .getCallee ( ) ) and
557+ isFunctionExprInvoke = false
558+ or
559+ // mutual recursion; call to a function expression: `callback(42)`
560+ result .asCallable ( ) = this .getInvokeTarget ( _) and
561+ isFunctionExprInvoke = true
562+ or
563+ // no mutual recursion; can be resolved directly with static name binding
564+ result = this .getTargetViaStaticNameBinding ( ) and
565+ isFunctionExprInvoke = false
566+ ) and
567+ // handled as a field access
568+ not result .asCallable ( ) instanceof AccessorDeclaration
520569 }
521570
522571 Callable getTarget ( InvocationResolutionContext c ) {
@@ -835,7 +884,19 @@ module CachedStage = M3::CachedStage;
835884cached
836885VariableDeclaration resolveFieldAccess ( Expr access ) {
837886 CachedStage:: ref ( ) and
838- result = access .( Input3:: FieldAccess ) .getField ( ) .getDecl ( )
887+ result = access .( Input3:: FieldAccess ) .getField ( ) .getAstNode ( )
888+ }
889+
890+ /**
891+ * Gets the accessor that is accessed by the given expression.
892+ *
893+ * `access` is either a `MemberAccessExpr` or an `Identifier` (when
894+ * the field is accessed with an implicit receiver).
895+ */
896+ cached
897+ AccessorDeclaration resolveAccessorAccess ( Expr access ) {
898+ CachedStage:: ref ( ) and
899+ result = access .( Input3:: FieldAccess ) .getField ( ) .getAstNode ( )
839900}
840901
841902/**
0 commit comments