@@ -439,8 +439,8 @@ module Public {
439439 CallNode getCallNode ( ) { result = call }
440440
441441 override Type getType ( ) {
442- exists ( Function f | f = call .getTarget ( ) |
443- result = f .getParameterType ( f .getNumParameter ( ) - 1 )
442+ exists ( SignatureType t | t = call .getCall ( ) . getCalleeType ( ) |
443+ result = t .getParameterType ( t .getNumParameter ( ) - 1 )
444444 )
445445 }
446446
@@ -474,7 +474,11 @@ module Public {
474474 class CallNode extends ExprNode {
475475 override CallExpr expr ;
476476
477- /** Gets the declared target of this call */
477+ /**
478+ * Gets the declared target of this call, if it exists.
479+ *
480+ * This doesn't exist when a function is called via a variable.
481+ */
478482 Function getTarget ( ) { result = expr .getTarget ( ) }
479483
480484 private DataFlow:: Node getACalleeSource ( ) { result = getACalleeSource ( this ) }
@@ -622,16 +626,40 @@ module Public {
622626 /** Gets a result of this call. */
623627 Node getAResult ( ) { result = this .getResult ( _) }
624628
625- /** Gets the data flow node corresponding to the receiver of this call, if any. */
629+ /**
630+ * Gets the data flow node corresponding to the receiver of this call, if any.
631+ *
632+ * When a method value is assigned to a variable then when it is called it
633+ * looks like a function call, as in the following example.
634+ * ```go
635+ * file, _ := os.Open("test.txt")
636+ * f := file.Close
637+ * f()
638+ * ```
639+ * In this case we use local flow to try to find the receiver (`file` in
640+ * the above example).
641+ */
626642 Node getReceiver ( ) { result = this .getACalleeSource ( ) .( MethodReadNode ) .getReceiver ( ) }
627643
628644 /** Holds if this call has an ellipsis after its last argument. */
629645 predicate hasEllipsis ( ) { expr .hasEllipsis ( ) }
630646 }
631647
632- /** A data flow node that represents a call to a method. */
648+ /**
649+ * A data flow node that represents a call to a method.
650+ *
651+ * When a method value is assigned to a variable then when it is called it
652+ * syntactically looks like a function call, as in the following example.
653+ * ```go
654+ * file, _ := os.Open("test.txt")
655+ * f := file.Close
656+ * f()
657+ * ```
658+ * In this case we use local flow to see whether a method is assigned to the
659+ * function.
660+ */
633661 class MethodCallNode extends CallNode {
634- MethodCallNode ( ) { expr . getTarget ( ) instanceof Method }
662+ MethodCallNode ( ) { getACalleeSource ( this ) instanceof MethodReadNode }
635663
636664 override Method getTarget ( ) { result = expr .getTarget ( ) }
637665
0 commit comments