<commit_before>use std;
use base::*;
use super::{LoudsTrie, NodeID, LoudsPos, LinkID, INVALID_LINK_ID};

struct State<'a> {
    trie_: &'a LoudsTrie,
    node_id_: NodeID,
    louds_pos_: LoudsPos,
    link_id_: LinkID,
    key_pos_: u32,
    //key_id_: u32,
}

impl<'a> std::fmt::Debug for State<'a> {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        fmt.debug_struct("State")
            .field("node_id_", &self.node_id_)
            .field("louds_pos_", &self.louds_pos_)
            .field("link_id_", &self.link_id_)
            .field("key_pos_", &self.key_pos_)
            .finish()
    }
}

impl<'a> State<'a> {
    fn new(trie: &'a LoudsTrie, node_id: NodeID, louds_pos: LoudsPos,
           link_id: LinkID, key_pos: u32) -> State<'a> {
        State { trie_: trie, node_id_: node_id, louds_pos_: louds_pos,
                link_id_: link_id, key_pos_: key_pos }
    }
}

#[derive(Debug)]
pub struct Nav<'a> {
    history_: Vec<State<'a> >,
    key_buf_: Vec<u8>,
}

// For lookups, marisa does caching based on the input character.
// We can't do that here. May want to remove or rethink the cache
// implementation in light of this.

impl<'a> Nav<'a> {
    fn new(trie: &'a LoudsTrie) -> Nav<'a> {
        let mut out = Nav { history_: Vec::new(), key_buf_: Vec::new() };
        out.history_.push(State::new(trie, NodeID(0), LoudsPos(0),
                          INVALID_LINK_ID, 0));
        out
    }

    fn get_node_id(&self) -> NodeID {
        self.history_.last().unwrap().node_id_
    }

    fn get_link_id(&self) -> LinkID {
        self.history_.last().unwrap().link_id_
    }

    fn push_str<'b>(&mut self, key: &'b[u8], trie: &'a LoudsTrie, node_id: NodeID,
                    louds_pos: LoudsPos, link_id: LinkID) {

        debug!("push_str: {:?}", key);

        self.key_buf_.extend(key);
        assert!(self.key_buf_.len() <= std::u32::MAX as usize);
        self.history_.push(State::new(trie, node_id, louds_pos, link_id,
                                      self.key_buf_.len() as u32));
    }

    fn push(&mut self, node_id: NodeID, louds_pos: LoudsPos) {
        let mut trie = self.history_.last().unwrap().trie_;
        loop {
            if trie.link_flags_.at(node_id.0 as usize) {
                let (node_id, link_id) = trie.get_linked_ids(node_id.0
                                                             as usize);
                // Proceed either to next trie or tail
                match &trie.next_trie_ {
                    &Some(ref next_trie) => {
                        trie = &**next_trie;
                        continue;
                    },
                    &None => {
                        // FIXME: Shouldn't need this temporary vector.
                        //        'restore' should return an iterator, and
                        //        state.push should consume it.
                        let mut v = Vec::new();
                        trie.tail_.restore(node_id.0 as usize, &mut v);

                        // Not sure if these values are correct/useful.
                        // If some stuff is only needed for some nodes...
                        // should reflect that in the types we use
                        self.push_str(&v, trie, node_id, louds_pos, link_id);
                    }
                }
            } else {
                let node_char = [ trie.bases_[node_id.0 as usize] ];
                self.push_str(&node_char, trie, node_id, louds_pos,
                              INVALID_LINK_ID);
            }
            break;
        }
    }
    pub fn has_child(&self) -> bool {
        self.history_.last().unwrap().trie_.has_child(self.get_node_id())
    }
    pub fn go_to_child(&mut self) -> bool {
        let init_node_id = self.get_node_id();
        if let Some((node_id, louds_pos)) = self.history_.last().unwrap()
                                            .trie_.child_pos(init_node_id) {
            self.push(node_id, louds_pos);
            true
        } else {
            false
        }
    }
    pub fn has_prev_sibling(&self) -> bool {
        // FIXME: Is this all...?
        self.history_.last().map(|h| {
            h.trie_.louds_.at(h.louds_pos_.0 as usize - 1)
        }).unwrap_or(false)
    }
    pub fn go_to_prev_sibling(&mut self) -> bool {
        // pop history and string
        // decrease louds_pos and node_id by 1 if we have a sibling
        // get string (factor this out?)
        // push new history & string

        panic!("not implemented")
    }
    pub fn has_sibling(&self) -> bool {
        self.history_.last().map(|h| {
            h.trie_.louds_.at(h.louds_pos_.0 as usize + 1)
        }).unwrap_or(false)
    }
    pub fn go_to_sibling(&mut self) -> bool {
        if let Some(h) = self.history_.pop() {
            if h.trie_.louds_.at(h.louds_pos_.0 as usize + 1) {
                // FIXME: What about LinkID?
                self.push(NodeID(h.node_id_.0 + 1),
                          LoudsPos(h.louds_pos_.0 + 1));
                true
            } else {
                false
            }
        } else {
            false
        }
    }
    pub fn has_parent(&self) -> bool {
        panic!("not implemented")
    }
    pub fn go_to_parent(&mut self) -> bool {
        // Could use LOUDS-trie select1(rank0(m)) to navigate upward (within a
        // single trie), but it's probably more efficient just to keep a stack
        // and pop to go up
        self.history_.pop().is_some()
    }
    pub fn is_leaf(&self) -> bool {
        panic!("not implemented")
    }
    //pub fn get_string(&self) -> &str {
    //    panic!("not implemented")
    //}
    pub fn get_u8(&self) -> &[u8] {
        &self.key_buf_[..]
    }
    pub fn is_end(&self) -> bool {
        panic!("not implemented")
    }
}

#[derive(Copy, Clone)]
enum DFT {
    ToChild,
    ToSibling,
    ToParentSibling,
    End
}

impl DFT {
    fn new() -> DFT {
        DFT::ToChild
    }
    fn depth_first_traversal_step<'a>(&mut self, nav: &mut Nav<'a>) -> bool {
        debug!("{:?}", *nav);

        panic!();
        match *self {
            DFT::ToChild => {
                if nav.go_to_child() {
                    return true;
                } else {
                    *self = DFT::ToSibling;
                    return false;
                }
            },
            DFT::ToSibling => {
                if nav.go_to_sibling() {
                    *self = DFT::ToChild;
                    return true;
                } else {
                    *self = DFT::ToParentSibling;
                    return false;
                }
            },
            DFT::ToParentSibling => {
                if !nav.go_to_parent() {
                    *self = DFT::End;
                    return false;
                }
                if nav.go_to_sibling() {
                    *self = DFT::ToChild;
                    return true;
                }
                return false;
            },
            DFT::End => {
                return false;
            }
        }
    }
    fn next_terminal<'a, 'b>(&mut self, nav: &'b mut Nav<'a>)
      -> Option<&'b[u8]> {
        loop {
            match *self {
                DFT::End => { return None; },
                _ => (),
            }
            if self.depth_first_traversal_step(nav) {
                return Some(nav.get_u8());
            }
        }
    }
}

#[cfg(test)]
mod test {
    use env_logger;
    use std::cmp::Ordering;
    use quickcheck as qc;
    use config::{Config, NumTries};
    use key::Key;
    use super::{DFT, Nav};
    use super::super::LoudsTrie;

    fn restore_with_nav_prop(v: Vec<String>, num_tries: NumTries)
      -> qc::TestResult {
        if v.iter().any(|x| x.is_empty()) {
            return qc::TestResult::discard();
        }
        let mut keys: Vec<Key> = v.iter().map(|s| Key::new(s.as_bytes()))
                                 .collect();
        let config = Config::new().with_num_tries(num_tries);
        let trie = LoudsTrie::build(&mut keys, &config);

        let mut nav = Nav::new(&trie);
        let mut dft = DFT::new();

        let mut vv1: Vec<Vec<u8>> = v.iter().map(|s| From::from(s.as_bytes()))
                                    .collect();

        let mut vv2: Vec<Vec<u8>> = Vec::new();
        while let Some(s) = dft.next_terminal(&mut nav) {
            vv2.push(From::from(s));
        }

        vv1.sort();
        vv2.sort();
        qc::TestResult::from_bool(vv1.cmp(&vv2) == Ordering::Equal)
        //qc::TestResult::passed()
    }

    #[test]
    fn restore_with_nav_qc() {
        let _ = env_logger::init();
        qc::quickcheck(restore_with_nav_prop as fn(Vec<String>, NumTries)
                       -> qc::TestResult);
    }

    #[test]
    fn restore_with_nav_manual() {
        let _ = env_logger::init();
        restore_with_nav_prop(vec!["Testing".to_owned()], NumTries::new(1));
    }
}

<commit_msg>actually failing manual test cases<commit_after>use std;
use base::*;
use super::{LoudsTrie, NodeID, LoudsPos, LinkID, INVALID_LINK_ID};

struct State<'a> {
    trie_: &'a LoudsTrie,
    node_id_: NodeID,
    louds_pos_: LoudsPos,
    link_id_: LinkID,
    key_pos_: u32,
    //key_id_: u32,
}

impl<'a> std::fmt::Debug for State<'a> {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
        fmt.debug_struct("State")
            .field("node_id_", &self.node_id_)
            .field("louds_pos_", &self.louds_pos_)
            .field("link_id_", &self.link_id_)
            .field("key_pos_", &self.key_pos_)
            .finish()
    }
}

impl<'a> State<'a> {
    fn new(trie: &'a LoudsTrie, node_id: NodeID, louds_pos: LoudsPos,
           link_id: LinkID, key_pos: u32) -> State<'a> {
        State { trie_: trie, node_id_: node_id, louds_pos_: louds_pos,
                link_id_: link_id, key_pos_: key_pos }
    }
}

#[derive(Debug)]
pub struct Nav<'a> {
    history_: Vec<State<'a> >,
    key_buf_: Vec<u8>,
}

// For lookups, marisa does caching based on the input character.
// We can't do that here. May want to remove or rethink the cache
// implementation in light of this.

impl<'a> Nav<'a> {
    fn new(trie: &'a LoudsTrie) -> Nav<'a> {
        let mut out = Nav { history_: Vec::new(), key_buf_: Vec::new() };
        out.history_.push(State::new(trie, NodeID(0), LoudsPos(0),
                          INVALID_LINK_ID, 0));
        out
    }

    fn get_link_id(&self) -> LinkID {
        self.history_.last().unwrap().link_id_
    }

    fn push_str<'b>(&mut self, key: &'b[u8], trie: &'a LoudsTrie, node_id: NodeID,
                    louds_pos: LoudsPos, link_id: LinkID) {

//        debug!("push_str(key: {:#?}, node_id: {:#?}, louds_pos: {:#?}, \
//                link_id: {:#?}", key, node_id, louds_pos, link_id);

        self.key_buf_.extend(key);
        assert!(self.key_buf_.len() <= std::u32::MAX as usize);
        self.history_.push(State::new(trie, node_id, louds_pos, link_id,
                                      self.key_buf_.len() as u32));
    }

    fn push(&mut self, mut node_id: NodeID, louds_pos: LoudsPos) {
//        debug!("push");
        let mut trie = self.history_.last().unwrap().trie_;
        loop {
            if trie.link_flags_.at(node_id.0 as usize) {
//                debug!("Link flags TRUE");
                let (linked_node_id, link_id) = trie.get_linked_ids(node_id.0
                                                                    as usize);
                // Proceed either to next trie or tail
                match &trie.next_trie_ {
                    &Some(ref next_trie) => {
                        trie = &**next_trie;
                        node_id = linked_node_id; // not sure about this
                        continue;
                    },
                    &None => {
                        // FIXME: Shouldn't need this temporary vector.
                        //        'restore' should return an iterator, and
                        //        state.push should consume it.
                        let mut v = Vec::new();
                        trie.tail_.restore(node_id.0 as usize, &mut v);

                        // Not sure if these values are correct/useful.
                        // If some stuff is only needed for some nodes...
                        // should reflect that in the types we use
                        self.push_str(&v, trie, node_id, louds_pos, link_id);
                    }
                }
            } else {
//                debug!("Link flags FALSE");
                let node_char = [ trie.bases_[node_id.0 as usize] ];
                self.push_str(&node_char, trie, node_id, louds_pos,
                              INVALID_LINK_ID);
            }
            break;
        }
    }
    pub fn has_child(&self) -> bool {
        self.history_.last().map(|s| s.trie_.has_child(s.node_id_))
            .unwrap_or(false)
    }
    pub fn go_to_child(&mut self) -> bool {
        if let Some((node_id, louds_pos)) =
            self.history_.last()
            .and_then(|s| { s.trie_.child_pos(s.node_id_) })
        {
//            debug!("(node_id: {:#?} louds_pos: {:#?})", node_id, louds_pos);
            self.push(node_id, louds_pos);
            true
        }
        else {
            false
        }
    }
    pub fn has_prev_sibling(&self) -> bool {
        // FIXME: Is this all...?
        self.history_.last().map(|h| {
            h.trie_.louds_.at(h.louds_pos_.0 as usize - 1)
        }).unwrap_or(false)
    }
    pub fn go_to_prev_sibling(&mut self) -> bool {
        // pop history and string
        // decrease louds_pos and node_id by 1 if we have a sibling
        // get string (factor this out?)
        // push new history & string

        panic!("not implemented")
    }
    pub fn has_sibling(&self) -> bool {
        self.history_.last().map(|h| {
            h.trie_.louds_.at(h.louds_pos_.0 as usize + 1)
        }).unwrap_or(false)
    }
    pub fn go_to_sibling(&mut self) -> bool {
        if let Some(h) = self.history_.pop() {
            if h.trie_.louds_.at(h.louds_pos_.0 as usize + 1) {
                // FIXME: What about LinkID?
                self.push(NodeID(h.node_id_.0 + 1),
                          LoudsPos(h.louds_pos_.0 + 1));
                true
            } else {
                false
            }
        } else {
            false
        }
    }
    pub fn has_parent(&self) -> bool {
        panic!("not implemented")
    }
    pub fn go_to_parent(&mut self) -> bool {
        // Could use LOUDS-trie select1(rank0(m)) to navigate upward (within a
        // single trie), but it's probably more efficient just to keep a stack
        // and pop to go up
        self.history_.pop().is_some()
    }
    pub fn is_leaf(&self) -> bool {
        self.history_.last().map(|s|
            s.trie_.terminal_flags_.at(s.node_id_.0 as usize)
        ).unwrap_or(false)
    }
    //pub fn get_string(&self) -> &str {
    //    panic!("not implemented")
    //}
    pub fn get_u8(&self) -> &[u8] {
        &self.key_buf_[..]
    }
    pub fn is_end(&self) -> bool {
        panic!("not implemented")
    }
}

#[derive(Copy, Clone, Debug)]
enum DFT {
    ToChild,
    ToSibling,
    ToParentSibling,
    End
}

impl DFT {
    fn new() -> DFT {
        DFT::ToChild
    }
    fn depth_first_traversal_step<'a>(&mut self, nav: &mut Nav<'a>) -> bool {

        match *self {
            DFT::ToChild => {
                if nav.go_to_child() {
//                    debug!("{:#?}, {:#?}", *self, *nav);
                    //if nav.history_.len() == 3 { panic!() }

                    return true;
                } else {
                    *self = DFT::ToSibling;
                    return false;
                }
            },
            DFT::ToSibling => {
                if nav.go_to_sibling() {
                    *self = DFT::ToChild;
                    return true;
                } else {
                    *self = DFT::ToParentSibling;
                    return false;
                }
            },
            DFT::ToParentSibling => {
                if !nav.go_to_parent() {
                    *self = DFT::End;
                    return false;
                }
                if nav.go_to_sibling() {
                    *self = DFT::ToChild;
                    return true;
                }
                return false;
            },
            DFT::End => {
                return false;
            }
        }
    }
    fn next_terminal<'a, 'b>(&mut self, nav: &'b mut Nav<'a>)
      -> Option<&'b[u8]> {
        loop {
            match *self {
                DFT::End => { return None; },
                _ => (),
            }
            if self.depth_first_traversal_step(nav) && nav.is_leaf() {
                return Some(nav.get_u8());
            }
        }
    }
}

#[cfg(test)]
mod test {
    use env_logger;
    use std::cmp::Ordering;
    use quickcheck as qc;
    use config::{Config, NumTries};
    use key::Key;
    use super::{DFT, Nav};
    use super::super::LoudsTrie;

    fn nav_restore_prop(v: Vec<String>, num_tries: NumTries)
      -> qc::TestResult {
        let mut vu: Vec<Vec<u8>> = Vec::new();
        for s in v.iter() {
            vu.push(From::from(s.as_bytes()));
        }

        debug!("in: {:?}", vu);
        if v.iter().any(|x| x.is_empty()) {
            debug!("");
            return qc::TestResult::discard();
        }
        let mut keys: Vec<Key> = v.iter().map(|s| Key::new(s.as_bytes()))
                                 .collect();
        let config = Config::new().with_num_tries(num_tries);
        let trie = LoudsTrie::build(&mut keys, &config);

        let mut nav = Nav::new(&trie);
        let mut dft = DFT::new();

        let mut vv1: Vec<Vec<u8>> = v.iter().map(|s| From::from(s.as_bytes()))
                                    .collect();

        let mut vv2: Vec<Vec<u8>> = Vec::new();
        while let Some(s) = dft.next_terminal(&mut nav) {
            vv2.push(From::from(s));
        }
        debug!("vv1: {:?}", vv1);
        debug!("vv2: {:?}", vv2);

        vv1.sort();
        vv2.sort();
        let b = vv1.cmp(&vv2) == Ordering::Equal;
        debug!("equal: {:?}", b);
        debug!("");
        qc::TestResult::from_bool(b)
    }

    fn nav_restore_prop_1(v: Vec<String>) -> qc::TestResult {
        nav_restore_prop(v, NumTries::new(1))
    }

    #[test]
    fn nav_restore_qc() {
        let _ = env_logger::init();
        qc::quickcheck(nav_restore_prop as fn(Vec<String>, NumTries)
                       -> qc::TestResult);
    }

    #[test]
    fn nav_restore_qc_1() {
        let _ = env_logger::init();
        qc::quickcheck(nav_restore_prop_1 as fn(Vec<String>)
                       -> qc::TestResult);
    }

    fn assert_passed(tr: qc::TestResult) {
        assert!(!tr.is_failure());
    }

    #[test]
    fn nav_restore_manual() {
        let _ = env_logger::init();
        assert_passed(nav_restore_prop_1(vec!["\u{194}\u{128}".to_owned()]));
        assert_passed(nav_restore_prop_1(vec!["Testing".to_owned()]));
        assert_passed(nav_restore_prop_1(vec!["\u{80}".to_owned()]));
        assert_passed(nav_restore_prop_1(vec!["\u{7f}".to_owned()]));
        assert_passed(nav_restore_prop_1(vec!["~".to_owned()]));
        assert_passed(nav_restore_prop_1(vec!["\u{0}".to_owned()]));
        assert_passed(nav_restore_prop_1(vec!["Testing".to_owned(),
                                              "Test".to_owned()]));
        assert_passed(nav_restore_prop_1(vec!["Testing".to_owned(),
                                              "trouble".to_owned(),
                                              "Trouble".to_owned(),
                                              "Threep".to_owned(),
                                              "Test".to_owned()]));
    }
}

<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with
// this file, You can obtain one at https://mozilla.org/MPL/2.0/.

use lang::Lang;
use error::{Result, Error};
use macrogen;

use std::fs::File;
use std::io::Write;

/// Main struct for initiating localization for a project.
///
/// # Example
///
/// ```rust
/// use crowbook_localize::Localizer;
/// let fr = r#"
/// msgid "Hello, {}"
/// msgstr "Bonjour, {}"
/// "#;
/// let es = r#"
/// msgid "Hello, {}"
/// msgstr "Hola, {}"
/// "#;
/// let mut localizer = Localizer::new();
/// localizer.add_lang("fr", fr).unwrap();
/// localizer.add_lang("es", es).unwrap();
/// ```
pub struct Localizer {
    langs: Vec<Lang>,
}

impl Localizer {
    /// Create a new, empty Localizer
    pub fn new() -> Localizer {
        Localizer { langs: vec!() }
    }

    /// Add a lang to the localizer
    ///
    /// # Arguments
    ///
    /// * `lang`: the code of the language (e.g. "fr", "en", ...);
    /// * `s`: a string containing localization information. It should be foramtted
    /// similarly to gettext `mo` files.
    pub fn add_lang<S: Into<String>>(&mut self, lang: S, s: &str) -> Result<()> {
        let lang = try!(Lang::new_from_str(lang, s));
        self.langs.push(lang);
        Ok(())
    }

    /// Generate the `localization_macros.rs` file.
    pub fn generate_macro_file(mut self) -> String {
        macrogen::generate_macro_file(&mut self.langs)
    }

    /// Write the `localization_macros.rs` file to a file.
    pub fn write_macro_file(self, file: &str) -> Result<()> {
        let mut f = try!(File::create(file).map_err(|e| Error::new(format!("Could not create file {}: {}",
                                                                              file, e))));
        let content = self.generate_macro_file();
        try!(f.write_all(content.as_bytes())
             .map_err(|e| Error::new(format!("Could not write to file {}: {}",
                                             file, e))));
        Ok(())
    }
}
<commit_msg>Fix docstring<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with
// this file, You can obtain one at https://mozilla.org/MPL/2.0/.

use lang::Lang;
use error::{Result, Error};
use macrogen;

use std::fs::File;
use std::io::Write;

/// Main struct for initiating localization for a project.
///
/// # Example
///
/// ```rust
/// use crowbook_localize::Localizer;
/// let fr = r#"
/// msgid "Hello, {}"
/// msgstr "Bonjour, {}"
/// "#;
/// let es = r#"
/// msgid "Hello, {}"
/// msgstr "Hola, {}"
/// "#;
/// let mut localizer = Localizer::new();
/// localizer.add_lang("fr", fr).unwrap();
/// localizer.add_lang("es", es).unwrap();
/// println!("{}", localizer.generate_macro_file());
/// ```
pub struct Localizer {
    langs: Vec<Lang>,
}

impl Localizer {
    /// Create a new, empty Localizer
    pub fn new() -> Localizer {
        Localizer { langs: vec!() }
    }

    /// Add a lang to the localizer
    ///
    /// # Arguments
    ///
    /// * `lang`: the code of the language (e.g. "fr", "en", ...);
    /// * `s`: a string containing localization information. It should be foramtted
    /// similarly to gettext `mo` files.
    pub fn add_lang<S: Into<String>>(&mut self, lang: S, s: &str) -> Result<()> {
        let lang = try!(Lang::new_from_str(lang, s));
        self.langs.push(lang);
        Ok(())
    }

    /// Generate the `localization_macros.rs` file.
    pub fn generate_macro_file(mut self) -> String {
        macrogen::generate_macro_file(&mut self.langs)
    }

    /// Write the `localization_macros.rs` file to a file.
    pub fn write_macro_file(self, file: &str) -> Result<()> {
        let mut f = try!(File::create(file).map_err(|e| Error::new(format!("Could not create file {}: {}",
                                                                              file, e))));
        let content = self.generate_macro_file();
        try!(f.write_all(content.as_bytes())
             .map_err(|e| Error::new(format!("Could not write to file {}: {}",
                                             file, e))));
        Ok(())
    }
}
<|endoftext|>


<commit_before>use ra_syntax::{
    algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset},
    Direction, SourceFileNode,
    SyntaxKind::*,
    SyntaxNodeRef, TextRange, TextUnit,
};

pub fn extend_selection(file: &SourceFileNode, range: TextRange) -> Option<TextRange> {
    let syntax = file.syntax();
    extend(syntax.borrowed(), range)
}

pub(crate) fn extend(root: SyntaxNodeRef, range: TextRange) -> Option<TextRange> {
    if range.is_empty() {
        let offset = range.start();
        let mut leaves = find_leaf_at_offset(root, offset);
        if leaves.clone().all(|it| it.kind() == WHITESPACE) {
            return Some(extend_ws(root, leaves.next()?, offset));
        }
        let leaf_range = match leaves {
            LeafAtOffset::None => return None,
            LeafAtOffset::Single(l) => {
                if l.kind() == COMMENT {
                    extend_single_word_in_comment(l, offset).unwrap_or_else(|| l.range())
                } else {
                    l.range()
                }
            }
            LeafAtOffset::Between(l, r) => pick_best(l, r).range(),
        };
        return Some(leaf_range);
    };
    let node = find_covering_node(root, range);
    if node.kind() == COMMENT && range == node.range() {
        if let Some(range) = extend_comments(node) {
            return Some(range);
        }
    }

    match node.ancestors().skip_while(|n| n.range() == range).next() {
        None => None,
        Some(parent) => Some(parent.range()),
    }
}

fn extend_single_word_in_comment(leaf: SyntaxNodeRef, offset: TextUnit) -> Option<TextRange> {
    let text: &str = leaf.leaf_text()?;
    let cursor_position: u32 = (offset - leaf.range().start()).into();

    let (before, after) = text.split_at(cursor_position as usize);
    let start_idx = before.rfind(char::is_whitespace)? as u32;
    let end_idx = after.find(char::is_whitespace)? as u32;

    let from: TextUnit = (start_idx + 1).into();
    let to: TextUnit = (cursor_position + end_idx).into();

    Some(TextRange::from_to(from, to) + leaf.range().start())
}

fn extend_ws(root: SyntaxNodeRef, ws: SyntaxNodeRef, offset: TextUnit) -> TextRange {
    let ws_text = ws.leaf_text().unwrap();
    let suffix = TextRange::from_to(offset, ws.range().end()) - ws.range().start();
    let prefix = TextRange::from_to(ws.range().start(), offset) - ws.range().start();
    let ws_suffix = &ws_text.as_str()[suffix];
    let ws_prefix = &ws_text.as_str()[prefix];
    if ws_text.contains('\n') && !ws_suffix.contains('\n') {
        if let Some(node) = ws.next_sibling() {
            let start = match ws_prefix.rfind('\n') {
                Some(idx) => ws.range().start() + TextUnit::from((idx + 1) as u32),
                None => node.range().start(),
            };
            let end = if root.text().char_at(node.range().end()) == Some('\n') {
                node.range().end() + TextUnit::of_char('\n')
            } else {
                node.range().end()
            };
            return TextRange::from_to(start, end);
        }
    }
    ws.range()
}

fn pick_best<'a>(l: SyntaxNodeRef<'a>, r: SyntaxNodeRef<'a>) -> SyntaxNodeRef<'a> {
    return if priority(r) > priority(l) { r } else { l };
    fn priority(n: SyntaxNodeRef) -> usize {
        match n.kind() {
            WHITESPACE => 0,
            IDENT | SELF_KW | SUPER_KW | CRATE_KW | LIFETIME => 2,
            _ => 1,
        }
    }
}

fn extend_comments(node: SyntaxNodeRef) -> Option<TextRange> {
    let prev = adj_comments(node, Direction::Prev);
    let next = adj_comments(node, Direction::Next);
    if prev != next {
        Some(TextRange::from_to(prev.range().start(), next.range().end()))
    } else {
        None
    }
}

fn adj_comments(node: SyntaxNodeRef, dir: Direction) -> SyntaxNodeRef {
    let mut res = node;
    for node in node.siblings(dir) {
        match node.kind() {
            COMMENT => res = node,
            WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (),
            _ => break,
        }
    }
    res
}

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

    fn do_check(before: &str, afters: &[&str]) {
        let (cursor, before) = extract_offset(before);
        let file = SourceFileNode::parse(&before);
        let mut range = TextRange::offset_len(cursor, 0.into());
        for &after in afters {
            range = extend_selection(&file, range).unwrap();
            let actual = &before[range];
            assert_eq!(after, actual);
        }
    }

    #[test]
    fn test_extend_selection_arith() {
        do_check(r#"fn foo() { <|>1 + 1 }"#, &["1", "1 + 1", "{ 1 + 1 }"]);
    }

    #[test]
    fn test_extend_selection_start_of_the_lind() {
        do_check(
            r#"
impl S {
<|>    fn foo() {

    }
}"#,
            &["    fn foo() {\n\n    }\n"],
        );
    }

    #[test]
    fn test_extend_selection_doc_comments() {
        do_check(
            r#"
struct A;

/// bla
/// bla
struct B {
    <|>
}
            "#,
            &[
                "\n    \n",
                "{\n    \n}",
                "/// bla\n/// bla\nstruct B {\n    \n}",
            ],
        )
    }

    #[test]
    fn test_extend_selection_comments() {
        do_check(
            r#"
fn bar(){}

// fn foo() {
// 1 + <|>1
// }

// fn foo(){}
    "#,
            &["// 1 + 1", "// fn foo() {\n// 1 + 1\n// }"],
        );
    }

    #[test]
    fn test_extend_selection_prefer_idents() {
        do_check(
            r#"
fn main() { foo<|>+bar;}
    "#,
            &["foo", "foo+bar"],
        );
        do_check(
            r#"
fn main() { foo+<|>bar;}
    "#,
            &["bar", "foo+bar"],
        );
    }

    #[test]
    fn test_extend_selection_prefer_lifetimes() {
        do_check(r#"fn foo<<|>'a>() {}"#, &["'a", "<'a>"]);
        do_check(r#"fn foo<'a<|>>() {}"#, &["'a", "<'a>"]);
    }

    #[test]
    fn test_extend_selection_select_first_word() {
        do_check(r#"// foo bar b<|>az quxx"#, &["baz", "// foo bar baz quxx"]);
        do_check(
            r#"
impl S {
    fn foo() {
        // hel<|>lo world
    }
}
        "#,
            &["hello", "// hello world"],
        );
    }
}
<commit_msg>check for empty range when extending in comment<commit_after>use ra_syntax::{
    algo::{find_covering_node, find_leaf_at_offset, LeafAtOffset},
    Direction, SourceFileNode,
    SyntaxKind::*,
    SyntaxNodeRef, TextRange, TextUnit,
};

pub fn extend_selection(file: &SourceFileNode, range: TextRange) -> Option<TextRange> {
    let syntax = file.syntax();
    extend(syntax.borrowed(), range)
}

pub(crate) fn extend(root: SyntaxNodeRef, range: TextRange) -> Option<TextRange> {
    if range.is_empty() {
        let offset = range.start();
        let mut leaves = find_leaf_at_offset(root, offset);
        if leaves.clone().all(|it| it.kind() == WHITESPACE) {
            return Some(extend_ws(root, leaves.next()?, offset));
        }
        let leaf_range = match leaves {
            LeafAtOffset::None => return None,
            LeafAtOffset::Single(l) => {
                if l.kind() == COMMENT {
                    extend_single_word_in_comment(l, offset).unwrap_or_else(|| l.range())
                } else {
                    l.range()
                }
            }
            LeafAtOffset::Between(l, r) => pick_best(l, r).range(),
        };
        return Some(leaf_range);
    };
    let node = find_covering_node(root, range);
    if node.kind() == COMMENT && range == node.range() {
        if let Some(range) = extend_comments(node) {
            return Some(range);
        }
    }

    match node.ancestors().skip_while(|n| n.range() == range).next() {
        None => None,
        Some(parent) => Some(parent.range()),
    }
}

fn extend_single_word_in_comment(leaf: SyntaxNodeRef, offset: TextUnit) -> Option<TextRange> {
    let text: &str = leaf.leaf_text()?;
    let cursor_position: u32 = (offset - leaf.range().start()).into();

    let (before, after) = text.split_at(cursor_position as usize);
    let start_idx = before.rfind(char::is_whitespace)? as u32;
    let end_idx = after.find(char::is_whitespace)? as u32;

    let from: TextUnit = (start_idx + 1).into();
    let to: TextUnit = (cursor_position + end_idx).into();

    let range = TextRange::from_to(from, to);
    if range.is_empty() {
        None
    } else {
        Some(range + leaf.range().start())
    }
}

fn extend_ws(root: SyntaxNodeRef, ws: SyntaxNodeRef, offset: TextUnit) -> TextRange {
    let ws_text = ws.leaf_text().unwrap();
    let suffix = TextRange::from_to(offset, ws.range().end()) - ws.range().start();
    let prefix = TextRange::from_to(ws.range().start(), offset) - ws.range().start();
    let ws_suffix = &ws_text.as_str()[suffix];
    let ws_prefix = &ws_text.as_str()[prefix];
    if ws_text.contains('\n') && !ws_suffix.contains('\n') {
        if let Some(node) = ws.next_sibling() {
            let start = match ws_prefix.rfind('\n') {
                Some(idx) => ws.range().start() + TextUnit::from((idx + 1) as u32),
                None => node.range().start(),
            };
            let end = if root.text().char_at(node.range().end()) == Some('\n') {
                node.range().end() + TextUnit::of_char('\n')
            } else {
                node.range().end()
            };
            return TextRange::from_to(start, end);
        }
    }
    ws.range()
}

fn pick_best<'a>(l: SyntaxNodeRef<'a>, r: SyntaxNodeRef<'a>) -> SyntaxNodeRef<'a> {
    return if priority(r) > priority(l) { r } else { l };
    fn priority(n: SyntaxNodeRef) -> usize {
        match n.kind() {
            WHITESPACE => 0,
            IDENT | SELF_KW | SUPER_KW | CRATE_KW | LIFETIME => 2,
            _ => 1,
        }
    }
}

fn extend_comments(node: SyntaxNodeRef) -> Option<TextRange> {
    let prev = adj_comments(node, Direction::Prev);
    let next = adj_comments(node, Direction::Next);
    if prev != next {
        Some(TextRange::from_to(prev.range().start(), next.range().end()))
    } else {
        None
    }
}

fn adj_comments(node: SyntaxNodeRef, dir: Direction) -> SyntaxNodeRef {
    let mut res = node;
    for node in node.siblings(dir) {
        match node.kind() {
            COMMENT => res = node,
            WHITESPACE if !node.leaf_text().unwrap().as_str().contains("\n\n") => (),
            _ => break,
        }
    }
    res
}

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

    fn do_check(before: &str, afters: &[&str]) {
        let (cursor, before) = extract_offset(before);
        let file = SourceFileNode::parse(&before);
        let mut range = TextRange::offset_len(cursor, 0.into());
        for &after in afters {
            range = extend_selection(&file, range).unwrap();
            let actual = &before[range];
            assert_eq!(after, actual);
        }
    }

    #[test]
    fn test_extend_selection_arith() {
        do_check(r#"fn foo() { <|>1 + 1 }"#, &["1", "1 + 1", "{ 1 + 1 }"]);
    }

    #[test]
    fn test_extend_selection_start_of_the_lind() {
        do_check(
            r#"
impl S {
<|>    fn foo() {

    }
}"#,
            &["    fn foo() {\n\n    }\n"],
        );
    }

    #[test]
    fn test_extend_selection_doc_comments() {
        do_check(
            r#"
struct A;

/// bla
/// bla
struct B {
    <|>
}
            "#,
            &[
                "\n    \n",
                "{\n    \n}",
                "/// bla\n/// bla\nstruct B {\n    \n}",
            ],
        )
    }

    #[test]
    fn test_extend_selection_comments() {
        do_check(
            r#"
fn bar(){}

// fn foo() {
// 1 + <|>1
// }

// fn foo(){}
    "#,
            &["// 1 + 1", "// fn foo() {\n// 1 + 1\n// }"],
        );

        do_check(
            r#"
// #[derive(Debug, Clone, Copy, PartialEq, Eq)]
// pub enum Direction {
//  <|>   Next,
//     Prev
// }
"#,
            &[
                "//     Next,",
                "// #[derive(Debug, Clone, Copy, PartialEq, Eq)]\n// pub enum Direction {\n//     Next,\n//     Prev\n// }",
            ],
        );
    }

    #[test]
    fn test_extend_selection_prefer_idents() {
        do_check(
            r#"
fn main() { foo<|>+bar;}
    "#,
            &["foo", "foo+bar"],
        );
        do_check(
            r#"
fn main() { foo+<|>bar;}
    "#,
            &["bar", "foo+bar"],
        );
    }

    #[test]
    fn test_extend_selection_prefer_lifetimes() {
        do_check(r#"fn foo<<|>'a>() {}"#, &["'a", "<'a>"]);
        do_check(r#"fn foo<'a<|>>() {}"#, &["'a", "<'a>"]);
    }

    #[test]
    fn test_extend_selection_select_first_word() {
        do_check(r#"// foo bar b<|>az quxx"#, &["baz", "// foo bar baz quxx"]);
        do_check(
            r#"
impl S {
    fn foo() {
        // hel<|>lo world
    }
}
        "#,
            &["hello", "// hello world"],
        );
    }
}
<|endoftext|>


<commit_before>//! Implementation of Chalk debug helper functions using TLS.
use std::fmt;

use chalk_ir::{AliasTy, Goal, Goals, Lifetime, Parameter, ProgramClauseImplication, TypeName};

use super::{from_chalk, Interner};
use crate::{db::HirDatabase, CallableDef, TypeCtor};
use hir_def::{AdtId, AssocContainerId, Lookup, TypeAliasId};

pub use unsafe_tls::{set_current_program, with_current_program};

pub struct DebugContext<'a>(&'a (dyn HirDatabase + 'a));

impl DebugContext<'_> {
    pub fn debug_struct_id(
        &self,
        id: super::StructId,
        f: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        let type_ctor: TypeCtor = from_chalk(self.0, TypeName::Struct(id));
        match type_ctor {
            TypeCtor::Bool => write!(f, "bool")?,
            TypeCtor::Char => write!(f, "char")?,
            TypeCtor::Int(t) => write!(f, "{}", t)?,
            TypeCtor::Float(t) => write!(f, "{}", t)?,
            TypeCtor::Str => write!(f, "str")?,
            TypeCtor::Slice => write!(f, "slice")?,
            TypeCtor::Array => write!(f, "array")?,
            TypeCtor::RawPtr(m) => write!(f, "*{}", m.as_keyword_for_ptr())?,
            TypeCtor::Ref(m) => write!(f, "&{}", m.as_keyword_for_ref())?,
            TypeCtor::Never => write!(f, "!")?,
            TypeCtor::Tuple { .. } => {
                write!(f, "()")?;
            }
            TypeCtor::FnPtr { .. } => {
                write!(f, "fn")?;
            }
            TypeCtor::FnDef(def) => {
                let name = match def {
                    CallableDef::FunctionId(ff) => self.0.function_data(ff).name.clone(),
                    CallableDef::StructId(s) => self.0.struct_data(s).name.clone(),
                    CallableDef::EnumVariantId(e) => {
                        let enum_data = self.0.enum_data(e.parent);
                        enum_data.variants[e.local_id].name.clone()
                    }
                };
                match def {
                    CallableDef::FunctionId(_) => write!(f, "{{fn {}}}", name)?,
                    CallableDef::StructId(_) | CallableDef::EnumVariantId(_) => {
                        write!(f, "{{ctor {}}}", name)?
                    }
                }
            }
            TypeCtor::Adt(def_id) => {
                let name = match def_id {
                    AdtId::StructId(it) => self.0.struct_data(it).name.clone(),
                    AdtId::UnionId(it) => self.0.union_data(it).name.clone(),
                    AdtId::EnumId(it) => self.0.enum_data(it).name.clone(),
                };
                write!(f, "{}", name)?;
            }
            TypeCtor::AssociatedType(type_alias) => {
                let trait_ = match type_alias.lookup(self.0.upcast()).container {
                    AssocContainerId::TraitId(it) => it,
                    _ => panic!("not an associated type"),
                };
                let trait_name = self.0.trait_data(trait_).name.clone();
                let name = self.0.type_alias_data(type_alias).name.clone();
                write!(f, "{}::{}", trait_name, name)?;
            }
            TypeCtor::Closure { def, expr } => {
                write!(f, "{{closure {:?} in {:?}}}", expr.into_raw(), def)?;
            }
        }
        Ok(())
    }

    pub fn debug_trait_id(
        &self,
        id: super::TraitId,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        let trait_: hir_def::TraitId = from_chalk(self.0, id);
        let trait_data = self.0.trait_data(trait_);
        write!(fmt, "{}", trait_data.name)
    }

    pub fn debug_assoc_type_id(
        &self,
        id: super::AssocTypeId,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        let type_alias: TypeAliasId = from_chalk(self.0, id);
        let type_alias_data = self.0.type_alias_data(type_alias);
        let trait_ = match type_alias.lookup(self.0.upcast()).container {
            AssocContainerId::TraitId(t) => t,
            _ => panic!("associated type not in trait"),
        };
        let trait_data = self.0.trait_data(trait_);
        write!(fmt, "{}::{}", trait_data.name, type_alias_data.name)
    }

    pub fn debug_alias(
        &self,
        alias: &AliasTy<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        let type_alias: TypeAliasId = from_chalk(self.0, alias.associated_ty_id);
        let type_alias_data = self.0.type_alias_data(type_alias);
        let trait_ = match type_alias.lookup(self.0.upcast()).container {
            AssocContainerId::TraitId(t) => t,
            _ => panic!("associated type not in trait"),
        };
        let trait_data = self.0.trait_data(trait_);
        let params = alias.substitution.parameters(&Interner);
        write!(
            fmt,
            "<{:?} as {}<{:?}>>::{}",
            &params[0],
            trait_data.name,
            &params[1..],
            type_alias_data.name
        )
    }

    pub fn debug_ty(
        &self,
        ty: &chalk_ir::Ty<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        write!(fmt, "{:?}", ty.data(&Interner))
    }

    pub fn debug_lifetime(
        &self,
        lifetime: &Lifetime<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        write!(fmt, "{:?}", lifetime.data(&Interner))
    }

    pub fn debug_parameter(
        &self,
        parameter: &Parameter<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        write!(fmt, "{:?}", parameter.data(&Interner).inner_debug())
    }

    pub fn debug_goal(
        &self,
        goal: &Goal<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        let goal_data = goal.data(&Interner);
        write!(fmt, "{:?}", goal_data)
    }

    pub fn debug_goals(
        &self,
        goals: &Goals<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        write!(fmt, "{:?}", goals.debug(&Interner))
    }

    pub fn debug_program_clause_implication(
        &self,
        pci: &ProgramClauseImplication<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        write!(fmt, "{:?}", pci.debug(&Interner))
    }

    pub fn debug_application_ty(
        &self,
        application_ty: &chalk_ir::ApplicationTy<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        write!(fmt, "{:?}", application_ty.debug(&Interner))
    }

    pub fn debug_substitution(
        &self,
        substitution: &chalk_ir::Substitution<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        write!(fmt, "{:?}", substitution.debug(&Interner))
    }

    pub fn debug_separator_trait_ref(
        &self,
        separator_trait_ref: &chalk_ir::SeparatorTraitRef<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        write!(fmt, "{:?}", separator_trait_ref.debug(&Interner))
    }
}

mod unsafe_tls {
    use super::DebugContext;
    use crate::db::HirDatabase;
    use scoped_tls::scoped_thread_local;

    scoped_thread_local!(static PROGRAM: DebugContext);

    pub fn with_current_program<R>(
        op: impl for<'a> FnOnce(Option<&'a DebugContext<'a>>) -> R,
    ) -> R {
        if PROGRAM.is_set() {
            PROGRAM.with(|prog| op(Some(prog)))
        } else {
            op(None)
        }
    }

    pub fn set_current_program<OP, R>(p: &dyn HirDatabase, op: OP) -> R
    where
        OP: FnOnce() -> R,
    {
        let ctx = DebugContext(p);
        // we're transmuting the lifetime in the DebugContext to static. This is
        // fine because we only keep the reference for the lifetime of this
        // function, *and* the only way to access the context is through
        // `with_current_program`, which hides the lifetime through the `for`
        // type.
        let static_p: &DebugContext<'static> =
            unsafe { std::mem::transmute::<&DebugContext, &DebugContext<'static>>(&ctx) };
        PROGRAM.set(static_p, || op())
    }
}
<commit_msg>Nicer display of closures in Chalk logs<commit_after>//! Implementation of Chalk debug helper functions using TLS.
use std::fmt;

use chalk_ir::{AliasTy, Goal, Goals, Lifetime, Parameter, ProgramClauseImplication, TypeName};

use super::{from_chalk, Interner};
use crate::{db::HirDatabase, CallableDef, TypeCtor};
use hir_def::{AdtId, AssocContainerId, DefWithBodyId, Lookup, TypeAliasId};

pub use unsafe_tls::{set_current_program, with_current_program};

pub struct DebugContext<'a>(&'a (dyn HirDatabase + 'a));

impl DebugContext<'_> {
    pub fn debug_struct_id(
        &self,
        id: super::StructId,
        f: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        let type_ctor: TypeCtor = from_chalk(self.0, TypeName::Struct(id));
        match type_ctor {
            TypeCtor::Bool => write!(f, "bool")?,
            TypeCtor::Char => write!(f, "char")?,
            TypeCtor::Int(t) => write!(f, "{}", t)?,
            TypeCtor::Float(t) => write!(f, "{}", t)?,
            TypeCtor::Str => write!(f, "str")?,
            TypeCtor::Slice => write!(f, "slice")?,
            TypeCtor::Array => write!(f, "array")?,
            TypeCtor::RawPtr(m) => write!(f, "*{}", m.as_keyword_for_ptr())?,
            TypeCtor::Ref(m) => write!(f, "&{}", m.as_keyword_for_ref())?,
            TypeCtor::Never => write!(f, "!")?,
            TypeCtor::Tuple { .. } => {
                write!(f, "()")?;
            }
            TypeCtor::FnPtr { .. } => {
                write!(f, "fn")?;
            }
            TypeCtor::FnDef(def) => {
                let name = match def {
                    CallableDef::FunctionId(ff) => self.0.function_data(ff).name.clone(),
                    CallableDef::StructId(s) => self.0.struct_data(s).name.clone(),
                    CallableDef::EnumVariantId(e) => {
                        let enum_data = self.0.enum_data(e.parent);
                        enum_data.variants[e.local_id].name.clone()
                    }
                };
                match def {
                    CallableDef::FunctionId(_) => write!(f, "{{fn {}}}", name)?,
                    CallableDef::StructId(_) | CallableDef::EnumVariantId(_) => {
                        write!(f, "{{ctor {}}}", name)?
                    }
                }
            }
            TypeCtor::Adt(def_id) => {
                let name = match def_id {
                    AdtId::StructId(it) => self.0.struct_data(it).name.clone(),
                    AdtId::UnionId(it) => self.0.union_data(it).name.clone(),
                    AdtId::EnumId(it) => self.0.enum_data(it).name.clone(),
                };
                write!(f, "{}", name)?;
            }
            TypeCtor::AssociatedType(type_alias) => {
                let trait_ = match type_alias.lookup(self.0.upcast()).container {
                    AssocContainerId::TraitId(it) => it,
                    _ => panic!("not an associated type"),
                };
                let trait_name = self.0.trait_data(trait_).name.clone();
                let name = self.0.type_alias_data(type_alias).name.clone();
                write!(f, "{}::{}", trait_name, name)?;
            }
            TypeCtor::Closure { def, expr } => {
                write!(f, "{{closure {:?} in ", expr.into_raw())?;
                match def {
                    DefWithBodyId::FunctionId(func) => {
                        write!(f, "fn {}", self.0.function_data(func).name)?
                    }
                    DefWithBodyId::StaticId(s) => {
                        if let Some(name) = self.0.static_data(s).name.as_ref() {
                            write!(f, "body of static {}", name)?;
                        } else {
                            write!(f, "body of unnamed static {:?}", s)?;
                        }
                    }
                    DefWithBodyId::ConstId(c) => {
                        if let Some(name) = self.0.const_data(c).name.as_ref() {
                            write!(f, "body of const {}", name)?;
                        } else {
                            write!(f, "body of unnamed const {:?}", c)?;
                        }
                    }
                };
                write!(f, "}}")?;
            }
        }
        Ok(())
    }

    pub fn debug_trait_id(
        &self,
        id: super::TraitId,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        let trait_: hir_def::TraitId = from_chalk(self.0, id);
        let trait_data = self.0.trait_data(trait_);
        write!(fmt, "{}", trait_data.name)
    }

    pub fn debug_assoc_type_id(
        &self,
        id: super::AssocTypeId,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        let type_alias: TypeAliasId = from_chalk(self.0, id);
        let type_alias_data = self.0.type_alias_data(type_alias);
        let trait_ = match type_alias.lookup(self.0.upcast()).container {
            AssocContainerId::TraitId(t) => t,
            _ => panic!("associated type not in trait"),
        };
        let trait_data = self.0.trait_data(trait_);
        write!(fmt, "{}::{}", trait_data.name, type_alias_data.name)
    }

    pub fn debug_alias(
        &self,
        alias: &AliasTy<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        let type_alias: TypeAliasId = from_chalk(self.0, alias.associated_ty_id);
        let type_alias_data = self.0.type_alias_data(type_alias);
        let trait_ = match type_alias.lookup(self.0.upcast()).container {
            AssocContainerId::TraitId(t) => t,
            _ => panic!("associated type not in trait"),
        };
        let trait_data = self.0.trait_data(trait_);
        let params = alias.substitution.parameters(&Interner);
        write!(
            fmt,
            "<{:?} as {}<{:?}>>::{}",
            &params[0],
            trait_data.name,
            &params[1..],
            type_alias_data.name
        )
    }

    pub fn debug_ty(
        &self,
        ty: &chalk_ir::Ty<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        write!(fmt, "{:?}", ty.data(&Interner))
    }

    pub fn debug_lifetime(
        &self,
        lifetime: &Lifetime<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        write!(fmt, "{:?}", lifetime.data(&Interner))
    }

    pub fn debug_parameter(
        &self,
        parameter: &Parameter<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        write!(fmt, "{:?}", parameter.data(&Interner).inner_debug())
    }

    pub fn debug_goal(
        &self,
        goal: &Goal<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        let goal_data = goal.data(&Interner);
        write!(fmt, "{:?}", goal_data)
    }

    pub fn debug_goals(
        &self,
        goals: &Goals<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        write!(fmt, "{:?}", goals.debug(&Interner))
    }

    pub fn debug_program_clause_implication(
        &self,
        pci: &ProgramClauseImplication<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        write!(fmt, "{:?}", pci.debug(&Interner))
    }

    pub fn debug_application_ty(
        &self,
        application_ty: &chalk_ir::ApplicationTy<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        write!(fmt, "{:?}", application_ty.debug(&Interner))
    }

    pub fn debug_substitution(
        &self,
        substitution: &chalk_ir::Substitution<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        write!(fmt, "{:?}", substitution.debug(&Interner))
    }

    pub fn debug_separator_trait_ref(
        &self,
        separator_trait_ref: &chalk_ir::SeparatorTraitRef<Interner>,
        fmt: &mut fmt::Formatter<'_>,
    ) -> Result<(), fmt::Error> {
        write!(fmt, "{:?}", separator_trait_ref.debug(&Interner))
    }
}

mod unsafe_tls {
    use super::DebugContext;
    use crate::db::HirDatabase;
    use scoped_tls::scoped_thread_local;

    scoped_thread_local!(static PROGRAM: DebugContext);

    pub fn with_current_program<R>(
        op: impl for<'a> FnOnce(Option<&'a DebugContext<'a>>) -> R,
    ) -> R {
        if PROGRAM.is_set() {
            PROGRAM.with(|prog| op(Some(prog)))
        } else {
            op(None)
        }
    }

    pub fn set_current_program<OP, R>(p: &dyn HirDatabase, op: OP) -> R
    where
        OP: FnOnce() -> R,
    {
        let ctx = DebugContext(p);
        // we're transmuting the lifetime in the DebugContext to static. This is
        // fine because we only keep the reference for the lifetime of this
        // function, *and* the only way to access the context is through
        // `with_current_program`, which hides the lifetime through the `for`
        // type.
        let static_p: &DebugContext<'static> =
            unsafe { std::mem::transmute::<&DebugContext, &DebugContext<'static>>(&ctx) };
        PROGRAM.set(static_p, || op())
    }
}
<|endoftext|>


<commit_before>extern crate gigasecond;

//Note: Your code must also start with the following two lines.
extern crate chrono;
use chrono::*;

#[test]
fn test_date() {
    let start_date = UTC.ymd(2011, 4, 25).and_hms(0,0,0);
    assert_eq!(gigasecond::after(start_date), UTC.ymd(2043, 1, 1).and_hms(1,46,40));
}

#[test]
#[ignore]
fn test_another_date() {
    let start_date = UTC.ymd(1977, 6, 13).and_hms(0,0,0);
    assert_eq!(gigasecond::after(start_date), UTC.ymd(2009, 2, 19).and_hms(1,46,40));
}

#[test]
#[ignore]
fn test_third_date() {
    let start_date = UTC.ymd(1959, 7, 19).and_hms(0,0,0);
    assert_eq!(gigasecond::after(start_date), UTC.ymd(1991, 3, 27).and_hms(1,46,40));
}

#[test]
#[ignore]
fn test_datetime() {
    let start_date = UTC.ymd(2015, 1, 24).and_hms(22,0,0);
    assert_eq!(gigasecond::after(start_date), UTC.ymd(2046, 10, 2).and_hms(23,46,40));
}

#[test]
#[ignore]
fn test_another_datetime() {
    let start_date = UTC.ymd(2015, 1, 24).and_hms(23,59,59);
    assert_eq!(gigasecond::after(start_date), UTC.ymd(2046, 10, 3).and_hms(1,46,39));
}
<commit_msg>Add documentation about crates & chrono<commit_after>extern crate gigasecond;

/*
 * Students,
 *
 * Rust does not currently have a library for handling Time. To solve this exercise
 * you'll need to use the Chrono 'crate' (which is Rust's term for an external library).
 *
 * The first time you run `cargo test`, the Chrono crate will automatically be downloaded
 * and installed. More information on crates can be found at
 * https://doc.rust-lang.org/book/guessing-game.html#generating-a-secret-number
 *
 * In order to use the crate, your solution will need to start with the two following lines
*/
extern crate chrono;
use chrono::*;

#[test]
fn test_date() {
    let start_date = UTC.ymd(2011, 4, 25).and_hms(0,0,0);
    assert_eq!(gigasecond::after(start_date), UTC.ymd(2043, 1, 1).and_hms(1,46,40));
}

#[test]
#[ignore]
fn test_another_date() {
    let start_date = UTC.ymd(1977, 6, 13).and_hms(0,0,0);
    assert_eq!(gigasecond::after(start_date), UTC.ymd(2009, 2, 19).and_hms(1,46,40));
}

#[test]
#[ignore]
fn test_third_date() {
    let start_date = UTC.ymd(1959, 7, 19).and_hms(0,0,0);
    assert_eq!(gigasecond::after(start_date), UTC.ymd(1991, 3, 27).and_hms(1,46,40));
}

#[test]
#[ignore]
fn test_datetime() {
    let start_date = UTC.ymd(2015, 1, 24).and_hms(22,0,0);
    assert_eq!(gigasecond::after(start_date), UTC.ymd(2046, 10, 2).and_hms(23,46,40));
}

#[test]
#[ignore]
fn test_another_datetime() {
    let start_date = UTC.ymd(2015, 1, 24).and_hms(23,59,59);
    assert_eq!(gigasecond::after(start_date), UTC.ymd(2046, 10, 3).and_hms(1,46,39));
}
<|endoftext|>


<commit_before>//! Status symbol interleaving and deinterleaving.

use bits;
use consts::SYNC_SYMBOLS;

use self::StatusCode::*;
use self::StreamSymbol::*;

/// Number of dibits output per status period, including the status symbol.
const DIBITS_PER_UPDATE: u32 = 70 / 2 + 1;

/// A source of status symbols.
pub trait StatusSource {
    /// The current status.
    fn status(&mut self) -> StatusCode;
}

/// Interleaves status symbols into a stream of dibits.
pub struct StatusInterleaver<T, S> where
    T: Iterator<Item = bits::Dibit>,
    S: StatusSource
{
    /// Source of dibits to interleave status symbols into.
    src: T,
    /// Source of status updates.
    status: S,
    /// Current dibit index in output stream.
    pos: u32,
}

impl<T, S> StatusInterleaver<T, S> where
    T: Iterator<Item = bits::Dibit>,
    S: StatusSource
{
    pub fn new(src: T, status: S) -> StatusInterleaver<T, S> {
        StatusInterleaver {
            status: status,
            src: src,
            pos: 0,
        }
    }
}

impl<T, S> Iterator for StatusInterleaver<T, S> where
    T: Iterator<Item = bits::Dibit>,
    S: StatusSource
{
    type Item = bits::Dibit;

    fn next(&mut self) -> Option<Self::Item> {
        self.pos += 1;
        self.pos %= DIBITS_PER_UPDATE;

        if self.pos == 0 {
            return Some(self.status.status().to_dibit());
        }

        match self.src.next() {
            Some(d) => Some(d),
            // If just after an update and no more source dibits, end the iteration.
            None if self.pos == 1 => None,
            // Pad until the next update.
            None => Some(bits::Dibit::new(0b00)),
        }
    }
}

/// A P25 status symbol.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum StatusCode {
    /// Used by a repeater when the inbound channel is idle.
    InboundIdle,
    /// Used by a repeater when the inbound channel is busy.
    InboundBusy,
    /// Used when a subscriber is transmitting to a repeater.
    SubscriberRepeater,
    /// Used when a subscriber is transmitting directly to another subscriber.
    SubscriberDirect,
}

impl StatusCode {
    /// Parse a status code from the given dibit.
    pub fn from_dibit(d: bits::Dibit) -> StatusCode {
        match d.bits() {
            0b01 => InboundBusy,
            0b00 => SubscriberDirect,
            0b10 => SubscriberRepeater,
            0b11 => InboundIdle,
            _ => unreachable!(),
        }
    }

    /// Convert the current status code into a dibit.
    pub fn to_dibit(&self) -> bits::Dibit {
        bits::Dibit::new(match *self {
            InboundBusy => 0b01,
            SubscriberDirect => 0b00,
            SubscriberRepeater => 0b10,
            InboundIdle => 0b11,
        })
    }
}

/// A symbol in a transmitted P25 stream.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum StreamSymbol {
    /// Current symbol is a status code.
    Status(StatusCode),
    /// Current symbol is a data dibit.
    Data(bits::Dibit),
}

/// Deinterleave a P25 transmitted stream into status codes and data symbols.
#[derive(Copy, Clone)]
pub struct StatusDeinterleaver {
    /// Current dibit position in current status period.
    pos: u32,
}

impl StatusDeinterleaver {
    /// Create a new `StatusDeinterleaver` for deinterlacing immediately after the frame sync
    /// sequence.
    pub fn new() -> StatusDeinterleaver {
        StatusDeinterleaver {
            // Since stream deinterleaving is started after the frame sync, and the frame sync
            // symbols count towards the first status symbol period, start the counter with those
            // symbols taken into account.
            pos: SYNC_SYMBOLS as u32,
        }
    }

    /// Parse the given symbol as a status or data symbol.
    pub fn feed(&mut self, d: bits::Dibit) -> StreamSymbol {
        self.pos += 1;
        self.pos %= DIBITS_PER_UPDATE;

        if self.pos == 0 {
            Status(StatusCode::from_dibit(d))
        } else {
            Data(d)
        }
    }
}

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

    #[test]
    fn test_interleave() {
        struct TestSource;
        impl StatusSource for TestSource {
            fn status(&mut self) -> StatusCode { StatusCode::InboundBusy }
        }

        let src = std::iter::repeat(bits::Dibit::new(0b10));
        let mut i = StatusInterleaver::new(src, TestSource);

        for _ in 0..35 {
            assert_eq!(i.next(), Some(bits::Dibit::new(0b10)));
        }

        assert_eq!(i.next(), Some(bits::Dibit::new(0b01)));

        for _ in 0..35 {
            assert_eq!(i.next(), Some(bits::Dibit::new(0b10)));
        }

        assert_eq!(i.next(), Some(bits::Dibit::new(0b01)));
    }

    #[test]
    fn test_deinterleave() {
        let mut d = StatusDeinterleaver::new();

        for _ in 0..11 {
            assert_eq!(d.feed(bits::Dibit::new(0)),
                StreamSymbol::Data(bits::Dibit::new(0)));
        }

        assert_eq!(d.feed(bits::Dibit::new(0)), StreamSymbol::Status(
                StatusCode::SubscriberDirect));

        for _ in 0..35 {
            assert_eq!(d.feed(bits::Dibit::new(0)),
                StreamSymbol::Data(bits::Dibit::new(0)));
        }

        assert_eq!(d.feed(bits::Dibit::new(0)), StreamSymbol::Status(
                StatusCode::SubscriberDirect));

        for _ in 0..35 {
            assert_eq!(d.feed(bits::Dibit::new(0)),
                StreamSymbol::Data(bits::Dibit::new(0)));
        }

        assert_eq!(d.feed(bits::Dibit::new(0)), StreamSymbol::Status(
                StatusCode::SubscriberDirect));
    }
}
<commit_msg>Make to_dibit by-value<commit_after>//! Status symbol interleaving and deinterleaving.

use bits;
use consts::SYNC_SYMBOLS;

use self::StatusCode::*;
use self::StreamSymbol::*;

/// Number of dibits output per status period, including the status symbol.
const DIBITS_PER_UPDATE: u32 = 70 / 2 + 1;

/// A source of status symbols.
pub trait StatusSource {
    /// The current status.
    fn status(&mut self) -> StatusCode;
}

/// Interleaves status symbols into a stream of dibits.
pub struct StatusInterleaver<T, S> where
    T: Iterator<Item = bits::Dibit>,
    S: StatusSource
{
    /// Source of dibits to interleave status symbols into.
    src: T,
    /// Source of status updates.
    status: S,
    /// Current dibit index in output stream.
    pos: u32,
}

impl<T, S> StatusInterleaver<T, S> where
    T: Iterator<Item = bits::Dibit>,
    S: StatusSource
{
    pub fn new(src: T, status: S) -> StatusInterleaver<T, S> {
        StatusInterleaver {
            status: status,
            src: src,
            pos: 0,
        }
    }
}

impl<T, S> Iterator for StatusInterleaver<T, S> where
    T: Iterator<Item = bits::Dibit>,
    S: StatusSource
{
    type Item = bits::Dibit;

    fn next(&mut self) -> Option<Self::Item> {
        self.pos += 1;
        self.pos %= DIBITS_PER_UPDATE;

        if self.pos == 0 {
            return Some(self.status.status().to_dibit());
        }

        match self.src.next() {
            Some(d) => Some(d),
            // If just after an update and no more source dibits, end the iteration.
            None if self.pos == 1 => None,
            // Pad until the next update.
            None => Some(bits::Dibit::new(0b00)),
        }
    }
}

/// A P25 status symbol.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum StatusCode {
    /// Used by a repeater when the inbound channel is idle.
    InboundIdle,
    /// Used by a repeater when the inbound channel is busy.
    InboundBusy,
    /// Used when a subscriber is transmitting to a repeater.
    SubscriberRepeater,
    /// Used when a subscriber is transmitting directly to another subscriber.
    SubscriberDirect,
}

impl StatusCode {
    /// Parse a status code from the given dibit.
    pub fn from_dibit(d: bits::Dibit) -> StatusCode {
        match d.bits() {
            0b01 => InboundBusy,
            0b00 => SubscriberDirect,
            0b10 => SubscriberRepeater,
            0b11 => InboundIdle,
            _ => unreachable!(),
        }
    }

    /// Convert the current status code into a dibit.
    pub fn to_dibit(self) -> bits::Dibit {
        bits::Dibit::new(match self {
            InboundBusy => 0b01,
            SubscriberDirect => 0b00,
            SubscriberRepeater => 0b10,
            InboundIdle => 0b11,
        })
    }
}

/// A symbol in a transmitted P25 stream.
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub enum StreamSymbol {
    /// Current symbol is a status code.
    Status(StatusCode),
    /// Current symbol is a data dibit.
    Data(bits::Dibit),
}

/// Deinterleave a P25 transmitted stream into status codes and data symbols.
#[derive(Copy, Clone)]
pub struct StatusDeinterleaver {
    /// Current dibit position in current status period.
    pos: u32,
}

impl StatusDeinterleaver {
    /// Create a new `StatusDeinterleaver` for deinterlacing immediately after the frame sync
    /// sequence.
    pub fn new() -> StatusDeinterleaver {
        StatusDeinterleaver {
            // Since stream deinterleaving is started after the frame sync, and the frame sync
            // symbols count towards the first status symbol period, start the counter with those
            // symbols taken into account.
            pos: SYNC_SYMBOLS as u32,
        }
    }

    /// Parse the given symbol as a status or data symbol.
    pub fn feed(&mut self, d: bits::Dibit) -> StreamSymbol {
        self.pos += 1;
        self.pos %= DIBITS_PER_UPDATE;

        if self.pos == 0 {
            Status(StatusCode::from_dibit(d))
        } else {
            Data(d)
        }
    }
}

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

    #[test]
    fn test_interleave() {
        struct TestSource;
        impl StatusSource for TestSource {
            fn status(&mut self) -> StatusCode { StatusCode::InboundBusy }
        }

        let src = std::iter::repeat(bits::Dibit::new(0b10));
        let mut i = StatusInterleaver::new(src, TestSource);

        for _ in 0..35 {
            assert_eq!(i.next(), Some(bits::Dibit::new(0b10)));
        }

        assert_eq!(i.next(), Some(bits::Dibit::new(0b01)));

        for _ in 0..35 {
            assert_eq!(i.next(), Some(bits::Dibit::new(0b10)));
        }

        assert_eq!(i.next(), Some(bits::Dibit::new(0b01)));
    }

    #[test]
    fn test_deinterleave() {
        let mut d = StatusDeinterleaver::new();

        for _ in 0..11 {
            assert_eq!(d.feed(bits::Dibit::new(0)),
                StreamSymbol::Data(bits::Dibit::new(0)));
        }

        assert_eq!(d.feed(bits::Dibit::new(0)), StreamSymbol::Status(
                StatusCode::SubscriberDirect));

        for _ in 0..35 {
            assert_eq!(d.feed(bits::Dibit::new(0)),
                StreamSymbol::Data(bits::Dibit::new(0)));
        }

        assert_eq!(d.feed(bits::Dibit::new(0)), StreamSymbol::Status(
                StatusCode::SubscriberDirect));

        for _ in 0..35 {
            assert_eq!(d.feed(bits::Dibit::new(0)),
                StreamSymbol::Data(bits::Dibit::new(0)));
        }

        assert_eq!(d.feed(bits::Dibit::new(0)), StreamSymbol::Status(
                StatusCode::SubscriberDirect));
    }
}
<|endoftext|>


<commit_before>//! FIXME: write short doc here

mod consts;
mod adt;
mod traits;
mod use_item;

pub(crate) use self::{
    adt::{enum_variant_list, record_field_def_list},
    expressions::{match_arm_list, record_field_list},
    traits::{impl_item_list, trait_item_list},
    use_item::use_tree_list,
};
use super::*;

// test mod_contents
// fn foo() {}
// macro_rules! foo {}
// foo::bar!();
// super::baz! {}
// struct S;
pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) {
    attributes::inner_attributes(p);
    while !p.at(EOF) && !(stop_on_r_curly && p.at(T!['}'])) {
        item_or_macro(p, stop_on_r_curly, ItemFlavor::Mod)
    }
}

pub(super) enum ItemFlavor {
    Mod,
    Trait,
}

pub(super) const ITEM_RECOVERY_SET: TokenSet = token_set![
    FN_KW, STRUCT_KW, ENUM_KW, IMPL_KW, TRAIT_KW, CONST_KW, STATIC_KW, LET_KW, MOD_KW, PUB_KW,
    CRATE_KW, USE_KW
];

pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) {
    let m = p.start();
    attributes::outer_attributes(p);
    let m = match maybe_item(p, m, flavor) {
        Ok(()) => {
            if p.at(T![;]) {
                p.err_and_bump(
                    "expected item, found `;`\n\
                     consider removing this semicolon",
                );
            }
            return;
        }
        Err(m) => m,
    };
    if paths::is_use_path_start(p) {
        match macro_call(p) {
            BlockLike::Block => (),
            BlockLike::NotBlock => {
                p.expect(T![;]);
            }
        }
        m.complete(p, MACRO_CALL);
    } else {
        m.abandon(p);
        if p.at(T!['{']) {
            error_block(p, "expected an item");
        } else if p.at(T!['}']) && !stop_on_r_curly {
            let e = p.start();
            p.error("unmatched `}`");
            p.bump(T!['}']);
            e.complete(p, ERROR);
        } else if !p.at(EOF) && !p.at(T!['}']) {
            p.err_and_bump("expected an item");
        } else {
            p.error("expected an item");
        }
    }
}

pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Result<(), Marker> {
    // test_err pub_expr
    // fn foo() { pub 92; }
    let has_visibility = opt_visibility(p);

    let m = match items_without_modifiers(p, m) {
        Ok(()) => return Ok(()),
        Err(m) => m,
    };

    let mut has_mods = false;

    // modifiers
    has_mods |= p.eat(T![const]);

    // test_err unsafe_block_in_mod
    // fn foo(){} unsafe { } fn bar(){}
    if p.at(T![unsafe]) && p.nth(1) != T!['{'] {
        p.eat(T![unsafe]);
        has_mods = true;
    }

    // test_err async_without_semicolon
    // fn foo() { let _ = async {} }
    if p.at(T![async]) && p.nth(1) != T!['{'] && p.nth(1) != T![move] && p.nth(1) != T![|] {
        p.eat(T![async]);
        has_mods = true;
    }

    if p.at(T![extern]) {
        has_mods = true;
        abi(p);
    }
    if p.at(IDENT) && p.at_contextual_kw("auto") && p.nth(1) == T![trait] {
        p.bump_remap(T![auto]);
        has_mods = true;
    }

    if p.at(IDENT)
        && p.at_contextual_kw("default")
        && (match p.nth(1) {
            T![impl] => true,
            T![fn] | T![type] => {
                if let ItemFlavor::Mod = flavor {
                    true
                } else {
                    false
                }
            }
            _ => false,
        })
    {
        p.bump_remap(T![default]);
        has_mods = true;
    }
    if p.at(IDENT) && p.at_contextual_kw("existential") && p.nth(1) == T![type] {
        p.bump_remap(T![existential]);
        has_mods = true;
    }

    // items
    match p.current() {
        // test async_fn
        // async fn foo() {}

        // test extern_fn
        // extern fn foo() {}

        // test const_fn
        // const fn foo() {}

        // test const_unsafe_fn
        // const unsafe fn foo() {}

        // test unsafe_extern_fn
        // unsafe extern "C" fn foo() {}

        // test unsafe_fn
        // unsafe fn foo() {}

        // test combined_fns
        // unsafe async fn foo() {}
        // const unsafe fn bar() {}

        // test_err wrong_order_fns
        // async unsafe fn foo() {}
        // unsafe const fn bar() {}
        T![fn] => {
            fn_def(p, flavor);
            m.complete(p, FN_DEF);
        }

        // test unsafe_trait
        // unsafe trait T {}

        // test auto_trait
        // auto trait T {}

        // test unsafe_auto_trait
        // unsafe auto trait T {}
        T![trait] => {
            traits::trait_def(p);
            m.complete(p, TRAIT_DEF);
        }

        // test unsafe_impl
        // unsafe impl Foo {}

        // test default_impl
        // default impl Foo {}

        // test_err default_fn_type
        // trait T {
        //     default type T = Bar;
        //     default fn foo() {}
        // }

        // test default_fn_type
        // impl T for Foo {
        //     default type T = Bar;
        //     default fn foo() {}
        // }

        // test unsafe_default_impl
        // unsafe default impl Foo {}
        T![impl] => {
            traits::impl_block(p);
            m.complete(p, IMPL_BLOCK);
        }

        // test existential_type
        // existential type Foo: Fn() -> usize;
        T![type] => {
            type_def(p, m);
        }
        _ => {
            if !has_visibility && !has_mods {
                return Err(m);
            } else {
                if has_mods {
                    p.error("expected existential, fn, trait or impl");
                } else {
                    p.error("expected an item");
                }
                m.complete(p, ERROR);
            }
        }
    }
    Ok(())
}

fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
    let la = p.nth(1);
    match p.current() {
        // test extern_crate
        // extern crate foo;
        T![extern] if la == T![crate] => extern_crate_item(p, m),
        T![type] => {
            type_def(p, m);
        }
        T![mod] => mod_item(p, m),
        T![struct] => {
            // test struct_items
            // struct Foo;
            // struct Foo {}
            // struct Foo();
            // struct Foo(String, usize);
            // struct Foo {
            //     a: i32,
            //     b: f32,
            // }
            adt::struct_def(p, m);
        }
        // test pub_macro_def
        // pub macro m($:ident) {}
        T![macro] => {
            macro_def(p, m);
        }
        IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => {
            // test union_items
            // union Foo {}
            // union Foo {
            //     a: i32,
            //     b: f32,
            // }
            adt::union_def(p, m);
        }
        T![enum] => adt::enum_def(p, m),
        T![use] => use_item::use_item(p, m),
        T![const] if (la == IDENT || la == T![_] || la == T![mut]) => consts::const_def(p, m),
        T![static] => consts::static_def(p, m),
        // test extern_block
        // extern {}
        T![extern]
            if la == T!['{'] || ((la == STRING || la == RAW_STRING) && p.nth(2) == T!['{']) =>
        {
            abi(p);
            extern_item_list(p);
            m.complete(p, EXTERN_BLOCK);
        }
        _ => return Err(m),
    };
    Ok(())
}

fn extern_crate_item(p: &mut Parser, m: Marker) {
    assert!(p.at(T![extern]));
    p.bump(T![extern]);
    assert!(p.at(T![crate]));
    p.bump(T![crate]);
    name_ref(p);
    opt_alias(p);
    p.expect(T![;]);
    m.complete(p, EXTERN_CRATE_ITEM);
}

pub(crate) fn extern_item_list(p: &mut Parser) {
    assert!(p.at(T!['{']));
    let m = p.start();
    p.bump(T!['{']);
    mod_contents(p, true);
    p.expect(T!['}']);
    m.complete(p, EXTERN_ITEM_LIST);
}

fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
    assert!(p.at(T![fn]));
    p.bump(T![fn]);

    name_r(p, ITEM_RECOVERY_SET);
    // test function_type_params
    // fn foo<T: Clone + Copy>(){}
    type_params::opt_type_param_list(p);

    if p.at(T!['(']) {
        match flavor {
            ItemFlavor::Mod => params::param_list(p),
            ItemFlavor::Trait => params::param_list_opt_patterns(p),
        }
    } else {
        p.error("expected function arguments");
    }
    // test function_ret_type
    // fn foo() {}
    // fn bar() -> () {}
    opt_fn_ret_type(p);

    // test function_where_clause
    // fn foo<T>() where T: Copy {}
    type_params::opt_where_clause(p);

    // test fn_decl
    // trait T { fn foo(); }
    if p.at(T![;]) {
        p.bump(T![;]);
    } else {
        expressions::block(p)
    }
}

// test type_item
// type Foo = Bar;
fn type_def(p: &mut Parser, m: Marker) {
    assert!(p.at(T![type]));
    p.bump(T![type]);

    name(p);

    // test type_item_type_params
    // type Result<T> = ();
    type_params::opt_type_param_list(p);

    if p.at(T![:]) {
        type_params::bounds(p);
    }

    // test type_item_where_clause
    // type Foo where Foo: Copy = ();
    type_params::opt_where_clause(p);
    if p.eat(T![=]) {
        types::type_(p);
    }
    p.expect(T![;]);
    m.complete(p, TYPE_ALIAS_DEF);
}

pub(crate) fn mod_item(p: &mut Parser, m: Marker) {
    assert!(p.at(T![mod]));
    p.bump(T![mod]);

    name(p);
    if p.at(T!['{']) {
        mod_item_list(p);
    } else if !p.eat(T![;]) {
        p.error("expected `;` or `{`");
    }
    m.complete(p, MODULE);
}

pub(crate) fn mod_item_list(p: &mut Parser) {
    assert!(p.at(T!['{']));
    let m = p.start();
    p.bump(T!['{']);
    mod_contents(p, true);
    p.expect(T!['}']);
    m.complete(p, ITEM_LIST);
}

// test macro_def
// macro m { ($i:ident) => {} }
// macro m($i:ident) {}
fn macro_def(p: &mut Parser, m: Marker) {
    p.expect(T![macro]);
    p.expect(IDENT);
    if p.at(T!['{']) {
        token_tree(p);
    } else if !p.at(T!['(']) {
        p.error("unmatched `(`");
    } else {
        let m = p.start();
        token_tree(p);
        match p.current() {
            T!['{'] | T!['['] | T!['('] => token_tree(p),
            _ => p.error("expected `{`, `[`, `(`"),
        }
        m.complete(p, TOKEN_TREE);
    }

    m.complete(p, MACRO_DEF);
}

fn macro_call(p: &mut Parser) -> BlockLike {
    assert!(paths::is_use_path_start(p));
    paths::use_path(p);
    macro_call_after_excl(p)
}

pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike {
    p.expect(T![!]);
    if p.at(IDENT) {
        name(p);
    }
    match p.current() {
        T!['{'] => {
            token_tree(p);
            BlockLike::Block
        }
        T!['('] | T!['['] => {
            token_tree(p);
            BlockLike::NotBlock
        }
        _ => {
            p.error("expected `{`, `[`, `(`");
            BlockLike::NotBlock
        }
    }
}

pub(crate) fn token_tree(p: &mut Parser) {
    let closing_paren_kind = match p.current() {
        T!['{'] => T!['}'],
        T!['('] => T![')'],
        T!['['] => T![']'],
        _ => unreachable!(),
    };
    let m = p.start();
    p.bump_any();
    while !p.at(EOF) && !p.at(closing_paren_kind) {
        match p.current() {
            T!['{'] | T!['('] | T!['['] => token_tree(p),
            T!['}'] => {
                p.error("unmatched `}`");
                m.complete(p, TOKEN_TREE);
                return;
            }
            T![')'] | T![']'] => p.err_and_bump("unmatched brace"),
            _ => p.bump_any(),
        }
    }
    p.expect(closing_paren_kind);
    m.complete(p, TOKEN_TREE);
}
<commit_msg>Add macro keyword to  ITEM_RECOVERY_SET<commit_after>//! FIXME: write short doc here

mod consts;
mod adt;
mod traits;
mod use_item;

pub(crate) use self::{
    adt::{enum_variant_list, record_field_def_list},
    expressions::{match_arm_list, record_field_list},
    traits::{impl_item_list, trait_item_list},
    use_item::use_tree_list,
};
use super::*;

// test mod_contents
// fn foo() {}
// macro_rules! foo {}
// foo::bar!();
// super::baz! {}
// struct S;
pub(super) fn mod_contents(p: &mut Parser, stop_on_r_curly: bool) {
    attributes::inner_attributes(p);
    while !p.at(EOF) && !(stop_on_r_curly && p.at(T!['}'])) {
        item_or_macro(p, stop_on_r_curly, ItemFlavor::Mod)
    }
}

pub(super) enum ItemFlavor {
    Mod,
    Trait,
}

pub(super) const ITEM_RECOVERY_SET: TokenSet = token_set![
    FN_KW, STRUCT_KW, ENUM_KW, IMPL_KW, TRAIT_KW, CONST_KW, STATIC_KW, LET_KW, MOD_KW, PUB_KW,
    CRATE_KW, USE_KW, MACRO_KW
];

pub(super) fn item_or_macro(p: &mut Parser, stop_on_r_curly: bool, flavor: ItemFlavor) {
    let m = p.start();
    attributes::outer_attributes(p);
    let m = match maybe_item(p, m, flavor) {
        Ok(()) => {
            if p.at(T![;]) {
                p.err_and_bump(
                    "expected item, found `;`\n\
                     consider removing this semicolon",
                );
            }
            return;
        }
        Err(m) => m,
    };
    if paths::is_use_path_start(p) {
        match macro_call(p) {
            BlockLike::Block => (),
            BlockLike::NotBlock => {
                p.expect(T![;]);
            }
        }
        m.complete(p, MACRO_CALL);
    } else {
        m.abandon(p);
        if p.at(T!['{']) {
            error_block(p, "expected an item");
        } else if p.at(T!['}']) && !stop_on_r_curly {
            let e = p.start();
            p.error("unmatched `}`");
            p.bump(T!['}']);
            e.complete(p, ERROR);
        } else if !p.at(EOF) && !p.at(T!['}']) {
            p.err_and_bump("expected an item");
        } else {
            p.error("expected an item");
        }
    }
}

pub(super) fn maybe_item(p: &mut Parser, m: Marker, flavor: ItemFlavor) -> Result<(), Marker> {
    // test_err pub_expr
    // fn foo() { pub 92; }
    let has_visibility = opt_visibility(p);

    let m = match items_without_modifiers(p, m) {
        Ok(()) => return Ok(()),
        Err(m) => m,
    };

    let mut has_mods = false;

    // modifiers
    has_mods |= p.eat(T![const]);

    // test_err unsafe_block_in_mod
    // fn foo(){} unsafe { } fn bar(){}
    if p.at(T![unsafe]) && p.nth(1) != T!['{'] {
        p.eat(T![unsafe]);
        has_mods = true;
    }

    // test_err async_without_semicolon
    // fn foo() { let _ = async {} }
    if p.at(T![async]) && p.nth(1) != T!['{'] && p.nth(1) != T![move] && p.nth(1) != T![|] {
        p.eat(T![async]);
        has_mods = true;
    }

    if p.at(T![extern]) {
        has_mods = true;
        abi(p);
    }
    if p.at(IDENT) && p.at_contextual_kw("auto") && p.nth(1) == T![trait] {
        p.bump_remap(T![auto]);
        has_mods = true;
    }

    if p.at(IDENT)
        && p.at_contextual_kw("default")
        && (match p.nth(1) {
            T![impl] => true,
            T![fn] | T![type] => {
                if let ItemFlavor::Mod = flavor {
                    true
                } else {
                    false
                }
            }
            _ => false,
        })
    {
        p.bump_remap(T![default]);
        has_mods = true;
    }
    if p.at(IDENT) && p.at_contextual_kw("existential") && p.nth(1) == T![type] {
        p.bump_remap(T![existential]);
        has_mods = true;
    }

    // items
    match p.current() {
        // test async_fn
        // async fn foo() {}

        // test extern_fn
        // extern fn foo() {}

        // test const_fn
        // const fn foo() {}

        // test const_unsafe_fn
        // const unsafe fn foo() {}

        // test unsafe_extern_fn
        // unsafe extern "C" fn foo() {}

        // test unsafe_fn
        // unsafe fn foo() {}

        // test combined_fns
        // unsafe async fn foo() {}
        // const unsafe fn bar() {}

        // test_err wrong_order_fns
        // async unsafe fn foo() {}
        // unsafe const fn bar() {}
        T![fn] => {
            fn_def(p, flavor);
            m.complete(p, FN_DEF);
        }

        // test unsafe_trait
        // unsafe trait T {}

        // test auto_trait
        // auto trait T {}

        // test unsafe_auto_trait
        // unsafe auto trait T {}
        T![trait] => {
            traits::trait_def(p);
            m.complete(p, TRAIT_DEF);
        }

        // test unsafe_impl
        // unsafe impl Foo {}

        // test default_impl
        // default impl Foo {}

        // test_err default_fn_type
        // trait T {
        //     default type T = Bar;
        //     default fn foo() {}
        // }

        // test default_fn_type
        // impl T for Foo {
        //     default type T = Bar;
        //     default fn foo() {}
        // }

        // test unsafe_default_impl
        // unsafe default impl Foo {}
        T![impl] => {
            traits::impl_block(p);
            m.complete(p, IMPL_BLOCK);
        }

        // test existential_type
        // existential type Foo: Fn() -> usize;
        T![type] => {
            type_def(p, m);
        }
        _ => {
            if !has_visibility && !has_mods {
                return Err(m);
            } else {
                if has_mods {
                    p.error("expected existential, fn, trait or impl");
                } else {
                    p.error("expected an item");
                }
                m.complete(p, ERROR);
            }
        }
    }
    Ok(())
}

fn items_without_modifiers(p: &mut Parser, m: Marker) -> Result<(), Marker> {
    let la = p.nth(1);
    match p.current() {
        // test extern_crate
        // extern crate foo;
        T![extern] if la == T![crate] => extern_crate_item(p, m),
        T![type] => {
            type_def(p, m);
        }
        T![mod] => mod_item(p, m),
        T![struct] => {
            // test struct_items
            // struct Foo;
            // struct Foo {}
            // struct Foo();
            // struct Foo(String, usize);
            // struct Foo {
            //     a: i32,
            //     b: f32,
            // }
            adt::struct_def(p, m);
        }
        // test pub_macro_def
        // pub macro m($:ident) {}
        T![macro] => {
            macro_def(p, m);
        }
        IDENT if p.at_contextual_kw("union") && p.nth(1) == IDENT => {
            // test union_items
            // union Foo {}
            // union Foo {
            //     a: i32,
            //     b: f32,
            // }
            adt::union_def(p, m);
        }
        T![enum] => adt::enum_def(p, m),
        T![use] => use_item::use_item(p, m),
        T![const] if (la == IDENT || la == T![_] || la == T![mut]) => consts::const_def(p, m),
        T![static] => consts::static_def(p, m),
        // test extern_block
        // extern {}
        T![extern]
            if la == T!['{'] || ((la == STRING || la == RAW_STRING) && p.nth(2) == T!['{']) =>
        {
            abi(p);
            extern_item_list(p);
            m.complete(p, EXTERN_BLOCK);
        }
        _ => return Err(m),
    };
    Ok(())
}

fn extern_crate_item(p: &mut Parser, m: Marker) {
    assert!(p.at(T![extern]));
    p.bump(T![extern]);
    assert!(p.at(T![crate]));
    p.bump(T![crate]);
    name_ref(p);
    opt_alias(p);
    p.expect(T![;]);
    m.complete(p, EXTERN_CRATE_ITEM);
}

pub(crate) fn extern_item_list(p: &mut Parser) {
    assert!(p.at(T!['{']));
    let m = p.start();
    p.bump(T!['{']);
    mod_contents(p, true);
    p.expect(T!['}']);
    m.complete(p, EXTERN_ITEM_LIST);
}

fn fn_def(p: &mut Parser, flavor: ItemFlavor) {
    assert!(p.at(T![fn]));
    p.bump(T![fn]);

    name_r(p, ITEM_RECOVERY_SET);
    // test function_type_params
    // fn foo<T: Clone + Copy>(){}
    type_params::opt_type_param_list(p);

    if p.at(T!['(']) {
        match flavor {
            ItemFlavor::Mod => params::param_list(p),
            ItemFlavor::Trait => params::param_list_opt_patterns(p),
        }
    } else {
        p.error("expected function arguments");
    }
    // test function_ret_type
    // fn foo() {}
    // fn bar() -> () {}
    opt_fn_ret_type(p);

    // test function_where_clause
    // fn foo<T>() where T: Copy {}
    type_params::opt_where_clause(p);

    // test fn_decl
    // trait T { fn foo(); }
    if p.at(T![;]) {
        p.bump(T![;]);
    } else {
        expressions::block(p)
    }
}

// test type_item
// type Foo = Bar;
fn type_def(p: &mut Parser, m: Marker) {
    assert!(p.at(T![type]));
    p.bump(T![type]);

    name(p);

    // test type_item_type_params
    // type Result<T> = ();
    type_params::opt_type_param_list(p);

    if p.at(T![:]) {
        type_params::bounds(p);
    }

    // test type_item_where_clause
    // type Foo where Foo: Copy = ();
    type_params::opt_where_clause(p);
    if p.eat(T![=]) {
        types::type_(p);
    }
    p.expect(T![;]);
    m.complete(p, TYPE_ALIAS_DEF);
}

pub(crate) fn mod_item(p: &mut Parser, m: Marker) {
    assert!(p.at(T![mod]));
    p.bump(T![mod]);

    name(p);
    if p.at(T!['{']) {
        mod_item_list(p);
    } else if !p.eat(T![;]) {
        p.error("expected `;` or `{`");
    }
    m.complete(p, MODULE);
}

pub(crate) fn mod_item_list(p: &mut Parser) {
    assert!(p.at(T!['{']));
    let m = p.start();
    p.bump(T!['{']);
    mod_contents(p, true);
    p.expect(T!['}']);
    m.complete(p, ITEM_LIST);
}

// test macro_def
// macro m { ($i:ident) => {} }
// macro m($i:ident) {}
fn macro_def(p: &mut Parser, m: Marker) {
    p.expect(T![macro]);
    p.expect(IDENT);
    if p.at(T!['{']) {
        token_tree(p);
    } else if !p.at(T!['(']) {
        p.error("unmatched `(`");
    } else {
        let m = p.start();
        token_tree(p);
        match p.current() {
            T!['{'] | T!['['] | T!['('] => token_tree(p),
            _ => p.error("expected `{`, `[`, `(`"),
        }
        m.complete(p, TOKEN_TREE);
    }

    m.complete(p, MACRO_DEF);
}

fn macro_call(p: &mut Parser) -> BlockLike {
    assert!(paths::is_use_path_start(p));
    paths::use_path(p);
    macro_call_after_excl(p)
}

pub(super) fn macro_call_after_excl(p: &mut Parser) -> BlockLike {
    p.expect(T![!]);
    if p.at(IDENT) {
        name(p);
    }
    match p.current() {
        T!['{'] => {
            token_tree(p);
            BlockLike::Block
        }
        T!['('] | T!['['] => {
            token_tree(p);
            BlockLike::NotBlock
        }
        _ => {
            p.error("expected `{`, `[`, `(`");
            BlockLike::NotBlock
        }
    }
}

pub(crate) fn token_tree(p: &mut Parser) {
    let closing_paren_kind = match p.current() {
        T!['{'] => T!['}'],
        T!['('] => T![')'],
        T!['['] => T![']'],
        _ => unreachable!(),
    };
    let m = p.start();
    p.bump_any();
    while !p.at(EOF) && !p.at(closing_paren_kind) {
        match p.current() {
            T!['{'] | T!['('] | T!['['] => token_tree(p),
            T!['}'] => {
                p.error("unmatched `}`");
                m.complete(p, TOKEN_TREE);
                return;
            }
            T![')'] | T![']'] => p.err_and_bump("unmatched brace"),
            _ => p.bump_any(),
        }
    }
    p.expect(closing_paren_kind);
    m.complete(p, TOKEN_TREE);
}
<|endoftext|>