<commit_before>// Feature: Postfix completion for `format`-like strings.
//
// `"Result {result} is {2 + 2}"` is expanded to the `"Result {} is {}", result, 2 + 2`.
//
// The following postfix snippets are available:
//
// - `format` -> `format!(...)`
// - `panic` -> `panic!(...)`
// - `println` -> `println!(...)`
// - `log`:
//   + `logd` -> `log::debug!(...)`
//   + `logt` -> `log::trace!(...)`
//   + `logi` -> `log::info!(...)`
//   + `logw` -> `log::warn!(...)`
//   + `loge` -> `log::error!(...)`

use crate::completion::{
    complete_postfix::postfix_snippet, completion_config::SnippetCap,
    completion_context::CompletionContext, completion_item::Completions,
};
use syntax::ast::{self, AstToken};

/// Mapping ("postfix completion item" => "macro to use")
static KINDS: &[(&str, &str)] = &[
    ("fmt", "format!"),
    ("panic", "panic!"),
    ("println", "println!"),
    ("logd", "log::debug!"),
    ("logt", "log::trace!"),
    ("logi", "log::info!"),
    ("logw", "log::warn!"),
    ("loge", "log::error!"),
];

pub(super) fn add_format_like_completions(
    acc: &mut Completions,
    ctx: &CompletionContext,
    dot_receiver: &ast::Expr,
    cap: SnippetCap,
    receiver_text: &ast::String,
) {
    let input = match string_literal_contents(receiver_text) {
        // It's not a string literal, do not parse input.
        Some(input) => input,
        None => return,
    };

    let mut parser = FormatStrParser::new(input);

    if parser.parse().is_ok() {
        for (label, macro_name) in KINDS {
            let snippet = parser.into_suggestion(macro_name);

            postfix_snippet(ctx, cap, &dot_receiver, label, macro_name, &snippet).add_to(acc);
        }
    }
}

/// Checks whether provided item is a string literal.
fn string_literal_contents(item: &ast::String) -> Option<String> {
    let item = item.text();
    if item.len() >= 2 && item.starts_with("\"") && item.ends_with("\"") {
        return Some(item[1..item.len() - 1].to_owned());
    }

    None
}

/// Parser for a format-like string. It is more allowing in terms of string contents,
/// as we expect variable placeholders to be filled with expressions.
#[derive(Debug)]
pub struct FormatStrParser {
    input: String,
    output: String,
    extracted_expressions: Vec<String>,
    state: State,
    parsed: bool,
}

#[derive(Debug, Clone, Copy, PartialEq)]
enum State {
    NotExpr,
    MaybeExpr,
    Expr,
    MaybeIncorrect,
    FormatOpts,
}

impl FormatStrParser {
    pub fn new(input: String) -> Self {
        Self {
            input: input.into(),
            output: String::new(),
            extracted_expressions: Vec::new(),
            state: State::NotExpr,
            parsed: false,
        }
    }

    pub fn parse(&mut self) -> Result<(), ()> {
        let mut current_expr = String::new();

        let mut placeholder_id = 1;

        // Count of open braces inside of an expression.
        // We assume that user knows what they're doing, thus we treat it like a correct pattern, e.g.
        // "{MyStruct { val_a: 0, val_b: 1 }}".
        let mut inexpr_open_count = 0;

        for chr in self.input.chars() {
            match (self.state, chr) {
                (State::NotExpr, '{') => {
                    self.output.push(chr);
                    self.state = State::MaybeExpr;
                }
                (State::NotExpr, '}') => {
                    self.output.push(chr);
                    self.state = State::MaybeIncorrect;
                }
                (State::NotExpr, _) => {
                    self.output.push(chr);
                }
                (State::MaybeIncorrect, '}') => {
                    // It's okay, we met "}}".
                    self.output.push(chr);
                    self.state = State::NotExpr;
                }
                (State::MaybeIncorrect, _) => {
                    // Error in the string.
                    return Err(());
                }
                (State::MaybeExpr, '{') => {
                    self.output.push(chr);
                    self.state = State::NotExpr;
                }
                (State::MaybeExpr, '}') => {
                    // This is an empty sequence '{}'. Replace it with placeholder.
                    self.output.push(chr);
                    self.extracted_expressions.push(format!("${}", placeholder_id));
                    placeholder_id += 1;
                    self.state = State::NotExpr;
                }
                (State::MaybeExpr, _) => {
                    current_expr.push(chr);
                    self.state = State::Expr;
                }
                (State::Expr, '}') => {
                    if inexpr_open_count == 0 {
                        self.output.push(chr);
                        self.extracted_expressions.push(current_expr.trim().into());
                        current_expr = String::new();
                        self.state = State::NotExpr;
                    } else {
                        // We're closing one brace met before inside of the expression.
                        current_expr.push(chr);
                        inexpr_open_count -= 1;
                    }
                }
                (State::Expr, ':') => {
                    if inexpr_open_count == 0 {
                        // We're outside of braces, thus assume that it's a specifier, like "{Some(value):?}"
                        self.output.push(chr);
                        self.extracted_expressions.push(current_expr.trim().into());
                        current_expr = String::new();
                        self.state = State::FormatOpts;
                    } else {
                        // We're inside of braced expression, assume that it's a struct field name/value delimeter.
                        current_expr.push(chr);
                    }
                }
                (State::Expr, '{') => {
                    current_expr.push(chr);
                    inexpr_open_count += 1;
                }
                (State::Expr, _) => {
                    current_expr.push(chr);
                }
                (State::FormatOpts, '}') => {
                    self.output.push(chr);
                    self.state = State::NotExpr;
                }
                (State::FormatOpts, _) => {
                    self.output.push(chr);
                }
            }
        }

        if self.state != State::NotExpr {
            return Err(());
        }

        self.parsed = true;
        Ok(())
    }

    pub fn into_suggestion(&self, macro_name: &str) -> String {
        assert!(self.parsed, "Attempt to get a suggestion from not parsed expression");

        let expressions_as_string = self.extracted_expressions.join(", ");
        format!(r#"{}("{}", {})"#, macro_name, self.output, expressions_as_string)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn format_str_parser() {
        let test_vector = &[
            ("no expressions", Some(("no expressions", vec![]))),
            ("{expr} is {2 + 2}", Some(("{} is {}", vec!["expr", "2 + 2"]))),
            ("{expr:?}", Some(("{:?}", vec!["expr"]))),
            ("{malformed", None),
            ("malformed}", None),
            ("{{correct", Some(("{{correct", vec![]))),
            ("correct}}", Some(("correct}}", vec![]))),
            ("{correct}}}", Some(("{}}}", vec!["correct"]))),
            ("{correct}}}}}", Some(("{}}}}}", vec!["correct"]))),
            ("{incorrect}}", None),
            ("placeholders {} {}", Some(("placeholders {} {}", vec!["$1", "$2"]))),
            ("mixed {} {2 + 2} {}", Some(("mixed {} {} {}", vec!["$1", "2 + 2", "$2"]))),
            (
                "{SomeStruct { val_a: 0, val_b: 1 }}",
                Some(("{}", vec!["SomeStruct { val_a: 0, val_b: 1 }"])),
            ),
            ("{expr:?} is {2.32f64:.5}", Some(("{:?} is {:.5}", vec!["expr", "2.32f64"]))),
            (
                "{SomeStruct { val_a: 0, val_b: 1 }:?}",
                Some(("{:?}", vec!["SomeStruct { val_a: 0, val_b: 1 }"])),
            ),
            ("{     2 + 2        }", Some(("{}", vec!["2 + 2"]))),
        ];

        for (input, output) in test_vector {
            let mut parser = FormatStrParser::new((*input).to_owned());
            let outcome = parser.parse();

            if let Some((result_str, result_args)) = output {
                assert!(
                    outcome.is_ok(),
                    "Outcome is error for input: {}, but the expected outcome is {:?}",
                    input,
                    output
                );
                assert_eq!(parser.output, *result_str);
                assert_eq!(&parser.extracted_expressions, result_args);
            } else {
                assert!(
                    outcome.is_err(),
                    "Outcome is OK for input: {}, but the expected outcome is error",
                    input
                );
            }
        }
    }

    #[test]
    fn test_into_suggestion() {
        let test_vector = &[
            ("println!", "{}", r#"println!("{}", $1)"#),
            (
                "log::info!",
                "{} {expr} {} {2 + 2}",
                r#"log::info!("{} {} {} {}", $1, expr, $2, 2 + 2)"#,
            ),
            ("format!", "{expr:?}", r#"format!("{:?}", expr)"#),
        ];

        for (kind, input, output) in test_vector {
            let mut parser = FormatStrParser::new((*input).to_owned());
            parser.parse().expect("Parsing must succeed");

            assert_eq!(&parser.into_suggestion(*kind), output);
        }
    }
}
<commit_msg>Use expect_test to make format_str_parser test more data-driven<commit_after>// Feature: Postfix completion for `format`-like strings.
//
// `"Result {result} is {2 + 2}"` is expanded to the `"Result {} is {}", result, 2 + 2`.
//
// The following postfix snippets are available:
//
// - `format` -> `format!(...)`
// - `panic` -> `panic!(...)`
// - `println` -> `println!(...)`
// - `log`:
//   + `logd` -> `log::debug!(...)`
//   + `logt` -> `log::trace!(...)`
//   + `logi` -> `log::info!(...)`
//   + `logw` -> `log::warn!(...)`
//   + `loge` -> `log::error!(...)`

use crate::completion::{
    complete_postfix::postfix_snippet, completion_config::SnippetCap,
    completion_context::CompletionContext, completion_item::Completions,
};
use syntax::ast::{self, AstToken};

/// Mapping ("postfix completion item" => "macro to use")
static KINDS: &[(&str, &str)] = &[
    ("fmt", "format!"),
    ("panic", "panic!"),
    ("println", "println!"),
    ("logd", "log::debug!"),
    ("logt", "log::trace!"),
    ("logi", "log::info!"),
    ("logw", "log::warn!"),
    ("loge", "log::error!"),
];

pub(super) fn add_format_like_completions(
    acc: &mut Completions,
    ctx: &CompletionContext,
    dot_receiver: &ast::Expr,
    cap: SnippetCap,
    receiver_text: &ast::String,
) {
    let input = match string_literal_contents(receiver_text) {
        // It's not a string literal, do not parse input.
        Some(input) => input,
        None => return,
    };

    let mut parser = FormatStrParser::new(input);

    if parser.parse().is_ok() {
        for (label, macro_name) in KINDS {
            let snippet = parser.into_suggestion(macro_name);

            postfix_snippet(ctx, cap, &dot_receiver, label, macro_name, &snippet).add_to(acc);
        }
    }
}

/// Checks whether provided item is a string literal.
fn string_literal_contents(item: &ast::String) -> Option<String> {
    let item = item.text();
    if item.len() >= 2 && item.starts_with("\"") && item.ends_with("\"") {
        return Some(item[1..item.len() - 1].to_owned());
    }

    None
}

/// Parser for a format-like string. It is more allowing in terms of string contents,
/// as we expect variable placeholders to be filled with expressions.
#[derive(Debug)]
pub struct FormatStrParser {
    input: String,
    output: String,
    extracted_expressions: Vec<String>,
    state: State,
    parsed: bool,
}

#[derive(Debug, Clone, Copy, PartialEq)]
enum State {
    NotExpr,
    MaybeExpr,
    Expr,
    MaybeIncorrect,
    FormatOpts,
}

impl FormatStrParser {
    pub fn new(input: String) -> Self {
        Self {
            input: input.into(),
            output: String::new(),
            extracted_expressions: Vec::new(),
            state: State::NotExpr,
            parsed: false,
        }
    }

    pub fn parse(&mut self) -> Result<(), ()> {
        let mut current_expr = String::new();

        let mut placeholder_id = 1;

        // Count of open braces inside of an expression.
        // We assume that user knows what they're doing, thus we treat it like a correct pattern, e.g.
        // "{MyStruct { val_a: 0, val_b: 1 }}".
        let mut inexpr_open_count = 0;

        for chr in self.input.chars() {
            match (self.state, chr) {
                (State::NotExpr, '{') => {
                    self.output.push(chr);
                    self.state = State::MaybeExpr;
                }
                (State::NotExpr, '}') => {
                    self.output.push(chr);
                    self.state = State::MaybeIncorrect;
                }
                (State::NotExpr, _) => {
                    self.output.push(chr);
                }
                (State::MaybeIncorrect, '}') => {
                    // It's okay, we met "}}".
                    self.output.push(chr);
                    self.state = State::NotExpr;
                }
                (State::MaybeIncorrect, _) => {
                    // Error in the string.
                    return Err(());
                }
                (State::MaybeExpr, '{') => {
                    self.output.push(chr);
                    self.state = State::NotExpr;
                }
                (State::MaybeExpr, '}') => {
                    // This is an empty sequence '{}'. Replace it with placeholder.
                    self.output.push(chr);
                    self.extracted_expressions.push(format!("${}", placeholder_id));
                    placeholder_id += 1;
                    self.state = State::NotExpr;
                }
                (State::MaybeExpr, _) => {
                    current_expr.push(chr);
                    self.state = State::Expr;
                }
                (State::Expr, '}') => {
                    if inexpr_open_count == 0 {
                        self.output.push(chr);
                        self.extracted_expressions.push(current_expr.trim().into());
                        current_expr = String::new();
                        self.state = State::NotExpr;
                    } else {
                        // We're closing one brace met before inside of the expression.
                        current_expr.push(chr);
                        inexpr_open_count -= 1;
                    }
                }
                (State::Expr, ':') => {
                    if inexpr_open_count == 0 {
                        // We're outside of braces, thus assume that it's a specifier, like "{Some(value):?}"
                        self.output.push(chr);
                        self.extracted_expressions.push(current_expr.trim().into());
                        current_expr = String::new();
                        self.state = State::FormatOpts;
                    } else {
                        // We're inside of braced expression, assume that it's a struct field name/value delimeter.
                        current_expr.push(chr);
                    }
                }
                (State::Expr, '{') => {
                    current_expr.push(chr);
                    inexpr_open_count += 1;
                }
                (State::Expr, _) => {
                    current_expr.push(chr);
                }
                (State::FormatOpts, '}') => {
                    self.output.push(chr);
                    self.state = State::NotExpr;
                }
                (State::FormatOpts, _) => {
                    self.output.push(chr);
                }
            }
        }

        if self.state != State::NotExpr {
            return Err(());
        }

        self.parsed = true;
        Ok(())
    }

    pub fn into_suggestion(&self, macro_name: &str) -> String {
        assert!(self.parsed, "Attempt to get a suggestion from not parsed expression");

        let expressions_as_string = self.extracted_expressions.join(", ");
        format!(r#"{}("{}", {})"#, macro_name, self.output, expressions_as_string)
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use expect_test::{expect, Expect};

    fn check(input: &str, expect: &Expect) {
        let mut parser = FormatStrParser::new((*input).to_owned());
        let outcome_repr = if parser.parse().is_ok() {
            // Parsing should be OK, expected repr is "string; expr_1, expr_2".
            if parser.extracted_expressions.is_empty() {
                parser.output
            } else {
                format!("{}; {}", parser.output, parser.extracted_expressions.join(", "))
            }
        } else {
            // Parsing should fail, expected repr is "-".
            "-".to_owned()
        };

        expect.assert_eq(&outcome_repr);
    }

    #[test]
    fn format_str_parser() {
        let test_vector = &[
            ("no expressions", expect![["no expressions"]]),
            ("{expr} is {2 + 2}", expect![["{} is {}; expr, 2 + 2"]]),
            ("{expr:?}", expect![["{:?}; expr"]]),
            ("{malformed", expect![["-"]]),
            ("malformed}", expect![["-"]]),
            ("{{correct", expect![["{{correct"]]),
            ("correct}}", expect![["correct}}"]]),
            ("{correct}}}", expect![["{}}}; correct"]]),
            ("{correct}}}}}", expect![["{}}}}}; correct"]]),
            ("{incorrect}}", expect![["-"]]),
            ("placeholders {} {}", expect![["placeholders {} {}; $1, $2"]]),
            ("mixed {} {2 + 2} {}", expect![["mixed {} {} {}; $1, 2 + 2, $2"]]),
            (
                "{SomeStruct { val_a: 0, val_b: 1 }}",
                expect![["{}; SomeStruct { val_a: 0, val_b: 1 }"]],
            ),
            ("{expr:?} is {2.32f64:.5}", expect![["{:?} is {:.5}; expr, 2.32f64"]]),
            (
                "{SomeStruct { val_a: 0, val_b: 1 }:?}",
                expect![["{:?}; SomeStruct { val_a: 0, val_b: 1 }"]],
            ),
            ("{     2 + 2        }", expect![["{}; 2 + 2"]]),
        ];

        for (input, output) in test_vector {
            check(input, output)
        }
    }

    #[test]
    fn test_into_suggestion() {
        let test_vector = &[
            ("println!", "{}", r#"println!("{}", $1)"#),
            (
                "log::info!",
                "{} {expr} {} {2 + 2}",
                r#"log::info!("{} {} {} {}", $1, expr, $2, 2 + 2)"#,
            ),
            ("format!", "{expr:?}", r#"format!("{:?}", expr)"#),
        ];

        for (kind, input, output) in test_vector {
            let mut parser = FormatStrParser::new((*input).to_owned());
            parser.parse().expect("Parsing must succeed");

            assert_eq!(&parser.into_suggestion(*kind), output);
        }
    }
}
<|endoftext|>


<commit_before>use ra_syntax::{
    ast::{self, AstNode},
    SyntaxKind::{WHITESPACE, BLOCK_EXPR},
    SyntaxNode, TextUnit,
};

use crate::assists::{AssistCtx, Assist};

pub fn introduce_variable<'a>(ctx: AssistCtx) -> Option<Assist> {
    let node = ctx.covering_node();
    let expr = node.ancestors().filter_map(ast::Expr::cast).next()?;

    let anchor_stmt = anchor_stmt(expr)?;
    let indent = anchor_stmt.prev_sibling()?;
    if indent.kind() != WHITESPACE {
        return None;
    }
    ctx.build("introduce variable", move |edit| {
        let mut buf = String::new();

        buf.push_str("let var_name = ");
        expr.syntax().text().push_to(&mut buf);
        let is_full_stmt = if let Some(expr_stmt) = ast::ExprStmt::cast(anchor_stmt) {
            Some(expr.syntax()) == expr_stmt.expr().map(|e| e.syntax())
        } else {
            false
        };
        if is_full_stmt {
            if expr.syntax().kind() == BLOCK_EXPR {
                buf.push_str(";");
            }
            edit.replace(expr.syntax().range(), buf);
        } else {
            buf.push_str(";");
            indent.text().push_to(&mut buf);
            edit.replace(expr.syntax().range(), "var_name".to_string());
            edit.insert(anchor_stmt.range().start(), buf);
        }
        edit.set_cursor(anchor_stmt.range().start() + TextUnit::of_str("let "));
    })
}

/// Statement or last in the block expression, which will follow
/// the freshly introduced var.
fn anchor_stmt(expr: &ast::Expr) -> Option<&SyntaxNode> {
    expr.syntax().ancestors().find(|&node| {
        if ast::Stmt::cast(node).is_some() {
            return true;
        }
        if let Some(expr) = node
            .parent()
            .and_then(ast::Block::cast)
            .and_then(|it| it.expr())
        {
            if expr.syntax() == node {
                return true;
            }
        }
        false
    })
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::assists::check_assist_range;

    #[test]
    fn test_introduce_var_simple() {
        check_assist_range(
            introduce_variable,
            "
fn foo() {
    foo(<|>1 + 1<|>);
}",
            "
fn foo() {
    let <|>var_name = 1 + 1;
    foo(var_name);
}",
        );
    }

    #[test]
    fn test_introduce_var_expr_stmt() {
        check_assist_range(
            introduce_variable,
            "
fn foo() {
    <|>1 + 1<|>;
}",
            "
fn foo() {
    let <|>var_name = 1 + 1;
}",
        );
    }

    #[test]
    fn test_introduce_var_part_of_expr_stmt() {
        check_assist_range(
            introduce_variable,
            "
fn foo() {
    <|>1<|> + 1;
}",
            "
fn foo() {
    let <|>var_name = 1;
    var_name + 1;
}",
        );
    }

    #[test]
    fn test_introduce_var_last_expr() {
        check_assist_range(
            introduce_variable,
            "
fn foo() {
    bar(<|>1 + 1<|>)
}",
            "
fn foo() {
    let <|>var_name = 1 + 1;
    bar(var_name)
}",
        );
    }

    #[test]
    fn test_introduce_var_last_full_expr() {
        check_assist_range(
            introduce_variable,
            "
fn foo() {
    <|>bar(1 + 1)<|>
}",
            "
fn foo() {
    let <|>var_name = bar(1 + 1);
    var_name
}",
        );
    }

    #[test]
    fn test_introduce_var_block_expr_second_to_last() {
        check_assist_range(
            introduce_variable,
            "
fn foo() {
    <|>{ let x = 0; x }<|>
    something_else();
}",
            "
fn foo() {
    let <|>var_name = { let x = 0; x };
    something_else();
}",
        );
    }
}
<commit_msg>add semi only if it wasn't present before or after<commit_after>use ra_syntax::{
    ast::{self, AstNode},
    SyntaxKind::{WHITESPACE, SEMI},
    SyntaxNode, TextUnit,
};

use crate::assists::{AssistCtx, Assist};

pub fn introduce_variable<'a>(ctx: AssistCtx) -> Option<Assist> {
    let node = ctx.covering_node();
    let expr = node.ancestors().filter_map(ast::Expr::cast).next()?;

    let anchor_stmt = anchor_stmt(expr)?;
    let indent = anchor_stmt.prev_sibling()?;
    if indent.kind() != WHITESPACE {
        return None;
    }
    ctx.build("introduce variable", move |edit| {
        let mut buf = String::new();

        buf.push_str("let var_name = ");
        expr.syntax().text().push_to(&mut buf);
        let is_full_stmt = if let Some(expr_stmt) = ast::ExprStmt::cast(anchor_stmt) {
            Some(expr.syntax()) == expr_stmt.expr().map(|e| e.syntax())
        } else {
            false
        };
        if is_full_stmt {
            if let Some(last_child) = expr.syntax().last_child() {
                if last_child.kind() != SEMI && !is_semi_right_after(expr.syntax()) {
                    buf.push_str(";");
                }
            }
            edit.replace(expr.syntax().range(), buf);
        } else {
            buf.push_str(";");
            indent.text().push_to(&mut buf);
            edit.replace(expr.syntax().range(), "var_name".to_string());
            edit.insert(anchor_stmt.range().start(), buf);
        }
        edit.set_cursor(anchor_stmt.range().start() + TextUnit::of_str("let "));
    })
}

/// Statement or last in the block expression, which will follow
/// the freshly introduced var.
fn anchor_stmt(expr: &ast::Expr) -> Option<&SyntaxNode> {
    expr.syntax().ancestors().find(|&node| {
        if ast::Stmt::cast(node).is_some() {
            return true;
        }
        if let Some(expr) = node
            .parent()
            .and_then(ast::Block::cast)
            .and_then(|it| it.expr())
        {
            if expr.syntax() == node {
                return true;
            }
        }
        false
    })
}

fn is_semi_right_after(node: &SyntaxNode) -> bool {
    let mut node = node;
    loop {
        if let Some(next) = node.next_sibling() {
            if next.kind() == WHITESPACE {
                node = next;
                continue;
            }
            return next.kind() == SEMI;
        }
        return false;
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::assists::check_assist_range;

    #[test]
    fn test_introduce_var_simple() {
        check_assist_range(
            introduce_variable,
            "
fn foo() {
    foo(<|>1 + 1<|>);
}",
            "
fn foo() {
    let <|>var_name = 1 + 1;
    foo(var_name);
}",
        );
    }

    #[test]
    fn test_introduce_var_expr_stmt() {
        check_assist_range(
            introduce_variable,
            "
fn foo() {
    <|>1 + 1<|>;
}",
            "
fn foo() {
    let <|>var_name = 1 + 1;
}",
        );
    }

    #[test]
    fn test_introduce_var_part_of_expr_stmt() {
        check_assist_range(
            introduce_variable,
            "
fn foo() {
    <|>1<|> + 1;
}",
            "
fn foo() {
    let <|>var_name = 1;
    var_name + 1;
}",
        );
    }

    #[test]
    fn test_introduce_var_last_expr() {
        check_assist_range(
            introduce_variable,
            "
fn foo() {
    bar(<|>1 + 1<|>)
}",
            "
fn foo() {
    let <|>var_name = 1 + 1;
    bar(var_name)
}",
        );
    }

    #[test]
    fn test_introduce_var_last_full_expr() {
        check_assist_range(
            introduce_variable,
            "
fn foo() {
    <|>bar(1 + 1)<|>
}",
            "
fn foo() {
    let <|>var_name = bar(1 + 1);
    var_name
}",
        );
    }

    #[test]
    fn test_introduce_var_block_expr_second_to_last() {
        check_assist_range(
            introduce_variable,
            "
fn foo() {
    <|>{ let x = 0; x }<|>
    something_else();
}",
            "
fn foo() {
    let <|>var_name = { let x = 0; x };
    something_else();
}",
        );
    }
}
<|endoftext|>


<commit_before>//! The Rust parser and macro expander.
//!
//! # Note
//!
//! This API is completely unstable and subject to change.

#![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
       test(attr(deny(warnings))))]

#![feature(box_syntax)]
#![feature(const_fn)]
#![feature(const_transmute)]
#![feature(crate_visibility_modifier)]
#![feature(label_break_value)]
#![feature(nll)]
#![feature(try_trait)]
#![feature(slice_patterns)]
#![feature(unicode_internals)]

#![recursion_limit="256"]

pub use errors;
use rustc_data_structures::sync::Lock;
use rustc_index::bit_set::GrowableBitSet;
pub use rustc_data_structures::thin_vec::ThinVec;
use ast::AttrId;
use syntax_pos::edition::Edition;

#[cfg(test)]
mod tests;

pub const MACRO_ARGUMENTS: Option<&'static str> = Some("macro arguments");

// A variant of 'panictry!' that works on a Vec<Diagnostic> instead of a single DiagnosticBuilder.
macro_rules! panictry_buffer {
    ($handler:expr, $e:expr) => ({
        use std::result::Result::{Ok, Err};
        use errors::FatalError;
        match $e {
            Ok(e) => e,
            Err(errs) => {
                for e in errs {
                    $handler.emit_diagnostic(&e);
                }
                FatalError.raise()
            }
        }
    })
}

#[macro_export]
macro_rules! unwrap_or {
    ($opt:expr, $default:expr) => {
        match $opt {
            Some(x) => x,
            None => $default,
        }
    }
}

pub struct Globals {
    used_attrs: Lock<GrowableBitSet<AttrId>>,
    known_attrs: Lock<GrowableBitSet<AttrId>>,
    syntax_pos_globals: syntax_pos::Globals,
}

impl Globals {
    fn new(edition: Edition) -> Globals {
        Globals {
            // We have no idea how many attributes their will be, so just
            // initiate the vectors with 0 bits. We'll grow them as necessary.
            used_attrs: Lock::new(GrowableBitSet::new_empty()),
            known_attrs: Lock::new(GrowableBitSet::new_empty()),
            syntax_pos_globals: syntax_pos::Globals::new(edition),
        }
    }
}

pub fn with_globals<F, R>(edition: Edition, f: F) -> R
    where F: FnOnce() -> R
{
    let globals = Globals::new(edition);
    GLOBALS.set(&globals, || {
        syntax_pos::GLOBALS.set(&globals.syntax_pos_globals, f)
    })
}

pub fn with_default_globals<F, R>(f: F) -> R
    where F: FnOnce() -> R
{
    with_globals(edition::DEFAULT_EDITION, f)
}

scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals);

#[macro_use]
pub mod diagnostics {
    #[macro_use]
    pub mod macros;
}

pub mod error_codes;

pub mod util {
    pub mod lev_distance;
    pub mod node_count;
    pub mod parser;
    pub mod map_in_place;
}

pub mod json;

pub mod ast;
pub mod attr;
pub mod source_map;
#[macro_use]
pub mod config;
pub mod entry;
pub mod feature_gate;
pub mod mut_visit;
pub mod parse;
pub mod ptr;
pub mod show_span;
pub use syntax_pos::edition;
pub use syntax_pos::symbol;
pub mod sess;
pub mod tokenstream;
pub mod visit;

pub mod print {
    pub mod pp;
    pub mod pprust;
    mod helpers;
}

pub mod early_buffered_lints;
<commit_msg>typo fix<commit_after>//! The Rust parser and macro expander.
//!
//! # Note
//!
//! This API is completely unstable and subject to change.

#![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
       test(attr(deny(warnings))))]

#![feature(box_syntax)]
#![feature(const_fn)]
#![feature(const_transmute)]
#![feature(crate_visibility_modifier)]
#![feature(label_break_value)]
#![feature(nll)]
#![feature(try_trait)]
#![feature(slice_patterns)]
#![feature(unicode_internals)]

#![recursion_limit="256"]

pub use errors;
use rustc_data_structures::sync::Lock;
use rustc_index::bit_set::GrowableBitSet;
pub use rustc_data_structures::thin_vec::ThinVec;
use ast::AttrId;
use syntax_pos::edition::Edition;

#[cfg(test)]
mod tests;

pub const MACRO_ARGUMENTS: Option<&'static str> = Some("macro arguments");

// A variant of 'panictry!' that works on a Vec<Diagnostic> instead of a single DiagnosticBuilder.
macro_rules! panictry_buffer {
    ($handler:expr, $e:expr) => ({
        use std::result::Result::{Ok, Err};
        use errors::FatalError;
        match $e {
            Ok(e) => e,
            Err(errs) => {
                for e in errs {
                    $handler.emit_diagnostic(&e);
                }
                FatalError.raise()
            }
        }
    })
}

#[macro_export]
macro_rules! unwrap_or {
    ($opt:expr, $default:expr) => {
        match $opt {
            Some(x) => x,
            None => $default,
        }
    }
}

pub struct Globals {
    used_attrs: Lock<GrowableBitSet<AttrId>>,
    known_attrs: Lock<GrowableBitSet<AttrId>>,
    syntax_pos_globals: syntax_pos::Globals,
}

impl Globals {
    fn new(edition: Edition) -> Globals {
        Globals {
            // We have no idea how many attributes there will be, so just
            // initiate the vectors with 0 bits. We'll grow them as necessary.
            used_attrs: Lock::new(GrowableBitSet::new_empty()),
            known_attrs: Lock::new(GrowableBitSet::new_empty()),
            syntax_pos_globals: syntax_pos::Globals::new(edition),
        }
    }
}

pub fn with_globals<F, R>(edition: Edition, f: F) -> R
    where F: FnOnce() -> R
{
    let globals = Globals::new(edition);
    GLOBALS.set(&globals, || {
        syntax_pos::GLOBALS.set(&globals.syntax_pos_globals, f)
    })
}

pub fn with_default_globals<F, R>(f: F) -> R
    where F: FnOnce() -> R
{
    with_globals(edition::DEFAULT_EDITION, f)
}

scoped_tls::scoped_thread_local!(pub static GLOBALS: Globals);

#[macro_use]
pub mod diagnostics {
    #[macro_use]
    pub mod macros;
}

pub mod error_codes;

pub mod util {
    pub mod lev_distance;
    pub mod node_count;
    pub mod parser;
    pub mod map_in_place;
}

pub mod json;

pub mod ast;
pub mod attr;
pub mod source_map;
#[macro_use]
pub mod config;
pub mod entry;
pub mod feature_gate;
pub mod mut_visit;
pub mod parse;
pub mod ptr;
pub mod show_span;
pub use syntax_pos::edition;
pub use syntax_pos::symbol;
pub mod sess;
pub mod tokenstream;
pub mod visit;

pub mod print {
    pub mod pp;
    pub mod pprust;
    mod helpers;
}

pub mod early_buffered_lints;
<|endoftext|>


<commit_before>use futures::{SinkExt, StreamExt};
use log::*;
use tokio_tungstenite::{connect_async, tungstenite::Result};
use url::Url;

const AGENT: &str = "Tungstenite";

async fn get_case_count() -> Result<u32> {
    let (mut socket, _) =
        connect_async(Url::parse("ws://localhost:9001/getCaseCount").unwrap()).await?;
    let msg = socket.next().await.unwrap()?;
    socket.close(None).await?;
    Ok(msg.into_text()?.parse::<u32>().unwrap())
}

async fn update_reports() -> Result<()> {
    let (mut socket, _) = connect_async(
        Url::parse(&format!(
            "ws://localhost:9001/updateReports?agent={}",
            AGENT
        ))
        .unwrap(),
    )
    .await?;
    socket.close(None).await?;
    Ok(())
}

async fn run_test(case: u32) {
    info!("Running test case {}", case);
    let case_url = Url::parse(&format!(
        "ws://localhost:9001/runCase?case={}&agent={}",
        case, AGENT
    ))
    .unwrap();

    let (mut ws_stream, _) = connect_async(case_url).await.expect("Connect error");
    while let Some(msg) = ws_stream.next().await {
        let msg = msg.expect("Failed to get message");
        if msg.is_text() || msg.is_binary() {
            ws_stream.send(msg).await.expect("Write error");
        }
    }
}

#[tokio::main]
async fn main() {
    env_logger::init();

    let total = get_case_count().await.unwrap();

    for case in 1..=total {
        run_test(case).await
    }

    update_reports().await.unwrap();
}
<commit_msg>autobahn: don't panic in client<commit_after>use futures::{SinkExt, StreamExt};
use log::*;
use tokio_tungstenite::{connect_async, tungstenite::Result};
use url::Url;

const AGENT: &str = "Tungstenite";

async fn get_case_count() -> Result<u32> {
    let (mut socket, _) = connect_async(
        Url::parse("ws://localhost:9001/getCaseCount").expect("Can't connect to case count URL"),
    )
    .await?;
    let msg = socket.next().await.expect("Can't fetch case count")?;
    socket.close(None).await?;
    Ok(msg
        .into_text()?
        .parse::<u32>()
        .expect("Can't parse case count"))
}

async fn update_reports() -> Result<()> {
    let (mut socket, _) = connect_async(
        Url::parse(&format!(
            "ws://localhost:9001/updateReports?agent={}",
            AGENT
        ))
        .expect("Can't update reports"),
    )
    .await?;
    socket.close(None).await?;
    Ok(())
}

async fn run_test(case: u32) -> Result<()> {
    info!("Running test case {}", case);
    let case_url = Url::parse(&format!(
        "ws://localhost:9001/runCase?case={}&agent={}",
        case, AGENT
    ))
    .expect("Bad testcase URL");

    let (mut ws_stream, _) = connect_async(case_url).await?;
    while let Some(msg) = ws_stream.next().await {
        let msg = msg?;
        if msg.is_text() || msg.is_binary() {
            ws_stream.send(msg).await?;
        }
    }

    Ok(())
}

#[tokio::main]
async fn main() {
    env_logger::init();

    let total = get_case_count().await.expect("Error getting case count");

    for case in 1..=total {
        if let Err(err) = run_test(case).await {
            error!("Testcase failed: {}", err);
        }
    }

    update_reports().await.expect("Error updating reports");
}
<|endoftext|>


<commit_before>extern crate pretty_assertions;
extern crate serde_json;
extern crate toml_edit;

use pretty_assertions::assert_eq;
use serde_json::Map as JsonMap;
use serde_json::Value as Json;

use toml_edit::{Document, Item, Iter, Value};

fn pair_to_json((key, value): (&str, Item)) -> (String, Json) {
    fn typed_json(s: &str, json: Json) -> Json {
        let mut map = JsonMap::new();
        map.insert("type".to_owned(), Json::String(s.into()));
        map.insert("value".to_owned(), json);
        Json::Object(map)
    }
    fn value_to_json(value: &Value) -> Json {
        match *value {
            Value::String(ref s) => typed_json("string", Json::String(s.value().clone())),
            Value::Integer(ref i) => typed_json("integer", Json::String(format!("{}", i.value()))),
            Value::Float(ref f) => typed_json("float", Json::String(format!("{}", f.value()))),
            Value::Boolean(ref b) => typed_json("bool", Json::String(b.raw().into())),
            Value::DateTime(ref d) => typed_json("datetime", Json::String(d.raw().into())),
            Value::Array(ref a) => {
                let json = Json::Array(a.iter().map(value_to_json).collect::<Vec<_>>());
                typed_json("array", json)
            }
            Value::InlineTable(ref t) => {
                to_json(Box::new(t.iter().map(|(k, v)| (k, Item::Value(v.clone())))))
            }
        }
    }
    let json = match value {
        Item::Value(ref v) => value_to_json(v),
        Item::ArrayOfTables(ref arr) => Json::Array(
            arr.iter()
                .map(|t| to_json(iter_to_owned(t.iter())))
                .collect::<Vec<_>>(),
        ),
        Item::Table(ref table) => to_json(iter_to_owned(table.iter())),
        Item::None => Json::Null,
    };
    (key.to_owned(), json)
}

fn iter_to_owned(iter: Iter) -> OwnedIter {
    Box::new(iter.map(|(k, v)| (k, v.clone())))
}

type OwnedIter<'s> = Box<dyn Iterator<Item = (&'s str, Item)> + 's>;

fn to_json(iter: OwnedIter) -> Json {
    Json::Object(iter.map(pair_to_json).collect())
}

fn run(json: &str, toml: &str) {
    let doc = toml.parse::<Document>();
    assert!(doc.is_ok());
    let doc = doc.unwrap();

    let json: Json = serde_json::from_str(json).unwrap();
    let toml_json = to_json(iter_to_owned(doc.iter()));
    // compare structure with jsons
    assert_eq!(json, toml_json);

    // check round-trip equality
    let toml = doc.to_string();
    let doc = toml.parse::<Document>();
    assert!(doc.is_ok());
    let doc = doc.unwrap();
    assert_eq!(doc.to_string(), toml);
}

macro_rules! t(
    ($name:ident, $json:expr, $toml:expr) => (
        #[test]
        fn $name() {
            run(include_str!($json),
                include_str!($toml));
        }
    )
);

#[test]
fn table_reordering() {
    let toml = r#"
[[bin]] # bin 1
[a.'b'.c.e]
[a]
[other.table]
[[bin]] # bin 2
[a.b.c.d]
[a."b".c]
[[bin]] # bin 3
"#;
    let expected_original_order = r#"
[[bin]] # bin 1
[a.'b'.c.e]
[a]
[other.table]
[[bin]] # bin 2
[a.'b'.c.d]
[a.'b'.c]
[[bin]] # bin 3
"#;
    let expected = r#"
[[bin]] # bin 1
[[bin]] # bin 2
[[bin]] # bin 3
[a]
[a.'b'.c]
[a.'b'.c.e]
[a.'b'.c.d]
[other.table]
"#;
    let doc = toml.parse::<Document>();
    assert!(doc.is_ok());
    let doc = doc.unwrap();

    assert_eq!(
        doc.to_string_in_original_order().unwrap(),
        expected_original_order
    );
    assert_eq!(doc.to_string(), expected);
}

t!(
    test_array_empty,
    "fixtures/valid/array-empty.json",
    "fixtures/valid/array-empty.toml"
);
t!(
    test_array_nopspaces,
    "fixtures/valid/array-nospaces.json",
    "fixtures/valid/array-nospaces.toml"
);
t!(
    test_arrays_hetergeneous,
    "fixtures/valid/arrays-hetergeneous.json",
    "fixtures/valid/arrays-hetergeneous.toml"
);
t!(
    test_arrays,
    "fixtures/valid/arrays.json",
    "fixtures/valid/arrays.toml"
);
t!(
    test_arrays_nested,
    "fixtures/valid/arrays-nested.json",
    "fixtures/valid/arrays-nested.toml"
);
t!(
    test_bool,
    "fixtures/valid/bool.json",
    "fixtures/valid/bool.toml"
);
t!(
    test_comment_at_eof2,
    "fixtures/valid/comments-at-eof2.json",
    "fixtures/valid/comments-at-eof2.toml"
);
t!(
    test_comment_at_eof,
    "fixtures/valid/comments-at-eof.json",
    "fixtures/valid/comments-at-eof.toml"
);
t!(
    test_comments_everywhere,
    "fixtures/valid/comments-everywhere.json",
    "fixtures/valid/comments-everywhere.toml"
);
t!(
    test_datetime,
    "fixtures/valid/datetime.json",
    "fixtures/valid/datetime.toml"
);
t!(
    test_empty,
    "fixtures/valid/empty.json",
    "fixtures/valid/empty.toml"
);
t!(
    test_example,
    "fixtures/valid/example.json",
    "fixtures/valid/example.toml"
);
t!(
    test_float_exponent,
    "fixtures/valid/float-exponent.json",
    "fixtures/valid/float-exponent.toml"
);
t!(
    test_float,
    "fixtures/valid/float.json",
    "fixtures/valid/float.toml"
);
t!(
    test_float_underscore,
    "fixtures/valid/float-underscore.json",
    "fixtures/valid/float-underscore.toml"
);
t!(
    test_implicit_and_explicit_after,
    "fixtures/valid/implicit-and-explicit-after.json",
    "fixtures/valid/implicit-and-explicit-after.toml"
);
t!(
    test_implicit_and_explicit_before,
    "fixtures/valid/implicit-and-explicit-before.json",
    "fixtures/valid/implicit-and-explicit-before.toml"
);
t!(
    test_implicit_groups,
    "fixtures/valid/implicit-groups.json",
    "fixtures/valid/implicit-groups.toml"
);
t!(
    test_inline_table,
    "fixtures/valid/inline-table.json",
    "fixtures/valid/inline-table.toml"
);
t!(
    test_integer,
    "fixtures/valid/integer.json",
    "fixtures/valid/integer.toml"
);
t!(
    test_integer_underscore,
    "fixtures/valid/integer-underscore.json",
    "fixtures/valid/integer-underscore.toml"
);
t!(
    test_keys_equal_nospace,
    "fixtures/valid/key-equals-nospace.json",
    "fixtures/valid/key-equals-nospace.toml"
);
t!(
    test_key_numeric,
    "fixtures/valid/key-numeric.json",
    "fixtures/valid/key-numeric.toml"
);
t!(
    test_key_space,
    "fixtures/valid/key-space.json",
    "fixtures/valid/key-space.toml"
);
t!(
    test_key_special_chars,
    "fixtures/valid/key-special-chars.json",
    "fixtures/valid/key-special-chars.toml"
);
t!(
    test_long_float,
    "fixtures/valid/long-float.json",
    "fixtures/valid/long-float.toml"
);
t!(
    test_long_integer,
    "fixtures/valid/long-integer.json",
    "fixtures/valid/long-integer.toml"
);
t!(
    test_multiline_string,
    "fixtures/valid/multiline-string.json",
    "fixtures/valid/multiline-string.toml"
);
t!(
    test_raw_multiline_string,
    "fixtures/valid/raw-multiline-string.json",
    "fixtures/valid/raw-multiline-string.toml"
);
t!(
    test_raw_string,
    "fixtures/valid/raw-string.json",
    "fixtures/valid/raw-string.toml"
);
t!(
    test_string_empty,
    "fixtures/valid/string-empty.json",
    "fixtures/valid/string-empty.toml"
);
t!(
    test_string_escapes,
    "fixtures/valid/string-escapes.json",
    "fixtures/valid/string-escapes.toml"
);
t!(
    test_string_nl,
    "fixtures/valid/string-nl.json",
    "fixtures/valid/string-nl.toml"
);
t!(
    test_string_simple,
    "fixtures/valid/string-simple.json",
    "fixtures/valid/string-simple.toml"
);
t!(
    test_string_with_pound,
    "fixtures/valid/string-with-pound.json",
    "fixtures/valid/string-with-pound.toml"
);
t!(
    test_table_array_implicit,
    "fixtures/valid/table-array-implicit.json",
    "fixtures/valid/table-array-implicit.toml"
);
t!(
    test_table_array_many,
    "fixtures/valid/table-array-many.json",
    "fixtures/valid/table-array-many.toml"
);
t!(
    test_table_array_nest,
    "fixtures/valid/table-array-nest.json",
    "fixtures/valid/table-array-nest.toml"
);
t!(
    test_array_one,
    "fixtures/valid/table-array-one.json",
    "fixtures/valid/table-array-one.toml"
);
t!(
    test_table_empty,
    "fixtures/valid/table-empty.json",
    "fixtures/valid/table-empty.toml"
);
t!(
    test_table_no_eol,
    "fixtures/valid/table-no-eol.json",
    "fixtures/valid/table-no-eol.toml"
);
t!(
    test_table_sub_empty,
    "fixtures/valid/table-sub-empty.json",
    "fixtures/valid/table-sub-empty.toml"
);
t!(
    test_whitespace,
    "fixtures/valid/table-whitespace.json",
    "fixtures/valid/table-whitespace.toml"
);
t!(
    test_table_with_literal_string,
    "fixtures/valid/table-with-literal-string.json",
    "fixtures/valid/table-with-literal-string.toml"
);
t!(
    test_table_with_poung,
    "fixtures/valid/table-with-pound.json",
    "fixtures/valid/table-with-pound.toml"
);
t!(
    test_table_with_single_quotes,
    "fixtures/valid/table-with-single-quotes.json",
    "fixtures/valid/table-with-single-quotes.toml"
);
t!(
    test_unicode_escape,
    "fixtures/valid/unicode-escape.json",
    "fixtures/valid/unicode-escape.toml"
);
t!(
    test_unicode_literal,
    "fixtures/valid/unicode-literal.json",
    "fixtures/valid/unicode-literal.toml"
);
t!(
    test_windows_path,
    "fixtures/valid/windows-path.json",
    "fixtures/valid/windows-path.toml"
);
<commit_msg>split out key unification test from table reordering<commit_after>extern crate pretty_assertions;
extern crate serde_json;
extern crate toml_edit;

use pretty_assertions::assert_eq;
use serde_json::Map as JsonMap;
use serde_json::Value as Json;

use toml_edit::{Document, Item, Iter, Value};

fn pair_to_json((key, value): (&str, Item)) -> (String, Json) {
    fn typed_json(s: &str, json: Json) -> Json {
        let mut map = JsonMap::new();
        map.insert("type".to_owned(), Json::String(s.into()));
        map.insert("value".to_owned(), json);
        Json::Object(map)
    }
    fn value_to_json(value: &Value) -> Json {
        match *value {
            Value::String(ref s) => typed_json("string", Json::String(s.value().clone())),
            Value::Integer(ref i) => typed_json("integer", Json::String(format!("{}", i.value()))),
            Value::Float(ref f) => typed_json("float", Json::String(format!("{}", f.value()))),
            Value::Boolean(ref b) => typed_json("bool", Json::String(b.raw().into())),
            Value::DateTime(ref d) => typed_json("datetime", Json::String(d.raw().into())),
            Value::Array(ref a) => {
                let json = Json::Array(a.iter().map(value_to_json).collect::<Vec<_>>());
                typed_json("array", json)
            }
            Value::InlineTable(ref t) => {
                to_json(Box::new(t.iter().map(|(k, v)| (k, Item::Value(v.clone())))))
            }
        }
    }
    let json = match value {
        Item::Value(ref v) => value_to_json(v),
        Item::ArrayOfTables(ref arr) => Json::Array(
            arr.iter()
                .map(|t| to_json(iter_to_owned(t.iter())))
                .collect::<Vec<_>>(),
        ),
        Item::Table(ref table) => to_json(iter_to_owned(table.iter())),
        Item::None => Json::Null,
    };
    (key.to_owned(), json)
}

fn iter_to_owned(iter: Iter) -> OwnedIter {
    Box::new(iter.map(|(k, v)| (k, v.clone())))
}

type OwnedIter<'s> = Box<dyn Iterator<Item = (&'s str, Item)> + 's>;

fn to_json(iter: OwnedIter) -> Json {
    Json::Object(iter.map(pair_to_json).collect())
}

fn run(json: &str, toml: &str) {
    let doc = toml.parse::<Document>();
    assert!(doc.is_ok());
    let doc = doc.unwrap();

    let json: Json = serde_json::from_str(json).unwrap();
    let toml_json = to_json(iter_to_owned(doc.iter()));
    // compare structure with jsons
    assert_eq!(json, toml_json);

    // check round-trip equality
    let toml = doc.to_string();
    let doc = toml.parse::<Document>();
    assert!(doc.is_ok());
    let doc = doc.unwrap();
    assert_eq!(doc.to_string(), toml);
}

macro_rules! t(
    ($name:ident, $json:expr, $toml:expr) => (
        #[test]
        fn $name() {
            run(include_str!($json),
                include_str!($toml));
        }
    )
);

#[test]
fn test_table_reordering() {
    let toml = r#"
[[bin]] # bin 1
[a.b.c.e]
[a]
[other.table]
[[bin]] # bin 2
[a.b.c.d]
[a.b.c]
[[bin]] # bin 3
"#;
    let expected = r#"
[[bin]] # bin 1
[[bin]] # bin 2
[[bin]] # bin 3
[a]
[a.b.c]
[a.b.c.e]
[a.b.c.d]
[other.table]
"#;
    let doc = toml.parse::<Document>();
    assert!(doc.is_ok());
    let doc = doc.unwrap();

    assert_eq!(doc.to_string(), expected);
    assert_eq!(doc.to_string_in_original_order().unwrap(), toml);
}

#[test]
fn test_key_unification() {
    let toml = r#"
[a]
[a.'b'.c]
[a."b".c.e]
[a.b.c.d]
"#;
    let expected = r#"
[a]
[a.'b'.c]
[a.'b'.c.e]
[a.'b'.c.d]
"#;
    let doc = toml.parse::<Document>();
    assert!(doc.is_ok());
    let doc = doc.unwrap();

    assert_eq!(doc.to_string(), expected);
    assert_eq!(doc.to_string_in_original_order().unwrap(), expected);
}

t!(
    test_array_empty,
    "fixtures/valid/array-empty.json",
    "fixtures/valid/array-empty.toml"
);
t!(
    test_array_nopspaces,
    "fixtures/valid/array-nospaces.json",
    "fixtures/valid/array-nospaces.toml"
);
t!(
    test_arrays_hetergeneous,
    "fixtures/valid/arrays-hetergeneous.json",
    "fixtures/valid/arrays-hetergeneous.toml"
);
t!(
    test_arrays,
    "fixtures/valid/arrays.json",
    "fixtures/valid/arrays.toml"
);
t!(
    test_arrays_nested,
    "fixtures/valid/arrays-nested.json",
    "fixtures/valid/arrays-nested.toml"
);
t!(
    test_bool,
    "fixtures/valid/bool.json",
    "fixtures/valid/bool.toml"
);
t!(
    test_comment_at_eof2,
    "fixtures/valid/comments-at-eof2.json",
    "fixtures/valid/comments-at-eof2.toml"
);
t!(
    test_comment_at_eof,
    "fixtures/valid/comments-at-eof.json",
    "fixtures/valid/comments-at-eof.toml"
);
t!(
    test_comments_everywhere,
    "fixtures/valid/comments-everywhere.json",
    "fixtures/valid/comments-everywhere.toml"
);
t!(
    test_datetime,
    "fixtures/valid/datetime.json",
    "fixtures/valid/datetime.toml"
);
t!(
    test_empty,
    "fixtures/valid/empty.json",
    "fixtures/valid/empty.toml"
);
t!(
    test_example,
    "fixtures/valid/example.json",
    "fixtures/valid/example.toml"
);
t!(
    test_float_exponent,
    "fixtures/valid/float-exponent.json",
    "fixtures/valid/float-exponent.toml"
);
t!(
    test_float,
    "fixtures/valid/float.json",
    "fixtures/valid/float.toml"
);
t!(
    test_float_underscore,
    "fixtures/valid/float-underscore.json",
    "fixtures/valid/float-underscore.toml"
);
t!(
    test_implicit_and_explicit_after,
    "fixtures/valid/implicit-and-explicit-after.json",
    "fixtures/valid/implicit-and-explicit-after.toml"
);
t!(
    test_implicit_and_explicit_before,
    "fixtures/valid/implicit-and-explicit-before.json",
    "fixtures/valid/implicit-and-explicit-before.toml"
);
t!(
    test_implicit_groups,
    "fixtures/valid/implicit-groups.json",
    "fixtures/valid/implicit-groups.toml"
);
t!(
    test_inline_table,
    "fixtures/valid/inline-table.json",
    "fixtures/valid/inline-table.toml"
);
t!(
    test_integer,
    "fixtures/valid/integer.json",
    "fixtures/valid/integer.toml"
);
t!(
    test_integer_underscore,
    "fixtures/valid/integer-underscore.json",
    "fixtures/valid/integer-underscore.toml"
);
t!(
    test_keys_equal_nospace,
    "fixtures/valid/key-equals-nospace.json",
    "fixtures/valid/key-equals-nospace.toml"
);
t!(
    test_key_numeric,
    "fixtures/valid/key-numeric.json",
    "fixtures/valid/key-numeric.toml"
);
t!(
    test_key_space,
    "fixtures/valid/key-space.json",
    "fixtures/valid/key-space.toml"
);
t!(
    test_key_special_chars,
    "fixtures/valid/key-special-chars.json",
    "fixtures/valid/key-special-chars.toml"
);
t!(
    test_long_float,
    "fixtures/valid/long-float.json",
    "fixtures/valid/long-float.toml"
);
t!(
    test_long_integer,
    "fixtures/valid/long-integer.json",
    "fixtures/valid/long-integer.toml"
);
t!(
    test_multiline_string,
    "fixtures/valid/multiline-string.json",
    "fixtures/valid/multiline-string.toml"
);
t!(
    test_raw_multiline_string,
    "fixtures/valid/raw-multiline-string.json",
    "fixtures/valid/raw-multiline-string.toml"
);
t!(
    test_raw_string,
    "fixtures/valid/raw-string.json",
    "fixtures/valid/raw-string.toml"
);
t!(
    test_string_empty,
    "fixtures/valid/string-empty.json",
    "fixtures/valid/string-empty.toml"
);
t!(
    test_string_escapes,
    "fixtures/valid/string-escapes.json",
    "fixtures/valid/string-escapes.toml"
);
t!(
    test_string_nl,
    "fixtures/valid/string-nl.json",
    "fixtures/valid/string-nl.toml"
);
t!(
    test_string_simple,
    "fixtures/valid/string-simple.json",
    "fixtures/valid/string-simple.toml"
);
t!(
    test_string_with_pound,
    "fixtures/valid/string-with-pound.json",
    "fixtures/valid/string-with-pound.toml"
);
t!(
    test_table_array_implicit,
    "fixtures/valid/table-array-implicit.json",
    "fixtures/valid/table-array-implicit.toml"
);
t!(
    test_table_array_many,
    "fixtures/valid/table-array-many.json",
    "fixtures/valid/table-array-many.toml"
);
t!(
    test_table_array_nest,
    "fixtures/valid/table-array-nest.json",
    "fixtures/valid/table-array-nest.toml"
);
t!(
    test_array_one,
    "fixtures/valid/table-array-one.json",
    "fixtures/valid/table-array-one.toml"
);
t!(
    test_table_empty,
    "fixtures/valid/table-empty.json",
    "fixtures/valid/table-empty.toml"
);
t!(
    test_table_no_eol,
    "fixtures/valid/table-no-eol.json",
    "fixtures/valid/table-no-eol.toml"
);
t!(
    test_table_sub_empty,
    "fixtures/valid/table-sub-empty.json",
    "fixtures/valid/table-sub-empty.toml"
);
t!(
    test_whitespace,
    "fixtures/valid/table-whitespace.json",
    "fixtures/valid/table-whitespace.toml"
);
t!(
    test_table_with_literal_string,
    "fixtures/valid/table-with-literal-string.json",
    "fixtures/valid/table-with-literal-string.toml"
);
t!(
    test_table_with_poung,
    "fixtures/valid/table-with-pound.json",
    "fixtures/valid/table-with-pound.toml"
);
t!(
    test_table_with_single_quotes,
    "fixtures/valid/table-with-single-quotes.json",
    "fixtures/valid/table-with-single-quotes.toml"
);
t!(
    test_unicode_escape,
    "fixtures/valid/unicode-escape.json",
    "fixtures/valid/unicode-escape.toml"
);
t!(
    test_unicode_literal,
    "fixtures/valid/unicode-literal.json",
    "fixtures/valid/unicode-literal.toml"
);
t!(
    test_windows_path,
    "fixtures/valid/windows-path.json",
    "fixtures/valid/windows-path.toml"
);
<|endoftext|>


<commit_before>use std::path::PathBuf;
use std::path::Path;
use std::borrow::Borrow;
use std::ops::Deref;

use semver::Version;
use std::fmt::{Display, Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;

use error::StoreErrorKind as SEK;
use store::Result;
use store::Store;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId(PathBuf);

impl StoreId {

    pub fn storified(self, store: &Store) -> StoreId {
        if self.starts_with(store.path()) {
            debug!("Not storifying {:?}, because it is already.", self);
            self
        } else {
            debug!("Create new store id out of: {:?} and {:?}", store.path(), self);
            let mut new_id = store.path().clone();
            new_id.push(self);
            debug!("Created: '{:?}'", new_id);
            StoreId::from(new_id)
        }
    }

}

impl Into<PathBuf> for StoreId {

    fn into(self) -> PathBuf {
        self.0
    }

}

impl Display for StoreId {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        match self.0.to_str() {
            Some(s) => write!(fmt, "{}", s),
            None    => write!(fmt, "<non-UTF8-StoreId>"), // TODO: Sure here?
        }
    }

}

impl Deref for StoreId {
    type Target = PathBuf;

    fn deref(&self) -> &PathBuf {
        &self.0
    }

}

impl From<PathBuf> for StoreId {

    fn from(pb: PathBuf) -> StoreId {
        StoreId(pb)
    }

}

impl From<String> for StoreId {

    fn from(string: String) -> StoreId {
        StoreId(string.into())
    }

}

impl AsRef<Path> for StoreId {

    fn as_ref(&self) -> &Path {
        self.0.as_ref()
    }

}

impl Borrow<Path> for StoreId {

    fn borrow(&self) -> &Path {
        self.0.borrow()
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> StoreId;
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> StoreId {
        StoreId(self)
    }
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> StoreId {
        self
    }
}

pub fn build_entry_path(store: &Store, path_elem: &str) -> Result<PathBuf> {
    debug!("Checking path element for version");
    if path_elem.split('~').last().map_or(false, |v| Version::parse(v).is_err()) {
        debug!("Version cannot be parsed from {:?}", path_elem);
        debug!("Path does not contain version!");
        return Err(SEK::StorePathLacksVersion.into());
    }
    debug!("Version checking succeeded");

    debug!("Building path from {:?}", path_elem);
    let mut path = store.path().clone();

    if path_elem.starts_with('/') {
        path.push(&path_elem[1..]);
    } else {
        path.push(path_elem);
    }

    Ok(path)
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr, $version:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use semver::Version;
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let version = Version::parse($version).unwrap();
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(format!("{}~{}",
                                               name,
                                               version));
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> $crate::storeid::StoreId {
                    StoreId::from(self.0)
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test", "0.2.0-alpha+leet1337");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().to_str().unwrap(), "test/test~0.2.0-alpha+leet1337");
    }

}
<commit_msg>Fix Display impl for StoreId by using lossy string rep if PathBuf::to_str() fails<commit_after>use std::path::PathBuf;
use std::path::Path;
use std::borrow::Borrow;
use std::ops::Deref;

use semver::Version;
use std::fmt::{Display, Debug, Formatter};
use std::fmt::Error as FmtError;
use std::result::Result as RResult;

use error::StoreErrorKind as SEK;
use store::Result;
use store::Store;

/// The Index into the Store
#[derive(Debug, Clone, PartialEq, Hash, Eq, PartialOrd, Ord)]
pub struct StoreId(PathBuf);

impl StoreId {

    pub fn storified(self, store: &Store) -> StoreId {
        if self.starts_with(store.path()) {
            debug!("Not storifying {:?}, because it is already.", self);
            self
        } else {
            debug!("Create new store id out of: {:?} and {:?}", store.path(), self);
            let mut new_id = store.path().clone();
            new_id.push(self);
            debug!("Created: '{:?}'", new_id);
            StoreId::from(new_id)
        }
    }

}

impl Into<PathBuf> for StoreId {

    fn into(self) -> PathBuf {
        self.0
    }

}

impl Display for StoreId {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        match self.0.to_str() {
            Some(s) => write!(fmt, "{}", s),
            None    => write!(fmt, "{}", self.0.to_string_lossy()),
        }
    }

}

impl Deref for StoreId {
    type Target = PathBuf;

    fn deref(&self) -> &PathBuf {
        &self.0
    }

}

impl From<PathBuf> for StoreId {

    fn from(pb: PathBuf) -> StoreId {
        StoreId(pb)
    }

}

impl From<String> for StoreId {

    fn from(string: String) -> StoreId {
        StoreId(string.into())
    }

}

impl AsRef<Path> for StoreId {

    fn as_ref(&self) -> &Path {
        self.0.as_ref()
    }

}

impl Borrow<Path> for StoreId {

    fn borrow(&self) -> &Path {
        self.0.borrow()
    }

}

/// This Trait allows you to convert various representations to a single one
/// suitable for usage in the Store
pub trait IntoStoreId {
    fn into_storeid(self) -> StoreId;
}

impl IntoStoreId for PathBuf {
    fn into_storeid(self) -> StoreId {
        StoreId(self)
    }
}

impl IntoStoreId for StoreId {
    fn into_storeid(self) -> StoreId {
        self
    }
}

pub fn build_entry_path(store: &Store, path_elem: &str) -> Result<PathBuf> {
    debug!("Checking path element for version");
    if path_elem.split('~').last().map_or(false, |v| Version::parse(v).is_err()) {
        debug!("Version cannot be parsed from {:?}", path_elem);
        debug!("Path does not contain version!");
        return Err(SEK::StorePathLacksVersion.into());
    }
    debug!("Version checking succeeded");

    debug!("Building path from {:?}", path_elem);
    let mut path = store.path().clone();

    if path_elem.starts_with('/') {
        path.push(&path_elem[1..]);
    } else {
        path.push(path_elem);
    }

    Ok(path)
}

#[macro_export]
macro_rules! module_entry_path_mod {
    ($name:expr, $version:expr) => (
        #[deny(missing_docs,
                missing_copy_implementations,
                trivial_casts, trivial_numeric_casts,
                unsafe_code,
                unstable_features,
                unused_import_braces, unused_qualifications,
                unused_imports)]
        /// A helper module to create valid module entry paths
        pub mod module_path {
            use semver::Version;
            use std::convert::AsRef;
            use std::path::Path;
            use std::path::PathBuf;

            use $crate::storeid::StoreId;

            /// A Struct giving you the ability to choose store entries assigned
            /// to it.
            ///
            /// It is created through a call to `new`.
            pub struct ModuleEntryPath(PathBuf);

            impl ModuleEntryPath {
                /// Path has to be a valid UTF-8 string or this will panic!
                pub fn new<P: AsRef<Path>>(pa: P) -> ModuleEntryPath {
                    let mut path = PathBuf::new();
                    path.push(format!("{}", $name));
                    path.push(pa.as_ref().clone());
                    let version = Version::parse($version).unwrap();
                    let name = pa.as_ref().file_name().unwrap()
                        .to_str().unwrap();
                    path.set_file_name(format!("{}~{}",
                                               name,
                                               version));
                    ModuleEntryPath(path)
                }
            }

            impl $crate::storeid::IntoStoreId for ModuleEntryPath {
                fn into_storeid(self) -> $crate::storeid::StoreId {
                    StoreId::from(self.0)
                }
            }
        }
    )
}

pub struct StoreIdIterator {
    iter: Box<Iterator<Item = StoreId>>,
}

impl Debug for StoreIdIterator {

    fn fmt(&self, fmt: &mut Formatter) -> RResult<(), FmtError> {
        write!(fmt, "StoreIdIterator")
    }

}

impl StoreIdIterator {

    pub fn new(iter: Box<Iterator<Item = StoreId>>) -> StoreIdIterator {
        StoreIdIterator {
            iter: iter,
        }
    }

}

impl Iterator for StoreIdIterator {
    type Item = StoreId;

    fn next(&mut self) -> Option<StoreId> {
        self.iter.next()
    }

}

#[cfg(test)]
mod test {

    use storeid::IntoStoreId;

    module_entry_path_mod!("test", "0.2.0-alpha+leet1337");

    #[test]
    fn correct_path() {
        let p = module_path::ModuleEntryPath::new("test");

        assert_eq!(p.into_storeid().to_str().unwrap(), "test/test~0.2.0-alpha+leet1337");
    }

}
<|endoftext|>


<commit_before>extern crate rand;

use rand::Rng;
use std::f64::consts::PI;

// `(f32, f32)` would be faster for some RNGs (including `rand::thread_rng` on 32-bit platforms
// and `rand::weak_rng` as of rand v0.4) as `next_u64` combines two `next_u32`s if not natively
// supported by the RNG.  It would less accurate however.
fn is_inside_circle((x, y): (f64, f64)) -> bool {
    x * x + y * y <= 1.0
}

fn simulate<R: Rng>(rng: &mut R, samples: usize) -> f64 {
    let mut count = 0;
    for _ in 0..samples {
        count += is_inside_circle(rng.gen()) as usize;
    }
    (count as f64) / (samples as f64)
}

fn main() {
    let mut rng = rand::weak_rng();

    println!("Real pi: {}", PI);

    for samples in (3..9).map(|e| 10_usize.pow(e)) {
        let estimate = 4.0 * simulate(&mut rng, samples);
        let deviation = 100.0 * (1.0 - estimate / PI).abs();
        println!("{:9}: {:<11} dev: {:.5}%", samples, estimate, deviation);
    }
}
<commit_msg>make logic more explicit<commit_after>extern crate rand;

use rand::Rng;
use std::f64::consts::PI;

// `(f32, f32)` would be faster for some RNGs (including `rand::thread_rng` on 32-bit platforms
// and `rand::weak_rng` as of rand v0.4) as `next_u64` combines two `next_u32`s if not natively
// supported by the RNG.  It would less accurate however.
fn is_inside_circle((x, y): (f64, f64)) -> bool {
    x * x + y * y <= 1.0
}

fn simulate<R: Rng>(rng: &mut R, samples: usize) -> f64 {
    let mut count = 0;
    for _ in 0..samples {
        if is_inside_circle(rng.gen()) {
            count += 1;
        }
    }
    (count as f64) / (samples as f64)
}

fn main() {
    let mut rng = rand::weak_rng();

    println!("Real pi: {}", PI);

    for samples in (3..9).map(|e| 10_usize.pow(e)) {
        let estimate = 4.0 * simulate(&mut rng, samples);
        let deviation = 100.0 * (1.0 - estimate / PI).abs();
        println!("{:9}: {:<11} dev: {:.5}%", samples, estimate, deviation);
    }
}
<|endoftext|>


<commit_before>use into::IntoError;

#[macro_export]
macro_rules! generate_error_imports {
    () => {
        use std::error::Error;
        use std::fmt::Error as FmtError;
        use std::fmt::{Display, Formatter};

        use $crate::into::IntoError;
    }
}

#[macro_export]
macro_rules! generate_error_module {
    ( $exprs:item ) => {
        pub mod error {
            generate_error_imports!();
            $exprs
        }
    }
}

#[macro_export]
macro_rules! generate_custom_error_types {
    {
        $name: ident,
        $kindname: ident,
        $customMemberTypeName: ident,
        $($kind:ident => $string:expr),*
    } => {
        #[derive(Clone, Copy, Debug, PartialEq)]
        pub enum $kindname {
            $( $kind ),*
        }

        impl Display for $kindname {

            fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
                let s = match *self {
                    $( $kindname::$kind => $string ),*
                };
                try!(write!(fmt, "{}", s));
                Ok(())
            }

        }

        impl IntoError for $kindname {
            type Target = $name;

            fn into_error(self) -> Self::Target {
                $name::new(self, None)
            }

            fn into_error_with_cause(self, cause: Box<Error>) -> Self::Target {
                $name::new(self, Some(cause))
            }

        }

        #[derive(Debug)]
        pub struct $name {
            err_type: $kindname,
            cause: Option<Box<Error>>,
            custom_data: Option<$customMemberTypeName>,
        }

        impl $name {

            pub fn new(errtype: $kindname, cause: Option<Box<Error>>) -> $name {
                $name {
                    err_type: errtype,
                    cause: cause,
                    custom_data: None,
                }
            }

            pub fn err_type(&self) -> $kindname {
                self.err_type
            }

        }

        impl Display for $name {

            fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
                try!(write!(fmt, "[{}]", self.err_type));
                Ok(())
            }

        }

        impl Error for $name {

            fn description(&self) -> &str {
                match self.err_type {
                    $( $kindname::$kind => $string ),*
                }
            }

            fn cause(&self) -> Option<&Error> {
                self.cause.as_ref().map(|e| &**e)
            }

        }

    }
}

#[macro_export]
macro_rules! generate_error_types {
    (
        $name: ident,
        $kindname: ident,
        $($kind:ident => $string:expr),*
    ) => {
        generate_custom_error_types!($name, $kindname, members = {}, functions = {}, $($kind),*);
    }
}

#[cfg(test)]
mod test {

    generate_error_module!(
        generate_error_types!(TestError, TestErrorKind,
            TestErrorKindA => "testerrorkind a",
            TestErrorKindB => "testerrorkind B");
    );

    #[test]
    fn test_a() {
        use self::error::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindA;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
    }

    #[test]
    fn test_b() {
        use self::error::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind B"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e));

    }

    #[test]
    fn test_ab() {
        use std::error::Error;
        use self::error::{TestError, TestErrorKind};

        let kinda = TestErrorKind::TestErrorKindA;
        let kindb = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kinda));
        assert_eq!(String::from("testerrorkind B"), format!("{}", kindb));

        let e = TestError::new(kinda, Some(Box::new(TestError::new(kindb, None))));
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
        assert_eq!(TestErrorKind::TestErrorKindA, e.err_type());
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e.cause().unwrap()));
    }

    pub mod anothererrormod {
        generate_error_imports!();
        generate_error_types!(TestError, TestErrorKind,
            TestErrorKindA => "testerrorkind a",
            TestErrorKindB => "testerrorkind B");
    }

    #[test]
    fn test_other_a() {
        use self::anothererrormod::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindA;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
    }

    #[test]
    fn test_other_b() {
        use self::anothererrormod::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind B"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e));

    }

    #[test]
    fn test_other_ab() {
        use std::error::Error;
        use self::anothererrormod::{TestError, TestErrorKind};

        let kinda = TestErrorKind::TestErrorKindA;
        let kindb = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kinda));
        assert_eq!(String::from("testerrorkind B"), format!("{}", kindb));

        let e = TestError::new(kinda, Some(Box::new(TestError::new(kindb, None))));
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
        assert_eq!(TestErrorKind::TestErrorKindA, e.err_type());
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e.cause().unwrap()));
    }
}
<commit_msg>Add tests for error types with custom functions and types<commit_after>use into::IntoError;

#[macro_export]
macro_rules! generate_error_imports {
    () => {
        use std::error::Error;
        use std::fmt::Error as FmtError;
        use std::fmt::{Display, Formatter};

        use $crate::into::IntoError;
    }
}

#[macro_export]
macro_rules! generate_error_module {
    ( $exprs:item ) => {
        pub mod error {
            generate_error_imports!();
            $exprs
        }
    }
}

#[macro_export]
macro_rules! generate_custom_error_types {
    {
        $name: ident,
        $kindname: ident,
        $customMemberTypeName: ident,
        $($kind:ident => $string:expr),*
    } => {
        #[derive(Clone, Copy, Debug, PartialEq)]
        pub enum $kindname {
            $( $kind ),*
        }

        impl Display for $kindname {

            fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
                let s = match *self {
                    $( $kindname::$kind => $string ),*
                };
                try!(write!(fmt, "{}", s));
                Ok(())
            }

        }

        impl IntoError for $kindname {
            type Target = $name;

            fn into_error(self) -> Self::Target {
                $name::new(self, None)
            }

            fn into_error_with_cause(self, cause: Box<Error>) -> Self::Target {
                $name::new(self, Some(cause))
            }

        }

        #[derive(Debug)]
        pub struct $name {
            err_type: $kindname,
            cause: Option<Box<Error>>,
            custom_data: Option<$customMemberTypeName>,
        }

        impl $name {

            pub fn new(errtype: $kindname, cause: Option<Box<Error>>) -> $name {
                $name {
                    err_type: errtype,
                    cause: cause,
                    custom_data: None,
                }
            }

            pub fn err_type(&self) -> $kindname {
                self.err_type
            }

        }

        impl Display for $name {

            fn fmt(&self, fmt: &mut Formatter) -> Result<(), FmtError> {
                try!(write!(fmt, "[{}]", self.err_type));
                Ok(())
            }

        }

        impl Error for $name {

            fn description(&self) -> &str {
                match self.err_type {
                    $( $kindname::$kind => $string ),*
                }
            }

            fn cause(&self) -> Option<&Error> {
                self.cause.as_ref().map(|e| &**e)
            }

        }

    }
}

#[macro_export]
macro_rules! generate_error_types {
    (
        $name: ident,
        $kindname: ident,
        $($kind:ident => $string:expr),*
    ) => {
        #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)]
        pub struct SomeNotExistingTypeWithATypeNameNoOneWillEverChoose {}
        generate_custom_error_types!($name, $kindname,
                                     SomeNotExistingTypeWithATypeNameNoOneWillEverChoose,
                                     $($kind => $string),*);
    }
}

#[cfg(test)]
mod test {

    generate_error_module!(
        generate_error_types!(TestError, TestErrorKind,
            TestErrorKindA => "testerrorkind a",
            TestErrorKindB => "testerrorkind B");
    );

    #[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Copy)]
    pub struct CustomData {
        pub test: i32,
        pub othr: i64,
    }

    generate_error_imports!();

    generate_custom_error_types!(CustomTestError, CustomTestErrorKind,
        CustomData,
        CustomErrorKindA => "customerrorkind a",
        CustomErrorKindB => "customerrorkind B");

    impl CustomTestError {
        pub fn test(&self) -> i32 {
            match self.custom_data {
                Some(t) => t.test,
                None => 0,
            }
        }

        pub fn bar(&self) -> i64 {
            match self.custom_data {
                Some(t) => t.othr,
                None => 0,
            }
        }
    }

    #[test]
    fn test_a() {
        use self::error::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindA;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
    }

    #[test]
    fn test_b() {
        use self::error::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind B"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e));

    }

    #[test]
    fn test_ab() {
        use std::error::Error;
        use self::error::{TestError, TestErrorKind};

        let kinda = TestErrorKind::TestErrorKindA;
        let kindb = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kinda));
        assert_eq!(String::from("testerrorkind B"), format!("{}", kindb));

        let e = TestError::new(kinda, Some(Box::new(TestError::new(kindb, None))));
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
        assert_eq!(TestErrorKind::TestErrorKindA, e.err_type());
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e.cause().unwrap()));
    }

    pub mod anothererrormod {
        generate_error_imports!();
        generate_error_types!(TestError, TestErrorKind,
            TestErrorKindA => "testerrorkind a",
            TestErrorKindB => "testerrorkind B");
    }

    #[test]
    fn test_other_a() {
        use self::anothererrormod::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindA;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
    }

    #[test]
    fn test_other_b() {
        use self::anothererrormod::{TestError, TestErrorKind};

        let kind = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind B"), format!("{}", kind));

        let e = TestError::new(kind, None);
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e));

    }

    #[test]
    fn test_other_ab() {
        use std::error::Error;
        use self::anothererrormod::{TestError, TestErrorKind};

        let kinda = TestErrorKind::TestErrorKindA;
        let kindb = TestErrorKind::TestErrorKindB;
        assert_eq!(String::from("testerrorkind a"), format!("{}", kinda));
        assert_eq!(String::from("testerrorkind B"), format!("{}", kindb));

        let e = TestError::new(kinda, Some(Box::new(TestError::new(kindb, None))));
        assert_eq!(String::from("[testerrorkind a]"), format!("{}", e));
        assert_eq!(TestErrorKind::TestErrorKindA, e.err_type());
        assert_eq!(String::from("[testerrorkind B]"), format!("{}", e.cause().unwrap()));
    }
}
<|endoftext|>


<commit_before>fn main() {

}
<commit_msg>implement rm<commit_after>#[macro_use]
extern crate clap;

use clap::{App, Arg};

use std::fs;

fn main() {
    let matches = App::new("rm")
                      .version("0.0.1")
                      .author("Redox Developers")
                      .about("Delete files and directories")
                      .arg(Arg::with_name("item")
                               .help("Item to remove")
                               .required(true)
                               .multiple(true))
                      .arg(Arg::with_name("interactive")
                               .help("Prompt before each removal")
                               .short("i")
                               .long("interactive"))
                      .arg(Arg::with_name("force")
                               .help("Ignore any errors or prompts. Guaranteed to delete the \
                                      file(s) or directory(s).")
                               .short("f")
                               .long("force"))
                      .arg(Arg::with_name("verbose")
                               .help("Print extra info")
                               .short("v")
                               .long("verbose"))
                      .get_matches();

    // TODO support arguments

    let path = matches.value_of("item").unwrap();

    if fs::remove_file(path).is_err() {
        println!("Failed to remove: {}", path);
    }
}
<|endoftext|>


<commit_before>//! Awesome compatibilty modules
use xcb::{xkb, Connection};

use rlua::{self, Lua, Table, LightUserData};

use std::mem;

pub mod keygrabber;
pub mod mousegrabber;
pub mod awful;
mod awesome;
mod client;
mod screen;
mod button;
mod tag;
mod key;
mod drawin;
mod drawable;
mod mouse;
mod root;
mod signal;
mod object;
mod class;
mod property;
mod xproperty;

pub use self::object::Object;
pub use self::keygrabber::keygrabber_handle;
pub use self::mousegrabber::mousegrabber_handle;

pub const GLOBAL_SIGNALS: &'static str = "__awesome_global_signals";
pub const XCB_CONNECTION_HANDLE: &'static str = "__xcb_connection";

use std::env;
use std::path::PathBuf;

pub fn init(lua: &Lua) -> rlua::Result<()> {
    setup_awesome_path(lua)?;
    setup_global_signals(lua)?;
    setup_xcb_connection(lua)?;
    button::init(lua)?;
    awesome::init(lua)?;
    key::init(lua)?;
    client::init(lua)?;
    screen::init(lua)?;
    keygrabber::init(lua)?;
    root::init(lua)?;
    mouse::init(lua)?;
    tag::init(lua)?;
    drawin::init(lua)?;
    drawable::init(lua)?;
    mousegrabber::init(lua)?;
    awful::init(lua)?;
    Ok(())
}

fn setup_awesome_path(lua: &Lua) -> rlua::Result<()> {
    let globals = lua.globals();
    let package: Table = globals.get("package")?;
    let mut path = package.get::<_, String>("path")?;
    let mut cpath = package.get::<_, String>("cpath")?;
    let mut xdg_data_path: PathBuf = env::var("XDG_DATA_DIRS").unwrap_or("/usr/share".into()).into();
    xdg_data_path.push("awesome/lib");
    path.push_str(&format!(";{0}/?.lua;{0}/?/init.lua",
                             xdg_data_path.as_os_str().to_string_lossy()));
    package.set("path", path)?;
    let mut xdg_config_path: PathBuf = env::var("XDG_CONFIG_DIRS").unwrap_or("/etc/xdg".into()).into();
    xdg_config_path.push("awesome");
    cpath.push_str(&format!(";{}/?.so;{}/?.so",
                            xdg_config_path.into_os_string().to_string_lossy(),
                            xdg_data_path.into_os_string().to_string_lossy()));
    package.set("cpath", cpath)?;

    // NOTE The debug library does some powerful reflection that can do crazy things,
    // which is why it's unsafe to load.
    unsafe {
        lua.load_debug();
    }
    Ok(())
}

/// Set up global signals value
///
/// We need to store this in Lua, because this make it safer to use.
fn setup_global_signals(lua: &Lua) -> rlua::Result<()> {
    let globals = lua.globals();
    globals.set::<_, Table>(GLOBAL_SIGNALS, lua.create_table())
}

/// Sets up the xcb connection and stores it in Lua (for us to access it later)
fn setup_xcb_connection(lua: &Lua) -> rlua::Result<()> {
    let con = Connection::connect(None).unwrap_or_else(|err| {
        error!("xcb: Could not connect to xwayland instance. Is it running?");
        panic!("{:?}", err);
    }).0;
    // Tell xcb we are using the xkb extension
    match xkb::use_extension(&con, 1, 0).get_reply() {
        Ok(r) => {
            if !r.supported() {
                panic!("xkb-1.0 is not supported");
            }
        },
        Err(err) => {
            panic!("Could not get xkb extension supported version {:?}", err);
        }
    }
    lua.globals().set(XCB_CONNECTION_HANDLE, LightUserData(con.get_raw_conn() as _))?;
    mem::forget(con);
    Ok(())
}

pub fn dummy<'lua>(_: &'lua Lua, _: rlua::Value) -> rlua::Result<()> { Ok(()) }
<commit_msg>Don't panic if xcb can't be established.<commit_after>//! Awesome compatibilty modules
use xcb::{xkb, Connection};

use rlua::{self, Lua, Table, LightUserData};

use std::mem;

pub mod keygrabber;
pub mod mousegrabber;
pub mod awful;
mod awesome;
mod client;
mod screen;
mod button;
mod tag;
mod key;
mod drawin;
mod drawable;
mod mouse;
mod root;
mod signal;
mod object;
mod class;
mod property;
mod xproperty;

pub use self::object::Object;
pub use self::keygrabber::keygrabber_handle;
pub use self::mousegrabber::mousegrabber_handle;

pub const GLOBAL_SIGNALS: &'static str = "__awesome_global_signals";
pub const XCB_CONNECTION_HANDLE: &'static str = "__xcb_connection";

use std::env;
use std::path::PathBuf;

pub fn init(lua: &Lua) -> rlua::Result<()> {
    setup_awesome_path(lua)?;
    setup_global_signals(lua)?;
    setup_xcb_connection(lua)?;
    button::init(lua)?;
    awesome::init(lua)?;
    key::init(lua)?;
    client::init(lua)?;
    screen::init(lua)?;
    keygrabber::init(lua)?;
    root::init(lua)?;
    mouse::init(lua)?;
    tag::init(lua)?;
    drawin::init(lua)?;
    drawable::init(lua)?;
    mousegrabber::init(lua)?;
    awful::init(lua)?;
    Ok(())
}

fn setup_awesome_path(lua: &Lua) -> rlua::Result<()> {
    let globals = lua.globals();
    let package: Table = globals.get("package")?;
    let mut path = package.get::<_, String>("path")?;
    let mut cpath = package.get::<_, String>("cpath")?;
    let mut xdg_data_path: PathBuf = env::var("XDG_DATA_DIRS").unwrap_or("/usr/share".into()).into();
    xdg_data_path.push("awesome/lib");
    path.push_str(&format!(";{0}/?.lua;{0}/?/init.lua",
                             xdg_data_path.as_os_str().to_string_lossy()));
    package.set("path", path)?;
    let mut xdg_config_path: PathBuf = env::var("XDG_CONFIG_DIRS").unwrap_or("/etc/xdg".into()).into();
    xdg_config_path.push("awesome");
    cpath.push_str(&format!(";{}/?.so;{}/?.so",
                            xdg_config_path.into_os_string().to_string_lossy(),
                            xdg_data_path.into_os_string().to_string_lossy()));
    package.set("cpath", cpath)?;

    // NOTE The debug library does some powerful reflection that can do crazy things,
    // which is why it's unsafe to load.
    unsafe {
        lua.load_debug();
    }
    Ok(())
}

/// Set up global signals value
///
/// We need to store this in Lua, because this make it safer to use.
fn setup_global_signals(lua: &Lua) -> rlua::Result<()> {
    let globals = lua.globals();
    globals.set::<_, Table>(GLOBAL_SIGNALS, lua.create_table())
}

/// Sets up the xcb connection and stores it in Lua (for us to access it later)
fn setup_xcb_connection(lua: &Lua) -> rlua::Result<()> {
    let con = match Connection::connect(None) {
        Err(err) => {
            error!("xcb: Could not connect to xwayland instance. Is it running?");
            error!("{:?}", err);
            return Ok(())
        },
        Ok(con) => con.0
    };
    // Tell xcb we are using the xkb extension
    match xkb::use_extension(&con, 1, 0).get_reply() {
        Ok(r) => {
            if !r.supported() {
                panic!("xkb-1.0 is not supported");
            }
        },
        Err(err) => {
            panic!("Could not get xkb extension supported version {:?}", err);
        }
    }
    lua.globals().set(XCB_CONNECTION_HANDLE, LightUserData(con.get_raw_conn() as _))?;
    mem::forget(con);
    Ok(())
}

pub fn dummy<'lua>(_: &'lua Lua, _: rlua::Value) -> rlua::Result<()> { Ok(()) }
<|endoftext|>