@@ -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,7 @@ 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 ( ) }
326359 }
327360
328361 Type inferFieldAccessReceiverType ( FieldAccess fa , TypePath path ) {
@@ -506,17 +539,21 @@ module Input3 implements InputSig3 {
506539 }
507540
508541 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
542+ (
543+ // mutual recursion; call with explicit receiver: `obj.foo(42)`
544+ result = lookupInstanceMember ( this .getCallee ( ) ) and
545+ isFunctionExprInvoke = false
546+ or
547+ // mutual recursion; call to a function expression: `callback(42)`
548+ result .asCallable ( ) = this .getInvokeTarget ( _) and
549+ isFunctionExprInvoke = true
550+ or
551+ // no mutual recursion; can be resolved directly with static name binding
552+ result = this .getTargetViaStaticNameBinding ( ) and
553+ isFunctionExprInvoke = false
554+ ) and
555+ // handled as a field access
556+ not result .asCallable ( ) instanceof AccessorDeclaration
520557 }
521558
522559 Callable getTarget ( InvocationResolutionContext c ) {
@@ -835,7 +872,19 @@ module CachedStage = M3::CachedStage;
835872cached
836873VariableDeclaration resolveFieldAccess ( Expr access ) {
837874 CachedStage:: ref ( ) and
838- result = access .( Input3:: FieldAccess ) .getField ( ) .getDecl ( )
875+ result = access .( Input3:: FieldAccess ) .getField ( ) .getAstNode ( )
876+ }
877+
878+ /**
879+ * Gets the accessor that is accessed by the given expression.
880+ *
881+ * `access` is either a `MemberAccessExpr` or an `Identifier` (when
882+ * the field is accessed with an implicit receiver).
883+ */
884+ cached
885+ AccessorDeclaration resolveAccessorAccess ( Expr access ) {
886+ CachedStage:: ref ( ) and
887+ result = access .( Input3:: FieldAccess ) .getField ( ) .getAstNode ( )
839888}
840889
841890/**
0 commit comments