aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_expand/src/lib.rs22
-rw-r--r--crates/ra_ide/src/goto_type_definition.rs22
-rw-r--r--crates/ra_lsp_server/src/main_loop/handlers.rs2
-rw-r--r--crates/ra_parser/src/grammar/params.rs5
-rw-r--r--crates/ra_project_model/Cargo.toml2
-rw-r--r--crates/ra_project_model/src/cargo_workspace.rs11
-rw-r--r--crates/ra_project_model/src/lib.rs51
-rw-r--r--crates/ra_project_model/src/sysroot.rs14
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rs1
-rw-r--r--crates/ra_syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.txt26
10 files changed, 116 insertions, 40 deletions
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs
index 7cf3b59a7..9506f2e1c 100644
--- a/crates/ra_hir_expand/src/lib.rs
+++ b/crates/ra_hir_expand/src/lib.rs
@@ -323,11 +323,18 @@ impl<T: Clone> InFile<&T> {
323 } 323 }
324} 324}
325 325
326impl<T> InFile<Option<T>> {
327 pub fn transpose(self) -> Option<InFile<T>> {
328 let value = self.value?;
329 Some(InFile::new(self.file_id, value))
330 }
331}
332
326impl InFile<SyntaxNode> { 333impl InFile<SyntaxNode> {
327 pub fn ancestors_with_macros<'a>( 334 pub fn ancestors_with_macros(
328 self, 335 self,
329 db: &'a impl crate::db::AstDatabase, 336 db: &impl crate::db::AstDatabase,
330 ) -> impl Iterator<Item = InFile<SyntaxNode>> + 'a { 337 ) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
331 std::iter::successors(Some(self), move |node| match node.value.parent() { 338 std::iter::successors(Some(self), move |node| match node.value.parent() {
332 Some(parent) => Some(node.with_value(parent)), 339 Some(parent) => Some(node.with_value(parent)),
333 None => { 340 None => {
@@ -338,6 +345,15 @@ impl InFile<SyntaxNode> {
338 } 345 }
339} 346}
340 347
348impl InFile<SyntaxToken> {
349 pub fn ancestors_with_macros(
350 self,
351 db: &impl crate::db::AstDatabase,
352 ) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
353 self.map(|it| it.parent()).ancestors_with_macros(db)
354 }
355}
356
341impl<N: AstNode> InFile<N> { 357impl<N: AstNode> InFile<N> {
342 pub fn descendants<T: AstNode>(self) -> impl Iterator<Item = InFile<T>> { 358 pub fn descendants<T: AstNode>(self) -> impl Iterator<Item = InFile<T>> {
343 self.value.syntax().descendants().filter_map(T::cast).map(move |n| self.with_value(n)) 359 self.value.syntax().descendants().filter_map(T::cast).map(move |n| self.with_value(n))
diff --git a/crates/ra_ide/src/goto_type_definition.rs b/crates/ra_ide/src/goto_type_definition.rs
index 11ad6d137..69940fc36 100644
--- a/crates/ra_ide/src/goto_type_definition.rs
+++ b/crates/ra_ide/src/goto_type_definition.rs
@@ -16,24 +16,16 @@ pub(crate) fn goto_type_definition(
16 let token = pick_best(file.token_at_offset(position.offset))?; 16 let token = pick_best(file.token_at_offset(position.offset))?;
17 let token = descend_into_macros(db, position.file_id, token); 17 let token = descend_into_macros(db, position.file_id, token);
18 18
19 let node = token.value.ancestors().find_map(|token| { 19 let node = token
20 token 20 .value
21 .ancestors() 21 .ancestors()
22 .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some()) 22 .find(|n| ast::Expr::cast(n.clone()).is_some() || ast::Pat::cast(n.clone()).is_some())?;
23 })?;
24 23
25 let analyzer = hir::SourceAnalyzer::new(db, token.with_value(&node), None); 24 let analyzer = hir::SourceAnalyzer::new(db, token.with_value(&node), None);
26 25
27 let ty: hir::Type = if let Some(ty) = 26 let ty: hir::Type = ast::Expr::cast(node.clone())
28 ast::Expr::cast(node.clone()).and_then(|e| analyzer.type_of(db, &e)) 27 .and_then(|e| analyzer.type_of(db, &e))
29 { 28 .or_else(|| ast::Pat::cast(node.clone()).and_then(|p| analyzer.type_of_pat(db, &p)))?;
30 ty
31 } else if let Some(ty) = ast::Pat::cast(node.clone()).and_then(|p| analyzer.type_of_pat(db, &p))
32 {
33 ty
34 } else {
35 return None;
36 };
37 29
38 let adt_def = ty.autoderef(db).find_map(|ty| ty.as_adt())?; 30 let adt_def = ty.autoderef(db).find_map(|ty| ty.as_adt())?;
39 31
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 59c86bbfa..2e598fdcd 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -758,7 +758,7 @@ pub fn handle_code_lens(
758 // Gather runnables 758 // Gather runnables
759 for runnable in world.analysis().runnables(file_id)? { 759 for runnable in world.analysis().runnables(file_id)? {
760 let title = match &runnable.kind { 760 let title = match &runnable.kind {
761 RunnableKind::Test { .. } | RunnableKind::TestMod { .. } => "▶️Run Test", 761 RunnableKind::Test { .. } | RunnableKind::TestMod { .. } => "▶️\u{fe0e}Run Test",
762 RunnableKind::Bench { .. } => "Run Bench", 762 RunnableKind::Bench { .. } => "Run Bench",
763 RunnableKind::Bin => "Run", 763 RunnableKind::Bin => "Run",
764 } 764 }
diff --git a/crates/ra_parser/src/grammar/params.rs b/crates/ra_parser/src/grammar/params.rs
index ed4f93347..272661b1d 100644
--- a/crates/ra_parser/src/grammar/params.rs
+++ b/crates/ra_parser/src/grammar/params.rs
@@ -114,8 +114,11 @@ fn value_parameter(p: &mut Parser, flavor: Flavor) {
114 // test fn_pointer_param_ident_path 114 // test fn_pointer_param_ident_path
115 // type Foo = fn(Bar::Baz); 115 // type Foo = fn(Bar::Baz);
116 // type Qux = fn(baz: Bar::Baz); 116 // type Qux = fn(baz: Bar::Baz);
117
118 // test fn_pointer_unnamed_arg
119 // type Foo = fn(_: bar);
117 Flavor::FnPointer => { 120 Flavor::FnPointer => {
118 if p.at(IDENT) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) { 121 if (p.at(IDENT) || p.at(UNDERSCORE)) && p.nth(1) == T![:] && !p.nth_at(1, T![::]) {
119 patterns::pattern_single(p); 122 patterns::pattern_single(p);
120 types::ascription(p); 123 types::ascription(p);
121 } else { 124 } else {
diff --git a/crates/ra_project_model/Cargo.toml b/crates/ra_project_model/Cargo.toml
index 69edc3c66..653d5bd14 100644
--- a/crates/ra_project_model/Cargo.toml
+++ b/crates/ra_project_model/Cargo.toml
@@ -19,3 +19,5 @@ ra_cfg = { path = "../ra_cfg" }
19 19
20serde = { version = "1.0.89", features = ["derive"] } 20serde = { version = "1.0.89", features = ["derive"] }
21serde_json = "1.0.39" 21serde_json = "1.0.39"
22
23anyhow = "1.0.26"
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs
index 60cb8c1eb..22d226a74 100644
--- a/crates/ra_project_model/src/cargo_workspace.rs
+++ b/crates/ra_project_model/src/cargo_workspace.rs
@@ -2,14 +2,13 @@
2 2
3use std::path::{Path, PathBuf}; 3use std::path::{Path, PathBuf};
4 4
5use anyhow::{Context, Result};
5use cargo_metadata::{CargoOpt, MetadataCommand}; 6use cargo_metadata::{CargoOpt, MetadataCommand};
6use ra_arena::{impl_arena_id, Arena, RawId}; 7use ra_arena::{impl_arena_id, Arena, RawId};
7use ra_db::Edition; 8use ra_db::Edition;
8use rustc_hash::FxHashMap; 9use rustc_hash::FxHashMap;
9use serde::Deserialize; 10use serde::Deserialize;
10 11
11use crate::Result;
12
13/// `CargoWorkspace` represents the logical structure of, well, a Cargo 12/// `CargoWorkspace` represents the logical structure of, well, a Cargo
14/// workspace. It pretty closely mirrors `cargo metadata` output. 13/// workspace. It pretty closely mirrors `cargo metadata` output.
15/// 14///
@@ -171,7 +170,9 @@ impl CargoWorkspace {
171 if let Some(parent) = cargo_toml.parent() { 170 if let Some(parent) = cargo_toml.parent() {
172 meta.current_dir(parent); 171 meta.current_dir(parent);
173 } 172 }
174 let meta = meta.exec().map_err(|e| format!("cargo metadata failed: {}", e))?; 173 let meta = meta.exec().with_context(|| {
174 format!("Failed to run `cargo metadata --manifest-path {}`", cargo_toml.display())
175 })?;
175 let mut pkg_by_id = FxHashMap::default(); 176 let mut pkg_by_id = FxHashMap::default();
176 let mut packages = Arena::default(); 177 let mut packages = Arena::default();
177 let mut targets = Arena::default(); 178 let mut targets = Arena::default();
@@ -181,7 +182,9 @@ impl CargoWorkspace {
181 for meta_pkg in meta.packages { 182 for meta_pkg in meta.packages {
182 let cargo_metadata::Package { id, edition, name, manifest_path, .. } = meta_pkg; 183 let cargo_metadata::Package { id, edition, name, manifest_path, .. } = meta_pkg;
183 let is_member = ws_members.contains(&id); 184 let is_member = ws_members.contains(&id);
184 let edition = edition.parse::<Edition>()?; 185 let edition = edition
186 .parse::<Edition>()
187 .with_context(|| format!("Failed to parse edition {}", edition))?;
185 let pkg = packages.alloc(PackageData { 188 let pkg = packages.alloc(PackageData {
186 name, 189 name,
187 manifest: manifest_path, 190 manifest: manifest_path,
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index bc1d15406..fef405b7f 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -12,6 +12,7 @@ use std::{
12 process::Command, 12 process::Command,
13}; 13};
14 14
15use anyhow::{bail, Context, Result};
15use ra_cfg::CfgOptions; 16use ra_cfg::CfgOptions;
16use ra_db::{CrateGraph, CrateId, CrateName, Edition, Env, FileId}; 17use ra_db::{CrateGraph, CrateId, CrateName, Edition, Env, FileId};
17use rustc_hash::FxHashMap; 18use rustc_hash::FxHashMap;
@@ -23,8 +24,6 @@ pub use crate::{
23 sysroot::Sysroot, 24 sysroot::Sysroot,
24}; 25};
25 26
26pub type Result<T> = ::std::result::Result<T, Box<dyn Error + Send + Sync>>;
27
28#[derive(Clone, PartialEq, Eq, Hash, Debug)] 27#[derive(Clone, PartialEq, Eq, Hash, Debug)]
29pub struct CargoTomlNotFoundError(pub PathBuf); 28pub struct CargoTomlNotFoundError(pub PathBuf);
30 29
@@ -81,15 +80,36 @@ impl ProjectWorkspace {
81 ) -> Result<ProjectWorkspace> { 80 ) -> Result<ProjectWorkspace> {
82 match find_rust_project_json(path) { 81 match find_rust_project_json(path) {
83 Some(json_path) => { 82 Some(json_path) => {
84 let file = File::open(json_path)?; 83 let file = File::open(&json_path)
84 .with_context(|| format!("Failed to open json file {}", json_path.display()))?;
85 let reader = BufReader::new(file); 85 let reader = BufReader::new(file);
86 Ok(ProjectWorkspace::Json { project: from_reader(reader)? }) 86 Ok(ProjectWorkspace::Json {
87 project: from_reader(reader).with_context(|| {
88 format!("Failed to deserialize json file {}", json_path.display())
89 })?,
90 })
87 } 91 }
88 None => { 92 None => {
89 let cargo_toml = find_cargo_toml(path)?; 93 let cargo_toml = find_cargo_toml(path).with_context(|| {
90 let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_features)?; 94 format!("Failed to find Cargo.toml for path {}", path.display())
91 let sysroot = 95 })?;
92 if with_sysroot { Sysroot::discover(&cargo_toml)? } else { Sysroot::default() }; 96 let cargo = CargoWorkspace::from_cargo_metadata(&cargo_toml, cargo_features)
97 .with_context(|| {
98 format!(
99 "Failed to read Cargo metadata from Cargo.toml file {}",
100 cargo_toml.display()
101 )
102 })?;
103 let sysroot = if with_sysroot {
104 Sysroot::discover(&cargo_toml).with_context(|| {
105 format!(
106 "Failed to find sysroot for Cargo.toml file {}",
107 cargo_toml.display()
108 )
109 })?
110 } else {
111 Sysroot::default()
112 };
93 Ok(ProjectWorkspace::Cargo { cargo, sysroot }) 113 Ok(ProjectWorkspace::Cargo { cargo, sysroot })
94 } 114 }
95 } 115 }
@@ -403,11 +423,20 @@ pub fn get_rustc_cfg_options() -> CfgOptions {
403 } 423 }
404 } 424 }
405 425
406 match (|| -> Result<_> { 426 match (|| -> Result<String> {
407 // `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here. 427 // `cfg(test)` and `cfg(debug_assertion)` are handled outside, so we suppress them here.
408 let output = Command::new("rustc").args(&["--print", "cfg", "-O"]).output()?; 428 let output = Command::new("rustc")
429 .args(&["--print", "cfg", "-O"])
430 .output()
431 .context("Failed to get output from rustc --print cfg -O")?;
409 if !output.status.success() { 432 if !output.status.success() {
410 Err("failed to get rustc cfgs")?; 433 bail!(
434 "rustc --print cfg -O exited with exit code ({})",
435 output
436 .status
437 .code()
438 .map_or(String::from("no exit code"), |code| format!("{}", code))
439 );
411 } 440 }
412 Ok(String::from_utf8(output.stdout)?) 441 Ok(String::from_utf8(output.stdout)?)
413 })() { 442 })() {
diff --git a/crates/ra_project_model/src/sysroot.rs b/crates/ra_project_model/src/sysroot.rs
index a23265fc0..7b9cc899c 100644
--- a/crates/ra_project_model/src/sysroot.rs
+++ b/crates/ra_project_model/src/sysroot.rs
@@ -1,5 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use anyhow::{anyhow, bail, Context, Result};
3use std::{ 4use std::{
4 env, 5 env,
5 path::{Path, PathBuf}, 6 path::{Path, PathBuf},
@@ -8,8 +9,6 @@ use std::{
8 9
9use ra_arena::{impl_arena_id, Arena, RawId}; 10use ra_arena::{impl_arena_id, Arena, RawId};
10 11
11use crate::Result;
12
13#[derive(Default, Debug, Clone)] 12#[derive(Default, Debug, Clone)]
14pub struct Sysroot { 13pub struct Sysroot {
15 crates: Arena<SysrootCrate, SysrootCrateData>, 14 crates: Arena<SysrootCrate, SysrootCrateData>,
@@ -51,7 +50,7 @@ impl Sysroot {
51 let src = try_find_src_path(cargo_toml)?; 50 let src = try_find_src_path(cargo_toml)?;
52 51
53 if !src.exists() { 52 if !src.exists() {
54 Err(format!( 53 Err(anyhow!(
55 "can't load standard library from sysroot\n\ 54 "can't load standard library from sysroot\n\
56 {}\n\ 55 {}\n\
57 (discovered via `rustc --print sysroot`)\n\ 56 (discovered via `rustc --print sysroot`)\n\
@@ -100,9 +99,14 @@ fn try_find_src_path(cargo_toml: &Path) -> Result<PathBuf> {
100 .current_dir(cargo_toml.parent().unwrap()) 99 .current_dir(cargo_toml.parent().unwrap())
101 .args(&["--print", "sysroot"]) 100 .args(&["--print", "sysroot"])
102 .output() 101 .output()
103 .map_err(|e| format!("rustc --print sysroot failed: {}", e))?; 102 .context("rustc --print sysroot failed")?;
104 if !rustc_output.status.success() { 103 if !rustc_output.status.success() {
105 Err("failed to locate sysroot")?; 104 match rustc_output.status.code() {
105 Some(code) => {
106 bail!("failed to locate sysroot: rustc --print sysroot exited with code {}", code)
107 }
108 None => bail!("failed to locate sysroot: rustc --print sysroot terminated by signal"),
109 };
106 } 110 }
107 let stdout = String::from_utf8(rustc_output.stdout)?; 111 let stdout = String::from_utf8(rustc_output.stdout)?;
108 let sysroot_path = Path::new(stdout.trim()); 112 let sysroot_path = Path::new(stdout.trim());
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rs b/crates/ra_syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rs
new file mode 100644
index 000000000..1ebbe5b03
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.rs
@@ -0,0 +1 @@
type Foo = fn(_: bar);
diff --git a/crates/ra_syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.txt b/crates/ra_syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.txt
new file mode 100644
index 000000000..52d8f21a4
--- /dev/null
+++ b/crates/ra_syntax/test_data/parser/inline/ok/0157_fn_pointer_unnamed_arg.txt
@@ -0,0 +1,26 @@
1SOURCE_FILE@[0; 23)
2 TYPE_ALIAS_DEF@[0; 22)
3 TYPE_KW@[0; 4) "type"
4 WHITESPACE@[4; 5) " "
5 NAME@[5; 8)
6 IDENT@[5; 8) "Foo"
7 WHITESPACE@[8; 9) " "
8 EQ@[9; 10) "="
9 WHITESPACE@[10; 11) " "
10 FN_POINTER_TYPE@[11; 21)
11 FN_KW@[11; 13) "fn"
12 PARAM_LIST@[13; 21)
13 L_PAREN@[13; 14) "("
14 PARAM@[14; 20)
15 PLACEHOLDER_PAT@[14; 15)
16 UNDERSCORE@[14; 15) "_"
17 COLON@[15; 16) ":"
18 WHITESPACE@[16; 17) " "
19 PATH_TYPE@[17; 20)
20 PATH@[17; 20)
21 PATH_SEGMENT@[17; 20)
22 NAME_REF@[17; 20)
23 IDENT@[17; 20) "bar"
24 R_PAREN@[20; 21) ")"
25 SEMI@[21; 22) ";"
26 WHITESPACE@[22; 23) "\n"