aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/release.yaml114
-rw-r--r--Cargo.lock8
-rw-r--r--crates/assists/src/assist_context.rs13
-rw-r--r--crates/assists/src/handlers/extract_module_to_file.rs133
-rw-r--r--crates/assists/src/handlers/invert_if.rs9
-rw-r--r--crates/assists/src/handlers/remove_unused_param.rs81
-rw-r--r--crates/assists/src/lib.rs2
-rw-r--r--crates/assists/src/tests.rs28
-rw-r--r--crates/assists/src/tests/generated.rs15
-rw-r--r--crates/assists/src/utils.rs8
-rw-r--r--crates/hir/src/code_model.rs1
-rw-r--r--crates/hir_def/src/generics.rs37
-rw-r--r--crates/hir_ty/src/lower.rs18
-rw-r--r--crates/hir_ty/src/utils.rs9
-rw-r--r--crates/ide/src/diagnostics.rs1
-rw-r--r--crates/ide/src/diagnostics/fixes.rs1
-rw-r--r--crates/ide/src/goto_definition.rs28
-rw-r--r--crates/ide/src/references.rs48
-rw-r--r--crates/ide_db/src/source_change.rs2
-rw-r--r--crates/mbe/src/tests.rs12
-rw-r--r--crates/parser/src/grammar.rs2
-rw-r--r--crates/parser/src/grammar/expressions/atom.rs8
-rw-r--r--crates/parser/src/grammar/params.rs17
-rw-r--r--crates/parser/src/grammar/type_params.rs2
-rw-r--r--crates/parser/src/grammar/types.rs26
-rw-r--r--crates/parser/src/lib.rs2
-rw-r--r--crates/rust-analyzer/src/config.rs34
-rw-r--r--crates/rust-analyzer/src/diagnostics/to_proto.rs4
-rw-r--r--crates/rust-analyzer/src/to_proto.rs37
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast20
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rast43
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rs1
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0154_tuple_attrs.rast50
-rw-r--r--crates/syntax/test_data/parser/inline/ok/0154_tuple_attrs.rs1
-rw-r--r--crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast222
-rw-r--r--crates/syntax/test_data/parser/ok/0063_variadic_fun.rast28
-rw-r--r--docs/user/generated_config.adoc26
-rw-r--r--docs/user/manual.adoc42
-rw-r--r--editors/code/.vscodeignore1
-rw-r--r--editors/code/package.json55
-rw-r--r--editors/code/rust.tmGrammar.json1140
-rw-r--r--editors/code/src/commands.ts2
-rw-r--r--editors/code/src/main.ts50
-rw-r--r--xtask/src/dist.rs72
44 files changed, 977 insertions, 1476 deletions
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 919d58925..09752b817 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -15,12 +15,9 @@ env:
15 RUSTUP_MAX_RETRIES: 10 15 RUSTUP_MAX_RETRIES: 10
16 16
17jobs: 17jobs:
18 dist: 18 dist-windows:
19 name: dist 19 name: dist (Windows)
20 runs-on: ${{ matrix.os }} 20 runs-on: windows-latest
21 strategy:
22 matrix:
23 os: [ubuntu-16.04, windows-latest, macos-latest]
24 21
25 steps: 22 steps:
26 - name: Checkout repository 23 - name: Checkout repository
@@ -30,8 +27,7 @@ jobs:
30 # which takes a long time. The fastest way to do this is to rename the 27 # which takes a long time. The fastest way to do this is to rename the
31 # existing folder, as deleting it takes about as much time as not doing 28 # existing folder, as deleting it takes about as much time as not doing
32 # anything and just updating rust-docs. 29 # anything and just updating rust-docs.
33 - name: Rename existing rust toolchain (Windows) 30 - name: Rename existing rust toolchain
34 if: matrix.os == 'windows-latest'
35 run: Rename-Item C:\Users\runneradmin\.rustup\toolchains\stable-x86_64-pc-windows-msvc C:\Users\runneradmin\.rustup\toolchains\stable-x86_64-pc-windows-msvc.old 31 run: Rename-Item C:\Users\runneradmin\.rustup\toolchains\stable-x86_64-pc-windows-msvc C:\Users\runneradmin\.rustup\toolchains\stable-x86_64-pc-windows-msvc.old
36 32
37 - name: Install Rust toolchain 33 - name: Install Rust toolchain
@@ -41,38 +37,116 @@ jobs:
41 profile: minimal 37 profile: minimal
42 override: true 38 override: true
43 39
40 - name: Dist
41 run: cargo xtask dist
42 env:
43 RA_TARGET: x86_64-pc-windows-msvc
44
45 - name: Upload artifacts
46 uses: actions/upload-artifact@v1
47 with:
48 name: dist-windows-latest
49 path: ./dist
50
51 dist-ubuntu:
52 name: dist (Ubuntu 16.04)
53 runs-on: ubuntu-16.04
54
55 steps:
56 - name: Checkout repository
57 uses: actions/checkout@v2
58
59 - name: Install Rust toolchain
60 uses: actions-rs/toolchain@v1
61 with:
62 toolchain: stable
63 profile: minimal
64 override: true
65
44 - name: Install Nodejs 66 - name: Install Nodejs
45 if: matrix.os == 'ubuntu-16.04'
46 uses: actions/setup-node@v1 67 uses: actions/setup-node@v1
47 with: 68 with:
48 node-version: 12.x 69 node-version: 12.x
49 70
50 - name: Dist 71 - name: Dist
51 if: matrix.os == 'ubuntu-16.04' && github.ref == 'refs/heads/release' 72 if: github.ref == 'refs/heads/release'
52 run: cargo xtask dist --client 0.2.$GITHUB_RUN_NUMBER 73 run: cargo xtask dist --client 0.2.$GITHUB_RUN_NUMBER
74 env:
75 RA_TARGET: x86_64-unknown-linux-gnu
53 76
54 - name: Dist 77 - name: Dist
55 if: matrix.os == 'ubuntu-16.04' && github.ref != 'refs/heads/release' 78 if: github.ref != 'refs/heads/release'
56 run: cargo xtask dist --nightly --client 0.3.$GITHUB_RUN_NUMBER-nightly 79 run: cargo xtask dist --nightly --client 0.3.$GITHUB_RUN_NUMBER-nightly
80 env:
81 RA_TARGET: x86_64-unknown-linux-gnu
82
83 - name: Nightly analysis-stats check
84 if: github.ref != 'refs/heads/release'
85 run: ./dist/rust-analyzer-x86_64-unknown-linux-gnu analysis-stats .
86
87 - name: Upload artifacts
88 uses: actions/upload-artifact@v1
89 with:
90 name: dist-ubuntu-16.04
91 path: ./dist
92
93 dist-macos-latest:
94 name: dist (MacOS latest)
95 runs-on: macos-latest
96
97 steps:
98 - name: Checkout repository
99 uses: actions/checkout@v2
100
101 - name: Install Rust toolchain
102 uses: actions-rs/toolchain@v1
103 with:
104 toolchain: stable
105 profile: minimal
106 override: true
57 107
58 - name: Dist 108 - name: Dist
59 if: matrix.os != 'ubuntu-16.04'
60 run: cargo xtask dist 109 run: cargo xtask dist
110 env:
111 RA_TARGET: x86_64-apple-darwin
61 112
62 - name: Nightly analysis-stats check 113 - name: Upload artifacts
63 if: matrix.os == 'ubuntu-16.04' && github.ref != 'refs/heads/release' 114 uses: actions/upload-artifact@v1
64 run: ./dist/rust-analyzer-linux analysis-stats . 115 with:
116 name: dist-macos-latest
117 path: ./dist
118
119 dist-macos-11:
120 name: dist (MacOS 11.0)
121 runs-on: macos-11.0
122
123 steps:
124 - name: Checkout repository
125 uses: actions/checkout@v2
126
127 - name: Install Rust toolchain (beta)
128 uses: actions-rs/toolchain@v1
129 with:
130 toolchain: beta
131 target: aarch64-apple-darwin
132 profile: minimal
133 override: true
134
135 - name: Dist
136 run: cargo xtask dist
137 env:
138 RA_TARGET: aarch64-apple-darwin
65 139
66 - name: Upload artifacts 140 - name: Upload artifacts
67 uses: actions/upload-artifact@v1 141 uses: actions/upload-artifact@v1
68 with: 142 with:
69 name: dist-${{ matrix.os }} 143 name: dist-macos-11.0
70 path: ./dist 144 path: ./dist
71 145
72 publish: 146 publish:
73 name: publish 147 name: publish
74 runs-on: ubuntu-16.04 148 runs-on: ubuntu-16.04
75 needs: ['dist'] 149 needs: ['dist-windows', 'dist-ubuntu', 'dist-macos-latest', 'dist-macos-11']
76 steps: 150 steps:
77 - name: Install Nodejs 151 - name: Install Nodejs
78 uses: actions/setup-node@v1 152 uses: actions/setup-node@v1
@@ -93,6 +167,10 @@ jobs:
93 167
94 - uses: actions/download-artifact@v1 168 - uses: actions/download-artifact@v1
95 with: 169 with:
170 name: dist-macos-11.0
171 path: dist
172 - uses: actions/download-artifact@v1
173 with:
96 name: dist-macos-latest 174 name: dist-macos-latest
97 path: dist 175 path: dist
98 - uses: actions/download-artifact@v1 176 - uses: actions/download-artifact@v1
@@ -103,7 +181,7 @@ jobs:
103 with: 181 with:
104 name: dist-windows-latest 182 name: dist-windows-latest
105 path: dist 183 path: dist
106 - run: ls -all ./dist 184 - run: ls -al ./dist
107 185
108 - name: Publish Release 186 - name: Publish Release
109 uses: ./.github/actions/github-release 187 uses: ./.github/actions/github-release
diff --git a/Cargo.lock b/Cargo.lock
index 1051c4ec6..fbb79e01f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1251,9 +1251,9 @@ dependencies = [
1251 1251
1252[[package]] 1252[[package]]
1253name = "quote" 1253name = "quote"
1254version = "1.0.7" 1254version = "1.0.8"
1255source = "registry+https://github.com/rust-lang/crates.io-index" 1255source = "registry+https://github.com/rust-lang/crates.io-index"
1256checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" 1256checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
1257dependencies = [ 1257dependencies = [
1258 "proc-macro2", 1258 "proc-macro2",
1259] 1259]
@@ -1588,9 +1588,9 @@ version = "0.0.0"
1588 1588
1589[[package]] 1589[[package]]
1590name = "syn" 1590name = "syn"
1591version = "1.0.54" 1591version = "1.0.55"
1592source = "registry+https://github.com/rust-lang/crates.io-index" 1592source = "registry+https://github.com/rust-lang/crates.io-index"
1593checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44" 1593checksum = "a571a711dddd09019ccc628e1b17fe87c59b09d513c06c026877aa708334f37a"
1594dependencies = [ 1594dependencies = [
1595 "proc-macro2", 1595 "proc-macro2",
1596 "quote", 1596 "quote",
diff --git a/crates/assists/src/assist_context.rs b/crates/assists/src/assist_context.rs
index 69499ea32..80cf9aba1 100644
--- a/crates/assists/src/assist_context.rs
+++ b/crates/assists/src/assist_context.rs
@@ -4,10 +4,10 @@ use std::mem;
4 4
5use algo::find_covering_element; 5use algo::find_covering_element;
6use hir::Semantics; 6use hir::Semantics;
7use ide_db::base_db::{FileId, FileRange}; 7use ide_db::base_db::{AnchoredPathBuf, FileId, FileRange};
8use ide_db::{ 8use ide_db::{
9 label::Label, 9 label::Label,
10 source_change::{SourceChange, SourceFileEdit}, 10 source_change::{FileSystemEdit, SourceChange, SourceFileEdit},
11 RootDatabase, 11 RootDatabase,
12}; 12};
13use syntax::{ 13use syntax::{
@@ -209,6 +209,7 @@ pub(crate) struct AssistBuilder {
209 file_id: FileId, 209 file_id: FileId,
210 is_snippet: bool, 210 is_snippet: bool,
211 source_file_edits: Vec<SourceFileEdit>, 211 source_file_edits: Vec<SourceFileEdit>,
212 file_system_edits: Vec<FileSystemEdit>,
212} 213}
213 214
214impl AssistBuilder { 215impl AssistBuilder {
@@ -218,6 +219,7 @@ impl AssistBuilder {
218 file_id, 219 file_id,
219 is_snippet: false, 220 is_snippet: false,
220 source_file_edits: Vec::default(), 221 source_file_edits: Vec::default(),
222 file_system_edits: Vec::default(),
221 } 223 }
222 } 224 }
223 225
@@ -282,12 +284,17 @@ impl AssistBuilder {
282 algo::diff(&node, &new).into_text_edit(&mut self.edit); 284 algo::diff(&node, &new).into_text_edit(&mut self.edit);
283 } 285 }
284 } 286 }
287 pub(crate) fn create_file(&mut self, dst: AnchoredPathBuf, content: impl Into<String>) {
288 let file_system_edit =
289 FileSystemEdit::CreateFile { dst: dst.clone(), initial_contents: content.into() };
290 self.file_system_edits.push(file_system_edit);
291 }
285 292
286 fn finish(mut self) -> SourceChange { 293 fn finish(mut self) -> SourceChange {
287 self.commit(); 294 self.commit();
288 SourceChange { 295 SourceChange {
289 source_file_edits: mem::take(&mut self.source_file_edits), 296 source_file_edits: mem::take(&mut self.source_file_edits),
290 file_system_edits: Default::default(), 297 file_system_edits: mem::take(&mut self.file_system_edits),
291 is_snippet: self.is_snippet, 298 is_snippet: self.is_snippet,
292 } 299 }
293 } 300 }
diff --git a/crates/assists/src/handlers/extract_module_to_file.rs b/crates/assists/src/handlers/extract_module_to_file.rs
new file mode 100644
index 000000000..3e67fdca2
--- /dev/null
+++ b/crates/assists/src/handlers/extract_module_to_file.rs
@@ -0,0 +1,133 @@
1use ast::edit::IndentLevel;
2use ide_db::base_db::AnchoredPathBuf;
3use syntax::{
4 ast::{self, edit::AstNodeEdit, NameOwner},
5 AstNode,
6};
7
8use crate::{AssistContext, AssistId, AssistKind, Assists};
9
10// Assist: extract_module_to_file
11//
12// This assist extract module to file.
13//
14// ```
15// mod foo {<|>
16// fn t() {}
17// }
18// ```
19// ->
20// ```
21// mod foo;
22// ```
23pub(crate) fn extract_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
24 let module_ast = ctx.find_node_at_offset::<ast::Module>()?;
25 let module_name = module_ast.name()?;
26
27 let module_def = ctx.sema.to_def(&module_ast)?;
28 let parent_module = module_def.parent(ctx.db())?;
29
30 let module_items = module_ast.item_list()?;
31 let target = module_ast.syntax().text_range();
32 let anchor_file_id = ctx.frange.file_id;
33
34 acc.add(
35 AssistId("extract_module_to_file", AssistKind::RefactorExtract),
36 "Extract module to file",
37 target,
38 |builder| {
39 let path = {
40 let dir = match parent_module.name(ctx.db()) {
41 Some(name) if !parent_module.is_mod_rs(ctx.db()) => format!("{}/", name),
42 _ => String::new(),
43 };
44 format!("./{}{}.rs", dir, module_name)
45 };
46 let contents = {
47 let items = module_items.dedent(IndentLevel(1)).to_string();
48 let mut items =
49 items.trim_start_matches('{').trim_end_matches('}').trim().to_string();
50 if !items.is_empty() {
51 items.push('\n');
52 }
53 items
54 };
55
56 builder.replace(target, format!("mod {};", module_name));
57
58 let dst = AnchoredPathBuf { anchor: anchor_file_id, path };
59 builder.create_file(dst, contents);
60 },
61 )
62}
63
64#[cfg(test)]
65mod tests {
66 use crate::tests::check_assist;
67
68 use super::*;
69
70 #[test]
71 fn extract_from_root() {
72 check_assist(
73 extract_module_to_file,
74 r#"
75mod tests {<|>
76 #[test] fn t() {}
77}
78"#,
79 r#"
80//- /main.rs
81mod tests;
82//- /tests.rs
83#[test] fn t() {}
84"#,
85 );
86 }
87
88 #[test]
89 fn extract_from_submodule() {
90 check_assist(
91 extract_module_to_file,
92 r#"
93//- /main.rs
94mod submodule;
95//- /submodule.rs
96mod inner<|> {
97 fn f() {}
98}
99fn g() {}
100"#,
101 r#"
102//- /submodule.rs
103mod inner;
104fn g() {}
105//- /submodule/inner.rs
106fn f() {}
107"#,
108 );
109 }
110
111 #[test]
112 fn extract_from_mod_rs() {
113 check_assist(
114 extract_module_to_file,
115 r#"
116//- /main.rs
117mod submodule;
118//- /submodule/mod.rs
119mod inner<|> {
120 fn f() {}
121}
122fn g() {}
123"#,
124 r#"
125//- /submodule/mod.rs
126mod inner;
127fn g() {}
128//- /submodule/inner.rs
129fn f() {}
130"#,
131 );
132 }
133}
diff --git a/crates/assists/src/handlers/invert_if.rs b/crates/assists/src/handlers/invert_if.rs
index 91e2f5c8c..f9c33b3f7 100644
--- a/crates/assists/src/handlers/invert_if.rs
+++ b/crates/assists/src/handlers/invert_if.rs
@@ -78,6 +78,15 @@ mod tests {
78 } 78 }
79 79
80 #[test] 80 #[test]
81 fn invert_if_remove_not_parentheses() {
82 check_assist(
83 invert_if,
84 "fn f() { i<|>f !(x == 3 || x == 4 || x == 5) { 3 * 2 } else { 1 } }",
85 "fn f() { if x == 3 || x == 4 || x == 5 { 1 } else { 3 * 2 } }",
86 )
87 }
88
89 #[test]
81 fn invert_if_remove_inequality() { 90 fn invert_if_remove_inequality() {
82 check_assist( 91 check_assist(
83 invert_if, 92 invert_if,
diff --git a/crates/assists/src/handlers/remove_unused_param.rs b/crates/assists/src/handlers/remove_unused_param.rs
index 1ff5e92b0..f72dd49ed 100644
--- a/crates/assists/src/handlers/remove_unused_param.rs
+++ b/crates/assists/src/handlers/remove_unused_param.rs
@@ -2,9 +2,10 @@ use ide_db::{defs::Definition, search::Reference};
2use syntax::{ 2use syntax::{
3 algo::find_node_at_range, 3 algo::find_node_at_range,
4 ast::{self, ArgListOwner}, 4 ast::{self, ArgListOwner},
5 AstNode, SyntaxNode, TextRange, T, 5 AstNode, SyntaxKind, SyntaxNode, TextRange, T,
6}; 6};
7use test_utils::mark; 7use test_utils::mark;
8use SyntaxKind::WHITESPACE;
8 9
9use crate::{ 10use crate::{
10 assist_context::AssistBuilder, utils::next_prev, AssistContext, AssistId, AssistKind, Assists, 11 assist_context::AssistBuilder, utils::next_prev, AssistContext, AssistId, AssistKind, Assists,
@@ -56,7 +57,7 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext) -> Opt
56 "Remove unused parameter", 57 "Remove unused parameter",
57 param.syntax().text_range(), 58 param.syntax().text_range(),
58 |builder| { 59 |builder| {
59 builder.delete(range_with_coma(param.syntax())); 60 builder.delete(range_to_remove(param.syntax()));
60 for usage in fn_def.usages(&ctx.sema).all() { 61 for usage in fn_def.usages(&ctx.sema).all() {
61 process_usage(ctx, builder, usage, param_position); 62 process_usage(ctx, builder, usage, param_position);
62 } 63 }
@@ -80,19 +81,34 @@ fn process_usage(
80 let arg = call_expr.arg_list()?.args().nth(arg_to_remove)?; 81 let arg = call_expr.arg_list()?.args().nth(arg_to_remove)?;
81 82
82 builder.edit_file(usage.file_range.file_id); 83 builder.edit_file(usage.file_range.file_id);
83 builder.delete(range_with_coma(arg.syntax())); 84 builder.delete(range_to_remove(arg.syntax()));
84 85
85 Some(()) 86 Some(())
86} 87}
87 88
88fn range_with_coma(node: &SyntaxNode) -> TextRange { 89fn range_to_remove(node: &SyntaxNode) -> TextRange {
89 let up_to = next_prev().find_map(|dir| { 90 let up_to_comma = next_prev().find_map(|dir| {
90 node.siblings_with_tokens(dir) 91 node.siblings_with_tokens(dir)
91 .filter_map(|it| it.into_token()) 92 .filter_map(|it| it.into_token())
92 .find(|it| it.kind() == T![,]) 93 .find(|it| it.kind() == T![,])
94 .map(|it| (dir, it))
93 }); 95 });
94 let up_to = up_to.map_or(node.text_range(), |it| it.text_range()); 96 if let Some((dir, token)) = up_to_comma {
95 node.text_range().cover(up_to) 97 if node.next_sibling().is_some() {
98 let up_to_space = token
99 .siblings_with_tokens(dir)
100 .skip(1)
101 .take_while(|it| it.kind() == WHITESPACE)
102 .last()
103 .and_then(|it| it.into_token());
104 return node
105 .text_range()
106 .cover(up_to_space.map_or(token.text_range(), |it| it.text_range()));
107 }
108 node.text_range().cover(token.text_range())
109 } else {
110 node.text_range()
111 }
96} 112}
97 113
98#[cfg(test)] 114#[cfg(test)]
@@ -119,6 +135,57 @@ fn b() { foo(9, ) }
119 } 135 }
120 136
121 #[test] 137 #[test]
138 fn remove_unused_first_param() {
139 check_assist(
140 remove_unused_param,
141 r#"
142fn foo(<|>x: i32, y: i32) { y; }
143fn a() { foo(1, 2) }
144fn b() { foo(1, 2,) }
145"#,
146 r#"
147fn foo(y: i32) { y; }
148fn a() { foo(2) }
149fn b() { foo(2,) }
150"#,
151 );
152 }
153
154 #[test]
155 fn remove_unused_single_param() {
156 check_assist(
157 remove_unused_param,
158 r#"
159fn foo(<|>x: i32) { 0; }
160fn a() { foo(1) }
161fn b() { foo(1, ) }
162"#,
163 r#"
164fn foo() { 0; }
165fn a() { foo() }
166fn b() { foo( ) }
167"#,
168 );
169 }
170
171 #[test]
172 fn remove_unused_surrounded_by_parms() {
173 check_assist(
174 remove_unused_param,
175 r#"
176fn foo(x: i32, <|>y: i32, z: i32) { x; }
177fn a() { foo(1, 2, 3) }
178fn b() { foo(1, 2, 3,) }
179"#,
180 r#"
181fn foo(x: i32, z: i32) { x; }
182fn a() { foo(1, 3) }
183fn b() { foo(1, 3,) }
184"#,
185 );
186 }
187
188 #[test]
122 fn remove_unused_qualified_call() { 189 fn remove_unused_qualified_call() {
123 check_assist( 190 check_assist(
124 remove_unused_param, 191 remove_unused_param,
diff --git a/crates/assists/src/lib.rs b/crates/assists/src/lib.rs
index 6e736ccb3..6b89b2d04 100644
--- a/crates/assists/src/lib.rs
+++ b/crates/assists/src/lib.rs
@@ -129,6 +129,7 @@ mod handlers {
129 mod convert_integer_literal; 129 mod convert_integer_literal;
130 mod early_return; 130 mod early_return;
131 mod expand_glob_import; 131 mod expand_glob_import;
132 mod extract_module_to_file;
132 mod extract_struct_from_enum_variant; 133 mod extract_struct_from_enum_variant;
133 mod extract_variable; 134 mod extract_variable;
134 mod fill_match_arms; 135 mod fill_match_arms;
@@ -179,6 +180,7 @@ mod handlers {
179 convert_integer_literal::convert_integer_literal, 180 convert_integer_literal::convert_integer_literal,
180 early_return::convert_to_guarded_return, 181 early_return::convert_to_guarded_return,
181 expand_glob_import::expand_glob_import, 182 expand_glob_import::expand_glob_import,
183 extract_module_to_file::extract_module_to_file,
182 extract_struct_from_enum_variant::extract_struct_from_enum_variant, 184 extract_struct_from_enum_variant::extract_struct_from_enum_variant,
183 extract_variable::extract_variable, 185 extract_variable::extract_variable,
184 fill_match_arms::fill_match_arms, 186 fill_match_arms::fill_match_arms,
diff --git a/crates/assists/src/tests.rs b/crates/assists/src/tests.rs
index 709a34d03..b41f4874a 100644
--- a/crates/assists/src/tests.rs
+++ b/crates/assists/src/tests.rs
@@ -2,6 +2,7 @@ mod generated;
2 2
3use hir::Semantics; 3use hir::Semantics;
4use ide_db::base_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt}; 4use ide_db::base_db::{fixture::WithFixture, FileId, FileRange, SourceDatabaseExt};
5use ide_db::source_change::FileSystemEdit;
5use ide_db::RootDatabase; 6use ide_db::RootDatabase;
6use syntax::TextRange; 7use syntax::TextRange;
7use test_utils::{assert_eq_text, extract_offset, extract_range}; 8use test_utils::{assert_eq_text, extract_offset, extract_range};
@@ -47,7 +48,7 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) {
47 let before = db.file_text(file_id).to_string(); 48 let before = db.file_text(file_id).to_string();
48 let frange = FileRange { file_id, range: selection.into() }; 49 let frange = FileRange { file_id, range: selection.into() };
49 50
50 let mut assist = Assist::resolved(&db, &AssistConfig::default(), frange) 51 let assist = Assist::resolved(&db, &AssistConfig::default(), frange)
51 .into_iter() 52 .into_iter()
52 .find(|assist| assist.assist.id.0 == assist_id) 53 .find(|assist| assist.assist.id.0 == assist_id)
53 .unwrap_or_else(|| { 54 .unwrap_or_else(|| {
@@ -63,9 +64,12 @@ fn check_doc_test(assist_id: &str, before: &str, after: &str) {
63 }); 64 });
64 65
65 let actual = { 66 let actual = {
66 let change = assist.source_change.source_file_edits.pop().unwrap();
67 let mut actual = before; 67 let mut actual = before;
68 change.edit.apply(&mut actual); 68 for source_file_edit in assist.source_change.source_file_edits {
69 if source_file_edit.file_id == file_id {
70 source_file_edit.edit.apply(&mut actual)
71 }
72 }
69 actual 73 actual
70 }; 74 };
71 assert_eq_text!(&after, &actual); 75 assert_eq_text!(&after, &actual);
@@ -99,7 +103,8 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label:
99 (Some(assist), ExpectedResult::After(after)) => { 103 (Some(assist), ExpectedResult::After(after)) => {
100 let mut source_change = assist.source_change; 104 let mut source_change = assist.source_change;
101 assert!(!source_change.source_file_edits.is_empty()); 105 assert!(!source_change.source_file_edits.is_empty());
102 let skip_header = source_change.source_file_edits.len() == 1; 106 let skip_header = source_change.source_file_edits.len() == 1
107 && source_change.file_system_edits.len() == 0;
103 source_change.source_file_edits.sort_by_key(|it| it.file_id); 108 source_change.source_file_edits.sort_by_key(|it| it.file_id);
104 109
105 let mut buf = String::new(); 110 let mut buf = String::new();
@@ -115,6 +120,21 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label:
115 buf.push_str(&text); 120 buf.push_str(&text);
116 } 121 }
117 122
123 for file_system_edit in source_change.file_system_edits.clone() {
124 match file_system_edit {
125 FileSystemEdit::CreateFile { dst, initial_contents } => {
126 let sr = db.file_source_root(dst.anchor);
127 let sr = db.source_root(sr);
128 let mut base = sr.path_for_file(&dst.anchor).unwrap().clone();
129 base.pop();
130 let created_file_path = format!("{}{}", base.to_string(), &dst.path[1..]);
131 format_to!(buf, "//- {}\n", created_file_path);
132 buf.push_str(&initial_contents);
133 }
134 _ => (),
135 }
136 }
137
118 assert_eq_text!(after, &buf); 138 assert_eq_text!(after, &buf);
119 } 139 }
120 (Some(assist), ExpectedResult::Target(target)) => { 140 (Some(assist), ExpectedResult::Target(target)) => {
diff --git a/crates/assists/src/tests/generated.rs b/crates/assists/src/tests/generated.rs
index cc7c4a343..e9093ec53 100644
--- a/crates/assists/src/tests/generated.rs
+++ b/crates/assists/src/tests/generated.rs
@@ -236,6 +236,21 @@ fn qux(bar: Bar, baz: Baz) {}
236} 236}
237 237
238#[test] 238#[test]
239fn doctest_extract_module_to_file() {
240 check_doc_test(
241 "extract_module_to_file",
242 r#####"
243mod foo {<|>
244 fn t() {}
245}
246"#####,
247 r#####"
248mod foo;
249"#####,
250 )
251}
252
253#[test]
239fn doctest_extract_struct_from_enum_variant() { 254fn doctest_extract_struct_from_enum_variant() {
240 check_doc_test( 255 check_doc_test(
241 "extract_struct_from_enum_variant", 256 "extract_struct_from_enum_variant",
diff --git a/crates/assists/src/utils.rs b/crates/assists/src/utils.rs
index f2cacf7c8..d41084b59 100644
--- a/crates/assists/src/utils.rs
+++ b/crates/assists/src/utils.rs
@@ -232,7 +232,13 @@ fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
232 }; 232 };
233 Some(make::expr_method_call(receiver, method, arg_list)) 233 Some(make::expr_method_call(receiver, method, arg_list))
234 } 234 }
235 ast::Expr::PrefixExpr(pe) if pe.op_kind()? == ast::PrefixOp::Not => pe.expr(), 235 ast::Expr::PrefixExpr(pe) if pe.op_kind()? == ast::PrefixOp::Not => {
236 if let ast::Expr::ParenExpr(parexpr) = pe.expr()? {
237 parexpr.expr()
238 } else {
239 pe.expr()
240 }
241 }
236 // FIXME: 242 // FIXME:
237 // ast::Expr::Literal(true | false ) 243 // ast::Expr::Literal(true | false )
238 _ => None, 244 _ => None,
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index dbc937e4f..1d7e5ddd7 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -1272,7 +1272,6 @@ impl LifetimeParam {
1272 } 1272 }
1273} 1273}
1274 1274
1275// FIXME: rename from `ImplDef` to `Impl`
1276#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 1275#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1277pub struct Impl { 1276pub struct Impl {
1278 pub(crate) id: ImplId, 1277 pub(crate) id: ImplId,
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs
index 41134d23b..bb8fca009 100644
--- a/crates/hir_def/src/generics.rs
+++ b/crates/hir_def/src/generics.rs
@@ -62,6 +62,7 @@ pub struct GenericParams {
62pub enum WherePredicate { 62pub enum WherePredicate {
63 TypeBound { target: WherePredicateTypeTarget, bound: TypeBound }, 63 TypeBound { target: WherePredicateTypeTarget, bound: TypeBound },
64 Lifetime { target: LifetimeRef, bound: LifetimeRef }, 64 Lifetime { target: LifetimeRef, bound: LifetimeRef },
65 ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound },
65} 66}
66 67
67#[derive(Clone, PartialEq, Eq, Debug)] 68#[derive(Clone, PartialEq, Eq, Debug)]
@@ -69,7 +70,6 @@ pub enum WherePredicateTypeTarget {
69 TypeRef(TypeRef), 70 TypeRef(TypeRef),
70 /// For desugared where predicates that can directly refer to a type param. 71 /// For desugared where predicates that can directly refer to a type param.
71 TypeParam(LocalTypeParamId), 72 TypeParam(LocalTypeParamId),
72 // FIXME: ForLifetime(Vec<LifetimeParamId>, TypeRef)
73} 73}
74 74
75#[derive(Default)] 75#[derive(Default)]
@@ -234,7 +234,7 @@ impl GenericParams {
234 for bound in 234 for bound in
235 node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) 235 node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds())
236 { 236 {
237 self.add_where_predicate_from_bound(lower_ctx, bound, target.clone()); 237 self.add_where_predicate_from_bound(lower_ctx, bound, None, target.clone());
238 } 238 }
239 } 239 }
240 240
@@ -279,8 +279,25 @@ impl GenericParams {
279 } else { 279 } else {
280 continue; 280 continue;
281 }; 281 };
282
283 let lifetimes: Option<Box<_>> = pred.generic_param_list().map(|param_list| {
284 // Higher-Ranked Trait Bounds
285 param_list
286 .lifetime_params()
287 .map(|lifetime_param| {
288 lifetime_param
289 .lifetime()
290 .map_or_else(Name::missing, |lt| Name::new_lifetime(&lt))
291 })
292 .collect()
293 });
282 for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { 294 for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) {
283 self.add_where_predicate_from_bound(lower_ctx, bound, target.clone()); 295 self.add_where_predicate_from_bound(
296 lower_ctx,
297 bound,
298 lifetimes.as_ref(),
299 target.clone(),
300 );
284 } 301 }
285 } 302 }
286 } 303 }
@@ -289,6 +306,7 @@ impl GenericParams {
289 &mut self, 306 &mut self,
290 lower_ctx: &LowerCtx, 307 lower_ctx: &LowerCtx,
291 bound: ast::TypeBound, 308 bound: ast::TypeBound,
309 hrtb_lifetimes: Option<&Box<[Name]>>,
292 target: Either<TypeRef, LifetimeRef>, 310 target: Either<TypeRef, LifetimeRef>,
293 ) { 311 ) {
294 if bound.question_mark_token().is_some() { 312 if bound.question_mark_token().is_some() {
@@ -297,9 +315,16 @@ impl GenericParams {
297 } 315 }
298 let bound = TypeBound::from_ast(lower_ctx, bound); 316 let bound = TypeBound::from_ast(lower_ctx, bound);
299 let predicate = match (target, bound) { 317 let predicate = match (target, bound) {
300 (Either::Left(type_ref), bound) => WherePredicate::TypeBound { 318 (Either::Left(type_ref), bound) => match hrtb_lifetimes {
301 target: WherePredicateTypeTarget::TypeRef(type_ref), 319 Some(hrtb_lifetimes) => WherePredicate::ForLifetime {
302 bound, 320 lifetimes: hrtb_lifetimes.clone(),
321 target: WherePredicateTypeTarget::TypeRef(type_ref),
322 bound,
323 },
324 None => WherePredicate::TypeBound {
325 target: WherePredicateTypeTarget::TypeRef(type_ref),
326 bound,
327 },
303 }, 328 },
304 (Either::Right(lifetime), TypeBound::Lifetime(bound)) => { 329 (Either::Right(lifetime), TypeBound::Lifetime(bound)) => {
305 WherePredicate::Lifetime { target: lifetime, bound } 330 WherePredicate::Lifetime { target: lifetime, bound }
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index 8392cb770..8da56cd11 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -675,7 +675,8 @@ impl GenericPredicate {
675 where_predicate: &'a WherePredicate, 675 where_predicate: &'a WherePredicate,
676 ) -> impl Iterator<Item = GenericPredicate> + 'a { 676 ) -> impl Iterator<Item = GenericPredicate> + 'a {
677 match where_predicate { 677 match where_predicate {
678 WherePredicate::TypeBound { target, bound } => { 678 WherePredicate::ForLifetime { target, bound, .. }
679 | WherePredicate::TypeBound { target, bound } => {
679 let self_ty = match target { 680 let self_ty = match target {
680 WherePredicateTypeTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref), 681 WherePredicateTypeTarget::TypeRef(type_ref) => Ty::from_hir(ctx, type_ref),
681 WherePredicateTypeTarget::TypeParam(param_id) => { 682 WherePredicateTypeTarget::TypeParam(param_id) => {
@@ -888,14 +889,13 @@ pub(crate) fn generic_predicates_for_param_query(
888 .where_predicates_in_scope() 889 .where_predicates_in_scope()
889 // we have to filter out all other predicates *first*, before attempting to lower them 890 // we have to filter out all other predicates *first*, before attempting to lower them
890 .filter(|pred| match pred { 891 .filter(|pred| match pred {
891 WherePredicate::TypeBound { 892 WherePredicate::ForLifetime { target, .. }
892 target: WherePredicateTypeTarget::TypeRef(type_ref), 893 | WherePredicate::TypeBound { target, .. } => match target {
893 .. 894 WherePredicateTypeTarget::TypeRef(type_ref) => {
894 } => Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id), 895 Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id)
895 WherePredicate::TypeBound { 896 }
896 target: WherePredicateTypeTarget::TypeParam(local_id), 897 WherePredicateTypeTarget::TypeParam(local_id) => *local_id == param_id.local_id,
897 .. 898 },
898 } => *local_id == param_id.local_id,
899 WherePredicate::Lifetime { .. } => false, 899 WherePredicate::Lifetime { .. } => false,
900 }) 900 })
901 .flat_map(|pred| { 901 .flat_map(|pred| {
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs
index af880c065..65b79df0d 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -5,7 +5,9 @@ use std::sync::Arc;
5use hir_def::{ 5use hir_def::{
6 adt::VariantData, 6 adt::VariantData,
7 db::DefDatabase, 7 db::DefDatabase,
8 generics::{GenericParams, TypeParamData, TypeParamProvenance, WherePredicateTypeTarget}, 8 generics::{
9 GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
10 },
9 path::Path, 11 path::Path,
10 resolver::{HasResolver, TypeNs}, 12 resolver::{HasResolver, TypeNs},
11 type_ref::TypeRef, 13 type_ref::TypeRef,
@@ -27,7 +29,8 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
27 .where_predicates 29 .where_predicates
28 .iter() 30 .iter()
29 .filter_map(|pred| match pred { 31 .filter_map(|pred| match pred {
30 hir_def::generics::WherePredicate::TypeBound { target, bound } => match target { 32 WherePredicate::ForLifetime { target, bound, .. }
33 | WherePredicate::TypeBound { target, bound } => match target {
31 WherePredicateTypeTarget::TypeRef(TypeRef::Path(p)) 34 WherePredicateTypeTarget::TypeRef(TypeRef::Path(p))
32 if p == &Path::from(name![Self]) => 35 if p == &Path::from(name![Self]) =>
33 { 36 {
@@ -38,7 +41,7 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
38 } 41 }
39 _ => None, 42 _ => None,
40 }, 43 },
41 hir_def::generics::WherePredicate::Lifetime { .. } => None, 44 WherePredicate::Lifetime { .. } => None,
42 }) 45 })
43 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) { 46 .filter_map(|path| match resolver.resolve_path_in_type_ns_fully(db, path.mod_path()) {
44 Some(TypeNs::TraitId(t)) => Some(t), 47 Some(TypeNs::TraitId(t)) => Some(t),
diff --git a/crates/ide/src/diagnostics.rs b/crates/ide/src/diagnostics.rs
index 049f808dc..3ad30f0c9 100644
--- a/crates/ide/src/diagnostics.rs
+++ b/crates/ide/src/diagnostics.rs
@@ -619,6 +619,7 @@ fn test_fn() {
619 ), 619 ),
620 path: "foo.rs", 620 path: "foo.rs",
621 }, 621 },
622 initial_contents: "",
622 }, 623 },
623 ], 624 ],
624 is_snippet: false, 625 is_snippet: false,
diff --git a/crates/ide/src/diagnostics/fixes.rs b/crates/ide/src/diagnostics/fixes.rs
index e8b896623..d79f5c170 100644
--- a/crates/ide/src/diagnostics/fixes.rs
+++ b/crates/ide/src/diagnostics/fixes.rs
@@ -40,6 +40,7 @@ impl DiagnosticWithFix for UnresolvedModule {
40 anchor: self.file.original_file(sema.db), 40 anchor: self.file.original_file(sema.db),
41 path: self.candidate.clone(), 41 path: self.candidate.clone(),
42 }, 42 },
43 initial_contents: "".to_string(),
43 } 44 }
44 .into(), 45 .into(),
45 unresolved_module.syntax().text_range(), 46 unresolved_module.syntax().text_range(),
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 7a12e9965..431da5d9c 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -1077,4 +1077,32 @@ fn foo<'foobar>(_: &'foobar ()) {
1077}"#, 1077}"#,
1078 ) 1078 )
1079 } 1079 }
1080
1081 #[test]
1082 #[ignore] // requires the HIR to somehow track these hrtb lifetimes
1083 fn goto_lifetime_hrtb() {
1084 check(
1085 r#"trait Foo<T> {}
1086fn foo<T>() where for<'a> T: Foo<&'a<|> (u8, u16)>, {}
1087 //^^
1088"#,
1089 );
1090 check(
1091 r#"trait Foo<T> {}
1092fn foo<T>() where for<'a<|>> T: Foo<&'a (u8, u16)>, {}
1093 //^^
1094"#,
1095 );
1096 }
1097
1098 #[test]
1099 #[ignore] // requires ForTypes to be implemented
1100 fn goto_lifetime_hrtb_for_type() {
1101 check(
1102 r#"trait Foo<T> {}
1103fn foo<T>() where T: for<'a> Foo<&'a<|> (u8, u16)>, {}
1104 //^^
1105"#,
1106 );
1107 }
1080} 1108}
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 18ea19305..33b7358f7 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -147,20 +147,20 @@ fn find_name(
147) -> Option<RangeInfo<Definition>> { 147) -> Option<RangeInfo<Definition>> {
148 if let Some(name) = opt_name { 148 if let Some(name) = opt_name {
149 let def = NameClass::classify(sema, &name)?.referenced_or_defined(sema.db); 149 let def = NameClass::classify(sema, &name)?.referenced_or_defined(sema.db);
150 let range = name.syntax().text_range(); 150 let FileRange { range, .. } = sema.original_range(name.syntax());
151 return Some(RangeInfo::new(range, def)); 151 return Some(RangeInfo::new(range, def));
152 } 152 }
153 153
154 let (text_range, def) = if let Some(lifetime) = 154 let (FileRange { range, .. }, def) = if let Some(lifetime) =
155 sema.find_node_at_offset_with_descend::<ast::Lifetime>(&syntax, position.offset) 155 sema.find_node_at_offset_with_descend::<ast::Lifetime>(&syntax, position.offset)
156 { 156 {
157 if let Some(def) = NameRefClass::classify_lifetime(sema, &lifetime) 157 if let Some(def) = NameRefClass::classify_lifetime(sema, &lifetime)
158 .map(|class| NameRefClass::referenced(class, sema.db)) 158 .map(|class| NameRefClass::referenced(class, sema.db))
159 { 159 {
160 (lifetime.syntax().text_range(), def) 160 (sema.original_range(lifetime.syntax()), def)
161 } else { 161 } else {
162 ( 162 (
163 lifetime.syntax().text_range(), 163 sema.original_range(lifetime.syntax()),
164 NameClass::classify_lifetime(sema, &lifetime)?.referenced_or_defined(sema.db), 164 NameClass::classify_lifetime(sema, &lifetime)?.referenced_or_defined(sema.db),
165 ) 165 )
166 } 166 }
@@ -168,11 +168,11 @@ fn find_name(
168 let name_ref = 168 let name_ref =
169 sema.find_node_at_offset_with_descend::<ast::NameRef>(&syntax, position.offset)?; 169 sema.find_node_at_offset_with_descend::<ast::NameRef>(&syntax, position.offset)?;
170 ( 170 (
171 name_ref.syntax().text_range(), 171 sema.original_range(name_ref.syntax()),
172 NameRefClass::classify(sema, &name_ref)?.referenced(sema.db), 172 NameRefClass::classify(sema, &name_ref)?.referenced(sema.db),
173 ) 173 )
174 }; 174 };
175 Some(RangeInfo::new(text_range, def)) 175 Some(RangeInfo::new(range, def))
176} 176}
177 177
178fn decl_access(def: &Definition, syntax: &SyntaxNode, range: TextRange) -> Option<ReferenceAccess> { 178fn decl_access(def: &Definition, syntax: &SyntaxNode, range: TextRange) -> Option<ReferenceAccess> {
@@ -1086,4 +1086,40 @@ impl<'a> Foo<'a> for &'a () {
1086 "#]], 1086 "#]],
1087 ); 1087 );
1088 } 1088 }
1089
1090 #[test]
1091 fn test_map_range_to_original() {
1092 check(
1093 r#"
1094macro_rules! foo {($i:ident) => {$i} }
1095fn main() {
1096 let a<|> = "test";
1097 foo!(a);
1098}
1099"#,
1100 expect![[r#"
1101 a Local FileId(0) 59..60 Other
1102
1103 FileId(0) 80..81 Other Read
1104 "#]],
1105 );
1106 }
1107
1108 #[test]
1109 fn test_map_range_to_original_ref() {
1110 check(
1111 r#"
1112macro_rules! foo {($i:ident) => {$i} }
1113fn main() {
1114 let a = "test";
1115 foo!(a<|>);
1116}
1117"#,
1118 expect![[r#"
1119 a Local FileId(0) 59..60 Other
1120
1121 FileId(0) 80..81 Other Read
1122 "#]],
1123 );
1124 }
1089} 1125}
diff --git a/crates/ide_db/src/source_change.rs b/crates/ide_db/src/source_change.rs
index e87d98dad..10c0abdac 100644
--- a/crates/ide_db/src/source_change.rs
+++ b/crates/ide_db/src/source_change.rs
@@ -44,7 +44,7 @@ impl From<Vec<SourceFileEdit>> for SourceChange {
44 44
45#[derive(Debug, Clone)] 45#[derive(Debug, Clone)]
46pub enum FileSystemEdit { 46pub enum FileSystemEdit {
47 CreateFile { dst: AnchoredPathBuf }, 47 CreateFile { dst: AnchoredPathBuf, initial_contents: String },
48 MoveFile { src: FileId, dst: AnchoredPathBuf }, 48 MoveFile { src: FileId, dst: AnchoredPathBuf },
49} 49}
50 50
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs
index f10e7a9b6..451fa1456 100644
--- a/crates/mbe/src/tests.rs
+++ b/crates/mbe/src/tests.rs
@@ -1004,6 +1004,18 @@ fn test_underscore() {
1004} 1004}
1005 1005
1006#[test] 1006#[test]
1007fn test_vertical_bar_with_pat() {
1008 parse_macro(
1009 r#"
1010 macro_rules! foo {
1011 (| $pat:pat | ) => { 0 }
1012 }
1013 "#,
1014 )
1015 .assert_expand_items(r#"foo! { | x | }"#, r#"0"#);
1016}
1017
1018#[test]
1007fn test_lifetime() { 1019fn test_lifetime() {
1008 parse_macro( 1020 parse_macro(
1009 r#" 1021 r#"
diff --git a/crates/parser/src/grammar.rs b/crates/parser/src/grammar.rs
index 1a078f6b4..f08c8bab7 100644
--- a/crates/parser/src/grammar.rs
+++ b/crates/parser/src/grammar.rs
@@ -55,7 +55,7 @@ pub(crate) mod fragments {
55 use super::*; 55 use super::*;
56 56
57 pub(crate) use super::{ 57 pub(crate) use super::{
58 expressions::block_expr, paths::type_path as path, patterns::pattern, types::type_, 58 expressions::block_expr, paths::type_path as path, patterns::pattern_single, types::type_,
59 }; 59 };
60 60
61 pub(crate) fn expr(p: &mut Parser) { 61 pub(crate) fn expr(p: &mut Parser) {
diff --git a/crates/parser/src/grammar/expressions/atom.rs b/crates/parser/src/grammar/expressions/atom.rs
index 18b63feb7..e897d5a52 100644
--- a/crates/parser/src/grammar/expressions/atom.rs
+++ b/crates/parser/src/grammar/expressions/atom.rs
@@ -156,11 +156,13 @@ fn tuple_expr(p: &mut Parser) -> CompletedMarker {
156 let mut saw_expr = false; 156 let mut saw_expr = false;
157 while !p.at(EOF) && !p.at(T![')']) { 157 while !p.at(EOF) && !p.at(T![')']) {
158 saw_expr = true; 158 saw_expr = true;
159 if !p.at_ts(EXPR_FIRST) { 159
160 p.error("expected expression"); 160 // test tuple_attrs
161 // const A: (i64, i64) = (1, #[cfg(test)] 2);
162 if !expr_with_attrs(p) {
161 break; 163 break;
162 } 164 }
163 expr(p); 165
164 if !p.at(T![')']) { 166 if !p.at(T![')']) {
165 saw_comma = true; 167 saw_comma = true;
166 p.expect(T![,]); 168 p.expect(T![,]);
diff --git a/crates/parser/src/grammar/params.rs b/crates/parser/src/grammar/params.rs
index 3ee4e4fca..2d006a1d5 100644
--- a/crates/parser/src/grammar/params.rs
+++ b/crates/parser/src/grammar/params.rs
@@ -47,20 +47,23 @@ fn list_(p: &mut Parser, flavor: Flavor) {
47 if let FnDef = flavor { 47 if let FnDef = flavor {
48 // test self_param_outer_attr 48 // test self_param_outer_attr
49 // fn f(#[must_use] self) {} 49 // fn f(#[must_use] self) {}
50 let m = p.start();
50 attributes::outer_attrs(p); 51 attributes::outer_attrs(p);
51 opt_self_param(p); 52 opt_self_param(p, m);
52 } 53 }
53 54
54 while !p.at(EOF) && !p.at(ket) { 55 while !p.at(EOF) && !p.at(ket) {
55 // test param_outer_arg 56 // test param_outer_arg
56 // fn f(#[attr1] pat: Type) {} 57 // fn f(#[attr1] pat: Type) {}
58 let m = p.start();
57 attributes::outer_attrs(p); 59 attributes::outer_attrs(p);
58 60
59 if !p.at_ts(PARAM_FIRST) { 61 if !p.at_ts(PARAM_FIRST) {
60 p.error("expected value parameter"); 62 p.error("expected value parameter");
63 m.abandon(p);
61 break; 64 break;
62 } 65 }
63 let param = param(p, flavor); 66 let param = param(p, m, flavor);
64 if !p.at(ket) { 67 if !p.at(ket) {
65 p.expect(T![,]); 68 p.expect(T![,]);
66 } 69 }
@@ -77,9 +80,8 @@ const PARAM_FIRST: TokenSet = patterns::PATTERN_FIRST.union(types::TYPE_FIRST);
77 80
78struct Variadic(bool); 81struct Variadic(bool);
79 82
80fn param(p: &mut Parser, flavor: Flavor) -> Variadic { 83fn param(p: &mut Parser, m: Marker, flavor: Flavor) -> Variadic {
81 let mut res = Variadic(false); 84 let mut res = Variadic(false);
82 let m = p.start();
83 match flavor { 85 match flavor {
84 // test param_list_vararg 86 // test param_list_vararg
85 // extern "C" { fn printf(format: *const i8, ...) -> i32; } 87 // extern "C" { fn printf(format: *const i8, ...) -> i32; }
@@ -151,10 +153,8 @@ fn variadic_param(p: &mut Parser) -> bool {
151// fn d(&'a mut self, x: i32) {} 153// fn d(&'a mut self, x: i32) {}
152// fn e(mut self) {} 154// fn e(mut self) {}
153// } 155// }
154fn opt_self_param(p: &mut Parser) { 156fn opt_self_param(p: &mut Parser, m: Marker) {
155 let m;
156 if p.at(T![self]) || p.at(T![mut]) && p.nth(1) == T![self] { 157 if p.at(T![self]) || p.at(T![mut]) && p.nth(1) == T![self] {
157 m = p.start();
158 p.eat(T![mut]); 158 p.eat(T![mut]);
159 p.eat(T![self]); 159 p.eat(T![self]);
160 // test arb_self_types 160 // test arb_self_types
@@ -174,9 +174,8 @@ fn opt_self_param(p: &mut Parser) {
174 (T![&], T![mut], T![self], _) => 3, 174 (T![&], T![mut], T![self], _) => 3,
175 (T![&], LIFETIME_IDENT, T![self], _) => 3, 175 (T![&], LIFETIME_IDENT, T![self], _) => 3,
176 (T![&], LIFETIME_IDENT, T![mut], T![self]) => 4, 176 (T![&], LIFETIME_IDENT, T![mut], T![self]) => 4,
177 _ => return, 177 _ => return m.abandon(p),
178 }; 178 };
179 m = p.start();
180 p.bump_any(); 179 p.bump_any();
181 if p.at(LIFETIME_IDENT) { 180 if p.at(LIFETIME_IDENT) {
182 lifetime(p); 181 lifetime(p);
diff --git a/crates/parser/src/grammar/type_params.rs b/crates/parser/src/grammar/type_params.rs
index 9c3f7c28a..4aeccd193 100644
--- a/crates/parser/src/grammar/type_params.rs
+++ b/crates/parser/src/grammar/type_params.rs
@@ -113,7 +113,7 @@ fn type_bound(p: &mut Parser) -> bool {
113 p.eat(T![?]); 113 p.eat(T![?]);
114 match p.current() { 114 match p.current() {
115 LIFETIME_IDENT => lifetime(p), 115 LIFETIME_IDENT => lifetime(p),
116 T![for] => types::for_type(p), 116 T![for] => types::for_type(p, false),
117 _ if paths::is_use_path_start(p) => types::path_type_(p, false), 117 _ if paths::is_use_path_start(p) => types::path_type_(p, false),
118 _ => { 118 _ => {
119 m.abandon(p); 119 m.abandon(p);
diff --git a/crates/parser/src/grammar/types.rs b/crates/parser/src/grammar/types.rs
index 36a15eace..94cbf7d85 100644
--- a/crates/parser/src/grammar/types.rs
+++ b/crates/parser/src/grammar/types.rs
@@ -44,7 +44,7 @@ fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) {
44 T![&] => ref_type(p), 44 T![&] => ref_type(p),
45 T![_] => infer_type(p), 45 T![_] => infer_type(p),
46 T![fn] | T![unsafe] | T![extern] => fn_ptr_type(p), 46 T![fn] | T![unsafe] | T![extern] => fn_ptr_type(p),
47 T![for] => for_type(p), 47 T![for] => for_type(p, allow_bounds),
48 T![impl] => impl_trait_type(p), 48 T![impl] => impl_trait_type(p),
49 T![dyn] => dyn_trait_type(p), 49 T![dyn] => dyn_trait_type(p),
50 // Some path types are not allowed to have bounds (no plus) 50 // Some path types are not allowed to have bounds (no plus)
@@ -227,7 +227,7 @@ pub(super) fn for_binder(p: &mut Parser) {
227// type A = for<'a> fn() -> (); 227// type A = for<'a> fn() -> ();
228// type B = for<'a> unsafe extern "C" fn(&'a ()) -> (); 228// type B = for<'a> unsafe extern "C" fn(&'a ()) -> ();
229// type Obj = for<'a> PartialEq<&'a i32>; 229// type Obj = for<'a> PartialEq<&'a i32>;
230pub(super) fn for_type(p: &mut Parser) { 230pub(super) fn for_type(p: &mut Parser, allow_bounds: bool) {
231 assert!(p.at(T![for])); 231 assert!(p.at(T![for]));
232 let m = p.start(); 232 let m = p.start();
233 for_binder(p); 233 for_binder(p);
@@ -240,7 +240,13 @@ pub(super) fn for_type(p: &mut Parser) {
240 } 240 }
241 } 241 }
242 type_no_bounds(p); 242 type_no_bounds(p);
243 m.complete(p, FOR_TYPE); 243 let completed = m.complete(p, FOR_TYPE);
244
245 // test no_dyn_trait_leading_for
246 // type A = for<'a> Test<'a> + Send;
247 if allow_bounds {
248 opt_type_bounds_as_dyn_trait_type(p, completed);
249 }
244} 250}
245 251
246// test impl_trait_type 252// test impl_trait_type
@@ -290,7 +296,7 @@ fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) {
290 let path = m.complete(p, kind); 296 let path = m.complete(p, kind);
291 297
292 if allow_bounds { 298 if allow_bounds {
293 opt_path_type_bounds_as_dyn_trait_type(p, path); 299 opt_type_bounds_as_dyn_trait_type(p, path);
294 } 300 }
295} 301}
296 302
@@ -304,19 +310,23 @@ pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) {
304 // fn foo() -> Box<dyn T + 'f> {} 310 // fn foo() -> Box<dyn T + 'f> {}
305 let path = m.complete(p, PATH_TYPE); 311 let path = m.complete(p, PATH_TYPE);
306 if allow_bounds { 312 if allow_bounds {
307 opt_path_type_bounds_as_dyn_trait_type(p, path); 313 opt_type_bounds_as_dyn_trait_type(p, path);
308 } 314 }
309} 315}
310 316
311/// This turns a parsed PATH_TYPE optionally into a DYN_TRAIT_TYPE 317/// This turns a parsed PATH_TYPE or FOR_TYPE optionally into a DYN_TRAIT_TYPE
312/// with a TYPE_BOUND_LIST 318/// with a TYPE_BOUND_LIST
313fn opt_path_type_bounds_as_dyn_trait_type(p: &mut Parser, path_type_marker: CompletedMarker) { 319fn opt_type_bounds_as_dyn_trait_type(p: &mut Parser, type_marker: CompletedMarker) {
320 assert!(matches!(
321 type_marker.kind(),
322 SyntaxKind::PATH_TYPE | SyntaxKind::FOR_TYPE | SyntaxKind::MACRO_CALL
323 ));
314 if !p.at(T![+]) { 324 if !p.at(T![+]) {
315 return; 325 return;
316 } 326 }
317 327
318 // First create a TYPE_BOUND from the completed PATH_TYPE 328 // First create a TYPE_BOUND from the completed PATH_TYPE
319 let m = path_type_marker.precede(p).complete(p, TYPE_BOUND); 329 let m = type_marker.precede(p).complete(p, TYPE_BOUND);
320 330
321 // Next setup a marker for the TYPE_BOUND_LIST 331 // Next setup a marker for the TYPE_BOUND_LIST
322 let m = m.precede(p); 332 let m = m.precede(p);
diff --git a/crates/parser/src/lib.rs b/crates/parser/src/lib.rs
index ab8e4c70e..811e740f9 100644
--- a/crates/parser/src/lib.rs
+++ b/crates/parser/src/lib.rs
@@ -112,7 +112,7 @@ pub fn parse_fragment(
112 FragmentKind::Path => grammar::fragments::path, 112 FragmentKind::Path => grammar::fragments::path,
113 FragmentKind::Expr => grammar::fragments::expr, 113 FragmentKind::Expr => grammar::fragments::expr,
114 FragmentKind::Type => grammar::fragments::type_, 114 FragmentKind::Type => grammar::fragments::type_,
115 FragmentKind::Pattern => grammar::fragments::pattern, 115 FragmentKind::Pattern => grammar::fragments::pattern_single,
116 FragmentKind::Item => grammar::fragments::item, 116 FragmentKind::Item => grammar::fragments::item,
117 FragmentKind::Block => grammar::fragments::block_expr, 117 FragmentKind::Block => grammar::fragments::block_expr,
118 FragmentKind::Visibility => grammar::fragments::opt_visibility, 118 FragmentKind::Visibility => grammar::fragments::opt_visibility,
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 1f4b5c24c..11cdae57f 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -33,7 +33,7 @@ config_data! {
33 callInfo_full: bool = "true", 33 callInfo_full: bool = "true",
34 34
35 /// Automatically refresh project info via `cargo metadata` on 35 /// Automatically refresh project info via `cargo metadata` on
36 /// Cargo.toml changes. 36 /// `Cargo.toml` changes.
37 cargo_autoreload: bool = "true", 37 cargo_autoreload: bool = "true",
38 /// Activate all available features. 38 /// Activate all available features.
39 cargo_allFeatures: bool = "false", 39 cargo_allFeatures: bool = "false",
@@ -52,7 +52,7 @@ config_data! {
52 /// Run specified `cargo check` command for diagnostics on save. 52 /// Run specified `cargo check` command for diagnostics on save.
53 checkOnSave_enable: bool = "true", 53 checkOnSave_enable: bool = "true",
54 /// Check with all features (will be passed as `--all-features`). 54 /// Check with all features (will be passed as `--all-features`).
55 /// Defaults to `rust-analyzer.cargo.allFeatures`. 55 /// Defaults to `#rust-analyzer.cargo.allFeatures#`.
56 checkOnSave_allFeatures: Option<bool> = "null", 56 checkOnSave_allFeatures: Option<bool> = "null",
57 /// Check all targets and tests (will be passed as `--all-targets`). 57 /// Check all targets and tests (will be passed as `--all-targets`).
58 checkOnSave_allTargets: bool = "true", 58 checkOnSave_allTargets: bool = "true",
@@ -61,12 +61,12 @@ config_data! {
61 /// Do not activate the `default` feature. 61 /// Do not activate the `default` feature.
62 checkOnSave_noDefaultFeatures: Option<bool> = "null", 62 checkOnSave_noDefaultFeatures: Option<bool> = "null",
63 /// Check for a specific target. Defaults to 63 /// Check for a specific target. Defaults to
64 /// `rust-analyzer.cargo.target`. 64 /// `#rust-analyzer.cargo.target#`.
65 checkOnSave_target: Option<String> = "null", 65 checkOnSave_target: Option<String> = "null",
66 /// Extra arguments for `cargo check`. 66 /// Extra arguments for `cargo check`.
67 checkOnSave_extraArgs: Vec<String> = "[]", 67 checkOnSave_extraArgs: Vec<String> = "[]",
68 /// List of features to activate. Defaults to 68 /// List of features to activate. Defaults to
69 /// `rust-analyzer.cargo.features`. 69 /// `#rust-analyzer.cargo.features#`.
70 checkOnSave_features: Option<Vec<String>> = "null", 70 checkOnSave_features: Option<Vec<String>> = "null",
71 /// Advanced option, fully override the command rust-analyzer uses for 71 /// Advanced option, fully override the command rust-analyzer uses for
72 /// checking. The command should include `--message-format=json` or 72 /// checking. The command should include `--message-format=json` or
@@ -80,7 +80,7 @@ config_data! {
80 /// Whether to show postfix snippets like `dbg`, `if`, `not`, etc. 80 /// Whether to show postfix snippets like `dbg`, `if`, `not`, etc.
81 completion_postfix_enable: bool = "true", 81 completion_postfix_enable: bool = "true",
82 /// Toggles the additional completions that automatically add imports when completed. 82 /// Toggles the additional completions that automatically add imports when completed.
83 /// Note that your client have to specify the `additionalTextEdits` LSP client capability to truly have this feature enabled. 83 /// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
84 completion_autoimport_enable: bool = "true", 84 completion_autoimport_enable: bool = "true",
85 85
86 /// Whether to show native rust-analyzer diagnostics. 86 /// Whether to show native rust-analyzer diagnostics.
@@ -90,13 +90,13 @@ config_data! {
90 diagnostics_enableExperimental: bool = "true", 90 diagnostics_enableExperimental: bool = "true",
91 /// List of rust-analyzer diagnostics to disable. 91 /// List of rust-analyzer diagnostics to disable.
92 diagnostics_disabled: FxHashSet<String> = "[]", 92 diagnostics_disabled: FxHashSet<String> = "[]",
93 /// List of warnings that should be displayed with info severity.\nThe 93 /// List of warnings that should be displayed with info severity.\n\nThe
94 /// warnings will be indicated by a blue squiggly underline in code and 94 /// warnings will be indicated by a blue squiggly underline in code and
95 /// a blue icon in the problems panel. 95 /// a blue icon in the `Problems Panel`.
96 diagnostics_warningsAsHint: Vec<String> = "[]", 96 diagnostics_warningsAsHint: Vec<String> = "[]",
97 /// List of warnings that should be displayed with hint severity.\nThe 97 /// List of warnings that should be displayed with hint severity.\n\nThe
98 /// warnings will be indicated by faded text or three dots in code and 98 /// warnings will be indicated by faded text or three dots in code and
99 /// will not show up in the problems panel. 99 /// will not show up in the `Problems Panel`.
100 diagnostics_warningsAsInfo: Vec<String> = "[]", 100 diagnostics_warningsAsInfo: Vec<String> = "[]",
101 101
102 /// Controls file watching implementation. 102 /// Controls file watching implementation.
@@ -121,7 +121,7 @@ config_data! {
121 121
122 /// Whether to show inlay type hints for method chains. 122 /// Whether to show inlay type hints for method chains.
123 inlayHints_chainingHints: bool = "true", 123 inlayHints_chainingHints: bool = "true",
124 /// Maximum length for inlay hints. 124 /// Maximum length for inlay hints. Default is unlimited.
125 inlayHints_maxLength: Option<usize> = "null", 125 inlayHints_maxLength: Option<usize> = "null",
126 /// Whether to show function parameter name inlay hints at the call 126 /// Whether to show function parameter name inlay hints at the call
127 /// site. 127 /// site.
@@ -145,27 +145,27 @@ config_data! {
145 lens_methodReferences: bool = "false", 145 lens_methodReferences: bool = "false",
146 146
147 /// Disable project auto-discovery in favor of explicitly specified set 147 /// Disable project auto-discovery in favor of explicitly specified set
148 /// of projects. \nElements must be paths pointing to Cargo.toml, 148 /// of projects.\n\nElements must be paths pointing to `Cargo.toml`,
149 /// rust-project.json, or JSON objects in rust-project.json format. 149 /// `rust-project.json`, or JSON objects in `rust-project.json` format.
150 linkedProjects: Vec<ManifestOrProjectJson> = "[]", 150 linkedProjects: Vec<ManifestOrProjectJson> = "[]",
151 /// Number of syntax trees rust-analyzer keeps in memory. 151 /// Number of syntax trees rust-analyzer keeps in memory. Defaults to 128.
152 lruCapacity: Option<usize> = "null", 152 lruCapacity: Option<usize> = "null",
153 /// Whether to show `can't find Cargo.toml` error message. 153 /// Whether to show `can't find Cargo.toml` error message.
154 notifications_cargoTomlNotFound: bool = "true", 154 notifications_cargoTomlNotFound: bool = "true",
155 /// Enable Proc macro support, cargo.loadOutDirsFromCheck must be 155 /// Enable Proc macro support, `#rust-analyzer.cargo.loadOutDirsFromCheck#` must be
156 /// enabled. 156 /// enabled.
157 procMacro_enable: bool = "false", 157 procMacro_enable: bool = "false",
158 158
159 /// Command to be executed instead of 'cargo' for runnables. 159 /// Command to be executed instead of 'cargo' for runnables.
160 runnables_overrideCargo: Option<String> = "null", 160 runnables_overrideCargo: Option<String> = "null",
161 /// Additional arguments to be passed to cargo for runnables such as 161 /// Additional arguments to be passed to cargo for runnables such as
162 /// tests or binaries.\nFor example, it may be '--release'. 162 /// tests or binaries.\nFor example, it may be `--release`.
163 runnables_cargoExtraArgs: Vec<String> = "[]", 163 runnables_cargoExtraArgs: Vec<String> = "[]",
164 164
165 /// Path to the rust compiler sources, for usage in rustc_private projects. 165 /// Path to the rust compiler sources, for usage in rustc_private projects.
166 rustcSource : Option<String> = "null", 166 rustcSource : Option<String> = "null",
167 167
168 /// Additional arguments to rustfmt. 168 /// Additional arguments to `rustfmt`.
169 rustfmt_extraArgs: Vec<String> = "[]", 169 rustfmt_extraArgs: Vec<String> = "[]",
170 /// Advanced option, fully override the command rust-analyzer uses for 170 /// Advanced option, fully override the command rust-analyzer uses for
171 /// formatting. 171 /// formatting.
@@ -758,7 +758,7 @@ fn field_props(field: &str, ty: &str, doc: &[&str], default: &str) -> serde_json
758 ], 758 ],
759 "enumDescriptions": [ 759 "enumDescriptions": [
760 "Insert import paths relative to the current module, using up to one `super` prefix if the parent module contains the requested item.", 760 "Insert import paths relative to the current module, using up to one `super` prefix if the parent module contains the requested item.",
761 "Prefix all import paths with `self` if they don't begin with `self`, `super`, `crate` or a crate name", 761 "Prefix all import paths with `self` if they don't begin with `self`, `super`, `crate` or a crate name.",
762 "Force import paths to be absolute by always starting them with `crate` or the crate name they refer to." 762 "Force import paths to be absolute by always starting them with `crate` or the crate name they refer to."
763 ], 763 ],
764 }, 764 },
diff --git a/crates/rust-analyzer/src/diagnostics/to_proto.rs b/crates/rust-analyzer/src/diagnostics/to_proto.rs
index f16f97131..540759198 100644
--- a/crates/rust-analyzer/src/diagnostics/to_proto.rs
+++ b/crates/rust-analyzer/src/diagnostics/to_proto.rs
@@ -319,6 +319,10 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
319 message: "original diagnostic".to_string(), 319 message: "original diagnostic".to_string(),
320 }; 320 };
321 for info in &related_information { 321 for info in &related_information {
322 // Filter out empty/non-existent messages, as they greatly confuse VS Code.
323 if info.message.is_empty() {
324 continue;
325 }
322 diagnostics.push(MappedRustDiagnostic { 326 diagnostics.push(MappedRustDiagnostic {
323 url: info.location.uri.clone(), 327 url: info.location.uri.clone(),
324 fixes: fixes.clone(), // share fixes to make them easier to apply 328 fixes: fixes.clone(), // share fixes to make them easier to apply
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index e0561b5a7..5a1ae96aa 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -634,30 +634,47 @@ pub(crate) fn snippet_text_document_edit(
634 Ok(lsp_ext::SnippetTextDocumentEdit { text_document, edits }) 634 Ok(lsp_ext::SnippetTextDocumentEdit { text_document, edits })
635} 635}
636 636
637pub(crate) fn resource_op( 637pub(crate) fn snippet_text_document_ops(
638 snap: &GlobalStateSnapshot, 638 snap: &GlobalStateSnapshot,
639 file_system_edit: FileSystemEdit, 639 file_system_edit: FileSystemEdit,
640) -> lsp_types::ResourceOp { 640) -> Vec<lsp_ext::SnippetDocumentChangeOperation> {
641 let mut ops = Vec::new();
641 match file_system_edit { 642 match file_system_edit {
642 FileSystemEdit::CreateFile { dst } => { 643 FileSystemEdit::CreateFile { dst, initial_contents } => {
643 let uri = snap.anchored_path(&dst); 644 let uri = snap.anchored_path(&dst);
644 lsp_types::ResourceOp::Create(lsp_types::CreateFile { 645 let create_file = lsp_types::ResourceOp::Create(lsp_types::CreateFile {
645 uri, 646 uri: uri.clone(),
646 options: None, 647 options: None,
647 annotation_id: None, 648 annotation_id: None,
648 }) 649 });
650 ops.push(lsp_ext::SnippetDocumentChangeOperation::Op(create_file));
651 if !initial_contents.is_empty() {
652 let text_document =
653 lsp_types::OptionalVersionedTextDocumentIdentifier { uri, version: None };
654 let range = range(&LineIndex::new(""), TextRange::empty(TextSize::from(0)));
655 let text_edit = lsp_ext::SnippetTextEdit {
656 range,
657 new_text: initial_contents,
658 insert_text_format: Some(lsp_types::InsertTextFormat::PlainText),
659 };
660 let edit_file =
661 lsp_ext::SnippetTextDocumentEdit { text_document, edits: vec![text_edit] };
662 ops.push(lsp_ext::SnippetDocumentChangeOperation::Edit(edit_file));
663 }
649 } 664 }
650 FileSystemEdit::MoveFile { src, dst } => { 665 FileSystemEdit::MoveFile { src, dst } => {
651 let old_uri = snap.file_id_to_url(src); 666 let old_uri = snap.file_id_to_url(src);
652 let new_uri = snap.anchored_path(&dst); 667 let new_uri = snap.anchored_path(&dst);
653 lsp_types::ResourceOp::Rename(lsp_types::RenameFile { 668 let rename_file = lsp_types::ResourceOp::Rename(lsp_types::RenameFile {
654 old_uri, 669 old_uri,
655 new_uri, 670 new_uri,
656 options: None, 671 options: None,
657 annotation_id: None, 672 annotation_id: None,
658 }) 673 });
674 ops.push(lsp_ext::SnippetDocumentChangeOperation::Op(rename_file))
659 } 675 }
660 } 676 }
677 ops
661} 678}
662 679
663pub(crate) fn snippet_workspace_edit( 680pub(crate) fn snippet_workspace_edit(
@@ -666,8 +683,8 @@ pub(crate) fn snippet_workspace_edit(
666) -> Result<lsp_ext::SnippetWorkspaceEdit> { 683) -> Result<lsp_ext::SnippetWorkspaceEdit> {
667 let mut document_changes: Vec<lsp_ext::SnippetDocumentChangeOperation> = Vec::new(); 684 let mut document_changes: Vec<lsp_ext::SnippetDocumentChangeOperation> = Vec::new();
668 for op in source_change.file_system_edits { 685 for op in source_change.file_system_edits {
669 let op = resource_op(&snap, op); 686 let ops = snippet_text_document_ops(snap, op);
670 document_changes.push(lsp_ext::SnippetDocumentChangeOperation::Op(op)); 687 document_changes.extend_from_slice(&ops);
671 } 688 }
672 for edit in source_change.source_file_edits { 689 for edit in source_change.source_file_edits {
673 let edit = snippet_text_document_edit(&snap, source_change.is_snippet, edit)?; 690 let edit = snippet_text_document_edit(&snap, source_change.is_snippet, edit)?;
diff --git a/crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast b/crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast
index 6403ff8d5..d3219f0b2 100644
--- a/crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast
+++ b/crates/syntax/test_data/parser/inline/ok/0138_self_param_outer_attr.rast
@@ -6,16 +6,16 @@ [email protected]
6 [email protected] "f" 6 [email protected] "f"
7 [email protected] 7 [email protected]
8 [email protected] "(" 8 [email protected] "("
9 ATT[email protected]6 9 SELF_PARAM@5..21
10 POUND@5..6 "#" 10 ATTR@5..16
11 L_BRACK@6..7 "[" 11 POUND@5..6 "#"
12 PATH@7..15 12 L_BRACK@6..7 "["
13 PATH_SEGMENT@7..15 13 [email protected]
14 NAME_REF@7..15 14 PATH_SEGMENT@7..15
15 IDENT@7..15 "must_use" 15 NAME_REF@7..15
16 R_BRACK@15..16 "]" 16 IDENT@7..15 "must_use"
17 WHITESPACE@16..17 " " 17 R_BRACK@15..16 "]"
18 SELF_PARAM@17..21 18 WHITESPACE@16..17 " "
19 [email protected] "self" 19 [email protected] "self"
20 [email protected] ")" 20 [email protected] ")"
21 [email protected] " " 21 [email protected] " "
diff --git a/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rast b/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rast
new file mode 100644
index 000000000..edfcb288c
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rast
@@ -0,0 +1,43 @@
1[email protected]
2 [email protected]
3 [email protected] "type"
4 [email protected] " "
5 [email protected]
6 [email protected] "A"
7 [email protected] " "
8 [email protected] "="
9 [email protected] " "
10 [email protected]
11 [email protected]
12 [email protected]
13 [email protected]
14 [email protected] "for"
15 [email protected]
16 [email protected] "<"
17 [email protected]
18 [email protected]
19 [email protected] "\'a"
20 [email protected] ">"
21 [email protected] " "
22 [email protected]
23 [email protected]
24 [email protected]
25 [email protected]
26 [email protected] "Test"
27 [email protected]
28 [email protected] "<"
29 [email protected]
30 [email protected]
31 [email protected] "\'a"
32 [email protected] ">"
33 [email protected] " "
34 [email protected] "+"
35 [email protected] " "
36 [email protected]
37 [email protected]
38 [email protected]
39 [email protected]
40 [email protected]
41 [email protected] "Send"
42 [email protected] ";"
43 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rs b/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rs
new file mode 100644
index 000000000..47a71fd19
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0154_no_dyn_trait_leading_for.rs
@@ -0,0 +1 @@
type A = for<'a> Test<'a> + Send;
diff --git a/crates/syntax/test_data/parser/inline/ok/0154_tuple_attrs.rast b/crates/syntax/test_data/parser/inline/ok/0154_tuple_attrs.rast
new file mode 100644
index 000000000..d34b21abe
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0154_tuple_attrs.rast
@@ -0,0 +1,50 @@
1[email protected]
2 [email protected]
3 [email protected] "const"
4 [email protected] " "
5 [email protected]
6 [email protected] "A"
7 [email protected] ":"
8 [email protected] " "
9 [email protected]
10 [email protected] "("
11 [email protected]
12 [email protected]
13 [email protected]
14 [email protected]
15 [email protected] "i64"
16 [email protected] ","
17 [email protected] " "
18 [email protected]
19 [email protected]
20 [email protected]
21 [email protected]
22 [email protected] "i64"
23 [email protected] ")"
24 [email protected] " "
25 [email protected] "="
26 [email protected] " "
27 [email protected]
28 [email protected] "("
29 [email protected]
30 [email protected] "1"
31 [email protected] ","
32 [email protected] " "
33 [email protected]
34 [email protected]
35 [email protected] "#"
36 [email protected] "["
37 [email protected]
38 [email protected]
39 [email protected]
40 [email protected] "cfg"
41 [email protected]
42 [email protected] "("
43 [email protected] "test"
44 [email protected] ")"
45 [email protected] "]"
46 [email protected] " "
47 [email protected] "2"
48 [email protected] ")"
49 [email protected] ";"
50 [email protected] "\n"
diff --git a/crates/syntax/test_data/parser/inline/ok/0154_tuple_attrs.rs b/crates/syntax/test_data/parser/inline/ok/0154_tuple_attrs.rs
new file mode 100644
index 000000000..f84b7ab31
--- /dev/null
+++ b/crates/syntax/test_data/parser/inline/ok/0154_tuple_attrs.rs
@@ -0,0 +1 @@
const A: (i64, i64) = (1, #[cfg(test)] 2);
diff --git a/crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast b/crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast
index 8974f9e40..3fed11838 100644
--- a/crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast
+++ b/crates/syntax/test_data/parser/ok/0051_parameter_attrs.rast
@@ -107,16 +107,16 @@ [email protected]
107 [email protected] "i8" 107 [email protected] "i8"
108 [email protected] "," 108 [email protected] ","
109 [email protected] " " 109 [email protected] " "
110 ATT[email protected]3 110 PARAM@106..117
111 POUND@106..107 "#" 111 ATTR@106..113
112 L_BRACK@107..108 "[" 112 POUND@106..107 "#"
113 PATH@108..112 113 L_BRACK@107..108 "["
114 PATH_SEGMENT@108..112 114 [email protected]
115 NAME_REF@108..112 115 PATH_SEGMENT@108..112
116 IDENT@108..112 "attr" 116 NAME_REF@108..112
117 R_BRACK@112..113 "]" 117 IDENT@108..112 "attr"
118 WHITESPACE@113..114 " " 118 R_BRACK@112..113 "]"
119 PARAM@114..117 119 WHITESPACE@113..114 " "
120 [email protected] "..." 120 [email protected] "..."
121 [email protected] ")" 121 [email protected] ")"
122 [email protected] " " 122 [email protected] " "
@@ -153,16 +153,16 @@ [email protected]
153 [email protected] "FnMut" 153 [email protected] "FnMut"
154 [email protected] 154 [email protected]
155 [email protected] "(" 155 [email protected] "("
156 ATT[email protected]53 156 PARAM@146..166
157 POUND@146..147 "#" 157 ATTR@146..153
158 L_BRACK@147..148 "[" 158 POUND@146..147 "#"
159 PATH@148..152 159 L_BRACK@147..148 "["
160 PATH_SEGMENT@148..152 160 [email protected]
161 NAME_REF@148..152 161 PATH_SEGMENT@148..152
162 IDENT@148..152 "attr" 162 NAME_REF@148..152
163 R_BRACK@152..153 "]" 163 IDENT@148..152 "attr"
164 WHITESPACE@153..154 " " 164 R_BRACK@152..153 "]"
165 PARAM@154..166 165 WHITESPACE@153..154 " "
166 [email protected] 166 [email protected]
167 [email protected] "&" 167 [email protected] "&"
168 [email protected] "mut" 168 [email protected] "mut"
@@ -224,17 +224,17 @@ [email protected]
224 [email protected] "u64" 224 [email protected] "u64"
225 [email protected] "," 225 [email protected] ","
226 [email protected] " " 226 [email protected] " "
227 ATT[email protected]1 227 PARAM@213..232
228 POUND@213..214 "#" 228 ATTR@213..221
229 WHITESPACE@214..215 " " 229 POUND@213..214 "#"
230 L_BRACK@215..216 "[" 230 WHITESPACE@214..215 " "
231 PATH@216..220 231 L_BRACK@215..216 "["
232 PATH_SEGMENT@216..220 232 [email protected]
233 NAME_REF@216..220 233 PATH_SEGMENT@216..220
234 IDENT@216..220 "attr" 234 NAME_REF@216..220
235 R_BRACK@220..221 "]" 235 IDENT@216..220 "attr"
236 WHITESPACE@221..222 " " 236 R_BRACK@220..221 "]"
237 PARAM@222..232 237 WHITESPACE@221..222 " "
238 [email protected] 238 [email protected]
239 [email protected] "mut" 239 [email protected] "mut"
240 [email protected] " " 240 [email protected] " "
@@ -271,16 +271,16 @@ [email protected]
271 [email protected] "f" 271 [email protected] "f"
272 [email protected] 272 [email protected]
273 [email protected] "(" 273 [email protected] "("
274 ATT[email protected]68 274 SELF_PARAM@257..273
275 POUND@257..258 "#" 275 ATTR@257..268
276 L_BRACK@258..259 "[" 276 POUND@257..258 "#"
277 PATH@259..267 277 L_BRACK@258..259 "["
278 PATH_SEGMENT@259..267 278 [email protected]
279 NAME_REF@259..267 279 PATH_SEGMENT@259..267
280 IDENT@259..267 "must_use" 280 NAME_REF@259..267
281 R_BRACK@267..268 "]" 281 IDENT@259..267 "must_use"
282 WHITESPACE@268..269 " " 282 R_BRACK@267..268 "]"
283 SELF_PARAM@269..273 283 WHITESPACE@268..269 " "
284 [email protected] "self" 284 [email protected] "self"
285 [email protected] ")" 285 [email protected] ")"
286 [email protected] " " 286 [email protected] " "
@@ -295,16 +295,16 @@ [email protected]
295 [email protected] "g1" 295 [email protected] "g1"
296 [email protected] 296 [email protected]
297 [email protected] "(" 297 [email protected] "("
298 ATTR@289..296 298 SELF_PARAM@289..301
299 POUND@289..290 "#" 299 ATTR@289..296
300 L_BRACK@290..291 "[" 300 POUND@289..290 "#"
301 PATH@291..295 301 L_BRACK@290..291 "["
302 PATH_SEGMENT@291..295 302 [email protected]
303 NAME_REF@291..295 303 PATH_SEGMENT@291..295
304 IDENT@291..295 "attr" 304 NAME_REF@291..295
305 R_BRACK@295..296 "]" 305 IDENT@291..295 "attr"
306 WHITESPACE@296..297 " " 306 R_BRACK@295..296 "]"
307 SELF_PARAM@297..301 307 WHITESPACE@296..297 " "
308 [email protected] "self" 308 [email protected] "self"
309 [email protected] ")" 309 [email protected] ")"
310 [email protected] " " 310 [email protected] " "
@@ -319,16 +319,16 @@ [email protected]
319 [email protected] "g2" 319 [email protected] "g2"
320 [email protected] 320 [email protected]
321 [email protected] "(" 321 [email protected] "("
322 ATT[email protected]24 322 SELF_PARAM@317..330
323 POUND@317..318 "#" 323 ATTR@317..324
324 L_BRACK@318..319 "[" 324 POUND@317..318 "#"
325 PATH@319..323 325 L_BRACK@318..319 "["
326 PATH_SEGMENT@319..323 326 [email protected]
327 NAME_REF@319..323 327 PATH_SEGMENT@319..323
328 IDENT@319..323 "attr" 328 NAME_REF@319..323
329 R_BRACK@323..324 "]" 329 IDENT@319..323 "attr"
330 WHITESPACE@324..325 " " 330 R_BRACK@323..324 "]"
331 SELF_PARAM@325..330 331 WHITESPACE@324..325 " "
332 [email protected] "&" 332 [email protected] "&"
333 [email protected] "self" 333 [email protected] "self"
334 [email protected] ")" 334 [email protected] ")"
@@ -350,16 +350,16 @@ [email protected]
350 [email protected] ">" 350 [email protected] ">"
351 [email protected] 351 [email protected]
352 [email protected] "(" 352 [email protected] "("
353 ATT[email protected]57 353 SELF_PARAM@350..367
354 POUND@350..351 "#" 354 ATTR@350..357
355 L_BRACK@351..352 "[" 355 POUND@350..351 "#"
356 PATH@352..356 356 L_BRACK@351..352 "["
357 PATH_SEGMENT@352..356 357 [email protected]
358 NAME_REF@352..356 358 PATH_SEGMENT@352..356
359 IDENT@352..356 "attr" 359 NAME_REF@352..356
360 R_BRACK@356..357 "]" 360 IDENT@352..356 "attr"
361 WHITESPACE@357..358 " " 361 R_BRACK@356..357 "]"
362 SELF_PARAM@358..367 362 WHITESPACE@357..358 " "
363 [email protected] "&" 363 [email protected] "&"
364 [email protected] "mut" 364 [email protected] "mut"
365 [email protected] " " 365 [email protected] " "
@@ -383,16 +383,16 @@ [email protected]
383 [email protected] ">" 383 [email protected] ">"
384 [email protected] 384 [email protected]
385 [email protected] "(" 385 [email protected] "("
386 ATTR@387..394 386 SELF_PARAM@387..403
387 POUND@387..388 "#" 387 ATTR@387..394
388 L_BRACK@388..389 "[" 388 POUND@387..388 "#"
389 PATH@389..393 389 L_BRACK@388..389 "["
390 PATH_SEGMENT@389..393 390 [email protected]
391 NAME_REF@389..393 391 PATH_SEGMENT@389..393
392 IDENT@389..393 "attr" 392 NAME_REF@389..393
393 R_BRACK@393..394 "]" 393 IDENT@389..393 "attr"
394 WHITESPACE@394..395 " " 394 R_BRACK@393..394 "]"
395 SELF_PARAM@395..403 395 WHITESPACE@394..395 " "
396 [email protected] "&" 396 [email protected] "&"
397 [email protected] 397 [email protected]
398 [email protected] "\'a" 398 [email protected] "\'a"
@@ -417,16 +417,16 @@ [email protected]
417 [email protected] ">" 417 [email protected] ">"
418 [email protected] 418 [email protected]
419 [email protected] "(" 419 [email protected] "("
420 ATT[email protected]0 420 SELF_PARAM@423..443
421 POUND@423..424 "#" 421 ATTR@423..430
422 L_BRACK@424..425 "[" 422 POUND@423..424 "#"
423 PATH@425..429 423 L_BRACK@424..425 "["
424 PATH_SEGMENT@425..429 424 [email protected]
425 NAME_REF@425..429 425 PATH_SEGMENT@425..429
426 IDENT@425..429 "attr" 426 NAME_REF@425..429
427 R_BRACK@429..430 "]" 427 IDENT@425..429 "attr"
428 WHITESPACE@430..431 " " 428 R_BRACK@429..430 "]"
429 SELF_PARAM@431..443 429 WHITESPACE@430..431 " "
430 [email protected] "&" 430 [email protected] "&"
431 [email protected] 431 [email protected]
432 [email protected] "\'a" 432 [email protected] "\'a"
@@ -447,16 +447,16 @@ [email protected]
447 [email protected] "c" 447 [email protected] "c"
448 [email protected] 448 [email protected]
449 [email protected] "(" 449 [email protected] "("
450 ATT[email protected]5 450 SELF_PARAM@458..476
451 POUND@458..459 "#" 451 ATTR@458..465
452 L_BRACK@459..460 "[" 452 POUND@458..459 "#"
453 PATH@460..464 453 L_BRACK@459..460 "["
454 PATH_SEGMENT@460..464 454 [email protected]
455 NAME_REF@460..464 455 PATH_SEGMENT@460..464
456 IDENT@460..464 "attr" 456 NAME_REF@460..464
457 R_BRACK@464..465 "]" 457 IDENT@460..464 "attr"
458 WHITESPACE@465..466 " " 458 R_BRACK@464..465 "]"
459 SELF_PARAM@466..476 459 WHITESPACE@465..466 " "
460 [email protected] "self" 460 [email protected] "self"
461 [email protected] ":" 461 [email protected] ":"
462 [email protected] " " 462 [email protected] " "
@@ -478,16 +478,16 @@ [email protected]
478 [email protected] "d" 478 [email protected] "d"
479 [email protected] 479 [email protected]
480 [email protected] "(" 480 [email protected] "("
481 ATTR@491..498 481 SELF_PARAM@491..513
482 POUND@491..492 "#" 482 ATTR@491..498
483 L_BRACK@492..493 "[" 483 POUND@491..492 "#"
484 PATH@493..497 484 L_BRACK@492..493 "["
485 PATH_SEGMENT@493..497 485 [email protected]
486 NAME_REF@493..497 486 PATH_SEGMENT@493..497
487 IDENT@493..497 "attr" 487 NAME_REF@493..497
488 R_BRACK@497..498 "]" 488 IDENT@493..497 "attr"
489 WHITESPACE@498..499 " " 489 R_BRACK@497..498 "]"
490 SELF_PARAM@499..513 490 WHITESPACE@498..499 " "
491 [email protected] "self" 491 [email protected] "self"
492 [email protected] ":" 492 [email protected] ":"
493 [email protected] " " 493 [email protected] " "
diff --git a/crates/syntax/test_data/parser/ok/0063_variadic_fun.rast b/crates/syntax/test_data/parser/ok/0063_variadic_fun.rast
index 4009b3ff8..f7c094898 100644
--- a/crates/syntax/test_data/parser/ok/0063_variadic_fun.rast
+++ b/crates/syntax/test_data/parser/ok/0063_variadic_fun.rast
@@ -92,20 +92,20 @@ [email protected]
92 [email protected] "u8" 92 [email protected] "u8"
93 [email protected] "," 93 [email protected] ","
94 [email protected] " " 94 [email protected] " "
95 ATT[email protected]5 95 PARAM@92..120
96 POUND@92..93 "#" 96 ATTR@92..105
97 L_BRACK@93..94 "[" 97 POUND@92..93 "#"
98 PATH@94..97 98 L_BRACK@93..94 "["
99 PATH_SEGMENT@94..97 99 [email protected]
100 NAME_REF@94..97 100 PATH_SEGMENT@94..97
101 IDENT@94..97 "cfg" 101 NAME_REF@94..97
102 TOKEN_TREE@97..104 102 IDENT@94..97 "cfg"
103 L_PAREN@97..98 "(" 103 TOKEN_TREE@97..104
104 IDENT@98..103 "never" 104 L_PAREN@97..98 "("
105 R_PAREN@103..104 ")" 105 IDENT@98..103 "never"
106 R_BRACK@104..105 "]" 106 R_PAREN@103..104 ")"
107 WHITESPACE@105..106 " " 107 R_BRACK@104..105 "]"
108 PARAM@106..120 108 WHITESPACE@105..106 " "
109 [email protected] 109 [email protected]
110 [email protected] "[" 110 [email protected] "["
111 [email protected] 111 [email protected]
diff --git a/docs/user/generated_config.adoc b/docs/user/generated_config.adoc
index cb2ae6fc1..3025dc8d6 100644
--- a/docs/user/generated_config.adoc
+++ b/docs/user/generated_config.adoc
@@ -5,7 +5,7 @@ rust-analyzer.assist.importPrefix (default: `"plain"`)::
5rust-analyzer.callInfo.full (default: `true`):: 5rust-analyzer.callInfo.full (default: `true`)::
6 Show function name and docs in parameter hints. 6 Show function name and docs in parameter hints.
7rust-analyzer.cargo.autoreload (default: `true`):: 7rust-analyzer.cargo.autoreload (default: `true`)::
8 Automatically refresh project info via `cargo metadata` on Cargo.toml changes. 8 Automatically refresh project info via `cargo metadata` on `Cargo.toml` changes.
9rust-analyzer.cargo.allFeatures (default: `false`):: 9rust-analyzer.cargo.allFeatures (default: `false`)::
10 Activate all available features. 10 Activate all available features.
11rust-analyzer.cargo.features (default: `[]`):: 11rust-analyzer.cargo.features (default: `[]`)::
@@ -21,7 +21,7 @@ rust-analyzer.cargo.noSysroot (default: `false`)::
21rust-analyzer.checkOnSave.enable (default: `true`):: 21rust-analyzer.checkOnSave.enable (default: `true`)::
22 Run specified `cargo check` command for diagnostics on save. 22 Run specified `cargo check` command for diagnostics on save.
23rust-analyzer.checkOnSave.allFeatures (default: `null`):: 23rust-analyzer.checkOnSave.allFeatures (default: `null`)::
24 Check with all features (will be passed as `--all-features`). Defaults to `rust-analyzer.cargo.allFeatures`. 24 Check with all features (will be passed as `--all-features`). Defaults to `#rust-analyzer.cargo.allFeatures#`.
25rust-analyzer.checkOnSave.allTargets (default: `true`):: 25rust-analyzer.checkOnSave.allTargets (default: `true`)::
26 Check all targets and tests (will be passed as `--all-targets`). 26 Check all targets and tests (will be passed as `--all-targets`).
27rust-analyzer.checkOnSave.command (default: `"check"`):: 27rust-analyzer.checkOnSave.command (default: `"check"`)::
@@ -29,11 +29,11 @@ rust-analyzer.checkOnSave.command (default: `"check"`)::
29rust-analyzer.checkOnSave.noDefaultFeatures (default: `null`):: 29rust-analyzer.checkOnSave.noDefaultFeatures (default: `null`)::
30 Do not activate the `default` feature. 30 Do not activate the `default` feature.
31rust-analyzer.checkOnSave.target (default: `null`):: 31rust-analyzer.checkOnSave.target (default: `null`)::
32 Check for a specific target. Defaults to `rust-analyzer.cargo.target`. 32 Check for a specific target. Defaults to `#rust-analyzer.cargo.target#`.
33rust-analyzer.checkOnSave.extraArgs (default: `[]`):: 33rust-analyzer.checkOnSave.extraArgs (default: `[]`)::
34 Extra arguments for `cargo check`. 34 Extra arguments for `cargo check`.
35rust-analyzer.checkOnSave.features (default: `null`):: 35rust-analyzer.checkOnSave.features (default: `null`)::
36 List of features to activate. Defaults to `rust-analyzer.cargo.features`. 36 List of features to activate. Defaults to `#rust-analyzer.cargo.features#`.
37rust-analyzer.checkOnSave.overrideCommand (default: `null`):: 37rust-analyzer.checkOnSave.overrideCommand (default: `null`)::
38 Advanced option, fully override the command rust-analyzer uses for checking. The command should include `--message-format=json` or similar option. 38 Advanced option, fully override the command rust-analyzer uses for checking. The command should include `--message-format=json` or similar option.
39rust-analyzer.completion.addCallArgumentSnippets (default: `true`):: 39rust-analyzer.completion.addCallArgumentSnippets (default: `true`)::
@@ -43,7 +43,7 @@ rust-analyzer.completion.addCallParenthesis (default: `true`)::
43rust-analyzer.completion.postfix.enable (default: `true`):: 43rust-analyzer.completion.postfix.enable (default: `true`)::
44 Whether to show postfix snippets like `dbg`, `if`, `not`, etc. 44 Whether to show postfix snippets like `dbg`, `if`, `not`, etc.
45rust-analyzer.completion.autoimport.enable (default: `true`):: 45rust-analyzer.completion.autoimport.enable (default: `true`)::
46 Toggles the additional completions that automatically add imports when completed. Note that your client have to specify the `additionalTextEdits` LSP client capability to truly have this feature enabled. 46 Toggles the additional completions that automatically add imports when completed. Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
47rust-analyzer.diagnostics.enable (default: `true`):: 47rust-analyzer.diagnostics.enable (default: `true`)::
48 Whether to show native rust-analyzer diagnostics. 48 Whether to show native rust-analyzer diagnostics.
49rust-analyzer.diagnostics.enableExperimental (default: `true`):: 49rust-analyzer.diagnostics.enableExperimental (default: `true`)::
@@ -51,9 +51,9 @@ rust-analyzer.diagnostics.enableExperimental (default: `true`)::
51rust-analyzer.diagnostics.disabled (default: `[]`):: 51rust-analyzer.diagnostics.disabled (default: `[]`)::
52 List of rust-analyzer diagnostics to disable. 52 List of rust-analyzer diagnostics to disable.
53rust-analyzer.diagnostics.warningsAsHint (default: `[]`):: 53rust-analyzer.diagnostics.warningsAsHint (default: `[]`)::
54 List of warnings that should be displayed with info severity.\nThe warnings will be indicated by a blue squiggly underline in code and a blue icon in the problems panel. 54 List of warnings that should be displayed with info severity.\n\nThe warnings will be indicated by a blue squiggly underline in code and a blue icon in the `Problems Panel`.
55rust-analyzer.diagnostics.warningsAsInfo (default: `[]`):: 55rust-analyzer.diagnostics.warningsAsInfo (default: `[]`)::
56 List of warnings that should be displayed with hint severity.\nThe warnings will be indicated by faded text or three dots in code and will not show up in the problems panel. 56 List of warnings that should be displayed with hint severity.\n\nThe warnings will be indicated by faded text or three dots in code and will not show up in the `Problems Panel`.
57rust-analyzer.files.watcher (default: `"client"`):: 57rust-analyzer.files.watcher (default: `"client"`)::
58 Controls file watching implementation. 58 Controls file watching implementation.
59rust-analyzer.hoverActions.debug (default: `true`):: 59rust-analyzer.hoverActions.debug (default: `true`)::
@@ -71,7 +71,7 @@ rust-analyzer.hoverActions.linksInHover (default: `true`)::
71rust-analyzer.inlayHints.chainingHints (default: `true`):: 71rust-analyzer.inlayHints.chainingHints (default: `true`)::
72 Whether to show inlay type hints for method chains. 72 Whether to show inlay type hints for method chains.
73rust-analyzer.inlayHints.maxLength (default: `null`):: 73rust-analyzer.inlayHints.maxLength (default: `null`)::
74 Maximum length for inlay hints. 74 Maximum length for inlay hints. Default is unlimited.
75rust-analyzer.inlayHints.parameterHints (default: `true`):: 75rust-analyzer.inlayHints.parameterHints (default: `true`)::
76 Whether to show function parameter name inlay hints at the call site. 76 Whether to show function parameter name inlay hints at the call site.
77rust-analyzer.inlayHints.typeHints (default: `true`):: 77rust-analyzer.inlayHints.typeHints (default: `true`)::
@@ -87,20 +87,20 @@ rust-analyzer.lens.run (default: `true`)::
87rust-analyzer.lens.methodReferences (default: `false`):: 87rust-analyzer.lens.methodReferences (default: `false`)::
88 Whether to show `Method References` lens. Only applies when `#rust-analyzer.lens.enable#` is set. 88 Whether to show `Method References` lens. Only applies when `#rust-analyzer.lens.enable#` is set.
89rust-analyzer.linkedProjects (default: `[]`):: 89rust-analyzer.linkedProjects (default: `[]`)::
90 Disable project auto-discovery in favor of explicitly specified set of projects. \nElements must be paths pointing to Cargo.toml, rust-project.json, or JSON objects in rust-project.json format. 90 Disable project auto-discovery in favor of explicitly specified set of projects.\n\nElements must be paths pointing to `Cargo.toml`, `rust-project.json`, or JSON objects in `rust-project.json` format.
91rust-analyzer.lruCapacity (default: `null`):: 91rust-analyzer.lruCapacity (default: `null`)::
92 Number of syntax trees rust-analyzer keeps in memory. 92 Number of syntax trees rust-analyzer keeps in memory. Defaults to 128.
93rust-analyzer.notifications.cargoTomlNotFound (default: `true`):: 93rust-analyzer.notifications.cargoTomlNotFound (default: `true`)::
94 Whether to show `can't find Cargo.toml` error message. 94 Whether to show `can't find Cargo.toml` error message.
95rust-analyzer.procMacro.enable (default: `false`):: 95rust-analyzer.procMacro.enable (default: `false`)::
96 Enable Proc macro support, cargo.loadOutDirsFromCheck must be enabled. 96 Enable Proc macro support, `#rust-analyzer.cargo.loadOutDirsFromCheck#` must be enabled.
97rust-analyzer.runnables.overrideCargo (default: `null`):: 97rust-analyzer.runnables.overrideCargo (default: `null`)::
98 Command to be executed instead of 'cargo' for runnables. 98 Command to be executed instead of 'cargo' for runnables.
99rust-analyzer.runnables.cargoExtraArgs (default: `[]`):: 99rust-analyzer.runnables.cargoExtraArgs (default: `[]`)::
100 Additional arguments to be passed to cargo for runnables such as tests or binaries.\nFor example, it may be '--release'. 100 Additional arguments to be passed to cargo for runnables such as tests or binaries.\nFor example, it may be `--release`.
101rust-analyzer.rustcSource (default: `null`):: 101rust-analyzer.rustcSource (default: `null`)::
102 Path to the rust compiler sources, for usage in rustc_private projects. 102 Path to the rust compiler sources, for usage in rustc_private projects.
103rust-analyzer.rustfmt.extraArgs (default: `[]`):: 103rust-analyzer.rustfmt.extraArgs (default: `[]`)::
104 Additional arguments to rustfmt. 104 Additional arguments to `rustfmt`.
105rust-analyzer.rustfmt.overrideCommand (default: `null`):: 105rust-analyzer.rustfmt.overrideCommand (default: `null`)::
106 Advanced option, fully override the command rust-analyzer uses for formatting. 106 Advanced option, fully override the command rust-analyzer uses for formatting.
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index 1ec6e81bb..40f10972f 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -46,8 +46,8 @@ You can install the latest release of the plugin from
46https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer[the marketplace]. 46https://marketplace.visualstudio.com/items?itemName=matklad.rust-analyzer[the marketplace].
47 47
48Note that the plugin may cause conflicts with the 48Note that the plugin may cause conflicts with the
49https://marketplace.visualstudio.com/items?itemName=rust-lang.rust[official Rust plugin]. It is 49https://marketplace.visualstudio.com/items?itemName=rust-lang.rust[official Rust plugin].
50recommended to disable the Rust plugin when using the rust-analyzer extension. 50It is recommended to disable the Rust plugin when using the rust-analyzer extension.
51 51
52By default, the plugin will prompt you to download the matching version of the server as well: 52By default, the plugin will prompt you to download the matching version of the server as well:
53 53
@@ -74,18 +74,21 @@ Note that we only support two most recent versions of VS Code.
74 74
75==== Updates 75==== Updates
76 76
77The extension will be updated automatically as new versions become available. It will ask your permission to download the matching language server version binary if needed. 77The extension will be updated automatically as new versions become available.
78It will ask your permission to download the matching language server version binary if needed.
78 79
79===== Nightly 80===== Nightly
80 81
81We ship nightly releases for VS Code. To help us out with testing the newest code and follow the bleeding edge of our `master`, please use the following config: 82We ship nightly releases for VS Code.
83To help us out with testing the newest code and follow the bleeding edge of our `master`, please use the following config:
82 84
83[source,json] 85[source,json]
84---- 86----
85{ "rust-analyzer.updates.channel": "nightly" } 87{ "rust-analyzer.updates.channel": "nightly" }
86---- 88----
87 89
88You will be prompted to install the `nightly` extension version. Just click `Download now` and from that moment you will get automatic updates every 24 hours. 90You will be prompted to install the `nightly` extension version.
91Just click `Download now` and from that moment you will get automatic updates every 24 hours.
89 92
90If you don't want to be asked for `Download now` every day when the new nightly version is released add the following to your `settings.json`: 93If you don't want to be asked for `Download now` every day when the new nightly version is released add the following to your `settings.json`:
91[source,json] 94[source,json]
@@ -160,7 +163,8 @@ $ chmod +x ~/.local/bin/rust-analyzer
160 163
161Ensure `~/.local/bin` is listed in the `$PATH` variable. 164Ensure `~/.local/bin` is listed in the `$PATH` variable.
162 165
163Alternatively, you can install it from source using the following command: 166Alternatively, you can install it from source using the command below.
167You'll need the latest stable version of the Rust toolchain.
164 168
165[source,bash] 169[source,bash]
166---- 170----
@@ -198,7 +202,8 @@ Emacs support is maintained as part of the https://github.com/emacs-lsp/lsp-mode
198 202
199=== Vim/NeoVim 203=== Vim/NeoVim
200 204
201Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>. Not needed if the extension can install/update it on its own, coc-rust-analyzer is one example. 205Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>.
206Not needed if the extension can install/update it on its own, coc-rust-analyzer is one example.
202 207
203The are several LSP client implementations for vim or neovim: 208The are several LSP client implementations for vim or neovim:
204 209
@@ -270,14 +275,16 @@ Once `neovim/nvim-lspconfig` is installed, use `+lua require'nvim_lsp'.rust_anal
270 275
271Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>. 276Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>.
272 277
273You also need the `LSP` package. To install it: 278You also need the `LSP` package.
279To install it:
274 280
2751. If you've never installed a Sublime Text package, install Package Control: 2811. If you've never installed a Sublime Text package, install Package Control:
276 * Open the command palette (Win/Linux: `ctrl+shift+p`, Mac: `cmd+shift+p`) 282 * Open the command palette (Win/Linux: `ctrl+shift+p`, Mac: `cmd+shift+p`)
277 * Type `Install Package Control`, press enter 283 * Type `Install Package Control`, press enter
2782. In the command palette, run `Package control: Install package`, and in the list that pops up, type `LSP` and press enter. 2842. In the command palette, run `Package control: Install package`, and in the list that pops up, type `LSP` and press enter.
279 285
280Finally, with your Rust project open, in the command palette, run `LSP: Enable Language Server In Project` or `LSP: Enable Language Server Globally`, then select `rust-analyzer` in the list that pops up to enable the rust-analyzer LSP. The latter means that rust-analyzer is enabled by default in Rust projects. 286Finally, with your Rust project open, in the command palette, run `LSP: Enable Language Server In Project` or `LSP: Enable Language Server Globally`, then select `rust-analyzer` in the list that pops up to enable the rust-analyzer LSP.
287The latter means that rust-analyzer is enabled by default in Rust projects.
281 288
282If it worked, you should see "rust-analyzer, Line X, Column Y" on the left side of the bottom bar, and after waiting a bit, functionality like tooltips on hovering over variables should become available. 289If it worked, you should see "rust-analyzer, Line X, Column Y" on the left side of the bottom bar, and after waiting a bit, functionality like tooltips on hovering over variables should become available.
283 290
@@ -285,7 +292,8 @@ If you get an error saying `No such file or directory: 'rust-analyzer'`, see the
285 292
286=== GNOME Builder 293=== GNOME Builder
287 294
288GNOME Builder 3.37.1 and newer has native `rust-analyzer` support. If the LSP binary is not available, GNOME Builder can install it when opening a Rust file. 295GNOME Builder 3.37.1 and newer has native `rust-analyzer` support.
296If the LSP binary is not available, GNOME Builder can install it when opening a Rust file.
289 297
290== Configuration 298== Configuration
291 299
@@ -413,8 +421,8 @@ include::./generated_diagnostic.adoc[]
413 421
414==== Color configurations 422==== Color configurations
415 423
416It is possible to change the foreground/background color of inlay hints. Just add this to your 424It is possible to change the foreground/background color of inlay hints.
417`settings.json`: 425Just add this to your `settings.json`:
418 426
419[source,jsonc] 427[source,jsonc]
420---- 428----
@@ -436,7 +444,8 @@ It is possible to change the foreground/background color of inlay hints. Just ad
436 444
437==== Semantic style customizations 445==== Semantic style customizations
438 446
439You can customize the look of different semantic elements in the source code. For example, mutable bindings are underlined by default and you can override this behavior by adding the following section to your `settings.json`: 447You can customize the look of different semantic elements in the source code.
448For example, mutable bindings are underlined by default and you can override this behavior by adding the following section to your `settings.json`:
440 449
441[source,jsonc] 450[source,jsonc]
442---- 451----
@@ -452,7 +461,9 @@ You can customize the look of different semantic elements in the source code. Fo
452---- 461----
453 462
454==== Special `when` clause context for keybindings. 463==== Special `when` clause context for keybindings.
455You may use `inRustProject` context to configure keybindings for rust projects only. For example: 464You may use `inRustProject` context to configure keybindings for rust projects only.
465For example:
466
456[source,json] 467[source,json]
457---- 468----
458{ 469{
@@ -491,7 +502,8 @@ Or it is possible to specify vars more granularly:
491] 502]
492``` 503```
493 504
494You can use any valid RegExp as a mask. Also note that a full runnable name is something like *run bin_or_example_name*, *test some::mod::test_name* or *test-mod some::mod*, so it is possible to distinguish binaries, single tests, and test modules with this masks: `"^run"`, `"^test "` (the trailing space matters!), and `"^test-mod"` respectively. 505You can use any valid regular expression as a mask.
506Also note that a full runnable name is something like *run bin_or_example_name*, *test some::mod::test_name* or *test-mod some::mod*, so it is possible to distinguish binaries, single tests, and test modules with this masks: `"^run"`, `"^test "` (the trailing space matters!), and `"^test-mod"` respectively.
495 507
496==== Compiler feedback from external commands 508==== Compiler feedback from external commands
497 509
diff --git a/editors/code/.vscodeignore b/editors/code/.vscodeignore
index 5096ce4da..c1cf00fa0 100644
--- a/editors/code/.vscodeignore
+++ b/editors/code/.vscodeignore
@@ -4,6 +4,5 @@
4!package.json 4!package.json
5!package-lock.json 5!package-lock.json
6!ra_syntax_tree.tmGrammar.json 6!ra_syntax_tree.tmGrammar.json
7!rust.tmGrammar.json
8!icon.png 7!icon.png
9!README.md 8!README.md
diff --git a/editors/code/package.json b/editors/code/package.json
index ad01fea7b..13749a084 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -250,12 +250,12 @@
250 } 250 }
251 ], 251 ],
252 "default": null, 252 "default": null,
253 "description": "Environment variables passed to the runnable launched using `Test ` or `Debug` lens or `rust-analyzer.run` command." 253 "markdownDescription": "Environment variables passed to the runnable launched using `Test` or `Debug` lens or `rust-analyzer.run` command."
254 }, 254 },
255 "rust-analyzer.inlayHints.enable": { 255 "rust-analyzer.inlayHints.enable": {
256 "type": "boolean", 256 "type": "boolean",
257 "default": true, 257 "default": true,
258 "description": "Whether to show inlay hints" 258 "description": "Whether to show inlay hints."
259 }, 259 },
260 "rust-analyzer.updates.channel": { 260 "rust-analyzer.updates.channel": {
261 "type": "string", 261 "type": "string",
@@ -265,15 +265,15 @@
265 ], 265 ],
266 "default": "stable", 266 "default": "stable",
267 "markdownEnumDescriptions": [ 267 "markdownEnumDescriptions": [
268 "`\"stable\"` updates are shipped weekly, they don't contain cutting-edge features from VSCode proposed APIs but have less bugs in general", 268 "`stable` updates are shipped weekly, they don't contain cutting-edge features from VSCode proposed APIs but have less bugs in general.",
269 "`\"nightly\"` updates are shipped daily (extension updates automatically by downloading artifacts directly from GitHub), they contain cutting-edge features and latest bug fixes. These releases help us get your feedback very quickly and speed up rust-analyzer development **drastically**" 269 "`nightly` updates are shipped daily (extension updates automatically by downloading artifacts directly from GitHub), they contain cutting-edge features and latest bug fixes. These releases help us get your feedback very quickly and speed up rust-analyzer development **drastically**."
270 ], 270 ],
271 "markdownDescription": "Choose `\"nightly\"` updates to get the latest features and bug fixes every day. While `\"stable\"` releases occur weekly and don't contain cutting-edge features from VSCode proposed APIs" 271 "markdownDescription": "Choose `nightly` updates to get the latest features and bug fixes every day. While `stable` releases occur weekly and don't contain cutting-edge features from VSCode proposed APIs."
272 }, 272 },
273 "rust-analyzer.updates.askBeforeDownload": { 273 "rust-analyzer.updates.askBeforeDownload": {
274 "type": "boolean", 274 "type": "boolean",
275 "default": true, 275 "default": true,
276 "description": "Whether to ask for permission before downloading any files from the Internet" 276 "description": "Whether to ask for permission before downloading any files from the Internet."
277 }, 277 },
278 "rust-analyzer.serverPath": { 278 "rust-analyzer.serverPath": {
279 "type": [ 279 "type": [
@@ -281,7 +281,7 @@
281 "string" 281 "string"
282 ], 282 ],
283 "default": null, 283 "default": null,
284 "description": "Path to rust-analyzer executable (points to bundled binary by default). If this is set, then \"rust-analyzer.updates.channel\" setting is not used" 284 "markdownDescription": "Path to rust-analyzer executable (points to bundled binary by default). If this is set, then `#rust-analyzer.updates.channel#` setting is not used"
285 }, 285 },
286 "rust-analyzer.trace.server": { 286 "rust-analyzer.trace.server": {
287 "type": "string", 287 "type": "string",
@@ -297,10 +297,10 @@
297 "Full log" 297 "Full log"
298 ], 298 ],
299 "default": "off", 299 "default": "off",
300 "description": "Trace requests to the rust-analyzer (this is usually overly verbose and not recommended for regular users)" 300 "description": "Trace requests to the rust-analyzer (this is usually overly verbose and not recommended for regular users)."
301 }, 301 },
302 "rust-analyzer.trace.extension": { 302 "rust-analyzer.trace.extension": {
303 "description": "Enable logging of VS Code extensions itself", 303 "description": "Enable logging of VS Code extensions itself.",
304 "type": "boolean", 304 "type": "boolean",
305 "default": false 305 "default": false
306 }, 306 },
@@ -327,14 +327,14 @@
327 } 327 }
328 }, 328 },
329 "rust-analyzer.debug.openDebugPane": { 329 "rust-analyzer.debug.openDebugPane": {
330 "description": "Whether to open up the Debug Pane on debugging start.", 330 "markdownDescription": "Whether to open up the `Debug Panel` on debugging start.",
331 "type": "boolean", 331 "type": "boolean",
332 "default": false 332 "default": false
333 }, 333 },
334 "rust-analyzer.debug.engineSettings": { 334 "rust-analyzer.debug.engineSettings": {
335 "type": "object", 335 "type": "object",
336 "default": {}, 336 "default": {},
337 "description": "Optional settings passed to the debug engine. Example:\n{ \"lldb\": { \"terminal\":\"external\"} }" 337 "markdownDescription": "Optional settings passed to the debug engine. Example: `{ \"lldb\": { \"terminal\":\"external\"} }`"
338 }, 338 },
339 "rust-analyzer.assist.importMergeBehaviour": { 339 "rust-analyzer.assist.importMergeBehaviour": {
340 "markdownDescription": "The strategy to use when inserting new imports or merging imports.", 340 "markdownDescription": "The strategy to use when inserting new imports or merging imports.",
@@ -362,7 +362,7 @@
362 ], 362 ],
363 "enumDescriptions": [ 363 "enumDescriptions": [
364 "Insert import paths relative to the current module, using up to one `super` prefix if the parent module contains the requested item.", 364 "Insert import paths relative to the current module, using up to one `super` prefix if the parent module contains the requested item.",
365 "Prefix all import paths with `self` if they don't begin with `self`, `super`, `crate` or a crate name", 365 "Prefix all import paths with `self` if they don't begin with `self`, `super`, `crate` or a crate name.",
366 "Force import paths to be absolute by always starting them with `crate` or the crate name they refer to." 366 "Force import paths to be absolute by always starting them with `crate` or the crate name they refer to."
367 ] 367 ]
368 }, 368 },
@@ -372,7 +372,7 @@
372 "type": "boolean" 372 "type": "boolean"
373 }, 373 },
374 "rust-analyzer.cargo.autoreload": { 374 "rust-analyzer.cargo.autoreload": {
375 "markdownDescription": "Automatically refresh project info via `cargo metadata` on Cargo.toml changes.", 375 "markdownDescription": "Automatically refresh project info via `cargo metadata` on `Cargo.toml` changes.",
376 "default": true, 376 "default": true,
377 "type": "boolean" 377 "type": "boolean"
378 }, 378 },
@@ -418,7 +418,7 @@
418 "type": "boolean" 418 "type": "boolean"
419 }, 419 },
420 "rust-analyzer.checkOnSave.allFeatures": { 420 "rust-analyzer.checkOnSave.allFeatures": {
421 "markdownDescription": "Check with all features (will be passed as `--all-features`). Defaults to `rust-analyzer.cargo.allFeatures`.", 421 "markdownDescription": "Check with all features (will be passed as `--all-features`). Defaults to `#rust-analyzer.cargo.allFeatures#`.",
422 "default": null, 422 "default": null,
423 "type": [ 423 "type": [
424 "null", 424 "null",
@@ -444,7 +444,7 @@
444 ] 444 ]
445 }, 445 },
446 "rust-analyzer.checkOnSave.target": { 446 "rust-analyzer.checkOnSave.target": {
447 "markdownDescription": "Check for a specific target. Defaults to `rust-analyzer.cargo.target`.", 447 "markdownDescription": "Check for a specific target. Defaults to `#rust-analyzer.cargo.target#`.",
448 "default": null, 448 "default": null,
449 "type": [ 449 "type": [
450 "null", 450 "null",
@@ -460,7 +460,7 @@
460 } 460 }
461 }, 461 },
462 "rust-analyzer.checkOnSave.features": { 462 "rust-analyzer.checkOnSave.features": {
463 "markdownDescription": "List of features to activate. Defaults to `rust-analyzer.cargo.features`.", 463 "markdownDescription": "List of features to activate. Defaults to `#rust-analyzer.cargo.features#`.",
464 "default": null, 464 "default": null,
465 "type": [ 465 "type": [
466 "null", 466 "null",
@@ -497,7 +497,7 @@
497 "type": "boolean" 497 "type": "boolean"
498 }, 498 },
499 "rust-analyzer.completion.autoimport.enable": { 499 "rust-analyzer.completion.autoimport.enable": {
500 "markdownDescription": "Toggles the additional completions that automatically add imports when completed. Note that your client have to specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.", 500 "markdownDescription": "Toggles the additional completions that automatically add imports when completed. Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.",
501 "default": true, 501 "default": true,
502 "type": "boolean" 502 "type": "boolean"
503 }, 503 },
@@ -521,7 +521,7 @@
521 "uniqueItems": true 521 "uniqueItems": true
522 }, 522 },
523 "rust-analyzer.diagnostics.warningsAsHint": { 523 "rust-analyzer.diagnostics.warningsAsHint": {
524 "markdownDescription": "List of warnings that should be displayed with info severity.\\nThe warnings will be indicated by a blue squiggly underline in code and a blue icon in the problems panel.", 524 "markdownDescription": "List of warnings that should be displayed with info severity.\\n\\nThe warnings will be indicated by a blue squiggly underline in code and a blue icon in the `Problems Panel`.",
525 "default": [], 525 "default": [],
526 "type": "array", 526 "type": "array",
527 "items": { 527 "items": {
@@ -529,7 +529,7 @@
529 } 529 }
530 }, 530 },
531 "rust-analyzer.diagnostics.warningsAsInfo": { 531 "rust-analyzer.diagnostics.warningsAsInfo": {
532 "markdownDescription": "List of warnings that should be displayed with hint severity.\\nThe warnings will be indicated by faded text or three dots in code and will not show up in the problems panel.", 532 "markdownDescription": "List of warnings that should be displayed with hint severity.\\n\\nThe warnings will be indicated by faded text or three dots in code and will not show up in the `Problems Panel`.",
533 "default": [], 533 "default": [],
534 "type": "array", 534 "type": "array",
535 "items": { 535 "items": {
@@ -577,7 +577,7 @@
577 "type": "boolean" 577 "type": "boolean"
578 }, 578 },
579 "rust-analyzer.inlayHints.maxLength": { 579 "rust-analyzer.inlayHints.maxLength": {
580 "markdownDescription": "Maximum length for inlay hints.", 580 "markdownDescription": "Maximum length for inlay hints. Default is unlimited.",
581 "default": null, 581 "default": null,
582 "type": [ 582 "type": [
583 "null", 583 "null",
@@ -621,7 +621,7 @@
621 "type": "boolean" 621 "type": "boolean"
622 }, 622 },
623 "rust-analyzer.linkedProjects": { 623 "rust-analyzer.linkedProjects": {
624 "markdownDescription": "Disable project auto-discovery in favor of explicitly specified set of projects. \\nElements must be paths pointing to Cargo.toml, rust-project.json, or JSON objects in rust-project.json format.", 624 "markdownDescription": "Disable project auto-discovery in favor of explicitly specified set of projects.\\n\\nElements must be paths pointing to `Cargo.toml`, `rust-project.json`, or JSON objects in `rust-project.json` format.",
625 "default": [], 625 "default": [],
626 "type": "array", 626 "type": "array",
627 "items": { 627 "items": {
@@ -632,7 +632,7 @@
632 } 632 }
633 }, 633 },
634 "rust-analyzer.lruCapacity": { 634 "rust-analyzer.lruCapacity": {
635 "markdownDescription": "Number of syntax trees rust-analyzer keeps in memory.", 635 "markdownDescription": "Number of syntax trees rust-analyzer keeps in memory. Defaults to 128.",
636 "default": null, 636 "default": null,
637 "type": [ 637 "type": [
638 "null", 638 "null",
@@ -646,7 +646,7 @@
646 "type": "boolean" 646 "type": "boolean"
647 }, 647 },
648 "rust-analyzer.procMacro.enable": { 648 "rust-analyzer.procMacro.enable": {
649 "markdownDescription": "Enable Proc macro support, cargo.loadOutDirsFromCheck must be enabled.", 649 "markdownDescription": "Enable Proc macro support, `#rust-analyzer.cargo.loadOutDirsFromCheck#` must be enabled.",
650 "default": false, 650 "default": false,
651 "type": "boolean" 651 "type": "boolean"
652 }, 652 },
@@ -659,7 +659,7 @@
659 ] 659 ]
660 }, 660 },
661 "rust-analyzer.runnables.cargoExtraArgs": { 661 "rust-analyzer.runnables.cargoExtraArgs": {
662 "markdownDescription": "Additional arguments to be passed to cargo for runnables such as tests or binaries.\\nFor example, it may be '--release'.", 662 "markdownDescription": "Additional arguments to be passed to cargo for runnables such as tests or binaries.\\nFor example, it may be `--release`.",
663 "default": [], 663 "default": [],
664 "type": "array", 664 "type": "array",
665 "items": { 665 "items": {
@@ -675,7 +675,7 @@
675 ] 675 ]
676 }, 676 },
677 "rust-analyzer.rustfmt.extraArgs": { 677 "rust-analyzer.rustfmt.extraArgs": {
678 "markdownDescription": "Additional arguments to rustfmt.", 678 "markdownDescription": "Additional arguments to `rustfmt`.",
679 "default": [], 679 "default": [],
680 "type": "array", 680 "type": "array",
681 "items": { 681 "items": {
@@ -749,11 +749,6 @@
749 ], 749 ],
750 "grammars": [ 750 "grammars": [
751 { 751 {
752 "language": "rust",
753 "scopeName": "source.rust",
754 "path": "rust.tmGrammar.json"
755 },
756 {
757 "language": "ra_syntax_tree", 752 "language": "ra_syntax_tree",
758 "scopeName": "source.ra_syntax_tree", 753 "scopeName": "source.ra_syntax_tree",
759 "path": "ra_syntax_tree.tmGrammar.json" 754 "path": "ra_syntax_tree.tmGrammar.json"
diff --git a/editors/code/rust.tmGrammar.json b/editors/code/rust.tmGrammar.json
deleted file mode 100644
index 4759bb116..000000000
--- a/editors/code/rust.tmGrammar.json
+++ /dev/null
@@ -1,1140 +0,0 @@
1{
2 "$schema": "https://raw.githubusercontent.com/martinring/tmlanguage/master/tmlanguage.json",
3 "name": "Rust",
4 "fileTypes": [
5 "rs"
6 ],
7 "scopeName": "source.rust",
8 "patterns": [
9 {
10 "comment": "boxed slice literal",
11 "begin": "(<)(\\[)",
12 "beginCaptures": {
13 "1": {
14 "name": "punctuation.brackets.angle.rust"
15 },
16 "2": {
17 "name": "punctuation.brackets.square.rust"
18 }
19 },
20 "end": ">",
21 "endCaptures": {
22 "0": {
23 "name": "punctuation.brackets.angle.rust"
24 }
25 },
26 "patterns": [
27 {
28 "include": "#block-comments"
29 },
30 {
31 "include": "#comments"
32 },
33 {
34 "include": "#gtypes"
35 },
36 {
37 "include": "#lvariables"
38 },
39 {
40 "include": "#lifetimes"
41 },
42 {
43 "include": "#punctuation"
44 },
45 {
46 "include": "#types"
47 }
48 ]
49 },
50 {
51 "comment": "macro type metavariables",
52 "name": "meta.macro.metavariable.type.rust",
53 "match": "(\\$)((crate)|([A-Z][A-Za-z0-9_]*))((:)(block|expr|ident|item|lifetime|literal|meta|path?|stmt|tt|ty|vis))?",
54 "captures": {
55 "1": {
56 "name": "keyword.operator.macro.dollar.rust"
57 },
58 "3": {
59 "name": "keyword.other.crate.rust"
60 },
61 "4": {
62 "name": "entity.name.type.metavariable.rust"
63 },
64 "6": {
65 "name": "keyword.operator.key-value.rust"
66 },
67 "7": {
68 "name": "variable.other.metavariable.specifier.rust"
69 }
70 },
71 "patterns": [
72 {
73 "include": "#keywords"
74 }
75 ]
76 },
77 {
78 "comment": "macro metavariables",
79 "name": "meta.macro.metavariable.rust",
80 "match": "(\\$)([a-z][A-Za-z0-9_]*)((:)(block|expr|ident|item|lifetime|literal|meta|path?|stmt|tt|ty|vis))?",
81 "captures": {
82 "1": {
83 "name": "keyword.operator.macro.dollar.rust"
84 },
85 "2": {
86 "name": "variable.other.metavariable.name.rust"
87 },
88 "4": {
89 "name": "keyword.operator.key-value.rust"
90 },
91 "5": {
92 "name": "variable.other.metavariable.specifier.rust"
93 }
94 },
95 "patterns": [
96 {
97 "include": "#keywords"
98 }
99 ]
100 },
101 {
102 "comment": "macro rules",
103 "name": "meta.macro.rules.rust",
104 "match": "\\b(macro_rules!)\\s+(([a-z0-9_]+)|([A-Z][a-z0-9_]*))\\s+(\\{)",
105 "captures": {
106 "1": {
107 "name": "entity.name.function.macro.rules.rust"
108 },
109 "3": {
110 "name": "entity.name.function.macro.rust"
111 },
112 "4": {
113 "name": "entity.name.type.macro.rust"
114 },
115 "5": {
116 "name": "punctuation.brackets.curly.rust"
117 }
118 }
119 },
120 {
121 "comment": "attributes",
122 "name": "meta.attribute.rust",
123 "begin": "(#)(\\!?)(\\[)",
124 "beginCaptures": {
125 "1": {
126 "name": "punctuation.definition.attribute.rust"
127 },
128 "2": {
129 "name": "keyword.operator.attribute.inner.rust"
130 },
131 "3": {
132 "name": "punctuation.brackets.attribute.rust"
133 }
134 },
135 "end": "\\]",
136 "endCaptures": {
137 "0": {
138 "name": "punctuation.brackets.attribute.rust"
139 }
140 },
141 "patterns": [
142 {
143 "include": "#block-comments"
144 },
145 {
146 "include": "#comments"
147 },
148 {
149 "include": "#keywords"
150 },
151 {
152 "include": "#punctuation"
153 },
154 {
155 "include": "#strings"
156 },
157 {
158 "include": "#gtypes"
159 },
160 {
161 "include": "#types"
162 }
163 ]
164 },
165 {
166 "comment": "modules",
167 "match": "(mod)\\s+((?:r#(?!crate|[Ss]elf|super))?[a-z][A-Za-z0-9_]*)",
168 "captures": {
169 "1": {
170 "name": "storage.type.rust"
171 },
172 "2": {
173 "name": "entity.name.module.rust"
174 }
175 }
176 },
177 {
178 "comment": "external crate imports",
179 "name": "meta.import.rust",
180 "begin": "\\b(extern)\\s+(crate)",
181 "beginCaptures": {
182 "1": {
183 "name": "storage.type.rust"
184 },
185 "2": {
186 "name": "keyword.other.crate.rust"
187 }
188 },
189 "end": ";",
190 "endCaptures": {
191 "0": {
192 "name": "punctuation.semi.rust"
193 }
194 },
195 "patterns": [
196 {
197 "include": "#block-comments"
198 },
199 {
200 "include": "#comments"
201 },
202 {
203 "include": "#keywords"
204 },
205 {
206 "include": "#punctuation"
207 }
208 ]
209 },
210 {
211 "comment": "use statements",
212 "name": "meta.use.rust",
213 "begin": "\\b(use)\\s",
214 "beginCaptures": {
215 "1": {
216 "name": "keyword.other.rust"
217 }
218 },
219 "end": ";",
220 "endCaptures": {
221 "0": {
222 "name": "punctuation.semi.rust"
223 }
224 },
225 "patterns": [
226 {
227 "include": "#block-comments"
228 },
229 {
230 "include": "#comments"
231 },
232 {
233 "include": "#keywords"
234 },
235 {
236 "include": "#namespaces"
237 },
238 {
239 "include": "#punctuation"
240 },
241 {
242 "include": "#types"
243 },
244 {
245 "include": "#lvariables"
246 }
247 ]
248 },
249 {
250 "include": "#block-comments"
251 },
252 {
253 "include": "#comments"
254 },
255 {
256 "include": "#lvariables"
257 },
258 {
259 "include": "#constants"
260 },
261 {
262 "include": "#gtypes"
263 },
264 {
265 "include": "#functions"
266 },
267 {
268 "include": "#types"
269 },
270 {
271 "include": "#keywords"
272 },
273 {
274 "include": "#lifetimes"
275 },
276 {
277 "include": "#macros"
278 },
279 {
280 "include": "#namespaces"
281 },
282 {
283 "include": "#punctuation"
284 },
285 {
286 "include": "#strings"
287 },
288 {
289 "include": "#variables"
290 }
291 ],
292 "repository": {
293 "comments": {
294 "patterns": [
295 {
296 "comment": "documentation comments",
297 "name": "comment.line.documentation.rust",
298 "match": "^\\s*///.*"
299 },
300 {
301 "comment": "line comments",
302 "name": "comment.line.double-slash.rust",
303 "match": "\\s*//.*"
304 }
305 ]
306 },
307 "block-comments": {
308 "patterns": [
309 {
310 "comment": "empty block comments",
311 "name": "comment.block.rust",
312 "match": "/\\*\\*/"
313 },
314 {
315 "comment": "block documentation comments",
316 "name": "comment.block.documentation.rust",
317 "begin": "/\\*\\*",
318 "end": "\\*/",
319 "patterns": [
320 {
321 "include": "#block-comments"
322 }
323 ]
324 },
325 {
326 "comment": "block comments",
327 "name": "comment.block.rust",
328 "begin": "/\\*(?!\\*)",
329 "end": "\\*/",
330 "patterns": [
331 {
332 "include": "#block-comments"
333 }
334 ]
335 }
336 ]
337 },
338 "constants": {
339 "patterns": [
340 {
341 "comment": "ALL CAPS constants",
342 "name": "constant.other.caps.rust",
343 "match": "\\b[A-Z]{2}[A-Z0-9_]*\\b"
344 },
345 {
346 "comment": "constant declarations",
347 "match": "\\b(const)\\s+([A-Z][A-Za-z0-9_]*)\\b",
348 "captures": {
349 "1": {
350 "name": "storage.type.rust"
351 },
352 "2": {
353 "name": "constant.other.caps.rust"
354 }
355 }
356 },
357 {
358 "comment": "decimal integers and floats",
359 "name": "constant.numeric.decimal.rust",
360 "match": "\\b\\d[\\d_]*(\\.?)[\\d_]*(?:(E)([+-])([\\d_]+))?(f32|f64|i128|i16|i32|i64|i8|isize|u128|u16|u32|u64|u8|usize)?\\b",
361 "captures": {
362 "1": {
363 "name": "punctuation.separator.dot.decimal.rust"
364 },
365 "2": {
366 "name": "keyword.operator.exponent.rust"
367 },
368 "3": {
369 "name": "keyword.operator.exponent.sign.rust"
370 },
371 "4": {
372 "name": "constant.numeric.decimal.exponent.mantissa.rust"
373 },
374 "5": {
375 "name": "entity.name.type.numeric.rust"
376 }
377 }
378 },
379 {
380 "comment": "hexadecimal integers",
381 "name": "constant.numeric.hex.rust",
382 "match": "\\b0x[\\da-fA-F_]+(i128|i16|i32|i64|i8|isize|u128|u16|u32|u64|u8|usize)?\\b",
383 "captures": {
384 "1": {
385 "name": "entity.name.type.numeric.rust"
386 }
387 }
388 },
389 {
390 "comment": "octal integers",
391 "name": "constant.numeric.oct.rust",
392 "match": "\\b0o[0-7_]+(i128|i16|i32|i64|i8|isize|u128|u16|u32|u64|u8|usize)?\\b",
393 "captures": {
394 "1": {
395 "name": "entity.name.type.numeric.rust"
396 }
397 }
398 },
399 {
400 "comment": "binary integers",
401 "name": "constant.numeric.bin.rust",
402 "match": "\\b0b[01_]+(i128|i16|i32|i64|i8|isize|u128|u16|u32|u64|u8|usize)?\\b",
403 "captures": {
404 "1": {
405 "name": "entity.name.type.numeric.rust"
406 }
407 }
408 },
409 {
410 "comment": "booleans",
411 "name": "constant.language.bool.rust",
412 "match": "\\b(true|false)\\b"
413 }
414 ]
415 },
416 "escapes": {
417 "comment": "escapes: ASCII, byte, Unicode, quote, regex",
418 "name": "constant.character.escape.rust",
419 "match": "(\\\\)(?:(?:(x[0-7][0-7a-fA-F])|(u(\\{)[\\da-fA-F]{4,6}(\\}))|.))",
420 "captures": {
421 "1": {
422 "name": "constant.character.escape.backslash.rust"
423 },
424 "2": {
425 "name": "constant.character.escape.bit.rust"
426 },
427 "3": {
428 "name": "constant.character.escape.unicode.rust"
429 },
430 "4": {
431 "name": "constant.character.escape.unicode.punctuation.rust"
432 },
433 "5": {
434 "name": "constant.character.escape.unicode.punctuation.rust"
435 }
436 }
437 },
438 "functions": {
439 "patterns": [
440 {
441 "comment": "pub as a function",
442 "match": "\\b(pub)(\\()",
443 "captures": {
444 "1": {
445 "name": "keyword.other.rust"
446 },
447 "2": {
448 "name": "punctuation.brackets.round.rust"
449 }
450 }
451 },
452 {
453 "comment": "function definition",
454 "name": "meta.function.definition.rust",
455 "begin": "\\b(fn)\\s+((?:r#(?!crate|[Ss]elf|super))?[A-Za-z0-9_]+)((\\()|(<))",
456 "beginCaptures": {
457 "1": {
458 "name": "keyword.other.fn.rust"
459 },
460 "2": {
461 "name": "entity.name.function.rust"
462 },
463 "4": {
464 "name": "punctuation.brackets.round.rust"
465 },
466 "5": {
467 "name": "punctuation.brackets.angle.rust"
468 }
469 },
470 "end": "\\{|;",
471 "endCaptures": {
472 "0": {
473 "name": "punctuation.brackets.curly.rust"
474 }
475 },
476 "patterns": [
477 {
478 "include": "#block-comments"
479 },
480 {
481 "include": "#comments"
482 },
483 {
484 "include": "#keywords"
485 },
486 {
487 "include": "#lvariables"
488 },
489 {
490 "include": "#constants"
491 },
492 {
493 "include": "#gtypes"
494 },
495 {
496 "include": "#functions"
497 },
498 {
499 "include": "#lifetimes"
500 },
501 {
502 "include": "#macros"
503 },
504 {
505 "include": "#namespaces"
506 },
507 {
508 "include": "#punctuation"
509 },
510 {
511 "include": "#strings"
512 },
513 {
514 "include": "#types"
515 },
516 {
517 "include": "#variables"
518 }
519 ]
520 },
521 {
522 "comment": "function/method calls, chaining",
523 "name": "meta.function.call.rust",
524 "begin": "((?:r#(?!crate|[Ss]elf|super))?[A-Za-z0-9_]+)(\\()",
525 "beginCaptures": {
526 "1": {
527 "name": "entity.name.function.rust"
528 },
529 "2": {
530 "name": "punctuation.brackets.round.rust"
531 }
532 },
533 "end": "\\)",
534 "endCaptures": {
535 "0": {
536 "name": "punctuation.brackets.round.rust"
537 }
538 },
539 "patterns": [
540 {
541 "include": "#block-comments"
542 },
543 {
544 "include": "#comments"
545 },
546 {
547 "include": "#keywords"
548 },
549 {
550 "include": "#lvariables"
551 },
552 {
553 "include": "#constants"
554 },
555 {
556 "include": "#gtypes"
557 },
558 {
559 "include": "#functions"
560 },
561 {
562 "include": "#lifetimes"
563 },
564 {
565 "include": "#macros"
566 },
567 {
568 "include": "#namespaces"
569 },
570 {
571 "include": "#punctuation"
572 },
573 {
574 "include": "#strings"
575 },
576 {
577 "include": "#types"
578 },
579 {
580 "include": "#variables"
581 }
582 ]
583 },
584 {
585 "comment": "function/method calls with turbofish",
586 "name": "meta.function.call.rust",
587 "begin": "((?:r#(?!crate|[Ss]elf|super))?[A-Za-z0-9_]+)(?=::<.*>\\()",
588 "beginCaptures": {
589 "1": {
590 "name": "entity.name.function.rust"
591 }
592 },
593 "end": "\\)",
594 "endCaptures": {
595 "0": {
596 "name": "punctuation.brackets.round.rust"
597 }
598 },
599 "patterns": [
600 {
601 "include": "#block-comments"
602 },
603 {
604 "include": "#comments"
605 },
606 {
607 "include": "#keywords"
608 },
609 {
610 "include": "#lvariables"
611 },
612 {
613 "include": "#constants"
614 },
615 {
616 "include": "#gtypes"
617 },
618 {
619 "include": "#functions"
620 },
621 {
622 "include": "#lifetimes"
623 },
624 {
625 "include": "#macros"
626 },
627 {
628 "include": "#namespaces"
629 },
630 {
631 "include": "#punctuation"
632 },
633 {
634 "include": "#strings"
635 },
636 {
637 "include": "#types"
638 },
639 {
640 "include": "#variables"
641 }
642 ]
643 }
644 ]
645 },
646 "keywords": {
647 "patterns": [
648 {
649 "comment": "control flow keywords",
650 "name": "keyword.control.rust",
651 "match": "\\b(await|break|continue|do|else|for|if|loop|match|return|try|while|yield)\\b"
652 },
653 {
654 "comment": "storage keywords",
655 "name": "storage.type.rust",
656 "match": "\\b(const|enum|extern|let|macro|mod|struct|trait|type)\\b"
657 },
658 {
659 "comment": "storage modifiers",
660 "name": "storage.modifier.rust",
661 "match": "\\b(abstract|static)\\b"
662 },
663 {
664 "comment": "other keywords",
665 "name": "keyword.other.rust",
666 "match": "\\b(as|async|become|box|dyn|move|final|impl|in|override|priv|pub|ref|typeof|union|unsafe|unsized|use|virtual|where)\\b"
667 },
668 {
669 "comment": "fn",
670 "name": "keyword.other.fn.rust",
671 "match": "\\bfn\\b"
672 },
673 {
674 "comment": "crate",
675 "name": "keyword.other.crate.rust",
676 "match": "\\bcrate\\b"
677 },
678 {
679 "comment": "mut",
680 "name": "storage.modifier.mut.rust",
681 "match": "\\bmut\\b"
682 },
683 {
684 "comment": "logical operators",
685 "name": "keyword.operator.logical.rust",
686 "match": "(\\^|\\||\\|\\||&&|<<|>>|!)(?!=)"
687 },
688 {
689 "comment": "logical AND, borrow references",
690 "name": "keyword.operator.borrow.and.rust",
691 "match": "&(?![&=])"
692 },
693 {
694 "comment": "assignment operators",
695 "name": "keyword.operator.assignment.rust",
696 "match": "(\\+=|-=|\\*=|/=|%=|\\^=|&=|\\|=|<<=|>>=)"
697 },
698 {
699 "comment": "single equal",
700 "name": "keyword.operator.assignment.equal.rust",
701 "match": "(?<![<>])=(?!=|>)"
702 },
703 {
704 "comment": "comparison operators",
705 "name": "keyword.operator.comparison.rust",
706 "match": "(=(=)?(?!>)|!=|<=|(?<!=)>=)"
707 },
708 {
709 "comment": "math operators",
710 "name": "keyword.operator.math.rust",
711 "match": "(([+%]|(\\*(?!\\w)))(?!=))|(-(?!>))|(/(?!/))"
712 },
713 {
714 "comment": "less than, greater than (special case)",
715 "match": "(?:\\b|(?:(\\))|(\\])|(\\})))[ \\t]+([<>])[ \\t]+(?:\\b|(?:(\\()|(\\[)|(\\{)))",
716 "captures": {
717 "1": {
718 "name": "punctuation.brackets.round.rust"
719 },
720 "2": {
721 "name": "punctuation.brackets.square.rust"
722 },
723 "3": {
724 "name": "punctuation.brackets.curly.rust"
725 },
726 "4": {
727 "name": "keyword.operator.comparison.rust"
728 },
729 "5": {
730 "name": "punctuation.brackets.round.rust"
731 },
732 "6": {
733 "name": "punctuation.brackets.square.rust"
734 },
735 "7": {
736 "name": "punctuation.brackets.curly.rust"
737 }
738 }
739 },
740 {
741 "comment": "namespace operator",
742 "name": "keyword.operator.namespace.rust",
743 "match": "::"
744 },
745 {
746 "comment": "dereference asterisk",
747 "match": "(\\*)(?=\\w+)",
748 "captures": {
749 "1": {
750 "name": "keyword.operator.dereference.rust"
751 }
752 }
753 },
754 {
755 "comment": "subpattern binding",
756 "name": "keyword.operator.subpattern.rust",
757 "match": "@"
758 },
759 {
760 "comment": "dot access",
761 "name": "keyword.operator.access.dot.rust",
762 "match": "\\.(?!\\.)"
763 },
764 {
765 "comment": "ranges, range patterns",
766 "name": "keyword.operator.range.rust",
767 "match": "\\.{2}(=|\\.)?"
768 },
769 {
770 "comment": "colon",
771 "name": "keyword.operator.key-value.rust",
772 "match": ":(?!:)"
773 },
774 {
775 "comment": "dashrocket, skinny arrow",
776 "name": "keyword.operator.arrow.skinny.rust",
777 "match": "->"
778 },
779 {
780 "comment": "hashrocket, fat arrow",
781 "name": "keyword.operator.arrow.fat.rust",
782 "match": "=>"
783 },
784 {
785 "comment": "dollar macros",
786 "name": "keyword.operator.macro.dollar.rust",
787 "match": "\\$"
788 },
789 {
790 "comment": "question mark operator, questionably sized, macro kleene matcher",
791 "name": "keyword.operator.question.rust",
792 "match": "\\?"
793 }
794 ]
795 },
796 "interpolations": {
797 "comment": "curly brace interpolations",
798 "name": "meta.interpolation.rust",
799 "match": "({)[^\"{}]*(})",
800 "captures": {
801 "1": {
802 "name": "punctuation.definition.interpolation.rust"
803 },
804 "2": {
805 "name": "punctuation.definition.interpolation.rust"
806 }
807 }
808 },
809 "lifetimes": {
810 "patterns": [
811 {
812 "comment": "named lifetime parameters",
813 "match": "(['])([a-zA-Z_][0-9a-zA-Z_]*)(?!['])\\b",
814 "captures": {
815 "1": {
816 "name": "punctuation.definition.lifetime.rust"
817 },
818 "2": {
819 "name": "entity.name.type.lifetime.rust"
820 }
821 }
822 },
823 {
824 "comment": "borrowing references to named lifetimes",
825 "match": "(\\&)(['])([a-zA-Z_][0-9a-zA-Z_]*)(?!['])\\b",
826 "captures": {
827 "1": {
828 "name": "keyword.operator.borrow.rust"
829 },
830 "2": {
831 "name": "punctuation.definition.lifetime.rust"
832 },
833 "3": {
834 "name": "entity.name.type.lifetime.rust"
835 }
836 }
837 }
838 ]
839 },
840 "macros": {
841 "patterns": [
842 {
843 "comment": "macros",
844 "name": "meta.macro.rust",
845 "match": "(([a-z_][A-Za-z0-9_]*!)|([A-Z_][A-Za-z0-9_]*!))",
846 "captures": {
847 "2": {
848 "name": "entity.name.function.macro.rust"
849 },
850 "3": {
851 "name": "entity.name.type.macro.rust"
852 }
853 }
854 }
855 ]
856 },
857 "namespaces": {
858 "patterns": [
859 {
860 "comment": "namespace (non-type, non-function path segment)",
861 "match": "(?<![A-Za-z0-9_])([a-z0-9_]+)((?<!super|self)::)",
862 "captures": {
863 "1": {
864 "name": "entity.name.namespace.rust"
865 },
866 "2": {
867 "name": "keyword.operator.namespace.rust"
868 }
869 }
870 }
871 ]
872 },
873 "types": {
874 "patterns": [
875 {
876 "comment": "numeric types",
877 "match": "(?<![A-Za-z])(f32|f64|i128|i16|i32|i64|i8|isize|u128|u16|u32|u64|u8|usize)\\b",
878 "captures": {
879 "1": {
880 "name": "entity.name.type.numeric.rust"
881 }
882 }
883 },
884 {
885 "comment": "parameterized types",
886 "begin": "\\b([A-Z][A-Za-z0-9]*)(<)",
887 "beginCaptures": {
888 "1": {
889 "name": "entity.name.type.rust"
890 },
891 "2": {
892 "name": "punctuation.brackets.angle.rust"
893 }
894 },
895 "end": ">",
896 "endCaptures": {
897 "0": {
898 "name": "punctuation.brackets.angle.rust"
899 }
900 },
901 "patterns": [
902 {
903 "include": "#block-comments"
904 },
905 {
906 "include": "#comments"
907 },
908 {
909 "include": "#keywords"
910 },
911 {
912 "include": "#lvariables"
913 },
914 {
915 "include": "#lifetimes"
916 },
917 {
918 "include": "#punctuation"
919 },
920 {
921 "include": "#types"
922 },
923 {
924 "include": "#variables"
925 }
926 ]
927 },
928 {
929 "comment": "primitive types",
930 "name": "entity.name.type.primitive.rust",
931 "match": "\\b(bool|char|str)\\b"
932 },
933 {
934 "comment": "trait declarations",
935 "match": "\\b(trait)\\s+([A-Z][A-Za-z0-9]*)\\b",
936 "captures": {
937 "1": {
938 "name": "storage.type.rust"
939 },
940 "2": {
941 "name": "entity.name.type.trait.rust"
942 }
943 }
944 },
945 {
946 "comment": "struct declarations",
947 "match": "\\b(struct)\\s+([A-Z][A-Za-z0-9]*)\\b",
948 "captures": {
949 "1": {
950 "name": "storage.type.rust"
951 },
952 "2": {
953 "name": "entity.name.type.struct.rust"
954 }
955 }
956 },
957 {
958 "comment": "enum declarations",
959 "match": "\\b(enum)\\s+([A-Z][A-Za-z0-9_]*)\\b",
960 "captures": {
961 "1": {
962 "name": "storage.type.rust"
963 },
964 "2": {
965 "name": "entity.name.type.enum.rust"
966 }
967 }
968 },
969 {
970 "comment": "type declarations",
971 "match": "\\b(type)\\s+([A-Z][A-Za-z0-9_]*)\\b",
972 "captures": {
973 "1": {
974 "name": "storage.type.rust"
975 },
976 "2": {
977 "name": "entity.name.type.declaration.rust"
978 }
979 }
980 },
981 {
982 "comment": "types",
983 "name": "entity.name.type.rust",
984 "match": "\\b[A-Z][A-Za-z0-9]*\\b(?!!)"
985 }
986 ]
987 },
988 "gtypes": {
989 "patterns": [
990 {
991 "comment": "option types",
992 "name": "entity.name.type.option.rust",
993 "match": "\\b(Some|None)\\b"
994 },
995 {
996 "comment": "result types",
997 "name": "entity.name.type.result.rust",
998 "match": "\\b(Ok|Err)\\b"
999 }
1000 ]
1001 },
1002 "punctuation": {
1003 "patterns": [
1004 {
1005 "comment": "comma",
1006 "name": "punctuation.comma.rust",
1007 "match": ","
1008 },
1009 {
1010 "comment": "curly braces",
1011 "name": "punctuation.brackets.curly.rust",
1012 "match": "[{}]"
1013 },
1014 {
1015 "comment": "parentheses, round brackets",
1016 "name": "punctuation.brackets.round.rust",
1017 "match": "[()]"
1018 },
1019 {
1020 "comment": "semicolon",
1021 "name": "punctuation.semi.rust",
1022 "match": ";"
1023 },
1024 {
1025 "comment": "square brackets",
1026 "name": "punctuation.brackets.square.rust",
1027 "match": "[\\[\\]]"
1028 },
1029 {
1030 "comment": "angle brackets",
1031 "name": "punctuation.brackets.angle.rust",
1032 "match": "(?<!=)[<>]"
1033 }
1034 ]
1035 },
1036 "strings": {
1037 "patterns": [
1038 {
1039 "comment": "double-quoted strings and byte strings",
1040 "name": "string.quoted.double.rust",
1041 "begin": "(b?)(\")",
1042 "beginCaptures": {
1043 "1": {
1044 "name": "string.quoted.byte.raw.rust"
1045 },
1046 "2": {
1047 "name": "punctuation.definition.string.rust"
1048 }
1049 },
1050 "end": "\"",
1051 "endCaptures": {
1052 "0": {
1053 "name": "punctuation.definition.string.rust"
1054 }
1055 },
1056 "patterns": [
1057 {
1058 "include": "#escapes"
1059 },
1060 {
1061 "include": "#interpolations"
1062 }
1063 ]
1064 },
1065 {
1066 "comment": "double-quoted raw strings and raw byte strings",
1067 "name": "string.quoted.double.rust",
1068 "begin": "(b?r)(#*)(\")",
1069 "beginCaptures": {
1070 "1": {
1071 "name": "string.quoted.byte.raw.rust"
1072 },
1073 "2": {
1074 "name": "punctuation.definition.string.raw.rust"
1075 },
1076 "3": {
1077 "name": "punctuation.definition.string.rust"
1078 }
1079 },
1080 "end": "(\")(\\2)",
1081 "endCaptures": {
1082 "1": {
1083 "name": "punctuation.definition.string.rust"
1084 },
1085 "2": {
1086 "name": "punctuation.definition.string.raw.rust"
1087 }
1088 }
1089 },
1090 {
1091 "comment": "characters and bytes",
1092 "name": "string.quoted.single.char.rust",
1093 "begin": "(b)?(')",
1094 "beginCaptures": {
1095 "1": {
1096 "name": "string.quoted.byte.raw.rust"
1097 },
1098 "2": {
1099 "name": "punctuation.definition.char.rust"
1100 }
1101 },
1102 "end": "'",
1103 "endCaptures": {
1104 "0": {
1105 "name": "punctuation.definition.char.rust"
1106 }
1107 },
1108 "patterns": [
1109 {
1110 "include": "#escapes"
1111 }
1112 ]
1113 }
1114 ]
1115 },
1116 "lvariables": {
1117 "patterns": [
1118 {
1119 "comment": "self",
1120 "name": "variable.language.self.rust",
1121 "match": "\\b[Ss]elf\\b"
1122 },
1123 {
1124 "comment": "super",
1125 "name": "variable.language.super.rust",
1126 "match": "\\bsuper\\b"
1127 }
1128 ]
1129 },
1130 "variables": {
1131 "patterns": [
1132 {
1133 "comment": "variables",
1134 "name": "variable.other.rust",
1135 "match": "\\b(?<!(?<!\\.)\\.)(?:r#(?!(crate|[Ss]elf|super)))?[a-z0-9_]+\\b"
1136 }
1137 ]
1138 }
1139 }
1140}
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index 92bc4d7f7..9d4823a34 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -470,7 +470,7 @@ export function resolveCodeAction(ctx: Ctx): Cmd {
470 return; 470 return;
471 } 471 }
472 const edit = client.protocol2CodeConverter.asWorkspaceEdit(item.edit); 472 const edit = client.protocol2CodeConverter.asWorkspaceEdit(item.edit);
473 await applySnippetWorkspaceEdit(edit); 473 await vscode.workspace.applyEdit(edit);
474 }; 474 };
475} 475}
476 476
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index 191960960..282240d84 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -19,9 +19,8 @@ let ctx: Ctx | undefined;
19const RUST_PROJECT_CONTEXT_NAME = "inRustProject"; 19const RUST_PROJECT_CONTEXT_NAME = "inRustProject";
20 20
21export async function activate(context: vscode.ExtensionContext) { 21export async function activate(context: vscode.ExtensionContext) {
22 // For some reason vscode not always shows pop-up error notifications 22 // VS Code doesn't show a notification when an extension fails to activate
23 // when an extension fails to activate, so we do it explicitly by ourselves. 23 // so we do it ourselves.
24 // FIXME: remove this bit of code once vscode fixes this issue: https://github.com/microsoft/vscode/issues/101242
25 await tryActivate(context).catch(err => { 24 await tryActivate(context).catch(err => {
26 void vscode.window.showErrorMessage(`Cannot activate rust-analyzer: ${err.message}`); 25 void vscode.window.showErrorMessage(`Cannot activate rust-analyzer: ${err.message}`);
27 throw err; 26 throw err;
@@ -132,7 +131,7 @@ async function tryActivate(context: vscode.ExtensionContext) {
132 ctx.pushCleanup(activateTaskProvider(workspaceFolder, ctx.config)); 131 ctx.pushCleanup(activateTaskProvider(workspaceFolder, ctx.config));
133 132
134 activateInlayHints(ctx); 133 activateInlayHints(ctx);
135 warnAboutRustLangExtensionConflict(); 134 warnAboutExtensionConflicts();
136 135
137 vscode.workspace.onDidChangeConfiguration( 136 vscode.workspace.onDidChangeConfiguration(
138 _ => ctx?.client?.sendNotification('workspace/didChangeConfiguration', { settings: "" }), 137 _ => ctx?.client?.sendNotification('workspace/didChangeConfiguration', { settings: "" }),
@@ -288,10 +287,14 @@ async function getServer(config: Config, state: PersistentState): Promise<string
288 if (config.package.releaseTag === null) return "rust-analyzer"; 287 if (config.package.releaseTag === null) return "rust-analyzer";
289 288
290 let platform: string | undefined; 289 let platform: string | undefined;
291 if (process.arch === "x64" || process.arch === "ia32") { 290 if ((process.arch === "x64" || process.arch === "ia32") && process.platform === "win32") {
292 if (process.platform === "linux") platform = "linux"; 291 platform = "x86_64-pc-windows-msvc";
293 if (process.platform === "darwin") platform = "mac"; 292 } else if (process.arch === "x64" && process.platform === "linux") {
294 if (process.platform === "win32") platform = "windows"; 293 platform = "x86_64-unknown-linux-gnu";
294 } else if (process.arch === "x64" && process.platform === "darwin") {
295 platform = "x86_64-apple-darwin";
296 } else if (process.arch === "arm64" && process.platform === "darwin") {
297 platform = "aarch64-apple-darwin";
295 } 298 }
296 if (platform === undefined) { 299 if (platform === undefined) {
297 vscode.window.showErrorMessage( 300 vscode.window.showErrorMessage(
@@ -304,7 +307,7 @@ async function getServer(config: Config, state: PersistentState): Promise<string
304 ); 307 );
305 return undefined; 308 return undefined;
306 } 309 }
307 const ext = platform === "windows" ? ".exe" : ""; 310 const ext = platform.indexOf("-windows-") !== -1 ? ".exe" : "";
308 const dest = path.join(config.globalStoragePath, `rust-analyzer-${platform}${ext}`); 311 const dest = path.join(config.globalStoragePath, `rust-analyzer-${platform}${ext}`);
309 const exists = await fs.stat(dest).then(() => true, () => false); 312 const exists = await fs.stat(dest).then(() => true, () => false);
310 if (!exists) { 313 if (!exists) {
@@ -340,7 +343,7 @@ async function getServer(config: Config, state: PersistentState): Promise<string
340 }); 343 });
341 344
342 // Patching executable if that's NixOS. 345 // Patching executable if that's NixOS.
343 if (await fs.stat("/etc/nixos").then(_ => true).catch(_ => false)) { 346 if (await isNixOs()) {
344 await patchelf(dest); 347 await patchelf(dest);
345 } 348 }
346 349
@@ -348,6 +351,15 @@ async function getServer(config: Config, state: PersistentState): Promise<string
348 return dest; 351 return dest;
349} 352}
350 353
354async function isNixOs(): Promise<boolean> {
355 try {
356 const contents = await fs.readFile("/etc/os-release");
357 return contents.indexOf("ID=nixos") !== -1;
358 } catch (e) {
359 return false;
360 }
361}
362
351async function downloadWithRetryDialog<T>(state: PersistentState, downloadFunc: () => Promise<T>): Promise<T> { 363async function downloadWithRetryDialog<T>(state: PersistentState, downloadFunc: () => Promise<T>): Promise<T> {
352 while (true) { 364 while (true) {
353 try { 365 try {
@@ -401,11 +413,21 @@ async function queryForGithubToken(state: PersistentState): Promise<void> {
401 } 413 }
402} 414}
403 415
404function warnAboutRustLangExtensionConflict() { 416function warnAboutExtensionConflicts() {
405 const rustLangExt = vscode.extensions.getExtension("rust-lang.rust"); 417 const conflicting = [
406 if (rustLangExt !== undefined) { 418 ["rust-analyzer", "matklad.rust-analyzer"],
419 ["Rust", "rust-lang.rust"],
420 ["Rust", "kalitaalexey.vscode-rust"],
421 ];
422
423 const found = conflicting.filter(
424 nameId => vscode.extensions.getExtension(nameId[1]) !== undefined);
425
426 if (found.length > 1) {
427 const fst = found[0];
428 const sec = found[1];
407 vscode.window.showWarningMessage( 429 vscode.window.showWarningMessage(
408 "You have both rust-analyzer (matklad.rust-analyzer) and Rust (rust-lang.rust) " + 430 `You have both the ${fst[0]} (${fst[1]}) and ${sec[0]} (${sec[1]}) ` +
409 "plugins enabled. These are known to conflict and cause various functions of " + 431 "plugins enabled. These are known to conflict and cause various functions of " +
410 "both plugins to not work correctly. You should disable one of them.", "Got it"); 432 "both plugins to not work correctly. You should disable one of them.", "Got it");
411 }; 433 };
diff --git a/xtask/src/dist.rs b/xtask/src/dist.rs
index 9e15a5a4c..d07ad9420 100644
--- a/xtask/src/dist.rs
+++ b/xtask/src/dist.rs
@@ -58,30 +58,74 @@ fn dist_client(version: &str, release_tag: &str) -> Result<()> {
58} 58}
59 59
60fn dist_server() -> Result<()> { 60fn dist_server() -> Result<()> {
61 if cfg!(target_os = "linux") { 61 let target = get_target();
62 if target.contains("-linux-gnu") {
62 env::set_var("CC", "clang"); 63 env::set_var("CC", "clang");
63 } 64 }
64 cmd!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release").run()?;
65
66 let (src, dst) = if cfg!(target_os = "linux") {
67 ("./target/release/rust-analyzer", "./dist/rust-analyzer-linux")
68 } else if cfg!(target_os = "windows") {
69 ("./target/release/rust-analyzer.exe", "./dist/rust-analyzer-windows.exe")
70 } else if cfg!(target_os = "macos") {
71 ("./target/release/rust-analyzer", "./dist/rust-analyzer-mac")
72 } else {
73 panic!("Unsupported OS")
74 };
75 65
76 let src = Path::new(src); 66 let toolchain = toolchain(&target);
77 let dst = Path::new(dst); 67 cmd!("cargo +{toolchain} build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --target {target} --release").run()?;
78 68
69 let suffix = exe_suffix(&target);
70 let src =
71 Path::new("target").join(&target).join("release").join(format!("rust-analyzer{}", suffix));
72 let dst = Path::new("dist").join(format!("rust-analyzer-{}{}", target, suffix));
79 cp(&src, &dst)?; 73 cp(&src, &dst)?;
80 gzip(&src, &dst.with_extension("gz"))?; 74 gzip(&src, &dst.with_extension("gz"))?;
81 75
76 // FIXME: the old names are temporarily kept for client compatibility, but they should be removed
77 // Remove this block after a couple of releases
78 match target.as_ref() {
79 "x86_64-unknown-linux-gnu" => {
80 cp(&src, "dist/rust-analyzer-linux")?;
81 gzip(&src, Path::new("dist/rust-analyzer-linux.gz"))?;
82 }
83 "x86_64-pc-windows-msvc" => {
84 cp(&src, "dist/rust-analyzer-windows.exe")?;
85 gzip(&src, Path::new("dist/rust-analyzer-windows.gz"))?;
86 }
87 "x86_64-apple-darwin" => {
88 cp(&src, "dist/rust-analyzer-mac")?;
89 gzip(&src, Path::new("dist/rust-analyzer-mac.gz"))?;
90 }
91 _ => {}
92 }
93
82 Ok(()) 94 Ok(())
83} 95}
84 96
97fn get_target() -> String {
98 match env::var("RA_TARGET") {
99 Ok(target) => target,
100 _ => {
101 if cfg!(target_os = "linux") {
102 "x86_64-unknown-linux-gnu".to_string()
103 } else if cfg!(target_os = "windows") {
104 "x86_64-pc-windows-msvc".to_string()
105 } else if cfg!(target_os = "macos") {
106 "x86_64-apple-darwin".to_string()
107 } else {
108 panic!("Unsupported OS, maybe try setting RA_TARGET")
109 }
110 }
111 }
112}
113
114fn exe_suffix(target: &str) -> String {
115 if target.contains("-windows-") {
116 ".exe".into()
117 } else {
118 "".into()
119 }
120}
121
122fn toolchain(target: &str) -> String {
123 match target {
124 "aarch64-apple-darwin" => "beta".to_string(),
125 _ => "stable".to_string(),
126 }
127}
128
85fn gzip(src_path: &Path, dest_path: &Path) -> Result<()> { 129fn gzip(src_path: &Path, dest_path: &Path) -> Result<()> {
86 let mut encoder = GzEncoder::new(File::create(dest_path)?, Compression::best()); 130 let mut encoder = GzEncoder::new(File::create(dest_path)?, Compression::best());
87 let mut input = io::BufReader::new(File::open(src_path)?); 131 let mut input = io::BufReader::new(File::open(src_path)?);