aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/hir_def/src/attr.rs4
-rw-r--r--crates/hir_def/src/find_path.rs63
-rw-r--r--crates/hir_expand/src/eager.rs18
-rw-r--r--crates/ide/src/expand_macro.rs23
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs2
-rw-r--r--crates/ide/src/syntax_highlighting/tags.rs4
-rw-r--r--crates/ide_assists/src/handlers/auto_import.rs33
-rw-r--r--crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs37
-rw-r--r--crates/rust-analyzer/src/semantic_tokens.rs2
-rw-r--r--crates/rust-analyzer/src/to_proto.rs2
-rw-r--r--crates/rust-analyzer/tests/rust-analyzer/main.rs2
-rw-r--r--crates/syntax/src/ast/node_ext.rs12
-rw-r--r--crates/syntax/src/validation/block.rs2
-rw-r--r--crates/syntax/test_data/parser/ok/0045_block_attrs.rast218
-rw-r--r--crates/syntax/test_data/parser/ok/0045_block_attrs.rs (renamed from crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rs)6
-rw-r--r--crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rast178
16 files changed, 367 insertions, 239 deletions
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index 786fad6e1..d9294d93a 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -545,7 +545,7 @@ fn inner_attributes(
545 _ => return None, 545 _ => return None,
546 } 546 }
547 }; 547 };
548 let attrs = attrs.filter(|attr| attr.excl_token().is_some()); 548 let attrs = attrs.filter(|attr| attr.kind().is_inner());
549 let docs = docs.filter(|doc| doc.is_inner()); 549 let docs = docs.filter(|doc| doc.is_inner());
550 Some((attrs, docs)) 550 Some((attrs, docs))
551} 551}
@@ -740,7 +740,7 @@ fn collect_attrs(
740 let (inner_attrs, inner_docs) = inner_attributes(owner.syntax()) 740 let (inner_attrs, inner_docs) = inner_attributes(owner.syntax())
741 .map_or((None, None), |(attrs, docs)| (Some(attrs), Some(docs))); 741 .map_or((None, None), |(attrs, docs)| (Some(attrs), Some(docs)));
742 742
743 let outer_attrs = owner.attrs().filter(|attr| attr.excl_token().is_none()); 743 let outer_attrs = owner.attrs().filter(|attr| attr.kind().is_outer());
744 let attrs = outer_attrs 744 let attrs = outer_attrs
745 .chain(inner_attrs.into_iter().flatten()) 745 .chain(inner_attrs.into_iter().flatten())
746 .map(|attr| (attr.syntax().text_range().start(), Either::Left(attr))); 746 .map(|attr| (attr.syntax().text_range().start(), Either::Left(attr)));
diff --git a/crates/hir_def/src/find_path.rs b/crates/hir_def/src/find_path.rs
index 2c4bbe585..dc3f2908f 100644
--- a/crates/hir_def/src/find_path.rs
+++ b/crates/hir_def/src/find_path.rs
@@ -119,8 +119,7 @@ fn find_path_inner(
119 119
120 // - if the item is the crate root, return `crate` 120 // - if the item is the crate root, return `crate`
121 let root = def_map.crate_root(db); 121 let root = def_map.crate_root(db);
122 if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) && def_map.block_id().is_none() { 122 if item == ItemInNs::Types(ModuleDefId::ModuleId(root)) {
123 // FIXME: the `block_id()` check should be unnecessary, but affects the result
124 return Some(ModPath::from_segments(PathKind::Crate, Vec::new())); 123 return Some(ModPath::from_segments(PathKind::Crate, Vec::new()));
125 } 124 }
126 125
@@ -131,7 +130,7 @@ fn find_path_inner(
131 } 130 }
132 131
133 // - if the item is the crate root of a dependency crate, return the name from the extern prelude 132 // - if the item is the crate root of a dependency crate, return the name from the extern prelude
134 for (name, def_id) in def_map.extern_prelude() { 133 for (name, def_id) in root.def_map(db).extern_prelude() {
135 if item == ItemInNs::Types(*def_id) { 134 if item == ItemInNs::Types(*def_id) {
136 let name = scope_name.unwrap_or_else(|| name.clone()); 135 let name = scope_name.unwrap_or_else(|| name.clone());
137 return Some(ModPath::from_segments(PathKind::Plain, vec![name])); 136 return Some(ModPath::from_segments(PathKind::Plain, vec![name]));
@@ -298,6 +297,7 @@ fn find_local_import_locations(
298 let data = &def_map[from.local_id]; 297 let data = &def_map[from.local_id];
299 let mut worklist = 298 let mut worklist =
300 data.children.values().map(|child| def_map.module_id(*child)).collect::<Vec<_>>(); 299 data.children.values().map(|child| def_map.module_id(*child)).collect::<Vec<_>>();
300 // FIXME: do we need to traverse out of block expressions here?
301 for ancestor in iter::successors(from.containing_module(db), |m| m.containing_module(db)) { 301 for ancestor in iter::successors(from.containing_module(db), |m| m.containing_module(db)) {
302 worklist.push(ancestor); 302 worklist.push(ancestor);
303 } 303 }
@@ -947,10 +947,11 @@ fn main() {
947 $0 947 $0
948} 948}
949 "#, 949 "#,
950 // FIXME: these could use fewer/better prefixes
950 "module::CompleteMe", 951 "module::CompleteMe",
951 "module::CompleteMe",
952 "crate::module::CompleteMe", 952 "crate::module::CompleteMe",
953 "self::module::CompleteMe", 953 "crate::module::CompleteMe",
954 "crate::module::CompleteMe",
954 ) 955 )
955 } 956 }
956 957
@@ -978,6 +979,28 @@ mod bar {
978 } 979 }
979 980
980 #[test] 981 #[test]
982 fn from_inside_module_with_inner_items() {
983 check_found_path(
984 r#"
985mod baz {
986 pub struct Foo {}
987}
988
989mod bar {
990 fn bar() {
991 fn inner() {}
992 $0
993 }
994}
995 "#,
996 "crate::baz::Foo",
997 "crate::baz::Foo",
998 "crate::baz::Foo",
999 "crate::baz::Foo",
1000 )
1001 }
1002
1003 #[test]
981 fn recursive_pub_mod_reexport() { 1004 fn recursive_pub_mod_reexport() {
982 cov_mark::check!(recursive_imports); 1005 cov_mark::check!(recursive_imports);
983 check_found_path( 1006 check_found_path(
@@ -1004,4 +1027,34 @@ pub mod name {
1004 "self::name::AsName", 1027 "self::name::AsName",
1005 ); 1028 );
1006 } 1029 }
1030
1031 #[test]
1032 fn extern_crate() {
1033 check_found_path(
1034 r#"
1035//- /main.rs crate:main deps:dep
1036$0
1037//- /dep.rs crate:dep
1038"#,
1039 "dep",
1040 "dep",
1041 "dep",
1042 "dep",
1043 );
1044
1045 check_found_path(
1046 r#"
1047//- /main.rs crate:main deps:dep
1048fn f() {
1049 fn inner() {}
1050 $0
1051}
1052//- /dep.rs crate:dep
1053"#,
1054 "dep",
1055 "dep",
1056 "dep",
1057 "dep",
1058 );
1059 }
1007} 1060}
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs
index a5ac32d3c..f12132f84 100644
--- a/crates/hir_expand/src/eager.rs
+++ b/crates/hir_expand/src/eager.rs
@@ -29,7 +29,7 @@ use base_db::CrateId;
29use mbe::ExpandResult; 29use mbe::ExpandResult;
30use parser::FragmentKind; 30use parser::FragmentKind;
31use std::sync::Arc; 31use std::sync::Arc;
32use syntax::{algo::SyntaxRewriter, SyntaxNode}; 32use syntax::{ted, SyntaxNode};
33 33
34#[derive(Debug)] 34#[derive(Debug)]
35pub struct ErrorEmitted { 35pub struct ErrorEmitted {
@@ -192,10 +192,10 @@ fn eager_macro_recur(
192 macro_resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>, 192 macro_resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>,
193 mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError), 193 mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError),
194) -> Result<SyntaxNode, ErrorEmitted> { 194) -> Result<SyntaxNode, ErrorEmitted> {
195 let original = curr.value.clone(); 195 let original = curr.value.clone().clone_for_update();
196 196
197 let children = curr.value.descendants().filter_map(ast::MacroCall::cast); 197 let children = original.descendants().filter_map(ast::MacroCall::cast);
198 let mut rewriter = SyntaxRewriter::default(); 198 let mut replacements = Vec::new();
199 199
200 // Collect replacement 200 // Collect replacement
201 for child in children { 201 for child in children {
@@ -214,6 +214,7 @@ fn eager_macro_recur(
214 .into(); 214 .into();
215 db.parse_or_expand(id.as_file()) 215 db.parse_or_expand(id.as_file())
216 .expect("successful macro expansion should be parseable") 216 .expect("successful macro expansion should be parseable")
217 .clone_for_update()
217 } 218 }
218 MacroDefKind::Declarative(_) 219 MacroDefKind::Declarative(_)
219 | MacroDefKind::BuiltIn(..) 220 | MacroDefKind::BuiltIn(..)
@@ -227,15 +228,14 @@ fn eager_macro_recur(
227 } 228 }
228 }; 229 };
229 230
230 // check if the whole original sytnax is replaced 231 // check if the whole original syntax is replaced
231 // Note that SyntaxRewriter cannot replace the root node itself
232 if child.syntax() == &original { 232 if child.syntax() == &original {
233 return Ok(insert); 233 return Ok(insert);
234 } 234 }
235 235
236 rewriter.replace(child.syntax(), &insert); 236 replacements.push((child, insert));
237 } 237 }
238 238
239 let res = rewriter.rewrite(&original); 239 replacements.into_iter().rev().for_each(|(old, new)| ted::replace(old.syntax(), new));
240 Ok(res) 240 Ok(original)
241} 241}
diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs
index be0ee03bf..eebae5ebe 100644
--- a/crates/ide/src/expand_macro.rs
+++ b/crates/ide/src/expand_macro.rs
@@ -3,9 +3,7 @@ use std::iter;
3use hir::Semantics; 3use hir::Semantics;
4use ide_db::RootDatabase; 4use ide_db::RootDatabase;
5use syntax::{ 5use syntax::{
6 algo::{find_node_at_offset, SyntaxRewriter}, 6 algo::find_node_at_offset, ast, ted, AstNode, NodeOrToken, SyntaxKind, SyntaxKind::*,
7 ast, AstNode, NodeOrToken, SyntaxKind,
8 SyntaxKind::*,
9 SyntaxNode, WalkEvent, T, 7 SyntaxNode, WalkEvent, T,
10}; 8};
11 9
@@ -46,26 +44,23 @@ fn expand_macro_recur(
46 sema: &Semantics<RootDatabase>, 44 sema: &Semantics<RootDatabase>,
47 macro_call: &ast::MacroCall, 45 macro_call: &ast::MacroCall,
48) -> Option<SyntaxNode> { 46) -> Option<SyntaxNode> {
49 let mut expanded = sema.expand(macro_call)?; 47 let expanded = sema.expand(macro_call)?.clone_for_update();
50 48
51 let children = expanded.descendants().filter_map(ast::MacroCall::cast); 49 let children = expanded.descendants().filter_map(ast::MacroCall::cast);
52 let mut rewriter = SyntaxRewriter::default(); 50 let mut replacements = Vec::new();
53 51
54 for child in children.into_iter() { 52 for child in children {
55 if let Some(new_node) = expand_macro_recur(sema, &child) { 53 if let Some(new_node) = expand_macro_recur(sema, &child) {
56 // Replace the whole node if it is root 54 // check if the whole original syntax is replaced
57 // `replace_descendants` will not replace the parent node
58 // but `SyntaxNode::descendants include itself
59 if expanded == *child.syntax() { 55 if expanded == *child.syntax() {
60 expanded = new_node; 56 return Some(new_node);
61 } else {
62 rewriter.replace(child.syntax(), &new_node)
63 } 57 }
58 replacements.push((child, new_node));
64 } 59 }
65 } 60 }
66 61
67 let res = rewriter.rewrite(&expanded); 62 replacements.into_iter().rev().for_each(|(old, new)| ted::replace(old.syntax(), new));
68 Some(res) 63 Some(expanded)
69} 64}
70 65
71// FIXME: It would also be cool to share logic here and in the mbe tests, 66// FIXME: It would also be cool to share logic here and in the mbe tests,
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index 8cc877c1c..18552459b 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -222,7 +222,7 @@ pub(super) fn element(
222 T![>] | T![<] | T![==] | T![>=] | T![<=] | T![!=] 222 T![>] | T![<] | T![==] | T![>=] | T![<=] | T![!=]
223 if element.parent().and_then(ast::BinExpr::cast).is_some() => 223 if element.parent().and_then(ast::BinExpr::cast).is_some() =>
224 { 224 {
225 HlTag::Operator(HlOperator::Comparision).into() 225 HlTag::Operator(HlOperator::Comparison).into()
226 } 226 }
227 _ if element.parent().and_then(ast::BinExpr::cast).is_some() => { 227 _ if element.parent().and_then(ast::BinExpr::cast).is_some() => {
228 HlTag::Operator(HlOperator::Other).into() 228 HlTag::Operator(HlOperator::Other).into()
diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs
index 8128d231d..e58392d67 100644
--- a/crates/ide/src/syntax_highlighting/tags.rs
+++ b/crates/ide/src/syntax_highlighting/tags.rs
@@ -96,7 +96,7 @@ pub enum HlOperator {
96 /// &&, ||, ! 96 /// &&, ||, !
97 Logical, 97 Logical,
98 /// >, <, ==, >=, <=, != 98 /// >, <, ==, >=, <=, !=
99 Comparision, 99 Comparison,
100 /// 100 ///
101 Other, 101 Other,
102} 102}
@@ -151,7 +151,7 @@ impl HlTag {
151 HlOperator::Bitwise => "bitwise", 151 HlOperator::Bitwise => "bitwise",
152 HlOperator::Arithmetic => "arithmetic", 152 HlOperator::Arithmetic => "arithmetic",
153 HlOperator::Logical => "logical", 153 HlOperator::Logical => "logical",
154 HlOperator::Comparision => "comparision", 154 HlOperator::Comparison => "comparison",
155 HlOperator::Other => "operator", 155 HlOperator::Other => "operator",
156 }, 156 },
157 HlTag::StringLiteral => "string_literal", 157 HlTag::StringLiteral => "string_literal",
diff --git a/crates/ide_assists/src/handlers/auto_import.rs b/crates/ide_assists/src/handlers/auto_import.rs
index 5ccd7f7a2..49aa70f74 100644
--- a/crates/ide_assists/src/handlers/auto_import.rs
+++ b/crates/ide_assists/src/handlers/auto_import.rs
@@ -934,4 +934,37 @@ fn main() {
934", 934",
935 ); 935 );
936 } 936 }
937
938 #[test]
939 fn inner_items() {
940 check_assist(
941 auto_import,
942 r#"
943mod baz {
944 pub struct Foo {}
945}
946
947mod bar {
948 fn bar() {
949 Foo$0;
950 println!("Hallo");
951 }
952}
953"#,
954 r#"
955mod baz {
956 pub struct Foo {}
957}
958
959mod bar {
960 use crate::baz::Foo;
961
962 fn bar() {
963 Foo;
964 println!("Hallo");
965 }
966}
967"#,
968 );
969 }
937} 970}
diff --git a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
index f872d20c8..870a8d4ff 100644
--- a/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
+++ b/crates/ide_assists/src/handlers/replace_derive_with_manual_impl.rs
@@ -5,7 +5,6 @@ use itertools::Itertools;
5use syntax::{ 5use syntax::{
6 ast::{self, make, AstNode, NameOwner}, 6 ast::{self, make, AstNode, NameOwner},
7 SyntaxKind::{IDENT, WHITESPACE}, 7 SyntaxKind::{IDENT, WHITESPACE},
8 TextSize,
9}; 8};
10 9
11use crate::{ 10use crate::{
@@ -43,32 +42,23 @@ pub(crate) fn replace_derive_with_manual_impl(
43 ctx: &AssistContext, 42 ctx: &AssistContext,
44) -> Option<()> { 43) -> Option<()> {
45 let attr = ctx.find_node_at_offset::<ast::Attr>()?; 44 let attr = ctx.find_node_at_offset::<ast::Attr>()?;
46 45 let (name, args) = attr.as_simple_call()?;
47 let has_derive = attr 46 if name != "derive" {
48 .syntax()
49 .descendants_with_tokens()
50 .filter(|t| t.kind() == IDENT)
51 .find_map(syntax::NodeOrToken::into_token)
52 .filter(|t| t.text() == "derive")
53 .is_some();
54 if !has_derive {
55 return None; 47 return None;
56 } 48 }
57 49
58 let trait_token = ctx.token_at_offset().find(|t| t.kind() == IDENT && t.text() != "derive")?; 50 let trait_token = args.syntax().token_at_offset(ctx.offset()).find(|t| t.kind() == IDENT)?;
59 let trait_path = make::path_unqualified(make::path_segment(make::name_ref(trait_token.text()))); 51 let trait_name = trait_token.text();
60 52
61 let adt = attr.syntax().parent().and_then(ast::Adt::cast)?; 53 let adt = attr.syntax().parent().and_then(ast::Adt::cast)?;
62 let annotated_name = adt.name()?;
63 let insert_pos = adt.syntax().text_range().end();
64 54
65 let current_module = ctx.sema.scope(annotated_name.syntax()).module()?; 55 let current_module = ctx.sema.scope(adt.syntax()).module()?;
66 let current_crate = current_module.krate(); 56 let current_crate = current_module.krate();
67 57
68 let found_traits = items_locator::items_with_name( 58 let found_traits = items_locator::items_with_name(
69 &ctx.sema, 59 &ctx.sema,
70 current_crate, 60 current_crate,
71 NameToImport::Exact(trait_token.text().to_string()), 61 NameToImport::Exact(trait_name.to_string()),
72 items_locator::AssocItemSearch::Exclude, 62 items_locator::AssocItemSearch::Exclude,
73 Some(items_locator::DEFAULT_QUERY_SEARCH_LIMIT), 63 Some(items_locator::DEFAULT_QUERY_SEARCH_LIMIT),
74 ) 64 )
@@ -86,10 +76,11 @@ pub(crate) fn replace_derive_with_manual_impl(
86 76
87 let mut no_traits_found = true; 77 let mut no_traits_found = true;
88 for (trait_path, trait_) in found_traits.inspect(|_| no_traits_found = false) { 78 for (trait_path, trait_) in found_traits.inspect(|_| no_traits_found = false) {
89 add_assist(acc, ctx, &attr, &trait_path, Some(trait_), &adt, &annotated_name, insert_pos)?; 79 add_assist(acc, ctx, &attr, &args, &trait_path, Some(trait_), &adt)?;
90 } 80 }
91 if no_traits_found { 81 if no_traits_found {
92 add_assist(acc, ctx, &attr, &trait_path, None, &adt, &annotated_name, insert_pos)?; 82 let trait_path = make::path_unqualified(make::path_segment(make::name_ref(trait_name)));
83 add_assist(acc, ctx, &attr, &args, &trait_path, None, &adt)?;
93 } 84 }
94 Some(()) 85 Some(())
95} 86}
@@ -98,15 +89,14 @@ fn add_assist(
98 acc: &mut Assists, 89 acc: &mut Assists,
99 ctx: &AssistContext, 90 ctx: &AssistContext,
100 attr: &ast::Attr, 91 attr: &ast::Attr,
92 input: &ast::TokenTree,
101 trait_path: &ast::Path, 93 trait_path: &ast::Path,
102 trait_: Option<hir::Trait>, 94 trait_: Option<hir::Trait>,
103 adt: &ast::Adt, 95 adt: &ast::Adt,
104 annotated_name: &ast::Name,
105 insert_pos: TextSize,
106) -> Option<()> { 96) -> Option<()> {
107 let target = attr.syntax().text_range(); 97 let target = attr.syntax().text_range();
108 let input = attr.token_tree()?; 98 let annotated_name = adt.name()?;
109 let label = format!("Convert to manual `impl {} for {}`", trait_path, annotated_name); 99 let label = format!("Convert to manual `impl {} for {}`", trait_path, annotated_name);
110 let trait_name = trait_path.segment().and_then(|seg| seg.name_ref())?; 100 let trait_name = trait_path.segment().and_then(|seg| seg.name_ref())?;
111 101
112 acc.add( 102 acc.add(
@@ -114,8 +104,9 @@ fn add_assist(
114 label, 104 label,
115 target, 105 target,
116 |builder| { 106 |builder| {
107 let insert_pos = adt.syntax().text_range().end();
117 let impl_def_with_items = 108 let impl_def_with_items =
118 impl_def_from_trait(&ctx.sema, annotated_name, trait_, trait_path); 109 impl_def_from_trait(&ctx.sema, &annotated_name, trait_, trait_path);
119 update_attribute(builder, &input, &trait_name, &attr); 110 update_attribute(builder, &input, &trait_name, &attr);
120 let trait_path = format!("{}", trait_path); 111 let trait_path = format!("{}", trait_path);
121 match (ctx.config.snippet_cap, impl_def_with_items) { 112 match (ctx.config.snippet_cap, impl_def_with_items) {
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs
index adc059817..ecab89b2a 100644
--- a/crates/rust-analyzer/src/semantic_tokens.rs
+++ b/crates/rust-analyzer/src/semantic_tokens.rs
@@ -49,7 +49,7 @@ define_semantic_token_types![
49 (CHAR_LITERAL, "characterLiteral"), 49 (CHAR_LITERAL, "characterLiteral"),
50 (COLON, "colon"), 50 (COLON, "colon"),
51 (COMMA, "comma"), 51 (COMMA, "comma"),
52 (COMPARISION, "comparision"), 52 (COMPARISON, "comparison"),
53 (CONST_PARAMETER, "constParameter"), 53 (CONST_PARAMETER, "constParameter"),
54 (DOT, "dot"), 54 (DOT, "dot"),
55 (ESCAPE_SEQUENCE, "escapeSequence"), 55 (ESCAPE_SEQUENCE, "escapeSequence"),
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index fe4d0733d..c2361b32e 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -469,7 +469,7 @@ fn semantic_token_type_and_modifiers(
469 HlOperator::Bitwise => semantic_tokens::BITWISE, 469 HlOperator::Bitwise => semantic_tokens::BITWISE,
470 HlOperator::Arithmetic => semantic_tokens::ARITHMETIC, 470 HlOperator::Arithmetic => semantic_tokens::ARITHMETIC,
471 HlOperator::Logical => semantic_tokens::LOGICAL, 471 HlOperator::Logical => semantic_tokens::LOGICAL,
472 HlOperator::Comparision => semantic_tokens::COMPARISION, 472 HlOperator::Comparison => semantic_tokens::COMPARISON,
473 HlOperator::Other => semantic_tokens::OPERATOR, 473 HlOperator::Other => semantic_tokens::OPERATOR,
474 }, 474 },
475 HlTag::StringLiteral => lsp_types::SemanticTokenType::STRING, 475 HlTag::StringLiteral => lsp_types::SemanticTokenType::STRING,
diff --git a/crates/rust-analyzer/tests/rust-analyzer/main.rs b/crates/rust-analyzer/tests/rust-analyzer/main.rs
index 52a2674d5..9e89209ea 100644
--- a/crates/rust-analyzer/tests/rust-analyzer/main.rs
+++ b/crates/rust-analyzer/tests/rust-analyzer/main.rs
@@ -525,7 +525,7 @@ version = \"0.0.0\"
525#[test] 525#[test]
526fn out_dirs_check() { 526fn out_dirs_check() {
527 if skip_slow_tests() { 527 if skip_slow_tests() {
528 // return; 528 return;
529 } 529 }
530 530
531 let server = Project::with_fixture( 531 let server = Project::with_fixture(
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index ae98dbd26..171099661 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -125,6 +125,18 @@ pub enum AttrKind {
125 Outer, 125 Outer,
126} 126}
127 127
128impl AttrKind {
129 /// Returns `true` if the attr_kind is [`Inner`].
130 pub fn is_inner(&self) -> bool {
131 matches!(self, Self::Inner)
132 }
133
134 /// Returns `true` if the attr_kind is [`Outer`].
135 pub fn is_outer(&self) -> bool {
136 matches!(self, Self::Outer)
137 }
138}
139
128impl ast::Attr { 140impl ast::Attr {
129 pub fn as_simple_atom(&self) -> Option<SmolStr> { 141 pub fn as_simple_atom(&self) -> Option<SmolStr> {
130 if self.eq_token().is_some() || self.token_tree().is_some() { 142 if self.eq_token().is_some() || self.token_tree().is_some() {
diff --git a/crates/syntax/src/validation/block.rs b/crates/syntax/src/validation/block.rs
index ad9901468..40170014f 100644
--- a/crates/syntax/src/validation/block.rs
+++ b/crates/syntax/src/validation/block.rs
@@ -13,7 +13,7 @@ pub(crate) fn validate_block_expr(block: ast::BlockExpr, errors: &mut Vec<Syntax
13 _ => {} 13 _ => {}
14 } 14 }
15 } 15 }
16 errors.extend(block.attrs().map(|attr| { 16 errors.extend(block.attrs().filter(|attr| attr.kind().is_inner()).map(|attr| {
17 SyntaxError::new( 17 SyntaxError::new(
18 "A block in this position cannot accept inner attributes", 18 "A block in this position cannot accept inner attributes",
19 attr.syntax().text_range(), 19 attr.syntax().text_range(),
diff --git a/crates/syntax/test_data/parser/ok/0045_block_attrs.rast b/crates/syntax/test_data/parser/ok/0045_block_attrs.rast
new file mode 100644
index 000000000..50ab52d32
--- /dev/null
+++ b/crates/syntax/test_data/parser/ok/0045_block_attrs.rast
@@ -0,0 +1,218 @@
1[email protected]
2 [email protected]
3 [email protected] "fn"
4 [email protected] " "
5 [email protected]
6 [email protected] "inner"
7 [email protected]
8 [email protected] "("
9 [email protected] ")"
10 [email protected] " "
11 [email protected]
12 [email protected] "{"
13 [email protected] "\n "
14 [email protected]
15 [email protected] "#"
16 [email protected] "!"
17 [email protected] "["
18 [email protected]
19 [email protected]
20 [email protected]
21 [email protected] "doc"
22 [email protected]
23 [email protected] "("
24 [email protected] "\"Inner attributes all ..."
25 [email protected] ")"
26 [email protected] "]"
27 [email protected] "\n "
28 [email protected] "//! As are ModuleDoc ..."
29 [email protected] "\n "
30 [email protected]
31 [email protected]
32 [email protected] "{"
33 [email protected] "\n "
34 [email protected]
35 [email protected] "#"
36 [email protected] "!"
37 [email protected] "["
38 [email protected]
39 [email protected]
40 [email protected]
41 [email protected] "doc"
42 [email protected]
43 [email protected] "("
44 [email protected] "\"Inner attributes are ..."
45 [email protected] ")"
46 [email protected] "]"
47 [email protected] "\n "
48 [email protected]
49 [email protected] "#"
50 [email protected] "!"
51 [email protected] "["
52 [email protected]
53 [email protected]
54 [email protected]
55 [email protected] "doc"
56 [email protected]
57 [email protected] "("
58 [email protected] "\"Being validated is n ..."
59 [email protected] ")"
60 [email protected] "]"
61 [email protected] "\n "
62 [email protected] "//! As are ModuleDoc ..."
63 [email protected] "\n "
64 [email protected] "}"
65 [email protected] ";"
66 [email protected] "\n "
67 [email protected]
68 [email protected] "{"
69 [email protected] "\n "
70 [email protected]
71 [email protected] "#"
72 [email protected] "!"
73 [email protected] "["
74 [email protected]
75 [email protected]
76 [email protected]
77 [email protected] "doc"
78 [email protected]
79 [email protected] "("
80 [email protected] "\"Inner attributes are ..."
81 [email protected] ")"
82 [email protected] "]"
83 [email protected] "\n "
84 [email protected] "//! As are ModuleDoc ..."
85 [email protected] "\n "
86 [email protected] "}"
87 [email protected] "\n"
88 [email protected] "}"
89 [email protected] "\n\n"
90 [email protected]
91 [email protected] "fn"
92 [email protected] " "
93 [email protected]
94 [email protected] "outer"
95 [email protected]
96 [email protected] "("
97 [email protected] ")"
98 [email protected] " "
99 [email protected]
100 [email protected] "{"
101 [email protected] "\n "
102 [email protected]
103 [email protected] "let"
104 [email protected] " "
105 [email protected]
106 [email protected] "_"
107 [email protected] " "
108 [email protected] "="
109 [email protected] " "
110 [email protected]
111 [email protected]
112 [email protected] "#"
113 [email protected] "["
114 [email protected]
115 [email protected]
116 [email protected]
117 [email protected] "doc"
118 [email protected]
119 [email protected] "("
120 [email protected] "\"Outer attributes are ..."
121 [email protected] ")"
122 [email protected] "]"
123 [email protected] " "
124 [email protected] "{"
125 [email protected] "}"
126 [email protected] ";"
127 [email protected] "\n"
128 [email protected] "}"
129 [email protected] "\n\n"
130 [email protected] "// https://github.com ..."
131 [email protected] "\n"
132 [email protected]
133 [email protected] "impl"
134 [email protected] " "
135 [email protected]
136 [email protected]
137 [email protected]
138 [email protected]
139 [email protected] "Whatever"
140 [email protected] " "
141 [email protected]
142 [email protected] "{"
143 [email protected] "\n "
144 [email protected]
145 [email protected] "fn"
146 [email protected] " "
147 [email protected]
148 [email protected] "salsa_event"
149 [email protected]
150 [email protected] "("
151 [email protected]
152 [email protected] "&"
153 [email protected]
154 [email protected] "self"
155 [email protected] ","
156 [email protected] " "
157 [email protected]
158 [email protected]
159 [email protected]
160 [email protected] "event_fn"
161 [email protected] ":"
162 [email protected] " "
163 [email protected]
164 [email protected] "impl"
165 [email protected] " "
166 [email protected]
167 [email protected]
168 [email protected]
169 [email protected]
170 [email protected]
171 [email protected]
172 [email protected] "Fn"
173 [email protected]
174 [email protected] "("
175 [email protected] ")"
176 [email protected] " "
177 [email protected]
178 [email protected] "->"
179 [email protected] " "
180 [email protected]
181 [email protected]
182 [email protected]
183 [email protected]
184 [email protected] "Event"
185 [email protected]
186 [email protected] "<"
187 [email protected]
188 [email protected]
189 [email protected]
190 [email protected]
191 [email protected]
192 [email protected] "Self"
193 [email protected] ">"
194 [email protected] ")"
195 [email protected] " "
196 [email protected]
197 [email protected] "{"
198 [email protected] "\n "
199 [email protected]
200 [email protected] "#"
201 [email protected] "!"
202 [email protected] "["
203 [email protected]
204 [email protected]
205 [email protected]
206 [email protected] "allow"
207 [email protected]
208 [email protected] "("
209 [email protected] "unused_variables"
210 [email protected] ")"
211 [email protected] "]"
212 [email protected] " "
213 [email protected] "// this is `inner_at ..."
214 [email protected] "\n "
215 [email protected] "}"
216 [email protected] "\n"
217 [email protected] "}"
218 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rs b/crates/syntax/test_data/parser/ok/0045_block_attrs.rs
index 88df8138e..ed4593759 100644
--- a/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rs
+++ b/crates/syntax/test_data/parser/ok/0045_block_attrs.rs
@@ -1,4 +1,4 @@
1fn block() { 1fn inner() {
2 #![doc("Inner attributes allowed here")] 2 #![doc("Inner attributes allowed here")]
3 //! As are ModuleDoc style comments 3 //! As are ModuleDoc style comments
4 { 4 {
@@ -12,6 +12,10 @@ fn block() {
12 } 12 }
13} 13}
14 14
15fn outer() {
16 let _ = #[doc("Outer attributes are always allowed")] {};
17}
18
15// https://github.com/rust-analyzer/rust-analyzer/issues/689 19// https://github.com/rust-analyzer/rust-analyzer/issues/689
16impl Whatever { 20impl Whatever {
17 fn salsa_event(&self, event_fn: impl Fn() -> Event<Self>) { 21 fn salsa_event(&self, event_fn: impl Fn() -> Event<Self>) {
diff --git a/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rast b/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rast
deleted file mode 100644
index 6afed5f05..000000000
--- a/crates/syntax/test_data/parser/ok/0045_block_inner_attrs.rast
+++ /dev/null
@@ -1,178 +0,0 @@
1[email protected]
2 [email protected]
3 [email protected] "fn"
4 [email protected] " "
5 [email protected]
6 [email protected] "block"
7 [email protected]
8 [email protected] "("
9 [email protected] ")"
10 [email protected] " "
11 [email protected]
12 [email protected] "{"
13 [email protected] "\n "
14 [email protected]
15 [email protected] "#"
16 [email protected] "!"
17 [email protected] "["
18 [email protected]
19 [email protected]
20 [email protected]
21 [email protected] "doc"
22 [email protected]
23 [email protected] "("
24 [email protected] "\"Inner attributes all ..."
25 [email protected] ")"
26 [email protected] "]"
27 [email protected] "\n "
28 [email protected] "//! As are ModuleDoc ..."
29 [email protected] "\n "
30 [email protected]
31 [email protected]
32 [email protected] "{"
33 [email protected] "\n "
34 [email protected]
35 [email protected] "#"
36 [email protected] "!"
37 [email protected] "["
38 [email protected]
39 [email protected]
40 [email protected]
41 [email protected] "doc"
42 [email protected]
43 [email protected] "("
44 [email protected] "\"Inner attributes are ..."
45 [email protected] ")"
46 [email protected] "]"
47 [email protected] "\n "
48 [email protected]
49 [email protected] "#"
50 [email protected] "!"
51 [email protected] "["
52 [email protected]
53 [email protected]
54 [email protected]
55 [email protected] "doc"
56 [email protected]
57 [email protected] "("
58 [email protected] "\"Being validated is n ..."
59 [email protected] ")"
60 [email protected] "]"
61 [email protected] "\n "
62 [email protected] "//! As are ModuleDoc ..."
63 [email protected] "\n "
64 [email protected] "}"
65 [email protected] ";"
66 [email protected] "\n "
67 [email protected]
68 [email protected] "{"
69 [email protected] "\n "
70 [email protected]
71 [email protected] "#"
72 [email protected] "!"
73 [email protected] "["
74 [email protected]
75 [email protected]
76 [email protected]
77 [email protected] "doc"
78 [email protected]
79 [email protected] "("
80 [email protected] "\"Inner attributes are ..."
81 [email protected] ")"
82 [email protected] "]"
83 [email protected] "\n "
84 [email protected] "//! As are ModuleDoc ..."
85 [email protected] "\n "
86 [email protected] "}"
87 [email protected] "\n"
88 [email protected] "}"
89 [email protected] "\n\n"
90 [email protected] "// https://github.com ..."
91 [email protected] "\n"
92 [email protected]
93 [email protected] "impl"
94 [email protected] " "
95 [email protected]
96 [email protected]
97 [email protected]
98 [email protected]
99 [email protected] "Whatever"
100 [email protected] " "
101 [email protected]
102 [email protected] "{"
103 [email protected] "\n "
104 [email protected]
105 [email protected] "fn"
106 [email protected] " "
107 [email protected]
108 [email protected] "salsa_event"
109 [email protected]
110 [email protected] "("
111 [email protected]
112 [email protected] "&"
113 [email protected]
114 [email protected] "self"
115 [email protected] ","
116 [email protected] " "
117 [email protected]
118 [email protected]
119 [email protected]
120 [email protected] "event_fn"
121 [email protected] ":"
122 [email protected] " "
123 [email protected]
124 [email protected] "impl"
125 [email protected] " "
126 [email protected]
127 [email protected]
128 [email protected]
129 [email protected]
130 [email protected]
131 [email protected]
132 [email protected] "Fn"
133 [email protected]
134 [email protected] "("
135 [email protected] ")"
136 [email protected] " "
137 [email protected]
138 [email protected] "->"
139 [email protected] " "
140 [email protected]
141 [email protected]
142 [email protected]
143 [email protected]
144 [email protected] "Event"
145 [email protected]
146 [email protected] "<"
147 [email protected]
148 [email protected]
149 [email protected]
150 [email protected]
151 [email protected]
152 [email protected] "Self"
153 [email protected] ">"
154 [email protected] ")"
155 [email protected] " "
156 [email protected]
157 [email protected] "{"
158 [email protected] "\n "
159 [email protected]
160 [email protected] "#"
161 [email protected] "!"
162 [email protected] "["
163 [email protected]
164 [email protected]
165 [email protected]
166 [email protected] "allow"
167 [email protected]
168 [email protected] "("
169 [email protected] "unused_variables"
170 [email protected] ")"
171 [email protected] "]"
172 [email protected] " "
173 [email protected] "// this is `inner_at ..."
174 [email protected] "\n "
175 [email protected] "}"
176 [email protected] "\n"
177 [email protected] "}"
178 [email protected] "\n"