diff options
-rw-r--r-- | .github/workflows/release.yaml | 114 | ||||
-rw-r--r-- | crates/assists/src/handlers/extract_module_to_file.rs | 169 | ||||
-rw-r--r-- | crates/completion/src/completions.rs | 33 | ||||
-rw-r--r-- | crates/completion/src/completions/pattern.rs | 178 | ||||
-rw-r--r-- | crates/completion/src/context.rs | 21 | ||||
-rw-r--r-- | crates/completion/src/render.rs | 7 | ||||
-rw-r--r-- | crates/completion/src/render/builder_ext.rs | 1 | ||||
-rw-r--r-- | crates/completion/src/render/enum_variant.rs | 45 | ||||
-rw-r--r-- | crates/completion/src/render/pattern.rs | 148 | ||||
-rw-r--r-- | crates/hir/src/code_model.rs | 4 | ||||
-rw-r--r-- | crates/rust-analyzer/src/config.rs | 34 | ||||
-rw-r--r-- | docs/user/generated_config.adoc | 26 | ||||
-rw-r--r-- | editors/code/package.json | 50 | ||||
-rw-r--r-- | editors/code/src/main.ts | 34 | ||||
-rw-r--r-- | xtask/src/dist.rs | 72 |
15 files changed, 661 insertions, 275 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 | ||
17 | jobs: | 17 | jobs: |
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/crates/assists/src/handlers/extract_module_to_file.rs b/crates/assists/src/handlers/extract_module_to_file.rs index 5fc190fa6..3e67fdca2 100644 --- a/crates/assists/src/handlers/extract_module_to_file.rs +++ b/crates/assists/src/handlers/extract_module_to_file.rs | |||
@@ -1,5 +1,5 @@ | |||
1 | use ast::edit::IndentLevel; | 1 | use ast::edit::IndentLevel; |
2 | use ide_db::base_db::{AnchoredPathBuf, SourceDatabaseExt}; | 2 | use ide_db::base_db::AnchoredPathBuf; |
3 | use syntax::{ | 3 | use syntax::{ |
4 | ast::{self, edit::AstNodeEdit, NameOwner}, | 4 | ast::{self, edit::AstNodeEdit, NameOwner}, |
5 | AstNode, | 5 | AstNode, |
@@ -21,43 +21,44 @@ use crate::{AssistContext, AssistId, AssistKind, Assists}; | |||
21 | // mod foo; | 21 | // mod foo; |
22 | // ``` | 22 | // ``` |
23 | pub(crate) fn extract_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | 23 | pub(crate) fn extract_module_to_file(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { |
24 | let assist_id = AssistId("extract_module_to_file", AssistKind::RefactorExtract); | ||
25 | let assist_label = "Extract module to file"; | ||
26 | let db = ctx.db(); | ||
27 | let module_ast = ctx.find_node_at_offset::<ast::Module>()?; | 24 | let module_ast = ctx.find_node_at_offset::<ast::Module>()?; |
28 | let module_items = module_ast.item_list()?; | ||
29 | let dedent_module_items_text = module_items.dedent(IndentLevel(1)).to_string(); | ||
30 | let module_name = module_ast.name()?; | 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(); | 31 | let target = module_ast.syntax().text_range(); |
32 | let anchor_file_id = ctx.frange.file_id; | 32 | let anchor_file_id = ctx.frange.file_id; |
33 | let sr = db.file_source_root(anchor_file_id); | ||
34 | let sr = db.source_root(sr); | ||
35 | let file_path = sr.path_for_file(&anchor_file_id)?; | ||
36 | let (file_name, file_ext) = file_path.name_and_extension()?; | ||
37 | acc.add(assist_id, assist_label, target, |builder| { | ||
38 | builder.replace(target, format!("mod {};", module_name)); | ||
39 | let path = if is_main_or_lib(file_name) { | ||
40 | format!("./{}.{}", module_name, file_ext.unwrap()) | ||
41 | } else { | ||
42 | format!("./{}/{}.{}", file_name, module_name, file_ext.unwrap()) | ||
43 | }; | ||
44 | let dst = AnchoredPathBuf { anchor: anchor_file_id, path }; | ||
45 | let contents = update_module_items_string(dedent_module_items_text); | ||
46 | builder.create_file(dst, contents); | ||
47 | }) | ||
48 | } | ||
49 | fn is_main_or_lib(file_name: &str) -> bool { | ||
50 | file_name == "main".to_string() || file_name == "lib".to_string() | ||
51 | } | ||
52 | fn update_module_items_string(items_str: String) -> String { | ||
53 | let mut items_string_lines: Vec<&str> = items_str.lines().collect(); | ||
54 | items_string_lines.pop(); // Delete last line | ||
55 | items_string_lines.reverse(); | ||
56 | items_string_lines.pop(); // Delete first line | ||
57 | items_string_lines.reverse(); | ||
58 | 33 | ||
59 | let string = items_string_lines.join("\n"); | 34 | acc.add( |
60 | format!("{}", string) | 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 | ) | ||
61 | } | 62 | } |
62 | 63 | ||
63 | #[cfg(test)] | 64 | #[cfg(test)] |
@@ -67,104 +68,66 @@ mod tests { | |||
67 | use super::*; | 68 | use super::*; |
68 | 69 | ||
69 | #[test] | 70 | #[test] |
70 | fn extract_module_to_file_with_basic_module() { | 71 | fn extract_from_root() { |
71 | check_assist( | 72 | check_assist( |
72 | extract_module_to_file, | 73 | extract_module_to_file, |
73 | r#" | 74 | r#" |
74 | //- /foo.rs crate:foo | ||
75 | mod tests {<|> | 75 | mod tests {<|> |
76 | #[test] fn t() {} | 76 | #[test] fn t() {} |
77 | } | 77 | } |
78 | "#, | 78 | "#, |
79 | r#" | 79 | r#" |
80 | //- /foo.rs | 80 | //- /main.rs |
81 | mod tests; | 81 | mod tests; |
82 | //- /foo/tests.rs | 82 | //- /tests.rs |
83 | #[test] fn t() {}"#, | 83 | #[test] fn t() {} |
84 | ) | ||
85 | } | ||
86 | |||
87 | #[test] | ||
88 | fn extract_module_to_file_with_file_path() { | ||
89 | check_assist( | ||
90 | extract_module_to_file, | ||
91 | r#" | ||
92 | //- /src/foo.rs crate:foo | ||
93 | mod bar {<|> | ||
94 | fn f() { | ||
95 | |||
96 | } | ||
97 | } | ||
98 | fn main() { | ||
99 | println!("Hello, world!"); | ||
100 | } | ||
101 | "#, | 84 | "#, |
102 | r#" | 85 | ); |
103 | //- /src/foo.rs | ||
104 | mod bar; | ||
105 | fn main() { | ||
106 | println!("Hello, world!"); | ||
107 | } | ||
108 | //- /src/foo/bar.rs | ||
109 | fn f() { | ||
110 | |||
111 | }"#, | ||
112 | ) | ||
113 | } | 86 | } |
114 | 87 | ||
115 | #[test] | 88 | #[test] |
116 | fn extract_module_to_file_with_main_filw() { | 89 | fn extract_from_submodule() { |
117 | check_assist( | 90 | check_assist( |
118 | extract_module_to_file, | 91 | extract_module_to_file, |
119 | r#" | 92 | r#" |
120 | //- /main.rs | 93 | //- /main.rs |
121 | mod foo {<|> | 94 | mod submodule; |
122 | fn f() { | 95 | //- /submodule.rs |
123 | 96 | mod inner<|> { | |
124 | } | 97 | fn f() {} |
125 | } | ||
126 | fn main() { | ||
127 | println!("Hello, world!"); | ||
128 | } | 98 | } |
99 | fn g() {} | ||
129 | "#, | 100 | "#, |
130 | r#" | 101 | r#" |
131 | //- /main.rs | 102 | //- /submodule.rs |
132 | mod foo; | 103 | mod inner; |
133 | fn main() { | 104 | fn g() {} |
134 | println!("Hello, world!"); | 105 | //- /submodule/inner.rs |
135 | } | 106 | fn f() {} |
136 | //- /foo.rs | 107 | "#, |
137 | fn f() { | 108 | ); |
138 | |||
139 | }"#, | ||
140 | ) | ||
141 | } | 109 | } |
142 | 110 | ||
143 | #[test] | 111 | #[test] |
144 | fn extract_module_to_file_with_lib_file() { | 112 | fn extract_from_mod_rs() { |
145 | check_assist( | 113 | check_assist( |
146 | extract_module_to_file, | 114 | extract_module_to_file, |
147 | r#" | 115 | r#" |
148 | //- /lib.rs | 116 | //- /main.rs |
149 | mod foo {<|> | 117 | mod submodule; |
150 | fn f() { | 118 | //- /submodule/mod.rs |
151 | 119 | mod inner<|> { | |
152 | } | 120 | fn f() {} |
153 | } | ||
154 | fn main() { | ||
155 | println!("Hello, world!"); | ||
156 | } | 121 | } |
122 | fn g() {} | ||
157 | "#, | 123 | "#, |
158 | r#" | 124 | r#" |
159 | //- /lib.rs | 125 | //- /submodule/mod.rs |
160 | mod foo; | 126 | mod inner; |
161 | fn main() { | 127 | fn g() {} |
162 | println!("Hello, world!"); | 128 | //- /submodule/inner.rs |
163 | } | 129 | fn f() {} |
164 | //- /foo.rs | 130 | "#, |
165 | fn f() { | 131 | ); |
166 | |||
167 | }"#, | ||
168 | ) | ||
169 | } | 132 | } |
170 | } | 133 | } |
diff --git a/crates/completion/src/completions.rs b/crates/completion/src/completions.rs index 1ef6b5f48..d9fe13485 100644 --- a/crates/completion/src/completions.rs +++ b/crates/completion/src/completions.rs | |||
@@ -19,9 +19,14 @@ use hir::{ModPath, ScopeDef, Type}; | |||
19 | use crate::{ | 19 | use crate::{ |
20 | item::Builder, | 20 | item::Builder, |
21 | render::{ | 21 | render::{ |
22 | const_::render_const, enum_variant::render_variant, function::render_fn, | 22 | const_::render_const, |
23 | macro_::render_macro, render_field, render_resolution, render_tuple_field, | 23 | enum_variant::render_variant, |
24 | type_alias::render_type_alias, RenderContext, | 24 | function::render_fn, |
25 | macro_::render_macro, | ||
26 | pattern::{render_struct_pat, render_variant_pat}, | ||
27 | render_field, render_resolution, render_tuple_field, | ||
28 | type_alias::render_type_alias, | ||
29 | RenderContext, | ||
25 | }, | 30 | }, |
26 | CompletionContext, CompletionItem, | 31 | CompletionContext, CompletionItem, |
27 | }; | 32 | }; |
@@ -105,6 +110,28 @@ impl Completions { | |||
105 | self.add(item) | 110 | self.add(item) |
106 | } | 111 | } |
107 | 112 | ||
113 | pub(crate) fn add_variant_pat( | ||
114 | &mut self, | ||
115 | ctx: &CompletionContext, | ||
116 | variant: hir::Variant, | ||
117 | local_name: Option<hir::Name>, | ||
118 | ) { | ||
119 | if let Some(item) = render_variant_pat(RenderContext::new(ctx), variant, local_name) { | ||
120 | self.add(item); | ||
121 | } | ||
122 | } | ||
123 | |||
124 | pub(crate) fn add_struct_pat( | ||
125 | &mut self, | ||
126 | ctx: &CompletionContext, | ||
127 | strukt: hir::Struct, | ||
128 | local_name: Option<hir::Name>, | ||
129 | ) { | ||
130 | if let Some(item) = render_struct_pat(RenderContext::new(ctx), strukt, local_name) { | ||
131 | self.add(item); | ||
132 | } | ||
133 | } | ||
134 | |||
108 | pub(crate) fn add_const(&mut self, ctx: &CompletionContext, constant: hir::Const) { | 135 | pub(crate) fn add_const(&mut self, ctx: &CompletionContext, constant: hir::Const) { |
109 | if let Some(item) = render_const(RenderContext::new(ctx), constant) { | 136 | if let Some(item) = render_const(RenderContext::new(ctx), constant) { |
110 | self.add(item); | 137 | self.add(item); |
diff --git a/crates/completion/src/completions/pattern.rs b/crates/completion/src/completions/pattern.rs index 4d56731ec..eee31098d 100644 --- a/crates/completion/src/completions/pattern.rs +++ b/crates/completion/src/completions/pattern.rs | |||
@@ -2,9 +2,9 @@ | |||
2 | 2 | ||
3 | use crate::{CompletionContext, Completions}; | 3 | use crate::{CompletionContext, Completions}; |
4 | 4 | ||
5 | /// Completes constats and paths in patterns. | 5 | /// Completes constants and paths in patterns. |
6 | pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { | 6 | pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { |
7 | if !(ctx.is_pat_binding_or_const || ctx.is_irrefutable_let_pat_binding) { | 7 | if !(ctx.is_pat_binding_or_const || ctx.is_irrefutable_pat_binding) { |
8 | return; | 8 | return; |
9 | } | 9 | } |
10 | if ctx.record_pat_syntax.is_some() { | 10 | if ctx.record_pat_syntax.is_some() { |
@@ -15,20 +15,21 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { | |||
15 | // suggest variants + auto-imports | 15 | // suggest variants + auto-imports |
16 | ctx.scope.process_all_names(&mut |name, res| { | 16 | ctx.scope.process_all_names(&mut |name, res| { |
17 | let add_resolution = match &res { | 17 | let add_resolution = match &res { |
18 | hir::ScopeDef::ModuleDef(def) => { | 18 | hir::ScopeDef::ModuleDef(def) => match def { |
19 | if ctx.is_irrefutable_let_pat_binding { | 19 | hir::ModuleDef::Adt(hir::Adt::Struct(strukt)) => { |
20 | matches!(def, hir::ModuleDef::Adt(hir::Adt::Struct(_))) | 20 | acc.add_struct_pat(ctx, strukt.clone(), Some(name.clone())); |
21 | } else { | 21 | true |
22 | matches!( | ||
23 | def, | ||
24 | hir::ModuleDef::Adt(hir::Adt::Enum(..)) | ||
25 | | hir::ModuleDef::Adt(hir::Adt::Struct(..)) | ||
26 | | hir::ModuleDef::Variant(..) | ||
27 | | hir::ModuleDef::Const(..) | ||
28 | | hir::ModuleDef::Module(..) | ||
29 | ) | ||
30 | } | 22 | } |
31 | } | 23 | hir::ModuleDef::Variant(variant) if !ctx.is_irrefutable_pat_binding => { |
24 | acc.add_variant_pat(ctx, variant.clone(), Some(name.clone())); | ||
25 | true | ||
26 | } | ||
27 | hir::ModuleDef::Adt(hir::Adt::Enum(..)) | ||
28 | | hir::ModuleDef::Variant(..) | ||
29 | | hir::ModuleDef::Const(..) | ||
30 | | hir::ModuleDef::Module(..) => !ctx.is_irrefutable_pat_binding, | ||
31 | _ => false, | ||
32 | }, | ||
32 | hir::ScopeDef::MacroDef(_) => true, | 33 | hir::ScopeDef::MacroDef(_) => true, |
33 | _ => false, | 34 | _ => false, |
34 | }; | 35 | }; |
@@ -42,13 +43,21 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { | |||
42 | mod tests { | 43 | mod tests { |
43 | use expect_test::{expect, Expect}; | 44 | use expect_test::{expect, Expect}; |
44 | 45 | ||
45 | use crate::{test_utils::completion_list, CompletionKind}; | 46 | use crate::{ |
47 | test_utils::{check_edit, completion_list}, | ||
48 | CompletionKind, | ||
49 | }; | ||
46 | 50 | ||
47 | fn check(ra_fixture: &str, expect: Expect) { | 51 | fn check(ra_fixture: &str, expect: Expect) { |
48 | let actual = completion_list(ra_fixture, CompletionKind::Reference); | 52 | let actual = completion_list(ra_fixture, CompletionKind::Reference); |
49 | expect.assert_eq(&actual) | 53 | expect.assert_eq(&actual) |
50 | } | 54 | } |
51 | 55 | ||
56 | fn check_snippet(ra_fixture: &str, expect: Expect) { | ||
57 | let actual = completion_list(ra_fixture, CompletionKind::Snippet); | ||
58 | expect.assert_eq(&actual) | ||
59 | } | ||
60 | |||
52 | #[test] | 61 | #[test] |
53 | fn completes_enum_variants_and_modules() { | 62 | fn completes_enum_variants_and_modules() { |
54 | check( | 63 | check( |
@@ -69,7 +78,7 @@ fn foo() { | |||
69 | en E | 78 | en E |
70 | ct Z | 79 | ct Z |
71 | st Bar | 80 | st Bar |
72 | ev X () | 81 | ev X |
73 | md m | 82 | md m |
74 | "#]], | 83 | "#]], |
75 | ); | 84 | ); |
@@ -114,4 +123,139 @@ fn foo() { | |||
114 | "#]], | 123 | "#]], |
115 | ); | 124 | ); |
116 | } | 125 | } |
126 | |||
127 | #[test] | ||
128 | fn completes_in_param() { | ||
129 | check( | ||
130 | r#" | ||
131 | enum E { X } | ||
132 | |||
133 | static FOO: E = E::X; | ||
134 | struct Bar { f: u32 } | ||
135 | |||
136 | fn foo(<|>) { | ||
137 | } | ||
138 | "#, | ||
139 | expect![[r#" | ||
140 | st Bar | ||
141 | "#]], | ||
142 | ); | ||
143 | } | ||
144 | |||
145 | #[test] | ||
146 | fn completes_pat_in_let() { | ||
147 | check_snippet( | ||
148 | r#" | ||
149 | struct Bar { f: u32 } | ||
150 | |||
151 | fn foo() { | ||
152 | let <|> | ||
153 | } | ||
154 | "#, | ||
155 | expect![[r#" | ||
156 | bn Bar Bar { f$1 }$0 | ||
157 | "#]], | ||
158 | ); | ||
159 | } | ||
160 | |||
161 | #[test] | ||
162 | fn completes_param_pattern() { | ||
163 | check_snippet( | ||
164 | r#" | ||
165 | struct Foo { bar: String, baz: String } | ||
166 | struct Bar(String, String); | ||
167 | struct Baz; | ||
168 | fn outer(<|>) {} | ||
169 | "#, | ||
170 | expect![[r#" | ||
171 | bn Foo Foo { bar$1, baz$2 }: Foo$0 | ||
172 | bn Bar Bar($1, $2): Bar$0 | ||
173 | "#]], | ||
174 | ) | ||
175 | } | ||
176 | |||
177 | #[test] | ||
178 | fn completes_let_pattern() { | ||
179 | check_snippet( | ||
180 | r#" | ||
181 | struct Foo { bar: String, baz: String } | ||
182 | struct Bar(String, String); | ||
183 | struct Baz; | ||
184 | fn outer() { | ||
185 | let <|> | ||
186 | } | ||
187 | "#, | ||
188 | expect![[r#" | ||
189 | bn Foo Foo { bar$1, baz$2 }$0 | ||
190 | bn Bar Bar($1, $2)$0 | ||
191 | "#]], | ||
192 | ) | ||
193 | } | ||
194 | |||
195 | #[test] | ||
196 | fn completes_refutable_pattern() { | ||
197 | check_snippet( | ||
198 | r#" | ||
199 | struct Foo { bar: i32, baz: i32 } | ||
200 | struct Bar(String, String); | ||
201 | struct Baz; | ||
202 | fn outer() { | ||
203 | match () { | ||
204 | <|> | ||
205 | } | ||
206 | } | ||
207 | "#, | ||
208 | expect![[r#" | ||
209 | bn Foo Foo { bar$1, baz$2 }$0 | ||
210 | bn Bar Bar($1, $2)$0 | ||
211 | "#]], | ||
212 | ) | ||
213 | } | ||
214 | |||
215 | #[test] | ||
216 | fn omits_private_fields_pat() { | ||
217 | check_snippet( | ||
218 | r#" | ||
219 | mod foo { | ||
220 | pub struct Foo { pub bar: i32, baz: i32 } | ||
221 | pub struct Bar(pub String, String); | ||
222 | pub struct Invisible(String, String); | ||
223 | } | ||
224 | use foo::*; | ||
225 | |||
226 | fn outer() { | ||
227 | match () { | ||
228 | <|> | ||
229 | } | ||
230 | } | ||
231 | "#, | ||
232 | expect![[r#" | ||
233 | bn Foo Foo { bar$1, .. }$0 | ||
234 | bn Bar Bar($1, ..)$0 | ||
235 | "#]], | ||
236 | ) | ||
237 | } | ||
238 | |||
239 | #[test] | ||
240 | fn only_shows_ident_completion() { | ||
241 | check_edit( | ||
242 | "Foo", | ||
243 | r#" | ||
244 | struct Foo(i32); | ||
245 | fn main() { | ||
246 | match Foo(92) { | ||
247 | <|>(92) => (), | ||
248 | } | ||
249 | } | ||
250 | "#, | ||
251 | r#" | ||
252 | struct Foo(i32); | ||
253 | fn main() { | ||
254 | match Foo(92) { | ||
255 | Foo(92) => (), | ||
256 | } | ||
257 | } | ||
258 | "#, | ||
259 | ); | ||
260 | } | ||
117 | } | 261 | } |
diff --git a/crates/completion/src/context.rs b/crates/completion/src/context.rs index 5cd11cf77..41de324d8 100644 --- a/crates/completion/src/context.rs +++ b/crates/completion/src/context.rs | |||
@@ -51,7 +51,7 @@ pub(crate) struct CompletionContext<'a> { | |||
51 | /// If a name-binding or reference to a const in a pattern. | 51 | /// If a name-binding or reference to a const in a pattern. |
52 | /// Irrefutable patterns (like let) are excluded. | 52 | /// Irrefutable patterns (like let) are excluded. |
53 | pub(super) is_pat_binding_or_const: bool, | 53 | pub(super) is_pat_binding_or_const: bool, |
54 | pub(super) is_irrefutable_let_pat_binding: bool, | 54 | pub(super) is_irrefutable_pat_binding: bool, |
55 | /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path. | 55 | /// A single-indent path, like `foo`. `::foo` should not be considered a trivial path. |
56 | pub(super) is_trivial_path: bool, | 56 | pub(super) is_trivial_path: bool, |
57 | /// If not a trivial path, the prefix (qualifier). | 57 | /// If not a trivial path, the prefix (qualifier). |
@@ -147,7 +147,7 @@ impl<'a> CompletionContext<'a> { | |||
147 | active_parameter: ActiveParameter::at(db, position), | 147 | active_parameter: ActiveParameter::at(db, position), |
148 | is_param: false, | 148 | is_param: false, |
149 | is_pat_binding_or_const: false, | 149 | is_pat_binding_or_const: false, |
150 | is_irrefutable_let_pat_binding: false, | 150 | is_irrefutable_pat_binding: false, |
151 | is_trivial_path: false, | 151 | is_trivial_path: false, |
152 | path_qual: None, | 152 | path_qual: None, |
153 | after_if: false, | 153 | after_if: false, |
@@ -327,14 +327,19 @@ impl<'a> CompletionContext<'a> { | |||
327 | if bind_pat.syntax().parent().and_then(ast::RecordPatFieldList::cast).is_some() { | 327 | if bind_pat.syntax().parent().and_then(ast::RecordPatFieldList::cast).is_some() { |
328 | self.is_pat_binding_or_const = false; | 328 | self.is_pat_binding_or_const = false; |
329 | } | 329 | } |
330 | if let Some(let_stmt) = bind_pat.syntax().ancestors().find_map(ast::LetStmt::cast) { | 330 | if let Some(Some(pat)) = bind_pat.syntax().ancestors().find_map(|node| { |
331 | if let Some(pat) = let_stmt.pat() { | 331 | match_ast! { |
332 | if pat.syntax().text_range().contains_range(bind_pat.syntax().text_range()) | 332 | match node { |
333 | { | 333 | ast::LetStmt(it) => Some(it.pat()), |
334 | self.is_pat_binding_or_const = false; | 334 | ast::Param(it) => Some(it.pat()), |
335 | self.is_irrefutable_let_pat_binding = true; | 335 | _ => None, |
336 | } | 336 | } |
337 | } | 337 | } |
338 | }) { | ||
339 | if pat.syntax().text_range().contains_range(bind_pat.syntax().text_range()) { | ||
340 | self.is_pat_binding_or_const = false; | ||
341 | self.is_irrefutable_pat_binding = true; | ||
342 | } | ||
338 | } | 343 | } |
339 | } | 344 | } |
340 | if is_node::<ast::Param>(name.syntax()) { | 345 | if is_node::<ast::Param>(name.syntax()) { |
diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs index 1092a4825..1ba7201a1 100644 --- a/crates/completion/src/render.rs +++ b/crates/completion/src/render.rs | |||
@@ -5,6 +5,7 @@ pub(crate) mod macro_; | |||
5 | pub(crate) mod function; | 5 | pub(crate) mod function; |
6 | pub(crate) mod enum_variant; | 6 | pub(crate) mod enum_variant; |
7 | pub(crate) mod const_; | 7 | pub(crate) mod const_; |
8 | pub(crate) mod pattern; | ||
8 | pub(crate) mod type_alias; | 9 | pub(crate) mod type_alias; |
9 | 10 | ||
10 | mod builder_ext; | 11 | mod builder_ext; |
@@ -159,6 +160,12 @@ impl<'a> Render<'a> { | |||
159 | let item = render_fn(self.ctx, import_to_add, Some(local_name), *func); | 160 | let item = render_fn(self.ctx, import_to_add, Some(local_name), *func); |
160 | return Some(item); | 161 | return Some(item); |
161 | } | 162 | } |
163 | ScopeDef::ModuleDef(Variant(_)) | ||
164 | if self.ctx.completion.is_pat_binding_or_const | ||
165 | | self.ctx.completion.is_irrefutable_pat_binding => | ||
166 | { | ||
167 | CompletionItemKind::EnumVariant | ||
168 | } | ||
162 | ScopeDef::ModuleDef(Variant(var)) => { | 169 | ScopeDef::ModuleDef(Variant(var)) => { |
163 | let item = render_variant(self.ctx, import_to_add, Some(local_name), *var, None); | 170 | let item = render_variant(self.ctx, import_to_add, Some(local_name), *var, None); |
164 | return Some(item); | 171 | return Some(item); |
diff --git a/crates/completion/src/render/builder_ext.rs b/crates/completion/src/render/builder_ext.rs index ce8718bd5..d053a988b 100644 --- a/crates/completion/src/render/builder_ext.rs +++ b/crates/completion/src/render/builder_ext.rs | |||
@@ -34,7 +34,6 @@ impl Builder { | |||
34 | return false; | 34 | return false; |
35 | } | 35 | } |
36 | if ctx.is_pattern_call { | 36 | if ctx.is_pattern_call { |
37 | mark::hit!(dont_duplicate_pattern_parens); | ||
38 | return false; | 37 | return false; |
39 | } | 38 | } |
40 | if ctx.is_call { | 39 | if ctx.is_call { |
diff --git a/crates/completion/src/render/enum_variant.rs b/crates/completion/src/render/enum_variant.rs index 7176fd9b3..732e139ec 100644 --- a/crates/completion/src/render/enum_variant.rs +++ b/crates/completion/src/render/enum_variant.rs | |||
@@ -126,50 +126,5 @@ fn main() -> Option<i32> { | |||
126 | } | 126 | } |
127 | "#, | 127 | "#, |
128 | ); | 128 | ); |
129 | check_edit( | ||
130 | "Some", | ||
131 | r#" | ||
132 | enum Option<T> { Some(T), None } | ||
133 | use Option::*; | ||
134 | fn main(value: Option<i32>) { | ||
135 | match value { | ||
136 | Som<|> | ||
137 | } | ||
138 | } | ||
139 | "#, | ||
140 | r#" | ||
141 | enum Option<T> { Some(T), None } | ||
142 | use Option::*; | ||
143 | fn main(value: Option<i32>) { | ||
144 | match value { | ||
145 | Some($0) | ||
146 | } | ||
147 | } | ||
148 | "#, | ||
149 | ); | ||
150 | } | ||
151 | |||
152 | #[test] | ||
153 | fn dont_duplicate_pattern_parens() { | ||
154 | mark::check!(dont_duplicate_pattern_parens); | ||
155 | check_edit( | ||
156 | "Var", | ||
157 | r#" | ||
158 | enum E { Var(i32) } | ||
159 | fn main() { | ||
160 | match E::Var(92) { | ||
161 | E::<|>(92) => (), | ||
162 | } | ||
163 | } | ||
164 | "#, | ||
165 | r#" | ||
166 | enum E { Var(i32) } | ||
167 | fn main() { | ||
168 | match E::Var(92) { | ||
169 | E::Var(92) => (), | ||
170 | } | ||
171 | } | ||
172 | "#, | ||
173 | ); | ||
174 | } | 129 | } |
175 | } | 130 | } |
diff --git a/crates/completion/src/render/pattern.rs b/crates/completion/src/render/pattern.rs new file mode 100644 index 000000000..a3b6a3cac --- /dev/null +++ b/crates/completion/src/render/pattern.rs | |||
@@ -0,0 +1,148 @@ | |||
1 | //! Renderer for patterns. | ||
2 | |||
3 | use hir::{db::HirDatabase, HasAttrs, HasVisibility, Name, StructKind}; | ||
4 | use itertools::Itertools; | ||
5 | |||
6 | use crate::{ | ||
7 | config::SnippetCap, item::CompletionKind, render::RenderContext, CompletionItem, | ||
8 | CompletionItemKind, | ||
9 | }; | ||
10 | |||
11 | fn visible_fields( | ||
12 | ctx: &RenderContext<'_>, | ||
13 | fields: &[hir::Field], | ||
14 | item: impl HasAttrs, | ||
15 | ) -> Option<(Vec<hir::Field>, bool)> { | ||
16 | let module = ctx.completion.scope.module()?; | ||
17 | let n_fields = fields.len(); | ||
18 | let fields = fields | ||
19 | .into_iter() | ||
20 | .filter(|field| field.is_visible_from(ctx.db(), module)) | ||
21 | .copied() | ||
22 | .collect::<Vec<_>>(); | ||
23 | |||
24 | let fields_omitted = | ||
25 | n_fields - fields.len() > 0 || item.attrs(ctx.db()).by_key("non_exhaustive").exists(); | ||
26 | Some((fields, fields_omitted)) | ||
27 | } | ||
28 | |||
29 | pub(crate) fn render_struct_pat( | ||
30 | ctx: RenderContext<'_>, | ||
31 | strukt: hir::Struct, | ||
32 | local_name: Option<Name>, | ||
33 | ) -> Option<CompletionItem> { | ||
34 | let _p = profile::span("render_struct_pat"); | ||
35 | |||
36 | let fields = strukt.fields(ctx.db()); | ||
37 | let (visible_fields, fields_omitted) = visible_fields(&ctx, &fields, strukt)?; | ||
38 | |||
39 | if visible_fields.is_empty() { | ||
40 | // Matching a struct without matching its fields is pointless, unlike matching a Variant without its fields | ||
41 | return None; | ||
42 | } | ||
43 | |||
44 | let name = local_name.unwrap_or_else(|| strukt.name(ctx.db())).to_string(); | ||
45 | let pat = render_pat(&ctx, &name, strukt.kind(ctx.db()), &visible_fields, fields_omitted)?; | ||
46 | |||
47 | Some(build_completion(ctx, name, pat, strukt)) | ||
48 | } | ||
49 | |||
50 | pub(crate) fn render_variant_pat( | ||
51 | ctx: RenderContext<'_>, | ||
52 | variant: hir::Variant, | ||
53 | local_name: Option<Name>, | ||
54 | ) -> Option<CompletionItem> { | ||
55 | let _p = profile::span("render_variant_pat"); | ||
56 | |||
57 | let fields = variant.fields(ctx.db()); | ||
58 | let (visible_fields, fields_omitted) = visible_fields(&ctx, &fields, variant)?; | ||
59 | |||
60 | let name = local_name.unwrap_or_else(|| variant.name(ctx.db())).to_string(); | ||
61 | let pat = render_pat(&ctx, &name, variant.kind(ctx.db()), &visible_fields, fields_omitted)?; | ||
62 | |||
63 | Some(build_completion(ctx, name, pat, variant)) | ||
64 | } | ||
65 | |||
66 | fn build_completion( | ||
67 | ctx: RenderContext<'_>, | ||
68 | name: String, | ||
69 | pat: String, | ||
70 | item: impl HasAttrs + Copy, | ||
71 | ) -> CompletionItem { | ||
72 | let completion = CompletionItem::new(CompletionKind::Snippet, ctx.source_range(), name) | ||
73 | .kind(CompletionItemKind::Binding) | ||
74 | .set_documentation(ctx.docs(item)) | ||
75 | .set_deprecated(ctx.is_deprecated(item)) | ||
76 | .detail(&pat); | ||
77 | let completion = if let Some(snippet_cap) = ctx.snippet_cap() { | ||
78 | completion.insert_snippet(snippet_cap, pat) | ||
79 | } else { | ||
80 | completion.insert_text(pat) | ||
81 | }; | ||
82 | completion.build() | ||
83 | } | ||
84 | |||
85 | fn render_pat( | ||
86 | ctx: &RenderContext<'_>, | ||
87 | name: &str, | ||
88 | kind: StructKind, | ||
89 | fields: &[hir::Field], | ||
90 | fields_omitted: bool, | ||
91 | ) -> Option<String> { | ||
92 | let mut pat = match kind { | ||
93 | StructKind::Tuple if ctx.snippet_cap().is_some() => { | ||
94 | render_tuple_as_pat(&fields, &name, fields_omitted) | ||
95 | } | ||
96 | StructKind::Record => { | ||
97 | render_record_as_pat(ctx.db(), ctx.snippet_cap(), &fields, &name, fields_omitted) | ||
98 | } | ||
99 | _ => return None, | ||
100 | }; | ||
101 | |||
102 | if ctx.completion.is_param { | ||
103 | pat.push(':'); | ||
104 | pat.push(' '); | ||
105 | pat.push_str(&name); | ||
106 | } | ||
107 | if ctx.snippet_cap().is_some() { | ||
108 | pat.push_str("$0"); | ||
109 | } | ||
110 | Some(pat) | ||
111 | } | ||
112 | |||
113 | fn render_record_as_pat( | ||
114 | db: &dyn HirDatabase, | ||
115 | snippet_cap: Option<SnippetCap>, | ||
116 | fields: &[hir::Field], | ||
117 | name: &str, | ||
118 | fields_omitted: bool, | ||
119 | ) -> String { | ||
120 | let fields = fields.iter(); | ||
121 | if snippet_cap.is_some() { | ||
122 | format!( | ||
123 | "{name} {{ {}{} }}", | ||
124 | fields | ||
125 | .enumerate() | ||
126 | .map(|(idx, field)| format!("{}${}", field.name(db), idx + 1)) | ||
127 | .format(", "), | ||
128 | if fields_omitted { ", .." } else { "" }, | ||
129 | name = name | ||
130 | ) | ||
131 | } else { | ||
132 | format!( | ||
133 | "{name} {{ {}{} }}", | ||
134 | fields.map(|field| field.name(db)).format(", "), | ||
135 | if fields_omitted { ", .." } else { "" }, | ||
136 | name = name | ||
137 | ) | ||
138 | } | ||
139 | } | ||
140 | |||
141 | fn render_tuple_as_pat(fields: &[hir::Field], name: &str, fields_omitted: bool) -> String { | ||
142 | format!( | ||
143 | "{name}({}{})", | ||
144 | fields.iter().enumerate().map(|(idx, _)| format!("${}", idx + 1)).format(", "), | ||
145 | if fields_omitted { ", .." } else { "" }, | ||
146 | name = name | ||
147 | ) | ||
148 | } | ||
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index 73ca6ba9f..1d7e5ddd7 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs | |||
@@ -511,6 +511,10 @@ impl Struct { | |||
511 | db.struct_data(self.id).repr.clone() | 511 | db.struct_data(self.id).repr.clone() |
512 | } | 512 | } |
513 | 513 | ||
514 | pub fn kind(self, db: &dyn HirDatabase) -> StructKind { | ||
515 | self.variant_data(db).kind() | ||
516 | } | ||
517 | |||
514 | fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> { | 518 | fn variant_data(self, db: &dyn HirDatabase) -> Arc<VariantData> { |
515 | db.struct_data(self.id).variant_data.clone() | 519 | db.struct_data(self.id).variant_data.clone() |
516 | } | 520 | } |
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/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"`):: | |||
5 | rust-analyzer.callInfo.full (default: `true`):: | 5 | rust-analyzer.callInfo.full (default: `true`):: |
6 | Show function name and docs in parameter hints. | 6 | Show function name and docs in parameter hints. |
7 | rust-analyzer.cargo.autoreload (default: `true`):: | 7 | rust-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. |
9 | rust-analyzer.cargo.allFeatures (default: `false`):: | 9 | rust-analyzer.cargo.allFeatures (default: `false`):: |
10 | Activate all available features. | 10 | Activate all available features. |
11 | rust-analyzer.cargo.features (default: `[]`):: | 11 | rust-analyzer.cargo.features (default: `[]`):: |
@@ -21,7 +21,7 @@ rust-analyzer.cargo.noSysroot (default: `false`):: | |||
21 | rust-analyzer.checkOnSave.enable (default: `true`):: | 21 | rust-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. |
23 | rust-analyzer.checkOnSave.allFeatures (default: `null`):: | 23 | rust-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#`. |
25 | rust-analyzer.checkOnSave.allTargets (default: `true`):: | 25 | rust-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`). |
27 | rust-analyzer.checkOnSave.command (default: `"check"`):: | 27 | rust-analyzer.checkOnSave.command (default: `"check"`):: |
@@ -29,11 +29,11 @@ rust-analyzer.checkOnSave.command (default: `"check"`):: | |||
29 | rust-analyzer.checkOnSave.noDefaultFeatures (default: `null`):: | 29 | rust-analyzer.checkOnSave.noDefaultFeatures (default: `null`):: |
30 | Do not activate the `default` feature. | 30 | Do not activate the `default` feature. |
31 | rust-analyzer.checkOnSave.target (default: `null`):: | 31 | rust-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#`. |
33 | rust-analyzer.checkOnSave.extraArgs (default: `[]`):: | 33 | rust-analyzer.checkOnSave.extraArgs (default: `[]`):: |
34 | Extra arguments for `cargo check`. | 34 | Extra arguments for `cargo check`. |
35 | rust-analyzer.checkOnSave.features (default: `null`):: | 35 | rust-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#`. |
37 | rust-analyzer.checkOnSave.overrideCommand (default: `null`):: | 37 | rust-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. |
39 | rust-analyzer.completion.addCallArgumentSnippets (default: `true`):: | 39 | rust-analyzer.completion.addCallArgumentSnippets (default: `true`):: |
@@ -43,7 +43,7 @@ rust-analyzer.completion.addCallParenthesis (default: `true`):: | |||
43 | rust-analyzer.completion.postfix.enable (default: `true`):: | 43 | rust-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. |
45 | rust-analyzer.completion.autoimport.enable (default: `true`):: | 45 | rust-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. |
47 | rust-analyzer.diagnostics.enable (default: `true`):: | 47 | rust-analyzer.diagnostics.enable (default: `true`):: |
48 | Whether to show native rust-analyzer diagnostics. | 48 | Whether to show native rust-analyzer diagnostics. |
49 | rust-analyzer.diagnostics.enableExperimental (default: `true`):: | 49 | rust-analyzer.diagnostics.enableExperimental (default: `true`):: |
@@ -51,9 +51,9 @@ rust-analyzer.diagnostics.enableExperimental (default: `true`):: | |||
51 | rust-analyzer.diagnostics.disabled (default: `[]`):: | 51 | rust-analyzer.diagnostics.disabled (default: `[]`):: |
52 | List of rust-analyzer diagnostics to disable. | 52 | List of rust-analyzer diagnostics to disable. |
53 | rust-analyzer.diagnostics.warningsAsHint (default: `[]`):: | 53 | rust-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`. |
55 | rust-analyzer.diagnostics.warningsAsInfo (default: `[]`):: | 55 | rust-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`. |
57 | rust-analyzer.files.watcher (default: `"client"`):: | 57 | rust-analyzer.files.watcher (default: `"client"`):: |
58 | Controls file watching implementation. | 58 | Controls file watching implementation. |
59 | rust-analyzer.hoverActions.debug (default: `true`):: | 59 | rust-analyzer.hoverActions.debug (default: `true`):: |
@@ -71,7 +71,7 @@ rust-analyzer.hoverActions.linksInHover (default: `true`):: | |||
71 | rust-analyzer.inlayHints.chainingHints (default: `true`):: | 71 | rust-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. |
73 | rust-analyzer.inlayHints.maxLength (default: `null`):: | 73 | rust-analyzer.inlayHints.maxLength (default: `null`):: |
74 | Maximum length for inlay hints. | 74 | Maximum length for inlay hints. Default is unlimited. |
75 | rust-analyzer.inlayHints.parameterHints (default: `true`):: | 75 | rust-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. |
77 | rust-analyzer.inlayHints.typeHints (default: `true`):: | 77 | rust-analyzer.inlayHints.typeHints (default: `true`):: |
@@ -87,20 +87,20 @@ rust-analyzer.lens.run (default: `true`):: | |||
87 | rust-analyzer.lens.methodReferences (default: `false`):: | 87 | rust-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. |
89 | rust-analyzer.linkedProjects (default: `[]`):: | 89 | rust-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. |
91 | rust-analyzer.lruCapacity (default: `null`):: | 91 | rust-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. |
93 | rust-analyzer.notifications.cargoTomlNotFound (default: `true`):: | 93 | rust-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. |
95 | rust-analyzer.procMacro.enable (default: `false`):: | 95 | rust-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. |
97 | rust-analyzer.runnables.overrideCargo (default: `null`):: | 97 | rust-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. |
99 | rust-analyzer.runnables.cargoExtraArgs (default: `[]`):: | 99 | rust-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`. |
101 | rust-analyzer.rustcSource (default: `null`):: | 101 | rust-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. |
103 | rust-analyzer.rustfmt.extraArgs (default: `[]`):: | 103 | rust-analyzer.rustfmt.extraArgs (default: `[]`):: |
104 | Additional arguments to rustfmt. | 104 | Additional arguments to `rustfmt`. |
105 | rust-analyzer.rustfmt.overrideCommand (default: `null`):: | 105 | rust-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/editors/code/package.json b/editors/code/package.json index abcc84eda..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": { |
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts index 4b2d3c8a5..282240d84 100644 --- a/editors/code/src/main.ts +++ b/editors/code/src/main.ts | |||
@@ -131,7 +131,7 @@ async function tryActivate(context: vscode.ExtensionContext) { | |||
131 | ctx.pushCleanup(activateTaskProvider(workspaceFolder, ctx.config)); | 131 | ctx.pushCleanup(activateTaskProvider(workspaceFolder, ctx.config)); |
132 | 132 | ||
133 | activateInlayHints(ctx); | 133 | activateInlayHints(ctx); |
134 | warnAboutRustLangExtensionConflict(); | 134 | warnAboutExtensionConflicts(); |
135 | 135 | ||
136 | vscode.workspace.onDidChangeConfiguration( | 136 | vscode.workspace.onDidChangeConfiguration( |
137 | _ => ctx?.client?.sendNotification('workspace/didChangeConfiguration', { settings: "" }), | 137 | _ => ctx?.client?.sendNotification('workspace/didChangeConfiguration', { settings: "" }), |
@@ -287,12 +287,14 @@ async function getServer(config: Config, state: PersistentState): Promise<string | |||
287 | if (config.package.releaseTag === null) return "rust-analyzer"; | 287 | if (config.package.releaseTag === null) return "rust-analyzer"; |
288 | 288 | ||
289 | let platform: string | undefined; | 289 | let platform: string | undefined; |
290 | if (process.arch === "x64" || process.arch === "ia32") { | 290 | if ((process.arch === "x64" || process.arch === "ia32") && process.platform === "win32") { |
291 | if (process.platform === "linux") platform = "linux"; | 291 | platform = "x86_64-pc-windows-msvc"; |
292 | if (process.platform === "darwin") platform = "mac"; | 292 | } else if (process.arch === "x64" && process.platform === "linux") { |
293 | 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"; | ||
294 | } else if (process.arch === "arm64" && process.platform === "darwin") { | 296 | } else if (process.arch === "arm64" && process.platform === "darwin") { |
295 | platform = "mac"; | 297 | platform = "aarch64-apple-darwin"; |
296 | } | 298 | } |
297 | if (platform === undefined) { | 299 | if (platform === undefined) { |
298 | vscode.window.showErrorMessage( | 300 | vscode.window.showErrorMessage( |
@@ -305,7 +307,7 @@ async function getServer(config: Config, state: PersistentState): Promise<string | |||
305 | ); | 307 | ); |
306 | return undefined; | 308 | return undefined; |
307 | } | 309 | } |
308 | const ext = platform === "windows" ? ".exe" : ""; | 310 | const ext = platform.indexOf("-windows-") !== -1 ? ".exe" : ""; |
309 | const dest = path.join(config.globalStoragePath, `rust-analyzer-${platform}${ext}`); | 311 | const dest = path.join(config.globalStoragePath, `rust-analyzer-${platform}${ext}`); |
310 | const exists = await fs.stat(dest).then(() => true, () => false); | 312 | const exists = await fs.stat(dest).then(() => true, () => false); |
311 | if (!exists) { | 313 | if (!exists) { |
@@ -411,11 +413,21 @@ async function queryForGithubToken(state: PersistentState): Promise<void> { | |||
411 | } | 413 | } |
412 | } | 414 | } |
413 | 415 | ||
414 | function warnAboutRustLangExtensionConflict() { | 416 | function warnAboutExtensionConflicts() { |
415 | const rustLangExt = vscode.extensions.getExtension("rust-lang.rust"); | 417 | const conflicting = [ |
416 | 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]; | ||
417 | vscode.window.showWarningMessage( | 429 | vscode.window.showWarningMessage( |
418 | "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]}) ` + |
419 | "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 " + |
420 | "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"); |
421 | }; | 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 | ||
60 | fn dist_server() -> Result<()> { | 60 | fn 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 | ||
97 | fn 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 | |||
114 | fn exe_suffix(target: &str) -> String { | ||
115 | if target.contains("-windows-") { | ||
116 | ".exe".into() | ||
117 | } else { | ||
118 | "".into() | ||
119 | } | ||
120 | } | ||
121 | |||
122 | fn toolchain(target: &str) -> String { | ||
123 | match target { | ||
124 | "aarch64-apple-darwin" => "beta".to_string(), | ||
125 | _ => "stable".to_string(), | ||
126 | } | ||
127 | } | ||
128 | |||
85 | fn gzip(src_path: &Path, dest_path: &Path) -> Result<()> { | 129 | fn 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)?); |