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') 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/assist_ctx.rs | 10 ++++++++-- 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 +- 5 files changed, 12 insertions(+), 8 deletions(-) (limited to 'crates/ra_assists') diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index 1908bdec9..71f7ce1b1 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs @@ -1,6 +1,5 @@ //! This module defines `AssistCtx` -- the API surface that is exposed to assists. - -use hir::db::HirDatabase; +use hir::{db::HirDatabase, SourceAnalyzer}; use ra_db::FileRange; use ra_fmt::{leading_indent, reindent}; use ra_syntax::{ @@ -113,6 +112,13 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> { pub(crate) fn covering_element(&self) -> SyntaxElement { find_covering_element(self.source_file.syntax(), self.frange.range) } + pub(crate) fn source_analyzer( + &self, + node: &SyntaxNode, + offset: Option, + ) -> SourceAnalyzer { + SourceAnalyzer::new(self.db, self.frange.file_id, node, offset) + } pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement { find_covering_element(self.source_file.syntax(), range) 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 d898ecb8f2c19eb041bcb27c7ce9edd9d891f2c2 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 16 Nov 2019 00:56:51 +0300 Subject: Force passing Source when creating a SourceAnalyzer --- crates/ra_assists/src/assist_ctx.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_assists') diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs index 71f7ce1b1..0ea84d548 100644 --- a/crates/ra_assists/src/assist_ctx.rs +++ b/crates/ra_assists/src/assist_ctx.rs @@ -117,7 +117,7 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> { node: &SyntaxNode, offset: Option, ) -> SourceAnalyzer { - SourceAnalyzer::new(self.db, self.frange.file_id, node, offset) + SourceAnalyzer::new(self.db, hir::Source::new(self.frange.file_id.into(), node), offset) } pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement { -- 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/Cargo.toml | 1 - crates/ra_assists/src/assists/raw_string.rs | 59 +++++++---------------------- 2 files changed, 13 insertions(+), 47 deletions(-) (limited to 'crates/ra_assists') diff --git a/crates/ra_assists/Cargo.toml b/crates/ra_assists/Cargo.toml index beebccbd9..125c6222d 100644 --- a/crates/ra_assists/Cargo.toml +++ b/crates/ra_assists/Cargo.toml @@ -8,7 +8,6 @@ authors = ["rust-analyzer developers"] format-buf = "1.0.0" join_to_string = "0.1.3" itertools = "0.8.0" -rustc_lexer = "0.1.0" ra_syntax = { path = "../ra_syntax" } ra_text_edit = { path = "../ra_text_edit" } 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 From 7e2f4b30db8a0d734b3a1fc9f6ad77b2adc9aa2a Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 17 Nov 2019 18:35:05 +0300 Subject: Disable doctests --- crates/ra_assists/Cargo.toml | 3 +++ 1 file changed, 3 insertions(+) (limited to 'crates/ra_assists') diff --git a/crates/ra_assists/Cargo.toml b/crates/ra_assists/Cargo.toml index 125c6222d..434e6656c 100644 --- a/crates/ra_assists/Cargo.toml +++ b/crates/ra_assists/Cargo.toml @@ -4,6 +4,9 @@ name = "ra_assists" version = "0.1.0" authors = ["rust-analyzer developers"] +[lib] +doctest = false + [dependencies] format-buf = "1.0.0" join_to_string = "0.1.3" -- cgit v1.2.3