@@ -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,20 +254,38 @@ 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 .getReturnType ( ) }
285+
286+ override AstNode getAstNode ( ) { result = accessor }
287+ }
288+
269289 abstract class FieldAccess extends Expr {
270290 abstract Expr getReceiver ( ) ;
271291
@@ -275,7 +295,7 @@ module Input3 implements InputSig3 {
275295 pragma [ nomagic]
276296 private predicate lookupMember0 ( MemberAccessExpr mae , ClassLikeDeclaration cls , string name ) {
277297 not exists ( getStaticBindingTargetFromRef ( mae ) ) and // if a static member can be resolved, use it
278- cls = inferType ( mae .getBase ( ) ) .( ClassLikeDeclarationType ) . getClassLikeDeclaration ( ) and
298+ cls = inferType ( mae .getBase ( ) ) .asClass ( ) and
279299 name = mae .getMemberName ( )
280300 }
281301
@@ -303,7 +323,7 @@ module Input3 implements InputSig3 {
303323 // also mutual recursion
304324 exists ( TupleType tuple , string name |
305325 this .isTupleProjection ( tuple , name ) and
306- result .getDecl ( ) = tuple .getField ( name )
326+ result .getAstNode ( ) = tuple .getField ( name )
307327 )
308328 or
309329 // no mutual recursion; can be resolved directly with static name binding
@@ -325,6 +345,18 @@ module Input3 implements InputSig3 {
325345 override Field getField ( ) { result .getNameNode ( ) = this .getTarget ( ) }
326346 }
327347
348+ private class LocalAccessorFieldAccess extends FieldAccess , LocalNameAccess {
349+ AccessorDeclaration target ;
350+
351+ LocalAccessorFieldAccess ( ) {
352+ target = getStaticBindingTargetFromIdentifier ( this ) .getDeclaration ( )
353+ }
354+
355+ override Expr getReceiver ( ) { none ( ) }
356+
357+ override Field getField ( ) { result .getAstNode ( ) = target }
358+ }
359+
328360 Type inferFieldAccessReceiverType ( FieldAccess fa , TypePath path ) {
329361 // instance field with explicit receiver
330362 result = inferType ( fa .getReceiver ( ) , path )
@@ -506,17 +538,21 @@ module Input3 implements InputSig3 {
506538 }
507539
508540 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
541+ (
542+ // mutual recursion; call with explicit receiver: `obj.foo(42)`
543+ result = lookupInstanceMember ( this .getCallee ( ) ) and
544+ isFunctionExprInvoke = false
545+ or
546+ // mutual recursion; call to a function expression: `callback(42)`
547+ result .asCallable ( ) = this .getInvokeTarget ( _) and
548+ isFunctionExprInvoke = true
549+ or
550+ // no mutual recursion; can be resolved directly with static name binding
551+ result = this .getTargetViaStaticNameBinding ( ) and
552+ isFunctionExprInvoke = false
553+ ) and
554+ // handled as a field access
555+ not result .asCallable ( ) instanceof AccessorDeclaration
520556 }
521557
522558 Callable getTarget ( InvocationResolutionContext c ) {
@@ -835,7 +871,23 @@ module CachedStage = M3::CachedStage;
835871cached
836872VariableDeclaration resolveFieldAccess ( Expr access ) {
837873 CachedStage:: ref ( ) and
838- result = access .( Input3:: FieldAccess ) .getField ( ) .getDecl ( )
874+ result = access .( Input3:: FieldAccess ) .getField ( ) .getAstNode ( )
875+ }
876+
877+ /**
878+ * Gets the accessor that is accessed by the given expression.
879+ *
880+ * Note that we do not attempt to distinguish between different kinds of
881+ * accessors; all accessors belonging to the same declaration will be
882+ * returned (for example both the getter and setter of a property).
883+ *
884+ * `access` is either a `MemberAccessExpr` or an `Identifier` (when
885+ * the field is accessed with an implicit receiver).
886+ */
887+ cached
888+ AccessorDeclaration resolveAccessorAccess ( Expr access ) {
889+ CachedStage:: ref ( ) and
890+ result = access .( Input3:: FieldAccess ) .getField ( ) .getAstNode ( )
839891}
840892
841893/**
0 commit comments