class DexReturnInliner extends DexTransformer {

  public static DexReturnInliner v() {
    return new DexReturnInliner();
  }

  private boolean isInstanceofReturn(Unit u) {
    if (u instanceof ReturnStmt || u instanceof ReturnVoidStmt) {
      return true;
    }
    return false;
  }

  private boolean isInstanceofFlowChange(Unit u) {
    if (u instanceof GotoStmt || isInstanceofReturn(u)) {
      return true;
    }
    return false;
  }

  @Override
  protected void internalTransform(final Body body, String phaseName, Map<String, String> options) {<FILL_FUNCTION_BODY>}

  /**
   * Gets the set of return statements that can be reached via fall-throughs, i.e. normal sequential code execution. Dually,
   * these are the statements that can be reached without jumping there.
   *
   * @param body
   *          The method body
   * @return The set of fall-through return statements
   */
  private Set<Unit> getFallThroughReturns(Body body) {
    Set<Unit> fallThroughReturns = null;
    Unit lastUnit = null;
    for (Unit u : body.getUnits()) {
      if (lastUnit != null && isInstanceofReturn(u) && !isInstanceofFlowChange(lastUnit)) {
        if (fallThroughReturns == null) {
          fallThroughReturns = new HashSet<Unit>();
        }
        fallThroughReturns.add(u);
      }
      lastUnit = u;
    }
    return fallThroughReturns;
  }

}

    Set<Unit> duplicateIfTargets = getFallThroughReturns(body);

    Iterator<Unit> it = body.getUnits().snapshotIterator();
    boolean mayBeMore = false;
    Unit last = null;
    do {
      mayBeMore = false;
      while (it.hasNext()) {
        Unit u = it.next();
        if (u instanceof GotoStmt) {
          GotoStmt gtStmt = (GotoStmt) u;
          if (isInstanceofReturn(gtStmt.getTarget())) {
            Stmt stmt = (Stmt) gtStmt.getTarget().clone();

            for (Trap t : body.getTraps()) {
              for (UnitBox ubox : t.getUnitBoxes()) {
                if (ubox.getUnit() == u) {
                  ubox.setUnit(stmt);
                }
              }
            }

            while (!u.getBoxesPointingToThis().isEmpty()) {
              u.getBoxesPointingToThis().get(0).setUnit(stmt);
            }
            // the cloned return stmt gets the tags of u
            stmt.addAllTagsOf(u);
            body.getUnits().swapWith(u, stmt);

            mayBeMore = true;
          }
        } else if (u instanceof IfStmt) {
          IfStmt ifstmt = (IfStmt) u;
          Unit t = ifstmt.getTarget();

          if (isInstanceofReturn(t)) {
            // We only copy this return if it is used more than
            // once, otherwise we will end up with unused copies
            if (duplicateIfTargets == null) {
              duplicateIfTargets = new HashSet<Unit>();
            }
            if (!duplicateIfTargets.add(t)) {
              Unit newTarget = (Unit) t.clone();
              body.getUnits().addLast(newTarget);
              ifstmt.setTarget(newTarget);
            }
          }
        } else if (isInstanceofReturn(u)) {
          // the original return stmt gets the tags of its predecessor
          if (last != null) {
            u.removeAllTags();
            u.addAllTagsOf(last);
          }
        }
        last = u;
      }
    } while (mayBeMore);
  
<methods>public non-sealed void <init>() <variables>