From dd0c3c41b927654553fa407fbb654bb3a2c64a48 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Wed, 19 Feb 2020 13:13:29 +0900 Subject: Fix a crash with non-ascii whitespace in doc-comments --- crates/ra_ide/src/hover.rs | 17 +++++++++++++++++ crates/ra_syntax/src/ast/traits.rs | 4 ++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs index 3f88bb260..1de3cb579 100644 --- a/crates/ra_ide/src/hover.rs +++ b/crates/ra_ide/src/hover.rs @@ -743,4 +743,21 @@ fn func(foo: i32) { if true { <|>foo; }; } &["u32"], ); } + + #[test] + fn test_hover_non_ascii_space_doc() { + check_hover_result( + " + //- /lib.rs + /// <- `\u{3000}` here + fn foo() { + } + + fn bar() { + fo<|>o(); + } + ", + &["fn foo()\n```\n\n<- `\u{3000}` here"], + ); + } } diff --git a/crates/ra_syntax/src/ast/traits.rs b/crates/ra_syntax/src/ast/traits.rs index f99984fe0..f8cf1e3eb 100644 --- a/crates/ra_syntax/src/ast/traits.rs +++ b/crates/ra_syntax/src/ast/traits.rs @@ -126,8 +126,8 @@ pub trait DocCommentsOwner: AstNode { // Determine if the prefix or prefix + 1 char is stripped let pos = - if line.chars().nth(prefix_len).map(|c| c.is_whitespace()).unwrap_or(false) { - prefix_len + 1 + if let Some(ws) = line.chars().nth(prefix_len).filter(|c| c.is_whitespace()) { + prefix_len + ws.len_utf8() } else { prefix_len }; -- cgit v1.2.3 From d06733efebc5d8b378398f1cbb4bbd9f3deb8270 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Wed, 19 Feb 2020 13:29:34 +0900 Subject: Cleanup --- crates/ra_assists/src/lib.rs | 2 +- crates/ra_ide/src/completion/presentation.rs | 6 +----- crates/ra_mbe/src/subtree_source.rs | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index a0e7fe17e..f4a7497db 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs @@ -38,7 +38,7 @@ pub struct GroupLabel(pub String); impl AssistLabel { pub(crate) fn new(label: String, id: AssistId) -> AssistLabel { // FIXME: make fields private, so that this invariant can't be broken - assert!(label.chars().next().unwrap().is_uppercase()); + assert!(label.starts_with(|c: char| c.is_uppercase())); AssistLabel { label, id } } } diff --git a/crates/ra_ide/src/completion/presentation.rs b/crates/ra_ide/src/completion/presentation.rs index 1a3bcffae..a524987fd 100644 --- a/crates/ra_ide/src/completion/presentation.rs +++ b/crates/ra_ide/src/completion/presentation.rs @@ -135,11 +135,7 @@ impl Completions { let (before, after) = (&docs[..idx], &docs[idx + s.len()..]); // Ensure to match the full word if after.starts_with('!') - && before - .chars() - .rev() - .next() - .map_or(true, |c| c != '_' && !c.is_ascii_alphanumeric()) + && !before.ends_with(|c: char| c == '_' || c.is_ascii_alphanumeric()) { // It may have spaces before the braces like `foo! {}` match after[1..].chars().find(|&c| !c.is_whitespace()) { diff --git a/crates/ra_mbe/src/subtree_source.rs b/crates/ra_mbe/src/subtree_source.rs index eb8b79e9a..dacca8279 100644 --- a/crates/ra_mbe/src/subtree_source.rs +++ b/crates/ra_mbe/src/subtree_source.rs @@ -141,7 +141,7 @@ fn convert_literal(l: &tt::Literal) -> TtToken { } fn convert_ident(ident: &tt::Ident) -> TtToken { - let kind = if let Some('\'') = ident.text.chars().next() { + let kind = if ident.text.starts_with('\'') { LIFETIME } else { SyntaxKind::from_keyword(ident.text.as_str()).unwrap_or(IDENT) -- cgit v1.2.3