mod common;
use common::TestServer;
#[tokio::test]
async fn references_function_same_file() {
let mut s = TestServer::new().await;
s.check_references_annotated(
r#"<?php
function gr$0eet(): void {}
// ^^^^^ def
greet();
//^^^^^ ref
greet();
//^^^^^ ref
"#,
)
.await;
}
#[tokio::test]
async fn references_method_same_file() {
let mut s = TestServer::new().await;
s.check_references_annotated(
r#"<?php
class Greeter {
public function he$0llo(): string { return 'hi'; }
// ^^^^^ def
}
$g = new Greeter();
$g->hello();
// ^^^^^ ref
$g->hello();
// ^^^^^ ref
"#,
)
.await;
}
#[tokio::test]
async fn references_static_method() {
let mut s = TestServer::new().await;
s.check_references_annotated(
r#"<?php
class Reg {
public static function ge$0t(): void {}
// ^^^ def
}
Reg::get();
// ^^^ ref
Reg::get();
// ^^^ ref
"#,
)
.await;
}
#[tokio::test]
async fn references_cross_file_via_use() {
let mut s = TestServer::new().await;
s.check_references_annotated(
r#"//- /src/Greeter.php
<?php
namespace App;
class Greeter {
public function hel$0lo(): string { return 'hi'; }
// ^^^^^ def
}
//- /src/main.php
<?php
use App\Greeter;
$g = new Greeter();
$g->hello();
// ^^^^^ ref
"#,
)
.await;
}
#[tokio::test]
async fn references_no_usages_for_unused_function() {
let mut s = TestServer::new().await;
s.check_references_annotated(
r#"<?php
function un$0used(): void {}
// ^^^^^^ def
"#,
)
.await;
}
#[tokio::test]
async fn references_class_used_in_new() {
let mut s = TestServer::new().await;
s.check_references_annotated(
r#"<?php
class Wi$0dget {}
// ^^^^^^ def
$a = new Widget();
// ^^^^^^ ref
$b = new Widget();
// ^^^^^^ ref
"#,
)
.await;
}
#[tokio::test]
async fn references_distinguishes_like_named_methods() {
let mut s = TestServer::new().await;
s.check_references_annotated(
r#"<?php
class Mailer {
public function pro$0cess(): void {}
// ^^^^^^^ def
}
class Queue {
public function process(): void {}
}
$m = new Mailer();
$m->process();
// ^^^^^^^ ref
$q = new Queue();
$q->process();
"#,
)
.await;
}
#[tokio::test]
async fn references_distinguishes_cross_namespace_functions() {
let mut s = TestServer::new().await;
s.check_references_annotated(
r#"//- /src/app.php
<?php
namespace App;
function gr$0eet(): void {}
// ^^^^^ def
greet();
//^^^^^ ref
//- /src/domain.php
<?php
namespace Domain;
function greet(): void {}
greet();
"#,
)
.await;
}
#[tokio::test]
async fn references_distinguishes_cross_namespace_classes() {
let mut s = TestServer::new().await;
s.check_references_annotated(
r#"//- /src/app.php
<?php
namespace App;
class Us$0er {}
// ^^^^ def
$a = new User();
// ^^^^ ref
//- /src/domain.php
<?php
namespace Domain;
class User {}
$b = new User();
"#,
)
.await;
}
#[tokio::test]
async fn references_method_via_subclass_receiver_found() {
let mut s = TestServer::new().await;
s.check_references_annotated(
r#"<?php
class Base {
public function wo$0rk(): void {}
// ^^^^ def
}
class Child extends Base {}
$c = new Child();
$c->work();
// ^^^^ ref
"#,
)
.await;
}
#[tokio::test]
async fn references_trait_method() {
let mut s = TestServer::new().await;
s.check_references_annotated(
r#"<?php
trait Timestampable {
public function touc$0hAt(): void {}
// ^^^^^^^ def
}
class Post {
use Timestampable;
}
$p = new Post();
$p->touchAt();
// ^^^^^^^ ref
$p->touchAt();
// ^^^^^^^ ref
"#,
)
.await;
}
#[tokio::test]
async fn references_interface_method_finds_call_sites() {
let mut s = TestServer::new().await;
s.check_references_annotated(
r#"<?php
interface Renderable {
public function ren$0der(): string;
// ^^^^^^ def
}
class Page implements Renderable {
public function render(): string { return ''; }
// ^^^^^^ def
}
$page = new Page();
echo $page->render();
// ^^^^^^ ref
"#,
)
.await;
}
#[tokio::test]
async fn references_enum_method() {
let mut s = TestServer::new().await;
s.check_references_annotated(
r#"<?php
enum Status {
case Active;
public function lab$0el(): string { return 'active'; }
// ^^^^^ def
}
echo Status::Active->label();
// ^^^^^ ref
echo Status::Active->label();
// ^^^^^ ref
"#,
)
.await;
}
#[tokio::test]
async fn references_nullsafe_method_call() {
let mut s = TestServer::new().await;
s.check_references_annotated(
r#"<?php
class Mailer {
public function se$0nd(): void {}
// ^^^^ def
}
$m = new Mailer();
$m->send();
// ^^^^ ref
$m?->send();
// ^^^^ ref
"#,
)
.await;
}
#[tokio::test]
async fn references_class_includes_type_hints_and_extends() {
let mut s = TestServer::new().await;
s.check_references_annotated(
r#"<?php
class Ev$0ent {}
// ^^^^^ def
class UserEvent extends Event {}
// ^^^^^ ref
function dispatch(Event $e): void {}
// ^^^^^ ref
$e = null;
if ($e instanceof Event) {}
// ^^^^^ ref
"#,
)
.await;
}
#[tokio::test]
async fn references_promoted_property_finds_nullsafe_access() {
let mut s = TestServer::new().await;
s.check_references_annotated(
r#"<?php
class Config {
public function __construct(public readonly string $ke$0y) {}
}
$c = new Config('x');
echo $c->key;
// ^^^ ref
echo $c?->key;
// ^^^ ref
"#,
)
.await;
}