Skip to content

Commit dc34162

Browse files
committed
Merge branch 'master' of github.com:rust-analyzer/rust-analyzer
2 parents bbe2264 + a5f2b16 commit dc34162

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

68 files changed

+1928
-592
lines changed

.github/workflows/release.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ jobs:
3939
with:
4040
toolchain: stable
4141
profile: minimal
42-
target: x86_64-unknown-linux-musl
4342
override: true
4443

4544
- name: Install Nodejs

.vscode/launch.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
"outFiles": [
4242
"${workspaceFolder}/editors/code/out/**/*.js"
4343
],
44-
"preLaunchTask": "Build Extension",
44+
"preLaunchTask": "Build Server and Extension",
4545
"skipFiles": [
4646
"<node_internals>/**/*.js"
4747
],
@@ -62,7 +62,7 @@
6262
"outFiles": [
6363
"${workspaceFolder}/editors/code/out/**/*.js"
6464
],
65-
"preLaunchTask": "Build Extension",
65+
"preLaunchTask": "Build Server (Release) and Extension",
6666
"skipFiles": [
6767
"<node_internals>/**/*.js"
6868
],

.vscode/tasks.json

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"version": "2.0.0",
55
"tasks": [
66
{
7-
"label": "Build Extension",
7+
"label": "Build Extension in Background",
88
"group": "build",
99
"type": "npm",
1010
"script": "watch",
@@ -15,12 +15,41 @@
1515
},
1616
"isBackground": true,
1717
},
18+
{
19+
"label": "Build Extension",
20+
"group": "build",
21+
"type": "npm",
22+
"script": "build",
23+
"path": "editors/code/",
24+
"problemMatcher": {
25+
"base": "$tsc",
26+
"fileLocation": ["relative", "${workspaceFolder}/editors/code/"]
27+
},
28+
},
1829
{
1930
"label": "Build Server",
2031
"group": "build",
2132
"type": "shell",
2233
"command": "cargo build --package rust-analyzer",
2334
"problemMatcher": "$rustc"
2435
},
36+
{
37+
"label": "Build Server (Release)",
38+
"group": "build",
39+
"type": "shell",
40+
"command": "cargo build --release --package rust-analyzer",
41+
"problemMatcher": "$rustc"
42+
},
43+
44+
{
45+
"label": "Build Server and Extension",
46+
"dependsOn": ["Build Server", "Build Extension"],
47+
"problemMatcher": "$rustc"
48+
},
49+
{
50+
"label": "Build Server (Release) and Extension",
51+
"dependsOn": ["Build Server (Release)", "Build Extension"],
52+
"problemMatcher": "$rustc"
53+
}
2554
]
2655
}

Cargo.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/ra_assists/src/handlers/add_from_impl_for_enum.rs

Lines changed: 34 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
1+
use ra_ide_db::RootDatabase;
12
use ra_syntax::{
23
ast::{self, AstNode, NameOwner},
34
TextSize,
45
};
56
use stdx::format_to;
67

7-
use crate::{Assist, AssistCtx, AssistId};
8-
use ra_ide_db::RootDatabase;
8+
use crate::{utils::FamousDefs, Assist, AssistCtx, AssistId};
9+
use test_utils::tested_by;
910

1011
// Assist add_from_impl_for_enum
1112
//
@@ -41,7 +42,8 @@ pub(crate) fn add_from_impl_for_enum(ctx: AssistCtx) -> Option<Assist> {
4142
_ => return None,
4243
};
4344

44-
if already_has_from_impl(ctx.sema, &variant) {
45+
if existing_from_impl(ctx.sema, &variant).is_some() {
46+
tested_by!(test_add_from_impl_already_exists);
4547
return None;
4648
}
4749

@@ -70,41 +72,33 @@ impl From<{0}> for {1} {{
7072
)
7173
}
7274

73-
fn already_has_from_impl(
75+
fn existing_from_impl(
7476
sema: &'_ hir::Semantics<'_, RootDatabase>,
7577
variant: &ast::EnumVariant,
76-
) -> bool {
77-
let scope = sema.scope(&variant.syntax());
78+
) -> Option<()> {
79+
let variant = sema.to_def(variant)?;
80+
let enum_ = variant.parent_enum(sema.db);
81+
let krate = enum_.module(sema.db).krate();
7882

79-
let from_path = ast::make::path_from_text("From");
80-
let from_hir_path = match hir::Path::from_ast(from_path) {
81-
Some(p) => p,
82-
None => return false,
83-
};
84-
let from_trait = match scope.resolve_hir_path(&from_hir_path) {
85-
Some(hir::PathResolution::Def(hir::ModuleDef::Trait(t))) => t,
86-
_ => return false,
87-
};
83+
let from_trait = FamousDefs(sema, krate).core_convert_From()?;
8884

89-
let e: hir::Enum = match sema.to_def(&variant.parent_enum()) {
90-
Some(e) => e,
91-
None => return false,
92-
};
93-
let e_ty = e.ty(sema.db);
85+
let enum_type = enum_.ty(sema.db);
9486

95-
let hir_enum_var: hir::EnumVariant = match sema.to_def(variant) {
96-
Some(ev) => ev,
97-
None => return false,
98-
};
99-
let var_ty = hir_enum_var.fields(sema.db)[0].signature_ty(sema.db);
87+
let wrapped_type = variant.fields(sema.db).get(0)?.signature_ty(sema.db);
10088

101-
e_ty.impls_trait(sema.db, from_trait, &[var_ty])
89+
if enum_type.impls_trait(sema.db, from_trait, &[wrapped_type]) {
90+
Some(())
91+
} else {
92+
None
93+
}
10294
}
10395

10496
#[cfg(test)]
10597
mod tests {
10698
use super::*;
99+
107100
use crate::helpers::{check_assist, check_assist_not_applicable};
101+
use test_utils::covers;
108102

109103
#[test]
110104
fn test_add_from_impl_for_enum() {
@@ -136,36 +130,40 @@ mod tests {
136130
);
137131
}
138132

133+
fn check_not_applicable(ra_fixture: &str) {
134+
let fixture =
135+
format!("//- main.rs crate:main deps:core\n{}\n{}", ra_fixture, FamousDefs::FIXTURE);
136+
check_assist_not_applicable(add_from_impl_for_enum, &fixture)
137+
}
138+
139139
#[test]
140140
fn test_add_from_impl_no_element() {
141-
check_assist_not_applicable(add_from_impl_for_enum, "enum A { <|>One }");
141+
check_not_applicable("enum A { <|>One }");
142142
}
143143

144144
#[test]
145145
fn test_add_from_impl_more_than_one_element_in_tuple() {
146-
check_assist_not_applicable(add_from_impl_for_enum, "enum A { <|>One(u32, String) }");
146+
check_not_applicable("enum A { <|>One(u32, String) }");
147147
}
148148

149149
#[test]
150150
fn test_add_from_impl_struct_variant() {
151-
check_assist_not_applicable(add_from_impl_for_enum, "enum A { <|>One { x: u32 } }");
151+
check_not_applicable("enum A { <|>One { x: u32 } }");
152152
}
153153

154154
#[test]
155155
fn test_add_from_impl_already_exists() {
156-
check_assist_not_applicable(
157-
add_from_impl_for_enum,
158-
r#"enum A { <|>One(u32), }
156+
covers!(test_add_from_impl_already_exists);
157+
check_not_applicable(
158+
r#"
159+
enum A { <|>One(u32), }
159160
160161
impl From<u32> for A {
161162
fn from(v: u32) -> Self {
162163
A::One(v)
163164
}
164165
}
165-
166-
pub trait From<T> {
167-
fn from(T) -> Self;
168-
}"#,
166+
"#,
169167
);
170168
}
171169

crates/ra_assists/src/handlers/replace_if_let_with_match.rs

Lines changed: 72 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
use ra_fmt::unwrap_trivial_block;
22
use ra_syntax::{
3-
ast::{self, make},
3+
ast::{self, edit::IndentLevel, make},
44
AstNode,
55
};
66

7-
use crate::{Assist, AssistCtx, AssistId};
8-
use ast::edit::IndentLevel;
7+
use crate::{utils::TryEnum, Assist, AssistCtx, AssistId};
98

109
// Assist: replace_if_let_with_match
1110
//
@@ -44,15 +43,21 @@ pub(crate) fn replace_if_let_with_match(ctx: AssistCtx) -> Option<Assist> {
4443
ast::ElseBranch::IfExpr(_) => return None,
4544
};
4645

47-
ctx.add_assist(AssistId("replace_if_let_with_match"), "Replace with match", |edit| {
46+
let sema = ctx.sema;
47+
ctx.add_assist(AssistId("replace_if_let_with_match"), "Replace with match", move |edit| {
4848
let match_expr = {
4949
let then_arm = {
5050
let then_expr = unwrap_trivial_block(then_block);
51-
make::match_arm(vec![pat], then_expr)
51+
make::match_arm(vec![pat.clone()], then_expr)
5252
};
5353
let else_arm = {
54+
let pattern = sema
55+
.type_of_pat(&pat)
56+
.and_then(|ty| TryEnum::from_ty(sema, &ty))
57+
.map(|it| it.sad_pattern())
58+
.unwrap_or_else(|| make::placeholder_pat().into());
5459
let else_expr = unwrap_trivial_block(else_block);
55-
make::match_arm(vec![make::placeholder_pat().into()], else_expr)
60+
make::match_arm(vec![pattern], else_expr)
5661
};
5762
make::expr_match(expr, make::match_arm_list(vec![then_arm, else_arm]))
5863
};
@@ -68,6 +73,7 @@ pub(crate) fn replace_if_let_with_match(ctx: AssistCtx) -> Option<Assist> {
6873
#[cfg(test)]
6974
mod tests {
7075
use super::*;
76+
7177
use crate::helpers::{check_assist, check_assist_target};
7278

7379
#[test]
@@ -145,4 +151,64 @@ impl VariantData {
145151
}",
146152
);
147153
}
154+
155+
#[test]
156+
fn special_case_option() {
157+
check_assist(
158+
replace_if_let_with_match,
159+
r#"
160+
enum Option<T> { Some(T), None }
161+
use Option::*;
162+
163+
fn foo(x: Option<i32>) {
164+
<|>if let Some(x) = x {
165+
println!("{}", x)
166+
} else {
167+
println!("none")
168+
}
169+
}
170+
"#,
171+
r#"
172+
enum Option<T> { Some(T), None }
173+
use Option::*;
174+
175+
fn foo(x: Option<i32>) {
176+
<|>match x {
177+
Some(x) => println!("{}", x),
178+
None => println!("none"),
179+
}
180+
}
181+
"#,
182+
);
183+
}
184+
185+
#[test]
186+
fn special_case_result() {
187+
check_assist(
188+
replace_if_let_with_match,
189+
r#"
190+
enum Result<T, E> { Ok(T), Err(E) }
191+
use Result::*;
192+
193+
fn foo(x: Result<i32, ()>) {
194+
<|>if let Ok(x) = x {
195+
println!("{}", x)
196+
} else {
197+
println!("none")
198+
}
199+
}
200+
"#,
201+
r#"
202+
enum Result<T, E> { Ok(T), Err(E) }
203+
use Result::*;
204+
205+
fn foo(x: Result<i32, ()>) {
206+
<|>match x {
207+
Ok(x) => println!("{}", x),
208+
Err(_) => println!("none"),
209+
}
210+
}
211+
"#,
212+
);
213+
}
148214
}

crates/ra_assists/src/handlers/replace_let_with_if_let.rs

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use std::iter::once;
22

3-
use hir::Adt;
43
use ra_syntax::{
54
ast::{
65
self,
@@ -12,6 +11,7 @@ use ra_syntax::{
1211

1312
use crate::{
1413
assist_ctx::{Assist, AssistCtx},
14+
utils::TryEnum,
1515
AssistId,
1616
};
1717

@@ -45,20 +45,10 @@ pub(crate) fn replace_let_with_if_let(ctx: AssistCtx) -> Option<Assist> {
4545
let init = let_stmt.initializer()?;
4646
let original_pat = let_stmt.pat()?;
4747
let ty = ctx.sema.type_of_expr(&init)?;
48-
let enum_ = match ty.as_adt() {
49-
Some(Adt::Enum(it)) => it,
50-
_ => return None,
51-
};
52-
let happy_case =
53-
[("Result", "Ok"), ("Option", "Some")].iter().find_map(|(known_type, happy_case)| {
54-
if &enum_.name(ctx.db).to_string() == known_type {
55-
return Some(happy_case);
56-
}
57-
None
58-
});
48+
let happy_variant = TryEnum::from_ty(ctx.sema, &ty).map(|it| it.happy_case());
5949

6050
ctx.add_assist(AssistId("replace_let_with_if_let"), "Replace with if-let", |edit| {
61-
let with_placeholder: ast::Pat = match happy_case {
51+
let with_placeholder: ast::Pat = match happy_variant {
6252
None => make::placeholder_pat().into(),
6353
Some(var_name) => make::tuple_struct_pat(
6454
make::path_unqualified(make::path_segment(make::name_ref(var_name))),

0 commit comments

Comments
 (0)