mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-14 14:13:58 +00:00
Auto merge of #17253 - ThouCheese:master, r=Veykril
Implement assist to switch between doc and normal comments Hey first PR to rust-analyzer to get my feet wet with the code base. It's an assist to switch a normal comment to a doc comment and back, something I've found myself doing by hand a couple of times. I shamelessly stole `relevant_line_comments` from `convert_comment_block`, because I didn't see any inter-assist imports happening in the files I peeked at so I thought this would be preferable.
This commit is contained in:
commit
f59ca41f23
3 changed files with 702 additions and 0 deletions
|
@ -0,0 +1,685 @@
|
||||||
|
use itertools::Itertools;
|
||||||
|
use syntax::{
|
||||||
|
ast::{self, edit::IndentLevel, Comment, CommentPlacement, Whitespace},
|
||||||
|
AstToken, Direction, SyntaxElement, TextRange,
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{AssistContext, AssistId, AssistKind, Assists};
|
||||||
|
|
||||||
|
// Assist: comment_to_doc
|
||||||
|
//
|
||||||
|
// Converts comments to documentation.
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
// // Wow what $0a nice module
|
||||||
|
// // I sure hope this shows up when I hover over it
|
||||||
|
// ```
|
||||||
|
// ->
|
||||||
|
// ```
|
||||||
|
// //! Wow what a nice module
|
||||||
|
// //! I sure hope this shows up when I hover over it
|
||||||
|
// ```
|
||||||
|
pub(crate) fn convert_comment_from_or_to_doc(
|
||||||
|
acc: &mut Assists,
|
||||||
|
ctx: &AssistContext<'_>,
|
||||||
|
) -> Option<()> {
|
||||||
|
let comment = ctx.find_token_at_offset::<ast::Comment>()?;
|
||||||
|
|
||||||
|
match comment.kind().doc {
|
||||||
|
Some(_) => doc_to_comment(acc, comment),
|
||||||
|
None => can_be_doc_comment(&comment).and_then(|style| comment_to_doc(acc, comment, style)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn doc_to_comment(acc: &mut Assists, comment: ast::Comment) -> Option<()> {
|
||||||
|
let target = if comment.kind().shape.is_line() {
|
||||||
|
line_comments_text_range(&comment)?
|
||||||
|
} else {
|
||||||
|
comment.syntax().text_range()
|
||||||
|
};
|
||||||
|
|
||||||
|
acc.add(
|
||||||
|
AssistId("doc_to_comment", AssistKind::RefactorRewrite),
|
||||||
|
"Replace comment with doc comment",
|
||||||
|
target,
|
||||||
|
|edit| {
|
||||||
|
// We need to either replace the first occurrence of /* with /***, or we need to replace
|
||||||
|
// the occurrences // at the start of each line with ///
|
||||||
|
let output = match comment.kind().shape {
|
||||||
|
ast::CommentShape::Line => {
|
||||||
|
let indentation = IndentLevel::from_token(comment.syntax());
|
||||||
|
let line_start = comment.prefix();
|
||||||
|
let prefix = format!("{indentation}//");
|
||||||
|
relevant_line_comments(&comment)
|
||||||
|
.iter()
|
||||||
|
.map(|comment| comment.text())
|
||||||
|
.flat_map(|text| text.lines())
|
||||||
|
.map(|line| line.replacen(line_start, &prefix, 1))
|
||||||
|
.join("\n")
|
||||||
|
}
|
||||||
|
ast::CommentShape::Block => {
|
||||||
|
let block_start = comment.prefix();
|
||||||
|
comment
|
||||||
|
.text()
|
||||||
|
.lines()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(idx, line)| {
|
||||||
|
if idx == 0 {
|
||||||
|
line.replacen(block_start, "/*", 1)
|
||||||
|
} else {
|
||||||
|
line.replacen("* ", "* ", 1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.join("\n")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
edit.replace(target, output)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn comment_to_doc(acc: &mut Assists, comment: ast::Comment, style: CommentPlacement) -> Option<()> {
|
||||||
|
let target = if comment.kind().shape.is_line() {
|
||||||
|
line_comments_text_range(&comment)?
|
||||||
|
} else {
|
||||||
|
comment.syntax().text_range()
|
||||||
|
};
|
||||||
|
|
||||||
|
acc.add(
|
||||||
|
AssistId("comment_to_doc", AssistKind::RefactorRewrite),
|
||||||
|
"Replace doc comment with comment",
|
||||||
|
target,
|
||||||
|
|edit| {
|
||||||
|
// We need to either replace the first occurrence of /* with /***, or we need to replace
|
||||||
|
// the occurrences // at the start of each line with ///
|
||||||
|
let output = match comment.kind().shape {
|
||||||
|
ast::CommentShape::Line => {
|
||||||
|
let indentation = IndentLevel::from_token(comment.syntax());
|
||||||
|
let line_start = match style {
|
||||||
|
CommentPlacement::Inner => format!("{indentation}//!"),
|
||||||
|
CommentPlacement::Outer => format!("{indentation}///"),
|
||||||
|
};
|
||||||
|
relevant_line_comments(&comment)
|
||||||
|
.iter()
|
||||||
|
.map(|comment| comment.text())
|
||||||
|
.flat_map(|text| text.lines())
|
||||||
|
.map(|line| line.replacen("//", &line_start, 1))
|
||||||
|
.join("\n")
|
||||||
|
}
|
||||||
|
ast::CommentShape::Block => {
|
||||||
|
let block_start = match style {
|
||||||
|
CommentPlacement::Inner => "/*!",
|
||||||
|
CommentPlacement::Outer => "/**",
|
||||||
|
};
|
||||||
|
comment
|
||||||
|
.text()
|
||||||
|
.lines()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(idx, line)| {
|
||||||
|
if idx == 0 {
|
||||||
|
// On the first line we replace the comment start with a doc comment
|
||||||
|
// start.
|
||||||
|
line.replacen("/*", block_start, 1)
|
||||||
|
} else {
|
||||||
|
// put one extra space after each * since we moved the first line to
|
||||||
|
// the right by one column as well.
|
||||||
|
line.replacen("* ", "* ", 1)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.join("\n")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
edit.replace(target, output)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Not all comments are valid candidates for conversion into doc comments. For example, the
|
||||||
|
/// comments in the code:
|
||||||
|
/// ```rust
|
||||||
|
/// // Brilliant module right here
|
||||||
|
///
|
||||||
|
/// // Really good right
|
||||||
|
/// fn good_function(foo: Foo) -> Bar {
|
||||||
|
/// foo.into_bar()
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // So nice
|
||||||
|
/// mod nice_module {}
|
||||||
|
/// ```
|
||||||
|
/// can be converted to doc comments. However, the comments in this example:
|
||||||
|
/// ```rust
|
||||||
|
/// fn foo_bar(foo: Foo /* not bar yet */) -> Bar {
|
||||||
|
/// foo.into_bar()
|
||||||
|
/// // Nicely done
|
||||||
|
/// }
|
||||||
|
/// // end of function
|
||||||
|
///
|
||||||
|
/// struct S {
|
||||||
|
/// // The S struct
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
/// are not allowed to become doc comments. Moreover, some comments _are_ allowed, but aren't common
|
||||||
|
/// style in Rust. For example, the following comments are allowed to be doc comments, but it is not
|
||||||
|
/// common style for them to be:
|
||||||
|
/// ```rust
|
||||||
|
/// fn foo_bar(foo: Foo) -> Bar {
|
||||||
|
/// // this could be an inner comment with //!
|
||||||
|
/// foo.into_bar()
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// trait T {
|
||||||
|
/// // The T struct could also be documented from within
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// mod mymod {
|
||||||
|
/// // Modules only normally get inner documentation when they are defined as a separate file.
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
fn can_be_doc_comment(comment: &ast::Comment) -> Option<CommentPlacement> {
|
||||||
|
use syntax::SyntaxKind::*;
|
||||||
|
|
||||||
|
// if the comment is not on its own line, then we do not propose anything.
|
||||||
|
match comment.syntax().prev_token() {
|
||||||
|
Some(prev) => {
|
||||||
|
// There was a previous token, now check if it was a newline
|
||||||
|
Whitespace::cast(prev).filter(|w| w.text().contains('\n'))?;
|
||||||
|
}
|
||||||
|
// There is no previous token, this is the start of the file.
|
||||||
|
None => return Some(CommentPlacement::Inner),
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if comment is followed by: `struct`, `trait`, `mod`, `fn`, `type`, `extern crate`,
|
||||||
|
// `use` or `const`.
|
||||||
|
let parent = comment.syntax().parent();
|
||||||
|
let par_kind = parent.as_ref().map(|parent| parent.kind());
|
||||||
|
matches!(par_kind, Some(STRUCT | TRAIT | MODULE | FN | TYPE_ALIAS | EXTERN_CRATE | USE | CONST))
|
||||||
|
.then_some(CommentPlacement::Outer)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The line -> block assist can be invoked from anywhere within a sequence of line comments.
|
||||||
|
/// relevant_line_comments crawls backwards and forwards finding the complete sequence of comments that will
|
||||||
|
/// be joined.
|
||||||
|
pub(crate) fn relevant_line_comments(comment: &ast::Comment) -> Vec<Comment> {
|
||||||
|
// The prefix identifies the kind of comment we're dealing with
|
||||||
|
let prefix = comment.prefix();
|
||||||
|
let same_prefix = |c: &ast::Comment| c.prefix() == prefix;
|
||||||
|
|
||||||
|
// These tokens are allowed to exist between comments
|
||||||
|
let skippable = |not: &SyntaxElement| {
|
||||||
|
not.clone()
|
||||||
|
.into_token()
|
||||||
|
.and_then(Whitespace::cast)
|
||||||
|
.map(|w| !w.spans_multiple_lines())
|
||||||
|
.unwrap_or(false)
|
||||||
|
};
|
||||||
|
|
||||||
|
// Find all preceding comments (in reverse order) that have the same prefix
|
||||||
|
let prev_comments = comment
|
||||||
|
.syntax()
|
||||||
|
.siblings_with_tokens(Direction::Prev)
|
||||||
|
.filter(|s| !skippable(s))
|
||||||
|
.map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix))
|
||||||
|
.take_while(|opt_com| opt_com.is_some())
|
||||||
|
.flatten()
|
||||||
|
.skip(1); // skip the first element so we don't duplicate it in next_comments
|
||||||
|
|
||||||
|
let next_comments = comment
|
||||||
|
.syntax()
|
||||||
|
.siblings_with_tokens(Direction::Next)
|
||||||
|
.filter(|s| !skippable(s))
|
||||||
|
.map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix))
|
||||||
|
.take_while(|opt_com| opt_com.is_some())
|
||||||
|
.flatten();
|
||||||
|
|
||||||
|
let mut comments: Vec<_> = prev_comments.collect();
|
||||||
|
comments.reverse();
|
||||||
|
comments.extend(next_comments);
|
||||||
|
comments
|
||||||
|
}
|
||||||
|
|
||||||
|
fn line_comments_text_range(comment: &ast::Comment) -> Option<TextRange> {
|
||||||
|
let comments = relevant_line_comments(comment);
|
||||||
|
let first = comments.first()?;
|
||||||
|
let indentation = IndentLevel::from_token(first.syntax());
|
||||||
|
let start =
|
||||||
|
first.syntax().text_range().start().checked_sub((indentation.0 as u32 * 4).into())?;
|
||||||
|
let end = comments.last()?.syntax().text_range().end();
|
||||||
|
Some(TextRange::new(start, end))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::tests::{check_assist, check_assist_not_applicable};
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn module_comment_to_doc() {
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"
|
||||||
|
// such a nice module$0
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
//! such a nice module
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn single_line_comment_to_doc() {
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"
|
||||||
|
|
||||||
|
// unseen$0 docs
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
|
||||||
|
/// unseen docs
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multi_line_comment_to_doc() {
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"
|
||||||
|
|
||||||
|
// unseen$0 docs
|
||||||
|
// make me seen!
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
|
||||||
|
/// unseen docs
|
||||||
|
/// make me seen!
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn single_line_doc_to_comment() {
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"
|
||||||
|
|
||||||
|
/// visible$0 docs
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
|
||||||
|
// visible docs
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multi_line_doc_to_comment() {
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"
|
||||||
|
|
||||||
|
/// visible$0 docs
|
||||||
|
/// Hide me!
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
|
||||||
|
// visible docs
|
||||||
|
// Hide me!
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn single_line_block_comment_to_doc() {
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"
|
||||||
|
|
||||||
|
/* unseen$0 docs */
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
|
||||||
|
/** unseen docs */
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multi_line_block_comment_to_doc() {
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"
|
||||||
|
|
||||||
|
/* unseen$0 docs
|
||||||
|
* make me seen!
|
||||||
|
*/
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
|
||||||
|
/** unseen docs
|
||||||
|
* make me seen!
|
||||||
|
*/
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn single_line_block_doc_to_comment() {
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"
|
||||||
|
|
||||||
|
/** visible$0 docs */
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
|
||||||
|
/* visible docs */
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multi_line_block_doc_to_comment() {
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"
|
||||||
|
|
||||||
|
/** visible$0 docs
|
||||||
|
* Hide me!
|
||||||
|
*/
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
|
||||||
|
/* visible docs
|
||||||
|
* Hide me!
|
||||||
|
*/
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn single_inner_line_comment_to_doc() {
|
||||||
|
check_assist_not_applicable(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"
|
||||||
|
mod mymod {
|
||||||
|
// unseen$0 docs
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn single_inner_line_doc_to_comment() {
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"
|
||||||
|
mod mymod {
|
||||||
|
//! visible$0 docs
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
mod mymod {
|
||||||
|
// visible docs
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multi_inner_line_doc_to_comment() {
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"
|
||||||
|
mod mymod {
|
||||||
|
//! visible$0 docs
|
||||||
|
//! Hide me!
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
mod mymod {
|
||||||
|
// visible docs
|
||||||
|
// Hide me!
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"
|
||||||
|
mod mymod {
|
||||||
|
/// visible$0 docs
|
||||||
|
/// Hide me!
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
mod mymod {
|
||||||
|
// visible docs
|
||||||
|
// Hide me!
|
||||||
|
foo();
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn single_inner_line_block_doc_to_comment() {
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"
|
||||||
|
mod mymod {
|
||||||
|
/*! visible$0 docs */
|
||||||
|
type Int = i32;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
mod mymod {
|
||||||
|
/* visible docs */
|
||||||
|
type Int = i32;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn multi_inner_line_block_doc_to_comment() {
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"
|
||||||
|
mod mymod {
|
||||||
|
/*! visible$0 docs
|
||||||
|
* Hide me!
|
||||||
|
*/
|
||||||
|
type Int = i32;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
r#"
|
||||||
|
mod mymod {
|
||||||
|
/* visible docs
|
||||||
|
* Hide me!
|
||||||
|
*/
|
||||||
|
type Int = i32;
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn not_overeager() {
|
||||||
|
check_assist_not_applicable(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"
|
||||||
|
fn main() {
|
||||||
|
foo();
|
||||||
|
// $0well that settles main
|
||||||
|
}
|
||||||
|
// $1 nicely done
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn all_possible_items() {
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"mod m {
|
||||||
|
/* Nice struct$0 */
|
||||||
|
struct S {}
|
||||||
|
}"#,
|
||||||
|
r#"mod m {
|
||||||
|
/** Nice struct */
|
||||||
|
struct S {}
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"mod m {
|
||||||
|
/* Nice trait$0 */
|
||||||
|
trait T {}
|
||||||
|
}"#,
|
||||||
|
r#"mod m {
|
||||||
|
/** Nice trait */
|
||||||
|
trait T {}
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"mod m {
|
||||||
|
/* Nice module$0 */
|
||||||
|
mod module {}
|
||||||
|
}"#,
|
||||||
|
r#"mod m {
|
||||||
|
/** Nice module */
|
||||||
|
mod module {}
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"mod m {
|
||||||
|
/* Nice function$0 */
|
||||||
|
fn function() {}
|
||||||
|
}"#,
|
||||||
|
r#"mod m {
|
||||||
|
/** Nice function */
|
||||||
|
fn function() {}
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"mod m {
|
||||||
|
/* Nice type$0 */
|
||||||
|
type Type Int = i32;
|
||||||
|
}"#,
|
||||||
|
r#"mod m {
|
||||||
|
/** Nice type */
|
||||||
|
type Type Int = i32;
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"mod m {
|
||||||
|
/* Nice crate$0 */
|
||||||
|
extern crate rust_analyzer;
|
||||||
|
}"#,
|
||||||
|
r#"mod m {
|
||||||
|
/** Nice crate */
|
||||||
|
extern crate rust_analyzer;
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"mod m {
|
||||||
|
/* Nice import$0 */
|
||||||
|
use ide_assists::convert_comment_from_or_to_doc::tests
|
||||||
|
}"#,
|
||||||
|
r#"mod m {
|
||||||
|
/** Nice import */
|
||||||
|
use ide_assists::convert_comment_from_or_to_doc::tests
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
check_assist(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"mod m {
|
||||||
|
/* Nice constant$0 */
|
||||||
|
const CONST: &str = "very const";
|
||||||
|
}"#,
|
||||||
|
r#"mod m {
|
||||||
|
/** Nice constant */
|
||||||
|
const CONST: &str = "very const";
|
||||||
|
}"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn no_inner_comments() {
|
||||||
|
check_assist_not_applicable(
|
||||||
|
convert_comment_from_or_to_doc,
|
||||||
|
r#"
|
||||||
|
mod mymod {
|
||||||
|
// aaa$0aa
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -116,6 +116,7 @@ mod handlers {
|
||||||
mod change_visibility;
|
mod change_visibility;
|
||||||
mod convert_bool_then;
|
mod convert_bool_then;
|
||||||
mod convert_comment_block;
|
mod convert_comment_block;
|
||||||
|
mod convert_comment_from_or_to_doc;
|
||||||
mod convert_from_to_tryfrom;
|
mod convert_from_to_tryfrom;
|
||||||
mod convert_integer_literal;
|
mod convert_integer_literal;
|
||||||
mod convert_into_to_from;
|
mod convert_into_to_from;
|
||||||
|
@ -239,6 +240,7 @@ mod handlers {
|
||||||
convert_bool_then::convert_bool_then_to_if,
|
convert_bool_then::convert_bool_then_to_if,
|
||||||
convert_bool_then::convert_if_to_bool_then,
|
convert_bool_then::convert_if_to_bool_then,
|
||||||
convert_comment_block::convert_comment_block,
|
convert_comment_block::convert_comment_block,
|
||||||
|
convert_comment_from_or_to_doc::convert_comment_from_or_to_doc,
|
||||||
convert_from_to_tryfrom::convert_from_to_tryfrom,
|
convert_from_to_tryfrom::convert_from_to_tryfrom,
|
||||||
convert_integer_literal::convert_integer_literal,
|
convert_integer_literal::convert_integer_literal,
|
||||||
convert_into_to_from::convert_into_to_from,
|
convert_into_to_from::convert_into_to_from,
|
||||||
|
|
|
@ -345,6 +345,21 @@ pub(crate) fn frobnicate() {}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn doctest_comment_to_doc() {
|
||||||
|
check_doc_test(
|
||||||
|
"comment_to_doc",
|
||||||
|
r#####"
|
||||||
|
// Wow what $0a nice module
|
||||||
|
// I sure hope this shows up when I hover over it
|
||||||
|
"#####,
|
||||||
|
r#####"
|
||||||
|
//! Wow what a nice module
|
||||||
|
//! I sure hope this shows up when I hover over it
|
||||||
|
"#####,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn doctest_convert_bool_then_to_if() {
|
fn doctest_convert_bool_then_to_if() {
|
||||||
check_doc_test(
|
check_doc_test(
|
||||||
|
|
Loading…
Reference in a new issue