Code with Finding: |
class InlineFunctions.FindCandidatesReferences {
/**
* Find functions that can be inlined.
*/
private void checkNameUsage(NodeTraversal t, Node n, Node parent) {
Preconditions.checkState(n.getType() == Token.NAME);
if (parent.getType() == Token.VAR || parent.getType() == Token.FUNCTION) {
// This is a declaration. Duplicate declarations are handle during
// function candidate gathering.
return;
}
if (parent.getType() == Token.CALL && parent.getFirstChild() == n) {
// This is a normal reference to the function.
return;
}
// Check for a ".call" to the named function:
// CALL
// GETPROP/GETELEM
// NAME
// STRING == "call"
// This-Value
// Function-parameter-1
// ...
if (NodeUtil.isGet(parent)
&& n == parent.getFirstChild()
&& n.getNext().getType() == Token.STRING
&& n.getNext().getString().equals("call")) {
Node gramps = n.getAncestor(2);
if (gramps.getType() == Token.CALL
&& gramps.getFirstChild() == parent) {
// Yep, a ".call".
return;
}
}
// Other refs to a function name remove its candidacy for inlining
String name = n.getString();
FunctionState fs = fns.get(name);
if (fs == null) {
return;
}
// If the name is being assigned to it can not be inlined.
if (parent.getType() == Token.ASSIGN && parent.getFirstChild() == n) {
// e.g. bar = something; <== we can't inline "bar"
// so mark the function as uninlinable.
// TODO(johnlenz): Should we just remove it from fns here?
fs.setInline(false);
} else {
// e.g. var fn = bar; <== we can't inline "bar"
// As this reference can't be inlined mark the function as
// unremovable.
fs.setRemove(false);
}
}
}
|