/** * Fills in all used scopes of the given one. * * @param curr current scope * @return IDs of all directly reachable scopes * @throws QueryException if a variable directly calls itself */ private int[] neighbors(final Scope curr) throws QueryException { final IntList adj = new IntList(0); final boolean ok = curr.visit( new ASTVisitor() { @Override public boolean staticVar(final StaticVar var) { return var != curr && neighbor(var); } @Override public boolean staticFuncCall(final StaticFuncCall call) { return neighbor(call.func()); } @Override public boolean inlineFunc(final Scope sub) { return sub.visit(this); } @Override public boolean funcItem(final FuncItem func) { return neighbor(func); } /** * Adds a neighbor of the currently inspected scope. * * @param scp the neighbor * @return {@code true} for convenience */ private boolean neighbor(final Scope scp) { final int old = id(scp), id = old == -1 ? add(scp) : old; if (old == -1 || !adj.contains(id)) adj.add(id); return true; } }); if (!ok) { final StaticVar var = (StaticVar) curr; throw CIRCREF_X.get(var.info, "$" + var.name); } return adj.finish(); }