From 76290afa9a654c9d2325acd644133c71a941faa9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Sep 2019 23:39:29 +0300 Subject: [PATCH 1/3] minor cleanup --- crates/ra_mbe/src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index 41720df79f5..a0904323cbb 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs @@ -52,6 +52,9 @@ pub(crate) struct Rule { impl MacroRules { pub fn parse(tt: &tt::Subtree) -> Result { + // Note: this parsing can be implemented using mbe machinery itself, by + // matching against `$($lhs:tt => $rhs:tt);*` pattern, but implementing + // manually seems easier. let mut src = TtIter::new(tt); let mut rules = Vec::new(); while src.len() > 0 { @@ -64,6 +67,11 @@ pub fn parse(tt: &tt::Subtree) -> Result { break; } } + + for rule in rules.iter() { + validate(&rule.lhs)?; + } + Ok(MacroRules { rules }) } pub fn expand(&self, tt: &tt::Subtree) -> Result { @@ -77,7 +85,6 @@ fn parse(src: &mut TtIter) -> Result { .expect_subtree() .map_err(|()| ParseError::Expected("expected subtree".to_string()))? .clone(); - validate(&lhs)?; lhs.delimiter = tt::Delimiter::None; src.expect_char('=').map_err(|()| ParseError::Expected("expected `=`".to_string()))?; src.expect_char('>').map_err(|()| ParseError::Expected("expected `>`".to_string()))?; From 9a0fef71cc2422502401d5e156df751dc242e3e8 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Sep 2019 23:43:23 +0300 Subject: [PATCH 2/3] test for TOODs as well --- crates/ra_assists/src/raw_string.rs | 740 ++++++++++++++-------------- crates/ra_tools/tests/cli.rs | 2 +- 2 files changed, 371 insertions(+), 371 deletions(-) diff --git a/crates/ra_assists/src/raw_string.rs b/crates/ra_assists/src/raw_string.rs index e0026706012..965a64c9870 100644 --- a/crates/ra_assists/src/raw_string.rs +++ b/crates/ra_assists/src/raw_string.rs @@ -1,370 +1,370 @@ -use hir::db::HirDatabase; -use ra_syntax::{ast::AstNode, ast::Literal, TextRange, TextUnit}; - -use crate::{Assist, AssistCtx, AssistId}; - -pub(crate) fn make_raw_string(mut ctx: AssistCtx) -> Option { - let literal = ctx.node_at_offset::()?; - if literal.token().kind() != ra_syntax::SyntaxKind::STRING { - return None; - } - ctx.add_action(AssistId("make_raw_string"), "make raw string", |edit| { - edit.target(literal.syntax().text_range()); - edit.insert(literal.syntax().text_range().start(), "r"); - }); - ctx.build() -} - -fn find_usual_string_range(s: &str) -> Option { - Some(TextRange::from_to( - TextUnit::from(s.find('"')? as u32), - TextUnit::from(s.rfind('"')? as u32), - )) -} - -pub(crate) fn make_usual_string(mut ctx: AssistCtx) -> Option { - let literal = ctx.node_at_offset::()?; - if literal.token().kind() != ra_syntax::SyntaxKind::RAW_STRING { - return None; - } - let token = literal.token(); - let text = token.text().as_str(); - let usual_string_range = find_usual_string_range(text)?; - ctx.add_action(AssistId("make_usual_string"), "make usual string", |edit| { - edit.target(literal.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(literal.syntax().text_range(), format!("\"{}\"", escaped)); - }); - ctx.build() -} - -pub(crate) fn add_hash(mut ctx: AssistCtx) -> Option { - let literal = ctx.node_at_offset::()?; - if literal.token().kind() != ra_syntax::SyntaxKind::RAW_STRING { - return None; - } - ctx.add_action(AssistId("add_hash"), "add hash to raw string", |edit| { - edit.target(literal.syntax().text_range()); - edit.insert(literal.syntax().text_range().start() + TextUnit::of_char('r'), "#"); - edit.insert(literal.syntax().text_range().end(), "#"); - }); - ctx.build() -} - -pub(crate) fn remove_hash(mut ctx: AssistCtx) -> Option { - let literal = ctx.node_at_offset::()?; - if literal.token().kind() != ra_syntax::SyntaxKind::RAW_STRING { - return None; - } - let token = literal.token(); - let text = token.text().as_str(); - if text.starts_with("r\"") { - // no hash to remove - return None; - } - ctx.add_action(AssistId("remove_hash"), "remove hash from raw string", |edit| { - edit.target(literal.syntax().text_range()); - let result = &text[2..text.len() - 1]; - let result = if result.starts_with("\"") { - // no more hash, escape - let internal_str = &result[1..result.len() - 1]; - format!("\"{}\"", internal_str.escape_default().to_string()) - } else { - result.to_owned() - }; - edit.replace(literal.syntax().text_range(), format!("r{}", result)); - }); - ctx.build() -} - -#[cfg(test)] -mod test { - use super::*; - use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; - - #[test] - fn make_raw_string_target() { - check_assist_target( - make_raw_string, - r#" - fn f() { - let s = <|>"random string"; - } - "#, - r#""random string""#, - ); - } - - #[test] - fn make_raw_string_works() { - check_assist( - make_raw_string, - r#" - fn f() { - let s = <|>"random string"; - } - "#, - r#" - fn f() { - let s = <|>r"random string"; - } - "#, - ) - } - - #[test] - fn make_raw_string_with_escaped_works() { - check_assist( - make_raw_string, - r#" - fn f() { - let s = <|>"random\nstring"; - } - "#, - r#" - fn f() { - let s = <|>r"random\nstring"; - } - "#, - ) - } - - #[test] - fn make_raw_string_not_works() { - check_assist_not_applicable( - make_raw_string, - r#" - fn f() { - let s = <|>r"random string"; - } - "#, - ); - } - - #[test] - fn add_hash_target() { - check_assist_target( - add_hash, - r#" - fn f() { - let s = <|>r"random string"; - } - "#, - r#"r"random string""#, - ); - } - - #[test] - fn add_hash_works() { - check_assist( - add_hash, - r#" - fn f() { - let s = <|>r"random string"; - } - "#, - r##" - fn f() { - let s = <|>r#"random string"#; - } - "##, - ) - } - - #[test] - fn add_more_hash_works() { - check_assist( - add_hash, - r##" - fn f() { - let s = <|>r#"random"string"#; - } - "##, - r###" - fn f() { - let s = <|>r##"random"string"##; - } - "###, - ) - } - - #[test] - fn add_hash_not_works() { - check_assist_not_applicable( - add_hash, - r#" - fn f() { - let s = <|>"random string"; - } - "#, - ); - } - - #[test] - fn remove_hash_target() { - check_assist_target( - remove_hash, - r##" - fn f() { - let s = <|>r#"random string"#; - } - "##, - r##"r#"random string"#"##, - ); - } - - #[test] - fn remove_hash_works() { - check_assist( - remove_hash, - r##" - fn f() { - let s = <|>r#"random string"#; - } - "##, - r#" - fn f() { - let s = <|>r"random string"; - } - "#, - ) - } - - #[test] - fn remove_hash_with_quote_works() { - check_assist( - remove_hash, - r##" - fn f() { - let s = <|>r#"random"str"ing"#; - } - "##, - r#" - fn f() { - let s = <|>r"random\"str\"ing"; - } - "#, - ) - } - - #[test] - fn remove_more_hash_works() { - check_assist( - remove_hash, - r###" - fn f() { - let s = <|>r##"random string"##; - } - "###, - r##" - fn f() { - let s = <|>r#"random string"#; - } - "##, - ) - } - - #[test] - fn remove_hash_not_works() { - check_assist_not_applicable( - remove_hash, - r#" - fn f() { - let s = <|>"random string"; - } - "#, - ); - } - - #[test] - fn remove_hash_no_hash_not_works() { - check_assist_not_applicable( - remove_hash, - r#" - fn f() { - let s = <|>r"random string"; - } - "#, - ); - } - - #[test] - fn make_usual_string_target() { - check_assist_target( - make_usual_string, - r##" - fn f() { - let s = <|>r#"random string"#; - } - "##, - r##"r#"random string"#"##, - ); - } - - #[test] - fn make_usual_string_works() { - check_assist( - make_usual_string, - r##" - fn f() { - let s = <|>r#"random string"#; - } - "##, - r#" - fn f() { - let s = <|>"random string"; - } - "#, - ) - } - - #[test] - fn make_usual_string_with_quote_works() { - check_assist( - make_usual_string, - r##" - fn f() { - let s = <|>r#"random"str"ing"#; - } - "##, - r#" - fn f() { - let s = <|>"random\"str\"ing"; - } - "#, - ) - } - - #[test] - fn make_usual_string_more_hash_works() { - check_assist( - make_usual_string, - r###" - fn f() { - let s = <|>r##"random string"##; - } - "###, - r##" - fn f() { - let s = <|>"random string"; - } - "##, - ) - } - - #[test] - fn make_usual_string_not_works() { - check_assist_not_applicable( - make_usual_string, - r#" - fn f() { - let s = <|>"random string"; - } - "#, - ); - } -} +use hir::db::HirDatabase; +use ra_syntax::{ast::AstNode, ast::Literal, TextRange, TextUnit}; + +use crate::{Assist, AssistCtx, AssistId}; + +pub(crate) fn make_raw_string(mut ctx: AssistCtx) -> Option { + let literal = ctx.node_at_offset::()?; + if literal.token().kind() != ra_syntax::SyntaxKind::STRING { + return None; + } + ctx.add_action(AssistId("make_raw_string"), "make raw string", |edit| { + edit.target(literal.syntax().text_range()); + edit.insert(literal.syntax().text_range().start(), "r"); + }); + ctx.build() +} + +fn find_usual_string_range(s: &str) -> Option { + Some(TextRange::from_to( + TextUnit::from(s.find('"')? as u32), + TextUnit::from(s.rfind('"')? as u32), + )) +} + +pub(crate) fn make_usual_string(mut ctx: AssistCtx) -> Option { + let literal = ctx.node_at_offset::()?; + if literal.token().kind() != ra_syntax::SyntaxKind::RAW_STRING { + return None; + } + let token = literal.token(); + let text = token.text().as_str(); + let usual_string_range = find_usual_string_range(text)?; + ctx.add_action(AssistId("make_usual_string"), "make usual string", |edit| { + edit.target(literal.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(literal.syntax().text_range(), format!("\"{}\"", escaped)); + }); + ctx.build() +} + +pub(crate) fn add_hash(mut ctx: AssistCtx) -> Option { + let literal = ctx.node_at_offset::()?; + if literal.token().kind() != ra_syntax::SyntaxKind::RAW_STRING { + return None; + } + ctx.add_action(AssistId("add_hash"), "add hash to raw string", |edit| { + edit.target(literal.syntax().text_range()); + edit.insert(literal.syntax().text_range().start() + TextUnit::of_char('r'), "#"); + edit.insert(literal.syntax().text_range().end(), "#"); + }); + ctx.build() +} + +pub(crate) fn remove_hash(mut ctx: AssistCtx) -> Option { + let literal = ctx.node_at_offset::()?; + if literal.token().kind() != ra_syntax::SyntaxKind::RAW_STRING { + return None; + } + let token = literal.token(); + let text = token.text().as_str(); + if text.starts_with("r\"") { + // no hash to remove + return None; + } + ctx.add_action(AssistId("remove_hash"), "remove hash from raw string", |edit| { + edit.target(literal.syntax().text_range()); + let result = &text[2..text.len() - 1]; + let result = if result.starts_with("\"") { + // no more hash, escape + let internal_str = &result[1..result.len() - 1]; + format!("\"{}\"", internal_str.escape_default().to_string()) + } else { + result.to_owned() + }; + edit.replace(literal.syntax().text_range(), format!("r{}", result)); + }); + ctx.build() +} + +#[cfg(test)] +mod test { + use super::*; + use crate::helpers::{check_assist, check_assist_not_applicable, check_assist_target}; + + #[test] + fn make_raw_string_target() { + check_assist_target( + make_raw_string, + r#" + fn f() { + let s = <|>"random string"; + } + "#, + r#""random string""#, + ); + } + + #[test] + fn make_raw_string_works() { + check_assist( + make_raw_string, + r#" + fn f() { + let s = <|>"random string"; + } + "#, + r#" + fn f() { + let s = <|>r"random string"; + } + "#, + ) + } + + #[test] + fn make_raw_string_with_escaped_works() { + check_assist( + make_raw_string, + r#" + fn f() { + let s = <|>"random\nstring"; + } + "#, + r#" + fn f() { + let s = <|>r"random\nstring"; + } + "#, + ) + } + + #[test] + fn make_raw_string_not_works() { + check_assist_not_applicable( + make_raw_string, + r#" + fn f() { + let s = <|>r"random string"; + } + "#, + ); + } + + #[test] + fn add_hash_target() { + check_assist_target( + add_hash, + r#" + fn f() { + let s = <|>r"random string"; + } + "#, + r#"r"random string""#, + ); + } + + #[test] + fn add_hash_works() { + check_assist( + add_hash, + r#" + fn f() { + let s = <|>r"random string"; + } + "#, + r##" + fn f() { + let s = <|>r#"random string"#; + } + "##, + ) + } + + #[test] + fn add_more_hash_works() { + check_assist( + add_hash, + r##" + fn f() { + let s = <|>r#"random"string"#; + } + "##, + r###" + fn f() { + let s = <|>r##"random"string"##; + } + "###, + ) + } + + #[test] + fn add_hash_not_works() { + check_assist_not_applicable( + add_hash, + r#" + fn f() { + let s = <|>"random string"; + } + "#, + ); + } + + #[test] + fn remove_hash_target() { + check_assist_target( + remove_hash, + r##" + fn f() { + let s = <|>r#"random string"#; + } + "##, + r##"r#"random string"#"##, + ); + } + + #[test] + fn remove_hash_works() { + check_assist( + remove_hash, + r##" + fn f() { + let s = <|>r#"random string"#; + } + "##, + r#" + fn f() { + let s = <|>r"random string"; + } + "#, + ) + } + + #[test] + fn remove_hash_with_quote_works() { + check_assist( + remove_hash, + r##" + fn f() { + let s = <|>r#"random"str"ing"#; + } + "##, + r#" + fn f() { + let s = <|>r"random\"str\"ing"; + } + "#, + ) + } + + #[test] + fn remove_more_hash_works() { + check_assist( + remove_hash, + r###" + fn f() { + let s = <|>r##"random string"##; + } + "###, + r##" + fn f() { + let s = <|>r#"random string"#; + } + "##, + ) + } + + #[test] + fn remove_hash_not_works() { + check_assist_not_applicable( + remove_hash, + r#" + fn f() { + let s = <|>"random string"; + } + "#, + ); + } + + #[test] + fn remove_hash_no_hash_not_works() { + check_assist_not_applicable( + remove_hash, + r#" + fn f() { + let s = <|>r"random string"; + } + "#, + ); + } + + #[test] + fn make_usual_string_target() { + check_assist_target( + make_usual_string, + r##" + fn f() { + let s = <|>r#"random string"#; + } + "##, + r##"r#"random string"#"##, + ); + } + + #[test] + fn make_usual_string_works() { + check_assist( + make_usual_string, + r##" + fn f() { + let s = <|>r#"random string"#; + } + "##, + r#" + fn f() { + let s = <|>"random string"; + } + "#, + ) + } + + #[test] + fn make_usual_string_with_quote_works() { + check_assist( + make_usual_string, + r##" + fn f() { + let s = <|>r#"random"str"ing"#; + } + "##, + r#" + fn f() { + let s = <|>"random\"str\"ing"; + } + "#, + ) + } + + #[test] + fn make_usual_string_more_hash_works() { + check_assist( + make_usual_string, + r###" + fn f() { + let s = <|>r##"random string"##; + } + "###, + r##" + fn f() { + let s = <|>"random string"; + } + "##, + ) + } + + #[test] + fn make_usual_string_not_works() { + check_assist_not_applicable( + make_usual_string, + r#" + fn f() { + let s = <|>"random string"; + } + "#, + ); + } +} diff --git a/crates/ra_tools/tests/cli.rs b/crates/ra_tools/tests/cli.rs index c672e578895..91b19c8f822 100644 --- a/crates/ra_tools/tests/cli.rs +++ b/crates/ra_tools/tests/cli.rs @@ -34,7 +34,7 @@ fn no_todo() { return; } let text = std::fs::read_to_string(e.path()).unwrap(); - if text.contains("TODO") { + if text.contains("TODO") || text.contains("TOOD") { panic!( "\nTODO markers should not be commited to the master branch,\n\ use FIXME instead\n\ From 43da23401dad3d708b91e61003e8503a61f57c14 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sun, 22 Sep 2019 23:43:37 +0300 Subject: [PATCH 3/3] remove obsolete TOOD I have no idea what I've meant to fix here :-( --- crates/ra_mbe/src/parser.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/ra_mbe/src/parser.rs b/crates/ra_mbe/src/parser.rs index 575f587cf3c..50b8011a909 100644 --- a/crates/ra_mbe/src/parser.rs +++ b/crates/ra_mbe/src/parser.rs @@ -142,7 +142,6 @@ fn is_boolean_literal(lit: &tt::Literal) -> bool { } } -///TOOD: impl for slice iter fn parse_repeat(src: &mut TtIter) -> Result<(Option, RepeatKind), ExpandError> { let mut separator = Separator::Puncts(SmallVec::new()); for tt in src {