From 20186cdf89a0b5027228ea01e0322bc4dac0456d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 15 Nov 2019 22:48:07 +0300 Subject: Fix add-new assist --- crates/ra_assists/src/assists/add_new.rs | 69 +++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 5 deletions(-) (limited to 'crates/ra_assists/src/assists') diff --git a/crates/ra_assists/src/assists/add_new.rs b/crates/ra_assists/src/assists/add_new.rs index a8839cfba..2038afdc6 100644 --- a/crates/ra_assists/src/assists/add_new.rs +++ b/crates/ra_assists/src/assists/add_new.rs @@ -158,9 +158,12 @@ fn find_struct_impl( let same_ty = blk.target_ty(db) == struct_ty; let not_trait_impl = blk.target_trait(db).is_none(); - found_new_fn = has_new_fn(impl_blk); + if !(same_ty && not_trait_impl) { + return false; + } - same_ty && not_trait_impl + found_new_fn = has_new_fn(impl_blk); + true }); if found_new_fn { @@ -186,9 +189,10 @@ fn has_new_fn(imp: &ast::ImplBlock) -> bool { #[cfg(test)] mod tests { - use super::*; use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; + use super::*; + #[test] #[rustfmt::skip] fn test_add_new() { @@ -345,7 +349,7 @@ struct Foo {<|>} impl Foo { fn new() -> Self { Self - } + } }", ); @@ -357,7 +361,7 @@ struct Foo {<|>} impl Foo { fn New() -> Self { Self - } + } }", ); } @@ -376,4 +380,59 @@ struct EvenMoreIrrelevant; struct Foo<'a, T: Foo<'a>> {}", ); } + + #[test] + fn test_unrelated_new() { + check_assist( + add_new, + r##" +pub struct AstId { + file_id: HirFileId, + file_ast_id: FileAstId, +} + +impl AstId { + pub fn new(file_id: HirFileId, file_ast_id: FileAstId) -> AstId { + AstId { file_id, file_ast_id } + } +} + +pub struct Source { + pub file_id: HirFileId,<|> + pub ast: T, +} + +impl Source { + pub fn map U, U>(self, f: F) -> Source { + Source { file_id: self.file_id, ast: f(self.ast) } + } +} +"##, + r##" +pub struct AstId { + file_id: HirFileId, + file_ast_id: FileAstId, +} + +impl AstId { + pub fn new(file_id: HirFileId, file_ast_id: FileAstId) -> AstId { + AstId { file_id, file_ast_id } + } +} + +pub struct Source { + pub file_id: HirFileId, + pub ast: T, +} + +impl Source { + pub fn new(file_id: HirFileId, ast: T) -> Self { Self { file_id, ast } }<|> + + pub fn map U, U>(self, f: F) -> Source { + Source { file_id: self.file_id, ast: f(self.ast) } + } +} +"##, + ); + } } -- cgit v1.2.3 From f36ac059f362050dae36569940b94a331387294a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 16 Nov 2019 01:14:56 +0300 Subject: Reduce some duplication --- crates/ra_assists/src/assists/add_explicit_type.rs | 2 +- crates/ra_assists/src/assists/add_missing_impl_members.rs | 3 +-- crates/ra_assists/src/assists/fill_match_arms.rs | 3 +-- crates/ra_assists/src/assists/inline_local_variable.rs | 2 +- 4 files changed, 4 insertions(+), 6 deletions(-) (limited to 'crates/ra_assists/src/assists') diff --git a/crates/ra_assists/src/assists/add_explicit_type.rs b/crates/ra_assists/src/assists/add_explicit_type.rs index ddda1a0f2..562a09685 100644 --- a/crates/ra_assists/src/assists/add_explicit_type.rs +++ b/crates/ra_assists/src/assists/add_explicit_type.rs @@ -40,7 +40,7 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx) -> Option) -> Option) -> Option< } else { let_stmt.syntax().text_range() }; - let analyzer = hir::SourceAnalyzer::new(ctx.db, ctx.frange.file_id, bind_pat.syntax(), None); + let analyzer = ctx.source_analyzer(bind_pat.syntax(), None); let refs = analyzer.find_all_refs(&bind_pat); let mut wrap_in_parens = vec![true; refs.len()]; -- cgit v1.2.3 From 5b54a93fe71137606674ff11dc57bc6e7eaa37f9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 16 Nov 2019 22:50:41 +0300 Subject: Add ast for plain and raw string literals --- crates/ra_assists/src/assists/raw_string.rs | 59 +++++++---------------------- 1 file changed, 13 insertions(+), 46 deletions(-) (limited to 'crates/ra_assists/src/assists') diff --git a/crates/ra_assists/src/assists/raw_string.rs b/crates/ra_assists/src/assists/raw_string.rs index 58f7157ae..93912a470 100644 --- a/crates/ra_assists/src/assists/raw_string.rs +++ b/crates/ra_assists/src/assists/raw_string.rs @@ -1,9 +1,9 @@ use hir::db::HirDatabase; use ra_syntax::{ + ast, AstToken, SyntaxKind::{RAW_STRING, STRING}, - TextRange, TextUnit, + TextUnit, }; -use rustc_lexer; use crate::{Assist, AssistCtx, AssistId}; @@ -23,32 +23,16 @@ use crate::{Assist, AssistCtx, AssistId}; // } // ``` pub(crate) fn make_raw_string(ctx: AssistCtx) -> Option { - let token = ctx.find_token_at_offset(STRING)?; - let text = token.text().as_str(); - let usual_string_range = find_usual_string_range(text)?; - let start_of_inside = usual_string_range.start().to_usize() + 1; - let end_of_inside = usual_string_range.end().to_usize(); - let inside_str = &text[start_of_inside..end_of_inside]; - let mut unescaped = String::with_capacity(inside_str.len()); - let mut error = Ok(()); - rustc_lexer::unescape::unescape_str( - inside_str, - &mut |_, unescaped_char| match unescaped_char { - Ok(c) => unescaped.push(c), - Err(_) => error = Err(()), - }, - ); - if error.is_err() { - return None; - } + let token = ctx.find_token_at_offset(STRING).and_then(ast::String::cast)?; + let value = token.value()?; ctx.add_assist(AssistId("make_raw_string"), "make raw string", |edit| { - edit.target(token.text_range()); - let max_hash_streak = count_hashes(&unescaped); + edit.target(token.syntax().text_range()); + let max_hash_streak = count_hashes(&value); let mut hashes = String::with_capacity(max_hash_streak + 1); for _ in 0..hashes.capacity() { hashes.push('#'); } - edit.replace(token.text_range(), format!("r{}\"{}\"{}", hashes, unescaped, hashes)); + edit.replace(token.syntax().text_range(), format!("r{}\"{}\"{}", hashes, value, hashes)); }) } @@ -68,17 +52,13 @@ pub(crate) fn make_raw_string(ctx: AssistCtx) -> Option) -> Option { - let token = ctx.find_token_at_offset(RAW_STRING)?; - let text = token.text().as_str(); - let usual_string_range = find_usual_string_range(text)?; + let token = ctx.find_token_at_offset(RAW_STRING).and_then(ast::RawString::cast)?; + let value = token.value()?; ctx.add_assist(AssistId("make_usual_string"), "make usual string", |edit| { - edit.target(token.text_range()); + edit.target(token.syntax().text_range()); // parse inside string to escape `"` - let start_of_inside = usual_string_range.start().to_usize() + 1; - let end_of_inside = usual_string_range.end().to_usize(); - let inside_str = &text[start_of_inside..end_of_inside]; - let escaped = inside_str.escape_default().to_string(); - edit.replace(token.text_range(), format!("\"{}\"", escaped)); + let escaped = value.escape_default().to_string(); + edit.replace(token.syntax().text_range(), format!("\"{}\"", escaped)); }) } @@ -132,6 +112,7 @@ pub(crate) fn remove_hash(ctx: AssistCtx) -> Option { edit.target(token.text_range()); let result = &text[2..text.len() - 1]; let result = if result.starts_with('\"') { + // FIXME: this logic is wrong, not only the last has has to handled specially // no more hash, escape let internal_str = &result[1..result.len() - 1]; format!("\"{}\"", internal_str.escape_default().to_string()) @@ -154,20 +135,6 @@ fn count_hashes(s: &str) -> usize { max_hash_streak } -fn find_usual_string_range(s: &str) -> Option { - let left_quote = s.find('"')?; - let right_quote = s.rfind('"')?; - if left_quote == right_quote { - // `s` only contains one quote - None - } else { - Some(TextRange::from_to( - TextUnit::from(left_quote as u32), - TextUnit::from(right_quote as u32), - )) - } -} - #[cfg(test)] mod test { use super::*; -- cgit v1.2.3