Skip to content

Go: improve CallNode documentation #14882

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 24, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 34 additions & 3 deletions go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,11 @@ module Public {
class CallNode extends ExprNode {
override CallExpr expr;

/** Gets the declared target of this call */
/**
* Gets the declared target of this call, if it exists.
*
* This doesn't exist when a function is called via a variable.
*/
Function getTarget() { result = expr.getTarget() }

private DataFlow::Node getACalleeSource() { result = getACalleeSource(this) }
Expand Down Expand Up @@ -637,14 +641,41 @@ module Public {
/** Gets a result of this call. */
Node getAResult() { result = this.getResult(_) }

/** Gets the data flow node corresponding to the receiver of this call, if any. */
/**
* Gets the data flow node corresponding to the receiver of this call, if any.
*
* When a method value is assigned to a variable then when it is called it
* looks like a function call, as in the following example.
*
* ```go
* file, _ := os.Open("test.txt")
* f := file.Close
* f()
* ```
*
* In this case we use local flow to try to find the receiver (`file` in
* the above example).
*/
Node getReceiver() { result = this.getACalleeSource().(MethodReadNode).getReceiver() }

/** Holds if this call has an ellipsis after its last argument. */
predicate hasEllipsis() { expr.hasEllipsis() }
}

/** A data flow node that represents a call to a method. */
/**
* A data flow node that represents a direct call to a method.
*
* When a method value is assigned to a variable then when it is called it
* syntactically looks like a function call, as in the following example.
*
* ```go
* file, _ := os.Open("test.txt")
* f := file.Close
* f()
* ```
*
* In this case it will not be considered a `MethodCallNode`.
*/
class MethodCallNode extends CallNode {
MethodCallNode() { expr.getTarget() instanceof Method }

Expand Down