aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-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
14 files changed, 259 insertions, 162 deletions
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)]