[[package]]
name = "anyhow"
-version = "1.0.35"
+version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2c0df63cb2955042487fad3aefd2c6e3ae7389ac5dc1beb28921de0b69f779d4"
+checksum = "68803225a7b13e47191bab76f2687382b60d259e8cf37f6e1893658b84bb9479"
[[package]]
name = "anymap"
[[package]]
name = "indexmap"
-version = "1.6.0"
+version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2"
+checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b"
dependencies = [
"autocfg",
"hashbrown",
[[package]]
name = "lsp-types"
-version = "0.85.0"
+version = "0.86.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "857650f3e83fb62f89d15410414e0ed7d0735445020da398d37f65d20a5423b9"
+checksum = "f2a5c40d566f2704dac30859bca152217583fc94fd5b178d8baba915e1abd382"
dependencies = [
"base64",
"bitflags",
[[package]]
name = "perf-event"
-version = "0.4.5"
+version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "273069d0b956939ba75e8b5663328b9b7f0dc2e262b3306c6be66c4d87e2240a"
+checksum = "b7a1c2678a77d65edf773bd900f5b87f0944ac3421949842a2c6a4efe42d6c66"
dependencies = [
"libc",
"perf-event-open-sys",
[[package]]
name = "xshell"
-version = "0.1.7"
+version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ed0728d188f2ae530490b7d92435728aba53c6aed06d07e1951da9bd4c1d0798"
+checksum = "ed373ede30cea03e8c0af22f48ee1ba80efbf06fec8b4746977e6ee703878de0"
dependencies = [
"xshell-macros",
]
[[package]]
name = "xshell-macros"
-version = "0.1.7"
+version = "0.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "367f903cc3f8bc4f4b2400d47dfa6c9e3e121ffb51a30cf0fb67a72c0a0f9617"
+checksum = "7f6af9f8119104697b0105989a73c578ce33f922d9d6f3dae0e8ae3d538db321"
[[package]]
name = "xtask"
use std::iter;
use either::Either;
-use hir::{AsName, EnumVariant, Module, ModuleDef, Name};
+use hir::{AsName, Module, ModuleDef, Name, Variant};
use ide_db::helpers::{
insert_use::{insert_use, ImportScope},
mod_path_to_ast,
let variant_hir_name = variant_hir.name(ctx.db());
let enum_module_def = ModuleDef::from(enum_hir);
let usages =
- Definition::ModuleDef(ModuleDef::EnumVariant(variant_hir)).usages(&ctx.sema).all();
+ Definition::ModuleDef(ModuleDef::Variant(variant_hir)).usages(&ctx.sema).all();
let mut visited_modules_set = FxHashSet::default();
let current_module = enum_hir.module(ctx.db());
}
}
-fn existing_definition(db: &RootDatabase, variant_name: &ast::Name, variant: &EnumVariant) -> bool {
+fn existing_definition(db: &RootDatabase, variant_name: &ast::Name, variant: &Variant) -> bool {
variant
.parent_enum(db)
.module(db)
// only check type-namespace
hir::ScopeDef::ModuleDef(def) => matches!(def,
ModuleDef::Module(_) | ModuleDef::Adt(_) |
- ModuleDef::EnumVariant(_) | ModuleDef::Trait(_) |
+ ModuleDef::Variant(_) | ModuleDef::Trait(_) |
ModuleDef::TypeAlias(_) | ModuleDef::BuiltinType(_)
),
_ => false,
.collect()
}
-fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::EnumVariant) -> Option<ast::Pat> {
+fn build_pat(db: &RootDatabase, module: hir::Module, var: hir::Variant) -> Option<ast::Pat> {
let path = mod_path_to_ast(&module.find_use_path(db, ModuleDef::from(var))?);
// FIXME: use HIR for this; it doesn't currently expose struct vs. tuple vs. unit variants though
(vis_offset(syntax), in_file_source.value.visibility(), syntax.text_range(), file_id)
}
// Enum variants can't be private, we can't modify builtin types
- hir::ModuleDef::EnumVariant(_) | hir::ModuleDef::BuiltinType(_) => return None,
+ hir::ModuleDef::Variant(_) | hir::ModuleDef::BuiltinType(_) => return None,
};
Some((offset, current_visibility, target, target_file, target_name))
self.type_params,
self.params,
fn_body,
- Some(make::ret_type(make::ty("()"))),
+ Some(make::ret_type(make::ty_unit())),
);
let leading_ws;
let trailing_ws;
use crate::{
item::Builder,
render::{
- const_::render_const, enum_variant::render_enum_variant, function::render_fn,
+ const_::render_const, enum_variant::render_variant, function::render_fn,
macro_::render_macro, render_field, render_resolution, render_tuple_field,
type_alias::render_type_alias, RenderContext,
},
pub(crate) fn add_qualified_enum_variant(
&mut self,
ctx: &CompletionContext,
- variant: hir::EnumVariant,
+ variant: hir::Variant,
path: ModPath,
) {
- let item = render_enum_variant(RenderContext::new(ctx), None, None, variant, Some(path));
+ let item = render_variant(RenderContext::new(ctx), None, None, variant, Some(path));
self.add(item);
}
pub(crate) fn add_enum_variant(
&mut self,
ctx: &CompletionContext,
- variant: hir::EnumVariant,
+ variant: hir::Variant,
local_name: Option<String>,
) {
- let item = render_enum_variant(RenderContext::new(ctx), None, local_name, variant, None);
+ let item = render_variant(RenderContext::new(ctx), None, local_name, variant, None);
self.add(item);
}
}
at Hash
at PartialEq
at PartialEq, Eq
- at PartialEq, Eq, PartialOrd, Ord
at PartialEq, PartialOrd
+ at PartialEq, Eq, PartialOrd, Ord
"#]],
);
}
at Clone, Copy
at Debug
at Default
- at Eq
- at Eq, PartialOrd, Ord
at Hash
+ at Eq
at PartialOrd
+ at Eq, PartialOrd, Ord
"#]],
)
}
expect![[r#"
at allow(…)
at automatically_derived
- at cfg(…)
at cfg_attr(…)
+ at cfg(…)
at cold
at deny(…)
at deprecated = "…"
at derive(…)
- at doc = "…"
at export_name = "…"
+ at doc = "…"
at forbid(…)
at ignore = "…"
at inline(…)
expect![[r#"
at allow(…)
at automatically_derived
- at cfg(…)
at cfg_attr(…)
+ at cfg(…)
at cold
at crate_name = ""
at deny(…)
at deprecated = "…"
at derive(…)
- at doc = "…"
at export_name = "…"
+ at doc = "…"
at feature(…)
at forbid(…)
at global_allocator
at macro_export
at macro_use
at must_use = "…"
- at no_implicit_prelude
at no_link
+ at no_implicit_prelude
at no_main
at no_mangle
at no_std
fn foo(s: S) { s.<|> }
"#,
expect![[r#"
- me bar() fn bar(&self)
fd foo u32
+ me bar() fn bar(&self)
"#]],
);
}
}
"#,
expect![[r#"
- me foo() fn foo(self)
fd the_field (u32,)
+ me foo() fn foo(self)
"#]],
)
}
}
"#,
expect![[r#"
- me foo() fn foo(&self)
fd the_field (u32, i32)
+ me foo() fn foo(&self)
"#]],
)
}
fn foo(a: inner::A) { a.<|> }
"#,
expect![[r#"
- fd crate_field u32
fd pub_field u32
+ fd crate_field u32
fd super_field u32
"#]],
);
check(
r"m<|>",
expect![[r#"
- kw const
- kw enum
- kw extern
kw fn
+ kw use
kw impl
- kw mod
- kw pub
- kw pub(crate)
- kw static
- kw struct
kw trait
- kw type
+ kw enum
+ kw struct
kw union
+ kw mod
+ kw const
+ kw type
+ kw static
+ kw extern
kw unsafe
- kw use
+ kw pub(crate)
+ kw pub
"#]],
);
}
check(
r"fn quux() { <|> }",
expect![[r#"
- kw const
- kw extern
kw fn
+ kw use
+ kw impl
+ kw trait
+ kw match
+ kw while
+ kw loop
kw if
kw if let
- kw impl
kw let
- kw loop
- kw match
kw mod
- kw return
- kw static
- kw trait
+ kw const
kw type
+ kw static
+ kw extern
kw unsafe
- kw use
- kw while
+ kw return
"#]],
);
}
check(
r"fn quux() { if true { <|> } }",
expect![[r#"
- kw const
- kw extern
kw fn
+ kw use
+ kw impl
+ kw trait
+ kw match
+ kw while
+ kw loop
kw if
kw if let
- kw impl
kw let
- kw loop
- kw match
kw mod
- kw return
- kw static
- kw trait
+ kw const
kw type
+ kw static
+ kw extern
kw unsafe
- kw use
- kw while
+ kw return
"#]],
);
}
check(
r#"fn quux() { if true { () } <|> }"#,
expect![[r#"
- kw const
- kw else
- kw else if
- kw extern
kw fn
+ kw use
+ kw impl
+ kw trait
+ kw match
+ kw while
+ kw loop
kw if
kw if let
- kw impl
kw let
- kw loop
- kw match
+ kw else
+ kw else if
kw mod
- kw return
- kw static
- kw trait
+ kw const
kw type
+ kw static
+ kw extern
kw unsafe
- kw use
- kw while
+ kw return
"#]],
);
check_edit(
}
"#,
expect![[r#"
+ kw match
+ kw while
+ kw loop
kw if
kw if let
- kw loop
- kw match
- kw return
kw unsafe
- kw while
+ kw return
"#]],
);
}
check(
r"trait My { <|> }",
expect![[r#"
- kw const
kw fn
+ kw const
kw type
kw unsafe
"#]],
check(
r"impl My { <|> }",
expect![[r#"
- kw const
kw fn
- kw pub
- kw pub(crate)
+ kw const
kw type
kw unsafe
+ kw pub(crate)
+ kw pub
"#]],
);
}
check(
r"fn my() { loop { <|> } }",
expect![[r#"
- kw break
- kw const
- kw continue
- kw extern
kw fn
+ kw use
+ kw impl
+ kw trait
+ kw match
+ kw while
+ kw loop
kw if
kw if let
- kw impl
kw let
- kw loop
- kw match
kw mod
- kw return
- kw static
- kw trait
+ kw const
kw type
+ kw static
+ kw extern
kw unsafe
- kw use
- kw while
+ kw continue
+ kw break
+ kw return
"#]],
);
}
r"unsafe <|>",
expect![[r#"
kw fn
- kw impl
kw trait
+ kw impl
"#]],
);
}
r"fn my_fn() { unsafe <|> }",
expect![[r#"
kw fn
- kw impl
kw trait
+ kw impl
"#]],
);
}
check(
r#"fn main() { let _ = <|> }"#,
expect![[r#"
+ kw match
+ kw while
+ kw loop
kw if
kw if let
- kw loop
- kw match
kw return
- kw while
"#]],
)
}
}
"#,
expect![[r#"
- kw pub
kw pub(crate)
+ kw pub
"#]],
)
}
}
"#,
expect![[r#"
+ kw match
+ kw while
+ kw loop
kw if
kw if let
- kw loop
- kw match
kw return
- kw while
"#]],
);
}
fn ignored_bar() {}
"#,
expect![[r#"
- md bar;
md foo;
+ md bar;
"#]],
);
}
fn ignored_bar() {}
"#,
expect![[r#"
- md bar;
md foo;
+ md bar;
"#]],
);
}
def,
hir::ModuleDef::Adt(hir::Adt::Enum(..))
| hir::ModuleDef::Adt(hir::Adt::Struct(..))
- | hir::ModuleDef::EnumVariant(..)
+ | hir::ModuleDef::Variant(..)
| hir::ModuleDef::Const(..)
| hir::ModuleDef::Module(..)
)
}
"#,
expect![[r#"
- st Bar
en E
- ev X ()
ct Z
+ st Bar
+ ev X ()
md m
"#]],
);
}
"#,
expect![[r#"
- sn box Box::new(expr)
- sn call function(expr)
- sn dbg dbg!(expr)
- sn dbgr dbg!(&expr)
sn if if expr {}
- sn let let
- sn letm let mut
- sn match match expr {}
+ sn while while expr {}
sn not !expr
- sn ok Ok(expr)
sn ref &expr
sn refm &mut expr
+ sn match match expr {}
+ sn box Box::new(expr)
+ sn ok Ok(expr)
sn some Some(expr)
- sn while while expr {}
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn call function(expr)
+ sn let let
+ sn letm let mut
"#]],
);
}
}
"#,
expect![[r#"
- sn box Box::new(expr)
- sn call function(expr)
- sn dbg dbg!(expr)
- sn dbgr dbg!(&expr)
sn if if expr {}
- sn match match expr {}
+ sn while while expr {}
sn not !expr
- sn ok Ok(expr)
sn ref &expr
sn refm &mut expr
+ sn match match expr {}
+ sn box Box::new(expr)
+ sn ok Ok(expr)
sn some Some(expr)
- sn while while expr {}
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn call function(expr)
"#]],
);
}
}
"#,
expect![[r#"
+ sn ref &expr
+ sn refm &mut expr
+ sn match match expr {}
sn box Box::new(expr)
- sn call function(expr)
+ sn ok Ok(expr)
+ sn some Some(expr)
sn dbg dbg!(expr)
sn dbgr dbg!(&expr)
+ sn call function(expr)
sn let let
sn letm let mut
- sn match match expr {}
- sn ok Ok(expr)
- sn ref &expr
- sn refm &mut expr
- sn some Some(expr)
"#]],
)
}
}
"#,
expect![[r#"
- sn box Box::new(expr)
- sn call function(expr)
- sn dbg dbg!(expr)
- sn dbgr dbg!(&expr)
sn if if expr {}
- sn let let
- sn letm let mut
- sn match match expr {}
+ sn while while expr {}
sn not !expr
- sn ok Ok(expr)
sn ref &expr
sn refm &mut expr
+ sn match match expr {}
+ sn box Box::new(expr)
+ sn ok Ok(expr)
sn some Some(expr)
- sn while while expr {}
+ sn dbg dbg!(expr)
+ sn dbgr dbg!(&expr)
+ sn call function(expr)
+ sn let let
+ sn letm let mut
"#]],
);
}
check_builtin(
r#"fn main() { let _: <|> = 92; }"#,
expect![[r#"
+ bt u32
bt bool
- bt char
+ bt u8
+ bt isize
+ bt u16
+ bt u64
+ bt u128
bt f32
- bt f64
bt i128
bt i16
- bt i32
+ bt str
bt i64
+ bt char
+ bt f64
+ bt i32
bt i8
- bt isize
- bt str
- bt u128
- bt u16
- bt u32
- bt u64
- bt u8
bt usize
"#]],
);
use crate::Sp<|>
"#,
expect![[r#"
- st Spam
md foo
+ st Spam
"#]],
);
}
use crate::{Sp<|>};
"#,
expect![[r#"
- st Spam
md foo
+ st Spam
"#]],
);
}
fn foo() { let _ = E::<|> }
"#,
expect![[r#"
- ev Bar(…) (i32)
ev Foo ()
+ ev Bar(…) (i32)
"#]],
);
}
fn foo() { let _ = S::<|> }
"#,
expect![[r#"
- ct C const C: i32 = 42;
- ta T type T = i32;
fn a() fn a()
me b(…) fn b(&self)
+ ct C const C: i32 = 42;
+ ta T type T = i32;
"#]],
);
}
fn foo() { let _ = S::<|> }
"#,
expect![[r#"
+ fn public_method() pub(crate) fn public_method()
ct PUBLIC_CONST pub(crate) const PUBLIC_CONST: u32 = 1;
ta PublicType pub(crate) type PublicType = u32;
- fn public_method() pub(crate) fn public_method()
"#]],
);
}
fn foo<T: Sub>() { T::<|> }
"#,
expect![[r#"
- ct C2 const C2: ();
- ct CONST const CONST: u8;
ta SubTy type SubTy;
ta Ty type Ty;
- fn func() fn func()
- me method(…) fn method(&self)
+ ct C2 const C2: ();
fn subfunc() fn subfunc()
me submethod(…) fn submethod(&self)
+ ct CONST const CONST: u8;
+ fn func() fn func()
+ me method(…) fn method(&self)
"#]],
);
}
}
"#,
expect![[r#"
- ct C2 const C2: () = ();
- ct CONST const CONST: u8 = 0;
ta SubTy type SubTy;
ta Ty type Ty;
+ ct CONST const CONST: u8 = 0;
fn func() fn func()
me method(…) fn method(&self)
+ ct C2 const C2: () = ();
fn subfunc() fn subfunc()
me submethod(…) fn submethod(&self)
"#]],
fn main() { T::<|>; }
"#,
expect![[r#"
- fn bar() fn bar()
fn foo() fn foo()
+ fn bar() fn bar()
"#]],
);
}
fn main() { let _ = crate::<|> }
"#,
expect![[r##"
+ fn main() fn main()
ma foo!(…) #[macro_export]
macro_rules! foo
- fn main() fn main()
"##]],
);
}
}
"#,
expect![[r#"
- ct A
md b
+ ct A
"#]],
);
}
"#,
expect![[r#"
ct RIGHT_CONST
- st RightType
fn right_fn() fn wrong_fn()
+ st RightType
"#]],
);
fn foo() {}
"#,
expect![[r#"
- fn foo() fn foo()
fn main() fn main()
+ fn foo() fn foo()
"#]],
);
}
}
"#,
expect![[r#"
- fn foo(…) fn foo(a: i32, b: i32)
fn main() fn main()
+ fn foo(…) fn foo(a: i32, b: i32)
"#]],
);
}
check_snippet(
test_code,
expect![[r#"
- fd ..Default::default()
sn pd
sn ppd
+ fd ..Default::default()
"#]],
);
}
}
"#,
expect![[r#"
- fd bar ()
fd foo u32
+ fd bar ()
"#]],
);
}
}
"#,
expect![[r#"
- sn macro_rules
- sn tfn (Test function)
sn tmod (Test module)
+ sn tfn (Test function)
+ sn macro_rules
"#]],
)
}
}
"#,
expect![["
+ta type TestType = \n\
ct const TEST_CONST: u16 = \n\
fn fn test()
-ta type TestType = \n\
- "]],
+"]],
);
}
//! Completion of names from the current scope, e.g. locals and imported items.
use either::Either;
-use hir::{Adt, ModuleDef, ScopeDef, Type};
+use hir::{Adt, ModPath, ModuleDef, ScopeDef, Type};
use ide_db::helpers::insert_use::ImportScope;
use ide_db::imports_locator;
use syntax::AstNode;
let anchor = ctx.name_ref_syntax.as_ref()?;
let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?;
- let possible_imports = imports_locator::find_similar_imports(
+ let mut all_mod_paths = imports_locator::find_similar_imports(
&ctx.sema,
ctx.krate?,
Some(100),
})
})
.filter(|(mod_path, _)| mod_path.len() > 1)
- .filter_map(|(import_path, definition)| {
+ .collect::<Vec<_>>();
+
+ let user_input_lowercased = potential_import_name.to_lowercase();
+ all_mod_paths.sort_by_cached_key(|(mod_path, _)| {
+ compute_fuzzy_completion_order_key(mod_path, &user_input_lowercased)
+ });
+
+ acc.add_all(all_mod_paths.into_iter().filter_map(|(import_path, definition)| {
render_resolution_with_import(
RenderContext::new(ctx),
ImportEdit { import_path, import_scope: import_scope.clone() },
&definition,
)
- });
-
- acc.add_all(possible_imports);
+ }));
Some(())
}
+fn compute_fuzzy_completion_order_key(
+ proposed_mod_path: &ModPath,
+ user_input_lowercased: &str,
+) -> usize {
+ mark::hit!(certain_fuzzy_order_test);
+ let proposed_import_name = match proposed_mod_path.segments.last() {
+ Some(name) => name.to_string().to_lowercase(),
+ None => return usize::MAX,
+ };
+ match proposed_import_name.match_indices(user_input_lowercased).next() {
+ Some((first_matching_index, _)) => first_matching_index,
+ None => usize::MAX,
+ }
+}
+
#[cfg(test)]
mod tests {
use expect_test::{expect, Expect};
use test_utils::mark;
use crate::{
- test_utils::{check_edit, check_edit_with_config, completion_list},
+ test_utils::{check_edit, check_edit_with_config, completion_list_with_config},
CompletionConfig, CompletionKind,
};
fn check(ra_fixture: &str, expect: Expect) {
- let actual = completion_list(ra_fixture, CompletionKind::Reference);
+ check_with_config(CompletionConfig::default(), ra_fixture, expect);
+ }
+
+ fn check_with_config(config: CompletionConfig, ra_fixture: &str, expect: Expect) {
+ let actual = completion_list_with_config(config, ra_fixture, CompletionKind::Reference);
expect.assert_eq(&actual)
}
+ fn fuzzy_completion_config() -> CompletionConfig {
+ let mut completion_config = CompletionConfig::default();
+ completion_config
+ .active_resolve_capabilities
+ .insert(crate::CompletionResolveCapability::AdditionalTextEdits);
+ completion_config
+ }
+
#[test]
fn self_fulfilling_completion() {
mark::check!(self_fulfilling_completion);
}
"#,
expect![[r#"
- fn quux(…) fn quux(x: i32)
- bn x i32
bn y i32
+ bn x i32
+ fn quux(…) fn quux(x: i32)
"#]],
);
}
}
"#,
expect![[r#"
- bn a
bn b i32
+ bn a
fn quux() fn quux()
"#]],
);
}
"#,
expect![[r#"
- fn quux() fn quux()
bn x
+ fn quux() fn quux()
"#]],
);
}
check(
r#"struct S<T> { x: <|>}"#,
expect![[r#"
- st S<…>
tp Self
tp T
+ st S<…>
"#]],
);
}
fn quux() { <|> }
"#,
expect![[r#"
- en E
st S
fn quux() fn quux()
+ en E
"#]],
);
}
}
"#,
expect![[r#"
- st Bar
fn quux() fn quux()
+ st Bar
"#]],
);
}
check(
r#"impl S { fn foo(&self) { <|> } }"#,
expect![[r#"
- tp Self
bn self &{unknown}
+ tp Self
"#]],
);
}
mod prelude { struct Option; }
"#,
expect![[r#"
- st Option
fn foo() fn foo()
md std
+ st Option
"#]],
);
}
mod prelude { struct String; }
"#,
expect![[r#"
- st String
- md core
fn foo() fn foo()
md std
+ md core
+ st String
"#]],
);
}
fn main() { let v = <|> }
"#,
expect![[r##"
- ma bar!(…) macro_rules! bar
+ md m1
ma baz!(…) #[macro_export]
macro_rules! baz
- ma foo!(…) macro_rules! foo
- md m1
- md m2
fn main() fn main()
+ md m2
+ ma bar!(…) macro_rules! bar
+ ma foo!(…) macro_rules! foo
"##]],
);
}
fn foo() { <|> }
"#,
expect![[r#"
- ma foo!(…) macro_rules! foo
fn foo() fn foo()
+ ma foo!(…) macro_rules! foo
"#]],
);
}
fn main() { let x: <|> }
"#,
expect![[r#"
- ma foo!(…) macro_rules! foo
fn main() fn main()
+ ma foo!(…) macro_rules! foo
"#]],
);
}
fn main() { <|> }
"#,
expect![[r#"
- ma foo!(…) macro_rules! foo
fn main() fn main()
+ ma foo!(…) macro_rules! foo
"#]],
);
}
}
"#,
expect![[r#"
- ma m!(…) macro_rules! m
- fn quux(…) fn quux(x: i32)
- bn x i32
bn y i32
+ bn x i32
+ fn quux(…) fn quux(x: i32)
+ ma m!(…) macro_rules! m
"#]],
);
}
}
",
expect![[r#"
- ma m!(…) macro_rules! m
- fn quux(…) fn quux(x: i32)
- bn x i32
bn y i32
+ bn x i32
+ fn quux(…) fn quux(x: i32)
+ ma m!(…) macro_rules! m
"#]],
);
}
}
"#,
expect![[r#"
- ma m!(…) macro_rules! m
- fn quux(…) fn quux(x: i32)
- bn x i32
bn y i32
+ bn x i32
+ fn quux(…) fn quux(x: i32)
+ ma m!(…) macro_rules! m
"#]],
);
}
fn main() { <|> }
"#,
expect![[r#"
- ?? Quux
fn main() fn main()
+ ?? Quux
"#]],
);
}
}
"#,
expect![[r#"
- en Foo
ev Foo::Bar ()
ev Foo::Baz ()
ev Foo::Quux ()
+ en Foo
"#]],
)
}
}
"#,
expect![[r#"
- en Foo
ev Foo::Bar ()
ev Foo::Baz ()
ev Foo::Quux ()
+ en Foo
"#]],
)
}
fn main() { let foo: Foo = Q<|> }
"#,
expect![[r#"
- en Foo
ev Foo::Bar ()
ev Foo::Baz ()
ev Foo::Quux ()
+ en Foo
fn main() fn main()
"#]],
)
fn f() -> m::E { V<|> }
"#,
expect![[r#"
- fn f() fn f() -> m::E
- md m
ev m::E::V ()
+ md m
+ fn f() fn f() -> m::E
"#]],
)
}
impl My<|>
"#,
expect![[r#"
- st MyStruct
- tt MyTrait
tp Self
+ tt MyTrait
+ st MyStruct
"#]],
)
}
#[test]
fn function_fuzzy_completion() {
- let mut completion_config = CompletionConfig::default();
- completion_config
- .active_resolve_capabilities
- .insert(crate::CompletionResolveCapability::AdditionalTextEdits);
-
check_edit_with_config(
- completion_config,
+ fuzzy_completion_config(),
"stdin",
r#"
//- /lib.rs crate:dep
#[test]
fn macro_fuzzy_completion() {
- let mut completion_config = CompletionConfig::default();
- completion_config
- .active_resolve_capabilities
- .insert(crate::CompletionResolveCapability::AdditionalTextEdits);
-
check_edit_with_config(
- completion_config,
+ fuzzy_completion_config(),
"macro_with_curlies!",
r#"
//- /lib.rs crate:dep
#[test]
fn struct_fuzzy_completion() {
- let mut completion_config = CompletionConfig::default();
- completion_config
- .active_resolve_capabilities
- .insert(crate::CompletionResolveCapability::AdditionalTextEdits);
-
check_edit_with_config(
- completion_config,
+ fuzzy_completion_config(),
"ThirdStruct",
r#"
//- /lib.rs crate:dep
"#,
);
}
+
+ #[test]
+ fn fuzzy_completions_come_in_specific_order() {
+ mark::check!(certain_fuzzy_order_test);
+ check_with_config(
+ fuzzy_completion_config(),
+ r#"
+//- /lib.rs crate:dep
+pub struct FirstStruct;
+pub mod some_module {
+ // already imported, omitted
+ pub struct SecondStruct;
+ // does not contain all letters from the query, omitted
+ pub struct UnrelatedOne;
+ // contains all letters from the query, but not in sequence, displayed last
+ pub struct ThiiiiiirdStruct;
+ // contains all letters from the query, but not in the beginning, displayed second
+ pub struct AfterThirdStruct;
+ // contains all letters from the query in the begginning, displayed first
+ pub struct ThirdStruct;
+}
+
+//- /main.rs crate:main deps:dep
+use dep::{FirstStruct, some_module::SecondStruct};
+
+fn main() {
+ hir<|>
+}
+"#,
+ expect![[r#"
+ fn main() fn main()
+ st SecondStruct
+ st FirstStruct
+ md dep
+ st dep::some_module::ThirdStruct
+ st dep::some_module::AfterThirdStruct
+ st dep::some_module::ThiiiiiirdStruct
+ "#]],
+ );
+ }
}
CompletionKind, CompletionScore,
};
-use crate::render::{enum_variant::render_enum_variant, function::render_fn, macro_::render_macro};
+use crate::render::{enum_variant::render_variant, function::render_fn, macro_::render_macro};
pub(crate) fn render_field<'a>(
ctx: RenderContext<'a>,
let item = render_fn(self.ctx, import_to_add, Some(local_name), *func);
return Some(item);
}
- ScopeDef::ModuleDef(EnumVariant(var)) => {
- let item =
- render_enum_variant(self.ctx, import_to_add, Some(local_name), *var, None);
+ ScopeDef::ModuleDef(Variant(var)) => {
+ let item = render_variant(self.ctx, import_to_add, Some(local_name), *var, None);
return Some(item);
}
ScopeDef::MacroDef(mac) => {
match resolution {
ScopeDef::ModuleDef(Module(it)) => it.docs(self.ctx.db()),
ScopeDef::ModuleDef(Adt(it)) => it.docs(self.ctx.db()),
- ScopeDef::ModuleDef(EnumVariant(it)) => it.docs(self.ctx.db()),
+ ScopeDef::ModuleDef(Variant(it)) => it.docs(self.ctx.db()),
ScopeDef::ModuleDef(Const(it)) => it.docs(self.ctx.db()),
ScopeDef::ModuleDef(Static(it)) => it.docs(self.ctx.db()),
ScopeDef::ModuleDef(Trait(it)) => it.docs(self.ctx.db()),
render::{builder_ext::Params, RenderContext},
};
-pub(crate) fn render_enum_variant<'a>(
+pub(crate) fn render_variant<'a>(
ctx: RenderContext<'a>,
import_to_add: Option<ImportEdit>,
local_name: Option<String>,
- variant: hir::EnumVariant,
+ variant: hir::Variant,
path: Option<ModPath>,
) -> CompletionItem {
let _p = profile::span("render_enum_variant");
- EnumVariantRender::new(ctx, local_name, variant, path).render(import_to_add)
+ EnumRender::new(ctx, local_name, variant, path).render(import_to_add)
}
#[derive(Debug)]
-struct EnumVariantRender<'a> {
+struct EnumRender<'a> {
ctx: RenderContext<'a>,
name: String,
- variant: hir::EnumVariant,
+ variant: hir::Variant,
path: Option<ModPath>,
qualified_name: String,
short_qualified_name: String,
variant_kind: StructKind,
}
-impl<'a> EnumVariantRender<'a> {
+impl<'a> EnumRender<'a> {
fn new(
ctx: RenderContext<'a>,
local_name: Option<String>,
- variant: hir::EnumVariant,
+ variant: hir::Variant,
path: Option<ModPath>,
- ) -> EnumVariantRender<'a> {
+ ) -> EnumRender<'a> {
let name = local_name.unwrap_or_else(|| variant.name(ctx.db()).to_string());
let variant_kind = variant.kind(ctx.db());
None => (name.to_string(), name.to_string()),
};
- EnumVariantRender {
- ctx,
- name,
- variant,
- path,
- qualified_name,
- short_qualified_name,
- variant_kind,
- }
+ EnumRender { ctx, name, variant, path, qualified_name, short_qualified_name, variant_kind }
}
fn render(self, import_to_add: Option<ImportEdit>) -> CompletionItem {
fn render(&self, import_to_add: Option<ImportEdit>) -> Option<CompletionItem> {
// FIXME: Currently proc-macro do not have ast-node,
// such that it does not have source
+ // more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913
if self.macro_.is_proc_macro() {
return None;
}
code: &str,
kind: CompletionKind,
) -> String {
- let mut kind_completions: Vec<CompletionItem> =
+ let kind_completions: Vec<CompletionItem> =
get_all_items(config, code).into_iter().filter(|c| c.completion_kind == kind).collect();
- kind_completions.sort_by_key(|c| c.label().to_owned());
let label_width = kind_completions
.iter()
.map(|it| monospace_width(it.label()))
use syntax::ast;
use crate::{
- Adt, Const, Enum, EnumVariant, Field, Function, MacroDef, Module, ModuleDef, Static, Struct,
- Trait, TypeAlias, Union,
+ Adt, Const, Enum, Field, Function, MacroDef, Module, ModuleDef, Static, Struct, Trait,
+ TypeAlias, Union, Variant,
};
pub trait HasAttrs {
impl_has_attrs![
(Field, FieldId),
- (EnumVariant, EnumVariantId),
+ (Variant, EnumVariantId),
(Static, StaticId),
(Const, ConstId),
(Trait, TraitId),
Function(Function),
Adt(Adt),
// Can't be directly declared, but can be imported.
- EnumVariant(EnumVariant),
+ Variant(Variant),
Const(Const),
Static(Static),
Trait(Trait),
Module,
Function,
Adt(Struct, Enum, Union),
- EnumVariant,
+ Variant,
Const,
Static,
Trait,
match var {
VariantDef::Struct(t) => Adt::from(t).into(),
VariantDef::Union(t) => Adt::from(t).into(),
- VariantDef::EnumVariant(t) => t.into(),
+ VariantDef::Variant(t) => t.into(),
}
}
}
ModuleDef::Module(it) => it.parent(db),
ModuleDef::Function(it) => Some(it.module(db)),
ModuleDef::Adt(it) => Some(it.module(db)),
- ModuleDef::EnumVariant(it) => Some(it.module(db)),
+ ModuleDef::Variant(it) => Some(it.module(db)),
ModuleDef::Const(it) => Some(it.module(db)),
ModuleDef::Static(it) => Some(it.module(db)),
ModuleDef::Trait(it) => Some(it.module(db)),
ModuleDef::Module(it) => it.parent(db)?,
ModuleDef::Function(it) => return Some(it.visibility(db)),
ModuleDef::Adt(it) => it.module(db),
- ModuleDef::EnumVariant(it) => {
+ ModuleDef::Variant(it) => {
let parent = it.parent_enum(db);
let module = it.module(db);
return module.visibility_of(db, &ModuleDef::Adt(Adt::Enum(parent)));
ModuleDef::Adt(it) => Some(it.name(db)),
ModuleDef::Trait(it) => Some(it.name(db)),
ModuleDef::Function(it) => Some(it.name(db)),
- ModuleDef::EnumVariant(it) => Some(it.name(db)),
+ ModuleDef::Variant(it) => Some(it.name(db)),
ModuleDef::TypeAlias(it) => Some(it.name(db)),
ModuleDef::Module(it) => it.name(db),
ModuleDef::Const(it) => it.name(db),
let generic_def_id: GenericDefId = match self.parent {
VariantDef::Struct(it) => it.id.into(),
VariantDef::Union(it) => it.id.into(),
- VariantDef::EnumVariant(it) => it.parent.id.into(),
+ VariantDef::Variant(it) => it.parent.id.into(),
};
let substs = Substs::type_params(db, generic_def_id);
let ty = db.field_types(var_id)[self.id].clone().subst(&substs);
db.enum_data(self.id).name.clone()
}
- pub fn variants(self, db: &dyn HirDatabase) -> Vec<EnumVariant> {
- db.enum_data(self.id)
- .variants
- .iter()
- .map(|(id, _)| EnumVariant { parent: self, id })
- .collect()
+ pub fn variants(self, db: &dyn HirDatabase) -> Vec<Variant> {
+ db.enum_data(self.id).variants.iter().map(|(id, _)| Variant { parent: self, id }).collect()
}
pub fn ty(self, db: &dyn HirDatabase) -> Type {
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct EnumVariant {
+pub struct Variant {
pub(crate) parent: Enum,
pub(crate) id: LocalEnumVariantId,
}
-impl EnumVariant {
+impl Variant {
pub fn module(self, db: &dyn HirDatabase) -> Module {
self.parent.module(db)
}
pub enum VariantDef {
Struct(Struct),
Union(Union),
- EnumVariant(EnumVariant),
+ Variant(Variant),
}
-impl_from!(Struct, Union, EnumVariant for VariantDef);
+impl_from!(Struct, Union, Variant for VariantDef);
impl VariantDef {
pub fn fields(self, db: &dyn HirDatabase) -> Vec<Field> {
match self {
VariantDef::Struct(it) => it.fields(db),
VariantDef::Union(it) => it.fields(db),
- VariantDef::EnumVariant(it) => it.fields(db),
+ VariantDef::Variant(it) => it.fields(db),
}
}
match self {
VariantDef::Struct(it) => it.module(db),
VariantDef::Union(it) => it.module(db),
- VariantDef::EnumVariant(it) => it.module(db),
+ VariantDef::Variant(it) => it.module(db),
}
}
match self {
VariantDef::Struct(s) => s.name(db),
VariantDef::Union(u) => u.name(db),
- VariantDef::EnumVariant(e) => e.name(db),
+ VariantDef::Variant(e) => e.name(db),
}
}
match self {
VariantDef::Struct(it) => it.variant_data(db),
VariantDef::Union(it) => it.variant_data(db),
- VariantDef::EnumVariant(it) => it.variant_data(db),
+ VariantDef::Variant(it) => it.variant_data(db),
}
}
}
/// XXX: this parses the file
pub fn name(self, db: &dyn HirDatabase) -> Option<Name> {
+ // FIXME: Currently proc-macro do not have ast-node,
+ // such that it does not have source
+ // more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913
+ if self.is_proc_macro() {
+ return None;
+ }
self.source(db).value.name().map(|it| it.as_name())
}
Impl(Impl),
// enum variants cannot have generics themselves, but their parent enums
// can, and this makes some code easier to write
- EnumVariant(EnumVariant),
+ Variant(Variant),
// consts can have type parameters from their parents (i.e. associated consts of traits)
Const(Const),
}
Trait,
TypeAlias,
Impl,
- EnumVariant,
+ Variant,
Const
for GenericDef
);
impls.for_trait(trait_.id).map(Self::from).collect()
}
+ // FIXME: the return type is wrong. This should be a hir version of
+ // `TraitRef` (ie, resolved `TypeRef`).
pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> {
db.impl_data(self.id).target_trait.clone()
}
- pub fn target_type(self, db: &dyn HirDatabase) -> TypeRef {
- db.impl_data(self.id).target_type.clone()
- }
-
pub fn target_ty(self, db: &dyn HirDatabase) -> Type {
let impl_data = db.impl_data(self.id);
let resolver = self.id.resolver(db.upcast());
let item = src.file_id.is_builtin_derive(db.upcast())?;
let hygenic = hir_expand::hygiene::Hygiene::new(db.upcast(), item.file_id);
+ // FIXME: handle `cfg_attr`
let attr = item
.value
.attrs()
pub enum CallableKind {
Function(Function),
TupleStruct(Struct),
- TupleEnumVariant(EnumVariant),
+ TupleEnumVariant(Variant),
Closure,
}
};
use crate::{
- Adt, AssocItem, DefWithBody, EnumVariant, Field, GenericDef, Local, MacroDef, ModuleDef,
- VariantDef,
+ Adt, AssocItem, DefWithBody, Field, GenericDef, Local, MacroDef, ModuleDef, Variant, VariantDef,
};
macro_rules! from_id {
}
}
-impl From<EnumVariantId> for EnumVariant {
+impl From<EnumVariantId> for Variant {
fn from(id: EnumVariantId) -> Self {
- EnumVariant { parent: id.parent.into(), id: id.local_id }
+ Variant { parent: id.parent.into(), id: id.local_id }
}
}
-impl From<EnumVariant> for EnumVariantId {
- fn from(def: EnumVariant) -> Self {
+impl From<Variant> for EnumVariantId {
+ fn from(def: Variant) -> Self {
EnumVariantId { parent: def.parent.id, local_id: def.id }
}
}
ModuleDefId::ModuleId(it) => ModuleDef::Module(it.into()),
ModuleDefId::FunctionId(it) => ModuleDef::Function(it.into()),
ModuleDefId::AdtId(it) => ModuleDef::Adt(it.into()),
- ModuleDefId::EnumVariantId(it) => ModuleDef::EnumVariant(it.into()),
+ ModuleDefId::EnumVariantId(it) => ModuleDef::Variant(it.into()),
ModuleDefId::ConstId(it) => ModuleDef::Const(it.into()),
ModuleDefId::StaticId(it) => ModuleDef::Static(it.into()),
ModuleDefId::TraitId(it) => ModuleDef::Trait(it.into()),
ModuleDef::Module(it) => ModuleDefId::ModuleId(it.into()),
ModuleDef::Function(it) => ModuleDefId::FunctionId(it.into()),
ModuleDef::Adt(it) => ModuleDefId::AdtId(it.into()),
- ModuleDef::EnumVariant(it) => ModuleDefId::EnumVariantId(it.into()),
+ ModuleDef::Variant(it) => ModuleDefId::EnumVariantId(it.into()),
ModuleDef::Const(it) => ModuleDefId::ConstId(it.into()),
ModuleDef::Static(it) => ModuleDefId::StaticId(it.into()),
ModuleDef::Trait(it) => ModuleDefId::TraitId(it.into()),
GenericDef::Trait(it) => GenericDefId::TraitId(it.id),
GenericDef::TypeAlias(it) => GenericDefId::TypeAliasId(it.id),
GenericDef::Impl(it) => GenericDefId::ImplId(it.id),
- GenericDef::EnumVariant(it) => {
+ GenericDef::Variant(it) => {
GenericDefId::EnumVariantId(EnumVariantId { parent: it.parent.id, local_id: it.id })
}
GenericDef::Const(it) => GenericDefId::ConstId(it.id),
GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()),
GenericDefId::ImplId(it) => GenericDef::Impl(it.into()),
GenericDefId::EnumVariantId(it) => {
- GenericDef::EnumVariant(EnumVariant { parent: it.parent.into(), id: it.local_id })
+ GenericDef::Variant(Variant { parent: it.parent.into(), id: it.local_id })
}
GenericDefId::ConstId(it) => GenericDef::Const(it.into()),
}
fn from(def: VariantId) -> Self {
match def {
VariantId::StructId(it) => VariantDef::Struct(it.into()),
- VariantId::EnumVariantId(it) => VariantDef::EnumVariant(it.into()),
+ VariantId::EnumVariantId(it) => VariantDef::Variant(it.into()),
VariantId::UnionId(it) => VariantDef::Union(it.into()),
}
}
fn from(def: VariantDef) -> Self {
match def {
VariantDef::Struct(it) => VariantId::StructId(it.id),
- VariantDef::EnumVariant(it) => VariantId::EnumVariantId(it.into()),
+ VariantDef::Variant(it) => VariantId::EnumVariantId(it.into()),
VariantDef::Union(it) => VariantId::UnionId(it.id),
}
}
use syntax::ast;
use crate::{
- db::HirDatabase, Const, Enum, EnumVariant, Field, FieldSource, Function, Impl, LifetimeParam,
- MacroDef, Module, Static, Struct, Trait, TypeAlias, TypeParam, Union,
+ db::HirDatabase, Const, Enum, Field, FieldSource, Function, Impl, LifetimeParam, MacroDef,
+ Module, Static, Struct, Trait, TypeAlias, TypeParam, Union, Variant,
};
pub trait HasSource {
self.id.lookup(db.upcast()).source(db.upcast())
}
}
-impl HasSource for EnumVariant {
+impl HasSource for Variant {
type Ast = ast::Variant;
fn source(self, db: &dyn HirDatabase) -> InFile<ast::Variant> {
self.parent.id.child_source(db.upcast()).map(|map| map[self.id].clone())
attrs::{HasAttrs, Namespace},
code_model::{
Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, Callable, CallableKind, Const,
- Crate, CrateDependency, DefWithBody, Enum, EnumVariant, Field, FieldSource, Function,
- GenericDef, HasVisibility, Impl, LifetimeParam, Local, MacroDef, Module, ModuleDef,
- ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef,
+ Crate, CrateDependency, DefWithBody, Enum, Field, FieldSource, Function, GenericDef,
+ HasVisibility, Impl, LifetimeParam, Local, MacroDef, Module, ModuleDef, ScopeDef, Static,
+ Struct, Trait, Type, TypeAlias, TypeParam, Union, Variant, VariantDef,
},
has_source::HasSource,
semantics::{PathResolution, Semantics, SemanticsScope},
Some(TypeNs::BuiltinType(*builtin))
}
PathResolution::Def(ModuleDef::Const(_))
- | PathResolution::Def(ModuleDef::EnumVariant(_))
+ | PathResolution::Def(ModuleDef::Variant(_))
| PathResolution::Def(ModuleDef::Function(_))
| PathResolution::Def(ModuleDef::Module(_))
| PathResolution::Def(ModuleDef::Static(_))
(crate::Function, ast::Fn, fn_to_def),
(crate::Field, ast::RecordField, record_field_to_def),
(crate::Field, ast::TupleField, tuple_field_to_def),
- (crate::EnumVariant, ast::Variant, enum_variant_to_def),
+ (crate::Variant, ast::Variant, enum_variant_to_def),
(crate::TypeParam, ast::TypeParam, type_param_to_def),
(crate::LifetimeParam, ast::LifetimeParam, lifetime_param_to_def),
(crate::MacroDef, ast::MacroRules, macro_rules_to_def),
};
use crate::{
- db::HirDatabase, semantics::PathResolution, Adt, Const, EnumVariant, Field, Function, Local,
- MacroDef, ModuleDef, Static, Struct, Trait, Type, TypeAlias, TypeParam,
+ db::HirDatabase, semantics::PathResolution, Adt, Const, Field, Function, Local, MacroDef,
+ ModuleDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Variant,
};
use base_db::CrateId;
if let Some(VariantId::EnumVariantId(variant)) =
self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
{
- return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into())));
+ return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
}
}
if let Some(VariantId::EnumVariantId(variant)) =
self.infer.as_ref()?.variant_resolution_for_pat(pat_id)
{
- return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into())));
+ return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
}
}
if let Some(VariantId::EnumVariantId(variant)) =
self.infer.as_ref()?.variant_resolution_for_expr(expr_id)
{
- return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into())));
+ return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
}
}
if let Some(VariantId::EnumVariantId(variant)) =
self.infer.as_ref()?.variant_resolution_for_pat(pat_id)
{
- return Some(PathResolution::Def(ModuleDef::EnumVariant(variant.into())));
+ return Some(PathResolution::Def(ModuleDef::Variant(variant.into())));
}
}
TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
PathResolution::Def(Adt::from(it).into())
}
- TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),
+ TypeNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
TypeNs::BuiltinType(it) => PathResolution::Def(it.into()),
TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
ValueNs::ConstId(it) => PathResolution::Def(Const::from(it).into()),
ValueNs::StaticId(it) => PathResolution::Def(Static::from(it).into()),
ValueNs::StructId(it) => PathResolution::Def(Struct::from(it).into()),
- ValueNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),
+ ValueNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
ValueNs::ImplSelf(impl_id) => PathResolution::SelfType(impl_id.into()),
};
Some(res)
TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }),
TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => PathResolution::Def(Adt::from(it).into()),
- TypeNs::EnumVariantId(it) => PathResolution::Def(EnumVariant::from(it).into()),
+ TypeNs::EnumVariantId(it) => PathResolution::Def(Variant::from(it).into()),
TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
TypeNs::BuiltinType(it) => PathResolution::Def(it.into()),
TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
use std::sync::Arc;
use arena::{map::ArenaMap, Arena};
+use base_db::CrateId;
use either::Either;
use hir_expand::{
name::{AsName, Name},
Other,
}
-fn repr_from_value(item_tree: &ItemTree, of: AttrOwner) -> Option<ReprKind> {
- item_tree.attrs(of).by_key("repr").tt_values().find_map(parse_repr_tt)
+fn repr_from_value(
+ db: &dyn DefDatabase,
+ krate: CrateId,
+ item_tree: &ItemTree,
+ of: AttrOwner,
+) -> Option<ReprKind> {
+ item_tree.attrs(db, krate, of).by_key("repr").tt_values().find_map(parse_repr_tt)
}
fn parse_repr_tt(tt: &Subtree) -> Option<ReprKind> {
impl StructData {
pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc<StructData> {
let loc = id.lookup(db);
+ let krate = loc.container.module(db).krate;
let item_tree = db.item_tree(loc.id.file_id);
- let repr = repr_from_value(&item_tree, ModItem::from(loc.id.value).into());
+ let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
let strukt = &item_tree[loc.id.value];
- let variant_data = lower_fields(&item_tree, &cfg_options, &strukt.fields, None);
+ let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &strukt.fields, None);
Arc::new(StructData {
name: strukt.name.clone(),
variant_data: Arc::new(variant_data),
}
pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc<StructData> {
let loc = id.lookup(db);
+ let krate = loc.container.module(db).krate;
let item_tree = db.item_tree(loc.id.file_id);
- let repr = repr_from_value(&item_tree, ModItem::from(loc.id.value).into());
+ let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into());
let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
let union = &item_tree[loc.id.value];
- let variant_data = lower_fields(&item_tree, &cfg_options, &union.fields, None);
+ let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &union.fields, None);
Arc::new(StructData {
name: union.name.clone(),
impl EnumData {
pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc<EnumData> {
let loc = e.lookup(db);
+ let krate = loc.container.module(db).krate;
let item_tree = db.item_tree(loc.id.file_id);
- let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone();
+ let cfg_options = db.crate_graph()[krate].cfg_options.clone();
let enum_ = &item_tree[loc.id.value];
let mut variants = Arena::new();
for var_id in enum_.variants.clone() {
- if item_tree.attrs(var_id.into()).is_cfg_enabled(&cfg_options) {
+ if item_tree.attrs(db, krate, var_id.into()).is_cfg_enabled(&cfg_options) {
let var = &item_tree[var_id];
- let var_data =
- lower_fields(&item_tree, &cfg_options, &var.fields, Some(enum_.visibility));
+ let var_data = lower_fields(
+ db,
+ krate,
+ &item_tree,
+ &cfg_options,
+ &var.fields,
+ Some(enum_.visibility),
+ );
variants.alloc(EnumVariantData {
name: var.name.clone(),
.variant_list()
.into_iter()
.flat_map(|it| it.variants())
- .filter(|var| expander.is_cfg_enabled(var));
+ .filter(|var| expander.is_cfg_enabled(db, var));
for var in variants {
trace.alloc(
|| var.clone(),
match &ast.value {
ast::StructKind::Tuple(fl) => {
for (i, fd) in fl.fields().enumerate() {
- if !expander.is_cfg_enabled(&fd) {
+ if !expander.is_cfg_enabled(db, &fd) {
continue;
}
}
ast::StructKind::Record(fl) => {
for fd in fl.fields() {
- if !expander.is_cfg_enabled(&fd) {
+ if !expander.is_cfg_enabled(db, &fd) {
continue;
}
}
fn lower_fields(
+ db: &dyn DefDatabase,
+ krate: CrateId,
item_tree: &ItemTree,
cfg_options: &CfgOptions,
fields: &Fields,
Fields::Record(flds) => {
let mut arena = Arena::new();
for field_id in flds.clone() {
- if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) {
+ if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) {
arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
}
}
Fields::Tuple(flds) => {
let mut arena = Arena::new();
for field_id in flds.clone() {
- if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) {
+ if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) {
arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility));
}
}
use std::{ops, sync::Arc};
+use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions};
use either::Either;
-use hir_expand::{hygiene::Hygiene, AstId, InFile};
+use hir_expand::{hygiene::Hygiene, name::AsName, AstId, InFile};
use itertools::Itertools;
use mbe::ast_to_token_tree;
use syntax::{
ast::{self, AstNode, AttrsOwner},
match_ast, AstToken, SmolStr, SyntaxNode,
};
+use test_utils::mark;
use tt::Subtree;
use crate::{
db::DefDatabase,
item_tree::{ItemTreeId, ItemTreeNode},
nameres::ModuleSource,
- path::ModPath,
+ path::{ModPath, PathKind},
src::HasChildSource,
AdtId, AttrDefId, Lookup,
};
}
}
+/// Syntactical attributes, without filtering of `cfg_attr`s.
#[derive(Default, Debug, Clone, PartialEq, Eq)]
-pub struct Attrs {
+pub(crate) struct RawAttrs {
entries: Option<Arc<[Attr]>>,
}
-impl ops::Deref for Attrs {
+#[derive(Default, Debug, Clone, PartialEq, Eq)]
+pub struct Attrs(RawAttrs);
+
+impl ops::Deref for RawAttrs {
type Target = [Attr];
fn deref(&self) -> &[Attr] {
}
}
+impl ops::Deref for Attrs {
+ type Target = [Attr];
+
+ fn deref(&self) -> &[Attr] {
+ match &self.0.entries {
+ Some(it) => &*it,
+ None => &[],
+ }
+ }
+}
+
+impl RawAttrs {
+ pub(crate) const EMPTY: Self = Self { entries: None };
+
+ pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Self {
+ let attrs: Vec<_> = collect_attrs(owner).collect();
+ let entries = if attrs.is_empty() {
+ // Avoid heap allocation
+ None
+ } else {
+ Some(
+ attrs
+ .into_iter()
+ .enumerate()
+ .flat_map(|(i, attr)| match attr {
+ Either::Left(attr) => Attr::from_src(attr, hygiene).map(|attr| (i, attr)),
+ Either::Right(comment) => comment.doc_comment().map(|doc| {
+ (
+ i,
+ Attr {
+ index: 0,
+ input: Some(AttrInput::Literal(SmolStr::new(doc))),
+ path: ModPath::from(hir_expand::name!(doc)),
+ },
+ )
+ }),
+ })
+ .map(|(i, attr)| Attr { index: i as u32, ..attr })
+ .collect(),
+ )
+ };
+ Self { entries }
+ }
+
+ fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Self {
+ let hygiene = Hygiene::new(db.upcast(), owner.file_id);
+ Self::new(owner.value, &hygiene)
+ }
+
+ pub(crate) fn merge(&self, other: Self) -> Self {
+ match (&self.entries, &other.entries) {
+ (None, None) => Self::EMPTY,
+ (Some(entries), None) | (None, Some(entries)) => {
+ Self { entries: Some(entries.clone()) }
+ }
+ (Some(a), Some(b)) => {
+ Self { entries: Some(a.iter().chain(b.iter()).cloned().collect()) }
+ }
+ }
+ }
+
+ /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
+ pub(crate) fn filter(self, db: &dyn DefDatabase, krate: CrateId) -> Attrs {
+ let has_cfg_attrs = self.iter().any(|attr| {
+ attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr])
+ });
+ if !has_cfg_attrs {
+ return Attrs(self);
+ }
+
+ let crate_graph = db.crate_graph();
+ let new_attrs = self
+ .iter()
+ .filter_map(|attr| {
+ let attr = attr.clone();
+ let is_cfg_attr =
+ attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr]);
+ if !is_cfg_attr {
+ return Some(attr);
+ }
+
+ let subtree = match &attr.input {
+ Some(AttrInput::TokenTree(it)) => it,
+ _ => return Some(attr),
+ };
+
+ // Input subtree is: `(cfg, attr)`
+ // Split it up into a `cfg` and an `attr` subtree.
+ // FIXME: There should be a common API for this.
+ let mut saw_comma = false;
+ let (mut cfg, attr): (Vec<_>, Vec<_>) =
+ subtree.clone().token_trees.into_iter().partition(|tree| {
+ if saw_comma {
+ return false;
+ }
+
+ match tree {
+ tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => {
+ saw_comma = true;
+ }
+ _ => {}
+ }
+
+ true
+ });
+ cfg.pop(); // `,` ends up in here
+
+ let attr = Subtree { delimiter: None, token_trees: attr };
+ let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg };
+ let cfg = CfgExpr::parse(&cfg);
+
+ let cfg_options = &crate_graph[krate].cfg_options;
+ if cfg_options.check(&cfg) == Some(false) {
+ None
+ } else {
+ mark::hit!(cfg_attr_active);
+
+ let attr = ast::Attr::parse(&format!("#[{}]", attr)).ok()?;
+ let hygiene = Hygiene::new_unhygienic(); // FIXME
+ Attr::from_src(attr, &hygiene)
+ }
+ })
+ .collect();
+
+ Attrs(RawAttrs { entries: Some(new_attrs) })
+ }
+}
+
impl Attrs {
- pub const EMPTY: Attrs = Attrs { entries: None };
+ pub const EMPTY: Self = Self(RawAttrs::EMPTY);
pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs {
- match def {
+ let raw_attrs = match def {
AttrDefId::ModuleId(module) => {
let def_map = db.crate_def_map(module.krate);
let mod_data = &def_map[module.local_id];
match mod_data.declaration_source(db) {
Some(it) => {
- Attrs::from_attrs_owner(db, it.as_ref().map(|it| it as &dyn AttrsOwner))
+ RawAttrs::from_attrs_owner(db, it.as_ref().map(|it| it as &dyn AttrsOwner))
}
- None => Attrs::from_attrs_owner(
+ None => RawAttrs::from_attrs_owner(
db,
mod_data.definition_source(db).as_ref().map(|src| match src {
ModuleSource::SourceFile(file) => file as &dyn AttrsOwner,
AttrDefId::FieldId(it) => {
let src = it.parent.child_source(db);
match &src.value[it.local_id] {
- Either::Left(_tuple) => Attrs::default(),
- Either::Right(record) => Attrs::from_attrs_owner(db, src.with_value(record)),
+ Either::Left(_tuple) => RawAttrs::default(),
+ Either::Right(record) => RawAttrs::from_attrs_owner(db, src.with_value(record)),
}
}
AttrDefId::EnumVariantId(var_id) => {
let src = var_id.parent.child_source(db);
let src = src.as_ref().map(|it| &it[var_id.local_id]);
- Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner))
+ RawAttrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner))
}
AttrDefId::AdtId(it) => match it {
AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db),
AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db),
- }
- }
-
- pub fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Attrs {
- let hygiene = Hygiene::new(db.upcast(), owner.file_id);
- Attrs::new(owner.value, &hygiene)
- }
-
- pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs {
- let (inner_attrs, inner_docs) = inner_attributes(owner.syntax())
- .map_or((None, None), |(attrs, docs)| ((Some(attrs), Some(docs))));
-
- let outer_attrs = owner.attrs().filter(|attr| attr.excl_token().is_none());
- let attrs = outer_attrs
- .chain(inner_attrs.into_iter().flatten())
- .map(|attr| (attr.syntax().text_range().start(), Attr::from_src(attr, hygiene)));
-
- let outer_docs =
- ast::CommentIter::from_syntax_node(owner.syntax()).filter(ast::Comment::is_outer);
- let docs = outer_docs.chain(inner_docs.into_iter().flatten()).map(|docs_text| {
- (
- docs_text.syntax().text_range().start(),
- docs_text.doc_comment().map(|doc| Attr {
- input: Some(AttrInput::Literal(SmolStr::new(doc))),
- path: ModPath::from(hir_expand::name!(doc)),
- }),
- )
- });
- // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved
- let attrs: Vec<_> = docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).collect();
- let entries = if attrs.is_empty() {
- // Avoid heap allocation
- None
- } else {
- Some(attrs.into_iter().flat_map(|(_, attr)| attr).collect())
};
- Attrs { entries }
- }
- pub fn merge(&self, other: Attrs) -> Attrs {
- match (&self.entries, &other.entries) {
- (None, None) => Attrs { entries: None },
- (Some(entries), None) | (None, Some(entries)) => {
- Attrs { entries: Some(entries.clone()) }
- }
- (Some(a), Some(b)) => {
- Attrs { entries: Some(a.iter().chain(b.iter()).cloned().collect()) }
- }
- }
+ raw_attrs.filter(db, def.krate(db))
}
pub fn by_key(&self, key: &'static str) -> AttrQuery<'_> {
}
pub fn cfg(&self) -> Option<CfgExpr> {
- // FIXME: handle cfg_attr :-)
let mut cfgs = self.by_key("cfg").tt_values().map(CfgExpr::parse).collect::<Vec<_>>();
match cfgs.len() {
0 => None,
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Attr {
+ index: u32,
pub(crate) path: ModPath,
pub(crate) input: Option<AttrInput>,
}
} else {
None
};
- Some(Attr { path, input })
+ Some(Attr { index: 0, path, input })
+ }
+
+ /// Maps this lowered `Attr` back to its original syntax node.
+ ///
+ /// `owner` must be the original owner of the attribute.
+ ///
+ /// Note that the returned syntax node might be a `#[cfg_attr]`, or a doc comment, instead of
+ /// the attribute represented by `Attr`.
+ pub fn to_src(&self, owner: &dyn AttrsOwner) -> Either<ast::Attr, ast::Comment> {
+ collect_attrs(owner).nth(self.index as usize).unwrap_or_else(|| {
+ panic!("cannot find `Attr` at index {} in {}", self.index, owner.syntax())
+ })
+ }
+
+ /// Parses this attribute as a `#[derive]`, returns an iterator that yields all contained paths
+ /// to derive macros.
+ ///
+ /// Returns `None` when the attribute is not a well-formed `#[derive]` attribute.
+ pub(crate) fn parse_derive(&self) -> Option<impl Iterator<Item = ModPath>> {
+ if self.path.as_ident() != Some(&hir_expand::name![derive]) {
+ return None;
+ }
+
+ match &self.input {
+ Some(AttrInput::TokenTree(args)) => {
+ let mut counter = 0;
+ let paths = args
+ .token_trees
+ .iter()
+ .group_by(move |tt| {
+ match tt {
+ tt::TokenTree::Leaf(tt::Leaf::Punct(p)) if p.char == ',' => {
+ counter += 1;
+ }
+ _ => {}
+ }
+ counter
+ })
+ .into_iter()
+ .map(|(_, tts)| {
+ let segments = tts.filter_map(|tt| match tt {
+ tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => Some(id.as_name()),
+ _ => None,
+ });
+ ModPath::from_segments(PathKind::Plain, segments)
+ })
+ .collect::<Vec<_>>();
+
+ Some(paths.into_iter())
+ }
+ _ => None,
+ }
}
}
self.attrs().next().is_some()
}
- fn attrs(self) -> impl Iterator<Item = &'a Attr> {
+ pub(crate) fn attrs(self) -> impl Iterator<Item = &'a Attr> {
let key = self.key;
self.attrs
.iter()
}
}
-fn attrs_from_ast<N>(src: AstId<N>, db: &dyn DefDatabase) -> Attrs
+fn attrs_from_ast<N>(src: AstId<N>, db: &dyn DefDatabase) -> RawAttrs
where
N: ast::AttrsOwner,
{
let src = InFile::new(src.file_id, src.to_node(db.upcast()));
- Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner))
+ RawAttrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner))
}
-fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase) -> Attrs {
+fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase) -> RawAttrs {
let tree = db.item_tree(id.file_id);
let mod_item = N::id_to_mod_item(id.value);
- tree.attrs(mod_item.into()).clone()
+ tree.raw_attrs(mod_item.into()).clone()
+}
+
+fn collect_attrs(owner: &dyn AttrsOwner) -> impl Iterator<Item = Either<ast::Attr, ast::Comment>> {
+ let (inner_attrs, inner_docs) = inner_attributes(owner.syntax())
+ .map_or((None, None), |(attrs, docs)| ((Some(attrs), Some(docs))));
+
+ let outer_attrs = owner.attrs().filter(|attr| attr.excl_token().is_none());
+ let attrs = outer_attrs
+ .chain(inner_attrs.into_iter().flatten())
+ .map(|attr| (attr.syntax().text_range().start(), Either::Left(attr)));
+
+ let outer_docs =
+ ast::CommentIter::from_syntax_node(owner.syntax()).filter(ast::Comment::is_outer);
+ let docs = outer_docs
+ .chain(inner_docs.into_iter().flatten())
+ .map(|docs_text| (docs_text.syntax().text_range().start(), Either::Right(docs_text)));
+ // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved
+ let attrs: Vec<_> = docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).collect();
+
+ attrs.into_iter().map(|(_, attr)| attr)
}
pub(crate) use lower::LowerCtx;
use crate::{
- attr::Attrs,
+ attr::{Attrs, RawAttrs},
db::DefDatabase,
expr::{Expr, ExprId, Pat, PatId},
item_scope::BuiltinShadowMode,
pub(crate) struct CfgExpander {
cfg_options: CfgOptions,
hygiene: Hygiene,
+ krate: CrateId,
}
pub(crate) struct Expander {
) -> CfgExpander {
let hygiene = Hygiene::new(db.upcast(), current_file_id);
let cfg_options = db.crate_graph()[krate].cfg_options.clone();
- CfgExpander { cfg_options, hygiene }
+ CfgExpander { cfg_options, hygiene, krate }
}
- pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs {
- Attrs::new(owner, &self.hygiene)
+ pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> Attrs {
+ RawAttrs::new(owner, &self.hygiene).filter(db, self.krate)
}
- pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool {
- let attrs = self.parse_attrs(owner);
+ pub(crate) fn is_cfg_enabled(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> bool {
+ let attrs = self.parse_attrs(db, owner);
attrs.is_cfg_enabled(&self.cfg_options)
}
}
InFile { file_id: self.current_file_id, value }
}
- pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs {
- self.cfg_expander.parse_attrs(owner)
+ pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> Attrs {
+ self.cfg_expander.parse_attrs(db, owner)
}
pub(crate) fn cfg_options(&self) -> &CfgOptions {
/// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when
/// not.
fn check_cfg(&mut self, owner: &dyn ast::AttrsOwner) -> Option<()> {
- match self.expander.parse_attrs(owner).cfg() {
+ match self.expander.parse_attrs(self.db, owner).cfg() {
Some(cfg) => {
if self.expander.cfg_options().check(&cfg) != Some(false) {
return Some(());
impl FunctionData {
pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc<FunctionData> {
let loc = func.lookup(db);
+ let krate = loc.container.module(db).krate;
let item_tree = db.item_tree(loc.id.file_id);
let func = &item_tree[loc.id.value];
name: func.name.clone(),
params: func.params.to_vec(),
ret_type: func.ret_type.clone(),
- attrs: item_tree.attrs(ModItem::from(loc.id.value).into()).clone(),
+ attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()).clone(),
has_self_param: func.has_self_param,
has_body: func.has_body,
is_unsafe: func.is_unsafe,
match item {
AssocItem::Function(id) => {
let item = &item_tree[id];
- let attrs = item_tree.attrs(ModItem::from(id).into());
+ let attrs = item_tree.attrs(db, module.krate, ModItem::from(id).into());
if !attrs.is_cfg_enabled(&cfg_options) {
continue;
}
};
use arena::{Arena, Idx, RawId};
-use ast::{AstNode, AttrsOwner, NameOwner, StructKind};
+use ast::{AstNode, NameOwner, StructKind};
+use base_db::CrateId;
use either::Either;
use hir_expand::{
ast_id_map::FileAstId,
use test_utils::mark;
use crate::{
- attr::Attrs,
+ attr::{Attrs, RawAttrs},
db::DefDatabase,
generics::GenericParams,
path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind},
#[derive(Debug, Eq, PartialEq)]
pub struct ItemTree {
top_level: SmallVec<[ModItem; 1]>,
- attrs: FxHashMap<AttrOwner, Attrs>,
+ attrs: FxHashMap<AttrOwner, RawAttrs>,
inner_items: FxHashMap<FileAstId<ast::Item>, SmallVec<[ModItem; 1]>>,
data: Option<Box<ItemTreeData>>,
let mut item_tree = match_ast! {
match syntax {
ast::SourceFile(file) => {
- top_attrs = Some(Attrs::new(&file, &hygiene));
+ top_attrs = Some(RawAttrs::new(&file, &hygiene));
ctx.lower_module_items(&file)
},
ast::MacroItems(items) => {
}
/// Returns the inner attributes of the source file.
- pub fn top_level_attrs(&self) -> &Attrs {
- self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&Attrs::EMPTY)
+ pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: CrateId) -> Attrs {
+ self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&RawAttrs::EMPTY).clone().filter(db, krate)
}
- pub fn attrs(&self, of: AttrOwner) -> &Attrs {
- self.attrs.get(&of).unwrap_or(&Attrs::EMPTY)
+ pub(crate) fn raw_attrs(&self, of: AttrOwner) -> &RawAttrs {
+ self.attrs.get(&of).unwrap_or(&RawAttrs::EMPTY)
+ }
+
+ pub fn attrs(&self, db: &dyn DefDatabase, krate: CrateId, of: AttrOwner) -> Attrs {
+ self.raw_attrs(of).clone().filter(db, krate)
}
/// Returns the lowered inner items that `ast` corresponds to.
pub alias: Option<ImportAlias>,
pub visibility: RawVisibilityId,
pub is_glob: bool,
- pub is_prelude: bool,
/// AST ID of the `use` or `extern crate` item this import was derived from. Note that many
/// `Import`s can map to the same `use` item.
pub ast_id: FileAstId<ast::Use>,
pub name: Name,
pub alias: Option<ImportAlias>,
pub visibility: RawVisibilityId,
- /// Whether this is a `#[macro_use] extern crate ...`.
- pub is_macro_use: bool,
pub ast_id: FileAstId<ast::ExternCrate>,
}
};
use crate::{
- attr::Attrs,
generics::{GenericParams, TypeParamData, TypeParamProvenance},
type_ref::LifetimeRef,
};
| ast::Item::MacroDef(_) => {}
};
- let attrs = Attrs::new(item, &self.hygiene);
+ let attrs = RawAttrs::new(item, &self.hygiene);
let items = match item {
ast::Item::Struct(ast) => self.lower_struct(ast).map(Into::into),
ast::Item::Union(ast) => self.lower_union(ast).map(Into::into),
items
}
- fn add_attrs(&mut self, item: AttrOwner, attrs: Attrs) {
+ fn add_attrs(&mut self, item: AttrOwner, attrs: RawAttrs) {
match self.tree.attrs.entry(item) {
Entry::Occupied(mut entry) => {
*entry.get_mut() = entry.get().merge(attrs);
for field in fields.fields() {
if let Some(data) = self.lower_record_field(&field) {
let idx = self.data().fields.alloc(data);
- self.add_attrs(idx.into(), Attrs::new(&field, &self.hygiene));
+ self.add_attrs(idx.into(), RawAttrs::new(&field, &self.hygiene));
}
}
let end = self.next_field_idx();
for (i, field) in fields.fields().enumerate() {
let data = self.lower_tuple_field(i, &field);
let idx = self.data().fields.alloc(data);
- self.add_attrs(idx.into(), Attrs::new(&field, &self.hygiene));
+ self.add_attrs(idx.into(), RawAttrs::new(&field, &self.hygiene));
}
let end = self.next_field_idx();
IdRange::new(start..end)
for variant in variants.variants() {
if let Some(data) = self.lower_variant(&variant) {
let idx = self.data().variants.alloc(data);
- self.add_attrs(idx.into(), Attrs::new(&variant, &self.hygiene));
+ self.add_attrs(idx.into(), RawAttrs::new(&variant, &self.hygiene));
}
}
let end = self.next_variant_idx();
self.with_inherited_visibility(visibility, |this| {
list.assoc_items()
.filter_map(|item| {
- let attrs = Attrs::new(&item, &this.hygiene);
+ let attrs = RawAttrs::new(&item, &this.hygiene);
this.collect_inner_items(item.syntax());
this.lower_assoc_item(&item).map(|item| {
this.add_attrs(ModItem::from(item).into(), attrs);
.filter_map(|item| {
self.collect_inner_items(item.syntax());
let assoc = self.lower_assoc_item(&item)?;
- let attrs = Attrs::new(&item, &self.hygiene);
+ let attrs = RawAttrs::new(&item, &self.hygiene);
self.add_attrs(ModItem::from(assoc).into(), attrs);
Some(assoc)
})
}
fn lower_use(&mut self, use_item: &ast::Use) -> Vec<FileItemTreeId<Import>> {
- // FIXME: cfg_attr
- let is_prelude = use_item.has_atom_attr("prelude_import");
let visibility = self.lower_visibility(use_item);
let ast_id = self.source_ast_id_map.ast_id(use_item);
alias,
visibility,
is_glob,
- is_prelude,
ast_id,
index: imports.len(),
})));
});
let visibility = self.lower_visibility(extern_crate);
let ast_id = self.source_ast_id_map.ast_id(extern_crate);
- // FIXME: cfg_attr
- let is_macro_use = extern_crate.has_atom_attr("macro_use");
- let res = ExternCrate { name, alias, visibility, is_macro_use, ast_id };
+ let res = ExternCrate { name, alias, visibility, ast_id };
Some(id(self.data().extern_crates.alloc(res)))
}
list.extern_items()
.filter_map(|item| {
self.collect_inner_items(item.syntax());
- let attrs = Attrs::new(&item, &self.hygiene);
+ let attrs = RawAttrs::new(&item, &self.hygiene);
let id: ModItem = match item {
ast::ExternItem::Fn(ast) => {
let func_id = self.lower_function(&ast)?;
}
}
+impl HasModule for VariantId {
+ fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
+ match self {
+ VariantId::EnumVariantId(it) => it.parent.lookup(db).container.module(db),
+ VariantId::StructId(it) => it.lookup(db).container.module(db),
+ VariantId::UnionId(it) => it.lookup(db).container.module(db),
+ }
+ }
+}
+
impl HasModule for DefWithBodyId {
fn module(&self, db: &dyn db::DefDatabase) -> ModuleId {
match self {
}
}
+impl AttrDefId {
+ pub fn krate(&self, db: &dyn db::DefDatabase) -> CrateId {
+ match self {
+ AttrDefId::ModuleId(it) => it.krate,
+ AttrDefId::FieldId(it) => it.parent.module(db).krate,
+ AttrDefId::AdtId(it) => it.module(db).krate,
+ AttrDefId::FunctionId(it) => it.lookup(db).module(db).krate,
+ AttrDefId::EnumVariantId(it) => it.parent.lookup(db).container.module(db).krate,
+ AttrDefId::StaticId(it) => it.lookup(db).module(db).krate,
+ AttrDefId::ConstId(it) => it.lookup(db).module(db).krate,
+ AttrDefId::TraitId(it) => it.lookup(db).container.module(db).krate,
+ AttrDefId::TypeAliasId(it) => it.lookup(db).module(db).krate,
+ AttrDefId::ImplId(it) => it.lookup(db).container.module(db).krate,
+ // FIXME: `MacroDefId` should store the defining module, then this can implement
+ // `HasModule`
+ AttrDefId::MacroDefId(it) => it.krate,
+ }
+ }
+}
+
/// A helper trait for converting to MacroCallId
pub trait AsMacroCall {
fn as_call_id(
}
impl Import {
- fn from_use(tree: &ItemTree, id: ItemTreeId<item_tree::Import>) -> Self {
+ fn from_use(
+ db: &dyn DefDatabase,
+ krate: CrateId,
+ tree: &ItemTree,
+ id: ItemTreeId<item_tree::Import>,
+ ) -> Self {
let it = &tree[id.value];
+ let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
let visibility = &tree[it.visibility];
Self {
path: it.path.clone(),
alias: it.alias.clone(),
visibility: visibility.clone(),
is_glob: it.is_glob,
- is_prelude: it.is_prelude,
+ is_prelude: attrs.by_key("prelude_import").exists(),
is_extern_crate: false,
is_macro_use: false,
source: ImportSource::Import(id),
}
}
- fn from_extern_crate(tree: &ItemTree, id: ItemTreeId<item_tree::ExternCrate>) -> Self {
+ fn from_extern_crate(
+ db: &dyn DefDatabase,
+ krate: CrateId,
+ tree: &ItemTree,
+ id: ItemTreeId<item_tree::ExternCrate>,
+ ) -> Self {
let it = &tree[id.value];
+ let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
let visibility = &tree[it.visibility];
Self {
path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())),
is_glob: false,
is_prelude: false,
is_extern_crate: true,
- is_macro_use: it.is_macro_use,
+ is_macro_use: attrs.by_key("macro_use").exists(),
source: ImportSource::ExternCrate(id),
}
}
let item_tree = self.db.item_tree(file_id.into());
let module_id = self.def_map.root;
self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id };
- let mut root_collector = ModCollector {
- def_collector: &mut *self,
- macro_depth: 0,
- module_id,
- file_id: file_id.into(),
- item_tree: &item_tree,
- mod_dir: ModDir::root(),
- };
- if item_tree.top_level_attrs().cfg().map_or(true, |cfg| root_collector.is_cfg_enabled(&cfg))
+ if item_tree
+ .top_level_attrs(self.db, self.def_map.krate)
+ .cfg()
+ .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false))
{
- root_collector.collect(item_tree.top_level_items());
+ ModCollector {
+ def_collector: &mut *self,
+ macro_depth: 0,
+ module_id,
+ file_id: file_id.into(),
+ item_tree: &item_tree,
+ mod_dir: ModDir::root(),
+ }
+ .collect(item_tree.top_level_items());
}
// main name resolution fixed-point loop.
impl ModCollector<'_, '_> {
fn collect(&mut self, items: &[ModItem]) {
+ let krate = self.def_collector.def_map.krate;
+
// Note: don't assert that inserted value is fresh: it's simply not true
// for macros.
self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
// `#[macro_use] extern crate` is hoisted to imports macros before collecting
// any other items.
for item in items {
- let attrs = self.item_tree.attrs((*item).into());
+ let attrs = self.item_tree.attrs(self.def_collector.db, krate, (*item).into());
if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) {
if let ModItem::ExternCrate(id) = item {
let import = self.item_tree[*id].clone();
- if import.is_macro_use {
+ let attrs = self.item_tree.attrs(
+ self.def_collector.db,
+ krate,
+ ModItem::from(*id).into(),
+ );
+ if attrs.by_key("macro_use").exists() {
self.def_collector.import_macros_from_extern_crate(self.module_id, &import);
}
}
}
for &item in items {
- let attrs = self.item_tree.attrs(item.into());
+ let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
if let Some(cfg) = attrs.cfg() {
if !self.is_cfg_enabled(&cfg) {
self.emit_unconfigured_diagnostic(item, &cfg);
let mut def = None;
match item {
- ModItem::Mod(m) => self.collect_module(&self.item_tree[m], attrs),
+ ModItem::Mod(m) => self.collect_module(&self.item_tree[m], &attrs),
ModItem::Import(import_id) => {
self.def_collector.unresolved_imports.push(ImportDirective {
module_id: self.module_id,
import: Import::from_use(
+ self.def_collector.db,
+ krate,
&self.item_tree,
InFile::new(self.file_id, import_id),
),
self.def_collector.unresolved_imports.push(ImportDirective {
module_id: self.module_id,
import: Import::from_extern_crate(
+ self.def_collector.db,
+ krate,
&self.item_tree,
InFile::new(self.file_id, import_id),
),
// "Macro 2.0" is not currently supported by rust-analyzer, but libcore uses it
// to define builtin macros, so we support at least that part.
- let attrs = self.item_tree.attrs(ModItem::from(id).into());
+ let attrs = self.item_tree.attrs(
+ self.def_collector.db,
+ krate,
+ ModItem::from(id).into(),
+ );
if attrs.by_key("rustc_builtin_macro").exists() {
let krate = self.def_collector.def_map.krate;
let macro_id = find_builtin_macro(&mac.name, krate, ast_id)
ModItem::Function(id) => {
let func = &self.item_tree[id];
- self.collect_proc_macro_def(&func.name, attrs);
+ self.collect_proc_macro_def(&func.name, &attrs);
def = Some(DefData {
id: FunctionLoc {
// FIXME: check attrs to see if this is an attribute macro invocation;
// in which case we don't add the invocation, just a single attribute
// macro invocation
- self.collect_derives(attrs, it.ast_id.upcast());
+ self.collect_derives(&attrs, it.ast_id.upcast());
def = Some(DefData {
id: StructLoc { container, id: ItemTreeId::new(self.file_id, id) }
// FIXME: check attrs to see if this is an attribute macro invocation;
// in which case we don't add the invocation, just a single attribute
// macro invocation
- self.collect_derives(attrs, it.ast_id.upcast());
+ self.collect_derives(&attrs, it.ast_id.upcast());
def = Some(DefData {
id: UnionLoc { container, id: ItemTreeId::new(self.file_id, id) }
// FIXME: check attrs to see if this is an attribute macro invocation;
// in which case we don't add the invocation, just a single attribute
// macro invocation
- self.collect_derives(attrs, it.ast_id.upcast());
+ self.collect_derives(&attrs, it.ast_id.upcast());
def = Some(DefData {
id: EnumLoc { container, id: ItemTreeId::new(self.file_id, id) }
}
fn collect_derives(&mut self, attrs: &Attrs, ast_id: FileAstId<ast::Item>) {
- for derive_subtree in attrs.by_key("derive").tt_values() {
- // for #[derive(Copy, Clone)], `derive_subtree` is the `(Copy, Clone)` subtree
- for tt in &derive_subtree.token_trees {
- let ident = match &tt {
- tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => ident,
- tt::TokenTree::Leaf(tt::Leaf::Punct(_)) => continue, // , is ok
- _ => continue, // anything else would be an error (which we currently ignore)
- };
- let path = ModPath::from_tt_ident(ident);
-
- let ast_id = AstIdWithPath::new(self.file_id, ast_id, path);
- self.def_collector
- .unexpanded_attribute_macros
- .push(DeriveDirective { module_id: self.module_id, ast_id });
+ for derive in attrs.by_key("derive").attrs() {
+ match derive.parse_derive() {
+ Some(derive_macros) => {
+ for path in derive_macros {
+ let ast_id = AstIdWithPath::new(self.file_id, ast_id, path);
+ self.def_collector
+ .unexpanded_attribute_macros
+ .push(DeriveDirective { module_id: self.module_id, ast_id });
+ }
+ }
+ None => {
+ // FIXME: diagnose
+ log::debug!("malformed derive: {:?}", derive);
+ }
}
}
}
}
fn collect_macro_rules(&mut self, id: FileItemTreeId<MacroRules>) {
+ let krate = self.def_collector.def_map.krate;
let mac = &self.item_tree[id];
- let attrs = self.item_tree.attrs(ModItem::from(id).into());
+ let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
let ast_id = InFile::new(self.file_id, mac.ast_id.upcast());
let export_attr = attrs.by_key("macro_export");
use crate::{db::DefDatabase, nameres::*, test_db::TestDB};
-fn compute_crate_def_map(fixture: &str) -> Arc<CrateDefMap> {
- let db = TestDB::with_files(fixture);
+fn compute_crate_def_map(ra_fixture: &str) -> Arc<CrateDefMap> {
+ let db = TestDB::with_files(ra_fixture);
let krate = db.crate_graph().iter().next().unwrap();
db.crate_def_map(krate)
}
use base_db::fixture::WithFixture;
+use test_utils::mark;
use crate::test_db::TestDB;
"#,
);
}
+
+/// Tests that `cfg` attributes behind `cfg_attr` is handled properly.
+#[test]
+fn inactive_via_cfg_attr() {
+ mark::check!(cfg_attr_active);
+ check_diagnostics(
+ r#"
+ //- /lib.rs
+ #[cfg_attr(not(never), cfg(no))] fn f() {}
+ //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ code is inactive due to #[cfg] directives: no is disabled
+
+ #[cfg_attr(not(never), cfg(not(no)))] fn f() {}
+
+ #[cfg_attr(never, cfg(no))] fn g() {}
+ "#,
+ );
+}
#[test]
fn expand_derive() {
let map = compute_crate_def_map(
- "
+ r#"
//- /main.rs crate:main deps:core
- use core::*;
+ use core::Copy;
- #[derive(Copy, Clone)]
+ #[derive(Copy, core::Clone)]
struct Foo;
//- /core.rs crate:core
#[rustc_builtin_macro]
pub macro Clone {}
- ",
+ "#,
);
assert_eq!(map.modules[map.root].scope.impls().len(), 2);
}
use crate::{body::LowerCtx, type_ref::LifetimeRef};
use base_db::CrateId;
-use hir_expand::{
- hygiene::Hygiene,
- name::{AsName, Name},
-};
-use syntax::ast::{self};
+use hir_expand::{hygiene::Hygiene, name::Name};
+use syntax::ast;
use crate::{
type_ref::{TypeBound, TypeRef},
ModPath { kind, segments }
}
- /// Converts an `tt::Ident` into a single-identifier `Path`.
- pub(crate) fn from_tt_ident(ident: &tt::Ident) -> ModPath {
- ident.as_name().into()
- }
-
/// Calls `cb` with all paths, represented by this use item.
pub(crate) fn expand_use_item(
item_src: InFile<ast::Use>,
str,
// Special names
macro_rules,
+ derive,
doc,
+ cfg_attr,
// Components of known path (value or mod name)
std,
core,
call<|>ee();
}
"#,
- "callee FN FileId(0) 0..14 3..9",
- &["caller FN FileId(0) 15..44 18..24 : [33..39]"],
+ "callee Function FileId(0) 0..14 3..9",
+ &["caller Function FileId(0) 15..44 18..24 : [33..39]"],
&[],
);
}
callee();
}
"#,
- "callee FN FileId(0) 0..14 3..9",
- &["caller FN FileId(0) 15..44 18..24 : [33..39]"],
+ "callee Function FileId(0) 0..14 3..9",
+ &["caller Function FileId(0) 15..44 18..24 : [33..39]"],
&[],
);
}
callee();
}
"#,
- "callee FN FileId(0) 0..14 3..9",
- &["caller FN FileId(0) 15..58 18..24 : [33..39, 47..53]"],
+ "callee Function FileId(0) 0..14 3..9",
+ &["caller Function FileId(0) 15..58 18..24 : [33..39, 47..53]"],
&[],
);
}
callee();
}
"#,
- "callee FN FileId(0) 0..14 3..9",
+ "callee Function FileId(0) 0..14 3..9",
&[
- "caller1 FN FileId(0) 15..45 18..25 : [34..40]",
- "caller2 FN FileId(0) 47..77 50..57 : [66..72]",
+ "caller1 Function FileId(0) 15..45 18..25 : [34..40]",
+ "caller2 Function FileId(0) 47..77 50..57 : [66..72]",
],
&[],
);
}
}
"#,
- "callee FN FileId(0) 0..14 3..9",
+ "callee Function FileId(0) 0..14 3..9",
&[
- "caller1 FN FileId(0) 15..45 18..25 : [34..40]",
- "test_caller FN FileId(0) 95..149 110..121 : [134..140]",
+ "caller1 Function FileId(0) 15..45 18..25 : [34..40]",
+ "test_caller Function FileId(0) 95..149 110..121 : [134..140]",
],
&[],
);
//- /foo/mod.rs
pub fn callee() {}
"#,
- "callee FN FileId(1) 0..18 7..13",
- &["caller FN FileId(0) 27..56 30..36 : [45..51]"],
+ "callee Function FileId(1) 0..18 7..13",
+ &["caller Function FileId(0) 27..56 30..36 : [45..51]"],
&[],
);
}
callee();
}
"#,
- "caller FN FileId(0) 15..58 18..24",
+ "caller Function FileId(0) 15..58 18..24",
&[],
- &["callee FN FileId(0) 0..14 3..9 : [33..39, 47..53]"],
+ &["callee Function FileId(0) 0..14 3..9 : [33..39, 47..53]"],
);
}
//- /foo/mod.rs
pub fn callee() {}
"#,
- "caller FN FileId(0) 27..56 30..36",
+ "caller Function FileId(0) 27..56 30..36",
&[],
- &["callee FN FileId(1) 0..18 7..13 : [45..51]"],
+ &["callee Function FileId(1) 0..18 7..13 : [45..51]"],
);
}
}
"#,
- "caller2 FN FileId(0) 33..64 36..43",
- &["caller1 FN FileId(0) 0..31 3..10 : [19..26]"],
- &["caller3 FN FileId(0) 66..83 69..76 : [52..59]"],
+ "caller2 Function FileId(0) 33..64 36..43",
+ &["caller1 Function FileId(0) 0..31 3..10 : [19..26]"],
+ &["caller3 Function FileId(0) 66..83 69..76 : [52..59]"],
);
}
a<|>()
}
"#,
- "a FN FileId(0) 0..18 3..4",
- &["main FN FileId(0) 31..52 34..38 : [47..48]"],
- &["b FN FileId(0) 20..29 23..24 : [13..14]"],
+ "a Function FileId(0) 0..18 3..4",
+ &["main Function FileId(0) 31..52 34..38 : [47..48]"],
+ &["b Function FileId(0) 20..29 23..24 : [13..14]"],
);
check_hierarchy(
a()
}
"#,
- "b FN FileId(0) 20..29 23..24",
- &["a FN FileId(0) 0..18 3..4 : [13..14]"],
+ "b Function FileId(0) 20..29 23..24",
+ &["a Function FileId(0) 0..18 3..4 : [13..14]"],
&[],
);
}
def_file_id = source.file_id;
source.value.record_field_list()?
}
- VariantDef::EnumVariant(e) => {
+ VariantDef::Variant(e) => {
module = e.module(sema.db);
let source = e.source(sema.db);
def_file_id = source.file_id;
//! This module contains utilities for turning SyntaxNodes and HIR types
//! into types that may be used to render in a UI.
-mod navigation_target;
+pub(crate) mod navigation_target;
mod short_label;
-pub use navigation_target::NavigationTarget;
pub(crate) use navigation_target::{ToNav, TryToNav};
pub(crate) use short_label::ShortLabel;
//! FIXME: write short doc here
+use std::fmt;
+
use either::Either;
-use hir::{
- AssocItem, Documentation, FieldSource, HasAttrs, HasSource, HirFileId, InFile, ModuleSource,
+use hir::{AssocItem, Documentation, FieldSource, HasAttrs, HasSource, InFile, ModuleSource};
+use ide_db::{
+ base_db::{FileId, SourceDatabase},
+ symbol_index::FileSymbolKind,
};
-use ide_db::base_db::{FileId, SourceDatabase};
use ide_db::{defs::Definition, RootDatabase};
use syntax::{
ast::{self, NameOwner},
- match_ast, AstNode, SmolStr,
- SyntaxKind::{self, IDENT_PAT, LIFETIME_PARAM, TYPE_PARAM},
- TextRange,
+ match_ast, AstNode, SmolStr, TextRange,
};
use crate::FileSymbol;
use super::short_label::ShortLabel;
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub enum SymbolKind {
+ Module,
+ Impl,
+ Field,
+ TypeParam,
+ LifetimeParam,
+ ValueParam,
+ SelfParam,
+ Local,
+ Function,
+ Const,
+ Static,
+ Struct,
+ Enum,
+ Variant,
+ Union,
+ TypeAlias,
+ Trait,
+ Macro,
+}
+
/// `NavigationTarget` represents and element in the editor's UI which you can
/// click on to navigate to a particular piece of code.
///
/// Typically, a `NavigationTarget` corresponds to some element in the source
/// code, like a function or a struct, but this is not strictly required.
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+#[derive(Clone, PartialEq, Eq, Hash)]
pub struct NavigationTarget {
pub file_id: FileId,
/// Range which encompasses the whole element.
/// Clients should place the cursor on this range when navigating to this target.
pub focus_range: Option<TextRange>,
pub name: SmolStr,
- pub kind: SyntaxKind,
+ pub kind: Option<SymbolKind>,
pub container_name: Option<SmolStr>,
pub description: Option<String>,
pub docs: Option<Documentation>,
}
+impl fmt::Debug for NavigationTarget {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ let mut f = f.debug_struct("NavigationTarget");
+ macro_rules! opt {
+ ($($name:ident)*) => {$(
+ if let Some(it) = &self.$name {
+ f.field(stringify!($name), it);
+ }
+ )*}
+ }
+ f.field("file_id", &self.file_id).field("full_range", &self.full_range);
+ opt!(focus_range);
+ f.field("name", &self.name);
+ opt!(kind container_name description docs);
+ f.finish()
+ }
+}
+
pub(crate) trait ToNav {
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget;
}
name,
None,
frange.range,
- src.value.syntax().kind(),
+ SymbolKind::Module,
);
res.docs = module.attrs(db).docs();
res.description = src.value.short_label();
#[cfg(test)]
pub(crate) fn debug_render(&self) -> String {
- let mut buf =
- format!("{} {:?} {:?} {:?}", self.name, self.kind, self.file_id, self.full_range);
+ let mut buf = format!(
+ "{} {:?} {:?} {:?}",
+ self.name,
+ self.kind.unwrap(),
+ self.file_id,
+ self.full_range
+ );
if let Some(focus_range) = self.focus_range {
buf.push_str(&format!(" {:?}", focus_range))
}
pub(crate) fn from_named(
db: &RootDatabase,
node: InFile<&dyn ast::NameOwner>,
+ kind: SymbolKind,
) -> NavigationTarget {
let name =
node.value.name().map(|it| it.text().clone()).unwrap_or_else(|| SmolStr::new("_"));
node.value.name().map(|it| node.with_value(it.syntax()).original_file_range(db).range);
let frange = node.map(|it| it.syntax()).original_file_range(db);
- NavigationTarget::from_syntax(
- frange.file_id,
- name,
- focus_range,
- frange.range,
- node.value.syntax().kind(),
- )
- }
-
- /// Allows `NavigationTarget` to be created from a `DocCommentsOwner` and a `NameOwner`
- pub(crate) fn from_doc_commented(
- db: &RootDatabase,
- named: InFile<&dyn ast::NameOwner>,
- node: InFile<&dyn ast::DocCommentsOwner>,
- ) -> NavigationTarget {
- let name =
- named.value.name().map(|it| it.text().clone()).unwrap_or_else(|| SmolStr::new("_"));
- let frange = node.map(|it| it.syntax()).original_file_range(db);
-
- NavigationTarget::from_syntax(
- frange.file_id,
- name,
- None,
- frange.range,
- node.value.syntax().kind(),
- )
+ NavigationTarget::from_syntax(frange.file_id, name, focus_range, frange.range, kind)
}
fn from_syntax(
name: SmolStr,
focus_range: Option<TextRange>,
full_range: TextRange,
- kind: SyntaxKind,
+ kind: SymbolKind,
) -> NavigationTarget {
NavigationTarget {
file_id,
name,
- kind,
+ kind: Some(kind),
full_range,
focus_range,
container_name: None,
NavigationTarget {
file_id: self.file_id,
name: self.name.clone(),
- kind: self.kind,
+ kind: Some(match self.kind {
+ FileSymbolKind::Function => SymbolKind::Function,
+ FileSymbolKind::Struct => SymbolKind::Struct,
+ FileSymbolKind::Enum => SymbolKind::Enum,
+ FileSymbolKind::Trait => SymbolKind::Trait,
+ FileSymbolKind::Module => SymbolKind::Module,
+ FileSymbolKind::TypeAlias => SymbolKind::TypeAlias,
+ FileSymbolKind::Const => SymbolKind::Const,
+ FileSymbolKind::Static => SymbolKind::Static,
+ FileSymbolKind::Macro => SymbolKind::Macro,
+ }),
full_range: self.range,
focus_range: self.name_range,
container_name: self.container_name.clone(),
description: description_from_symbol(db, self),
- docs: docs_from_symbol(db, self),
+ docs: None,
}
}
}
impl TryToNav for Definition {
fn try_to_nav(&self, db: &RootDatabase) -> Option<NavigationTarget> {
match self {
- Definition::Macro(it) => Some(it.to_nav(db)),
+ Definition::Macro(it) => {
+ // FIXME: Currently proc-macro do not have ast-node,
+ // such that it does not have source
+ // more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913
+ if it.is_proc_macro() {
+ return None;
+ }
+ Some(it.to_nav(db))
+ }
Definition::Field(it) => Some(it.to_nav(db)),
Definition::ModuleDef(it) => it.try_to_nav(db),
Definition::SelfType(it) => Some(it.to_nav(db)),
hir::ModuleDef::Module(it) => it.to_nav(db),
hir::ModuleDef::Function(it) => it.to_nav(db),
hir::ModuleDef::Adt(it) => it.to_nav(db),
- hir::ModuleDef::EnumVariant(it) => it.to_nav(db),
+ hir::ModuleDef::Variant(it) => it.to_nav(db),
hir::ModuleDef::Const(it) => it.to_nav(db),
hir::ModuleDef::Static(it) => it.to_nav(db),
hir::ModuleDef::Trait(it) => it.to_nav(db),
}
}
-pub(crate) trait ToNavFromAst {}
-impl ToNavFromAst for hir::Function {}
-impl ToNavFromAst for hir::Const {}
-impl ToNavFromAst for hir::Static {}
-impl ToNavFromAst for hir::Struct {}
-impl ToNavFromAst for hir::Enum {}
-impl ToNavFromAst for hir::EnumVariant {}
-impl ToNavFromAst for hir::Union {}
-impl ToNavFromAst for hir::TypeAlias {}
-impl ToNavFromAst for hir::Trait {}
+pub(crate) trait ToNavFromAst {
+ const KIND: SymbolKind;
+}
+impl ToNavFromAst for hir::Function {
+ const KIND: SymbolKind = SymbolKind::Function;
+}
+impl ToNavFromAst for hir::Const {
+ const KIND: SymbolKind = SymbolKind::Const;
+}
+impl ToNavFromAst for hir::Static {
+ const KIND: SymbolKind = SymbolKind::Static;
+}
+impl ToNavFromAst for hir::Struct {
+ const KIND: SymbolKind = SymbolKind::Struct;
+}
+impl ToNavFromAst for hir::Enum {
+ const KIND: SymbolKind = SymbolKind::Enum;
+}
+impl ToNavFromAst for hir::Variant {
+ const KIND: SymbolKind = SymbolKind::Variant;
+}
+impl ToNavFromAst for hir::Union {
+ const KIND: SymbolKind = SymbolKind::Union;
+}
+impl ToNavFromAst for hir::TypeAlias {
+ const KIND: SymbolKind = SymbolKind::TypeAlias;
+}
+impl ToNavFromAst for hir::Trait {
+ const KIND: SymbolKind = SymbolKind::Trait;
+}
impl<D> ToNav for D
where
{
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
let src = self.source(db);
- let mut res =
- NavigationTarget::from_named(db, src.as_ref().map(|it| it as &dyn ast::NameOwner));
+ let mut res = NavigationTarget::from_named(
+ db,
+ src.as_ref().map(|it| it as &dyn ast::NameOwner),
+ D::KIND,
+ );
res.docs = self.docs(db);
res.description = src.value.short_label();
res
}
};
let frange = src.with_value(syntax).original_file_range(db);
- NavigationTarget::from_syntax(frange.file_id, name, focus, frange.range, syntax.kind())
+ NavigationTarget::from_syntax(frange.file_id, name, focus, frange.range, SymbolKind::Module)
}
}
"impl".into(),
focus_range,
frange.range,
- src.value.syntax().kind(),
+ SymbolKind::Impl,
)
}
}
match &src.value {
FieldSource::Named(it) => {
- let mut res = NavigationTarget::from_named(db, src.with_value(it));
+ let mut res =
+ NavigationTarget::from_named(db, src.with_value(it), SymbolKind::Field);
res.docs = self.docs(db);
res.description = it.short_label();
res
"".into(),
None,
frange.range,
- it.syntax().kind(),
+ SymbolKind::Field,
)
}
}
fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
let src = self.source(db);
log::debug!("nav target {:#?}", src.value.syntax());
- let mut res =
- NavigationTarget::from_named(db, src.as_ref().map(|it| it as &dyn ast::NameOwner));
+ let mut res = NavigationTarget::from_named(
+ db,
+ src.as_ref().map(|it| it as &dyn ast::NameOwner),
+ SymbolKind::Macro,
+ );
res.docs = self.docs(db);
res
}
Some(it) => it.to_string().into(),
None => "".into(),
};
+ let kind = if self.is_param(db) { SymbolKind::ValueParam } else { SymbolKind::Local };
NavigationTarget {
file_id: full_range.file_id,
name,
- kind: IDENT_PAT,
+ kind: Some(kind),
full_range: full_range.range,
focus_range: None,
container_name: None,
NavigationTarget {
file_id: src.file_id.original_file(db),
name: self.name(db).to_string().into(),
- kind: TYPE_PARAM,
+ kind: Some(SymbolKind::TypeParam),
full_range,
focus_range,
container_name: None,
NavigationTarget {
file_id: src.file_id.original_file(db),
name: self.name(db).to_string().into(),
- kind: LIFETIME_PARAM,
+ kind: Some(SymbolKind::LifetimeParam),
full_range,
focus_range: Some(full_range),
container_name: None,
}
}
-pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<Documentation> {
- let parse = db.parse(symbol.file_id);
- let node = symbol.ptr.to_node(parse.tree().syntax());
- let file_id = HirFileId::from(symbol.file_id);
-
- let it = match_ast! {
- match node {
- ast::Fn(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
- ast::Struct(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
- ast::Enum(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
- ast::Trait(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
- ast::Module(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
- ast::TypeAlias(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
- ast::Const(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
- ast::Static(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
- ast::RecordField(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
- ast::Variant(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
- ast::MacroCall(it) => hir::Attrs::from_attrs_owner(db, InFile::new(file_id, &it)),
- _ => return None,
- }
- };
- it.docs()
-}
-
/// Get a description of a symbol.
///
/// e.g. `struct Name`, `enum Name`, `fn Name`
0,
),
full_range: 0..17,
- focus_range: Some(
- 5..13,
- ),
+ focus_range: 5..13,
name: "FooInner",
- kind: ENUM,
- container_name: None,
- description: Some(
- "enum FooInner",
- ),
- docs: None,
+ kind: Enum,
+ description: "enum FooInner",
},
NavigationTarget {
file_id: FileId(
0,
),
full_range: 29..46,
- focus_range: Some(
- 34..42,
- ),
+ focus_range: 34..42,
name: "FooInner",
- kind: ENUM,
- container_name: Some(
- "foo",
- ),
- description: Some(
- "enum FooInner",
- ),
- docs: None,
+ kind: Enum,
+ container_name: "foo",
+ description: "enum FooInner",
},
]
"#]]
ModuleDef::Module(it) => it.resolve_doc_path(db, link, ns),
ModuleDef::Function(it) => it.resolve_doc_path(db, link, ns),
ModuleDef::Adt(it) => it.resolve_doc_path(db, link, ns),
- ModuleDef::EnumVariant(it) => it.resolve_doc_path(db, link, ns),
+ ModuleDef::Variant(it) => it.resolve_doc_path(db, link, ns),
ModuleDef::Const(it) => it.resolve_doc_path(db, link, ns),
ModuleDef::Static(it) => it.resolve_doc_path(db, link, ns),
ModuleDef::Trait(it) => it.resolve_doc_path(db, link, ns),
ModuleDef::TypeAlias(t) => format!("type.{}.html", t.name(db)),
ModuleDef::BuiltinType(t) => format!("primitive.{}.html", t.as_name()),
ModuleDef::Function(f) => format!("fn.{}.html", f.name(db)),
- ModuleDef::EnumVariant(ev) => {
+ ModuleDef::Variant(ev) => {
format!("enum.{}.html#variant.{}", ev.parent_enum(db).name(db), ev.name(db))
}
ModuleDef::Const(c) => format!("const.{}.html", c.name(db)?),
use syntax::{
ast::{self, AttrsOwner, GenericParamsOwner, NameOwner},
- match_ast, AstNode, SourceFile, SyntaxKind, SyntaxNode, TextRange, WalkEvent,
+ match_ast, AstNode, SourceFile, SyntaxNode, TextRange, WalkEvent,
};
+use crate::SymbolKind;
+
#[derive(Debug, Clone)]
pub struct StructureNode {
pub parent: Option<usize>,
pub label: String,
pub navigation_range: TextRange,
pub node_range: TextRange,
- pub kind: SyntaxKind,
+ pub kind: SymbolKind,
pub detail: Option<String>,
pub deprecated: bool,
}
}
fn structure_node(node: &SyntaxNode) -> Option<StructureNode> {
- fn decl<N: NameOwner + AttrsOwner>(node: N) -> Option<StructureNode> {
- decl_with_detail(&node, None)
+ fn decl<N: NameOwner + AttrsOwner>(node: N, kind: SymbolKind) -> Option<StructureNode> {
+ decl_with_detail(&node, None, kind)
}
fn decl_with_type_ref<N: NameOwner + AttrsOwner>(
node: &N,
type_ref: Option<ast::Type>,
+ kind: SymbolKind,
) -> Option<StructureNode> {
let detail = type_ref.map(|type_ref| {
let mut detail = String::new();
collapse_ws(type_ref.syntax(), &mut detail);
detail
});
- decl_with_detail(node, detail)
+ decl_with_detail(node, detail, kind)
}
fn decl_with_detail<N: NameOwner + AttrsOwner>(
node: &N,
detail: Option<String>,
+ kind: SymbolKind,
) -> Option<StructureNode> {
let name = node.name()?;
label: name.text().to_string(),
navigation_range: name.syntax().text_range(),
node_range: node.syntax().text_range(),
- kind: node.syntax().kind(),
+ kind,
detail,
deprecated: node.attrs().filter_map(|x| x.simple_name()).any(|x| x == "deprecated"),
})
collapse_ws(ret_type.syntax(), &mut detail);
}
- decl_with_detail(&it, Some(detail))
+ decl_with_detail(&it, Some(detail), SymbolKind::Function)
},
- ast::Struct(it) => decl(it),
- ast::Union(it) => decl(it),
- ast::Enum(it) => decl(it),
- ast::Variant(it) => decl(it),
- ast::Trait(it) => decl(it),
- ast::Module(it) => decl(it),
- ast::TypeAlias(it) => decl_with_type_ref(&it, it.ty()),
- ast::RecordField(it) => decl_with_type_ref(&it, it.ty()),
- ast::Const(it) => decl_with_type_ref(&it, it.ty()),
- ast::Static(it) => decl_with_type_ref(&it, it.ty()),
+ ast::Struct(it) => decl(it, SymbolKind::Struct),
+ ast::Union(it) => decl(it, SymbolKind::Union),
+ ast::Enum(it) => decl(it, SymbolKind::Enum),
+ ast::Variant(it) => decl(it, SymbolKind::Variant),
+ ast::Trait(it) => decl(it, SymbolKind::Trait),
+ ast::Module(it) => decl(it, SymbolKind::Module),
+ ast::TypeAlias(it) => decl_with_type_ref(&it, it.ty(), SymbolKind::TypeAlias),
+ ast::RecordField(it) => decl_with_type_ref(&it, it.ty(), SymbolKind::Field),
+ ast::Const(it) => decl_with_type_ref(&it, it.ty(), SymbolKind::Const),
+ ast::Static(it) => decl_with_type_ref(&it, it.ty(), SymbolKind::Static),
ast::Impl(it) => {
let target_type = it.self_ty()?;
let target_trait = it.trait_();
label,
navigation_range: target_type.syntax().text_range(),
node_range: it.syntax().text_range(),
- kind: it.syntax().kind(),
+ kind: SymbolKind::Impl,
detail: None,
deprecated: false,
};
Some(node)
},
- ast::MacroRules(it) => decl(it),
+ ast::MacroRules(it) => decl(it, SymbolKind::Macro),
_ => None,
}
}
label: "Foo",
navigation_range: 8..11,
node_range: 1..26,
- kind: STRUCT,
+ kind: Struct,
detail: None,
deprecated: false,
},
label: "x",
navigation_range: 18..19,
node_range: 18..24,
- kind: RECORD_FIELD,
+ kind: Field,
detail: Some(
"i32",
),
label: "m",
navigation_range: 32..33,
node_range: 28..158,
- kind: MODULE,
+ kind: Module,
detail: None,
deprecated: false,
},
label: "bar1",
navigation_range: 43..47,
node_range: 40..52,
- kind: FN,
+ kind: Function,
detail: Some(
"fn()",
),
label: "bar2",
navigation_range: 60..64,
node_range: 57..81,
- kind: FN,
+ kind: Function,
detail: Some(
"fn<T>(t: T) -> T",
),
label: "bar3",
navigation_range: 89..93,
node_range: 86..156,
- kind: FN,
+ kind: Function,
detail: Some(
"fn<A, B>(a: A, b: B) -> Vec< u32 >",
),
label: "E",
navigation_range: 165..166,
node_range: 160..180,
- kind: ENUM,
+ kind: Enum,
detail: None,
deprecated: false,
},
label: "X",
navigation_range: 169..170,
node_range: 169..170,
- kind: VARIANT,
+ kind: Variant,
detail: None,
deprecated: false,
},
label: "Y",
navigation_range: 172..173,
node_range: 172..178,
- kind: VARIANT,
+ kind: Variant,
detail: None,
deprecated: false,
},
label: "T",
navigation_range: 186..187,
node_range: 181..193,
- kind: TYPE_ALIAS,
+ kind: TypeAlias,
detail: Some(
"()",
),
label: "S",
navigation_range: 201..202,
node_range: 194..213,
- kind: STATIC,
+ kind: Static,
detail: Some(
"i32",
),
label: "C",
navigation_range: 220..221,
node_range: 214..232,
- kind: CONST,
+ kind: Const,
detail: Some(
"i32",
),
label: "impl E",
navigation_range: 239..240,
node_range: 234..243,
- kind: IMPL,
+ kind: Impl,
detail: None,
deprecated: false,
},
label: "impl fmt::Debug for E",
navigation_range: 265..266,
node_range: 245..269,
- kind: IMPL,
+ kind: Impl,
detail: None,
deprecated: false,
},
label: "mc",
navigation_range: 284..286,
node_range: 271..303,
- kind: MACRO_RULES,
+ kind: Macro,
detail: None,
deprecated: false,
},
label: "mcexp",
navigation_range: 334..339,
node_range: 305..356,
- kind: MACRO_RULES,
+ kind: Macro,
detail: None,
deprecated: false,
},
label: "mcexp",
navigation_range: 387..392,
node_range: 358..409,
- kind: MACRO_RULES,
+ kind: Macro,
detail: None,
deprecated: false,
},
label: "obsolete",
navigation_range: 428..436,
node_range: 411..441,
- kind: FN,
+ kind: Function,
detail: Some(
"fn()",
),
label: "very_obsolete",
navigation_range: 481..494,
node_range: 443..499,
- kind: FN,
+ kind: Function,
detail: Some(
"fn()",
),
use crate::{
display::{ToNav, TryToNav},
- FilePosition, NavigationTarget, RangeInfo,
+ FilePosition, NavigationTarget, RangeInfo, SymbolKind,
};
// Feature: Go to Definition
full_range: self_param.syntax().text_range(),
focus_range: Some(self_token.text_range()),
name: self_token.text().clone(),
- kind: self_token.kind(),
+ kind: Some(SymbolKind::SelfParam),
container_name: None,
description: None,
docs: None,
AssocItemContainer::Trait(t) => Some(t.name(db)),
AssocItemContainer::Impl(i) => i.target_ty(db).as_adt().map(|adt| adt.name(db)),
},
- ModuleDef::EnumVariant(e) => Some(e.parent_enum(db).name(db)),
+ ModuleDef::Variant(e) => Some(e.parent_enum(db).name(db)),
_ => None,
},
_ => None,
let mod_path = definition_mod_path(db, &def);
return match def {
Definition::Macro(it) => {
+ // FIXME: Currently proc-macro do not have ast-node,
+ // such that it does not have source
+ // more discussion: https://github.com/rust-analyzer/rust-analyzer/issues/6913
+ if it.is_proc_macro() {
+ return None;
+ }
let label = macro_label(&it.source(db).value);
from_def_source_labeled(db, it, Some(label), mod_path)
}
ModuleDef::Adt(Adt::Struct(it)) => from_def_source(db, it, mod_path),
ModuleDef::Adt(Adt::Union(it)) => from_def_source(db, it, mod_path),
ModuleDef::Adt(Adt::Enum(it)) => from_def_source(db, it, mod_path),
- ModuleDef::EnumVariant(it) => from_def_source(db, it, mod_path),
+ ModuleDef::Variant(it) => from_def_source(db, it, mod_path),
ModuleDef::Const(it) => from_def_source(db, it, mod_path),
ModuleDef::Static(it) => from_def_source(db, it, mod_path),
ModuleDef::Trait(it) => from_def_source(db, it, mod_path),
0,
),
full_range: 0..24,
- focus_range: Some(
- 11..19,
- ),
+ focus_range: 11..19,
name: "foo_test",
- kind: FN,
- container_name: None,
- description: None,
- docs: None,
+ kind: Function,
},
kind: Test {
test_id: Path(
0,
),
full_range: 0..46,
- focus_range: Some(
- 4..9,
- ),
+ focus_range: 4..9,
name: "tests",
- kind: MODULE,
- container_name: None,
- description: None,
- docs: None,
+ kind: Module,
},
kind: TestMod {
path: "tests",
0,
),
full_range: 0..19,
- focus_range: Some(
- 7..8,
- ),
+ focus_range: 7..8,
name: "S",
- kind: STRUCT,
- container_name: None,
- description: Some(
- "struct S",
- ),
- docs: None,
+ kind: Struct,
+ description: "struct S",
},
},
],
0,
),
full_range: 17..37,
- focus_range: Some(
- 24..25,
- ),
+ focus_range: 24..25,
name: "S",
- kind: STRUCT,
- container_name: None,
- description: Some(
- "struct S",
- ),
- docs: None,
+ kind: Struct,
+ description: "struct S",
},
},
HoverGotoTypeData {
0,
),
full_range: 0..16,
- focus_range: Some(
- 7..10,
- ),
+ focus_range: 7..10,
name: "Arg",
- kind: STRUCT,
- container_name: None,
- description: Some(
- "struct Arg",
- ),
- docs: None,
+ kind: Struct,
+ description: "struct Arg",
},
},
],
0,
),
full_range: 17..37,
- focus_range: Some(
- 24..25,
- ),
+ focus_range: 24..25,
name: "S",
- kind: STRUCT,
- container_name: None,
- description: Some(
- "struct S",
- ),
- docs: None,
+ kind: Struct,
+ description: "struct S",
},
},
HoverGotoTypeData {
0,
),
full_range: 0..16,
- focus_range: Some(
- 7..10,
- ),
+ focus_range: 7..10,
name: "Arg",
- kind: STRUCT,
- container_name: None,
- description: Some(
- "struct Arg",
- ),
- docs: None,
+ kind: Struct,
+ description: "struct Arg",
},
},
],
0,
),
full_range: 0..14,
- focus_range: Some(
- 7..8,
- ),
+ focus_range: 7..8,
name: "A",
- kind: STRUCT,
- container_name: None,
- description: Some(
- "struct A",
- ),
- docs: None,
+ kind: Struct,
+ description: "struct A",
},
},
HoverGotoTypeData {
0,
),
full_range: 15..29,
- focus_range: Some(
- 22..23,
- ),
+ focus_range: 22..23,
name: "B",
- kind: STRUCT,
- container_name: None,
- description: Some(
- "struct B",
- ),
- docs: None,
+ kind: Struct,
+ description: "struct B",
},
},
HoverGotoTypeData {
0,
),
full_range: 42..60,
- focus_range: Some(
- 53..54,
- ),
+ focus_range: 53..54,
name: "C",
- kind: STRUCT,
- container_name: None,
- description: Some(
- "pub struct C",
- ),
- docs: None,
+ kind: Struct,
+ description: "pub struct C",
},
},
],
0,
),
full_range: 0..12,
- focus_range: Some(
- 6..9,
- ),
+ focus_range: 6..9,
name: "Foo",
- kind: TRAIT,
- container_name: None,
- description: Some(
- "trait Foo",
- ),
- docs: None,
+ kind: Trait,
+ description: "trait Foo",
},
},
],
0,
),
full_range: 0..15,
- focus_range: Some(
- 6..9,
- ),
+ focus_range: 6..9,
name: "Foo",
- kind: TRAIT,
- container_name: None,
- description: Some(
- "trait Foo",
- ),
- docs: None,
+ kind: Trait,
+ description: "trait Foo",
},
},
HoverGotoTypeData {
0,
),
full_range: 16..25,
- focus_range: Some(
- 23..24,
- ),
+ focus_range: 23..24,
name: "S",
- kind: STRUCT,
- container_name: None,
- description: Some(
- "struct S",
- ),
- docs: None,
+ kind: Struct,
+ description: "struct S",
},
},
],
0,
),
full_range: 0..12,
- focus_range: Some(
- 6..9,
- ),
+ focus_range: 6..9,
name: "Foo",
- kind: TRAIT,
- container_name: None,
- description: Some(
- "trait Foo",
- ),
- docs: None,
+ kind: Trait,
+ description: "trait Foo",
},
},
HoverGotoTypeData {
0,
),
full_range: 13..25,
- focus_range: Some(
- 19..22,
- ),
+ focus_range: 19..22,
name: "Bar",
- kind: TRAIT,
- container_name: None,
- description: Some(
- "trait Bar",
- ),
- docs: None,
+ kind: Trait,
+ description: "trait Bar",
},
},
],
0,
),
full_range: 0..15,
- focus_range: Some(
- 6..9,
- ),
+ focus_range: 6..9,
name: "Foo",
- kind: TRAIT,
- container_name: None,
- description: Some(
- "trait Foo",
- ),
- docs: None,
+ kind: Trait,
+ description: "trait Foo",
},
},
HoverGotoTypeData {
0,
),
full_range: 16..31,
- focus_range: Some(
- 22..25,
- ),
+ focus_range: 22..25,
name: "Bar",
- kind: TRAIT,
- container_name: None,
- description: Some(
- "trait Bar",
- ),
- docs: None,
+ kind: Trait,
+ description: "trait Bar",
},
},
HoverGotoTypeData {
0,
),
full_range: 32..44,
- focus_range: Some(
- 39..41,
- ),
+ focus_range: 39..41,
name: "S1",
- kind: STRUCT,
- container_name: None,
- description: Some(
- "struct S1",
- ),
- docs: None,
+ kind: Struct,
+ description: "struct S1",
},
},
HoverGotoTypeData {
0,
),
full_range: 45..57,
- focus_range: Some(
- 52..54,
- ),
+ focus_range: 52..54,
name: "S2",
- kind: STRUCT,
- container_name: None,
- description: Some(
- "struct S2",
- ),
- docs: None,
+ kind: Struct,
+ description: "struct S2",
},
},
],
0,
),
full_range: 0..12,
- focus_range: Some(
- 6..9,
- ),
+ focus_range: 6..9,
name: "Foo",
- kind: TRAIT,
- container_name: None,
- description: Some(
- "trait Foo",
- ),
- docs: None,
+ kind: Trait,
+ description: "trait Foo",
},
},
],
0,
),
full_range: 0..12,
- focus_range: Some(
- 6..9,
- ),
+ focus_range: 6..9,
name: "Foo",
- kind: TRAIT,
- container_name: None,
- description: Some(
- "trait Foo",
- ),
- docs: None,
+ kind: Trait,
+ description: "trait Foo",
},
},
HoverGotoTypeData {
0,
),
full_range: 13..28,
- focus_range: Some(
- 19..22,
- ),
+ focus_range: 19..22,
name: "Bar",
- kind: TRAIT,
- container_name: None,
- description: Some(
- "trait Bar",
- ),
- docs: None,
+ kind: Trait,
+ description: "trait Bar",
},
},
HoverGotoTypeData {
0,
),
full_range: 29..39,
- focus_range: Some(
- 36..37,
- ),
+ focus_range: 36..37,
name: "S",
- kind: STRUCT,
- container_name: None,
- description: Some(
- "struct S",
- ),
- docs: None,
+ kind: Struct,
+ description: "struct S",
},
},
],
0,
),
full_range: 101..163,
- focus_range: Some(
- 140..146,
- ),
+ focus_range: 140..146,
name: "Future",
- kind: TRAIT,
- container_name: None,
- description: Some(
- "pub trait Future",
- ),
- docs: None,
+ kind: Trait,
+ description: "pub trait Future",
},
},
HoverGotoTypeData {
0,
),
full_range: 0..9,
- focus_range: Some(
- 7..8,
- ),
+ focus_range: 7..8,
name: "S",
- kind: STRUCT,
- container_name: None,
- description: Some(
- "struct S",
- ),
- docs: None,
+ kind: Struct,
+ description: "struct S",
},
},
],
0,
),
full_range: 0..15,
- focus_range: Some(
- 6..9,
- ),
+ focus_range: 6..9,
name: "Foo",
- kind: TRAIT,
- container_name: None,
- description: Some(
- "trait Foo",
- ),
- docs: None,
+ kind: Trait,
+ description: "trait Foo",
},
},
HoverGotoTypeData {
0,
),
full_range: 16..27,
- focus_range: Some(
- 23..24,
- ),
+ focus_range: 23..24,
name: "S",
- kind: STRUCT,
- container_name: None,
- description: Some(
- "struct S",
- ),
- docs: None,
+ kind: Struct,
+ description: "struct S",
},
},
],
0,
),
full_range: 42..55,
- focus_range: Some(
- 49..50,
- ),
+ focus_range: 49..50,
name: "B",
- kind: STRUCT,
- container_name: None,
- description: Some(
- "struct B",
- ),
- docs: None,
+ kind: Struct,
+ description: "struct B",
},
},
HoverGotoTypeData {
0,
),
full_range: 0..12,
- focus_range: Some(
- 6..9,
- ),
+ focus_range: 6..9,
name: "Foo",
- kind: TRAIT,
- container_name: None,
- description: Some(
- "trait Foo",
- ),
- docs: None,
+ kind: Trait,
+ description: "trait Foo",
},
},
],
0,
),
full_range: 0..12,
- focus_range: Some(
- 6..9,
- ),
+ focus_range: 6..9,
name: "Foo",
- kind: TRAIT,
- container_name: None,
- description: Some(
- "trait Foo",
- ),
- docs: None,
+ kind: Trait,
+ description: "trait Foo",
},
},
],
0,
),
full_range: 0..15,
- focus_range: Some(
- 6..9,
- ),
+ focus_range: 6..9,
name: "Foo",
- kind: TRAIT,
- container_name: None,
- description: Some(
- "trait Foo",
- ),
- docs: None,
+ kind: Trait,
+ description: "trait Foo",
},
},
HoverGotoTypeData {
0,
),
full_range: 16..27,
- focus_range: Some(
- 23..24,
- ),
+ focus_range: 23..24,
name: "S",
- kind: STRUCT,
- container_name: None,
- description: Some(
- "struct S",
- ),
- docs: None,
+ kind: Struct,
+ description: "struct S",
},
},
],
0,
),
full_range: 0..21,
- focus_range: Some(
- 6..15,
- ),
+ focus_range: 6..15,
name: "ImplTrait",
- kind: TRAIT,
- container_name: None,
- description: Some(
- "trait ImplTrait",
- ),
- docs: None,
+ kind: Trait,
+ description: "trait ImplTrait",
},
},
HoverGotoTypeData {
0,
),
full_range: 43..57,
- focus_range: Some(
- 50..51,
- ),
+ focus_range: 50..51,
name: "B",
- kind: STRUCT,
- container_name: None,
- description: Some(
- "struct B",
- ),
- docs: None,
+ kind: Struct,
+ description: "struct B",
},
},
HoverGotoTypeData {
0,
),
full_range: 22..42,
- focus_range: Some(
- 28..36,
- ),
+ focus_range: 28..36,
name: "DynTrait",
- kind: TRAIT,
- container_name: None,
- description: Some(
- "trait DynTrait",
- ),
- docs: None,
+ kind: Trait,
+ description: "trait DynTrait",
},
},
HoverGotoTypeData {
0,
),
full_range: 58..69,
- focus_range: Some(
- 65..66,
- ),
+ focus_range: 65..66,
name: "S",
- kind: STRUCT,
- container_name: None,
- description: Some(
- "struct S",
- ),
- docs: None,
+ kind: Struct,
+ description: "struct S",
},
},
],
0,
),
full_range: 0..62,
- focus_range: Some(
- 6..9,
- ),
+ focus_range: 6..9,
name: "Foo",
- kind: TRAIT,
- container_name: None,
- description: Some(
- "trait Foo",
- ),
- docs: None,
+ kind: Trait,
+ description: "trait Foo",
},
},
],
symbol_index::{self, FileSymbol},
LineIndexDatabase,
};
-use syntax::{SourceFile, TextRange, TextSize};
+use syntax::SourceFile;
use crate::display::ToNav;
pub use crate::{
call_hierarchy::CallItem,
diagnostics::{Diagnostic, DiagnosticsConfig, Fix, Severity},
- display::NavigationTarget,
+ display::navigation_target::{NavigationTarget, SymbolKind},
expand_macro::ExpandedMacro,
file_structure::StructureNode,
folding_ranges::{Fold, FoldKind},
HighlightedRange,
},
};
+pub use assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist};
pub use completion::{
CompletionConfig, CompletionItem, CompletionItemKind, CompletionResolveCapability,
CompletionScore, ImportEdit, InsertTextFormat,
};
-pub use ide_db::{
- call_info::CallInfo,
- search::{Reference, ReferenceAccess, ReferenceKind},
-};
-
-pub use assists::{Assist, AssistConfig, AssistId, AssistKind, ResolvedAssist};
pub use hir::{Documentation, Semantics};
pub use ide_db::base_db::{
Canceled, Change, CrateGraph, CrateId, Edition, FileId, FilePosition, FileRange, SourceRoot,
SourceRootId,
};
+pub use ide_db::{
+ call_info::CallInfo,
+ search::{Reference, ReferenceAccess, ReferenceKind},
+};
pub use ide_db::{
label::Label,
line_index::{LineCol, LineIndex},
RootDatabase,
};
pub use ssr::SsrError;
+pub use syntax::{TextRange, TextSize};
pub use text_edit::{Indel, TextEdit};
pub type Cancelable<T> = Result<T, Canceled>;
",
);
let nav = analysis.parent_module(pos).unwrap().pop().unwrap();
- nav.assert_match("foo MODULE FileId(0) 0..8");
+ nav.assert_match("foo Module FileId(0) 0..8");
}
#[test]
",
);
let nav = analysis.parent_module(pos).unwrap().pop().unwrap();
- nav.assert_match("foo MODULE FileId(0) 0..8");
+ nav.assert_match("foo Module FileId(0) 0..8");
}
#[test]
",
);
let nav = analysis.parent_module(pos).unwrap().pop().unwrap();
- nav.assert_match("baz MODULE FileId(0) 32..44");
+ nav.assert_match("baz Module FileId(0) 32..44");
}
#[test]
match_ast, AstNode, SyntaxKind, SyntaxNode, TextRange, TokenAtOffset,
};
-use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo};
+use crate::{display::TryToNav, FilePosition, FileRange, NavigationTarget, RangeInfo, SymbolKind};
#[derive(Debug, Clone)]
pub struct ReferenceSearchResult {
full_range: self_param.syntax().text_range(),
focus_range: Some(param_self_token.text_range()),
name: param_self_token.text().clone(),
- kind: param_self_token.kind(),
+ kind: Some(SymbolKind::SelfParam),
container_name: None,
description: None,
docs: None,
}
"#,
expect![[r#"
- Foo STRUCT FileId(0) 0..26 7..10 Other
+ Foo Struct FileId(0) 0..26 7..10 Other
FileId(0) 101..104 StructLiteral
"#]],
}
"#,
expect![[r#"
- Foo STRUCT FileId(0) 0..13 7..10 Other
+ Foo Struct FileId(0) 0..13 7..10 Other
FileId(0) 41..44 Other
FileId(0) 54..57 StructLiteral
}
"#,
expect![[r#"
- Foo STRUCT FileId(0) 0..16 7..10 Other
+ Foo Struct FileId(0) 0..16 7..10 Other
FileId(0) 64..67 StructLiteral
"#]],
}
"#,
expect![[r#"
- Foo STRUCT FileId(0) 0..16 7..10 Other
+ Foo Struct FileId(0) 0..16 7..10 Other
FileId(0) 54..57 StructLiteral
"#]],
}
"#,
expect![[r#"
- Foo ENUM FileId(0) 0..26 5..8 Other
+ Foo Enum FileId(0) 0..26 5..8 Other
FileId(0) 63..66 EnumLiteral
"#]],
}
"#,
expect![[r#"
- Foo ENUM FileId(0) 0..26 5..8 Other
+ Foo Enum FileId(0) 0..26 5..8 Other
FileId(0) 50..53 Other
FileId(0) 63..66 EnumLiteral
}
"#,
expect![[r#"
- Foo ENUM FileId(0) 0..32 5..8 Other
+ Foo Enum FileId(0) 0..32 5..8 Other
FileId(0) 73..76 EnumLiteral
"#]],
}
"#,
expect![[r#"
- Foo ENUM FileId(0) 0..33 5..8 Other
+ Foo Enum FileId(0) 0..33 5..8 Other
FileId(0) 70..73 EnumLiteral
"#]],
i = 5;
}"#,
expect![[r#"
- i IDENT_PAT FileId(0) 24..25 Other Write
+ i Local FileId(0) 24..25 Other Write
FileId(0) 50..51 Other Write
FileId(0) 54..55 Other Read
}
"#,
expect![[r#"
- spam IDENT_PAT FileId(0) 19..23 Other
+ spam Local FileId(0) 19..23 Other
FileId(0) 34..38 Other Read
FileId(0) 41..45 Other Read
fn foo(i : u32) -> u32 { i<|> }
"#,
expect![[r#"
- i IDENT_PAT FileId(0) 7..8 Other
+ i ValueParam FileId(0) 7..8 Other
FileId(0) 25..26 Other Read
"#]],
fn foo(i<|> : u32) -> u32 { i }
"#,
expect![[r#"
- i IDENT_PAT FileId(0) 7..8 Other
+ i ValueParam FileId(0) 7..8 Other
FileId(0) 25..26 Other Read
"#]],
}
"#,
expect![[r#"
- spam RECORD_FIELD FileId(0) 17..30 21..25 Other
+ spam Field FileId(0) 17..30 21..25 Other
FileId(0) 67..71 Other Read
"#]],
}
"#,
expect![[r#"
- f FN FileId(0) 27..43 30..31 Other
+ f Function FileId(0) 27..43 30..31 Other
"#]],
);
}
"#,
expect![[r#"
- B VARIANT FileId(0) 22..23 22..23 Other
+ B Variant FileId(0) 22..23 22..23 Other
"#]],
);
}
"#,
expect![[r#"
- field RECORD_FIELD FileId(0) 26..35 26..31 Other
+ field Field FileId(0) 26..35 26..31 Other
"#]],
);
}
"#,
expect![[r#"
- Foo STRUCT FileId(1) 17..51 28..31 Other
+ Foo Struct FileId(1) 17..51 28..31 Other
FileId(0) 53..56 StructLiteral
FileId(2) 79..82 StructLiteral
}
"#,
expect![[r#"
- foo SOURCE_FILE FileId(1) 0..35 Other
+ foo Module FileId(1) 0..35 Other
FileId(0) 14..17 Other
"#]],
}
"#,
expect![[r#"
- Foo STRUCT FileId(2) 0..41 18..21 Other
+ Foo Struct FileId(2) 0..41 18..21 Other
FileId(1) 20..23 Other
FileId(1) 47..50 StructLiteral
code,
None,
expect![[r#"
- quux FN FileId(0) 19..35 26..30 Other
+ quux Function FileId(0) 19..35 26..30 Other
FileId(1) 16..20 StructLiteral
FileId(2) 16..20 StructLiteral
code,
Some(SearchScope::single_file(FileId(2))),
expect![[r#"
- quux FN FileId(0) 19..35 26..30 Other
+ quux Function FileId(0) 19..35 26..30 Other
FileId(2) 16..20 StructLiteral
"#]],
}
"#,
expect![[r#"
- m1 MACRO_RULES FileId(0) 0..46 29..31 Other
+ m1 Macro FileId(0) 0..46 29..31 Other
FileId(0) 63..65 StructLiteral
FileId(0) 73..75 StructLiteral
}
"#,
expect![[r#"
- i IDENT_PAT FileId(0) 23..24 Other Write
+ i Local FileId(0) 23..24 Other Write
FileId(0) 34..35 Other Write
FileId(0) 38..39 Other Read
}
"#,
expect![[r#"
- f RECORD_FIELD FileId(0) 15..21 15..16 Other
+ f Field FileId(0) 15..21 15..16 Other
FileId(0) 55..56 RecordFieldExprOrPat Read
FileId(0) 68..69 Other Write
}
"#,
expect![[r#"
- i IDENT_PAT FileId(0) 19..20 Other
+ i Local FileId(0) 19..20 Other
FileId(0) 26..27 Other Write
"#]],
}
"#,
expect![[r#"
- new FN FileId(0) 54..81 61..64 Other
+ new Function FileId(0) 54..81 61..64 Other
FileId(0) 126..129 StructLiteral
"#]],
fn g() { f(); }
"#,
expect![[r#"
- f FN FileId(0) 22..31 25..26 Other
+ f Function FileId(0) 22..31 25..26 Other
FileId(1) 11..12 Other
FileId(1) 24..25 StructLiteral
}
"#,
expect![[r#"
- field RECORD_FIELD FileId(0) 15..24 15..20 Other
+ field Field FileId(0) 15..24 15..20 Other
FileId(0) 68..73 FieldShorthandForField Read
"#]],
}
"#,
expect![[r#"
- field RECORD_FIELD FileId(0) 32..41 32..37 Other
+ field Field FileId(0) 32..41 32..37 Other
FileId(0) 102..107 FieldShorthandForField Read
"#]],
}
"#,
expect![[r#"
- field RECORD_FIELD FileId(0) 56..65 56..61 Other
+ field Field FileId(0) 56..65 56..61 Other
FileId(0) 125..130 RecordFieldExprOrPat Read
"#]],
}
"#,
expect![[r#"
- self SELF_KW FileId(0) 47..51 47..51 SelfKw Read
+ self SelfParam FileId(0) 47..51 47..51 SelfKw Read
FileId(0) 71..75 SelfKw Read
FileId(0) 152..156 SelfKw Read
}
"#,
expect![[r#"
- 'a LIFETIME_PARAM FileId(0) 55..57 55..57 Lifetime
+ 'a LifetimeParam FileId(0) 55..57 55..57 Lifetime
FileId(0) 63..65 Lifetime
FileId(0) 71..73 Lifetime
type Foo<'a, T> where T: 'a<|> = &'a T;
"#,
expect![[r#"
- 'a LIFETIME_PARAM FileId(0) 9..11 9..11 Lifetime
+ 'a LifetimeParam FileId(0) 9..11 9..11 Lifetime
FileId(0) 25..27 Lifetime
FileId(0) 31..33 Lifetime
}
"#,
expect![[r#"
- 'a LIFETIME_PARAM FileId(0) 47..49 47..49 Lifetime
+ 'a LifetimeParam FileId(0) 47..49 47..49 Lifetime
FileId(0) 55..57 Lifetime
FileId(0) 64..66 Lifetime
"#,
)
}
+
+ #[test]
+ fn test_rename_bind_pat() {
+ check(
+ "new_name",
+ r#"
+fn main() {
+ enum CustomOption<T> {
+ None,
+ Some(T),
+ }
+
+ let test_variable = CustomOption::Some(22);
+
+ match test_variable {
+ CustomOption::Some(foo<|>) if foo == 11 => {}
+ _ => (),
+ }
+}"#,
+ r#"
+fn main() {
+ enum CustomOption<T> {
+ None,
+ Some(T),
+ }
+
+ let test_variable = CustomOption::Some(22);
+
+ match test_variable {
+ CustomOption::Some(new_name) if new_name == 11 => {}
+ _ => (),
+ }
+}"#,
+ );
+ }
}
use assists::utils::test_related_attribute;
use cfg::CfgExpr;
-use hir::{AsAssocItem, Attrs, HirFileId, InFile, Semantics};
+use hir::{AsAssocItem, HasAttrs, InFile, Semantics};
use ide_db::RootDatabase;
use itertools::Itertools;
use syntax::{
match_ast, SyntaxNode,
};
-use crate::{display::ToNav, FileId, NavigationTarget};
+use crate::{
+ display::{ToNav, TryToNav},
+ FileId, NavigationTarget, SymbolKind,
+};
#[derive(Debug, Clone)]
pub struct Runnable {
item: SyntaxNode,
file_id: FileId,
) -> Option<Runnable> {
- match_ast! {
- match item {
- ast::Struct(it) => runnable_struct(sema, it, file_id),
+ let runnable_item = match_ast! {
+ match (item.clone()) {
ast::Fn(it) => runnable_fn(sema, it, file_id),
- ast::Module(it) => runnable_mod(sema, it, file_id),
+ ast::Module(it) => runnable_mod(sema, it),
_ => None,
}
- }
+ };
+ runnable_item.or_else(|| runnable_doctest(sema, item))
}
-fn runnable_fn(
- sema: &Semantics<RootDatabase>,
- fn_def: ast::Fn,
- file_id: FileId,
-) -> Option<Runnable> {
- let name_string = fn_def.name()?.text().to_string();
+fn runnable_fn(sema: &Semantics<RootDatabase>, func: ast::Fn, file_id: FileId) -> Option<Runnable> {
+ let def = sema.to_def(&func)?;
+ let name_string = func.name()?.text().to_string();
- let attrs = Attrs::from_attrs_owner(sema.db, InFile::new(HirFileId::from(file_id), &fn_def));
let kind = if name_string == "main" {
RunnableKind::Bin
} else {
- let test_id = match sema.to_def(&fn_def).map(|def| def.module(sema.db)) {
- Some(module) => {
- let def = sema.to_def(&fn_def)?;
- let impl_trait_name = def.as_assoc_item(sema.db).and_then(|assoc_item| {
- match assoc_item.container(sema.db) {
- hir::AssocItemContainer::Trait(trait_item) => {
- Some(trait_item.name(sema.db).to_string())
- }
- hir::AssocItemContainer::Impl(impl_def) => impl_def
- .target_ty(sema.db)
- .as_adt()
- .map(|adt| adt.name(sema.db).to_string()),
- }
- });
-
- let path_iter = module
- .path_to_root(sema.db)
- .into_iter()
- .rev()
- .filter_map(|it| it.name(sema.db))
- .map(|name| name.to_string());
-
- let path = if let Some(impl_trait_name) = impl_trait_name {
- path_iter
- .chain(std::iter::once(impl_trait_name))
- .chain(std::iter::once(name_string))
- .join("::")
- } else {
- path_iter.chain(std::iter::once(name_string)).join("::")
- };
-
- TestId::Path(path)
- }
- None => TestId::Name(name_string),
- };
-
- if test_related_attribute(&fn_def).is_some() {
- let attr = TestAttr::from_fn(&fn_def);
+ let canonical_path = sema.to_def(&func).and_then(|def| {
+ let def: hir::ModuleDef = def.into();
+ def.canonical_path(sema.db)
+ });
+ let test_id = canonical_path.map(TestId::Path).unwrap_or(TestId::Name(name_string));
+
+ if test_related_attribute(&func).is_some() {
+ let attr = TestAttr::from_fn(&func);
RunnableKind::Test { test_id, attr }
- } else if fn_def.has_atom_attr("bench") {
+ } else if func.has_atom_attr("bench") {
RunnableKind::Bench { test_id }
- } else if has_runnable_doc_test(&attrs) {
- RunnableKind::DocTest { test_id }
} else {
return None;
}
};
- let cfg = attrs.cfg();
-
- let nav = if let RunnableKind::DocTest { .. } = kind {
- NavigationTarget::from_doc_commented(
- sema.db,
- InFile::new(file_id.into(), &fn_def),
- InFile::new(file_id.into(), &fn_def),
- )
- } else {
- NavigationTarget::from_named(sema.db, InFile::new(file_id.into(), &fn_def))
- };
+ let nav = NavigationTarget::from_named(
+ sema.db,
+ InFile::new(file_id.into(), &func),
+ SymbolKind::Function,
+ );
+ let cfg = def.attrs(sema.db).cfg();
Some(Runnable { nav, kind, cfg })
}
-fn runnable_struct(
- sema: &Semantics<RootDatabase>,
- struct_def: ast::Struct,
- file_id: FileId,
-) -> Option<Runnable> {
- let name_string = struct_def.name()?.text().to_string();
+fn runnable_doctest(sema: &Semantics<RootDatabase>, item: SyntaxNode) -> Option<Runnable> {
+ match_ast! {
+ match item {
+ ast::Fn(it) => module_def_doctest(sema, sema.to_def(&it)?.into()),
+ ast::Struct(it) => module_def_doctest(sema, sema.to_def(&it)?.into()),
+ ast::Enum(it) => module_def_doctest(sema, sema.to_def(&it)?.into()),
+ ast::Union(it) => module_def_doctest(sema, sema.to_def(&it)?.into()),
+ ast::Trait(it) => module_def_doctest(sema, sema.to_def(&it)?.into()),
+ ast::Const(it) => module_def_doctest(sema, sema.to_def(&it)?.into()),
+ ast::Static(it) => module_def_doctest(sema, sema.to_def(&it)?.into()),
+ ast::TypeAlias(it) => module_def_doctest(sema, sema.to_def(&it)?.into()),
+ _ => None,
+ }
+ }
+}
- let attrs =
- Attrs::from_attrs_owner(sema.db, InFile::new(HirFileId::from(file_id), &struct_def));
+fn module_def_doctest(sema: &Semantics<RootDatabase>, def: hir::ModuleDef) -> Option<Runnable> {
+ let attrs = match def {
+ hir::ModuleDef::Module(it) => it.attrs(sema.db),
+ hir::ModuleDef::Function(it) => it.attrs(sema.db),
+ hir::ModuleDef::Adt(it) => it.attrs(sema.db),
+ hir::ModuleDef::Variant(it) => it.attrs(sema.db),
+ hir::ModuleDef::Const(it) => it.attrs(sema.db),
+ hir::ModuleDef::Static(it) => it.attrs(sema.db),
+ hir::ModuleDef::Trait(it) => it.attrs(sema.db),
+ hir::ModuleDef::TypeAlias(it) => it.attrs(sema.db),
+ hir::ModuleDef::BuiltinType(_) => return None,
+ };
if !has_runnable_doc_test(&attrs) {
return None;
}
- let cfg = attrs.cfg();
-
- let test_id = match sema.to_def(&struct_def).map(|def| def.module(sema.db)) {
- Some(module) => {
- let path_iter = module
- .path_to_root(sema.db)
- .into_iter()
- .rev()
- .filter_map(|it| it.name(sema.db))
- .map(|name| name.to_string());
- let path = path_iter.chain(std::iter::once(name_string)).join("::");
-
- TestId::Path(path)
- }
- None => TestId::Name(name_string),
- };
-
- let nav = NavigationTarget::from_doc_commented(
- sema.db,
- InFile::new(file_id.into(), &struct_def),
- InFile::new(file_id.into(), &struct_def),
- );
- Some(Runnable { nav, kind: RunnableKind::DocTest { test_id }, cfg })
+ let def_name = def.name(sema.db).map(|it| it.to_string());
+ let test_id = def
+ .canonical_path(sema.db)
+ // This probably belongs to canonical path?
+ .map(|path| {
+ let assoc_def = match def {
+ hir::ModuleDef::Function(it) => it.as_assoc_item(sema.db),
+ hir::ModuleDef::Const(it) => it.as_assoc_item(sema.db),
+ hir::ModuleDef::TypeAlias(it) => it.as_assoc_item(sema.db),
+ _ => None,
+ };
+ // FIXME: this also looks very wrong
+ if let Some(assoc_def) = assoc_def {
+ if let hir::AssocItemContainer::Impl(imp) = assoc_def.container(sema.db) {
+ if let Some(adt) = imp.target_ty(sema.db).as_adt() {
+ let name = adt.name(sema.db).to_string();
+ let idx = path.rfind(':').unwrap_or(0);
+ let (prefix, suffix) = path.split_at(idx);
+ return format!("{}{}::{}", prefix, name, suffix);
+ }
+ }
+ }
+ path
+ })
+ .map(TestId::Path)
+ .or_else(|| def_name.clone().map(TestId::Name))?;
+
+ let mut nav = def.try_to_nav(sema.db)?;
+ nav.focus_range = None;
+ nav.description = None;
+ nav.docs = None;
+ nav.kind = None;
+ let res = Runnable { nav, kind: RunnableKind::DocTest { test_id }, cfg: attrs.cfg() };
+ Some(res)
}
#[derive(Debug, Copy, Clone)]
})
}
-fn runnable_mod(
- sema: &Semantics<RootDatabase>,
- module: ast::Module,
- file_id: FileId,
-) -> Option<Runnable> {
+fn runnable_mod(sema: &Semantics<RootDatabase>, module: ast::Module) -> Option<Runnable> {
if !has_test_function_or_multiple_test_submodules(&module) {
return None;
}
.filter_map(|it| it.name(sema.db))
.join("::");
- let attrs = Attrs::from_attrs_owner(sema.db, InFile::new(HirFileId::from(file_id), &module));
+ let def = sema.to_def(&module)?;
+ let attrs = def.attrs(sema.db);
let cfg = attrs.cfg();
let nav = module_def.to_nav(sema.db);
Some(Runnable { nav, kind: RunnableKind::TestMod { path }, cfg })
use crate::fixture;
- use super::{RunnableAction, BENCH, BIN, DOCTEST, TEST};
+ use super::*;
fn check(
ra_fixture: &str,
0,
),
full_range: 1..13,
- focus_range: Some(
- 4..8,
- ),
+ focus_range: 4..8,
name: "main",
- kind: FN,
- container_name: None,
- description: None,
- docs: None,
+ kind: Function,
},
kind: Bin,
cfg: None,
0,
),
full_range: 15..39,
- focus_range: Some(
- 26..34,
- ),
+ focus_range: 26..34,
name: "test_foo",
- kind: FN,
- container_name: None,
- description: None,
- docs: None,
+ kind: Function,
},
kind: Test {
test_id: Path(
0,
),
full_range: 41..75,
- focus_range: Some(
- 62..70,
- ),
+ focus_range: 62..70,
name: "test_foo",
- kind: FN,
- container_name: None,
- description: None,
- docs: None,
+ kind: Function,
},
kind: Test {
test_id: Path(
0,
),
full_range: 77..99,
- focus_range: Some(
- 89..94,
- ),
+ focus_range: 89..94,
name: "bench",
- kind: FN,
- container_name: None,
- description: None,
- docs: None,
+ kind: Function,
},
kind: Bench {
test_id: Path(
0,
),
full_range: 1..13,
- focus_range: Some(
- 4..8,
- ),
+ focus_range: 4..8,
name: "main",
- kind: FN,
- container_name: None,
- description: None,
- docs: None,
+ kind: Function,
},
kind: Bin,
cfg: None,
0,
),
full_range: 15..74,
- focus_range: None,
name: "should_have_runnable",
- kind: FN,
- container_name: None,
- description: None,
- docs: None,
},
kind: DocTest {
test_id: Path(
0,
),
full_range: 76..148,
- focus_range: None,
name: "should_have_runnable_1",
- kind: FN,
- container_name: None,
- description: None,
- docs: None,
},
kind: DocTest {
test_id: Path(
0,
),
full_range: 150..254,
- focus_range: None,
name: "should_have_runnable_2",
- kind: FN,
- container_name: None,
- description: None,
- docs: None,
},
kind: DocTest {
test_id: Path(
0,
),
full_range: 756..821,
- focus_range: None,
name: "StructWithRunnable",
- kind: STRUCT,
- container_name: None,
- description: None,
- docs: None,
},
kind: DocTest {
test_id: Path(
0,
),
full_range: 1..13,
- focus_range: Some(
- 4..8,
- ),
+ focus_range: 4..8,
name: "main",
- kind: FN,
- container_name: None,
- description: None,
- docs: None,
+ kind: Function,
},
kind: Bin,
cfg: None,
0,
),
full_range: 44..98,
- focus_range: None,
name: "foo",
- kind: FN,
- container_name: None,
- description: None,
- docs: None,
},
kind: DocTest {
test_id: Path(
0,
),
full_range: 1..51,
- focus_range: Some(
- 5..13,
- ),
+ focus_range: 5..13,
name: "test_mod",
- kind: MODULE,
- container_name: None,
- description: None,
- docs: None,
+ kind: Module,
},
kind: TestMod {
path: "test_mod",
0,
),
full_range: 20..49,
- focus_range: Some(
- 35..44,
- ),
+ focus_range: 35..44,
name: "test_foo1",
- kind: FN,
- container_name: None,
- description: None,
- docs: None,
+ kind: Function,
},
kind: Test {
test_id: Path(
0,
),
full_range: 22..323,
- focus_range: Some(
- 26..40,
- ),
+ focus_range: 26..40,
name: "nested_tests_0",
- kind: MODULE,
- container_name: None,
- description: None,
- docs: None,
+ kind: Module,
},
kind: TestMod {
path: "root_tests::nested_tests_0",
0,
),
full_range: 51..192,
- focus_range: Some(
- 55..69,
- ),
+ focus_range: 55..69,
name: "nested_tests_1",
- kind: MODULE,
- container_name: None,
- description: None,
- docs: None,
+ kind: Module,
},
kind: TestMod {
path: "root_tests::nested_tests_0::nested_tests_1",
0,
),
full_range: 84..126,
- focus_range: Some(
- 107..121,
- ),
+ focus_range: 107..121,
name: "nested_test_11",
- kind: FN,
- container_name: None,
- description: None,
- docs: None,
+ kind: Function,
},
kind: Test {
test_id: Path(
0,
),
full_range: 140..182,
- focus_range: Some(
- 163..177,
- ),
+ focus_range: 163..177,
name: "nested_test_12",
- kind: FN,
- container_name: None,
- description: None,
- docs: None,
+ kind: Function,
},
kind: Test {
test_id: Path(
0,
),
full_range: 202..286,
- focus_range: Some(
- 206..220,
- ),
+ focus_range: 206..220,
name: "nested_tests_2",
- kind: MODULE,
- container_name: None,
- description: None,
- docs: None,
+ kind: Module,
},
kind: TestMod {
path: "root_tests::nested_tests_0::nested_tests_2",
0,
),
full_range: 235..276,
- focus_range: Some(
- 258..271,
- ),
+ focus_range: 258..271,
name: "nested_test_2",
- kind: FN,
- container_name: None,
- description: None,
- docs: None,
+ kind: Function,
},
kind: Test {
test_id: Path(
0,
),
full_range: 1..50,
- focus_range: Some(
- 36..45,
- ),
+ focus_range: 36..45,
name: "test_foo1",
- kind: FN,
- container_name: None,
- description: None,
- docs: None,
+ kind: Function,
},
kind: Test {
test_id: Path(
0,
),
full_range: 1..72,
- focus_range: Some(
- 58..67,
- ),
+ focus_range: 58..67,
name: "test_foo1",
- kind: FN,
- container_name: None,
- description: None,
- docs: None,
+ kind: Function,
},
kind: Test {
test_id: Path(
syntax_highlighting::{
format::FormatStringHighlighter, macro_rules::MacroRulesHighlighter, tags::Highlight,
},
- FileId, HighlightModifier, HighlightTag,
+ FileId, HighlightModifier, HighlightTag, SymbolKind,
};
pub(crate) use html::highlight_as_html;
if let Some(range) = macro_call_range(&mc) {
stack.add(HighlightedRange {
range,
- highlight: HighlightTag::Macro.into(),
+ highlight: HighlightTag::Symbol(SymbolKind::Macro).into(),
binding_hash: None,
});
}
};
match name_kind {
- Some(NameClass::ExternCrate(_)) => HighlightTag::Module.into(),
+ Some(NameClass::ExternCrate(_)) => HighlightTag::Symbol(SymbolKind::Module).into(),
Some(NameClass::Definition(def)) => {
highlight_def(db, def) | HighlightModifier::Definition
}
Some(NameClass::ConstReference(def)) => highlight_def(db, def),
Some(NameClass::PatFieldShorthand { field_ref, .. }) => {
- let mut h = HighlightTag::Field.into();
+ let mut h = HighlightTag::Symbol(SymbolKind::Field).into();
if let Definition::Field(field) = field_ref {
if let VariantDef::Union(_) = field.parent_def(db) {
h |= HighlightModifier::Unsafe;
NAME_REF if element.ancestors().any(|it| it.kind() == ATTR) => {
// even though we track whether we are in an attribute or not we still need this special case
// as otherwise we would emit unresolved references for name refs inside attributes
- Highlight::from(HighlightTag::Function)
+ Highlight::from(HighlightTag::Symbol(SymbolKind::Function))
}
NAME_REF => {
let name_ref = element.into_node().and_then(ast::NameRef::cast).unwrap();
highlight_func_by_name_ref(sema, &name_ref).unwrap_or_else(|| {
match NameRefClass::classify(sema, &name_ref) {
Some(name_kind) => match name_kind {
- NameRefClass::ExternCrate(_) => HighlightTag::Module.into(),
+ NameRefClass::ExternCrate(_) => {
+ HighlightTag::Symbol(SymbolKind::Module).into()
+ }
NameRefClass::Definition(def) => {
if let Definition::Local(local) = &def {
if let Some(name) = local.name(db) {
h
}
- NameRefClass::FieldShorthand { .. } => HighlightTag::Field.into(),
+ NameRefClass::FieldShorthand { .. } => {
+ HighlightTag::Symbol(SymbolKind::Field).into()
+ }
},
None if syntactic_name_ref_highlighting => {
highlight_name_ref_by_syntax(name_ref, sema)
CHAR => HighlightTag::CharLiteral.into(),
QUESTION => Highlight::new(HighlightTag::Operator) | HighlightModifier::ControlFlow,
LIFETIME => {
- let h = Highlight::new(HighlightTag::Lifetime);
+ let h = Highlight::new(HighlightTag::Symbol(SymbolKind::LifetimeParam));
match element.parent().map(|it| it.kind()) {
Some(LIFETIME_PARAM) | Some(LABEL) => h | HighlightModifier::Definition,
_ => h,
HighlightTag::Operator.into()
}
T![!] if element.parent().and_then(ast::MacroCall::cast).is_some() => {
- HighlightTag::Macro.into()
+ HighlightTag::Symbol(SymbolKind::Macro).into()
}
T![!] if element.parent().and_then(ast::NeverType::cast).is_some() => {
HighlightTag::BuiltinType.into()
.and_then(SyntaxNode::parent)
.and_then(ast::Path::cast)
.and_then(|p| sema.resolve_path(&p));
- let mut h = HighlightTag::SelfKeyword.into();
+ let mut h = HighlightTag::Symbol(SymbolKind::SelfParam).into();
if self_param_is_mut
|| matches!(self_path,
Some(hir::PathResolution::Local(local))
method_call: &ast::MethodCallExpr,
) -> Option<Highlight> {
let func = sema.resolve_method_call(&method_call)?;
- let mut h = HighlightTag::Method.into();
+ let mut h = HighlightTag::Symbol(SymbolKind::Function).into();
+ h |= HighlightModifier::Associated;
if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) {
h |= HighlightModifier::Unsafe;
}
fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
match def {
- Definition::Macro(_) => HighlightTag::Macro,
- Definition::Field(_) => HighlightTag::Field,
+ Definition::Macro(_) => HighlightTag::Symbol(SymbolKind::Macro),
+ Definition::Field(_) => HighlightTag::Symbol(SymbolKind::Field),
Definition::ModuleDef(def) => match def {
- hir::ModuleDef::Module(_) => HighlightTag::Module,
+ hir::ModuleDef::Module(_) => HighlightTag::Symbol(SymbolKind::Module),
hir::ModuleDef::Function(func) => {
- let mut h = if func.as_assoc_item(db).is_some() {
+ let mut h = Highlight::new(HighlightTag::Symbol(SymbolKind::Function));
+ if func.as_assoc_item(db).is_some() {
+ h |= HighlightModifier::Associated;
if func.self_param(db).is_none() {
- Highlight::from(HighlightTag::Method) | HighlightModifier::Static
- } else {
- HighlightTag::Method.into()
+ h |= HighlightModifier::Static
}
- } else {
- HighlightTag::Function.into()
- };
+ }
if func.is_unsafe(db) {
h |= HighlightModifier::Unsafe;
}
return h;
}
- hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HighlightTag::Struct,
- hir::ModuleDef::Adt(hir::Adt::Enum(_)) => HighlightTag::Enum,
- hir::ModuleDef::Adt(hir::Adt::Union(_)) => HighlightTag::Union,
- hir::ModuleDef::EnumVariant(_) => HighlightTag::EnumVariant,
- hir::ModuleDef::Const(_) => HighlightTag::Constant,
- hir::ModuleDef::Trait(_) => HighlightTag::Trait,
- hir::ModuleDef::TypeAlias(_) => HighlightTag::TypeAlias,
+ hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HighlightTag::Symbol(SymbolKind::Struct),
+ hir::ModuleDef::Adt(hir::Adt::Enum(_)) => HighlightTag::Symbol(SymbolKind::Enum),
+ hir::ModuleDef::Adt(hir::Adt::Union(_)) => HighlightTag::Symbol(SymbolKind::Union),
+ hir::ModuleDef::Variant(_) => HighlightTag::Symbol(SymbolKind::Variant),
+ hir::ModuleDef::Const(konst) => {
+ let mut h = Highlight::new(HighlightTag::Symbol(SymbolKind::Const));
+ if konst.as_assoc_item(db).is_some() {
+ h |= HighlightModifier::Associated
+ }
+ return h;
+ }
+ hir::ModuleDef::Trait(_) => HighlightTag::Symbol(SymbolKind::Trait),
+ hir::ModuleDef::TypeAlias(type_) => {
+ let mut h = Highlight::new(HighlightTag::Symbol(SymbolKind::TypeAlias));
+ if type_.as_assoc_item(db).is_some() {
+ h |= HighlightModifier::Associated
+ }
+ return h;
+ }
hir::ModuleDef::BuiltinType(_) => HighlightTag::BuiltinType,
hir::ModuleDef::Static(s) => {
- let mut h = Highlight::new(HighlightTag::Static);
+ let mut h = Highlight::new(HighlightTag::Symbol(SymbolKind::Static));
if s.is_mut(db) {
h |= HighlightModifier::Mutable;
h |= HighlightModifier::Unsafe;
return h;
}
},
- Definition::SelfType(_) => HighlightTag::SelfType,
- Definition::TypeParam(_) => HighlightTag::TypeParam,
+ Definition::SelfType(_) => HighlightTag::Symbol(SymbolKind::Impl),
+ Definition::TypeParam(_) => HighlightTag::Symbol(SymbolKind::TypeParam),
Definition::Local(local) => {
- let tag =
- if local.is_param(db) { HighlightTag::ValueParam } else { HighlightTag::Local };
+ let tag = if local.is_param(db) {
+ HighlightTag::Symbol(SymbolKind::ValueParam)
+ } else {
+ HighlightTag::Symbol(SymbolKind::Local)
+ };
let mut h = Highlight::new(tag);
if local.is_mut(db) || local.ty(db).is_mutable_reference() {
h |= HighlightModifier::Mutable;
}
return h;
}
- Definition::LifetimeParam(_) => HighlightTag::Lifetime,
+ Definition::LifetimeParam(_) => HighlightTag::Symbol(SymbolKind::LifetimeParam),
}
.into()
}
};
let tag = match parent.kind() {
- STRUCT => HighlightTag::Struct,
- ENUM => HighlightTag::Enum,
- UNION => HighlightTag::Union,
- TRAIT => HighlightTag::Trait,
- TYPE_ALIAS => HighlightTag::TypeAlias,
- TYPE_PARAM => HighlightTag::TypeParam,
- RECORD_FIELD => HighlightTag::Field,
- MODULE => HighlightTag::Module,
- FN => HighlightTag::Function,
- CONST => HighlightTag::Constant,
- STATIC => HighlightTag::Static,
- VARIANT => HighlightTag::EnumVariant,
- IDENT_PAT => HighlightTag::Local,
+ STRUCT => HighlightTag::Symbol(SymbolKind::Struct),
+ ENUM => HighlightTag::Symbol(SymbolKind::Enum),
+ VARIANT => HighlightTag::Symbol(SymbolKind::Variant),
+ UNION => HighlightTag::Symbol(SymbolKind::Union),
+ TRAIT => HighlightTag::Symbol(SymbolKind::Trait),
+ TYPE_ALIAS => HighlightTag::Symbol(SymbolKind::TypeAlias),
+ TYPE_PARAM => HighlightTag::Symbol(SymbolKind::TypeParam),
+ RECORD_FIELD => HighlightTag::Symbol(SymbolKind::Field),
+ MODULE => HighlightTag::Symbol(SymbolKind::Module),
+ FN => HighlightTag::Symbol(SymbolKind::Function),
+ CONST => HighlightTag::Symbol(SymbolKind::Const),
+ STATIC => HighlightTag::Symbol(SymbolKind::Static),
+ IDENT_PAT => HighlightTag::Symbol(SymbolKind::Local),
_ => default,
};
METHOD_CALL_EXPR => {
return ast::MethodCallExpr::cast(parent)
.and_then(|method_call| highlight_method_call(sema, &method_call))
- .unwrap_or_else(|| HighlightTag::Function.into());
+ .unwrap_or_else(|| HighlightTag::Symbol(SymbolKind::Function).into());
}
FIELD_EXPR => {
- let h = HighlightTag::Field;
+ let h = HighlightTag::Symbol(SymbolKind::Field);
let is_union = ast::FieldExpr::cast(parent)
.and_then(|field_expr| {
let field = sema.resolve_field(&field_expr)?;
_ => {
// within path, decide whether it is module or adt by checking for uppercase name
return if name.text().chars().next().unwrap_or_default().is_uppercase() {
- HighlightTag::Struct
+ HighlightTag::Symbol(SymbolKind::Struct)
} else {
- HighlightTag::Module
+ HighlightTag::Symbol(SymbolKind::Module)
}
.into();
}
};
match parent.kind() {
- CALL_EXPR => HighlightTag::Function.into(),
+ CALL_EXPR => HighlightTag::Symbol(SymbolKind::Function).into(),
_ => if name.text().chars().next().unwrap_or_default().is_uppercase() {
- HighlightTag::Struct.into()
+ HighlightTag::Symbol(SymbolKind::Struct)
} else {
- HighlightTag::Constant
+ HighlightTag::Symbol(SymbolKind::Const)
}
.into(),
}
AstNode, AstToken, SyntaxElement, SyntaxKind, SyntaxNode, TextRange,
};
-use crate::{syntax_highlighting::HighlightedRangeStack, HighlightTag, HighlightedRange};
+use crate::{
+ syntax_highlighting::HighlightedRangeStack, HighlightTag, HighlightedRange, SymbolKind,
+};
#[derive(Default)]
pub(super) struct FormatStringHighlighter {
| FormatSpecifier::Asterisk
| FormatSpecifier::QuestionMark => HighlightTag::FormatSpecifier,
FormatSpecifier::Integer | FormatSpecifier::Zero => HighlightTag::NumericLiteral,
- FormatSpecifier::Identifier => HighlightTag::Local,
+ FormatSpecifier::Identifier => HighlightTag::Symbol(SymbolKind::Local),
})
}
stack.add(comment);
}
stack.pop_and_inject(None);
- stack
- .pop_and_inject(Some(Highlight::from(HighlightTag::Generic) | HighlightModifier::Injected));
+ stack.pop_and_inject(Some(Highlight::from(HighlightTag::Dummy) | HighlightModifier::Injected));
}
use std::{fmt, ops};
+use crate::SymbolKind;
+
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct Highlight {
pub tag: HighlightTag,
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub enum HighlightTag {
- Attribute,
+ Symbol(SymbolKind),
+
BoolLiteral,
BuiltinType,
ByteLiteral,
CharLiteral,
+ NumericLiteral,
+ StringLiteral,
+ Attribute,
Comment,
- Constant,
- Enum,
- EnumVariant,
EscapeSequence,
- Field,
- Function,
- Generic,
+ FormatSpecifier,
Keyword,
- Lifetime,
- Macro,
- Method,
- Module,
- NumericLiteral,
Punctuation,
- SelfKeyword,
- SelfType,
- Static,
- StringLiteral,
- Struct,
- Trait,
- TypeAlias,
- TypeParam,
- Union,
- ValueParam,
- Local,
- UnresolvedReference,
- FormatSpecifier,
Operator,
+ UnresolvedReference,
+
+ // For things which don't have proper Tag, but want to use modifiers.
+ Dummy,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
Injected,
Mutable,
Consuming,
- Unsafe,
Callable,
/// Used for associated functions
Static,
+ /// Used for items in impls&traits.
+ Associated,
+
+ /// Keep this last!
+ Unsafe,
}
impl HighlightTag {
fn as_str(self) -> &'static str {
match self {
+ HighlightTag::Symbol(symbol) => match symbol {
+ SymbolKind::Const => "constant",
+ SymbolKind::Static => "static",
+ SymbolKind::Enum => "enum",
+ SymbolKind::Variant => "enum_variant",
+ SymbolKind::Struct => "struct",
+ SymbolKind::Union => "union",
+ SymbolKind::Field => "field",
+ SymbolKind::Module => "module",
+ SymbolKind::Trait => "trait",
+ SymbolKind::Function => "function",
+ SymbolKind::TypeAlias => "type_alias",
+ SymbolKind::TypeParam => "type_param",
+ SymbolKind::LifetimeParam => "lifetime",
+ SymbolKind::Macro => "macro",
+ SymbolKind::Local => "variable",
+ SymbolKind::ValueParam => "value_param",
+ SymbolKind::SelfParam => "self_keyword",
+ SymbolKind::Impl => "self_type",
+ },
HighlightTag::Attribute => "attribute",
HighlightTag::BoolLiteral => "bool_literal",
HighlightTag::BuiltinType => "builtin_type",
HighlightTag::ByteLiteral => "byte_literal",
HighlightTag::CharLiteral => "char_literal",
HighlightTag::Comment => "comment",
- HighlightTag::Constant => "constant",
- HighlightTag::Enum => "enum",
- HighlightTag::EnumVariant => "enum_variant",
HighlightTag::EscapeSequence => "escape_sequence",
- HighlightTag::Field => "field",
HighlightTag::FormatSpecifier => "format_specifier",
- HighlightTag::Function => "function",
- HighlightTag::Generic => "generic",
+ HighlightTag::Dummy => "dummy",
HighlightTag::Keyword => "keyword",
- HighlightTag::Lifetime => "lifetime",
HighlightTag::Punctuation => "punctuation",
- HighlightTag::Macro => "macro",
- HighlightTag::Method => "method",
- HighlightTag::Module => "module",
HighlightTag::NumericLiteral => "numeric_literal",
HighlightTag::Operator => "operator",
- HighlightTag::SelfKeyword => "self_keyword",
- HighlightTag::SelfType => "self_type",
- HighlightTag::Static => "static",
HighlightTag::StringLiteral => "string_literal",
- HighlightTag::Struct => "struct",
- HighlightTag::Trait => "trait",
- HighlightTag::TypeAlias => "type_alias",
- HighlightTag::TypeParam => "type_param",
- HighlightTag::Union => "union",
- HighlightTag::ValueParam => "value_param",
- HighlightTag::Local => "variable",
HighlightTag::UnresolvedReference => "unresolved_reference",
}
}
}
impl HighlightModifier {
- const ALL: &'static [HighlightModifier] = &[
+ const ALL: &'static [HighlightModifier; HighlightModifier::Unsafe as u8 as usize + 1] = &[
HighlightModifier::Attribute,
HighlightModifier::ControlFlow,
HighlightModifier::Definition,
HighlightModifier::Injected,
HighlightModifier::Mutable,
HighlightModifier::Consuming,
- HighlightModifier::Unsafe,
HighlightModifier::Callable,
HighlightModifier::Static,
+ HighlightModifier::Associated,
+ HighlightModifier::Unsafe,
];
fn as_str(self) -> &'static str {
HighlightModifier::Unsafe => "unsafe",
HighlightModifier::Callable => "callable",
HighlightModifier::Static => "static",
+ HighlightModifier::Associated => "associated",
}
}
}
impl HighlightModifiers {
+ pub fn contains(self, m: HighlightModifier) -> bool {
+ self.0 & m.mask() == m.mask()
+ }
+
pub fn iter(self) -> impl Iterator<Item = HighlightModifier> {
HighlightModifier::ALL.iter().copied().filter(move |it| self.0 & it.mask() == it.mask())
}
<span class="keyword">struct</span> <span class="struct declaration">foo</span> <span class="punctuation">{</span><span class="punctuation">}</span>
<span class="keyword">impl</span> <span class="struct">foo</span> <span class="punctuation">{</span>
- <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="method declaration static">is_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
- <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="method declaration">is_not_static</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
+ <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
+ <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
<span class="punctuation">}</span>
<span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="punctuation">{</span>
- <span class="keyword">fn</span> <span class="method declaration static">t_is_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
- <span class="keyword">fn</span> <span class="method declaration">t_is_not_static</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
+ <span class="keyword">fn</span> <span class="function declaration static associated">t_is_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
+ <span class="keyword">fn</span> <span class="function declaration associated">t_is_not_static</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
<span class="punctuation">}</span>
<span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="punctuation">{</span>
- <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="method declaration static">is_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
- <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="method declaration">is_not_static</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
+ <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
+ <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
<span class="punctuation">}</span>
</code></pre>
\ No newline at end of file
.unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
</style>
<pre><code><span class="comment documentation">/// ```</span>
-<span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="punctuation injected">_</span><span class="generic injected"> </span><span class="operator injected">=</span><span class="generic injected"> </span><span class="string_literal injected">"early doctests should not go boom"</span><span class="punctuation injected">;</span><span class="punctuation injected">
+<span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="dummy injected"> </span><span class="punctuation injected">_</span><span class="dummy injected"> </span><span class="operator injected">=</span><span class="dummy injected"> </span><span class="string_literal injected">"early doctests should not go boom"</span><span class="punctuation injected">;</span><span class="punctuation injected">
</span><span class="comment documentation">/// ```</span>
<span class="keyword">struct</span> <span class="struct declaration">Foo</span> <span class="punctuation">{</span>
<span class="field declaration">bar</span><span class="punctuation">:</span> <span class="builtin_type">bool</span><span class="punctuation">,</span>
<span class="punctuation">}</span>
<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
- <span class="keyword">pub</span> <span class="keyword">const</span> <span class="constant declaration">bar</span><span class="punctuation">:</span> <span class="builtin_type">bool</span> <span class="operator">=</span> <span class="bool_literal">true</span><span class="punctuation">;</span>
+ <span class="keyword">pub</span> <span class="keyword">const</span> <span class="constant declaration associated">bar</span><span class="punctuation">:</span> <span class="builtin_type">bool</span> <span class="operator">=</span> <span class="bool_literal">true</span><span class="punctuation">;</span>
<span class="comment documentation">/// Constructs a new `Foo`.</span>
<span class="comment documentation">///</span>
<span class="comment documentation">/// # Examples</span>
<span class="comment documentation">///</span>
<span class="comment documentation">/// ```</span>
- <span class="comment documentation">/// #</span><span class="generic injected"> </span><span class="attribute attribute injected">#</span><span class="attribute attribute injected">!</span><span class="attribute attribute injected">[</span><span class="function attribute injected">allow</span><span class="punctuation attribute injected">(</span><span class="attribute attribute injected">unused_mut</span><span class="punctuation attribute injected">)</span><span class="attribute attribute injected">]</span>
- <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="keyword injected">mut</span><span class="generic injected"> </span><span class="variable declaration injected mutable">foo</span><span class="punctuation injected">:</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="generic injected"> </span><span class="operator injected">=</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected">
+ <span class="comment documentation">/// #</span><span class="dummy injected"> </span><span class="attribute attribute injected">#</span><span class="attribute attribute injected">!</span><span class="attribute attribute injected">[</span><span class="function attribute injected">allow</span><span class="punctuation attribute injected">(</span><span class="attribute attribute injected">unused_mut</span><span class="punctuation attribute injected">)</span><span class="attribute attribute injected">]</span>
+ <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="dummy injected"> </span><span class="keyword injected">mut</span><span class="dummy injected"> </span><span class="variable declaration injected mutable">foo</span><span class="punctuation injected">:</span><span class="dummy injected"> </span><span class="struct injected">Foo</span><span class="dummy injected"> </span><span class="operator injected">=</span><span class="dummy injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected">
</span> <span class="comment documentation">/// ```</span>
- <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="method declaration static">new</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="struct">Foo</span> <span class="punctuation">{</span>
+ <span class="keyword">pub</span> <span class="keyword">const</span> <span class="keyword">fn</span> <span class="function declaration static associated">new</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="struct">Foo</span> <span class="punctuation">{</span>
<span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">bar</span><span class="punctuation">:</span> <span class="bool_literal">true</span> <span class="punctuation">}</span>
<span class="punctuation">}</span>
<span class="comment documentation">/// # Examples</span>
<span class="comment documentation">///</span>
<span class="comment documentation">/// ```</span>
- <span class="comment documentation">/// </span><span class="keyword injected">use</span><span class="generic injected"> </span><span class="module injected">x</span><span class="operator injected">::</span><span class="module injected">y</span><span class="punctuation injected">;</span>
+ <span class="comment documentation">/// </span><span class="keyword injected">use</span><span class="dummy injected"> </span><span class="module injected">x</span><span class="operator injected">::</span><span class="module injected">y</span><span class="punctuation injected">;</span>
<span class="comment documentation">///</span>
- <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">foo</span><span class="generic injected"> </span><span class="operator injected">=</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span>
+ <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="dummy injected"> </span><span class="variable declaration injected">foo</span><span class="dummy injected"> </span><span class="operator injected">=</span><span class="dummy injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span>
<span class="comment documentation">///</span>
<span class="comment documentation">/// </span><span class="comment injected">// calls bar on foo</span>
- <span class="comment documentation">/// </span><span class="macro injected">assert!</span><span class="punctuation injected">(</span><span class="generic injected">foo</span><span class="operator injected">.</span><span class="generic injected">bar</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span>
+ <span class="comment documentation">/// </span><span class="macro injected">assert!</span><span class="punctuation injected">(</span><span class="dummy injected">foo</span><span class="operator injected">.</span><span class="dummy injected">bar</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span>
<span class="comment documentation">///</span>
- <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">bar</span><span class="generic injected"> </span><span class="operator injected">=</span><span class="generic injected"> </span><span class="variable injected">foo</span><span class="operator injected">.</span><span class="field injected">bar</span><span class="generic injected"> </span><span class="operator injected">||</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="constant injected">bar</span><span class="punctuation injected">;</span>
+ <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="dummy injected"> </span><span class="variable declaration injected">bar</span><span class="dummy injected"> </span><span class="operator injected">=</span><span class="dummy injected"> </span><span class="variable injected">foo</span><span class="operator injected">.</span><span class="field injected">bar</span><span class="dummy injected"> </span><span class="operator injected">||</span><span class="dummy injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="constant injected">bar</span><span class="punctuation injected">;</span>
<span class="comment documentation">///</span>
<span class="comment documentation">/// </span><span class="comment injected">/* multi-line
</span><span class="comment documentation">/// </span><span class="comment injected"> comment */</span>
<span class="comment documentation">///</span>
- <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">multi_line_string</span><span class="generic injected"> </span><span class="operator injected">=</span><span class="generic injected"> </span><span class="string_literal injected">"Foo
+ <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="dummy injected"> </span><span class="variable declaration injected">multi_line_string</span><span class="dummy injected"> </span><span class="operator injected">=</span><span class="dummy injected"> </span><span class="string_literal injected">"Foo
</span><span class="comment documentation">/// </span><span class="string_literal injected"> bar
</span><span class="comment documentation">/// </span><span class="string_literal injected"> "</span><span class="punctuation injected">;</span>
<span class="comment documentation">///</span>
<span class="comment documentation">/// ```</span>
<span class="comment documentation">///</span>
<span class="comment documentation">/// ```rust,no_run</span>
- <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="generic injected"> </span><span class="variable declaration injected">foobar</span><span class="generic injected"> </span><span class="operator injected">=</span><span class="generic injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="operator injected">.</span><span class="function injected">bar</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected">
+ <span class="comment documentation">/// </span><span class="keyword injected">let</span><span class="dummy injected"> </span><span class="variable declaration injected">foobar</span><span class="dummy injected"> </span><span class="operator injected">=</span><span class="dummy injected"> </span><span class="struct injected">Foo</span><span class="operator injected">::</span><span class="function injected">new</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="operator injected">.</span><span class="function injected">bar</span><span class="punctuation injected">(</span><span class="punctuation injected">)</span><span class="punctuation injected">;</span><span class="punctuation injected">
</span> <span class="comment documentation">/// ```</span>
<span class="comment documentation">///</span>
<span class="comment documentation">/// ```sh</span>
<span class="comment documentation">/// echo 1</span>
<span class="comment documentation">/// ```</span>
- <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="method declaration">foo</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">bool</span> <span class="punctuation">{</span>
+ <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">foo</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">bool</span> <span class="punctuation">{</span>
<span class="bool_literal">true</span>
<span class="punctuation">}</span>
<span class="punctuation">}</span>
<span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
<span class="function">fixture</span><span class="punctuation">(</span><span class="string_literal">r#"</span>
<span class="keyword">trait</span> <span class="trait declaration">Foo</span> <span class="punctuation">{</span>
- <span class="keyword">fn</span> <span class="method declaration static">foo</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
+ <span class="keyword">fn</span> <span class="function declaration static associated">foo</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
<span class="macro">println!</span><span class="punctuation">(</span><span class="string_literal">"2 + 2 = {}"</span><span class="punctuation">,</span> <span class="numeric_literal">4</span><span class="punctuation">)</span><span class="punctuation">;</span>
<span class="punctuation">}</span>
<span class="punctuation">}</span><span class="string_literal">"#</span>
<span class="keyword">struct</span> <span class="struct declaration">HasUnsafeFn</span><span class="punctuation">;</span>
<span class="keyword">impl</span> <span class="struct">HasUnsafeFn</span> <span class="punctuation">{</span>
- <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="method declaration unsafe">unsafe_method</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
+ <span class="keyword unsafe">unsafe</span> <span class="keyword">fn</span> <span class="function declaration associated unsafe">unsafe_method</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
<span class="punctuation">}</span>
<span class="keyword">struct</span> <span class="struct declaration">TypeForStaticMut</span> <span class="punctuation">{</span>
<span class="punctuation">}</span>
<span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="punctuation">{</span>
- <span class="keyword">fn</span> <span class="method declaration">calls_autoref</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span><span class="punctuation">;</span>
+ <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span><span class="punctuation">;</span>
<span class="punctuation">}</span>
<span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="punctuation">{</span>
- <span class="keyword">fn</span> <span class="method declaration">calls_autoref</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
+ <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="punctuation">{</span><span class="punctuation">}</span>
<span class="punctuation">}</span>
<span class="keyword">fn</span> <span class="function declaration">main</span><span class="punctuation">(</span><span class="punctuation">)</span> <span class="punctuation">{</span>
<span class="union">Union</span> <span class="punctuation">{</span> <span class="field unsafe">b</span><span class="punctuation">:</span> <span class="numeric_literal">0</span> <span class="punctuation">}</span> <span class="operator">=></span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span>
<span class="union">Union</span> <span class="punctuation">{</span> <span class="field unsafe">a</span> <span class="punctuation">}</span> <span class="operator">=></span> <span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span>
<span class="punctuation">}</span>
- <span class="struct">HasUnsafeFn</span><span class="operator">.</span><span class="method unsafe">unsafe_method</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
+ <span class="struct">HasUnsafeFn</span><span class="operator">.</span><span class="function associated unsafe">unsafe_method</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
<span class="comment">// unsafe deref</span>
<span class="keyword">let</span> <span class="variable declaration">y</span> <span class="operator">=</span> <span class="operator unsafe">*</span><span class="variable">x</span><span class="punctuation">;</span>
<span class="keyword">let</span> <span class="struct">Packed</span> <span class="punctuation">{</span> <span class="field">a</span><span class="punctuation">:</span> <span class="keyword unsafe">ref</span> <span class="variable declaration">_a</span> <span class="punctuation">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="punctuation">;</span>
<span class="comment">// unsafe auto ref of packed field</span>
- <span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="operator">.</span><span class="method unsafe">calls_autoref</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
+ <span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="operator">.</span><span class="function associated unsafe">calls_autoref</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
<span class="punctuation">}</span>
<span class="punctuation">}</span></code></pre>
\ No newline at end of file
<span class="punctuation">}</span>
<span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="punctuation">{</span>
- <span class="keyword">fn</span> <span class="method declaration">bar</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span><span class="punctuation">;</span>
+ <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span><span class="punctuation">;</span>
<span class="punctuation">}</span>
<span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
- <span class="keyword">fn</span> <span class="method declaration">bar</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
+ <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
<span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span>
<span class="punctuation">}</span>
<span class="punctuation">}</span>
<span class="keyword">impl</span> <span class="struct">Foo</span> <span class="punctuation">{</span>
- <span class="keyword">fn</span> <span class="method declaration">baz</span><span class="punctuation">(</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">,</span> <span class="value_param declaration">f</span><span class="punctuation">:</span> <span class="struct">Foo</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
- <span class="value_param">f</span><span class="operator">.</span><span class="method consuming">baz</span><span class="punctuation">(</span><span class="self_keyword mutable consuming">self</span><span class="punctuation">)</span>
+ <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="punctuation">(</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">,</span> <span class="value_param declaration">f</span><span class="punctuation">:</span> <span class="struct">Foo</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
+ <span class="value_param">f</span><span class="operator">.</span><span class="function consuming associated">baz</span><span class="punctuation">(</span><span class="self_keyword mutable consuming">self</span><span class="punctuation">)</span>
<span class="punctuation">}</span>
- <span class="keyword">fn</span> <span class="method declaration">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span>
+ <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span>
<span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span>
<span class="punctuation">}</span>
- <span class="keyword">fn</span> <span class="method declaration">quop</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
+ <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="punctuation">{</span>
<span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span>
<span class="punctuation">}</span>
<span class="punctuation">}</span>
<span class="punctuation">}</span>
<span class="keyword">impl</span> <span class="struct">FooCopy</span> <span class="punctuation">{</span>
- <span class="keyword">fn</span> <span class="method declaration">baz</span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">,</span> <span class="value_param declaration">f</span><span class="punctuation">:</span> <span class="struct">FooCopy</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">u32</span> <span class="punctuation">{</span>
- <span class="value_param">f</span><span class="operator">.</span><span class="method">baz</span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">)</span>
+ <span class="keyword">fn</span> <span class="function declaration associated">baz</span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">,</span> <span class="value_param declaration">f</span><span class="punctuation">:</span> <span class="struct">FooCopy</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">u32</span> <span class="punctuation">{</span>
+ <span class="value_param">f</span><span class="operator">.</span><span class="function associated">baz</span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">)</span>
<span class="punctuation">}</span>
- <span class="keyword">fn</span> <span class="method declaration">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span>
+ <span class="keyword">fn</span> <span class="function declaration associated">qux</span><span class="punctuation">(</span><span class="operator">&</span><span class="keyword">mut</span> <span class="self_keyword mutable">self</span><span class="punctuation">)</span> <span class="punctuation">{</span>
<span class="self_keyword mutable">self</span><span class="operator">.</span><span class="field">x</span> <span class="operator">=</span> <span class="numeric_literal">0</span><span class="punctuation">;</span>
<span class="punctuation">}</span>
- <span class="keyword">fn</span> <span class="method declaration">quop</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">u32</span> <span class="punctuation">{</span>
+ <span class="keyword">fn</span> <span class="function declaration associated">quop</span><span class="punctuation">(</span><span class="operator">&</span><span class="self_keyword">self</span><span class="punctuation">)</span> <span class="operator">-></span> <span class="builtin_type">u32</span> <span class="punctuation">{</span>
<span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span>
<span class="punctuation">}</span>
<span class="punctuation">}</span>
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">foo</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">,</span> <span class="field">y</span><span class="punctuation">:</span> <span class="variable mutable">x</span> <span class="punctuation">}</span><span class="punctuation">;</span>
<span class="keyword">let</span> <span class="variable declaration">foo2</span> <span class="operator">=</span> <span class="struct">Foo</span> <span class="punctuation">{</span> <span class="field">x</span><span class="punctuation">,</span> <span class="field">y</span><span class="punctuation">:</span> <span class="variable mutable">x</span> <span class="punctuation">}</span><span class="punctuation">;</span>
- <span class="variable mutable">foo</span><span class="operator">.</span><span class="method">quop</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
- <span class="variable mutable">foo</span><span class="operator">.</span><span class="method mutable">qux</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
- <span class="variable mutable">foo</span><span class="operator">.</span><span class="method consuming">baz</span><span class="punctuation">(</span><span class="variable consuming">foo2</span><span class="punctuation">)</span><span class="punctuation">;</span>
+ <span class="variable mutable">foo</span><span class="operator">.</span><span class="function associated">quop</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
+ <span class="variable mutable">foo</span><span class="operator">.</span><span class="function mutable associated">qux</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
+ <span class="variable mutable">foo</span><span class="operator">.</span><span class="function consuming associated">baz</span><span class="punctuation">(</span><span class="variable consuming">foo2</span><span class="punctuation">)</span><span class="punctuation">;</span>
<span class="keyword">let</span> <span class="keyword">mut</span> <span class="variable declaration mutable">copy</span> <span class="operator">=</span> <span class="struct">FooCopy</span> <span class="punctuation">{</span> <span class="field">x</span> <span class="punctuation">}</span><span class="punctuation">;</span>
- <span class="variable mutable">copy</span><span class="operator">.</span><span class="method">quop</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
- <span class="variable mutable">copy</span><span class="operator">.</span><span class="method mutable">qux</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
- <span class="variable mutable">copy</span><span class="operator">.</span><span class="method">baz</span><span class="punctuation">(</span><span class="variable mutable">copy</span><span class="punctuation">)</span><span class="punctuation">;</span>
+ <span class="variable mutable">copy</span><span class="operator">.</span><span class="function associated">quop</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
+ <span class="variable mutable">copy</span><span class="operator">.</span><span class="function mutable associated">qux</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">;</span>
+ <span class="variable mutable">copy</span><span class="operator">.</span><span class="function associated">baz</span><span class="punctuation">(</span><span class="variable mutable">copy</span><span class="punctuation">)</span><span class="punctuation">;</span>
<span class="keyword">let</span> <span class="variable declaration callable">a</span> <span class="operator">=</span> <span class="punctuation">|</span><span class="value_param declaration">x</span><span class="punctuation">|</span> <span class="value_param">x</span><span class="punctuation">;</span>
- <span class="keyword">let</span> <span class="variable declaration callable">bar</span> <span class="operator">=</span> <span class="struct">Foo</span><span class="operator">::</span><span class="method">baz</span><span class="punctuation">;</span>
+ <span class="keyword">let</span> <span class="variable declaration callable">bar</span> <span class="operator">=</span> <span class="struct">Foo</span><span class="operator">::</span><span class="function associated">baz</span><span class="punctuation">;</span>
<span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="numeric_literal">-</span><span class="numeric_literal">42</span><span class="punctuation">;</span>
<span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="operator">-</span><span class="variable">baz</span><span class="punctuation">;</span>
<span class="keyword">use</span> <span class="enum">Option</span><span class="operator">::</span><span class="punctuation">*</span><span class="punctuation">;</span>
<span class="keyword">impl</span><span class="punctuation"><</span><span class="type_param declaration">T</span><span class="punctuation">></span> <span class="enum">Option</span><span class="punctuation"><</span><span class="type_param">T</span><span class="punctuation">></span> <span class="punctuation">{</span>
- <span class="keyword">fn</span> <span class="method declaration">and</span><span class="punctuation"><</span><span class="type_param declaration">U</span><span class="punctuation">></span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">,</span> <span class="value_param declaration">other</span><span class="punctuation">:</span> <span class="enum">Option</span><span class="punctuation"><</span><span class="type_param">U</span><span class="punctuation">></span><span class="punctuation">)</span> <span class="operator">-></span> <span class="enum">Option</span><span class="punctuation"><</span><span class="punctuation">(</span><span class="type_param">T</span><span class="punctuation">,</span> <span class="type_param">U</span><span class="punctuation">)</span><span class="punctuation">></span> <span class="punctuation">{</span>
+ <span class="keyword">fn</span> <span class="function declaration associated">and</span><span class="punctuation"><</span><span class="type_param declaration">U</span><span class="punctuation">></span><span class="punctuation">(</span><span class="self_keyword">self</span><span class="punctuation">,</span> <span class="value_param declaration">other</span><span class="punctuation">:</span> <span class="enum">Option</span><span class="punctuation"><</span><span class="type_param">U</span><span class="punctuation">></span><span class="punctuation">)</span> <span class="operator">-></span> <span class="enum">Option</span><span class="punctuation"><</span><span class="punctuation">(</span><span class="type_param">T</span><span class="punctuation">,</span> <span class="type_param">U</span><span class="punctuation">)</span><span class="punctuation">></span> <span class="punctuation">{</span>
<span class="keyword control">match</span> <span class="value_param">other</span> <span class="punctuation">{</span>
<span class="enum_variant">None</span> <span class="operator">=></span> <span class="macro">unimplemented!</span><span class="punctuation">(</span><span class="punctuation">)</span><span class="punctuation">,</span>
<span class="variable declaration">Nope</span> <span class="operator">=></span> <span class="variable">Nope</span><span class="punctuation">,</span>
hir::Adt::Union(it) => it.name(db),
hir::Adt::Enum(it) => it.name(db),
},
- hir::ModuleDef::EnumVariant(it) => it.name(db),
+ hir::ModuleDef::Variant(it) => it.name(db),
hir::ModuleDef::Const(it) => it.name(db)?,
hir::ModuleDef::Static(it) => it.name(db)?,
hir::ModuleDef::Trait(it) => it.name(db),
Some(NameClass::Definition(Definition::ModuleDef(def.into())))
},
ast::Variant(it) => {
- let def: hir::EnumVariant = sema.to_def(&it)?;
+ let def: hir::Variant = sema.to_def(&it)?;
Some(NameClass::Definition(Definition::ModuleDef(def.into())))
},
ast::Fn(it) => {
ast::{
self,
edit::{AstNodeEdit, IndentLevel},
- make, AstNode, PathSegmentKind, VisibilityOwner,
+ make, AstNode, AttrsOwner, PathSegmentKind, VisibilityOwner,
},
AstToken, InsertPosition, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken,
};
}
}
+fn eq_attrs(
+ attrs0: impl Iterator<Item = ast::Attr>,
+ attrs1: impl Iterator<Item = ast::Attr>,
+) -> bool {
+ let attrs0 = attrs0.map(|attr| attr.to_string());
+ let attrs1 = attrs1.map(|attr| attr.to_string());
+ attrs0.eq(attrs1)
+}
+
pub fn try_merge_imports(
lhs: &ast::Use,
rhs: &ast::Use,
if !eq_visibility(lhs.visibility(), rhs.visibility()) {
return None;
}
+ if !eq_attrs(lhs.attrs(), rhs.attrs()) {
+ return None;
+ }
+
let lhs_tree = lhs.use_tree()?;
let rhs_tree = rhs.use_tree()?;
let merged = try_merge_trees(&lhs_tree, &rhs_tree, merge_behavior)?;
)
}
+#[test]
+fn merge_groups_skip_attributed() {
+ check_full(
+ "std::io",
+ r#"
+#[cfg(feature = "gated")] use std::fmt::{Result, Display};
+"#,
+ r#"
+#[cfg(feature = "gated")] use std::fmt::{Result, Display};
+use std::io;
+"#,
+ )
+}
+
#[test]
#[ignore] // FIXME: Support this
fn split_out_merge() {
hir::GenericDef::Trait(it) => it.source(db).value.syntax().text_range(),
hir::GenericDef::TypeAlias(it) => it.source(db).value.syntax().text_range(),
hir::GenericDef::Impl(it) => it.source(db).value.syntax().text_range(),
- hir::GenericDef::EnumVariant(it) => it.source(db).value.syntax().text_range(),
+ hir::GenericDef::Variant(it) => it.source(db).value.syntax().text_range(),
hir::GenericDef::Const(it) => it.source(db).value.syntax().text_range(),
};
let mut res = FxHashMap::default();
use syntax::{
ast::{self, NameOwner},
match_ast, AstNode, Parse, SmolStr, SourceFile,
- SyntaxKind::{self, *},
+ SyntaxKind::*,
SyntaxNode, SyntaxNodePtr, TextRange, WalkEvent,
};
let (start, end) = SymbolIndex::map_value_to_range(indexed_value.value);
for symbol in &symbol_index.symbols[start..end] {
- if self.only_types && !is_type(symbol.kind) {
+ if self.only_types && !symbol.kind.is_type() {
continue;
}
if self.exact && symbol.name != self.query {
}
}
-fn is_type(kind: SyntaxKind) -> bool {
- matches!(kind, STRUCT | ENUM | TRAIT | TYPE_ALIAS)
-}
-
/// The actual data that is stored in the index. It should be as compact as
/// possible.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct FileSymbol {
pub file_id: FileId,
pub name: SmolStr,
- pub kind: SyntaxKind,
+ pub kind: FileSymbolKind,
pub range: TextRange,
pub ptr: SyntaxNodePtr,
pub name_range: Option<TextRange>,
pub container_name: Option<SmolStr>,
}
+#[derive(PartialEq, Eq, Hash, Clone, Copy, Debug)]
+pub enum FileSymbolKind {
+ Function,
+ Struct,
+ Enum,
+ Trait,
+ Module,
+ TypeAlias,
+ Const,
+ Static,
+ Macro,
+}
+
+impl FileSymbolKind {
+ fn is_type(self: FileSymbolKind) -> bool {
+ matches!(
+ self,
+ FileSymbolKind::Struct
+ | FileSymbolKind::Enum
+ | FileSymbolKind::Trait
+ | FileSymbolKind::TypeAlias
+ )
+ }
+}
+
fn source_file_to_file_symbols(source_file: &SourceFile, file_id: FileId) -> Vec<FileSymbol> {
let mut symbols = Vec::new();
let mut stack = Vec::new();
fn to_file_symbol(node: &SyntaxNode, file_id: FileId) -> Option<FileSymbol> {
to_symbol(node).map(move |(name, ptr, name_range)| FileSymbol {
name,
- kind: node.kind(),
+ kind: match node.kind() {
+ FN => FileSymbolKind::Function,
+ STRUCT => FileSymbolKind::Struct,
+ ENUM => FileSymbolKind::Enum,
+ TRAIT => FileSymbolKind::Trait,
+ MODULE => FileSymbolKind::Module,
+ TYPE_ALIAS => FileSymbolKind::TypeAlias,
+ CONST => FileSymbolKind::Const,
+ STATIC => FileSymbolKind::Static,
+ MACRO_RULES => FileSymbolKind::Macro,
+ kind => unreachable!("{:?}", kind),
+ },
range: node.text_range(),
ptr,
file_id,
err = err.or(e);
arena.push(tt.into());
}
- Op::Var { name, kind: _ } => {
+ Op::Var { name, .. } => {
let ExpandResult { value: fragment, err: e } = expand_var(ctx, name);
err = err.or(e);
push_fragment(arena, fragment);
Op::Repeat { subtree, separator, kind }
}
tt::TokenTree::Leaf(leaf) => match leaf {
- tt::Leaf::Punct(..) => return Err(ExpandError::UnexpectedToken),
+ tt::Leaf::Punct(_) => {
+ return Err(ExpandError::UnexpectedToken);
+ }
tt::Leaf::Ident(ident) => {
let name = &ident.text;
let kind = eat_fragment_kind(src, mode)?;
return;
}
- result.push(if k.is_punct() {
+ result.push(if k.is_punct() && k != UNDERSCORE {
assert_eq!(range.len(), TextSize::of('.'));
let delim = match k {
T!['('] => Some((tt::DelimiterKind::Parenthesis, T![')'])),
let leaf: tt::Leaf = match k {
T![true] | T![false] => make_leaf!(Ident),
IDENT => make_leaf!(Ident),
+ UNDERSCORE => make_leaf!(Ident),
k if k.is_keyword() => make_leaf!(Ident),
k if k.is_literal() => make_leaf!(Literal),
LIFETIME_IDENT => {
);
}
+#[test]
+fn test_underscore() {
+ parse_macro(
+ r#"
+ macro_rules! foo {
+ ($_:tt) => { 0 }
+ }
+ "#,
+ )
+ .assert_expand_items(r#"foo! { => }"#, r#"0"#);
+}
+
#[test]
fn test_lifetime() {
parse_macro(
m.complete(p, MACRO_STMTS);
}
+
+ pub(crate) fn attr(p: &mut Parser) {
+ attributes::outer_attrs(p)
+ }
}
pub(crate) fn reparser(
// FIXME: use separate fragment kinds for macro inputs and outputs?
Items,
Statements,
+
+ Attr,
}
pub fn parse_fragment(
FragmentKind::Statement => grammar::fragments::stmt,
FragmentKind::Items => grammar::fragments::macro_items,
FragmentKind::Statements => grammar::fragments::macro_stmts,
+ FragmentKind::Attr => grammar::fragments::attr,
};
parse_from_tokens(token_source, tree_sink, parser)
}
use rustc_hash::FxHashMap;
use crate::cfg_flag::CfgFlag;
+use crate::utf8_stdout;
/// `CargoWorkspace` represents the logical structure of, well, a Cargo
/// workspace. It pretty closely mirrors `cargo metadata` output.
if let Some(parent) = cargo_toml.parent() {
meta.current_dir(parent.to_path_buf());
}
- if let Some(target) = config.target.as_ref() {
- meta.other_options(vec![String::from("--filter-platform"), target.clone()]);
+ let target = if let Some(target) = config.target.as_ref() {
+ Some(target.clone())
+ } else {
+ // cargo metadata defaults to giving information for _all_ targets.
+ // In the absence of a preference from the user, we use the host platform.
+ let mut rustc = Command::new(toolchain::rustc());
+ rustc.current_dir(cargo_toml.parent().unwrap()).arg("-vV");
+ log::debug!("Discovering host platform by {:?}", rustc);
+ match utf8_stdout(rustc) {
+ Ok(stdout) => {
+ let field = "host: ";
+ let target = stdout.lines().find_map(|l| l.strip_prefix(field));
+ if let Some(target) = target {
+ Some(target.to_string())
+ } else {
+ // If we fail to resolve the host platform, it's not the end of the world.
+ log::info!("rustc -vV did not report host platform, got:\n{}", stdout);
+ None
+ }
+ }
+ Err(e) => {
+ log::warn!("Failed to discover host platform: {}", e);
+ None
+ }
+ }
+ };
+ if let Some(target) = target {
+ meta.other_options(vec![String::from("--filter-platform"), target]);
}
let mut meta = meta.exec().with_context(|| {
format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display())
itertools = "0.9.0"
jod-thread = "0.1.0"
log = "0.4.8"
-lsp-types = { version = "0.85.0", features = ["proposed"] }
+lsp-types = { version = "0.86.0", features = ["proposed"] }
parking_lot = "0.11.0"
pico-args = "0.3.1"
oorandom = "11.1.2"
prepare_provider: Some(true),
work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
})),
- on_type_rename_provider: None,
+ linked_editing_range_provider: None,
document_link_provider: None,
color_provider: None,
execute_command_provider: None,
}
.into(),
),
+ moniker_provider: None,
experimental: Some(json!({
"joinLines": true,
"ssr": true,
use ide::{
CompletionResolveCapability, FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData,
- NavigationTarget, Query, RangeInfo, Runnable, RunnableKind, SearchScope, TextEdit,
+ NavigationTarget, Query, RangeInfo, Runnable, RunnableKind, SearchScope, SymbolKind, TextEdit,
};
use itertools::Itertools;
use lsp_server::ErrorCode;
use serde::{Deserialize, Serialize};
use serde_json::to_value;
use stdx::{format_to, split_once};
-use syntax::{algo, ast, AstNode, SyntaxKind, TextRange, TextSize};
+use syntax::{algo, ast, AstNode, TextRange, TextSize};
use crate::{
cargo_target_spec::CargoTargetSpec,
#[allow(deprecated)]
let info = SymbolInformation {
name: nav.name.to_string(),
- kind: to_proto::symbol_kind(nav.kind),
+ kind: nav
+ .kind
+ .map(to_proto::symbol_kind)
+ .unwrap_or(lsp_types::SymbolKind::Variable),
tags: None,
location: to_proto::location_from_nav(snap, nav)?,
container_name,
.filter(|it| {
matches!(
it.kind,
- SyntaxKind::TRAIT
- | SyntaxKind::STRUCT
- | SyntaxKind::ENUM
- | SyntaxKind::UNION
+ SymbolKind::Trait
+ | SymbolKind::Struct
+ | SymbolKind::Enum
+ | SymbolKind::Union
)
})
.map(|it| {
let RangeInfo { range: _, info: navs } = nav_info;
let res = navs
.into_iter()
- .filter(|it| it.kind == SyntaxKind::FN)
+ .filter(|it| it.kind == Some(SymbolKind::Function))
.map(|it| to_proto::call_hierarchy_item(&snap, it))
.collect::<Result<Vec<_>>>()?;
};
use ide::{
- Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, Documentation,
- FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag, HighlightedRange,
- Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup, NavigationTarget,
- ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange, SourceFileEdit, TextEdit,
+ Assist, AssistKind, CallInfo, CompletionItem, CompletionItemKind, Documentation, FileId,
+ FileRange, FileSystemEdit, Fold, FoldKind, Highlight, HighlightModifier, HighlightTag,
+ HighlightedRange, Indel, InlayHint, InlayKind, InsertTextFormat, LineIndex, Markup,
+ NavigationTarget, ReferenceAccess, ResolvedAssist, Runnable, Severity, SourceChange,
+ SourceFileEdit, SymbolKind, TextEdit, TextRange, TextSize,
};
-use ide_db::base_db::{FileId, FileRange};
use itertools::Itertools;
-use syntax::{SyntaxKind, TextRange, TextSize};
use crate::{
cargo_target_spec::CargoTargetSpec, global_state::GlobalStateSnapshot,
lsp_types::Range::new(start, end)
}
-pub(crate) fn symbol_kind(syntax_kind: SyntaxKind) -> lsp_types::SymbolKind {
- match syntax_kind {
- SyntaxKind::FN => lsp_types::SymbolKind::Function,
- SyntaxKind::STRUCT => lsp_types::SymbolKind::Struct,
- SyntaxKind::ENUM => lsp_types::SymbolKind::Enum,
- SyntaxKind::VARIANT => lsp_types::SymbolKind::EnumMember,
- SyntaxKind::TRAIT => lsp_types::SymbolKind::Interface,
- SyntaxKind::MACRO_CALL => lsp_types::SymbolKind::Function,
- SyntaxKind::MODULE => lsp_types::SymbolKind::Module,
- SyntaxKind::TYPE_ALIAS => lsp_types::SymbolKind::TypeParameter,
- SyntaxKind::RECORD_FIELD => lsp_types::SymbolKind::Field,
- SyntaxKind::STATIC => lsp_types::SymbolKind::Constant,
- SyntaxKind::CONST => lsp_types::SymbolKind::Constant,
- SyntaxKind::IMPL => lsp_types::SymbolKind::Object,
- _ => lsp_types::SymbolKind::Variable,
+pub(crate) fn symbol_kind(symbol_kind: SymbolKind) -> lsp_types::SymbolKind {
+ match symbol_kind {
+ SymbolKind::Function => lsp_types::SymbolKind::Function,
+ SymbolKind::Struct => lsp_types::SymbolKind::Struct,
+ SymbolKind::Enum => lsp_types::SymbolKind::Enum,
+ SymbolKind::Variant => lsp_types::SymbolKind::EnumMember,
+ SymbolKind::Trait => lsp_types::SymbolKind::Interface,
+ SymbolKind::Macro => lsp_types::SymbolKind::Function,
+ SymbolKind::Module => lsp_types::SymbolKind::Module,
+ SymbolKind::TypeAlias | SymbolKind::TypeParam => lsp_types::SymbolKind::TypeParameter,
+ SymbolKind::Field => lsp_types::SymbolKind::Field,
+ SymbolKind::Static => lsp_types::SymbolKind::Constant,
+ SymbolKind::Const => lsp_types::SymbolKind::Constant,
+ SymbolKind::Impl => lsp_types::SymbolKind::Object,
+ SymbolKind::Local
+ | SymbolKind::SelfParam
+ | SymbolKind::LifetimeParam
+ | SymbolKind::ValueParam => lsp_types::SymbolKind::Variable,
+ SymbolKind::Union => lsp_types::SymbolKind::Struct,
}
}
) -> (lsp_types::SemanticTokenType, semantic_tokens::ModifierSet) {
let mut mods = semantic_tokens::ModifierSet::default();
let type_ = match highlight.tag {
- HighlightTag::Struct => lsp_types::SemanticTokenType::STRUCT,
- HighlightTag::Enum => lsp_types::SemanticTokenType::ENUM,
- HighlightTag::Union => semantic_tokens::UNION,
- HighlightTag::TypeAlias => semantic_tokens::TYPE_ALIAS,
- HighlightTag::Trait => lsp_types::SemanticTokenType::INTERFACE,
+ HighlightTag::Symbol(symbol) => match symbol {
+ SymbolKind::Module => lsp_types::SemanticTokenType::NAMESPACE,
+ SymbolKind::Impl => lsp_types::SemanticTokenType::TYPE,
+ SymbolKind::Field => lsp_types::SemanticTokenType::PROPERTY,
+ SymbolKind::TypeParam => lsp_types::SemanticTokenType::TYPE_PARAMETER,
+ SymbolKind::LifetimeParam => semantic_tokens::LIFETIME,
+ SymbolKind::ValueParam => lsp_types::SemanticTokenType::PARAMETER,
+ SymbolKind::SelfParam => semantic_tokens::SELF_KEYWORD,
+ SymbolKind::Local => lsp_types::SemanticTokenType::VARIABLE,
+ SymbolKind::Function => {
+ if highlight.modifiers.contains(HighlightModifier::Associated) {
+ lsp_types::SemanticTokenType::METHOD
+ } else {
+ lsp_types::SemanticTokenType::FUNCTION
+ }
+ }
+ SymbolKind::Const => {
+ mods |= semantic_tokens::CONSTANT;
+ mods |= lsp_types::SemanticTokenModifier::STATIC;
+ lsp_types::SemanticTokenType::VARIABLE
+ }
+ SymbolKind::Static => {
+ mods |= lsp_types::SemanticTokenModifier::STATIC;
+ lsp_types::SemanticTokenType::VARIABLE
+ }
+ SymbolKind::Struct => lsp_types::SemanticTokenType::STRUCT,
+ SymbolKind::Enum => lsp_types::SemanticTokenType::ENUM,
+ SymbolKind::Variant => lsp_types::SemanticTokenType::ENUM_MEMBER,
+ SymbolKind::Union => semantic_tokens::UNION,
+ SymbolKind::TypeAlias => semantic_tokens::TYPE_ALIAS,
+ SymbolKind::Trait => lsp_types::SemanticTokenType::INTERFACE,
+ SymbolKind::Macro => lsp_types::SemanticTokenType::MACRO,
+ },
HighlightTag::BuiltinType => semantic_tokens::BUILTIN_TYPE,
- HighlightTag::SelfKeyword => semantic_tokens::SELF_KEYWORD,
- HighlightTag::SelfType => lsp_types::SemanticTokenType::TYPE,
- HighlightTag::Field => lsp_types::SemanticTokenType::PROPERTY,
- HighlightTag::Function => lsp_types::SemanticTokenType::FUNCTION,
- HighlightTag::Generic => semantic_tokens::GENERIC,
- HighlightTag::Module => lsp_types::SemanticTokenType::NAMESPACE,
- HighlightTag::Method => lsp_types::SemanticTokenType::METHOD,
- HighlightTag::Constant => {
- mods |= semantic_tokens::CONSTANT;
- mods |= lsp_types::SemanticTokenModifier::STATIC;
- lsp_types::SemanticTokenType::VARIABLE
- }
- HighlightTag::Static => {
- mods |= lsp_types::SemanticTokenModifier::STATIC;
- lsp_types::SemanticTokenType::VARIABLE
- }
- HighlightTag::EnumVariant => lsp_types::SemanticTokenType::ENUM_MEMBER,
- HighlightTag::Macro => lsp_types::SemanticTokenType::MACRO,
- HighlightTag::ValueParam => lsp_types::SemanticTokenType::PARAMETER,
- HighlightTag::Local => lsp_types::SemanticTokenType::VARIABLE,
- HighlightTag::TypeParam => lsp_types::SemanticTokenType::TYPE_PARAMETER,
- HighlightTag::Lifetime => semantic_tokens::LIFETIME,
+ HighlightTag::Dummy => semantic_tokens::GENERIC,
HighlightTag::ByteLiteral | HighlightTag::NumericLiteral => {
lsp_types::SemanticTokenType::NUMBER
}
HighlightModifier::Unsafe => semantic_tokens::UNSAFE,
HighlightModifier::Callable => semantic_tokens::CALLABLE,
HighlightModifier::Static => lsp_types::SemanticTokenModifier::STATIC,
+ HighlightModifier::Associated => continue,
};
mods |= modifier;
}
lsp_types::ResourceOp::Create(lsp_types::CreateFile {
uri,
options: None,
- annotation: None,
+ annotation_id: None,
})
}
FileSystemEdit::MoveFile { src, dst } => {
old_uri,
new_uri,
options: None,
- annotation: None,
+ annotation_id: None,
})
}
}
.collect(),
)
}),
+ change_annotations: None,
}
}
}
) -> Result<lsp_types::CallHierarchyItem> {
let name = target.name.to_string();
let detail = target.description.clone();
- let kind = symbol_kind(target.kind);
+ let kind = target.kind.map(symbol_kind).unwrap_or(lsp_types::SymbolKind::Function);
let (uri, range, selection_range) = location_info(snap, target)?;
Ok(lsp_types::CallHierarchyItem {
name,
pub fn ty(text: &str) -> ast::Type {
ast_from_text(&format!("impl {} for D {{}};", text))
}
+pub fn ty_unit() -> ast::Type {
+ ty("()")
+}
pub fn assoc_item_list() -> ast::AssocItemList {
ast_from_text("impl C for D {};")
}
}
+impl ast::Attr {
+ /// Returns `text`, parsed as an attribute, but only if it has no errors.
+ pub fn parse(text: &str) -> Result<Self, ()> {
+ parsing::parse_text_fragment(text, parser::FragmentKind::Attr)
+ }
+}
+
/// Matches a `SyntaxNode` against an `ast` type.
///
/// # Example:
}
},
"@types/vscode": {
- "version": "1.51.0",
- "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.51.0.tgz",
- "integrity": "sha512-C/jZ35OT5k/rsJyAK8mS1kM++vMcm89oSWegkzxRCvHllIq0cToZAkIDs6eCY4SKrvik3nrhELizyLcM0onbQA==",
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/@types/vscode/-/vscode-1.52.0.tgz",
+ "integrity": "sha512-Kt3bvWzAvvF/WH9YEcrCICDp0Z7aHhJGhLJ1BxeyNP6yRjonWqWnAIh35/pXAjswAnWOABrYlF7SwXR9+1nnLA==",
"dev": true
},
"@typescript-eslint/eslint-plugin": {
"balanced-match": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
- "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=",
- "dev": true
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
},
"binary-extensions": {
"version": "2.1.0",
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
- "dev": true,
"requires": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
"concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=",
- "dev": true
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
},
"cross-spawn": {
"version": "7.0.3",
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
- "dev": true,
"requires": {
"brace-expansion": "^1.1.7"
}
"dev": true
},
"semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
+ "version": "7.3.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.4.tgz",
+ "integrity": "sha512-tCfb2WLjqFAtXn4KEdxIhalnRtoKFN7nAwj0B3ZXCbQloV2tq5eDbcTmT68JJD3nRJq24/XgxtQKFIpQdtvmVw==",
+ "requires": {
+ "lru-cache": "^6.0.0"
+ },
+ "dependencies": {
+ "lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "requires": {
+ "yallist": "^4.0.0"
+ }
+ },
+ "yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
+ }
+ }
},
"serialize-javascript": {
"version": "5.0.1",
}
},
"vscode-jsonrpc": {
- "version": "6.0.0-next.7",
- "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0-next.7.tgz",
- "integrity": "sha512-1nG+6cuTtpzmXe7yYfO9GCkYlyV6Ai+jDnwidHiT2T7zhc+bJM+VTtc0T/CdTlDyTNTqIcCj0V1nD4TcVjJ7Ug=="
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-6.0.0.tgz",
+ "integrity": "sha512-wnJA4BnEjOSyFMvjZdpiOwhSq9uDoK8e/kpRJDTaMYzwlkrhG1fwDIZI94CLsLzlCK5cIbMMtFlJlfR57Lavmg=="
},
"vscode-languageclient": {
- "version": "7.0.0-next.14",
- "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0-next.14.tgz",
- "integrity": "sha512-QUccfXK2F6AXXRFR8QJCaIz7N2BhJK6ok8E1aO8LHq2IBU33+5hTSJBXs7nEqrqZ/cY2VlDDbMWtMvCxz+/y1w==",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/vscode-languageclient/-/vscode-languageclient-7.0.0.tgz",
+ "integrity": "sha512-P9AXdAPlsCgslpP9pRxYPqkNYV7Xq8300/aZDpO35j1fJm/ncize8iGswzYlcvFw5DQUx4eVk+KvfXdL0rehNg==",
"requires": {
- "semver": "^6.3.0",
- "vscode-languageserver-protocol": "3.16.0-next.11"
+ "minimatch": "^3.0.4",
+ "semver": "^7.3.4",
+ "vscode-languageserver-protocol": "3.16.0"
}
},
"vscode-languageserver-protocol": {
- "version": "3.16.0-next.11",
- "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0-next.11.tgz",
- "integrity": "sha512-31FmupmSmfznuMuGp7qN6h3d/hKUbexbvcwTvrUE/igqRlzFU542s8MtGICx1ERbVuDOLGp96W2Z92qbUbmBPA==",
+ "version": "3.16.0",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.16.0.tgz",
+ "integrity": "sha512-sdeUoAawceQdgIfTI+sdcwkiK2KU+2cbEYA0agzM2uqaUy2UpnnGHtWTHVEtS0ES4zHU0eMFRGN+oQgDxlD66A==",
"requires": {
- "vscode-jsonrpc": "6.0.0-next.7",
- "vscode-languageserver-types": "3.16.0-next.5"
+ "vscode-jsonrpc": "6.0.0",
+ "vscode-languageserver-types": "3.16.0"
}
},
"vscode-languageserver-types": {
- "version": "3.16.0-next.5",
- "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0-next.5.tgz",
- "integrity": "sha512-lf8Y1XXMtF1r2oDDAmJe+drizNXkybSRXAQQk5dPy2rYJsY9SPXYNO074L3THu9zNYepzV5fRJZUPo/V/TLBRQ=="
+ "version": "3.16.0",
+ "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.16.0.tgz",
+ "integrity": "sha512-k8luDIWJWyenLc5ToFQQMaSrqCHiLwyKPHKPQZ5zz21vM+vIVUSvsRpcbiECH4WR88K2XZqc4ScRcZ7nk/jbeA=="
},
"vscode-test": {
"version": "1.4.1",
"Programming Languages"
],
"engines": {
- "vscode": "^1.51.0"
+ "vscode": "^1.52.0"
},
"enableProposedApi": true,
"scripts": {
},
"dependencies": {
"node-fetch": "^2.6.1",
- "vscode-languageclient": "7.0.0-next.14"
+ "vscode-languageclient": "7.0.0"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^17.0.0",
"@types/mocha": "^8.0.4",
"@types/node": "~12.12.6",
"@types/node-fetch": "^2.5.7",
- "@types/vscode": "^1.51.0",
+ "@types/vscode": "^1.52.0",
"@typescript-eslint/eslint-plugin": "^4.9.0",
"@typescript-eslint/parser": "^4.9.0",
"eslint": "^7.15.0",
ctx.pushCleanup(activateTaskProvider(workspaceFolder, ctx.config));
activateInlayHints(ctx);
+ warnAboutRustLangExtensionConflict();
vscode.workspace.onDidChangeConfiguration(
_ => ctx?.client?.sendNotification('workspace/didChangeConfiguration', { settings: "" }),
await state.updateGithubToken(newToken);
}
}
+
+function warnAboutRustLangExtensionConflict() {
+ const rustLangExt = vscode.extensions.getExtension("rust-lang.rust");
+ if (rustLangExt !== undefined) {
+ vscode.window.showWarningMessage(
+ "You have both rust-analyzer (matklad.rust-analyzer) and Rust (rust-lang.rust) " +
+ "plugins enabled. These are known to conflict and cause various functions of " +
+ "both plugins to not work correctly. You should disable one of them.", "Got it");
+ };
+}