Skip to content

Commit

Permalink
⬆️ rust-analyzer
Browse files Browse the repository at this point in the history
  • Loading branch information
lnicola committed Oct 26, 2022
1 parent 26a413e commit 8807fc4
Show file tree
Hide file tree
Showing 64 changed files with 2,221 additions and 1,584 deletions.
6 changes: 4 additions & 2 deletions .github/workflows/publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ name: publish
on:
workflow_dispatch: # We can add version input when 1.0 is released and scheduled releases are removed

# schedule:
# - cron: "0 0 * * *" # midnight UTC
# schedule:
# - cron: "0 0 * * *" # midnight UTC

push:
branches:
Expand Down Expand Up @@ -50,5 +50,7 @@ jobs:
cargo workspaces rename --from test-utils test_utils
cargo workspaces rename --from text-edit text_edit
cargo workspaces rename ra_ap_%n
# Remove library crates from the workspaces so we don't auto-publish them as well
sed -i 's/ "lib\/\*",//' ./Cargo.toml
find crates/rust-analyzer -type f -name '*.rs' -exec sed -i 's/rust_analyzer/ra_ap_rust_analyzer/g' {} +
cargo workspaces publish --yes --force '*' --exact --no-git-commit --allow-dirty --skip-published custom 0.0.$PATCH
82 changes: 63 additions & 19 deletions crates/flycheck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,20 @@ pub use cargo_metadata::diagnostic::{
DiagnosticSpanMacroExpansion,
};

#[derive(Copy, Clone, Debug, Default, PartialEq, Eq)]
pub enum InvocationStrategy {
Once,
#[default]
PerWorkspace,
}

#[derive(Clone, Debug, Default, PartialEq, Eq)]
pub enum InvocationLocation {
Root(AbsPathBuf),
#[default]
Workspace,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum FlycheckConfig {
CargoCommand {
Expand All @@ -37,6 +51,8 @@ pub enum FlycheckConfig {
command: String,
args: Vec<String>,
extra_env: FxHashMap<String, String>,
invocation_strategy: InvocationStrategy,
invocation_location: InvocationLocation,
},
}

Expand Down Expand Up @@ -136,11 +152,15 @@ enum Restart {
No,
}

/// A [`FlycheckActor`] is a single check instance of a workspace.
struct FlycheckActor {
/// The workspace id of this flycheck instance.
id: usize,
sender: Box<dyn Fn(Message) + Send>,
config: FlycheckConfig,
workspace_root: AbsPathBuf,
/// Either the workspace root of the workspace we are flychecking,
/// or the project root of the project.
root: AbsPathBuf,
/// CargoHandle exists to wrap around the communication needed to be able to
/// run `cargo check` without blocking. Currently the Rust standard library
/// doesn't provide a way to read sub-process output without blocking, so we
Expand All @@ -162,11 +182,13 @@ impl FlycheckActor {
workspace_root: AbsPathBuf,
) -> FlycheckActor {
tracing::info!(%id, ?workspace_root, "Spawning flycheck");
FlycheckActor { id, sender, config, workspace_root, cargo_handle: None }
FlycheckActor { id, sender, config, root: workspace_root, cargo_handle: None }
}
fn progress(&self, progress: Progress) {

fn report_progress(&self, progress: Progress) {
self.send(Message::Progress { id: self.id, progress });
}

fn next_event(&self, inbox: &Receiver<Restart>) -> Option<Event> {
let check_chan = self.cargo_handle.as_ref().map(|cargo| &cargo.receiver);
if let Ok(msg) = inbox.try_recv() {
Expand All @@ -178,6 +200,7 @@ impl FlycheckActor {
recv(check_chan.unwrap_or(&never())) -> msg => Some(Event::CheckEvent(msg.ok())),
}
}

fn run(mut self, inbox: Receiver<Restart>) {
'event: while let Some(event) = self.next_event(&inbox) {
match event {
Expand All @@ -203,10 +226,10 @@ impl FlycheckActor {
"did restart flycheck"
);
self.cargo_handle = Some(cargo_handle);
self.progress(Progress::DidStart);
self.report_progress(Progress::DidStart);
}
Err(error) => {
self.progress(Progress::DidFailToRestart(format!(
self.report_progress(Progress::DidFailToRestart(format!(
"Failed to run the following command: {:?} error={}",
self.check_command(),
error
Expand All @@ -226,17 +249,17 @@ impl FlycheckActor {
self.check_command()
);
}
self.progress(Progress::DidFinish(res));
self.report_progress(Progress::DidFinish(res));
}
Event::CheckEvent(Some(message)) => match message {
CargoMessage::CompilerArtifact(msg) => {
self.progress(Progress::DidCheckCrate(msg.target.name));
self.report_progress(Progress::DidCheckCrate(msg.target.name));
}

CargoMessage::Diagnostic(msg) => {
self.send(Message::AddDiagnostic {
id: self.id,
workspace_root: self.workspace_root.clone(),
workspace_root: self.root.clone(),
diagnostic: msg,
});
}
Expand All @@ -254,12 +277,12 @@ impl FlycheckActor {
"did cancel flycheck"
);
cargo_handle.cancel();
self.progress(Progress::DidCancel);
self.report_progress(Progress::DidCancel);
}
}

fn check_command(&self) -> Command {
let mut cmd = match &self.config {
let (mut cmd, args) = match &self.config {
FlycheckConfig::CargoCommand {
command,
target_triple,
Expand All @@ -272,9 +295,7 @@ impl FlycheckActor {
} => {
let mut cmd = Command::new(toolchain::cargo());
cmd.arg(command);
cmd.current_dir(&self.workspace_root);
cmd.args(&["--workspace", "--message-format=json", "--manifest-path"])
.arg(self.workspace_root.join("Cargo.toml").as_os_str());
cmd.args(&["--workspace", "--message-format=json"]);

if let Some(target) = target_triple {
cmd.args(&["--target", target.as_str()]);
Expand All @@ -293,18 +314,41 @@ impl FlycheckActor {
cmd.arg(features.join(" "));
}
}
cmd.args(extra_args);
cmd.envs(extra_env);
cmd
(cmd, extra_args)
}
FlycheckConfig::CustomCommand { command, args, extra_env } => {
FlycheckConfig::CustomCommand {
command,
args,
extra_env,
invocation_strategy,
invocation_location,
} => {
let mut cmd = Command::new(command);
cmd.args(args);
cmd.envs(extra_env);
cmd

match invocation_location {
InvocationLocation::Workspace => {
match invocation_strategy {
InvocationStrategy::Once => {
cmd.current_dir(&self.root);
}
InvocationStrategy::PerWorkspace => {
// FIXME: cmd.current_dir(&affected_workspace);
cmd.current_dir(&self.root);
}
}
}
InvocationLocation::Root(root) => {
cmd.current_dir(root);
}
}

(cmd, args)
}
};
cmd.current_dir(&self.workspace_root);

cmd.args(args);
cmd
}

Expand Down
36 changes: 26 additions & 10 deletions crates/hir-def/src/macro_expansion_tests/builtin_derive_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ fn test_copy_expand_simple() {
#[derive(Copy)]
struct Foo;
"#,
expect![[r##"
expect![[r#"
#[derive(Copy)]
struct Foo;
impl < > core::marker::Copy for Foo< > {}"##]],
impl < > core::marker::Copy for Foo< > {}"#]],
);
}

Expand All @@ -33,15 +33,15 @@ macro Copy {}
#[derive(Copy)]
struct Foo;
"#,
expect![[r##"
expect![[r#"
#[rustc_builtin_macro]
macro derive {}
#[rustc_builtin_macro]
macro Copy {}
#[derive(Copy)]
struct Foo;
impl < > crate ::marker::Copy for Foo< > {}"##]],
impl < > crate ::marker::Copy for Foo< > {}"#]],
);
}

Expand All @@ -53,11 +53,11 @@ fn test_copy_expand_with_type_params() {
#[derive(Copy)]
struct Foo<A, B>;
"#,
expect![[r##"
expect![[r#"
#[derive(Copy)]
struct Foo<A, B>;
impl <T0: core::marker::Copy, T1: core::marker::Copy> core::marker::Copy for Foo<T0, T1> {}"##]],
impl <T0: core::marker::Copy, T1: core::marker::Copy, > core::marker::Copy for Foo<T0, T1, > {}"#]],
);
}

Expand All @@ -70,11 +70,11 @@ fn test_copy_expand_with_lifetimes() {
#[derive(Copy)]
struct Foo<A, B, 'a, 'b>;
"#,
expect![[r##"
expect![[r#"
#[derive(Copy)]
struct Foo<A, B, 'a, 'b>;
impl <T0: core::marker::Copy, T1: core::marker::Copy> core::marker::Copy for Foo<T0, T1> {}"##]],
impl <T0: core::marker::Copy, T1: core::marker::Copy, > core::marker::Copy for Foo<T0, T1, > {}"#]],
);
}

Expand All @@ -86,10 +86,26 @@ fn test_clone_expand() {
#[derive(Clone)]
struct Foo<A, B>;
"#,
expect![[r##"
expect![[r#"
#[derive(Clone)]
struct Foo<A, B>;
impl <T0: core::clone::Clone, T1: core::clone::Clone> core::clone::Clone for Foo<T0, T1> {}"##]],
impl <T0: core::clone::Clone, T1: core::clone::Clone, > core::clone::Clone for Foo<T0, T1, > {}"#]],
);
}

#[test]
fn test_clone_expand_with_const_generics() {
check(
r#"
//- minicore: derive, clone
#[derive(Clone)]
struct Foo<const X: usize, T>(u32);
"#,
expect![[r#"
#[derive(Clone)]
struct Foo<const X: usize, T>(u32);
impl <const T0: usize, T1: core::clone::Clone, > core::clone::Clone for Foo<T0, T1, > {}"#]],
);
}
86 changes: 36 additions & 50 deletions crates/hir-expand/src/builtin_derive_macro.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ pub fn find_builtin_derive(ident: &name::Name) -> Option<BuiltinDeriveExpander>

struct BasicAdtInfo {
name: tt::Ident,
type_or_const_params: usize,
/// `Some(ty)` if it's a const param of type `ty`, `None` if it's a type param.
param_types: Vec<Option<tt::Subtree>>,
}

fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, ExpandError> {
Expand Down Expand Up @@ -92,65 +93,50 @@ fn parse_adt(tt: &tt::Subtree) -> Result<BasicAdtInfo, ExpandError> {
let name_token_id =
token_map.token_by_range(name.syntax().text_range()).unwrap_or_else(TokenId::unspecified);
let name_token = tt::Ident { id: name_token_id, text: name.text().into() };
let type_or_const_params =
params.map_or(0, |type_param_list| type_param_list.type_or_const_params().count());
Ok(BasicAdtInfo { name: name_token, type_or_const_params })
}

fn make_type_args(n: usize, bound: Vec<tt::TokenTree>) -> Vec<tt::TokenTree> {
let mut result = Vec::<tt::TokenTree>::with_capacity(n * 2);
result.push(
tt::Leaf::Punct(tt::Punct {
char: '<',
spacing: tt::Spacing::Alone,
id: tt::TokenId::unspecified(),
})
.into(),
);
for i in 0..n {
if i > 0 {
result.push(
tt::Leaf::Punct(tt::Punct {
char: ',',
spacing: tt::Spacing::Alone,
id: tt::TokenId::unspecified(),
})
.into(),
);
}
result.push(
tt::Leaf::Ident(tt::Ident {
id: tt::TokenId::unspecified(),
text: format!("T{}", i).into(),
})
.into(),
);
result.extend(bound.iter().cloned());
}
result.push(
tt::Leaf::Punct(tt::Punct {
char: '>',
spacing: tt::Spacing::Alone,
id: tt::TokenId::unspecified(),
let param_types = params
.into_iter()
.flat_map(|param_list| param_list.type_or_const_params())
.map(|param| {
if let ast::TypeOrConstParam::Const(param) = param {
let ty = param
.ty()
.map(|ty| mbe::syntax_node_to_token_tree(ty.syntax()).0)
.unwrap_or_default();
Some(ty)
} else {
None
}
})
.into(),
);
result
.collect();
Ok(BasicAdtInfo { name: name_token, param_types })
}

fn expand_simple_derive(tt: &tt::Subtree, trait_path: tt::Subtree) -> ExpandResult<tt::Subtree> {
let info = match parse_adt(tt) {
Ok(info) => info,
Err(e) => return ExpandResult::only_err(e),
};
let (params, args): (Vec<_>, Vec<_>) = info
.param_types
.into_iter()
.enumerate()
.map(|(idx, param_ty)| {
let ident = tt::Leaf::Ident(tt::Ident {
id: tt::TokenId::unspecified(),
text: format!("T{idx}").into(),
});
let ident_ = ident.clone();
if let Some(ty) = param_ty {
(quote! { const #ident : #ty , }, quote! { #ident_ , })
} else {
let bound = trait_path.clone();
(quote! { #ident : #bound , }, quote! { #ident_ , })
}
})
.unzip();
let name = info.name;
let trait_path_clone = trait_path.token_trees.clone();
let bound = (quote! { : ##trait_path_clone }).token_trees;
let type_params = make_type_args(info.type_or_const_params, bound);
let type_args = make_type_args(info.type_or_const_params, Vec::new());
let trait_path = trait_path.token_trees;
let expanded = quote! {
impl ##type_params ##trait_path for #name ##type_args {}
impl < ##params > #trait_path for #name < ##args > {}
};
ExpandResult::ok(expanded)
}
Expand Down
Loading

0 comments on commit 8807fc4

Please sign in to comment.