diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_db/src/input.rs | 17 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 16 | ||||
-rw-r--r-- | crates/ra_hir/src/db.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/db.rs | 13 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 203 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk.rs | 10 | ||||
-rw-r--r-- | crates/ra_ide/src/display/structure.rs | 428 | ||||
-rw-r--r-- | crates/ra_ide/src/folding_ranges.rs | 161 | ||||
-rw-r--r-- | crates/ra_ide/src/goto_implementation.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide_db/src/change.rs | 5 | ||||
-rw-r--r-- | crates/rust-analyzer/src/to_proto.rs | 31 | ||||
-rw-r--r-- | crates/test_utils/src/lib.rs | 27 |
12 files changed, 477 insertions, 446 deletions
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs index 445a1ee48..aaa492759 100644 --- a/crates/ra_db/src/input.rs +++ b/crates/ra_db/src/input.rs | |||
@@ -197,6 +197,23 @@ impl CrateGraph { | |||
197 | self.arena.keys().copied() | 197 | self.arena.keys().copied() |
198 | } | 198 | } |
199 | 199 | ||
200 | /// Returns an iterator over all transitive dependencies of the given crate. | ||
201 | pub fn transitive_deps(&self, of: CrateId) -> impl Iterator<Item = CrateId> + '_ { | ||
202 | let mut worklist = vec![of]; | ||
203 | let mut deps = FxHashSet::default(); | ||
204 | |||
205 | while let Some(krate) = worklist.pop() { | ||
206 | if !deps.insert(krate) { | ||
207 | continue; | ||
208 | } | ||
209 | |||
210 | worklist.extend(self[krate].dependencies.iter().map(|dep| dep.crate_id)); | ||
211 | } | ||
212 | |||
213 | deps.remove(&of); | ||
214 | deps.into_iter() | ||
215 | } | ||
216 | |||
200 | // FIXME: this only finds one crate with the given root; we could have multiple | 217 | // FIXME: this only finds one crate with the given root; we could have multiple |
201 | pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> { | 218 | pub fn crate_id_for_crate_root(&self, file_id: FileId) -> Option<CrateId> { |
202 | let (&crate_id, _) = | 219 | let (&crate_id, _) = |
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index e09eb77c2..cc72964ff 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -1053,12 +1053,14 @@ pub struct ImplDef { | |||
1053 | 1053 | ||
1054 | impl ImplDef { | 1054 | impl ImplDef { |
1055 | pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<ImplDef> { | 1055 | pub fn all_in_crate(db: &dyn HirDatabase, krate: Crate) -> Vec<ImplDef> { |
1056 | let impls = db.impls_in_crate(krate.id); | 1056 | let inherent = db.inherent_impls_in_crate(krate.id); |
1057 | impls.all_impls().map(Self::from).collect() | 1057 | let trait_ = db.trait_impls_in_crate(krate.id); |
1058 | |||
1059 | inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect() | ||
1058 | } | 1060 | } |
1059 | pub fn for_trait(db: &dyn HirDatabase, krate: Crate, trait_: Trait) -> Vec<ImplDef> { | 1061 | pub fn for_trait(db: &dyn HirDatabase, krate: Crate, trait_: Trait) -> Vec<ImplDef> { |
1060 | let impls = db.impls_in_crate(krate.id); | 1062 | let impls = db.trait_impls_in_crate(krate.id); |
1061 | impls.lookup_impl_defs_for_trait(trait_.id).map(Self::from).collect() | 1063 | impls.for_trait(trait_.id).map(Self::from).collect() |
1062 | } | 1064 | } |
1063 | 1065 | ||
1064 | pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> { | 1066 | pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> { |
@@ -1303,10 +1305,10 @@ impl Type { | |||
1303 | mut callback: impl FnMut(AssocItem) -> Option<T>, | 1305 | mut callback: impl FnMut(AssocItem) -> Option<T>, |
1304 | ) -> Option<T> { | 1306 | ) -> Option<T> { |
1305 | for krate in self.ty.value.def_crates(db, krate.id)? { | 1307 | for krate in self.ty.value.def_crates(db, krate.id)? { |
1306 | let impls = db.impls_in_crate(krate); | 1308 | let impls = db.inherent_impls_in_crate(krate); |
1307 | 1309 | ||
1308 | for impl_def in impls.lookup_impl_defs(&self.ty.value) { | 1310 | for impl_def in impls.for_self_ty(&self.ty.value) { |
1309 | for &item in db.impl_data(impl_def).items.iter() { | 1311 | for &item in db.impl_data(*impl_def).items.iter() { |
1310 | if let Some(result) = callback(item.into()) { | 1312 | if let Some(result) = callback(item.into()) { |
1311 | return Some(result); | 1313 | return Some(result); |
1312 | } | 1314 | } |
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index bb67952de..cb48ca065 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -16,10 +16,10 @@ pub use hir_expand::db::{ | |||
16 | pub use hir_ty::db::{ | 16 | pub use hir_ty::db::{ |
17 | AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery, | 17 | AssociatedTyDataQuery, AssociatedTyValueQuery, CallableItemSignatureQuery, FieldTypesQuery, |
18 | GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase, | 18 | GenericDefaultsQuery, GenericPredicatesForParamQuery, GenericPredicatesQuery, HirDatabase, |
19 | HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, ImplsFromDepsQuery, | 19 | HirDatabaseStorage, ImplDatumQuery, ImplSelfTyQuery, ImplTraitQuery, InferQueryQuery, |
20 | ImplsInCrateQuery, InferQueryQuery, InternAssocTyValueQuery, InternChalkImplQuery, | 20 | InherentImplsInCrateQuery, InternAssocTyValueQuery, InternChalkImplQuery, InternTypeCtorQuery, |
21 | InternTypeCtorQuery, InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery, | 21 | InternTypeParamIdQuery, ReturnTypeImplTraitsQuery, StructDatumQuery, TraitDatumQuery, |
22 | TraitDatumQuery, TraitSolveQuery, TyQuery, ValueTyQuery, | 22 | TraitImplsInCrateQuery, TraitImplsInDepsQuery, TraitSolveQuery, TyQuery, ValueTyQuery, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | #[test] | 25 | #[test] |
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs index cad553273..dc06c0ee7 100644 --- a/crates/ra_hir_ty/src/db.rs +++ b/crates/ra_hir_ty/src/db.rs | |||
@@ -11,7 +11,7 @@ use ra_db::{impl_intern_key, salsa, CrateId, Upcast}; | |||
11 | use ra_prof::profile; | 11 | use ra_prof::profile; |
12 | 12 | ||
13 | use crate::{ | 13 | use crate::{ |
14 | method_resolution::CrateImplDefs, | 14 | method_resolution::{InherentImpls, TraitImpls}, |
15 | traits::{chalk, AssocTyValue, Impl}, | 15 | traits::{chalk, AssocTyValue, Impl}, |
16 | Binders, CallableDef, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig, | 16 | Binders, CallableDef, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig, |
17 | ReturnTypeImplTraits, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId, | 17 | ReturnTypeImplTraits, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId, |
@@ -67,11 +67,14 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
67 | #[salsa::invoke(crate::lower::generic_defaults_query)] | 67 | #[salsa::invoke(crate::lower::generic_defaults_query)] |
68 | fn generic_defaults(&self, def: GenericDefId) -> Arc<[Binders<Ty>]>; | 68 | fn generic_defaults(&self, def: GenericDefId) -> Arc<[Binders<Ty>]>; |
69 | 69 | ||
70 | #[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_in_crate_query)] | 70 | #[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)] |
71 | fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplDefs>; | 71 | fn inherent_impls_in_crate(&self, krate: CrateId) -> Arc<InherentImpls>; |
72 | 72 | ||
73 | #[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_from_deps_query)] | 73 | #[salsa::invoke(TraitImpls::trait_impls_in_crate_query)] |
74 | fn impls_from_deps(&self, krate: CrateId) -> Arc<CrateImplDefs>; | 74 | fn trait_impls_in_crate(&self, krate: CrateId) -> Arc<TraitImpls>; |
75 | |||
76 | #[salsa::invoke(TraitImpls::trait_impls_in_deps_query)] | ||
77 | fn trait_impls_in_deps(&self, krate: CrateId) -> Arc<TraitImpls>; | ||
75 | 78 | ||
76 | // Interned IDs for Chalk integration | 79 | // Interned IDs for Chalk integration |
77 | #[salsa::interned] | 80 | #[salsa::interned] |
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index c19519cf1..5dbabd12b 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -38,136 +38,131 @@ impl TyFingerprint { | |||
38 | } | 38 | } |
39 | } | 39 | } |
40 | 40 | ||
41 | /// A queryable and mergeable collection of impls. | 41 | /// Trait impls defined or available in some crate. |
42 | #[derive(Debug, PartialEq, Eq)] | 42 | #[derive(Debug, Eq, PartialEq)] |
43 | pub struct CrateImplDefs { | 43 | pub struct TraitImpls { |
44 | inherent_impls: FxHashMap<TyFingerprint, Vec<ImplId>>, | 44 | // If the `Option<TyFingerprint>` is `None`, the impl may apply to any self type. |
45 | impls_by_trait: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>, | 45 | map: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>, |
46 | } | 46 | } |
47 | 47 | ||
48 | impl CrateImplDefs { | 48 | impl TraitImpls { |
49 | pub(crate) fn impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<CrateImplDefs> { | 49 | pub(crate) fn trait_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> { |
50 | let _p = profile("impls_in_crate_query"); | 50 | let _p = profile("trait_impls_in_crate_query"); |
51 | let mut res = CrateImplDefs { | 51 | let mut impls = Self { map: FxHashMap::default() }; |
52 | inherent_impls: FxHashMap::default(), | ||
53 | impls_by_trait: FxHashMap::default(), | ||
54 | }; | ||
55 | res.fill(db, krate); | ||
56 | 52 | ||
57 | Arc::new(res) | 53 | let crate_def_map = db.crate_def_map(krate); |
54 | for (_module_id, module_data) in crate_def_map.modules.iter() { | ||
55 | for impl_id in module_data.scope.impls() { | ||
56 | let target_trait = match db.impl_trait(impl_id) { | ||
57 | Some(tr) => tr.value.trait_, | ||
58 | None => continue, | ||
59 | }; | ||
60 | let self_ty = db.impl_self_ty(impl_id); | ||
61 | let self_ty_fp = TyFingerprint::for_impl(&self_ty.value); | ||
62 | impls | ||
63 | .map | ||
64 | .entry(target_trait) | ||
65 | .or_default() | ||
66 | .entry(self_ty_fp) | ||
67 | .or_default() | ||
68 | .push(impl_id); | ||
69 | } | ||
70 | } | ||
71 | |||
72 | Arc::new(impls) | ||
58 | } | 73 | } |
59 | 74 | ||
60 | /// Collects all impls from transitive dependencies of `krate` that may be used by `krate`. | 75 | pub(crate) fn trait_impls_in_deps_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> { |
61 | /// | 76 | let _p = profile("trait_impls_in_deps_query"); |
62 | /// The full set of impls that can be used by `krate` is the returned map plus all the impls | ||
63 | /// from `krate` itself. | ||
64 | pub(crate) fn impls_from_deps_query( | ||
65 | db: &dyn HirDatabase, | ||
66 | krate: CrateId, | ||
67 | ) -> Arc<CrateImplDefs> { | ||
68 | let _p = profile("impls_from_deps_query"); | ||
69 | let crate_graph = db.crate_graph(); | 77 | let crate_graph = db.crate_graph(); |
70 | let mut res = CrateImplDefs { | 78 | let mut res = Self { map: FxHashMap::default() }; |
71 | inherent_impls: FxHashMap::default(), | ||
72 | impls_by_trait: FxHashMap::default(), | ||
73 | }; | ||
74 | 79 | ||
75 | // For each dependency, calculate `impls_from_deps` recursively, then add its own | 80 | for krate in crate_graph.transitive_deps(krate) { |
76 | // `impls_in_crate`. | 81 | res.merge(&db.trait_impls_in_crate(krate)); |
77 | // As we might visit crates multiple times, `merge` has to deduplicate impls to avoid | ||
78 | // wasting memory. | ||
79 | for dep in &crate_graph[krate].dependencies { | ||
80 | res.merge(&db.impls_from_deps(dep.crate_id)); | ||
81 | res.merge(&db.impls_in_crate(dep.crate_id)); | ||
82 | } | 82 | } |
83 | 83 | ||
84 | Arc::new(res) | 84 | Arc::new(res) |
85 | } | 85 | } |
86 | 86 | ||
87 | fn fill(&mut self, db: &dyn HirDatabase, krate: CrateId) { | ||
88 | let crate_def_map = db.crate_def_map(krate); | ||
89 | for (_module_id, module_data) in crate_def_map.modules.iter() { | ||
90 | for impl_id in module_data.scope.impls() { | ||
91 | match db.impl_trait(impl_id) { | ||
92 | Some(tr) => { | ||
93 | let self_ty = db.impl_self_ty(impl_id); | ||
94 | let self_ty_fp = TyFingerprint::for_impl(&self_ty.value); | ||
95 | self.impls_by_trait | ||
96 | .entry(tr.value.trait_) | ||
97 | .or_default() | ||
98 | .entry(self_ty_fp) | ||
99 | .or_default() | ||
100 | .push(impl_id); | ||
101 | } | ||
102 | None => { | ||
103 | let self_ty = db.impl_self_ty(impl_id); | ||
104 | if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty.value) { | ||
105 | self.inherent_impls.entry(self_ty_fp).or_default().push(impl_id); | ||
106 | } | ||
107 | } | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | } | ||
112 | |||
113 | fn merge(&mut self, other: &Self) { | 87 | fn merge(&mut self, other: &Self) { |
114 | for (fp, impls) in &other.inherent_impls { | 88 | for (trait_, other_map) in &other.map { |
115 | let vec = self.inherent_impls.entry(*fp).or_default(); | 89 | let map = self.map.entry(*trait_).or_default(); |
116 | vec.extend(impls); | ||
117 | vec.sort(); | ||
118 | vec.dedup(); | ||
119 | } | ||
120 | |||
121 | for (trait_, other_map) in &other.impls_by_trait { | ||
122 | let map = self.impls_by_trait.entry(*trait_).or_default(); | ||
123 | for (fp, impls) in other_map { | 90 | for (fp, impls) in other_map { |
124 | let vec = map.entry(*fp).or_default(); | 91 | let vec = map.entry(*fp).or_default(); |
125 | vec.extend(impls); | 92 | vec.extend(impls); |
126 | vec.sort(); | ||
127 | vec.dedup(); | ||
128 | } | 93 | } |
129 | } | 94 | } |
130 | } | 95 | } |
131 | 96 | ||
132 | pub fn lookup_impl_defs(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ { | 97 | /// Queries all impls of the given trait. |
133 | let fingerprint = TyFingerprint::for_impl(ty); | 98 | pub fn for_trait(&self, trait_: TraitId) -> impl Iterator<Item = ImplId> + '_ { |
134 | fingerprint.and_then(|f| self.inherent_impls.get(&f)).into_iter().flatten().copied() | 99 | self.map |
135 | } | 100 | .get(&trait_) |
136 | |||
137 | pub fn lookup_impl_defs_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ { | ||
138 | self.impls_by_trait | ||
139 | .get(&tr) | ||
140 | .into_iter() | 101 | .into_iter() |
141 | .flat_map(|m| m.values().flat_map(|v| v.iter().copied())) | 102 | .flat_map(|map| map.values().flat_map(|v| v.iter().copied())) |
142 | } | 103 | } |
143 | 104 | ||
144 | pub fn lookup_impl_defs_for_trait_and_ty( | 105 | /// Queries all impls of `trait_` that may apply to `self_ty`. |
106 | pub fn for_trait_and_self_ty( | ||
145 | &self, | 107 | &self, |
146 | tr: TraitId, | 108 | trait_: TraitId, |
147 | fp: TyFingerprint, | 109 | self_ty: TyFingerprint, |
148 | ) -> impl Iterator<Item = ImplId> + '_ { | 110 | ) -> impl Iterator<Item = ImplId> + '_ { |
149 | self.impls_by_trait | 111 | self.map |
150 | .get(&tr) | 112 | .get(&trait_) |
151 | .and_then(|m| m.get(&Some(fp))) | ||
152 | .into_iter() | 113 | .into_iter() |
153 | .flatten() | 114 | .flat_map(move |map| map.get(&None).into_iter().chain(map.get(&Some(self_ty)))) |
154 | .copied() | 115 | .flat_map(|v| v.iter().copied()) |
155 | .chain( | 116 | } |
156 | self.impls_by_trait | 117 | |
157 | .get(&tr) | 118 | pub fn all_impls(&self) -> impl Iterator<Item = ImplId> + '_ { |
158 | .and_then(|m| m.get(&None)) | 119 | self.map.values().flat_map(|map| map.values().flat_map(|v| v.iter().copied())) |
159 | .into_iter() | 120 | } |
160 | .flatten() | 121 | } |
161 | .copied(), | 122 | |
162 | ) | 123 | /// Inherent impls defined in some crate. |
124 | /// | ||
125 | /// Inherent impls can only be defined in the crate that also defines the self type of the impl | ||
126 | /// (note that some primitives are considered to be defined by both libcore and liballoc). | ||
127 | /// | ||
128 | /// This makes inherent impl lookup easier than trait impl lookup since we only have to consider a | ||
129 | /// single crate. | ||
130 | #[derive(Debug, Eq, PartialEq)] | ||
131 | pub struct InherentImpls { | ||
132 | map: FxHashMap<TyFingerprint, Vec<ImplId>>, | ||
133 | } | ||
134 | |||
135 | impl InherentImpls { | ||
136 | pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> { | ||
137 | let mut map: FxHashMap<_, Vec<_>> = FxHashMap::default(); | ||
138 | |||
139 | let crate_def_map = db.crate_def_map(krate); | ||
140 | for (_module_id, module_data) in crate_def_map.modules.iter() { | ||
141 | for impl_id in module_data.scope.impls() { | ||
142 | let data = db.impl_data(impl_id); | ||
143 | if data.target_trait.is_some() { | ||
144 | continue; | ||
145 | } | ||
146 | |||
147 | let self_ty = db.impl_self_ty(impl_id); | ||
148 | if let Some(fp) = TyFingerprint::for_impl(&self_ty.value) { | ||
149 | map.entry(fp).or_default().push(impl_id); | ||
150 | } | ||
151 | } | ||
152 | } | ||
153 | |||
154 | Arc::new(Self { map }) | ||
155 | } | ||
156 | |||
157 | pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] { | ||
158 | match TyFingerprint::for_impl(self_ty) { | ||
159 | Some(fp) => self.map.get(&fp).map(|vec| vec.as_ref()).unwrap_or(&[]), | ||
160 | None => &[], | ||
161 | } | ||
163 | } | 162 | } |
164 | 163 | ||
165 | pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a { | 164 | pub fn all_impls(&self) -> impl Iterator<Item = ImplId> + '_ { |
166 | self.inherent_impls | 165 | self.map.values().flat_map(|v| v.iter().copied()) |
167 | .values() | ||
168 | .chain(self.impls_by_trait.values().flat_map(|m| m.values())) | ||
169 | .flatten() | ||
170 | .copied() | ||
171 | } | 166 | } |
172 | } | 167 | } |
173 | 168 | ||
@@ -524,9 +519,9 @@ fn iterate_inherent_methods( | |||
524 | None => return false, | 519 | None => return false, |
525 | }; | 520 | }; |
526 | for krate in def_crates { | 521 | for krate in def_crates { |
527 | let impls = db.impls_in_crate(krate); | 522 | let impls = db.inherent_impls_in_crate(krate); |
528 | 523 | ||
529 | for impl_def in impls.lookup_impl_defs(&self_ty.value) { | 524 | for &impl_def in impls.for_self_ty(&self_ty.value) { |
530 | for &item in db.impl_data(impl_def).items.iter() { | 525 | for &item in db.impl_data(impl_def).items.iter() { |
531 | if !is_valid_candidate(db, name, receiver_ty, item, self_ty) { | 526 | if !is_valid_candidate(db, name, receiver_ty, item, self_ty) { |
532 | continue; | 527 | continue; |
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 8ef4941c0..c97b81d57 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -77,8 +77,8 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
77 | // Note: Since we're using impls_for_trait, only impls where the trait | 77 | // Note: Since we're using impls_for_trait, only impls where the trait |
78 | // can be resolved should ever reach Chalk. `impl_datum` relies on that | 78 | // can be resolved should ever reach Chalk. `impl_datum` relies on that |
79 | // and will panic if the trait can't be resolved. | 79 | // and will panic if the trait can't be resolved. |
80 | let in_deps = self.db.impls_from_deps(self.krate); | 80 | let in_deps = self.db.trait_impls_in_deps(self.krate); |
81 | let in_self = self.db.impls_in_crate(self.krate); | 81 | let in_self = self.db.trait_impls_in_crate(self.krate); |
82 | let impl_maps = [in_deps, in_self]; | 82 | let impl_maps = [in_deps, in_self]; |
83 | 83 | ||
84 | let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db); | 84 | let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db); |
@@ -87,14 +87,12 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
87 | Some(fp) => impl_maps | 87 | Some(fp) => impl_maps |
88 | .iter() | 88 | .iter() |
89 | .flat_map(|crate_impl_defs| { | 89 | .flat_map(|crate_impl_defs| { |
90 | crate_impl_defs.lookup_impl_defs_for_trait_and_ty(trait_, fp).map(id_to_chalk) | 90 | crate_impl_defs.for_trait_and_self_ty(trait_, fp).map(id_to_chalk) |
91 | }) | 91 | }) |
92 | .collect(), | 92 | .collect(), |
93 | None => impl_maps | 93 | None => impl_maps |
94 | .iter() | 94 | .iter() |
95 | .flat_map(|crate_impl_defs| { | 95 | .flat_map(|crate_impl_defs| crate_impl_defs.for_trait(trait_).map(id_to_chalk)) |
96 | crate_impl_defs.lookup_impl_defs_for_trait(trait_).map(id_to_chalk) | ||
97 | }) | ||
98 | .collect(), | 96 | .collect(), |
99 | }; | 97 | }; |
100 | 98 | ||
diff --git a/crates/ra_ide/src/display/structure.rs b/crates/ra_ide/src/display/structure.rs index aad5a8e4d..c22a5d17b 100644 --- a/crates/ra_ide/src/display/structure.rs +++ b/crates/ra_ide/src/display/structure.rs | |||
@@ -173,12 +173,19 @@ fn structure_node(node: &SyntaxNode) -> Option<StructureNode> { | |||
173 | 173 | ||
174 | #[cfg(test)] | 174 | #[cfg(test)] |
175 | mod tests { | 175 | mod tests { |
176 | use expect::{expect, Expect}; | ||
177 | |||
176 | use super::*; | 178 | use super::*; |
177 | use insta::assert_debug_snapshot; | 179 | |
180 | fn check(ra_fixture: &str, expect: Expect) { | ||
181 | let file = SourceFile::parse(ra_fixture).ok().unwrap(); | ||
182 | let structure = file_structure(&file); | ||
183 | expect.assert_debug_eq(&structure) | ||
184 | } | ||
178 | 185 | ||
179 | #[test] | 186 | #[test] |
180 | fn test_file_structure() { | 187 | fn test_file_structure() { |
181 | let file = SourceFile::parse( | 188 | check( |
182 | r#" | 189 | r#" |
183 | struct Foo { | 190 | struct Foo { |
184 | x: i32 | 191 | x: i32 |
@@ -223,216 +230,211 @@ fn obsolete() {} | |||
223 | #[deprecated(note = "for awhile")] | 230 | #[deprecated(note = "for awhile")] |
224 | fn very_obsolete() {} | 231 | fn very_obsolete() {} |
225 | "#, | 232 | "#, |
226 | ) | 233 | expect![[r#" |
227 | .ok() | 234 | [ |
228 | .unwrap(); | 235 | StructureNode { |
229 | let structure = file_structure(&file); | 236 | parent: None, |
230 | assert_debug_snapshot!(structure, | 237 | label: "Foo", |
231 | @r###" | 238 | navigation_range: 8..11, |
232 | [ | 239 | node_range: 1..26, |
233 | StructureNode { | 240 | kind: STRUCT_DEF, |
234 | parent: None, | 241 | detail: None, |
235 | label: "Foo", | 242 | deprecated: false, |
236 | navigation_range: 8..11, | 243 | }, |
237 | node_range: 1..26, | 244 | StructureNode { |
238 | kind: STRUCT_DEF, | 245 | parent: Some( |
239 | detail: None, | 246 | 0, |
240 | deprecated: false, | 247 | ), |
241 | }, | 248 | label: "x", |
242 | StructureNode { | 249 | navigation_range: 18..19, |
243 | parent: Some( | 250 | node_range: 18..24, |
244 | 0, | 251 | kind: RECORD_FIELD_DEF, |
245 | ), | 252 | detail: Some( |
246 | label: "x", | 253 | "i32", |
247 | navigation_range: 18..19, | 254 | ), |
248 | node_range: 18..24, | 255 | deprecated: false, |
249 | kind: RECORD_FIELD_DEF, | 256 | }, |
250 | detail: Some( | 257 | StructureNode { |
251 | "i32", | 258 | parent: None, |
252 | ), | 259 | label: "m", |
253 | deprecated: false, | 260 | navigation_range: 32..33, |
254 | }, | 261 | node_range: 28..158, |
255 | StructureNode { | 262 | kind: MODULE, |
256 | parent: None, | 263 | detail: None, |
257 | label: "m", | 264 | deprecated: false, |
258 | navigation_range: 32..33, | 265 | }, |
259 | node_range: 28..158, | 266 | StructureNode { |
260 | kind: MODULE, | 267 | parent: Some( |
261 | detail: None, | 268 | 2, |
262 | deprecated: false, | 269 | ), |
263 | }, | 270 | label: "bar1", |
264 | StructureNode { | 271 | navigation_range: 43..47, |
265 | parent: Some( | 272 | node_range: 40..52, |
266 | 2, | 273 | kind: FN_DEF, |
267 | ), | 274 | detail: Some( |
268 | label: "bar1", | 275 | "fn()", |
269 | navigation_range: 43..47, | 276 | ), |
270 | node_range: 40..52, | 277 | deprecated: false, |
271 | kind: FN_DEF, | 278 | }, |
272 | detail: Some( | 279 | StructureNode { |
273 | "fn()", | 280 | parent: Some( |
274 | ), | 281 | 2, |
275 | deprecated: false, | 282 | ), |
276 | }, | 283 | label: "bar2", |
277 | StructureNode { | 284 | navigation_range: 60..64, |
278 | parent: Some( | 285 | node_range: 57..81, |
279 | 2, | 286 | kind: FN_DEF, |
280 | ), | 287 | detail: Some( |
281 | label: "bar2", | 288 | "fn<T>(t: T) -> T", |
282 | navigation_range: 60..64, | 289 | ), |
283 | node_range: 57..81, | 290 | deprecated: false, |
284 | kind: FN_DEF, | 291 | }, |
285 | detail: Some( | 292 | StructureNode { |
286 | "fn<T>(t: T) -> T", | 293 | parent: Some( |
287 | ), | 294 | 2, |
288 | deprecated: false, | 295 | ), |
289 | }, | 296 | label: "bar3", |
290 | StructureNode { | 297 | navigation_range: 89..93, |
291 | parent: Some( | 298 | node_range: 86..156, |
292 | 2, | 299 | kind: FN_DEF, |
293 | ), | 300 | detail: Some( |
294 | label: "bar3", | 301 | "fn<A, B>(a: A, b: B) -> Vec< u32 >", |
295 | navigation_range: 89..93, | 302 | ), |
296 | node_range: 86..156, | 303 | deprecated: false, |
297 | kind: FN_DEF, | 304 | }, |
298 | detail: Some( | 305 | StructureNode { |
299 | "fn<A, B>(a: A, b: B) -> Vec< u32 >", | 306 | parent: None, |
300 | ), | 307 | label: "E", |
301 | deprecated: false, | 308 | navigation_range: 165..166, |
302 | }, | 309 | node_range: 160..180, |
303 | StructureNode { | 310 | kind: ENUM_DEF, |
304 | parent: None, | 311 | detail: None, |
305 | label: "E", | 312 | deprecated: false, |
306 | navigation_range: 165..166, | 313 | }, |
307 | node_range: 160..180, | 314 | StructureNode { |
308 | kind: ENUM_DEF, | 315 | parent: Some( |
309 | detail: None, | 316 | 6, |
310 | deprecated: false, | 317 | ), |
311 | }, | 318 | label: "X", |
312 | StructureNode { | 319 | navigation_range: 169..170, |
313 | parent: Some( | 320 | node_range: 169..170, |
314 | 6, | 321 | kind: ENUM_VARIANT, |
315 | ), | 322 | detail: None, |
316 | label: "X", | 323 | deprecated: false, |
317 | navigation_range: 169..170, | 324 | }, |
318 | node_range: 169..170, | 325 | StructureNode { |
319 | kind: ENUM_VARIANT, | 326 | parent: Some( |
320 | detail: None, | 327 | 6, |
321 | deprecated: false, | 328 | ), |
322 | }, | 329 | label: "Y", |
323 | StructureNode { | 330 | navigation_range: 172..173, |
324 | parent: Some( | 331 | node_range: 172..178, |
325 | 6, | 332 | kind: ENUM_VARIANT, |
326 | ), | 333 | detail: None, |
327 | label: "Y", | 334 | deprecated: false, |
328 | navigation_range: 172..173, | 335 | }, |
329 | node_range: 172..178, | 336 | StructureNode { |
330 | kind: ENUM_VARIANT, | 337 | parent: None, |
331 | detail: None, | 338 | label: "T", |
332 | deprecated: false, | 339 | navigation_range: 186..187, |
333 | }, | 340 | node_range: 181..193, |
334 | StructureNode { | 341 | kind: TYPE_ALIAS_DEF, |
335 | parent: None, | 342 | detail: Some( |
336 | label: "T", | 343 | "()", |
337 | navigation_range: 186..187, | 344 | ), |
338 | node_range: 181..193, | 345 | deprecated: false, |
339 | kind: TYPE_ALIAS_DEF, | 346 | }, |
340 | detail: Some( | 347 | StructureNode { |
341 | "()", | 348 | parent: None, |
342 | ), | 349 | label: "S", |
343 | deprecated: false, | 350 | navigation_range: 201..202, |
344 | }, | 351 | node_range: 194..213, |
345 | StructureNode { | 352 | kind: STATIC_DEF, |
346 | parent: None, | 353 | detail: Some( |
347 | label: "S", | 354 | "i32", |
348 | navigation_range: 201..202, | 355 | ), |
349 | node_range: 194..213, | 356 | deprecated: false, |
350 | kind: STATIC_DEF, | 357 | }, |
351 | detail: Some( | 358 | StructureNode { |
352 | "i32", | 359 | parent: None, |
353 | ), | 360 | label: "C", |
354 | deprecated: false, | 361 | navigation_range: 220..221, |
355 | }, | 362 | node_range: 214..232, |
356 | StructureNode { | 363 | kind: CONST_DEF, |
357 | parent: None, | 364 | detail: Some( |
358 | label: "C", | 365 | "i32", |
359 | navigation_range: 220..221, | 366 | ), |
360 | node_range: 214..232, | 367 | deprecated: false, |
361 | kind: CONST_DEF, | 368 | }, |
362 | detail: Some( | 369 | StructureNode { |
363 | "i32", | 370 | parent: None, |
364 | ), | 371 | label: "impl E", |
365 | deprecated: false, | 372 | navigation_range: 239..240, |
366 | }, | 373 | node_range: 234..243, |
367 | StructureNode { | 374 | kind: IMPL_DEF, |
368 | parent: None, | 375 | detail: None, |
369 | label: "impl E", | 376 | deprecated: false, |
370 | navigation_range: 239..240, | 377 | }, |
371 | node_range: 234..243, | 378 | StructureNode { |
372 | kind: IMPL_DEF, | 379 | parent: None, |
373 | detail: None, | 380 | label: "impl fmt::Debug for E", |
374 | deprecated: false, | 381 | navigation_range: 265..266, |
375 | }, | 382 | node_range: 245..269, |
376 | StructureNode { | 383 | kind: IMPL_DEF, |
377 | parent: None, | 384 | detail: None, |
378 | label: "impl fmt::Debug for E", | 385 | deprecated: false, |
379 | navigation_range: 265..266, | 386 | }, |
380 | node_range: 245..269, | 387 | StructureNode { |
381 | kind: IMPL_DEF, | 388 | parent: None, |
382 | detail: None, | 389 | label: "mc", |
383 | deprecated: false, | 390 | navigation_range: 284..286, |
384 | }, | 391 | node_range: 271..303, |
385 | StructureNode { | 392 | kind: MACRO_CALL, |
386 | parent: None, | 393 | detail: None, |
387 | label: "mc", | 394 | deprecated: false, |
388 | navigation_range: 284..286, | 395 | }, |
389 | node_range: 271..303, | 396 | StructureNode { |
390 | kind: MACRO_CALL, | 397 | parent: None, |
391 | detail: None, | 398 | label: "mcexp", |
392 | deprecated: false, | 399 | navigation_range: 334..339, |
393 | }, | 400 | node_range: 305..356, |
394 | StructureNode { | 401 | kind: MACRO_CALL, |
395 | parent: None, | 402 | detail: None, |
396 | label: "mcexp", | 403 | deprecated: false, |
397 | navigation_range: 334..339, | 404 | }, |
398 | node_range: 305..356, | 405 | StructureNode { |
399 | kind: MACRO_CALL, | 406 | parent: None, |
400 | detail: None, | 407 | label: "mcexp", |
401 | deprecated: false, | 408 | navigation_range: 387..392, |
402 | }, | 409 | node_range: 358..409, |
403 | StructureNode { | 410 | kind: MACRO_CALL, |
404 | parent: None, | 411 | detail: None, |
405 | label: "mcexp", | 412 | deprecated: false, |
406 | navigation_range: 387..392, | 413 | }, |
407 | node_range: 358..409, | 414 | StructureNode { |
408 | kind: MACRO_CALL, | 415 | parent: None, |
409 | detail: None, | 416 | label: "obsolete", |
410 | deprecated: false, | 417 | navigation_range: 428..436, |
411 | }, | 418 | node_range: 411..441, |
412 | StructureNode { | 419 | kind: FN_DEF, |
413 | parent: None, | 420 | detail: Some( |
414 | label: "obsolete", | 421 | "fn()", |
415 | navigation_range: 428..436, | 422 | ), |
416 | node_range: 411..441, | 423 | deprecated: true, |
417 | kind: FN_DEF, | 424 | }, |
418 | detail: Some( | 425 | StructureNode { |
419 | "fn()", | 426 | parent: None, |
420 | ), | 427 | label: "very_obsolete", |
421 | deprecated: true, | 428 | navigation_range: 481..494, |
422 | }, | 429 | node_range: 443..499, |
423 | StructureNode { | 430 | kind: FN_DEF, |
424 | parent: None, | 431 | detail: Some( |
425 | label: "very_obsolete", | 432 | "fn()", |
426 | navigation_range: 481..494, | 433 | ), |
427 | node_range: 443..499, | 434 | deprecated: true, |
428 | kind: FN_DEF, | 435 | }, |
429 | detail: Some( | 436 | ] |
430 | "fn()", | 437 | "#]], |
431 | ), | 438 | ); |
432 | deprecated: true, | ||
433 | }, | ||
434 | ] | ||
435 | "### | ||
436 | ); | ||
437 | } | 439 | } |
438 | } | 440 | } |
diff --git a/crates/ra_ide/src/folding_ranges.rs b/crates/ra_ide/src/folding_ranges.rs index 8657377de..5cec689f8 100644 --- a/crates/ra_ide/src/folding_ranges.rs +++ b/crates/ra_ide/src/folding_ranges.rs | |||
@@ -15,6 +15,7 @@ pub enum FoldKind { | |||
15 | Imports, | 15 | Imports, |
16 | Mods, | 16 | Mods, |
17 | Block, | 17 | Block, |
18 | ArgList, | ||
18 | } | 19 | } |
19 | 20 | ||
20 | #[derive(Debug)] | 21 | #[derive(Debug)] |
@@ -83,6 +84,7 @@ fn fold_kind(kind: SyntaxKind) -> Option<FoldKind> { | |||
83 | match kind { | 84 | match kind { |
84 | COMMENT => Some(FoldKind::Comment), | 85 | COMMENT => Some(FoldKind::Comment), |
85 | USE_ITEM => Some(FoldKind::Imports), | 86 | USE_ITEM => Some(FoldKind::Imports), |
87 | ARG_LIST => Some(FoldKind::ArgList), | ||
86 | RECORD_FIELD_DEF_LIST | 88 | RECORD_FIELD_DEF_LIST |
87 | | RECORD_FIELD_PAT_LIST | 89 | | RECORD_FIELD_PAT_LIST |
88 | | ITEM_LIST | 90 | | ITEM_LIST |
@@ -196,89 +198,85 @@ fn contiguous_range_for_comment( | |||
196 | 198 | ||
197 | #[cfg(test)] | 199 | #[cfg(test)] |
198 | mod tests { | 200 | mod tests { |
201 | use test_utils::extract_tags; | ||
202 | |||
199 | use super::*; | 203 | use super::*; |
200 | use test_utils::extract_ranges; | ||
201 | 204 | ||
202 | fn do_check(text: &str, fold_kinds: &[FoldKind]) { | 205 | fn check(ra_fixture: &str) { |
203 | let (ranges, text) = extract_ranges(text, "fold"); | 206 | let (ranges, text) = extract_tags(ra_fixture, "fold"); |
207 | |||
204 | let parse = SourceFile::parse(&text); | 208 | let parse = SourceFile::parse(&text); |
205 | let folds = folding_ranges(&parse.tree()); | 209 | let folds = folding_ranges(&parse.tree()); |
206 | |||
207 | assert_eq!( | 210 | assert_eq!( |
208 | folds.len(), | 211 | folds.len(), |
209 | ranges.len(), | 212 | ranges.len(), |
210 | "The amount of folds is different than the expected amount" | 213 | "The amount of folds is different than the expected amount" |
211 | ); | 214 | ); |
212 | assert_eq!( | 215 | |
213 | folds.len(), | 216 | for (fold, (range, attr)) in folds.iter().zip(ranges.into_iter()) { |
214 | fold_kinds.len(), | ||
215 | "The amount of fold kinds is different than the expected amount" | ||
216 | ); | ||
217 | for ((fold, range), fold_kind) in | ||
218 | folds.iter().zip(ranges.into_iter()).zip(fold_kinds.iter()) | ||
219 | { | ||
220 | assert_eq!(fold.range.start(), range.start()); | 217 | assert_eq!(fold.range.start(), range.start()); |
221 | assert_eq!(fold.range.end(), range.end()); | 218 | assert_eq!(fold.range.end(), range.end()); |
222 | assert_eq!(&fold.kind, fold_kind); | 219 | |
220 | let kind = match fold.kind { | ||
221 | FoldKind::Comment => "comment", | ||
222 | FoldKind::Imports => "imports", | ||
223 | FoldKind::Mods => "mods", | ||
224 | FoldKind::Block => "block", | ||
225 | FoldKind::ArgList => "arglist", | ||
226 | }; | ||
227 | assert_eq!(kind, &attr.unwrap()); | ||
223 | } | 228 | } |
224 | } | 229 | } |
225 | 230 | ||
226 | #[test] | 231 | #[test] |
227 | fn test_fold_comments() { | 232 | fn test_fold_comments() { |
228 | let text = r#" | 233 | check( |
229 | <fold>// Hello | 234 | r#" |
235 | <fold comment>// Hello | ||
230 | // this is a multiline | 236 | // this is a multiline |
231 | // comment | 237 | // comment |
232 | //</fold> | 238 | //</fold> |
233 | 239 | ||
234 | // But this is not | 240 | // But this is not |
235 | 241 | ||
236 | fn main() <fold>{ | 242 | fn main() <fold block>{ |
237 | <fold>// We should | 243 | <fold comment>// We should |
238 | // also | 244 | // also |
239 | // fold | 245 | // fold |
240 | // this one.</fold> | 246 | // this one.</fold> |
241 | <fold>//! But this one is different | 247 | <fold comment>//! But this one is different |
242 | //! because it has another flavor</fold> | 248 | //! because it has another flavor</fold> |
243 | <fold>/* As does this | 249 | <fold comment>/* As does this |
244 | multiline comment */</fold> | 250 | multiline comment */</fold> |
245 | }</fold>"#; | 251 | }</fold>"#, |
246 | 252 | ); | |
247 | let fold_kinds = &[ | ||
248 | FoldKind::Comment, | ||
249 | FoldKind::Block, | ||
250 | FoldKind::Comment, | ||
251 | FoldKind::Comment, | ||
252 | FoldKind::Comment, | ||
253 | ]; | ||
254 | do_check(text, fold_kinds); | ||
255 | } | 253 | } |
256 | 254 | ||
257 | #[test] | 255 | #[test] |
258 | fn test_fold_imports() { | 256 | fn test_fold_imports() { |
259 | let text = r#" | 257 | check( |
260 | <fold>use std::<fold>{ | 258 | r#" |
259 | <fold imports>use std::<fold block>{ | ||
261 | str, | 260 | str, |
262 | vec, | 261 | vec, |
263 | io as iop | 262 | io as iop |
264 | }</fold>;</fold> | 263 | }</fold>;</fold> |
265 | 264 | ||
266 | fn main() <fold>{ | 265 | fn main() <fold block>{ |
267 | }</fold>"#; | 266 | }</fold>"#, |
268 | 267 | ); | |
269 | let folds = &[FoldKind::Imports, FoldKind::Block, FoldKind::Block]; | ||
270 | do_check(text, folds); | ||
271 | } | 268 | } |
272 | 269 | ||
273 | #[test] | 270 | #[test] |
274 | fn test_fold_mods() { | 271 | fn test_fold_mods() { |
275 | let text = r#" | 272 | check( |
273 | r#" | ||
276 | 274 | ||
277 | pub mod foo; | 275 | pub mod foo; |
278 | <fold>mod after_pub; | 276 | <fold mods>mod after_pub; |
279 | mod after_pub_next;</fold> | 277 | mod after_pub_next;</fold> |
280 | 278 | ||
281 | <fold>mod before_pub; | 279 | <fold mods>mod before_pub; |
282 | mod before_pub_next;</fold> | 280 | mod before_pub_next;</fold> |
283 | pub mod bar; | 281 | pub mod bar; |
284 | 282 | ||
@@ -286,90 +284,93 @@ mod not_folding_single; | |||
286 | pub mod foobar; | 284 | pub mod foobar; |
287 | pub not_folding_single_next; | 285 | pub not_folding_single_next; |
288 | 286 | ||
289 | <fold>#[cfg(test)] | 287 | <fold mods>#[cfg(test)] |
290 | mod with_attribute; | 288 | mod with_attribute; |
291 | mod with_attribute_next;</fold> | 289 | mod with_attribute_next;</fold> |
292 | 290 | ||
293 | fn main() <fold>{ | 291 | fn main() <fold block>{ |
294 | }</fold>"#; | 292 | }</fold>"#, |
295 | 293 | ); | |
296 | let folds = &[FoldKind::Mods, FoldKind::Mods, FoldKind::Mods, FoldKind::Block]; | ||
297 | do_check(text, folds); | ||
298 | } | 294 | } |
299 | 295 | ||
300 | #[test] | 296 | #[test] |
301 | fn test_fold_import_groups() { | 297 | fn test_fold_import_groups() { |
302 | let text = r#" | 298 | check( |
303 | <fold>use std::str; | 299 | r#" |
300 | <fold imports>use std::str; | ||
304 | use std::vec; | 301 | use std::vec; |
305 | use std::io as iop;</fold> | 302 | use std::io as iop;</fold> |
306 | 303 | ||
307 | <fold>use std::mem; | 304 | <fold imports>use std::mem; |
308 | use std::f64;</fold> | 305 | use std::f64;</fold> |
309 | 306 | ||
310 | use std::collections::HashMap; | 307 | use std::collections::HashMap; |
311 | // Some random comment | 308 | // Some random comment |
312 | use std::collections::VecDeque; | 309 | use std::collections::VecDeque; |
313 | 310 | ||
314 | fn main() <fold>{ | 311 | fn main() <fold block>{ |
315 | }</fold>"#; | 312 | }</fold>"#, |
316 | 313 | ); | |
317 | let folds = &[FoldKind::Imports, FoldKind::Imports, FoldKind::Block]; | ||
318 | do_check(text, folds); | ||
319 | } | 314 | } |
320 | 315 | ||
321 | #[test] | 316 | #[test] |
322 | fn test_fold_import_and_groups() { | 317 | fn test_fold_import_and_groups() { |
323 | let text = r#" | 318 | check( |
324 | <fold>use std::str; | 319 | r#" |
320 | <fold imports>use std::str; | ||
325 | use std::vec; | 321 | use std::vec; |
326 | use std::io as iop;</fold> | 322 | use std::io as iop;</fold> |
327 | 323 | ||
328 | <fold>use std::mem; | 324 | <fold imports>use std::mem; |
329 | use std::f64;</fold> | 325 | use std::f64;</fold> |
330 | 326 | ||
331 | <fold>use std::collections::<fold>{ | 327 | <fold imports>use std::collections::<fold block>{ |
332 | HashMap, | 328 | HashMap, |
333 | VecDeque, | 329 | VecDeque, |
334 | }</fold>;</fold> | 330 | }</fold>;</fold> |
335 | // Some random comment | 331 | // Some random comment |
336 | 332 | ||
337 | fn main() <fold>{ | 333 | fn main() <fold block>{ |
338 | }</fold>"#; | 334 | }</fold>"#, |
339 | 335 | ); | |
340 | let folds = &[ | ||
341 | FoldKind::Imports, | ||
342 | FoldKind::Imports, | ||
343 | FoldKind::Imports, | ||
344 | FoldKind::Block, | ||
345 | FoldKind::Block, | ||
346 | ]; | ||
347 | do_check(text, folds); | ||
348 | } | 336 | } |
349 | 337 | ||
350 | #[test] | 338 | #[test] |
351 | fn test_folds_macros() { | 339 | fn test_folds_macros() { |
352 | let text = r#" | 340 | check( |
353 | macro_rules! foo <fold>{ | 341 | r#" |
342 | macro_rules! foo <fold block>{ | ||
354 | ($($tt:tt)*) => { $($tt)* } | 343 | ($($tt:tt)*) => { $($tt)* } |
355 | }</fold> | 344 | }</fold> |
356 | "#; | 345 | "#, |
357 | 346 | ); | |
358 | let folds = &[FoldKind::Block]; | ||
359 | do_check(text, folds); | ||
360 | } | 347 | } |
361 | 348 | ||
362 | #[test] | 349 | #[test] |
363 | fn test_fold_match_arms() { | 350 | fn test_fold_match_arms() { |
364 | let text = r#" | 351 | check( |
365 | fn main() <fold>{ | 352 | r#" |
366 | match 0 <fold>{ | 353 | fn main() <fold block>{ |
354 | match 0 <fold block>{ | ||
367 | 0 => 0, | 355 | 0 => 0, |
368 | _ => 1, | 356 | _ => 1, |
369 | }</fold> | 357 | }</fold> |
370 | }</fold>"#; | 358 | }</fold>"#, |
359 | ); | ||
360 | } | ||
371 | 361 | ||
372 | let folds = &[FoldKind::Block, FoldKind::Block]; | 362 | #[test] |
373 | do_check(text, folds); | 363 | fn fold_big_calls() { |
364 | check( | ||
365 | r#" | ||
366 | fn main() <fold block>{ | ||
367 | frobnicate<fold arglist>( | ||
368 | 1, | ||
369 | 2, | ||
370 | 3, | ||
371 | )</fold> | ||
372 | }</fold> | ||
373 | "#, | ||
374 | ) | ||
374 | } | 375 | } |
375 | } | 376 | } |
diff --git a/crates/ra_ide/src/goto_implementation.rs b/crates/ra_ide/src/goto_implementation.rs index 99a7022a4..9acc960fc 100644 --- a/crates/ra_ide/src/goto_implementation.rs +++ b/crates/ra_ide/src/goto_implementation.rs | |||
@@ -219,6 +219,10 @@ impl T for &Foo {} | |||
219 | #[derive(Copy)] | 219 | #[derive(Copy)] |
220 | //^^^^^^^^^^^^^^^ | 220 | //^^^^^^^^^^^^^^^ |
221 | struct Foo<|>; | 221 | struct Foo<|>; |
222 | |||
223 | mod marker { | ||
224 | trait Copy {} | ||
225 | } | ||
222 | "#, | 226 | "#, |
223 | ); | 227 | ); |
224 | } | 228 | } |
diff --git a/crates/ra_ide_db/src/change.rs b/crates/ra_ide_db/src/change.rs index b507000f2..dbe6eacc5 100644 --- a/crates/ra_ide_db/src/change.rs +++ b/crates/ra_ide_db/src/change.rs | |||
@@ -243,8 +243,9 @@ impl RootDatabase { | |||
243 | hir::db::GenericPredicatesForParamQuery | 243 | hir::db::GenericPredicatesForParamQuery |
244 | hir::db::GenericPredicatesQuery | 244 | hir::db::GenericPredicatesQuery |
245 | hir::db::GenericDefaultsQuery | 245 | hir::db::GenericDefaultsQuery |
246 | hir::db::ImplsInCrateQuery | 246 | hir::db::InherentImplsInCrateQuery |
247 | hir::db::ImplsFromDepsQuery | 247 | hir::db::TraitImplsInCrateQuery |
248 | hir::db::TraitImplsInDepsQuery | ||
248 | hir::db::InternTypeCtorQuery | 249 | hir::db::InternTypeCtorQuery |
249 | hir::db::InternTypeParamIdQuery | 250 | hir::db::InternTypeParamIdQuery |
250 | hir::db::InternChalkImplQuery | 251 | hir::db::InternChalkImplQuery |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index a0a58f689..95dd8e408 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -352,7 +352,7 @@ pub(crate) fn folding_range( | |||
352 | let kind = match fold.kind { | 352 | let kind = match fold.kind { |
353 | FoldKind::Comment => Some(lsp_types::FoldingRangeKind::Comment), | 353 | FoldKind::Comment => Some(lsp_types::FoldingRangeKind::Comment), |
354 | FoldKind::Imports => Some(lsp_types::FoldingRangeKind::Imports), | 354 | FoldKind::Imports => Some(lsp_types::FoldingRangeKind::Imports), |
355 | FoldKind::Mods | FoldKind::Block => None, | 355 | FoldKind::Mods | FoldKind::Block | FoldKind::ArgList => None, |
356 | }; | 356 | }; |
357 | 357 | ||
358 | let range = range(line_index, fold.range); | 358 | let range = range(line_index, fold.range); |
@@ -685,32 +685,27 @@ pub(crate) fn runnable( | |||
685 | 685 | ||
686 | #[cfg(test)] | 686 | #[cfg(test)] |
687 | mod tests { | 687 | mod tests { |
688 | use test_utils::extract_ranges; | 688 | use ra_ide::Analysis; |
689 | 689 | ||
690 | use super::*; | 690 | use super::*; |
691 | 691 | ||
692 | #[test] | 692 | #[test] |
693 | fn conv_fold_line_folding_only_fixup() { | 693 | fn conv_fold_line_folding_only_fixup() { |
694 | let text = r#"<fold>mod a; | 694 | let text = r#"mod a; |
695 | mod b; | 695 | mod b; |
696 | mod c;</fold> | 696 | mod c; |
697 | 697 | ||
698 | fn main() <fold>{ | 698 | fn main() { |
699 | if cond <fold>{ | 699 | if cond { |
700 | a::do_a(); | 700 | a::do_a(); |
701 | }</fold> else <fold>{ | 701 | } else { |
702 | b::do_b(); | 702 | b::do_b(); |
703 | }</fold> | 703 | } |
704 | }</fold>"#; | 704 | }"#; |
705 | 705 | ||
706 | let (ranges, text) = extract_ranges(text, "fold"); | 706 | let (analysis, file_id) = Analysis::from_single_file(text.to_string()); |
707 | assert_eq!(ranges.len(), 4); | 707 | let folds = analysis.folding_ranges(file_id).unwrap(); |
708 | let folds = vec![ | 708 | assert_eq!(folds.len(), 4); |
709 | Fold { range: ranges[0], kind: FoldKind::Mods }, | ||
710 | Fold { range: ranges[1], kind: FoldKind::Block }, | ||
711 | Fold { range: ranges[2], kind: FoldKind::Block }, | ||
712 | Fold { range: ranges[3], kind: FoldKind::Block }, | ||
713 | ]; | ||
714 | 709 | ||
715 | let line_index = LineIndex::new(&text); | 710 | let line_index = LineIndex::new(&text); |
716 | let converted: Vec<lsp_types::FoldingRange> = | 711 | let converted: Vec<lsp_types::FoldingRange> = |
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index fba5f4281..e4aa894ac 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs | |||
@@ -118,8 +118,8 @@ pub fn extract_range_or_offset(text: &str) -> (RangeOrOffset, String) { | |||
118 | } | 118 | } |
119 | 119 | ||
120 | /// Extracts ranges, marked with `<tag> </tag>` pairs from the `text` | 120 | /// Extracts ranges, marked with `<tag> </tag>` pairs from the `text` |
121 | pub fn extract_ranges(mut text: &str, tag: &str) -> (Vec<TextRange>, String) { | 121 | pub fn extract_tags(mut text: &str, tag: &str) -> (Vec<(TextRange, Option<String>)>, String) { |
122 | let open = format!("<{}>", tag); | 122 | let open = format!("<{}", tag); |
123 | let close = format!("</{}>", tag); | 123 | let close = format!("</{}>", tag); |
124 | let mut ranges = Vec::new(); | 124 | let mut ranges = Vec::new(); |
125 | let mut res = String::new(); | 125 | let mut res = String::new(); |
@@ -134,22 +134,35 @@ pub fn extract_ranges(mut text: &str, tag: &str) -> (Vec<TextRange>, String) { | |||
134 | res.push_str(&text[..i]); | 134 | res.push_str(&text[..i]); |
135 | text = &text[i..]; | 135 | text = &text[i..]; |
136 | if text.starts_with(&open) { | 136 | if text.starts_with(&open) { |
137 | text = &text[open.len()..]; | 137 | let close_open = text.find('>').unwrap(); |
138 | let attr = text[open.len()..close_open].trim(); | ||
139 | let attr = if attr.is_empty() { None } else { Some(attr.to_string()) }; | ||
140 | text = &text[close_open + '>'.len_utf8()..]; | ||
138 | let from = TextSize::of(&res); | 141 | let from = TextSize::of(&res); |
139 | stack.push(from); | 142 | stack.push((from, attr)); |
140 | } else if text.starts_with(&close) { | 143 | } else if text.starts_with(&close) { |
141 | text = &text[close.len()..]; | 144 | text = &text[close.len()..]; |
142 | let from = stack.pop().unwrap_or_else(|| panic!("unmatched </{}>", tag)); | 145 | let (from, attr) = |
146 | stack.pop().unwrap_or_else(|| panic!("unmatched </{}>", tag)); | ||
143 | let to = TextSize::of(&res); | 147 | let to = TextSize::of(&res); |
144 | ranges.push(TextRange::new(from, to)); | 148 | ranges.push((TextRange::new(from, to), attr)); |
149 | } else { | ||
150 | res.push('<'); | ||
151 | text = &text['<'.len_utf8()..]; | ||
145 | } | 152 | } |
146 | } | 153 | } |
147 | } | 154 | } |
148 | } | 155 | } |
149 | assert!(stack.is_empty(), "unmatched <{}>", tag); | 156 | assert!(stack.is_empty(), "unmatched <{}>", tag); |
150 | ranges.sort_by_key(|r| (r.start(), r.end())); | 157 | ranges.sort_by_key(|r| (r.0.start(), r.0.end())); |
151 | (ranges, res) | 158 | (ranges, res) |
152 | } | 159 | } |
160 | #[test] | ||
161 | fn test_extract_tags() { | ||
162 | let (tags, text) = extract_tags(r#"<tag fn>fn <tag>main</tag>() {}</tag>"#, "tag"); | ||
163 | let actual = tags.into_iter().map(|(range, attr)| (&text[range], attr)).collect::<Vec<_>>(); | ||
164 | assert_eq!(actual, vec![("fn main() {}", Some("fn".into())), ("main", None),]); | ||
165 | } | ||
153 | 166 | ||
154 | /// Inserts `<|>` marker into the `text` at `offset`. | 167 | /// Inserts `<|>` marker into the `text` at `offset`. |
155 | pub fn add_cursor(text: &str, offset: TextSize) -> String { | 168 | pub fn add_cursor(text: &str, offset: TextSize) -> String { |