]> git.lizzy.rs Git - rust.git/commitdiff
Merge #4161
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>
Tue, 28 Apr 2020 20:12:44 +0000 (20:12 +0000)
committerGitHub <noreply@github.com>
Tue, 28 Apr 2020 20:12:44 +0000 (20:12 +0000)
4161: lsp-types 0.74 r=kjeremy a=kjeremy

* Fixes a bunch of param types to take partial progress into account.
* Will allow us to support insert/replace text in completions

Co-authored-by: kjeremy <kjeremy@gmail.com>
18 files changed:
.github/workflows/release.yaml
crates/ra_hir_expand/src/builtin_derive.rs
crates/ra_hir_ty/src/tests/macros.rs
crates/ra_ide/src/snapshots/highlight_injection.html
crates/ra_ide/src/snapshots/highlight_strings.html
crates/ra_ide/src/snapshots/highlighting.html
crates/ra_ide/src/snapshots/rainbow_highlighting.html
crates/ra_ide/src/syntax_highlighting.rs
crates/ra_ide/src/syntax_highlighting/html.rs
crates/ra_ide/src/syntax_highlighting/tags.rs
crates/ra_prof/src/hprof.rs
crates/ra_syntax/src/ast.rs
crates/ra_syntax/src/ast/tokens.rs
crates/rust-analyzer/src/conv.rs
crates/rust-analyzer/src/semantic_tokens.rs
docs/dev/architecture.md
docs/user/readme.adoc
xtask/src/dist.rs

index 2c1192f0728d7636cedbb77a666e9562889a3852..3f52f31f805d85989f947f32fb1d35a9ef713e34 100644 (file)
@@ -39,7 +39,6 @@ jobs:
       with:
         toolchain: stable
         profile: minimal
-        target: x86_64-unknown-linux-musl
         override: true
 
     - name: Install Nodejs
index bb45b0f1da06388a543325d27202da2f368c6917..e60f879a393548b4de21c06d261c064ac373e10e 100644 (file)
@@ -9,7 +9,7 @@
 };
 
 use crate::db::AstDatabase;
-use crate::{name, quote, LazyMacroId, MacroDefId, MacroDefKind};
+use crate::{name, quote, LazyMacroId, MacroCallId, MacroDefId, MacroDefKind};
 
 macro_rules! register_builtin {
     ( $($trait:ident => $expand:ident),* ) => {
@@ -153,76 +153,113 @@ impl ##type_params ##trait_path for #name ##type_args {}
     Ok(expanded)
 }
 
+fn find_builtin_crate(db: &dyn AstDatabase, id: LazyMacroId) -> tt::TokenTree {
+    // FIXME: make hygiene works for builtin derive macro
+    // such that $crate can be used here.
+
+    let m: MacroCallId = id.into();
+    let file_id = m.as_file().original_file(db);
+    let cg = db.crate_graph();
+    let krates = db.relevant_crates(file_id);
+    let krate = match krates.get(0) {
+        Some(krate) => krate,
+        None => {
+            let tt = quote! { core };
+            return tt.token_trees[0].clone();
+        }
+    };
+
+    // XXX
+    //  All crates except core itself should have a dependency on core,
+    //  We detect `core` by seeing whether it doesn't have such a dependency.
+    let tt = if cg[*krate].dependencies.iter().any(|dep| dep.name == "core") {
+        quote! { core }
+    } else {
+        quote! { crate }
+    };
+
+    tt.token_trees[0].clone()
+}
+
 fn copy_expand(
-    _db: &dyn AstDatabase,
-    _id: LazyMacroId,
+    db: &dyn AstDatabase,
+    id: LazyMacroId,
     tt: &tt::Subtree,
 ) -> Result<tt::Subtree, mbe::ExpandError> {
-    expand_simple_derive(tt, quote! { std::marker::Copy })
+    let krate = find_builtin_crate(db, id);
+    expand_simple_derive(tt, quote! { #krate::marker::Copy })
 }
 
 fn clone_expand(
-    _db: &dyn AstDatabase,
-    _id: LazyMacroId,
+    db: &dyn AstDatabase,
+    id: LazyMacroId,
     tt: &tt::Subtree,
 ) -> Result<tt::Subtree, mbe::ExpandError> {
-    expand_simple_derive(tt, quote! { std::clone::Clone })
+    let krate = find_builtin_crate(db, id);
+    expand_simple_derive(tt, quote! { #krate::clone::Clone })
 }
 
 fn default_expand(
-    _db: &dyn AstDatabase,
-    _id: LazyMacroId,
+    db: &dyn AstDatabase,
+    id: LazyMacroId,
     tt: &tt::Subtree,
 ) -> Result<tt::Subtree, mbe::ExpandError> {
-    expand_simple_derive(tt, quote! { std::default::Default })
+    let krate = find_builtin_crate(db, id);
+    expand_simple_derive(tt, quote! { #krate::default::Default })
 }
 
 fn debug_expand(
-    _db: &dyn AstDatabase,
-    _id: LazyMacroId,
+    db: &dyn AstDatabase,
+    id: LazyMacroId,
     tt: &tt::Subtree,
 ) -> Result<tt::Subtree, mbe::ExpandError> {
-    expand_simple_derive(tt, quote! { std::fmt::Debug })
+    let krate = find_builtin_crate(db, id);
+    expand_simple_derive(tt, quote! { #krate::fmt::Debug })
 }
 
 fn hash_expand(
-    _db: &dyn AstDatabase,
-    _id: LazyMacroId,
+    db: &dyn AstDatabase,
+    id: LazyMacroId,
     tt: &tt::Subtree,
 ) -> Result<tt::Subtree, mbe::ExpandError> {
-    expand_simple_derive(tt, quote! { std::hash::Hash })
+    let krate = find_builtin_crate(db, id);
+    expand_simple_derive(tt, quote! { #krate::hash::Hash })
 }
 
 fn eq_expand(
-    _db: &dyn AstDatabase,
-    _id: LazyMacroId,
+    db: &dyn AstDatabase,
+    id: LazyMacroId,
     tt: &tt::Subtree,
 ) -> Result<tt::Subtree, mbe::ExpandError> {
-    expand_simple_derive(tt, quote! { std::cmp::Eq })
+    let krate = find_builtin_crate(db, id);
+    expand_simple_derive(tt, quote! { #krate::cmp::Eq })
 }
 
 fn partial_eq_expand(
-    _db: &dyn AstDatabase,
-    _id: LazyMacroId,
+    db: &dyn AstDatabase,
+    id: LazyMacroId,
     tt: &tt::Subtree,
 ) -> Result<tt::Subtree, mbe::ExpandError> {
-    expand_simple_derive(tt, quote! { std::cmp::PartialEq })
+    let krate = find_builtin_crate(db, id);
+    expand_simple_derive(tt, quote! { #krate::cmp::PartialEq })
 }
 
 fn ord_expand(
-    _db: &dyn AstDatabase,
-    _id: LazyMacroId,
+    db: &dyn AstDatabase,
+    id: LazyMacroId,
     tt: &tt::Subtree,
 ) -> Result<tt::Subtree, mbe::ExpandError> {
-    expand_simple_derive(tt, quote! { std::cmp::Ord })
+    let krate = find_builtin_crate(db, id);
+    expand_simple_derive(tt, quote! { #krate::cmp::Ord })
 }
 
 fn partial_ord_expand(
-    _db: &dyn AstDatabase,
-    _id: LazyMacroId,
+    db: &dyn AstDatabase,
+    id: LazyMacroId,
     tt: &tt::Subtree,
 ) -> Result<tt::Subtree, mbe::ExpandError> {
-    expand_simple_derive(tt, quote! { std::cmp::PartialOrd })
+    let krate = find_builtin_crate(db, id);
+    expand_simple_derive(tt, quote! { #krate::cmp::PartialOrd })
 }
 
 #[cfg(test)]
@@ -234,8 +271,18 @@ mod tests {
 
     fn expand_builtin_derive(s: &str, name: Name) -> String {
         let def = find_builtin_derive(&name).unwrap();
+        let fixture = format!(
+            r#"//- /main.rs crate:main deps:core
+<|>
+{}
+//- /lib.rs crate:core
+// empty
+"#,
+            s
+        );
 
-        let (db, file_id) = TestDB::with_single_file(&s);
+        let (db, file_pos) = TestDB::with_position(&fixture);
+        let file_id = file_pos.file_id;
         let parsed = db.parse(file_id);
         let items: Vec<_> =
             parsed.syntax_node().descendants().filter_map(ast::ModuleItem::cast).collect();
@@ -264,7 +311,7 @@ fn test_copy_expand_simple() {
             known::Copy,
         );
 
-        assert_eq!(expanded, "impl< >std::marker::CopyforFoo< >{}");
+        assert_eq!(expanded, "impl< >core::marker::CopyforFoo< >{}");
     }
 
     #[test]
@@ -279,7 +326,7 @@ fn test_copy_expand_with_type_params() {
 
         assert_eq!(
             expanded,
-            "impl<T0:std::marker::Copy,T1:std::marker::Copy>std::marker::CopyforFoo<T0,T1>{}"
+            "impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}"
         );
     }
 
@@ -297,7 +344,7 @@ fn test_copy_expand_with_lifetimes() {
 
         assert_eq!(
             expanded,
-            "impl<T0:std::marker::Copy,T1:std::marker::Copy>std::marker::CopyforFoo<T0,T1>{}"
+            "impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}"
         );
     }
 
@@ -313,7 +360,7 @@ fn test_clone_expand() {
 
         assert_eq!(
             expanded,
-            "impl<T0:std::clone::Clone,T1:std::clone::Clone>std::clone::CloneforFoo<T0,T1>{}"
+            "impl<T0:core::clone::Clone,T1:core::clone::Clone>core::clone::CloneforFoo<T0,T1>{}"
         );
     }
 }
index 6b5267232585cd24b61cf81354e9bc394d0019c6..5ddecbdc6808bb728402d565f7a07c5e5ae03dc7 100644 (file)
@@ -622,14 +622,14 @@ fn main() {
 fn infer_derive_clone_simple() {
     let (db, pos) = TestDB::with_position(
         r#"
-//- /main.rs crate:main deps:std
+//- /main.rs crate:main deps:core
 #[derive(Clone)]
 struct S;
 fn test() {
     S.clone()<|>;
 }
 
-//- /lib.rs crate:std
+//- /lib.rs crate:core
 #[prelude_import]
 use clone::*;
 mod clone {
@@ -642,11 +642,36 @@ trait Clone {
     assert_eq!("S", type_at_pos(&db, pos));
 }
 
+#[test]
+fn infer_derive_clone_in_core() {
+    let (db, pos) = TestDB::with_position(
+        r#"
+//- /lib.rs crate:core
+#[prelude_import]
+use clone::*;
+mod clone {
+    trait Clone {
+        fn clone(&self) -> Self;
+    }
+}
+#[derive(Clone)]
+pub struct S;
+
+//- /main.rs crate:main deps:core
+use core::S;
+fn test() {
+    S.clone()<|>;
+}
+"#,
+    );
+    assert_eq!("S", type_at_pos(&db, pos));
+}
+
 #[test]
 fn infer_derive_clone_with_params() {
     let (db, pos) = TestDB::with_position(
         r#"
-//- /main.rs crate:main deps:std
+//- /main.rs crate:main deps:core
 #[derive(Clone)]
 struct S;
 #[derive(Clone)]
@@ -656,7 +681,7 @@ fn test() {
     (Wrapper(S).clone(), Wrapper(NonClone).clone())<|>;
 }
 
-//- /lib.rs crate:std
+//- /lib.rs crate:core
 #[prelude_import]
 use clone::*;
 mod clone {
index 6ec13bd80fbfb188b874add97e889120a1265f82..ea026d7a046439ded1ab209a00c8e44fd7dff28c 100644 (file)
@@ -20,6 +20,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .macro              { color: #94BFF3; }
 .module             { color: #AFD8AF; }
 .variable           { color: #DCDCCC; }
+.format_specifier   { color: #CC696B; }
 .mutable            { text-decoration: underline; }
 
 .keyword            { color: #F0DFAF; font-weight: bold; }
index 433f2e0c5e91eb8c5d328781ff36e6dfe40616d7..de06daf72b089302f822f98efec42db1d5966191 100644 (file)
@@ -20,6 +20,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .macro              { color: #94BFF3; }
 .module             { color: #AFD8AF; }
 .variable           { color: #DCDCCC; }
+.format_specifier   { color: #CC696B; }
 .mutable            { text-decoration: underline; }
 
 .keyword            { color: #F0DFAF; font-weight: bold; }
@@ -40,43 +41,43 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="keyword">fn</span> <span class="function declaration">main</span>() {
     <span class="comment">// from https://doc.rust-lang.org/std/fmt/index.html</span>
     <span class="macro">println!</span>(<span class="string_literal">"Hello"</span>);                 <span class="comment">// =&gt; "Hello"</span>
-    <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>
-    <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>
-    <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>
-    <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>
-    <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>
-    <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>
-    <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>
-    <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>
-    <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>
-    <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>
-    <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>);
-    <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>);
-    <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>);
-    <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>);
-    <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>);
-    <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>);
-    <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>);
-    <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>);
-    <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>);
-    <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>);
-    <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>);
-    <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>);
-    <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>);
-    <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>);
-    <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>);
-    <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>);
-    <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>);
-    <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>);
-    <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>);
-    <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>);
-    <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>);
-    <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>);
+    <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>
+    <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>
+    <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>
+    <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>
+    <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>
+    <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>
+    <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>
+    <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>
+    <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>
+    <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>
+    <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>);
+    <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>);
+    <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>);
+    <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>);
+    <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>);
+    <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>);
+    <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>);
+    <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>);
+    <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>);
+    <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>);
+    <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>);
+    <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>);
+    <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>);
+    <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>);
+    <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>);
+    <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>);
+    <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>);
+    <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>);
+    <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>);
+    <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>);
+    <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>);
+    <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>);
     <span class="macro">println!</span>(<span class="string_literal">"Hello {{}}"</span>);
     <span class="macro">println!</span>(<span class="string_literal">"{{ Hello"</span>);
 
-    <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>);
+    <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>);
 
-    <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>);
-    <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>);
+    <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>);
+    <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>);
 }</code></pre>
\ No newline at end of file
index ccb1fc7516c989f928ab464bbf615f0729a544e6..4b12fe8238cf910c52d18abc65fdabfa47f98a49 100644 (file)
@@ -20,6 +20,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .macro              { color: #94BFF3; }
 .module             { color: #AFD8AF; }
 .variable           { color: #DCDCCC; }
+.format_specifier   { color: #CC696B; }
 .mutable            { text-decoration: underline; }
 
 .keyword            { color: #F0DFAF; font-weight: bold; }
index 3df82c45fbe9885ddc7a12a7a8d835edfc32c50e..11e1f3e44e59607faa5df4a03d59d0ce09499890 100644 (file)
@@ -20,6 +20,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 .macro              { color: #94BFF3; }
 .module             { color: #AFD8AF; }
 .variable           { color: #DCDCCC; }
+.format_specifier   { color: #CC696B; }
 .mutable            { text-decoration: underline; }
 
 .keyword            { color: #F0DFAF; font-weight: bold; }
index be0f8c827aae97cdb89f51a448505452c2a8b3c2..6658c7bb270e93cea27bdc126276475ad59cd6d3 100644 (file)
@@ -290,7 +290,7 @@ fn highlight_format_specifier(kind: FormatSpecifier) -> Option<HighlightTag> {
         | FormatSpecifier::DollarSign
         | FormatSpecifier::Dot
         | FormatSpecifier::Asterisk
-        | FormatSpecifier::QuestionMark => HighlightTag::Attribute,
+        | FormatSpecifier::QuestionMark => HighlightTag::FormatSpecifier,
         FormatSpecifier::Integer | FormatSpecifier::Zero => HighlightTag::NumericLiteral,
         FormatSpecifier::Identifier => HighlightTag::Local,
     })
index 010db40175cc6d1a4b57914ea2a816f6ea927c75..ff0eeeb52c062eeca8ad2800cdf0f171c6831431 100644 (file)
@@ -79,6 +79,7 @@ fn html_escape(text: &str) -> String {
 .macro              { color: #94BFF3; }
 .module             { color: #AFD8AF; }
 .variable           { color: #DCDCCC; }
+.format_specifier   { color: #CC696B; }
 .mutable            { text-decoration: underline; }
 
 .keyword            { color: #F0DFAF; font-weight: bold; }
index f2c42165454e0408d54c174c57626416bc9f5835..be1a0f12b25bfaeb044e28f2d07ff4d4c0fbe80e 100644 (file)
@@ -39,6 +39,7 @@ pub enum HighlightTag {
     Union,
     Local,
     UnresolvedReference,
+    FormatSpecifier,
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
@@ -81,6 +82,7 @@ fn as_str(self) -> &'static str {
             HighlightTag::Union => "union",
             HighlightTag::Local => "variable",
             HighlightTag::UnresolvedReference => "unresolved_reference",
+            HighlightTag::FormatSpecifier => "format_specifier",
         }
     }
 }
index 2b8a903636ca645c512940deb3ad77628862e7f8..a3f5321fb3c1619ce66fee30155443d1017d96ca 100644 (file)
@@ -30,8 +30,9 @@ pub fn init_from(spec: &str) {
 pub type Label = &'static str;
 
 /// This function starts a profiling scope in the current execution stack with a given description.
-/// It returns a Profile structure and measure elapsed time between this method invocation and Profile structure drop.
-/// 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.
+/// It returns a `Profile` struct that measures elapsed time between this method invocation and `Profile` struct drop.
+/// It supports nested profiling scopes in case when this function is invoked multiple times at the execution stack.
+/// In this case the profiling information will be nested at the output.
 /// Profiling information is being printed in the stderr.
 ///
 /// # Example
@@ -58,36 +59,35 @@ pub fn init_from(spec: &str) {
 /// ```
 pub fn profile(label: Label) -> Profiler {
     assert!(!label.is_empty());
-    let enabled = PROFILING_ENABLED.load(Ordering::Relaxed)
-        && PROFILE_STACK.with(|stack| stack.borrow_mut().push(label));
-    let label = if enabled { Some(label) } else { None };
-    Profiler { label, detail: None }
+
+    if PROFILING_ENABLED.load(Ordering::Relaxed)
+        && PROFILE_STACK.with(|stack| stack.borrow_mut().push(label))
+    {
+        Profiler(Some(ProfilerImpl { label, detail: None }))
+    } else {
+        Profiler(None)
+    }
 }
 
-pub struct Profiler {
-    label: Option<Label>,
+pub struct Profiler(Option<ProfilerImpl>);
+
+struct ProfilerImpl {
+    label: Label,
     detail: Option<String>,
 }
 
 impl Profiler {
     pub fn detail(mut self, detail: impl FnOnce() -> String) -> Profiler {
-        if self.label.is_some() {
-            self.detail = Some(detail())
+        if let Some(profiler) = &mut self.0 {
+            profiler.detail = Some(detail())
         }
         self
     }
 }
 
-impl Drop for Profiler {
+impl Drop for ProfilerImpl {
     fn drop(&mut self) {
-        match self {
-            Profiler { label: Some(label), detail } => {
-                PROFILE_STACK.with(|stack| {
-                    stack.borrow_mut().pop(label, detail.take());
-                });
-            }
-            Profiler { label: None, .. } => (),
-        }
+        PROFILE_STACK.with(|it| it.borrow_mut().pop(self.label, self.detail.take()));
     }
 }
 
@@ -179,21 +179,18 @@ fn push(&mut self, label: Label) -> bool {
     pub fn pop(&mut self, label: Label, detail: Option<String>) {
         let start = self.starts.pop().unwrap();
         let duration = start.elapsed();
-        let level = self.starts.len();
         self.messages.finish(Message { duration, label, detail });
-        if level == 0 {
+        if self.starts.is_empty() {
             let longer_than = self.filter.longer_than;
             // Convert to millis for comparison to avoid problems with rounding
             // (otherwise we could print `0ms` despite user's `>0` filter when
             // `duration` is just a few nanos).
             if duration.as_millis() > longer_than.as_millis() {
-                let stderr = stderr();
                 if let Some(root) = self.messages.root() {
-                    print(&self.messages, root, 0, longer_than, &mut stderr.lock());
+                    print(&self.messages, root, 0, longer_than, &mut stderr().lock());
                 }
             }
             self.messages.clear();
-            assert!(self.starts.is_empty())
         }
     }
 }
index 7fca5661ef98a7ce584792f1fee20039d6bf8e0a..a716e525b9520a828b3ab0ccc11f77054d318120 100644 (file)
@@ -242,6 +242,21 @@ fn test_comments_preserve_trailing_whitespace() {
     );
 }
 
+#[test]
+fn test_four_slash_line_comment() {
+    let file = SourceFile::parse(
+        r#"
+        //// too many slashes to be a doc comment
+        /// doc comment
+        mod foo {}
+        "#,
+    )
+    .ok()
+    .unwrap();
+    let module = file.syntax().descendants().find_map(Module::cast).unwrap();
+    assert_eq!("doc comment", module.doc_comment_text().unwrap());
+}
+
 #[test]
 fn test_where_predicates() {
     fn assert_bound(text: &str, bound: Option<TypeBound>) {
index 3865729b8c42267728c95380f3da394ffd952336..74906d8a62efe732ef6f4b765e0c132264327e7e 100644 (file)
@@ -13,7 +13,12 @@ pub fn kind(&self) -> CommentKind {
     }
 
     pub fn prefix(&self) -> &'static str {
-        prefix_by_kind(self.kind())
+        for (prefix, k) in COMMENT_PREFIX_TO_KIND.iter() {
+            if *k == self.kind() && self.text().starts_with(prefix) {
+                return prefix;
+            }
+        }
+        unreachable!()
     }
 }
 
@@ -48,6 +53,7 @@ pub enum CommentPlacement {
 const COMMENT_PREFIX_TO_KIND: &[(&str, CommentKind)] = {
     use {CommentPlacement::*, CommentShape::*};
     &[
+        ("////", CommentKind { shape: Line, doc: None }),
         ("///", CommentKind { shape: Line, doc: Some(Outer) }),
         ("//!", CommentKind { shape: Line, doc: Some(Inner) }),
         ("/**", CommentKind { shape: Block, doc: Some(Outer) }),
@@ -69,15 +75,6 @@ fn kind_by_prefix(text: &str) -> CommentKind {
     panic!("bad comment text: {:?}", text)
 }
 
-fn prefix_by_kind(kind: CommentKind) -> &'static str {
-    for (prefix, k) in COMMENT_PREFIX_TO_KIND.iter() {
-        if *k == kind {
-            return prefix;
-        }
-    }
-    unreachable!()
-}
-
 impl Whitespace {
     pub fn spans_multiple_lines(&self) -> bool {
         let text = self.text();
index f7e65372d966e6f08c176e05087535c069d68e9b..7be5ebcdb5a0d13599cc5a8d628c48186cc46936 100644 (file)
@@ -25,7 +25,8 @@
     Result,
 };
 use semantic_tokens::{
-    ATTRIBUTE, BUILTIN_TYPE, ENUM_MEMBER, LIFETIME, TYPE_ALIAS, UNION, UNRESOLVED_REFERENCE,
+    ATTRIBUTE, BUILTIN_TYPE, ENUM_MEMBER, FORMAT_SPECIFIER, LIFETIME, TYPE_ALIAS, UNION,
+    UNRESOLVED_REFERENCE,
 };
 
 pub trait Conv {
@@ -381,6 +382,7 @@ fn conv(self) -> Self::Output {
             HighlightTag::Attribute => ATTRIBUTE,
             HighlightTag::Keyword => SemanticTokenType::KEYWORD,
             HighlightTag::UnresolvedReference => UNRESOLVED_REFERENCE,
+            HighlightTag::FormatSpecifier => FORMAT_SPECIFIER,
         };
 
         for modifier in self.modifiers.iter() {
index 10fe696f6f108bad64fdf25471f75b97fe34e24e..2dc5cb1196fc41e6f374185d731ac043c300ed3a 100644 (file)
@@ -4,62 +4,69 @@
 
 use lsp_types::{Range, SemanticToken, SemanticTokenModifier, SemanticTokenType, SemanticTokens};
 
-pub(crate) const ATTRIBUTE: SemanticTokenType = SemanticTokenType::new("attribute");
-pub(crate) const BUILTIN_TYPE: SemanticTokenType = SemanticTokenType::new("builtinType");
-pub(crate) const ENUM_MEMBER: SemanticTokenType = SemanticTokenType::new("enumMember");
-pub(crate) const LIFETIME: SemanticTokenType = SemanticTokenType::new("lifetime");
-pub(crate) const TYPE_ALIAS: SemanticTokenType = SemanticTokenType::new("typeAlias");
-pub(crate) const UNION: SemanticTokenType = SemanticTokenType::new("union");
-pub(crate) const UNRESOLVED_REFERENCE: SemanticTokenType =
-    SemanticTokenType::new("unresolvedReference");
-
-pub(crate) const CONSTANT: SemanticTokenModifier = SemanticTokenModifier::new("constant");
-pub(crate) const CONTROL_FLOW: SemanticTokenModifier = SemanticTokenModifier::new("controlFlow");
-pub(crate) const MUTABLE: SemanticTokenModifier = SemanticTokenModifier::new("mutable");
-pub(crate) const UNSAFE: SemanticTokenModifier = SemanticTokenModifier::new("unsafe");
-
-pub(crate) const SUPPORTED_TYPES: &[SemanticTokenType] = &[
-    SemanticTokenType::COMMENT,
-    SemanticTokenType::KEYWORD,
-    SemanticTokenType::STRING,
-    SemanticTokenType::NUMBER,
-    SemanticTokenType::REGEXP,
-    SemanticTokenType::OPERATOR,
-    SemanticTokenType::NAMESPACE,
-    SemanticTokenType::TYPE,
-    SemanticTokenType::STRUCT,
-    SemanticTokenType::CLASS,
-    SemanticTokenType::INTERFACE,
-    SemanticTokenType::ENUM,
-    SemanticTokenType::TYPE_PARAMETER,
-    SemanticTokenType::FUNCTION,
-    SemanticTokenType::MEMBER,
-    SemanticTokenType::PROPERTY,
-    SemanticTokenType::MACRO,
-    SemanticTokenType::VARIABLE,
-    SemanticTokenType::PARAMETER,
-    SemanticTokenType::LABEL,
-    ATTRIBUTE,
-    BUILTIN_TYPE,
-    ENUM_MEMBER,
-    LIFETIME,
-    TYPE_ALIAS,
-    UNION,
-    UNRESOLVED_REFERENCE,
+macro_rules! define_semantic_token_types {
+    ($(($ident:ident, $string:literal)),*$(,)?) => {
+        $(pub(crate) const $ident: SemanticTokenType = SemanticTokenType::new($string);)*
+
+        pub(crate) const SUPPORTED_TYPES: &[SemanticTokenType] = &[
+            SemanticTokenType::COMMENT,
+            SemanticTokenType::KEYWORD,
+            SemanticTokenType::STRING,
+            SemanticTokenType::NUMBER,
+            SemanticTokenType::REGEXP,
+            SemanticTokenType::OPERATOR,
+            SemanticTokenType::NAMESPACE,
+            SemanticTokenType::TYPE,
+            SemanticTokenType::STRUCT,
+            SemanticTokenType::CLASS,
+            SemanticTokenType::INTERFACE,
+            SemanticTokenType::ENUM,
+            SemanticTokenType::TYPE_PARAMETER,
+            SemanticTokenType::FUNCTION,
+            SemanticTokenType::MEMBER,
+            SemanticTokenType::PROPERTY,
+            SemanticTokenType::MACRO,
+            SemanticTokenType::VARIABLE,
+            SemanticTokenType::PARAMETER,
+            SemanticTokenType::LABEL,
+            $($ident),*
+        ];
+    };
+}
+
+define_semantic_token_types![
+    (ATTRIBUTE, "attribute"),
+    (BUILTIN_TYPE, "builtinType"),
+    (ENUM_MEMBER, "enumMember"),
+    (LIFETIME, "lifetime"),
+    (TYPE_ALIAS, "typeAlias"),
+    (UNION, "union"),
+    (UNRESOLVED_REFERENCE, "unresolvedReference"),
+    (FORMAT_SPECIFIER, "formatSpecifier"),
 ];
 
-pub(crate) const SUPPORTED_MODIFIERS: &[SemanticTokenModifier] = &[
-    SemanticTokenModifier::DOCUMENTATION,
-    SemanticTokenModifier::DECLARATION,
-    SemanticTokenModifier::DEFINITION,
-    SemanticTokenModifier::STATIC,
-    SemanticTokenModifier::ABSTRACT,
-    SemanticTokenModifier::DEPRECATED,
-    SemanticTokenModifier::READONLY,
-    CONSTANT,
-    MUTABLE,
-    UNSAFE,
-    CONTROL_FLOW,
+macro_rules! define_semantic_token_modifiers {
+    ($(($ident:ident, $string:literal)),*$(,)?) => {
+        $(pub(crate) const $ident: SemanticTokenModifier = SemanticTokenModifier::new($string);)*
+
+        pub(crate) const SUPPORTED_MODIFIERS: &[SemanticTokenModifier] = &[
+            SemanticTokenModifier::DOCUMENTATION,
+            SemanticTokenModifier::DECLARATION,
+            SemanticTokenModifier::DEFINITION,
+            SemanticTokenModifier::STATIC,
+            SemanticTokenModifier::ABSTRACT,
+            SemanticTokenModifier::DEPRECATED,
+            SemanticTokenModifier::READONLY,
+            $($ident),*
+        ];
+    };
+}
+
+define_semantic_token_modifiers![
+    (CONSTANT, "constant"),
+    (CONTROL_FLOW, "controlFlow"),
+    (MUTABLE, "mutable"),
+    (UNSAFE, "unsafe"),
 ];
 
 #[derive(Default)]
index 0343b6c81f41dbeae0b603ceaaa890bf7dd4890e..3a337c57462eef30811fc2df5f8d04e32c17de20 100644 (file)
@@ -56,7 +56,7 @@ In particular, `cargo xtask codegen` generates:
 2. [`ast/generated`](https://github.com/rust-analyzer/rust-analyzer/blob/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_syntax/src/ast/generated.rs)
   -- AST data structure.
 
-.3 [`doc_tests/generated`](https://github.com/rust-analyzer/rust-analyzer/blob/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_assists/src/doc_tests/generated.rs),
+3. [`doc_tests/generated`](https://github.com/rust-analyzer/rust-analyzer/blob/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_assists/src/doc_tests/generated.rs),
   [`test_data/parser/inline`](https://github.com/rust-analyzer/rust-analyzer/tree/a0be39296d2925972cacd9fbf8b5fb258fad6947/crates/ra_syntax/test_data/parser/inline)
   -- tests for assists and the parser.
 
index ce57048366631f85c978d99159d28181fc7f6afb..76d065d35b154cbd1c67c13ea50530d8f159bf0b 100644 (file)
@@ -23,7 +23,7 @@ https://github.com/rust-analyzer/rust-analyzer/blob/master/docs/user/readme.adoc
 
 == Installation
 
-In theory, one should be able to just install the server binary and have it automatically work with any editor.
+In 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.
 We are not there yet, so some editor specific setup is required.
 
 Additionally, rust-analyzer needs the sources of the standard library.
@@ -108,15 +108,26 @@ Here are some useful self-diagnostic commands:
 * To log all LSP requests, add `"rust-analyzer.trace.server": "verbose"` to the settings and look for `Server Trace` in the panel.
 * To enable client-side logging, add `"rust-analyzer.trace.extension": true` to the settings and open the `Console` tab of VS Code developer tools.
 
-=== Language Server Binary
+=== rust-analyzer Language Server Binary
 
 Other editors generally require the `rust-analyzer` binary to be in `$PATH`.
 You 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`.
 
+On Linux to install the `rust-analyzer` binary into `~/.local/bin`, this commands could be used
+
+[source,bash]
+----
+$ curl -L https://github.com/rust-analyzer/rust-analyzer/releases/latest/download/rust-analyzer-linux -o ~/.local/bin/rust-analyzer
+$ chmod +x ~/.local/bin/rust-analyzer
+----
+
+Ensure `~/.local/bin` is listed in the `$PATH` variable.
+
 Alternatively, you can install it from source using the following command:
 
 [source,bash]
 ----
+$ git clone https://github.com/rust-analyzer/rust-analyzer.git && cd rust-analyzer
 $ cargo xtask install --server
 ----
 
@@ -139,15 +150,19 @@ $ yay -S rust-analyzer-bin
 
 === Emacs
 
-Emacs support is maintained https://github.com/emacs-lsp/lsp-mode/blob/master/lsp-rust.el[upstream].
+Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>.
 
-1. Install the most recent version of `emacs-lsp` package by following the instructions https://github.com/emacs-lsp/lsp-mode[here].
+Emacs 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].
+
+1. Install the most recent version of `emacs-lsp` package by following the https://github.com/emacs-lsp/lsp-mode[Emacs-LSP instructions].
 2. Set `lsp-rust-server` to `'rust-analyzer`.
 3. Run `lsp` in a Rust buffer.
 4. (Optionally) bind commands like `lsp-rust-analyzer-join-lines`, `lsp-extend-selection` and `lsp-rust-analyzer-expand-macro` to keys.
 
 === Vim
 
+Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>.
+
 The are several LSP client implementations for vim:
 
 ==== coc-rust-analyzer
@@ -205,7 +220,7 @@ Once `neovim/nvim-lsp` is installed, use `+lua require'nvim_lsp'.rust_analyzer.s
 
 === Sublime Text 3
 
-Prerequisites: You have installed the <<language-server-binary,`rust-analyzer` binary>>.
+Prerequisites: You have installed the <<rust-analyzer-language-server-binary,`rust-analyzer` binary>>.
 
 You also need the `LSP` package. To install it:
 
@@ -218,7 +233,7 @@ Finally, with your Rust project open, in the command palette, run `LSP: Enable L
 
 If 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.
 
-If you get an error saying `No such file or directory: 'rust-analyzer'`, see the <<language-server-binary,section on installing the language server binary>>.
+If 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.
 
 == Usage
 
index a56eeef8d29d250cda72400278134369a7ce6121..aef68089e1ec8db7d1637b01c1cebc1a43765d2c 100644 (file)
@@ -50,21 +50,19 @@ fn dist_server(nightly: bool) -> Result<()> {
     if cfg!(target_os = "linux") {
         std::env::set_var("CC", "clang");
         run!(
-            "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release
-             --target x86_64-unknown-linux-musl
-            "
+            "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release"
             // We'd want to add, but that requires setting the right linker somehow
             // --features=jemalloc
         )?;
         if !nightly {
-            run!("strip ./target/x86_64-unknown-linux-musl/release/rust-analyzer")?;
+            run!("strip ./target/release/rust-analyzer")?;
         }
     } else {
         run!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release")?;
     }
 
     let (src, dst) = if cfg!(target_os = "linux") {
-        ("./target/x86_64-unknown-linux-musl/release/rust-analyzer", "./dist/rust-analyzer-linux")
+        ("./target/release/rust-analyzer", "./dist/rust-analyzer-linux")
     } else if cfg!(target_os = "windows") {
         ("./target/release/rust-analyzer.exe", "./dist/rust-analyzer-windows.exe")
     } else if cfg!(target_os = "macos") {