aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSeivan Heidari <[email protected]>2019-11-21 00:11:41 +0000
committerSeivan Heidari <[email protected]>2019-11-21 00:11:41 +0000
commit358a1bcd708c622836723e5201b6de77cc9ff327 (patch)
treeaeff9c96a6059fa2b02e7c87ec88753bc7993d8d
parent1e2d090ab8a9bda18f148b894b7948eb05b976e6 (diff)
parent612a72fc4ea4376920f2a7da7b3c334227c1716c (diff)
Merge branch 'master' of https://github.com/rust-analyzer/rust-analyzer into feature/themes
-rw-r--r--.cargo/config1
-rw-r--r--README.md1
-rw-r--r--crates/ra_assists/src/assists/add_missing_impl_members.rs2
-rw-r--r--crates/ra_assists/src/assists/add_new.rs4
-rw-r--r--crates/ra_assists/src/assists/fill_match_arms.rs2
-rw-r--r--crates/ra_assists/src/assists/replace_if_let_with_match.rs32
-rw-r--r--crates/ra_cli/src/analysis_stats.rs4
-rw-r--r--crates/ra_fmt/src/lib.rs3
-rw-r--r--crates/ra_hir/src/adt.rs54
-rw-r--r--crates/ra_hir/src/code_model.rs278
-rw-r--r--crates/ra_hir/src/code_model/attrs.rs6
-rw-r--r--crates/ra_hir/src/code_model/docs.rs24
-rw-r--r--crates/ra_hir/src/code_model/src.rs34
-rw-r--r--crates/ra_hir/src/db.rs17
-rw-r--r--crates/ra_hir/src/diagnostics.rs10
-rw-r--r--crates/ra_hir/src/expr.rs5
-rw-r--r--crates/ra_hir/src/from_id.rs44
-rw-r--r--crates/ra_hir/src/from_source.rs160
-rw-r--r--crates/ra_hir/src/generics.rs190
-rw-r--r--crates/ra_hir/src/impl_block.rs20
-rw-r--r--crates/ra_hir/src/lang_item.rs4
-rw-r--r--crates/ra_hir/src/lib.rs9
-rw-r--r--crates/ra_hir/src/resolve.rs139
-rw-r--r--crates/ra_hir/src/source_binder.rs60
-rw-r--r--crates/ra_hir/src/traits.rs82
-rw-r--r--crates/ra_hir/src/ty.rs25
-rw-r--r--crates/ra_hir/src/ty/display.rs43
-rw-r--r--crates/ra_hir/src/ty/infer.rs5
-rw-r--r--crates/ra_hir/src/ty/lower.rs9
-rw-r--r--crates/ra_hir/src/ty/method_resolution.rs6
-rw-r--r--crates/ra_hir/src/ty/tests.rs39
-rw-r--r--crates/ra_hir/src/type_alias.rs2
-rw-r--r--crates/ra_hir_def/src/adt.rs8
-rw-r--r--crates/ra_hir_def/src/body.rs16
-rw-r--r--crates/ra_hir_def/src/body/scope.rs9
-rw-r--r--crates/ra_hir_def/src/db.rs18
-rw-r--r--crates/ra_hir_def/src/diagnostics.rs2
-rw-r--r--crates/ra_hir_def/src/generics.rs185
-rw-r--r--crates/ra_hir_def/src/impls.rs (renamed from crates/ra_hir_def/src/imp.rs)35
-rw-r--r--crates/ra_hir_def/src/lib.rs180
-rw-r--r--crates/ra_hir_def/src/nameres.rs8
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs33
-rw-r--r--crates/ra_hir_def/src/nameres/raw.rs2
-rw-r--r--crates/ra_hir_def/src/path.rs2
-rw-r--r--crates/ra_hir_def/src/traits.rs59
-rw-r--r--crates/ra_hir_expand/src/diagnostics.rs4
-rw-r--r--crates/ra_hir_expand/src/lib.rs38
-rw-r--r--crates/ra_ide_api/src/change.rs1
-rw-r--r--crates/ra_ide_api/src/completion/complete_scope.rs7
-rw-r--r--crates/ra_ide_api/src/completion/completion_context.rs2
-rw-r--r--crates/ra_ide_api/src/completion/presentation.rs8
-rw-r--r--crates/ra_ide_api/src/diagnostics.rs2
-rw-r--r--crates/ra_ide_api/src/display/function_signature.rs8
-rw-r--r--crates/ra_ide_api/src/display/navigation_target.rs36
-rw-r--r--crates/ra_ide_api/src/expand.rs22
-rw-r--r--crates/ra_ide_api/src/expand_macro.rs16
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs38
-rw-r--r--crates/ra_ide_api/src/goto_type_definition.rs4
-rw-r--r--crates/ra_ide_api/src/hover.rs24
-rw-r--r--crates/ra_ide_api/src/impls.rs8
-rw-r--r--crates/ra_ide_api/src/inlay_hints.rs74
-rw-r--r--crates/ra_ide_api/src/join_lines.rs28
-rw-r--r--crates/ra_ide_api/src/lib.rs10
-rw-r--r--crates/ra_ide_api/src/parent_module.rs5
-rw-r--r--crates/ra_ide_api/src/references/classify.rs40
-rw-r--r--crates/ra_ide_api/src/references/name_definition.rs30
-rw-r--r--crates/ra_ide_api/src/references/rename.rs136
-rw-r--r--crates/ra_ide_api/src/references/search_scope.rs10
-rw-r--r--crates/ra_lsp_server/src/config.rs3
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs1
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs2
-rw-r--r--crates/ra_lsp_server/src/world.rs1
-rw-r--r--crates/ra_syntax/src/ast/generated.rs7
-rw-r--r--crates/ra_syntax/src/ast/traits.rs6
-rw-r--r--crates/ra_syntax/src/grammar.ron5
-rw-r--r--crates/ra_syntax/src/ptr.rs10
-rw-r--r--docs/user/README.md2
-rw-r--r--editors/code/src/commands/inlay_hints.ts14
-rw-r--r--editors/code/src/server.ts1
-rw-r--r--editors/emacs/ra-emacs-lsp.el28
-rw-r--r--xtask/Cargo.toml3
-rw-r--r--xtask/src/main.rs13
82 files changed, 1451 insertions, 1067 deletions
diff --git a/.cargo/config b/.cargo/config
index 9a04b9462..560ab3075 100644
--- a/.cargo/config
+++ b/.cargo/config
@@ -2,3 +2,4 @@
2xtask = "run --package xtask --bin xtask --" 2xtask = "run --package xtask --bin xtask --"
3install-ra = "run --package xtask --bin xtask -- install" # for backwards compat 3install-ra = "run --package xtask --bin xtask -- install" # for backwards compat
4tq = "test -- -q" 4tq = "test -- -q"
5qt = "tq"
diff --git a/README.md b/README.md
index ee7afebce..ea1c25d7f 100644
--- a/README.md
+++ b/README.md
@@ -58,6 +58,7 @@ https://rust-lang.zulipchat.com/#narrow/stream/185405-t-compiler.2Frls-2.2E0
58 58
59* API docs: https://rust-analyzer.github.io/rust-analyzer/ra_ide_api/ 59* API docs: https://rust-analyzer.github.io/rust-analyzer/ra_ide_api/
60 60
61
61## License 62## License
62 63
63Rust analyzer is primarily distributed under the terms of both the MIT 64Rust analyzer is primarily distributed under the terms of both the MIT
diff --git a/crates/ra_assists/src/assists/add_missing_impl_members.rs b/crates/ra_assists/src/assists/add_missing_impl_members.rs
index 91af161ee..cef669cb5 100644
--- a/crates/ra_assists/src/assists/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/assists/add_missing_impl_members.rs
@@ -174,7 +174,7 @@ fn resolve_target_trait_def(
174 .path()?; 174 .path()?;
175 175
176 match analyzer.resolve_path(db, &ast_path) { 176 match analyzer.resolve_path(db, &ast_path) {
177 Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def.source(db).ast), 177 Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def.source(db).value),
178 _ => None, 178 _ => None,
179 } 179 }
180} 180}
diff --git a/crates/ra_assists/src/assists/add_new.rs b/crates/ra_assists/src/assists/add_new.rs
index 2038afdc6..b5f8afb4e 100644
--- a/crates/ra_assists/src/assists/add_new.rs
+++ b/crates/ra_assists/src/assists/add_new.rs
@@ -141,7 +141,7 @@ fn find_struct_impl(
141 })?; 141 })?;
142 142
143 let struct_ty = { 143 let struct_ty = {
144 let src = hir::Source { file_id: ctx.frange.file_id.into(), ast: strukt.clone() }; 144 let src = hir::Source { file_id: ctx.frange.file_id.into(), value: strukt.clone() };
145 hir::Struct::from_source(db, src).unwrap().ty(db) 145 hir::Struct::from_source(db, src).unwrap().ty(db)
146 }; 146 };
147 147
@@ -152,7 +152,7 @@ fn find_struct_impl(
152 return false; 152 return false;
153 } 153 }
154 154
155 let src = hir::Source { file_id: ctx.frange.file_id.into(), ast: impl_blk.clone() }; 155 let src = hir::Source { file_id: ctx.frange.file_id.into(), value: impl_blk.clone() };
156 let blk = hir::ImplBlock::from_source(db, src).unwrap(); 156 let blk = hir::ImplBlock::from_source(db, src).unwrap();
157 157
158 let same_ty = blk.target_ty(db) == struct_ty; 158 let same_ty = blk.target_ty(db) == struct_ty;
diff --git a/crates/ra_assists/src/assists/fill_match_arms.rs b/crates/ra_assists/src/assists/fill_match_arms.rs
index b851c2082..9354466d9 100644
--- a/crates/ra_assists/src/assists/fill_match_arms.rs
+++ b/crates/ra_assists/src/assists/fill_match_arms.rs
@@ -84,7 +84,7 @@ fn resolve_enum_def(
84 let expr_ty = analyzer.type_of(db, &expr)?; 84 let expr_ty = analyzer.type_of(db, &expr)?;
85 85
86 analyzer.autoderef(db, expr_ty).find_map(|ty| match ty.as_adt() { 86 analyzer.autoderef(db, expr_ty).find_map(|ty| match ty.as_adt() {
87 Some((Adt::Enum(e), _)) => Some(e.source(db).ast), 87 Some((Adt::Enum(e), _)) => Some(e.source(db).value),
88 _ => None, 88 _ => None,
89 }) 89 })
90} 90}
diff --git a/crates/ra_assists/src/assists/replace_if_let_with_match.rs b/crates/ra_assists/src/assists/replace_if_let_with_match.rs
index dff84d865..3272801ff 100644
--- a/crates/ra_assists/src/assists/replace_if_let_with_match.rs
+++ b/crates/ra_assists/src/assists/replace_if_let_with_match.rs
@@ -66,8 +66,8 @@ fn build_match_expr(
66 66
67fn format_arm(block: &ast::BlockExpr) -> String { 67fn format_arm(block: &ast::BlockExpr) -> String {
68 match extract_trivial_expression(block) { 68 match extract_trivial_expression(block) {
69 None => block.syntax().text().to_string(), 69 Some(e) if !e.syntax().text().contains_char('\n') => format!("{},", e.syntax().text()),
70 Some(e) => format!("{},", e.syntax().text()), 70 _ => block.syntax().text().to_string(),
71 } 71 }
72} 72}
73 73
@@ -103,6 +103,34 @@ impl VariantData {
103 } 103 }
104 104
105 #[test] 105 #[test]
106 fn test_replace_if_let_with_match_doesnt_unwrap_multiline_expressions() {
107 check_assist(
108 replace_if_let_with_match,
109 "
110fn foo() {
111 if <|>let VariantData::Struct(..) = a {
112 bar(
113 123
114 )
115 } else {
116 false
117 }
118} ",
119 "
120fn foo() {
121 <|>match a {
122 VariantData::Struct(..) => {
123 bar(
124 123
125 )
126 }
127 _ => false,
128 }
129} ",
130 )
131 }
132
133 #[test]
106 fn replace_if_let_with_match_target() { 134 fn replace_if_let_with_match_target() {
107 check_assist_target( 135 check_assist_target(
108 replace_if_let_with_match, 136 replace_if_let_with_match,
diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs
index 3429a3c49..9cd21e4b6 100644
--- a/crates/ra_cli/src/analysis_stats.rs
+++ b/crates/ra_cli/src/analysis_stats.rs
@@ -98,7 +98,7 @@ pub fn run(
98 let src = f.source(db); 98 let src = f.source(db);
99 let original_file = src.file_id.original_file(db); 99 let original_file = src.file_id.original_file(db);
100 let path = db.file_relative_path(original_file); 100 let path = db.file_relative_path(original_file);
101 let syntax_range = src.ast.syntax().text_range(); 101 let syntax_range = src.value.syntax().text_range();
102 write!(msg, " ({:?} {})", path, syntax_range).unwrap(); 102 write!(msg, " ({:?} {})", path, syntax_range).unwrap();
103 } 103 }
104 bar.set_message(&msg); 104 bar.set_message(&msg);
@@ -135,7 +135,7 @@ pub fn run(
135 let path = db.file_relative_path(original_file); 135 let path = db.file_relative_path(original_file);
136 let line_index = host.analysis().file_line_index(original_file).unwrap(); 136 let line_index = host.analysis().file_line_index(original_file).unwrap();
137 let text_range = src 137 let text_range = src
138 .ast 138 .value
139 .either(|it| it.syntax().text_range(), |it| it.syntax().text_range()); 139 .either(|it| it.syntax().text_range(), |it| it.syntax().text_range());
140 let (start, end) = ( 140 let (start, end) = (
141 line_index.line_col(text_range.start()), 141 line_index.line_col(text_range.start()),
diff --git a/crates/ra_fmt/src/lib.rs b/crates/ra_fmt/src/lib.rs
index a30ed4cbb..10f592257 100644
--- a/crates/ra_fmt/src/lib.rs
+++ b/crates/ra_fmt/src/lib.rs
@@ -38,9 +38,6 @@ fn prev_tokens(token: SyntaxToken) -> impl Iterator<Item = SyntaxToken> {
38pub fn extract_trivial_expression(expr: &ast::BlockExpr) -> Option<ast::Expr> { 38pub fn extract_trivial_expression(expr: &ast::BlockExpr) -> Option<ast::Expr> {
39 let block = expr.block()?; 39 let block = expr.block()?;
40 let expr = block.expr()?; 40 let expr = block.expr()?;
41 if expr.syntax().text().contains_char('\n') {
42 return None;
43 }
44 let non_trivial_children = block.syntax().children().filter(|it| match it.kind() { 41 let non_trivial_children = block.syntax().children().filter(|it| match it.kind() {
45 WHITESPACE | T!['{'] | T!['}'] => false, 42 WHITESPACE | T!['{'] | T!['}'] => false,
46 _ => it != expr.syntax(), 43 _ => it != expr.syntax(),
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
deleted file mode 100644
index 945f236c2..000000000
--- a/crates/ra_hir/src/adt.rs
+++ /dev/null
@@ -1,54 +0,0 @@
1//! This module contains the implementation details of the HIR for ADTs, i.e.
2//! structs and enums (and unions).
3
4use std::sync::Arc;
5
6use hir_def::adt::VariantData;
7
8use crate::{
9 db::{DefDatabase, HirDatabase},
10 EnumVariant, Module, Name, Struct, StructField,
11};
12
13impl Struct {
14 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
15 db.struct_data(self.id.into()).variant_data.clone()
16 }
17}
18
19#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
20pub enum VariantDef {
21 Struct(Struct),
22 EnumVariant(EnumVariant),
23}
24impl_froms!(VariantDef: Struct, EnumVariant);
25
26impl VariantDef {
27 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
28 match self {
29 VariantDef::Struct(it) => it.fields(db),
30 VariantDef::EnumVariant(it) => it.fields(db),
31 }
32 }
33
34 pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> {
35 match self {
36 VariantDef::Struct(it) => it.field(db, name),
37 VariantDef::EnumVariant(it) => it.field(db, name),
38 }
39 }
40
41 pub fn module(self, db: &impl HirDatabase) -> Module {
42 match self {
43 VariantDef::Struct(it) => it.module(db),
44 VariantDef::EnumVariant(it) => it.module(db),
45 }
46 }
47
48 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
49 match self {
50 VariantDef::Struct(it) => it.variant_data(db),
51 VariantDef::EnumVariant(it) => it.variant_data(db),
52 }
53 }
54}
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 731cc1fff..a132d128b 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -10,8 +10,10 @@ use hir_def::{
10 adt::VariantData, 10 adt::VariantData,
11 body::scope::ExprScopes, 11 body::scope::ExprScopes,
12 builtin_type::BuiltinType, 12 builtin_type::BuiltinType,
13 traits::TraitData,
13 type_ref::{Mutability, TypeRef}, 14 type_ref::{Mutability, TypeRef},
14 CrateModuleId, ImplId, LocalEnumVariantId, LocalStructFieldId, ModuleId, UnionId, 15 AssocItemId, ContainerId, CrateModuleId, HasModule, ImplId, LocalEnumVariantId,
16 LocalStructFieldId, Lookup, ModuleId, UnionId,
15}; 17};
16use hir_expand::{ 18use hir_expand::{
17 diagnostics::DiagnosticSink, 19 diagnostics::DiagnosticSink,
@@ -21,7 +23,6 @@ use ra_db::{CrateId, Edition};
21use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; 23use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner};
22 24
23use crate::{ 25use crate::{
24 adt::VariantDef,
25 db::{AstDatabase, DefDatabase, HirDatabase}, 26 db::{AstDatabase, DefDatabase, HirDatabase},
26 expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId}, 27 expr::{BindingAnnotation, Body, BodySourceMap, ExprValidator, Pat, PatId},
27 generics::{GenericDef, HasGenericParams}, 28 generics::{GenericDef, HasGenericParams},
@@ -29,8 +30,7 @@ use crate::{
29 AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId, 30 AstItemDef, ConstId, EnumId, FunctionId, MacroDefId, StaticId, StructId, TraitId,
30 TypeAliasId, 31 TypeAliasId,
31 }, 32 },
32 resolve::{Resolver, Scope, TypeNs}, 33 resolve::{HasResolver, TypeNs},
33 traits::TraitData,
34 ty::{InferenceResult, Namespace, TraitRef}, 34 ty::{InferenceResult, Namespace, TraitRef},
35 Either, HasSource, ImportId, Name, ScopeDef, Source, Ty, 35 Either, HasSource, ImportId, Name, ScopeDef, Source, Ty,
36}; 36};
@@ -139,7 +139,7 @@ impl Module {
139 ) -> Either<ast::UseTree, ast::ExternCrateItem> { 139 ) -> Either<ast::UseTree, ast::ExternCrateItem> {
140 let src = self.definition_source(db); 140 let src = self.definition_source(db);
141 let (_, source_map) = db.raw_items_with_source_map(src.file_id); 141 let (_, source_map) = db.raw_items_with_source_map(src.file_id);
142 source_map.get(&src.ast, import) 142 source_map.get(&src.value, import)
143 } 143 }
144 144
145 /// Returns the crate this module is part of. 145 /// Returns the crate this module is part of.
@@ -206,7 +206,7 @@ impl Module {
206 crate::ModuleDef::Function(f) => f.diagnostics(db, sink), 206 crate::ModuleDef::Function(f) => f.diagnostics(db, sink),
207 crate::ModuleDef::Module(m) => { 207 crate::ModuleDef::Module(m) => {
208 // Only add diagnostics from inline modules 208 // Only add diagnostics from inline modules
209 if let ModuleSource::Module(_) = m.definition_source(db).ast { 209 if let ModuleSource::Module(_) = m.definition_source(db).value {
210 m.diagnostics(db, sink) 210 m.diagnostics(db, sink)
211 } 211 }
212 } 212 }
@@ -223,22 +223,9 @@ impl Module {
223 } 223 }
224 } 224 }
225 225
226 pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver {
227 let def_map = db.crate_def_map(self.id.krate);
228 Resolver::default().push_module_scope(def_map, self.id.module_id)
229 }
230
231 pub fn declarations(self, db: &impl DefDatabase) -> Vec<ModuleDef> { 226 pub fn declarations(self, db: &impl DefDatabase) -> Vec<ModuleDef> {
232 let def_map = db.crate_def_map(self.id.krate); 227 let def_map = db.crate_def_map(self.id.krate);
233 def_map[self.id.module_id] 228 def_map[self.id.module_id].scope.declarations().map(ModuleDef::from).collect()
234 .scope
235 .entries()
236 .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None })
237 .flat_map(|per_ns| {
238 per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter())
239 })
240 .map(ModuleDef::from)
241 .collect()
242 } 229 }
243 230
244 pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec<ImplBlock> { 231 pub fn impl_blocks(self, db: &impl DefDatabase) -> Vec<ImplBlock> {
@@ -323,15 +310,8 @@ impl Struct {
323 db.type_for_def(self.into(), Namespace::Values) 310 db.type_for_def(self.into(), Namespace::Values)
324 } 311 }
325 312
326 // FIXME move to a more general type 313 fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
327 /// Builds a resolver for type references inside this struct. 314 db.struct_data(self.id.into()).variant_data.clone()
328 pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
329 // take the outer scope...
330 let r = self.module(db).resolver(db);
331 // ...and add generic params, if present
332 let p = self.generic_params(db);
333 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
334 r
335 } 315 }
336} 316}
337 317
@@ -345,24 +325,13 @@ impl Union {
345 db.struct_data(self.id.into()).name.clone() 325 db.struct_data(self.id.into()).name.clone()
346 } 326 }
347 327
348 pub fn module(self, db: &impl HirDatabase) -> Module { 328 pub fn module(self, db: &impl DefDatabase) -> Module {
349 Module { id: self.id.0.module(db) } 329 Module { id: self.id.0.module(db) }
350 } 330 }
351 331
352 pub fn ty(self, db: &impl HirDatabase) -> Ty { 332 pub fn ty(self, db: &impl HirDatabase) -> Ty {
353 db.type_for_def(self.into(), Namespace::Types) 333 db.type_for_def(self.into(), Namespace::Types)
354 } 334 }
355
356 // FIXME move to a more general type
357 /// Builds a resolver for type references inside this union.
358 pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
359 // take the outer scope...
360 let r = self.module(db).resolver(db);
361 // ...and add generic params, if present
362 let p = self.generic_params(db);
363 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
364 r
365 }
366} 335}
367 336
368#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 337#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -402,17 +371,6 @@ impl Enum {
402 pub fn ty(self, db: &impl HirDatabase) -> Ty { 371 pub fn ty(self, db: &impl HirDatabase) -> Ty {
403 db.type_for_def(self.into(), Namespace::Types) 372 db.type_for_def(self.into(), Namespace::Types)
404 } 373 }
405
406 // FIXME: move to a more general type
407 /// Builds a resolver for type references inside this struct.
408 pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
409 // take the outer scope...
410 let r = self.module(db).resolver(db);
411 // ...and add generic params, if present
412 let p = self.generic_params(db);
413 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
414 r.push_scope(Scope::AdtScope(self.into()))
415 }
416} 374}
417 375
418#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 376#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -474,22 +432,52 @@ impl Adt {
474 } 432 }
475 } 433 }
476 434
435 pub fn module(self, db: &impl DefDatabase) -> Module {
436 match self {
437 Adt::Struct(s) => s.module(db),
438 Adt::Union(s) => s.module(db),
439 Adt::Enum(e) => e.module(db),
440 }
441 }
442
477 pub fn krate(self, db: &impl HirDatabase) -> Option<Crate> { 443 pub fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
478 Some( 444 Some(self.module(db).krate())
479 match self { 445 }
480 Adt::Struct(s) => s.module(db), 446}
481 Adt::Union(s) => s.module(db), 447
482 Adt::Enum(e) => e.module(db), 448#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
483 } 449pub enum VariantDef {
484 .krate(), 450 Struct(Struct),
485 ) 451 EnumVariant(EnumVariant),
452}
453impl_froms!(VariantDef: Struct, EnumVariant);
454
455impl VariantDef {
456 pub fn fields(self, db: &impl HirDatabase) -> Vec<StructField> {
457 match self {
458 VariantDef::Struct(it) => it.fields(db),
459 VariantDef::EnumVariant(it) => it.fields(db),
460 }
461 }
462
463 pub fn field(self, db: &impl HirDatabase, name: &Name) -> Option<StructField> {
464 match self {
465 VariantDef::Struct(it) => it.field(db, name),
466 VariantDef::EnumVariant(it) => it.field(db, name),
467 }
468 }
469
470 pub fn module(self, db: &impl HirDatabase) -> Module {
471 match self {
472 VariantDef::Struct(it) => it.module(db),
473 VariantDef::EnumVariant(it) => it.module(db),
474 }
486 } 475 }
487 476
488 pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver { 477 pub(crate) fn variant_data(self, db: &impl DefDatabase) -> Arc<VariantData> {
489 match self { 478 match self {
490 Adt::Struct(it) => it.resolver(db), 479 VariantDef::Struct(it) => it.variant_data(db),
491 Adt::Union(it) => it.resolver(db), 480 VariantDef::EnumVariant(it) => it.variant_data(db),
492 Adt::Enum(it) => it.resolver(db),
493 } 481 }
494 } 482 }
495} 483}
@@ -505,15 +493,6 @@ pub enum DefWithBody {
505impl_froms!(DefWithBody: Function, Const, Static); 493impl_froms!(DefWithBody: Function, Const, Static);
506 494
507impl DefWithBody { 495impl DefWithBody {
508 /// Builds a resolver for code inside this item.
509 pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
510 match self {
511 DefWithBody::Const(c) => c.resolver(db),
512 DefWithBody::Function(f) => f.resolver(db),
513 DefWithBody::Static(s) => s.resolver(db),
514 }
515 }
516
517 pub(crate) fn krate(self, db: &impl HirDatabase) -> Option<Crate> { 496 pub(crate) fn krate(self, db: &impl HirDatabase) -> Option<Crate> {
518 match self { 497 match self {
519 DefWithBody::Const(c) => c.krate(db), 498 DefWithBody::Const(c) => c.krate(db),
@@ -598,10 +577,10 @@ impl FnData {
598 func: Function, 577 func: Function,
599 ) -> Arc<FnData> { 578 ) -> Arc<FnData> {
600 let src = func.source(db); 579 let src = func.source(db);
601 let name = src.ast.name().map(|n| n.as_name()).unwrap_or_else(Name::missing); 580 let name = src.value.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
602 let mut params = Vec::new(); 581 let mut params = Vec::new();
603 let mut has_self_param = false; 582 let mut has_self_param = false;
604 if let Some(param_list) = src.ast.param_list() { 583 if let Some(param_list) = src.value.param_list() {
605 if let Some(self_param) = param_list.self_param() { 584 if let Some(self_param) = param_list.self_param() {
606 let self_type = if let Some(type_ref) = self_param.ascribed_type() { 585 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
607 TypeRef::from_ast(type_ref) 586 TypeRef::from_ast(type_ref)
@@ -625,7 +604,7 @@ impl FnData {
625 params.push(type_ref); 604 params.push(type_ref);
626 } 605 }
627 } 606 }
628 let ret_type = if let Some(type_ref) = src.ast.ret_type().and_then(|rt| rt.type_ref()) { 607 let ret_type = if let Some(type_ref) = src.value.ret_type().and_then(|rt| rt.type_ref()) {
629 TypeRef::from_ast(type_ref) 608 TypeRef::from_ast(type_ref)
630 } else { 609 } else {
631 TypeRef::unit() 610 TypeRef::unit()
@@ -655,7 +634,7 @@ impl FnData {
655 634
656impl Function { 635impl Function {
657 pub fn module(self, db: &impl DefDatabase) -> Module { 636 pub fn module(self, db: &impl DefDatabase) -> Module {
658 Module { id: self.id.module(db) } 637 self.id.lookup(db).module(db).into()
659 } 638 }
660 639
661 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { 640 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
@@ -688,35 +667,28 @@ impl Function {
688 667
689 /// The containing impl block, if this is a method. 668 /// The containing impl block, if this is a method.
690 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { 669 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
691 ImplBlock::containing(db, self.into()) 670 match self.container(db) {
671 Some(Container::ImplBlock(it)) => Some(it),
672 _ => None,
673 }
692 } 674 }
693 675
694 /// The containing trait, if this is a trait method definition. 676 /// The containing trait, if this is a trait method definition.
695 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> { 677 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> {
696 db.trait_items_index(self.module(db)).get_parent_trait(self.into()) 678 match self.container(db) {
679 Some(Container::Trait(it)) => Some(it),
680 _ => None,
681 }
697 } 682 }
698 683
699 pub fn container(self, db: &impl DefDatabase) -> Option<Container> { 684 pub fn container(self, db: &impl DefDatabase) -> Option<Container> {
700 if let Some(impl_block) = self.impl_block(db) { 685 match self.id.lookup(db).container {
701 Some(impl_block.into()) 686 ContainerId::TraitId(it) => Some(Container::Trait(it.into())),
702 } else if let Some(trait_) = self.parent_trait(db) { 687 ContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())),
703 Some(trait_.into()) 688 ContainerId::ModuleId(_) => None,
704 } else {
705 None
706 } 689 }
707 } 690 }
708 691
709 // FIXME: move to a more general type for 'body-having' items
710 /// Builds a resolver for code inside this item.
711 pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
712 // take the outer scope...
713 let r = self.container(db).map_or_else(|| self.module(db).resolver(db), |c| c.resolver(db));
714 // ...and add generic params, if present
715 let p = self.generic_params(db);
716 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
717 r
718 }
719
720 pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) { 692 pub fn diagnostics(self, db: &impl HirDatabase, sink: &mut DiagnosticSink) {
721 let infer = self.infer(db); 693 let infer = self.infer(db);
722 infer.add_diagnostics(db, self, sink); 694 infer.add_diagnostics(db, self, sink);
@@ -732,7 +704,7 @@ pub struct Const {
732 704
733impl Const { 705impl Const {
734 pub fn module(self, db: &impl DefDatabase) -> Module { 706 pub fn module(self, db: &impl DefDatabase) -> Module {
735 Module { id: self.id.module(db) } 707 Module { id: self.id.lookup(db).module(db) }
736 } 708 }
737 709
738 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { 710 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
@@ -751,35 +723,29 @@ impl Const {
751 db.infer(self.into()) 723 db.infer(self.into())
752 } 724 }
753 725
754 /// The containing impl block, if this is a method. 726 /// The containing impl block, if this is a type alias.
755 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { 727 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
756 ImplBlock::containing(db, self.into()) 728 match self.container(db) {
729 Some(Container::ImplBlock(it)) => Some(it),
730 _ => None,
731 }
757 } 732 }
758 733
734 /// The containing trait, if this is a trait type alias definition.
759 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> { 735 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> {
760 db.trait_items_index(self.module(db)).get_parent_trait(self.into()) 736 match self.container(db) {
737 Some(Container::Trait(it)) => Some(it),
738 _ => None,
739 }
761 } 740 }
762 741
763 pub fn container(self, db: &impl DefDatabase) -> Option<Container> { 742 pub fn container(self, db: &impl DefDatabase) -> Option<Container> {
764 if let Some(impl_block) = self.impl_block(db) { 743 match self.id.lookup(db).container {
765 Some(impl_block.into()) 744 ContainerId::TraitId(it) => Some(Container::Trait(it.into())),
766 } else if let Some(trait_) = self.parent_trait(db) { 745 ContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())),
767 Some(trait_.into()) 746 ContainerId::ModuleId(_) => None,
768 } else {
769 None
770 } 747 }
771 } 748 }
772
773 // FIXME: move to a more general type for 'body-having' items
774 /// Builds a resolver for code inside this item.
775 pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
776 // take the outer scope...
777 let r = self
778 .impl_block(db)
779 .map(|ib| ib.resolver(db))
780 .unwrap_or_else(|| self.module(db).resolver(db));
781 r
782 }
783} 749}
784 750
785#[derive(Debug, Clone, PartialEq, Eq)] 751#[derive(Debug, Clone, PartialEq, Eq)]
@@ -801,7 +767,7 @@ impl ConstData {
801 db: &(impl DefDatabase + AstDatabase), 767 db: &(impl DefDatabase + AstDatabase),
802 konst: Const, 768 konst: Const,
803 ) -> Arc<ConstData> { 769 ) -> Arc<ConstData> {
804 let node = konst.source(db).ast; 770 let node = konst.source(db).value;
805 const_data_for(&node) 771 const_data_for(&node)
806 } 772 }
807 773
@@ -809,7 +775,7 @@ impl ConstData {
809 db: &(impl DefDatabase + AstDatabase), 775 db: &(impl DefDatabase + AstDatabase),
810 konst: Static, 776 konst: Static,
811 ) -> Arc<ConstData> { 777 ) -> Arc<ConstData> {
812 let node = konst.source(db).ast; 778 let node = konst.source(db).value;
813 const_data_for(&node) 779 const_data_for(&node)
814 } 780 }
815} 781}
@@ -839,12 +805,6 @@ impl Static {
839 db.static_data(self) 805 db.static_data(self)
840 } 806 }
841 807
842 /// Builds a resolver for code inside this item.
843 pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
844 // take the outer scope...
845 self.module(db).resolver(db)
846 }
847
848 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> { 808 pub fn infer(self, db: &impl HirDatabase) -> Arc<InferenceResult> {
849 db.infer(self.into()) 809 db.infer(self.into())
850 } 810 }
@@ -861,11 +821,11 @@ impl Trait {
861 } 821 }
862 822
863 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 823 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
864 self.trait_data(db).name().clone() 824 self.trait_data(db).name.clone()
865 } 825 }
866 826
867 pub fn items(self, db: &impl DefDatabase) -> Vec<AssocItem> { 827 pub fn items(self, db: &impl DefDatabase) -> Vec<AssocItem> {
868 self.trait_data(db).items().to_vec() 828 self.trait_data(db).items.iter().map(|it| (*it).into()).collect()
869 } 829 }
870 830
871 fn direct_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> { 831 fn direct_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> {
@@ -912,10 +872,10 @@ impl Trait {
912 pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> { 872 pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> {
913 let trait_data = self.trait_data(db); 873 let trait_data = self.trait_data(db);
914 trait_data 874 trait_data
915 .items() 875 .items
916 .iter() 876 .iter()
917 .filter_map(|item| match item { 877 .filter_map(|item| match item {
918 AssocItem::TypeAlias(t) => Some(*t), 878 AssocItemId::TypeAliasId(t) => Some(TypeAlias::from(*t)),
919 _ => None, 879 _ => None,
920 }) 880 })
921 .find(|t| &t.name(db) == name) 881 .find(|t| &t.name(db) == name)
@@ -930,7 +890,7 @@ impl Trait {
930 } 890 }
931 891
932 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> { 892 pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> {
933 db.trait_data(self) 893 db.trait_data(self.id)
934 } 894 }
935 895
936 pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef { 896 pub fn trait_ref(self, db: &impl HirDatabase) -> TraitRef {
@@ -938,15 +898,7 @@ impl Trait {
938 } 898 }
939 899
940 pub fn is_auto(self, db: &impl DefDatabase) -> bool { 900 pub fn is_auto(self, db: &impl DefDatabase) -> bool {
941 self.trait_data(db).is_auto() 901 self.trait_data(db).auto
942 }
943
944 pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver {
945 let r = self.module(db).resolver(db);
946 // add generic params, if present
947 let p = self.generic_params(db);
948 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
949 r
950 } 902 }
951} 903}
952 904
@@ -957,30 +909,34 @@ pub struct TypeAlias {
957 909
958impl TypeAlias { 910impl TypeAlias {
959 pub fn module(self, db: &impl DefDatabase) -> Module { 911 pub fn module(self, db: &impl DefDatabase) -> Module {
960 Module { id: self.id.module(db) } 912 Module { id: self.id.lookup(db).module(db) }
961 } 913 }
962 914
963 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> { 915 pub fn krate(self, db: &impl DefDatabase) -> Option<Crate> {
964 Some(self.module(db).krate()) 916 Some(self.module(db).krate())
965 } 917 }
966 918
967 /// The containing impl block, if this is a method. 919 /// The containing impl block, if this is a type alias.
968 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> { 920 pub fn impl_block(self, db: &impl DefDatabase) -> Option<ImplBlock> {
969 ImplBlock::containing(db, self.into()) 921 match self.container(db) {
922 Some(Container::ImplBlock(it)) => Some(it),
923 _ => None,
924 }
970 } 925 }
971 926
972 /// The containing trait, if this is a trait method definition. 927 /// The containing trait, if this is a trait type alias definition.
973 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> { 928 pub fn parent_trait(self, db: &impl DefDatabase) -> Option<Trait> {
974 db.trait_items_index(self.module(db)).get_parent_trait(self.into()) 929 match self.container(db) {
930 Some(Container::Trait(it)) => Some(it),
931 _ => None,
932 }
975 } 933 }
976 934
977 pub fn container(self, db: &impl DefDatabase) -> Option<Container> { 935 pub fn container(self, db: &impl DefDatabase) -> Option<Container> {
978 if let Some(impl_block) = self.impl_block(db) { 936 match self.id.lookup(db).container {
979 Some(impl_block.into()) 937 ContainerId::TraitId(it) => Some(Container::Trait(it.into())),
980 } else if let Some(trait_) = self.parent_trait(db) { 938 ContainerId::ImplId(it) => Some(Container::ImplBlock(it.into())),
981 Some(trait_.into()) 939 ContainerId::ModuleId(_) => None,
982 } else {
983 None
984 } 940 }
985 } 941 }
986 942
@@ -995,19 +951,6 @@ impl TypeAlias {
995 pub fn name(self, db: &impl DefDatabase) -> Name { 951 pub fn name(self, db: &impl DefDatabase) -> Name {
996 db.type_alias_data(self).name.clone() 952 db.type_alias_data(self).name.clone()
997 } 953 }
998
999 /// Builds a resolver for the type references in this type alias.
1000 pub(crate) fn resolver(self, db: &impl HirDatabase) -> Resolver {
1001 // take the outer scope...
1002 let r = self
1003 .impl_block(db)
1004 .map(|ib| ib.resolver(db))
1005 .unwrap_or_else(|| self.module(db).resolver(db));
1006 // ...and add generic params, if present
1007 let p = self.generic_params(db);
1008 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
1009 r
1010 }
1011} 954}
1012 955
1013#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 956#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -1023,15 +966,6 @@ pub enum Container {
1023} 966}
1024impl_froms!(Container: Trait, ImplBlock); 967impl_froms!(Container: Trait, ImplBlock);
1025 968
1026impl Container {
1027 pub(crate) fn resolver(self, db: &impl DefDatabase) -> Resolver {
1028 match self {
1029 Container::Trait(trait_) => trait_.resolver(db),
1030 Container::ImplBlock(impl_block) => impl_block.resolver(db),
1031 }
1032 }
1033}
1034
1035#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 969#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1036pub enum AssocItem { 970pub enum AssocItem {
1037 Function(Function), 971 Function(Function),
diff --git a/crates/ra_hir/src/code_model/attrs.rs b/crates/ra_hir/src/code_model/attrs.rs
index f7db36b66..9e304217c 100644
--- a/crates/ra_hir/src/code_model/attrs.rs
+++ b/crates/ra_hir/src/code_model/attrs.rs
@@ -49,9 +49,9 @@ pub(crate) fn attributes_query(
49 AttrDef::Module(it) => { 49 AttrDef::Module(it) => {
50 let src = it.declaration_source(db)?; 50 let src = it.declaration_source(db)?;
51 let hygiene = Hygiene::new(db, src.file_id); 51 let hygiene = Hygiene::new(db, src.file_id);
52 Attr::from_attrs_owner(&src.ast, &hygiene) 52 Attr::from_attrs_owner(&src.value, &hygiene)
53 } 53 }
54 AttrDef::StructField(it) => match it.source(db).ast { 54 AttrDef::StructField(it) => match it.source(db).value {
55 FieldSource::Named(named) => { 55 FieldSource::Named(named) => {
56 let src = it.source(db); 56 let src = it.source(db);
57 let hygiene = Hygiene::new(db, src.file_id); 57 let hygiene = Hygiene::new(db, src.file_id);
@@ -82,7 +82,7 @@ where
82{ 82{
83 let src = node.source(db); 83 let src = node.source(db);
84 let hygiene = Hygiene::new(db, src.file_id); 84 let hygiene = Hygiene::new(db, src.file_id);
85 Attr::from_attrs_owner(&src.ast, &hygiene) 85 Attr::from_attrs_owner(&src.value, &hygiene)
86} 86}
87 87
88impl<T: Into<AttrDef> + Copy> Attrs for T { 88impl<T: Into<AttrDef> + Copy> Attrs for T {
diff --git a/crates/ra_hir/src/code_model/docs.rs b/crates/ra_hir/src/code_model/docs.rs
index 8533b4f5e..e40efef34 100644
--- a/crates/ra_hir/src/code_model/docs.rs
+++ b/crates/ra_hir/src/code_model/docs.rs
@@ -70,23 +70,23 @@ pub(crate) fn documentation_query(
70 def: DocDef, 70 def: DocDef,
71) -> Option<Documentation> { 71) -> Option<Documentation> {
72 match def { 72 match def {
73 DocDef::Module(it) => docs_from_ast(&it.declaration_source(db)?.ast), 73 DocDef::Module(it) => docs_from_ast(&it.declaration_source(db)?.value),
74 DocDef::StructField(it) => match it.source(db).ast { 74 DocDef::StructField(it) => match it.source(db).value {
75 FieldSource::Named(named) => docs_from_ast(&named), 75 FieldSource::Named(named) => docs_from_ast(&named),
76 FieldSource::Pos(..) => None, 76 FieldSource::Pos(..) => None,
77 }, 77 },
78 DocDef::Adt(it) => match it { 78 DocDef::Adt(it) => match it {
79 Adt::Struct(it) => docs_from_ast(&it.source(db).ast), 79 Adt::Struct(it) => docs_from_ast(&it.source(db).value),
80 Adt::Enum(it) => docs_from_ast(&it.source(db).ast), 80 Adt::Enum(it) => docs_from_ast(&it.source(db).value),
81 Adt::Union(it) => docs_from_ast(&it.source(db).ast), 81 Adt::Union(it) => docs_from_ast(&it.source(db).value),
82 }, 82 },
83 DocDef::EnumVariant(it) => docs_from_ast(&it.source(db).ast), 83 DocDef::EnumVariant(it) => docs_from_ast(&it.source(db).value),
84 DocDef::Static(it) => docs_from_ast(&it.source(db).ast), 84 DocDef::Static(it) => docs_from_ast(&it.source(db).value),
85 DocDef::Const(it) => docs_from_ast(&it.source(db).ast), 85 DocDef::Const(it) => docs_from_ast(&it.source(db).value),
86 DocDef::Function(it) => docs_from_ast(&it.source(db).ast), 86 DocDef::Function(it) => docs_from_ast(&it.source(db).value),
87 DocDef::Trait(it) => docs_from_ast(&it.source(db).ast), 87 DocDef::Trait(it) => docs_from_ast(&it.source(db).value),
88 DocDef::TypeAlias(it) => docs_from_ast(&it.source(db).ast), 88 DocDef::TypeAlias(it) => docs_from_ast(&it.source(db).value),
89 DocDef::MacroDef(it) => docs_from_ast(&it.source(db).ast), 89 DocDef::MacroDef(it) => docs_from_ast(&it.source(db).value),
90 } 90 }
91} 91}
92 92
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
index 247ae3e55..4aa427de4 100644
--- a/crates/ra_hir/src/code_model/src.rs
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -1,13 +1,13 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use hir_def::{HasSource as _, Lookup};
3use ra_syntax::ast::{self, AstNode}; 4use ra_syntax::ast::{self, AstNode};
4 5
5use crate::{ 6use crate::{
6 adt::VariantDef,
7 db::{AstDatabase, DefDatabase, HirDatabase}, 7 db::{AstDatabase, DefDatabase, HirDatabase},
8 ids::AstItemDef, 8 ids::AstItemDef,
9 Const, Either, Enum, EnumVariant, FieldSource, Function, HasBody, HirFileId, MacroDef, Module, 9 Const, Either, Enum, EnumVariant, FieldSource, Function, HasBody, HirFileId, MacroDef, Module,
10 ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, 10 ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, VariantDef,
11}; 11};
12 12
13pub use hir_expand::Source; 13pub use hir_expand::Source;
@@ -25,9 +25,9 @@ impl Module {
25 let def_map = db.crate_def_map(self.id.krate); 25 let def_map = db.crate_def_map(self.id.krate);
26 let decl_id = def_map[self.id.module_id].declaration; 26 let decl_id = def_map[self.id.module_id].declaration;
27 let file_id = def_map[self.id.module_id].definition; 27 let file_id = def_map[self.id.module_id].definition;
28 let ast = ModuleSource::new(db, file_id, decl_id); 28 let value = ModuleSource::new(db, file_id, decl_id);
29 let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id()); 29 let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id());
30 Source { file_id, ast } 30 Source { file_id, value }
31 } 31 }
32 32
33 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. 33 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
@@ -38,8 +38,8 @@ impl Module {
38 ) -> Option<Source<ast::Module>> { 38 ) -> Option<Source<ast::Module>> {
39 let def_map = db.crate_def_map(self.id.krate); 39 let def_map = db.crate_def_map(self.id.krate);
40 let decl = def_map[self.id.module_id].declaration?; 40 let decl = def_map[self.id.module_id].declaration?;
41 let ast = decl.to_node(db); 41 let value = decl.to_node(db);
42 Some(Source { file_id: decl.file_id(), ast }) 42 Some(Source { file_id: decl.file_id(), value })
43 } 43 }
44} 44}
45 45
@@ -53,11 +53,11 @@ impl HasSource for StructField {
53 let (file_id, struct_kind) = match self.parent { 53 let (file_id, struct_kind) = match self.parent {
54 VariantDef::Struct(s) => { 54 VariantDef::Struct(s) => {
55 ss = s.source(db); 55 ss = s.source(db);
56 (ss.file_id, ss.ast.kind()) 56 (ss.file_id, ss.value.kind())
57 } 57 }
58 VariantDef::EnumVariant(e) => { 58 VariantDef::EnumVariant(e) => {
59 es = e.source(db); 59 es = e.source(db);
60 (es.file_id, es.ast.kind()) 60 (es.file_id, es.value.kind())
61 } 61 }
62 }; 62 };
63 63
@@ -66,13 +66,13 @@ impl HasSource for StructField {
66 ast::StructKind::Named(fl) => fl.fields().map(|it| FieldSource::Named(it)).collect(), 66 ast::StructKind::Named(fl) => fl.fields().map(|it| FieldSource::Named(it)).collect(),
67 ast::StructKind::Unit => Vec::new(), 67 ast::StructKind::Unit => Vec::new(),
68 }; 68 };
69 let ast = field_sources 69 let value = field_sources
70 .into_iter() 70 .into_iter()
71 .zip(fields.iter()) 71 .zip(fields.iter())
72 .find(|(_syntax, (id, _))| *id == self.id) 72 .find(|(_syntax, (id, _))| *id == self.id)
73 .unwrap() 73 .unwrap()
74 .0; 74 .0;
75 Source { file_id, ast } 75 Source { file_id, value }
76 } 76 }
77} 77}
78impl HasSource for Struct { 78impl HasSource for Struct {
@@ -98,8 +98,8 @@ impl HasSource for EnumVariant {
98 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::EnumVariant> { 98 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::EnumVariant> {
99 let enum_data = db.enum_data(self.parent.id); 99 let enum_data = db.enum_data(self.parent.id);
100 let src = self.parent.id.source(db); 100 let src = self.parent.id.source(db);
101 let ast = src 101 let value = src
102 .ast 102 .value
103 .variant_list() 103 .variant_list()
104 .into_iter() 104 .into_iter()
105 .flat_map(|it| it.variants()) 105 .flat_map(|it| it.variants())
@@ -107,19 +107,19 @@ impl HasSource for EnumVariant {
107 .find(|(_syntax, (id, _))| *id == self.id) 107 .find(|(_syntax, (id, _))| *id == self.id)
108 .unwrap() 108 .unwrap()
109 .0; 109 .0;
110 Source { file_id: src.file_id, ast } 110 Source { file_id: src.file_id, value }
111 } 111 }
112} 112}
113impl HasSource for Function { 113impl HasSource for Function {
114 type Ast = ast::FnDef; 114 type Ast = ast::FnDef;
115 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::FnDef> { 115 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::FnDef> {
116 self.id.source(db) 116 self.id.lookup(db).source(db)
117 } 117 }
118} 118}
119impl HasSource for Const { 119impl HasSource for Const {
120 type Ast = ast::ConstDef; 120 type Ast = ast::ConstDef;
121 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::ConstDef> { 121 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::ConstDef> {
122 self.id.source(db) 122 self.id.lookup(db).source(db)
123 } 123 }
124} 124}
125impl HasSource for Static { 125impl HasSource for Static {
@@ -137,13 +137,13 @@ impl HasSource for Trait {
137impl HasSource for TypeAlias { 137impl HasSource for TypeAlias {
138 type Ast = ast::TypeAliasDef; 138 type Ast = ast::TypeAliasDef;
139 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::TypeAliasDef> { 139 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::TypeAliasDef> {
140 self.id.source(db) 140 self.id.lookup(db).source(db)
141 } 141 }
142} 142}
143impl HasSource for MacroDef { 143impl HasSource for MacroDef {
144 type Ast = ast::MacroCall; 144 type Ast = ast::MacroCall;
145 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::MacroCall> { 145 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ast::MacroCall> {
146 Source { file_id: self.id.ast_id.file_id(), ast: self.id.ast_id.to_node(db) } 146 Source { file_id: self.id.ast_id.file_id(), value: self.id.ast_id.to_node(db) }
147 } 147 }
148} 148}
149 149
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index d75d71d66..a9982a70f 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -8,10 +8,9 @@ use ra_syntax::SmolStr;
8 8
9use crate::{ 9use crate::{
10 debug::HirDebugDatabase, 10 debug::HirDebugDatabase,
11 generics::{GenericDef, GenericParams}, 11 generics::GenericDef,
12 ids, 12 ids,
13 lang_item::{LangItemTarget, LangItems}, 13 lang_item::{LangItemTarget, LangItems},
14 traits::TraitData,
15 ty::{ 14 ty::{
16 method_resolution::CrateImplBlocks, 15 method_resolution::CrateImplBlocks,
17 traits::{AssocTyValue, Impl}, 16 traits::{AssocTyValue, Impl},
@@ -25,8 +24,9 @@ use crate::{
25 24
26pub use hir_def::db::{ 25pub use hir_def::db::{
27 BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage, 26 BodyQuery, BodyWithSourceMapQuery, CrateDefMapQuery, DefDatabase2, DefDatabase2Storage,
28 EnumDataQuery, ExprScopesQuery, ImplDataQuery, InternDatabase, InternDatabaseStorage, 27 EnumDataQuery, ExprScopesQuery, GenericParamsQuery, ImplDataQuery, InternDatabase,
29 RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery, 28 InternDatabaseStorage, RawItemsQuery, RawItemsWithSourceMapQuery, StructDataQuery,
29 TraitDataQuery,
30}; 30};
31pub use hir_expand::db::{ 31pub use hir_expand::db::{
32 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery, 32 AstDatabase, AstDatabaseStorage, AstIdMapQuery, MacroArgQuery, MacroDefQuery, MacroExpandQuery,
@@ -37,15 +37,6 @@ pub use hir_expand::db::{
37#[salsa::query_group(DefDatabaseStorage)] 37#[salsa::query_group(DefDatabaseStorage)]
38#[salsa::requires(AstDatabase)] 38#[salsa::requires(AstDatabase)]
39pub trait DefDatabase: HirDebugDatabase + DefDatabase2 { 39pub trait DefDatabase: HirDebugDatabase + DefDatabase2 {
40 #[salsa::invoke(crate::traits::TraitData::trait_data_query)]
41 fn trait_data(&self, t: Trait) -> Arc<TraitData>;
42
43 #[salsa::invoke(crate::traits::TraitItemsIndex::trait_items_index)]
44 fn trait_items_index(&self, module: Module) -> crate::traits::TraitItemsIndex;
45
46 #[salsa::invoke(crate::generics::GenericParams::generic_params_query)]
47 fn generic_params(&self, def: GenericDef) -> Arc<GenericParams>;
48
49 #[salsa::invoke(FnData::fn_data_query)] 40 #[salsa::invoke(FnData::fn_data_query)]
50 fn fn_data(&self, func: Function) -> Arc<FnData>; 41 fn fn_data(&self, func: Function) -> Arc<FnData>;
51 42
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs
index 1751e7be3..7d1b64858 100644
--- a/crates/ra_hir/src/diagnostics.rs
+++ b/crates/ra_hir/src/diagnostics.rs
@@ -21,7 +21,7 @@ impl Diagnostic for NoSuchField {
21 } 21 }
22 22
23 fn source(&self) -> Source<SyntaxNodePtr> { 23 fn source(&self) -> Source<SyntaxNodePtr> {
24 Source { file_id: self.file, ast: self.field.into() } 24 Source { file_id: self.file, value: self.field.into() }
25 } 25 }
26 26
27 fn as_any(&self) -> &(dyn Any + Send + 'static) { 27 fn as_any(&self) -> &(dyn Any + Send + 'static) {
@@ -41,7 +41,7 @@ impl Diagnostic for MissingFields {
41 "fill structure fields".to_string() 41 "fill structure fields".to_string()
42 } 42 }
43 fn source(&self) -> Source<SyntaxNodePtr> { 43 fn source(&self) -> Source<SyntaxNodePtr> {
44 Source { file_id: self.file, ast: self.field_list.into() } 44 Source { file_id: self.file, value: self.field_list.into() }
45 } 45 }
46 fn as_any(&self) -> &(dyn Any + Send + 'static) { 46 fn as_any(&self) -> &(dyn Any + Send + 'static) {
47 self 47 self
@@ -53,7 +53,7 @@ impl AstDiagnostic for MissingFields {
53 53
54 fn ast(&self, db: &impl AstDatabase) -> Self::AST { 54 fn ast(&self, db: &impl AstDatabase) -> Self::AST {
55 let root = db.parse_or_expand(self.source().file_id).unwrap(); 55 let root = db.parse_or_expand(self.source().file_id).unwrap();
56 let node = self.source().ast.to_node(&root); 56 let node = self.source().value.to_node(&root);
57 ast::RecordFieldList::cast(node).unwrap() 57 ast::RecordFieldList::cast(node).unwrap()
58 } 58 }
59} 59}
@@ -69,7 +69,7 @@ impl Diagnostic for MissingOkInTailExpr {
69 "wrap return expression in Ok".to_string() 69 "wrap return expression in Ok".to_string()
70 } 70 }
71 fn source(&self) -> Source<SyntaxNodePtr> { 71 fn source(&self) -> Source<SyntaxNodePtr> {
72 Source { file_id: self.file, ast: self.expr.into() } 72 Source { file_id: self.file, value: self.expr.into() }
73 } 73 }
74 fn as_any(&self) -> &(dyn Any + Send + 'static) { 74 fn as_any(&self) -> &(dyn Any + Send + 'static) {
75 self 75 self
@@ -81,7 +81,7 @@ impl AstDiagnostic for MissingOkInTailExpr {
81 81
82 fn ast(&self, db: &impl AstDatabase) -> Self::AST { 82 fn ast(&self, db: &impl AstDatabase) -> Self::AST {
83 let root = db.parse_or_expand(self.file).unwrap(); 83 let root = db.parse_or_expand(self.file).unwrap();
84 let node = self.source().ast.to_node(&root); 84 let node = self.source().value.to_node(&root);
85 ast::Expr::cast(node).unwrap() 85 ast::Expr::cast(node).unwrap()
86 } 86 }
87} 87}
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index e3733779e..869879bdf 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -11,6 +11,7 @@ use rustc_hash::FxHashSet;
11use crate::{ 11use crate::{
12 db::HirDatabase, 12 db::HirDatabase,
13 diagnostics::{MissingFields, MissingOkInTailExpr}, 13 diagnostics::{MissingFields, MissingOkInTailExpr},
14 resolve::HasResolver,
14 ty::{ApplicationTy, InferenceResult, Ty, TypeCtor}, 15 ty::{ApplicationTy, InferenceResult, Ty, TypeCtor},
15 Adt, DefWithBody, Function, HasBody, Name, Path, Resolver, 16 Adt, DefWithBody, Function, HasBody, Name, Path, Resolver,
16}; 17};
@@ -116,7 +117,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
116 let source_map = self.func.body_source_map(db); 117 let source_map = self.func.body_source_map(db);
117 118
118 if let Some(source_ptr) = source_map.expr_syntax(id) { 119 if let Some(source_ptr) = source_map.expr_syntax(id) {
119 if let Some(expr) = source_ptr.ast.a() { 120 if let Some(expr) = source_ptr.value.a() {
120 let root = source_ptr.file_syntax(db); 121 let root = source_ptr.file_syntax(db);
121 if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) { 122 if let ast::Expr::RecordLit(record_lit) = expr.to_node(&root) {
122 if let Some(field_list) = record_lit.record_field_list() { 123 if let Some(field_list) = record_lit.record_field_list() {
@@ -161,7 +162,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
161 let source_map = self.func.body_source_map(db); 162 let source_map = self.func.body_source_map(db);
162 163
163 if let Some(source_ptr) = source_map.expr_syntax(id) { 164 if let Some(source_ptr) = source_map.expr_syntax(id) {
164 if let Some(expr) = source_ptr.ast.a() { 165 if let Some(expr) = source_ptr.value.a() {
165 self.sink.push(MissingOkInTailExpr { file: source_ptr.file_id, expr }); 166 self.sink.push(MissingOkInTailExpr { file: source_ptr.file_id, expr });
166 } 167 }
167 } 168 }
diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs
index f2203e995..b7692d407 100644
--- a/crates/ra_hir/src/from_id.rs
+++ b/crates/ra_hir/src/from_id.rs
@@ -3,9 +3,9 @@
3//! It's unclear if we need this long-term, but it's definitelly useful while we 3//! It's unclear if we need this long-term, but it's definitelly useful while we
4//! are splitting the hir. 4//! are splitting the hir.
5 5
6use hir_def::{AdtId, AssocItemId, DefWithBodyId, EnumVariantId, ModuleDefId}; 6use hir_def::{AdtId, AssocItemId, DefWithBodyId, EnumVariantId, GenericDefId, ModuleDefId};
7 7
8use crate::{Adt, AssocItem, DefWithBody, EnumVariant, ModuleDef}; 8use crate::{Adt, AssocItem, DefWithBody, EnumVariant, GenericDef, ModuleDef};
9 9
10macro_rules! from_id { 10macro_rules! from_id {
11 ($(($id:path, $ty:path)),*) => {$( 11 ($(($id:path, $ty:path)),*) => {$(
@@ -41,6 +41,16 @@ impl From<AdtId> for Adt {
41 } 41 }
42} 42}
43 43
44impl From<Adt> for AdtId {
45 fn from(id: Adt) -> Self {
46 match id {
47 Adt::Struct(it) => AdtId::StructId(it.id),
48 Adt::Union(it) => AdtId::UnionId(it.id),
49 Adt::Enum(it) => AdtId::EnumId(it.id),
50 }
51 }
52}
53
44impl From<EnumVariantId> for EnumVariant { 54impl From<EnumVariantId> for EnumVariant {
45 fn from(id: EnumVariantId) -> Self { 55 fn from(id: EnumVariantId) -> Self {
46 EnumVariant { parent: id.parent.into(), id: id.local_id } 56 EnumVariant { parent: id.parent.into(), id: id.local_id }
@@ -82,3 +92,33 @@ impl From<AssocItemId> for AssocItem {
82 } 92 }
83 } 93 }
84} 94}
95
96impl From<GenericDef> for GenericDefId {
97 fn from(def: GenericDef) -> Self {
98 match def {
99 GenericDef::Function(it) => GenericDefId::FunctionId(it.id),
100 GenericDef::Adt(it) => GenericDefId::AdtId(it.into()),
101 GenericDef::Trait(it) => GenericDefId::TraitId(it.id),
102 GenericDef::TypeAlias(it) => GenericDefId::TypeAliasId(it.id),
103 GenericDef::ImplBlock(it) => GenericDefId::ImplId(it.id),
104 GenericDef::EnumVariant(it) => {
105 GenericDefId::EnumVariantId(EnumVariantId { parent: it.parent.id, local_id: it.id })
106 }
107 GenericDef::Const(it) => GenericDefId::ConstId(it.id),
108 }
109 }
110}
111
112impl From<GenericDefId> for GenericDef {
113 fn from(def: GenericDefId) -> Self {
114 match def {
115 GenericDefId::FunctionId(it) => GenericDef::Function(it.into()),
116 GenericDefId::AdtId(it) => GenericDef::Adt(it.into()),
117 GenericDefId::TraitId(it) => GenericDef::Trait(it.into()),
118 GenericDefId::TypeAliasId(it) => GenericDef::TypeAlias(it.into()),
119 GenericDefId::ImplId(it) => GenericDef::ImplBlock(it.into()),
120 GenericDefId::EnumVariantId(it) => GenericDef::EnumVariant(it.into()),
121 GenericDefId::ConstId(it) => GenericDef::Const(it.into()),
122 }
123 }
124}
diff --git a/crates/ra_hir/src/from_source.rs b/crates/ra_hir/src/from_source.rs
index 1c26756c9..b86307c58 100644
--- a/crates/ra_hir/src/from_source.rs
+++ b/crates/ra_hir/src/from_source.rs
@@ -4,15 +4,15 @@ use hir_def::{ModuleId, StructId, StructOrUnionId, UnionId};
4use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind}; 4use hir_expand::{name::AsName, AstId, MacroDefId, MacroDefKind};
5use ra_syntax::{ 5use ra_syntax::{
6 ast::{self, AstNode, NameOwner}, 6 ast::{self, AstNode, NameOwner},
7 match_ast, 7 match_ast, AstPtr, SyntaxNode,
8}; 8};
9 9
10use crate::{ 10use crate::{
11 db::{AstDatabase, DefDatabase, HirDatabase}, 11 db::{AstDatabase, DefDatabase, HirDatabase},
12 ids::{AstItemDef, LocationCtx}, 12 ids::{AstItemDef, LocationCtx},
13 Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource, ImplBlock, 13 AssocItem, Const, DefWithBody, Enum, EnumVariant, FieldSource, Function, HasBody, HasSource,
14 Local, MacroDef, Module, ModuleSource, Source, Static, Struct, StructField, Trait, TypeAlias, 14 ImplBlock, Local, MacroDef, Module, ModuleDef, ModuleSource, Source, Static, Struct,
15 Union, VariantDef, 15 StructField, Trait, TypeAlias, Union, VariantDef,
16}; 16};
17 17
18pub trait FromSource: Sized { 18pub trait FromSource: Sized {
@@ -52,15 +52,54 @@ impl FromSource for Trait {
52impl FromSource for Function { 52impl FromSource for Function {
53 type Ast = ast::FnDef; 53 type Ast = ast::FnDef;
54 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { 54 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
55 let id = from_source(db, src)?; 55 let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? {
56 Some(Function { id }) 56 Container::Trait(it) => it.items(db),
57 Container::ImplBlock(it) => it.items(db),
58 Container::Module(m) => {
59 return m
60 .declarations(db)
61 .into_iter()
62 .filter_map(|it| match it {
63 ModuleDef::Function(it) => Some(it),
64 _ => None,
65 })
66 .find(|it| same_source(&it.source(db), &src))
67 }
68 };
69 items
70 .into_iter()
71 .filter_map(|it| match it {
72 AssocItem::Function(it) => Some(it),
73 _ => None,
74 })
75 .find(|it| same_source(&it.source(db), &src))
57 } 76 }
58} 77}
78
59impl FromSource for Const { 79impl FromSource for Const {
60 type Ast = ast::ConstDef; 80 type Ast = ast::ConstDef;
61 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { 81 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
62 let id = from_source(db, src)?; 82 let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? {
63 Some(Const { id }) 83 Container::Trait(it) => it.items(db),
84 Container::ImplBlock(it) => it.items(db),
85 Container::Module(m) => {
86 return m
87 .declarations(db)
88 .into_iter()
89 .filter_map(|it| match it {
90 ModuleDef::Const(it) => Some(it),
91 _ => None,
92 })
93 .find(|it| same_source(&it.source(db), &src))
94 }
95 };
96 items
97 .into_iter()
98 .filter_map(|it| match it {
99 AssocItem::Const(it) => Some(it),
100 _ => None,
101 })
102 .find(|it| same_source(&it.source(db), &src))
64 } 103 }
65} 104}
66impl FromSource for Static { 105impl FromSource for Static {
@@ -73,8 +112,27 @@ impl FromSource for Static {
73impl FromSource for TypeAlias { 112impl FromSource for TypeAlias {
74 type Ast = ast::TypeAliasDef; 113 type Ast = ast::TypeAliasDef;
75 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { 114 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
76 let id = from_source(db, src)?; 115 let items = match Container::find(db, src.as_ref().map(|it| it.syntax()))? {
77 Some(TypeAlias { id }) 116 Container::Trait(it) => it.items(db),
117 Container::ImplBlock(it) => it.items(db),
118 Container::Module(m) => {
119 return m
120 .declarations(db)
121 .into_iter()
122 .filter_map(|it| match it {
123 ModuleDef::TypeAlias(it) => Some(it),
124 _ => None,
125 })
126 .find(|it| same_source(&it.source(db), &src))
127 }
128 };
129 items
130 .into_iter()
131 .filter_map(|it| match it {
132 AssocItem::TypeAlias(it) => Some(it),
133 _ => None,
134 })
135 .find(|it| same_source(&it.source(db), &src))
78 } 136 }
79} 137}
80 138
@@ -87,7 +145,7 @@ impl FromSource for MacroDef {
87 let module = Module::from_definition(db, Source::new(src.file_id, module_src))?; 145 let module = Module::from_definition(db, Source::new(src.file_id, module_src))?;
88 let krate = module.krate().crate_id(); 146 let krate = module.krate().crate_id();
89 147
90 let ast_id = AstId::new(src.file_id, db.ast_id_map(src.file_id).ast_id(&src.ast)); 148 let ast_id = AstId::new(src.file_id, db.ast_id_map(src.file_id).ast_id(&src.value));
91 149
92 let id: MacroDefId = MacroDefId { krate, ast_id, kind }; 150 let id: MacroDefId = MacroDefId { krate, ast_id, kind };
93 Some(MacroDef { id }) 151 Some(MacroDef { id })
@@ -105,26 +163,26 @@ impl FromSource for ImplBlock {
105impl FromSource for EnumVariant { 163impl FromSource for EnumVariant {
106 type Ast = ast::EnumVariant; 164 type Ast = ast::EnumVariant;
107 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { 165 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
108 let parent_enum = src.ast.parent_enum(); 166 let parent_enum = src.value.parent_enum();
109 let src_enum = Source { file_id: src.file_id, ast: parent_enum }; 167 let src_enum = Source { file_id: src.file_id, value: parent_enum };
110 let variants = Enum::from_source(db, src_enum)?.variants(db); 168 let variants = Enum::from_source(db, src_enum)?.variants(db);
111 variants.into_iter().find(|v| v.source(db) == src) 169 variants.into_iter().find(|v| same_source(&v.source(db), &src))
112 } 170 }
113} 171}
114 172
115impl FromSource for StructField { 173impl FromSource for StructField {
116 type Ast = FieldSource; 174 type Ast = FieldSource;
117 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> { 175 fn from_source(db: &(impl DefDatabase + AstDatabase), src: Source<Self::Ast>) -> Option<Self> {
118 let variant_def: VariantDef = match src.ast { 176 let variant_def: VariantDef = match src.value {
119 FieldSource::Named(ref field) => { 177 FieldSource::Named(ref field) => {
120 let ast = field.syntax().ancestors().find_map(ast::StructDef::cast)?; 178 let value = field.syntax().ancestors().find_map(ast::StructDef::cast)?;
121 let src = Source { file_id: src.file_id, ast }; 179 let src = Source { file_id: src.file_id, value };
122 let def = Struct::from_source(db, src)?; 180 let def = Struct::from_source(db, src)?;
123 VariantDef::from(def) 181 VariantDef::from(def)
124 } 182 }
125 FieldSource::Pos(ref field) => { 183 FieldSource::Pos(ref field) => {
126 let ast = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?; 184 let value = field.syntax().ancestors().find_map(ast::EnumVariant::cast)?;
127 let src = Source { file_id: src.file_id, ast }; 185 let src = Source { file_id: src.file_id, value };
128 let def = EnumVariant::from_source(db, src)?; 186 let def = EnumVariant::from_source(db, src)?;
129 VariantDef::from(def) 187 VariantDef::from(def)
130 } 188 }
@@ -142,12 +200,12 @@ impl FromSource for StructField {
142impl Local { 200impl Local {
143 pub fn from_source(db: &impl HirDatabase, src: Source<ast::BindPat>) -> Option<Self> { 201 pub fn from_source(db: &impl HirDatabase, src: Source<ast::BindPat>) -> Option<Self> {
144 let file_id = src.file_id; 202 let file_id = src.file_id;
145 let parent: DefWithBody = src.ast.syntax().ancestors().find_map(|it| { 203 let parent: DefWithBody = src.value.syntax().ancestors().find_map(|it| {
146 let res = match_ast! { 204 let res = match_ast! {
147 match it { 205 match it {
148 ast::ConstDef(ast) => { Const::from_source(db, Source { ast, file_id})?.into() }, 206 ast::ConstDef(value) => { Const::from_source(db, Source { value, file_id})?.into() },
149 ast::StaticDef(ast) => { Static::from_source(db, Source { ast, file_id})?.into() }, 207 ast::StaticDef(value) => { Static::from_source(db, Source { value, file_id})?.into() },
150 ast::FnDef(ast) => { Function::from_source(db, Source { ast, file_id})?.into() }, 208 ast::FnDef(value) => { Function::from_source(db, Source { value, file_id})?.into() },
151 _ => return None, 209 _ => return None,
152 } 210 }
153 }; 211 };
@@ -162,33 +220,33 @@ impl Local {
162 220
163impl Module { 221impl Module {
164 pub fn from_declaration(db: &impl DefDatabase, src: Source<ast::Module>) -> Option<Self> { 222 pub fn from_declaration(db: &impl DefDatabase, src: Source<ast::Module>) -> Option<Self> {
165 let parent_declaration = src.ast.syntax().ancestors().skip(1).find_map(ast::Module::cast); 223 let parent_declaration = src.value.syntax().ancestors().skip(1).find_map(ast::Module::cast);
166 224
167 let parent_module = match parent_declaration { 225 let parent_module = match parent_declaration {
168 Some(parent_declaration) => { 226 Some(parent_declaration) => {
169 let src_parent = Source { file_id: src.file_id, ast: parent_declaration }; 227 let src_parent = Source { file_id: src.file_id, value: parent_declaration };
170 Module::from_declaration(db, src_parent) 228 Module::from_declaration(db, src_parent)
171 } 229 }
172 _ => { 230 _ => {
173 let src_parent = Source { 231 let src_parent = Source {
174 file_id: src.file_id, 232 file_id: src.file_id,
175 ast: ModuleSource::new(db, Some(src.file_id.original_file(db)), None), 233 value: ModuleSource::new(db, Some(src.file_id.original_file(db)), None),
176 }; 234 };
177 Module::from_definition(db, src_parent) 235 Module::from_definition(db, src_parent)
178 } 236 }
179 }?; 237 }?;
180 238
181 let child_name = src.ast.name()?; 239 let child_name = src.value.name()?;
182 parent_module.child(db, &child_name.as_name()) 240 parent_module.child(db, &child_name.as_name())
183 } 241 }
184 242
185 pub fn from_definition(db: &impl DefDatabase, src: Source<ModuleSource>) -> Option<Self> { 243 pub fn from_definition(db: &impl DefDatabase, src: Source<ModuleSource>) -> Option<Self> {
186 match src.ast { 244 match src.value {
187 ModuleSource::Module(ref module) => { 245 ModuleSource::Module(ref module) => {
188 assert!(!module.has_semi()); 246 assert!(!module.has_semi());
189 return Module::from_declaration( 247 return Module::from_declaration(
190 db, 248 db,
191 Source { file_id: src.file_id, ast: module.clone() }, 249 Source { file_id: src.file_id, value: module.clone() },
192 ); 250 );
193 } 251 }
194 ModuleSource::SourceFile(_) => (), 252 ModuleSource::SourceFile(_) => (),
@@ -214,5 +272,47 @@ where
214 let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); 272 let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax()));
215 let module = Module::from_definition(db, Source::new(src.file_id, module_src))?; 273 let module = Module::from_definition(db, Source::new(src.file_id, module_src))?;
216 let ctx = LocationCtx::new(db, module.id, src.file_id); 274 let ctx = LocationCtx::new(db, module.id, src.file_id);
217 Some(DEF::from_ast(ctx, &src.ast)) 275 Some(DEF::from_ast(ctx, &src.value))
276}
277
278enum Container {
279 Trait(Trait),
280 ImplBlock(ImplBlock),
281 Module(Module),
282}
283
284impl Container {
285 fn find(db: &impl DefDatabase, src: Source<&SyntaxNode>) -> Option<Container> {
286 // FIXME: this doesn't try to handle nested declarations
287 for container in src.value.ancestors() {
288 let res = match_ast! {
289 match container {
290 ast::TraitDef(it) => {
291 let c = Trait::from_source(db, src.with_value(it))?;
292 Container::Trait(c)
293 },
294 ast::ImplBlock(it) => {
295 let c = ImplBlock::from_source(db, src.with_value(it))?;
296 Container::ImplBlock(c)
297 },
298 _ => { continue },
299 }
300 };
301 return Some(res);
302 }
303
304 let module_source = ModuleSource::from_child_node(db, src);
305 let c = Module::from_definition(db, src.with_value(module_source))?;
306 Some(Container::Module(c))
307 }
308}
309
310/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
311/// equal if they point to exactly the same object.
312///
313/// In general, we do not guarantee that we have exactly one instance of a
314/// syntax tree for each file. We probably should add such guarantee, but, for
315/// the time being, we will use identity-less AstPtr comparison.
316fn same_source<N: AstNode>(s1: &Source<N>, s2: &Source<N>) -> bool {
317 s1.as_ref().map(AstPtr::new) == s2.as_ref().map(AstPtr::new)
218} 318}
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index c35482ae8..f1bf2ee9d 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -1,50 +1,12 @@
1//! Many kinds of items or constructs can have generic parameters: functions, 1//! Temp module to wrap hir_def::generics
2//! structs, impls, traits, etc. This module provides a common HIR for these
3//! generic parameters. See also the `Generics` type and the `generics_of` query
4//! in rustc.
5
6use std::sync::Arc; 2use std::sync::Arc;
7 3
8use hir_def::{
9 path::Path,
10 type_ref::{TypeBound, TypeRef},
11};
12use hir_expand::name::{self, AsName};
13use ra_syntax::ast::{self, DefaultTypeParamOwner, NameOwner, TypeBoundsOwner, TypeParamsOwner};
14
15use crate::{ 4use crate::{
16 db::{AstDatabase, DefDatabase, HirDatabase}, 5 db::DefDatabase, Adt, Const, Container, Enum, EnumVariant, Function, ImplBlock, Struct, Trait,
17 Adt, Const, Container, Enum, EnumVariant, Function, HasSource, ImplBlock, Name, Struct, Trait,
18 TypeAlias, Union, 6 TypeAlias, Union,
19}; 7};
20 8
21/// Data about a generic parameter (to a function, struct, impl, ...). 9pub use hir_def::generics::{GenericParam, GenericParams, WherePredicate};
22#[derive(Clone, PartialEq, Eq, Debug)]
23pub struct GenericParam {
24 // FIXME: give generic params proper IDs
25 pub idx: u32,
26 pub name: Name,
27 pub default: Option<Path>,
28}
29
30/// Data about the generic parameters of a function, struct, impl, etc.
31#[derive(Clone, PartialEq, Eq, Debug)]
32pub struct GenericParams {
33 pub(crate) def: GenericDef,
34 pub(crate) parent_params: Option<Arc<GenericParams>>,
35 pub(crate) params: Vec<GenericParam>,
36 pub(crate) where_predicates: Vec<WherePredicate>,
37}
38
39/// A single predicate from a where clause, i.e. `where Type: Trait`. Combined
40/// where clauses like `where T: Foo + Bar` are turned into multiple of these.
41/// It might still result in multiple actual predicates though, because of
42/// associated type bindings like `Iterator<Item = u32>`.
43#[derive(Clone, PartialEq, Eq, Debug)]
44pub struct WherePredicate {
45 pub(crate) type_ref: TypeRef,
46 pub(crate) bound: TypeBound,
47}
48 10
49#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)] 11#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
50pub enum GenericDef { 12pub enum GenericDef {
@@ -69,150 +31,6 @@ impl_froms!(
69 Const 31 Const
70); 32);
71 33
72impl GenericParams {
73 pub(crate) fn generic_params_query(
74 db: &(impl DefDatabase + AstDatabase),
75 def: GenericDef,
76 ) -> Arc<GenericParams> {
77 let parent = match def {
78 GenericDef::Function(it) => it.container(db).map(GenericDef::from),
79 GenericDef::TypeAlias(it) => it.container(db).map(GenericDef::from),
80 GenericDef::Const(it) => it.container(db).map(GenericDef::from),
81 GenericDef::EnumVariant(it) => Some(it.parent_enum(db).into()),
82 GenericDef::Adt(_) | GenericDef::Trait(_) => None,
83 GenericDef::ImplBlock(_) => None,
84 };
85 let mut generics = GenericParams {
86 def,
87 params: Vec::new(),
88 parent_params: parent.map(|p| db.generic_params(p)),
89 where_predicates: Vec::new(),
90 };
91 let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32;
92 // FIXME: add `: Sized` bound for everything except for `Self` in traits
93 match def {
94 GenericDef::Function(it) => generics.fill(&it.source(db).ast, start),
95 GenericDef::Adt(Adt::Struct(it)) => generics.fill(&it.source(db).ast, start),
96 GenericDef::Adt(Adt::Union(it)) => generics.fill(&it.source(db).ast, start),
97 GenericDef::Adt(Adt::Enum(it)) => generics.fill(&it.source(db).ast, start),
98 GenericDef::Trait(it) => {
99 // traits get the Self type as an implicit first type parameter
100 generics.params.push(GenericParam {
101 idx: start,
102 name: name::SELF_TYPE,
103 default: None,
104 });
105 generics.fill(&it.source(db).ast, start + 1);
106 // add super traits as bounds on Self
107 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
108 let self_param = TypeRef::Path(name::SELF_TYPE.into());
109 generics.fill_bounds(&it.source(db).ast, self_param);
110 }
111 GenericDef::TypeAlias(it) => generics.fill(&it.source(db).ast, start),
112 // Note that we don't add `Self` here: in `impl`s, `Self` is not a
113 // type-parameter, but rather is a type-alias for impl's target
114 // type, so this is handled by the resolver.
115 GenericDef::ImplBlock(it) => generics.fill(&it.source(db).ast, start),
116 GenericDef::EnumVariant(_) | GenericDef::Const(_) => {}
117 }
118
119 Arc::new(generics)
120 }
121
122 fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) {
123 if let Some(params) = node.type_param_list() {
124 self.fill_params(params, start)
125 }
126 if let Some(where_clause) = node.where_clause() {
127 self.fill_where_predicates(where_clause);
128 }
129 }
130
131 fn fill_bounds(&mut self, node: &impl ast::TypeBoundsOwner, type_ref: TypeRef) {
132 for bound in
133 node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds())
134 {
135 self.add_where_predicate_from_bound(bound, type_ref.clone());
136 }
137 }
138
139 fn fill_params(&mut self, params: ast::TypeParamList, start: u32) {
140 for (idx, type_param) in params.type_params().enumerate() {
141 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
142 // FIXME: Use `Path::from_src`
143 let default = type_param.default_type().and_then(|t| t.path()).and_then(Path::from_ast);
144
145 let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default };
146 self.params.push(param);
147
148 let type_ref = TypeRef::Path(name.into());
149 self.fill_bounds(&type_param, type_ref);
150 }
151 }
152
153 fn fill_where_predicates(&mut self, where_clause: ast::WhereClause) {
154 for pred in where_clause.predicates() {
155 let type_ref = match pred.type_ref() {
156 Some(type_ref) => type_ref,
157 None => continue,
158 };
159 let type_ref = TypeRef::from_ast(type_ref);
160 for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) {
161 self.add_where_predicate_from_bound(bound, type_ref.clone());
162 }
163 }
164 }
165
166 fn add_where_predicate_from_bound(&mut self, bound: ast::TypeBound, type_ref: TypeRef) {
167 if bound.has_question_mark() {
168 // FIXME: remove this bound
169 return;
170 }
171 let bound = TypeBound::from_ast(bound);
172 self.where_predicates.push(WherePredicate { type_ref, bound });
173 }
174
175 pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> {
176 self.params.iter().find(|p| &p.name == name)
177 }
178
179 pub fn count_parent_params(&self) -> usize {
180 self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0)
181 }
182
183 pub fn count_params_including_parent(&self) -> usize {
184 let parent_count = self.count_parent_params();
185 parent_count + self.params.len()
186 }
187
188 fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParam)) {
189 if let Some(parent) = &self.parent_params {
190 parent.for_each_param(f);
191 }
192 self.params.iter().for_each(f);
193 }
194
195 pub fn params_including_parent(&self) -> Vec<&GenericParam> {
196 let mut vec = Vec::with_capacity(self.count_params_including_parent());
197 self.for_each_param(&mut |p| vec.push(p));
198 vec
199 }
200}
201
202impl GenericDef {
203 pub(crate) fn resolver(&self, db: &impl HirDatabase) -> crate::Resolver {
204 match self {
205 GenericDef::Function(inner) => inner.resolver(db),
206 GenericDef::Adt(adt) => adt.resolver(db),
207 GenericDef::Trait(inner) => inner.resolver(db),
208 GenericDef::TypeAlias(inner) => inner.resolver(db),
209 GenericDef::ImplBlock(inner) => inner.resolver(db),
210 GenericDef::EnumVariant(inner) => inner.parent_enum(db).resolver(db),
211 GenericDef::Const(inner) => inner.resolver(db),
212 }
213 }
214}
215
216impl From<Container> for GenericDef { 34impl From<Container> for GenericDef {
217 fn from(c: Container) -> Self { 35 fn from(c: Container) -> Self {
218 match c { 36 match c {
@@ -231,6 +49,6 @@ where
231 T: Into<GenericDef> + Copy, 49 T: Into<GenericDef> + Copy,
232{ 50{
233 fn generic_params(self, db: &impl DefDatabase) -> Arc<GenericParams> { 51 fn generic_params(self, db: &impl DefDatabase) -> Arc<GenericParams> {
234 db.generic_params(self.into()) 52 db.generic_params(self.into().into())
235 } 53 }
236} 54}
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index 0c2bb8fee..964a3da8c 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -5,8 +5,7 @@ use ra_syntax::ast::{self};
5 5
6use crate::{ 6use crate::{
7 db::{AstDatabase, DefDatabase, HirDatabase}, 7 db::{AstDatabase, DefDatabase, HirDatabase},
8 generics::HasGenericParams, 8 resolve::HasResolver,
9 resolve::Resolver,
10 ty::Ty, 9 ty::Ty,
11 AssocItem, Crate, HasSource, ImplBlock, Module, Source, TraitRef, 10 AssocItem, Crate, HasSource, ImplBlock, Module, Source, TraitRef,
12}; 11};
@@ -19,14 +18,6 @@ impl HasSource for ImplBlock {
19} 18}
20 19
21impl ImplBlock { 20impl ImplBlock {
22 pub(crate) fn containing(db: &impl DefDatabase, item: AssocItem) -> Option<ImplBlock> {
23 let module = item.module(db);
24 let crate_def_map = db.crate_def_map(module.id.krate);
25 crate_def_map[module.id.module_id].impls.iter().copied().map(ImplBlock::from).find(|it| {
26 db.impl_data(it.id).items().iter().copied().map(AssocItem::from).any(|it| it == item)
27 })
28 }
29
30 pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> { 21 pub fn target_trait(&self, db: &impl DefDatabase) -> Option<TypeRef> {
31 db.impl_data(self.id).target_trait().cloned() 22 db.impl_data(self.id).target_trait().cloned()
32 } 23 }
@@ -59,13 +50,4 @@ impl ImplBlock {
59 pub fn krate(&self, db: &impl DefDatabase) -> Crate { 50 pub fn krate(&self, db: &impl DefDatabase) -> Crate {
60 Crate { crate_id: self.module(db).id.krate } 51 Crate { crate_id: self.module(db).id.krate }
61 } 52 }
62
63 pub(crate) fn resolver(&self, db: &impl DefDatabase) -> Resolver {
64 let r = self.module(db).resolver(db);
65 // add generic params, if present
66 let p = self.generic_params(db);
67 let r = if !p.params.is_empty() { r.push_generic_params_scope(p) } else { r };
68 let r = r.push_impl_block_scope(self.clone());
69 r
70 }
71} 53}
diff --git a/crates/ra_hir/src/lang_item.rs b/crates/ra_hir/src/lang_item.rs
index fa2ef8a17..89fd85f59 100644
--- a/crates/ra_hir/src/lang_item.rs
+++ b/crates/ra_hir/src/lang_item.rs
@@ -97,7 +97,7 @@ impl LangItems {
97 // Look for impl targets 97 // Look for impl targets
98 for impl_block in module.impl_blocks(db) { 98 for impl_block in module.impl_blocks(db) {
99 let src = impl_block.source(db); 99 let src = impl_block.source(db);
100 if let Some(lang_item_name) = lang_item_name(&src.ast) { 100 if let Some(lang_item_name) = lang_item_name(&src.value) {
101 self.items 101 self.items
102 .entry(lang_item_name) 102 .entry(lang_item_name)
103 .or_insert_with(|| LangItemTarget::ImplBlock(impl_block)); 103 .or_insert_with(|| LangItemTarget::ImplBlock(impl_block));
@@ -144,7 +144,7 @@ impl LangItems {
144 T: Copy + HasSource<Ast = N>, 144 T: Copy + HasSource<Ast = N>,
145 N: AttrsOwner, 145 N: AttrsOwner,
146 { 146 {
147 let node = item.source(db).ast; 147 let node = item.source(db).value;
148 if let Some(lang_item_name) = lang_item_name(&node) { 148 if let Some(lang_item_name) = lang_item_name(&node) {
149 self.items.entry(lang_item_name).or_insert_with(|| constructor(item)); 149 self.items.entry(lang_item_name).or_insert_with(|| constructor(item));
150 } 150 }
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index da33c9591..31da74d2f 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -32,8 +32,6 @@ pub mod db;
32pub mod source_binder; 32pub mod source_binder;
33 33
34mod ids; 34mod ids;
35mod adt;
36mod traits;
37mod type_alias; 35mod type_alias;
38mod ty; 36mod ty;
39mod impl_block; 37mod impl_block;
@@ -57,15 +55,14 @@ mod marks;
57use crate::resolve::Resolver; 55use crate::resolve::Resolver;
58 56
59pub use crate::{ 57pub use crate::{
60 adt::VariantDef,
61 code_model::ImplBlock,
62 code_model::{ 58 code_model::{
63 attrs::{AttrDef, Attrs}, 59 attrs::{AttrDef, Attrs},
64 docs::{DocDef, Docs, Documentation}, 60 docs::{DocDef, Docs, Documentation},
65 src::{HasBodySource, HasSource}, 61 src::{HasBodySource, HasSource},
66 Adt, AssocItem, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, Enum, 62 Adt, AssocItem, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, Enum,
67 EnumVariant, FieldSource, FnData, Function, GenericParam, HasBody, Local, MacroDef, Module, 63 EnumVariant, FieldSource, FnData, Function, GenericParam, HasBody, ImplBlock, Local,
68 ModuleDef, ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, 64 MacroDef, Module, ModuleDef, ModuleSource, Static, Struct, StructField, Trait, TypeAlias,
65 Union, VariantDef,
69 }, 66 },
70 expr::ExprScopes, 67 expr::ExprScopes,
71 from_source::FromSource, 68 from_source::FromSource,
diff --git a/crates/ra_hir/src/resolve.rs b/crates/ra_hir/src/resolve.rs
index 79b92180a..eca8e0596 100644
--- a/crates/ra_hir/src/resolve.rs
+++ b/crates/ra_hir/src/resolve.rs
@@ -14,9 +14,9 @@ use crate::{
14 code_model::Crate, 14 code_model::Crate,
15 db::{DefDatabase, HirDatabase}, 15 db::{DefDatabase, HirDatabase},
16 expr::{ExprScopes, PatId, ScopeId}, 16 expr::{ExprScopes, PatId, ScopeId},
17 generics::GenericParams, 17 generics::{GenericParams, HasGenericParams},
18 Adt, Const, DefWithBody, Enum, EnumVariant, Function, ImplBlock, Local, MacroDef, ModuleDef, 18 Adt, Const, Container, DefWithBody, Enum, EnumVariant, Function, GenericDef, ImplBlock, Local,
19 PerNs, Static, Struct, Trait, TypeAlias, 19 MacroDef, Module, ModuleDef, PerNs, Static, Struct, Trait, TypeAlias,
20}; 20};
21 21
22#[derive(Debug, Clone, Default)] 22#[derive(Debug, Clone, Default)]
@@ -43,7 +43,7 @@ pub(crate) enum Scope {
43 /// All the items and imported names of a module 43 /// All the items and imported names of a module
44 ModuleScope(ModuleItemMap), 44 ModuleScope(ModuleItemMap),
45 /// Brings the generic parameters of an item into scope 45 /// Brings the generic parameters of an item into scope
46 GenericParams(Arc<GenericParams>), 46 GenericParams { def: GenericDef, params: Arc<GenericParams> },
47 /// Brings `Self` in `impl` block into scope 47 /// Brings `Self` in `impl` block into scope
48 ImplBlockScope(ImplBlock), 48 ImplBlockScope(ImplBlock),
49 /// Brings `Self` in enum, struct and union definitions into scope 49 /// Brings `Self` in enum, struct and union definitions into scope
@@ -141,9 +141,9 @@ impl Resolver {
141 for scope in self.scopes.iter().rev() { 141 for scope in self.scopes.iter().rev() {
142 match scope { 142 match scope {
143 Scope::ExprScope(_) => continue, 143 Scope::ExprScope(_) => continue,
144 Scope::GenericParams(_) | Scope::ImplBlockScope(_) if skip_to_mod => continue, 144 Scope::GenericParams { .. } | Scope::ImplBlockScope(_) if skip_to_mod => continue,
145 145
146 Scope::GenericParams(params) => { 146 Scope::GenericParams { params, .. } => {
147 if let Some(param) = params.find_by_name(first_name) { 147 if let Some(param) = params.find_by_name(first_name) {
148 let idx = if path.segments.len() == 1 { None } else { Some(1) }; 148 let idx = if path.segments.len() == 1 { None } else { Some(1) };
149 return Some((TypeNs::GenericParam(param.idx), idx)); 149 return Some((TypeNs::GenericParam(param.idx), idx));
@@ -212,7 +212,7 @@ impl Resolver {
212 match scope { 212 match scope {
213 Scope::AdtScope(_) 213 Scope::AdtScope(_)
214 | Scope::ExprScope(_) 214 | Scope::ExprScope(_)
215 | Scope::GenericParams(_) 215 | Scope::GenericParams { .. }
216 | Scope::ImplBlockScope(_) 216 | Scope::ImplBlockScope(_)
217 if skip_to_mod => 217 if skip_to_mod =>
218 { 218 {
@@ -232,13 +232,13 @@ impl Resolver {
232 } 232 }
233 Scope::ExprScope(_) => continue, 233 Scope::ExprScope(_) => continue,
234 234
235 Scope::GenericParams(params) if n_segments > 1 => { 235 Scope::GenericParams { params, .. } if n_segments > 1 => {
236 if let Some(param) = params.find_by_name(first_name) { 236 if let Some(param) = params.find_by_name(first_name) {
237 let ty = TypeNs::GenericParam(param.idx); 237 let ty = TypeNs::GenericParam(param.idx);
238 return Some(ResolveValueResult::Partial(ty, 1)); 238 return Some(ResolveValueResult::Partial(ty, 1));
239 } 239 }
240 } 240 }
241 Scope::GenericParams(_) => continue, 241 Scope::GenericParams { .. } => continue,
242 242
243 Scope::ImplBlockScope(impl_) if n_segments > 1 => { 243 Scope::ImplBlockScope(impl_) if n_segments > 1 => {
244 if first_name == &name::SELF_TYPE { 244 if first_name == &name::SELF_TYPE {
@@ -361,7 +361,7 @@ impl Resolver {
361 self.scopes 361 self.scopes
362 .iter() 362 .iter()
363 .filter_map(|scope| match scope { 363 .filter_map(|scope| match scope {
364 Scope::GenericParams(params) => Some(params), 364 Scope::GenericParams { params, .. } => Some(params),
365 _ => None, 365 _ => None,
366 }) 366 })
367 .flat_map(|params| params.where_predicates.iter()) 367 .flat_map(|params| params.where_predicates.iter())
@@ -369,7 +369,7 @@ impl Resolver {
369 369
370 pub(crate) fn generic_def(&self) -> Option<crate::generics::GenericDef> { 370 pub(crate) fn generic_def(&self) -> Option<crate::generics::GenericDef> {
371 self.scopes.iter().find_map(|scope| match scope { 371 self.scopes.iter().find_map(|scope| match scope {
372 Scope::GenericParams(params) => Some(params.def), 372 Scope::GenericParams { def, .. } => Some(*def),
373 _ => None, 373 _ => None,
374 }) 374 })
375 } 375 }
@@ -381,8 +381,17 @@ impl Resolver {
381 self 381 self
382 } 382 }
383 383
384 pub(crate) fn push_generic_params_scope(self, params: Arc<GenericParams>) -> Resolver { 384 pub(crate) fn push_generic_params_scope(
385 self.push_scope(Scope::GenericParams(params)) 385 self,
386 db: &impl DefDatabase,
387 def: GenericDef,
388 ) -> Resolver {
389 let params = def.generic_params(db);
390 if params.params.is_empty() {
391 self
392 } else {
393 self.push_scope(Scope::GenericParams { def, params })
394 }
386 } 395 }
387 396
388 pub(crate) fn push_impl_block_scope(self, impl_block: ImplBlock) -> Resolver { 397 pub(crate) fn push_impl_block_scope(self, impl_block: ImplBlock) -> Resolver {
@@ -457,8 +466,8 @@ impl Scope {
457 }); 466 });
458 } 467 }
459 } 468 }
460 Scope::GenericParams(gp) => { 469 Scope::GenericParams { params, .. } => {
461 for param in &gp.params { 470 for param in params.params.iter() {
462 f(param.name.clone(), ScopeDef::GenericParam(param.idx)) 471 f(param.name.clone(), ScopeDef::GenericParam(param.idx))
463 } 472 }
464 } 473 }
@@ -477,3 +486,103 @@ impl Scope {
477 } 486 }
478 } 487 }
479} 488}
489
490pub(crate) trait HasResolver {
491 /// Builds a resolver for type references inside this def.
492 fn resolver(self, db: &impl DefDatabase) -> Resolver;
493}
494
495impl HasResolver for Module {
496 fn resolver(self, db: &impl DefDatabase) -> Resolver {
497 let def_map = db.crate_def_map(self.id.krate);
498 Resolver::default().push_module_scope(def_map, self.id.module_id)
499 }
500}
501
502impl HasResolver for Trait {
503 fn resolver(self, db: &impl DefDatabase) -> Resolver {
504 self.module(db).resolver(db).push_generic_params_scope(db, self.into())
505 }
506}
507
508impl<T: Into<Adt>> HasResolver for T {
509 fn resolver(self, db: &impl DefDatabase) -> Resolver {
510 let def = self.into();
511 def.module(db)
512 .resolver(db)
513 .push_generic_params_scope(db, def.into())
514 .push_scope(Scope::AdtScope(def))
515 }
516}
517
518impl HasResolver for Function {
519 fn resolver(self, db: &impl DefDatabase) -> Resolver {
520 self.container(db)
521 .map(|c| c.resolver(db))
522 .unwrap_or_else(|| self.module(db).resolver(db))
523 .push_generic_params_scope(db, self.into())
524 }
525}
526
527impl HasResolver for DefWithBody {
528 fn resolver(self, db: &impl DefDatabase) -> Resolver {
529 match self {
530 DefWithBody::Const(c) => c.resolver(db),
531 DefWithBody::Function(f) => f.resolver(db),
532 DefWithBody::Static(s) => s.resolver(db),
533 }
534 }
535}
536
537impl HasResolver for Const {
538 fn resolver(self, db: &impl DefDatabase) -> Resolver {
539 self.container(db).map(|c| c.resolver(db)).unwrap_or_else(|| self.module(db).resolver(db))
540 }
541}
542
543impl HasResolver for Static {
544 fn resolver(self, db: &impl DefDatabase) -> Resolver {
545 self.module(db).resolver(db)
546 }
547}
548
549impl HasResolver for TypeAlias {
550 fn resolver(self, db: &impl DefDatabase) -> Resolver {
551 self.container(db)
552 .map(|ib| ib.resolver(db))
553 .unwrap_or_else(|| self.module(db).resolver(db))
554 .push_generic_params_scope(db, self.into())
555 }
556}
557
558impl HasResolver for Container {
559 fn resolver(self, db: &impl DefDatabase) -> Resolver {
560 match self {
561 Container::Trait(trait_) => trait_.resolver(db),
562 Container::ImplBlock(impl_block) => impl_block.resolver(db),
563 }
564 }
565}
566
567impl HasResolver for GenericDef {
568 fn resolver(self, db: &impl DefDatabase) -> crate::Resolver {
569 match self {
570 GenericDef::Function(inner) => inner.resolver(db),
571 GenericDef::Adt(adt) => adt.resolver(db),
572 GenericDef::Trait(inner) => inner.resolver(db),
573 GenericDef::TypeAlias(inner) => inner.resolver(db),
574 GenericDef::ImplBlock(inner) => inner.resolver(db),
575 GenericDef::EnumVariant(inner) => inner.parent_enum(db).resolver(db),
576 GenericDef::Const(inner) => inner.resolver(db),
577 }
578 }
579}
580
581impl HasResolver for ImplBlock {
582 fn resolver(self, db: &impl DefDatabase) -> Resolver {
583 self.module(db)
584 .resolver(db)
585 .push_generic_params_scope(db, self.into())
586 .push_impl_block_scope(self)
587 }
588}
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 5d3196c2a..727310f06 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -23,7 +23,7 @@ use crate::{
23 db::HirDatabase, 23 db::HirDatabase,
24 expr::{self, BodySourceMap, ExprScopes, ScopeId}, 24 expr::{self, BodySourceMap, ExprScopes, ScopeId},
25 ids::LocationCtx, 25 ids::LocationCtx,
26 resolve::{ScopeDef, TypeNs, ValueNs}, 26 resolve::{HasResolver, ScopeDef, TypeNs, ValueNs},
27 ty::method_resolution::{self, implements_trait}, 27 ty::method_resolution::{self, implements_trait},
28 AssocItem, Const, DefWithBody, Either, Enum, FromSource, Function, GenericParam, HasBody, 28 AssocItem, Const, DefWithBody, Either, Enum, FromSource, Function, GenericParam, HasBody,
29 HirFileId, Local, MacroDef, Module, Name, Path, Resolver, Static, Struct, Ty, 29 HirFileId, Local, MacroDef, Module, Name, Path, Resolver, Static, Struct, Ty,
@@ -31,24 +31,24 @@ use crate::{
31 31
32fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> { 32fn try_get_resolver_for_node(db: &impl HirDatabase, node: Source<&SyntaxNode>) -> Option<Resolver> {
33 match_ast! { 33 match_ast! {
34 match (node.ast) { 34 match (node.value) {
35 ast::Module(it) => { 35 ast::Module(it) => {
36 let src = node.with_ast(it); 36 let src = node.with_value(it);
37 Some(crate::Module::from_declaration(db, src)?.resolver(db)) 37 Some(crate::Module::from_declaration(db, src)?.resolver(db))
38 }, 38 },
39 ast::SourceFile(it) => { 39 ast::SourceFile(it) => {
40 let src = node.with_ast(crate::ModuleSource::SourceFile(it)); 40 let src = node.with_value(crate::ModuleSource::SourceFile(it));
41 Some(crate::Module::from_definition(db, src)?.resolver(db)) 41 Some(crate::Module::from_definition(db, src)?.resolver(db))
42 }, 42 },
43 ast::StructDef(it) => { 43 ast::StructDef(it) => {
44 let src = node.with_ast(it); 44 let src = node.with_value(it);
45 Some(Struct::from_source(db, src)?.resolver(db)) 45 Some(Struct::from_source(db, src)?.resolver(db))
46 }, 46 },
47 ast::EnumDef(it) => { 47 ast::EnumDef(it) => {
48 let src = node.with_ast(it); 48 let src = node.with_value(it);
49 Some(Enum::from_source(db, src)?.resolver(db)) 49 Some(Enum::from_source(db, src)?.resolver(db))
50 }, 50 },
51 _ => match node.ast.kind() { 51 _ => match node.value.kind() {
52 FN_DEF | CONST_DEF | STATIC_DEF => { 52 FN_DEF | CONST_DEF | STATIC_DEF => {
53 Some(def_with_body_from_child_node(db, node)?.resolver(db)) 53 Some(def_with_body_from_child_node(db, node)?.resolver(db))
54 } 54 }
@@ -67,11 +67,11 @@ fn def_with_body_from_child_node(
67 let module = Module::from_definition(db, Source::new(child.file_id, module_source))?; 67 let module = Module::from_definition(db, Source::new(child.file_id, module_source))?;
68 let ctx = LocationCtx::new(db, module.id, child.file_id); 68 let ctx = LocationCtx::new(db, module.id, child.file_id);
69 69
70 child.ast.ancestors().find_map(|node| { 70 child.value.ancestors().find_map(|node| {
71 match_ast! { 71 match_ast! {
72 match node { 72 match node {
73 ast::FnDef(def) => { Some(Function {id: ctx.to_def(&def) }.into()) }, 73 ast::FnDef(def) => { return Function::from_source(db, child.with_value(def)).map(DefWithBody::from); },
74 ast::ConstDef(def) => { Some(Const { id: ctx.to_def(&def) }.into()) }, 74 ast::ConstDef(def) => { return Const::from_source(db, child.with_value(def)).map(DefWithBody::from); },
75 ast::StaticDef(def) => { Some(Static { id: ctx.to_def(&def) }.into()) }, 75 ast::StaticDef(def) => { Some(Static { id: ctx.to_def(&def) }.into()) },
76 _ => { None }, 76 _ => { None },
77 } 77 }
@@ -157,7 +157,7 @@ impl SourceAnalyzer {
157 let scopes = def.expr_scopes(db); 157 let scopes = def.expr_scopes(db);
158 let scope = match offset { 158 let scope = match offset {
159 None => scope_for(&scopes, &source_map, node), 159 None => scope_for(&scopes, &source_map, node),
160 Some(offset) => scope_for_offset(&scopes, &source_map, node.with_ast(offset)), 160 Some(offset) => scope_for_offset(&scopes, &source_map, node.with_value(offset)),
161 }; 161 };
162 let resolver = expr::resolver_for_scope(db, def, scope); 162 let resolver = expr::resolver_for_scope(db, def, scope);
163 SourceAnalyzer { 163 SourceAnalyzer {
@@ -171,9 +171,9 @@ impl SourceAnalyzer {
171 } else { 171 } else {
172 SourceAnalyzer { 172 SourceAnalyzer {
173 resolver: node 173 resolver: node
174 .ast 174 .value
175 .ancestors() 175 .ancestors()
176 .find_map(|it| try_get_resolver_for_node(db, node.with_ast(&it))) 176 .find_map(|it| try_get_resolver_for_node(db, node.with_value(&it)))
177 .unwrap_or_default(), 177 .unwrap_or_default(),
178 body_owner: None, 178 body_owner: None,
179 body_source_map: None, 179 body_source_map: None,
@@ -185,12 +185,12 @@ impl SourceAnalyzer {
185 } 185 }
186 186
187 fn expr_id(&self, expr: &ast::Expr) -> Option<ExprId> { 187 fn expr_id(&self, expr: &ast::Expr) -> Option<ExprId> {
188 let src = Source { file_id: self.file_id, ast: expr }; 188 let src = Source { file_id: self.file_id, value: expr };
189 self.body_source_map.as_ref()?.node_expr(src) 189 self.body_source_map.as_ref()?.node_expr(src)
190 } 190 }
191 191
192 fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> { 192 fn pat_id(&self, pat: &ast::Pat) -> Option<PatId> {
193 let src = Source { file_id: self.file_id, ast: pat }; 193 let src = Source { file_id: self.file_id, value: pat };
194 self.body_source_map.as_ref()?.node_pat(src) 194 self.body_source_map.as_ref()?.node_pat(src)
195 } 195 }
196 196
@@ -302,7 +302,7 @@ impl SourceAnalyzer {
302 let entry = scopes.resolve_name_in_scope(scope, &name)?; 302 let entry = scopes.resolve_name_in_scope(scope, &name)?;
303 Some(ScopeEntryWithSyntax { 303 Some(ScopeEntryWithSyntax {
304 name: entry.name().clone(), 304 name: entry.name().clone(),
305 ptr: source_map.pat_syntax(entry.pat())?.ast, 305 ptr: source_map.pat_syntax(entry.pat())?.value,
306 }) 306 })
307 } 307 }
308 308
@@ -405,9 +405,16 @@ impl SourceAnalyzer {
405 implements_trait(&canonical_ty, db, &self.resolver, krate, std_future_trait) 405 implements_trait(&canonical_ty, db, &self.resolver, krate, std_future_trait)
406 } 406 }
407 407
408 pub fn expand(&self, db: &impl HirDatabase, macro_call: &ast::MacroCall) -> Option<Expansion> { 408 pub fn expand(
409 let def = self.resolve_macro_call(db, macro_call)?.id; 409 &self,
410 let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(macro_call)); 410 db: &impl HirDatabase,
411 macro_call: Source<&ast::MacroCall>,
412 ) -> Option<Expansion> {
413 let def = self.resolve_macro_call(db, macro_call.value)?.id;
414 let ast_id = AstId::new(
415 macro_call.file_id,
416 db.ast_id_map(macro_call.file_id).ast_id(macro_call.value),
417 );
411 let macro_call_loc = MacroCallLoc { def, ast_id }; 418 let macro_call_loc = MacroCallLoc { def, ast_id };
412 Some(Expansion { macro_call_id: db.intern_macro(macro_call_loc) }) 419 Some(Expansion { macro_call_id: db.intern_macro(macro_call_loc) })
413 } 420 }
@@ -421,6 +428,11 @@ impl SourceAnalyzer {
421 pub(crate) fn inference_result(&self) -> Arc<crate::ty::InferenceResult> { 428 pub(crate) fn inference_result(&self) -> Arc<crate::ty::InferenceResult> {
422 self.infer.clone().unwrap() 429 self.infer.clone().unwrap()
423 } 430 }
431
432 #[cfg(test)]
433 pub(crate) fn analyzed_declaration(&self) -> Option<DefWithBody> {
434 self.body_owner
435 }
424} 436}
425 437
426fn scope_for( 438fn scope_for(
@@ -428,7 +440,7 @@ fn scope_for(
428 source_map: &BodySourceMap, 440 source_map: &BodySourceMap,
429 node: Source<&SyntaxNode>, 441 node: Source<&SyntaxNode>,
430) -> Option<ScopeId> { 442) -> Option<ScopeId> {
431 node.ast 443 node.value
432 .ancestors() 444 .ancestors()
433 .filter_map(ast::Expr::cast) 445 .filter_map(ast::Expr::cast)
434 .filter_map(|it| source_map.node_expr(Source::new(node.file_id, &it))) 446 .filter_map(|it| source_map.node_expr(Source::new(node.file_id, &it)))
@@ -450,18 +462,18 @@ fn scope_for_offset(
450 return None; 462 return None;
451 } 463 }
452 let syntax_node_ptr = 464 let syntax_node_ptr =
453 source.ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); 465 source.value.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr());
454 Some((syntax_node_ptr, scope)) 466 Some((syntax_node_ptr, scope))
455 }) 467 })
456 // find containing scope 468 // find containing scope
457 .min_by_key(|(ptr, _scope)| { 469 .min_by_key(|(ptr, _scope)| {
458 ( 470 (
459 !(ptr.range().start() <= offset.ast && offset.ast <= ptr.range().end()), 471 !(ptr.range().start() <= offset.value && offset.value <= ptr.range().end()),
460 ptr.range().len(), 472 ptr.range().len(),
461 ) 473 )
462 }) 474 })
463 .map(|(ptr, scope)| { 475 .map(|(ptr, scope)| {
464 adjust(scopes, source_map, ptr, offset.file_id, offset.ast).unwrap_or(*scope) 476 adjust(scopes, source_map, ptr, offset.file_id, offset.value).unwrap_or(*scope)
465 }) 477 })
466} 478}
467 479
@@ -485,7 +497,7 @@ fn adjust(
485 return None; 497 return None;
486 } 498 }
487 let syntax_node_ptr = 499 let syntax_node_ptr =
488 source.ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); 500 source.value.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr());
489 Some((syntax_node_ptr, scope)) 501 Some((syntax_node_ptr, scope))
490 }) 502 })
491 .map(|(ptr, scope)| (ptr.range(), scope)) 503 .map(|(ptr, scope)| (ptr.range(), scope))
diff --git a/crates/ra_hir/src/traits.rs b/crates/ra_hir/src/traits.rs
deleted file mode 100644
index 1a45dacba..000000000
--- a/crates/ra_hir/src/traits.rs
+++ /dev/null
@@ -1,82 +0,0 @@
1//! HIR for trait definitions.
2
3use std::sync::Arc;
4
5use hir_expand::name::AsName;
6
7use ra_syntax::ast::{self, NameOwner};
8use rustc_hash::FxHashMap;
9
10use crate::{
11 db::{AstDatabase, DefDatabase},
12 ids::LocationCtx,
13 AssocItem, Const, Function, HasSource, Module, Name, Trait, TypeAlias,
14};
15
16#[derive(Debug, Clone, PartialEq, Eq)]
17pub struct TraitData {
18 name: Option<Name>,
19 items: Vec<AssocItem>,
20 auto: bool,
21}
22
23impl TraitData {
24 pub(crate) fn trait_data_query(
25 db: &(impl DefDatabase + AstDatabase),
26 tr: Trait,
27 ) -> Arc<TraitData> {
28 let src = tr.source(db);
29 let name = src.ast.name().map(|n| n.as_name());
30 let module = tr.module(db);
31 let ctx = LocationCtx::new(db, module.id, src.file_id);
32 let auto = src.ast.is_auto();
33 let items = if let Some(item_list) = src.ast.item_list() {
34 item_list
35 .impl_items()
36 .map(|item_node| match item_node {
37 ast::ImplItem::FnDef(it) => Function { id: ctx.to_def(&it) }.into(),
38 ast::ImplItem::ConstDef(it) => Const { id: ctx.to_def(&it) }.into(),
39 ast::ImplItem::TypeAliasDef(it) => TypeAlias { id: ctx.to_def(&it) }.into(),
40 })
41 .collect()
42 } else {
43 Vec::new()
44 };
45 Arc::new(TraitData { name, items, auto })
46 }
47
48 pub(crate) fn name(&self) -> &Option<Name> {
49 &self.name
50 }
51
52 pub(crate) fn items(&self) -> &[AssocItem] {
53 &self.items
54 }
55
56 pub(crate) fn is_auto(&self) -> bool {
57 self.auto
58 }
59}
60
61#[derive(Debug, Clone, PartialEq, Eq)]
62pub struct TraitItemsIndex {
63 traits_by_def: FxHashMap<AssocItem, Trait>,
64}
65
66impl TraitItemsIndex {
67 pub(crate) fn trait_items_index(db: &impl DefDatabase, module: Module) -> TraitItemsIndex {
68 let mut index = TraitItemsIndex { traits_by_def: FxHashMap::default() };
69 for decl in module.declarations(db) {
70 if let crate::ModuleDef::Trait(tr) = decl {
71 for item in tr.trait_data(db).items() {
72 index.traits_by_def.insert(*item, tr);
73 }
74 }
75 }
76 index
77 }
78
79 pub(crate) fn get_parent_trait(&self, item: AssocItem) -> Option<Trait> {
80 self.traits_by_def.get(&item).cloned()
81 }
82}
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index b7f50b714..36ece723f 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -3,8 +3,6 @@
3 3
4mod autoderef; 4mod autoderef;
5pub(crate) mod primitive; 5pub(crate) mod primitive;
6#[cfg(test)]
7mod tests;
8pub(crate) mod traits; 6pub(crate) mod traits;
9pub(crate) mod method_resolution; 7pub(crate) mod method_resolution;
10mod op; 8mod op;
@@ -12,6 +10,9 @@ mod lower;
12mod infer; 10mod infer;
13pub(crate) mod display; 11pub(crate) mod display;
14 12
13#[cfg(test)]
14mod tests;
15
15use std::ops::Deref; 16use std::ops::Deref;
16use std::sync::Arc; 17use std::sync::Arc;
17use std::{fmt, iter, mem}; 18use std::{fmt, iter, mem};
@@ -800,6 +801,10 @@ impl HirDisplay for &Ty {
800 801
801impl HirDisplay for ApplicationTy { 802impl HirDisplay for ApplicationTy {
802 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { 803 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
804 if f.should_truncate() {
805 return write!(f, "…");
806 }
807
803 match self.ctor { 808 match self.ctor {
804 TypeCtor::Bool => write!(f, "bool")?, 809 TypeCtor::Bool => write!(f, "bool")?,
805 TypeCtor::Char => write!(f, "char")?, 810 TypeCtor::Char => write!(f, "char")?,
@@ -901,6 +906,10 @@ impl HirDisplay for ApplicationTy {
901 906
902impl HirDisplay for ProjectionTy { 907impl HirDisplay for ProjectionTy {
903 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { 908 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
909 if f.should_truncate() {
910 return write!(f, "…");
911 }
912
904 let trait_name = self 913 let trait_name = self
905 .associated_ty 914 .associated_ty
906 .parent_trait(f.db) 915 .parent_trait(f.db)
@@ -919,6 +928,10 @@ impl HirDisplay for ProjectionTy {
919 928
920impl HirDisplay for Ty { 929impl HirDisplay for Ty {
921 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { 930 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
931 if f.should_truncate() {
932 return write!(f, "…");
933 }
934
922 match self { 935 match self {
923 Ty::Apply(a_ty) => a_ty.hir_fmt(f)?, 936 Ty::Apply(a_ty) => a_ty.hir_fmt(f)?,
924 Ty::Projection(p_ty) => p_ty.hir_fmt(f)?, 937 Ty::Projection(p_ty) => p_ty.hir_fmt(f)?,
@@ -1001,6 +1014,10 @@ impl HirDisplay for Ty {
1001 1014
1002impl TraitRef { 1015impl TraitRef {
1003 fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result { 1016 fn hir_fmt_ext(&self, f: &mut HirFormatter<impl HirDatabase>, use_as: bool) -> fmt::Result {
1017 if f.should_truncate() {
1018 return write!(f, "…");
1019 }
1020
1004 self.substs[0].hir_fmt(f)?; 1021 self.substs[0].hir_fmt(f)?;
1005 if use_as { 1022 if use_as {
1006 write!(f, " as ")?; 1023 write!(f, " as ")?;
@@ -1031,6 +1048,10 @@ impl HirDisplay for &GenericPredicate {
1031 1048
1032impl HirDisplay for GenericPredicate { 1049impl HirDisplay for GenericPredicate {
1033 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result { 1050 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result {
1051 if f.should_truncate() {
1052 return write!(f, "…");
1053 }
1054
1034 match self { 1055 match self {
1035 GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?, 1056 GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
1036 GenericPredicate::Projection(projection_pred) => { 1057 GenericPredicate::Projection(projection_pred) => {
diff --git a/crates/ra_hir/src/ty/display.rs b/crates/ra_hir/src/ty/display.rs
index 7910429d7..9bb3ece6c 100644
--- a/crates/ra_hir/src/ty/display.rs
+++ b/crates/ra_hir/src/ty/display.rs
@@ -7,15 +7,30 @@ use crate::db::HirDatabase;
7pub struct HirFormatter<'a, 'b, DB> { 7pub struct HirFormatter<'a, 'b, DB> {
8 pub db: &'a DB, 8 pub db: &'a DB,
9 fmt: &'a mut fmt::Formatter<'b>, 9 fmt: &'a mut fmt::Formatter<'b>,
10 buf: String,
11 curr_size: usize,
12 max_size: Option<usize>,
10} 13}
11 14
12pub trait HirDisplay { 15pub trait HirDisplay {
13 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result; 16 fn hir_fmt(&self, f: &mut HirFormatter<impl HirDatabase>) -> fmt::Result;
17
14 fn display<'a, DB>(&'a self, db: &'a DB) -> HirDisplayWrapper<'a, DB, Self> 18 fn display<'a, DB>(&'a self, db: &'a DB) -> HirDisplayWrapper<'a, DB, Self>
15 where 19 where
16 Self: Sized, 20 Self: Sized,
17 { 21 {
18 HirDisplayWrapper(db, self) 22 HirDisplayWrapper(db, self, None)
23 }
24
25 fn display_truncated<'a, DB>(
26 &'a self,
27 db: &'a DB,
28 max_size: Option<usize>,
29 ) -> HirDisplayWrapper<'a, DB, Self>
30 where
31 Self: Sized,
32 {
33 HirDisplayWrapper(db, self, max_size)
19 } 34 }
20} 35}
21 36
@@ -41,11 +56,25 @@ where
41 56
42 /// This allows using the `write!` macro directly with a `HirFormatter`. 57 /// This allows using the `write!` macro directly with a `HirFormatter`.
43 pub fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result { 58 pub fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result {
44 fmt::write(self.fmt, args) 59 // We write to a buffer first to track output size
60 self.buf.clear();
61 fmt::write(&mut self.buf, args)?;
62 self.curr_size += self.buf.len();
63
64 // Then we write to the internal formatter from the buffer
65 self.fmt.write_str(&self.buf)
66 }
67
68 pub fn should_truncate(&self) -> bool {
69 if let Some(max_size) = self.max_size {
70 self.curr_size >= max_size
71 } else {
72 false
73 }
45 } 74 }
46} 75}
47 76
48pub struct HirDisplayWrapper<'a, DB, T>(&'a DB, &'a T); 77pub struct HirDisplayWrapper<'a, DB, T>(&'a DB, &'a T, Option<usize>);
49 78
50impl<'a, DB, T> fmt::Display for HirDisplayWrapper<'a, DB, T> 79impl<'a, DB, T> fmt::Display for HirDisplayWrapper<'a, DB, T>
51where 80where
@@ -53,6 +82,12 @@ where
53 T: HirDisplay, 82 T: HirDisplay,
54{ 83{
55 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 84 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
56 self.1.hir_fmt(&mut HirFormatter { db: self.0, fmt: f }) 85 self.1.hir_fmt(&mut HirFormatter {
86 db: self.0,
87 fmt: f,
88 buf: String::with_capacity(20),
89 curr_size: 0,
90 max_size: self.2,
91 })
57 } 92 }
58} 93}
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index c35378cc4..7f9e81d64 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -37,14 +37,13 @@ use super::{
37 TypeCtor, TypeWalk, Uncertain, 37 TypeCtor, TypeWalk, Uncertain,
38}; 38};
39use crate::{ 39use crate::{
40 adt::VariantDef,
41 code_model::TypeAlias, 40 code_model::TypeAlias,
42 db::HirDatabase, 41 db::HirDatabase,
43 expr::{BindingAnnotation, Body, ExprId, PatId}, 42 expr::{BindingAnnotation, Body, ExprId, PatId},
44 resolve::{Resolver, TypeNs}, 43 resolve::{HasResolver, Resolver, TypeNs},
45 ty::infer::diagnostics::InferenceDiagnostic, 44 ty::infer::diagnostics::InferenceDiagnostic,
46 Adt, AssocItem, ConstData, DefWithBody, FloatTy, FnData, Function, HasBody, IntTy, Path, 45 Adt, AssocItem, ConstData, DefWithBody, FloatTy, FnData, Function, HasBody, IntTy, Path,
47 StructField, 46 StructField, VariantDef,
48}; 47};
49 48
50macro_rules! ty_app { 49macro_rules! ty_app {
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index de3c56097..397ee7d5f 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -19,18 +19,17 @@ use super::{
19 TypeWalk, 19 TypeWalk,
20}; 20};
21use crate::{ 21use crate::{
22 adt::VariantDef,
23 db::HirDatabase, 22 db::HirDatabase,
24 generics::HasGenericParams, 23 generics::HasGenericParams,
25 generics::{GenericDef, WherePredicate}, 24 generics::{GenericDef, WherePredicate},
26 resolve::{Resolver, TypeNs}, 25 resolve::{HasResolver, Resolver, TypeNs},
27 ty::{ 26 ty::{
28 primitive::{FloatTy, IntTy, Uncertain}, 27 primitive::{FloatTy, IntTy, Uncertain},
29 Adt, 28 Adt,
30 }, 29 },
31 util::make_mut_slice, 30 util::make_mut_slice,
32 Const, Enum, EnumVariant, Function, ModuleDef, Path, Static, Struct, StructField, Trait, 31 Const, Enum, EnumVariant, Function, ModuleDef, Path, Static, Struct, StructField, Trait,
33 TypeAlias, Union, 32 TypeAlias, Union, VariantDef,
34}; 33};
35 34
36// FIXME: this is only really used in `type_for_def`, which contains a bunch of 35// FIXME: this is only really used in `type_for_def`, which contains a bunch of
@@ -611,9 +610,7 @@ pub(crate) fn generic_defaults_query(db: &impl HirDatabase, def: GenericDef) ->
611 let defaults = generic_params 610 let defaults = generic_params
612 .params_including_parent() 611 .params_including_parent()
613 .into_iter() 612 .into_iter()
614 .map(|p| { 613 .map(|p| p.default.as_ref().map_or(Ty::Unknown, |t| Ty::from_hir(db, &resolver, t)))
615 p.default.as_ref().map_or(Ty::Unknown, |path| Ty::from_hir_path(db, &resolver, path))
616 })
617 .collect(); 614 .collect();
618 615
619 Substs(defaults) 616 Substs(defaults)
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index d20aeaacf..f377fca48 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -232,8 +232,8 @@ fn iterate_trait_method_candidates<T>(
232 // trait, but if we find out it doesn't, we'll skip the rest of the 232 // trait, but if we find out it doesn't, we'll skip the rest of the
233 // iteration 233 // iteration
234 let mut known_implemented = false; 234 let mut known_implemented = false;
235 for &item in data.items() { 235 for &item in data.items.iter() {
236 if !is_valid_candidate(db, name, mode, item) { 236 if !is_valid_candidate(db, name, mode, item.into()) {
237 continue; 237 continue;
238 } 238 }
239 if !known_implemented { 239 if !known_implemented {
@@ -243,7 +243,7 @@ fn iterate_trait_method_candidates<T>(
243 } 243 }
244 } 244 }
245 known_implemented = true; 245 known_implemented = true;
246 if let Some(result) = callback(&ty.value, item) { 246 if let Some(result) = callback(&ty.value, item.into()) {
247 return Some(result); 247 return Some(result);
248 } 248 }
249 } 249 }
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index ca1693679..74c12a0a2 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -11,6 +11,7 @@ use ra_syntax::{
11 ast::{self, AstNode}, 11 ast::{self, AstNode},
12 SyntaxKind::*, 12 SyntaxKind::*,
13}; 13};
14use rustc_hash::FxHashSet;
14use test_utils::covers; 15use test_utils::covers;
15 16
16use crate::{ 17use crate::{
@@ -1980,6 +1981,30 @@ fn test() {
1980} 1981}
1981 1982
1982#[test] 1983#[test]
1984fn infer_associated_method_generics_with_default_tuple_param() {
1985 let t = type_at(
1986 r#"
1987//- /main.rs
1988struct Gen<T=()> {
1989 val: T
1990}
1991
1992impl<T> Gen<T> {
1993 pub fn make() -> Gen<T> {
1994 loop { }
1995 }
1996}
1997
1998fn test() {
1999 let a = Gen::make();
2000 a.val<|>;
2001}
2002"#,
2003 );
2004 assert_eq!(t, "()");
2005}
2006
2007#[test]
1983fn infer_associated_method_generics_without_args() { 2008fn infer_associated_method_generics_without_args() {
1984 assert_snapshot!( 2009 assert_snapshot!(
1985 infer(r#" 2010 infer(r#"
@@ -2494,7 +2519,6 @@ fn test() {
2494 [167; 179) 'GLOBAL_CONST': u32 2519 [167; 179) 'GLOBAL_CONST': u32
2495 [189; 191) 'id': u32 2520 [189; 191) 'id': u32
2496 [194; 210) 'Foo::A..._CONST': u32 2521 [194; 210) 'Foo::A..._CONST': u32
2497 [126; 128) '99': u32
2498 "### 2522 "###
2499 ); 2523 );
2500} 2524}
@@ -4694,14 +4718,16 @@ fn infer(content: &str) -> String {
4694 } 4718 }
4695 4719
4696 // sort ranges for consistency 4720 // sort ranges for consistency
4697 types.sort_by_key(|(src_ptr, _)| (src_ptr.ast.range().start(), src_ptr.ast.range().end())); 4721 types.sort_by_key(|(src_ptr, _)| {
4722 (src_ptr.value.range().start(), src_ptr.value.range().end())
4723 });
4698 for (src_ptr, ty) in &types { 4724 for (src_ptr, ty) in &types {
4699 let node = src_ptr.ast.to_node(&src_ptr.file_syntax(&db)); 4725 let node = src_ptr.value.to_node(&src_ptr.file_syntax(&db));
4700 4726
4701 let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) { 4727 let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) {
4702 (self_param.self_kw_token().text_range(), "self".to_string()) 4728 (self_param.self_kw_token().text_range(), "self".to_string())
4703 } else { 4729 } else {
4704 (src_ptr.ast.range(), node.text().to_string().replace("\n", " ")) 4730 (src_ptr.value.range(), node.text().to_string().replace("\n", " "))
4705 }; 4731 };
4706 let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" }; 4732 let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" };
4707 write!( 4733 write!(
@@ -4716,10 +4742,13 @@ fn infer(content: &str) -> String {
4716 } 4742 }
4717 }; 4743 };
4718 4744
4745 let mut analyzed = FxHashSet::default();
4719 for node in source_file.syntax().descendants() { 4746 for node in source_file.syntax().descendants() {
4720 if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF { 4747 if node.kind() == FN_DEF || node.kind() == CONST_DEF || node.kind() == STATIC_DEF {
4721 let analyzer = SourceAnalyzer::new(&db, Source::new(file_id.into(), &node), None); 4748 let analyzer = SourceAnalyzer::new(&db, Source::new(file_id.into(), &node), None);
4722 infer_def(analyzer.inference_result(), analyzer.body_source_map()); 4749 if analyzed.insert(analyzer.analyzed_declaration()) {
4750 infer_def(analyzer.inference_result(), analyzer.body_source_map());
4751 }
4723 } 4752 }
4724 } 4753 }
4725 4754
diff --git a/crates/ra_hir/src/type_alias.rs b/crates/ra_hir/src/type_alias.rs
index 078e6295e..392f244cf 100644
--- a/crates/ra_hir/src/type_alias.rs
+++ b/crates/ra_hir/src/type_alias.rs
@@ -23,7 +23,7 @@ impl TypeAliasData {
23 db: &(impl DefDatabase + AstDatabase), 23 db: &(impl DefDatabase + AstDatabase),
24 typ: TypeAlias, 24 typ: TypeAlias,
25 ) -> Arc<TypeAliasData> { 25 ) -> Arc<TypeAliasData> {
26 let node = typ.source(db).ast; 26 let node = typ.source(db).value;
27 let name = node.name().map_or_else(Name::missing, |n| n.as_name()); 27 let name = node.name().map_or_else(Name::missing, |n| n.as_name());
28 let type_ref = node.type_ref().map(TypeRef::from_ast); 28 let type_ref = node.type_ref().map(TypeRef::from_ast);
29 Arc::new(TypeAliasData { name, type_ref }) 29 Arc::new(TypeAliasData { name, type_ref })
diff --git a/crates/ra_hir_def/src/adt.rs b/crates/ra_hir_def/src/adt.rs
index a29c4d41e..d04f54e15 100644
--- a/crates/ra_hir_def/src/adt.rs
+++ b/crates/ra_hir_def/src/adt.rs
@@ -54,8 +54,8 @@ impl StructData {
54 id: StructOrUnionId, 54 id: StructOrUnionId,
55 ) -> Arc<StructData> { 55 ) -> Arc<StructData> {
56 let src = id.source(db); 56 let src = id.source(db);
57 let name = src.ast.name().map(|n| n.as_name()); 57 let name = src.value.name().map(|n| n.as_name());
58 let variant_data = VariantData::new(src.ast.kind()); 58 let variant_data = VariantData::new(src.value.kind());
59 let variant_data = Arc::new(variant_data); 59 let variant_data = Arc::new(variant_data);
60 Arc::new(StructData { name, variant_data }) 60 Arc::new(StructData { name, variant_data })
61 } 61 }
@@ -64,9 +64,9 @@ impl StructData {
64impl EnumData { 64impl EnumData {
65 pub(crate) fn enum_data_query(db: &impl DefDatabase2, e: EnumId) -> Arc<EnumData> { 65 pub(crate) fn enum_data_query(db: &impl DefDatabase2, e: EnumId) -> Arc<EnumData> {
66 let src = e.source(db); 66 let src = e.source(db);
67 let name = src.ast.name().map(|n| n.as_name()); 67 let name = src.value.name().map(|n| n.as_name());
68 let variants = src 68 let variants = src
69 .ast 69 .value
70 .variant_list() 70 .variant_list()
71 .into_iter() 71 .into_iter()
72 .flat_map(|it| it.variants()) 72 .flat_map(|it| it.variants())
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 85dc4feb0..dfb79a30a 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -17,7 +17,7 @@ use crate::{
17 expr::{Expr, ExprId, Pat, PatId}, 17 expr::{Expr, ExprId, Pat, PatId},
18 nameres::CrateDefMap, 18 nameres::CrateDefMap,
19 path::Path, 19 path::Path,
20 AstItemDef, DefWithBodyId, ModuleId, 20 AstItemDef, DefWithBodyId, HasModule, HasSource, Lookup, ModuleId,
21}; 21};
22 22
23pub struct Expander { 23pub struct Expander {
@@ -73,8 +73,8 @@ impl Expander {
73 std::mem::forget(mark); 73 std::mem::forget(mark);
74 } 74 }
75 75
76 fn to_source<T>(&self, ast: T) -> Source<T> { 76 fn to_source<T>(&self, value: T) -> Source<T> {
77 Source { file_id: self.current_file_id, ast } 77 Source { file_id: self.current_file_id, value }
78 } 78 }
79 79
80 fn parse_path(&mut self, path: ast::Path) -> Option<Path> { 80 fn parse_path(&mut self, path: ast::Path) -> Option<Path> {
@@ -149,17 +149,19 @@ impl Body {
149 149
150 let (file_id, module, body) = match def { 150 let (file_id, module, body) = match def {
151 DefWithBodyId::FunctionId(f) => { 151 DefWithBodyId::FunctionId(f) => {
152 let f = f.lookup(db);
152 let src = f.source(db); 153 let src = f.source(db);
153 params = src.ast.param_list(); 154 params = src.value.param_list();
154 (src.file_id, f.module(db), src.ast.body().map(ast::Expr::from)) 155 (src.file_id, f.module(db), src.value.body().map(ast::Expr::from))
155 } 156 }
156 DefWithBodyId::ConstId(c) => { 157 DefWithBodyId::ConstId(c) => {
158 let c = c.lookup(db);
157 let src = c.source(db); 159 let src = c.source(db);
158 (src.file_id, c.module(db), src.ast.body()) 160 (src.file_id, c.module(db), src.value.body())
159 } 161 }
160 DefWithBodyId::StaticId(s) => { 162 DefWithBodyId::StaticId(s) => {
161 let src = s.source(db); 163 let src = s.source(db);
162 (src.file_id, s.module(db), src.ast.body()) 164 (src.file_id, s.module(db), src.value.body())
163 } 165 }
164 }; 166 };
165 let expander = Expander::new(db, file_id, module); 167 let expander = Expander::new(db, file_id, module);
diff --git a/crates/ra_hir_def/src/body/scope.rs b/crates/ra_hir_def/src/body/scope.rs
index 10cb87d37..aeb71ff22 100644
--- a/crates/ra_hir_def/src/body/scope.rs
+++ b/crates/ra_hir_def/src/body/scope.rs
@@ -210,8 +210,9 @@ mod tests {
210 let scopes = db.expr_scopes(function.into()); 210 let scopes = db.expr_scopes(function.into());
211 let (_body, source_map) = db.body_with_source_map(function.into()); 211 let (_body, source_map) = db.body_with_source_map(function.into());
212 212
213 let expr_id = 213 let expr_id = source_map
214 source_map.node_expr(Source { file_id: file_id.into(), ast: &marker.into() }).unwrap(); 214 .node_expr(Source { file_id: file_id.into(), value: &marker.into() })
215 .unwrap();
215 let scope = scopes.scope_for(expr_id); 216 let scope = scopes.scope_for(expr_id);
216 217
217 let actual = scopes 218 let actual = scopes
@@ -317,14 +318,14 @@ mod tests {
317 let expr_scope = { 318 let expr_scope = {
318 let expr_ast = name_ref.syntax().ancestors().find_map(ast::Expr::cast).unwrap(); 319 let expr_ast = name_ref.syntax().ancestors().find_map(ast::Expr::cast).unwrap();
319 let expr_id = 320 let expr_id =
320 source_map.node_expr(Source { file_id: file_id.into(), ast: &expr_ast }).unwrap(); 321 source_map.node_expr(Source { file_id: file_id.into(), value: &expr_ast }).unwrap();
321 scopes.scope_for(expr_id).unwrap() 322 scopes.scope_for(expr_id).unwrap()
322 }; 323 };
323 324
324 let resolved = scopes.resolve_name_in_scope(expr_scope, &name_ref.as_name()).unwrap(); 325 let resolved = scopes.resolve_name_in_scope(expr_scope, &name_ref.as_name()).unwrap();
325 let pat_src = source_map.pat_syntax(resolved.pat()).unwrap(); 326 let pat_src = source_map.pat_syntax(resolved.pat()).unwrap();
326 327
327 let local_name = pat_src.ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()); 328 let local_name = pat_src.value.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr());
328 assert_eq!(local_name.range(), expected_name.syntax().text_range()); 329 assert_eq!(local_name.range(), expected_name.syntax().text_range());
329 } 330 }
330 331
diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs
index 348aca07f..844f8bbe8 100644
--- a/crates/ra_hir_def/src/db.rs
+++ b/crates/ra_hir_def/src/db.rs
@@ -8,30 +8,32 @@ use ra_syntax::ast;
8use crate::{ 8use crate::{
9 adt::{EnumData, StructData}, 9 adt::{EnumData, StructData},
10 body::{scope::ExprScopes, Body, BodySourceMap}, 10 body::{scope::ExprScopes, Body, BodySourceMap},
11 imp::ImplData, 11 generics::GenericParams,
12 impls::ImplData,
12 nameres::{ 13 nameres::{
13 raw::{ImportSourceMap, RawItems}, 14 raw::{ImportSourceMap, RawItems},
14 CrateDefMap, 15 CrateDefMap,
15 }, 16 },
16 DefWithBodyId, EnumId, ImplId, ItemLoc, StructOrUnionId, 17 traits::TraitData,
18 DefWithBodyId, EnumId, GenericDefId, ImplId, ItemLoc, StructOrUnionId, TraitId,
17}; 19};
18 20
19#[salsa::query_group(InternDatabaseStorage)] 21#[salsa::query_group(InternDatabaseStorage)]
20pub trait InternDatabase: SourceDatabase { 22pub trait InternDatabase: SourceDatabase {
21 #[salsa::interned] 23 #[salsa::interned]
22 fn intern_function(&self, loc: ItemLoc<ast::FnDef>) -> crate::FunctionId; 24 fn intern_function(&self, loc: crate::FunctionLoc) -> crate::FunctionId;
23 #[salsa::interned] 25 #[salsa::interned]
24 fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> crate::StructOrUnionId; 26 fn intern_struct_or_union(&self, loc: ItemLoc<ast::StructDef>) -> crate::StructOrUnionId;
25 #[salsa::interned] 27 #[salsa::interned]
26 fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> crate::EnumId; 28 fn intern_enum(&self, loc: ItemLoc<ast::EnumDef>) -> crate::EnumId;
27 #[salsa::interned] 29 #[salsa::interned]
28 fn intern_const(&self, loc: ItemLoc<ast::ConstDef>) -> crate::ConstId; 30 fn intern_const(&self, loc: crate::ConstLoc) -> crate::ConstId;
29 #[salsa::interned] 31 #[salsa::interned]
30 fn intern_static(&self, loc: ItemLoc<ast::StaticDef>) -> crate::StaticId; 32 fn intern_static(&self, loc: ItemLoc<ast::StaticDef>) -> crate::StaticId;
31 #[salsa::interned] 33 #[salsa::interned]
32 fn intern_trait(&self, loc: ItemLoc<ast::TraitDef>) -> crate::TraitId; 34 fn intern_trait(&self, loc: ItemLoc<ast::TraitDef>) -> crate::TraitId;
33 #[salsa::interned] 35 #[salsa::interned]
34 fn intern_type_alias(&self, loc: ItemLoc<ast::TypeAliasDef>) -> crate::TypeAliasId; 36 fn intern_type_alias(&self, loc: crate::TypeAliasLoc) -> crate::TypeAliasId;
35 #[salsa::interned] 37 #[salsa::interned]
36 fn intern_impl(&self, loc: ItemLoc<ast::ImplBlock>) -> crate::ImplId; 38 fn intern_impl(&self, loc: ItemLoc<ast::ImplBlock>) -> crate::ImplId;
37} 39}
@@ -59,6 +61,9 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
59 #[salsa::invoke(ImplData::impl_data_query)] 61 #[salsa::invoke(ImplData::impl_data_query)]
60 fn impl_data(&self, e: ImplId) -> Arc<ImplData>; 62 fn impl_data(&self, e: ImplId) -> Arc<ImplData>;
61 63
64 #[salsa::invoke(TraitData::trait_data_query)]
65 fn trait_data(&self, e: TraitId) -> Arc<TraitData>;
66
62 #[salsa::invoke(Body::body_with_source_map_query)] 67 #[salsa::invoke(Body::body_with_source_map_query)]
63 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>); 68 fn body_with_source_map(&self, def: DefWithBodyId) -> (Arc<Body>, Arc<BodySourceMap>);
64 69
@@ -67,4 +72,7 @@ pub trait DefDatabase2: InternDatabase + AstDatabase {
67 72
68 #[salsa::invoke(ExprScopes::expr_scopes_query)] 73 #[salsa::invoke(ExprScopes::expr_scopes_query)]
69 fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>; 74 fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>;
75
76 #[salsa::invoke(GenericParams::generic_params_query)]
77 fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>;
70} 78}
diff --git a/crates/ra_hir_def/src/diagnostics.rs b/crates/ra_hir_def/src/diagnostics.rs
index 9843009a5..eda9b2269 100644
--- a/crates/ra_hir_def/src/diagnostics.rs
+++ b/crates/ra_hir_def/src/diagnostics.rs
@@ -20,7 +20,7 @@ impl Diagnostic for UnresolvedModule {
20 "unresolved module".to_string() 20 "unresolved module".to_string()
21 } 21 }
22 fn source(&self) -> Source<SyntaxNodePtr> { 22 fn source(&self) -> Source<SyntaxNodePtr> {
23 Source { file_id: self.file, ast: self.decl.into() } 23 Source { file_id: self.file, value: self.decl.into() }
24 } 24 }
25 fn as_any(&self) -> &(dyn Any + Send + 'static) { 25 fn as_any(&self) -> &(dyn Any + Send + 'static) {
26 self 26 self
diff --git a/crates/ra_hir_def/src/generics.rs b/crates/ra_hir_def/src/generics.rs
new file mode 100644
index 000000000..9e2e4c3cc
--- /dev/null
+++ b/crates/ra_hir_def/src/generics.rs
@@ -0,0 +1,185 @@
1//! Many kinds of items or constructs can have generic parameters: functions,
2//! structs, impls, traits, etc. This module provides a common HIR for these
3//! generic parameters. See also the `Generics` type and the `generics_of` query
4//! in rustc.
5use std::sync::Arc;
6
7use hir_expand::name::{self, AsName, Name};
8use ra_syntax::ast::{self, NameOwner, TypeBoundsOwner, TypeParamsOwner};
9
10use crate::{
11 db::DefDatabase2,
12 type_ref::{TypeBound, TypeRef},
13 AdtId, AstItemDef, ContainerId, GenericDefId, HasSource, Lookup,
14};
15
16/// Data about a generic parameter (to a function, struct, impl, ...).
17#[derive(Clone, PartialEq, Eq, Debug)]
18pub struct GenericParam {
19 // FIXME: give generic params proper IDs
20 pub idx: u32,
21 pub name: Name,
22 pub default: Option<TypeRef>,
23}
24
25/// Data about the generic parameters of a function, struct, impl, etc.
26#[derive(Clone, PartialEq, Eq, Debug)]
27pub struct GenericParams {
28 pub parent_params: Option<Arc<GenericParams>>,
29 pub params: Vec<GenericParam>,
30 pub where_predicates: Vec<WherePredicate>,
31}
32
33/// A single predicate from a where clause, i.e. `where Type: Trait`. Combined
34/// where clauses like `where T: Foo + Bar` are turned into multiple of these.
35/// It might still result in multiple actual predicates though, because of
36/// associated type bindings like `Iterator<Item = u32>`.
37#[derive(Clone, PartialEq, Eq, Debug)]
38pub struct WherePredicate {
39 pub type_ref: TypeRef,
40 pub bound: TypeBound,
41}
42
43impl GenericParams {
44 pub(crate) fn generic_params_query(
45 db: &impl DefDatabase2,
46 def: GenericDefId,
47 ) -> Arc<GenericParams> {
48 let parent_generics = parent_generic_def(db, def).map(|it| db.generic_params(it));
49 Arc::new(GenericParams::new(db, def.into(), parent_generics))
50 }
51
52 fn new(
53 db: &impl DefDatabase2,
54 def: GenericDefId,
55 parent_params: Option<Arc<GenericParams>>,
56 ) -> GenericParams {
57 let mut generics =
58 GenericParams { params: Vec::new(), parent_params, where_predicates: Vec::new() };
59 let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32;
60 // FIXME: add `: Sized` bound for everything except for `Self` in traits
61 match def {
62 GenericDefId::FunctionId(it) => generics.fill(&it.lookup(db).source(db).value, start),
63 GenericDefId::AdtId(AdtId::StructId(it)) => {
64 generics.fill(&it.0.source(db).value, start)
65 }
66 GenericDefId::AdtId(AdtId::UnionId(it)) => generics.fill(&it.0.source(db).value, start),
67 GenericDefId::AdtId(AdtId::EnumId(it)) => generics.fill(&it.source(db).value, start),
68 GenericDefId::TraitId(it) => {
69 // traits get the Self type as an implicit first type parameter
70 generics.params.push(GenericParam {
71 idx: start,
72 name: name::SELF_TYPE,
73 default: None,
74 });
75 generics.fill(&it.source(db).value, start + 1);
76 // add super traits as bounds on Self
77 // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar
78 let self_param = TypeRef::Path(name::SELF_TYPE.into());
79 generics.fill_bounds(&it.source(db).value, self_param);
80 }
81 GenericDefId::TypeAliasId(it) => generics.fill(&it.lookup(db).source(db).value, start),
82 // Note that we don't add `Self` here: in `impl`s, `Self` is not a
83 // type-parameter, but rather is a type-alias for impl's target
84 // type, so this is handled by the resolver.
85 GenericDefId::ImplId(it) => generics.fill(&it.source(db).value, start),
86 GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {}
87 }
88
89 generics
90 }
91
92 fn fill(&mut self, node: &impl TypeParamsOwner, start: u32) {
93 if let Some(params) = node.type_param_list() {
94 self.fill_params(params, start)
95 }
96 if let Some(where_clause) = node.where_clause() {
97 self.fill_where_predicates(where_clause);
98 }
99 }
100
101 fn fill_bounds(&mut self, node: &impl ast::TypeBoundsOwner, type_ref: TypeRef) {
102 for bound in
103 node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds())
104 {
105 self.add_where_predicate_from_bound(bound, type_ref.clone());
106 }
107 }
108
109 fn fill_params(&mut self, params: ast::TypeParamList, start: u32) {
110 for (idx, type_param) in params.type_params().enumerate() {
111 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
112 // FIXME: Use `Path::from_src`
113 let default = type_param.default_type().map(TypeRef::from_ast);
114 let param = GenericParam { idx: idx as u32 + start, name: name.clone(), default };
115 self.params.push(param);
116
117 let type_ref = TypeRef::Path(name.into());
118 self.fill_bounds(&type_param, type_ref);
119 }
120 }
121
122 fn fill_where_predicates(&mut self, where_clause: ast::WhereClause) {
123 for pred in where_clause.predicates() {
124 let type_ref = match pred.type_ref() {
125 Some(type_ref) => type_ref,
126 None => continue,
127 };
128 let type_ref = TypeRef::from_ast(type_ref);
129 for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) {
130 self.add_where_predicate_from_bound(bound, type_ref.clone());
131 }
132 }
133 }
134
135 fn add_where_predicate_from_bound(&mut self, bound: ast::TypeBound, type_ref: TypeRef) {
136 if bound.has_question_mark() {
137 // FIXME: remove this bound
138 return;
139 }
140 let bound = TypeBound::from_ast(bound);
141 self.where_predicates.push(WherePredicate { type_ref, bound });
142 }
143
144 pub fn find_by_name(&self, name: &Name) -> Option<&GenericParam> {
145 self.params.iter().find(|p| &p.name == name)
146 }
147
148 pub fn count_parent_params(&self) -> usize {
149 self.parent_params.as_ref().map(|p| p.count_params_including_parent()).unwrap_or(0)
150 }
151
152 pub fn count_params_including_parent(&self) -> usize {
153 let parent_count = self.count_parent_params();
154 parent_count + self.params.len()
155 }
156
157 fn for_each_param<'a>(&'a self, f: &mut impl FnMut(&'a GenericParam)) {
158 if let Some(parent) = &self.parent_params {
159 parent.for_each_param(f);
160 }
161 self.params.iter().for_each(f);
162 }
163
164 pub fn params_including_parent(&self) -> Vec<&GenericParam> {
165 let mut vec = Vec::with_capacity(self.count_params_including_parent());
166 self.for_each_param(&mut |p| vec.push(p));
167 vec
168 }
169}
170
171fn parent_generic_def(db: &impl DefDatabase2, def: GenericDefId) -> Option<GenericDefId> {
172 let container = match def {
173 GenericDefId::FunctionId(it) => it.lookup(db).container,
174 GenericDefId::TypeAliasId(it) => it.lookup(db).container,
175 GenericDefId::ConstId(it) => it.lookup(db).container,
176 GenericDefId::EnumVariantId(it) => return Some(it.parent.into()),
177 GenericDefId::AdtId(_) | GenericDefId::TraitId(_) | GenericDefId::ImplId(_) => return None,
178 };
179
180 match container {
181 ContainerId::ImplId(it) => Some(it.into()),
182 ContainerId::TraitId(it) => Some(it.into()),
183 ContainerId::ModuleId(_) => None,
184 }
185}
diff --git a/crates/ra_hir_def/src/imp.rs b/crates/ra_hir_def/src/impls.rs
index 717991c40..750a869f2 100644
--- a/crates/ra_hir_def/src/imp.rs
+++ b/crates/ra_hir_def/src/impls.rs
@@ -5,11 +5,12 @@
5 5
6use std::sync::Arc; 6use std::sync::Arc;
7 7
8use hir_expand::AstId;
8use ra_syntax::ast; 9use ra_syntax::ast;
9 10
10use crate::{ 11use crate::{
11 db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstId, FunctionId, ImplId, 12 db::DefDatabase2, type_ref::TypeRef, AssocItemId, AstItemDef, ConstLoc, ContainerId,
12 LocationCtx, TypeAliasId, 13 FunctionLoc, ImplId, Intern, TypeAliasLoc,
13}; 14};
14 15
15#[derive(Debug, Clone, PartialEq, Eq)] 16#[derive(Debug, Clone, PartialEq, Eq)]
@@ -25,23 +26,37 @@ impl ImplData {
25 let src = id.source(db); 26 let src = id.source(db);
26 let items = db.ast_id_map(src.file_id); 27 let items = db.ast_id_map(src.file_id);
27 28
28 let target_trait = src.ast.target_trait().map(TypeRef::from_ast); 29 let target_trait = src.value.target_trait().map(TypeRef::from_ast);
29 let target_type = TypeRef::from_ast_opt(src.ast.target_type()); 30 let target_type = TypeRef::from_ast_opt(src.value.target_type());
30 let negative = src.ast.is_negative(); 31 let negative = src.value.is_negative();
31 32
32 let items = if let Some(item_list) = src.ast.item_list() { 33 let items = if let Some(item_list) = src.value.item_list() {
33 let ctx = LocationCtx::new(db, id.module(db), src.file_id);
34 item_list 34 item_list
35 .impl_items() 35 .impl_items()
36 .map(|item_node| match item_node { 36 .map(|item_node| match item_node {
37 ast::ImplItem::FnDef(it) => { 37 ast::ImplItem::FnDef(it) => {
38 FunctionId::from_ast_id(ctx, items.ast_id(&it)).into() 38 let def = FunctionLoc {
39 container: ContainerId::ImplId(id),
40 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
41 }
42 .intern(db);
43 def.into()
39 } 44 }
40 ast::ImplItem::ConstDef(it) => { 45 ast::ImplItem::ConstDef(it) => {
41 ConstId::from_ast_id(ctx, items.ast_id(&it)).into() 46 let def = ConstLoc {
47 container: ContainerId::ImplId(id),
48 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
49 }
50 .intern(db);
51 def.into()
42 } 52 }
43 ast::ImplItem::TypeAliasDef(it) => { 53 ast::ImplItem::TypeAliasDef(it) => {
44 TypeAliasId::from_ast_id(ctx, items.ast_id(&it)).into() 54 let def = TypeAliasLoc {
55 container: ContainerId::ImplId(id),
56 ast_id: AstId::new(src.file_id, items.ast_id(&it)),
57 }
58 .intern(db);
59 def.into()
45 } 60 }
46 }) 61 })
47 .collect() 62 .collect()
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index a240a10b8..0af41de87 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -13,10 +13,12 @@ pub mod path;
13pub mod type_ref; 13pub mod type_ref;
14pub mod builtin_type; 14pub mod builtin_type;
15pub mod adt; 15pub mod adt;
16pub mod imp; 16pub mod impls;
17pub mod diagnostics; 17pub mod diagnostics;
18pub mod expr; 18pub mod expr;
19pub mod body; 19pub mod body;
20pub mod generics;
21pub mod traits;
20 22
21#[cfg(test)] 23#[cfg(test)]
22mod test_db; 24mod test_db;
@@ -80,7 +82,7 @@ impl ModuleSource {
80 82
81 pub fn from_child_node(db: &impl db::DefDatabase2, child: Source<&SyntaxNode>) -> ModuleSource { 83 pub fn from_child_node(db: &impl db::DefDatabase2, child: Source<&SyntaxNode>) -> ModuleSource {
82 if let Some(m) = 84 if let Some(m) =
83 child.ast.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) 85 child.value.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi())
84 { 86 {
85 ModuleSource::Module(m) 87 ModuleSource::Module(m)
86 } else { 88 } else {
@@ -184,8 +186,8 @@ pub trait AstItemDef<N: AstNode>: salsa::InternKey + Clone {
184 } 186 }
185 fn source(self, db: &(impl AstDatabase + InternDatabase)) -> Source<N> { 187 fn source(self, db: &(impl AstDatabase + InternDatabase)) -> Source<N> {
186 let loc = self.lookup_intern(db); 188 let loc = self.lookup_intern(db);
187 let ast = loc.ast_id.to_node(db); 189 let value = loc.ast_id.to_node(db);
188 Source { file_id: loc.ast_id.file_id(), ast } 190 Source { file_id: loc.ast_id.file_id(), value }
189 } 191 }
190 fn module(self, db: &impl InternDatabase) -> ModuleId { 192 fn module(self, db: &impl InternDatabase) -> ModuleId {
191 let loc = self.lookup_intern(db); 193 let loc = self.lookup_intern(db);
@@ -197,12 +199,23 @@ pub trait AstItemDef<N: AstNode>: salsa::InternKey + Clone {
197pub struct FunctionId(salsa::InternId); 199pub struct FunctionId(salsa::InternId);
198impl_intern_key!(FunctionId); 200impl_intern_key!(FunctionId);
199 201
200impl AstItemDef<ast::FnDef> for FunctionId { 202#[derive(Debug, Clone, PartialEq, Eq, Hash)]
201 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::FnDef>) -> Self { 203pub struct FunctionLoc {
202 db.intern_function(loc) 204 pub container: ContainerId,
205 pub ast_id: AstId<ast::FnDef>,
206}
207
208impl Intern for FunctionLoc {
209 type ID = FunctionId;
210 fn intern(self, db: &impl db::DefDatabase2) -> FunctionId {
211 db.intern_function(self)
203 } 212 }
204 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::FnDef> { 213}
205 db.lookup_intern_function(self) 214
215impl Lookup for FunctionId {
216 type Data = FunctionLoc;
217 fn lookup(&self, db: &impl db::DefDatabase2) -> FunctionLoc {
218 db.lookup_intern_function(*self)
206 } 219 }
207} 220}
208 221
@@ -276,12 +289,23 @@ impl_arena_id!(LocalStructFieldId);
276#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 289#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
277pub struct ConstId(salsa::InternId); 290pub struct ConstId(salsa::InternId);
278impl_intern_key!(ConstId); 291impl_intern_key!(ConstId);
279impl AstItemDef<ast::ConstDef> for ConstId { 292#[derive(Debug, Clone, PartialEq, Eq, Hash)]
280 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::ConstDef>) -> Self { 293pub struct ConstLoc {
281 db.intern_const(loc) 294 pub container: ContainerId,
295 pub ast_id: AstId<ast::ConstDef>,
296}
297
298impl Intern for ConstLoc {
299 type ID = ConstId;
300 fn intern(self, db: &impl db::DefDatabase2) -> ConstId {
301 db.intern_const(self)
282 } 302 }
283 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::ConstDef> { 303}
284 db.lookup_intern_const(self) 304
305impl Lookup for ConstId {
306 type Data = ConstLoc;
307 fn lookup(&self, db: &impl db::DefDatabase2) -> ConstLoc {
308 db.lookup_intern_const(*self)
285 } 309 }
286} 310}
287 311
@@ -312,12 +336,24 @@ impl AstItemDef<ast::TraitDef> for TraitId {
312#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 336#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
313pub struct TypeAliasId(salsa::InternId); 337pub struct TypeAliasId(salsa::InternId);
314impl_intern_key!(TypeAliasId); 338impl_intern_key!(TypeAliasId);
315impl AstItemDef<ast::TypeAliasDef> for TypeAliasId { 339
316 fn intern(db: &impl InternDatabase, loc: ItemLoc<ast::TypeAliasDef>) -> Self { 340#[derive(Debug, Clone, PartialEq, Eq, Hash)]
317 db.intern_type_alias(loc) 341pub struct TypeAliasLoc {
342 pub container: ContainerId,
343 pub ast_id: AstId<ast::TypeAliasDef>,
344}
345
346impl Intern for TypeAliasLoc {
347 type ID = TypeAliasId;
348 fn intern(self, db: &impl db::DefDatabase2) -> TypeAliasId {
349 db.intern_type_alias(self)
318 } 350 }
319 fn lookup_intern(self, db: &impl InternDatabase) -> ItemLoc<ast::TypeAliasDef> { 351}
320 db.lookup_intern_type_alias(self) 352
353impl Lookup for TypeAliasId {
354 type Data = TypeAliasLoc;
355 fn lookup(&self, db: &impl db::DefDatabase2) -> TypeAliasLoc {
356 db.lookup_intern_type_alias(*self)
321 } 357 }
322} 358}
323 359
@@ -352,6 +388,13 @@ macro_rules! impl_froms {
352 } 388 }
353} 389}
354 390
391#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
392pub enum ContainerId {
393 ModuleId(ModuleId),
394 ImplId(ImplId),
395 TraitId(TraitId),
396}
397
355/// A Data Type 398/// A Data Type
356#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] 399#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
357pub enum AdtId { 400pub enum AdtId {
@@ -408,3 +451,102 @@ pub enum AssocItemId {
408// require not implementing From, and instead having some checked way of 451// require not implementing From, and instead having some checked way of
409// casting them, and somehow making the constructors private, which would be annoying. 452// casting them, and somehow making the constructors private, which would be annoying.
410impl_froms!(AssocItemId: FunctionId, ConstId, TypeAliasId); 453impl_froms!(AssocItemId: FunctionId, ConstId, TypeAliasId);
454
455#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash)]
456pub enum GenericDefId {
457 FunctionId(FunctionId),
458 AdtId(AdtId),
459 TraitId(TraitId),
460 TypeAliasId(TypeAliasId),
461 ImplId(ImplId),
462 // enum variants cannot have generics themselves, but their parent enums
463 // can, and this makes some code easier to write
464 EnumVariantId(EnumVariantId),
465 // consts can have type parameters from their parents (i.e. associated consts of traits)
466 ConstId(ConstId),
467}
468impl_froms!(
469 GenericDefId: FunctionId,
470 AdtId(StructId, EnumId, UnionId),
471 TraitId,
472 TypeAliasId,
473 ImplId,
474 EnumVariantId,
475 ConstId
476);
477
478trait Intern {
479 type ID;
480 fn intern(self, db: &impl db::DefDatabase2) -> Self::ID;
481}
482
483pub trait Lookup {
484 type Data;
485 fn lookup(&self, db: &impl db::DefDatabase2) -> Self::Data;
486}
487
488pub trait HasModule {
489 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId;
490}
491
492impl HasModule for FunctionLoc {
493 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId {
494 match self.container {
495 ContainerId::ModuleId(it) => it,
496 ContainerId::ImplId(it) => it.module(db),
497 ContainerId::TraitId(it) => it.module(db),
498 }
499 }
500}
501
502impl HasModule for TypeAliasLoc {
503 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId {
504 match self.container {
505 ContainerId::ModuleId(it) => it,
506 ContainerId::ImplId(it) => it.module(db),
507 ContainerId::TraitId(it) => it.module(db),
508 }
509 }
510}
511
512impl HasModule for ConstLoc {
513 fn module(&self, db: &impl db::DefDatabase2) -> ModuleId {
514 match self.container {
515 ContainerId::ModuleId(it) => it,
516 ContainerId::ImplId(it) => it.module(db),
517 ContainerId::TraitId(it) => it.module(db),
518 }
519 }
520}
521
522pub trait HasSource {
523 type Value;
524 fn source(&self, db: &impl db::DefDatabase2) -> Source<Self::Value>;
525}
526
527impl HasSource for FunctionLoc {
528 type Value = ast::FnDef;
529
530 fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::FnDef> {
531 let node = self.ast_id.to_node(db);
532 Source::new(self.ast_id.file_id(), node)
533 }
534}
535
536impl HasSource for TypeAliasLoc {
537 type Value = ast::TypeAliasDef;
538
539 fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::TypeAliasDef> {
540 let node = self.ast_id.to_node(db);
541 Source::new(self.ast_id.file_id(), node)
542 }
543}
544
545impl HasSource for ConstLoc {
546 type Value = ast::ConstDef;
547
548 fn source(&self, db: &impl db::DefDatabase2) -> Source<ast::ConstDef> {
549 let node = self.ast_id.to_node(db);
550 Source::new(self.ast_id.file_id(), node)
551 }
552}
diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs
index e5b073a0f..c01e020ef 100644
--- a/crates/ra_hir_def/src/nameres.rs
+++ b/crates/ra_hir_def/src/nameres.rs
@@ -165,6 +165,14 @@ impl ModuleScope {
165 self.items.iter().chain(BUILTIN_SCOPE.iter()) 165 self.items.iter().chain(BUILTIN_SCOPE.iter())
166 } 166 }
167 167
168 pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
169 self.entries()
170 .filter_map(|(_name, res)| if res.import.is_none() { Some(res.def) } else { None })
171 .flat_map(|per_ns| {
172 per_ns.take_types().into_iter().chain(per_ns.take_values().into_iter())
173 })
174 }
175
168 /// Iterate over all module scoped macros 176 /// Iterate over all module scoped macros
169 pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a { 177 pub fn macros<'a>(&'a self) -> impl Iterator<Item = (&'a Name, MacroDefId)> + 'a {
170 self.items 178 self.items
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 8f426b097..aae3dcadf 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -19,9 +19,9 @@ use crate::{
19 per_ns::PerNs, raw, CrateDefMap, ModuleData, Resolution, ResolveMode, 19 per_ns::PerNs, raw, CrateDefMap, ModuleData, Resolution, ResolveMode,
20 }, 20 },
21 path::{Path, PathKind}, 21 path::{Path, PathKind},
22 AdtId, AstId, AstItemDef, ConstId, CrateModuleId, EnumId, EnumVariantId, FunctionId, ImplId, 22 AdtId, AstId, AstItemDef, ConstLoc, ContainerId, CrateModuleId, EnumId, EnumVariantId,
23 LocationCtx, ModuleDefId, ModuleId, StaticId, StructId, StructOrUnionId, TraitId, TypeAliasId, 23 FunctionLoc, ImplId, Intern, LocationCtx, ModuleDefId, ModuleId, StaticId, StructId,
24 UnionId, 24 StructOrUnionId, TraitId, TypeAliasLoc, UnionId,
25}; 25};
26 26
27pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap { 27pub(super) fn collect_defs(db: &impl DefDatabase2, mut def_map: CrateDefMap) -> CrateDefMap {
@@ -673,8 +673,13 @@ where
673 let name = def.name.clone(); 673 let name = def.name.clone();
674 let def: PerNs = match def.kind { 674 let def: PerNs = match def.kind {
675 raw::DefKind::Function(ast_id) => { 675 raw::DefKind::Function(ast_id) => {
676 let f = FunctionId::from_ast_id(ctx, ast_id); 676 let def = FunctionLoc {
677 PerNs::values(f.into()) 677 container: ContainerId::ModuleId(module),
678 ast_id: AstId::new(self.file_id, ast_id),
679 }
680 .intern(self.def_collector.db);
681
682 PerNs::values(def.into())
678 } 683 }
679 raw::DefKind::Struct(ast_id) => { 684 raw::DefKind::Struct(ast_id) => {
680 let id = StructOrUnionId::from_ast_id(ctx, ast_id).into(); 685 let id = StructOrUnionId::from_ast_id(ctx, ast_id).into();
@@ -687,13 +692,27 @@ where
687 PerNs::both(u, u) 692 PerNs::both(u, u)
688 } 693 }
689 raw::DefKind::Enum(ast_id) => PerNs::types(EnumId::from_ast_id(ctx, ast_id).into()), 694 raw::DefKind::Enum(ast_id) => PerNs::types(EnumId::from_ast_id(ctx, ast_id).into()),
690 raw::DefKind::Const(ast_id) => PerNs::values(ConstId::from_ast_id(ctx, ast_id).into()), 695 raw::DefKind::Const(ast_id) => {
696 let def = ConstLoc {
697 container: ContainerId::ModuleId(module),
698 ast_id: AstId::new(self.file_id, ast_id),
699 }
700 .intern(self.def_collector.db);
701
702 PerNs::values(def.into())
703 }
691 raw::DefKind::Static(ast_id) => { 704 raw::DefKind::Static(ast_id) => {
692 PerNs::values(StaticId::from_ast_id(ctx, ast_id).into()) 705 PerNs::values(StaticId::from_ast_id(ctx, ast_id).into())
693 } 706 }
694 raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()), 707 raw::DefKind::Trait(ast_id) => PerNs::types(TraitId::from_ast_id(ctx, ast_id).into()),
695 raw::DefKind::TypeAlias(ast_id) => { 708 raw::DefKind::TypeAlias(ast_id) => {
696 PerNs::types(TypeAliasId::from_ast_id(ctx, ast_id).into()) 709 let def = TypeAliasLoc {
710 container: ContainerId::ModuleId(module),
711 ast_id: AstId::new(self.file_id, ast_id),
712 }
713 .intern(self.def_collector.db);
714
715 PerNs::types(def.into())
697 } 716 }
698 }; 717 };
699 let resolution = Resolution { def, import: None }; 718 let resolution = Resolution { def, import: None };
diff --git a/crates/ra_hir_def/src/nameres/raw.rs b/crates/ra_hir_def/src/nameres/raw.rs
index a0a2c7273..7c68fd638 100644
--- a/crates/ra_hir_def/src/nameres/raw.rs
+++ b/crates/ra_hir_def/src/nameres/raw.rs
@@ -327,7 +327,7 @@ impl RawItemsCollector {
327 327
328 let mut buf = Vec::new(); 328 let mut buf = Vec::new();
329 Path::expand_use_item( 329 Path::expand_use_item(
330 Source { ast: use_item, file_id: self.file_id }, 330 Source { value: use_item, file_id: self.file_id },
331 &self.hygiene, 331 &self.hygiene,
332 |path, use_tree, is_glob, alias| { 332 |path, use_tree, is_glob, alias| {
333 let import_data = ImportData { 333 let import_data = ImportData {
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index 04039376f..626ebffdc 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -71,7 +71,7 @@ impl Path {
71 hygiene: &Hygiene, 71 hygiene: &Hygiene,
72 mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>), 72 mut cb: impl FnMut(Path, &ast::UseTree, bool, Option<Name>),
73 ) { 73 ) {
74 if let Some(tree) = item_src.ast.use_tree() { 74 if let Some(tree) = item_src.value.use_tree() {
75 expand_use_tree(None, tree, hygiene, &mut cb); 75 expand_use_tree(None, tree, hygiene, &mut cb);
76 } 76 }
77 } 77 }
diff --git a/crates/ra_hir_def/src/traits.rs b/crates/ra_hir_def/src/traits.rs
new file mode 100644
index 000000000..877d73d66
--- /dev/null
+++ b/crates/ra_hir_def/src/traits.rs
@@ -0,0 +1,59 @@
1//! HIR for trait definitions.
2
3use std::sync::Arc;
4
5use hir_expand::{
6 name::{AsName, Name},
7 AstId,
8};
9
10use ra_syntax::ast::{self, NameOwner};
11
12use crate::{
13 db::DefDatabase2, AssocItemId, AstItemDef, ConstLoc, ContainerId, FunctionLoc, Intern, TraitId,
14 TypeAliasLoc,
15};
16
17#[derive(Debug, Clone, PartialEq, Eq)]
18pub struct TraitData {
19 pub name: Option<Name>,
20 pub items: Vec<AssocItemId>,
21 pub auto: bool,
22}
23
24impl TraitData {
25 pub(crate) fn trait_data_query(db: &impl DefDatabase2, tr: TraitId) -> Arc<TraitData> {
26 let src = tr.source(db);
27 let name = src.value.name().map(|n| n.as_name());
28 let auto = src.value.is_auto();
29 let ast_id_map = db.ast_id_map(src.file_id);
30 let items = if let Some(item_list) = src.value.item_list() {
31 item_list
32 .impl_items()
33 .map(|item_node| match item_node {
34 ast::ImplItem::FnDef(it) => FunctionLoc {
35 container: ContainerId::TraitId(tr),
36 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
37 }
38 .intern(db)
39 .into(),
40 ast::ImplItem::ConstDef(it) => ConstLoc {
41 container: ContainerId::TraitId(tr),
42 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
43 }
44 .intern(db)
45 .into(),
46 ast::ImplItem::TypeAliasDef(it) => TypeAliasLoc {
47 container: ContainerId::TraitId(tr),
48 ast_id: AstId::new(src.file_id, ast_id_map.ast_id(&it)),
49 }
50 .intern(db)
51 .into(),
52 })
53 .collect()
54 } else {
55 Vec::new()
56 };
57 Arc::new(TraitData { name, items, auto })
58 }
59}
diff --git a/crates/ra_hir_expand/src/diagnostics.rs b/crates/ra_hir_expand/src/diagnostics.rs
index 201884b95..3d37e9335 100644
--- a/crates/ra_hir_expand/src/diagnostics.rs
+++ b/crates/ra_hir_expand/src/diagnostics.rs
@@ -24,7 +24,7 @@ pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static {
24 fn message(&self) -> String; 24 fn message(&self) -> String;
25 fn source(&self) -> Source<SyntaxNodePtr>; 25 fn source(&self) -> Source<SyntaxNodePtr>;
26 fn highlight_range(&self) -> TextRange { 26 fn highlight_range(&self) -> TextRange {
27 self.source().ast.range() 27 self.source().value.range()
28 } 28 }
29 fn as_any(&self) -> &(dyn Any + Send + 'static); 29 fn as_any(&self) -> &(dyn Any + Send + 'static);
30} 30}
@@ -37,7 +37,7 @@ pub trait AstDiagnostic {
37impl dyn Diagnostic { 37impl dyn Diagnostic {
38 pub fn syntax_node(&self, db: &impl AstDatabase) -> SyntaxNode { 38 pub fn syntax_node(&self, db: &impl AstDatabase) -> SyntaxNode {
39 let node = db.parse_or_expand(self.source().file_id).unwrap(); 39 let node = db.parse_or_expand(self.source().file_id).unwrap();
40 self.source().ast.to_node(&node) 40 self.source().value.to_node(&node)
41 } 41 }
42 42
43 pub fn downcast_ref<D: Diagnostic>(&self) -> Option<&D> { 43 pub fn downcast_ref<D: Diagnostic>(&self) -> Option<&D> {
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs
index cfe7e6d15..1389f64ce 100644
--- a/crates/ra_hir_expand/src/lib.rs
+++ b/crates/ra_hir_expand/src/lib.rs
@@ -166,19 +166,19 @@ impl ExpansionInfo {
166 pub fn map_token_down(&self, token: Source<&SyntaxToken>) -> Option<Source<SyntaxToken>> { 166 pub fn map_token_down(&self, token: Source<&SyntaxToken>) -> Option<Source<SyntaxToken>> {
167 assert_eq!(token.file_id, self.arg.file_id); 167 assert_eq!(token.file_id, self.arg.file_id);
168 let range = 168 let range =
169 token.ast.text_range().checked_sub(self.arg.ast.syntax().text_range().start())?; 169 token.value.text_range().checked_sub(self.arg.value.syntax().text_range().start())?;
170 let token_id = self.macro_arg.1.token_by_range(range)?; 170 let token_id = self.macro_arg.1.token_by_range(range)?;
171 let token_id = self.macro_def.0.map_id_down(token_id); 171 let token_id = self.macro_def.0.map_id_down(token_id);
172 172
173 let range = self.exp_map.range_by_token(token_id)?; 173 let range = self.exp_map.range_by_token(token_id)?;
174 174
175 let token = algo::find_covering_element(&self.expanded.ast, range).into_token()?; 175 let token = algo::find_covering_element(&self.expanded.value, range).into_token()?;
176 176
177 Some(self.expanded.with_ast(token)) 177 Some(self.expanded.with_value(token))
178 } 178 }
179 179
180 pub fn map_token_up(&self, token: Source<&SyntaxToken>) -> Option<Source<SyntaxToken>> { 180 pub fn map_token_up(&self, token: Source<&SyntaxToken>) -> Option<Source<SyntaxToken>> {
181 let token_id = self.exp_map.token_by_range(token.ast.text_range())?; 181 let token_id = self.exp_map.token_by_range(token.value.text_range())?;
182 182
183 let (token_id, origin) = self.macro_def.0.map_id_up(token_id); 183 let (token_id, origin) = self.macro_def.0.map_id_up(token_id);
184 let (token_map, tt) = match origin { 184 let (token_map, tt) = match origin {
@@ -188,11 +188,11 @@ impl ExpansionInfo {
188 188
189 let range = token_map.range_by_token(token_id)?; 189 let range = token_map.range_by_token(token_id)?;
190 let token = algo::find_covering_element( 190 let token = algo::find_covering_element(
191 tt.ast.syntax(), 191 tt.value.syntax(),
192 range + tt.ast.syntax().text_range().start(), 192 range + tt.value.syntax().text_range().start(),
193 ) 193 )
194 .into_token()?; 194 .into_token()?;
195 Some(tt.with_ast(token)) 195 Some(tt.with_value(token))
196 } 196 }
197} 197}
198 198
@@ -240,30 +240,34 @@ impl<N: AstNode> AstId<N> {
240 } 240 }
241} 241}
242 242
243/// FIXME: https://github.com/matklad/with ? 243/// `Source<T>` stores a value of `T` inside a particular file/syntax tree.
244///
245/// Typical usages are:
246///
247/// * `Source<SyntaxNode>` -- syntax node in a file
248/// * `Source<ast::FnDef>` -- ast node in a file
249/// * `Source<TextUnit>` -- offset in a file
244#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)] 250#[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
245pub struct Source<T> { 251pub struct Source<T> {
246 pub file_id: HirFileId, 252 pub file_id: HirFileId,
247 // FIXME: this stores all kind of things, not only `ast`. 253 pub value: T,
248 // There should be a better name...
249 pub ast: T,
250} 254}
251 255
252impl<T> Source<T> { 256impl<T> Source<T> {
253 pub fn new(file_id: HirFileId, ast: T) -> Source<T> { 257 pub fn new(file_id: HirFileId, value: T) -> Source<T> {
254 Source { file_id, ast } 258 Source { file_id, value }
255 } 259 }
256 260
257 // Similarly, naming here is stupid... 261 // Similarly, naming here is stupid...
258 pub fn with_ast<U>(&self, ast: U) -> Source<U> { 262 pub fn with_value<U>(&self, value: U) -> Source<U> {
259 Source::new(self.file_id, ast) 263 Source::new(self.file_id, value)
260 } 264 }
261 265
262 pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> { 266 pub fn map<F: FnOnce(T) -> U, U>(self, f: F) -> Source<U> {
263 Source::new(self.file_id, f(self.ast)) 267 Source::new(self.file_id, f(self.value))
264 } 268 }
265 pub fn as_ref(&self) -> Source<&T> { 269 pub fn as_ref(&self) -> Source<&T> {
266 self.with_ast(&self.ast) 270 self.with_value(&self.value)
267 } 271 }
268 pub fn file_syntax(&self, db: &impl db::AstDatabase) -> SyntaxNode { 272 pub fn file_syntax(&self, db: &impl db::AstDatabase) -> SyntaxNode {
269 db.parse_or_expand(self.file_id).expect("source created from invalid file") 273 db.parse_or_expand(self.file_id).expect("source created from invalid file")
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs
index 5c9dec13e..3c607d5b5 100644
--- a/crates/ra_ide_api/src/change.rs
+++ b/crates/ra_ide_api/src/change.rs
@@ -309,7 +309,6 @@ impl RootDatabase {
309 hir::db::StructDataQuery 309 hir::db::StructDataQuery
310 hir::db::EnumDataQuery 310 hir::db::EnumDataQuery
311 hir::db::TraitDataQuery 311 hir::db::TraitDataQuery
312 hir::db::TraitItemsIndexQuery
313 hir::db::RawItemsWithSourceMapQuery 312 hir::db::RawItemsWithSourceMapQuery
314 hir::db::RawItemsQuery 313 hir::db::RawItemsQuery
315 hir::db::CrateDefMapQuery 314 hir::db::CrateDefMapQuery
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs
index 8c57c907d..d5739b58a 100644
--- a/crates/ra_ide_api/src/completion/complete_scope.rs
+++ b/crates/ra_ide_api/src/completion/complete_scope.rs
@@ -305,6 +305,13 @@ mod tests {
305 @r###" 305 @r###"
306 [ 306 [
307 CompletionItem { 307 CompletionItem {
308 label: "Self",
309 source_range: [54; 54),
310 delete: [54; 54),
311 insert: "Self",
312 kind: TypeParam,
313 },
314 CompletionItem {
308 label: "T", 315 label: "T",
309 source_range: [54; 54), 316 source_range: [54; 54),
310 delete: [54; 54), 317 delete: [54; 54),
diff --git a/crates/ra_ide_api/src/completion/completion_context.rs b/crates/ra_ide_api/src/completion/completion_context.rs
index 0906a4e1b..b8345c91d 100644
--- a/crates/ra_ide_api/src/completion/completion_context.rs
+++ b/crates/ra_ide_api/src/completion/completion_context.rs
@@ -54,7 +54,7 @@ impl<'a> CompletionContext<'a> {
54 let src = hir::ModuleSource::from_position(db, position); 54 let src = hir::ModuleSource::from_position(db, position);
55 let module = hir::Module::from_definition( 55 let module = hir::Module::from_definition(
56 db, 56 db,
57 hir::Source { file_id: position.file_id.into(), ast: src }, 57 hir::Source { file_id: position.file_id.into(), value: src },
58 ); 58 );
59 let token = 59 let token =
60 original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?; 60 original_parse.tree().syntax().token_at_offset(position.offset).left_biased()?;
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index 501b7da4e..b20329459 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -169,7 +169,7 @@ impl Completions {
169 None => return, 169 None => return,
170 }; 170 };
171 171
172 let ast_node = macro_.source(ctx.db).ast; 172 let ast_node = macro_.source(ctx.db).value;
173 let detail = macro_label(&ast_node); 173 let detail = macro_label(&ast_node);
174 174
175 let docs = macro_.docs(ctx.db); 175 let docs = macro_.docs(ctx.db);
@@ -201,7 +201,7 @@ impl Completions {
201 ) { 201 ) {
202 let data = func.data(ctx.db); 202 let data = func.data(ctx.db);
203 let name = name.unwrap_or_else(|| data.name().to_string()); 203 let name = name.unwrap_or_else(|| data.name().to_string());
204 let ast_node = func.source(ctx.db).ast; 204 let ast_node = func.source(ctx.db).value;
205 let detail = function_label(&ast_node); 205 let detail = function_label(&ast_node);
206 206
207 let mut builder = 207 let mut builder =
@@ -234,7 +234,7 @@ impl Completions {
234 } 234 }
235 235
236 pub(crate) fn add_const(&mut self, ctx: &CompletionContext, constant: hir::Const) { 236 pub(crate) fn add_const(&mut self, ctx: &CompletionContext, constant: hir::Const) {
237 let ast_node = constant.source(ctx.db).ast; 237 let ast_node = constant.source(ctx.db).value;
238 let name = match ast_node.name() { 238 let name = match ast_node.name() {
239 Some(name) => name, 239 Some(name) => name,
240 _ => return, 240 _ => return,
@@ -250,7 +250,7 @@ impl Completions {
250 } 250 }
251 251
252 pub(crate) fn add_type_alias(&mut self, ctx: &CompletionContext, type_alias: hir::TypeAlias) { 252 pub(crate) fn add_type_alias(&mut self, ctx: &CompletionContext, type_alias: hir::TypeAlias) {
253 let type_def = type_alias.source(ctx.db).ast; 253 let type_def = type_alias.source(ctx.db).value;
254 let name = match type_def.name() { 254 let name = match type_def.name() {
255 Some(name) => name, 255 Some(name) => name,
256 _ => return, 256 _ => return,
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs
index e52ffefb3..cc1ccab4b 100644
--- a/crates/ra_ide_api/src/diagnostics.rs
+++ b/crates/ra_ide_api/src/diagnostics.rs
@@ -96,7 +96,7 @@ pub(crate) fn diagnostics(db: &RootDatabase, file_id: FileId) -> Vec<Diagnostic>
96 }); 96 });
97 let source_file = db.parse(file_id).tree(); 97 let source_file = db.parse(file_id).tree();
98 let src = 98 let src =
99 hir::Source { file_id: file_id.into(), ast: hir::ModuleSource::SourceFile(source_file) }; 99 hir::Source { file_id: file_id.into(), value: hir::ModuleSource::SourceFile(source_file) };
100 if let Some(m) = hir::Module::from_definition(db, src) { 100 if let Some(m) = hir::Module::from_definition(db, src) {
101 m.diagnostics(db, &mut sink); 101 m.diagnostics(db, &mut sink);
102 }; 102 };
diff --git a/crates/ra_ide_api/src/display/function_signature.rs b/crates/ra_ide_api/src/display/function_signature.rs
index 9075ca443..f42dffc87 100644
--- a/crates/ra_ide_api/src/display/function_signature.rs
+++ b/crates/ra_ide_api/src/display/function_signature.rs
@@ -48,12 +48,12 @@ impl FunctionSignature {
48 48
49 pub(crate) fn from_hir(db: &db::RootDatabase, function: hir::Function) -> Self { 49 pub(crate) fn from_hir(db: &db::RootDatabase, function: hir::Function) -> Self {
50 let doc = function.docs(db); 50 let doc = function.docs(db);
51 let ast_node = function.source(db).ast; 51 let ast_node = function.source(db).value;
52 FunctionSignature::from(&ast_node).with_doc_opt(doc) 52 FunctionSignature::from(&ast_node).with_doc_opt(doc)
53 } 53 }
54 54
55 pub(crate) fn from_struct(db: &db::RootDatabase, st: hir::Struct) -> Option<Self> { 55 pub(crate) fn from_struct(db: &db::RootDatabase, st: hir::Struct) -> Option<Self> {
56 let node: ast::StructDef = st.source(db).ast; 56 let node: ast::StructDef = st.source(db).value;
57 match node.kind() { 57 match node.kind() {
58 ast::StructKind::Named(_) => return None, 58 ast::StructKind::Named(_) => return None,
59 _ => (), 59 _ => (),
@@ -87,7 +87,7 @@ impl FunctionSignature {
87 db: &db::RootDatabase, 87 db: &db::RootDatabase,
88 variant: hir::EnumVariant, 88 variant: hir::EnumVariant,
89 ) -> Option<Self> { 89 ) -> Option<Self> {
90 let node: ast::EnumVariant = variant.source(db).ast; 90 let node: ast::EnumVariant = variant.source(db).value;
91 match node.kind() { 91 match node.kind() {
92 ast::StructKind::Named(_) | ast::StructKind::Unit => return None, 92 ast::StructKind::Named(_) | ast::StructKind::Unit => return None,
93 _ => (), 93 _ => (),
@@ -126,7 +126,7 @@ impl FunctionSignature {
126 } 126 }
127 127
128 pub(crate) fn from_macro(db: &db::RootDatabase, macro_def: hir::MacroDef) -> Option<Self> { 128 pub(crate) fn from_macro(db: &db::RootDatabase, macro_def: hir::MacroDef) -> Option<Self> {
129 let node: ast::MacroCall = macro_def.source(db).ast; 129 let node: ast::MacroCall = macro_def.source(db).value;
130 130
131 let params = vec![]; 131 let params = vec![];
132 132
diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs
index b30ef8e05..6ac60722b 100644
--- a/crates/ra_ide_api/src/display/navigation_target.rs
+++ b/crates/ra_ide_api/src/display/navigation_target.rs
@@ -86,9 +86,9 @@ impl NavigationTarget {
86 name, 86 name,
87 None, 87 None,
88 frange.range, 88 frange.range,
89 src.ast.syntax().kind(), 89 src.value.syntax().kind(),
90 src.ast.doc_comment_text(), 90 src.value.doc_comment_text(),
91 src.ast.short_label(), 91 src.value.short_label(),
92 ); 92 );
93 } 93 }
94 module.to_nav(db) 94 module.to_nav(db)
@@ -146,9 +146,9 @@ impl NavigationTarget {
146 description: Option<String>, 146 description: Option<String>,
147 ) -> NavigationTarget { 147 ) -> NavigationTarget {
148 //FIXME: use `_` instead of empty string 148 //FIXME: use `_` instead of empty string
149 let name = node.ast.name().map(|it| it.text().clone()).unwrap_or_default(); 149 let name = node.value.name().map(|it| it.text().clone()).unwrap_or_default();
150 let focus_range = 150 let focus_range =
151 node.ast.name().map(|it| original_range(db, node.with_ast(it.syntax())).range); 151 node.value.name().map(|it| original_range(db, node.with_value(it.syntax())).range);
152 let frange = original_range(db, node.map(|it| it.syntax())); 152 let frange = original_range(db, node.map(|it| it.syntax()));
153 153
154 NavigationTarget::from_syntax( 154 NavigationTarget::from_syntax(
@@ -156,7 +156,7 @@ impl NavigationTarget {
156 name, 156 name,
157 focus_range, 157 focus_range,
158 frange.range, 158 frange.range,
159 node.ast.syntax().kind(), 159 node.value.syntax().kind(),
160 docs, 160 docs,
161 description, 161 description,
162 ) 162 )
@@ -220,8 +220,8 @@ where
220 NavigationTarget::from_named( 220 NavigationTarget::from_named(
221 db, 221 db,
222 src.as_ref().map(|it| it as &dyn ast::NameOwner), 222 src.as_ref().map(|it| it as &dyn ast::NameOwner),
223 src.ast.doc_comment_text(), 223 src.value.doc_comment_text(),
224 src.ast.short_label(), 224 src.value.short_label(),
225 ) 225 )
226 } 226 }
227} 227}
@@ -230,9 +230,9 @@ impl ToNav for hir::Module {
230 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 230 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
231 let src = self.definition_source(db); 231 let src = self.definition_source(db);
232 let name = self.name(db).map(|it| it.to_string().into()).unwrap_or_default(); 232 let name = self.name(db).map(|it| it.to_string().into()).unwrap_or_default();
233 match &src.ast { 233 match &src.value {
234 ModuleSource::SourceFile(node) => { 234 ModuleSource::SourceFile(node) => {
235 let frange = original_range(db, src.with_ast(node.syntax())); 235 let frange = original_range(db, src.with_value(node.syntax()));
236 236
237 NavigationTarget::from_syntax( 237 NavigationTarget::from_syntax(
238 frange.file_id, 238 frange.file_id,
@@ -245,7 +245,7 @@ impl ToNav for hir::Module {
245 ) 245 )
246 } 246 }
247 ModuleSource::Module(node) => { 247 ModuleSource::Module(node) => {
248 let frange = original_range(db, src.with_ast(node.syntax())); 248 let frange = original_range(db, src.with_value(node.syntax()));
249 249
250 NavigationTarget::from_syntax( 250 NavigationTarget::from_syntax(
251 frange.file_id, 251 frange.file_id,
@@ -271,7 +271,7 @@ impl ToNav for hir::ImplBlock {
271 "impl".into(), 271 "impl".into(),
272 None, 272 None,
273 frange.range, 273 frange.range,
274 src.ast.syntax().kind(), 274 src.value.syntax().kind(),
275 None, 275 None,
276 None, 276 None,
277 ) 277 )
@@ -282,15 +282,15 @@ impl ToNav for hir::StructField {
282 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 282 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
283 let src = self.source(db); 283 let src = self.source(db);
284 284
285 match &src.ast { 285 match &src.value {
286 FieldSource::Named(it) => NavigationTarget::from_named( 286 FieldSource::Named(it) => NavigationTarget::from_named(
287 db, 287 db,
288 src.with_ast(it), 288 src.with_value(it),
289 it.doc_comment_text(), 289 it.doc_comment_text(),
290 it.short_label(), 290 it.short_label(),
291 ), 291 ),
292 FieldSource::Pos(it) => { 292 FieldSource::Pos(it) => {
293 let frange = original_range(db, src.with_ast(it.syntax())); 293 let frange = original_range(db, src.with_value(it.syntax()));
294 NavigationTarget::from_syntax( 294 NavigationTarget::from_syntax(
295 frange.file_id, 295 frange.file_id,
296 "".into(), 296 "".into(),
@@ -308,11 +308,11 @@ impl ToNav for hir::StructField {
308impl ToNav for hir::MacroDef { 308impl ToNav for hir::MacroDef {
309 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 309 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
310 let src = self.source(db); 310 let src = self.source(db);
311 log::debug!("nav target {:#?}", src.ast.syntax()); 311 log::debug!("nav target {:#?}", src.value.syntax());
312 NavigationTarget::from_named( 312 NavigationTarget::from_named(
313 db, 313 db,
314 src.as_ref().map(|it| it as &dyn ast::NameOwner), 314 src.as_ref().map(|it| it as &dyn ast::NameOwner),
315 src.ast.doc_comment_text(), 315 src.value.doc_comment_text(),
316 None, 316 None,
317 ) 317 )
318 } 318 }
@@ -341,7 +341,7 @@ impl ToNav for hir::AssocItem {
341impl ToNav for hir::Local { 341impl ToNav for hir::Local {
342 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget { 342 fn to_nav(&self, db: &RootDatabase) -> NavigationTarget {
343 let src = self.source(db); 343 let src = self.source(db);
344 let (full_range, focus_range) = match src.ast { 344 let (full_range, focus_range) = match src.value {
345 Either::A(it) => { 345 Either::A(it) => {
346 (it.syntax().text_range(), it.name().map(|it| it.syntax().text_range())) 346 (it.syntax().text_range(), it.name().map(|it| it.syntax().text_range()))
347 } 347 }
diff --git a/crates/ra_ide_api/src/expand.rs b/crates/ra_ide_api/src/expand.rs
index 7f59e46d2..2f1abf509 100644
--- a/crates/ra_ide_api/src/expand.rs
+++ b/crates/ra_ide_api/src/expand.rs
@@ -12,7 +12,7 @@ pub(crate) fn original_range(db: &RootDatabase, node: Source<&SyntaxNode>) -> Fi
12 None => { 12 None => {
13 return FileRange { 13 return FileRange {
14 file_id: node.file_id.original_file(db), 14 file_id: node.file_id.original_file(db),
15 range: node.ast.text_range(), 15 range: node.value.text_range(),
16 } 16 }
17 } 17 }
18 Some(it) => it, 18 Some(it) => it,
@@ -25,14 +25,18 @@ pub(crate) fn original_range(db: &RootDatabase, node: Source<&SyntaxNode>) -> Fi
25 // *Second*, we should handle recurside macro expansions 25 // *Second*, we should handle recurside macro expansions
26 26
27 let token = node 27 let token = node
28 .ast 28 .value
29 .descendants_with_tokens() 29 .descendants_with_tokens()
30 .filter_map(|it| it.into_token()) 30 .filter_map(|it| it.into_token())
31 .find_map(|it| expansion.map_token_up(node.with_ast(&it))); 31 .find_map(|it| expansion.map_token_up(node.with_value(&it)));
32 32
33 match token { 33 match token {
34 Some(it) => FileRange { file_id: it.file_id.original_file(db), range: it.ast.text_range() }, 34 Some(it) => {
35 None => FileRange { file_id: node.file_id.original_file(db), range: node.ast.text_range() }, 35 FileRange { file_id: it.file_id.original_file(db), range: it.value.text_range() }
36 }
37 None => {
38 FileRange { file_id: node.file_id.original_file(db), range: node.value.text_range() }
39 }
36 } 40 }
37} 41}
38 42
@@ -44,14 +48,14 @@ pub(crate) fn descend_into_macros(
44 let src = Source::new(file_id.into(), token); 48 let src = Source::new(file_id.into(), token);
45 49
46 successors(Some(src), |token| { 50 successors(Some(src), |token| {
47 let macro_call = token.ast.ancestors().find_map(ast::MacroCall::cast)?; 51 let macro_call = token.value.ancestors().find_map(ast::MacroCall::cast)?;
48 let tt = macro_call.token_tree()?; 52 let tt = macro_call.token_tree()?;
49 if !token.ast.text_range().is_subrange(&tt.syntax().text_range()) { 53 if !token.value.text_range().is_subrange(&tt.syntax().text_range()) {
50 return None; 54 return None;
51 } 55 }
52 let source_analyzer = 56 let source_analyzer =
53 hir::SourceAnalyzer::new(db, token.with_ast(token.ast.parent()).as_ref(), None); 57 hir::SourceAnalyzer::new(db, token.with_value(token.value.parent()).as_ref(), None);
54 let exp = source_analyzer.expand(db, &macro_call)?; 58 let exp = source_analyzer.expand(db, token.with_value(&macro_call))?;
55 exp.map_token_down(db, token.as_ref()) 59 exp.map_token_down(db, token.as_ref())
56 }) 60 })
57 .last() 61 .last()
diff --git a/crates/ra_ide_api/src/expand_macro.rs b/crates/ra_ide_api/src/expand_macro.rs
index e9eb2a7fb..7f39262dc 100644
--- a/crates/ra_ide_api/src/expand_macro.rs
+++ b/crates/ra_ide_api/src/expand_macro.rs
@@ -23,7 +23,7 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
23 let mac = name_ref.syntax().ancestors().find_map(ast::MacroCall::cast)?; 23 let mac = name_ref.syntax().ancestors().find_map(ast::MacroCall::cast)?;
24 24
25 let source = hir::Source::new(position.file_id.into(), mac.syntax()); 25 let source = hir::Source::new(position.file_id.into(), mac.syntax());
26 let expanded = expand_macro_recur(db, source, &mac)?; 26 let expanded = expand_macro_recur(db, source, source.with_value(&mac))?;
27 27
28 // FIXME: 28 // FIXME:
29 // macro expansion may lose all white space information 29 // macro expansion may lose all white space information
@@ -35,10 +35,10 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
35fn expand_macro_recur( 35fn expand_macro_recur(
36 db: &RootDatabase, 36 db: &RootDatabase,
37 source: hir::Source<&SyntaxNode>, 37 source: hir::Source<&SyntaxNode>,
38 macro_call: &ast::MacroCall, 38 macro_call: hir::Source<&ast::MacroCall>,
39) -> Option<SyntaxNode> { 39) -> Option<SyntaxNode> {
40 let analyzer = hir::SourceAnalyzer::new(db, source, None); 40 let analyzer = hir::SourceAnalyzer::new(db, source, None);
41 let expansion = analyzer.expand(db, &macro_call)?; 41 let expansion = analyzer.expand(db, macro_call)?;
42 let macro_file_id = expansion.file_id(); 42 let macro_file_id = expansion.file_id();
43 let expanded: SyntaxNode = db.parse_or_expand(macro_file_id)?; 43 let expanded: SyntaxNode = db.parse_or_expand(macro_file_id)?;
44 44
@@ -46,8 +46,8 @@ fn expand_macro_recur(
46 let mut replaces = FxHashMap::default(); 46 let mut replaces = FxHashMap::default();
47 47
48 for child in children.into_iter() { 48 for child in children.into_iter() {
49 let source = hir::Source::new(macro_file_id, source.ast); 49 let node = hir::Source::new(macro_file_id, &child);
50 let new_node = expand_macro_recur(db, source, &child)?; 50 let new_node = expand_macro_recur(db, source, node)?;
51 51
52 replaces.insert(child.syntax().clone().into(), new_node.into()); 52 replaces.insert(child.syntax().clone().into(), new_node.into());
53 } 53 }
@@ -139,7 +139,7 @@ mod tests {
139 } 139 }
140 macro_rules! baz { 140 macro_rules! baz {
141 () => { foo!(); } 141 () => { foo!(); }
142 } 142 }
143 f<|>oo!(); 143 f<|>oo!();
144 "#, 144 "#,
145 ); 145 );
@@ -156,7 +156,7 @@ fn b(){}
156 r#" 156 r#"
157 //- /lib.rs 157 //- /lib.rs
158 macro_rules! foo { 158 macro_rules! foo {
159 () => { 159 () => {
160 fn some_thing() -> u32 { 160 fn some_thing() -> u32 {
161 let a = 0; 161 let a = 0;
162 a + 10 162 a + 10
@@ -172,7 +172,7 @@ fn b(){}
172fn some_thing() -> u32 { 172fn some_thing() -> u32 {
173 let a = 0; 173 let a = 0;
174 a+10 174 a+10
175} 175}
176"###); 176"###);
177 } 177 }
178} 178}
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 3f16e9566..b6c72efdf 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -23,13 +23,13 @@ pub(crate) fn goto_definition(
23 let token = descend_into_macros(db, position.file_id, token); 23 let token = descend_into_macros(db, position.file_id, token);
24 24
25 let res = match_ast! { 25 let res = match_ast! {
26 match (token.ast.parent()) { 26 match (token.value.parent()) {
27 ast::NameRef(name_ref) => { 27 ast::NameRef(name_ref) => {
28 let navs = reference_definition(db, token.with_ast(&name_ref)).to_vec(); 28 let navs = reference_definition(db, token.with_value(&name_ref)).to_vec();
29 RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec()) 29 RangeInfo::new(name_ref.syntax().text_range(), navs.to_vec())
30 }, 30 },
31 ast::Name(name) => { 31 ast::Name(name) => {
32 let navs = name_definition(db, token.with_ast(&name))?; 32 let navs = name_definition(db, token.with_value(&name))?;
33 RangeInfo::new(name.syntax().text_range(), navs) 33 RangeInfo::new(name.syntax().text_range(), navs)
34 34
35 }, 35 },
@@ -84,7 +84,7 @@ pub(crate) fn reference_definition(
84 }; 84 };
85 85
86 // Fallback index based approach: 86 // Fallback index based approach:
87 let navs = crate::symbol_index::index_resolve(db, name_ref.ast) 87 let navs = crate::symbol_index::index_resolve(db, name_ref.value)
88 .into_iter() 88 .into_iter()
89 .map(|s| s.to_nav(db)) 89 .map(|s| s.to_nav(db))
90 .collect(); 90 .collect();
@@ -95,11 +95,11 @@ pub(crate) fn name_definition(
95 db: &RootDatabase, 95 db: &RootDatabase,
96 name: Source<&ast::Name>, 96 name: Source<&ast::Name>,
97) -> Option<Vec<NavigationTarget>> { 97) -> Option<Vec<NavigationTarget>> {
98 let parent = name.ast.syntax().parent()?; 98 let parent = name.value.syntax().parent()?;
99 99
100 if let Some(module) = ast::Module::cast(parent.clone()) { 100 if let Some(module) = ast::Module::cast(parent.clone()) {
101 if module.has_semi() { 101 if module.has_semi() {
102 let src = name.with_ast(module); 102 let src = name.with_value(module);
103 if let Some(child_module) = hir::Module::from_declaration(db, src) { 103 if let Some(child_module) = hir::Module::from_declaration(db, src) {
104 let nav = child_module.to_nav(db); 104 let nav = child_module.to_nav(db);
105 return Some(vec![nav]); 105 return Some(vec![nav]);
@@ -107,7 +107,7 @@ pub(crate) fn name_definition(
107 } 107 }
108 } 108 }
109 109
110 if let Some(nav) = named_target(db, name.with_ast(&parent)) { 110 if let Some(nav) = named_target(db, name.with_value(&parent)) {
111 return Some(vec![nav]); 111 return Some(vec![nav]);
112 } 112 }
113 113
@@ -116,11 +116,11 @@ pub(crate) fn name_definition(
116 116
117fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<NavigationTarget> { 117fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<NavigationTarget> {
118 match_ast! { 118 match_ast! {
119 match (node.ast) { 119 match (node.value) {
120 ast::StructDef(it) => { 120 ast::StructDef(it) => {
121 Some(NavigationTarget::from_named( 121 Some(NavigationTarget::from_named(
122 db, 122 db,
123 node.with_ast(&it), 123 node.with_value(&it),
124 it.doc_comment_text(), 124 it.doc_comment_text(),
125 it.short_label(), 125 it.short_label(),
126 )) 126 ))
@@ -128,7 +128,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
128 ast::EnumDef(it) => { 128 ast::EnumDef(it) => {
129 Some(NavigationTarget::from_named( 129 Some(NavigationTarget::from_named(
130 db, 130 db,
131 node.with_ast(&it), 131 node.with_value(&it),
132 it.doc_comment_text(), 132 it.doc_comment_text(),
133 it.short_label(), 133 it.short_label(),
134 )) 134 ))
@@ -136,7 +136,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
136 ast::EnumVariant(it) => { 136 ast::EnumVariant(it) => {
137 Some(NavigationTarget::from_named( 137 Some(NavigationTarget::from_named(
138 db, 138 db,
139 node.with_ast(&it), 139 node.with_value(&it),
140 it.doc_comment_text(), 140 it.doc_comment_text(),
141 it.short_label(), 141 it.short_label(),
142 )) 142 ))
@@ -144,7 +144,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
144 ast::FnDef(it) => { 144 ast::FnDef(it) => {
145 Some(NavigationTarget::from_named( 145 Some(NavigationTarget::from_named(
146 db, 146 db,
147 node.with_ast(&it), 147 node.with_value(&it),
148 it.doc_comment_text(), 148 it.doc_comment_text(),
149 it.short_label(), 149 it.short_label(),
150 )) 150 ))
@@ -152,7 +152,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
152 ast::TypeAliasDef(it) => { 152 ast::TypeAliasDef(it) => {
153 Some(NavigationTarget::from_named( 153 Some(NavigationTarget::from_named(
154 db, 154 db,
155 node.with_ast(&it), 155 node.with_value(&it),
156 it.doc_comment_text(), 156 it.doc_comment_text(),
157 it.short_label(), 157 it.short_label(),
158 )) 158 ))
@@ -160,7 +160,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
160 ast::ConstDef(it) => { 160 ast::ConstDef(it) => {
161 Some(NavigationTarget::from_named( 161 Some(NavigationTarget::from_named(
162 db, 162 db,
163 node.with_ast(&it), 163 node.with_value(&it),
164 it.doc_comment_text(), 164 it.doc_comment_text(),
165 it.short_label(), 165 it.short_label(),
166 )) 166 ))
@@ -168,7 +168,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
168 ast::StaticDef(it) => { 168 ast::StaticDef(it) => {
169 Some(NavigationTarget::from_named( 169 Some(NavigationTarget::from_named(
170 db, 170 db,
171 node.with_ast(&it), 171 node.with_value(&it),
172 it.doc_comment_text(), 172 it.doc_comment_text(),
173 it.short_label(), 173 it.short_label(),
174 )) 174 ))
@@ -176,7 +176,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
176 ast::TraitDef(it) => { 176 ast::TraitDef(it) => {
177 Some(NavigationTarget::from_named( 177 Some(NavigationTarget::from_named(
178 db, 178 db,
179 node.with_ast(&it), 179 node.with_value(&it),
180 it.doc_comment_text(), 180 it.doc_comment_text(),
181 it.short_label(), 181 it.short_label(),
182 )) 182 ))
@@ -184,7 +184,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
184 ast::RecordFieldDef(it) => { 184 ast::RecordFieldDef(it) => {
185 Some(NavigationTarget::from_named( 185 Some(NavigationTarget::from_named(
186 db, 186 db,
187 node.with_ast(&it), 187 node.with_value(&it),
188 it.doc_comment_text(), 188 it.doc_comment_text(),
189 it.short_label(), 189 it.short_label(),
190 )) 190 ))
@@ -192,7 +192,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
192 ast::Module(it) => { 192 ast::Module(it) => {
193 Some(NavigationTarget::from_named( 193 Some(NavigationTarget::from_named(
194 db, 194 db,
195 node.with_ast(&it), 195 node.with_value(&it),
196 it.doc_comment_text(), 196 it.doc_comment_text(),
197 it.short_label(), 197 it.short_label(),
198 )) 198 ))
@@ -200,7 +200,7 @@ fn named_target(db: &RootDatabase, node: Source<&SyntaxNode>) -> Option<Navigati
200 ast::MacroCall(it) => { 200 ast::MacroCall(it) => {
201 Some(NavigationTarget::from_named( 201 Some(NavigationTarget::from_named(
202 db, 202 db,
203 node.with_ast(&it), 203 node.with_value(&it),
204 it.doc_comment_text(), 204 it.doc_comment_text(),
205 None, 205 None,
206 )) 206 ))
diff --git a/crates/ra_ide_api/src/goto_type_definition.rs b/crates/ra_ide_api/src/goto_type_definition.rs
index 7d694e1f6..28a83a3e2 100644
--- a/crates/ra_ide_api/src/goto_type_definition.rs
+++ b/crates/ra_ide_api/src/goto_type_definition.rs
@@ -16,13 +16,13 @@ pub(crate) fn goto_type_definition(
16 let token = file.token_at_offset(position.offset).filter(|it| !it.kind().is_trivia()).next()?; 16 let token = file.token_at_offset(position.offset).filter(|it| !it.kind().is_trivia()).next()?;
17 let token = descend_into_macros(db, position.file_id, token); 17 let token = descend_into_macros(db, position.file_id, token);
18 18
19 let node = token.ast.ancestors().find_map(|token| { 19 let node = token.value.ancestors().find_map(|token| {
20 token 20 token
21 .ancestors() 21 .ancestors()
22 .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some()) 22 .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some())
23 })?; 23 })?;
24 24
25 let analyzer = hir::SourceAnalyzer::new(db, token.with_ast(&node), None); 25 let analyzer = hir::SourceAnalyzer::new(db, token.with_value(&node), None);
26 26
27 let ty: hir::Ty = if let Some(ty) = 27 let ty: hir::Ty = if let Some(ty) =
28 ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e)) 28 ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e))
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index 787b714b3..9839be985 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -101,11 +101,11 @@ fn hover_text_from_name_kind(
101 return match name_kind { 101 return match name_kind {
102 Macro(it) => { 102 Macro(it) => {
103 let src = it.source(db); 103 let src = it.source(db);
104 hover_text(src.ast.doc_comment_text(), Some(macro_label(&src.ast))) 104 hover_text(src.value.doc_comment_text(), Some(macro_label(&src.value)))
105 } 105 }
106 Field(it) => { 106 Field(it) => {
107 let src = it.source(db); 107 let src = it.source(db);
108 match src.ast { 108 match src.value {
109 hir::FieldSource::Named(it) => hover_text(it.doc_comment_text(), it.short_label()), 109 hir::FieldSource::Named(it) => hover_text(it.doc_comment_text(), it.short_label()),
110 _ => None, 110 _ => None,
111 } 111 }
@@ -116,7 +116,7 @@ fn hover_text_from_name_kind(
116 hir::AssocItem::TypeAlias(it) => from_def_source(db, it), 116 hir::AssocItem::TypeAlias(it) => from_def_source(db, it),
117 }, 117 },
118 Def(it) => match it { 118 Def(it) => match it {
119 hir::ModuleDef::Module(it) => match it.definition_source(db).ast { 119 hir::ModuleDef::Module(it) => match it.definition_source(db).value {
120 hir::ModuleSource::Module(it) => { 120 hir::ModuleSource::Module(it) => {
121 hover_text(it.doc_comment_text(), it.short_label()) 121 hover_text(it.doc_comment_text(), it.short_label())
122 } 122 }
@@ -158,7 +158,7 @@ fn hover_text_from_name_kind(
158 A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel, 158 A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel,
159 { 159 {
160 let src = def.source(db); 160 let src = def.source(db);
161 hover_text(src.ast.doc_comment_text(), src.ast.short_label()) 161 hover_text(src.value.doc_comment_text(), src.value.short_label())
162 } 162 }
163} 163}
164 164
@@ -170,11 +170,11 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
170 let mut res = HoverResult::new(); 170 let mut res = HoverResult::new();
171 171
172 let mut range = match_ast! { 172 let mut range = match_ast! {
173 match (token.ast.parent()) { 173 match (token.value.parent()) {
174 ast::NameRef(name_ref) => { 174 ast::NameRef(name_ref) => {
175 let mut no_fallback = false; 175 let mut no_fallback = false;
176 if let Some(name_kind) = 176 if let Some(name_kind) =
177 classify_name_ref(db, token.with_ast(&name_ref)).map(|d| d.kind) 177 classify_name_ref(db, token.with_value(&name_ref)).map(|d| d.kind)
178 { 178 {
179 res.extend(hover_text_from_name_kind(db, name_kind, &mut no_fallback)) 179 res.extend(hover_text_from_name_kind(db, name_kind, &mut no_fallback))
180 } 180 }
@@ -196,7 +196,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
196 } 196 }
197 }, 197 },
198 ast::Name(name) => { 198 ast::Name(name) => {
199 if let Some(name_kind) = classify_name(db, token.with_ast(&name)).map(|d| d.kind) { 199 if let Some(name_kind) = classify_name(db, token.with_value(&name)).map(|d| d.kind) {
200 res.extend(hover_text_from_name_kind(db, name_kind, &mut true)); 200 res.extend(hover_text_from_name_kind(db, name_kind, &mut true));
201 } 201 }
202 202
@@ -211,7 +211,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
211 }; 211 };
212 212
213 if range.is_none() { 213 if range.is_none() {
214 let node = token.ast.ancestors().find(|n| { 214 let node = token.value.ancestors().find(|n| {
215 ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some() 215 ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some()
216 })?; 216 })?;
217 let frange = FileRange { file_id: position.file_id, range: node.text_range() }; 217 let frange = FileRange { file_id: position.file_id, range: node.text_range() };
@@ -404,9 +404,7 @@ mod tests {
404 check_hover_result( 404 check_hover_result(
405 r#" 405 r#"
406 //- /main.rs 406 //- /main.rs
407 fn main() { 407 const foo<|>: u32 = 0;
408 const foo<|>: u32 = 0;
409 }
410 "#, 408 "#,
411 &["const foo: u32"], 409 &["const foo: u32"],
412 ); 410 );
@@ -414,9 +412,7 @@ mod tests {
414 check_hover_result( 412 check_hover_result(
415 r#" 413 r#"
416 //- /main.rs 414 //- /main.rs
417 fn main() { 415 static foo<|>: u32 = 0;
418 static foo<|>: u32 = 0;
419 }
420 "#, 416 "#,
421 &["static foo: u32"], 417 &["static foo: u32"],
422 ); 418 );
diff --git a/crates/ra_ide_api/src/impls.rs b/crates/ra_ide_api/src/impls.rs
index bc9b66550..3e3012559 100644
--- a/crates/ra_ide_api/src/impls.rs
+++ b/crates/ra_ide_api/src/impls.rs
@@ -16,7 +16,7 @@ pub(crate) fn goto_implementation(
16 let src = hir::ModuleSource::from_position(db, position); 16 let src = hir::ModuleSource::from_position(db, position);
17 let module = hir::Module::from_definition( 17 let module = hir::Module::from_definition(
18 db, 18 db,
19 hir::Source { file_id: position.file_id.into(), ast: src }, 19 hir::Source { file_id: position.file_id.into(), value: src },
20 )?; 20 )?;
21 21
22 if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) { 22 if let Some(nominal_def) = find_node_at_offset::<ast::NominalDef>(&syntax, position.offset) {
@@ -42,11 +42,11 @@ fn impls_for_def(
42) -> Option<Vec<NavigationTarget>> { 42) -> Option<Vec<NavigationTarget>> {
43 let ty = match node { 43 let ty = match node {
44 ast::NominalDef::StructDef(def) => { 44 ast::NominalDef::StructDef(def) => {
45 let src = hir::Source { file_id: position.file_id.into(), ast: def.clone() }; 45 let src = hir::Source { file_id: position.file_id.into(), value: def.clone() };
46 hir::Struct::from_source(db, src)?.ty(db) 46 hir::Struct::from_source(db, src)?.ty(db)
47 } 47 }
48 ast::NominalDef::EnumDef(def) => { 48 ast::NominalDef::EnumDef(def) => {
49 let src = hir::Source { file_id: position.file_id.into(), ast: def.clone() }; 49 let src = hir::Source { file_id: position.file_id.into(), value: def.clone() };
50 hir::Enum::from_source(db, src)?.ty(db) 50 hir::Enum::from_source(db, src)?.ty(db)
51 } 51 }
52 }; 52 };
@@ -69,7 +69,7 @@ fn impls_for_trait(
69 node: &ast::TraitDef, 69 node: &ast::TraitDef,
70 module: hir::Module, 70 module: hir::Module,
71) -> Option<Vec<NavigationTarget>> { 71) -> Option<Vec<NavigationTarget>> {
72 let src = hir::Source { file_id: position.file_id.into(), ast: node.clone() }; 72 let src = hir::Source { file_id: position.file_id.into(), value: node.clone() };
73 let tr = hir::Trait::from_source(db, src)?; 73 let tr = hir::Trait::from_source(db, src)?;
74 74
75 let krate = module.krate(); 75 let krate = module.krate();
diff --git a/crates/ra_ide_api/src/inlay_hints.rs b/crates/ra_ide_api/src/inlay_hints.rs
index 0cd959848..24a7ca5e7 100644
--- a/crates/ra_ide_api/src/inlay_hints.rs
+++ b/crates/ra_ide_api/src/inlay_hints.rs
@@ -19,10 +19,15 @@ pub struct InlayHint {
19 pub label: SmolStr, 19 pub label: SmolStr,
20} 20}
21 21
22pub(crate) fn inlay_hints(db: &RootDatabase, file_id: FileId, file: &SourceFile) -> Vec<InlayHint> { 22pub(crate) fn inlay_hints(
23 db: &RootDatabase,
24 file_id: FileId,
25 file: &SourceFile,
26 max_inlay_hint_length: Option<usize>,
27) -> Vec<InlayHint> {
23 file.syntax() 28 file.syntax()
24 .descendants() 29 .descendants()
25 .map(|node| get_inlay_hints(db, file_id, &node).unwrap_or_default()) 30 .map(|node| get_inlay_hints(db, file_id, &node, max_inlay_hint_length).unwrap_or_default())
26 .flatten() 31 .flatten()
27 .collect() 32 .collect()
28} 33}
@@ -31,6 +36,7 @@ fn get_inlay_hints(
31 db: &RootDatabase, 36 db: &RootDatabase,
32 file_id: FileId, 37 file_id: FileId,
33 node: &SyntaxNode, 38 node: &SyntaxNode,
39 max_inlay_hint_length: Option<usize>,
34) -> Option<Vec<InlayHint>> { 40) -> Option<Vec<InlayHint>> {
35 let analyzer = SourceAnalyzer::new(db, hir::Source::new(file_id.into(), node), None); 41 let analyzer = SourceAnalyzer::new(db, hir::Source::new(file_id.into(), node), None);
36 match_ast! { 42 match_ast! {
@@ -40,7 +46,7 @@ fn get_inlay_hints(
40 return None; 46 return None;
41 } 47 }
42 let pat = it.pat()?; 48 let pat = it.pat()?;
43 Some(get_pat_type_hints(db, &analyzer, pat, false)) 49 Some(get_pat_type_hints(db, &analyzer, pat, false, max_inlay_hint_length))
44 }, 50 },
45 ast::LambdaExpr(it) => { 51 ast::LambdaExpr(it) => {
46 it.param_list().map(|param_list| { 52 it.param_list().map(|param_list| {
@@ -48,22 +54,22 @@ fn get_inlay_hints(
48 .params() 54 .params()
49 .filter(|closure_param| closure_param.ascribed_type().is_none()) 55 .filter(|closure_param| closure_param.ascribed_type().is_none())
50 .filter_map(|closure_param| closure_param.pat()) 56 .filter_map(|closure_param| closure_param.pat())
51 .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, false)) 57 .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, false, max_inlay_hint_length))
52 .flatten() 58 .flatten()
53 .collect() 59 .collect()
54 }) 60 })
55 }, 61 },
56 ast::ForExpr(it) => { 62 ast::ForExpr(it) => {
57 let pat = it.pat()?; 63 let pat = it.pat()?;
58 Some(get_pat_type_hints(db, &analyzer, pat, false)) 64 Some(get_pat_type_hints(db, &analyzer, pat, false, max_inlay_hint_length))
59 }, 65 },
60 ast::IfExpr(it) => { 66 ast::IfExpr(it) => {
61 let pat = it.condition()?.pat()?; 67 let pat = it.condition()?.pat()?;
62 Some(get_pat_type_hints(db, &analyzer, pat, true)) 68 Some(get_pat_type_hints(db, &analyzer, pat, true, max_inlay_hint_length))
63 }, 69 },
64 ast::WhileExpr(it) => { 70 ast::WhileExpr(it) => {
65 let pat = it.condition()?.pat()?; 71 let pat = it.condition()?.pat()?;
66 Some(get_pat_type_hints(db, &analyzer, pat, true)) 72 Some(get_pat_type_hints(db, &analyzer, pat, true, max_inlay_hint_length))
67 }, 73 },
68 ast::MatchArmList(it) => { 74 ast::MatchArmList(it) => {
69 Some( 75 Some(
@@ -71,7 +77,7 @@ fn get_inlay_hints(
71 .arms() 77 .arms()
72 .map(|match_arm| match_arm.pats()) 78 .map(|match_arm| match_arm.pats())
73 .flatten() 79 .flatten()
74 .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, true)) 80 .map(|root_pat| get_pat_type_hints(db, &analyzer, root_pat, true, max_inlay_hint_length))
75 .flatten() 81 .flatten()
76 .collect(), 82 .collect(),
77 ) 83 )
@@ -86,6 +92,7 @@ fn get_pat_type_hints(
86 analyzer: &SourceAnalyzer, 92 analyzer: &SourceAnalyzer,
87 root_pat: ast::Pat, 93 root_pat: ast::Pat,
88 skip_root_pat_hint: bool, 94 skip_root_pat_hint: bool,
95 max_inlay_hint_length: Option<usize>,
89) -> Vec<InlayHint> { 96) -> Vec<InlayHint> {
90 let original_pat = &root_pat.clone(); 97 let original_pat = &root_pat.clone();
91 98
@@ -99,7 +106,7 @@ fn get_pat_type_hints(
99 .map(|(range, pat_type)| InlayHint { 106 .map(|(range, pat_type)| InlayHint {
100 range, 107 range,
101 kind: InlayKind::TypeHint, 108 kind: InlayKind::TypeHint,
102 label: pat_type.display(db).to_string().into(), 109 label: pat_type.display_truncated(db, max_inlay_hint_length).to_string().into(),
103 }) 110 })
104 .collect() 111 .collect()
105} 112}
@@ -209,7 +216,7 @@ fn main() {
209}"#, 216}"#,
210 ); 217 );
211 218
212 assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" 219 assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
213 [ 220 [
214 InlayHint { 221 InlayHint {
215 range: [193; 197), 222 range: [193; 197),
@@ -278,7 +285,7 @@ fn main() {
278}"#, 285}"#,
279 ); 286 );
280 287
281 assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" 288 assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
282 [ 289 [
283 InlayHint { 290 InlayHint {
284 range: [21; 30), 291 range: [21; 30),
@@ -307,7 +314,7 @@ fn main() {
307}"#, 314}"#,
308 ); 315 );
309 316
310 assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" 317 assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
311 [ 318 [
312 InlayHint { 319 InlayHint {
313 range: [21; 30), 320 range: [21; 30),
@@ -355,7 +362,7 @@ fn main() {
355}"#, 362}"#,
356 ); 363 );
357 364
358 assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" 365 assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
359 [ 366 [
360 InlayHint { 367 InlayHint {
361 range: [166; 170), 368 range: [166; 170),
@@ -418,7 +425,7 @@ fn main() {
418}"#, 425}"#,
419 ); 426 );
420 427
421 assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" 428 assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
422 [ 429 [
423 InlayHint { 430 InlayHint {
424 range: [166; 170), 431 range: [166; 170),
@@ -481,7 +488,7 @@ fn main() {
481}"#, 488}"#,
482 ); 489 );
483 490
484 assert_debug_snapshot!(analysis.inlay_hints(file_id).unwrap(), @r###" 491 assert_debug_snapshot!(analysis.inlay_hints(file_id, None).unwrap(), @r###"
485 [ 492 [
486 InlayHint { 493 InlayHint {
487 range: [311; 315), 494 range: [311; 315),
@@ -507,4 +514,41 @@ fn main() {
507 "### 514 "###
508 ); 515 );
509 } 516 }
517
518 #[test]
519 fn hint_truncation() {
520 let (analysis, file_id) = single_file(
521 r#"
522struct Smol<T>(T);
523
524struct VeryLongOuterName<T>(T);
525
526fn main() {
527 let a = Smol(0u32);
528 let b = VeryLongOuterName(0usize);
529 let c = Smol(Smol(0u32))
530}"#,
531 );
532
533 assert_debug_snapshot!(analysis.inlay_hints(file_id, Some(8)).unwrap(), @r###"
534 [
535 InlayHint {
536 range: [74; 75),
537 kind: TypeHint,
538 label: "Smol<u32>",
539 },
540 InlayHint {
541 range: [98; 99),
542 kind: TypeHint,
543 label: "VeryLongOuterName<…>",
544 },
545 InlayHint {
546 range: [137; 138),
547 kind: TypeHint,
548 label: "Smol<Smol<…>>",
549 },
550 ]
551 "###
552 );
553 }
510} 554}
diff --git a/crates/ra_ide_api/src/join_lines.rs b/crates/ra_ide_api/src/join_lines.rs
index 6f71b27db..7deeb3494 100644
--- a/crates/ra_ide_api/src/join_lines.rs
+++ b/crates/ra_ide_api/src/join_lines.rs
@@ -244,6 +244,34 @@ fn foo(e: Result<U, V>) {
244 } 244 }
245 245
246 #[test] 246 #[test]
247 fn join_lines_multiline_in_block() {
248 check_join_lines(
249 r"
250fn foo() {
251 match ty {
252 <|> Some(ty) => {
253 match ty {
254 _ => false,
255 }
256 }
257 _ => true,
258 }
259}
260",
261 r"
262fn foo() {
263 match ty {
264 <|> Some(ty) => match ty {
265 _ => false,
266 },
267 _ => true,
268 }
269}
270",
271 );
272 }
273
274 #[test]
247 fn join_lines_keeps_comma_for_block_in_match_arm() { 275 fn join_lines_keeps_comma_for_block_in_match_arm() {
248 // We already have a comma 276 // We already have a comma
249 check_join_lines( 277 check_join_lines(
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index 57ed97147..62ad996bc 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -344,8 +344,14 @@ impl Analysis {
344 } 344 }
345 345
346 /// Returns a list of the places in the file where type hints can be displayed. 346 /// Returns a list of the places in the file where type hints can be displayed.
347 pub fn inlay_hints(&self, file_id: FileId) -> Cancelable<Vec<InlayHint>> { 347 pub fn inlay_hints(
348 self.with_db(|db| inlay_hints::inlay_hints(db, file_id, &db.parse(file_id).tree())) 348 &self,
349 file_id: FileId,
350 max_inlay_hint_length: Option<usize>,
351 ) -> Cancelable<Vec<InlayHint>> {
352 self.with_db(|db| {
353 inlay_hints::inlay_hints(db, file_id, &db.parse(file_id).tree(), max_inlay_hint_length)
354 })
349 } 355 }
350 356
351 /// Returns the set of folding ranges. 357 /// Returns the set of folding ranges.
diff --git a/crates/ra_ide_api/src/parent_module.rs b/crates/ra_ide_api/src/parent_module.rs
index 4c57566e2..fa232a379 100644
--- a/crates/ra_ide_api/src/parent_module.rs
+++ b/crates/ra_ide_api/src/parent_module.rs
@@ -10,7 +10,7 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<Na
10 let src = hir::ModuleSource::from_position(db, position); 10 let src = hir::ModuleSource::from_position(db, position);
11 let module = match hir::Module::from_definition( 11 let module = match hir::Module::from_definition(
12 db, 12 db,
13 hir::Source { file_id: position.file_id.into(), ast: src }, 13 hir::Source { file_id: position.file_id.into(), value: src },
14 ) { 14 ) {
15 None => return Vec::new(), 15 None => return Vec::new(),
16 Some(it) => it, 16 Some(it) => it,
@@ -23,7 +23,8 @@ pub(crate) fn parent_module(db: &RootDatabase, position: FilePosition) -> Vec<Na
23pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> { 23pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> {
24 let src = hir::ModuleSource::from_file_id(db, file_id); 24 let src = hir::ModuleSource::from_file_id(db, file_id);
25 let module = 25 let module =
26 match hir::Module::from_definition(db, hir::Source { file_id: file_id.into(), ast: src }) { 26 match hir::Module::from_definition(db, hir::Source { file_id: file_id.into(), value: src })
27 {
27 Some(it) => it, 28 Some(it) => it,
28 None => return Vec::new(), 29 None => return Vec::new(),
29 }; 30 };
diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs
index ea9d20e71..4a4b030f8 100644
--- a/crates/ra_ide_api/src/references/classify.rs
+++ b/crates/ra_ide_api/src/references/classify.rs
@@ -13,12 +13,12 @@ use crate::db::RootDatabase;
13 13
14pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Option<NameDefinition> { 14pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Option<NameDefinition> {
15 let _p = profile("classify_name"); 15 let _p = profile("classify_name");
16 let parent = name.ast.syntax().parent()?; 16 let parent = name.value.syntax().parent()?;
17 17
18 match_ast! { 18 match_ast! {
19 match parent { 19 match parent {
20 ast::BindPat(it) => { 20 ast::BindPat(it) => {
21 let src = name.with_ast(it); 21 let src = name.with_value(it);
22 let local = hir::Local::from_source(db, src)?; 22 let local = hir::Local::from_source(db, src)?;
23 Some(NameDefinition { 23 Some(NameDefinition {
24 visibility: None, 24 visibility: None,
@@ -28,7 +28,7 @@ pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Opti
28 }, 28 },
29 ast::RecordFieldDef(it) => { 29 ast::RecordFieldDef(it) => {
30 let ast = hir::FieldSource::Named(it); 30 let ast = hir::FieldSource::Named(it);
31 let src = name.with_ast(ast); 31 let src = name.with_value(ast);
32 let field = hir::StructField::from_source(db, src)?; 32 let field = hir::StructField::from_source(db, src)?;
33 Some(from_struct_field(db, field)) 33 Some(from_struct_field(db, field))
34 }, 34 },
@@ -36,42 +36,42 @@ pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Opti
36 let def = { 36 let def = {
37 if !it.has_semi() { 37 if !it.has_semi() {
38 let ast = hir::ModuleSource::Module(it); 38 let ast = hir::ModuleSource::Module(it);
39 let src = name.with_ast(ast); 39 let src = name.with_value(ast);
40 hir::Module::from_definition(db, src) 40 hir::Module::from_definition(db, src)
41 } else { 41 } else {
42 let src = name.with_ast(it); 42 let src = name.with_value(it);
43 hir::Module::from_declaration(db, src) 43 hir::Module::from_declaration(db, src)
44 } 44 }
45 }?; 45 }?;
46 Some(from_module_def(db, def.into(), None)) 46 Some(from_module_def(db, def.into(), None))
47 }, 47 },
48 ast::StructDef(it) => { 48 ast::StructDef(it) => {
49 let src = name.with_ast(it); 49 let src = name.with_value(it);
50 let def = hir::Struct::from_source(db, src)?; 50 let def = hir::Struct::from_source(db, src)?;
51 Some(from_module_def(db, def.into(), None)) 51 Some(from_module_def(db, def.into(), None))
52 }, 52 },
53 ast::EnumDef(it) => { 53 ast::EnumDef(it) => {
54 let src = name.with_ast(it); 54 let src = name.with_value(it);
55 let def = hir::Enum::from_source(db, src)?; 55 let def = hir::Enum::from_source(db, src)?;
56 Some(from_module_def(db, def.into(), None)) 56 Some(from_module_def(db, def.into(), None))
57 }, 57 },
58 ast::TraitDef(it) => { 58 ast::TraitDef(it) => {
59 let src = name.with_ast(it); 59 let src = name.with_value(it);
60 let def = hir::Trait::from_source(db, src)?; 60 let def = hir::Trait::from_source(db, src)?;
61 Some(from_module_def(db, def.into(), None)) 61 Some(from_module_def(db, def.into(), None))
62 }, 62 },
63 ast::StaticDef(it) => { 63 ast::StaticDef(it) => {
64 let src = name.with_ast(it); 64 let src = name.with_value(it);
65 let def = hir::Static::from_source(db, src)?; 65 let def = hir::Static::from_source(db, src)?;
66 Some(from_module_def(db, def.into(), None)) 66 Some(from_module_def(db, def.into(), None))
67 }, 67 },
68 ast::EnumVariant(it) => { 68 ast::EnumVariant(it) => {
69 let src = name.with_ast(it); 69 let src = name.with_value(it);
70 let def = hir::EnumVariant::from_source(db, src)?; 70 let def = hir::EnumVariant::from_source(db, src)?;
71 Some(from_module_def(db, def.into(), None)) 71 Some(from_module_def(db, def.into(), None))
72 }, 72 },
73 ast::FnDef(it) => { 73 ast::FnDef(it) => {
74 let src = name.with_ast(it); 74 let src = name.with_value(it);
75 let def = hir::Function::from_source(db, src)?; 75 let def = hir::Function::from_source(db, src)?;
76 if parent.parent().and_then(ast::ItemList::cast).is_some() { 76 if parent.parent().and_then(ast::ItemList::cast).is_some() {
77 Some(from_assoc_item(db, def.into())) 77 Some(from_assoc_item(db, def.into()))
@@ -80,7 +80,7 @@ pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Opti
80 } 80 }
81 }, 81 },
82 ast::ConstDef(it) => { 82 ast::ConstDef(it) => {
83 let src = name.with_ast(it); 83 let src = name.with_value(it);
84 let def = hir::Const::from_source(db, src)?; 84 let def = hir::Const::from_source(db, src)?;
85 if parent.parent().and_then(ast::ItemList::cast).is_some() { 85 if parent.parent().and_then(ast::ItemList::cast).is_some() {
86 Some(from_assoc_item(db, def.into())) 86 Some(from_assoc_item(db, def.into()))
@@ -89,7 +89,7 @@ pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Opti
89 } 89 }
90 }, 90 },
91 ast::TypeAliasDef(it) => { 91 ast::TypeAliasDef(it) => {
92 let src = name.with_ast(it); 92 let src = name.with_value(it);
93 let def = hir::TypeAlias::from_source(db, src)?; 93 let def = hir::TypeAlias::from_source(db, src)?;
94 if parent.parent().and_then(ast::ItemList::cast).is_some() { 94 if parent.parent().and_then(ast::ItemList::cast).is_some() {
95 Some(from_assoc_item(db, def.into())) 95 Some(from_assoc_item(db, def.into()))
@@ -98,11 +98,11 @@ pub(crate) fn classify_name(db: &RootDatabase, name: Source<&ast::Name>) -> Opti
98 } 98 }
99 }, 99 },
100 ast::MacroCall(it) => { 100 ast::MacroCall(it) => {
101 let src = name.with_ast(it); 101 let src = name.with_value(it);
102 let def = hir::MacroDef::from_source(db, src.clone())?; 102 let def = hir::MacroDef::from_source(db, src.clone())?;
103 103
104 let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax())); 104 let module_src = ModuleSource::from_child_node(db, src.as_ref().map(|it| it.syntax()));
105 let module = Module::from_definition(db, src.with_ast(module_src))?; 105 let module = Module::from_definition(db, src.with_value(module_src))?;
106 106
107 Some(NameDefinition { 107 Some(NameDefinition {
108 visibility: None, 108 visibility: None,
@@ -121,7 +121,7 @@ pub(crate) fn classify_name_ref(
121) -> Option<NameDefinition> { 121) -> Option<NameDefinition> {
122 let _p = profile("classify_name_ref"); 122 let _p = profile("classify_name_ref");
123 123
124 let parent = name_ref.ast.syntax().parent()?; 124 let parent = name_ref.value.syntax().parent()?;
125 let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None); 125 let analyzer = SourceAnalyzer::new(db, name_ref.map(|it| it.syntax()), None);
126 126
127 if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) { 127 if let Some(method_call) = ast::MethodCallExpr::cast(parent.clone()) {
@@ -142,16 +142,16 @@ pub(crate) fn classify_name_ref(
142 tested_by!(goto_definition_works_for_record_fields); 142 tested_by!(goto_definition_works_for_record_fields);
143 if let Some(record_lit) = record_field.syntax().ancestors().find_map(ast::RecordLit::cast) { 143 if let Some(record_lit) = record_field.syntax().ancestors().find_map(ast::RecordLit::cast) {
144 let variant_def = analyzer.resolve_record_literal(&record_lit)?; 144 let variant_def = analyzer.resolve_record_literal(&record_lit)?;
145 let hir_path = Path::from_name_ref(name_ref.ast); 145 let hir_path = Path::from_name_ref(name_ref.value);
146 let hir_name = hir_path.as_ident()?; 146 let hir_name = hir_path.as_ident()?;
147 let field = variant_def.field(db, hir_name)?; 147 let field = variant_def.field(db, hir_name)?;
148 return Some(from_struct_field(db, field)); 148 return Some(from_struct_field(db, field));
149 } 149 }
150 } 150 }
151 151
152 let ast = ModuleSource::from_child_node(db, name_ref.with_ast(&parent)); 152 let ast = ModuleSource::from_child_node(db, name_ref.with_value(&parent));
153 // FIXME: find correct container and visibility for each case 153 // FIXME: find correct container and visibility for each case
154 let container = Module::from_definition(db, name_ref.with_ast(ast))?; 154 let container = Module::from_definition(db, name_ref.with_value(ast))?;
155 let visibility = None; 155 let visibility = None;
156 156
157 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { 157 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
@@ -162,7 +162,7 @@ pub(crate) fn classify_name_ref(
162 } 162 }
163 } 163 }
164 164
165 let path = name_ref.ast.syntax().ancestors().find_map(ast::Path::cast)?; 165 let path = name_ref.value.syntax().ancestors().find_map(ast::Path::cast)?;
166 let resolved = analyzer.resolve_path(db, &path)?; 166 let resolved = analyzer.resolve_path(db, &path)?;
167 match resolved { 167 match resolved {
168 PathResolution::Def(def) => Some(from_module_def(db, def, Some(container))), 168 PathResolution::Def(def) => Some(from_module_def(db, def, Some(container))),
diff --git a/crates/ra_ide_api/src/references/name_definition.rs b/crates/ra_ide_api/src/references/name_definition.rs
index ccd75278a..aca23f79e 100644
--- a/crates/ra_ide_api/src/references/name_definition.rs
+++ b/crates/ra_ide_api/src/references/name_definition.rs
@@ -32,9 +32,9 @@ pub(crate) struct NameDefinition {
32pub(super) fn from_assoc_item(db: &RootDatabase, item: AssocItem) -> NameDefinition { 32pub(super) fn from_assoc_item(db: &RootDatabase, item: AssocItem) -> NameDefinition {
33 let container = item.module(db); 33 let container = item.module(db);
34 let visibility = match item { 34 let visibility = match item {
35 AssocItem::Function(f) => f.source(db).ast.visibility(), 35 AssocItem::Function(f) => f.source(db).value.visibility(),
36 AssocItem::Const(c) => c.source(db).ast.visibility(), 36 AssocItem::Const(c) => c.source(db).value.visibility(),
37 AssocItem::TypeAlias(a) => a.source(db).ast.visibility(), 37 AssocItem::TypeAlias(a) => a.source(db).value.visibility(),
38 }; 38 };
39 let kind = NameKind::AssocItem(item); 39 let kind = NameKind::AssocItem(item);
40 NameDefinition { kind, container, visibility } 40 NameDefinition { kind, container, visibility }
@@ -45,8 +45,8 @@ pub(super) fn from_struct_field(db: &RootDatabase, field: StructField) -> NameDe
45 let parent = field.parent_def(db); 45 let parent = field.parent_def(db);
46 let container = parent.module(db); 46 let container = parent.module(db);
47 let visibility = match parent { 47 let visibility = match parent {
48 VariantDef::Struct(s) => s.source(db).ast.visibility(), 48 VariantDef::Struct(s) => s.source(db).value.visibility(),
49 VariantDef::EnumVariant(e) => e.source(db).ast.parent_enum().visibility(), 49 VariantDef::EnumVariant(e) => e.source(db).value.parent_enum().visibility(),
50 }; 50 };
51 NameDefinition { kind, container, visibility } 51 NameDefinition { kind, container, visibility }
52} 52}
@@ -60,22 +60,22 @@ pub(super) fn from_module_def(
60 let (container, visibility) = match def { 60 let (container, visibility) = match def {
61 ModuleDef::Module(it) => { 61 ModuleDef::Module(it) => {
62 let container = it.parent(db).or_else(|| Some(it)).unwrap(); 62 let container = it.parent(db).or_else(|| Some(it)).unwrap();
63 let visibility = it.declaration_source(db).and_then(|s| s.ast.visibility()); 63 let visibility = it.declaration_source(db).and_then(|s| s.value.visibility());
64 (container, visibility) 64 (container, visibility)
65 } 65 }
66 ModuleDef::EnumVariant(it) => { 66 ModuleDef::EnumVariant(it) => {
67 let container = it.module(db); 67 let container = it.module(db);
68 let visibility = it.source(db).ast.parent_enum().visibility(); 68 let visibility = it.source(db).value.parent_enum().visibility();
69 (container, visibility) 69 (container, visibility)
70 } 70 }
71 ModuleDef::Function(it) => (it.module(db), it.source(db).ast.visibility()), 71 ModuleDef::Function(it) => (it.module(db), it.source(db).value.visibility()),
72 ModuleDef::Const(it) => (it.module(db), it.source(db).ast.visibility()), 72 ModuleDef::Const(it) => (it.module(db), it.source(db).value.visibility()),
73 ModuleDef::Static(it) => (it.module(db), it.source(db).ast.visibility()), 73 ModuleDef::Static(it) => (it.module(db), it.source(db).value.visibility()),
74 ModuleDef::Trait(it) => (it.module(db), it.source(db).ast.visibility()), 74 ModuleDef::Trait(it) => (it.module(db), it.source(db).value.visibility()),
75 ModuleDef::TypeAlias(it) => (it.module(db), it.source(db).ast.visibility()), 75 ModuleDef::TypeAlias(it) => (it.module(db), it.source(db).value.visibility()),
76 ModuleDef::Adt(Adt::Struct(it)) => (it.module(db), it.source(db).ast.visibility()), 76 ModuleDef::Adt(Adt::Struct(it)) => (it.module(db), it.source(db).value.visibility()),
77 ModuleDef::Adt(Adt::Union(it)) => (it.module(db), it.source(db).ast.visibility()), 77 ModuleDef::Adt(Adt::Union(it)) => (it.module(db), it.source(db).value.visibility()),
78 ModuleDef::Adt(Adt::Enum(it)) => (it.module(db), it.source(db).ast.visibility()), 78 ModuleDef::Adt(Adt::Enum(it)) => (it.module(db), it.source(db).value.visibility()),
79 ModuleDef::BuiltinType(..) => (module.unwrap(), None), 79 ModuleDef::BuiltinType(..) => (module.unwrap(), None),
80 }; 80 };
81 NameDefinition { kind, container, visibility } 81 NameDefinition { kind, container, visibility }
diff --git a/crates/ra_ide_api/src/references/rename.rs b/crates/ra_ide_api/src/references/rename.rs
index 11f81cbb3..d58496049 100644
--- a/crates/ra_ide_api/src/references/rename.rs
+++ b/crates/ra_ide_api/src/references/rename.rs
@@ -55,11 +55,11 @@ fn rename_mod(
55) -> Option<SourceChange> { 55) -> Option<SourceChange> {
56 let mut source_file_edits = Vec::new(); 56 let mut source_file_edits = Vec::new();
57 let mut file_system_edits = Vec::new(); 57 let mut file_system_edits = Vec::new();
58 let module_src = hir::Source { file_id: position.file_id.into(), ast: ast_module.clone() }; 58 let module_src = hir::Source { file_id: position.file_id.into(), value: ast_module.clone() };
59 if let Some(module) = hir::Module::from_declaration(db, module_src) { 59 if let Some(module) = hir::Module::from_declaration(db, module_src) {
60 let src = module.definition_source(db); 60 let src = module.definition_source(db);
61 let file_id = src.file_id.original_file(db); 61 let file_id = src.file_id.original_file(db);
62 match src.ast { 62 match src.value {
63 ModuleSource::SourceFile(..) => { 63 ModuleSource::SourceFile(..) => {
64 let mod_path: RelativePathBuf = db.file_relative_path(file_id); 64 let mod_path: RelativePathBuf = db.file_relative_path(file_id);
65 // mod is defined in path/to/dir/mod.rs 65 // mod is defined in path/to/dir/mod.rs
@@ -121,141 +121,9 @@ mod tests {
121 121
122 use crate::{ 122 use crate::{
123 mock_analysis::analysis_and_position, mock_analysis::single_file_with_position, FileId, 123 mock_analysis::analysis_and_position, mock_analysis::single_file_with_position, FileId,
124 ReferenceSearchResult,
125 }; 124 };
126 125
127 #[test] 126 #[test]
128 fn test_find_all_refs_for_local() {
129 let code = r#"
130 fn main() {
131 let mut i = 1;
132 let j = 1;
133 i = i<|> + j;
134
135 {
136 i = 0;
137 }
138
139 i = 5;
140 }"#;
141
142 let refs = get_all_refs(code);
143 assert_eq!(refs.len(), 5);
144 }
145
146 #[test]
147 fn test_find_all_refs_for_param_inside() {
148 let code = r#"
149 fn foo(i : u32) -> u32 {
150 i<|>
151 }"#;
152
153 let refs = get_all_refs(code);
154 assert_eq!(refs.len(), 2);
155 }
156
157 #[test]
158 fn test_find_all_refs_for_fn_param() {
159 let code = r#"
160 fn foo(i<|> : u32) -> u32 {
161 i
162 }"#;
163
164 let refs = get_all_refs(code);
165 assert_eq!(refs.len(), 2);
166 }
167
168 #[test]
169 fn test_find_all_refs_field_name() {
170 let code = r#"
171 //- /lib.rs
172 struct Foo {
173 pub spam<|>: u32,
174 }
175
176 fn main(s: Foo) {
177 let f = s.spam;
178 }
179 "#;
180
181 let refs = get_all_refs(code);
182 assert_eq!(refs.len(), 2);
183 }
184
185 #[test]
186 fn test_find_all_refs_impl_item_name() {
187 let code = r#"
188 //- /lib.rs
189 struct Foo;
190 impl Foo {
191 fn f<|>(&self) { }
192 }
193 "#;
194
195 let refs = get_all_refs(code);
196 assert_eq!(refs.len(), 1);
197 }
198
199 #[test]
200 fn test_find_all_refs_enum_var_name() {
201 let code = r#"
202 //- /lib.rs
203 enum Foo {
204 A,
205 B<|>,
206 C,
207 }
208 "#;
209
210 let refs = get_all_refs(code);
211 assert_eq!(refs.len(), 1);
212 }
213
214 #[test]
215 fn test_find_all_refs_modules() {
216 let code = r#"
217 //- /lib.rs
218 pub mod foo;
219 pub mod bar;
220
221 fn f() {
222 let i = foo::Foo { n: 5 };
223 }
224
225 //- /foo.rs
226 use crate::bar;
227
228 pub struct Foo {
229 pub n: u32,
230 }
231
232 fn f() {
233 let i = bar::Bar { n: 5 };
234 }
235
236 //- /bar.rs
237 use crate::foo;
238
239 pub struct Bar {
240 pub n: u32,
241 }
242
243 fn f() {
244 let i = foo::Foo<|> { n: 5 };
245 }
246 "#;
247
248 let (analysis, pos) = analysis_and_position(code);
249 let refs = analysis.find_all_refs(pos, None).unwrap().unwrap();
250 assert_eq!(refs.len(), 3);
251 }
252
253 fn get_all_refs(text: &str) -> ReferenceSearchResult {
254 let (analysis, position) = single_file_with_position(text);
255 analysis.find_all_refs(position, None).unwrap().unwrap()
256 }
257
258 #[test]
259 fn test_rename_for_local() { 127 fn test_rename_for_local() {
260 test_rename( 128 test_rename(
261 r#" 129 r#"
diff --git a/crates/ra_ide_api/src/references/search_scope.rs b/crates/ra_ide_api/src/references/search_scope.rs
index 2907787c2..f5c9589f4 100644
--- a/crates/ra_ide_api/src/references/search_scope.rs
+++ b/crates/ra_ide_api/src/references/search_scope.rs
@@ -73,9 +73,9 @@ impl NameDefinition {
73 73
74 if let NameKind::Local(var) = self.kind { 74 if let NameKind::Local(var) = self.kind {
75 let range = match var.parent(db) { 75 let range = match var.parent(db) {
76 DefWithBody::Function(f) => f.source(db).ast.syntax().text_range(), 76 DefWithBody::Function(f) => f.source(db).value.syntax().text_range(),
77 DefWithBody::Const(c) => c.source(db).ast.syntax().text_range(), 77 DefWithBody::Const(c) => c.source(db).value.syntax().text_range(),
78 DefWithBody::Static(s) => s.source(db).ast.syntax().text_range(), 78 DefWithBody::Static(s) => s.source(db).value.syntax().text_range(),
79 }; 79 };
80 let mut res = FxHashMap::default(); 80 let mut res = FxHashMap::default();
81 res.insert(file_id, Some(range)); 81 res.insert(file_id, Some(range));
@@ -91,7 +91,7 @@ impl NameDefinition {
91 let parent_src = parent_module.definition_source(db); 91 let parent_src = parent_module.definition_source(db);
92 let file_id = parent_src.file_id.original_file(db); 92 let file_id = parent_src.file_id.original_file(db);
93 93
94 match parent_src.ast { 94 match parent_src.value {
95 ModuleSource::Module(m) => { 95 ModuleSource::Module(m) => {
96 let range = Some(m.syntax().text_range()); 96 let range = Some(m.syntax().text_range());
97 res.insert(file_id, range); 97 res.insert(file_id, range);
@@ -135,7 +135,7 @@ impl NameDefinition {
135 } 135 }
136 136
137 let mut res = FxHashMap::default(); 137 let mut res = FxHashMap::default();
138 let range = match module_src.ast { 138 let range = match module_src.value {
139 ModuleSource::Module(m) => Some(m.syntax().text_range()), 139 ModuleSource::Module(m) => Some(m.syntax().text_range()),
140 ModuleSource::SourceFile(_) => None, 140 ModuleSource::SourceFile(_) => None,
141 }; 141 };
diff --git a/crates/ra_lsp_server/src/config.rs b/crates/ra_lsp_server/src/config.rs
index 9871a3b37..8045f3d60 100644
--- a/crates/ra_lsp_server/src/config.rs
+++ b/crates/ra_lsp_server/src/config.rs
@@ -29,6 +29,8 @@ pub struct ServerConfig {
29 29
30 pub lru_capacity: Option<usize>, 30 pub lru_capacity: Option<usize>,
31 31
32 pub max_inlay_hint_length: Option<usize>,
33
32 /// For internal usage to make integrated tests faster. 34 /// For internal usage to make integrated tests faster.
33 #[serde(deserialize_with = "nullable_bool_true")] 35 #[serde(deserialize_with = "nullable_bool_true")]
34 pub with_sysroot: bool, 36 pub with_sysroot: bool,
@@ -44,6 +46,7 @@ impl Default for ServerConfig {
44 exclude_globs: Vec::new(), 46 exclude_globs: Vec::new(),
45 use_client_watching: false, 47 use_client_watching: false,
46 lru_capacity: None, 48 lru_capacity: None,
49 max_inlay_hint_length: None,
47 with_sysroot: true, 50 with_sysroot: true,
48 feature_flags: FxHashMap::default(), 51 feature_flags: FxHashMap::default(),
49 } 52 }
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index f828efdee..0dc0aeee8 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -123,6 +123,7 @@ pub fn main_loop(
123 .and_then(|it| it.folding_range.as_ref()) 123 .and_then(|it| it.folding_range.as_ref())
124 .and_then(|it| it.line_folding_only) 124 .and_then(|it| it.line_folding_only)
125 .unwrap_or(false), 125 .unwrap_or(false),
126 max_inlay_hint_length: config.max_inlay_hint_length,
126 } 127 }
127 }; 128 };
128 129
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 0461bf385..e552f2106 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -888,7 +888,7 @@ pub fn handle_inlay_hints(
888 let analysis = world.analysis(); 888 let analysis = world.analysis();
889 let line_index = analysis.file_line_index(file_id)?; 889 let line_index = analysis.file_line_index(file_id)?;
890 Ok(analysis 890 Ok(analysis
891 .inlay_hints(file_id)? 891 .inlay_hints(file_id, world.options.max_inlay_hint_length)?
892 .into_iter() 892 .into_iter()
893 .map(|api_type| InlayHint { 893 .map(|api_type| InlayHint {
894 label: api_type.label.to_string(), 894 label: api_type.label.to_string(),
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs
index 51824e7a3..9bdea70c7 100644
--- a/crates/ra_lsp_server/src/world.rs
+++ b/crates/ra_lsp_server/src/world.rs
@@ -28,6 +28,7 @@ pub struct Options {
28 pub publish_decorations: bool, 28 pub publish_decorations: bool,
29 pub supports_location_link: bool, 29 pub supports_location_link: bool,
30 pub line_folding_only: bool, 30 pub line_folding_only: bool,
31 pub max_inlay_hint_length: Option<usize>,
31} 32}
32 33
33/// `WorldState` is the primary mutable state of the language server 34/// `WorldState` is the primary mutable state of the language server
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs
index 2b381dcdb..de506d7cd 100644
--- a/crates/ra_syntax/src/ast/generated.rs
+++ b/crates/ra_syntax/src/ast/generated.rs
@@ -3625,8 +3625,11 @@ impl AstNode for TypeParam {
3625impl ast::NameOwner for TypeParam {} 3625impl ast::NameOwner for TypeParam {}
3626impl ast::AttrsOwner for TypeParam {} 3626impl ast::AttrsOwner for TypeParam {}
3627impl ast::TypeBoundsOwner for TypeParam {} 3627impl ast::TypeBoundsOwner for TypeParam {}
3628impl ast::DefaultTypeParamOwner for TypeParam {} 3628impl TypeParam {
3629impl TypeParam {} 3629 pub fn default_type(&self) -> Option<TypeRef> {
3630 AstChildren::new(&self.syntax).next()
3631 }
3632}
3630#[derive(Debug, Clone, PartialEq, Eq, Hash)] 3633#[derive(Debug, Clone, PartialEq, Eq, Hash)]
3631pub struct TypeParamList { 3634pub struct TypeParamList {
3632 pub(crate) syntax: SyntaxNode, 3635 pub(crate) syntax: SyntaxNode,
diff --git a/crates/ra_syntax/src/ast/traits.rs b/crates/ra_syntax/src/ast/traits.rs
index c2b005886..f99984fe0 100644
--- a/crates/ra_syntax/src/ast/traits.rs
+++ b/crates/ra_syntax/src/ast/traits.rs
@@ -163,9 +163,3 @@ impl Iterator for CommentIter {
163 self.iter.by_ref().find_map(|el| el.into_token().and_then(ast::Comment::cast)) 163 self.iter.by_ref().find_map(|el| el.into_token().and_then(ast::Comment::cast))
164 } 164 }
165} 165}
166
167pub trait DefaultTypeParamOwner: AstNode {
168 fn default_type(&self) -> Option<ast::PathType> {
169 child_opt(self)
170 }
171}
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron
index 70d85a8e6..88d1dc109 100644
--- a/crates/ra_syntax/src/grammar.ron
+++ b/crates/ra_syntax/src/grammar.ron
@@ -587,7 +587,10 @@ Grammar(
587 ("lifetime_params", "LifetimeParam" ), 587 ("lifetime_params", "LifetimeParam" ),
588 ] 588 ]
589 ), 589 ),
590 "TypeParam": ( traits: ["NameOwner", "AttrsOwner", "TypeBoundsOwner", "DefaultTypeParamOwner"] ), 590 "TypeParam": (
591 options: [("default_type", "TypeRef")],
592 traits: ["NameOwner", "AttrsOwner", "TypeBoundsOwner"],
593 ),
591 "LifetimeParam": ( 594 "LifetimeParam": (
592 traits: ["AttrsOwner"], 595 traits: ["AttrsOwner"],
593 ), 596 ),
diff --git a/crates/ra_syntax/src/ptr.rs b/crates/ra_syntax/src/ptr.rs
index 31167cada..e049fce61 100644
--- a/crates/ra_syntax/src/ptr.rs
+++ b/crates/ra_syntax/src/ptr.rs
@@ -43,7 +43,7 @@ impl SyntaxNodePtr {
43} 43}
44 44
45/// Like `SyntaxNodePtr`, but remembers the type of node 45/// Like `SyntaxNodePtr`, but remembers the type of node
46#[derive(Debug, PartialEq, Eq, Hash)] 46#[derive(Debug, Hash)]
47pub struct AstPtr<N: AstNode> { 47pub struct AstPtr<N: AstNode> {
48 raw: SyntaxNodePtr, 48 raw: SyntaxNodePtr,
49 _ty: PhantomData<fn() -> N>, 49 _ty: PhantomData<fn() -> N>,
@@ -56,6 +56,14 @@ impl<N: AstNode> Clone for AstPtr<N> {
56 } 56 }
57} 57}
58 58
59impl<N: AstNode> Eq for AstPtr<N> {}
60
61impl<N: AstNode> PartialEq for AstPtr<N> {
62 fn eq(&self, other: &AstPtr<N>) -> bool {
63 self.raw == other.raw
64 }
65}
66
59impl<N: AstNode> AstPtr<N> { 67impl<N: AstNode> AstPtr<N> {
60 pub fn new(node: &N) -> AstPtr<N> { 68 pub fn new(node: &N) -> AstPtr<N> {
61 AstPtr { raw: SyntaxNodePtr::new(node.syntax()), _ty: PhantomData } 69 AstPtr { raw: SyntaxNodePtr::new(node.syntax()), _ty: PhantomData }
diff --git a/docs/user/README.md b/docs/user/README.md
index eac9c50d2..235676850 100644
--- a/docs/user/README.md
+++ b/docs/user/README.md
@@ -136,7 +136,7 @@ Installation:
136[ra-emacs-lsp.el](https://github.com/rust-analyzer/rust-analyzer/blob/69ee5c9c5ef212f7911028c9ddf581559e6565c3/editors/emacs/ra-emacs-lsp.el) 136[ra-emacs-lsp.el](https://github.com/rust-analyzer/rust-analyzer/blob/69ee5c9c5ef212f7911028c9ddf581559e6565c3/editors/emacs/ra-emacs-lsp.el)
137to load path and require it in `init.el` 137to load path and require it in `init.el`
138* run `lsp` in a rust buffer 138* run `lsp` in a rust buffer
139* (Optionally) bind commands like `rust-analyzer-join-lines` or `rust-analyzer-extend-selection` to keys, and enable `rust-analyzer-inlay-hints-mode` to get inline type hints 139* (Optionally) bind commands like `rust-analyzer-join-lines`, `rust-analyzer-extend-selection` and `rust-analyzer-expand-macro` to keys, and enable `rust-analyzer-inlay-hints-mode` to get inline type hints
140 140
141 141
142## Vim and NeoVim 142## Vim and NeoVim
diff --git a/editors/code/src/commands/inlay_hints.ts b/editors/code/src/commands/inlay_hints.ts
index ffaaaebcb..0dbdd94fb 100644
--- a/editors/code/src/commands/inlay_hints.ts
+++ b/editors/code/src/commands/inlay_hints.ts
@@ -87,7 +87,7 @@ export class HintsUpdater {
87 range: hint.range, 87 range: hint.range,
88 renderOptions: { 88 renderOptions: {
89 after: { 89 after: {
90 contentText: `: ${this.truncateHint(hint.label)}` 90 contentText: `: ${hint.label}`
91 } 91 }
92 } 92 }
93 })); 93 }));
@@ -98,18 +98,6 @@ export class HintsUpdater {
98 } 98 }
99 } 99 }
100 100
101 private truncateHint(label: string): string {
102 if (!Server.config.maxInlayHintLength) {
103 return label;
104 }
105
106 let newLabel = label.substring(0, Server.config.maxInlayHintLength);
107 if (label.length > Server.config.maxInlayHintLength) {
108 newLabel += '…';
109 }
110 return newLabel;
111 }
112
113 private async queryHints(documentUri: string): Promise<InlayHint[] | null> { 101 private async queryHints(documentUri: string): Promise<InlayHint[] | null> {
114 const request: InlayHintsParams = { 102 const request: InlayHintsParams = {
115 textDocument: { uri: documentUri } 103 textDocument: { uri: documentUri }
diff --git a/editors/code/src/server.ts b/editors/code/src/server.ts
index a3ef21a16..7907b70bc 100644
--- a/editors/code/src/server.ts
+++ b/editors/code/src/server.ts
@@ -43,6 +43,7 @@ export class Server {
43 initializationOptions: { 43 initializationOptions: {
44 publishDecorations: true, 44 publishDecorations: true,
45 lruCapacity: Server.config.lruCapacity, 45 lruCapacity: Server.config.lruCapacity,
46 maxInlayHintLength: Server.config.maxInlayHintLength,
46 excludeGlobs: Server.config.excludeGlobs, 47 excludeGlobs: Server.config.excludeGlobs,
47 useClientWatching: Server.config.useClientWatching, 48 useClientWatching: Server.config.useClientWatching,
48 featureFlags: Server.config.featureFlags 49 featureFlags: Server.config.featureFlags
diff --git a/editors/emacs/ra-emacs-lsp.el b/editors/emacs/ra-emacs-lsp.el
index 79822c8ce..fafb9cbe7 100644
--- a/editors/emacs/ra-emacs-lsp.el
+++ b/editors/emacs/ra-emacs-lsp.el
@@ -16,6 +16,7 @@
16;; - implements joinLines (you need to bind rust-analyzer-join-lines to a key) 16;; - implements joinLines (you need to bind rust-analyzer-join-lines to a key)
17;; - implements selectionRanges (either bind lsp-extend-selection to a key, or use expand-region) 17;; - implements selectionRanges (either bind lsp-extend-selection to a key, or use expand-region)
18;; - provides rust-analyzer-inlay-hints-mode for inline type hints 18;; - provides rust-analyzer-inlay-hints-mode for inline type hints
19;; - provides rust-analyzer-expand-macro to expand macros
19 20
20;; What's missing: 21;; What's missing:
21;; - file system changes in apply-source-change 22;; - file system changes in apply-source-change
@@ -247,5 +248,32 @@
247 (remove-hook 'after-change-functions #'rust-analyzer--inlay-hints-change-handler t)))) 248 (remove-hook 'after-change-functions #'rust-analyzer--inlay-hints-change-handler t))))
248 249
249 250
251
252;; expand macros
253(defun rust-analyzer-expand-macro ()
254 "Expands the macro call at point recursively."
255 (interactive)
256 (when (eq 'rust-mode major-mode)
257 (let* ((workspace (lsp-find-workspace 'rust-analyzer (buffer-file-name)))
258 (params (list :textDocument (lsp--text-document-identifier)
259 :position (lsp--cur-position))))
260 (when workspace
261 (let* ((response (with-lsp-workspace workspace
262 (lsp-send-request (lsp-make-request
263 "rust-analyzer/expandMacro"
264 params))))
265 (result (when response (ht-get response "expansion"))))
266 (if result
267 (let ((buf (get-buffer-create (concat "*rust-analyzer macro expansion " (with-lsp-workspace workspace (lsp-workspace-root)) "*"))))
268 (with-current-buffer buf
269 (let ((inhibit-read-only t))
270 (erase-buffer)
271 (insert result)
272 (setq buffer-read-only t)
273 (special-mode)))
274 (pop-to-buffer buf))
275 (message "No macro found at point, or it could not be expanded")))))))
276
277
250(provide 'ra-emacs-lsp) 278(provide 'ra-emacs-lsp)
251;;; ra-emacs-lsp.el ends here 279;;; ra-emacs-lsp.el ends here
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml
index 77b9ae2b4..65cabf005 100644
--- a/xtask/Cargo.toml
+++ b/xtask/Cargo.toml
@@ -5,6 +5,9 @@ version = "0.1.0"
5authors = ["rust-analyzer developers"] 5authors = ["rust-analyzer developers"]
6publish = false 6publish = false
7 7
8[lib]
9doctest = false
10
8[dependencies] 11[dependencies]
9walkdir = "2.1.3" 12walkdir = "2.1.3"
10pico-args = "0.3.0" 13pico-args = "0.3.0"
diff --git a/xtask/src/main.rs b/xtask/src/main.rs
index 663e28103..c97bfec97 100644
--- a/xtask/src/main.rs
+++ b/xtask/src/main.rs
@@ -9,11 +9,10 @@
9//! `.cargo/config`. 9//! `.cargo/config`.
10mod help; 10mod help;
11 11
12use std::{env, fmt::Write, path::PathBuf, str};
13
12use anyhow::Context; 14use anyhow::Context;
13use core::fmt::Write;
14use core::str;
15use pico_args::Arguments; 15use pico_args::Arguments;
16use std::{env, path::PathBuf};
17use xtask::{ 16use xtask::{
18 codegen::{self, Mode}, 17 codegen::{self, Mode},
19 install_pre_commit_hook, reformat_staged_files, run, run_clippy, run_fuzzer, run_rustfmt, 18 install_pre_commit_hook, reformat_staged_files, run, run_clippy, run_fuzzer, run_rustfmt,
@@ -37,7 +36,7 @@ struct ServerOpt {
37} 36}
38 37
39fn main() -> Result<()> { 38fn main() -> Result<()> {
40 if std::env::args().next().map(|it| it.contains("pre-commit")) == Some(true) { 39 if env::args().next().map(|it| it.contains("pre-commit")) == Some(true) {
41 return reformat_staged_files(); 40 return reformat_staged_files();
42 } 41 }
43 42
@@ -174,7 +173,7 @@ fn fix_path_for_mac() -> Result<()> {
174fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> { 173fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> {
175 let npm_version = Cmd { 174 let npm_version = Cmd {
176 unix: r"npm --version", 175 unix: r"npm --version",
177 windows: r"cmd.exe /c npm.cmd --version", 176 windows: r"cmd.exe /c npm --version",
178 work_dir: "./editors/code", 177 work_dir: "./editors/code",
179 } 178 }
180 .run(); 179 .run();
@@ -183,10 +182,10 @@ fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> {
183 eprintln!("\nERROR: `npm --version` failed, `npm` is required to build the VS Code plugin") 182 eprintln!("\nERROR: `npm --version` failed, `npm` is required to build the VS Code plugin")
184 } 183 }
185 184
186 Cmd { unix: r"npm ci", windows: r"cmd.exe /c npm.cmd ci", work_dir: "./editors/code" }.run()?; 185 Cmd { unix: r"npm ci", windows: r"cmd.exe /c npm ci", work_dir: "./editors/code" }.run()?;
187 Cmd { 186 Cmd {
188 unix: r"npm run package --scripts-prepend-node-path", 187 unix: r"npm run package --scripts-prepend-node-path",
189 windows: r"cmd.exe /c npm.cmd run package", 188 windows: r"cmd.exe /c npm run package",
190 work_dir: "./editors/code", 189 work_dir: "./editors/code",
191 } 190 }
192 .run()?; 191 .run()?;