aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/release.yaml1
-rw-r--r--crates/ra_hir_expand/src/builtin_derive.rs113
-rw-r--r--crates/ra_hir_ty/src/tests/macros.rs33
-rw-r--r--crates/ra_ide/src/snapshots/highlight_injection.html1
-rw-r--r--crates/ra_ide/src/snapshots/highlight_strings.html71
-rw-r--r--crates/ra_ide/src/snapshots/highlighting.html1
-rw-r--r--crates/ra_ide/src/snapshots/rainbow_highlighting.html1
-rw-r--r--crates/ra_ide/src/syntax_highlighting.rs2
-rw-r--r--crates/ra_ide/src/syntax_highlighting/html.rs1
-rw-r--r--crates/ra_ide/src/syntax_highlighting/tags.rs2
-rw-r--r--crates/ra_prof/src/hprof.rs45
-rw-r--r--crates/ra_syntax/src/ast.rs15
-rw-r--r--crates/ra_syntax/src/ast/tokens.rs17
-rw-r--r--crates/rust-analyzer/src/conv.rs4
-rw-r--r--crates/rust-analyzer/src/semantic_tokens.rs115
-rw-r--r--docs/dev/architecture.md2
-rw-r--r--docs/user/readme.adoc27
-rw-r--r--xtask/src/dist.rs8
18 files changed, 284 insertions, 175 deletions
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index 2c1192f07..3f52f31f8 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -39,7 +39,6 @@ jobs:
39 with: 39 with:
40 toolchain: stable 40 toolchain: stable
41 profile: minimal 41 profile: minimal
42 target: x86_64-unknown-linux-musl
43 override: true 42 override: true
44 43
45 - name: Install Nodejs 44 - name: Install Nodejs
diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs
index bb45b0f1d..e60f879a3 100644
--- a/crates/ra_hir_expand/src/builtin_derive.rs
+++ b/crates/ra_hir_expand/src/builtin_derive.rs
@@ -9,7 +9,7 @@ use ra_syntax::{
9}; 9};
10 10
11use crate::db::AstDatabase; 11use crate::db::AstDatabase;
12use crate::{name, quote, LazyMacroId, MacroDefId, MacroDefKind}; 12use crate::{name, quote, LazyMacroId, MacroCallId, MacroDefId, MacroDefKind};
13 13
14macro_rules! register_builtin { 14macro_rules! register_builtin {
15 ( $($trait:ident => $expand:ident),* ) => { 15 ( $($trait:ident => $expand:ident),* ) => {
@@ -153,76 +153,113 @@ fn expand_simple_derive(
153 Ok(expanded) 153 Ok(expanded)
154} 154}
155 155
156fn find_builtin_crate(db: &dyn AstDatabase, id: LazyMacroId) -> tt::TokenTree {
157 // FIXME: make hygiene works for builtin derive macro
158 // such that $crate can be used here.
159
160 let m: MacroCallId = id.into();
161 let file_id = m.as_file().original_file(db);
162 let cg = db.crate_graph();
163 let krates = db.relevant_crates(file_id);
164 let krate = match krates.get(0) {
165 Some(krate) => krate,
166 None => {
167 let tt = quote! { core };
168 return tt.token_trees[0].clone();
169 }
170 };
171
172 // XXX
173 // All crates except core itself should have a dependency on core,
174 // We detect `core` by seeing whether it doesn't have such a dependency.
175 let tt = if cg[*krate].dependencies.iter().any(|dep| dep.name == "core") {
176 quote! { core }
177 } else {
178 quote! { crate }
179 };
180
181 tt.token_trees[0].clone()
182}
183
156fn copy_expand( 184fn copy_expand(
157 _db: &dyn AstDatabase, 185 db: &dyn AstDatabase,
158 _id: LazyMacroId, 186 id: LazyMacroId,
159 tt: &tt::Subtree, 187 tt: &tt::Subtree,
160) -> Result<tt::Subtree, mbe::ExpandError> { 188) -> Result<tt::Subtree, mbe::ExpandError> {
161 expand_simple_derive(tt, quote! { std::marker::Copy }) 189 let krate = find_builtin_crate(db, id);
190 expand_simple_derive(tt, quote! { #krate::marker::Copy })
162} 191}
163 192
164fn clone_expand( 193fn clone_expand(
165 _db: &dyn AstDatabase, 194 db: &dyn AstDatabase,
166 _id: LazyMacroId, 195 id: LazyMacroId,
167 tt: &tt::Subtree, 196 tt: &tt::Subtree,
168) -> Result<tt::Subtree, mbe::ExpandError> { 197) -> Result<tt::Subtree, mbe::ExpandError> {
169 expand_simple_derive(tt, quote! { std::clone::Clone }) 198 let krate = find_builtin_crate(db, id);
199 expand_simple_derive(tt, quote! { #krate::clone::Clone })
170} 200}
171 201
172fn default_expand( 202fn default_expand(
173 _db: &dyn AstDatabase, 203 db: &dyn AstDatabase,
174 _id: LazyMacroId, 204 id: LazyMacroId,
175 tt: &tt::Subtree, 205 tt: &tt::Subtree,
176) -> Result<tt::Subtree, mbe::ExpandError> { 206) -> Result<tt::Subtree, mbe::ExpandError> {
177 expand_simple_derive(tt, quote! { std::default::Default }) 207 let krate = find_builtin_crate(db, id);
208 expand_simple_derive(tt, quote! { #krate::default::Default })
178} 209}
179 210
180fn debug_expand( 211fn debug_expand(
181 _db: &dyn AstDatabase, 212 db: &dyn AstDatabase,
182 _id: LazyMacroId, 213 id: LazyMacroId,
183 tt: &tt::Subtree, 214 tt: &tt::Subtree,
184) -> Result<tt::Subtree, mbe::ExpandError> { 215) -> Result<tt::Subtree, mbe::ExpandError> {
185 expand_simple_derive(tt, quote! { std::fmt::Debug }) 216 let krate = find_builtin_crate(db, id);
217 expand_simple_derive(tt, quote! { #krate::fmt::Debug })
186} 218}
187 219
188fn hash_expand( 220fn hash_expand(
189 _db: &dyn AstDatabase, 221 db: &dyn AstDatabase,
190 _id: LazyMacroId, 222 id: LazyMacroId,
191 tt: &tt::Subtree, 223 tt: &tt::Subtree,
192) -> Result<tt::Subtree, mbe::ExpandError> { 224) -> Result<tt::Subtree, mbe::ExpandError> {
193 expand_simple_derive(tt, quote! { std::hash::Hash }) 225 let krate = find_builtin_crate(db, id);
226 expand_simple_derive(tt, quote! { #krate::hash::Hash })
194} 227}
195 228
196fn eq_expand( 229fn eq_expand(
197 _db: &dyn AstDatabase, 230 db: &dyn AstDatabase,
198 _id: LazyMacroId, 231 id: LazyMacroId,
199 tt: &tt::Subtree, 232 tt: &tt::Subtree,
200) -> Result<tt::Subtree, mbe::ExpandError> { 233) -> Result<tt::Subtree, mbe::ExpandError> {
201 expand_simple_derive(tt, quote! { std::cmp::Eq }) 234 let krate = find_builtin_crate(db, id);
235 expand_simple_derive(tt, quote! { #krate::cmp::Eq })
202} 236}
203 237
204fn partial_eq_expand( 238fn partial_eq_expand(
205 _db: &dyn AstDatabase, 239 db: &dyn AstDatabase,
206 _id: LazyMacroId, 240 id: LazyMacroId,
207 tt: &tt::Subtree, 241 tt: &tt::Subtree,
208) -> Result<tt::Subtree, mbe::ExpandError> { 242) -> Result<tt::Subtree, mbe::ExpandError> {
209 expand_simple_derive(tt, quote! { std::cmp::PartialEq }) 243 let krate = find_builtin_crate(db, id);
244 expand_simple_derive(tt, quote! { #krate::cmp::PartialEq })
210} 245}
211 246
212fn ord_expand( 247fn ord_expand(
213 _db: &dyn AstDatabase, 248 db: &dyn AstDatabase,
214 _id: LazyMacroId, 249 id: LazyMacroId,
215 tt: &tt::Subtree, 250 tt: &tt::Subtree,
216) -> Result<tt::Subtree, mbe::ExpandError> { 251) -> Result<tt::Subtree, mbe::ExpandError> {
217 expand_simple_derive(tt, quote! { std::cmp::Ord }) 252 let krate = find_builtin_crate(db, id);
253 expand_simple_derive(tt, quote! { #krate::cmp::Ord })
218} 254}
219 255
220fn partial_ord_expand( 256fn partial_ord_expand(
221 _db: &dyn AstDatabase, 257 db: &dyn AstDatabase,
222 _id: LazyMacroId, 258 id: LazyMacroId,
223 tt: &tt::Subtree, 259 tt: &tt::Subtree,
224) -> Result<tt::Subtree, mbe::ExpandError> { 260) -> Result<tt::Subtree, mbe::ExpandError> {
225 expand_simple_derive(tt, quote! { std::cmp::PartialOrd }) 261 let krate = find_builtin_crate(db, id);
262 expand_simple_derive(tt, quote! { #krate::cmp::PartialOrd })
226} 263}
227 264
228#[cfg(test)] 265#[cfg(test)]
@@ -234,8 +271,18 @@ mod tests {
234 271
235 fn expand_builtin_derive(s: &str, name: Name) -> String { 272 fn expand_builtin_derive(s: &str, name: Name) -> String {
236 let def = find_builtin_derive(&name).unwrap(); 273 let def = find_builtin_derive(&name).unwrap();
274 let fixture = format!(
275 r#"//- /main.rs crate:main deps:core
276<|>
277{}
278//- /lib.rs crate:core
279// empty
280"#,
281 s
282 );
237 283
238 let (db, file_id) = TestDB::with_single_file(&s); 284 let (db, file_pos) = TestDB::with_position(&fixture);
285 let file_id = file_pos.file_id;
239 let parsed = db.parse(file_id); 286 let parsed = db.parse(file_id);
240 let items: Vec<_> = 287 let items: Vec<_> =
241 parsed.syntax_node().descendants().filter_map(ast::ModuleItem::cast).collect(); 288 parsed.syntax_node().descendants().filter_map(ast::ModuleItem::cast).collect();
@@ -264,7 +311,7 @@ mod tests {
264 known::Copy, 311 known::Copy,
265 ); 312 );
266 313
267 assert_eq!(expanded, "impl< >std::marker::CopyforFoo< >{}"); 314 assert_eq!(expanded, "impl< >core::marker::CopyforFoo< >{}");
268 } 315 }
269 316
270 #[test] 317 #[test]
@@ -279,7 +326,7 @@ mod tests {
279 326
280 assert_eq!( 327 assert_eq!(
281 expanded, 328 expanded,
282 "impl<T0:std::marker::Copy,T1:std::marker::Copy>std::marker::CopyforFoo<T0,T1>{}" 329 "impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}"
283 ); 330 );
284 } 331 }
285 332
@@ -297,7 +344,7 @@ mod tests {
297 344
298 assert_eq!( 345 assert_eq!(
299 expanded, 346 expanded,
300 "impl<T0:std::marker::Copy,T1:std::marker::Copy>std::marker::CopyforFoo<T0,T1>{}" 347 "impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}"
301 ); 348 );
302 } 349 }
303 350
@@ -313,7 +360,7 @@ mod tests {
313 360
314 assert_eq!( 361 assert_eq!(
315 expanded, 362 expanded,
316 "impl<T0:std::clone::Clone,T1:std::clone::Clone>std::clone::CloneforFoo<T0,T1>{}" 363 "impl<T0:core::clone::Clone,T1:core::clone::Clone>core::clone::CloneforFoo<T0,T1>{}"
317 ); 364 );
318 } 365 }
319} 366}
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs
index 6b5267232..5ddecbdc6 100644
--- a/crates/ra_hir_ty/src/tests/macros.rs
+++ b/crates/ra_hir_ty/src/tests/macros.rs
@@ -622,14 +622,14 @@ fn main() {
622fn infer_derive_clone_simple() { 622fn infer_derive_clone_simple() {
623 let (db, pos) = TestDB::with_position( 623 let (db, pos) = TestDB::with_position(
624 r#" 624 r#"
625//- /main.rs crate:main deps:std 625//- /main.rs crate:main deps:core
626#[derive(Clone)] 626#[derive(Clone)]
627struct S; 627struct S;
628fn test() { 628fn test() {
629 S.clone()<|>; 629 S.clone()<|>;
630} 630}
631 631
632//- /lib.rs crate:std 632//- /lib.rs crate:core
633#[prelude_import] 633#[prelude_import]
634use clone::*; 634use clone::*;
635mod clone { 635mod clone {
@@ -643,10 +643,35 @@ mod clone {
643} 643}
644 644
645#[test] 645#[test]
646fn infer_derive_clone_in_core() {
647 let (db, pos) = TestDB::with_position(
648 r#"
649//- /lib.rs crate:core
650#[prelude_import]
651use clone::*;
652mod clone {
653 trait Clone {
654 fn clone(&self) -> Self;
655 }
656}
657#[derive(Clone)]
658pub struct S;
659
660//- /main.rs crate:main deps:core
661use core::S;
662fn test() {
663 S.clone()<|>;
664}
665"#,
666 );
667 assert_eq!("S", type_at_pos(&db, pos));
668}
669
670#[test]
646fn infer_derive_clone_with_params() { 671fn infer_derive_clone_with_params() {
647 let (db, pos) = TestDB::with_position( 672 let (db, pos) = TestDB::with_position(
648 r#" 673 r#"
649//- /main.rs crate:main deps:std 674//- /main.rs crate:main deps:core
650#[derive(Clone)] 675#[derive(Clone)]
651struct S; 676struct S;
652#[derive(Clone)] 677#[derive(Clone)]
@@ -656,7 +681,7 @@ fn test() {
656 (Wrapper(S).clone(), Wrapper(NonClone).clone())<|>; 681 (Wrapper(S).clone(), Wrapper(NonClone).clone())<|>;
657} 682}
658 683
659//- /lib.rs crate:std 684//- /lib.rs crate:core
660#[prelude_import] 685#[prelude_import]
661use clone::*; 686use clone::*;
662mod clone { 687mod clone {
diff --git a/crates/ra_ide/src/snapshots/highlight_injection.html b/crates/ra_ide/src/snapshots/highlight_injection.html
index 6ec13bd80..ea026d7a0 100644
--- a/crates/ra_ide/src/snapshots/highlight_injection.html
+++ b/crates/ra_ide/src/snapshots/highlight_injection.html
@@ -20,6 +20,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
20.macro { color: #94BFF3; } 20.macro { color: #94BFF3; }
21.module { color: #AFD8AF; } 21.module { color: #AFD8AF; }
22.variable { color: #DCDCCC; } 22.variable { color: #DCDCCC; }
23.format_specifier { color: #CC696B; }
23.mutable { text-decoration: underline; } 24.mutable { text-decoration: underline; }
24 25
25.keyword { color: #F0DFAF; font-weight: bold; } 26.keyword { color: #F0DFAF; font-weight: bold; }
diff --git a/crates/ra_ide/src/snapshots/highlight_strings.html b/crates/ra_ide/src/snapshots/highlight_strings.html
index 433f2e0c5..de06daf72 100644
--- a/crates/ra_ide/src/snapshots/highlight_strings.html
+++ b/crates/ra_ide/src/snapshots/highlight_strings.html
@@ -20,6 +20,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
20.macro { color: #94BFF3; } 20.macro { color: #94BFF3; }
21.module { color: #AFD8AF; } 21.module { color: #AFD8AF; }
22.variable { color: #DCDCCC; } 22.variable { color: #DCDCCC; }
23.format_specifier { color: #CC696B; }
23.mutable { text-decoration: underline; } 24.mutable { text-decoration: underline; }
24 25
25.keyword { color: #F0DFAF; font-weight: bold; } 26.keyword { color: #F0DFAF; font-weight: bold; }
@@ -40,43 +41,43 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
40<span class="keyword">fn</span> <span class="function declaration">main</span>() { 41<span class="keyword">fn</span> <span class="function declaration">main</span>() {
41 <span class="comment">// from https://doc.rust-lang.org/std/fmt/index.html</span> 42 <span class="comment">// from https://doc.rust-lang.org/std/fmt/index.html</span>
42 <span class="macro">println!</span>(<span class="string_literal">"Hello"</span>); <span class="comment">// =&gt; "Hello"</span> 43 <span class="macro">println!</span>(<span class="string_literal">"Hello"</span>); <span class="comment">// =&gt; "Hello"</span>
43 <span class="macro">println!</span>(<span class="string_literal">"Hello, </span><span class="attribute">{</span><span class="attribute">}</span><span class="string_literal">!"</span>, <span class="string_literal">"world"</span>); <span class="comment">// =&gt; "Hello, world!"</span> 44 <span class="macro">println!</span>(<span class="string_literal">"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="string_literal">"world"</span>); <span class="comment">// =&gt; "Hello, world!"</span>
44 <span class="macro">println!</span>(<span class="string_literal">"The number is </span><span class="attribute">{</span><span class="attribute">}</span><span class="string_literal">"</span>, <span class="numeric_literal">1</span>); <span class="comment">// =&gt; "The number is 1"</span> 45 <span class="macro">println!</span>(<span class="string_literal">"The number is </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="numeric_literal">1</span>); <span class="comment">// =&gt; "The number is 1"</span>
45 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="attribute">{</span><span class="attribute">:</span><span class="attribute">?</span><span class="attribute">}</span><span class="string_literal">"</span>, (<span class="numeric_literal">3</span>, <span class="numeric_literal">4</span>)); <span class="comment">// =&gt; "(3, 4)"</span> 46 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">?</span><span class="format_specifier">}</span><span class="string_literal">"</span>, (<span class="numeric_literal">3</span>, <span class="numeric_literal">4</span>)); <span class="comment">// =&gt; "(3, 4)"</span>
46 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="attribute">{</span><span class="variable">value</span><span class="attribute">}</span><span class="string_literal">"</span>, value=<span class="numeric_literal">4</span>); <span class="comment">// =&gt; "4"</span> 47 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">value</span><span class="format_specifier">}</span><span class="string_literal">"</span>, value=<span class="numeric_literal">4</span>); <span class="comment">// =&gt; "4"</span>
47 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="attribute">{</span><span class="attribute">}</span><span class="string_literal"> </span><span class="attribute">{</span><span class="attribute">}</span><span class="string_literal">"</span>, <span class="numeric_literal">1</span>, <span class="numeric_literal">2</span>); <span class="comment">// =&gt; "1 2"</span> 48 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="numeric_literal">1</span>, <span class="numeric_literal">2</span>); <span class="comment">// =&gt; "1 2"</span>
48 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="attribute">{</span><span class="attribute">:</span><span class="numeric_literal">0</span><span class="numeric_literal">4</span><span class="attribute">}</span><span class="string_literal">"</span>, <span class="numeric_literal">42</span>); <span class="comment">// =&gt; "0042" with leading zerosV</span> 49 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">4</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="numeric_literal">42</span>); <span class="comment">// =&gt; "0042" with leading zerosV</span>
49 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="attribute">{</span><span class="numeric_literal">1</span><span class="attribute">}</span><span class="string_literal"> </span><span class="attribute">{</span><span class="attribute">}</span><span class="string_literal"> </span><span class="attribute">{</span><span class="numeric_literal">0</span><span class="attribute">}</span><span class="string_literal"> </span><span class="attribute">{</span><span class="attribute">}</span><span class="string_literal">"</span>, <span class="numeric_literal">1</span>, <span class="numeric_literal">2</span>); <span class="comment">// =&gt; "2 1 1 2"</span> 50 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="numeric_literal">1</span>, <span class="numeric_literal">2</span>); <span class="comment">// =&gt; "2 1 1 2"</span>
50 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="attribute">{</span><span class="variable">argument</span><span class="attribute">}</span><span class="string_literal">"</span>, argument = <span class="string_literal">"test"</span>); <span class="comment">// =&gt; "test"</span> 51 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">argument</span><span class="format_specifier">}</span><span class="string_literal">"</span>, argument = <span class="string_literal">"test"</span>); <span class="comment">// =&gt; "test"</span>
51 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="attribute">{</span><span class="variable">name</span><span class="attribute">}</span><span class="string_literal"> </span><span class="attribute">{</span><span class="attribute">}</span><span class="string_literal">"</span>, <span class="numeric_literal">1</span>, name = <span class="numeric_literal">2</span>); <span class="comment">// =&gt; "2 1"</span> 52 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="numeric_literal">1</span>, name = <span class="numeric_literal">2</span>); <span class="comment">// =&gt; "2 1"</span>
52 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="attribute">{</span><span class="variable">a</span><span class="attribute">}</span><span class="string_literal"> </span><span class="attribute">{</span><span class="variable">c</span><span class="attribute">}</span><span class="string_literal"> </span><span class="attribute">{</span><span class="variable">b</span><span class="attribute">}</span><span class="string_literal">"</span>, a=<span class="string_literal">"a"</span>, b=<span class="char_literal">'b'</span>, c=<span class="numeric_literal">3</span>); <span class="comment">// =&gt; "a 3 b"</span> 53 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">a</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="variable">c</span><span class="format_specifier">}</span><span class="string_literal"> </span><span class="format_specifier">{</span><span class="variable">b</span><span class="format_specifier">}</span><span class="string_literal">"</span>, a=<span class="string_literal">"a"</span>, b=<span class="char_literal">'b'</span>, c=<span class="numeric_literal">3</span>); <span class="comment">// =&gt; "a 3 b"</span>
53 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="attribute">{</span><span class="attribute">:</span><span class="numeric_literal">5</span><span class="attribute">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>); 54 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>);
54 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="attribute">{</span><span class="attribute">:</span><span class="numeric_literal">1</span><span class="attribute">$</span><span class="attribute">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>, <span class="numeric_literal">5</span>); 55 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>, <span class="numeric_literal">5</span>);
55 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="attribute">{</span><span class="numeric_literal">1</span><span class="attribute">:</span><span class="numeric_literal">0</span><span class="attribute">$</span><span class="attribute">}</span><span class="string_literal">!"</span>, <span class="numeric_literal">5</span>, <span class="string_literal">"x"</span>); 56 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="numeric_literal">5</span>, <span class="string_literal">"x"</span>);
56 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="attribute">{</span><span class="attribute">:</span><span class="variable">width</span><span class="attribute">$</span><span class="attribute">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>, width = <span class="numeric_literal">5</span>); 57 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="variable">width</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>, width = <span class="numeric_literal">5</span>);
57 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="attribute">{</span><span class="attribute">:</span><span class="attribute">&lt;</span><span class="numeric_literal">5</span><span class="attribute">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>); 58 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">&lt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>);
58 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="attribute">{</span><span class="attribute">:</span><span class="attribute">-</span><span class="attribute">&lt;</span><span class="numeric_literal">5</span><span class="attribute">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>); 59 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">-</span><span class="format_specifier">&lt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>);
59 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="attribute">{</span><span class="attribute">:</span><span class="attribute">^</span><span class="numeric_literal">5</span><span class="attribute">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>); 60 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">^</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>);
60 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="attribute">{</span><span class="attribute">:</span><span class="attribute">&gt;</span><span class="numeric_literal">5</span><span class="attribute">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>); 61 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="string_literal">"x"</span>);
61 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="attribute">{</span><span class="attribute">:</span><span class="attribute">+</span><span class="attribute">}</span><span class="string_literal">!"</span>, <span class="numeric_literal">5</span>); 62 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">+</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="numeric_literal">5</span>);
62 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="attribute">{</span><span class="attribute">:</span><span class="attribute">#</span><span class="variable">x</span><span class="string_literal">}!"</span>, <span class="numeric_literal">27</span>); 63 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="variable">x</span><span class="string_literal">}!"</span>, <span class="numeric_literal">27</span>);
63 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="attribute">{</span><span class="attribute">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="attribute">}</span><span class="string_literal">!"</span>, <span class="numeric_literal">5</span>); 64 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="numeric_literal">5</span>);
64 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="attribute">{</span><span class="attribute">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="attribute">}</span><span class="string_literal">!"</span>, -<span class="numeric_literal">5</span>); 65 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="numeric_literal">0</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, -<span class="numeric_literal">5</span>);
65 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="attribute">{</span><span class="attribute">:</span><span class="attribute">#</span><span class="numeric_literal">0</span><span class="numeric_literal">10</span><span class="variable">x</span><span class="attribute">}</span><span class="string_literal">!"</span>, <span class="numeric_literal">27</span>); 66 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">#</span><span class="numeric_literal">0</span><span class="numeric_literal">10</span><span class="variable">x</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="numeric_literal">27</span>);
66 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="attribute">{</span><span class="numeric_literal">0</span><span class="attribute">}</span><span class="string_literal"> is </span><span class="attribute">{</span><span class="numeric_literal">1</span><span class="attribute">:</span><span class="attribute">.</span><span class="numeric_literal">5</span><span class="attribute">}</span><span class="string_literal">"</span>, <span class="string_literal">"x"</span>, <span class="numeric_literal">0.01</span>); 67 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">5</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="string_literal">"x"</span>, <span class="numeric_literal">0.01</span>);
67 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="attribute">{</span><span class="numeric_literal">1</span><span class="attribute">}</span><span class="string_literal"> is </span><span class="attribute">{</span><span class="numeric_literal">2</span><span class="attribute">:</span><span class="attribute">.</span><span class="numeric_literal">0</span><span class="attribute">$</span><span class="attribute">}</span><span class="string_literal">"</span>, <span class="numeric_literal">5</span>, <span class="string_literal">"x"</span>, <span class="numeric_literal">0.01</span>); 68 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">1</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">0</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="numeric_literal">5</span>, <span class="string_literal">"x"</span>, <span class="numeric_literal">0.01</span>);
68 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="attribute">{</span><span class="numeric_literal">0</span><span class="attribute">}</span><span class="string_literal"> is </span><span class="attribute">{</span><span class="numeric_literal">2</span><span class="attribute">:</span><span class="attribute">.</span><span class="numeric_literal">1</span><span class="attribute">$</span><span class="attribute">}</span><span class="string_literal">"</span>, <span class="string_literal">"x"</span>, <span class="numeric_literal">5</span>, <span class="numeric_literal">0.01</span>); 69 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="numeric_literal">0</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="numeric_literal">1</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="string_literal">"x"</span>, <span class="numeric_literal">5</span>, <span class="numeric_literal">0.01</span>);
69 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="attribute">{</span><span class="attribute">}</span><span class="string_literal"> is </span><span class="attribute">{</span><span class="attribute">:</span><span class="attribute">.</span><span class="attribute">*</span><span class="attribute">}</span><span class="string_literal">"</span>, <span class="string_literal">"x"</span>, <span class="numeric_literal">5</span>, <span class="numeric_literal">0.01</span>); 70 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="string_literal">"x"</span>, <span class="numeric_literal">5</span>, <span class="numeric_literal">0.01</span>);
70 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="attribute">{</span><span class="attribute">}</span><span class="string_literal"> is </span><span class="attribute">{</span><span class="numeric_literal">2</span><span class="attribute">:</span><span class="attribute">.</span><span class="attribute">*</span><span class="attribute">}</span><span class="string_literal">"</span>, <span class="string_literal">"x"</span>, <span class="numeric_literal">5</span>, <span class="numeric_literal">0.01</span>); 71 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="numeric_literal">2</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="string_literal">"x"</span>, <span class="numeric_literal">5</span>, <span class="numeric_literal">0.01</span>);
71 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="attribute">{</span><span class="attribute">}</span><span class="string_literal"> is </span><span class="attribute">{</span><span class="variable">number</span><span class="attribute">:</span><span class="attribute">.</span><span class="variable">prec</span><span class="attribute">$</span><span class="attribute">}</span><span class="string_literal">"</span>, <span class="string_literal">"x"</span>, prec = <span class="numeric_literal">5</span>, number = <span class="numeric_literal">0.01</span>); 72 <span class="macro">println!</span>(<span class="string_literal">"Hello </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal"> is </span><span class="format_specifier">{</span><span class="variable">number</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="variable">prec</span><span class="format_specifier">$</span><span class="format_specifier">}</span><span class="string_literal">"</span>, <span class="string_literal">"x"</span>, prec = <span class="numeric_literal">5</span>, number = <span class="numeric_literal">0.01</span>);
72 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="attribute">{</span><span class="attribute">}</span><span class="string_literal">, `</span><span class="attribute">{</span><span class="variable">name</span><span class="attribute">:</span><span class="attribute">.</span><span class="attribute">*</span><span class="attribute">}</span><span class="string_literal">` has 3 fractional digits"</span>, <span class="string_literal">"Hello"</span>, <span class="numeric_literal">3</span>, name=<span class="numeric_literal">1234.56</span>); 73 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">` has 3 fractional digits"</span>, <span class="string_literal">"Hello"</span>, <span class="numeric_literal">3</span>, name=<span class="numeric_literal">1234.56</span>);
73 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="attribute">{</span><span class="attribute">}</span><span class="string_literal">, `</span><span class="attribute">{</span><span class="variable">name</span><span class="attribute">:</span><span class="attribute">.</span><span class="attribute">*</span><span class="attribute">}</span><span class="string_literal">` has 3 characters"</span>, <span class="string_literal">"Hello"</span>, <span class="numeric_literal">3</span>, name=<span class="string_literal">"1234.56"</span>); 74 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">` has 3 characters"</span>, <span class="string_literal">"Hello"</span>, <span class="numeric_literal">3</span>, name=<span class="string_literal">"1234.56"</span>);
74 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="attribute">{</span><span class="attribute">}</span><span class="string_literal">, `</span><span class="attribute">{</span><span class="variable">name</span><span class="attribute">:</span><span class="attribute">&gt;</span><span class="numeric_literal">8</span><span class="attribute">.</span><span class="attribute">*</span><span class="attribute">}</span><span class="string_literal">` has 3 right-aligned characters"</span>, <span class="string_literal">"Hello"</span>, <span class="numeric_literal">3</span>, name=<span class="string_literal">"1234.56"</span>); 75 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">, `</span><span class="format_specifier">{</span><span class="variable">name</span><span class="format_specifier">:</span><span class="format_specifier">&gt;</span><span class="numeric_literal">8</span><span class="format_specifier">.</span><span class="format_specifier">*</span><span class="format_specifier">}</span><span class="string_literal">` has 3 right-aligned characters"</span>, <span class="string_literal">"Hello"</span>, <span class="numeric_literal">3</span>, name=<span class="string_literal">"1234.56"</span>);
75 <span class="macro">println!</span>(<span class="string_literal">"Hello {{}}"</span>); 76 <span class="macro">println!</span>(<span class="string_literal">"Hello {{}}"</span>);
76 <span class="macro">println!</span>(<span class="string_literal">"{{ Hello"</span>); 77 <span class="macro">println!</span>(<span class="string_literal">"{{ Hello"</span>);
77 78
78 <span class="macro">println!</span>(<span class="string_literal">r"Hello, </span><span class="attribute">{</span><span class="attribute">}</span><span class="string_literal">!"</span>, <span class="string_literal">"world"</span>); 79 <span class="macro">println!</span>(<span class="string_literal">r"Hello, </span><span class="format_specifier">{</span><span class="format_specifier">}</span><span class="string_literal">!"</span>, <span class="string_literal">"world"</span>);
79 80
80 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="attribute">{</span><span class="variable">\x41</span><span class="attribute">}</span><span class="string_literal">"</span>, A = <span class="numeric_literal">92</span>); 81 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">\x41</span><span class="format_specifier">}</span><span class="string_literal">"</span>, A = <span class="numeric_literal">92</span>);
81 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="attribute">{</span><span class="variable">ничоси</span><span class="attribute">}</span><span class="string_literal">"</span>, ничоси = <span class="numeric_literal">92</span>); 82 <span class="macro">println!</span>(<span class="string_literal">"</span><span class="format_specifier">{</span><span class="variable">ничоси</span><span class="format_specifier">}</span><span class="string_literal">"</span>, ничоси = <span class="numeric_literal">92</span>);
82}</code></pre> \ No newline at end of file 83}</code></pre> \ No newline at end of file
diff --git a/crates/ra_ide/src/snapshots/highlighting.html b/crates/ra_ide/src/snapshots/highlighting.html
index ccb1fc751..4b12fe823 100644
--- a/crates/ra_ide/src/snapshots/highlighting.html
+++ b/crates/ra_ide/src/snapshots/highlighting.html
@@ -20,6 +20,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
20.macro { color: #94BFF3; } 20.macro { color: #94BFF3; }
21.module { color: #AFD8AF; } 21.module { color: #AFD8AF; }
22.variable { color: #DCDCCC; } 22.variable { color: #DCDCCC; }
23.format_specifier { color: #CC696B; }
23.mutable { text-decoration: underline; } 24.mutable { text-decoration: underline; }
24 25
25.keyword { color: #F0DFAF; font-weight: bold; } 26.keyword { color: #F0DFAF; font-weight: bold; }
diff --git a/crates/ra_ide/src/snapshots/rainbow_highlighting.html b/crates/ra_ide/src/snapshots/rainbow_highlighting.html
index 3df82c45f..11e1f3e44 100644
--- a/crates/ra_ide/src/snapshots/rainbow_highlighting.html
+++ b/crates/ra_ide/src/snapshots/rainbow_highlighting.html
@@ -20,6 +20,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
20.macro { color: #94BFF3; } 20.macro { color: #94BFF3; }
21.module { color: #AFD8AF; } 21.module { color: #AFD8AF; }
22.variable { color: #DCDCCC; } 22.variable { color: #DCDCCC; }
23.format_specifier { color: #CC696B; }
23.mutable { text-decoration: underline; } 24.mutable { text-decoration: underline; }
24 25
25.keyword { color: #F0DFAF; font-weight: bold; } 26.keyword { color: #F0DFAF; font-weight: bold; }
diff --git a/crates/ra_ide/src/syntax_highlighting.rs b/crates/ra_ide/src/syntax_highlighting.rs
index be0f8c827..6658c7bb2 100644
--- a/crates/ra_ide/src/syntax_highlighting.rs
+++ b/crates/ra_ide/src/syntax_highlighting.rs
@@ -290,7 +290,7 @@ fn highlight_format_specifier(kind: FormatSpecifier) -> Option<HighlightTag> {
290 | FormatSpecifier::DollarSign 290 | FormatSpecifier::DollarSign
291 | FormatSpecifier::Dot 291 | FormatSpecifier::Dot
292 | FormatSpecifier::Asterisk 292 | FormatSpecifier::Asterisk
293 | FormatSpecifier::QuestionMark => HighlightTag::Attribute, 293 | FormatSpecifier::QuestionMark => HighlightTag::FormatSpecifier,
294 FormatSpecifier::Integer | FormatSpecifier::Zero => HighlightTag::NumericLiteral, 294 FormatSpecifier::Integer | FormatSpecifier::Zero => HighlightTag::NumericLiteral,
295 FormatSpecifier::Identifier => HighlightTag::Local, 295 FormatSpecifier::Identifier => HighlightTag::Local,
296 }) 296 })
diff --git a/crates/ra_ide/src/syntax_highlighting/html.rs b/crates/ra_ide/src/syntax_highlighting/html.rs
index 010db4017..ff0eeeb52 100644
--- a/crates/ra_ide/src/syntax_highlighting/html.rs
+++ b/crates/ra_ide/src/syntax_highlighting/html.rs
@@ -79,6 +79,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
79.macro { color: #94BFF3; } 79.macro { color: #94BFF3; }
80.module { color: #AFD8AF; } 80.module { color: #AFD8AF; }
81.variable { color: #DCDCCC; } 81.variable { color: #DCDCCC; }
82.format_specifier { color: #CC696B; }
82.mutable { text-decoration: underline; } 83.mutable { text-decoration: underline; }
83 84
84.keyword { color: #F0DFAF; font-weight: bold; } 85.keyword { color: #F0DFAF; font-weight: bold; }
diff --git a/crates/ra_ide/src/syntax_highlighting/tags.rs b/crates/ra_ide/src/syntax_highlighting/tags.rs
index f2c421654..be1a0f12b 100644
--- a/crates/ra_ide/src/syntax_highlighting/tags.rs
+++ b/crates/ra_ide/src/syntax_highlighting/tags.rs
@@ -39,6 +39,7 @@ pub enum HighlightTag {
39 Union, 39 Union,
40 Local, 40 Local,
41 UnresolvedReference, 41 UnresolvedReference,
42 FormatSpecifier,
42} 43}
43 44
44#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] 45#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
@@ -81,6 +82,7 @@ impl HighlightTag {
81 HighlightTag::Union => "union", 82 HighlightTag::Union => "union",
82 HighlightTag::Local => "variable", 83 HighlightTag::Local => "variable",
83 HighlightTag::UnresolvedReference => "unresolved_reference", 84 HighlightTag::UnresolvedReference => "unresolved_reference",
85 HighlightTag::FormatSpecifier => "format_specifier",
84 } 86 }
85 } 87 }
86} 88}
diff --git a/crates/ra_prof/src/hprof.rs b/crates/ra_prof/src/hprof.rs
index 2b8a90363..a3f5321fb 100644
--- a/crates/ra_prof/src/hprof.rs
+++ b/crates/ra_prof/src/hprof.rs
@@ -30,8 +30,9 @@ pub fn init_from(spec: &str) {
30pub type Label = &'static str; 30pub type Label = &'static str;
31 31
32/// This function starts a profiling scope in the current execution stack with a given description. 32/// This function starts a profiling scope in the current execution stack with a given description.
33/// It returns a Profile structure and measure elapsed time between this method invocation and Profile structure drop. 33/// It returns a `Profile` struct that measures elapsed time between this method invocation and `Profile` struct drop.
34/// It supports nested profiling scopes in case when this function invoked multiple times at the execution stack. In this case the profiling information will be nested at the output. 34/// It supports nested profiling scopes in case when this function is invoked multiple times at the execution stack.
35/// In this case the profiling information will be nested at the output.
35/// Profiling information is being printed in the stderr. 36/// Profiling information is being printed in the stderr.
36/// 37///
37/// # Example 38/// # Example
@@ -58,36 +59,35 @@ pub type Label = &'static str;
58/// ``` 59/// ```
59pub fn profile(label: Label) -> Profiler { 60pub fn profile(label: Label) -> Profiler {
60 assert!(!label.is_empty()); 61 assert!(!label.is_empty());
61 let enabled = PROFILING_ENABLED.load(Ordering::Relaxed) 62
62 && PROFILE_STACK.with(|stack| stack.borrow_mut().push(label)); 63 if PROFILING_ENABLED.load(Ordering::Relaxed)
63 let label = if enabled { Some(label) } else { None }; 64 && PROFILE_STACK.with(|stack| stack.borrow_mut().push(label))
64 Profiler { label, detail: None } 65 {
66 Profiler(Some(ProfilerImpl { label, detail: None }))
67 } else {
68 Profiler(None)
69 }
65} 70}
66 71
67pub struct Profiler { 72pub struct Profiler(Option<ProfilerImpl>);
68 label: Option<Label>, 73
74struct ProfilerImpl {
75 label: Label,
69 detail: Option<String>, 76 detail: Option<String>,
70} 77}
71 78
72impl Profiler { 79impl Profiler {
73 pub fn detail(mut self, detail: impl FnOnce() -> String) -> Profiler { 80 pub fn detail(mut self, detail: impl FnOnce() -> String) -> Profiler {
74 if self.label.is_some() { 81 if let Some(profiler) = &mut self.0 {
75 self.detail = Some(detail()) 82 profiler.detail = Some(detail())
76 } 83 }
77 self 84 self
78 } 85 }
79} 86}
80 87
81impl Drop for Profiler { 88impl Drop for ProfilerImpl {
82 fn drop(&mut self) { 89 fn drop(&mut self) {
83 match self { 90 PROFILE_STACK.with(|it| it.borrow_mut().pop(self.label, self.detail.take()));
84 Profiler { label: Some(label), detail } => {
85 PROFILE_STACK.with(|stack| {
86 stack.borrow_mut().pop(label, detail.take());
87 });
88 }
89 Profiler { label: None, .. } => (),
90 }
91 } 91 }
92} 92}
93 93
@@ -179,21 +179,18 @@ impl ProfileStack {
179 pub fn pop(&mut self, label: Label, detail: Option<String>) { 179 pub fn pop(&mut self, label: Label, detail: Option<String>) {
180 let start = self.starts.pop().unwrap(); 180 let start = self.starts.pop().unwrap();
181 let duration = start.elapsed(); 181 let duration = start.elapsed();
182 let level = self.starts.len();
183 self.messages.finish(Message { duration, label, detail }); 182 self.messages.finish(Message { duration, label, detail });
184 if level == 0 { 183 if self.starts.is_empty() {
185 let longer_than = self.filter.longer_than; 184 let longer_than = self.filter.longer_than;
186 // Convert to millis for comparison to avoid problems with rounding 185 // Convert to millis for comparison to avoid problems with rounding
187 // (otherwise we could print `0ms` despite user's `>0` filter when 186 // (otherwise we could print `0ms` despite user's `>0` filter when
188 // `duration` is just a few nanos). 187 // `duration` is just a few nanos).
189 if duration.as_millis() > longer_than.as_millis() { 188 if duration.as_millis() > longer_than.as_millis() {
190 let stderr = stderr();
191 if let Some(root) = self.messages.root() { 189 if let Some(root) = self.messages.root() {
192 print(&self.messages, root, 0, longer_than, &mut stderr.lock()); 190 print(&self.messages, root, 0, longer_than, &mut stderr().lock());
193 } 191 }
194 } 192 }
195 self.messages.clear(); 193 self.messages.clear();
196 assert!(self.starts.is_empty())
197 } 194 }
198 } 195 }
199} 196}
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index 7fca5661e..a716e525b 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -243,6 +243,21 @@ fn test_comments_preserve_trailing_whitespace() {
243} 243}
244 244
245#[test] 245#[test]
246fn test_four_slash_line_comment() {
247 let file = SourceFile::parse(
248 r#"
249 //// too many slashes to be a doc comment
250 /// doc comment
251 mod foo {}
252 "#,
253 )
254 .ok()
255 .unwrap();
256 let module = file.syntax().descendants().find_map(Module::cast).unwrap();
257 assert_eq!("doc comment", module.doc_comment_text().unwrap());
258}
259
260#[test]
246fn test_where_predicates() { 261fn test_where_predicates() {
247 fn assert_bound(text: &str, bound: Option<TypeBound>) { 262 fn assert_bound(text: &str, bound: Option<TypeBound>) {
248 assert_eq!(text, bound.unwrap().syntax().text().to_string()); 263 assert_eq!(text, bound.unwrap().syntax().text().to_string());
diff --git a/crates/ra_syntax/src/ast/tokens.rs b/crates/ra_syntax/src/ast/tokens.rs
index 3865729b8..74906d8a6 100644
--- a/crates/ra_syntax/src/ast/tokens.rs
+++ b/crates/ra_syntax/src/ast/tokens.rs
@@ -13,7 +13,12 @@ impl Comment {
13 } 13 }
14 14
15 pub fn prefix(&self) -> &'static str { 15 pub fn prefix(&self) -> &'static str {
16 prefix_by_kind(self.kind()) 16 for (prefix, k) in COMMENT_PREFIX_TO_KIND.iter() {
17 if *k == self.kind() && self.text().starts_with(prefix) {
18 return prefix;
19 }
20 }
21 unreachable!()
17 } 22 }
18} 23}
19 24
@@ -48,6 +53,7 @@ pub enum CommentPlacement {
48const COMMENT_PREFIX_TO_KIND: &[(&str, CommentKind)] = { 53const COMMENT_PREFIX_TO_KIND: &[(&str, CommentKind)] = {
49 use {CommentPlacement::*, CommentShape::*}; 54 use {CommentPlacement::*, CommentShape::*};
50 &[ 55 &[
56 ("////", CommentKind { shape: Line, doc: None }),
51 ("///", CommentKind { shape: Line, doc: Some(Outer) }), 57 ("///", CommentKind { shape: Line, doc: Some(Outer) }),
52 ("//!", CommentKind { shape: Line, doc: Some(Inner) }), 58 ("//!", CommentKind { shape: Line, doc: Some(Inner) }),
53 ("/**", CommentKind { shape: Block, doc: Some(Outer) }), 59 ("/**", CommentKind { shape: Block, doc: Some(Outer) }),
@@ -69,15 +75,6 @@ fn kind_by_prefix(text: &str) -> CommentKind {
69 panic!("bad comment text: {:?}", text) 75 panic!("bad comment text: {:?}", text)
70} 76}
71 77
72fn prefix_by_kind(kind: CommentKind) -> &'static str {
73 for (prefix, k) in COMMENT_PREFIX_TO_KIND.iter() {
74 if *k == kind {
75 return prefix;
76 }
77 }
78 unreachable!()
79}
80
81impl Whitespace { 78impl Whitespace {
82 pub fn spans_multiple_lines(&self) -> bool { 79 pub fn spans_multiple_lines(&self) -> bool {
83 let text = self.text(); 80 let text = self.text();
diff --git a/crates/rust-analyzer/src/conv.rs b/crates/rust-analyzer/src/conv.rs
index f7e65372d..7be5ebcdb 100644
--- a/crates/rust-analyzer/src/conv.rs
+++ b/crates/rust-analyzer/src/conv.rs
@@ -25,7 +25,8 @@ use crate::{
25 Result, 25 Result,
26}; 26};
27use semantic_tokens::{ 27use semantic_tokens::{
28 ATTRIBUTE, BUILTIN_TYPE, ENUM_MEMBER, LIFETIME, TYPE_ALIAS, UNION, UNRESOLVED_REFERENCE, 28 ATTRIBUTE, BUILTIN_TYPE, ENUM_MEMBER, FORMAT_SPECIFIER, LIFETIME, TYPE_ALIAS, UNION,
29 UNRESOLVED_REFERENCE,
29}; 30};
30 31
31pub trait Conv { 32pub trait Conv {
@@ -381,6 +382,7 @@ impl Conv for Highlight {
381 HighlightTag::Attribute => ATTRIBUTE, 382 HighlightTag::Attribute => ATTRIBUTE,
382 HighlightTag::Keyword => SemanticTokenType::KEYWORD, 383 HighlightTag::Keyword => SemanticTokenType::KEYWORD,
383 HighlightTag::UnresolvedReference => UNRESOLVED_REFERENCE, 384 HighlightTag::UnresolvedReference => UNRESOLVED_REFERENCE,
385 HighlightTag::FormatSpecifier => FORMAT_SPECIFIER,
384 }; 386 };
385 387
386 for modifier in self.modifiers.iter() { 388 for modifier in self.modifiers.iter() {
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs
index 10fe696f6..2dc5cb119 100644
--- a/crates/rust-analyzer/src/semantic_tokens.rs
+++ b/crates/rust-analyzer/src/semantic_tokens.rs
@@ -4,62 +4,69 @@ use std::ops;
4 4
5use lsp_types::{Range, SemanticToken, SemanticTokenModifier, SemanticTokenType, SemanticTokens}; 5use lsp_types::{Range, SemanticToken, SemanticTokenModifier, SemanticTokenType, SemanticTokens};
6 6
7pub(crate) const ATTRIBUTE: SemanticTokenType = SemanticTokenType::new("attribute"); 7macro_rules! define_semantic_token_types {
8pub(crate) const BUILTIN_TYPE: SemanticTokenType = SemanticTokenType::new("builtinType"); 8 ($(($ident:ident, $string:literal)),*$(,)?) => {
9pub(crate) const ENUM_MEMBER: SemanticTokenType = SemanticTokenType::new("enumMember"); 9 $(pub(crate) const $ident: SemanticTokenType = SemanticTokenType::new($string);)*
10pub(crate) const LIFETIME: SemanticTokenType = SemanticTokenType::new("lifetime"); 10
11pub(crate) const TYPE_ALIAS: SemanticTokenType = SemanticTokenType::new("typeAlias"); 11 pub(crate) const SUPPORTED_TYPES: &[SemanticTokenType] = &[
12pub(crate) const UNION: SemanticTokenType = SemanticTokenType::new("union"); 12 SemanticTokenType::COMMENT,
13pub(crate) const UNRESOLVED_REFERENCE: SemanticTokenType = 13 SemanticTokenType::KEYWORD,
14 SemanticTokenType::new("unresolvedReference"); 14 SemanticTokenType::STRING,
15 15 SemanticTokenType::NUMBER,
16pub(crate) const CONSTANT: SemanticTokenModifier = SemanticTokenModifier::new("constant"); 16 SemanticTokenType::REGEXP,
17pub(crate) const CONTROL_FLOW: SemanticTokenModifier = SemanticTokenModifier::new("controlFlow"); 17 SemanticTokenType::OPERATOR,
18pub(crate) const MUTABLE: SemanticTokenModifier = SemanticTokenModifier::new("mutable"); 18 SemanticTokenType::NAMESPACE,
19pub(crate) const UNSAFE: SemanticTokenModifier = SemanticTokenModifier::new("unsafe"); 19 SemanticTokenType::TYPE,
20 20 SemanticTokenType::STRUCT,
21pub(crate) const SUPPORTED_TYPES: &[SemanticTokenType] = &[ 21 SemanticTokenType::CLASS,
22 SemanticTokenType::COMMENT, 22 SemanticTokenType::INTERFACE,
23 SemanticTokenType::KEYWORD, 23 SemanticTokenType::ENUM,
24 SemanticTokenType::STRING, 24 SemanticTokenType::TYPE_PARAMETER,
25 SemanticTokenType::NUMBER, 25 SemanticTokenType::FUNCTION,
26 SemanticTokenType::REGEXP, 26 SemanticTokenType::MEMBER,
27 SemanticTokenType::OPERATOR, 27 SemanticTokenType::PROPERTY,
28 SemanticTokenType::NAMESPACE, 28 SemanticTokenType::MACRO,
29 SemanticTokenType::TYPE, 29 SemanticTokenType::VARIABLE,
30 SemanticTokenType::STRUCT, 30 SemanticTokenType::PARAMETER,
31 SemanticTokenType::CLASS, 31 SemanticTokenType::LABEL,
32 SemanticTokenType::INTERFACE, 32 $($ident),*
33 SemanticTokenType::ENUM, 33 ];
34 SemanticTokenType::TYPE_PARAMETER, 34 };
35 SemanticTokenType::FUNCTION, 35}
36 SemanticTokenType::MEMBER, 36
37 SemanticTokenType::PROPERTY, 37define_semantic_token_types![
38 SemanticTokenType::MACRO, 38 (ATTRIBUTE, "attribute"),
39 SemanticTokenType::VARIABLE, 39 (BUILTIN_TYPE, "builtinType"),
40 SemanticTokenType::PARAMETER, 40 (ENUM_MEMBER, "enumMember"),
41 SemanticTokenType::LABEL, 41 (LIFETIME, "lifetime"),
42 ATTRIBUTE, 42 (TYPE_ALIAS, "typeAlias"),
43 BUILTIN_TYPE, 43 (UNION, "union"),
44 ENUM_MEMBER, 44 (UNRESOLVED_REFERENCE, "unresolvedReference"),
45 LIFETIME, 45 (FORMAT_SPECIFIER, "formatSpecifier"),
46 TYPE_ALIAS,
47 UNION,
48 UNRESOLVED_REFERENCE,
49]; 46];
50 47
51pub(crate) const SUPPORTED_MODIFIERS: &[SemanticTokenModifier] = &[ 48macro_rules! define_semantic_token_modifiers {
52 SemanticTokenModifier::DOCUMENTATION, 49 ($(($ident:ident, $string:literal)),*$(,)?) => {
53 SemanticTokenModifier::DECLARATION, 50 $(pub(crate) const $ident: SemanticTokenModifier = SemanticTokenModifier::new($string);)*
54 SemanticTokenModifier::DEFINITION, 51
55 SemanticTokenModifier::STATIC, 52 pub(crate) const SUPPORTED_MODIFIERS: &[SemanticTokenModifier] = &[
56 SemanticTokenModifier::ABSTRACT, 53 SemanticTokenModifier::DOCUMENTATION,
57 SemanticTokenModifier::DEPRECATED, 54 SemanticTokenModifier::DECLARATION,
58 SemanticTokenModifier::READONLY, 55 SemanticTokenModifier::DEFINITION,
59 CONSTANT, 56 SemanticTokenModifier::STATIC,
60 MUTABLE, 57 SemanticTokenModifier::ABSTRACT,
61 UNSAFE, 58 SemanticTokenModifier::DEPRECATED,
62 CONTROL_FLOW, 59 SemanticTokenModifier::READONLY,
60 $($ident),*
61 ];
62 };
63}
64
65define_semantic_token_modifiers![
66 (CONSTANT, "constant"),
67 (CONTROL_FLOW, "controlFlow"),
68 (MUTABLE, "mutable"),
69 (UNSAFE, "unsafe"),
63]; 70];
64 71
65#[derive(Default)] 72#[derive(Default)]
diff --git a/docs/dev/architecture.md b/docs/dev/architecture.md
index 0343b6c81..3a337c574 100644
--- a/docs/dev/architecture.md
+++ b/docs/dev/architecture.md
@@ -56,7 +56,7 @@ In particular, `cargo xtask codegen` generates:
562. [`ast/generated`](https://github.com/rust-analyzer/rust-analyzer/blob/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_syntax/src/ast/generated.rs) 562. [`ast/generated`](https://github.com/rust-analyzer/rust-analyzer/blob/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_syntax/src/ast/generated.rs)
57 -- AST data structure. 57 -- AST data structure.
58 58
59.3 [`doc_tests/generated`](https://github.com/rust-analyzer/rust-analyzer/blob/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_assists/src/doc_tests/generated.rs), 593. [`doc_tests/generated`](https://github.com/rust-analyzer/rust-analyzer/blob/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_assists/src/doc_tests/generated.rs),
60 [`test_data/parser/inline`](https://github.com/rust-analyzer/rust-analyzer/tree/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_syntax/test_data/parser/inline) 60 [`test_data/parser/inline`](https://github.com/rust-analyzer/rust-analyzer/tree/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_syntax/test_data/parser/inline)
61 -- tests for assists and the parser. 61 -- tests for assists and the parser.
62 62
diff --git a/docs/user/readme.adoc b/docs/user/readme.adoc
index ce5704836..76d065d35 100644
--- a/docs/user/readme.adoc
+++ b/docs/user/readme.adoc
@@ -23,7 +23,7 @@ https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/readme.adoc
23 23
24== Installation 24== Installation
25 25
26In theory, one should be able to just install the server binary and have it automatically work with any editor. 26In theory, one should be able to just install the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>> and have it automatically work with any editor.
27We are not there yet, so some editor specific setup is required. 27We are not there yet, so some editor specific setup is required.
28 28
29Additionally, rust-analyzer needs the sources of the standard library. 29Additionally, rust-analyzer needs the sources of the standard library.
@@ -108,15 +108,26 @@ Here are some useful self-diagnostic commands:
108* To log all LSP requests, add `"rust-analyzer.trace.server": "verbose"` to the settings and look for `Server Trace` in the panel. 108* To log all LSP requests, add `"rust-analyzer.trace.server": "verbose"` to the settings and look for `Server Trace` in the panel.
109* To enable client-side logging, add `"rust-analyzer.trace.extension": true` to the settings and open the `Console` tab of VS Code developer tools. 109* To enable client-side logging, add `"rust-analyzer.trace.extension": true` to the settings and open the `Console` tab of VS Code developer tools.
110 110
111=== Language Server Binary 111=== rust-analyzer Language Server Binary
112 112
113Other editors generally require the `rust-analyzer` binary to be in `$PATH`. 113Other editors generally require the `rust-analyzer` binary to be in `$PATH`.
114You can download the pre-built binary from the https://github.com/rust-analyzer/rust-analyzer/releases[releases] page. Typically, you then need to rename the binary for your platform, e.g. `rust-analyzer-mac` if you're on Mac OS, to `rust-analzyer` and make it executable in addition to moving it into a directory in your `$PATH`. 114You can download the pre-built binary from the https://github.com/rust-analyzer/rust-analyzer/releases[releases] page. Typically, you then need to rename the binary for your platform, e.g. `rust-analyzer-mac` if you're on Mac OS, to `rust-analzyer` and make it executable in addition to moving it into a directory in your `$PATH`.
115 115
116On Linux to install the `rust-analyzer` binary into `~/.local/bin`, this commands could be used
117
118[source,bash]
119----
120$ curl -L https://github.com/rust-analyzer/rust-analyzer/releases/latest/download/rust-analyzer-linux -o ~/.local/bin/rust-analyzer
121$ chmod +x ~/.local/bin/rust-analyzer
122----
123
124Ensure `~/.local/bin` is listed in the `$PATH` variable.
125
116Alternatively, you can install it from source using the following command: 126Alternatively, you can install it from source using the following command:
117 127
118[source,bash] 128[source,bash]
119---- 129----
130$ git clone https://github.com/rust-analyzer/rust-analyzer.git && cd rust-analyzer
120$ cargo xtask install --server 131$ cargo xtask install --server
121---- 132----
122 133
@@ -139,15 +150,19 @@ $ yay -S rust-analyzer-bin
139 150
140=== Emacs 151=== Emacs
141 152
142Emacs support is maintained https://github.com/emacs-lsp/lsp-mode/blob/master/lsp-rust.el[upstream]. 153Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>.
143 154
1441. Install the most recent version of `emacs-lsp` package by following the instructions https://github.com/emacs-lsp/lsp-mode[here]. 155Emacs support is maintained as part of the https://github.com/emacs-lsp/lsp-mode[Emacs-LSP] package in https://github.com/emacs-lsp/lsp-mode/blob/master/lsp-rust.el[lsp-rust.el].
156
1571. Install the most recent version of `emacs-lsp` package by following the https://github.com/emacs-lsp/lsp-mode[Emacs-LSP instructions].
1452. Set `lsp-rust-server` to `'rust-analyzer`. 1582. Set `lsp-rust-server` to `'rust-analyzer`.
1463. Run `lsp` in a Rust buffer. 1593. Run `lsp` in a Rust buffer.
1474. (Optionally) bind commands like `lsp-rust-analyzer-join-lines`, `lsp-extend-selection` and `lsp-rust-analyzer-expand-macro` to keys. 1604. (Optionally) bind commands like `lsp-rust-analyzer-join-lines`, `lsp-extend-selection` and `lsp-rust-analyzer-expand-macro` to keys.
148 161
149=== Vim 162=== Vim
150 163
164Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>.
165
151The are several LSP client implementations for vim: 166The are several LSP client implementations for vim:
152 167
153==== coc-rust-analyzer 168==== coc-rust-analyzer
@@ -205,7 +220,7 @@ Once `neovim/nvim-lsp` is installed, use `+lua require'nvim_lsp'.rust_analyzer.s
205 220
206=== Sublime Text 3 221=== Sublime Text 3
207 222
208Prerequisites: You have installed the <<language-server-binary,`rust-analyzer` binary>>. 223Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>.
209 224
210You also need the `LSP` package. To install it: 225You also need the `LSP` package. To install it:
211 226
@@ -218,7 +233,7 @@ Finally, with your Rust project open, in the command palette, run `LSP: Enable L
218 233
219If it worked, you should see "rust-analzyer, 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. 234If it worked, you should see "rust-analzyer, 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.
220 235
221If you get an error saying `No such file or directory: 'rust-analyzer'`, see the <<language-server-binary,section on installing the language server binary>>. 236If you get an error saying `No such file or directory: 'rust-analyzer'`, see the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>> section on installing the language server binary.
222 237
223== Usage 238== Usage
224 239
diff --git a/xtask/src/dist.rs b/xtask/src/dist.rs
index a56eeef8d..aef68089e 100644
--- a/xtask/src/dist.rs
+++ b/xtask/src/dist.rs
@@ -50,21 +50,19 @@ fn dist_server(nightly: bool) -> Result<()> {
50 if cfg!(target_os = "linux") { 50 if cfg!(target_os = "linux") {
51 std::env::set_var("CC", "clang"); 51 std::env::set_var("CC", "clang");
52 run!( 52 run!(
53 "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release 53 "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release"
54 --target x86_64-unknown-linux-musl
55 "
56 // We'd want to add, but that requires setting the right linker somehow 54 // We'd want to add, but that requires setting the right linker somehow
57 // --features=jemalloc 55 // --features=jemalloc
58 )?; 56 )?;
59 if !nightly { 57 if !nightly {
60 run!("strip ./target/x86_64-unknown-linux-musl/release/rust-analyzer")?; 58 run!("strip ./target/release/rust-analyzer")?;
61 } 59 }
62 } else { 60 } else {
63 run!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release")?; 61 run!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release")?;
64 } 62 }
65 63
66 let (src, dst) = if cfg!(target_os = "linux") { 64 let (src, dst) = if cfg!(target_os = "linux") {
67 ("./target/x86_64-unknown-linux-musl/release/rust-analyzer", "./dist/rust-analyzer-linux") 65 ("./target/release/rust-analyzer", "./dist/rust-analyzer-linux")
68 } else if cfg!(target_os = "windows") { 66 } else if cfg!(target_os = "windows") {
69 ("./target/release/rust-analyzer.exe", "./dist/rust-analyzer-windows.exe") 67 ("./target/release/rust-analyzer.exe", "./dist/rust-analyzer-windows.exe")
70 } else if cfg!(target_os = "macos") { 68 } else if cfg!(target_os = "macos") {