aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock7
-rw-r--r--crates/ra_assists/src/add_missing_impl_members.rs4
-rw-r--r--crates/ra_assists/src/fill_match_arms.rs6
-rw-r--r--crates/ra_batch/src/lib.rs8
-rw-r--r--crates/ra_cli/src/analysis_stats.rs8
-rw-r--r--crates/ra_db/Cargo.toml2
-rw-r--r--crates/ra_db/src/lib.rs2
-rw-r--r--crates/ra_hir/src/adt.rs39
-rw-r--r--crates/ra_hir/src/code_model.rs120
-rw-r--r--crates/ra_hir/src/code_model/docs.rs (renamed from crates/ra_hir/src/docs.rs)26
-rw-r--r--crates/ra_hir/src/code_model/src.rs110
-rw-r--r--crates/ra_hir/src/db.rs4
-rw-r--r--crates/ra_hir/src/expr.rs19
-rw-r--r--crates/ra_hir/src/expr/validation.rs4
-rw-r--r--crates/ra_hir/src/generics.rs18
-rw-r--r--crates/ra_hir/src/ids.rs6
-rw-r--r--crates/ra_hir/src/impl_block.rs27
-rw-r--r--crates/ra_hir/src/lang_item.rs2
-rw-r--r--crates/ra_hir/src/lib.rs4
-rw-r--r--crates/ra_hir/src/source_binder.rs6
-rw-r--r--crates/ra_hir/src/traits.rs12
-rw-r--r--crates/ra_hir/src/ty/infer.rs4
-rw-r--r--crates/ra_hir/src/type_alias.rs4
-rw-r--r--crates/ra_ide_api/src/change.rs1
-rw-r--r--crates/ra_ide_api/src/completion/presentation.rs12
-rw-r--r--crates/ra_ide_api/src/db.rs11
-rw-r--r--crates/ra_ide_api/src/display/function_signature.rs9
-rw-r--r--crates/ra_ide_api/src/display/navigation_target.rs200
-rw-r--r--crates/ra_ide_api/src/goto_definition.rs8
-rw-r--r--crates/ra_ide_api/src/hover.rs144
-rw-r--r--crates/ra_ide_api/src/lib.rs11
-rw-r--r--crates/ra_ide_api/src/references.rs6
-rw-r--r--crates/ra_lsp_server/src/init.rs14
-rw-r--r--crates/ra_lsp_server/src/main_loop.rs2
-rw-r--r--crates/ra_lsp_server/src/world.rs8
-rw-r--r--docs/dev/architecture.md14
-rw-r--r--editors/code/package.json5
-rw-r--r--editors/code/src/config.ts4
-rw-r--r--editors/code/src/server.ts3
39 files changed, 417 insertions, 477 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 579daecf1..2c1c7099e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1058,7 +1058,7 @@ dependencies = [
1058 "ra_syntax 0.1.0", 1058 "ra_syntax 0.1.0",
1059 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", 1059 "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
1060 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", 1060 "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
1061 "salsa 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", 1061 "salsa 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)",
1062 "test_utils 0.1.0", 1062 "test_utils 0.1.0",
1063] 1063]
1064 1064
@@ -1478,11 +1478,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
1478 1478
1479[[package]] 1479[[package]]
1480name = "salsa" 1480name = "salsa"
1481version = "0.12.2" 1481version = "0.12.3"
1482source = "registry+https://github.com/rust-lang/crates.io-index" 1482source = "registry+https://github.com/rust-lang/crates.io-index"
1483dependencies = [ 1483dependencies = [
1484 "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)", 1484 "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
1485 "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 1485 "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
1486 "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
1486 "lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 1487 "lock_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
1487 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", 1488 "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
1488 "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", 1489 "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2125,7 +2126,7 @@ dependencies = [
2125"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8" 2126"checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
2126"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" 2127"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
2127"checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f" 2128"checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f"
2128"checksum salsa 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f2208fabe493ad352dc4f544c482b39e9b9a2c1719d9aa4a0f5e828a61210956" 2129"checksum salsa 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2891cd628406e8a0ca714b827511de1bff76f796e3382cc72a3de732ccad5aea"
2129"checksum salsa-macros 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7f1e25ca2b995bdf032946174929d62156ffd57abd7ff88dc6f9bdeb5ac0c59" 2130"checksum salsa-macros 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7f1e25ca2b995bdf032946174929d62156ffd57abd7ff88dc6f9bdeb5ac0c59"
2130"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" 2131"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
2131"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" 2132"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
diff --git a/crates/ra_assists/src/add_missing_impl_members.rs b/crates/ra_assists/src/add_missing_impl_members.rs
index 23c01e747..0e49b0401 100644
--- a/crates/ra_assists/src/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/add_missing_impl_members.rs
@@ -1,6 +1,6 @@
1use crate::{Assist, AssistId, AssistCtx, ast_editor::{AstEditor, AstBuilder}}; 1use crate::{Assist, AssistId, AssistCtx, ast_editor::{AstEditor, AstBuilder}};
2 2
3use hir::db::HirDatabase; 3use hir::{HasSource, db::HirDatabase};
4use ra_syntax::{SmolStr, TreeArc}; 4use ra_syntax::{SmolStr, TreeArc};
5use ra_syntax::ast::{self, AstNode, FnDef, ImplItem, ImplItemKind, NameOwner}; 5use ra_syntax::ast::{self, AstNode, FnDef, ImplItem, ImplItemKind, NameOwner};
6use ra_db::FilePosition; 6use ra_db::FilePosition;
@@ -110,7 +110,7 @@ fn resolve_target_trait_def(
110 impl_block.target_trait().map(AstNode::syntax).and_then(ast::PathType::cast)?.path()?; 110 impl_block.target_trait().map(AstNode::syntax).and_then(ast::PathType::cast)?.path()?;
111 111
112 match analyzer.resolve_path(db, &ast_path) { 112 match analyzer.resolve_path(db, &ast_path) {
113 Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def.source(db).1), 113 Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def.source(db).ast),
114 _ => None, 114 _ => None,
115 } 115 }
116} 116}
diff --git a/crates/ra_assists/src/fill_match_arms.rs b/crates/ra_assists/src/fill_match_arms.rs
index 45e327cd4..a7de6ae9f 100644
--- a/crates/ra_assists/src/fill_match_arms.rs
+++ b/crates/ra_assists/src/fill_match_arms.rs
@@ -1,7 +1,7 @@
1use std::fmt::Write; 1use std::fmt::Write;
2 2
3use hir::{ 3use hir::{
4 AdtDef, FieldSource, 4 AdtDef, FieldSource, HasSource,
5 db::HirDatabase, 5 db::HirDatabase,
6}; 6};
7use ra_syntax::ast::{self, AstNode}; 7use ra_syntax::ast::{self, AstNode};
@@ -44,8 +44,8 @@ pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<As
44 .into_iter() 44 .into_iter()
45 .map(|field| { 45 .map(|field| {
46 let name = field.name(db).to_string(); 46 let name = field.name(db).to_string();
47 let (_, source) = field.source(db); 47 let src = field.source(db);
48 match source { 48 match src.ast {
49 FieldSource::Named(_) => name, 49 FieldSource::Named(_) => name,
50 FieldSource::Pos(_) => "_".to_string(), 50 FieldSource::Pos(_) => "_".to_string(),
51 } 51 }
diff --git a/crates/ra_batch/src/lib.rs b/crates/ra_batch/src/lib.rs
index a445dcb4d..c59821f44 100644
--- a/crates/ra_batch/src/lib.rs
+++ b/crates/ra_batch/src/lib.rs
@@ -7,7 +7,7 @@ use std::collections::HashSet;
7use rustc_hash::FxHashMap; 7use rustc_hash::FxHashMap;
8 8
9use ra_db::{ 9use ra_db::{
10 CrateGraph, FileId, SourceRoot, SourceRootId, SourceDatabase, salsa, 10 CrateGraph, FileId, SourceRoot, SourceRootId, SourceDatabase, salsa::{self, Database},
11}; 11};
12use ra_hir::db; 12use ra_hir::db;
13use ra_project_model::ProjectWorkspace; 13use ra_project_model::ProjectWorkspace;
@@ -43,6 +43,12 @@ fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId {
43impl BatchDatabase { 43impl BatchDatabase {
44 pub fn load(crate_graph: CrateGraph, vfs: &mut Vfs) -> BatchDatabase { 44 pub fn load(crate_graph: CrateGraph, vfs: &mut Vfs) -> BatchDatabase {
45 let mut db = BatchDatabase { runtime: salsa::Runtime::default() }; 45 let mut db = BatchDatabase { runtime: salsa::Runtime::default() };
46 let lru_cap = std::env::var("RA_LRU_CAP")
47 .ok()
48 .and_then(|it| it.parse::<usize>().ok())
49 .unwrap_or(ra_db::DEFAULT_LRU_CAP);
50 db.query_mut(ra_db::ParseQuery).set_lru_capacity(lru_cap);
51 db.query_mut(ra_hir::db::ParseMacroQuery).set_lru_capacity(lru_cap);
46 db.set_crate_graph(Arc::new(crate_graph)); 52 db.set_crate_graph(Arc::new(crate_graph));
47 53
48 // wait until Vfs has loaded all roots 54 // wait until Vfs has loaded all roots
diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs
index 8bb524ce3..c19976bd2 100644
--- a/crates/ra_cli/src/analysis_stats.rs
+++ b/crates/ra_cli/src/analysis_stats.rs
@@ -2,7 +2,7 @@ use std::{collections::HashSet, time::Instant, fmt::Write};
2 2
3use ra_db::SourceDatabase; 3use ra_db::SourceDatabase;
4use ra_batch::BatchDatabase; 4use ra_batch::BatchDatabase;
5use ra_hir::{Crate, ModuleDef, Ty, ImplItem}; 5use ra_hir::{Crate, ModuleDef, Ty, ImplItem, HasSource};
6use ra_syntax::AstNode; 6use ra_syntax::AstNode;
7 7
8use crate::Result; 8use crate::Result;
@@ -64,10 +64,10 @@ pub fn run(verbose: bool, path: &str, only: Option<&str>) -> Result<()> {
64 let name = f.name(&db); 64 let name = f.name(&db);
65 let mut msg = format!("processing: {}", name); 65 let mut msg = format!("processing: {}", name);
66 if verbose { 66 if verbose {
67 let (file_id, source) = f.source(&db); 67 let src = f.source(&db);
68 let original_file = file_id.original_file(&db); 68 let original_file = src.file_id.original_file(&db);
69 let path = db.file_relative_path(original_file); 69 let path = db.file_relative_path(original_file);
70 let syntax_range = source.syntax().range(); 70 let syntax_range = src.ast.syntax().range();
71 write!(msg, " ({:?} {})", path, syntax_range).unwrap(); 71 write!(msg, " ({:?} {})", path, syntax_range).unwrap();
72 } 72 }
73 bar.set_message(&msg); 73 bar.set_message(&msg);
diff --git a/crates/ra_db/Cargo.toml b/crates/ra_db/Cargo.toml
index 827855b2f..f73dd739a 100644
--- a/crates/ra_db/Cargo.toml
+++ b/crates/ra_db/Cargo.toml
@@ -5,7 +5,7 @@ version = "0.1.0"
5authors = ["rust-analyzer developers"] 5authors = ["rust-analyzer developers"]
6 6
7[dependencies] 7[dependencies]
8salsa = "0.12.1" 8salsa = "0.12.3"
9relative-path = "0.4.0" 9relative-path = "0.4.0"
10rustc-hash = "1.0" 10rustc-hash = "1.0"
11 11
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index 7c49c585b..f08616100 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -65,6 +65,8 @@ pub struct FileRange {
65 pub range: TextRange, 65 pub range: TextRange,
66} 66}
67 67
68pub const DEFAULT_LRU_CAP: usize = 128;
69
68/// Database which stores all significant input facts: source code and project 70/// Database which stores all significant input facts: source code and project
69/// model. Everything else in rust-analyzer is derived from these queries. 71/// model. Everything else in rust-analyzer is derived from these queries.
70#[salsa::query_group(SourceDatabaseStorage)] 72#[salsa::query_group(SourceDatabaseStorage)]
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index 38ff1d6f6..b3843b35c 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -11,7 +11,7 @@ use ra_syntax::{
11 11
12use crate::{ 12use crate::{
13 Name, AsName, Struct, Union, Enum, EnumVariant, Crate, AstDatabase, 13 Name, AsName, Struct, Union, Enum, EnumVariant, Crate, AstDatabase,
14 HirDatabase, HirFileId, StructField, FieldSource, 14 HirDatabase, StructField, FieldSource, Source, HasSource,
15 type_ref::TypeRef, DefDatabase, 15 type_ref::TypeRef, DefDatabase,
16}; 16};
17 17
@@ -59,8 +59,8 @@ impl StructData {
59 db: &(impl DefDatabase + AstDatabase), 59 db: &(impl DefDatabase + AstDatabase),
60 struct_: Struct, 60 struct_: Struct,
61 ) -> Arc<StructData> { 61 ) -> Arc<StructData> {
62 let (_, struct_def) = struct_.source(db); 62 let src = struct_.source(db);
63 Arc::new(StructData::new(&*struct_def)) 63 Arc::new(StructData::new(&*src.ast))
64 } 64 }
65} 65}
66 66
@@ -72,15 +72,15 @@ impl EnumVariant {
72 pub(crate) fn source_impl( 72 pub(crate) fn source_impl(
73 &self, 73 &self,
74 db: &(impl DefDatabase + AstDatabase), 74 db: &(impl DefDatabase + AstDatabase),
75 ) -> (HirFileId, TreeArc<ast::EnumVariant>) { 75 ) -> Source<TreeArc<ast::EnumVariant>> {
76 let (file_id, enum_def) = self.parent.source(db); 76 let src = self.parent.source(db);
77 let var = variants(&*enum_def) 77 let ast = variants(&*src.ast)
78 .zip(db.enum_data(self.parent).variants.iter()) 78 .zip(db.enum_data(self.parent).variants.iter())
79 .find(|(_syntax, (id, _))| *id == self.id) 79 .find(|(_syntax, (id, _))| *id == self.id)
80 .unwrap() 80 .unwrap()
81 .0 81 .0
82 .to_owned(); 82 .to_owned();
83 (file_id, var) 83 Source { file_id: src.file_id, ast }
84 } 84 }
85 pub(crate) fn variant_data(&self, db: &impl DefDatabase) -> Arc<VariantData> { 85 pub(crate) fn variant_data(&self, db: &impl DefDatabase) -> Arc<VariantData> {
86 db.enum_data(self.parent).variants[self.id].variant_data.clone() 86 db.enum_data(self.parent).variants[self.id].variant_data.clone()
@@ -95,9 +95,9 @@ pub struct EnumData {
95 95
96impl EnumData { 96impl EnumData {
97 pub(crate) fn enum_data_query(db: &(impl DefDatabase + AstDatabase), e: Enum) -> Arc<EnumData> { 97 pub(crate) fn enum_data_query(db: &(impl DefDatabase + AstDatabase), e: Enum) -> Arc<EnumData> {
98 let (_file_id, enum_def) = e.source(db); 98 let src = e.source(db);
99 let name = enum_def.name().map(|n| n.as_name()); 99 let name = src.ast.name().map(|n| n.as_name());
100 let variants = variants(&*enum_def) 100 let variants = variants(&*src.ast)
101 .map(|var| EnumVariantData { 101 .map(|var| EnumVariantData {
102 name: var.name().map(|it| it.as_name()), 102 name: var.name().map(|it| it.as_name()),
103 variant_data: Arc::new(VariantData::new(var.kind())), 103 variant_data: Arc::new(VariantData::new(var.kind())),
@@ -201,24 +201,19 @@ impl VariantDef {
201} 201}
202 202
203impl StructField { 203impl StructField {
204 pub(crate) fn source_impl( 204 pub(crate) fn source_impl(&self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> {
205 &self,
206 db: &(impl DefDatabase + AstDatabase),
207 ) -> (HirFileId, FieldSource) {
208 let var_data = self.parent.variant_data(db); 205 let var_data = self.parent.variant_data(db);
209 let fields = var_data.fields().unwrap(); 206 let fields = var_data.fields().unwrap();
210 let ss; 207 let ss;
211 let es; 208 let es;
212 let (file_id, struct_kind) = match self.parent { 209 let (file_id, struct_kind) = match self.parent {
213 VariantDef::Struct(s) => { 210 VariantDef::Struct(s) => {
214 let (file_id, source) = s.source(db); 211 ss = s.source(db);
215 ss = source; 212 (ss.file_id, ss.ast.kind())
216 (file_id, ss.kind())
217 } 213 }
218 VariantDef::EnumVariant(e) => { 214 VariantDef::EnumVariant(e) => {
219 let (file_id, source) = e.source(db); 215 es = e.source(db);
220 es = source; 216 (es.file_id, es.ast.kind())
221 (file_id, es.kind())
222 } 217 }
223 }; 218 };
224 219
@@ -231,12 +226,12 @@ impl StructField {
231 } 226 }
232 ast::StructKind::Unit => Vec::new(), 227 ast::StructKind::Unit => Vec::new(),
233 }; 228 };
234 let field = field_sources 229 let ast = field_sources
235 .into_iter() 230 .into_iter()
236 .zip(fields.iter()) 231 .zip(fields.iter())
237 .find(|(_syntax, (id, _))| *id == self.id) 232 .find(|(_syntax, (id, _))| *id == self.id)
238 .unwrap() 233 .unwrap()
239 .0; 234 .0;
240 (file_id, field) 235 Source { file_id, ast }
241 } 236 }
242} 237}
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 27850028b..830aea1f3 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -1,10 +1,13 @@
1pub(crate) mod src;
2pub(crate) mod docs;
3
1use std::sync::Arc; 4use std::sync::Arc;
2 5
3use ra_db::{CrateId, SourceRootId, Edition, FileId}; 6use ra_db::{CrateId, SourceRootId, Edition, FileId};
4use ra_syntax::{ast::{self, NameOwner, TypeAscriptionOwner}, TreeArc}; 7use ra_syntax::{ast::{self, NameOwner, TypeAscriptionOwner}, TreeArc};
5 8
6use crate::{ 9use crate::{
7 Name, AsName, AstId, Ty, HirFileId, Either, KnownName, 10 Name, AsName, AstId, Ty, Either, KnownName, HasSource,
8 HirDatabase, DefDatabase, AstDatabase, 11 HirDatabase, DefDatabase, AstDatabase,
9 type_ref::TypeRef, 12 type_ref::TypeRef,
10 nameres::{ModuleScope, Namespace, ImportId, CrateModuleId}, 13 nameres::{ModuleScope, Namespace, ImportId, CrateModuleId},
@@ -179,40 +182,15 @@ impl Module {
179 }) 182 })
180 } 183 }
181 184
182 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
183 pub fn definition_source(
184 self,
185 db: &(impl DefDatabase + AstDatabase),
186 ) -> (HirFileId, ModuleSource) {
187 let def_map = db.crate_def_map(self.krate);
188 let decl_id = def_map[self.module_id].declaration;
189 let file_id = def_map[self.module_id].definition;
190 let module_source = ModuleSource::new(db, file_id, decl_id);
191 let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id());
192 (file_id, module_source)
193 }
194
195 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
196 /// `None` for the crate root.
197 pub fn declaration_source(
198 self,
199 db: &(impl DefDatabase + AstDatabase),
200 ) -> Option<(HirFileId, TreeArc<ast::Module>)> {
201 let def_map = db.crate_def_map(self.krate);
202 let decl = def_map[self.module_id].declaration?;
203 let ast = decl.to_node(db);
204 Some((decl.file_id(), ast))
205 }
206
207 /// Returns the syntax of the last path segment corresponding to this import 185 /// Returns the syntax of the last path segment corresponding to this import
208 pub fn import_source( 186 pub fn import_source(
209 self, 187 self,
210 db: &impl HirDatabase, 188 db: &impl HirDatabase,
211 import: ImportId, 189 import: ImportId,
212 ) -> Either<TreeArc<ast::UseTree>, TreeArc<ast::ExternCrateItem>> { 190 ) -> Either<TreeArc<ast::UseTree>, TreeArc<ast::ExternCrateItem>> {
213 let (file_id, source) = self.definition_source(db); 191 let src = self.definition_source(db);
214 let (_, source_map) = db.raw_items_with_source_map(file_id); 192 let (_, source_map) = db.raw_items_with_source_map(src.file_id);
215 source_map.get(&source, import) 193 source_map.get(&src.ast, import)
216 } 194 }
217 195
218 /// Returns the crate this module is part of. 196 /// Returns the crate this module is part of.
@@ -335,10 +313,6 @@ impl StructField {
335 self.parent.variant_data(db).fields().unwrap()[self.id].name.clone() 313 self.parent.variant_data(db).fields().unwrap()[self.id].name.clone()
336 } 314 }
337 315
338 pub fn source(&self, db: &(impl DefDatabase + AstDatabase)) -> (HirFileId, FieldSource) {
339 self.source_impl(db)
340 }
341
342 pub fn ty(&self, db: &impl HirDatabase) -> Ty { 316 pub fn ty(&self, db: &impl HirDatabase) -> Ty {
343 db.type_for_field(*self) 317 db.type_for_field(*self)
344 } 318 }
@@ -354,13 +328,6 @@ pub struct Struct {
354} 328}
355 329
356impl Struct { 330impl Struct {
357 pub fn source(
358 self,
359 db: &(impl DefDatabase + AstDatabase),
360 ) -> (HirFileId, TreeArc<ast::StructDef>) {
361 self.id.source(db)
362 }
363
364 pub fn module(self, db: &impl HirDatabase) -> Module { 331 pub fn module(self, db: &impl HirDatabase) -> Module {
365 self.id.module(db) 332 self.id.module(db)
366 } 333 }
@@ -415,13 +382,6 @@ pub struct Union {
415} 382}
416 383
417impl Union { 384impl Union {
418 pub fn source(
419 self,
420 db: &(impl DefDatabase + AstDatabase),
421 ) -> (HirFileId, TreeArc<ast::StructDef>) {
422 self.id.source(db)
423 }
424
425 pub fn name(self, db: &impl DefDatabase) -> Option<Name> { 385 pub fn name(self, db: &impl DefDatabase) -> Option<Name> {
426 db.struct_data(Struct { id: self.id }).name.clone() 386 db.struct_data(Struct { id: self.id }).name.clone()
427 } 387 }
@@ -448,13 +408,6 @@ pub struct Enum {
448} 408}
449 409
450impl Enum { 410impl Enum {
451 pub fn source(
452 self,
453 db: &(impl DefDatabase + AstDatabase),
454 ) -> (HirFileId, TreeArc<ast::EnumDef>) {
455 self.id.source(db)
456 }
457
458 pub fn module(self, db: &impl HirDatabase) -> Module { 411 pub fn module(self, db: &impl HirDatabase) -> Module {
459 self.id.module(db) 412 self.id.module(db)
460 } 413 }
@@ -498,12 +451,6 @@ pub struct EnumVariant {
498} 451}
499 452
500impl EnumVariant { 453impl EnumVariant {
501 pub fn source(
502 &self,
503 db: &(impl DefDatabase + AstDatabase),
504 ) -> (HirFileId, TreeArc<ast::EnumVariant>) {
505 self.source_impl(db)
506 }
507 pub fn module(&self, db: &impl HirDatabase) -> Module { 454 pub fn module(&self, db: &impl HirDatabase) -> Module {
508 self.parent.module(db) 455 self.parent.module(db)
509 } 456 }
@@ -588,11 +535,11 @@ impl FnSignature {
588 db: &(impl DefDatabase + AstDatabase), 535 db: &(impl DefDatabase + AstDatabase),
589 func: Function, 536 func: Function,
590 ) -> Arc<FnSignature> { 537 ) -> Arc<FnSignature> {
591 let (_, node) = func.source(db); 538 let src = func.source(db);
592 let name = node.name().map(|n| n.as_name()).unwrap_or_else(Name::missing); 539 let name = src.ast.name().map(|n| n.as_name()).unwrap_or_else(Name::missing);
593 let mut params = Vec::new(); 540 let mut params = Vec::new();
594 let mut has_self_param = false; 541 let mut has_self_param = false;
595 if let Some(param_list) = node.param_list() { 542 if let Some(param_list) = src.ast.param_list() {
596 if let Some(self_param) = param_list.self_param() { 543 if let Some(self_param) = param_list.self_param() {
597 let self_type = if let Some(type_ref) = self_param.ascribed_type() { 544 let self_type = if let Some(type_ref) = self_param.ascribed_type() {
598 TypeRef::from_ast(type_ref) 545 TypeRef::from_ast(type_ref)
@@ -616,7 +563,7 @@ impl FnSignature {
616 params.push(type_ref); 563 params.push(type_ref);
617 } 564 }
618 } 565 }
619 let ret_type = if let Some(type_ref) = node.ret_type().and_then(|rt| rt.type_ref()) { 566 let ret_type = if let Some(type_ref) = src.ast.ret_type().and_then(|rt| rt.type_ref()) {
620 TypeRef::from_ast(type_ref) 567 TypeRef::from_ast(type_ref)
621 } else { 568 } else {
622 TypeRef::unit() 569 TypeRef::unit()
@@ -645,10 +592,6 @@ impl FnSignature {
645} 592}
646 593
647impl Function { 594impl Function {
648 pub fn source(self, db: &(impl DefDatabase + AstDatabase)) -> (HirFileId, TreeArc<ast::FnDef>) {
649 self.id.source(db)
650 }
651
652 pub fn module(self, db: &impl DefDatabase) -> Module { 595 pub fn module(self, db: &impl DefDatabase) -> Module {
653 self.id.module(db) 596 self.id.module(db)
654 } 597 }
@@ -723,13 +666,6 @@ pub struct Const {
723} 666}
724 667
725impl Const { 668impl Const {
726 pub fn source(
727 self,
728 db: &(impl DefDatabase + AstDatabase),
729 ) -> (HirFileId, TreeArc<ast::ConstDef>) {
730 self.id.source(db)
731 }
732
733 pub fn module(self, db: &impl DefDatabase) -> Module { 669 pub fn module(self, db: &impl DefDatabase) -> Module {
734 self.id.module(db) 670 self.id.module(db)
735 } 671 }
@@ -780,7 +716,7 @@ impl ConstSignature {
780 db: &(impl DefDatabase + AstDatabase), 716 db: &(impl DefDatabase + AstDatabase),
781 konst: Const, 717 konst: Const,
782 ) -> Arc<ConstSignature> { 718 ) -> Arc<ConstSignature> {
783 let (_, node) = konst.source(db); 719 let node = konst.source(db).ast;
784 const_signature_for(&*node) 720 const_signature_for(&*node)
785 } 721 }
786 722
@@ -788,7 +724,7 @@ impl ConstSignature {
788 db: &(impl DefDatabase + AstDatabase), 724 db: &(impl DefDatabase + AstDatabase),
789 konst: Static, 725 konst: Static,
790 ) -> Arc<ConstSignature> { 726 ) -> Arc<ConstSignature> {
791 let (_, node) = konst.source(db); 727 let node = konst.source(db).ast;
792 const_signature_for(&*node) 728 const_signature_for(&*node)
793 } 729 }
794} 730}
@@ -806,13 +742,6 @@ pub struct Static {
806} 742}
807 743
808impl Static { 744impl Static {
809 pub fn source(
810 self,
811 db: &(impl DefDatabase + AstDatabase),
812 ) -> (HirFileId, TreeArc<ast::StaticDef>) {
813 self.id.source(db)
814 }
815
816 pub fn module(self, db: &impl DefDatabase) -> Module { 745 pub fn module(self, db: &impl DefDatabase) -> Module {
817 self.id.module(db) 746 self.id.module(db)
818 } 747 }
@@ -838,13 +767,6 @@ pub struct Trait {
838} 767}
839 768
840impl Trait { 769impl Trait {
841 pub fn source(
842 self,
843 db: &(impl DefDatabase + AstDatabase),
844 ) -> (HirFileId, TreeArc<ast::TraitDef>) {
845 self.id.source(db)
846 }
847
848 pub fn module(self, db: &impl DefDatabase) -> Module { 770 pub fn module(self, db: &impl DefDatabase) -> Module {
849 self.id.module(db) 771 self.id.module(db)
850 } 772 }
@@ -884,13 +806,6 @@ pub struct TypeAlias {
884} 806}
885 807
886impl TypeAlias { 808impl TypeAlias {
887 pub fn source(
888 self,
889 db: &(impl DefDatabase + AstDatabase),
890 ) -> (HirFileId, TreeArc<ast::TypeAliasDef>) {
891 self.id.source(db)
892 }
893
894 pub fn module(self, db: &impl DefDatabase) -> Module { 809 pub fn module(self, db: &impl DefDatabase) -> Module {
895 self.id.module(db) 810 self.id.module(db)
896 } 811 }
@@ -939,14 +854,7 @@ pub struct MacroDef {
939 pub(crate) id: MacroDefId, 854 pub(crate) id: MacroDefId,
940} 855}
941 856
942impl MacroDef { 857impl MacroDef {}
943 pub fn source(
944 &self,
945 db: &(impl DefDatabase + AstDatabase),
946 ) -> (HirFileId, TreeArc<ast::MacroCall>) {
947 (self.id.0.file_id(), self.id.0.to_node(db))
948 }
949}
950 858
951pub enum Container { 859pub enum Container {
952 Trait(Trait), 860 Trait(Trait),
diff --git a/crates/ra_hir/src/docs.rs b/crates/ra_hir/src/code_model/docs.rs
index 1b0f84de5..da2b9b854 100644
--- a/crates/ra_hir/src/docs.rs
+++ b/crates/ra_hir/src/code_model/docs.rs
@@ -3,7 +3,7 @@ use std::sync::Arc;
3use ra_syntax::ast; 3use ra_syntax::ast;
4 4
5use crate::{ 5use crate::{
6 HirDatabase, DefDatabase, AstDatabase, 6 HirDatabase, DefDatabase, AstDatabase, HasSource,
7 Module, StructField, Struct, Enum, EnumVariant, Static, Const, Function, Union, Trait, TypeAlias, FieldSource, MacroDef, 7 Module, StructField, Struct, Enum, EnumVariant, Static, Const, Function, Union, Trait, TypeAlias, FieldSource, MacroDef,
8}; 8};
9 9
@@ -71,21 +71,21 @@ pub(crate) fn documentation_query(
71 def: DocDef, 71 def: DocDef,
72) -> Option<Documentation> { 72) -> Option<Documentation> {
73 match def { 73 match def {
74 DocDef::Module(it) => docs_from_ast(&*it.declaration_source(db)?.1), 74 DocDef::Module(it) => docs_from_ast(&*it.declaration_source(db)?.ast),
75 DocDef::StructField(it) => match it.source(db).1 { 75 DocDef::StructField(it) => match it.source(db).ast {
76 FieldSource::Named(named) => docs_from_ast(&*named), 76 FieldSource::Named(named) => docs_from_ast(&*named),
77 FieldSource::Pos(..) => return None, 77 FieldSource::Pos(..) => return None,
78 }, 78 },
79 DocDef::Struct(it) => docs_from_ast(&*it.source(db).1), 79 DocDef::Struct(it) => docs_from_ast(&*it.source(db).ast),
80 DocDef::Enum(it) => docs_from_ast(&*it.source(db).1), 80 DocDef::Enum(it) => docs_from_ast(&*it.source(db).ast),
81 DocDef::EnumVariant(it) => docs_from_ast(&*it.source(db).1), 81 DocDef::EnumVariant(it) => docs_from_ast(&*it.source(db).ast),
82 DocDef::Static(it) => docs_from_ast(&*it.source(db).1), 82 DocDef::Static(it) => docs_from_ast(&*it.source(db).ast),
83 DocDef::Const(it) => docs_from_ast(&*it.source(db).1), 83 DocDef::Const(it) => docs_from_ast(&*it.source(db).ast),
84 DocDef::Function(it) => docs_from_ast(&*it.source(db).1), 84 DocDef::Function(it) => docs_from_ast(&*it.source(db).ast),
85 DocDef::Union(it) => docs_from_ast(&*it.source(db).1), 85 DocDef::Union(it) => docs_from_ast(&*it.source(db).ast),
86 DocDef::Trait(it) => docs_from_ast(&*it.source(db).1), 86 DocDef::Trait(it) => docs_from_ast(&*it.source(db).ast),
87 DocDef::TypeAlias(it) => docs_from_ast(&*it.source(db).1), 87 DocDef::TypeAlias(it) => docs_from_ast(&*it.source(db).ast),
88 DocDef::MacroDef(it) => docs_from_ast(&*it.source(db).1), 88 DocDef::MacroDef(it) => docs_from_ast(&*it.source(db).ast),
89 } 89 }
90} 90}
91 91
diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs
new file mode 100644
index 000000000..5785d3b26
--- /dev/null
+++ b/crates/ra_hir/src/code_model/src.rs
@@ -0,0 +1,110 @@
1use ra_syntax::{TreeArc, ast};
2
3use crate::{
4 HirFileId, DefDatabase, AstDatabase, Module, ModuleSource,
5 StructField, Struct, Enum, Union, EnumVariant, Function, Static, Trait, Const, TypeAlias,
6 FieldSource, MacroDef, ids::AstItemDef,
7};
8
9pub struct Source<T> {
10 pub file_id: HirFileId,
11 pub ast: T,
12}
13
14pub trait HasSource {
15 type Ast;
16 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<Self::Ast>;
17}
18
19/// NB: Module is !HasSource, because it has two source nodes at the same time:
20/// definition and declaration.
21impl Module {
22 /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items.
23 pub fn definition_source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<ModuleSource> {
24 let def_map = db.crate_def_map(self.krate);
25 let decl_id = def_map[self.module_id].declaration;
26 let file_id = def_map[self.module_id].definition;
27 let ast = ModuleSource::new(db, file_id, decl_id);
28 let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id());
29 Source { file_id, ast }
30 }
31
32 /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`.
33 /// `None` for the crate root.
34 pub fn declaration_source(
35 self,
36 db: &(impl DefDatabase + AstDatabase),
37 ) -> Option<Source<TreeArc<ast::Module>>> {
38 let def_map = db.crate_def_map(self.krate);
39 let decl = def_map[self.module_id].declaration?;
40 let ast = decl.to_node(db);
41 Some(Source { file_id: decl.file_id(), ast })
42 }
43}
44
45impl HasSource for StructField {
46 type Ast = FieldSource;
47 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<FieldSource> {
48 self.source_impl(db)
49 }
50}
51impl HasSource for Struct {
52 type Ast = TreeArc<ast::StructDef>;
53 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::StructDef>> {
54 self.id.source(db)
55 }
56}
57impl HasSource for Union {
58 type Ast = TreeArc<ast::StructDef>;
59 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::StructDef>> {
60 self.id.source(db)
61 }
62}
63impl HasSource for Enum {
64 type Ast = TreeArc<ast::EnumDef>;
65 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::EnumDef>> {
66 self.id.source(db)
67 }
68}
69impl HasSource for EnumVariant {
70 type Ast = TreeArc<ast::EnumVariant>;
71 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::EnumVariant>> {
72 self.source_impl(db)
73 }
74}
75impl HasSource for Function {
76 type Ast = TreeArc<ast::FnDef>;
77 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::FnDef>> {
78 self.id.source(db)
79 }
80}
81impl HasSource for Const {
82 type Ast = TreeArc<ast::ConstDef>;
83 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::ConstDef>> {
84 self.id.source(db)
85 }
86}
87impl HasSource for Static {
88 type Ast = TreeArc<ast::StaticDef>;
89 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::StaticDef>> {
90 self.id.source(db)
91 }
92}
93impl HasSource for Trait {
94 type Ast = TreeArc<ast::TraitDef>;
95 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::TraitDef>> {
96 self.id.source(db)
97 }
98}
99impl HasSource for TypeAlias {
100 type Ast = TreeArc<ast::TypeAliasDef>;
101 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::TypeAliasDef>> {
102 self.id.source(db)
103 }
104}
105impl HasSource for MacroDef {
106 type Ast = TreeArc<ast::MacroCall>;
107 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::MacroCall>> {
108 Source { file_id: self.id.0.file_id(), ast: self.id.0.to_node(db) }
109 }
110}
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index d2a372f3b..d2d6f95b7 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -128,8 +128,8 @@ pub trait DefDatabase: SourceDatabase {
128 #[salsa::invoke(crate::lang_item::LangItems::lang_item_query)] 128 #[salsa::invoke(crate::lang_item::LangItems::lang_item_query)]
129 fn lang_item(&self, start_crate: Crate, item: SmolStr) -> Option<LangItemTarget>; 129 fn lang_item(&self, start_crate: Crate, item: SmolStr) -> Option<LangItemTarget>;
130 130
131 #[salsa::invoke(crate::docs::documentation_query)] 131 #[salsa::invoke(crate::code_model::docs::documentation_query)]
132 fn documentation(&self, def: crate::docs::DocDef) -> Option<crate::docs::Documentation>; 132 fn documentation(&self, def: crate::DocDef) -> Option<crate::Documentation>;
133} 133}
134 134
135#[salsa::query_group(HirDatabaseStorage)] 135#[salsa::query_group(HirDatabaseStorage)]
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index 012f374ec..b1973d19d 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -11,6 +11,7 @@ use ra_syntax::{
11 11
12use crate::{ 12use crate::{
13 Path, Name, HirDatabase, Resolver,DefWithBody, Either, HirFileId, MacroCallLoc, MacroFileKind, 13 Path, Name, HirDatabase, Resolver,DefWithBody, Either, HirFileId, MacroCallLoc, MacroFileKind,
14 HasSource,
14 name::AsName, 15 name::AsName,
15 type_ref::{Mutability, TypeRef}, 16 type_ref::{Mutability, TypeRef},
16}; 17};
@@ -1018,19 +1019,19 @@ pub(crate) fn body_with_source_map_query(
1018 1019
1019 match def { 1020 match def {
1020 DefWithBody::Const(ref c) => { 1021 DefWithBody::Const(ref c) => {
1021 let (file_id, src) = c.source(db); 1022 let src = c.source(db);
1022 collector = ExprCollector::new(def, file_id, def.resolver(db), db); 1023 collector = ExprCollector::new(def, src.file_id, def.resolver(db), db);
1023 collector.collect_const_body(&src) 1024 collector.collect_const_body(&src.ast)
1024 } 1025 }
1025 DefWithBody::Function(ref f) => { 1026 DefWithBody::Function(ref f) => {
1026 let (file_id, src) = f.source(db); 1027 let src = f.source(db);
1027 collector = ExprCollector::new(def, file_id, def.resolver(db), db); 1028 collector = ExprCollector::new(def, src.file_id, def.resolver(db), db);
1028 collector.collect_fn_body(&src) 1029 collector.collect_fn_body(&src.ast)
1029 } 1030 }
1030 DefWithBody::Static(ref s) => { 1031 DefWithBody::Static(ref s) => {
1031 let (file_id, src) = s.source(db); 1032 let src = s.source(db);
1032 collector = ExprCollector::new(def, file_id, def.resolver(db), db); 1033 collector = ExprCollector::new(def, src.file_id, def.resolver(db), db);
1033 collector.collect_static_body(&src) 1034 collector.collect_static_body(&src.ast)
1034 } 1035 }
1035 } 1036 }
1036 1037
diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs
index a1b2641da..534fd482b 100644
--- a/crates/ra_hir/src/expr/validation.rs
+++ b/crates/ra_hir/src/expr/validation.rs
@@ -5,7 +5,7 @@ use ra_syntax::ast::{AstNode, StructLit};
5 5
6use crate::{ 6use crate::{
7 expr::AstPtr, 7 expr::AstPtr,
8 HirDatabase, Function, Name, 8 HirDatabase, Function, Name, HasSource,
9 diagnostics::{DiagnosticSink, MissingFields}, 9 diagnostics::{DiagnosticSink, MissingFields},
10 adt::AdtDef, 10 adt::AdtDef,
11 Path, 11 Path,
@@ -71,7 +71,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
71 return; 71 return;
72 } 72 }
73 let source_map = self.func.body_source_map(db); 73 let source_map = self.func.body_source_map(db);
74 let file_id = self.func.source(db).0; 74 let file_id = self.func.source(db).file_id;
75 let source_file = db.parse(file_id.original_file(db)).tree; 75 let source_file = db.parse(file_id.original_file(db)).tree;
76 if let Some(field_list_node) = source_map 76 if let Some(field_list_node) = source_map
77 .expr_syntax(id) 77 .expr_syntax(id)
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index b6c5e18d3..462b136b7 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -8,8 +8,10 @@ use std::sync::Arc;
8use ra_syntax::ast::{self, NameOwner, TypeParamsOwner, TypeBoundsOwner, DefaultTypeParamOwner}; 8use ra_syntax::ast::{self, NameOwner, TypeParamsOwner, TypeBoundsOwner, DefaultTypeParamOwner};
9 9
10use crate::{ 10use crate::{
11 HasSource,
12 Name, AsName, Function, Struct, Union, Enum, Trait, TypeAlias, ImplBlock, Container, AdtDef,
11 db::{HirDatabase, DefDatabase, AstDatabase}, 13 db::{HirDatabase, DefDatabase, AstDatabase},
12 Name, AsName, Function, Struct, Union, Enum, Trait, TypeAlias, ImplBlock, Container, path::Path, type_ref::TypeRef, AdtDef 14 path::Path, type_ref::TypeRef,
13}; 15};
14 16
15/// Data about a generic parameter (to a function, struct, impl, ...). 17/// Data about a generic parameter (to a function, struct, impl, ...).
@@ -68,10 +70,10 @@ impl GenericParams {
68 generics.parent_params = parent.map(|p| db.generic_params(p)); 70 generics.parent_params = parent.map(|p| db.generic_params(p));
69 let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32; 71 let start = generics.parent_params.as_ref().map(|p| p.params.len()).unwrap_or(0) as u32;
70 match def { 72 match def {
71 GenericDef::Function(it) => generics.fill(&*it.source(db).1, start), 73 GenericDef::Function(it) => generics.fill(&*it.source(db).ast, start),
72 GenericDef::Struct(it) => generics.fill(&*it.source(db).1, start), 74 GenericDef::Struct(it) => generics.fill(&*it.source(db).ast, start),
73 GenericDef::Union(it) => generics.fill(&*it.source(db).1, start), 75 GenericDef::Union(it) => generics.fill(&*it.source(db).ast, start),
74 GenericDef::Enum(it) => generics.fill(&*it.source(db).1, start), 76 GenericDef::Enum(it) => generics.fill(&*it.source(db).ast, start),
75 GenericDef::Trait(it) => { 77 GenericDef::Trait(it) => {
76 // traits get the Self type as an implicit first type parameter 78 // traits get the Self type as an implicit first type parameter
77 generics.params.push(GenericParam { 79 generics.params.push(GenericParam {
@@ -79,10 +81,10 @@ impl GenericParams {
79 name: Name::self_type(), 81 name: Name::self_type(),
80 default: None, 82 default: None,
81 }); 83 });
82 generics.fill(&*it.source(db).1, start + 1); 84 generics.fill(&*it.source(db).ast, start + 1);
83 } 85 }
84 GenericDef::TypeAlias(it) => generics.fill(&*it.source(db).1, start), 86 GenericDef::TypeAlias(it) => generics.fill(&*it.source(db).ast, start),
85 GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).1, start), 87 GenericDef::ImplBlock(it) => generics.fill(&*it.source(db).ast, start),
86 } 88 }
87 89
88 Arc::new(generics) 90 Arc::new(generics)
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index a95561812..352f9ffd9 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -9,7 +9,7 @@ use ra_prof::profile;
9use mbe::MacroRules; 9use mbe::MacroRules;
10 10
11use crate::{ 11use crate::{
12 Module, DefDatabase, AstId, FileAstId, AstDatabase, 12 Module, DefDatabase, AstId, FileAstId, AstDatabase, Source,
13}; 13};
14 14
15/// hir makes heavy use of ids: integer (u32) handlers to various things. You 15/// hir makes heavy use of ids: integer (u32) handlers to various things. You
@@ -265,10 +265,10 @@ pub(crate) trait AstItemDef<N: AstNode>: salsa::InternKey + Clone {
265 let loc = ItemLoc { module: ctx.module, ast_id: ast_id.with_file_id(ctx.file_id) }; 265 let loc = ItemLoc { module: ctx.module, ast_id: ast_id.with_file_id(ctx.file_id) };
266 Self::intern(ctx.db, loc) 266 Self::intern(ctx.db, loc)
267 } 267 }
268 fn source(self, db: &(impl AstDatabase + DefDatabase)) -> (HirFileId, TreeArc<N>) { 268 fn source(self, db: &(impl AstDatabase + DefDatabase)) -> Source<TreeArc<N>> {
269 let loc = self.lookup_intern(db); 269 let loc = self.lookup_intern(db);
270 let ast = loc.ast_id.to_node(db); 270 let ast = loc.ast_id.to_node(db);
271 (loc.ast_id.file_id(), ast) 271 Source { file_id: loc.ast_id.file_id(), ast }
272 } 272 }
273 fn module(self, db: &impl DefDatabase) -> Module { 273 fn module(self, db: &impl DefDatabase) -> Module {
274 let loc = self.lookup_intern(db); 274 let loc = self.lookup_intern(db);
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index a0d3b33fe..fb9daf1bf 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -8,7 +8,7 @@ use ra_syntax::{
8}; 8};
9 9
10use crate::{ 10use crate::{
11 Const, TypeAlias, Function, HirFileId, AstDatabase, 11 Const, TypeAlias, Function, HirFileId, AstDatabase, HasSource, Source,
12 HirDatabase, DefDatabase, TraitRef, 12 HirDatabase, DefDatabase, TraitRef,
13 type_ref::TypeRef, 13 type_ref::TypeRef,
14 ids::LocationCtx, 14 ids::LocationCtx,
@@ -44,6 +44,15 @@ pub struct ImplBlock {
44 impl_id: ImplId, 44 impl_id: ImplId,
45} 45}
46 46
47impl HasSource for ImplBlock {
48 type Ast = TreeArc<ast::ImplBlock>;
49 fn source(self, db: &(impl DefDatabase + AstDatabase)) -> Source<TreeArc<ast::ImplBlock>> {
50 let source_map = db.impls_in_module_with_source_map(self.module).1;
51 let src = self.module.definition_source(db);
52 Source { file_id: src.file_id, ast: source_map.get(&src.ast, self.impl_id) }
53 }
54}
55
47impl ImplBlock { 56impl ImplBlock {
48 pub(crate) fn containing( 57 pub(crate) fn containing(
49 module_impl_blocks: Arc<ModuleImplBlocks>, 58 module_impl_blocks: Arc<ModuleImplBlocks>,
@@ -57,16 +66,6 @@ impl ImplBlock {
57 ImplBlock { module, impl_id } 66 ImplBlock { module, impl_id }
58 } 67 }
59 68
60 /// Returns the syntax of the impl block
61 pub fn source(
62 &self,
63 db: &(impl DefDatabase + AstDatabase),
64 ) -> (HirFileId, TreeArc<ast::ImplBlock>) {
65 let source_map = db.impls_in_module_with_source_map(self.module).1;
66 let (file_id, source) = self.module.definition_source(db);
67 (file_id, source_map.get(&source, self.impl_id))
68 }
69
70 pub fn id(&self) -> ImplId { 69 pub fn id(&self) -> ImplId {
71 self.impl_id 70 self.impl_id
72 } 71 }
@@ -201,8 +200,8 @@ impl ModuleImplBlocks {
201 impls_by_def: FxHashMap::default(), 200 impls_by_def: FxHashMap::default(),
202 }; 201 };
203 202
204 let (file_id, module_source) = m.module.definition_source(db); 203 let src = m.module.definition_source(db);
205 let node = match &module_source { 204 let node = match &src.ast {
206 ModuleSource::SourceFile(node) => node.syntax(), 205 ModuleSource::SourceFile(node) => node.syntax(),
207 ModuleSource::Module(node) => { 206 ModuleSource::Module(node) => {
208 node.item_list().expect("inline module should have item list").syntax() 207 node.item_list().expect("inline module should have item list").syntax()
@@ -210,7 +209,7 @@ impl ModuleImplBlocks {
210 }; 209 };
211 210
212 for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) { 211 for impl_block_ast in node.children().filter_map(ast::ImplBlock::cast) {
213 let impl_block = ImplData::from_ast(db, file_id, m.module, impl_block_ast); 212 let impl_block = ImplData::from_ast(db, src.file_id, m.module, impl_block_ast);
214 let id = m.impls.alloc(impl_block); 213 let id = m.impls.alloc(impl_block);
215 for &impl_item in &m.impls[id].items { 214 for &impl_item in &m.impls[id].items {
216 m.impls_by_def.insert(impl_item, id); 215 m.impls_by_def.insert(impl_item, id);
diff --git a/crates/ra_hir/src/lang_item.rs b/crates/ra_hir/src/lang_item.rs
index 684fbc068..cdc9182d6 100644
--- a/crates/ra_hir/src/lang_item.rs
+++ b/crates/ra_hir/src/lang_item.rs
@@ -84,7 +84,7 @@ impl LangItems {
84 ) { 84 ) {
85 // Look for impl targets 85 // Look for impl targets
86 let (impl_blocks, source_map) = db.impls_in_module_with_source_map(module.clone()); 86 let (impl_blocks, source_map) = db.impls_in_module_with_source_map(module.clone());
87 let source = module.definition_source(db).1; 87 let source = module.definition_source(db).ast;
88 for (impl_id, _) in impl_blocks.impls.iter() { 88 for (impl_id, _) in impl_blocks.impls.iter() {
89 let impl_block = source_map.get(&source, impl_id); 89 let impl_block = source_map.get(&source, impl_id);
90 let lang_item_name = impl_block 90 let lang_item_name = impl_block
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 0e4aaf678..2e99bdac8 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -38,7 +38,6 @@ mod impl_block;
38mod expr; 38mod expr;
39mod lang_item; 39mod lang_item;
40mod generics; 40mod generics;
41mod docs;
42mod resolve; 41mod resolve;
43pub mod diagnostics; 42pub mod diagnostics;
44 43
@@ -64,7 +63,6 @@ pub use self::{
64 nameres::{PerNs, Namespace, ImportId}, 63 nameres::{PerNs, Namespace, ImportId},
65 ty::{Ty, ApplicationTy, TypeCtor, TraitRef, Substs, display::HirDisplay, CallableDef}, 64 ty::{Ty, ApplicationTy, TypeCtor, TraitRef, Substs, display::HirDisplay, CallableDef},
66 impl_block::{ImplBlock, ImplItem}, 65 impl_block::{ImplBlock, ImplItem},
67 docs::{Docs, Documentation},
68 adt::AdtDef, 66 adt::AdtDef,
69 expr::ExprScopes, 67 expr::ExprScopes,
70 resolve::Resolution, 68 resolve::Resolution,
@@ -82,4 +80,6 @@ pub use self::code_model::{
82 Static, Const, ConstSignature, 80 Static, Const, ConstSignature,
83 Trait, TypeAlias, MacroDef, Container, 81 Trait, TypeAlias, MacroDef, Container,
84 BuiltinType, 82 BuiltinType,
83 src::{Source, HasSource},
84 docs::{Docs, Documentation, DocDef},
85}; 85};
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 876ebe0e3..4f9e8c5a9 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -97,13 +97,13 @@ pub fn struct_from_module(
97 module: Module, 97 module: Module,
98 struct_def: &ast::StructDef, 98 struct_def: &ast::StructDef,
99) -> Struct { 99) -> Struct {
100 let (file_id, _) = module.definition_source(db); 100 let file_id = module.definition_source(db).file_id;
101 let ctx = LocationCtx::new(db, module, file_id); 101 let ctx = LocationCtx::new(db, module, file_id);
102 Struct { id: ctx.to_def(struct_def) } 102 Struct { id: ctx.to_def(struct_def) }
103} 103}
104 104
105pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum { 105pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum {
106 let (file_id, _) = module.definition_source(db); 106 let file_id = module.definition_source(db).file_id;
107 let ctx = LocationCtx::new(db, module, file_id); 107 let ctx = LocationCtx::new(db, module, file_id);
108 Enum { id: ctx.to_def(enum_def) } 108 Enum { id: ctx.to_def(enum_def) }
109} 109}
@@ -113,7 +113,7 @@ pub fn trait_from_module(
113 module: Module, 113 module: Module,
114 trait_def: &ast::TraitDef, 114 trait_def: &ast::TraitDef,
115) -> Trait { 115) -> Trait {
116 let (file_id, _) = module.definition_source(db); 116 let file_id = module.definition_source(db).file_id;
117 let ctx = LocationCtx::new(db, module, file_id); 117 let ctx = LocationCtx::new(db, module, file_id);
118 Trait { id: ctx.to_def(trait_def) } 118 Trait { id: ctx.to_def(trait_def) }
119} 119}
diff --git a/crates/ra_hir/src/traits.rs b/crates/ra_hir/src/traits.rs
index 967654e97..f2950e1b2 100644
--- a/crates/ra_hir/src/traits.rs
+++ b/crates/ra_hir/src/traits.rs
@@ -6,7 +6,7 @@ use rustc_hash::FxHashMap;
6use ra_syntax::ast::{self, NameOwner}; 6use ra_syntax::ast::{self, NameOwner};
7 7
8use crate::{ 8use crate::{
9 Function, Const, TypeAlias, Name, DefDatabase, Trait, AstDatabase, Module, 9 Function, Const, TypeAlias, Name, DefDatabase, Trait, AstDatabase, Module, HasSource,
10 ids::LocationCtx, name::AsName, 10 ids::LocationCtx, name::AsName,
11}; 11};
12 12
@@ -22,12 +22,12 @@ impl TraitData {
22 db: &(impl DefDatabase + AstDatabase), 22 db: &(impl DefDatabase + AstDatabase),
23 tr: Trait, 23 tr: Trait,
24 ) -> Arc<TraitData> { 24 ) -> Arc<TraitData> {
25 let (file_id, node) = tr.source(db); 25 let src = tr.source(db);
26 let name = node.name().map(|n| n.as_name()); 26 let name = src.ast.name().map(|n| n.as_name());
27 let module = tr.module(db); 27 let module = tr.module(db);
28 let ctx = LocationCtx::new(db, module, file_id); 28 let ctx = LocationCtx::new(db, module, src.file_id);
29 let auto = node.is_auto(); 29 let auto = src.ast.is_auto();
30 let items = if let Some(item_list) = node.item_list() { 30 let items = if let Some(item_list) = src.ast.item_list() {
31 item_list 31 item_list
32 .impl_items() 32 .impl_items()
33 .map(|item_node| match item_node.kind() { 33 .map(|item_node| match item_node.kind() {
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 6aa727ea1..fef0f1d24 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -1415,7 +1415,7 @@ mod diagnostics {
1415 use crate::{ 1415 use crate::{
1416 expr::ExprId, 1416 expr::ExprId,
1417 diagnostics::{DiagnosticSink, NoSuchField}, 1417 diagnostics::{DiagnosticSink, NoSuchField},
1418 HirDatabase, Function, 1418 HirDatabase, Function, HasSource,
1419}; 1419};
1420 1420
1421 #[derive(Debug, PartialEq, Eq, Clone)] 1421 #[derive(Debug, PartialEq, Eq, Clone)]
@@ -1432,7 +1432,7 @@ mod diagnostics {
1432 ) { 1432 ) {
1433 match self { 1433 match self {
1434 InferenceDiagnostic::NoSuchField { expr, field } => { 1434 InferenceDiagnostic::NoSuchField { expr, field } => {
1435 let (file, _) = owner.source(db); 1435 let file = owner.source(db).file_id;
1436 let field = owner.body_source_map(db).field_syntax(*expr, *field); 1436 let field = owner.body_source_map(db).field_syntax(*expr, *field);
1437 sink.push(NoSuchField { file, field }) 1437 sink.push(NoSuchField { file, field })
1438 } 1438 }
diff --git a/crates/ra_hir/src/type_alias.rs b/crates/ra_hir/src/type_alias.rs
index 970468e3c..87b9caa8a 100644
--- a/crates/ra_hir/src/type_alias.rs
+++ b/crates/ra_hir/src/type_alias.rs
@@ -2,12 +2,12 @@
2 2
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use crate::{TypeAlias, DefDatabase, AstDatabase, type_ref::TypeRef}; 5use crate::{TypeAlias, DefDatabase, AstDatabase, HasSource, type_ref::TypeRef};
6 6
7pub(crate) fn type_alias_ref_query( 7pub(crate) fn type_alias_ref_query(
8 db: &(impl DefDatabase + AstDatabase), 8 db: &(impl DefDatabase + AstDatabase),
9 typ: TypeAlias, 9 typ: TypeAlias,
10) -> Arc<TypeRef> { 10) -> Arc<TypeRef> {
11 let (_, node) = typ.source(db); 11 let node = typ.source(db).ast;
12 Arc::new(TypeRef::from_ast_opt(node.type_ref())) 12 Arc::new(TypeRef::from_ast_opt(node.type_ref()))
13} 13}
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs
index 247dc0fee..ce03a0f95 100644
--- a/crates/ra_ide_api/src/change.rs
+++ b/crates/ra_ide_api/src/change.rs
@@ -225,7 +225,6 @@ impl RootDatabase {
225 let sweep = SweepStrategy::default().discard_values().sweep_all_revisions(); 225 let sweep = SweepStrategy::default().discard_values().sweep_all_revisions();
226 226
227 self.query(ra_db::ParseQuery).sweep(sweep); 227 self.query(ra_db::ParseQuery).sweep(sweep);
228
229 self.query(hir::db::ParseMacroQuery).sweep(sweep); 228 self.query(hir::db::ParseMacroQuery).sweep(sweep);
230 self.query(hir::db::MacroDefQuery).sweep(sweep); 229 self.query(hir::db::MacroDefQuery).sweep(sweep);
231 self.query(hir::db::MacroArgQuery).sweep(sweep); 230 self.query(hir::db::MacroArgQuery).sweep(sweep);
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs
index d405161d6..f4ff4404b 100644
--- a/crates/ra_ide_api/src/completion/presentation.rs
+++ b/crates/ra_ide_api/src/completion/presentation.rs
@@ -1,7 +1,7 @@
1//! This modules takes care of rendering various defenitions as completion items. 1//! This modules takes care of rendering various defenitions as completion items.
2use join_to_string::join; 2use join_to_string::join;
3use test_utils::tested_by; 3use test_utils::tested_by;
4use hir::{Docs, PerNs, Resolution, HirDisplay}; 4use hir::{Docs, PerNs, Resolution, HirDisplay, HasSource};
5use ra_syntax::ast::NameOwner; 5use ra_syntax::ast::NameOwner;
6 6
7use crate::completion::{ 7use crate::completion::{
@@ -100,7 +100,7 @@ impl Completions {
100 ) { 100 ) {
101 let sig = func.signature(ctx.db); 101 let sig = func.signature(ctx.db);
102 let name = name.unwrap_or_else(|| sig.name().to_string()); 102 let name = name.unwrap_or_else(|| sig.name().to_string());
103 let (_, ast_node) = func.source(ctx.db); 103 let ast_node = func.source(ctx.db).ast;
104 let detail = function_label(&ast_node); 104 let detail = function_label(&ast_node);
105 105
106 let mut builder = CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name) 106 let mut builder = CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name)
@@ -126,12 +126,11 @@ impl Completions {
126 } 126 }
127 127
128 pub(crate) fn add_const(&mut self, ctx: &CompletionContext, constant: hir::Const) { 128 pub(crate) fn add_const(&mut self, ctx: &CompletionContext, constant: hir::Const) {
129 let (_file_id, ast_node) = constant.source(ctx.db); 129 let ast_node = constant.source(ctx.db).ast;
130 let name = match ast_node.name() { 130 let name = match ast_node.name() {
131 Some(name) => name, 131 Some(name) => name,
132 _ => return, 132 _ => return,
133 }; 133 };
134 let (_, ast_node) = constant.source(ctx.db);
135 let detail = const_label(&ast_node); 134 let detail = const_label(&ast_node);
136 135
137 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string()) 136 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string())
@@ -142,13 +141,12 @@ impl Completions {
142 } 141 }
143 142
144 pub(crate) fn add_type_alias(&mut self, ctx: &CompletionContext, type_alias: hir::TypeAlias) { 143 pub(crate) fn add_type_alias(&mut self, ctx: &CompletionContext, type_alias: hir::TypeAlias) {
145 let (_file_id, type_def) = type_alias.source(ctx.db); 144 let type_def = type_alias.source(ctx.db).ast;
146 let name = match type_def.name() { 145 let name = match type_def.name() {
147 Some(name) => name, 146 Some(name) => name,
148 _ => return, 147 _ => return,
149 }; 148 };
150 let (_, ast_node) = type_alias.source(ctx.db); 149 let detail = type_label(&type_def);
151 let detail = type_label(&ast_node);
152 150
153 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string()) 151 CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string())
154 .kind(CompletionItemKind::TypeAlias) 152 .kind(CompletionItemKind::TypeAlias)
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs
index d1a452ecb..b3f395502 100644
--- a/crates/ra_ide_api/src/db.rs
+++ b/crates/ra_ide_api/src/db.rs
@@ -5,7 +5,7 @@ use std::{
5 5
6use ra_db::{ 6use ra_db::{
7 CheckCanceled, FileId, Canceled, SourceDatabase, 7 CheckCanceled, FileId, Canceled, SourceDatabase,
8 salsa, 8 salsa::{self, Database},
9}; 9};
10 10
11use crate::{LineIndex, symbol_index::{self, SymbolsDatabase}}; 11use crate::{LineIndex, symbol_index::{self, SymbolsDatabase}};
@@ -41,6 +41,12 @@ impl salsa::Database for RootDatabase {
41 41
42impl Default for RootDatabase { 42impl Default for RootDatabase {
43 fn default() -> RootDatabase { 43 fn default() -> RootDatabase {
44 RootDatabase::new(None)
45 }
46}
47
48impl RootDatabase {
49 pub fn new(lru_capacity: Option<usize>) -> RootDatabase {
44 let mut db = RootDatabase { 50 let mut db = RootDatabase {
45 runtime: salsa::Runtime::default(), 51 runtime: salsa::Runtime::default(),
46 last_gc: time::Instant::now(), 52 last_gc: time::Instant::now(),
@@ -49,6 +55,9 @@ impl Default for RootDatabase {
49 db.set_crate_graph(Default::default()); 55 db.set_crate_graph(Default::default());
50 db.set_local_roots(Default::default()); 56 db.set_local_roots(Default::default());
51 db.set_library_roots(Default::default()); 57 db.set_library_roots(Default::default());
58 let lru_capacity = lru_capacity.unwrap_or(ra_db::DEFAULT_LRU_CAP);
59 db.query_mut(ra_db::ParseQuery).set_lru_capacity(lru_capacity);
60 db.query_mut(hir::db::ParseMacroQuery).set_lru_capacity(lru_capacity);
52 db 61 db
53 } 62 }
54} 63}
diff --git a/crates/ra_ide_api/src/display/function_signature.rs b/crates/ra_ide_api/src/display/function_signature.rs
index d09950bce..b0b0c7122 100644
--- a/crates/ra_ide_api/src/display/function_signature.rs
+++ b/crates/ra_ide_api/src/display/function_signature.rs
@@ -1,10 +1,11 @@
1use super::{where_predicates, generic_parameters};
2use crate::db;
3use std::fmt::{self, Display}; 1use std::fmt::{self, Display};
2
4use join_to_string::join; 3use join_to_string::join;
5use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner}; 4use ra_syntax::ast::{self, AstNode, NameOwner, VisibilityOwner};
6use std::convert::From; 5use std::convert::From;
7use hir::{Docs, Documentation}; 6use hir::{Docs, Documentation, HasSource};
7
8use crate::{db, display::{where_predicates, generic_parameters}};
8 9
9/// Contains information about a function signature 10/// Contains information about a function signature
10#[derive(Debug)] 11#[derive(Debug)]
@@ -33,7 +34,7 @@ impl FunctionSignature {
33 34
34 pub(crate) fn from_hir(db: &db::RootDatabase, function: hir::Function) -> Self { 35 pub(crate) fn from_hir(db: &db::RootDatabase, function: hir::Function) -> Self {
35 let doc = function.docs(db); 36 let doc = function.docs(db);
36 let (_, ast_node) = function.source(db); 37 let ast_node = function.source(db).ast;
37 FunctionSignature::from(&*ast_node).with_doc_opt(doc) 38 FunctionSignature::from(&*ast_node).with_doc_opt(doc)
38 } 39 }
39} 40}
diff --git a/crates/ra_ide_api/src/display/navigation_target.rs b/crates/ra_ide_api/src/display/navigation_target.rs
index cfd3f5478..823cdaaf3 100644
--- a/crates/ra_ide_api/src/display/navigation_target.rs
+++ b/crates/ra_ide_api/src/display/navigation_target.rs
@@ -1,11 +1,11 @@
1use ra_db::{FileId, SourceDatabase}; 1use ra_db::{FileId, SourceDatabase};
2use ra_syntax::{ 2use ra_syntax::{
3 SyntaxNode, AstNode, SmolStr, TextRange, AstPtr, 3 SyntaxNode, AstNode, SmolStr, TextRange, AstPtr, TreeArc,
4 SyntaxKind::{self, NAME}, 4 SyntaxKind::{self, NAME},
5 ast::{self, DocCommentsOwner}, 5 ast::{self, DocCommentsOwner},
6 algo::visit::{visitor, Visitor}, 6 algo::visit::{visitor, Visitor},
7}; 7};
8use hir::{ModuleSource, FieldSource, ImplItem}; 8use hir::{ModuleSource, FieldSource, ImplItem, HasSource};
9 9
10use crate::{FileSymbol, db::RootDatabase}; 10use crate::{FileSymbol, db::RootDatabase};
11use super::short_label::ShortLabel; 11use super::short_label::ShortLabel;
@@ -129,10 +129,10 @@ impl NavigationTarget {
129 } 129 }
130 130
131 pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget { 131 pub(crate) fn from_module(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
132 let (file_id, source) = module.definition_source(db); 132 let src = module.definition_source(db);
133 let file_id = file_id.as_original_file(); 133 let file_id = src.file_id.as_original_file();
134 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); 134 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
135 match source { 135 match src.ast {
136 ModuleSource::SourceFile(node) => { 136 ModuleSource::SourceFile(node) => {
137 NavigationTarget::from_syntax(file_id, name, None, node.syntax(), None, None) 137 NavigationTarget::from_syntax(file_id, name, None, node.syntax(), None, None)
138 } 138 }
@@ -149,34 +149,24 @@ impl NavigationTarget {
149 149
150 pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget { 150 pub(crate) fn from_module_to_decl(db: &RootDatabase, module: hir::Module) -> NavigationTarget {
151 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default(); 151 let name = module.name(db).map(|it| it.to_string().into()).unwrap_or_default();
152 if let Some((file_id, source)) = module.declaration_source(db) { 152 if let Some(src) = module.declaration_source(db) {
153 let file_id = file_id.as_original_file(); 153 let file_id = src.file_id.as_original_file();
154 return NavigationTarget::from_syntax( 154 return NavigationTarget::from_syntax(
155 file_id, 155 file_id,
156 name, 156 name,
157 None, 157 None,
158 source.syntax(), 158 src.ast.syntax(),
159 source.doc_comment_text(), 159 src.ast.doc_comment_text(),
160 source.short_label(), 160 src.ast.short_label(),
161 ); 161 );
162 } 162 }
163 NavigationTarget::from_module(db, module) 163 NavigationTarget::from_module(db, module)
164 } 164 }
165 165
166 pub(crate) fn from_function(db: &RootDatabase, func: hir::Function) -> NavigationTarget {
167 let (file_id, fn_def) = func.source(db);
168 NavigationTarget::from_named(
169 file_id.original_file(db),
170 &*fn_def,
171 fn_def.doc_comment_text(),
172 fn_def.short_label(),
173 )
174 }
175
176 pub(crate) fn from_field(db: &RootDatabase, field: hir::StructField) -> NavigationTarget { 166 pub(crate) fn from_field(db: &RootDatabase, field: hir::StructField) -> NavigationTarget {
177 let (file_id, field) = field.source(db); 167 let src = field.source(db);
178 let file_id = file_id.original_file(db); 168 let file_id = src.file_id.original_file(db);
179 match field { 169 match src.ast {
180 FieldSource::Named(it) => { 170 FieldSource::Named(it) => {
181 NavigationTarget::from_named(file_id, &*it, it.doc_comment_text(), it.short_label()) 171 NavigationTarget::from_named(file_id, &*it, it.doc_comment_text(), it.short_label())
182 } 172 }
@@ -186,35 +176,25 @@ impl NavigationTarget {
186 } 176 }
187 } 177 }
188 178
179 pub(crate) fn from_def_source<A, D>(db: &RootDatabase, def: D) -> NavigationTarget
180 where
181 D: HasSource<Ast = TreeArc<A>>,
182 A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel,
183 {
184 let src = def.source(db);
185 NavigationTarget::from_named(
186 src.file_id.original_file(db),
187 &*src.ast,
188 src.ast.doc_comment_text(),
189 src.ast.short_label(),
190 )
191 }
192
189 pub(crate) fn from_adt_def(db: &RootDatabase, adt_def: hir::AdtDef) -> NavigationTarget { 193 pub(crate) fn from_adt_def(db: &RootDatabase, adt_def: hir::AdtDef) -> NavigationTarget {
190 match adt_def { 194 match adt_def {
191 hir::AdtDef::Struct(s) => { 195 hir::AdtDef::Struct(it) => NavigationTarget::from_def_source(db, it),
192 let (file_id, node) = s.source(db); 196 hir::AdtDef::Union(it) => NavigationTarget::from_def_source(db, it),
193 NavigationTarget::from_named( 197 hir::AdtDef::Enum(it) => NavigationTarget::from_def_source(db, it),
194 file_id.original_file(db),
195 &*node,
196 node.doc_comment_text(),
197 node.short_label(),
198 )
199 }
200 hir::AdtDef::Union(s) => {
201 let (file_id, node) = s.source(db);
202 NavigationTarget::from_named(
203 file_id.original_file(db),
204 &*node,
205 node.doc_comment_text(),
206 node.short_label(),
207 )
208 }
209 hir::AdtDef::Enum(s) => {
210 let (file_id, node) = s.source(db);
211 NavigationTarget::from_named(
212 file_id.original_file(db),
213 &*node,
214 node.doc_comment_text(),
215 node.short_label(),
216 )
217 }
218 } 198 }
219 } 199 }
220 200
@@ -224,79 +204,15 @@ impl NavigationTarget {
224 ) -> Option<NavigationTarget> { 204 ) -> Option<NavigationTarget> {
225 let nav = match module_def { 205 let nav = match module_def {
226 hir::ModuleDef::Module(module) => NavigationTarget::from_module(db, module), 206 hir::ModuleDef::Module(module) => NavigationTarget::from_module(db, module),
227 hir::ModuleDef::Function(func) => NavigationTarget::from_function(db, func), 207 hir::ModuleDef::Function(func) => NavigationTarget::from_def_source(db, func),
228 hir::ModuleDef::Struct(s) => { 208 hir::ModuleDef::Struct(it) => NavigationTarget::from_adt_def(db, it.into()),
229 let (file_id, node) = s.source(db); 209 hir::ModuleDef::Enum(it) => NavigationTarget::from_adt_def(db, it.into()),
230 NavigationTarget::from_named( 210 hir::ModuleDef::Union(it) => NavigationTarget::from_adt_def(db, it.into()),
231 file_id.original_file(db), 211 hir::ModuleDef::Const(it) => NavigationTarget::from_def_source(db, it),
232 &*node, 212 hir::ModuleDef::Static(it) => NavigationTarget::from_def_source(db, it),
233 node.doc_comment_text(), 213 hir::ModuleDef::EnumVariant(it) => NavigationTarget::from_def_source(db, it),
234 node.short_label(), 214 hir::ModuleDef::Trait(it) => NavigationTarget::from_def_source(db, it),
235 ) 215 hir::ModuleDef::TypeAlias(it) => NavigationTarget::from_def_source(db, it),
236 }
237 hir::ModuleDef::Union(s) => {
238 let (file_id, node) = s.source(db);
239 NavigationTarget::from_named(
240 file_id.original_file(db),
241 &*node,
242 node.doc_comment_text(),
243 node.short_label(),
244 )
245 }
246 hir::ModuleDef::Const(s) => {
247 let (file_id, node) = s.source(db);
248 NavigationTarget::from_named(
249 file_id.original_file(db),
250 &*node,
251 node.doc_comment_text(),
252 node.short_label(),
253 )
254 }
255 hir::ModuleDef::Static(s) => {
256 let (file_id, node) = s.source(db);
257 NavigationTarget::from_named(
258 file_id.original_file(db),
259 &*node,
260 node.doc_comment_text(),
261 node.short_label(),
262 )
263 }
264 hir::ModuleDef::Enum(e) => {
265 let (file_id, node) = e.source(db);
266 NavigationTarget::from_named(
267 file_id.original_file(db),
268 &*node,
269 node.doc_comment_text(),
270 node.short_label(),
271 )
272 }
273 hir::ModuleDef::EnumVariant(var) => {
274 let (file_id, node) = var.source(db);
275 NavigationTarget::from_named(
276 file_id.original_file(db),
277 &*node,
278 node.doc_comment_text(),
279 node.short_label(),
280 )
281 }
282 hir::ModuleDef::Trait(e) => {
283 let (file_id, node) = e.source(db);
284 NavigationTarget::from_named(
285 file_id.original_file(db),
286 &*node,
287 node.doc_comment_text(),
288 node.short_label(),
289 )
290 }
291 hir::ModuleDef::TypeAlias(e) => {
292 let (file_id, node) = e.source(db);
293 NavigationTarget::from_named(
294 file_id.original_file(db),
295 &*node,
296 node.doc_comment_text(),
297 node.short_label(),
298 )
299 }
300 hir::ModuleDef::BuiltinType(..) => { 216 hir::ModuleDef::BuiltinType(..) => {
301 return None; 217 return None;
302 } 218 }
@@ -308,12 +224,12 @@ impl NavigationTarget {
308 db: &RootDatabase, 224 db: &RootDatabase,
309 impl_block: hir::ImplBlock, 225 impl_block: hir::ImplBlock,
310 ) -> NavigationTarget { 226 ) -> NavigationTarget {
311 let (file_id, node) = impl_block.source(db); 227 let src = impl_block.source(db);
312 NavigationTarget::from_syntax( 228 NavigationTarget::from_syntax(
313 file_id.as_original_file(), 229 src.file_id.as_original_file(),
314 "impl".into(), 230 "impl".into(),
315 None, 231 None,
316 node.syntax(), 232 src.ast.syntax(),
317 None, 233 None,
318 None, 234 None,
319 ) 235 )
@@ -321,35 +237,19 @@ impl NavigationTarget {
321 237
322 pub(crate) fn from_impl_item(db: &RootDatabase, impl_item: hir::ImplItem) -> NavigationTarget { 238 pub(crate) fn from_impl_item(db: &RootDatabase, impl_item: hir::ImplItem) -> NavigationTarget {
323 match impl_item { 239 match impl_item {
324 ImplItem::Method(f) => NavigationTarget::from_function(db, f), 240 ImplItem::Method(it) => NavigationTarget::from_def_source(db, it),
325 ImplItem::Const(c) => { 241 ImplItem::Const(it) => NavigationTarget::from_def_source(db, it),
326 let (file_id, node) = c.source(db); 242 ImplItem::TypeAlias(it) => NavigationTarget::from_def_source(db, it),
327 NavigationTarget::from_named(
328 file_id.original_file(db),
329 &*node,
330 node.doc_comment_text(),
331 node.short_label(),
332 )
333 }
334 ImplItem::TypeAlias(a) => {
335 let (file_id, node) = a.source(db);
336 NavigationTarget::from_named(
337 file_id.original_file(db),
338 &*node,
339 node.doc_comment_text(),
340 node.short_label(),
341 )
342 }
343 } 243 }
344 } 244 }
345 245
346 pub(crate) fn from_macro_def(db: &RootDatabase, macro_call: hir::MacroDef) -> NavigationTarget { 246 pub(crate) fn from_macro_def(db: &RootDatabase, macro_call: hir::MacroDef) -> NavigationTarget {
347 let (file_id, node) = macro_call.source(db); 247 let src = macro_call.source(db);
348 log::debug!("nav target {}", node.syntax().debug_dump()); 248 log::debug!("nav target {}", src.ast.syntax().debug_dump());
349 NavigationTarget::from_named( 249 NavigationTarget::from_named(
350 file_id.original_file(db), 250 src.file_id.original_file(db),
351 &*node, 251 &*src.ast,
352 node.doc_comment_text(), 252 src.ast.doc_comment_text(),
353 None, 253 None,
354 ) 254 )
355 } 255 }
diff --git a/crates/ra_ide_api/src/goto_definition.rs b/crates/ra_ide_api/src/goto_definition.rs
index 325a5a4f3..63ba6cf9d 100644
--- a/crates/ra_ide_api/src/goto_definition.rs
+++ b/crates/ra_ide_api/src/goto_definition.rs
@@ -59,10 +59,10 @@ pub(crate) fn reference_definition(
59 let analyzer = hir::SourceAnalyzer::new(db, file_id, name_ref.syntax(), None); 59 let analyzer = hir::SourceAnalyzer::new(db, file_id, name_ref.syntax(), None);
60 60
61 match classify_name_ref(db, &analyzer, name_ref) { 61 match classify_name_ref(db, &analyzer, name_ref) {
62 Some(Method(func)) => return Exact(NavigationTarget::from_function(db, func)),
63 Some(Macro(mac)) => return Exact(NavigationTarget::from_macro_def(db, mac)), 62 Some(Macro(mac)) => return Exact(NavigationTarget::from_macro_def(db, mac)),
64 Some(FieldAccess(field)) => return Exact(NavigationTarget::from_field(db, field)), 63 Some(FieldAccess(field)) => return Exact(NavigationTarget::from_field(db, field)),
65 Some(AssocItem(assoc)) => return Exact(NavigationTarget::from_impl_item(db, assoc)), 64 Some(AssocItem(assoc)) => return Exact(NavigationTarget::from_impl_item(db, assoc)),
65 Some(Method(func)) => return Exact(NavigationTarget::from_def_source(db, func)),
66 Some(Def(def)) => match NavigationTarget::from_def(db, def) { 66 Some(Def(def)) => match NavigationTarget::from_def(db, def) {
67 Some(nav) => return Exact(nav), 67 Some(nav) => return Exact(nav),
68 None => return Approximate(vec![]), 68 None => return Approximate(vec![]),
@@ -253,12 +253,12 @@ mod tests {
253 //- /foo/lib.rs 253 //- /foo/lib.rs
254 #[macro_export] 254 #[macro_export]
255 macro_rules! foo { 255 macro_rules! foo {
256 () => { 256 () => {
257 {} 257 {}
258 }; 258 };
259 } 259 }
260 ", 260 ",
261 "foo MACRO_CALL FileId(2) [0; 79) [29; 32)", 261 "foo MACRO_CALL FileId(2) [0; 66) [29; 32)",
262 ); 262 );
263 } 263 }
264 264
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index fbabeb194..df877c324 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -1,9 +1,10 @@
1use ra_db::SourceDatabase; 1use ra_db::SourceDatabase;
2use ra_syntax::{ 2use ra_syntax::{
3 AstNode, ast::{self, DocCommentsOwner}, 3 AstNode, TreeArc,
4 ast::{self, DocCommentsOwner},
4 algo::{find_covering_element, find_node_at_offset, ancestors_at_offset, visit::{visitor, Visitor}}, 5 algo::{find_covering_element, find_node_at_offset, ancestors_at_offset, visit::{visitor, Visitor}},
5}; 6};
6use hir::HirDisplay; 7use hir::{HirDisplay, HasSource};
7 8
8use crate::{ 9use crate::{
9 db::RootDatabase, 10 db::RootDatabase,
@@ -94,79 +95,41 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
94 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) { 95 if let Some(name_ref) = find_node_at_offset::<ast::NameRef>(file.syntax(), position.offset) {
95 let analyzer = hir::SourceAnalyzer::new(db, position.file_id, name_ref.syntax(), None); 96 let analyzer = hir::SourceAnalyzer::new(db, position.file_id, name_ref.syntax(), None);
96 97
98 let mut no_fallback = false;
99
97 match classify_name_ref(db, &analyzer, name_ref) { 100 match classify_name_ref(db, &analyzer, name_ref) {
98 Some(Method(it)) => { 101 Some(Method(it)) => res.extend(from_def_source(db, it)),
99 let it = it.source(db).1;
100 res.extend(hover_text(it.doc_comment_text(), it.short_label()));
101 }
102 Some(Macro(it)) => { 102 Some(Macro(it)) => {
103 let it = it.source(db).1; 103 let src = it.source(db);
104 res.extend(hover_text(it.doc_comment_text(), None)); 104 res.extend(hover_text(src.ast.doc_comment_text(), None));
105 } 105 }
106 Some(FieldAccess(it)) => { 106 Some(FieldAccess(it)) => {
107 let it = it.source(db).1; 107 let src = it.source(db);
108 if let hir::FieldSource::Named(it) = it { 108 if let hir::FieldSource::Named(it) = src.ast {
109 res.extend(hover_text(it.doc_comment_text(), it.short_label())); 109 res.extend(hover_text(it.doc_comment_text(), it.short_label()));
110 } 110 }
111 } 111 }
112 Some(AssocItem(it)) => match it { 112 Some(AssocItem(it)) => res.extend(match it {
113 hir::ImplItem::Method(it) => { 113 hir::ImplItem::Method(it) => from_def_source(db, it),
114 let it = it.source(db).1; 114 hir::ImplItem::Const(it) => from_def_source(db, it),
115 res.extend(hover_text(it.doc_comment_text(), it.short_label())) 115 hir::ImplItem::TypeAlias(it) => from_def_source(db, it),
116 } 116 }),
117 hir::ImplItem::Const(it) => {
118 let it = it.source(db).1;
119 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
120 }
121 hir::ImplItem::TypeAlias(it) => {
122 let it = it.source(db).1;
123 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
124 }
125 },
126 Some(Def(it)) => { 117 Some(Def(it)) => {
127 match it { 118 match it {
128 hir::ModuleDef::Module(it) => { 119 hir::ModuleDef::Module(it) => {
129 let it = it.definition_source(db).1; 120 if let hir::ModuleSource::Module(it) = it.definition_source(db).ast {
130 if let hir::ModuleSource::Module(it) = it {
131 res.extend(hover_text(it.doc_comment_text(), it.short_label())) 121 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
132 } 122 }
133 } 123 }
134 hir::ModuleDef::Function(it) => { 124 hir::ModuleDef::Function(it) => res.extend(from_def_source(db, it)),
135 let it = it.source(db).1; 125 hir::ModuleDef::Struct(it) => res.extend(from_def_source(db, it)),
136 res.extend(hover_text(it.doc_comment_text(), it.short_label())) 126 hir::ModuleDef::Union(it) => res.extend(from_def_source(db, it)),
137 } 127 hir::ModuleDef::Enum(it) => res.extend(from_def_source(db, it)),
138 hir::ModuleDef::Struct(it) => { 128 hir::ModuleDef::EnumVariant(it) => res.extend(from_def_source(db, it)),
139 let it = it.source(db).1; 129 hir::ModuleDef::Const(it) => res.extend(from_def_source(db, it)),
140 res.extend(hover_text(it.doc_comment_text(), it.short_label())) 130 hir::ModuleDef::Static(it) => res.extend(from_def_source(db, it)),
141 } 131 hir::ModuleDef::Trait(it) => res.extend(from_def_source(db, it)),
142 hir::ModuleDef::Union(it) => { 132 hir::ModuleDef::TypeAlias(it) => res.extend(from_def_source(db, it)),
143 let it = it.source(db).1;
144 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
145 }
146 hir::ModuleDef::Enum(it) => {
147 let it = it.source(db).1;
148 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
149 }
150 hir::ModuleDef::EnumVariant(it) => {
151 let it = it.source(db).1;
152 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
153 }
154 hir::ModuleDef::Const(it) => {
155 let it = it.source(db).1;
156 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
157 }
158 hir::ModuleDef::Static(it) => {
159 let it = it.source(db).1;
160 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
161 }
162 hir::ModuleDef::Trait(it) => {
163 let it = it.source(db).1;
164 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
165 }
166 hir::ModuleDef::TypeAlias(it) => {
167 let it = it.source(db).1;
168 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
169 }
170 hir::ModuleDef::BuiltinType(_) => { 133 hir::ModuleDef::BuiltinType(_) => {
171 // FIXME: hover for builtin Type ? 134 // FIXME: hover for builtin Type ?
172 } 135 }
@@ -174,27 +137,16 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
174 } 137 }
175 Some(SelfType(ty)) => { 138 Some(SelfType(ty)) => {
176 if let Some((adt_def, _)) = ty.as_adt() { 139 if let Some((adt_def, _)) = ty.as_adt() {
177 match adt_def { 140 res.extend(match adt_def {
178 hir::AdtDef::Struct(it) => { 141 hir::AdtDef::Struct(it) => from_def_source(db, it),
179 let it = it.source(db).1; 142 hir::AdtDef::Union(it) => from_def_source(db, it),
180 res.extend(hover_text(it.doc_comment_text(), it.short_label())) 143 hir::AdtDef::Enum(it) => from_def_source(db, it),
181 } 144 })
182 hir::AdtDef::Union(it) => {
183 let it = it.source(db).1;
184 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
185 }
186 hir::AdtDef::Enum(it) => {
187 let it = it.source(db).1;
188 res.extend(hover_text(it.doc_comment_text(), it.short_label()))
189 }
190 }
191 } 145 }
192 } 146 }
193 Some(Pat(_)) => { 147 Some(Pat(_)) | Some(SelfParam(_)) => {
194 res.extend(None); 148 // Hover for these shows type names
195 } 149 no_fallback = true;
196 Some(SelfParam(_)) => {
197 res.extend(None);
198 } 150 }
199 Some(GenericParam(_)) => { 151 Some(GenericParam(_)) => {
200 // FIXME: Hover for generic param 152 // FIXME: Hover for generic param
@@ -202,7 +154,7 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
202 None => {} 154 None => {}
203 } 155 }
204 156
205 if res.is_empty() { 157 if res.is_empty() && !no_fallback {
206 // Fallback index based approach: 158 // Fallback index based approach:
207 let symbols = crate::symbol_index::index_resolve(db, name_ref); 159 let symbols = crate::symbol_index::index_resolve(db, name_ref);
208 for sym in symbols { 160 for sym in symbols {
@@ -270,7 +222,16 @@ pub(crate) fn hover(db: &RootDatabase, position: FilePosition) -> Option<RangeIn
270 return None; 222 return None;
271 } 223 }
272 let res = RangeInfo::new(range, res); 224 let res = RangeInfo::new(range, res);
273 Some(res) 225 return Some(res);
226
227 fn from_def_source<A, D>(db: &RootDatabase, def: D) -> Option<String>
228 where
229 D: HasSource<Ast = TreeArc<A>>,
230 A: ast::DocCommentsOwner + ast::NameOwner + ShortLabel,
231 {
232 let src = def.source(db);
233 hover_text(src.ast.doc_comment_text(), src.ast.short_label())
234 }
274} 235}
275 236
276pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option<String> { 237pub(crate) fn type_of(db: &RootDatabase, frange: FileRange) -> Option<String> {
@@ -714,4 +675,21 @@ fn func(foo: i32) { if true { <|>foo; }; }
714 assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing")); 675 assert_eq!(trim_markup_opt(hover.info.first()), Some("enum Thing"));
715 assert_eq!(hover.info.is_exact(), true); 676 assert_eq!(hover.info.is_exact(), true);
716 } 677 }
678
679 #[test]
680 fn test_hover_shadowing_pat() {
681 let (analysis, position) = single_file_with_position(
682 "
683 fn x() {}
684
685 fn y() {
686 let x = 0i32;
687 x<|>;
688 }
689 ",
690 );
691 let hover = analysis.hover(position).unwrap().unwrap();
692 assert_eq!(trim_markup_opt(hover.info.first()), Some("i32"));
693 assert_eq!(hover.info.is_exact(), true);
694 }
717} 695}
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs
index dbebf50a6..8741e736f 100644
--- a/crates/ra_ide_api/src/lib.rs
+++ b/crates/ra_ide_api/src/lib.rs
@@ -242,12 +242,21 @@ pub struct CallInfo {
242} 242}
243 243
244/// `AnalysisHost` stores the current state of the world. 244/// `AnalysisHost` stores the current state of the world.
245#[derive(Debug, Default)] 245#[derive(Debug)]
246pub struct AnalysisHost { 246pub struct AnalysisHost {
247 db: db::RootDatabase, 247 db: db::RootDatabase,
248} 248}
249 249
250impl Default for AnalysisHost {
251 fn default() -> AnalysisHost {
252 AnalysisHost::new(None)
253 }
254}
255
250impl AnalysisHost { 256impl AnalysisHost {
257 pub fn new(lru_capcity: Option<usize>) -> AnalysisHost {
258 AnalysisHost { db: db::RootDatabase::new(lru_capcity) }
259 }
251 /// Returns a snapshot of the current state, which you can query for 260 /// Returns a snapshot of the current state, which you can query for
252 /// semantic information. 261 /// semantic information.
253 pub fn analysis(&self) -> Analysis { 262 pub fn analysis(&self) -> Analysis {
diff --git a/crates/ra_ide_api/src/references.rs b/crates/ra_ide_api/src/references.rs
index a75042b76..12cdc6a6d 100644
--- a/crates/ra_ide_api/src/references.rs
+++ b/crates/ra_ide_api/src/references.rs
@@ -148,9 +148,9 @@ fn rename_mod(
148 let mut file_system_edits = Vec::new(); 148 let mut file_system_edits = Vec::new();
149 if let Some(module) = source_binder::module_from_declaration(db, position.file_id, &ast_module) 149 if let Some(module) = source_binder::module_from_declaration(db, position.file_id, &ast_module)
150 { 150 {
151 let (file_id, module_source) = module.definition_source(db); 151 let src = module.definition_source(db);
152 let file_id = file_id.as_original_file(); 152 let file_id = src.file_id.as_original_file();
153 match module_source { 153 match src.ast {
154 ModuleSource::SourceFile(..) => { 154 ModuleSource::SourceFile(..) => {
155 let mod_path: RelativePathBuf = db.file_relative_path(file_id); 155 let mod_path: RelativePathBuf = db.file_relative_path(file_id);
156 // mod is defined in path/to/dir/mod.rs 156 // mod is defined in path/to/dir/mod.rs
diff --git a/crates/ra_lsp_server/src/init.rs b/crates/ra_lsp_server/src/init.rs
index 1b77e0312..b894b449d 100644
--- a/crates/ra_lsp_server/src/init.rs
+++ b/crates/ra_lsp_server/src/init.rs
@@ -17,11 +17,17 @@ pub struct InitializationOptions {
17 /// Defaults to `true` 17 /// Defaults to `true`
18 #[serde(deserialize_with = "nullable_bool_true")] 18 #[serde(deserialize_with = "nullable_bool_true")]
19 pub show_workspace_loaded: bool, 19 pub show_workspace_loaded: bool,
20
21 pub lru_capacity: Option<usize>,
20} 22}
21 23
22impl Default for InitializationOptions { 24impl Default for InitializationOptions {
23 fn default() -> InitializationOptions { 25 fn default() -> InitializationOptions {
24 InitializationOptions { publish_decorations: false, show_workspace_loaded: true } 26 InitializationOptions {
27 publish_decorations: false,
28 show_workspace_loaded: true,
29 lru_capacity: None,
30 }
25 } 31 }
26} 32}
27 33
@@ -54,8 +60,10 @@ mod test {
54 assert_eq!(default, serde_json::from_str(r#"{}"#).unwrap()); 60 assert_eq!(default, serde_json::from_str(r#"{}"#).unwrap());
55 assert_eq!( 61 assert_eq!(
56 default, 62 default,
57 serde_json::from_str(r#"{"publishDecorations":null, "showWorkspaceLoaded":null}"#) 63 serde_json::from_str(
58 .unwrap() 64 r#"{"publishDecorations":null, "showWorkspaceLoaded":null, "lruCapacity":null}"#
65 )
66 .unwrap()
59 ); 67 );
60 } 68 }
61} 69}
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 090fb9b1b..0790ea472 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -73,7 +73,7 @@ pub fn main_loop(
73 loaded_workspaces 73 loaded_workspaces
74 }; 74 };
75 75
76 let mut state = WorldState::new(ws_roots, workspaces); 76 let mut state = WorldState::new(ws_roots, workspaces, options.lru_capacity);
77 77
78 let pool = ThreadPool::new(THREADPOOL_SIZE); 78 let pool = ThreadPool::new(THREADPOOL_SIZE);
79 let (task_sender, task_receiver) = unbounded::<Task>(); 79 let (task_sender, task_receiver) = unbounded::<Task>();
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs
index cd8df4fdb..f9ce570ca 100644
--- a/crates/ra_lsp_server/src/world.rs
+++ b/crates/ra_lsp_server/src/world.rs
@@ -46,7 +46,11 @@ pub struct WorldSnapshot {
46} 46}
47 47
48impl WorldState { 48impl WorldState {
49 pub fn new(folder_roots: Vec<PathBuf>, workspaces: Vec<ProjectWorkspace>) -> WorldState { 49 pub fn new(
50 folder_roots: Vec<PathBuf>,
51 workspaces: Vec<ProjectWorkspace>,
52 lru_capacity: Option<usize>,
53 ) -> WorldState {
50 let mut change = AnalysisChange::new(); 54 let mut change = AnalysisChange::new();
51 55
52 let mut roots = Vec::new(); 56 let mut roots = Vec::new();
@@ -74,7 +78,7 @@ impl WorldState {
74 } 78 }
75 change.set_crate_graph(crate_graph); 79 change.set_crate_graph(crate_graph);
76 80
77 let mut analysis_host = AnalysisHost::default(); 81 let mut analysis_host = AnalysisHost::new(lru_capacity);
78 analysis_host.apply_change(change); 82 analysis_host.apply_change(change);
79 WorldState { 83 WorldState {
80 roots_to_scan, 84 roots_to_scan,
diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md
index 890b18fcd..cf714d659 100644
--- a/docs/dev/architecture.md
+++ b/docs/dev/architecture.md
@@ -50,15 +50,15 @@ processes. These are outlined below:
50 the grammar described in [grammar.ron]: 50 the grammar described in [grammar.ron]:
51 - [ast/generated.rs][ast generated] in `ra_syntax` based on 51 - [ast/generated.rs][ast generated] in `ra_syntax` based on
52 [ast/generated.tera.rs][ast source] 52 [ast/generated.tera.rs][ast source]
53 - [syntax_kinds/generated.rs][syntax_kinds generated] in `ra_syntax` based on 53 - [syntax_kind/generated.rs][syntax_kind generated] in `ra_syntax` based on
54 [syntax_kinds/generated.tera.rs][syntax_kinds source] 54 [syntax_kind/generated.tera.rs][syntax_kind source]
55 55
56[tera]: https://tera.netlify.com/ 56[tera]: https://tera.netlify.com/
57[grammar.ron]: ./crates/ra_syntax/src/grammar.ron 57[grammar.ron]: ../../crates/ra_syntax/src/grammar.ron
58[ast generated]: ./crates/ra_syntax/src/ast/generated.rs 58[ast generated]: ../../crates/ra_syntax/src/ast/generated.rs
59[ast source]: ./crates/ra_syntax/src/ast/generated.rs.tera 59[ast source]: ../../crates/ra_syntax/src/ast/generated.rs.tera
60[syntax_kinds generated]: ./crates/ra_syntax/src/syntax_kinds/generated.rs 60[syntax_kind generated]: ../../crates/ra_parser/src/syntax_kind/generated.rs
61[syntax_kinds source]: ./crates/ra_syntax/src/syntax_kinds/generated.rs.tera 61[syntax_kind source]: ../../crates/ra_parser/src/syntax_kind/generated.rs.tera
62 62
63 63
64## Code Walk-Through 64## Code Walk-Through
diff --git a/editors/code/package.json b/editors/code/package.json
index 05c808394..c2ed8d126 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -232,6 +232,11 @@
232 ], 232 ],
233 "default": "off", 233 "default": "off",
234 "description": "Trace output of cargo-watch" 234 "description": "Trace output of cargo-watch"
235 },
236 "rust-analyzer.lruCapacity": {
237 "type": "number",
238 "default": null,
239 "description": "Number of syntax trees rust-analyzer keeps in memory"
235 } 240 }
236 } 241 }
237 }, 242 },
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index 8d73a6b34..3024546d2 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -19,6 +19,7 @@ export class Config {
19 public enableEnhancedTyping = true; 19 public enableEnhancedTyping = true;
20 public raLspServerPath = RA_LSP_DEBUG || 'ra_lsp_server'; 20 public raLspServerPath = RA_LSP_DEBUG || 'ra_lsp_server';
21 public showWorkspaceLoadedNotification = true; 21 public showWorkspaceLoadedNotification = true;
22 public lruCapacity: null | number = null;
22 public cargoWatchOptions: CargoWatchOptions = { 23 public cargoWatchOptions: CargoWatchOptions = {
23 enableOnStartup: 'ask', 24 enableOnStartup: 'ask',
24 trace: 'off', 25 trace: 'off',
@@ -109,5 +110,8 @@ export class Config {
109 '' 110 ''
110 ); 111 );
111 } 112 }
113 if (config.has('lruCapacity')) {
114 this.lruCapacity = config.get('lruCapacity') as number;
115 }
112 } 116 }
113} 117}
diff --git a/editors/code/src/server.ts b/editors/code/src/server.ts
index 81c2b3fff..7029142fd 100644
--- a/editors/code/src/server.ts
+++ b/editors/code/src/server.ts
@@ -35,7 +35,8 @@ export class Server {
35 initializationOptions: { 35 initializationOptions: {
36 publishDecorations: true, 36 publishDecorations: true,
37 showWorkspaceLoaded: 37 showWorkspaceLoaded:
38 Server.config.showWorkspaceLoadedNotification 38 Server.config.showWorkspaceLoadedNotification,
39 lruCapacity: Server.config.lruCapacity
39 }, 40 },
40 traceOutputChannel 41 traceOutputChannel
41 }; 42 };