use racer;
use racer::{complete_from_file, Coordinate, MatchType};
use std::path::Path;
use racer_testutils::*;
#[test]
fn completes_fn() {
let src = "
fn apple() {
}
fn main() {
let b = ap~
}";
let got = get_one_completion(src, None);
assert_eq!("apple", got.matchstr);
}
#[test]
fn finds_fn_docs() {
let src = "
/// Orange
/// juice
fn apple() {
}
fn main() {
apple~
}";
let got = get_one_completion(src, None);
assert_eq!("apple", got.matchstr);
assert_eq!("Orange\njuice", got.docs);
}
#[test]
fn finds_struct_docs() {
let src = "
/// Orange
/// juice
struct Apple {
}
fn main() {
Apple~
}";
let got = get_one_completion(src, None);
assert_eq!("Apple", got.matchstr);
assert_eq!("Orange\njuice", got.docs);
}
#[test]
fn finds_struct_field_docs() {
let src = "
struct Foo {
/// Hello docs
///
/// How are you?
#[allow(dead_code)]
hello: String,
}
fn do_things(f: Foo) -> String {
f.h~ello.clone()
}
";
let got = get_definition(src, None);
assert_eq!("hello", got.matchstr);
assert_eq!("Hello docs\n\nHow are you?", got.docs);
}
#[test]
fn finds_tuple_struct_field_docs() {
let src = "
struct Bar(
/// Hello docs
String
);
fn do_things(b: Bar) -> String {
b.~0.clone()
}
";
let got = get_definition(src, None);
assert_eq!("0", got.matchstr);
assert_eq!("Hello docs", got.docs);
}
#[test]
fn completes_fn_with_substitute_file() {
let src = "
fn apple() {
}
fn main() {
let b = ap~
}";
let (_pos, src) = get_pos_and_source(src);
let cache = racer::FileCache::default();
let real_file = Path::new("not_real.rs");
let session = racer::Session::new(&cache, None);
session.cache_file_contents(real_file, src);
let cursor = Coordinate::new(6, 18);
let got = complete_from_file(real_file, cursor, &session)
.nth(0)
.unwrap();
assert_eq!(Some(Coordinate::new(2, 8)), got.coords);
assert_eq!("apple", got.matchstr);
}
#[test]
fn completes_pub_fn_locally() {
let src = "
pub fn apple() {
}
fn main() {
let b = ap~
}";
let got = get_one_completion(src, None);
assert_eq!("apple", got.matchstr);
}
#[test]
fn completes_pub_fn_locally_precached() {
let src = "
pub fn apple() {
}
fn main() {
let b = ap~
}";
let (pos, src) = get_pos_and_source(src);
let f = TmpFile::new(&src);
let path = f.path();
let cache = racer::FileCache::default();
let session = racer::Session::new(&cache, Some(path));
session.cache_file_contents(path, src.clone());
let got = complete_from_file(path, pos, &session).nth(0).unwrap();
assert_eq!("apple", got.matchstr);
}
#[test]
fn completes_pub_const_fn_locally() {
let src = "
pub const fn apple() {
}
fn main() {
let b = ap~
}";
let got = get_one_completion(src, None);
assert_eq!("apple", got.matchstr);
}
#[test]
fn completes_local_scope_let() {
let src = "
fn main() {
let apple = 35;
let b = ap~
}";
let got = get_one_completion(src, None);
assert_eq!("apple", got.matchstr);
assert_eq!(29, got.point.0);
}
#[test]
fn completes_via_parent_scope_let() {
let src = "
fn main() {
let mut apple = 35;
if foo {
let b = ap~
}
}";
let got = get_one_completion(src, None);
assert_eq!("apple", got.matchstr);
assert_eq!(33, got.point.0);
}
#[test]
fn completes_for_vec_field_and_method() {
let src = "
struct St
{
stfield: i32,
}
impl St {
pub fn stmethod(&self) -> u32 {2}
}
fn main()
{
let mut arr: Vec<St> = Vec::new();
arr.push( St{stfield: 4} );
for it in arr
{
it.stf
it.stm
}
}
";
let dir = TmpDir::new();
let path = dir.write_file("src.rs", src);
let cache = racer::FileCache::default();
let session = racer::Session::new(&cache, None);
let cursor1 = Coordinate::new(18, 18);
let got1 = complete_from_file(&path, cursor1, &session).nth(0).unwrap();
assert_eq!("stfield", got1.matchstr);
let cursor2 = Coordinate::new(19, 18);
let got2 = complete_from_file(&path, cursor2, &session).nth(0).unwrap();
assert_eq!("stmethod", got2.matchstr);
}
#[test]
fn completes_trait_methods() {
let src = "
mod sub {
pub trait Trait {
fn traitf() -> bool;
fn traitm(&self) -> bool;
}
pub struct Foo(pub bool);
impl Trait for Foo {
fn traitf() -> bool { false }
fn traitm(&self) -> bool { true }
}
}
fn main() { // l16
let t = sub::Foo(true);
sub::Foo::traitf();
t.traitm();
}
";
let f = TmpFile::new(src);
let path = f.path();
let cache1 = racer::FileCache::default();
let session1 = racer::Session::new(&cache1, None);
let cursor1 = Coordinate::new(18, 18);
let got1 = complete_from_file(&path, cursor1, &session1)
.nth(0)
.unwrap();
let cache2 = racer::FileCache::default();
let session2 = racer::Session::new(&cache2, None);
let cursor2 = Coordinate::new(19, 11);
let got2 = complete_from_file(&path, cursor2, &session2)
.nth(0)
.unwrap();
println!("{:?}", got1);
println!("{:?}", got2);
assert_eq!(got1.matchstr, "traitf");
assert_eq!(got2.matchstr, "traitm");
assert_eq!(got1.contextstr, "fn traitf() -> bool");
assert_eq!(got2.contextstr, "fn traitm(&self) -> bool");
}
#[test]
fn completes_trait_bounded_methods() {
let src = "
pub trait Trait1 {}
impl Trait1 for Foo {}
pub trait Trait2 {
fn traitf() -> bool;
fn traitm(&self) -> bool;
}
impl<T: Trait1> Trait2 for T {
fn traitf() -> bool { true }
fn traitm(&self) -> bool { false }
}
pub struct Foo(pub bool);
fn main() {
let t = Foo(true);
Foo::tra
t.tr
}";
let f = TmpFile::new(src);
let path = f.path();
let cache1 = racer::FileCache::default();
let session1 = racer::Session::new(&cache1, None);
let cursor1 = Coordinate::new(20, 16);
let got1 = complete_from_file(&path, cursor1, &session1)
.nth(0)
.unwrap();
let cache2 = racer::FileCache::default();
let session2 = racer::Session::new(&cache2, None);
let cursor2 = Coordinate::new(21, 12);
let got2 = complete_from_file(&path, cursor2, &session2)
.nth(0)
.unwrap();
println!("{:?}", got1);
println!("{:?}", got2);
assert_eq!(got1.matchstr, "traitf");
assert_eq!(got2.matchstr, "traitm");
assert_eq!(got1.contextstr, "fn traitf() -> bool");
assert_eq!(got2.contextstr, "fn traitm(&self) -> bool");
}
#[test]
fn completes_trait_bounded_methods_generic_return() {
let src = "
pub trait Trait1 {
fn traitfn(&self) -> u32 { 2 }
}
impl Trait1 for Foo {}
pub trait Trait2 {
fn traitm(self) -> Self;
}
impl<T: Trait1> Trait2 for T {
fn traitm(self) -> T { self }
}
pub struct Foo(pub bool);
impl Foo {
pub fn structfn(&self) -> bool {self.0}
}
fn main() {
let t = Foo(true);
t.traitm().struc
t.traitm().traitf
}";
let f = TmpFile::new(src);
let path = f.path();
let cache = racer::FileCache::default();
let session = racer::Session::new(&cache, None);
let cursor1 = Coordinate::new(24, 24);
let cursor2 = Coordinate::new(25, 25);
let got1 = complete_from_file(&path, cursor1, &session).nth(0).unwrap();
println!("got1: {:?}", got1);
assert_eq!(got1.matchstr, "structfn");
let got2 = complete_from_file(&path, cursor2, &session).nth(0).unwrap();
println!("{:?}", got2);
assert_eq!(got2.matchstr, "traitfn");
}
#[test]
fn completes_iter_variable_fiedlds() {
let src = "
struct St {
pub item: StItem,
pub used: bool
}
struct StItem {
pub field: u32
}
impl Iterator for St {
type Item = StItem;
fn next(&mut self) -> Option<StItem> {
if self.used {
self.used = false;
return Some(self.item);
}
None
}
}
fn main()
{
let it = St {
text: StItem { field: 22 },
used: false
};
for item in it {
item.fie~
}
}
";
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "field");
}
#[test]
#[ignore]
fn completes_for_vec_iter_field_and_method() {
let src = "
pub mod mymod;
use mymod::{Vec, IntoIter, IntoIterator, Option};
use Option::{Some, None};
struct St
{
stfield: i32,
}
impl St {
pub fn stmethod(&self) -> u32 {2}
}
fn main()
{
let mut arr: Vec<St> = Vec::new();
arr.push( St{stfield: 4} );
for it in arr.iter()
{
it.stf
it.stm
}
}
";
let dir = TmpDir::new();
let path = dir.write_file("src.rs", src);
let cache = racer::FileCache::default();
let session = racer::Session::new(&cache, None);
let cursor1 = Coordinate::new(22, 18);
let got1 = complete_from_file(&path, cursor1, &session).nth(0).unwrap();
assert_eq!("stfield", got1.matchstr);
let cursor2 = Coordinate::new(23, 18);
let got2 = complete_from_file(&path, cursor2, &session).nth(0).unwrap();
assert_eq!("stmethod", got2.matchstr);
}
#[test]
fn completes_trait_methods_when_at_scope_end() {
let src = "
mod sub {
pub trait Trait {
fn traitf() -> bool;
fn traitm(&self) -> bool;
}
impl Trait for Foo {
fn traitf() -> bool { false }
fn traitm(&self) -> bool { true }
}
pub struct Foo(pub bool);
}
fn main() { // l16
let t = sub::Foo(true);
sub::Foo::traitf();
t.traitm();
}
";
let f = TmpFile::new(src);
let path = f.path();
let cache = racer::FileCache::default();
let session = racer::Session::new(&cache, None);
let cursor1 = Coordinate::new(18, 18);
let got1 = complete_from_file(&path, cursor1, &session).nth(0).unwrap();
let cursor2 = Coordinate::new(19, 11);
let got2 = complete_from_file(&path, cursor2, &session).nth(0).unwrap();
println!("{:?}", got1);
println!("{:?}", got2);
assert_eq!(got1.matchstr, "traitf");
assert_eq!(got2.matchstr, "traitm");
assert_eq!(got1.contextstr, "fn traitf() -> bool");
assert_eq!(got2.contextstr, "fn traitm(&self) -> bool");
}
#[test]
fn follows_use() {
let src1 = "
pub fn myfn() {}
pub fn foo() {}
";
let src = "
use src1::{foo,myfn};
mod src1;
fn main() {
myfn~();
}
";
let dir = TmpDir::new();
let _src1 = dir.write_file("src1.rs", src1);
let got = get_definition(src, Some(dir));
assert_eq!(got.matchstr, "myfn");
assert_eq!(got.contextstr, "pub fn myfn()");
}
#[test]
fn follows_use_in_braces() {
let src = "
mod foo {
pub fn myfn() {}
pub fn second() {}
}
fn main() {
use foo::{
myfn,
second
};
my~fn();
}
";
let got = get_definition(src, None);
assert_eq!(got.matchstr, "myfn");
}
#[test]
fn follows_use_glob() {
let src3 = "
pub fn myfn() {}
pub fn foo() {}
";
let src = "
use src3::*;
mod src3;
fn main() {
my~fn();
}
";
let dir = TmpDir::new();
let _src3 = dir.write_file("src3.rs", src3);
let got = get_definition(src, Some(dir));
assert_eq!(got.matchstr, "myfn");
}
#[test]
fn follows_multiple_use_globs() {
let src1 = "
pub fn src1fn() {}
";
let src2 = "
pub fn src2fn() {}
";
let src = "
use multiple_glob_test1::*;
use multiple_glob_test2::*;
mod multiple_glob_test1;
mod multiple_glob_test2;
src~
";
let dir = TmpDir::new();
let _src1 = dir.write_file("multiple_glob_test1.rs", src1);
let _src2 = dir.write_file("multiple_glob_test2.rs", src2);
let mut has_1 = false;
let mut has_2 = false;
let completions = get_all_completions(src, Some(dir));
for m in completions {
if m.matchstr == "src1fn" {
has_1 = true;
}
if m.matchstr == "src2fn" {
has_2 = true;
}
}
assert!(has_1 && has_2);
}
#[test]
fn single_import_shadows_glob_import() {
let src = "
use shadowed::*;
use shadower::Foo;
mod shadowed {
pub struct Foo;
}
mod shadower {
pub struct Foo;
}
fn main() {
Foo~;
}
";
let got = get_definition(src, None);
assert_eq!(got.matchstr, "Foo");
println!("{}", got.filepath.display());
println!("{:?}", got.point);
assert_eq!(got.coords, Some(Coordinate::new(10, 19)));
}
#[test]
fn follows_use_self() {
let src = "
use foo::use_self_test::{self, bar};
mod foo {
pub mod use_self_test {
pub fn bar() {}
}
}
use_s~
";
let completions = get_all_completions(src, None);
assert!(completions
.into_iter()
.any(|m| m.matchstr == "use_self_test"));
let src = "
use use_self_test::self;
mod use_self_test {
}
use_s~
";
let completions = get_all_completions(src, None);
assert!(completions
.into_iter()
.any(|m| m.matchstr == "use_self_test"));
}
#[test]
fn completes_mod_exactly_once() {
let src = "
mod sample {
pub struct Bar;
}
mod happy {
use sample;
fn do_things(bar: sampl~e::Bar) {
}
}
";
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "sample");
assert_eq!(got.mtype, MatchType::Module);
}
#[test]
fn completes_mod_and_local_with_same_name() {
let src = "
mod sample {
pub struct Bar;
}
mod happy {
use sample;
fn do_things(bar: sample::Bar) {
let sample = bar;
let other = sampl~e::Bar;
}
}
";
let got = get_all_completions(src, None);
assert_eq!(got.len(), 2);
assert_eq!(got[0].matchstr, "sample");
assert_eq!(got[1].matchstr, "sample");
}
#[test]
fn completes_out_of_order_mod_use_with_same_fn_name_as_mod() {
let src = "
use foo::foo;
mod foo {
pub fn foo() {}
}
fn main() {
f~
}";
let mut has_module = false;
let mut has_function = false;
let completions = get_all_completions(src, None);
for m in completions {
match (&*m.matchstr, m.mtype) {
("foo", MatchType::Module) => has_module = true,
("foo", MatchType::Function) => has_function = true,
_ => (),
}
}
assert!(has_module && has_function);
}
#[test]
fn ignores_self_referential_unresolved_import() {
let src = "use foo::foo;f~";
let completions = get_all_completions(src, None);
assert!(!completions.iter().any(|m| m.matchstr == "foo"));
}
#[test]
fn ignores_self_referential_unresolved_import_long() {
let src = "use foo::bar::foo;f~";
let completions = get_all_completions(src, None);
assert!(!completions.iter().any(|m| m.matchstr == "foo"));
}
#[test]
fn ignores_self_referential_unresolved_imports() {
let src = "
use foo::bar;
use bar::baz;
use baz::foo;
f~";
let completions = get_all_completions(src, None);
assert!(!completions.iter().any(|m| m.matchstr == "foo"));
}
#[test]
fn ignores_self_referential_unresolved_imports_across_modules() {
let src = "
use foo::bar;
mod foo {
pub use super::bar;
}
b~";
let completions = get_all_completions(src, None);
assert!(!completions.iter().any(|m| m.matchstr == "bar"));
}
#[test]
fn finds_external_mod_docs() {
let src1 = "// Copyright notice
//! The mods multiline
//! documentation
";
let src = "
mod external_mod;
use external_mod;
fn main() {
external_mod~
}
";
let dir = TmpDir::new();
let _src1 = dir.write_file("external_mod.rs", src1);
let got = get_one_completion(src, Some(dir));
assert_eq!("external_mod", got.matchstr);
assert_eq!("The mods multiline\ndocumentation", got.docs);
}
#[test]
fn finds_external_struct_docs() {
let src1 = "
/// Orange
/// juice
pub struct Apple {
pub a: u8,
}";
let src = "
use external_struct::Apple;
mod external_struct;
fn main() {
Apple~
}";
let dir = TmpDir::new();
let _src1 = dir.write_file("external_struct.rs", src1);
let got = get_one_completion(src, Some(dir));
assert_eq!("Apple", got.matchstr);
assert_eq!("Orange\njuice", got.docs);
}
#[test]
fn finds_external_fn_docs() {
let src1 = "
/// Orange
/// juice
pub fn apple() {
let x = 1;
}";
let src = "
use external_fn::apple;
mod external_fn;
fn main() {
apple~
}";
let dir = TmpDir::new();
let _src1 = dir.write_file("external_fn.rs", src1);
let got = get_one_completion(src, Some(dir));
assert_eq!("apple", got.matchstr);
assert_eq!("Orange\njuice", got.docs);
}
#[test]
fn keeps_newlines_in_external_mod_doc() {
let src1 = "// Copyright notice
//! The mods multiline documentation
//!
//! with an empty line
";
let src = "
mod external_mod;
use external_mod;
fn main() {
external_mod~
}
";
let dir = TmpDir::new();
let _src1 = dir.write_file("external_mod.rs", src1);
let got = get_one_completion(src, Some(dir));
assert_eq!("external_mod", got.matchstr);
assert_eq!(
"The mods multiline documentation\n\nwith an empty line",
got.docs
);
}
#[test]
fn always_get_all_doc_lines() {
let src = "
/// Orange
/// juice
pub fn apple() {
app~le()
}";
let got = get_only_completion(src, None);
assert_eq!("apple", got.matchstr);
assert_eq!("Orange\njuice", got.docs);
}
#[test]
fn find_complete_docs_with_parentheses_on_last_line() {
let src = "
/// Hello world
/// (quux)
pub fn foo() {}
pub fn bar() {
foo~()
}
";
let got = get_only_completion(src, None);
assert_eq!("foo", got.matchstr);
assert_eq!("Hello world\n(quux)", got.docs);
}
#[test]
fn completes_struct_field_via_assignment() {
let src = "
struct Point {
/// The first item.
first: f64,
second: f64
}
let var = Point {first: 35, second: 22};
var.f~
";
let got = get_one_completion(src, None);
assert_eq!(got.matchstr, "first");
assert_eq!("The first item.", got.docs);
}
#[test]
fn finds_defn_of_struct_field() {
let src = "
struct Point {
/// The first item.
first: f64,
second: f64
}
let var = Point {first: 35, second: 22};
var.f~irst
";
let got = get_definition(src, None);
assert_eq!(got.matchstr, "first");
assert_eq!("The first item.", got.docs);
}
#[test]
fn finds_impl_fn() {
let src = "
struct Foo;
impl Foo {
fn new() {}
}
Foo::n~ew();
";
let got = get_definition(src, None);
assert_eq!(got.matchstr, "new");
}
#[test]
fn follows_use_to_inline_mod() {
let src = "
use foo::myfn;
mod foo {
pub fn myfn() {}
}
fn main() {
m~yfn();
}
";
let got = get_definition(src, None);
assert_eq!(got.matchstr, "myfn");
}
#[test]
fn finds_enum() {
let src = "
enum MyEnum {
One, Two
}
fn myfn(e: M~yEnum) {}
";
let got = get_definition(src, None);
assert_eq!(got.matchstr, "MyEnum");
}
#[test]
fn finds_type() {
let src = "
type SpannedIdent = Spanned<Ident>
S~pannedIdent;
";
let got = get_definition(src, None);
assert_eq!(got.matchstr, "SpannedIdent");
}
#[test]
fn finds_trait() {
let src = "
pub trait MyTrait<E: Clone> {}
M~yTrait
";
let got = get_definition(src, None);
assert_eq!(got.matchstr, "MyTrait");
assert_eq!(got.contextstr, "pub trait MyTrait<E: Clone>");
}
#[test]
fn finds_macro() {
let src = "
macro_rules! my_macro {
() => {}
}
m~y_macro!();
";
let got = get_definition(src, None);
assert_eq!(got.matchstr, "my_macro!");
}
#[test]
fn finds_fn_arg() {
let src = "
fn myfn(myarg: &str) {
my~arg
}
";
let got = get_definition(src, None);
assert_eq!(got.matchstr, "myarg");
}
#[test]
fn finds_fn_arg_in_incomplete_fn() {
let src = "
fn myfn(myarg: &str) {
my~arg
";
let got = get_definition(src, None);
assert_eq!(got.matchstr, "myarg");
}
#[test]
fn finds_inline_fn() {
let src = "
#[inline]
fn contains<'a>(&needle: &'a str)
-> bool {
}
conta~ins();
";
let got = get_definition(src, None);
assert_eq!(got.matchstr, "contains");
assert_eq!(got.contextstr, "fn contains<'a>(&needle: &'a str) -> bool");
}
#[test]
fn follows_self_use() {
let modsrc = "
pub use self::src4::{Foo,myfn};
pub mod src4;
";
let src4 = "
struct Foo;
pub fn myfn() {}
";
let src = "
use mymod::{Foo,myfn};
pub mod mymod;
fn main() {
my~fn();
}
";
let dir = TmpDir::new();
let mymod = dir.nested_dir("mymod");
let _mod = mymod.write_file("mod.rs", modsrc);
let src4file = mymod.write_file("src4.rs", src4);
let got = get_definition(src, Some(dir));
assert_eq!(got.matchstr, "myfn");
assert_eq!(src4file.path(), got.filepath);
assert_eq!(28, got.point.0);
}
#[test]
fn finds_nested_submodule_file() {
let sub3src = "
pub fn myfn() {}
";
let src = "
pub mod sub1 {
pub mod sub2 {
pub mod sub3;
}
}
sub1::sub2::sub3::m~yfn();
";
let dir = TmpDir::new();
let sub1 = dir.nested_dir("sub1");
let sub2 = sub1.nested_dir("sub2");
let src3 = sub2.write_file("sub3.rs", sub3src);
let got = get_definition(src, Some(dir));
assert_eq!(got.matchstr, "myfn");
assert_eq!(src3.path(), got.filepath);
}
#[test]
fn follows_super_in_sub_module() {
let src = "
pub fn iamhere() { }
mod inner { pub use super::ia~mhere; }
";
let got = get_definition(src, None);
assert_eq!("iamhere", got.matchstr);
}
#[test]
fn follows_super_super_in_sub_sub_module() {
let src = "
pub fn iamhere() { }
mod inner { mod inner { pub use super::super::ia~mhere; } }
";
let got = get_definition(src, None);
assert_eq!("iamhere", got.matchstr);
}
#[test]
fn follows_super_in_local_sub_module() {
let src = "
mod inner {
pub fn iamhere() { }
mod inner2 { pub use super::iamh~ere; }
}
";
let got = get_definition(src, None);
assert_eq!("iamhere", got.matchstr);
}
#[test]
fn follows_use_to_impl() {
let modsrc = "
pub struct Foo;
impl Foo { // impl doesn't need to be 'pub'
pub fn new() -> Foo {
Foo
}
}
";
let src = "
use mymod::{Foo};
mod mymod;
fn main() {
Foo::n~ew();
}
";
let dir = TmpDir::new();
let mod_path = dir.write_file("mymod.rs", modsrc);
let got = get_definition(src, Some(dir));
assert_eq!(got.matchstr, "new");
assert_eq!(90, got.point.0);
assert_eq!(mod_path.path(), got.filepath);
}
#[test]
fn finds_templated_impl_fn() {
let src = "
struct Foo<T>;
impl<T> Foo<T> {
fn new() {}
}
Foo::n~ew();
";
let got = get_definition(src, None);
assert_eq!(got.matchstr, "new");
}
#[test]
fn follows_fn_to_method() {
let src = "
struct Foo<T>;
impl<T> Foo<T> {
fn new() -> Foo<T> {}
fn mymethod(&self) {}
}
fn main() {
let v = Foo::new();
v.my~
}
";
let got = get_one_completion(src, None);
assert_eq!("mymethod", got.matchstr);
}
#[test]
fn simple_struct_contextstr() {
let src = "
struct Foo<T>;
fn myfn() {
let x: Foo~
}
";
let got = get_one_completion(src, None);
assert_eq!(got.contextstr, "struct Foo<T>;");
}
#[test]
fn struct_contextstr() {
let src = "
struct
Foo<T> {
pub fn foo1();
}
fn myfn() {
let x: Foo~
}
";
let got = get_one_completion(src, None);
assert_eq!(got.contextstr, "struct Foo<T>");
}
#[test]
fn follows_arg_to_method() {
let src = "
struct Foo<T>;
impl<T> Foo<T> {
fn mymethod(&self) {}
}
fn myfn(v: &Foo) {
v.my~
}
";
let got = get_one_completion(src, None);
assert_eq!("mymethod", got.matchstr);
}
#[test]
fn follows_arg_to_enum_method() {
let src = "
enum Foo<T> {
EnumVal
}
impl<T> Foo<T> {
fn mymethod(&self) {}
}
fn myfn(v: &Foo) {
v.my~
}
";
let got = get_one_completion(src, None);
assert_eq!("mymethod", got.matchstr);
}
#[test]
fn finds_enum_static_method() {
let src = "
enum Foo {
Bar,
Baz
}
impl Foo {
pub fn make_baz() -> Self {
Foo::Baz
}
}
fn myfn() -> Foo {
Foo::ma~ke_baz()
}
";
let got = get_only_completion(src, None);
assert_eq!("make_baz", got.matchstr);
assert_eq!(MatchType::Function, got.mtype);
}
#[test]
fn finds_enum_variants_first() {
let src = "
enum Foo {
Bar,
Baz
}
impl Foo {
pub fn amazing() -> Self {
Foo::Baz
}
}
fn myfn() -> Foo {
Foo::~Bar
}
";
let got = get_all_completions(src, None);
assert_eq!(3, got.len());
assert_eq!("Bar", got[0].matchstr);
assert_eq!("Baz", got[1].matchstr);
assert_eq!("amazing", got[2].matchstr);
}
#[test]
fn follows_let_method_call() {
let src = "
struct Foo;
struct Bar;
impl Foo {
fn mymethod(&self) -> Bar {}
}
impl Bar {
fn mybarmethod(&self) -> Bar {}
}
fn myfn(v: &Foo) {
let f = v.mymethod();
f.my~
}
";
let got = get_one_completion(src, None);
assert_eq!("mybarmethod", got.matchstr);
}
#[test]
fn follows_chained_method_call() {
let src = "
struct Foo;
struct Bar;
impl Foo {
fn mymethod(&self) -> Bar {}
}
impl Bar {
fn mybarmethod(&self) -> Bar {}
}
fn myfn(v: &Foo) {
v.mymethod().my~
}
";
let got = get_one_completion(src, None);
assert_eq!("mybarmethod", got.matchstr);
}
#[test]
fn follows_chained_method_call_returning_self() {
let src = "
struct Foo;
impl Foo {
fn mymethod(&self) {}
fn new() -> Self {}
}
Foo::new().~
";
let got = get_only_completion(src, None);
assert_eq!("mymethod", got.matchstr);
}
#[test]
fn follows_chained_method_call_on_new_line() {
let src = "
struct Foo;
impl Foo {
fn mymethod(&self) {}
fn new() -> Self {}
}
Foo::
// comment
new()
.~
";
let got = get_only_completion(src, None);
assert_eq!("mymethod", got.matchstr);
}
#[test]
fn discards_inner_fns() {
let src = "
struct Foo;
impl<T> Foo<T> {
fn mymethod(&self) -> Bar {
fn inner() {
}
}
}
fn myfn(v: &Foo) {
v.i~
}
";
let got = get_all_completions(src, None);
assert!(got.is_empty(), "should not match inner function");
}
#[test]
fn differentiates_type_and_value_namespaces() {
let src = "
enum MyEnum{ Foo }
struct Foo;
impl Foo { pub fn new() -> Foo {} }
let l = Foo::n~ew();
";
let got = get_definition(src, None);
println!("{}", got.matchstr);
println!("{:?}", got.mtype);
assert_eq!("new", got.matchstr);
}
#[test]
fn finds_trait_method() {
let src = "
pub trait MyTrait {
fn op(self);
fn trait_method(self){}
}
struct Foo;
impl MyTrait for Foo {
fn op(self) {
self.trait~_method();
}
}";
let got = get_definition(src, None);
assert_eq!("trait_method", got.matchstr);
}
#[test]
fn finds_field_type() {
let src = "
pub struct Blah { subfield: uint }
pub struct Foo {
myfield : Blah
}
let f = Foo{ myfield: Blah { subfield: 3}};
f.myfield.subfi~eld
";
let got = get_definition(src, None);
assert_eq!("subfield", got.matchstr);
}
#[test]
fn finds_tuple_struct_field_type() {
let src = "
pub struct Blah(Foo);
pub struct Foo {
bar: usize,
}
let f = Blah(Foo { bar: 3 });
f.0.b~ar
";
let got = get_definition(src, None);
assert_eq!("bar", got.matchstr);
}
#[test]
fn finds_a_generic_retval_from_a_function() {
let src = "
pub struct Blah { subfield: uint }
pub struct Foo<T> {
myfield: T
}
fn myfn() -> Foo<Blah> {}
myfn().myfield.subfi~eld
";
let got = get_definition(src, None);
assert_eq!("subfield", got.matchstr);
}
#[test]
fn handles_an_enum_option_style_return_type() {
let src = "
pub struct Blah { subfield: uint }
pub enum MyOption<T> {
MySome(T),
MyNone
}
impl MyOption<T> {
pub fn unwrap(&self) -> T {}
}
fn myfn() -> MyOption<Blah> {}
let s = myfn();
s.unwrap().sub~field
";
let got = get_definition(src, None);
assert_eq!("subfield", got.matchstr);
}
#[test]
fn finds_definition_of_const() {
let src = "
pub const MYCONST:uint = 3;
MYC~ONST
";
let got = get_definition(src, None);
assert_eq!("MYCONST", got.matchstr);
}
#[test]
fn finds_definition_of_static() {
let src = "
pub static MYSTATIC:uint = 3;
MYS~TATIC
";
let got = get_definition(src, None);
assert_eq!("MYSTATIC", got.matchstr);
}
#[test]
fn handles_dotdot_before_searchstr() {
let src = "
static MYLEN:uint = 30;
let f = [0i32, ..M~YLEN];
";
let got = get_definition(src, None);
assert_eq!("MYLEN", got.matchstr);
}
#[test]
#[ignore]
fn finds_definition_of_lambda_argument() {
let src = "
fn myfn(&|int|) {}
myfn(|a|~a+3);
";
let got = get_definition(src, None);
assert_eq!("a", got.matchstr);
}
#[test]
fn finds_definition_of_let_tuple() {
let src = "
let (a, b) = (2,3);
~a
";
let got = get_definition(src, None);
assert_eq!("a", got.matchstr);
}
#[test]
fn finds_type_of_tuple_member_via_let_type() {
let src = "
pub struct Blah { subfield: uint }
let (a, b): (uint, Blah);
b.subfi~eld
";
let got = get_definition(src, None);
assert_eq!("subfield", got.matchstr);
}
#[test]
fn finds_type_of_tuple_member_via_let_expr() {
let src = "
pub struct Blah { subfield: uint }
let (a, b) = (3, Blah{subfield:3});
b.subfi~eld
";
let got = get_definition(src, None);
assert_eq!("subfield", got.matchstr);
}
#[test]
fn finds_type_of_struct_member_via_let_expr() {
let src = "
pub struct Blah { subfield: uint }
pub struct Foo { field: Blah }
let Foo { ref field } = Foo { field: Blah { subfield: 1 }};
field.subfi~eld
";
let got = get_definition(src, None);
assert_eq!("subfield", got.matchstr);
}
#[test]
fn finds_type_of_tuple_member_via_fn_retval() {
let src = "
pub struct Blah { subfield: uint }
fn myfn() -> (uint, Blah) {}
let (a, b) = myfn();
b.subfi~eld
";
let got = get_definition(src, None);
assert_eq!("subfield", got.matchstr);
}
#[test]
fn finds_type_of_tuple_member_in_fn_arg() {
let src = "
pub struct Blah { subfield: uint }
fn myfn(a: uint, (b, c): (uint, Blah)) {
c.s~ubfield
}
";
let got = get_definition(src, None);
assert_eq!("subfield", got.matchstr);
}
#[test]
fn finds_namespaced_enum_variant() {
let src = "
pub enum Blah { MyVariant }
Blah::MyVa~riant
";
let got = get_definition(src, None);
assert_eq!("MyVariant", got.matchstr);
}
#[test]
fn finds_glob_imported_enum_variant() {
let src = "
use self::Blah::*;
pub enum Blah { MyVariant, MyVariant2 }
MyVa~riant
";
let got = get_definition(src, None);
assert_eq!("MyVariant", got.matchstr);
}
#[test]
fn finds_enum_variant_through_recursive_glob_imports() {
let src = "
use foo::*;
use Bar::*;
mod foo {
pub enum Bar { MyVariant, MyVariant2 }
}
MyVa~riant
";
let got = get_definition(src, None);
assert_eq!("MyVariant", got.matchstr);
}
#[test]
#[ignore]
fn uses_generic_arg_to_resolve_trait_method() {
let src = "
pub trait MyTrait {
fn trait_method(self){}
}
pub fn doit<T:MyTrait>(stream: &mut T) {
T.trait_met~hod
}
";
let got = get_definition(src, None);
assert_eq!("trait_method", got.matchstr);
}
#[test]
fn destructures_a_tuplestruct() {
let src = "
pub struct Blah { subfield: uint }
pub struct TupleStruct(Blah);
let TupleStruct(var) = TupleStruct(Blah{subfield:35});
var.su~bfield
";
let got = get_definition(src, None);
assert_eq!("subfield", got.matchstr);
}
#[test]
fn destructures_a_tuplestruct_with_generic_arg() {
let src = "
pub struct Blah { subfield: uint }
pub struct TupleStruct<T>(T);
let a : TupleStruct<Blah> = TupleStruct(Blah{subfield:35});
let TupleStruct(var) = a;
var.su~bfield
";
let got = get_definition(src, None);
assert_eq!("subfield", got.matchstr);
}
#[test]
fn finds_if_let_ident_defn() {
let src = "
if let MyOption(myvar) = myvar {
myvar~
}
";
let got = get_only_completion(src, None);
assert_eq!("myvar", got.matchstr);
}
#[test]
fn doesnt_find_if_let_if_not_in_the_subscope() {
let src = "
let myvar = 3u32;
if let MyOption(myvar) = myvar {
myvar
}
my~var
";
let got = get_definition(src, None);
assert_eq!("myvar", got.matchstr);
assert_eq!(9, got.point.0);
}
#[test]
fn finds_rebound_var_in_iflet() {
let src = "
let o: MyOption<Blah>;
if let MyOption::MySome(o) = o {
~o
}
";
let got = get_definition(src, None);
assert_eq!(56, got.point.0);
}
#[test]
fn handles_if_let() {
let src = "
pub struct Blah { subfield: uint }
pub enum MyOption<T> {
MySome(T),
MyNone
}
let o: MyOption<Blah>;
if let MyOption::MySome(a) = o {
a.sub~field
}
";
let got = get_definition(src, None);
assert_eq!("subfield", got.matchstr);
}
#[test]
fn handles_if_let_as_expression() {
let src = "
pub struct Blah { subfield: uint }
pub enum MyOption<T> {
MySome(T),
MyNone
}
let o: MyOption<Blah>;
let foo = if let MyOption::MySome(a) = o { // iflet is an expression
a.sub~field
};
";
let got = get_definition(src, None);
assert_eq!("subfield", got.matchstr);
}
#[test]
fn finds_match_arm_var() {
let src = "
match foo {
Some(a) => ~a
";
let got = get_definition(src, None);
assert_eq!("a", got.matchstr);
}
#[test]
fn finds_match_arm_var_in_scope() {
let src = "
match foo {
Some(a) => { ~a }
";
let got = get_definition(src, None);
assert_eq!("a", got.matchstr);
}
#[test]
fn finds_match_arm_enum() {
let src = "
enum MyEnum {
Foo,
Bar
}
match foo {
MyEnum::Foo~ => 1,
MyEnum::Bar => 2
";
let got = get_definition(src, None);
assert_eq!("Foo", got.matchstr);
}
#[test]
fn finds_match_arm_var_with_nested_match() {
let src = "
match foo {
bar => {something}
Some(a) => {
let b = match blah {
None => ()
}
~a
}
";
let got = get_definition(src, None);
assert_eq!("a", got.matchstr);
}
#[test]
fn gets_type_via_match_arm() {
let src = "
pub struct Blah { subfield: uint }
pub enum MyOption<T> {
MySome(T),
MyNone
}
let o: MyOption<Blah>;
match o {
MyOption::MySome(a) => a.subfi~eld
";
let got = get_definition(src, None);
assert_eq!("subfield", got.matchstr);
}
#[test]
fn handles_default_arm() {
let src = "
let o: MyOption<Blah>;
match o {
Foo => { }
_ => ~o
}
";
let got = get_definition(src, None);
assert_eq!("o", got.matchstr);
assert_eq!(9, got.point.0);
}
#[test]
fn doesnt_match_rhs_of_let_in_same_stmt() {
let src = "
let a = 3; // <--- should match this 'a'
let a = ~a + 2; // not this one
";
let got = get_definition(src, None);
assert_eq!("a", got.matchstr);
assert_eq!(9, got.point.0);
}
#[test]
fn finds_unsafe_fn() {
let src = "
unsafe fn foo() {}
fn bar() {
f~oo()
}
";
let got = get_definition(src, None);
assert_eq!(got.matchstr, "foo");
assert_eq!(got.point.0, 15);
}
#[test]
fn completes_methods_on_deref_type() {
let modsrc = "
pub struct B {
c: C,
}
pub struct C;
pub trait GetOne {
fn one(&self) -> u32 { 1u32 }
}
impl GetOne for C {}
impl Deref for B {
type Target = C;
fn deref(&self) -> &C {
&self.c
}
}
";
let src = "
mod mymod;
use mymod::{B, C, GetOne};
fn main() {
let b: B = B{ c: C};
b.o~
}
";
let dir = TmpDir::new();
let _mymod = dir.write_file("mymod.rs", modsrc);
let got = get_one_completion(src, Some(dir));
assert_eq!(got.matchstr, "one");
}
#[test]
fn finds_type_of_struct_field_reference() {
let src = "
struct Dolor { sit: u8 }
struct Lorem<'a> { ipsum: &'a Dolor }
impl<'a> Lorem<'a> {
fn sit(&self) {
let _ = self.ipsum.s~it;
}
}
";
let got = get_definition(src, None);
assert_eq!("sit", got.matchstr);
}
#[test]
fn finds_self_param_when_fn_has_generic_closure_arg() {
let src = "
struct MyOption;
impl MyOption {
// needs to find 'self' here to see it is a method
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> {
}
}
let a: MyOption;
a.~map()
";
let got = get_definition(src, None);
assert_eq!("map", got.matchstr);
}
#[test]
fn completes_static_method_containing_self() {
let src = "
struct X;
impl X {
fn foo<T>(_: T) {
struct Y;
impl Y {
fn bar(&self) {}
}
}
}
X::~foo(0);
";
let got = get_definition(src, None);
assert_eq!("foo", got.matchstr);
}
#[test]
fn completes_methods_on_deref_generic_type() {
let modsrc = "
pub struct B<T> {
c: T,
}
pub struct C;
pub trait GetOne {
fn one(&self) -> u32 { 1u32 }
}
impl GetOne for C {}
impl<T> Deref for B<T> {
type Target = T;
fn deref(&self) -> &T {
&self.c
}
}
";
let src = "
mod mymod;
use mymod::{B, C, GetOne};
fn main() {
let b: B<C> = B{ c: C};
b.o~
}
";
let dir = TmpDir::new();
let _mymod = dir.write_file("mymod.rs", modsrc);
let got = get_one_completion(src, Some(dir));
assert_eq!(got.matchstr, "one");
}
#[test]
fn completes_multiple_use_bracket() {
let modfile = "
pub struct StarWars {
pub Vadar: u8,
};
pub struct StarTrek {
pub Spock: u8,
};";
let srcwo = "
mod modfile1;
use modfile1::~S
";
let srcwi = "
mod modfile1;
use modfile1::{~S
";
let dir = TmpDir::new();
let _mod1 = dir.write_file("modfile1.rs", modfile);
let gotwo = get_all_completions(srcwo, Some(dir));
let dir = TmpDir::new();
let _mod1 = dir.write_file("modfile1.rs", modfile);
let gotwi = get_all_completions(srcwi, Some(dir));
assert_eq!(gotwo.len(), gotwi.len());
for (wo, wi) in gotwo.into_iter().zip(gotwi) {
assert_eq!(wo.matchstr, wi.matchstr);
}
}
#[test]
fn completes_multiple_use_comma() {
let modfile = "
pub struct StarWars {
pub Kenobi: u8,
};
pub struct StarTrek {
pub Spock: u8,
};";
let srcwo = "
mod modfile2;
use modfile2::~S
";
let srcwi = "
mod modfile2;
use modfile2::{StarWars, ~S
";
let dir = TmpDir::new();
let _mod2 = dir.write_file("modfile2.rs", modfile);
let gotwo = get_all_completions(srcwo, Some(dir));
let dir = TmpDir::new();
let _mod2 = dir.write_file("modfile2.rs", modfile);
let gotwi = get_all_completions(srcwi, Some(dir));
assert_eq!(gotwo.len(), gotwi.len());
for (wo, wi) in gotwo.into_iter().zip(gotwi) {
assert_eq!(wo.matchstr, wi.matchstr);
}
}
#[test]
fn completes_multiple_use_newline() {
let src = "
mod foo {
pub struct Bar;
pub fn myfn() {}
}
fn main() {
use foo::{
Bar,
my~fn
};
myfn();
}
";
let got = get_all_completions(src, None);
assert_eq!(got.len(), 1);
assert_eq!(got[0].matchstr, "myfn");
}
#[test]
fn completes_trait_methods_in_trait_impl() {
let src = "
mod sub {
pub trait Trait {
fn traitf() -> bool;
fn traitm(&self) -> bool;
}
pub struct Foo(bool);
impl Trait for Foo {
fn traitf() -> bool { false }
fn traitm~(&self) -> bool { true }
}
}
";
let got = get_one_completion(src, None);
assert_eq!(got.matchstr, "traitm");
assert_eq!(got.contextstr, "fn traitm(&self) -> bool");
}
#[test]
fn completes_trait_fn_in_trait_impl() {
let src = "
mod sub {
pub trait Trait {
fn traitf() -> bool;
fn traitm(&self) -> bool;
}
pub struct Foo(bool);
impl Trait for Foo {
fn traitf~() -> bool { false }
fn traitm(&self) -> bool { true }
}
}
";
let got = get_one_completion(src, None);
assert_eq!(got.matchstr, "traitf");
assert_eq!(got.contextstr, "fn traitf() -> bool");
}
#[test]
fn completes_optional_trait_fn_in_trait_impl() {
let src = "
mod sub {
pub trait Trait {
fn traitf() -> bool {
true
}
fn traitm(&self) -> bool;
}
pub struct Foo(bool);
impl Trait for Foo {
fn traitf~() -> bool { false }
fn traitm(&self) -> bool { true }
}
}
";
let got = get_one_completion(src, None);
assert_eq!(got.matchstr, "traitf");
assert_eq!(got.contextstr, "fn traitf() -> bool");
}
#[test]
fn finds_mod_with_same_name_as_trait_method_in_sig() {
let src = "
mod sub {
pub struct Formatter;
pub trait Fmt {
fn sub(&self, f: &Formatter);
}
}
struct Sample;
impl sub::Fmt for Sample {
fn sub(&self, f: &sub::Fo~rmatter) {
}
}
";
let got = get_one_completion(src, None);
assert_eq!(got.matchstr, "Formatter");
}
#[test]
fn finds_mod_with_same_name_as_trait_method_in_body() {
let src = "
mod sub {
pub struct Formatter;
pub trait Fmt {
fn sub(&self) -> sub::Formatter;
}
}
struct Sample;
impl sub::Fmt for Sample {
fn sub(&self) -> sub::Formatter {
sub::Fo~rmatter
}
}
";
let got = get_one_completion(src, None);
assert_eq!(got.matchstr, "Formatter");
}
#[test]
fn finds_fmt_formatter() {
let src = r#"
use std::fmt;
struct Foo;
impl fmt::Display for Foo {
fn fmt(&self, f: &mut fmt::Formatt~er) -> fmt::Result {
write!(f, "Hello")
}
}
"#;
let got = get_all_completions(src, None);
assert!(!got.is_empty());
assert_eq!(got[0].matchstr, "Formatter");
}
#[test]
fn finds_fmt_method() {
let src = r#"
use std::fmt;
struct Foo;
impl fmt::Display for Foo {
fn fm~t(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Hello")
}
}
"#;
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "fmt");
assert_eq!(got.mtype, MatchType::Function);
}
#[test]
fn finds_field_with_same_name_as_method() {
let src = "
struct Foo { same_name: uint }
impl Foo { fn same_name(&self){} }
let a: Foo;
a.same_na~me;
";
let got = get_definition(src, None);
assert_eq!("same_name", got.matchstr);
assert_eq!(MatchType::StructField, got.mtype);
}
#[test]
fn finds_method_with_same_name_as_field() {
let src = "
struct Foo { same_name: uint }
impl Foo { fn same_name(&self){}}
let a: Foo;
a.same_na~me();
";
let got = get_definition(src, None);
assert_eq!("same_name", got.matchstr);
assert_eq!(MatchType::Function, got.mtype);
}
#[test]
fn finds_self() {
let src = "
struct Foo;
impl Foo {
fn foo() {
Se~lf
}
}
";
let got = get_definition(src, None);
assert_eq!("Foo", got.matchstr);
}
#[test]
fn finds_self_referenced_functions() {
let src = "
struct Foo;
impl Foo {
fn foo() {
Self::myfun~ction
}
fn myfunction() {}
}
";
let got = get_definition(src, None);
assert_eq!("myfunction", got.matchstr);
}
#[test]
fn closure_bracket_scope() {
let src = "
fn main() {
let y = Some(5);
y.map(| x | { x~ } );
}
";
let got = get_definition(src, None);
assert_eq!("x", got.matchstr);
assert_eq!("| x |", got.contextstr);
}
#[test]
fn closure_bracket_scope_multiple_args() {
let src = "
fn main() {
let y = Some(5);
y.map(| x,y,z,u | { x~ } );
}
";
let got = get_definition(src, None);
assert_eq!("x", got.matchstr);
assert_eq!("| x,y,z,u |", got.contextstr);
}
#[test]
fn closure_bracket_scope_multiple_args_different_definition() {
let src = "
fn main() {
let y = Some(5);
y.map(| x,y,z,u | { z~ } );
}
";
let got = get_definition(src, None);
assert_eq!("z", got.matchstr);
assert_eq!("| x,y,z,u |", got.contextstr);
}
#[test]
fn closure_bracket_scope_overwrite() {
let src = "
fn main() {
let y = Some(5);
y.map(| x, y | { y~ } );
}
";
let got = get_definition(src, None);
assert_eq!("y", got.matchstr);
assert_eq!("| x, y |", got.contextstr);
}
#[test]
fn closure_bracket_scope_with_types() {
let src = "
fn main() {
let y = Some(5);
y.map(| x: i32, y: String | { y~ } );
}
";
let got = get_definition(src, None);
assert_eq!("y", got.matchstr);
assert_eq!("| x: i32, y: String |", got.contextstr);
}
#[test]
fn closure_bracket_scope_find_outside() {
let src = "
fn main() {
let y = Some(5);
y.map(| x: i32 | { y~ } );
}
";
let got = get_definition(src, None);
assert_eq!("y", got.matchstr);
assert_eq!("let y = Some(5);", got.contextstr);
}
#[test]
fn closure_scope() {
let src = "
fn main() {
let y = Some(5);
y.map(| x | x~ );
}
";
let got = get_definition(src, None);
assert_eq!("x", got.matchstr);
assert_eq!("| x |", got.contextstr);
}
#[test]
fn closure_scope_multiple_args() {
let src = "
fn main() {
let y = Some(5);
y.map(| x,y,z,u | x~ );
}
";
let got = get_definition(src, None);
assert_eq!("x", got.matchstr);
assert_eq!("| x,y,z,u |", got.contextstr);
}
#[test]
fn closure_scope_multiple_args_different_definition() {
let src = "
fn main() {
let y = Some(5);
y.map(| x,y,z,u | z~ );
}
";
let got = get_definition(src, None);
assert_eq!("z", got.matchstr);
assert_eq!("| x,y,z,u |", got.contextstr);
}
#[test]
fn closure_scope_overwrite() {
let src = "
fn main() {
let y = Some(5);
y.map(| x, y | y~ );
}
";
let got = get_definition(src, None);
assert_eq!("y", got.matchstr);
assert_eq!("| x, y |", got.contextstr);
}
#[test]
fn closure_scope_with_types() {
let src = "
fn main() {
let y = Some(5);
y.map(| x: i32, y: String | y~ );
}
";
let got = get_definition(src, None);
assert_eq!("y", got.matchstr);
assert_eq!("| x: i32, y: String |", got.contextstr);
}
#[test]
fn finds_impl_with_bang() {
let src = "
struct Foo;
impl Foo {
fn invert(&self, b: bool) -> bool { !b }
fn tst(&self) -> bool {
self.inv~ert(false)
}
";
let got = get_definition(src, None);
assert_eq!("invert", got.matchstr);
}
#[test]
fn ignores_impl_macro() {
let src = "
struct Foo;
impl!(Foo);
impl Foo {
fn tst(&self) -> bool {
self.ts~t()
}
";
let got = get_definition(src, None);
assert_eq!("tst", got.matchstr);
}
#[test]
fn closure_scope_dont_match_type_annotations() {
let src = "
struct Foo;
fn main() {
let y = Some(Foo);
y.map(|x: Foo| Fo~o);
}
";
let got = get_definition(src, None);
println!("{:?}", got);
assert!(got.mtype.is_struct());
assert_eq!(2, got.coords.unwrap().row.0);
}
#[test]
#[should_panic]
fn closure_scope_dont_match_bitwise_or() {
let src = "
fn foo() {
i~
}
fn bar() {
let i = 0;
let x = 0 | i;
}
fn baz() {
// 1 || 2;
}
";
let got = get_definition(src, None);
println!("Unexpectedly found definition: {:?}", got);
}
#[test]
fn closure_scope_find_outside() {
let src = "
fn main() {
let y = Some(5);
y.map(| x: i32 | y~ );
}
";
let got = get_definition(src, None);
assert_eq!("y", got.matchstr);
assert_eq!("let y = Some(5);", got.contextstr);
}
#[test]
fn closure_scope_with_newlines() {
let src = "
fn main() {
let y = Some(5);
y.map(|
x: i32
| x~ );
}
";
let got = get_definition(src, None);
assert_eq!("x", got.matchstr);
assert_eq!(
"|
x: i32
|",
got.contextstr
);
}
#[test]
fn closure_bracket_scope_with_newlines() {
let src = "
fn main() {
let y = Some(5);
y.map(|
x: i32
| {x~} );
}
";
let got = get_definition(src, None);
assert_eq!("x", got.matchstr);
assert_eq!(
"|
x: i32
|",
got.contextstr
);
}
#[test]
fn closure_scope_nested() {
let src = "
fn main() {
let y = Some(5);
y.map(| x: i32 | y.map(|z| z~) );
}
";
let got = get_definition(src, None);
assert_eq!("z", got.matchstr);
assert_eq!("|z|", got.contextstr);
}
#[test]
fn closure_bracket_scope_nested() {
let src = "
fn main() {
let y = Some(5);
y.map(| x: i32 | { y.map(|z| { z~ }) });
}
";
let got = get_definition(src, None);
assert_eq!("z", got.matchstr);
assert_eq!("|z|", got.contextstr);
}
#[test]
fn closure_scope_nested_math_outside() {
let src = "
fn main() {
let y = Some(5);
y.map(| x: i32 | y.map(|z| x~) );
}
";
let got = get_definition(src, None);
assert_eq!("x", got.matchstr);
assert_eq!("| x: i32 |", got.contextstr);
}
#[test]
fn closure_bracket_scope_nested_match_outside() {
let src = "
fn main() {
let y = Some(5);
y.map(| x: i32 | { y.map(|z| { x~ }) });
}
";
let got = get_definition(src, None);
assert_eq!("x", got.matchstr);
assert_eq!("| x: i32 |", got.contextstr);
}
#[test]
fn closure_dont_detect_normal_pipes() {
let src = "
enum Fruit {
Apple = 1,
}
fn foo(ty: Fruit) -> bool {
(1 as u8 | Fruit~::Apple as u8) == Fruit::Apple as u8
}
fn bar(ty: Fruit) -> bool {
match ty {
Fruit::Apple |
Fruit::Apple => {
false
}
}
}
";
let got = get_definition(src, None);
assert_eq!("Fruit", got.matchstr);
assert!(got.mtype.is_enum());
}
#[test]
fn closure_test_curly_brackets_in_args() {
let src = "
struct Foo {
bar: u16
}
fn example() -> Result<Foo, ()> {
Ok(Foo { bar: 10 })
}
fn main() {
example().and_then(|Foo { bar }| { println!(\"{}\", bar~); Ok(()) });
}
";
let got = get_definition(src, None);
assert_eq!("bar", got.matchstr);
assert_eq!("|Foo { bar }|", got.contextstr);
}
#[test]
fn closure_test_multiple_curly_brackets_in_args() {
let src = "
struct Foo {
bar: u16
}
fn example() -> Result<Foo, ()> {
Ok(Foo { bar: 10 })
}
fn main() {
example().and_then(|Foo { bar }, Foo { ex }, Foo { b }| { println!(\"{}\", bar~); Ok(()) });
}
";
let got = get_definition(src, None);
assert_eq!("bar", got.matchstr);
assert_eq!("|Foo { bar }, Foo { ex }, Foo { b }|", got.contextstr);
}
#[test]
fn crate_restricted_fn_completes() {
let src = r#"
pub(crate) fn do_stuff() {
println!("Hello");
}
fn more_stuff() {
do_~stuff();
}
"#;
let got = get_all_completions(src, None);
assert_eq!(1, got.len());
assert_eq!("do_stuff", got[0].matchstr);
}
#[test]
fn mod_restricted_fn_completes() {
let src = r#"
pub(in some::place_where) fn do_stuff() {
println!("Hello");
}
fn more_stuff() {
do_~stuff();
}
"#;
let got = get_all_completions(src, None);
assert_eq!(1, got.len());
assert_eq!("do_stuff", got[0].matchstr);
}
#[test]
fn finds_definition_of_fn_arg() {
let src = r#"
pub fn say_hello(name: String) {
println!("{}", nam~e);
}
"#;
let got = get_definition(src, None);
assert_eq!(got.matchstr, "name");
}
#[test]
fn finds_definition_of_crate_restricted_fn_arg() {
let src = r#"
pub(crate) fn say_hello(name: String) {
println!("{}", nam~e);
}
"#;
let got = get_definition(src, None);
assert_eq!(got.matchstr, "name");
}
#[test]
#[ignore]
fn finds_definition_of_mod_restricted_fn_arg() {
let src = r#"
pub(in foo) fn say_hello(name: String) {
println!("{}", nam~e);
}
"#;
let got = get_definition(src, None);
assert_eq!(got.matchstr, "name");
}
#[test]
fn finds_definition_of_super_restricted_fn() {
let src = r#"
pub(super) fn do_stuff() {
println!("Hello");
}
fn more_stuff() {
do_~stuff();
}
"#;
let got = get_definition(src, None);
assert_eq!("do_stuff", got.matchstr);
}
#[test]
fn crate_restricted_struct_completes() {
let src = r#"
mod codegen {
pub(crate) struct Foo {
pub bar: String,
}
fn stuff(f: Foo) -> String {
f.b~ar
}
}
"#;
let got = get_all_completions(src, None);
assert_eq!(1, got.len());
assert_eq!("bar", got[0].matchstr);
}
#[test]
fn crate_restricted_named_struct_field_completes() {
let src = r#"
mod codegen {
pub struct Foo {
pub(crate) bar: String,
}
fn stuff(f: Foo) -> String {
f.b~ar
}
}
"#;
let got = get_all_completions(src, None);
assert_eq!(1, got.len());
assert_eq!("bar", got[0].matchstr);
}
#[test]
fn crate_restricted_static_method_completes() {
let src = r#"
mod codegen {
pub struct Foo {
pub bar: String,
}
impl Foo {
pub(crate) fn with_bar(b: String) -> Self {
Foo { bar: b }
}
}
fn stuff() -> String {
Foo::wi~th_bar("Hello".to_string()).bar
}
}
"#;
let got = get_all_completions(src, None);
assert_eq!(1, got.len());
assert_eq!("with_bar", got[0].matchstr);
}
#[test]
fn crate_restricted_impl_method_completes() {
let src = r#"
mod codegen {
pub struct Foo {
bar: String,
}
impl Foo {
pub(crate) fn get_bar(&self) -> &str {
&self.bar
}
}
fn stuff(f: Foo) -> String {
f.ge~t_bar().clone()
}
}
"#;
let got = get_all_completions(src, None);
assert_eq!(1, got.len());
assert_eq!("get_bar", got[0].matchstr);
}
#[test]
#[ignore]
fn mod_restricted_struct_completes() {
let src = r#"
mod codegen {
pub(in codegen) struct Foo {
pub bar: String,
}
fn stuff(f: Foo) -> String {
f.b~ar
}
}
"#;
let got = get_all_completions(src, None);
assert_eq!(1, got.len());
assert_eq!("bar", got[0].matchstr);
}
#[test]
fn completes_for_global_path_in_fn_return() {
let src = "
mod bar {
pub struct Foo;
}
mod baz {
fn foo() -> ::bar::F~oo {
Foo
}
}
fn main() {}
";
let got = get_one_completion(src, None);
assert_eq!(got.matchstr, "Foo");
}
#[test]
fn completes_for_global_path_in_trait_impl_decl() {
let src = "
mod foo {
pub trait Bar {}
}
mod baz {
pub struct Test;
impl ::foo::~Bar for Test {}
}
fn main() {}
";
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "Bar");
assert_eq!(got.mtype, MatchType::Trait);
}
#[test]
fn completes_for_match_type_inference_let_expr() {
let src = r#"
use std::fs::File;
fn main() {
let f = File::open("hey");
let f = match f {
Ok(file) => file,
Err(error) => {
panic!("Error opening file: {:?}", error)
}
};
f.set_p~ermissions(/* args */);
}
"#;
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "set_permissions");
assert_eq!(got.mtype, MatchType::Function);
}
#[test]
fn completes_for_match_type_inference_let_expr_with_block() {
let src = r#"
use std::fs::File;
fn main() {
let f = File::open("hey");
let f = match f {
Ok(file) => { file },
Err(error) => {
panic!("Error opening file: {:?}", error)
}
};
f.set_p~ermissions(/* args */);
}
"#;
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "set_permissions");
assert_eq!(got.mtype, MatchType::Function);
}
#[test]
fn completes_for_match_type_inference_let_expr_with_return() {
let src = r#"
use std::fs::File;
fn test() -> String {
let f = File::open("hey");
let f = match f {
Err(error) => {
return "result".to_string();
},
Ok(file) => { file }
};
f.set_p~ermissions(/* args */);
}
"#;
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "set_permissions");
assert_eq!(got.mtype, MatchType::Function);
}
#[test]
fn completes_for_let_if_let() {
let src = r#"
use std::fs::File;
fn test() -> String {
let f = File::open("hey");
let f = if let Ok(f) = f { f } else { return "result".to_string(); };
f.set_p~ermissions(/* args */);
}
"#;
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "set_permissions");
assert_eq!(got.mtype, MatchType::Function);
}
#[test]
fn completes_for_match_type_inference_with_if() {
let src = r#"
use std::fs::File;
fn test() -> String {
let f = File::open("hey");
let f = match f {
Err(error) => {
return "result".to_string();
},
Ok(file) => { if file.sync_data().is_ok() { return "nice".to_string(); } else { file } }
};
f.set_p~ermissions(/* args */);
}
"#;
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "set_permissions");
assert_eq!(got.mtype, MatchType::Function);
}
#[test]
fn completes_before_first_statement() {
let src = r#"
fn test() {
~
let x = 8;
}
"#;
let completions = get_all_completions(src, None);
assert!(completions.into_iter().any(|m| m.matchstr == "std"));
}
#[test]
fn completes_between_statements() {
let src = r#"
fn test() {
let x = 8;
~
let y = 55;
}
"#;
let completions = get_all_completions(src, None);
assert!(completions.into_iter().any(|m| m.matchstr == "std"));
}
#[test]
fn completes_for_let_after_comments_with_multibyte_char() {
let src = "
fn main() {
let option = Some(5);
let _ = match option {
// multibyte comment ☆
Some(variable) => {
let b = vari~;
3
}
None => 4,
};
}
";
assert_eq!(get_only_completion(src, None).matchstr, "variable");
}
#[test]
fn completes_for_let_destracted_var_over_comment() {
let src = "
fn main() {
let option = Some(5);
let _ = match option {
Some(variable) /* C-style-comment*/
// one -liner comment
/* nested and /* multiline
comment*/ */
=> {
let b = vari~;
3
}
None => 4,
};
}
";
assert_eq!(get_only_completion(src, None).matchstr, "variable");
}
#[test]
fn completes_methods_for_global_enum() {
let src = r#"
fn main() {
let bar = Some("Hello");
bar.unwrap_or_def~
}
"#;
assert_eq!(get_only_completion(src, None).matchstr, "unwrap_or_default");
}
#[test]
fn completes_methods_for_local_enum() {
let src = "
fn main() {
enum MyEnum {
A
}
impl MyEnum {
fn method(&self) {}
}
let bar = MyEnum::A;
bar.met~
}
";
assert_eq!(get_only_completion(src, None).matchstr, "method");
}
#[test]
fn completes_methods_after_raw_string() {
let src = r##"
fn main() {
let s = r#"""#;
let v = Vec::<u32>::new();
v.l~
}
"##;
assert!(get_all_completions(src, None)
.iter()
.any(|ma| ma.matchstr == "len"));
}
#[test]
fn completes_methods_for_tuple_struct() {
let src = r"
fn main() {
struct A(i32, Vec<i32>);
let mut a = A(0, vec![3, 4]);
a.1.appen~
}
";
assert!(get_all_completions(src, None)
.into_iter()
.any(|ma| ma.matchstr == "append"));
}
#[test]
fn follows_use_nested_from_std() {
let src = r"
use std::collections::{hash_map::*, HashMap};
fn main() {
let h = HashMap::n~ew();
}
";
let got = get_definition(src, None);
assert_eq!(got.matchstr, "new");
let src = r"
use std::collections::{hash_map::*, HashMap};
fn main() {
let h = HashMap::new();
let a = DefaultHasher::ne~w();
}
";
let got = get_definition(src, None);
assert_eq!(got.matchstr, "new");
}
#[test]
fn use_tree_complete_all() {
let src = r"
mod MyMod {
pub enum MyEnum {
ErrorKind1,
ErrorKind2,
}
pub struct ErrorInfo;
}
use self::MyMod::{MyEnum::*, ErrorInfo};
let a = Erro~
";
let got = get_all_completions(src, None);
assert!(got.iter().any(|ma| ma.matchstr == "ErrorKind1"));
assert!(got.iter().any(|ma| ma.matchstr == "ErrorInfo"));
}
#[test]
fn match_statements_confusing_closure_args() {
let src = r#"
fn main() {
enum EnumA {
A,
B,
}
enum EnumB {
A,
B,
}
let a = EnumA::A;
let b = EnumB::A;
match a {
EnumA::A => match b {
EnumB::A | Enu~mB::B => {},
},
EnumA::B => match b {
EnumB::A | EnumB::B => {},
},
}
}
"#;
let got = get_definition(src, None);
assert_eq!(got.matchstr, "EnumB");
}
#[test]
fn completes_methods_for_closure_arg() {
let src = r"
fn main() {
let mut v = Vec::new();
v.push(3);
let s = Some(v);
let x = s.map(|v: Vec<i32>| v.appen~);
}
";
assert!(get_all_completions(src, None)
.into_iter()
.any(|ma| ma.matchstr == "append"));
let src = r"
fn main() {
let mut v = Vec::new();
v.push(3);
let s = Some(v);
let x = s.map(|v: Vec<i32>| {
v.appen~
});
}
";
assert!(get_all_completions(src, None)
.into_iter()
.any(|ma| ma.matchstr == "append"));
}
#[test]
fn finds_method_definition_in_1line_closure() {
let src = r"
fn main() {
let mut v = Vec::new();
v.push(3);
let s = Some(v);
let x = s.map(|v: Vec<i32>| v.pus~h(2));
}
";
let got = get_definition(src, None);
assert_eq!(got.matchstr, "push");
}
#[test]
fn recursive_glob_depth2() {
let src = "
use mod1::*;
use Bar::*;
mod mod1 {
pub enum Bar { MyVariant, MyVariant2 }
}
MyVa~riant
";
let got = get_definition(src, None);
assert_eq!("MyVariant", got.matchstr);
}
#[test]
#[should_panic]
fn recursive_glob_depth3() {
let src = "
use mod1::*;
use mod2::*;
use Bar::*;
mod mod1 { pub mod mod2 {
pub enum Bar { MyVariant, MyVariant2 }
}}
MyVa~riant
";
let got = get_definition(src, None);
assert_eq!("MyVariant", got.matchstr);
}
#[test]
fn completes_const_unsafe_fn() {
let src = r"
const unsafe fn unsafe_func() {}
let var = unsafe_fu~
";
let got = get_only_completion(src, None);
assert_eq!("unsafe_func", got.matchstr);
let src = r"
pub const unsafe fn unsafe_func() {}
let var = unsafe_fu~
";
let got = get_only_completion(src, None);
assert_eq!("unsafe_func", got.matchstr);
}
#[test]
fn completes_fn_with_crate_visibility_modifier() {
let src = r"
crate unsafe fn unsafe_func() {}
let var = unsafe_fu~
";
let got = get_only_completion(src, None);
assert_eq!("unsafe_func", got.matchstr);
}
#[test]
fn follows_complicated_use() {
let src = "
pub use std::{collections::{hash_map, HashM~
";
let got = get_only_completion(src, None);
assert_eq!("HashMap", got.matchstr);
let src = "
pub use std::{collections::{hash_map, ~
";
let got = get_all_completions(src, None);
assert!(got.into_iter().any(|ma| ma.matchstr == "HashMap"));
let src = "
crate use std::{collections::{~
";
let got = get_all_completions(src, None);
assert!(got.into_iter().any(|ma| ma.matchstr == "HashMap"));
}
#[test]
fn get_completion_in_example_dir() {
let src = r"
extern crate test_project;
use test_project::TestStruct;
fn main() {
let test_struct = TestStruct::n~
}
";
with_test_project(|dir| {
let example_dir = dir.nested_dir("examples");
let got = get_only_completion(src, Some(example_dir));
assert_eq!(got.matchstr, "new");
})
}
#[test]
fn follows_use_crate() {
let mod_src = "
pub fn myfn() {}
pub fn foo() {}
";
let lib_src = "
mod mymod;
use crate::mymod::*;
fn main() {
myf~
}
";
let dir = TmpDir::new();
let _lib = dir.write_file("mymod.rs", mod_src);
let got = get_only_completion(lib_src, Some(dir));
assert_eq!(got.matchstr, "myfn");
assert_eq!(got.contextstr, "pub fn myfn()");
}
#[test]
fn completes_static_method_for_typedef() {
let src = "
type UsizeVec = Vec<usize>;
fn func() {
let u = UsizeVec::with_capacity();
u.append_elem~
}
";
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "append_elements");
}
#[test]
fn finds_definition_in_use_tree() {
let src = "
pub use std::{collections::{HashMap, hash_map::DefaultHa~sher,
";
let got = get_definition(src, None);
assert_eq!(got.matchstr, "DefaultHasher");
}
#[test]
fn finds_fn_in_extern_block() {
let src = r#"
use std::os::raw::c_char;
extern "C" {
pub fn MyCFunction() -> *mut c_char;
}
fn main() {
let ptr = MyCFunc~
}
"#;
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "MyCFunction");
}
#[test]
fn finds_std_fn_in_extern_block() {
let src = r#"
use std::ptr::copy_nonoverla~
"#;
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "copy_nonoverlapping");
}
#[test]
fn complets_println() {
let src = r#"
fn main() {
printl~
}
"#;
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "println!");
}
#[test]
fn doesnt_complete_cfg_if() {
let src = r#"
fn main() {
cfg_i~
}
"#;
let got = get_all_completions(src, None);
assert!(got.is_empty(), "got: {:?}", got);
}
#[test]
fn finds_def_of_println() {
let src = r#"
fn main() {
printl~n!("Hello@_@");
}
"#;
let got = get_definition(src, None);
assert_eq!(got.matchstr, "println!");
}
#[test]
fn doesnt_complete_macro_after_use() {
let src = r#"
use printl~
"#;
let got = get_all_completions(src, None);
assert!(got.is_empty(), "got: {:?}", got);
let src = r#"
macro_rules! macro {
() => {}
}
use macr~
"#;
let got = get_all_completions(src, None);
assert!(got.is_empty(), "got: {:?}", got);
}
#[test]
#[ignore]
fn complets_stringify() {
let src = r#"
fn main() {
let ident = 100;
let s = stringi~
}
"#;
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "stringify!");
}
#[test]
fn completes_writeln() {
let src = r#"
fn main() {
writel~
}
"#;
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "writeln!");
}
#[test]
fn completes_vec() {
let src = r#"
fn main() {
ve~
}
"#;
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "vec!");
}
#[test]
#[ignore]
fn finds_std_macro_doc() {
let src = r#"
fn main() {
module_pat~h!();
}
"#;
let got = get_definition(src, None);
assert!(!got.docs.is_empty());
}
#[test]
fn finds_local_macro_doc() {
let src = r#"
/// my macro
macro_rules! local_macro { () => {} }
fn main() {
local_mac~ro!();
}
"#;
let got = get_definition(src, None);
let doc = "my macro";
assert_eq!(got.docs, doc);
}
#[test]
fn follows_multiline_use() {
let src = r#"
use std::{
cell::RefC~
collections::{
hash_map::{self, HashMap},
HashSet,
},
"#;
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "RefCell");
let src = r#"
use std::{
cell::RefCell,
collections::{
hash_map::{self, HashM~
HashSet,
},
"#;
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "HashMap");
}
#[test]
fn completes_trait_method_only_once() {
let src = "
trait Trait {
fn function(&self) -> usize { 5 }
}
struct S;
impl Trait for S {
type A = usize;
fn function(&self) -> usize { 6 }
}
fn main() {
let s = S {};
s.fun~
}
";
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "function");
}
#[test]
fn completes_methods_vec_macro() {
let src = "
fn main() {
let vec = vec![];
let a = vec.append_ele~
}
";
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "append_elements");
}
#[test]
fn completes_trait_methods_in_path() {
let src = "
let a = Default::de~
";
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "default");
}
#[test]
fn completes_closure_return_type() {
let src = r"
fn second<F: Fn() -> Option<i32>>(f: F) {
f().un~
}
";
let got = get_one_completion(src, None);
assert_eq!("unwrap", got.matchstr);
}
#[test]
fn completes_generic_closure_return_type() {
let src = r"
fn second<T: Clone, F: Fn() -> T>(f: F) {
f().cl~
}
";
let got = get_one_completion(src, None);
assert_eq!("clone", got.matchstr);
}
#[test]
fn completes_impl_generic_arg_in_closure() {
let src = r"
struct Something<T> {
t: T
}
impl<M: Clone> Something<M> {
fn second<T, F: Fn(T) -> M>(f: F) {
f().cl~
}
}
";
let got = get_one_completion(src, None);
assert_eq!("clone", got.matchstr);
}
#[test]
fn completes_closure_output_type_params() {
let src = r"
trait Foo {
fn foo(&self) -> String;
}
fn second<K: Foo, F: Fn() -> Option<K>>(f: F) {
f().unwrap().f~
}
";
let got = get_one_completion(src, None);
assert_eq!("foo", got.matchstr);
}
#[test]
fn completes_functions_from_trait_objects() {
let src = r"
pub trait Foo {
fn foo(&self);
}
fn get_foo() -> Box<Foo + Send> {
unimplemented!();
}
fn main() {
let mut t = get_foo();
t.f~
}
";
let got = get_all_completions(src, None);
assert!(got.into_iter().any(|ma| ma.matchstr == "foo"));
}
#[test]
fn import_stmt_doesnt_jump_to_closure_arg() {
let src = r#"
use req~west;
fn main() {
let y = Some(32i32).map(|reqwest| "something");
}
"#;
assert!(find_definition(src, None).is_none());
}
#[test]
fn test_resolve_global_path() {
let src = r#"
pub fn name() {
}
fn main() {
let name = 1;
let _ = ::nam~e();
}
"#;
let got = find_definition_with_name(src, None, "lib.rs").unwrap();
assert_eq!(got.matchstr, "name");
assert_eq!(got.mtype, MatchType::Function);
}
#[test]
fn test_resolve_global_path_in_modules() {
let src = r#"
fn foo() {
let name = 1;
let a = ::nam~e();
}
"#;
with_test_project(|dir| {
let srcdir = dir.nested_dir("src");
let got = get_one_completion(src, Some(srcdir));
assert_eq!(got.matchstr, "name");
assert_eq!(got.mtype, MatchType::Function);
});
let src = r#"
fn foo() {
let a = ::TestStruct::n~
}
"#;
with_test_project(|dir| {
let srcdir = dir.nested_dir("src");
let got = get_one_completion(src, Some(srcdir));
assert_eq!(got.matchstr, "new");
})
}
#[test]
fn completes_methods_for_as_bytes() {
let src = r#"
fn main() {
let s = "Foo".as_bytes();
let t = s.conca~
}
"#;
let got = get_only_completion(src, None);
assert_eq!(got.matchstr, "concat");
}
#[test]
fn completes_crate_local_enum_variant() {
let src = "
pub(crate) enum Enum {
Variant,
}
fn main() {
let bar = Enum::V~;
}
";
assert_eq!(get_only_completion(src, None).matchstr, "Variant");
}