diff options
Diffstat (limited to 'crates/ra_ide_api/src')
-rw-r--r-- | crates/ra_ide_api/src/call_info.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide_api/src/change.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_dot.rs | 3 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/complete_path.rs | 10 | ||||
-rw-r--r-- | crates/ra_ide_api/src/completion/presentation.rs | 31 | ||||
-rw-r--r-- | crates/ra_ide_api/src/db.rs | 1 | ||||
-rw-r--r-- | crates/ra_ide_api/src/display/function_signature.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide_api/src/expand_macro.rs | 124 | ||||
-rw-r--r-- | crates/ra_ide_api/src/lib.rs | 4 | ||||
-rw-r--r-- | crates/ra_ide_api/src/mock_analysis.rs | 12 | ||||
-rw-r--r-- | crates/ra_ide_api/src/parent_module.rs | 11 | ||||
-rw-r--r-- | crates/ra_ide_api/src/references/classify.rs | 10 | ||||
-rw-r--r-- | crates/ra_ide_api/src/typing.rs | 34 |
13 files changed, 189 insertions, 63 deletions
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs index 41ee81511..7c367230e 100644 --- a/crates/ra_ide_api/src/call_info.rs +++ b/crates/ra_ide_api/src/call_info.rs | |||
@@ -30,7 +30,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal | |||
30 | let (callable_def, _subst) = analyzer.type_of(db, &expr.expr()?)?.as_callable()?; | 30 | let (callable_def, _subst) = analyzer.type_of(db, &expr.expr()?)?.as_callable()?; |
31 | match callable_def { | 31 | match callable_def { |
32 | hir::CallableDef::Function(it) => { | 32 | hir::CallableDef::Function(it) => { |
33 | (CallInfo::with_fn(db, it), it.data(db).has_self_param()) | 33 | (CallInfo::with_fn(db, it), it.has_self_param(db)) |
34 | } | 34 | } |
35 | hir::CallableDef::Struct(it) => (CallInfo::with_struct(db, it)?, false), | 35 | hir::CallableDef::Struct(it) => (CallInfo::with_struct(db, it)?, false), |
36 | hir::CallableDef::EnumVariant(it) => (CallInfo::with_enum_variant(db, it)?, false), | 36 | hir::CallableDef::EnumVariant(it) => (CallInfo::with_enum_variant(db, it)?, false), |
@@ -38,7 +38,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal | |||
38 | } | 38 | } |
39 | FnCallNode::MethodCallExpr(expr) => { | 39 | FnCallNode::MethodCallExpr(expr) => { |
40 | let function = analyzer.resolve_method_call(&expr)?; | 40 | let function = analyzer.resolve_method_call(&expr)?; |
41 | (CallInfo::with_fn(db, function), function.data(db).has_self_param()) | 41 | (CallInfo::with_fn(db, function), function.has_self_param(db)) |
42 | } | 42 | } |
43 | FnCallNode::MacroCallExpr(expr) => { | 43 | FnCallNode::MacroCallExpr(expr) => { |
44 | let macro_def = analyzer.resolve_macro_call(db, &expr)?; | 44 | let macro_def = analyzer.resolve_macro_call(db, &expr)?; |
diff --git a/crates/ra_ide_api/src/change.rs b/crates/ra_ide_api/src/change.rs index 3c607d5b5..0f692460d 100644 --- a/crates/ra_ide_api/src/change.rs +++ b/crates/ra_ide_api/src/change.rs | |||
@@ -313,7 +313,7 @@ impl RootDatabase { | |||
313 | hir::db::RawItemsQuery | 313 | hir::db::RawItemsQuery |
314 | hir::db::CrateDefMapQuery | 314 | hir::db::CrateDefMapQuery |
315 | hir::db::GenericParamsQuery | 315 | hir::db::GenericParamsQuery |
316 | hir::db::FnDataQuery | 316 | hir::db::FunctionDataQuery |
317 | hir::db::TypeAliasDataQuery | 317 | hir::db::TypeAliasDataQuery |
318 | hir::db::ConstDataQuery | 318 | hir::db::ConstDataQuery |
319 | hir::db::StaticDataQuery | 319 | hir::db::StaticDataQuery |
@@ -324,7 +324,7 @@ impl RootDatabase { | |||
324 | hir::db::ExprScopesQuery | 324 | hir::db::ExprScopesQuery |
325 | hir::db::InferQuery | 325 | hir::db::InferQuery |
326 | hir::db::TypeForDefQuery | 326 | hir::db::TypeForDefQuery |
327 | hir::db::TypeForFieldQuery | 327 | hir::db::FieldTypesQuery |
328 | hir::db::CallableItemSignatureQuery | 328 | hir::db::CallableItemSignatureQuery |
329 | hir::db::GenericPredicatesQuery | 329 | hir::db::GenericPredicatesQuery |
330 | hir::db::GenericDefaultsQuery | 330 | hir::db::GenericDefaultsQuery |
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 4e2c497e1..5a3f9b5f6 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs | |||
@@ -59,8 +59,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) | |||
59 | fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { | 59 | fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) { |
60 | let mut seen_methods = FxHashSet::default(); | 60 | let mut seen_methods = FxHashSet::default(); |
61 | ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| { | 61 | ctx.analyzer.iterate_method_candidates(ctx.db, receiver, None, |_ty, func| { |
62 | let data = func.data(ctx.db); | 62 | if func.has_self_param(ctx.db) && seen_methods.insert(func.name(ctx.db)) { |
63 | if data.has_self_param() && seen_methods.insert(data.name().clone()) { | ||
64 | acc.add_function(ctx, func); | 63 | acc.add_function(ctx, func); |
65 | } | 64 | } |
66 | None::<()> | 65 | None::<()> |
diff --git a/crates/ra_ide_api/src/completion/complete_path.rs b/crates/ra_ide_api/src/completion/complete_path.rs index 5d974cf6d..63e25e0bf 100644 --- a/crates/ra_ide_api/src/completion/complete_path.rs +++ b/crates/ra_ide_api/src/completion/complete_path.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use hir::{Adt, Either, PathResolution}; | 3 | use hir::{Adt, Either, HasSource, PathResolution}; |
4 | use ra_syntax::AstNode; | 4 | use ra_syntax::AstNode; |
5 | use test_utils::tested_by; | 5 | use test_utils::tested_by; |
6 | 6 | ||
@@ -27,7 +27,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
27 | } | 27 | } |
28 | if Some(module) == ctx.module { | 28 | if Some(module) == ctx.module { |
29 | if let Some(import) = import { | 29 | if let Some(import) = import { |
30 | if let Either::A(use_tree) = module.import_source(ctx.db, import) { | 30 | if let Either::A(use_tree) = import.source(ctx.db).value { |
31 | if use_tree.syntax().text_range().contains_inclusive(ctx.offset) { | 31 | if use_tree.syntax().text_range().contains_inclusive(ctx.offset) { |
32 | // for `use self::foo<|>`, don't suggest `foo` as a completion | 32 | // for `use self::foo<|>`, don't suggest `foo` as a completion |
33 | tested_by!(dont_complete_current_use); | 33 | tested_by!(dont_complete_current_use); |
@@ -53,8 +53,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
53 | ctx.analyzer.iterate_path_candidates(ctx.db, ty.clone(), None, |_ty, item| { | 53 | ctx.analyzer.iterate_path_candidates(ctx.db, ty.clone(), None, |_ty, item| { |
54 | match item { | 54 | match item { |
55 | hir::AssocItem::Function(func) => { | 55 | hir::AssocItem::Function(func) => { |
56 | let data = func.data(ctx.db); | 56 | if !func.has_self_param(ctx.db) { |
57 | if !data.has_self_param() { | ||
58 | acc.add_function(ctx, func); | 57 | acc.add_function(ctx, func); |
59 | } | 58 | } |
60 | } | 59 | } |
@@ -80,8 +79,7 @@ pub(super) fn complete_path(acc: &mut Completions, ctx: &CompletionContext) { | |||
80 | for item in t.items(ctx.db) { | 79 | for item in t.items(ctx.db) { |
81 | match item { | 80 | match item { |
82 | hir::AssocItem::Function(func) => { | 81 | hir::AssocItem::Function(func) => { |
83 | let data = func.data(ctx.db); | 82 | if !func.has_self_param(ctx.db) { |
84 | if !data.has_self_param() { | ||
85 | acc.add_function(ctx, func); | 83 | acc.add_function(ctx, func); |
86 | } | 84 | } |
87 | } | 85 | } |
diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs index b20329459..85b053a6e 100644 --- a/crates/ra_ide_api/src/completion/presentation.rs +++ b/crates/ra_ide_api/src/completion/presentation.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! This modules takes care of rendering various definitions as completion items. | 1 | //! This modules takes care of rendering various definitions as completion items. |
2 | 2 | ||
3 | use hir::{db::HirDatabase, Attrs, Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk}; | 3 | use hir::{db::HirDatabase, Docs, HasAttrs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk}; |
4 | use join_to_string::join; | 4 | use join_to_string::join; |
5 | use ra_syntax::ast::NameOwner; | 5 | use ra_syntax::ast::NameOwner; |
6 | use test_utils::tested_by; | 6 | use test_utils::tested_by; |
@@ -199,14 +199,17 @@ impl Completions { | |||
199 | name: Option<String>, | 199 | name: Option<String>, |
200 | func: hir::Function, | 200 | func: hir::Function, |
201 | ) { | 201 | ) { |
202 | let data = func.data(ctx.db); | 202 | let func_name = func.name(ctx.db); |
203 | let name = name.unwrap_or_else(|| data.name().to_string()); | 203 | let has_self_param = func.has_self_param(ctx.db); |
204 | let params = func.params(ctx.db); | ||
205 | |||
206 | let name = name.unwrap_or_else(|| func_name.to_string()); | ||
204 | let ast_node = func.source(ctx.db).value; | 207 | let ast_node = func.source(ctx.db).value; |
205 | let detail = function_label(&ast_node); | 208 | let detail = function_label(&ast_node); |
206 | 209 | ||
207 | let mut builder = | 210 | let mut builder = |
208 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone()) | 211 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone()) |
209 | .kind(if data.has_self_param() { | 212 | .kind(if has_self_param { |
210 | CompletionItemKind::Method | 213 | CompletionItemKind::Method |
211 | } else { | 214 | } else { |
212 | CompletionItemKind::Function | 215 | CompletionItemKind::Function |
@@ -221,12 +224,11 @@ impl Completions { | |||
221 | && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis") | 224 | && ctx.db.feature_flags.get("completion.insertion.add-call-parenthesis") |
222 | { | 225 | { |
223 | tested_by!(inserts_parens_for_function_calls); | 226 | tested_by!(inserts_parens_for_function_calls); |
224 | let (snippet, label) = | 227 | let (snippet, label) = if params.is_empty() || has_self_param && params.len() == 1 { |
225 | if data.params().is_empty() || data.has_self_param() && data.params().len() == 1 { | 228 | (format!("{}()$0", func_name), format!("{}()", name)) |
226 | (format!("{}()$0", data.name()), format!("{}()", name)) | 229 | } else { |
227 | } else { | 230 | (format!("{}($0)", func_name), format!("{}(…)", name)) |
228 | (format!("{}($0)", data.name()), format!("{}(…)", name)) | 231 | }; |
229 | }; | ||
230 | builder = builder.lookup_by(name).label(label).insert_snippet(snippet); | 232 | builder = builder.lookup_by(name).label(label).insert_snippet(snippet); |
231 | } | 233 | } |
232 | 234 | ||
@@ -285,15 +287,12 @@ impl Completions { | |||
285 | } | 287 | } |
286 | } | 288 | } |
287 | 289 | ||
288 | fn is_deprecated(node: impl Attrs, db: &impl HirDatabase) -> bool { | 290 | fn is_deprecated(node: impl HasAttrs, db: &impl HirDatabase) -> bool { |
289 | match node.attrs(db) { | 291 | node.attrs(db).by_key("deprecated").exists() |
290 | None => false, | ||
291 | Some(attrs) => attrs.iter().any(|x| x.is_simple_atom("deprecated")), | ||
292 | } | ||
293 | } | 292 | } |
294 | 293 | ||
295 | fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool { | 294 | fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool { |
296 | let subst = db.generic_defaults(def); | 295 | let subst = db.generic_defaults(def.into()); |
297 | subst.iter().any(|ty| ty == &Ty::Unknown) | 296 | subst.iter().any(|ty| ty == &Ty::Unknown) |
298 | } | 297 | } |
299 | 298 | ||
diff --git a/crates/ra_ide_api/src/db.rs b/crates/ra_ide_api/src/db.rs index c96465b6a..c2a9dcdd1 100644 --- a/crates/ra_ide_api/src/db.rs +++ b/crates/ra_ide_api/src/db.rs | |||
@@ -22,7 +22,6 @@ use crate::{ | |||
22 | hir::db::InternDatabaseStorage, | 22 | hir::db::InternDatabaseStorage, |
23 | hir::db::AstDatabaseStorage, | 23 | hir::db::AstDatabaseStorage, |
24 | hir::db::DefDatabaseStorage, | 24 | hir::db::DefDatabaseStorage, |
25 | hir::db::DefDatabase2Storage, | ||
26 | hir::db::HirDatabaseStorage | 25 | hir::db::HirDatabaseStorage |
27 | )] | 26 | )] |
28 | #[derive(Debug)] | 27 | #[derive(Debug)] |
diff --git a/crates/ra_ide_api/src/display/function_signature.rs b/crates/ra_ide_api/src/display/function_signature.rs index f42dffc87..d96de4e4c 100644 --- a/crates/ra_ide_api/src/display/function_signature.rs +++ b/crates/ra_ide_api/src/display/function_signature.rs | |||
@@ -55,7 +55,7 @@ impl FunctionSignature { | |||
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).value; | 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::Record(_) => return None, |
59 | _ => (), | 59 | _ => (), |
60 | }; | 60 | }; |
61 | 61 | ||
@@ -89,7 +89,7 @@ impl FunctionSignature { | |||
89 | ) -> Option<Self> { | 89 | ) -> Option<Self> { |
90 | let node: ast::EnumVariant = variant.source(db).value; | 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::Record(_) | ast::StructKind::Unit => return None, |
93 | _ => (), | 93 | _ => (), |
94 | }; | 94 | }; |
95 | 95 | ||
diff --git a/crates/ra_ide_api/src/expand_macro.rs b/crates/ra_ide_api/src/expand_macro.rs index 7f39262dc..0b540b8cd 100644 --- a/crates/ra_ide_api/src/expand_macro.rs +++ b/crates/ra_ide_api/src/expand_macro.rs | |||
@@ -40,16 +40,23 @@ fn expand_macro_recur( | |||
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 mut expanded: SyntaxNode = db.parse_or_expand(macro_file_id)?; |
44 | 44 | ||
45 | let children = expanded.descendants().filter_map(ast::MacroCall::cast); | 45 | let children = expanded.descendants().filter_map(ast::MacroCall::cast); |
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 node = hir::Source::new(macro_file_id, &child); | 49 | let node = hir::Source::new(macro_file_id, &child); |
50 | let new_node = expand_macro_recur(db, source, node)?; | 50 | if let Some(new_node) = expand_macro_recur(db, source, node) { |
51 | 51 | // Replace the whole node if it is root | |
52 | replaces.insert(child.syntax().clone().into(), new_node.into()); | 52 | // `replace_descendants` will not replace the parent node |
53 | // but `SyntaxNode::descendants include itself | ||
54 | if expanded == *child.syntax() { | ||
55 | expanded = new_node; | ||
56 | } else { | ||
57 | replaces.insert(child.syntax().clone().into(), new_node.into()); | ||
58 | } | ||
59 | } | ||
53 | } | 60 | } |
54 | 61 | ||
55 | Some(replace_descendants(&expanded, &replaces)) | 62 | Some(replace_descendants(&expanded, &replaces)) |
@@ -84,24 +91,19 @@ fn insert_whitespaces(syn: SyntaxNode) -> String { | |||
84 | }; | 91 | }; |
85 | 92 | ||
86 | res += &match token.kind() { | 93 | res += &match token.kind() { |
87 | k @ _ | 94 | k @ _ if is_text(k) && is_next(|it| !it.is_punct(), true) => { |
88 | if (k.is_keyword() || k.is_literal() || k == IDENT) | ||
89 | && is_next(|it| !it.is_punct(), true) => | ||
90 | { | ||
91 | token.text().to_string() + " " | 95 | token.text().to_string() + " " |
92 | } | 96 | } |
93 | L_CURLY if is_next(|it| it != R_CURLY, true) => { | 97 | L_CURLY if is_next(|it| it != R_CURLY, true) => { |
94 | indent += 1; | 98 | indent += 1; |
95 | format!(" {{\n{}", " ".repeat(indent)) | 99 | let leading_space = if is_last(|it| is_text(it), false) { " " } else { "" }; |
100 | format!("{}{{\n{}", leading_space, " ".repeat(indent)) | ||
96 | } | 101 | } |
97 | R_CURLY if is_last(|it| it != L_CURLY, true) => { | 102 | R_CURLY if is_last(|it| it != L_CURLY, true) => { |
98 | indent = indent.checked_sub(1).unwrap_or(0); | 103 | indent = indent.checked_sub(1).unwrap_or(0); |
99 | format!("\n}}{}", " ".repeat(indent)) | 104 | format!("\n{}}}", " ".repeat(indent)) |
100 | } | ||
101 | R_CURLY => { | ||
102 | indent = indent.checked_sub(1).unwrap_or(0); | ||
103 | format!("}}\n{}", " ".repeat(indent)) | ||
104 | } | 105 | } |
106 | R_CURLY => format!("}}\n{}", " ".repeat(indent)), | ||
105 | T![;] => format!(";\n{}", " ".repeat(indent)), | 107 | T![;] => format!(";\n{}", " ".repeat(indent)), |
106 | T![->] => " -> ".to_string(), | 108 | T![->] => " -> ".to_string(), |
107 | T![=] => " = ".to_string(), | 109 | T![=] => " = ".to_string(), |
@@ -112,7 +114,11 @@ fn insert_whitespaces(syn: SyntaxNode) -> String { | |||
112 | last = Some(token.kind()); | 114 | last = Some(token.kind()); |
113 | } | 115 | } |
114 | 116 | ||
115 | res | 117 | return res; |
118 | |||
119 | fn is_text(k: SyntaxKind) -> bool { | ||
120 | k.is_keyword() || k.is_literal() || k == IDENT | ||
121 | } | ||
116 | } | 122 | } |
117 | 123 | ||
118 | #[cfg(test)] | 124 | #[cfg(test)] |
@@ -175,4 +181,92 @@ fn some_thing() -> u32 { | |||
175 | } | 181 | } |
176 | "###); | 182 | "###); |
177 | } | 183 | } |
184 | |||
185 | #[test] | ||
186 | fn macro_expand_match_ast() { | ||
187 | let res = check_expand_macro( | ||
188 | r#" | ||
189 | //- /lib.rs | ||
190 | macro_rules! match_ast { | ||
191 | (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) }; | ||
192 | |||
193 | (match ($node:expr) { | ||
194 | $( ast::$ast:ident($it:ident) => $res:block, )* | ||
195 | _ => $catch_all:expr $(,)? | ||
196 | }) => {{ | ||
197 | $( if let Some($it) = ast::$ast::cast($node.clone()) $res else )* | ||
198 | { $catch_all } | ||
199 | }}; | ||
200 | } | ||
201 | |||
202 | fn main() { | ||
203 | mat<|>ch_ast! { | ||
204 | match container { | ||
205 | ast::TraitDef(it) => {}, | ||
206 | ast::ImplBlock(it) => {}, | ||
207 | _ => { continue }, | ||
208 | } | ||
209 | } | ||
210 | } | ||
211 | "#, | ||
212 | ); | ||
213 | |||
214 | assert_eq!(res.name, "match_ast"); | ||
215 | assert_snapshot!(res.expansion, @r###" | ||
216 | { | ||
217 | if let Some(it) = ast::TraitDef::cast(container.clone()){} | ||
218 | else if let Some(it) = ast::ImplBlock::cast(container.clone()){} | ||
219 | else { | ||
220 | { | ||
221 | continue | ||
222 | } | ||
223 | } | ||
224 | } | ||
225 | "###); | ||
226 | } | ||
227 | |||
228 | #[test] | ||
229 | fn macro_expand_match_ast_inside_let_statement() { | ||
230 | let res = check_expand_macro( | ||
231 | r#" | ||
232 | //- /lib.rs | ||
233 | macro_rules! match_ast { | ||
234 | (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) }; | ||
235 | (match ($node:expr) {}) => {{}}; | ||
236 | } | ||
237 | |||
238 | fn main() { | ||
239 | let p = f(|it| { | ||
240 | let res = mat<|>ch_ast! { match c {}}; | ||
241 | Some(res) | ||
242 | })?; | ||
243 | } | ||
244 | "#, | ||
245 | ); | ||
246 | |||
247 | assert_eq!(res.name, "match_ast"); | ||
248 | assert_snapshot!(res.expansion, @r###"{}"###); | ||
249 | } | ||
250 | |||
251 | #[test] | ||
252 | fn macro_expand_inner_macro_fail_to_expand() { | ||
253 | let res = check_expand_macro( | ||
254 | r#" | ||
255 | //- /lib.rs | ||
256 | macro_rules! bar { | ||
257 | (BAD) => {}; | ||
258 | } | ||
259 | macro_rules! foo { | ||
260 | () => {bar!()}; | ||
261 | } | ||
262 | |||
263 | fn main() { | ||
264 | let res = fo<|>o!(); | ||
265 | } | ||
266 | "#, | ||
267 | ); | ||
268 | |||
269 | assert_eq!(res.name, "foo"); | ||
270 | assert_snapshot!(res.expansion, @r###"bar!()"###); | ||
271 | } | ||
178 | } | 272 | } |
diff --git a/crates/ra_ide_api/src/lib.rs b/crates/ra_ide_api/src/lib.rs index 62ad996bc..cb6c24eaa 100644 --- a/crates/ra_ide_api/src/lib.rs +++ b/crates/ra_ide_api/src/lib.rs | |||
@@ -54,7 +54,7 @@ use std::sync::Arc; | |||
54 | use ra_cfg::CfgOptions; | 54 | use ra_cfg::CfgOptions; |
55 | use ra_db::{ | 55 | use ra_db::{ |
56 | salsa::{self, ParallelDatabase}, | 56 | salsa::{self, ParallelDatabase}, |
57 | CheckCanceled, FileLoader, SourceDatabase, | 57 | CheckCanceled, Env, FileLoader, SourceDatabase, |
58 | }; | 58 | }; |
59 | use ra_syntax::{SourceFile, TextRange, TextUnit}; | 59 | use ra_syntax::{SourceFile, TextRange, TextUnit}; |
60 | 60 | ||
@@ -240,7 +240,7 @@ impl Analysis { | |||
240 | // Default to enable test for single file. | 240 | // Default to enable test for single file. |
241 | let mut cfg_options = CfgOptions::default(); | 241 | let mut cfg_options = CfgOptions::default(); |
242 | cfg_options.insert_atom("test".into()); | 242 | cfg_options.insert_atom("test".into()); |
243 | crate_graph.add_crate_root(file_id, Edition::Edition2018, cfg_options); | 243 | crate_graph.add_crate_root(file_id, Edition::Edition2018, cfg_options, Env::default()); |
244 | change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text)); | 244 | change.add_file(source_root, file_id, "main.rs".into(), Arc::new(text)); |
245 | change.set_crate_graph(crate_graph); | 245 | change.set_crate_graph(crate_graph); |
246 | host.apply_change(change); | 246 | host.apply_change(change); |
diff --git a/crates/ra_ide_api/src/mock_analysis.rs b/crates/ra_ide_api/src/mock_analysis.rs index 2b1c96dbf..bf8a54932 100644 --- a/crates/ra_ide_api/src/mock_analysis.rs +++ b/crates/ra_ide_api/src/mock_analysis.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use ra_cfg::CfgOptions; | 5 | use ra_cfg::CfgOptions; |
6 | use ra_db::RelativePathBuf; | 6 | use ra_db::{Env, RelativePathBuf}; |
7 | use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER}; | 7 | use test_utils::{extract_offset, extract_range, parse_fixture, CURSOR_MARKER}; |
8 | 8 | ||
9 | use crate::{ | 9 | use crate::{ |
@@ -96,9 +96,15 @@ impl MockAnalysis { | |||
96 | let file_id = FileId(i as u32 + 1); | 96 | let file_id = FileId(i as u32 + 1); |
97 | let cfg_options = CfgOptions::default(); | 97 | let cfg_options = CfgOptions::default(); |
98 | if path == "/lib.rs" || path == "/main.rs" { | 98 | if path == "/lib.rs" || path == "/main.rs" { |
99 | root_crate = Some(crate_graph.add_crate_root(file_id, Edition2018, cfg_options)); | 99 | root_crate = Some(crate_graph.add_crate_root( |
100 | file_id, | ||
101 | Edition2018, | ||
102 | cfg_options, | ||
103 | Env::default(), | ||
104 | )); | ||
100 | } else if path.ends_with("/lib.rs") { | 105 | } else if path.ends_with("/lib.rs") { |
101 | let other_crate = crate_graph.add_crate_root(file_id, Edition2018, cfg_options); | 106 | let other_crate = |
107 | crate_graph.add_crate_root(file_id, Edition2018, cfg_options, Env::default()); | ||
102 | let crate_name = path.parent().unwrap().file_name().unwrap(); | 108 | let crate_name = path.parent().unwrap().file_name().unwrap(); |
103 | if let Some(root_crate) = root_crate { | 109 | if let Some(root_crate) = root_crate { |
104 | crate_graph.add_dep(root_crate, crate_name.into(), other_crate).unwrap(); | 110 | crate_graph.add_dep(root_crate, crate_name.into(), other_crate).unwrap(); |
diff --git a/crates/ra_ide_api/src/parent_module.rs b/crates/ra_ide_api/src/parent_module.rs index fa232a379..6027e7d54 100644 --- a/crates/ra_ide_api/src/parent_module.rs +++ b/crates/ra_ide_api/src/parent_module.rs | |||
@@ -34,12 +34,14 @@ pub(crate) fn crate_for(db: &RootDatabase, file_id: FileId) -> Vec<CrateId> { | |||
34 | 34 | ||
35 | #[cfg(test)] | 35 | #[cfg(test)] |
36 | mod tests { | 36 | mod tests { |
37 | use ra_cfg::CfgOptions; | ||
38 | use ra_db::Env; | ||
39 | |||
37 | use crate::{ | 40 | use crate::{ |
38 | mock_analysis::{analysis_and_position, MockAnalysis}, | 41 | mock_analysis::{analysis_and_position, MockAnalysis}, |
39 | AnalysisChange, CrateGraph, | 42 | AnalysisChange, CrateGraph, |
40 | Edition::Edition2018, | 43 | Edition::Edition2018, |
41 | }; | 44 | }; |
42 | use ra_cfg::CfgOptions; | ||
43 | 45 | ||
44 | #[test] | 46 | #[test] |
45 | fn test_resolve_parent_module() { | 47 | fn test_resolve_parent_module() { |
@@ -87,7 +89,12 @@ mod tests { | |||
87 | assert!(host.analysis().crate_for(mod_file).unwrap().is_empty()); | 89 | assert!(host.analysis().crate_for(mod_file).unwrap().is_empty()); |
88 | 90 | ||
89 | let mut crate_graph = CrateGraph::default(); | 91 | let mut crate_graph = CrateGraph::default(); |
90 | let crate_id = crate_graph.add_crate_root(root_file, Edition2018, CfgOptions::default()); | 92 | let crate_id = crate_graph.add_crate_root( |
93 | root_file, | ||
94 | Edition2018, | ||
95 | CfgOptions::default(), | ||
96 | Env::default(), | ||
97 | ); | ||
91 | let mut change = AnalysisChange::new(); | 98 | let mut change = AnalysisChange::new(); |
92 | change.set_crate_graph(crate_graph); | 99 | change.set_crate_graph(crate_graph); |
93 | host.apply_change(change); | 100 | host.apply_change(change); |
diff --git a/crates/ra_ide_api/src/references/classify.rs b/crates/ra_ide_api/src/references/classify.rs index 4a4b030f8..cab06dea9 100644 --- a/crates/ra_ide_api/src/references/classify.rs +++ b/crates/ra_ide_api/src/references/classify.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! Functions that are used to classify an element from its definition or reference. | 1 | //! Functions that are used to classify an element from its definition or reference. |
2 | 2 | ||
3 | use hir::{FromSource, Module, ModuleSource, Path, PathResolution, Source, SourceAnalyzer}; | 3 | use hir::{FromSource, Module, ModuleSource, PathResolution, Source, SourceAnalyzer}; |
4 | use ra_prof::profile; | 4 | use ra_prof::profile; |
5 | use ra_syntax::{ast, match_ast, AstNode}; | 5 | use ra_syntax::{ast, match_ast, AstNode}; |
6 | use test_utils::tested_by; | 6 | use test_utils::tested_by; |
@@ -140,12 +140,8 @@ pub(crate) fn classify_name_ref( | |||
140 | 140 | ||
141 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { | 141 | if let Some(record_field) = ast::RecordField::cast(parent.clone()) { |
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(field_def) = analyzer.resolve_record_field(&record_field) { |
144 | let variant_def = analyzer.resolve_record_literal(&record_lit)?; | 144 | return Some(from_struct_field(db, field_def)); |
145 | let hir_path = Path::from_name_ref(name_ref.value); | ||
146 | let hir_name = hir_path.as_ident()?; | ||
147 | let field = variant_def.field(db, hir_name)?; | ||
148 | return Some(from_struct_field(db, field)); | ||
149 | } | 145 | } |
150 | } | 146 | } |
151 | 147 | ||
diff --git a/crates/ra_ide_api/src/typing.rs b/crates/ra_ide_api/src/typing.rs index d51132f73..21e5be9b3 100644 --- a/crates/ra_ide_api/src/typing.rs +++ b/crates/ra_ide_api/src/typing.rs | |||
@@ -40,9 +40,13 @@ pub(crate) fn on_enter(db: &RootDatabase, position: FilePosition) -> Option<Sour | |||
40 | } | 40 | } |
41 | 41 | ||
42 | let prefix = comment.prefix(); | 42 | let prefix = comment.prefix(); |
43 | if position.offset | 43 | let comment_range = comment.syntax().text_range(); |
44 | < comment.syntax().text_range().start() + TextUnit::of_str(prefix) + TextUnit::from(1) | 44 | if position.offset < comment_range.start() + TextUnit::of_str(prefix) + TextUnit::from(1) { |
45 | { | 45 | return None; |
46 | } | ||
47 | |||
48 | // Continuing non-doc line comments (like this one :) ) is annoying | ||
49 | if prefix == "//" && comment_range.end() == position.offset { | ||
46 | return None; | 50 | return None; |
47 | } | 51 | } |
48 | 52 | ||
@@ -247,6 +251,30 @@ impl S { | |||
247 | } | 251 | } |
248 | ", | 252 | ", |
249 | ); | 253 | ); |
254 | do_check( | ||
255 | r" | ||
256 | fn main() { | ||
257 | // Fix<|> me | ||
258 | let x = 1 + 1; | ||
259 | } | ||
260 | ", | ||
261 | r" | ||
262 | fn main() { | ||
263 | // Fix | ||
264 | // <|> me | ||
265 | let x = 1 + 1; | ||
266 | } | ||
267 | ", | ||
268 | ); | ||
269 | do_check_noop( | ||
270 | r" | ||
271 | fn main() { | ||
272 | // Fix me<|> | ||
273 | let x = 1 + 1; | ||
274 | } | ||
275 | ", | ||
276 | ); | ||
277 | |||
250 | do_check_noop(r"<|>//! docz"); | 278 | do_check_noop(r"<|>//! docz"); |
251 | } | 279 | } |
252 | 280 | ||