Skip to content

Commit

Permalink
Don't fire the duplicate return lint on positive exit codes
Browse files Browse the repository at this point in the history
Reviewed By: periodic1236

Differential Revision: D38948922

fbshipit-source-id: 9e667fcc33c9df7a5608b61b87686a790667f16c
  • Loading branch information
Wilfred authored and facebook-github-bot committed Sep 1, 2022
1 parent 7f18108 commit b10078b
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 17 deletions.
60 changes: 43 additions & 17 deletions hphp/hack/src/lints/linter_branches_return_same_value.ml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,22 @@
open Aast
open Hh_prelude

(**
Lint on functions/methods that always return the same value. This
is usually a copy-paste error.
function some_prediate(Whatever $value): bool {
if ($value->foo()) {
return false;
}
if ($value->bar()) {
return false;
}
return false; // oops!
} *)

let is_expr_same ((_, _, expr1) : Tast.expr) ((_, _, expr2) : Tast.expr) : bool
=
match (expr1, expr2) with
Expand All @@ -26,6 +42,21 @@ let is_expr_same ((_, _, expr1) : Tast.expr) ((_, _, expr2) : Tast.expr) : bool
true
| _ -> false

(* Does this value look like a success exit code? We don't want to
lint on code like this:
function my_main(): int {
if (quick_check()) { return 0; }
normal_work();
return 0;
} *)
let is_success_ish ((_, _, e_) : Tast.expr) : bool =
match e_ with
| Aast.Int "0" -> true
| Aast.Class_const (_, (_, "SUCCESS")) -> true
| _ -> false

let rec are_return_expressions_same (ret_list : Tast.expr list) : bool =
match ret_list with
| expr1 :: expr2 :: tail ->
Expand Down Expand Up @@ -61,25 +92,20 @@ let get_return_expr_visitor =
let get_return_exprs (stmts : Tast.stmt list) : Tast.expr list =
get_return_expr_visitor#on_block () stmts

let check_block (block : Tast.block) : unit =
let ret_list = get_return_exprs block in
match ret_list with
| expr1 :: _ :: _ when are_return_expressions_same ret_list ->
if not (is_success_ish expr1) then
List.iter ret_list ~f:(fun (_, pos, _) ->
Lints_errors.branches_return_same_value pos)
| _ -> ()

let handler =
object
inherit Tast_visitor.handler_base

method! at_fun_def _env f =
let ret_list = get_return_exprs f.fd_fun.f_body.fb_ast in
if List.length ret_list > 1 then (
if are_return_expressions_same ret_list then
List.iter ret_list ~f:(fun (_, pos, _) ->
Lints_errors.branches_return_same_value pos)
) else
()

method! at_method_ _env m =
let ret_list = get_return_exprs m.m_body.fb_ast in
if List.length ret_list > 1 then (
if are_return_expressions_same ret_list then
List.iter ret_list ~f:(fun (_, pos, _) ->
Lints_errors.branches_return_same_value pos)
) else
()
method! at_fun_def _env f = check_block f.fd_fun.f_body.fb_ast

method! at_method_ _env m = check_block m.m_body.fb_ast
end
22 changes: 22 additions & 0 deletions hphp/hack/test/lint/branches_returning_same_success.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<?hh

enum MyExitCode: int {
SUCCESS = 0;
FAILURE = 1;
}

function main_function_early_terminate(): int {
if (1 === 1) {
return 0;
}

return 0;
}

function main_function_early_terminate_enum(): int {
if (1 === 1) {
return MyExitCode::SUCCESS;
}

return MyExitCode::SUCCESS;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
No lint errors

0 comments on commit b10078b

Please sign in to comment.