with:
toolchain: stable
profile: minimal
- target: x86_64-unknown-linux-musl
override: true
- name: Install Nodejs
};
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),* ) => {
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)]
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();
known::Copy,
);
- assert_eq!(expanded, "impl< >std::marker::CopyforFoo< >{}");
+ assert_eq!(expanded, "impl< >core::marker::CopyforFoo< >{}");
}
#[test]
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>{}"
);
}
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>{}"
);
}
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>{}"
);
}
}
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 {
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)]
(Wrapper(S).clone(), Wrapper(NonClone).clone())<|>;
}
-//- /lib.rs crate:std
+//- /lib.rs crate:core
#[prelude_import]
use clone::*;
mod clone {
.macro { color: #94BFF3; }
.module { color: #AFD8AF; }
.variable { color: #DCDCCC; }
+.format_specifier { color: #CC696B; }
.mutable { text-decoration: underline; }
.keyword { color: #F0DFAF; font-weight: bold; }
.macro { color: #94BFF3; }
.module { color: #AFD8AF; }
.variable { color: #DCDCCC; }
+.format_specifier { color: #CC696B; }
.mutable { text-decoration: underline; }
.keyword { color: #F0DFAF; font-weight: bold; }
<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">// => "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">// => "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">// => "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">// => "(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">// => "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">// => "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">// => "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">// => "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">// => "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">// => "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">// => "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"><</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="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">></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">></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">// => "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">// => "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">// => "(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">// => "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">// => "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">// => "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">// => "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">// => "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">// => "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">// => "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"><</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="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">></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">></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
.macro { color: #94BFF3; }
.module { color: #AFD8AF; }
.variable { color: #DCDCCC; }
+.format_specifier { color: #CC696B; }
.mutable { text-decoration: underline; }
.keyword { color: #F0DFAF; font-weight: bold; }
.macro { color: #94BFF3; }
.module { color: #AFD8AF; }
.variable { color: #DCDCCC; }
+.format_specifier { color: #CC696B; }
.mutable { text-decoration: underline; }
.keyword { color: #F0DFAF; font-weight: bold; }
| FormatSpecifier::DollarSign
| FormatSpecifier::Dot
| FormatSpecifier::Asterisk
- | FormatSpecifier::QuestionMark => HighlightTag::Attribute,
+ | FormatSpecifier::QuestionMark => HighlightTag::FormatSpecifier,
FormatSpecifier::Integer | FormatSpecifier::Zero => HighlightTag::NumericLiteral,
FormatSpecifier::Identifier => HighlightTag::Local,
})
.macro { color: #94BFF3; }
.module { color: #AFD8AF; }
.variable { color: #DCDCCC; }
+.format_specifier { color: #CC696B; }
.mutable { text-decoration: underline; }
.keyword { color: #F0DFAF; font-weight: bold; }
Union,
Local,
UnresolvedReference,
+ FormatSpecifier,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
HighlightTag::Union => "union",
HighlightTag::Local => "variable",
HighlightTag::UnresolvedReference => "unresolved_reference",
+ HighlightTag::FormatSpecifier => "format_specifier",
}
}
}
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
/// ```
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()));
}
}
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())
}
}
}
);
}
+#[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>) {
}
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!()
}
}
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) }),
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();
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 {
HighlightTag::Attribute => ATTRIBUTE,
HighlightTag::Keyword => SemanticTokenType::KEYWORD,
HighlightTag::UnresolvedReference => UNRESOLVED_REFERENCE,
+ HighlightTag::FormatSpecifier => FORMAT_SPECIFIER,
};
for modifier in self.modifiers.iter() {
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)]
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.
== 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.
* 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
----
=== 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
=== 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:
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
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") {