Permalink
Browse files

Test both ServerInferType visitors.

Summary: Right now we only have direct automated testing for `ServerInferType.function_following_visitor` (`ServerInferType.base_visitor` is indirectly tested in `Test_server_hover`).  This change adds direct tests for `ServerInferType.base_visitor`.

Differential Revision: D6918103

fbshipit-source-id: d39da2ca97f017cbc0e3bdabbfbd83d379e4832e
  • Loading branch information...
pittsw authored and hhvm-bot committed Feb 9, 2018
1 parent 82add8e commit 7fcd844abadd8d1b8be6e55eefb8b57122ff1333
Showing with 64 additions and 228 deletions.
  1. +63 −42 hphp/hack/test/integration_ml/test_infer_type.ml
  2. +1 −186 hphp/hack/test/integration_ml/test_server_hover.ml
@@ -20,7 +20,7 @@ function id(int $x): int {
"
let id_cases = [
("id.php", 3, 10), "int";
("id.php", 3, 10), ("int", "int");
]
let class_A = "<?hh // strict
@@ -36,8 +36,8 @@ class A {
"
let class_A_cases = [
("A.php", 7, 12), "<static>";
("A.php", 7, 19), "int";
("A.php", 7, 12), ("<static>", "<static>");
("A.php", 7, 19), ("int", "int");
]
let pair = "<?hh // strict
@@ -81,14 +81,14 @@ function test_pair(Pair<A> $v): Pair<A> {
"
let test_pair_cases = [
("test_pair.php", 6, 8), "Pair<A>";
("test_pair.php", 6, 15), "A";
("test_pair.php", 8, 4), "Pair";
("test_pair.php", 8, 17), "B";
("test_pair.php", 10, 14), "A";
("test_pair.php", 12, 10), "Pair<A>";
("test_pair.php", 12, 19), "Pair<A>";
("test_pair.php", 12, 20), "Pair";
("test_pair.php", 6, 8), ("Pair<A>", "Pair<A>");
("test_pair.php", 6, 15), ("(function(): A)", "A");
("test_pair.php", 8, 4), ("Pair", "Pair");
("test_pair.php", 8, 17), ("B", "B");
("test_pair.php", 10, 14), ("A", "A");
("test_pair.php", 12, 10), ("(function(Pair<A> $v): Pair<A>)", "Pair<A>");
("test_pair.php", 12, 19), ("Pair<A>", "Pair<A>");
("test_pair.php", 12, 20), ("Pair", "Pair");
]
let loop_assignment = "<?hh // strict
@@ -110,10 +110,10 @@ function loop_assignment(): void {
"
let loop_assignment_cases = [
("loop_assignment.php", 5, 4), "int";
("loop_assignment.php", 8, 9), "(string | int)";
("loop_assignment.php", 11, 7), "string";
("loop_assignment.php", 14, 7), "(string | int)";
("loop_assignment.php", 5, 4), ("int", "int");
("loop_assignment.php", 8, 9), ("(string | int)", "(string | int)");
("loop_assignment.php", 11, 7), ("string", "string");
("loop_assignment.php", 14, 7), ("(string | int)", "(string | int)");
]
let lambda1 = "<?hh // strict
@@ -129,14 +129,14 @@ function test_lambda1(): void {
"
let lambda_cases = [
("lambda1.php", 4, 3), "[fun]";
("lambda1.php", 4, 29), "string";
("lambda1.php", 6, 3), "string";
("lambda1.php", 6, 8), "string";
("lambda1.php", 6, 11), "int";
("lambda1.php", 8, 3), "string";
("lambda1.php", 8, 8), "string";
("lambda1.php", 8, 11), "string";
("lambda1.php", 4, 3), ("[fun]", "[fun]");
("lambda1.php", 4, 29), ("string", "string");
("lambda1.php", 6, 3), ("string", "string");
("lambda1.php", 6, 8), ("[fun]", "string");
("lambda1.php", 6, 11), ("int", "int");
("lambda1.php", 8, 3), ("string", "string");
("lambda1.php", 8, 8), ("[fun]", "string");
("lambda1.php", 8, 11), ("string", "string");
]
let callback = "<?hh // strict
@@ -149,9 +149,9 @@ function test_callback((function(int): string) $cb): void {
"
let callback_cases = [
("callback.php", 3, 3), "(function(int): string)";
("callback.php", 5, 3), "string";
("callback.php", 5, 8), "string";
("callback.php", 3, 3), ("(function(int): string)", "(function(int): string)");
("callback.php", 5, 3), ("(function(int): string)", "string");
("callback.php", 5, 8), ("string", "string");
]
let invariant_violation = "<?hh // strict
@@ -171,8 +171,8 @@ function nullthrows<T>(?T $x): T {
"
let nullthrows_cases = [
("nullthrows.php", 3, 13), "?T";
("nullthrows.php", 5, 10), "T";
("nullthrows.php", 3, 13), ("?T", "?T");
("nullthrows.php", 5, 10), ("T", "T");
]
let curried = "<?hh // strict
@@ -187,8 +187,14 @@ function test_curried(bool $cond): void {
"
let curried_cases = [
("curried.php", 6, 3), "(function(): (function(int): (function(bool): string)))";
("curried.php", 7, 3), "string";
("curried.php", 6, 3), (
"(function(): (function(int): (function(bool): string)))",
"(function(): (function(int): (function(bool): string)))"
);
("curried.php", 7, 3), (
"(function(): (function(int): (function(bool): string)))",
"string"
);
]
let multiple_type = "<?hh // strict
@@ -202,8 +208,8 @@ function test_multiple_type(C1 $c1, C2 $c2, bool $cond): arraykey {
"
let multiple_type_cases = [
("multiple_type.php", 6, 10), "(C1 | C2)";
("multiple_type.php", 6, 14), "(int | string)";
("multiple_type.php", 6, 10), ("(C1 | C2)", "(C1 | C2)");
("multiple_type.php", 6, 14), ("((function(): string) | (function(): int))", "(int | string)");
]
let files = [
@@ -237,15 +243,30 @@ let () =
Test.assert_no_errors env;
List.iter cases ~f:begin fun ((file, line, col), expected_type) ->
let fn = ServerUtils.FileName ("/" ^ file) in
let ty = ServerInferType.go env (fn, line, col) in
let ty_name, _ty_json =
match ty with
| Some ty -> ty
| None ->
Test.fail (Printf.sprintf "No type inferred at %s:%d:%d" file line col);
failwith "unreachable"
List.iter cases ~f:begin fun
((file, line, col), (expected_type, expected_returned_type))
->
let compare_type expected type_at =
let ty_str =
match type_at with
| Some (env, ty) -> Typing_print.full_strip_ns env ty
| None ->
Test.fail (Printf.sprintf "No type inferred at %s:%d:%d" file line col);
failwith "unreachable"
in
let fmt = Printf.sprintf "%s:%d:%d %s" file line col in
Test.assertEqual (fmt expected) (fmt ty_str)
in
Test.assertEqual expected_type ty_name
let fn = ServerUtils.FileName ("/" ^ file) in
let ServerEnv.{tcopt; files_info; _} = env in
let _, tast = ServerIdeUtils.check_file_input tcopt files_info fn in
let ty = ServerInferType.type_at_pos tast line col in
compare_type expected_type ty;
let ty = ServerInferType.returned_type_at_pos tast line col in
compare_type expected_returned_type ty
end
@@ -13,173 +13,6 @@ open HoverService
module Test = Integration_test_base
let id = "<?hh // strict
function id(int $x): int {
return $x;
// ^3:10
}
"
let id_cases = [
("id.php", 3, 10), [{ info = "int"; doc_block = None }];
]
let class_A = "<?hh // strict
class A {
public function __construct(
private int $id,
) {}
public function getId(): int {
return $this->id;
// ^7:12 ^7:19
}
}
"
let class_A_cases = [
("A.php", 7, 12), [{ info = "<static>"; doc_block = None }];
("A.php", 7, 19), [{ info = "int"; doc_block = None }];
]
let pair = "<?hh // strict
class Pair<T> {
private T $fst;
private T $snd;
public function __construct(T $fst, T $snd) {
$this->fst = $fst;
$this->snd = $snd;
}
public function getFst(): T {
return $this->fst;
}
public function setFst(T $fst): void {
$this->fst = $fst;
}
public function getSnd(): T {
return $this->snd;
}
public function setSnd(T $snd): void {
$this->snd = $snd;
}
}
"
let test_pair = "<?hh // strict
class B extends A {}
class C extends A {}
function test_pair(Pair<A> $v): Pair<A> {
$c = $v->getSnd();
// ^6:8 ^6:15
$v = new Pair(new B(1), new C(2));
// ^8:4 ^8:17
$v->setFst($c);
// ^10:14
return test_pair($v);
// ^12:10 ^12:20
}
"
let test_pair_cases = [
("test_pair.php", 6, 8), [{ info = "Pair<A>"; doc_block = None }];
("test_pair.php", 6, 15), [{ info = "getSnd(): A"; doc_block = None }];
("test_pair.php", 8, 4), [{ info = "Pair"; doc_block = None }];
("test_pair.php", 8, 17), [{ info = "B"; doc_block = None }];
("test_pair.php", 10, 14), [{ info = "A"; doc_block = None }];
("test_pair.php", 12, 10), [{ info = "test_pair(Pair<A> $v): Pair<A>"; doc_block = None }];
("test_pair.php", 12, 19), [{ info = "Pair<A>"; doc_block = None }];
("test_pair.php", 12, 20), [{ info = "Pair"; doc_block = None }];
]
let loop_assignment = "<?hh // strict
function use(mixed $item): void {}
function cond(): bool { return true; }
function loop_assignment(): void {
$x = 1;
// ^5:4
while (true) {
use($x);
// ^8:9
if (cond())
$x = 'foo';
// ^11:7
}
use($x);
// ^14:7
}
"
let loop_assignment_cases = [
("loop_assignment.php", 5, 4), [{ info = "int"; doc_block = None }];
("loop_assignment.php", 8, 9), [{ info = "(string | int)"; doc_block = None }];
("loop_assignment.php", 11, 7), [{ info = "string"; doc_block = None }];
("loop_assignment.php", 14, 7), [{ info = "(string | int)"; doc_block = None }];
]
let lambda1 = "<?hh // strict
function test_lambda1(): void {
$s = 'foo';
$f = $n ==> { return $n . $s . '\\n'; };
//^4:3 ^4:29
$x = $f(4);
//^6:3 ^6:8
$y = $f('bar');
//^8:3 ^8:11
}
"
let lambda_cases = [
("lambda1.php", 4, 3), [{ info = "[fun]"; doc_block = None }];
("lambda1.php", 4, 29), [{ info = "string"; doc_block = None }];
("lambda1.php", 6, 3), [{ info = "string"; doc_block = None }];
("lambda1.php", 6, 8), [{ info = "string"; doc_block = None }];
("lambda1.php", 6, 11), [{ info = "int"; doc_block = None }];
("lambda1.php", 8, 3), [{ info = "string"; doc_block = None }];
("lambda1.php", 8, 8), [{ info = "string"; doc_block = None }];
("lambda1.php", 8, 11), [{ info = "string"; doc_block = None }];
]
let callback = "<?hh // strict
function test_callback((function(int): string) $cb): void {
$cb;
//^3:3
$cb(5);
//^5:3 ^5:8
test_callback($cb);
//^7:3
}
"
let callback_cases = [
("callback.php", 3, 3), [{ info = "(function(int): string)"; doc_block = None }];
("callback.php", 5, 3), [{ info = "(function(int): string)"; doc_block = None }];
("callback.php", 5, 8), [{ info = "string"; doc_block = None }];
("callback.php", 7, 3), [
{ info = "test_callback(\n (function(int): string) $cb\n): void"; doc_block = None }];
]
let invariant_violation = "<?hh // strict
class Exception {}
function invariant_violation(string $msg): noreturn {
throw new Exception();
}
"
let nullthrows = "<?hh // strict
function nullthrows<T>(?T $x): T {
invariant($x !== null, 'got null');
// ^3:13
return $x;
// ^5:10
}
"
let nullthrows_cases = [
("nullthrows.php", 3, 13), [{ info = "?T"; doc_block = None }];
("nullthrows.php", 5, 10), [{ info = "T"; doc_block = None }];
]
let classname_call = "<?hh // strict
class ClassnameCall {
static function foo(): int {
@@ -253,32 +86,14 @@ let classname_variable_cases = [
]
let files = [
"id.php", id;
"A.php", class_A;
"Pair.php", pair;
"test_pair.php", test_pair;
"loop_assignment.php", loop_assignment;
"lambda1.php", lambda1;
"callback.php", callback;
"invariant_violation.php", invariant_violation;
"nullthrows.php", nullthrows;
"classname_call.php", classname_call;
"chained_calls.php", chained_calls;
"multiple_potential_types.php", multiple_potential_types;
"classname_variable.php", classname_variable;
]
let cases =
id_cases
@ class_A_cases
@ test_pair_cases
@ loop_assignment_cases
@ lambda_cases
@ callback_cases
@ nullthrows_cases
@ classname_call_cases
classname_call_cases
@ chained_calls_cases
@ multiple_potential_types_cases
@ classname_variable_cases
let () =

0 comments on commit 7fcd844

Please sign in to comment.