support range selection in assist docs

This commit is contained in:
Aleksey Kladov 2019-10-26 19:58:18 +03:00
parent 733fd64260
commit 4a83aae098
5 changed files with 85 additions and 9 deletions

View file

@ -1,5 +1,3 @@
//! FIXME: write short doc here
use format_buf::format;
use hir::db::HirDatabase;
use ra_syntax::{
@ -14,6 +12,22 @@ use test_utils::tested_by;
use crate::{Assist, AssistCtx, AssistId};
// Assist: introduce_variable
//
// Extracts subexpression into a variable.
//
// ```
// fn main() {
// <|>(1 + 2)<|> * 4;
// }
// ```
// ->
// ```
// fn main() {
// let var_name = (1 + 2);
// var_name * 4;
// }
// ```
pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
if ctx.frange.range.is_empty() {
return None;

View file

@ -7,13 +7,12 @@ mod generated;
use hir::mock::MockDatabase;
use ra_db::FileRange;
use ra_syntax::TextRange;
use test_utils::{assert_eq_text, extract_offset};
use test_utils::{assert_eq_text, extract_range_or_offset};
fn check(assist_id: &str, before: &str, after: &str) {
let (before_cursor_pos, before) = extract_offset(before);
let (selection, before) = extract_range_or_offset(before);
let (db, _source_root, file_id) = MockDatabase::with_single_file(&before);
let frange = FileRange { file_id, range: TextRange::offset_len(before_cursor_pos, 0.into()) };
let frange = FileRange { file_id, range: selection.into() };
let (_assist_id, action) = crate::assists(&db, frange)
.into_iter()

View file

@ -255,3 +255,21 @@ fn main() {
"#####,
)
}
#[test]
fn doctest_introduce_variable() {
check(
"introduce_variable",
r#####"
fn main() {
<|>(1 + 2)<|> * 4;
}
"#####,
r#####"
fn main() {
let var_name = (1 + 2);
var_name * 4;
}
"#####,
)
}

View file

@ -1,4 +1,10 @@
//! FIXME: write short doc here
//! Assorted testing utilities.
//!
//! Most notable things are:
//!
//! * Rich text comparison, which outputs a diff.
//! * Extracting markup (mainly, `<|>` markers) out of fixture strings.
//! * marks (see the eponymous module).
#[macro_use]
pub mod marks;
@ -43,7 +49,7 @@ pub fn extract_offset(text: &str) -> (TextUnit, String) {
}
}
pub fn try_extract_offset(text: &str) -> Option<(TextUnit, String)> {
fn try_extract_offset(text: &str) -> Option<(TextUnit, String)> {
let cursor_pos = text.find(CURSOR_MARKER)?;
let mut new_text = String::with_capacity(text.len() - CURSOR_MARKER.len());
new_text.push_str(&text[..cursor_pos]);
@ -59,12 +65,34 @@ pub fn extract_range(text: &str) -> (TextRange, String) {
}
}
pub fn try_extract_range(text: &str) -> Option<(TextRange, String)> {
fn try_extract_range(text: &str) -> Option<(TextRange, String)> {
let (start, text) = try_extract_offset(text)?;
let (end, text) = try_extract_offset(&text)?;
Some((TextRange::from_to(start, end), text))
}
pub enum RangeOrOffset {
Range(TextRange),
Offset(TextUnit),
}
impl From<RangeOrOffset> for TextRange {
fn from(selection: RangeOrOffset) -> Self {
match selection {
RangeOrOffset::Range(it) => it,
RangeOrOffset::Offset(it) => TextRange::from_to(it, it),
}
}
}
pub fn extract_range_or_offset(text: &str) -> (RangeOrOffset, String) {
if let Some((range, text)) = try_extract_range(text) {
return (RangeOrOffset::Range(range), text);
}
let (offset, text) = extract_offset(text);
(RangeOrOffset::Offset(offset), text)
}
/// Extracts ranges, marked with `<tag> </tag>` paris from the `text`
pub fn extract_ranges(mut text: &str, tag: &str) -> (Vec<TextRange>, String) {
let open = format!("<{}>", tag);

View file

@ -245,3 +245,20 @@ fn main() {
(1 + 2) * 4;
}
```
## `introduce_variable`
Extracts subexpression into a variable.
```rust
// BEFORE
fn main() {
<|>(1 + 2)<|> * 4;
}
// AFTER
fn main() {
let var_name = (1 + 2);
var_name * 4;
}
```