diff options
31 files changed, 634 insertions, 331 deletions
diff --git a/.travis.yml b/.travis.yml index 7d66f72d8..af71a9cce 100644 --- a/.travis.yml +++ b/.travis.yml | |||
@@ -14,7 +14,6 @@ matrix: | |||
14 | script: | 14 | script: |
15 | - rustup component add rustfmt | 15 | - rustup component add rustfmt |
16 | - rustup component add rust-src | 16 | - rustup component add rust-src |
17 | - sed -i "s/debug = 1/debug = false/g" Cargo.toml | ||
18 | - cargo test --no-run # let's measure compile time separately | 17 | - cargo test --no-run # let's measure compile time separately |
19 | - cargo test | 18 | - cargo test |
20 | env: | 19 | env: |
diff --git a/Cargo.toml b/Cargo.toml index 97c02b40f..5c57020f7 100644 --- a/Cargo.toml +++ b/Cargo.toml | |||
@@ -2,7 +2,9 @@ | |||
2 | members = [ "crates/*", "xtask/" ] | 2 | members = [ "crates/*", "xtask/" ] |
3 | 3 | ||
4 | [profile.dev] | 4 | [profile.dev] |
5 | debug = 1 # only line info | 5 | # disabling debug info speeds up builds a bunch, |
6 | # and we don't rely on it for debugging that much. | ||
7 | debug = 0 | ||
6 | 8 | ||
7 | [profile.release] | 9 | [profile.release] |
8 | incremental = true | 10 | incremental = true |
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs index 0436d20b7..945f236c2 100644 --- a/crates/ra_hir/src/adt.rs +++ b/crates/ra_hir/src/adt.rs | |||
@@ -12,7 +12,7 @@ use crate::{ | |||
12 | 12 | ||
13 | impl Struct { | 13 | impl Struct { |
14 | pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { | 14 | pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> { |
15 | db.struct_data(self.id).variant_data.clone() | 15 | db.struct_data(self.id.into()).variant_data.clone() |
16 | } | 16 | } |
17 | } | 17 | } |
18 | 18 | ||
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 9d0db8024..e5bfad3ca 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -288,7 +288,7 @@ pub struct Struct { | |||
288 | 288 | ||
289 | impl Struct { | 289 | impl Struct { |
290 | pub fn module(self, db: &impl DefDatabase) -> Module { | 290 | pub fn module(self, db: &impl DefDatabase) -> Module { |
291 | Module { id: self.id.module(db) } | 291 | Module { id: self.id.0.module(db) } |
292 | } | 292 | } |
293 | 293 | ||
294 | pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { | 294 | pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { |
@@ -296,11 +296,11 @@ impl Struct { | |||
296 | } | 296 | } |
297 | 297 | ||
298 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { | 298 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { |
299 | db.struct_data(self.id).name.clone() | 299 | db.struct_data(self.id.into()).name.clone() |
300 | } | 300 | } |
301 | 301 | ||
302 | pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { | 302 | pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> { |
303 | db.struct_data(self.id) | 303 | db.struct_data(self.id.into()) |
304 | .variant_data | 304 | .variant_data |
305 | .fields() | 305 | .fields() |
306 | .into_iter() | 306 | .into_iter() |
@@ -310,7 +310,7 @@ impl Struct { | |||
310 | } | 310 | } |
311 | 311 | ||
312 | pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { | 312 | pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> { |
313 | db.struct_data(self.id) | 313 | db.struct_data(self.id.into()) |
314 | .variant_data | 314 | .variant_data |
315 | .fields() | 315 | .fields() |
316 | .into_iter() | 316 | .into_iter() |
@@ -346,11 +346,11 @@ pub struct Union { | |||
346 | 346 | ||
347 | impl Union { | 347 | impl Union { |
348 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { | 348 | pub fn name(self, db: &impl DefDatabase) -> Option<Name> { |
349 | db.union_data(self.id).name.clone() | 349 | db.struct_data(self.id.into()).name.clone() |
350 | } | 350 | } |
351 | 351 | ||
352 | pub fn module(self, db: &impl HirDatabase) -> Module { | 352 | pub fn module(self, db: &impl HirDatabase) -> Module { |
353 | Module { id: self.id.module(db) } | 353 | Module { id: self.id.0.module(db) } |
354 | } | 354 | } |
355 | 355 | ||
356 | pub fn ty(self, db: &impl HirDatabase) -> Ty { | 356 | pub fn ty(self, db: &impl HirDatabase) -> Ty { |
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index 6d116ee75..247ae3e55 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs | |||
@@ -78,13 +78,13 @@ impl HasSource for StructField { | |||
78 | impl HasSource for Struct { | 78 | impl HasSource for Struct { |
79 | type Ast = ast::StructDef; | 79 | type Ast = ast::StructDef; |
80 | fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::StructDef> { | 80 | fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::StructDef> { |
81 | self.id.source(db) | 81 | self.id.0.source(db) |
82 | } | 82 | } |
83 | } | 83 | } |
84 | impl HasSource for Union { | 84 | impl HasSource for Union { |
85 | type Ast = ast::StructDef; | 85 | type Ast = ast::StructDef; |
86 | fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::StructDef> { | 86 | fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::StructDef> { |
87 | self.id.source(db) | 87 | self.id.0.source(db) |
88 | } | 88 | } |
89 | } | 89 | } |
90 | impl HasSource for Enum { | 90 | impl HasSource for Enum { |
diff --git a/crates/ra_hir/src/expr/scope.rs b/crates/ra_hir/src/expr/scope.rs index c14c2ab66..5a1eade2c 100644 --- a/crates/ra_hir/src/expr/scope.rs +++ b/crates/ra_hir/src/expr/scope.rs | |||
@@ -67,10 +67,7 @@ impl ExprScopes { | |||
67 | &self.scopes[scope].entries | 67 | &self.scopes[scope].entries |
68 | } | 68 | } |
69 | 69 | ||
70 | pub(crate) fn scope_chain<'a>( | 70 | pub(crate) fn scope_chain(&self, scope: Option<ScopeId>) -> impl Iterator<Item = ScopeId> + '_ { |
71 | &'a self, | ||
72 | scope: Option<ScopeId>, | ||
73 | ) -> impl Iterator<Item = ScopeId> + 'a { | ||
74 | std::iter::successors(scope, move |&scope| self.scopes[scope].parent) | 71 | std::iter::successors(scope, move |&scope| self.scopes[scope].parent) |
75 | } | 72 | } |
76 | 73 | ||
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs index 9899bdbbc..c95d2cdd0 100644 --- a/crates/ra_hir/src/from_source.rs +++ b/crates/ra_hir/src/from_source.rs | |||
@@ -1,5 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir_def::{StructId, StructOrUnionId, UnionId}; | ||
3 | use hir_expand::name::AsName; | 4 | use hir_expand::name::AsName; |
4 | use ra_syntax::ast::{self, AstNode, NameOwner}; | 5 | use ra_syntax::ast::{self, AstNode, NameOwner}; |
5 | 6 | ||
@@ -15,18 +16,19 @@ pub trait FromSource: Sized { | |||
15 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self>; | 16 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self>; |
16 | } | 17 | } |
17 | 18 | ||
19 | // FIXIME: these two impls are wrong, `ast::StructDef` might produce either a struct or a union | ||
18 | impl FromSource for Struct { | 20 | impl FromSource for Struct { |
19 | type Ast = ast::StructDef; | 21 | type Ast = ast::StructDef; |
20 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | 22 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { |
21 | let id = from_source(db, src)?; | 23 | let id: StructOrUnionId = from_source(db, src)?; |
22 | Some(Struct { id }) | 24 | Some(Struct { id: StructId(id) }) |
23 | } | 25 | } |
24 | } | 26 | } |
25 | impl FromSource for Union { | 27 | impl FromSource for Union { |
26 | type Ast = ast::StructDef; | 28 | type Ast = ast::StructDef; |
27 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { | 29 | fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { |
28 | let id = from_source(db, src)?; | 30 | let id: StructOrUnionId = from_source(db, src)?; |
29 | Some(Union { id }) | 31 | Some(Union { id: UnionId(id) }) |
30 | } | 32 | } |
31 | } | 33 | } |
32 | impl FromSource for Enum { | 34 | impl FromSource for Enum { |
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 131f6c797..9dc8d139b 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs | |||
@@ -76,7 +76,11 @@ pub use crate::{ | |||
76 | resolve::ScopeDef, | 76 | resolve::ScopeDef, |
77 | source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, | 77 | source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, |
78 | ty::{ | 78 | ty::{ |
79 | display::HirDisplay, ApplicationTy, CallableDef, Substs, TraitRef, Ty, TypeCtor, TypeWalk, | 79 | display::HirDisplay, |
80 | primitive::{ | ||
81 | FloatBitness, FloatTy, IntBitness, IntTy, Signedness, UncertainFloatTy, UncertainIntTy, | ||
82 | }, | ||
83 | ApplicationTy, CallableDef, Substs, TraitRef, Ty, TypeCtor, TypeWalk, | ||
80 | }, | 84 | }, |
81 | }; | 85 | }; |
82 | 86 | ||
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index d26b16cb2..1fed5025e 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -665,7 +665,7 @@ fn type_for_builtin(def: BuiltinType) -> Ty { | |||
665 | } | 665 | } |
666 | 666 | ||
667 | fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { | 667 | fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { |
668 | let struct_data = db.struct_data(def.id); | 668 | let struct_data = db.struct_data(def.id.into()); |
669 | let fields = match struct_data.variant_data.fields() { | 669 | let fields = match struct_data.variant_data.fields() { |
670 | Some(fields) => fields, | 670 | Some(fields) => fields, |
671 | None => panic!("fn_sig_for_struct_constructor called on unit struct"), | 671 | None => panic!("fn_sig_for_struct_constructor called on unit struct"), |
@@ -681,7 +681,7 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { | |||
681 | 681 | ||
682 | /// Build the type of a tuple struct constructor. | 682 | /// Build the type of a tuple struct constructor. |
683 | fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { | 683 | fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { |
684 | let struct_data = db.struct_data(def.id); | 684 | let struct_data = db.struct_data(def.id.into()); |
685 | if struct_data.variant_data.fields().is_none() { | 685 | if struct_data.variant_data.fields().is_none() { |
686 | return type_for_adt(db, def); // Unit struct | 686 | return type_for_adt(db, def); // Unit struct |
687 | } | 687 | } |
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs index 8f41e55d2..a29c4d41e 100644 --- a/crates/ra_hir_def/src/adt.rs +++ b/crates/ra_hir_def/src/adt.rs | |||
@@ -8,7 +8,7 @@ use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; | |||
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
10 | db::DefDatabase2, type_ref::TypeRef, AstItemDef, EnumId, LocalEnumVariantId, | 10 | db::DefDatabase2, type_ref::TypeRef, AstItemDef, EnumId, LocalEnumVariantId, |
11 | LocalStructFieldId, StructId, UnionId, | 11 | LocalStructFieldId, StructOrUnionId, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | /// Note that we use `StructData` for unions as well! | 14 | /// Note that we use `StructData` for unions as well! |
@@ -49,15 +49,11 @@ pub struct StructFieldData { | |||
49 | } | 49 | } |
50 | 50 | ||
51 | impl StructData { | 51 | impl StructData { |
52 | pub(crate) fn struct_data_query(db: &impl DefDatabase2, struct_: StructId) -> Arc<StructData> { | 52 | pub(crate) fn struct_data_query( |
53 | let src = struct_.source(db); | 53 | db: &impl DefDatabase2, |
54 | let name = src.ast.name().map(|n| n.as_name()); | 54 | id: StructOrUnionId, |
55 | let variant_data = VariantData::new(src.ast.kind()); | 55 | ) -> Arc<StructData> { |
56 | let variant_data = Arc::new(variant_data); | 56 | let src = id.source(db); |
57 | Arc::new(StructData { name, variant_data }) | ||
58 | } | ||
59 | pub(crate) fn union_data_query(db: &impl DefDatabase2, struct_: UnionId) -> Arc<StructData> { | ||
60 | let src = struct_.source(db); | ||
61 | let name = src.ast.name().map(|n| n.as_name()); | 57 | let name = src.ast.name().map(|n| n.as_name()); |
62 | let variant_data = VariantData::new(src.ast.kind()); | 58 | let variant_data = VariantData::new(src.ast.kind()); |
63 | let variant_data = Arc::new(variant_data); | 59 | let variant_data = Arc::new(variant_data); |
diff --git a/crates/ra_hir_def/src/builtin_type.rs b/crates/ra_hir_def/src/builtin_type.rs index 12929caa9..2ec0c83fe 100644 --- a/crates/ra_hir_def/src/builtin_type.rs +++ b/crates/ra_hir_def/src/builtin_type.rs | |||
@@ -3,6 +3,8 @@ | |||
3 | //! A peculiarity of built-in types is that they are always available and are | 3 | //! A peculiarity of built-in types is that they are always available and are |
4 | //! not associated with any particular crate. | 4 | //! not associated with any particular crate. |
5 | 5 | ||
6 | use std::fmt; | ||
7 | |||
6 | use hir_expand::name::{self, Name}; | 8 | use hir_expand::name::{self, Name}; |
7 | 9 | ||
8 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] | 10 | #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] |
@@ -61,3 +63,33 @@ impl BuiltinType { | |||
61 | (name::F64, BuiltinType::Float { bitness: FloatBitness::X64 }), | 63 | (name::F64, BuiltinType::Float { bitness: FloatBitness::X64 }), |
62 | ]; | 64 | ]; |
63 | } | 65 | } |
66 | |||
67 | impl fmt::Display for BuiltinType { | ||
68 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
69 | let type_name = match self { | ||
70 | BuiltinType::Char => "char", | ||
71 | BuiltinType::Bool => "bool", | ||
72 | BuiltinType::Str => "str", | ||
73 | BuiltinType::Int { signedness, bitness } => match (signedness, bitness) { | ||
74 | (Signedness::Signed, IntBitness::Xsize) => "isize", | ||
75 | (Signedness::Signed, IntBitness::X8) => "i8", | ||
76 | (Signedness::Signed, IntBitness::X16) => "i16", | ||
77 | (Signedness::Signed, IntBitness::X32) => "i32", | ||
78 | (Signedness::Signed, IntBitness::X64) => "i64", | ||
79 | (Signedness::Signed, IntBitness::X128) => "i128", | ||
80 | |||
81 | (Signedness::Unsigned, IntBitness::Xsize) => "usize", | ||
82 | (Signedness::Unsigned, IntBitness::X8) => "u8", | ||
83 | (Signedness::Unsigned, IntBitness::X16) => "u16", | ||
84 | (Signedness::Unsigned, IntBitness::X32) => "u32", | ||
85 | (Signedness::Unsigned, IntBitness::X64) => "u64", | ||
86 | (Signedness::Unsigned, IntBitness::X128) => "u128", | ||
87 | }, | ||
88 | BuiltinType::Float { bitness } => match bitness { | ||
89 | FloatBitness::X32 => "f32", | ||
90 | FloatBitness::X64 => "f64", | ||
91 | }, | ||
92 | }; | ||
93 | f.write_str(type_name) | ||
94 | } | ||
95 | } | ||
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index a42348101..29cf71a59 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs | |||
@@ -11,7 +11,7 @@ use crate::{ | |||
11 | raw::{ImportSourceMap, RawItems}, | 11 | raw::{ImportSourceMap, RawItems}, |
12 | CrateDefMap, | 12 | CrateDefMap, |
13 | }, | 13 | }, |
14 | EnumId, StructId, UnionId, | 14 | EnumId, StructOrUnionId, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | #[salsa::query_group(InternDatabaseStorage)] | 17 | #[salsa::query_group(InternDatabaseStorage)] |
@@ -19,9 +19,8 @@ pub trait InternDatabase: SourceDatabase { | |||
19 | #[salsa::interned] | 19 | #[salsa::interned] |
20 | fn intern_function(&self, loc: crate::ItemLoc<ast::FnDef>) -> crate::FunctionId; | 20 | fn intern_function(&self, loc: crate::ItemLoc<ast::FnDef>) -> crate::FunctionId; |
21 | #[salsa::interned] | 21 | #[salsa::interned] |
22 | fn intern_struct(&self, loc: crate::ItemLoc<ast::StructDef>) -> crate::StructId; | 22 | fn intern_struct_or_union(&self, loc: crate::ItemLoc<ast::StructDef>) |
23 | #[salsa::interned] | 23 | -> crate::StructOrUnionId; |
24 | fn intern_union(&self, loc: crate::ItemLoc<ast::StructDef>) -> crate::UnionId; | ||
25 | #[salsa::interned] | 24 | #[salsa::interned] |
26 | fn intern_enum(&self, loc: crate::ItemLoc<ast::EnumDef>) -> crate::EnumId; | 25 | fn intern_enum(&self, loc: crate::ItemLoc<ast::EnumDef>) -> crate::EnumId; |
27 | #[salsa::interned] | 26 | #[salsa::interned] |
@@ -49,10 +48,7 @@ pub trait DefDatabase2: InternDatabase + AstDatabase { | |||
49 | fn crate_def_map(&self, krate: CrateId) -> Arc<CrateDefMap>; | 48 | fn crate_def_map(&self, krate: CrateId) -> Arc<CrateDefMap>; |
50 | 49 | ||
51 | #[salsa::invoke(StructData::struct_data_query)] | 50 | #[salsa::invoke(StructData::struct_data_query)] |
52 | fn struct_data(&self, s: StructId) -> Arc<StructData>; | 51 | fn struct_data(&self, id: StructOrUnionId) -> Arc<StructData>; |
53 | |||
54 | #[salsa::invoke(StructData::union_data_query)] | ||
55 | fn union_data(&self, s: UnionId) -> Arc<StructData>; | ||
56 | 52 | ||
57 | #[salsa::invoke(EnumData::enum_data_query)] | 53 | #[salsa::invoke(EnumData::enum_data_query)] |
58 | fn enum_data(&self, e: EnumId) -> Arc<EnumData>; | 54 | fn enum_data(&self, e: EnumId) -> Arc<EnumData>; |
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 63ed2a098..239317efe 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs | |||
@@ -205,26 +205,30 @@ impl AstItemDef<ast::FnDef> for FunctionId { | |||
205 | } | 205 | } |
206 | 206 | ||
207 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 207 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
208 | pub struct StructId(salsa::InternId); | 208 | pub struct StructOrUnionId(salsa::InternId); |
209 | impl_intern_key!(StructId); | 209 | impl_intern_key!(StructOrUnionId); |
210 | impl AstItemDef<ast::StructDef> for StructId { | 210 | impl AstItemDef<ast::StructDef> for StructOrUnionId { |
211 | fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::StructDef>) -> Self { | 211 | fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::StructDef>) -> Self { |
212 | db.intern_struct(loc) | 212 | db.intern_struct_or_union(loc) |
213 | } | 213 | } |
214 | fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::StructDef> { | 214 | fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::StructDef> { |
215 | db.lookup_intern_struct(self) | 215 | db.lookup_intern_struct_or_union(self) |
216 | } | 216 | } |
217 | } | 217 | } |
218 | 218 | ||
219 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 219 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
220 | pub struct UnionId(salsa::InternId); | 220 | pub struct StructId(pub StructOrUnionId); |
221 | impl_intern_key!(UnionId); | 221 | impl From<StructId> for StructOrUnionId { |
222 | impl AstItemDef<ast::StructDef> for UnionId { | 222 | fn from(id: StructId) -> StructOrUnionId { |
223 | fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::StructDef>) -> Self { | 223 | id.0 |
224 | db.intern_union(loc) | ||
225 | } | 224 | } |
226 | fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::StructDef> { | 225 | } |
227 | db.lookup_intern_union(self) | 226 | |
227 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
228 | pub struct UnionId(pub StructOrUnionId); | ||
229 | impl From<UnionId> for StructOrUnionId { | ||
230 | fn from(id: UnionId) -> StructOrUnionId { | ||
231 | id.0 | ||
228 | } | 232 | } |
229 | } | 233 | } |
230 | 234 | ||
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs index 30664278e..37d0f3093 100644 --- a/crates/ra_hir_def/src/nameres/collector.rs +++ b/crates/ra_hir_def/src/nameres/collector.rs | |||
@@ -20,7 +20,8 @@ use crate::{ | |||
20 | }, | 20 | }, |
21 | path::{Path, PathKind}, | 21 | path::{Path, PathKind}, |
22 | AdtId, AstId, AstItemDef, ConstId, CrateModuleId, EnumId, EnumVariantId, FunctionId, | 22 | AdtId, AstId, AstItemDef, ConstId, CrateModuleId, EnumId, EnumVariantId, FunctionId, |
23 | LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, TraitId, TypeAliasId, UnionId, | 23 | LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, StructOrUnionId, TraitId, TypeAliasId, |
24 | UnionId, | ||
24 | }; | 25 | }; |
25 | 26 | ||
26 | pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap { | 27 | pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap { |
@@ -36,11 +37,12 @@ pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> | |||
36 | ); | 37 | ); |
37 | 38 | ||
38 | // look for the prelude | 39 | // look for the prelude |
39 | if def_map.prelude.is_none() { | 40 | // If the dependency defines a prelude, we overwrite an already defined |
40 | let map = db.crate_def_map(dep.crate_id); | 41 | // prelude. This is necessary to import the "std" prelude if a crate |
41 | if map.prelude.is_some() { | 42 | // depends on both "core" and "std". |
42 | def_map.prelude = map.prelude; | 43 | let dep_def_map = db.crate_def_map(dep.crate_id); |
43 | } | 44 | if dep_def_map.prelude.is_some() { |
45 | def_map.prelude = dep_def_map.prelude; | ||
44 | } | 46 | } |
45 | } | 47 | } |
46 | 48 | ||
@@ -665,12 +667,14 @@ where | |||
665 | PerNs::values(FunctionId::from_ast_id(ctx, ast_id).into()) | 667 | PerNs::values(FunctionId::from_ast_id(ctx, ast_id).into()) |
666 | } | 668 | } |
667 | raw::DefKind::Struct(ast_id) => { | 669 | raw::DefKind::Struct(ast_id) => { |
668 | let s = StructId::from_ast_id(ctx, ast_id).into(); | 670 | let id = StructOrUnionId::from_ast_id(ctx, ast_id).into(); |
671 | let s = StructId(id).into(); | ||
669 | PerNs::both(s, s) | 672 | PerNs::both(s, s) |
670 | } | 673 | } |
671 | raw::DefKind::Union(ast_id) => { | 674 | raw::DefKind::Union(ast_id) => { |
672 | let s = UnionId::from_ast_id(ctx, ast_id).into(); | 675 | let id = StructOrUnionId::from_ast_id(ctx, ast_id).into(); |
673 | PerNs::both(s, s) | 676 | let u = UnionId(id).into(); |
677 | PerNs::both(u, u) | ||
674 | } | 678 | } |
675 | raw::DefKind::Enum(ast_id) => PerNs::types(EnumId::from_ast_id(ctx, ast_id).into()), | 679 | raw::DefKind::Enum(ast_id) => PerNs::types(EnumId::from_ast_id(ctx, ast_id).into()), |
676 | raw::DefKind::Const(ast_id) => PerNs::values(ConstId::from_ast_id(ctx, ast_id).into()), | 680 | raw::DefKind::Const(ast_id) => PerNs::values(ConstId::from_ast_id(ctx, ast_id).into()), |
diff --git a/crates/ra_hir_def/src/nameres/tests.rs b/crates/ra_hir_def/src/nameres/tests.rs index 52bd0aa91..256f7d4be 100644 --- a/crates/ra_hir_def/src/nameres/tests.rs +++ b/crates/ra_hir_def/src/nameres/tests.rs | |||
@@ -464,6 +464,37 @@ fn values_dont_shadow_extern_crates() { | |||
464 | } | 464 | } |
465 | 465 | ||
466 | #[test] | 466 | #[test] |
467 | fn std_prelude_takes_precedence_above_core_prelude() { | ||
468 | let map = def_map( | ||
469 | r#" | ||
470 | //- /main.rs crate:main deps:core,std | ||
471 | use {Foo, Bar}; | ||
472 | |||
473 | //- /std.rs crate:std deps:core | ||
474 | #[prelude_import] | ||
475 | pub use self::prelude::*; | ||
476 | mod prelude { | ||
477 | pub struct Foo; | ||
478 | pub use core::prelude::Bar; | ||
479 | } | ||
480 | |||
481 | //- /core.rs crate:core | ||
482 | #[prelude_import] | ||
483 | pub use self::prelude::*; | ||
484 | mod prelude { | ||
485 | pub struct Bar; | ||
486 | } | ||
487 | "#, | ||
488 | ); | ||
489 | |||
490 | assert_snapshot!(map, @r###" | ||
491 | â‹®crate | ||
492 | â‹®Bar: t v | ||
493 | â‹®Foo: t v | ||
494 | "###); | ||
495 | } | ||
496 | |||
497 | #[test] | ||
467 | fn cfg_not_test() { | 498 | fn cfg_not_test() { |
468 | let map = def_map( | 499 | let map = def_map( |
469 | r#" | 500 | r#" |
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs index 4e56de3f5..3e205efd1 100644 --- a/crates/ra_ide_api/src/completion/complete_scope.rs +++ b/crates/ra_ide_api/src/completion/complete_scope.rs | |||
@@ -598,6 +598,68 @@ mod tests { | |||
598 | } | 598 | } |
599 | 599 | ||
600 | #[test] | 600 | #[test] |
601 | fn completes_std_prelude_if_core_is_defined() { | ||
602 | assert_debug_snapshot!( | ||
603 | do_reference_completion( | ||
604 | " | ||
605 | //- /main.rs | ||
606 | fn foo() { let x: <|> } | ||
607 | |||
608 | //- /core/lib.rs | ||
609 | #[prelude_import] | ||
610 | use prelude::*; | ||
611 | |||
612 | mod prelude { | ||
613 | struct Option; | ||
614 | } | ||
615 | |||
616 | //- /std/lib.rs | ||
617 | #[prelude_import] | ||
618 | use prelude::*; | ||
619 | |||
620 | mod prelude { | ||
621 | struct String; | ||
622 | } | ||
623 | " | ||
624 | ), | ||
625 | @r###" | ||
626 | [ | ||
627 | CompletionItem { | ||
628 | label: "String", | ||
629 | source_range: [18; 18), | ||
630 | delete: [18; 18), | ||
631 | insert: "String", | ||
632 | kind: Struct, | ||
633 | }, | ||
634 | CompletionItem { | ||
635 | label: "core", | ||
636 | source_range: [18; 18), | ||
637 | delete: [18; 18), | ||
638 | insert: "core", | ||
639 | kind: Module, | ||
640 | }, | ||
641 | CompletionItem { | ||
642 | label: "foo()", | ||
643 | source_range: [18; 18), | ||
644 | delete: [18; 18), | ||
645 | insert: "foo()$0", | ||
646 | kind: Function, | ||
647 | lookup: "foo", | ||
648 | detail: "fn foo()", | ||
649 | }, | ||
650 | CompletionItem { | ||
651 | label: "std", | ||
652 | source_range: [18; 18), | ||
653 | delete: [18; 18), | ||
654 | insert: "std", | ||
655 | kind: Module, | ||
656 | }, | ||
657 | ] | ||
658 | "### | ||
659 | ); | ||
660 | } | ||
661 | |||
662 | #[test] | ||
601 | fn completes_macros_as_value() { | 663 | fn completes_macros_as_value() { |
602 | assert_debug_snapshot!( | 664 | assert_debug_snapshot!( |
603 | do_reference_completion( | 665 | do_reference_completion( |
diff --git a/crates/ra_ide_api/src/display.rs b/crates/ra_ide_api/src/display.rs index a980c56bc..30617412a 100644 --- a/crates/ra_ide_api/src/display.rs +++ b/crates/ra_ide_api/src/display.rs | |||
@@ -15,7 +15,7 @@ pub use function_signature::FunctionSignature; | |||
15 | pub use navigation_target::NavigationTarget; | 15 | pub use navigation_target::NavigationTarget; |
16 | pub use structure::{file_structure, StructureNode}; | 16 | pub use structure::{file_structure, StructureNode}; |
17 | 17 | ||
18 | pub(crate) use navigation_target::{description_from_symbol, docs_from_symbol}; | 18 | pub(crate) use navigation_target::{description_from_symbol, docs_from_symbol, ToNav}; |
19 | pub(crate) use short_label::ShortLabel; | 19 | pub(crate) use short_label::ShortLabel; |
20 | 20 | ||
21 | pub(crate) fn function_label(node: &ast::FnDef) -> String { | 21 | pub(crate) fn function_label(node: &ast::FnDef) -> String { |
diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs index 1bf81e7d5..41d467564 100644 --- a/crates/ra_ide_api/src/display/navigation_target.rs +++ b/crates/ra_ide_api/src/display/navigation_target.rs | |||
@@ -29,19 +29,8 @@ pub struct NavigationTarget { | |||
29 | docs: Option<String>, | 29 | docs: Option<String>, |
30 | } | 30 | } |
31 | 31 | ||
32 | fn find_range_from_node( | 32 | pub(crate) trait ToNav { |
33 | db: &RootDatabase, | 33 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget; |
34 | src: hir::HirFileId, | ||
35 | node: &SyntaxNode, | ||
36 | ) -> (FileId, TextRange) { | ||
37 | let text_range = node.text_range(); | ||
38 | let (file_id, text_range) = src | ||
39 | .expansion_info(db) | ||
40 | .and_then(|expansion_info| expansion_info.find_range(text_range)) | ||
41 | .unwrap_or((src, text_range)); | ||
42 | |||
43 | // FIXME: handle recursive macro generated macro | ||
44 | (file_id.original_file(db), text_range) | ||
45 | } | 34 | } |
46 | 35 | ||
47 | impl NavigationTarget { | 36 | impl NavigationTarget { |
@@ -95,19 +84,6 @@ impl NavigationTarget { | |||
95 | NavigationTarget::from_named(db, file_id.into(), pat, None, None) | 84 | NavigationTarget::from_named(db, file_id.into(), pat, None, None) |
96 | } | 85 | } |
97 | 86 | ||
98 | pub(crate) fn from_symbol(db: &RootDatabase, symbol: FileSymbol) -> NavigationTarget { | ||
99 | NavigationTarget { | ||
100 | file_id: symbol.file_id, | ||
101 | name: symbol.name.clone(), | ||
102 | kind: symbol.ptr.kind(), | ||
103 | full_range: symbol.ptr.range(), | ||
104 | focus_range: symbol.name_range, | ||
105 | container_name: symbol.container_name.clone(), | ||
106 | description: description_from_symbol(db, &symbol), | ||
107 | docs: docs_from_symbol(db, &symbol), | ||
108 | } | ||
109 | } | ||
110 | |||
111 | pub(crate) fn from_pat( | 87 | pub(crate) fn from_pat( |
112 | db: &RootDatabase, | 88 | db: &RootDatabase, |
113 | file_id: FileId, | 89 | file_id: FileId, |
@@ -136,39 +112,6 @@ impl NavigationTarget { | |||
136 | } | 112 | } |
137 | } | 113 | } |
138 | 114 | ||
139 | pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget { | ||
140 | let src = module.definition_source(db); | ||
141 | let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); | ||
142 | match src.ast { | ||
143 | ModuleSource::SourceFile(node) => { | ||
144 | let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax()); | ||
145 | |||
146 | NavigationTarget::from_syntax( | ||
147 | file_id, | ||
148 | name, | ||
149 | None, | ||
150 | text_range, | ||
151 | node.syntax(), | ||
152 | None, | ||
153 | None, | ||
154 | ) | ||
155 | } | ||
156 | ModuleSource::Module(node) => { | ||
157 | let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax()); | ||
158 | |||
159 | NavigationTarget::from_syntax( | ||
160 | file_id, | ||
161 | name, | ||
162 | None, | ||
163 | text_range, | ||
164 | node.syntax(), | ||
165 | node.doc_comment_text(), | ||
166 | node.short_label(), | ||
167 | ) | ||
168 | } | ||
169 | } | ||
170 | } | ||
171 | |||
172 | pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget { | 115 | pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget { |
173 | let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); | 116 | let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); |
174 | if let Some(src) = module.declaration_source(db) { | 117 | if let Some(src) = module.declaration_source(db) { |
@@ -183,55 +126,7 @@ impl NavigationTarget { | |||
183 | src.ast.short_label(), | 126 | src.ast.short_label(), |
184 | ); | 127 | ); |
185 | } | 128 | } |
186 | NavigationTarget::from_module(db, module) | 129 | module.to_nav(db) |
187 | } | ||
188 | |||
189 | pub(crate) fn from_field(db: &RootDatabase, field: hir::StructField) -> NavigationTarget { | ||
190 | let src = field.source(db); | ||
191 | match src.ast { | ||
192 | FieldSource::Named(it) => NavigationTarget::from_named( | ||
193 | db, | ||
194 | src.file_id, | ||
195 | &it, | ||
196 | it.doc_comment_text(), | ||
197 | it.short_label(), | ||
198 | ), | ||
199 | FieldSource::Pos(it) => { | ||
200 | let (file_id, text_range) = find_range_from_node(db, src.file_id, it.syntax()); | ||
201 | NavigationTarget::from_syntax( | ||
202 | file_id, | ||
203 | "".into(), | ||
204 | None, | ||
205 | text_range, | ||
206 | it.syntax(), | ||
207 | None, | ||
208 | None, | ||
209 | ) | ||
210 | } | ||
211 | } | ||
212 | } | ||
213 | |||
214 | pub(crate) fn from_def_source<A, D>(db: &RootDatabase, def: D) -> NavigationTarget | ||
215 | where | ||
216 | D: HasSource<Ast = A>, | ||
217 | A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel, | ||
218 | { | ||
219 | let src = def.source(db); | ||
220 | NavigationTarget::from_named( | ||
221 | db, | ||
222 | src.file_id, | ||
223 | &src.ast, | ||
224 | src.ast.doc_comment_text(), | ||
225 | src.ast.short_label(), | ||
226 | ) | ||
227 | } | ||
228 | |||
229 | pub(crate) fn from_adt_def(db: &RootDatabase, adt_def: hir::Adt) -> NavigationTarget { | ||
230 | match adt_def { | ||
231 | hir::Adt::Struct(it) => NavigationTarget::from_def_source(db, it), | ||
232 | hir::Adt::Union(it) => NavigationTarget::from_def_source(db, it), | ||
233 | hir::Adt::Enum(it) => NavigationTarget::from_def_source(db, it), | ||
234 | } | ||
235 | } | 130 | } |
236 | 131 | ||
237 | pub(crate) fn from_def( | 132 | pub(crate) fn from_def( |
@@ -239,14 +134,14 @@ impl NavigationTarget { | |||
239 | module_def: hir::ModuleDef, | 134 | module_def: hir::ModuleDef, |
240 | ) -> Option<NavigationTarget> { | 135 | ) -> Option<NavigationTarget> { |
241 | let nav = match module_def { | 136 | let nav = match module_def { |
242 | hir::ModuleDef::Module(module) => NavigationTarget::from_module(db, module), | 137 | hir::ModuleDef::Module(module) => module.to_nav(db), |
243 | hir::ModuleDef::Function(func) => NavigationTarget::from_def_source(db, func), | 138 | hir::ModuleDef::Function(it) => it.to_nav(db), |
244 | hir::ModuleDef::Adt(it) => NavigationTarget::from_adt_def(db, it), | 139 | hir::ModuleDef::Adt(it) => it.to_nav(db), |
245 | hir::ModuleDef::Const(it) => NavigationTarget::from_def_source(db, it), | 140 | hir::ModuleDef::Const(it) => it.to_nav(db), |
246 | hir::ModuleDef::Static(it) => NavigationTarget::from_def_source(db, it), | 141 | hir::ModuleDef::Static(it) => it.to_nav(db), |
247 | hir::ModuleDef::EnumVariant(it) => NavigationTarget::from_def_source(db, it), | 142 | hir::ModuleDef::EnumVariant(it) => it.to_nav(db), |
248 | hir::ModuleDef::Trait(it) => NavigationTarget::from_def_source(db, it), | 143 | hir::ModuleDef::Trait(it) => it.to_nav(db), |
249 | hir::ModuleDef::TypeAlias(it) => NavigationTarget::from_def_source(db, it), | 144 | hir::ModuleDef::TypeAlias(it) => it.to_nav(db), |
250 | hir::ModuleDef::BuiltinType(..) => { | 145 | hir::ModuleDef::BuiltinType(..) => { |
251 | return None; | 146 | return None; |
252 | } | 147 | } |
@@ -254,41 +149,6 @@ impl NavigationTarget { | |||
254 | Some(nav) | 149 | Some(nav) |
255 | } | 150 | } |
256 | 151 | ||
257 | pub(crate) fn from_impl_block( | ||
258 | db: &RootDatabase, | ||
259 | impl_block: hir::ImplBlock, | ||
260 | ) -> NavigationTarget { | ||
261 | let src = impl_block.source(db); | ||
262 | let (file_id, text_range) = find_range_from_node(db, src.file_id, src.ast.syntax()); | ||
263 | |||
264 | NavigationTarget::from_syntax( | ||
265 | file_id, | ||
266 | "impl".into(), | ||
267 | None, | ||
268 | text_range, | ||
269 | src.ast.syntax(), | ||
270 | None, | ||
271 | None, | ||
272 | ) | ||
273 | } | ||
274 | |||
275 | pub(crate) fn from_assoc_item( | ||
276 | db: &RootDatabase, | ||
277 | assoc_item: hir::AssocItem, | ||
278 | ) -> NavigationTarget { | ||
279 | match assoc_item { | ||
280 | AssocItem::Function(it) => NavigationTarget::from_def_source(db, it), | ||
281 | AssocItem::Const(it) => NavigationTarget::from_def_source(db, it), | ||
282 | AssocItem::TypeAlias(it) => NavigationTarget::from_def_source(db, it), | ||
283 | } | ||
284 | } | ||
285 | |||
286 | pub(crate) fn from_macro_def(db: &RootDatabase, macro_call: hir::MacroDef) -> NavigationTarget { | ||
287 | let src = macro_call.source(db); | ||
288 | log::debug!("nav target {:#?}", src.ast.syntax()); | ||
289 | NavigationTarget::from_named(db, src.file_id, &src.ast, src.ast.doc_comment_text(), None) | ||
290 | } | ||
291 | |||
292 | #[cfg(test)] | 152 | #[cfg(test)] |
293 | pub(crate) fn assert_match(&self, expected: &str) { | 153 | pub(crate) fn assert_match(&self, expected: &str) { |
294 | let actual = self.debug_render(); | 154 | let actual = self.debug_render(); |
@@ -359,6 +219,172 @@ impl NavigationTarget { | |||
359 | } | 219 | } |
360 | } | 220 | } |
361 | 221 | ||
222 | impl ToNav for FileSymbol { | ||
223 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | ||
224 | NavigationTarget { | ||
225 | file_id: self.file_id, | ||
226 | name: self.name.clone(), | ||
227 | kind: self.ptr.kind(), | ||
228 | full_range: self.ptr.range(), | ||
229 | focus_range: self.name_range, | ||
230 | container_name: self.container_name.clone(), | ||
231 | description: description_from_symbol(db, self), | ||
232 | docs: docs_from_symbol(db, self), | ||
233 | } | ||
234 | } | ||
235 | } | ||
236 | |||
237 | pub(crate) trait ToNavFromAst {} | ||
238 | impl ToNavFromAst for hir::Function {} | ||
239 | impl ToNavFromAst for hir::Const {} | ||
240 | impl ToNavFromAst for hir::Static {} | ||
241 | impl ToNavFromAst for hir::Struct {} | ||
242 | impl ToNavFromAst for hir::Enum {} | ||
243 | impl ToNavFromAst for hir::EnumVariant {} | ||
244 | impl ToNavFromAst for hir::Union {} | ||
245 | impl ToNavFromAst for hir::TypeAlias {} | ||
246 | impl ToNavFromAst for hir::Trait {} | ||
247 | |||
248 | impl<D> ToNav for D | ||
249 | where | ||
250 | D: HasSource + ToNavFromAst + Copy, | ||
251 | D::Ast: ast::DocCommentsOwner + ast::NameOwner + ShortLabel, | ||
252 | { | ||
253 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | ||
254 | let src = self.source(db); | ||
255 | NavigationTarget::from_named( | ||
256 | db, | ||
257 | src.file_id, | ||
258 | &src.ast, | ||
259 | src.ast.doc_comment_text(), | ||
260 | src.ast.short_label(), | ||
261 | ) | ||
262 | } | ||
263 | } | ||
264 | |||
265 | impl ToNav for hir::Module { | ||
266 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | ||
267 | let src = self.definition_source(db); | ||
268 | let name = self.name(db).map(|it| it.to_string().into()).unwrap_or_default(); | ||
269 | match src.ast { | ||
270 | ModuleSource::SourceFile(node) => { | ||
271 | let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax()); | ||
272 | |||
273 | NavigationTarget::from_syntax( | ||
274 | file_id, | ||
275 | name, | ||
276 | None, | ||
277 | text_range, | ||
278 | node.syntax(), | ||
279 | None, | ||
280 | None, | ||
281 | ) | ||
282 | } | ||
283 | ModuleSource::Module(node) => { | ||
284 | let (file_id, text_range) = find_range_from_node(db, src.file_id, node.syntax()); | ||
285 | |||
286 | NavigationTarget::from_syntax( | ||
287 | file_id, | ||
288 | name, | ||
289 | None, | ||
290 | text_range, | ||
291 | node.syntax(), | ||
292 | node.doc_comment_text(), | ||
293 | node.short_label(), | ||
294 | ) | ||
295 | } | ||
296 | } | ||
297 | } | ||
298 | } | ||
299 | |||
300 | impl ToNav for hir::ImplBlock { | ||
301 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | ||
302 | let src = self.source(db); | ||
303 | let (file_id, text_range) = find_range_from_node(db, src.file_id, src.ast.syntax()); | ||
304 | |||
305 | NavigationTarget::from_syntax( | ||
306 | file_id, | ||
307 | "impl".into(), | ||
308 | None, | ||
309 | text_range, | ||
310 | src.ast.syntax(), | ||
311 | None, | ||
312 | None, | ||
313 | ) | ||
314 | } | ||
315 | } | ||
316 | |||
317 | impl ToNav for hir::StructField { | ||
318 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | ||
319 | let src = self.source(db); | ||
320 | |||
321 | match src.ast { | ||
322 | FieldSource::Named(it) => NavigationTarget::from_named( | ||
323 | db, | ||
324 | src.file_id, | ||
325 | &it, | ||
326 | it.doc_comment_text(), | ||
327 | it.short_label(), | ||
328 | ), | ||
329 | FieldSource::Pos(it) => { | ||
330 | let (file_id, text_range) = find_range_from_node(db, src.file_id, it.syntax()); | ||
331 | NavigationTarget::from_syntax( | ||
332 | file_id, | ||
333 | "".into(), | ||
334 | None, | ||
335 | text_range, | ||
336 | it.syntax(), | ||
337 | None, | ||
338 | None, | ||
339 | ) | ||
340 | } | ||
341 | } | ||
342 | } | ||
343 | } | ||
344 | |||
345 | impl ToNav for hir::MacroDef { | ||
346 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | ||
347 | let src = self.source(db); | ||
348 | log::debug!("nav target {:#?}", src.ast.syntax()); | ||
349 | NavigationTarget::from_named(db, src.file_id, &src.ast, src.ast.doc_comment_text(), None) | ||
350 | } | ||
351 | } | ||
352 | |||
353 | impl ToNav for hir::Adt { | ||
354 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | ||
355 | match self { | ||
356 | hir::Adt::Struct(it) => it.to_nav(db), | ||
357 | hir::Adt::Union(it) => it.to_nav(db), | ||
358 | hir::Adt::Enum(it) => it.to_nav(db), | ||
359 | } | ||
360 | } | ||
361 | } | ||
362 | |||
363 | impl ToNav for hir::AssocItem { | ||
364 | fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { | ||
365 | match self { | ||
366 | AssocItem::Function(it) => it.to_nav(db), | ||
367 | AssocItem::Const(it) => it.to_nav(db), | ||
368 | AssocItem::TypeAlias(it) => it.to_nav(db), | ||
369 | } | ||
370 | } | ||
371 | } | ||
372 | |||
373 | fn find_range_from_node( | ||
374 | db: &RootDatabase, | ||
375 | src: hir::HirFileId, | ||
376 | node: &SyntaxNode, | ||
377 | ) -> (FileId, TextRange) { | ||
378 | let text_range = node.text_range(); | ||
379 | let (file_id, text_range) = src | ||
380 | .expansion_info(db) | ||
381 | .and_then(|expansion_info| expansion_info.find_range(text_range)) | ||
382 | .unwrap_or((src, text_range)); | ||
383 | |||
384 | // FIXME: handle recursive macro generated macro | ||
385 | (file_id.original_file(db), text_range) | ||
386 | } | ||
387 | |||
362 | pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> { | 388 | pub(crate) fn docs_from_symbol(db: &RootDatabase, symbol: &FileSymbol) -> Option<String> { |
363 | let parse = db.parse(symbol.file_id); | 389 | let parse = db.parse(symbol.file_id); |
364 | let node = symbol.ptr.to_node(parse.tree().syntax()); | 390 | let node = symbol.ptr.to_node(parse.tree().syntax()); |
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs index afa59cbe3..713b61d5e 100644 --- a/crates/ra_ide_api/src/goto_definition.rs +++ b/crates/ra_ide_api/src/goto_definition.rs | |||
@@ -9,7 +9,7 @@ use ra_syntax::{ | |||
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | db::RootDatabase, | 11 | db::RootDatabase, |
12 | display::ShortLabel, | 12 | display::{ShortLabel, ToNav}, |
13 | references::{classify_name_ref, NameKind::*}, | 13 | references::{classify_name_ref, NameKind::*}, |
14 | FilePosition, NavigationTarget, RangeInfo, | 14 | FilePosition, NavigationTarget, RangeInfo, |
15 | }; | 15 | }; |
@@ -56,16 +56,16 @@ pub(crate) fn reference_definition( | |||
56 | 56 | ||
57 | let name_kind = classify_name_ref(db, file_id, &name_ref).map(|d| d.kind); | 57 | let name_kind = classify_name_ref(db, file_id, &name_ref).map(|d| d.kind); |
58 | match name_kind { | 58 | match name_kind { |
59 | Some(Macro(mac)) => return Exact(NavigationTarget::from_macro_def(db, mac)), | 59 | Some(Macro(mac)) => return Exact(mac.to_nav(db)), |
60 | Some(Field(field)) => return Exact(NavigationTarget::from_field(db, field)), | 60 | Some(Field(field)) => return Exact(field.to_nav(db)), |
61 | Some(AssocItem(assoc)) => return Exact(NavigationTarget::from_assoc_item(db, assoc)), | 61 | Some(AssocItem(assoc)) => return Exact(assoc.to_nav(db)), |
62 | Some(Def(def)) => match NavigationTarget::from_def(db, def) { | 62 | Some(Def(def)) => match NavigationTarget::from_def(db, def) { |
63 | Some(nav) => return Exact(nav), | 63 | Some(nav) => return Exact(nav), |
64 | None => return Approximate(vec![]), | 64 | None => return Approximate(vec![]), |
65 | }, | 65 | }, |
66 | Some(SelfType(ty)) => { | 66 | Some(SelfType(ty)) => { |
67 | if let Some((def_id, _)) = ty.as_adt() { | 67 | if let Some((adt, _)) = ty.as_adt() { |
68 | return Exact(NavigationTarget::from_adt_def(db, def_id)); | 68 | return Exact(adt.to_nav(db)); |
69 | } | 69 | } |
70 | } | 70 | } |
71 | Some(Pat((_, pat))) => return Exact(NavigationTarget::from_pat(db, file_id, pat)), | 71 | Some(Pat((_, pat))) => return Exact(NavigationTarget::from_pat(db, file_id, pat)), |
@@ -79,7 +79,7 @@ pub(crate) fn reference_definition( | |||
79 | // Fallback index based approach: | 79 | // Fallback index based approach: |
80 | let navs = crate::symbol_index::index_resolve(db, name_ref) | 80 | let navs = crate::symbol_index::index_resolve(db, name_ref) |
81 | .into_iter() | 81 | .into_iter() |
82 | .map(|s| NavigationTarget::from_symbol(db, s)) | 82 | .map(|s| s.to_nav(db)) |
83 | .collect(); | 83 | .collect(); |
84 | Approximate(navs) | 84 | Approximate(navs) |
85 | } | 85 | } |
@@ -95,7 +95,7 @@ pub(crate) fn name_definition( | |||
95 | if module.has_semi() { | 95 | if module.has_semi() { |
96 | let src = hir::Source { file_id: file_id.into(), ast: module }; | 96 | let src = hir::Source { file_id: file_id.into(), ast: module }; |
97 | if let Some(child_module) = hir::Module::from_declaration(db, src) { | 97 | if let Some(child_module) = hir::Module::from_declaration(db, src) { |
98 | let nav = NavigationTarget::from_module(db, child_module); | 98 | let nav = child_module.to_nav(db); |
99 | return Some(vec![nav]); | 99 | return Some(vec![nav]); |
100 | } | 100 | } |
101 | } | 101 | } |
diff --git a/crates/ra_ide_api/src/goto_type_definition.rs b/crates/ra_ide_api/src/goto_type_definition.rs index 059d80524..71146591d 100644 --- a/crates/ra_ide_api/src/goto_type_definition.rs +++ b/crates/ra_ide_api/src/goto_type_definition.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use ra_db::SourceDatabase; | 3 | use ra_db::SourceDatabase; |
4 | use ra_syntax::{ast, AstNode}; | 4 | use ra_syntax::{ast, AstNode}; |
5 | 5 | ||
6 | use crate::{db::RootDatabase, FilePosition, NavigationTarget, RangeInfo}; | 6 | use crate::{db::RootDatabase, display::ToNav, FilePosition, NavigationTarget, RangeInfo}; |
7 | 7 | ||
8 | pub(crate) fn goto_type_definition( | 8 | pub(crate) fn goto_type_definition( |
9 | db: &RootDatabase, | 9 | db: &RootDatabase, |
@@ -33,7 +33,7 @@ pub(crate) fn goto_type_definition( | |||
33 | 33 | ||
34 | let adt_def = analyzer.autoderef(db, ty).find_map(|ty| ty.as_adt().map(|adt| adt.0))?; | 34 | let adt_def = analyzer.autoderef(db, ty).find_map(|ty| ty.as_adt().map(|adt| adt.0))?; |
35 | 35 | ||
36 | let nav = NavigationTarget::from_adt_def(db, adt_def); | 36 | let nav = adt_def.to_nav(db); |
37 | Some(RangeInfo::new(node.text_range(), vec![nav])) | 37 | Some(RangeInfo::new(node.text_range(), vec![nav])) |
38 | } | 38 | } |
39 | 39 | ||
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs index ba328efa1..cc41390b2 100644 --- a/crates/ra_ide_api/src/hover.rs +++ b/crates/ra_ide_api/src/hover.rs | |||
@@ -117,27 +117,23 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn | |||
117 | hir::AssocItem::Const(it) => from_def_source(db, it), | 117 | hir::AssocItem::Const(it) => from_def_source(db, it), |
118 | hir::AssocItem::TypeAlias(it) => from_def_source(db, it), | 118 | hir::AssocItem::TypeAlias(it) => from_def_source(db, it), |
119 | }), | 119 | }), |
120 | Some(Def(it)) => { | 120 | Some(Def(it)) => match it { |
121 | match it { | 121 | hir::ModuleDef::Module(it) => { |
122 | hir::ModuleDef::Module(it) => { | 122 | if let hir::ModuleSource::Module(it) = it.definition_source(db).ast { |
123 | if let hir::ModuleSource::Module(it) = it.definition_source(db).ast { | 123 | res.extend(hover_text(it.doc_comment_text(), it.short_label())) |
124 | res.extend(hover_text(it.doc_comment_text(), it.short_label())) | ||
125 | } | ||
126 | } | ||
127 | hir::ModuleDef::Function(it) => res.extend(from_def_source(db, it)), | ||
128 | hir::ModuleDef::Adt(Adt::Struct(it)) => res.extend(from_def_source(db, it)), | ||
129 | hir::ModuleDef::Adt(Adt::Union(it)) => res.extend(from_def_source(db, it)), | ||
130 | hir::ModuleDef::Adt(Adt::Enum(it)) => res.extend(from_def_source(db, it)), | ||
131 | hir::ModuleDef::EnumVariant(it) => res.extend(from_def_source(db, it)), | ||
132 | hir::ModuleDef::Const(it) => res.extend(from_def_source(db, it)), | ||
133 | hir::ModuleDef::Static(it) => res.extend(from_def_source(db, it)), | ||
134 | hir::ModuleDef::Trait(it) => res.extend(from_def_source(db, it)), | ||
135 | hir::ModuleDef::TypeAlias(it) => res.extend(from_def_source(db, it)), | ||
136 | hir::ModuleDef::BuiltinType(_) => { | ||
137 | // FIXME: hover for builtin Type ? | ||
138 | } | 124 | } |
139 | } | 125 | } |
140 | } | 126 | hir::ModuleDef::Function(it) => res.extend(from_def_source(db, it)), |
127 | hir::ModuleDef::Adt(Adt::Struct(it)) => res.extend(from_def_source(db, it)), | ||
128 | hir::ModuleDef::Adt(Adt::Union(it)) => res.extend(from_def_source(db, it)), | ||
129 | hir::ModuleDef::Adt(Adt::Enum(it)) => res.extend(from_def_source(db, it)), | ||
130 | hir::ModuleDef::EnumVariant(it) => res.extend(from_def_source(db, it)), | ||
131 | hir::ModuleDef::Const(it) => res.extend(from_def_source(db, it)), | ||
132 | hir::ModuleDef::Static(it) => res.extend(from_def_source(db, it)), | ||
133 | hir::ModuleDef::Trait(it) => res.extend(from_def_source(db, it)), | ||
134 | hir::ModuleDef::TypeAlias(it) => res.extend(from_def_source(db, it)), | ||
135 | hir::ModuleDef::BuiltinType(it) => res.extend(Some(it.to_string())), | ||
136 | }, | ||
141 | Some(SelfType(ty)) => { | 137 | Some(SelfType(ty)) => { |
142 | if let Some((adt_def, _)) = ty.as_adt() { | 138 | if let Some((adt_def, _)) = ty.as_adt() { |
143 | res.extend(match adt_def { | 139 | res.extend(match adt_def { |
@@ -722,4 +718,16 @@ fn func(foo: i32) { if true { <|>foo; }; } | |||
722 | assert_eq!(trim_markup_opt(hover.info.first()), Some("macro_rules! foo")); | 718 | assert_eq!(trim_markup_opt(hover.info.first()), Some("macro_rules! foo")); |
723 | assert_eq!(hover.info.is_exact(), true); | 719 | assert_eq!(hover.info.is_exact(), true); |
724 | } | 720 | } |
721 | |||
722 | #[test] | ||
723 | fn test_hover_tuple_field() { | ||
724 | let (analysis, position) = single_file_with_position( | ||
725 | " | ||
726 | struct TS(String, i32<|>); | ||
727 | ", | ||
728 | ); | ||
729 | let hover = analysis.hover(position).unwrap().unwrap(); | ||
730 | assert_eq!(trim_markup_opt(hover.info.first()), Some("i32")); | ||
731 | assert_eq!(hover.info.is_exact(), true); | ||
732 | } | ||
725 | } | 733 | } |
diff --git a/crates/ra_ide_api/src/impls.rs b/crates/ra_ide_api/src/impls.rs index b899ed3a5..bc9b66550 100644 --- a/crates/ra_ide_api/src/impls.rs +++ b/crates/ra_ide_api/src/impls.rs | |||
@@ -4,7 +4,7 @@ use hir::{db::HirDatabase, ApplicationTy, FromSource, Ty, TypeCtor}; | |||
4 | use ra_db::SourceDatabase; | 4 | use ra_db::SourceDatabase; |
5 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; | 5 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode}; |
6 | 6 | ||
7 | use crate::{db::RootDatabase, FilePosition, NavigationTarget, RangeInfo}; | 7 | use crate::{db::RootDatabase, display::ToNav, FilePosition, NavigationTarget, RangeInfo}; |
8 | 8 | ||
9 | pub(crate) fn goto_implementation( | 9 | pub(crate) fn goto_implementation( |
10 | db: &RootDatabase, | 10 | db: &RootDatabase, |
@@ -58,7 +58,7 @@ fn impls_for_def( | |||
58 | impls | 58 | impls |
59 | .all_impls() | 59 | .all_impls() |
60 | .filter(|impl_block| is_equal_for_find_impls(&ty, &impl_block.target_ty(db))) | 60 | .filter(|impl_block| is_equal_for_find_impls(&ty, &impl_block.target_ty(db))) |
61 | .map(|imp| NavigationTarget::from_impl_block(db, imp)) | 61 | .map(|imp| imp.to_nav(db)) |
62 | .collect(), | 62 | .collect(), |
63 | ) | 63 | ) |
64 | } | 64 | } |
@@ -75,12 +75,7 @@ fn impls_for_trait( | |||
75 | let krate = module.krate(); | 75 | let krate = module.krate(); |
76 | let impls = db.impls_in_crate(krate); | 76 | let impls = db.impls_in_crate(krate); |
77 | 77 | ||
78 | Some( | 78 | Some(impls.lookup_impl_blocks_for_trait(tr).map(|imp| imp.to_nav(db)).collect()) |
79 | impls | ||
80 | .lookup_impl_blocks_for_trait(tr) | ||
81 | .map(|imp| NavigationTarget::from_impl_block(db, imp)) | ||
82 | .collect(), | ||
83 | ) | ||
84 | } | 79 | } |
85 | 80 | ||
86 | fn is_equal_for_find_impls(original_ty: &Ty, impl_ty: &Ty) -> bool { | 81 | fn is_equal_for_find_impls(original_ty: &Ty, impl_ty: &Ty) -> bool { |
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index d0188da44..484fbcc82 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs | |||
@@ -56,7 +56,7 @@ use ra_db::{ | |||
56 | }; | 56 | }; |
57 | use ra_syntax::{SourceFile, TextRange, TextUnit}; | 57 | use ra_syntax::{SourceFile, TextRange, TextUnit}; |
58 | 58 | ||
59 | use crate::{db::LineIndexDatabase, symbol_index::FileSymbol}; | 59 | use crate::{db::LineIndexDatabase, display::ToNav, symbol_index::FileSymbol}; |
60 | 60 | ||
61 | pub use crate::{ | 61 | pub use crate::{ |
62 | assists::{Assist, AssistId}, | 62 | assists::{Assist, AssistId}, |
@@ -351,7 +351,7 @@ impl Analysis { | |||
351 | self.with_db(|db| { | 351 | self.with_db(|db| { |
352 | symbol_index::world_symbols(db, query) | 352 | symbol_index::world_symbols(db, query) |
353 | .into_iter() | 353 | .into_iter() |
354 | .map(|s| NavigationTarget::from_symbol(db, s)) | 354 | .map(|s| s.to_nav(db)) |
355 | .collect::<Vec<_>>() | 355 | .collect::<Vec<_>>() |
356 | }) | 356 | }) |
357 | } | 357 | } |
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs index b5b1c9a16..0a76bf484 100644 --- a/crates/ra_ide_api/src/references.rs +++ b/crates/ra_ide_api/src/references.rs | |||
@@ -19,7 +19,9 @@ use ra_db::{SourceDatabase, SourceDatabaseExt}; | |||
19 | use ra_prof::profile; | 19 | use ra_prof::profile; |
20 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SourceFile, SyntaxNode, TextUnit}; | 20 | use ra_syntax::{algo::find_node_at_offset, ast, AstNode, SourceFile, SyntaxNode, TextUnit}; |
21 | 21 | ||
22 | use crate::{db::RootDatabase, FilePosition, FileRange, NavigationTarget, RangeInfo}; | 22 | use crate::{ |
23 | db::RootDatabase, display::ToNav, FilePosition, FileRange, NavigationTarget, RangeInfo, | ||
24 | }; | ||
23 | 25 | ||
24 | pub(crate) use self::{ | 26 | pub(crate) use self::{ |
25 | classify::{classify_name, classify_name_ref}, | 27 | classify::{classify_name, classify_name_ref}, |
@@ -76,12 +78,12 @@ pub(crate) fn find_all_refs( | |||
76 | let RangeInfo { range, info: (name, def) } = find_name(db, &syntax, position)?; | 78 | let RangeInfo { range, info: (name, def) } = find_name(db, &syntax, position)?; |
77 | 79 | ||
78 | let declaration = match def.kind { | 80 | let declaration = match def.kind { |
79 | NameKind::Macro(mac) => NavigationTarget::from_macro_def(db, mac), | 81 | NameKind::Macro(mac) => mac.to_nav(db), |
80 | NameKind::Field(field) => NavigationTarget::from_field(db, field), | 82 | NameKind::Field(field) => field.to_nav(db), |
81 | NameKind::AssocItem(assoc) => NavigationTarget::from_assoc_item(db, assoc), | 83 | NameKind::AssocItem(assoc) => assoc.to_nav(db), |
82 | NameKind::Def(def) => NavigationTarget::from_def(db, def)?, | 84 | NameKind::Def(def) => NavigationTarget::from_def(db, def)?, |
83 | NameKind::SelfType(ref ty) => match ty.as_adt() { | 85 | NameKind::SelfType(ref ty) => match ty.as_adt() { |
84 | Some((def_id, _)) => NavigationTarget::from_adt_def(db, def_id), | 86 | Some((adt, _)) => adt.to_nav(db), |
85 | None => return None, | 87 | None => return None, |
86 | }, | 88 | }, |
87 | NameKind::Pat((_, pat)) => NavigationTarget::from_pat(db, position.file_id, pat), | 89 | NameKind::Pat((_, pat)) => NavigationTarget::from_pat(db, position.file_id, pat), |
diff --git a/crates/ra_ide_api/src/syntax_highlighting.rs b/crates/ra_ide_api/src/syntax_highlighting.rs index 33f3caceb..1ee68abe2 100644 --- a/crates/ra_ide_api/src/syntax_highlighting.rs +++ b/crates/ra_ide_api/src/syntax_highlighting.rs | |||
@@ -9,12 +9,15 @@ use ra_syntax::{ | |||
9 | ast::{self, NameOwner}, | 9 | ast::{self, NameOwner}, |
10 | AstNode, Direction, SmolStr, SyntaxElement, SyntaxKind, | 10 | AstNode, Direction, SmolStr, SyntaxElement, SyntaxKind, |
11 | SyntaxKind::*, | 11 | SyntaxKind::*, |
12 | TextRange, T, | 12 | SyntaxNode, TextRange, T, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | use crate::{ | 15 | use crate::{ |
16 | db::RootDatabase, | 16 | db::RootDatabase, |
17 | references::{classify_name_ref, NameKind::*}, | 17 | references::{ |
18 | classify_name, classify_name_ref, | ||
19 | NameKind::{self, *}, | ||
20 | }, | ||
18 | FileId, | 21 | FileId, |
19 | }; | 22 | }; |
20 | 23 | ||
@@ -100,81 +103,43 @@ pub(crate) fn highlight(db: &RootDatabase, file_id: FileId) -> Vec<HighlightedRa | |||
100 | if node.ancestors().any(|it| it.kind() == ATTR) { | 103 | if node.ancestors().any(|it| it.kind() == ATTR) { |
101 | continue; | 104 | continue; |
102 | } | 105 | } |
103 | if let Some(name_ref) = node.as_node().cloned().and_then(ast::NameRef::cast) { | ||
104 | let name_kind = classify_name_ref(db, file_id, &name_ref).map(|d| d.kind); | ||
105 | match name_kind { | ||
106 | Some(Macro(_)) => "macro", | ||
107 | Some(Field(_)) => "field", | ||
108 | Some(AssocItem(hir::AssocItem::Function(_))) => "function", | ||
109 | Some(AssocItem(hir::AssocItem::Const(_))) => "constant", | ||
110 | Some(AssocItem(hir::AssocItem::TypeAlias(_))) => "type", | ||
111 | Some(Def(hir::ModuleDef::Module(_))) => "module", | ||
112 | Some(Def(hir::ModuleDef::Function(_))) => "function", | ||
113 | Some(Def(hir::ModuleDef::Adt(_))) => "type", | ||
114 | Some(Def(hir::ModuleDef::EnumVariant(_))) => "constant", | ||
115 | Some(Def(hir::ModuleDef::Const(_))) => "constant", | ||
116 | Some(Def(hir::ModuleDef::Static(_))) => "constant", | ||
117 | Some(Def(hir::ModuleDef::Trait(_))) => "type", | ||
118 | Some(Def(hir::ModuleDef::TypeAlias(_))) => "type", | ||
119 | Some(Def(hir::ModuleDef::BuiltinType(_))) => "type", | ||
120 | Some(SelfType(_)) => "type", | ||
121 | Some(Pat((_, ptr))) => { | ||
122 | let pat = ptr.to_node(&root); | ||
123 | if let Some(name) = pat.name() { | ||
124 | let text = name.text(); | ||
125 | let shadow_count = | ||
126 | bindings_shadow_count.entry(text.clone()).or_default(); | ||
127 | binding_hash = | ||
128 | Some(calc_binding_hash(file_id, &text, *shadow_count)) | ||
129 | } | ||
130 | 106 | ||
131 | let analyzer = | 107 | let name_ref = node.as_node().cloned().and_then(ast::NameRef::cast).unwrap(); |
132 | hir::SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); | 108 | let name_kind = classify_name_ref(db, file_id, &name_ref).map(|d| d.kind); |
133 | if is_variable_mutable(db, &analyzer, ptr.to_node(&root)) { | 109 | |
134 | "variable.mut" | 110 | if let Some(Pat((_, ptr))) = &name_kind { |
135 | } else { | 111 | let pat = ptr.to_node(&root); |
136 | "variable" | 112 | if let Some(name) = pat.name() { |
137 | } | 113 | let text = name.text(); |
138 | } | 114 | let shadow_count = bindings_shadow_count.entry(text.clone()).or_default(); |
139 | Some(SelfParam(_)) => "type", | 115 | binding_hash = Some(calc_binding_hash(file_id, &text, *shadow_count)) |
140 | Some(GenericParam(_)) => "type", | ||
141 | None => "text", | ||
142 | } | 116 | } |
143 | } else { | 117 | }; |
144 | "text" | 118 | |
145 | } | 119 | name_kind |
120 | .map_or("text", |it| highlight_name(db, file_id, name_ref.syntax(), &root, it)) | ||
146 | } | 121 | } |
147 | NAME => { | 122 | NAME => { |
148 | if let Some(name) = node.as_node().cloned().and_then(ast::Name::cast) { | 123 | let name = node.as_node().cloned().and_then(ast::Name::cast).unwrap(); |
149 | let analyzer = hir::SourceAnalyzer::new(db, file_id, name.syntax(), None); | 124 | let name_kind = classify_name(db, file_id, &name).map(|d| d.kind); |
150 | if let Some(pat) = name.syntax().ancestors().find_map(ast::BindPat::cast) { | 125 | |
151 | if let Some(name) = pat.name() { | 126 | if let Some(Pat((_, ptr))) = &name_kind { |
152 | let text = name.text(); | 127 | let pat = ptr.to_node(&root); |
153 | let shadow_count = | 128 | if let Some(name) = pat.name() { |
154 | bindings_shadow_count.entry(text.clone()).or_default(); | 129 | let text = name.text(); |
155 | *shadow_count += 1; | 130 | let shadow_count = bindings_shadow_count.entry(text.clone()).or_default(); |
156 | binding_hash = Some(calc_binding_hash(file_id, &text, *shadow_count)) | 131 | *shadow_count += 1; |
157 | } | 132 | binding_hash = Some(calc_binding_hash(file_id, &text, *shadow_count)) |
158 | |||
159 | if is_variable_mutable(db, &analyzer, pat) { | ||
160 | "variable.mut" | ||
161 | } else { | ||
162 | "variable" | ||
163 | } | ||
164 | } else { | ||
165 | name.syntax() | ||
166 | .parent() | ||
167 | .map(|x| match x.kind() { | ||
168 | TYPE_PARAM | STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => { | ||
169 | "type" | ||
170 | } | ||
171 | RECORD_FIELD_DEF => "field", | ||
172 | _ => "function", | ||
173 | }) | ||
174 | .unwrap_or("function") | ||
175 | } | 133 | } |
176 | } else { | 134 | }; |
177 | "text" | 135 | |
136 | match name_kind { | ||
137 | Some(name_kind) => highlight_name(db, file_id, name.syntax(), &root, name_kind), | ||
138 | None => name.syntax().parent().map_or("function", |x| match x.kind() { | ||
139 | TYPE_PARAM | STRUCT_DEF | ENUM_DEF | TRAIT_DEF | TYPE_ALIAS_DEF => "type", | ||
140 | RECORD_FIELD_DEF => "field", | ||
141 | _ => "function", | ||
142 | }), | ||
178 | } | 143 | } |
179 | } | 144 | } |
180 | INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE => "literal", | 145 | INT_NUMBER | FLOAT_NUMBER | CHAR | BYTE => "literal", |
@@ -272,6 +237,42 @@ pub(crate) fn highlight_as_html(db: &RootDatabase, file_id: FileId, rainbow: boo | |||
272 | buf | 237 | buf |
273 | } | 238 | } |
274 | 239 | ||
240 | fn highlight_name( | ||
241 | db: &RootDatabase, | ||
242 | file_id: FileId, | ||
243 | node: &SyntaxNode, | ||
244 | root: &SyntaxNode, | ||
245 | name_kind: NameKind, | ||
246 | ) -> &'static str { | ||
247 | match name_kind { | ||
248 | Macro(_) => "macro", | ||
249 | Field(_) => "field", | ||
250 | AssocItem(hir::AssocItem::Function(_)) => "function", | ||
251 | AssocItem(hir::AssocItem::Const(_)) => "constant", | ||
252 | AssocItem(hir::AssocItem::TypeAlias(_)) => "type", | ||
253 | Def(hir::ModuleDef::Module(_)) => "module", | ||
254 | Def(hir::ModuleDef::Function(_)) => "function", | ||
255 | Def(hir::ModuleDef::Adt(_)) => "type", | ||
256 | Def(hir::ModuleDef::EnumVariant(_)) => "constant", | ||
257 | Def(hir::ModuleDef::Const(_)) => "constant", | ||
258 | Def(hir::ModuleDef::Static(_)) => "constant", | ||
259 | Def(hir::ModuleDef::Trait(_)) => "type", | ||
260 | Def(hir::ModuleDef::TypeAlias(_)) => "type", | ||
261 | Def(hir::ModuleDef::BuiltinType(_)) => "type", | ||
262 | SelfType(_) => "type", | ||
263 | SelfParam(_) => "type", | ||
264 | GenericParam(_) => "type", | ||
265 | Pat((_, ptr)) => { | ||
266 | let analyzer = hir::SourceAnalyzer::new(db, file_id, node, None); | ||
267 | if is_variable_mutable(db, &analyzer, ptr.to_node(&root)) { | ||
268 | "variable.mut" | ||
269 | } else { | ||
270 | "variable" | ||
271 | } | ||
272 | } | ||
273 | } | ||
274 | } | ||
275 | |||
275 | //FIXME: like, real html escaping | 276 | //FIXME: like, real html escaping |
276 | fn html_escape(text: &str) -> String { | 277 | fn html_escape(text: &str) -> String { |
277 | text.replace("<", "<").replace(">", ">") | 278 | text.replace("<", "<").replace(">", ">") |
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs index 8b8663a78..0e14f1b70 100644 --- a/crates/ra_project_model/src/lib.rs +++ b/crates/ra_project_model/src/lib.rs | |||
@@ -199,6 +199,7 @@ impl ProjectWorkspace { | |||
199 | } | 199 | } |
200 | } | 200 | } |
201 | 201 | ||
202 | let libcore = sysroot.core().and_then(|it| sysroot_crates.get(&it).copied()); | ||
202 | let libstd = sysroot.std().and_then(|it| sysroot_crates.get(&it).copied()); | 203 | let libstd = sysroot.std().and_then(|it| sysroot_crates.get(&it).copied()); |
203 | 204 | ||
204 | let mut pkg_to_lib_crate = FxHashMap::default(); | 205 | let mut pkg_to_lib_crate = FxHashMap::default(); |
@@ -226,7 +227,7 @@ impl ProjectWorkspace { | |||
226 | } | 227 | } |
227 | } | 228 | } |
228 | 229 | ||
229 | // Set deps to the std and to the lib target of the current package | 230 | // Set deps to the core, std and to the lib target of the current package |
230 | for &from in pkg_crates.get(&pkg).into_iter().flatten() { | 231 | for &from in pkg_crates.get(&pkg).into_iter().flatten() { |
231 | if let Some(to) = lib_tgt { | 232 | if let Some(to) = lib_tgt { |
232 | if to != from { | 233 | if to != from { |
@@ -240,6 +241,13 @@ impl ProjectWorkspace { | |||
240 | } | 241 | } |
241 | } | 242 | } |
242 | } | 243 | } |
244 | // core is added as a dependency before std in order to | ||
245 | // mimic rustcs dependency order | ||
246 | if let Some(core) = libcore { | ||
247 | if let Err(_) = crate_graph.add_dep(from, "core".into(), core) { | ||
248 | log::error!("cyclic dependency on core for {}", pkg.name(&cargo)) | ||
249 | } | ||
250 | } | ||
243 | if let Some(std) = libstd { | 251 | if let Some(std) = libstd { |
244 | if let Err(_) = crate_graph.add_dep(from, "std".into(), std) { | 252 | if let Err(_) = crate_graph.add_dep(from, "std".into(), std) { |
245 | log::error!("cyclic dependency on std for {}", pkg.name(&cargo)) | 253 | log::error!("cyclic dependency on std for {}", pkg.name(&cargo)) |
diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs index 35d6df5cb..3d827809e 100644 --- a/crates/ra_project_model/src/sysroot.rs +++ b/crates/ra_project_model/src/sysroot.rs | |||
@@ -27,6 +27,10 @@ struct SysrootCrateData { | |||
27 | } | 27 | } |
28 | 28 | ||
29 | impl Sysroot { | 29 | impl Sysroot { |
30 | pub fn core(&self) -> Option<SysrootCrate> { | ||
31 | self.by_name("core") | ||
32 | } | ||
33 | |||
30 | pub fn std(&self) -> Option<SysrootCrate> { | 34 | pub fn std(&self) -> Option<SysrootCrate> { |
31 | self.by_name("std") | 35 | self.by_name("std") |
32 | } | 36 | } |
diff --git a/crates/ra_syntax/src/syntax_error.rs b/crates/ra_syntax/src/syntax_error.rs index d6eca2ad7..1f60a7aab 100644 --- a/crates/ra_syntax/src/syntax_error.rs +++ b/crates/ra_syntax/src/syntax_error.rs | |||
@@ -82,6 +82,7 @@ pub enum SyntaxErrorKind { | |||
82 | InvalidBlockAttr, | 82 | InvalidBlockAttr, |
83 | InvalidMatchInnerAttr, | 83 | InvalidMatchInnerAttr, |
84 | InvalidTupleIndexFormat, | 84 | InvalidTupleIndexFormat, |
85 | VisibilityNotAllowed, | ||
85 | } | 86 | } |
86 | 87 | ||
87 | impl fmt::Display for SyntaxErrorKind { | 88 | impl fmt::Display for SyntaxErrorKind { |
@@ -99,6 +100,9 @@ impl fmt::Display for SyntaxErrorKind { | |||
99 | } | 100 | } |
100 | ParseError(msg) => write!(f, "{}", msg.0), | 101 | ParseError(msg) => write!(f, "{}", msg.0), |
101 | EscapeError(err) => write!(f, "{}", err), | 102 | EscapeError(err) => write!(f, "{}", err), |
103 | VisibilityNotAllowed => { | ||
104 | write!(f, "unnecessary visibility qualifier") | ||
105 | } | ||
102 | } | 106 | } |
103 | } | 107 | } |
104 | } | 108 | } |
diff --git a/crates/ra_syntax/src/validation.rs b/crates/ra_syntax/src/validation.rs index ab4f15908..2d596763e 100644 --- a/crates/ra_syntax/src/validation.rs +++ b/crates/ra_syntax/src/validation.rs | |||
@@ -6,7 +6,7 @@ use rustc_lexer::unescape; | |||
6 | 6 | ||
7 | use crate::{ | 7 | use crate::{ |
8 | ast, match_ast, AstNode, SyntaxError, SyntaxErrorKind, | 8 | ast, match_ast, AstNode, SyntaxError, SyntaxErrorKind, |
9 | SyntaxKind::{BYTE, BYTE_STRING, CHAR, INT_NUMBER, STRING}, | 9 | SyntaxKind::{BYTE, BYTE_STRING, CHAR, CONST_DEF, FN_DEF, INT_NUMBER, STRING, TYPE_ALIAS_DEF}, |
10 | SyntaxNode, SyntaxToken, TextUnit, T, | 10 | SyntaxNode, SyntaxToken, TextUnit, T, |
11 | }; | 11 | }; |
12 | 12 | ||
@@ -102,6 +102,7 @@ pub(crate) fn validate(root: &SyntaxNode) -> Vec<SyntaxError> { | |||
102 | ast::BlockExpr(it) => { block::validate_block_expr(it, &mut errors) }, | 102 | ast::BlockExpr(it) => { block::validate_block_expr(it, &mut errors) }, |
103 | ast::FieldExpr(it) => { validate_numeric_name(it.name_ref(), &mut errors) }, | 103 | ast::FieldExpr(it) => { validate_numeric_name(it.name_ref(), &mut errors) }, |
104 | ast::RecordField(it) => { validate_numeric_name(it.name_ref(), &mut errors) }, | 104 | ast::RecordField(it) => { validate_numeric_name(it.name_ref(), &mut errors) }, |
105 | ast::Visibility(it) => { validate_visibility(it, &mut errors) }, | ||
105 | _ => (), | 106 | _ => (), |
106 | } | 107 | } |
107 | } | 108 | } |
@@ -206,3 +207,23 @@ fn validate_numeric_name(name_ref: Option<ast::NameRef>, errors: &mut Vec<Syntax | |||
206 | name_ref?.syntax().first_child_or_token()?.into_token().filter(|it| it.kind() == INT_NUMBER) | 207 | name_ref?.syntax().first_child_or_token()?.into_token().filter(|it| it.kind() == INT_NUMBER) |
207 | } | 208 | } |
208 | } | 209 | } |
210 | |||
211 | fn validate_visibility(vis: ast::Visibility, errors: &mut Vec<SyntaxError>) { | ||
212 | let parent = match vis.syntax().parent() { | ||
213 | Some(it) => it, | ||
214 | None => return, | ||
215 | }; | ||
216 | match parent.kind() { | ||
217 | FN_DEF | CONST_DEF | TYPE_ALIAS_DEF => (), | ||
218 | _ => return, | ||
219 | } | ||
220 | let impl_block = match parent.parent().and_then(|it| it.parent()).and_then(ast::ImplBlock::cast) | ||
221 | { | ||
222 | Some(it) => it, | ||
223 | None => return, | ||
224 | }; | ||
225 | if impl_block.target_trait().is_some() { | ||
226 | errors | ||
227 | .push(SyntaxError::new(SyntaxErrorKind::VisibilityNotAllowed, vis.syntax.text_range())) | ||
228 | } | ||
229 | } | ||
diff --git a/crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.rs b/crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.rs new file mode 100644 index 000000000..a43e7ef10 --- /dev/null +++ b/crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.rs | |||
@@ -0,0 +1,6 @@ | |||
1 | impl T for () { | ||
2 | fn foo() {} | ||
3 | pub fn bar() {} | ||
4 | pub(crate) type Baz = (); | ||
5 | pub(crate) const C: i32 = 92; | ||
6 | } | ||
diff --git a/crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.txt b/crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.txt new file mode 100644 index 000000000..749c8cddb --- /dev/null +++ b/crates/ra_syntax/test_data/parser/err/0037_visibility_in_traits.txt | |||
@@ -0,0 +1,99 @@ | |||
1 | SOURCE_FILE@[0; 118) | ||
2 | IMPL_BLOCK@[0; 117) | ||
3 | IMPL_KW@[0; 4) "impl" | ||
4 | WHITESPACE@[4; 5) " " | ||
5 | PATH_TYPE@[5; 6) | ||
6 | PATH@[5; 6) | ||
7 | PATH_SEGMENT@[5; 6) | ||
8 | NAME_REF@[5; 6) | ||
9 | IDENT@[5; 6) "T" | ||
10 | WHITESPACE@[6; 7) " " | ||
11 | FOR_KW@[7; 10) "for" | ||
12 | WHITESPACE@[10; 11) " " | ||
13 | TUPLE_TYPE@[11; 13) | ||
14 | L_PAREN@[11; 12) "(" | ||
15 | R_PAREN@[12; 13) ")" | ||
16 | WHITESPACE@[13; 14) " " | ||
17 | ITEM_LIST@[14; 117) | ||
18 | L_CURLY@[14; 15) "{" | ||
19 | WHITESPACE@[15; 20) "\n " | ||
20 | FN_DEF@[20; 31) | ||
21 | FN_KW@[20; 22) "fn" | ||
22 | WHITESPACE@[22; 23) " " | ||
23 | NAME@[23; 26) | ||
24 | IDENT@[23; 26) "foo" | ||
25 | PARAM_LIST@[26; 28) | ||
26 | L_PAREN@[26; 27) "(" | ||
27 | R_PAREN@[27; 28) ")" | ||
28 | WHITESPACE@[28; 29) " " | ||
29 | BLOCK_EXPR@[29; 31) | ||
30 | BLOCK@[29; 31) | ||
31 | L_CURLY@[29; 30) "{" | ||
32 | R_CURLY@[30; 31) "}" | ||
33 | WHITESPACE@[31; 36) "\n " | ||
34 | FN_DEF@[36; 51) | ||
35 | VISIBILITY@[36; 39) | ||
36 | PUB_KW@[36; 39) "pub" | ||
37 | WHITESPACE@[39; 40) " " | ||
38 | FN_KW@[40; 42) "fn" | ||
39 | WHITESPACE@[42; 43) " " | ||
40 | NAME@[43; 46) | ||
41 | IDENT@[43; 46) "bar" | ||
42 | PARAM_LIST@[46; 48) | ||
43 | L_PAREN@[46; 47) "(" | ||
44 | R_PAREN@[47; 48) ")" | ||
45 | WHITESPACE@[48; 49) " " | ||
46 | BLOCK_EXPR@[49; 51) | ||
47 | BLOCK@[49; 51) | ||
48 | L_CURLY@[49; 50) "{" | ||
49 | R_CURLY@[50; 51) "}" | ||
50 | WHITESPACE@[51; 56) "\n " | ||
51 | TYPE_ALIAS_DEF@[56; 81) | ||
52 | VISIBILITY@[56; 66) | ||
53 | PUB_KW@[56; 59) "pub" | ||
54 | L_PAREN@[59; 60) "(" | ||
55 | CRATE_KW@[60; 65) "crate" | ||
56 | R_PAREN@[65; 66) ")" | ||
57 | WHITESPACE@[66; 67) " " | ||
58 | TYPE_KW@[67; 71) "type" | ||
59 | WHITESPACE@[71; 72) " " | ||
60 | NAME@[72; 75) | ||
61 | IDENT@[72; 75) "Baz" | ||
62 | WHITESPACE@[75; 76) " " | ||
63 | EQ@[76; 77) "=" | ||
64 | WHITESPACE@[77; 78) " " | ||
65 | TUPLE_TYPE@[78; 80) | ||
66 | L_PAREN@[78; 79) "(" | ||
67 | R_PAREN@[79; 80) ")" | ||
68 | SEMI@[80; 81) ";" | ||
69 | WHITESPACE@[81; 86) "\n " | ||
70 | CONST_DEF@[86; 115) | ||
71 | VISIBILITY@[86; 96) | ||
72 | PUB_KW@[86; 89) "pub" | ||
73 | L_PAREN@[89; 90) "(" | ||
74 | CRATE_KW@[90; 95) "crate" | ||
75 | R_PAREN@[95; 96) ")" | ||
76 | WHITESPACE@[96; 97) " " | ||
77 | CONST_KW@[97; 102) "const" | ||
78 | WHITESPACE@[102; 103) " " | ||
79 | NAME@[103; 104) | ||
80 | IDENT@[103; 104) "C" | ||
81 | COLON@[104; 105) ":" | ||
82 | WHITESPACE@[105; 106) " " | ||
83 | PATH_TYPE@[106; 109) | ||
84 | PATH@[106; 109) | ||
85 | PATH_SEGMENT@[106; 109) | ||
86 | NAME_REF@[106; 109) | ||
87 | IDENT@[106; 109) "i32" | ||
88 | WHITESPACE@[109; 110) " " | ||
89 | EQ@[110; 111) "=" | ||
90 | WHITESPACE@[111; 112) " " | ||
91 | LITERAL@[112; 114) | ||
92 | INT_NUMBER@[112; 114) "92" | ||
93 | SEMI@[114; 115) ";" | ||
94 | WHITESPACE@[115; 116) "\n" | ||
95 | R_CURLY@[116; 117) "}" | ||
96 | WHITESPACE@[117; 118) "\n" | ||
97 | error [36; 39): unnecessary visibility qualifier | ||
98 | error [56; 66): unnecessary visibility qualifier | ||
99 | error [86; 96): unnecessary visibility qualifier | ||