<commit_before>use std::collections::HashMap;
use std::i32;
use std::hash::Hash;
use std::iter::FromIterator;
use std::cmp::{max, min};
use std::fmt;
use euclid::{Point2D, Size2D};

/// A structure for storing a piece of a grid map.
///
/// All contents are guaranteed to be stored in the rectangle between (0, 0) (inclusive) and `dim`
/// (exclusive).
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Prefab<T> {
    terrain: HashMap<Point2D<i32>, usize>,
    elements: Vec<T>,
    dim: Size2D<u32>,
}

impl<T: Clone + Eq + Hash> Prefab<T> {
    fn new() -> Prefab<T> {
        Prefab {
            terrain: HashMap::new(),
            elements: Vec::new(),
            dim: Size2D::new(0, 0),
        }
    }

    pub fn get<'a>(&'a self, pos: Point2D<i32>) -> Option<&'a T> {
        self.terrain.get(&pos).map(|&idx| &self.elements[idx])
    }

    pub fn map<F: Fn(T) -> U, U>(self, f: F) -> Prefab<U> {
        Prefab {
            terrain: self.terrain,
            elements: self.elements.into_iter().map(f).collect(),
            dim: self.dim,
        }
    }

    pub fn dim(&self) -> Size2D<u32> { self.dim }

    // TODO: Need to write a custom iterator type if you want iteration.
    //
    // Prefabs are generally pretty dense, so you can just iterate all points in the rectangle from
    // origin to dim.
}

impl<T: Clone + Eq + Hash> FromIterator<(Point2D<i32>, T)> for Prefab<T> {
    fn from_iter<I: IntoIterator<Item = (Point2D<i32>, T)>>(iter: I) -> Self {
        // List of unique values.
        let mut element_idx: HashMap<T, usize> = HashMap::new();
        let mut ret = Prefab::new();

        let mut min_x = i32::MAX;
        let mut min_y = i32::MAX;

        // Temporary storage before positions have been normalized.
        let mut temp_buffer = Vec::new();

        for (p, e) in iter.into_iter() {
            min_x = min(min_x, p.x);
            min_y = min(min_y, p.y);

            let val = *element_idx.entry(e.clone()).or_insert_with(|| {
                ret.elements.push(e);
                ret.elements.len() - 1
            });

            temp_buffer.push((p, val));
        }

        // Normalization: Snap bounding box to origin.
        let mut max_x = 0;
        let mut max_y = 0;

        for (mut p, e) in temp_buffer.into_iter() {
            p.x -= min_x;
            assert!(p.x >= 0);
            p.y -= min_y;
            assert!(p.y >= 0);

            max_x = max(p.x as u32, max_x);
            max_y = max(p.y as u32, max_y);

            ret.terrain.insert(p, e);
        }

        ret.dim = Size2D::new(max_x + 1, max_y + 1);

        ret
    }
}

impl Prefab<char> {
    fn from_text<F>(map: &str, project: F) -> Prefab<char>
        where F: Fn(usize, usize) -> (i32, i32)
    {
        let mut buf = Vec::new();
        for (y, line) in map.lines().enumerate() {
            for (x, c) in line.chars().enumerate() {
                let (map_x, map_y) = project(x, y);
                if !c.is_whitespace() {
                    buf.push((Point2D::new(map_x, map_y), c));
                }
            }
        }

        Prefab::from_iter(buf.into_iter())
    }

    pub fn from_text_map(map: &str) -> Prefab<char> {
        Prefab::from_text(map, |x, y| (x as i32, y as i32))
    }

    pub fn from_text_hexmap(map: &str) -> Prefab<char> {
        Prefab::from_text(map, |x, y| ((x + y) as i32 / 2, y as i32))
    }
}

impl<T: fmt::Display + Clone + Eq + Hash> fmt::Display for Prefab<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for y in 0..self.dim.height {
            for x in 0..self.dim.width {
                if let Some(c) = self.get(Point2D::new(x as i32, y as i32)) {
                    write!(f, "{}", c)?;
                } else {
                    write!(f, " ")?;
                }
            }
            writeln!(f, "")?;
        }
        Ok(())
    }
}

impl<T: fmt::Display + Clone + Eq + Hash> Prefab<T> {
    /// Return a wrapper for printing the map in hex layout.
    ///
    /// Without the wrapper the print format will be a traditional dense text map.
    pub fn hexmap_display<'a>(&'a self) -> HexmapDisplay<'a, T> { HexmapDisplay(self) }
}

/// Wrapper type for displaying the `Prefab` as a text hexmap.
pub struct HexmapDisplay<'a, T: 'a>(&'a Prefab<T>);

impl<'a, T: fmt::Display + Clone + Eq + Hash> fmt::Display for HexmapDisplay<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let max_width = self.0.dim.width * 2 + self.0.dim.height;

        // Find the smallest displayed x-coordinate that actually shows up in the map.
        let min_x = (0..self.0.dim.width).zip(0..self.0.dim.height)
                       .map(|(x, y)| Point2D::new(x as i32, y as i32))
                       .filter(|&p| self.0.get(p).is_some())
                       .map(|p| p.x * 2 - p.y)
                       .min().unwrap_or(0) + 1;

        for y in 0..(self.0.dim.height) {
            for x in 0..max_width {
                if (x as i32 - y as i32) % 2 != 0 {
                    write!(f, " ")?;
                    continue;
                }
                let map_x = (x + y) as i32 / 2 - min_x;
                let map_y = y as i32;
                if let Some(c) = self.0.get(Point2D::new(map_x, map_y)) {
                    write!(f, "{}", c)?;
                } else {
                    write!(f, " ")?;
                }
            }
            writeln!(f, "")?;
        }
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use euclid::Point2D;
    use super::Prefab;

    #[test]
    fn test_from_text() {
        let a = Prefab::from_text_map("
###
#..
##.
#..
");
        let b = Prefab::from_text_hexmap("
    # # #
   # . .
  # # .
 # . .
");

        assert_eq!(a, b);

        assert_eq!(Some(&'#'), a.get(Point2D::new(0, 0)));
        assert_eq!(Some(&'.'), a.get(Point2D::new(1, 1)));
        assert_eq!(Some(&'#'), a.get(Point2D::new(1, 2)));
    }

    /// Remove whitespace differences from text map strings.
    fn normalize(dirty: &str) -> String {
        // XXX: This should also normalize indetation by removing the longest whitespace prefix
        // shared by every line from each line.

        let mut ret = String::new();
        // Remove trailing whitespace and empty lines.
        let dirty = dirty.trim_right();
        // Remove heading empty lines in iterator construction.
        for line in dirty.lines().skip_while(|line| line.trim() == "") {
            ret.push_str(line.trim_right());
            ret.push('\n');
        }
        ret
    }

    #[test]
    fn test_print() {
        let hex_text = "
      # #
   # . .
  # # . .
 # . .
@ @ @ @";

        let dense_text = "
 ##
#..
##..
#..
@@@@";
        let map = Prefab::from_text_hexmap(&hex_text);

        assert_eq!(normalize(&format!("{}", map.hexmap_display())),
                   normalize(hex_text));
        assert_eq!(normalize(&format!("{}", map)), normalize(dense_text));
    }

    #[test]
    fn test_left_align() {
        let big_hex = "
                                                            * *
                                                         * * * *
                                                      * * * * * *
                                                   * * * * * * * *
                                                * * * * * * * * * *
                                             * * * * * * * * * * * *
                                          * * * * * * * * * * * * * *
                                       * * * * * * * * * * * * * * * *
                                    * * * * * * * * * * * * * * * * * *
                                 * * * * * * * * * * * * * * * * * * * *
                              * * * * * * * * * * * * * * * * * * * * * *
                           * * * * * * * * * * * * * * * * * * * * * * * *
                        * * * * * * * * * * * * * * ^ * * * * * * * * * * *
                     * * * * * * * * * * * * * * * * * * * * * * * * * * * *
                  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
               * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
            * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
         * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
      * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
   * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * * * * * * * * * * * * * * * * * * * * , , % # # , , , * * * * * * * * * * * * * *
   * * * * * * * * * * * * * * * * * * * , , , , , , , , * * * * * * * * * * * * * *
    * * * * * * * * * * * * * * * * * * , , , * * , , , * * * * * * * * * * * * * *
     * * * * * * * * * * * * * * * * * , , , , , , , , * * * * * * * * * * * * *
      * * * * * * * * * * * * * * * * , , , , , , , , * * * * * * * * * * * *
       * * * * * * * * * * * * * * * , , , , , , , , * * * * * * * * * * *
        * * * * * * * * * * * * * * , , , , , , , , * * * * * * * * * *
         * * * * * * * * * * * * * , , , , , , , , * * * * * * * * *
          * * * * * * * * * * * * * * * * * * * * * * * * * * * *
           * * * * * * * * * * * * * * * * * * * * * * * * * *
            * * * * * * * * * * * * * * * * * * * * * * * *
             * * * * * * * * * * * * * * * * * * * * * *
              * * * * * * * * * * * * * * * * * * * *
               * * * * * * * * * * * * * * * * * *
                * * * * * * * * * * * * * * * *
                 * * * * * * * * * * * * * *
                  * * * * * * * * * * * *
                   * * * * * * * * * *
                    * * * * * * * *
                     * * * * * *
                      * * * *
                       * *";
        let map = Prefab::from_text_hexmap(&big_hex);

        let map2 = Prefab::from_text_hexmap(&format!("{}", map.hexmap_display()));
        assert_eq!(map, map2);

        assert_eq!(normalize(&format!("{}", map.hexmap_display())),
                   normalize(big_hex));

    }
}
<commit_msg>Fix prefab left align method<commit_after>use std::collections::HashMap;
use std::i32;
use std::hash::Hash;
use std::iter::FromIterator;
use std::cmp::{max, min};
use std::fmt;
use euclid::{Point2D, Size2D};

/// A structure for storing a piece of a grid map.
///
/// All contents are guaranteed to be stored in the rectangle between (0, 0) (inclusive) and `dim`
/// (exclusive).
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct Prefab<T> {
    terrain: HashMap<Point2D<i32>, usize>,
    elements: Vec<T>,
    dim: Size2D<u32>,
}

impl<T: Clone + Eq + Hash> Prefab<T> {
    fn new() -> Prefab<T> {
        Prefab {
            terrain: HashMap::new(),
            elements: Vec::new(),
            dim: Size2D::new(0, 0),
        }
    }

    pub fn get<'a>(&'a self, pos: Point2D<i32>) -> Option<&'a T> {
        self.terrain.get(&pos).map(|&idx| &self.elements[idx])
    }

    pub fn map<F: Fn(T) -> U, U>(self, f: F) -> Prefab<U> {
        Prefab {
            terrain: self.terrain,
            elements: self.elements.into_iter().map(f).collect(),
            dim: self.dim,
        }
    }

    pub fn dim(&self) -> Size2D<u32> { self.dim }

    // TODO: Need to write a custom iterator type if you want iteration.
    //
    // Prefabs are generally pretty dense, so you can just iterate all points in the rectangle from
    // origin to dim.
}

impl<T: Clone + Eq + Hash> FromIterator<(Point2D<i32>, T)> for Prefab<T> {
    fn from_iter<I: IntoIterator<Item = (Point2D<i32>, T)>>(iter: I) -> Self {
        // List of unique values.
        let mut element_idx: HashMap<T, usize> = HashMap::new();
        let mut ret = Prefab::new();

        let mut min_x = i32::MAX;
        let mut min_y = i32::MAX;

        // Temporary storage before positions have been normalized.
        let mut temp_buffer = Vec::new();

        for (p, e) in iter.into_iter() {
            min_x = min(min_x, p.x);
            min_y = min(min_y, p.y);

            let val = *element_idx.entry(e.clone()).or_insert_with(|| {
                ret.elements.push(e);
                ret.elements.len() - 1
            });

            temp_buffer.push((p, val));
        }

        // Normalization: Snap bounding box to origin.
        let mut max_x = 0;
        let mut max_y = 0;

        for (mut p, e) in temp_buffer.into_iter() {
            p.x -= min_x;
            assert!(p.x >= 0);
            p.y -= min_y;
            assert!(p.y >= 0);

            max_x = max(p.x as u32, max_x);
            max_y = max(p.y as u32, max_y);

            ret.terrain.insert(p, e);
        }

        ret.dim = Size2D::new(max_x + 1, max_y + 1);

        ret
    }
}

impl Prefab<char> {
    fn from_text<F>(map: &str, project: F) -> Prefab<char>
        where F: Fn(usize, usize) -> (i32, i32)
    {
        let mut buf = Vec::new();
        for (y, line) in map.lines().enumerate() {
            for (x, c) in line.chars().enumerate() {
                let (map_x, map_y) = project(x, y);
                if !c.is_whitespace() {
                    buf.push((Point2D::new(map_x, map_y), c));
                }
            }
        }

        Prefab::from_iter(buf.into_iter())
    }

    pub fn from_text_map(map: &str) -> Prefab<char> {
        Prefab::from_text(map, |x, y| (x as i32, y as i32))
    }

    pub fn from_text_hexmap(map: &str) -> Prefab<char> {
        Prefab::from_text(map, |x, y| ((x + y) as i32 / 2, y as i32))
    }
}

impl<T: fmt::Display + Clone + Eq + Hash> fmt::Display for Prefab<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        for y in 0..self.dim.height {
            for x in 0..self.dim.width {
                if let Some(c) = self.get(Point2D::new(x as i32, y as i32)) {
                    write!(f, "{}", c)?;
                } else {
                    write!(f, " ")?;
                }
            }
            writeln!(f, "")?;
        }
        Ok(())
    }
}

impl<T: fmt::Display + Clone + Eq + Hash> Prefab<T> {
    /// Return a wrapper for printing the map in hex layout.
    ///
    /// Without the wrapper the print format will be a traditional dense text map.
    pub fn hexmap_display<'a>(&'a self) -> HexmapDisplay<'a, T> { HexmapDisplay(self) }
}

/// Wrapper type for displaying the `Prefab` as a text hexmap.
pub struct HexmapDisplay<'a, T: 'a>(&'a Prefab<T>);

impl<'a, T: fmt::Display + Clone + Eq + Hash> fmt::Display for HexmapDisplay<'a, T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let max_width = (self.0.dim.width * 2 + self.0.dim.height) as i32;

        // Find the smallest displayed x-coordinate that actually shows up in the map.
        let min_x = (0..(self.0.dim.width * self.0.dim.height))
                       .map(|i| Point2D::new((i % self.0.dim.width) as i32, (i / self.0.dim.width) as i32))
                       .filter(|&p| self.0.get(p).is_some())
                       .map(|p| p.x * 2 - p.y)
                       .min().unwrap_or(0);

        for y in 0..(self.0.dim.height as i32) {
            for x in min_x..(min_x + max_width) {
                if (x - y) % 2 != 0 {
                    write!(f, " ")?;
                    continue;
                }
                let map_x = (x + y) / 2;
                let map_y = y;
                if let Some(c) = self.0.get(Point2D::new(map_x, map_y)) {
                    write!(f, "{}", c)?;
                } else {
                    write!(f, " ")?;
                }
            }
            writeln!(f, "")?;
        }
        Ok(())
    }
}

#[cfg(test)]
mod test {
    use euclid::Point2D;
    use super::Prefab;

    #[test]
    fn test_from_text() {
        let a = Prefab::from_text_map("
###
#..
##.
#..
");
        let b = Prefab::from_text_hexmap("
    # # #
   # . .
  # # .
 # . .
");

        assert_eq!(a, b);

        assert_eq!(Some(&'#'), a.get(Point2D::new(0, 0)));
        assert_eq!(Some(&'.'), a.get(Point2D::new(1, 1)));
        assert_eq!(Some(&'#'), a.get(Point2D::new(1, 2)));
    }

    /// Remove whitespace differences from text map strings.
    fn normalize(dirty: &str) -> String {
        // XXX: This should also normalize indetation by removing the longest whitespace prefix
        // shared by every line from each line.

        let mut ret = String::new();
        // Remove trailing whitespace and empty lines.
        let dirty = dirty.trim_right();
        // Remove heading empty lines in iterator construction.
        for line in dirty.lines().skip_while(|line| line.trim() == "") {
            ret.push_str(line.trim_right());
            ret.push('\n');
        }
        ret
    }

    #[test]
    fn test_print() {
        let hex_text = "
      # #
   # . .
  # # . .
 # . .
@ @ @ @";

        let dense_text = "
 ##
#..
##..
#..
@@@@";
        let map = Prefab::from_text_hexmap(&hex_text);

        assert_eq!(normalize(&format!("{}", map.hexmap_display())),
                   normalize(hex_text));
        assert_eq!(normalize(&format!("{}", map)), normalize(dense_text));
    }

    #[test]
    fn test_left_align() {
        let big_hex = "
                                                           * *
                                                        * * * *
                                                     * * * * * *
                                                  * * * * * * * *
                                               * * * * * * * * * *
                                            * * * * * * * * * * * *
                                         * * * * * * * * * * * * * *
                                      * * * * * * * * * * * * * * * *
                                   * * * * * * * * * * * * * * * * * *
                                * * * * * * * * * * * * * * * * * * * *
                             * * * * * * * * * * * * * * * * * * * * * *
                          * * * * * * * * * * * * * * * * * * * * * * * *
                       * * * * * * * * * * * * * * ^ * * * * * * * * * * *
                    * * * * * * * * * * * * * * * * * * * * * * * * * * * *
                 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
              * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
           * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
        * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
     * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * * * * * * * * * * * * * * * * * * * * , , % # # , , , * * * * * * * * * * * * * *
  * * * * * * * * * * * * * * * * * * * , , , , , , , , * * * * * * * * * * * * * *
   * * * * * * * * * * * * * * * * * * , , , * * , , , * * * * * * * * * * * * * *
    * * * * * * * * * * * * * * * * * , , , , , , , , * * * * * * * * * * * * *
     * * * * * * * * * * * * * * * * , , , , , , , , * * * * * * * * * * * *
      * * * * * * * * * * * * * * * , , , , , , , , * * * * * * * * * * *
       * * * * * * * * * * * * * * , , , , , , , , * * * * * * * * * *
        * * * * * * * * * * * * * , , , , , , , , * * * * * * * * *
         * * * * * * * * * * * * * * * * * * * * * * * * * * * *
          * * * * * * * * * * * * * * * * * * * * * * * * * *
           * * * * * * * * * * * * * * * * * * * * * * * *
            * * * * * * * * * * * * * * * * * * * * * *
             * * * * * * * * * * * * * * * * * * * *
              * * * * * * * * * * * * * * * * * *
               * * * * * * * * * * * * * * * *
                * * * * * * * * * * * * * *
                 * * * * * * * * * * * *
                  * * * * * * * * * *
                   * * * * * * * *
                    * * * * * *
                     * * * *
                      * *";
        let map = Prefab::from_text_hexmap(&big_hex);

        let map2 = Prefab::from_text_hexmap(&format!("{}", map.hexmap_display()));
        assert_eq!(map, map2);

        assert_eq!(normalize(&format!("{}", map.hexmap_display())),
                   normalize(big_hex));

    }
}
<|endoftext|>


<commit_before>//! This modules implements a function to resolve a path `foo::bar::baz` to a
//! def, which is used within the name resolution.
//!
//! When name resolution is finished, the result of resolving a path is either
//! `Some(def)` or `None`. However, when we are in process of resolving imports
//! or macros, there's a third possibility:
//!
//!   I can't resolve this path right now, but I might be resolve this path
//!   later, when more macros are expanded.
//!
//! `ReachedFixedPoint` signals about this.

use std::iter::successors;

use hir_expand::name::Name;
use ra_db::Edition;
use test_utils::tested_by;

use crate::{
    db::DefDatabase,
    nameres::{BuiltinShadowMode, CrateDefMap},
    path::{ModPath, PathKind},
    per_ns::PerNs,
    AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId,
};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum ResolveMode {
    Import,
    Other,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum ReachedFixedPoint {
    Yes,
    No,
}

#[derive(Debug, Clone)]
pub(super) struct ResolvePathResult {
    pub(super) resolved_def: PerNs,
    pub(super) segment_index: Option<usize>,
    pub(super) reached_fixedpoint: ReachedFixedPoint,
    pub(super) krate: Option<CrateId>,
}

impl ResolvePathResult {
    fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult {
        ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None, None)
    }

    fn with(
        resolved_def: PerNs,
        reached_fixedpoint: ReachedFixedPoint,
        segment_index: Option<usize>,
        krate: Option<CrateId>,
    ) -> ResolvePathResult {
        ResolvePathResult { resolved_def, reached_fixedpoint, segment_index, krate }
    }
}

impl CrateDefMap {
    pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs {
        self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it))
    }

    // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
    // the result.
    pub(super) fn resolve_path_fp_with_macro(
        &self,
        db: &impl DefDatabase,
        mode: ResolveMode,
        original_module: LocalModuleId,
        path: &ModPath,
        shadow: BuiltinShadowMode,
    ) -> ResolvePathResult {
        // if it is not the last segment, we prefer the module to the builtin
        let prefer_module = |index| {
            if index == path.segments.len() - 1 {
                shadow
            } else {
                BuiltinShadowMode::Module
            }
        };

        let mut segments = path.segments.iter().enumerate();
        let mut curr_per_ns: PerNs = match path.kind {
            PathKind::DollarCrate(krate) => {
                if krate == self.krate {
                    tested_by!(macro_dollar_crate_self);
                    PerNs::types(ModuleId { krate: self.krate, local_id: self.root }.into())
                } else {
                    let def_map = db.crate_def_map(krate);
                    let module = ModuleId { krate, local_id: def_map.root };
                    tested_by!(macro_dollar_crate_other);
                    PerNs::types(module.into())
                }
            }
            PathKind::Crate => {
                PerNs::types(ModuleId { krate: self.krate, local_id: self.root }.into())
            }
            // plain import or absolute path in 2015: crate-relative with
            // fallback to extern prelude (with the simplification in
            // rust-lang/rust#57745)
            // FIXME there must be a nicer way to write this condition
            PathKind::Plain | PathKind::Abs
                if self.edition == Edition::Edition2015
                    && (path.kind == PathKind::Abs || mode == ResolveMode::Import) =>
            {
                let (idx, segment) = match segments.next() {
                    Some((idx, segment)) => (idx, segment),
                    None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
                };
                log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
                self.resolve_name_in_crate_root_or_extern_prelude(&segment, prefer_module(idx))
            }
            PathKind::Plain => {
                let (idx, segment) = match segments.next() {
                    Some((idx, segment)) => (idx, segment),
                    None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
                };
                log::debug!("resolving {:?} in module", segment);
                self.resolve_name_in_module(db, original_module, &segment, prefer_module(idx))
            }
            // PathKind::Self_ => {
            //     PerNs::types(ModuleId { krate: self.krate, local_id: original_module }.into())
            // }
            // PathKind::Super => {
            //     if let Some(p) = self.modules[original_module].parent {
            //         PerNs::types(ModuleId { krate: self.krate, local_id: p }.into())
            //     } else {
            //         log::debug!("super path in root module");
            //         return ResolvePathResult::empty(ReachedFixedPoint::Yes);
            //     }
            // }
            PathKind::Super(lvl) => {
                let m = successors(Some(original_module), |m| self.modules[*m].parent)
                    .nth(lvl as usize);
                if let Some(local_id) = m {
                    PerNs::types(ModuleId { krate: self.krate, local_id }.into())
                } else {
                    log::debug!("super path in root module");
                    return ResolvePathResult::empty(ReachedFixedPoint::Yes);
                }
            }
            PathKind::Abs => {
                // 2018-style absolute path -- only extern prelude
                let segment = match segments.next() {
                    Some((_, segment)) => segment,
                    None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
                };
                if let Some(def) = self.extern_prelude.get(&segment) {
                    log::debug!("absolute path {:?} resolved to crate {:?}", path, def);
                    PerNs::types(*def)
                } else {
                    return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
                }
            }
            PathKind::Type(_) => {
                // This is handled in `infer::infer_path_expr`
                // The result returned here does not matter
                return ResolvePathResult::empty(ReachedFixedPoint::Yes);
            }
        };

        for (i, segment) in segments {
            let curr = match curr_per_ns.take_types() {
                Some(r) => r,
                None => {
                    // we still have path segments left, but the path so far
                    // didn't resolve in the types namespace => no resolution
                    // (don't break here because `curr_per_ns` might contain
                    // something in the value namespace, and it would be wrong
                    // to return that)
                    return ResolvePathResult::empty(ReachedFixedPoint::No);
                }
            };
            // resolve segment in curr

            curr_per_ns = match curr {
                ModuleDefId::ModuleId(module) => {
                    if module.krate != self.krate {
                        let path = ModPath {
                            segments: path.segments[i..].to_vec(),
                            kind: PathKind::Super(0),
                        };
                        log::debug!("resolving {:?} in other crate", path);
                        let defp_map = db.crate_def_map(module.krate);
                        let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow);
                        return ResolvePathResult::with(
                            def,
                            ReachedFixedPoint::Yes,
                            s.map(|s| s + i),
                            Some(module.krate),
                        );
                    }

                    // Since it is a qualified path here, it should not contains legacy macros
                    match self[module.local_id].scope.get(&segment, prefer_module(i)) {
                        Some(res) => res.def,
                        _ => {
                            log::debug!("path segment {:?} not found", segment);
                            return ResolvePathResult::empty(ReachedFixedPoint::No);
                        }
                    }
                }
                ModuleDefId::AdtId(AdtId::EnumId(e)) => {
                    // enum variant
                    tested_by!(can_import_enum_variant);
                    let enum_data = db.enum_data(e);
                    match enum_data.variant(&segment) {
                        Some(local_id) => {
                            let variant = EnumVariantId { parent: e, local_id };
                            PerNs::both(variant.into(), variant.into())
                        }
                        None => {
                            return ResolvePathResult::with(
                                PerNs::types(e.into()),
                                ReachedFixedPoint::Yes,
                                Some(i),
                                Some(self.krate),
                            );
                        }
                    }
                }
                s => {
                    // could be an inherent method call in UFCS form
                    // (`Struct::method`), or some other kind of associated item
                    log::debug!(
                        "path segment {:?} resolved to non-module {:?}, but is not last",
                        segment,
                        curr,
                    );

                    return ResolvePathResult::with(
                        PerNs::types(s),
                        ReachedFixedPoint::Yes,
                        Some(i),
                        Some(self.krate),
                    );
                }
            };
        }

        ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None, Some(self.krate))
    }

    fn resolve_name_in_module(
        &self,
        db: &impl DefDatabase,
        module: LocalModuleId,
        name: &Name,
        shadow: BuiltinShadowMode,
    ) -> PerNs {
        // Resolve in:
        //  - legacy scope of macro
        //  - current module / scope
        //  - extern prelude
        //  - std prelude
        let from_legacy_macro =
            self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros);
        let from_scope =
            self[module].scope.get(name, shadow).map_or_else(PerNs::none, |res| res.def);
        let from_extern_prelude =
            self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
        let from_prelude = self.resolve_in_prelude(db, name, shadow);

        from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude)
    }

    fn resolve_name_in_crate_root_or_extern_prelude(
        &self,
        name: &Name,
        shadow: BuiltinShadowMode,
    ) -> PerNs {
        let from_crate_root =
            self[self.root].scope.get(name, shadow).map_or_else(PerNs::none, |res| res.def);
        let from_extern_prelude = self.resolve_name_in_extern_prelude(name);

        from_crate_root.or(from_extern_prelude)
    }

    fn resolve_in_prelude(
        &self,
        db: &impl DefDatabase,
        name: &Name,
        shadow: BuiltinShadowMode,
    ) -> PerNs {
        if let Some(prelude) = self.prelude {
            let keep;
            let def_map = if prelude.krate == self.krate {
                self
            } else {
                // Extend lifetime
                keep = db.crate_def_map(prelude.krate);
                &keep
            };
            def_map[prelude.local_id]
                .scope
                .get(name, shadow)
                .map_or_else(PerNs::none, |res| res.def)
        } else {
            PerNs::none()
        }
    }
}
<commit_msg>Drop dead code<commit_after>//! This modules implements a function to resolve a path `foo::bar::baz` to a
//! def, which is used within the name resolution.
//!
//! When name resolution is finished, the result of resolving a path is either
//! `Some(def)` or `None`. However, when we are in process of resolving imports
//! or macros, there's a third possibility:
//!
//!   I can't resolve this path right now, but I might be resolve this path
//!   later, when more macros are expanded.
//!
//! `ReachedFixedPoint` signals about this.

use std::iter::successors;

use hir_expand::name::Name;
use ra_db::Edition;
use test_utils::tested_by;

use crate::{
    db::DefDatabase,
    nameres::{BuiltinShadowMode, CrateDefMap},
    path::{ModPath, PathKind},
    per_ns::PerNs,
    AdtId, CrateId, EnumVariantId, LocalModuleId, ModuleDefId, ModuleId,
};

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum ResolveMode {
    Import,
    Other,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub(super) enum ReachedFixedPoint {
    Yes,
    No,
}

#[derive(Debug, Clone)]
pub(super) struct ResolvePathResult {
    pub(super) resolved_def: PerNs,
    pub(super) segment_index: Option<usize>,
    pub(super) reached_fixedpoint: ReachedFixedPoint,
    pub(super) krate: Option<CrateId>,
}

impl ResolvePathResult {
    fn empty(reached_fixedpoint: ReachedFixedPoint) -> ResolvePathResult {
        ResolvePathResult::with(PerNs::none(), reached_fixedpoint, None, None)
    }

    fn with(
        resolved_def: PerNs,
        reached_fixedpoint: ReachedFixedPoint,
        segment_index: Option<usize>,
        krate: Option<CrateId>,
    ) -> ResolvePathResult {
        ResolvePathResult { resolved_def, reached_fixedpoint, segment_index, krate }
    }
}

impl CrateDefMap {
    pub(super) fn resolve_name_in_extern_prelude(&self, name: &Name) -> PerNs {
        self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it))
    }

    // Returns Yes if we are sure that additions to `ItemMap` wouldn't change
    // the result.
    pub(super) fn resolve_path_fp_with_macro(
        &self,
        db: &impl DefDatabase,
        mode: ResolveMode,
        original_module: LocalModuleId,
        path: &ModPath,
        shadow: BuiltinShadowMode,
    ) -> ResolvePathResult {
        // if it is not the last segment, we prefer the module to the builtin
        let prefer_module = |index| {
            if index == path.segments.len() - 1 {
                shadow
            } else {
                BuiltinShadowMode::Module
            }
        };

        let mut segments = path.segments.iter().enumerate();
        let mut curr_per_ns: PerNs = match path.kind {
            PathKind::DollarCrate(krate) => {
                if krate == self.krate {
                    tested_by!(macro_dollar_crate_self);
                    PerNs::types(ModuleId { krate: self.krate, local_id: self.root }.into())
                } else {
                    let def_map = db.crate_def_map(krate);
                    let module = ModuleId { krate, local_id: def_map.root };
                    tested_by!(macro_dollar_crate_other);
                    PerNs::types(module.into())
                }
            }
            PathKind::Crate => {
                PerNs::types(ModuleId { krate: self.krate, local_id: self.root }.into())
            }
            // plain import or absolute path in 2015: crate-relative with
            // fallback to extern prelude (with the simplification in
            // rust-lang/rust#57745)
            // FIXME there must be a nicer way to write this condition
            PathKind::Plain | PathKind::Abs
                if self.edition == Edition::Edition2015
                    && (path.kind == PathKind::Abs || mode == ResolveMode::Import) =>
            {
                let (idx, segment) = match segments.next() {
                    Some((idx, segment)) => (idx, segment),
                    None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
                };
                log::debug!("resolving {:?} in crate root (+ extern prelude)", segment);
                self.resolve_name_in_crate_root_or_extern_prelude(&segment, prefer_module(idx))
            }
            PathKind::Plain => {
                let (idx, segment) = match segments.next() {
                    Some((idx, segment)) => (idx, segment),
                    None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
                };
                log::debug!("resolving {:?} in module", segment);
                self.resolve_name_in_module(db, original_module, &segment, prefer_module(idx))
            }
            PathKind::Super(lvl) => {
                let m = successors(Some(original_module), |m| self.modules[*m].parent)
                    .nth(lvl as usize);
                if let Some(local_id) = m {
                    PerNs::types(ModuleId { krate: self.krate, local_id }.into())
                } else {
                    log::debug!("super path in root module");
                    return ResolvePathResult::empty(ReachedFixedPoint::Yes);
                }
            }
            PathKind::Abs => {
                // 2018-style absolute path -- only extern prelude
                let segment = match segments.next() {
                    Some((_, segment)) => segment,
                    None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
                };
                if let Some(def) = self.extern_prelude.get(&segment) {
                    log::debug!("absolute path {:?} resolved to crate {:?}", path, def);
                    PerNs::types(*def)
                } else {
                    return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
                }
            }
            PathKind::Type(_) => {
                // This is handled in `infer::infer_path_expr`
                // The result returned here does not matter
                return ResolvePathResult::empty(ReachedFixedPoint::Yes);
            }
        };

        for (i, segment) in segments {
            let curr = match curr_per_ns.take_types() {
                Some(r) => r,
                None => {
                    // we still have path segments left, but the path so far
                    // didn't resolve in the types namespace => no resolution
                    // (don't break here because `curr_per_ns` might contain
                    // something in the value namespace, and it would be wrong
                    // to return that)
                    return ResolvePathResult::empty(ReachedFixedPoint::No);
                }
            };
            // resolve segment in curr

            curr_per_ns = match curr {
                ModuleDefId::ModuleId(module) => {
                    if module.krate != self.krate {
                        let path = ModPath {
                            segments: path.segments[i..].to_vec(),
                            kind: PathKind::Super(0),
                        };
                        log::debug!("resolving {:?} in other crate", path);
                        let defp_map = db.crate_def_map(module.krate);
                        let (def, s) = defp_map.resolve_path(db, module.local_id, &path, shadow);
                        return ResolvePathResult::with(
                            def,
                            ReachedFixedPoint::Yes,
                            s.map(|s| s + i),
                            Some(module.krate),
                        );
                    }

                    // Since it is a qualified path here, it should not contains legacy macros
                    match self[module.local_id].scope.get(&segment, prefer_module(i)) {
                        Some(res) => res.def,
                        _ => {
                            log::debug!("path segment {:?} not found", segment);
                            return ResolvePathResult::empty(ReachedFixedPoint::No);
                        }
                    }
                }
                ModuleDefId::AdtId(AdtId::EnumId(e)) => {
                    // enum variant
                    tested_by!(can_import_enum_variant);
                    let enum_data = db.enum_data(e);
                    match enum_data.variant(&segment) {
                        Some(local_id) => {
                            let variant = EnumVariantId { parent: e, local_id };
                            PerNs::both(variant.into(), variant.into())
                        }
                        None => {
                            return ResolvePathResult::with(
                                PerNs::types(e.into()),
                                ReachedFixedPoint::Yes,
                                Some(i),
                                Some(self.krate),
                            );
                        }
                    }
                }
                s => {
                    // could be an inherent method call in UFCS form
                    // (`Struct::method`), or some other kind of associated item
                    log::debug!(
                        "path segment {:?} resolved to non-module {:?}, but is not last",
                        segment,
                        curr,
                    );

                    return ResolvePathResult::with(
                        PerNs::types(s),
                        ReachedFixedPoint::Yes,
                        Some(i),
                        Some(self.krate),
                    );
                }
            };
        }

        ResolvePathResult::with(curr_per_ns, ReachedFixedPoint::Yes, None, Some(self.krate))
    }

    fn resolve_name_in_module(
        &self,
        db: &impl DefDatabase,
        module: LocalModuleId,
        name: &Name,
        shadow: BuiltinShadowMode,
    ) -> PerNs {
        // Resolve in:
        //  - legacy scope of macro
        //  - current module / scope
        //  - extern prelude
        //  - std prelude
        let from_legacy_macro =
            self[module].scope.get_legacy_macro(name).map_or_else(PerNs::none, PerNs::macros);
        let from_scope =
            self[module].scope.get(name, shadow).map_or_else(PerNs::none, |res| res.def);
        let from_extern_prelude =
            self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
        let from_prelude = self.resolve_in_prelude(db, name, shadow);

        from_legacy_macro.or(from_scope).or(from_extern_prelude).or(from_prelude)
    }

    fn resolve_name_in_crate_root_or_extern_prelude(
        &self,
        name: &Name,
        shadow: BuiltinShadowMode,
    ) -> PerNs {
        let from_crate_root =
            self[self.root].scope.get(name, shadow).map_or_else(PerNs::none, |res| res.def);
        let from_extern_prelude = self.resolve_name_in_extern_prelude(name);

        from_crate_root.or(from_extern_prelude)
    }

    fn resolve_in_prelude(
        &self,
        db: &impl DefDatabase,
        name: &Name,
        shadow: BuiltinShadowMode,
    ) -> PerNs {
        if let Some(prelude) = self.prelude {
            let keep;
            let def_map = if prelude.krate == self.krate {
                self
            } else {
                // Extend lifetime
                keep = db.crate_def_map(prelude.krate);
                &keep
            };
            def_map[prelude.local_id]
                .scope
                .get(name, shadow)
                .map_or_else(PerNs::none, |res| res.def)
        } else {
            PerNs::none()
        }
    }
}
<|endoftext|>


<commit_before>use std::iter;
use std::ops::{Index, IndexMut};

#[derive(Clone, PartialEq, Eq)]
pub struct CellBuffer {
    cols: usize,
    rows: usize,
    cells: Vec<Vec<Cell>>,
}

impl CellBuffer {
    pub fn new(cols: usize, rows: usize) -> CellBuffer {
        CellBuffer::with_cell(cols, rows, Cell::default())
    }

    pub fn with_char(cols: usize, rows: usize, ch: char) -> CellBuffer {
        CellBuffer::with_cell(cols, rows, Cell::with_char(ch))
    }

    pub fn with_styles(cols: usize, rows: usize, fg: Style, bg: Style) -> CellBuffer {
        CellBuffer::with_cell(cols, rows, Cell::with_styles(fg, bg))
    }

    pub fn with_cell(cols: usize, rows: usize, cell: Cell) -> CellBuffer {
        CellBuffer {
            cols: cols,
            rows: rows,
            cells: vec![vec![cell; rows]; cols],
        }
    }

    pub fn cols(&self) -> usize {
        self.cols
    }

    pub fn rows(&self) -> usize {
        self.rows
    }

    pub fn size(&self) -> (usize, usize) {
        (self.cols, self.rows)
    }

    pub fn clear(&mut self) {
        self.clear_with_cell(Cell::default());
    }

    pub fn clear_with_char(&mut self, ch: char) {
        self.clear_with_cell(Cell::with_char(ch));
    }

    pub fn clear_with_styles(&mut self, fg: Style, bg: Style) {
        self.clear_with_cell(Cell::with_styles(fg, bg));
    }

    pub fn clear_with_cell(&mut self, blank: Cell) {
        for col in &mut self.cells {
            for cell in col.iter_mut() {
                cell.ch = blank.ch;
                cell.fg = blank.fg;
                cell.bg = blank.bg;
            }
        }
    }

    pub fn resize(&mut self, newcols: usize, newrows: usize, blank: Cell) {
        self.cells.resize(newcols, vec![blank; newrows]);
        for col in &mut self.cells {
            col.resize(newrows, blank);
        }
        self.cols = newcols;
        self.rows = newrows;
    }
}

impl Default for CellBuffer {
    fn default() -> CellBuffer {
        CellBuffer::with_cell(0, 0, Cell::default())
    }
}

impl Index<usize> for CellBuffer {
    type Output = Vec<Cell>;

    fn index(&self, index: usize) -> &Vec<Cell> {
        &self.cells[index]
    }
}

impl IndexMut<usize> for CellBuffer {
    fn index_mut(&mut self, index: usize) -> &mut Vec<Cell> {
        &mut self.cells[index]
    }
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Cell {
    ch: char,
    fg: Style,
    bg: Style,
}

impl Cell {
    pub fn new(ch: char, fg: Style, bg: Style) -> Cell {
        Cell {
            ch: ch,
            fg: fg,
            bg: bg,
        }
    }

    pub fn with_char(ch: char) -> Cell {
        Cell::new(ch, Style::default(), Style::default())
    }

    pub fn with_styles(fg: Style, bg: Style) -> Cell {
        Cell::new(' ', fg, bg)
    }

    pub fn ch(&self) -> char {
        self.ch
    }

    pub fn set_ch(&mut self, newch: char) -> Cell {
        self.ch = newch;
        *self
    }

    pub fn fg(&self) -> Style {
        self.fg
    }

    pub fn fg_mut(&mut self) -> &mut Style {
        &mut self.fg
    }

    pub fn set_fg(&mut self, newfg: Style) -> Cell {
        self.fg = newfg;
        *self
    }

    pub fn bg(&self) -> Style {
        self.bg
    }

    pub fn bg_mut(&mut self) -> &mut Style {
        &mut self.bg
    }

    pub fn set_bg(&mut self, newbg: Style) -> Cell {
        self.bg = newbg;
        *self
    }
}

impl Default for Cell {
    fn default() -> Cell {
        Cell::new(' ', Style::default(), Style::default())
    }
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Style(Color, Attr);

impl Style {
    pub fn new(color: Color, attr: Attr) -> Style {
        Style(color, attr)
    }

    pub fn with_color(c: Color) -> Style {
        Style::new(c, Attr::Default)
    }

    pub fn with_attr(a: Attr) -> Style {
        Style::new(Color::Default, a)
    }

    pub fn color(&self) -> Color {
        self.0
    }

    pub fn set_color(&mut self, newcolor: Color) -> Style {
        self.0 = newcolor;
        *self
    }

    pub fn attr(&self) -> Attr {
        self.1
    }

    pub fn set_attr(&mut self, newattr: Attr) -> Style {
        self.1 = newattr;
        *self
    }
}

impl Default for Style {
    fn default() -> Style {
        Style::new(Color::Default, Attr::Default)
    }
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Color {
    Black = 0x0000,
    Red = 0x0001,
    Green = 0x0002,
    Yellow = 0x0003,
    Blue = 0x0004,
    Magenta = 0x0005,
    Cyan = 0x0006,
    White = 0x0007,
    Default,
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Attr {
    Default,
    Bold,
    Underline,
    Reverse,
}

<commit_msg>use mutable references to allow method chaining<commit_after>use std::iter;
use std::ops::{Index, IndexMut};

#[derive(Clone, PartialEq, Eq)]
pub struct CellBuffer {
    cols: usize,
    rows: usize,
    cells: Vec<Vec<Cell>>,
}

impl CellBuffer {
    pub fn new(cols: usize, rows: usize) -> CellBuffer {
        CellBuffer::with_cell(cols, rows, Cell::default())
    }

    pub fn with_char(cols: usize, rows: usize, ch: char) -> CellBuffer {
        CellBuffer::with_cell(cols, rows, Cell::with_char(ch))
    }

    pub fn with_styles(cols: usize, rows: usize, fg: Style, bg: Style) -> CellBuffer {
        CellBuffer::with_cell(cols, rows, Cell::with_styles(fg, bg))
    }

    pub fn with_cell(cols: usize, rows: usize, cell: Cell) -> CellBuffer {
        CellBuffer {
            cols: cols,
            rows: rows,
            cells: vec![vec![cell; rows]; cols],
        }
    }

    pub fn cols(&self) -> usize {
        self.cols
    }

    pub fn rows(&self) -> usize {
        self.rows
    }

    pub fn size(&self) -> (usize, usize) {
        (self.cols, self.rows)
    }

    pub fn clear(&mut self) {
        self.clear_with_cell(Cell::default());
    }

    pub fn clear_with_char(&mut self, ch: char) {
        self.clear_with_cell(Cell::with_char(ch));
    }

    pub fn clear_with_styles(&mut self, fg: Style, bg: Style) {
        self.clear_with_cell(Cell::with_styles(fg, bg));
    }

    pub fn clear_with_cell(&mut self, blank: Cell) {
        for col in &mut self.cells {
            for cell in col.iter_mut() {
                cell.ch = blank.ch;
                cell.fg = blank.fg;
                cell.bg = blank.bg;
            }
        }
    }

    pub fn resize(&mut self, newcols: usize, newrows: usize, blank: Cell) {
        self.cells.resize(newcols, vec![blank; newrows]);
        for col in &mut self.cells {
            col.resize(newrows, blank);
        }
        self.cols = newcols;
        self.rows = newrows;
    }
}

impl Default for CellBuffer {
    fn default() -> CellBuffer {
        CellBuffer::with_cell(0, 0, Cell::default())
    }
}

impl Index<usize> for CellBuffer {
    type Output = Vec<Cell>;

    fn index(&self, index: usize) -> &Vec<Cell> {
        &self.cells[index]
    }
}

impl IndexMut<usize> for CellBuffer {
    fn index_mut(&mut self, index: usize) -> &mut Vec<Cell> {
        &mut self.cells[index]
    }
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Cell {
    ch: char,
    fg: Style,
    bg: Style,
}

impl Cell {
    pub fn new(ch: char, fg: Style, bg: Style) -> Cell {
        Cell {
            ch: ch,
            fg: fg,
            bg: bg,
        }
    }

    pub fn with_char(ch: char) -> Cell {
        Cell::new(ch, Style::default(), Style::default())
    }

    pub fn with_styles(fg: Style, bg: Style) -> Cell {
        Cell::new(' ', fg, bg)
    }

    pub fn ch(&self) -> char {
        self.ch
    }

    pub fn set_ch(&mut self, newch: char) -> &mut Cell {
        self.ch = newch;
        self
    }

    pub fn fg(&self) -> Style {
        self.fg
    }

    pub fn fg_mut(&mut self) -> &mut Style {
        &mut self.fg
    }

    pub fn set_fg(&mut self, newfg: Style) -> &mut Cell {
        self.fg = newfg;
        self
    }

    pub fn bg(&self) -> Style {
        self.bg
    }

    pub fn bg_mut(&mut self) -> &mut Style {
        &mut self.bg
    }

    pub fn set_bg(&mut self, newbg: Style) -> &mut Cell {
        self.bg = newbg;
        self
    }
}

impl Default for Cell {
    fn default() -> Cell {
        Cell::new(' ', Style::default(), Style::default())
    }
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub struct Style(Color, Attr);

impl Style {
    pub fn new(color: Color, attr: Attr) -> Style {
        Style(color, attr)
    }

    pub fn with_color(c: Color) -> Style {
        Style::new(c, Attr::Default)
    }

    pub fn with_attr(a: Attr) -> Style {
        Style::new(Color::Default, a)
    }

    pub fn color(&self) -> Color {
        self.0
    }

    pub fn set_color(&mut self, newcolor: Color) -> &mut Style {
        self.0 = newcolor;
        self
    }

    pub fn attr(&self) -> Attr {
        self.1
    }

    pub fn set_attr(&mut self, newattr: Attr) -> &mut Style {
        self.1 = newattr;
        self
    }
}

impl Default for Style {
    fn default() -> Style {
        Style::new(Color::Default, Attr::Default)
    }
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Color {
    Black = 0x0000,
    Red = 0x0001,
    Green = 0x0002,
    Yellow = 0x0003,
    Blue = 0x0004,
    Magenta = 0x0005,
    Cyan = 0x0006,
    White = 0x0007,
    Default,
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum Attr {
    Default,
    Bold,
    Underline,
    Reverse,
}

<|endoftext|>


<commit_before>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use clap::{ArgEnum, Parser};
use common::ConsoleLogger;
use log::{error, info};
use relay_compiler::{
    build_project::artifact_writer::ArtifactValidationWriter,
    compiler::Compiler,
    config::{Config, SingleProjectConfigFile},
    FileSourceKind, LocalPersister, OperationPersister, PersistConfig, RemotePersister,
};
use relay_typegen::TypegenLanguage;
use simplelog::{ColorChoice, ConfigBuilder, LevelFilter, TermLogger, TerminalMode};
use std::{
    env::{self, current_dir},
    path::PathBuf,
    process::Command,
    sync::Arc,
};

#[derive(Parser)]
#[clap(
    name = "Relay Compiler",
    version = option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"),
    about = "Compiles Relay files and writes generated files.",
    rename_all = "camel_case"
)]
struct Opt {
    /// Compile and watch for changes
    #[clap(long, short)]
    watch: bool,

    /// Compile using this config file. If not provided, searches for a config in
    /// package.json under the `relay` key or `relay.config.json` files among other up
    /// from the current working directory.
    config: Option<PathBuf>,

    #[clap(flatten)]
    cli_config: CliConfig,

    /// Run the persister even if the query has not changed.
    #[clap(long)]
    repersist: bool,

    /// Verbosity level
    #[clap(long, arg_enum, default_value = "verbose")]
    output: OutputKind,

    /// Looks for pending changes and exits with non-zero code instead of
    /// writing to disk
    #[clap(long)]
    validate: bool,
}

#[derive(ArgEnum, Clone, Copy)]
enum OutputKind {
    Debug,
    Quiet,
    QuietWithErrors,
    Verbose,
}

#[derive(Parser)]
#[clap(rename_all = "camel_case")]
pub struct CliConfig {
    /// Path for the directory where to search for source code
    #[clap(long)]
    pub src: Option<PathBuf>,
    /// Path to schema file
    #[clap(long)]
    pub schema: Option<PathBuf>,
    /// Path to a directory, where the compiler should write artifacts
    #[clap(long)]
    pub artifact_directory: Option<PathBuf>,
}

impl CliConfig {
    pub fn is_defined(&self) -> bool {
        self.src.is_some() || self.schema.is_some() || self.artifact_directory.is_some()
    }
}

impl From<CliConfig> for SingleProjectConfigFile {
    fn from(cli_config: CliConfig) -> Self {
        SingleProjectConfigFile {
            schema: cli_config.schema.expect("schema is required."),
            artifact_directory: cli_config.artifact_directory,
            src: cli_config.src.unwrap_or_else(|| PathBuf::from("./")),
            language: Some(TypegenLanguage::TypeScript),
            ..Default::default()
        }
    }
}

#[tokio::main]
async fn main() {
    let opt = Opt::parse();

    let log_level = match opt.output {
        OutputKind::Debug => LevelFilter::Debug,
        OutputKind::Quiet => LevelFilter::Off,
        OutputKind::QuietWithErrors => LevelFilter::Error,
        OutputKind::Verbose => LevelFilter::Info,
    };

    let config = ConfigBuilder::new()
        .set_time_level(LevelFilter::Off)
        .set_target_level(LevelFilter::Off)
        .set_location_level(LevelFilter::Off)
        .set_thread_level(LevelFilter::Off)
        .build();

    TermLogger::init(log_level, config, TerminalMode::Mixed, ColorChoice::Auto).unwrap();

    let config_result = if let Some(config_path) = opt.config {
        Config::load(config_path)
    } else if opt.cli_config.is_defined() {
        Ok(Config::from(SingleProjectConfigFile::from(opt.cli_config)))
    } else {
        Config::search(&current_dir().expect("Unable to get current working directory."))
    };

    let mut config = config_result.unwrap_or_else(|err| {
        error!("{}", err);
        std::process::exit(1);
    });

    if opt.validate {
        config.artifact_writer = Box::new(ArtifactValidationWriter::default());
    }

    config.create_operation_persister = Some(Box::new(|project_config| {
        project_config.persist.as_ref().map(
            |persist_config| -> Box<dyn OperationPersister + Send + Sync> {
                match persist_config {
                    PersistConfig::Remote(remote_config) => {
                        Box::new(RemotePersister::new(remote_config.clone()))
                    }
                    PersistConfig::Local(local_config) => {
                        Box::new(LocalPersister::new(local_config.clone()))
                    }
                }
            },
        )
    }));

    config.file_source_config = if should_use_watchman() {
        FileSourceKind::Watchman
    } else {
        FileSourceKind::WalkDir
    };
    config.repersist_operations = opt.repersist;

    if opt.watch && !matches!(&config.file_source_config, FileSourceKind::Watchman) {
        panic!(
            "Cannot run relay in watch mode if `watchman` is not available (or explicitly disabled)."
        );
    }

    let compiler = Compiler::new(Arc::new(config), Arc::new(ConsoleLogger));

    if opt.watch {
        if let Err(err) = compiler.watch().await {
            error!("Watchman error: {}", err);
            std::process::exit(1);
        }
    } else {
        match compiler.compile().await {
            Ok(_compiler_state) => {
                info!("Done");
            }
            Err(_err) => {
                std::process::exit(1);
            }
        }
    }
}

/// Check if `watchman` is available.
/// Additionally, this method is checking for an existence of `FORCE_NO_WATCHMAN`
/// environment variable. If this `FORCE_NO_WATCHMAN` is set, this method will return `false`
/// and compiler will use non-watchman file finder.
fn should_use_watchman() -> bool {
    let check_watchman = Command::new("watchman")
        .args(["list-capabilities"])
        .output();

    check_watchman.is_ok() && env::var("FORCE_NO_WATCHMAN").is_err()
}
<commit_msg>Rename config to log_config<commit_after>/*
 * Copyright (c) Meta Platforms, Inc. and affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use clap::{ArgEnum, Parser};
use common::ConsoleLogger;
use log::{error, info};
use relay_compiler::{
    build_project::artifact_writer::ArtifactValidationWriter,
    compiler::Compiler,
    config::{Config, SingleProjectConfigFile},
    FileSourceKind, LocalPersister, OperationPersister, PersistConfig, RemotePersister,
};
use relay_typegen::TypegenLanguage;
use simplelog::{
    ColorChoice, ConfigBuilder as SimpleLogConfigBuilder, LevelFilter, TermLogger, TerminalMode,
};
use std::{
    env::{self, current_dir},
    path::PathBuf,
    process::Command,
    sync::Arc,
};

#[derive(Parser)]
#[clap(
    name = "Relay Compiler",
    version = option_env!("CARGO_PKG_VERSION").unwrap_or("unknown"),
    about = "Compiles Relay files and writes generated files.",
    rename_all = "camel_case"
)]
struct Opt {
    /// Compile and watch for changes
    #[clap(long, short)]
    watch: bool,

    /// Compile using this config file. If not provided, searches for a config in
    /// package.json under the `relay` key or `relay.config.json` files among other up
    /// from the current working directory.
    config: Option<PathBuf>,

    #[clap(flatten)]
    cli_config: CliConfig,

    /// Run the persister even if the query has not changed.
    #[clap(long)]
    repersist: bool,

    /// Verbosity level
    #[clap(long, arg_enum, default_value = "verbose")]
    output: OutputKind,

    /// Looks for pending changes and exits with non-zero code instead of
    /// writing to disk
    #[clap(long)]
    validate: bool,
}

#[derive(ArgEnum, Clone, Copy)]
enum OutputKind {
    Debug,
    Quiet,
    QuietWithErrors,
    Verbose,
}

#[derive(Parser)]
#[clap(rename_all = "camel_case")]
pub struct CliConfig {
    /// Path for the directory where to search for source code
    #[clap(long)]
    pub src: Option<PathBuf>,
    /// Path to schema file
    #[clap(long)]
    pub schema: Option<PathBuf>,
    /// Path to a directory, where the compiler should write artifacts
    #[clap(long)]
    pub artifact_directory: Option<PathBuf>,
}

impl CliConfig {
    pub fn is_defined(&self) -> bool {
        self.src.is_some() || self.schema.is_some() || self.artifact_directory.is_some()
    }
}

impl From<CliConfig> for SingleProjectConfigFile {
    fn from(cli_config: CliConfig) -> Self {
        SingleProjectConfigFile {
            schema: cli_config.schema.expect("schema is required."),
            artifact_directory: cli_config.artifact_directory,
            src: cli_config.src.unwrap_or_else(|| PathBuf::from("./")),
            language: Some(TypegenLanguage::TypeScript),
            ..Default::default()
        }
    }
}

#[tokio::main]
async fn main() {
    let opt = Opt::parse();

    let log_level = match opt.output {
        OutputKind::Debug => LevelFilter::Debug,
        OutputKind::Quiet => LevelFilter::Off,
        OutputKind::QuietWithErrors => LevelFilter::Error,
        OutputKind::Verbose => LevelFilter::Info,
    };

    let log_config = SimpleLogConfigBuilder::new()
        .set_time_level(LevelFilter::Off)
        .set_target_level(LevelFilter::Off)
        .set_location_level(LevelFilter::Off)
        .set_thread_level(LevelFilter::Off)
        .build();

    TermLogger::init(
        log_level,
        log_config,
        TerminalMode::Mixed,
        ColorChoice::Auto,
    )
    .unwrap();

    let config_result = if let Some(config_path) = opt.config {
        Config::load(config_path)
    } else if opt.cli_config.is_defined() {
        Ok(Config::from(SingleProjectConfigFile::from(opt.cli_config)))
    } else {
        Config::search(&current_dir().expect("Unable to get current working directory."))
    };

    let mut config = config_result.unwrap_or_else(|err| {
        error!("{}", err);
        std::process::exit(1);
    });

    if opt.validate {
        config.artifact_writer = Box::new(ArtifactValidationWriter::default());
    }

    config.create_operation_persister = Some(Box::new(|project_config| {
        project_config.persist.as_ref().map(
            |persist_config| -> Box<dyn OperationPersister + Send + Sync> {
                match persist_config {
                    PersistConfig::Remote(remote_config) => {
                        Box::new(RemotePersister::new(remote_config.clone()))
                    }
                    PersistConfig::Local(local_config) => {
                        Box::new(LocalPersister::new(local_config.clone()))
                    }
                }
            },
        )
    }));

    config.file_source_config = if should_use_watchman() {
        FileSourceKind::Watchman
    } else {
        FileSourceKind::WalkDir
    };
    config.repersist_operations = opt.repersist;

    if opt.watch && !matches!(&config.file_source_config, FileSourceKind::Watchman) {
        panic!(
            "Cannot run relay in watch mode if `watchman` is not available (or explicitly disabled)."
        );
    }

    let compiler = Compiler::new(Arc::new(config), Arc::new(ConsoleLogger));

    if opt.watch {
        if let Err(err) = compiler.watch().await {
            error!("Watchman error: {}", err);
            std::process::exit(1);
        }
    } else {
        match compiler.compile().await {
            Ok(_compiler_state) => {
                info!("Done");
            }
            Err(_err) => {
                std::process::exit(1);
            }
        }
    }
}

/// Check if `watchman` is available.
/// Additionally, this method is checking for an existence of `FORCE_NO_WATCHMAN`
/// environment variable. If this `FORCE_NO_WATCHMAN` is set, this method will return `false`
/// and compiler will use non-watchman file finder.
fn should_use_watchman() -> bool {
    let check_watchman = Command::new("watchman")
        .args(["list-capabilities"])
        .output();

    check_watchman.is_ok() && env::var("FORCE_NO_WATCHMAN").is_err()
}
<|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 http://mozilla.org/MPL/2.0/. */

use canvas_traits::{CanvasMsg, FromLayoutMsg};
use dom::attr::Attr;
use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding;
use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes;
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast};
use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRenderingContext;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{HeapGCValue, JS, LayoutJS, MutNullableHeap, Root};
use dom::bindings::utils::{Reflectable};
use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers};
use dom::document::Document;
use dom::element::AttributeMutation;
use dom::htmlelement::HTMLElement;
use dom::node::{Node, window_from_node};
use dom::virtualmethods::VirtualMethods;
use dom::webglrenderingcontext::{LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext};
use euclid::size::Size2D;
use ipc_channel::ipc::{self, IpcSender};
use js::jsapi::{HandleValue, JSContext};
use offscreen_gl_context::GLContextAttributes;
use std::cell::Cell;
use std::default::Default;
use std::iter::repeat;
use util::str::{DOMString, parse_unsigned_integer};

const DEFAULT_WIDTH: u32 = 300;
const DEFAULT_HEIGHT: u32 = 150;

#[must_root]
#[derive(JSTraceable, Clone, HeapSizeOf)]
pub enum CanvasContext {
    Context2d(JS<CanvasRenderingContext2D>),
    WebGL(JS<WebGLRenderingContext>),
}

impl HeapGCValue for CanvasContext {}

#[dom_struct]
pub struct HTMLCanvasElement {
    htmlelement: HTMLElement,
    context: MutNullableHeap<CanvasContext>,
    width: Cell<u32>,
    height: Cell<u32>,
}

impl PartialEq for HTMLCanvasElement {
    fn eq(&self, other: &HTMLCanvasElement) -> bool {
        self as *const HTMLCanvasElement == &*other
    }
}

impl HTMLCanvasElement {
    fn new_inherited(localName: DOMString,
                     prefix: Option<DOMString>,
                     document: &Document) -> HTMLCanvasElement {
        HTMLCanvasElement {
            htmlelement:
                HTMLElement::new_inherited(localName, prefix, document),
            context: Default::default(),
            width: Cell::new(DEFAULT_WIDTH),
            height: Cell::new(DEFAULT_HEIGHT),
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(localName: DOMString,
               prefix: Option<DOMString>,
               document: &Document) -> Root<HTMLCanvasElement> {
        let element = HTMLCanvasElement::new_inherited(localName, prefix, document);
        Node::reflect_node(box element, document, HTMLCanvasElementBinding::Wrap)
    }

    fn recreate_contexts(&self) {
        let size = self.get_size();
        if let Some(context) = self.context.get() {
            match context {
                CanvasContext::Context2d(context) => context.root().r().recreate(size),
                CanvasContext::WebGL(context) => context.root().r().recreate(size),
            }
        }
    }

    pub fn get_size(&self) -> Size2D<i32> {
        Size2D::new(self.width.get() as i32, self.height.get() as i32)
    }
}

pub trait LayoutHTMLCanvasElementHelpers {
    #[allow(unsafe_code)]
    unsafe fn get_renderer_id(&self) -> Option<usize>;
    #[allow(unsafe_code)]
    unsafe fn get_ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>>;
    #[allow(unsafe_code)]
    unsafe fn get_canvas_width(&self) -> u32;
    #[allow(unsafe_code)]
    unsafe fn get_canvas_height(&self) -> u32;
}

impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> {
    #[allow(unsafe_code)]
    unsafe fn get_renderer_id(&self) -> Option<usize> {
        let ref canvas = *self.unsafe_get();
        canvas.context.get().map(|context| {
            match context {
                CanvasContext::Context2d(context) => context.to_layout().get_renderer_id(),
                CanvasContext::WebGL(context) => context.to_layout().get_renderer_id(),
            }
        })
    }

    #[allow(unsafe_code)]
    unsafe fn get_ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> {
        let ref canvas = *self.unsafe_get();
        canvas.context.get().map(|context| {
            match context {
                CanvasContext::Context2d(context) => context.to_layout().get_ipc_renderer(),
                CanvasContext::WebGL(context) => context.to_layout().get_ipc_renderer(),
            }
        })
    }

    #[allow(unsafe_code)]
    unsafe fn get_canvas_width(&self) -> u32 {
        (*self.unsafe_get()).width.get()
    }

    #[allow(unsafe_code)]
    unsafe fn get_canvas_height(&self) -> u32 {
        (*self.unsafe_get()).height.get()
    }
}

impl HTMLCanvasElement {
    pub fn ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> {
        self.context.get().map(|context| {
            match context {
                CanvasContext::Context2d(context) => context.root().r().ipc_renderer(),
                CanvasContext::WebGL(context) => context.root().r().ipc_renderer(),
            }
        })
    }

    pub fn get_or_init_2d_context(&self) -> Option<Root<CanvasRenderingContext2D>> {
        if self.context.get().is_none() {
            let window = window_from_node(self);
            let size = self.get_size();
            let context = CanvasRenderingContext2D::new(GlobalRef::Window(window.r()), self, size);
            self.context.set(Some(CanvasContext::Context2d(JS::from_rooted(&context))));
        }

        match self.context.get().unwrap() {
            CanvasContext::Context2d(context) => Some(context.root()),
            _   => None,
        }
    }

    pub fn get_or_init_webgl_context(&self,
                                 cx: *mut JSContext,
                                 attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>> {
        if self.context.get().is_none() {
            let window = window_from_node(self);
            let size = self.get_size();

            let attrs = if let Some(webgl_attributes) = attrs {
                if let Ok(ref attrs) = WebGLContextAttributes::new(cx, webgl_attributes) {
                    From::from(attrs)
                } else {
                    debug!("Unexpected error on conversion of WebGLContextAttributes");
                    return None;
                }
            } else {
                GLContextAttributes::default()
            };

            let maybe_ctx = WebGLRenderingContext::new(GlobalRef::Window(window.r()), self, size, attrs);

            self.context.set(maybe_ctx.map( |ctx| CanvasContext::WebGL(JS::from_rooted(&ctx))));
        }

        if let Some(context) = self.context.get() {
            match context {
                CanvasContext::WebGL(context) => Some(context.root()),
                _ => None,
            }
        } else {
            None
        }
    }

    pub fn is_valid(&self) -> bool {
        self.height.get() != 0 && self.width.get() != 0
    }

    pub fn fetch_all_data(&self) -> Option<(Vec<u8>, Size2D<i32>)> {
        let size = self.get_size();

        if size.width == 0 || size.height == 0 {
            return None
        }

        let data = if let Some(renderer) = self.ipc_renderer() {
            let (sender, receiver) = ipc::channel().unwrap();
            let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendPixelContents(sender));
            renderer.send(msg).unwrap();

            receiver.recv().unwrap().to_vec()
        } else {
            repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect()
        };

        Some((data, size))
    }
}

impl HTMLCanvasElementMethods for HTMLCanvasElement {
    // https://html.spec.whatwg.org/multipage/#dom-canvas-width
    fn Width(&self) -> u32 {
        self.width.get()
    }

    // https://html.spec.whatwg.org/multipage/#dom-canvas-width
    fn SetWidth(&self, width: u32) {
        let elem = ElementCast::from_ref(self);
        elem.set_uint_attribute(&atom!("width"), width)
    }

    // https://html.spec.whatwg.org/multipage/#dom-canvas-height
    fn Height(&self) -> u32 {
        self.height.get()
    }

    // https://html.spec.whatwg.org/multipage/#dom-canvas-height
    fn SetHeight(&self, height: u32) {
        let elem = ElementCast::from_ref(self);
        elem.set_uint_attribute(&atom!("height"), height)
    }

    // https://html.spec.whatwg.org/multipage/#dom-canvas-getcontext
    fn GetContext(&self,
                  cx: *mut JSContext,
                  id: DOMString,
                  attributes: Vec<HandleValue>)
        -> Option<CanvasRenderingContext2DOrWebGLRenderingContext> {
        match &*id {
            "2d" => {
                self.get_or_init_2d_context()
                    .map(|ctx| CanvasRenderingContext2DOrWebGLRenderingContext::eCanvasRenderingContext2D(
                                   ctx))
            }
            "webgl" | "experimental-webgl" => {
                self.get_or_init_webgl_context(cx, attributes.get(0).map(|p| *p))
                    .map(|ctx| CanvasRenderingContext2DOrWebGLRenderingContext::eWebGLRenderingContext(
                                   ctx))
            }
            _ => None
        }
    }
}

impl VirtualMethods for HTMLCanvasElement {
    fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
        let element: &HTMLElement = HTMLElementCast::from_ref(self);
        Some(element as &VirtualMethods)
    }

    fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
        self.super_type().unwrap().attribute_mutated(attr, mutation);
        let recreate = match attr.local_name() {
            &atom!(width) => {
                let width = mutation.new_value(attr).and_then(|value| {
                    parse_unsigned_integer(value.chars())
                });
                self.width.set(width.unwrap_or(DEFAULT_WIDTH));
                true
            },
            &atom!(height) => {
                let height = mutation.new_value(attr).and_then(|value| {
                    parse_unsigned_integer(value.chars())
                });
                self.height.set(height.unwrap_or(DEFAULT_HEIGHT));
                true
            },
            _ => false,
        };
        if recreate {
            self.recreate_contexts();
        }
    }
}

impl<'a> From<&'a WebGLContextAttributes> for GLContextAttributes {
    fn from(attrs: &'a WebGLContextAttributes) -> GLContextAttributes {
        GLContextAttributes {
            alpha: attrs.alpha,
            depth: attrs.depth,
            stencil: attrs.stencil,
            antialias: attrs.antialias,
            premultiplied_alpha: attrs.premultipliedAlpha,
            preserve_drawing_buffer: attrs.preserveDrawingBuffer,
        }
    }
}

pub mod utils {
    use dom::window::Window;
    use ipc_channel::ipc;
    use net_traits::image_cache_task::{ImageCacheChan, ImageResponse};
    use url::Url;

    pub fn request_image_from_cache(window: &Window, url: Url) -> ImageResponse {
        let image_cache = window.image_cache_task();
        let (response_chan, response_port) = ipc::channel().unwrap();
        image_cache.request_image(url, ImageCacheChan(response_chan), None);
        let result = response_port.recv().unwrap();
        result.image_response
    }
}
<commit_msg>Don't use MutNullableHeap in HTMLCanvasElement.<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 http://mozilla.org/MPL/2.0/. */

use canvas_traits::{CanvasMsg, FromLayoutMsg};
use dom::attr::Attr;
use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding;
use dom::bindings::codegen::Bindings::HTMLCanvasElementBinding::HTMLCanvasElementMethods;
use dom::bindings::codegen::Bindings::WebGLRenderingContextBinding::WebGLContextAttributes;
use dom::bindings::codegen::InheritTypes::{ElementCast, HTMLElementCast};
use dom::bindings::codegen::UnionTypes::CanvasRenderingContext2DOrWebGLRenderingContext;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{HeapGCValue, JS, LayoutJS, Root};
use dom::bindings::utils::{Reflectable};
use dom::canvasrenderingcontext2d::{CanvasRenderingContext2D, LayoutCanvasRenderingContext2DHelpers};
use dom::document::Document;
use dom::element::AttributeMutation;
use dom::htmlelement::HTMLElement;
use dom::node::{Node, window_from_node};
use dom::virtualmethods::VirtualMethods;
use dom::webglrenderingcontext::{LayoutCanvasWebGLRenderingContextHelpers, WebGLRenderingContext};
use euclid::size::Size2D;
use ipc_channel::ipc::{self, IpcSender};
use js::jsapi::{HandleValue, JSContext};
use offscreen_gl_context::GLContextAttributes;
use std::cell::Cell;
use std::iter::repeat;
use util::str::{DOMString, parse_unsigned_integer};

const DEFAULT_WIDTH: u32 = 300;
const DEFAULT_HEIGHT: u32 = 150;

#[must_root]
#[derive(JSTraceable, Clone, HeapSizeOf)]
pub enum CanvasContext {
    Context2d(JS<CanvasRenderingContext2D>),
    WebGL(JS<WebGLRenderingContext>),
}

impl HeapGCValue for CanvasContext {}

#[dom_struct]
pub struct HTMLCanvasElement {
    htmlelement: HTMLElement,
    context: DOMRefCell<Option<CanvasContext>>,
    width: Cell<u32>,
    height: Cell<u32>,
}

impl PartialEq for HTMLCanvasElement {
    fn eq(&self, other: &HTMLCanvasElement) -> bool {
        self as *const HTMLCanvasElement == &*other
    }
}

impl HTMLCanvasElement {
    fn new_inherited(localName: DOMString,
                     prefix: Option<DOMString>,
                     document: &Document) -> HTMLCanvasElement {
        HTMLCanvasElement {
            htmlelement: HTMLElement::new_inherited(localName, prefix, document),
            context: DOMRefCell::new(None),
            width: Cell::new(DEFAULT_WIDTH),
            height: Cell::new(DEFAULT_HEIGHT),
        }
    }

    #[allow(unrooted_must_root)]
    pub fn new(localName: DOMString,
               prefix: Option<DOMString>,
               document: &Document) -> Root<HTMLCanvasElement> {
        let element = HTMLCanvasElement::new_inherited(localName, prefix, document);
        Node::reflect_node(box element, document, HTMLCanvasElementBinding::Wrap)
    }

    fn recreate_contexts(&self) {
        let size = self.get_size();
        if let Some(ref context) = *self.context.borrow() {
            match *context {
                CanvasContext::Context2d(ref context) => context.root().r().recreate(size),
                CanvasContext::WebGL(ref context) => context.root().r().recreate(size),
            }
        }
    }

    pub fn get_size(&self) -> Size2D<i32> {
        Size2D::new(self.width.get() as i32, self.height.get() as i32)
    }
}

pub trait LayoutHTMLCanvasElementHelpers {
    #[allow(unsafe_code)]
    unsafe fn get_renderer_id(&self) -> Option<usize>;
    #[allow(unsafe_code)]
    unsafe fn get_ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>>;
    #[allow(unsafe_code)]
    unsafe fn get_canvas_width(&self) -> u32;
    #[allow(unsafe_code)]
    unsafe fn get_canvas_height(&self) -> u32;
}

impl LayoutHTMLCanvasElementHelpers for LayoutJS<HTMLCanvasElement> {
    #[allow(unsafe_code)]
    unsafe fn get_renderer_id(&self) -> Option<usize> {
        let ref canvas = *self.unsafe_get();
        canvas.context.borrow_for_layout().as_ref().map(|context| {
            match *context {
                CanvasContext::Context2d(ref context) => context.to_layout().get_renderer_id(),
                CanvasContext::WebGL(ref context) => context.to_layout().get_renderer_id(),
            }
        })
    }

    #[allow(unsafe_code)]
    unsafe fn get_ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> {
        let ref canvas = *self.unsafe_get();
        canvas.context.borrow_for_layout().as_ref().map(|context| {
            match *context {
                CanvasContext::Context2d(ref context) => context.to_layout().get_ipc_renderer(),
                CanvasContext::WebGL(ref context) => context.to_layout().get_ipc_renderer(),
            }
        })
    }

    #[allow(unsafe_code)]
    unsafe fn get_canvas_width(&self) -> u32 {
        (*self.unsafe_get()).width.get()
    }

    #[allow(unsafe_code)]
    unsafe fn get_canvas_height(&self) -> u32 {
        (*self.unsafe_get()).height.get()
    }
}

impl HTMLCanvasElement {
    pub fn ipc_renderer(&self) -> Option<IpcSender<CanvasMsg>> {
        self.context.borrow().as_ref().map(|context| {
            match *context {
                CanvasContext::Context2d(ref context) => context.root().r().ipc_renderer(),
                CanvasContext::WebGL(ref context) => context.root().r().ipc_renderer(),
            }
        })
    }

    pub fn get_or_init_2d_context(&self) -> Option<Root<CanvasRenderingContext2D>> {
        if self.context.borrow().is_none() {
            let window = window_from_node(self);
            let size = self.get_size();
            let context = CanvasRenderingContext2D::new(GlobalRef::Window(window.r()), self, size);
            *self.context.borrow_mut() = Some(CanvasContext::Context2d(JS::from_rooted(&context)));
        }

        match *self.context.borrow().as_ref().unwrap() {
            CanvasContext::Context2d(ref context) => Some(context.root()),
            _   => None,
        }
    }

    pub fn get_or_init_webgl_context(&self,
                                 cx: *mut JSContext,
                                 attrs: Option<HandleValue>) -> Option<Root<WebGLRenderingContext>> {
        if self.context.borrow().is_none() {
            let window = window_from_node(self);
            let size = self.get_size();

            let attrs = if let Some(webgl_attributes) = attrs {
                if let Ok(ref attrs) = WebGLContextAttributes::new(cx, webgl_attributes) {
                    From::from(attrs)
                } else {
                    debug!("Unexpected error on conversion of WebGLContextAttributes");
                    return None;
                }
            } else {
                GLContextAttributes::default()
            };

            let maybe_ctx = WebGLRenderingContext::new(GlobalRef::Window(window.r()), self, size, attrs);

            *self.context.borrow_mut() = maybe_ctx.map( |ctx| CanvasContext::WebGL(JS::from_rooted(&ctx)));
        }

        if let Some(ref context) = *self.context.borrow() {
            match *context {
                CanvasContext::WebGL(ref context) => Some(context.root()),
                _ => None,
            }
        } else {
            None
        }
    }

    pub fn is_valid(&self) -> bool {
        self.height.get() != 0 && self.width.get() != 0
    }

    pub fn fetch_all_data(&self) -> Option<(Vec<u8>, Size2D<i32>)> {
        let size = self.get_size();

        if size.width == 0 || size.height == 0 {
            return None
        }

        let data = if let Some(renderer) = self.ipc_renderer() {
            let (sender, receiver) = ipc::channel().unwrap();
            let msg = CanvasMsg::FromLayout(FromLayoutMsg::SendPixelContents(sender));
            renderer.send(msg).unwrap();

            receiver.recv().unwrap().to_vec()
        } else {
            repeat(0xffu8).take((size.height as usize) * (size.width as usize) * 4).collect()
        };

        Some((data, size))
    }
}

impl HTMLCanvasElementMethods for HTMLCanvasElement {
    // https://html.spec.whatwg.org/multipage/#dom-canvas-width
    fn Width(&self) -> u32 {
        self.width.get()
    }

    // https://html.spec.whatwg.org/multipage/#dom-canvas-width
    fn SetWidth(&self, width: u32) {
        let elem = ElementCast::from_ref(self);
        elem.set_uint_attribute(&atom!("width"), width)
    }

    // https://html.spec.whatwg.org/multipage/#dom-canvas-height
    fn Height(&self) -> u32 {
        self.height.get()
    }

    // https://html.spec.whatwg.org/multipage/#dom-canvas-height
    fn SetHeight(&self, height: u32) {
        let elem = ElementCast::from_ref(self);
        elem.set_uint_attribute(&atom!("height"), height)
    }

    // https://html.spec.whatwg.org/multipage/#dom-canvas-getcontext
    fn GetContext(&self,
                  cx: *mut JSContext,
                  id: DOMString,
                  attributes: Vec<HandleValue>)
        -> Option<CanvasRenderingContext2DOrWebGLRenderingContext> {
        match &*id {
            "2d" => {
                self.get_or_init_2d_context()
                    .map(|ctx| CanvasRenderingContext2DOrWebGLRenderingContext::eCanvasRenderingContext2D(
                                   ctx))
            }
            "webgl" | "experimental-webgl" => {
                self.get_or_init_webgl_context(cx, attributes.get(0).map(|p| *p))
                    .map(|ctx| CanvasRenderingContext2DOrWebGLRenderingContext::eWebGLRenderingContext(
                                   ctx))
            }
            _ => None
        }
    }
}

impl VirtualMethods for HTMLCanvasElement {
    fn super_type<'b>(&'b self) -> Option<&'b VirtualMethods> {
        let element: &HTMLElement = HTMLElementCast::from_ref(self);
        Some(element as &VirtualMethods)
    }

    fn attribute_mutated(&self, attr: &Attr, mutation: AttributeMutation) {
        self.super_type().unwrap().attribute_mutated(attr, mutation);
        let recreate = match attr.local_name() {
            &atom!(width) => {
                let width = mutation.new_value(attr).and_then(|value| {
                    parse_unsigned_integer(value.chars())
                });
                self.width.set(width.unwrap_or(DEFAULT_WIDTH));
                true
            },
            &atom!(height) => {
                let height = mutation.new_value(attr).and_then(|value| {
                    parse_unsigned_integer(value.chars())
                });
                self.height.set(height.unwrap_or(DEFAULT_HEIGHT));
                true
            },
            _ => false,
        };
        if recreate {
            self.recreate_contexts();
        }
    }
}

impl<'a> From<&'a WebGLContextAttributes> for GLContextAttributes {
    fn from(attrs: &'a WebGLContextAttributes) -> GLContextAttributes {
        GLContextAttributes {
            alpha: attrs.alpha,
            depth: attrs.depth,
            stencil: attrs.stencil,
            antialias: attrs.antialias,
            premultiplied_alpha: attrs.premultipliedAlpha,
            preserve_drawing_buffer: attrs.preserveDrawingBuffer,
        }
    }
}

pub mod utils {
    use dom::window::Window;
    use ipc_channel::ipc;
    use net_traits::image_cache_task::{ImageCacheChan, ImageResponse};
    use url::Url;

    pub fn request_image_from_cache(window: &Window, url: Url) -> ImageResponse {
        let image_cache = window.image_cache_task();
        let (response_chan, response_port) = ipc::channel().unwrap();
        image_cache.request_image(url, ImageCacheChan(response_chan), None);
        let result = response_port.recv().unwrap();
        result.image_response
    }
}
<|endoftext|>


<commit_before>// Copyright 2015 The Rust Project Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::mem;
use std::cell::UnsafeCell;

pub struct ReentrantMutex { inner: UnsafeCell<ffi::CRITICAL_SECTION> }

unsafe impl Send for ReentrantMutex {}
unsafe impl Sync for ReentrantMutex {}

impl ReentrantMutex {
    pub unsafe fn uninitialized() -> ReentrantMutex {
        mem::uninitialized()
    }

    pub unsafe fn init(&mut self) -> ReentrantMutex {
        ffi::InitializeCriticalSection(self.inner.get());
    }

    pub unsafe fn lock(&self) {
        ffi::EnterCriticalSection(self.inner.get());
    }

    #[inline]
    pub unsafe fn try_lock(&self) -> bool {
        ffi::TryEnterCriticalSection(self.inner.get()) != 0
    }

    pub unsafe fn unlock(&self) {
        ffi::LeaveCriticalSection(self.inner.get());
    }

    pub unsafe fn destroy(&self) {
        ffi::DeleteCriticalSection(self.inner.get());
    }
}

mod ffi {
    use libc::{LPVOID, LONG, HANDLE, c_ulong};
    pub type ULONG_PTR = c_ulong;

    #[repr(C)]
    pub struct CRITICAL_SECTION {
        CriticalSectionDebug: LPVOID,
        LockCount: LONG,
        RecursionCount: LONG,
        OwningThread: HANDLE,
        LockSemaphore: HANDLE,
        SpinCount: ULONG_PTR
    }

    extern "system" {
        pub fn InitializeCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
        pub fn EnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
        pub fn TryEnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION) -> BOOLEAN;
        pub fn LeaveCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
        pub fn DeleteCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
    }
}
<commit_msg>! fix remutx windows API calls<commit_after>// Copyright 2015 The Rust Project Developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::mem;
use std::cell::UnsafeCell;

pub struct ReentrantMutex { inner: UnsafeCell<ffi::CRITICAL_SECTION> }

unsafe impl Send for ReentrantMutex {}
unsafe impl Sync for ReentrantMutex {}

impl ReentrantMutex {
    pub unsafe fn uninitialized() -> ReentrantMutex {
        mem::uninitialized()
    }

    //pub unsafe fn init(&mut self) -> ReentrantMutex {
    //    ffi::InitializeCriticalSection(self.inner.get());
    //}
    pub unsafe fn init(&mut self) {
        ffi::InitializeCriticalSection(self.inner.get());
    }

    pub unsafe fn lock(&self) {
        ffi::EnterCriticalSection(self.inner.get());
    }

    #[inline]
    pub unsafe fn try_lock(&self) -> bool {
        ffi::TryEnterCriticalSection(self.inner.get()) != 0
    }

    pub unsafe fn unlock(&self) {
        ffi::LeaveCriticalSection(self.inner.get());
    }

    pub unsafe fn destroy(&self) {
        ffi::DeleteCriticalSection(self.inner.get());
    }
}

mod ffi {
    use libc::{LPVOID, LONG, HANDLE, c_ulong, BOOLEAN};
    pub type ULONG_PTR = c_ulong;

    #[repr(C)]
    pub struct CRITICAL_SECTION {
        CriticalSectionDebug: LPVOID,
        LockCount: LONG,
        RecursionCount: LONG,
        OwningThread: HANDLE,
        LockSemaphore: HANDLE,
        SpinCount: ULONG_PTR
    }

    extern "system" {
        pub fn InitializeCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
        pub fn EnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
        pub fn TryEnterCriticalSection(CriticalSection: *mut CRITICAL_SECTION) -> BOOLEAN;
        pub fn LeaveCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
        pub fn DeleteCriticalSection(CriticalSection: *mut CRITICAL_SECTION);
    }
}
<|endoftext|>


<commit_before>use parser::ast::{Expression, BinaryOperator, PrefixOperator, SuffixOperator};

// TODO: add test
// TODO: handle semantic errors e.g. 1 / 0
pub fn execute_expression(expression: Expression) -> f64 {
    match expression {
        Expression::Number(n) => n,
        Expression::BinaryOperation(left, op, right) => {
            let left = execute_expression(*left);
            let right = execute_expression(*right);

            match op {
                BinaryOperator::Plus => left + right,
                BinaryOperator::Minus => left - right,
                BinaryOperator::Multiplication => left * right,
                BinaryOperator::Divide => left / right,
                BinaryOperator::Power => left.powf(right),
            }
        }
        Expression::UnaryPrefixOperation(op, right) => {
            let right = execute_expression(*right);

            match op {
                PrefixOperator::PlusSign => right,
                PrefixOperator::MinusSign => -right,
            }
        }
        Expression::UnarySuffixOperation(left, op) => {
            let left = execute_expression(*left);

            match op {
                SuffixOperator::Factorial => factorial(left as u64) as f64,
            }
        }
    }
}

fn factorial(value: u64) -> u64 {
    let mut curr = 1;
    for i in 1..(value + 1) {
        curr *= i;
    }
    curr
}

#[test]
fn test_factorial() {
    assert_eq!(factorial(0u64), 1u64);
    assert_eq!(factorial(1u64), 1u64);
    assert_eq!(factorial(2u64), 2u64);
    assert_eq!(factorial(3u64), 6u64);
    assert_eq!(factorial(4u64), 24u64);
    assert_eq!(factorial(5u64), 120u64);
}
<commit_msg>Disjoint factorial tests<commit_after>use parser::ast::{Expression, BinaryOperator, PrefixOperator, SuffixOperator};

// TODO: add test
// TODO: handle semantic errors e.g. 1 / 0
pub fn execute_expression(expression: Expression) -> f64 {
    match expression {
        Expression::Number(n) => n,
        Expression::BinaryOperation(left, op, right) => {
            let left = execute_expression(*left);
            let right = execute_expression(*right);

            match op {
                BinaryOperator::Plus => left + right,
                BinaryOperator::Minus => left - right,
                BinaryOperator::Multiplication => left * right,
                BinaryOperator::Divide => left / right,
                BinaryOperator::Power => left.powf(right),
            }
        }
        Expression::UnaryPrefixOperation(op, right) => {
            let right = execute_expression(*right);

            match op {
                PrefixOperator::PlusSign => right,
                PrefixOperator::MinusSign => -right,
            }
        }
        Expression::UnarySuffixOperation(left, op) => {
            let left = execute_expression(*left);

            match op {
                SuffixOperator::Factorial => factorial(left as u64) as f64,
            }
        }
    }
}

fn factorial(value: u64) -> u64 {
    let mut curr = 1;
    for i in 1..(value + 1) {
        curr *= i;
    }
    curr
}

#[test]
fn test_factorial_of_0() {
    assert_eq!(factorial(0u64), 1u64);
}

#[test]
fn test_factorial_of_1() {
    assert_eq!(factorial(1u64), 1u64);
}

#[test]
fn test_factorial_of_2() {
    assert_eq!(factorial(2u64), 2u64);
}

#[test]
fn test_factorial_of_3() {
    assert_eq!(factorial(3u64), 6u64);
}

#[test]
fn test_factorial_of_4() {
    assert_eq!(factorial(4u64), 24u64);
}

#[test]
fn test_factorial_of_5() {
    assert_eq!(factorial(5u64), 120u64);
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use std::io::{Error, ErrorKind};
use toml;

#[derive(Clone)]
pub struct Config {
    config: toml::Value
}

impl Config {
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Config, Error>{
        let mut fd = try!(File::open(path));
        let mut toml = String::new();
        try!(fd.read_to_string(&mut toml));
        let config = match toml.parse() {
            Ok(config) => config,
            Err(_) => return Err(Error::new(ErrorKind::InvalidData, "Syntax error"))
        };
        println!("{:#?}", config);
        Ok(Config {
            config: config
        })
    }

    pub fn lookup<'a>(&'a self, path: &'a str) -> Option<&'a toml::Value> {
        self.config.lookup(path)
    }
}
<commit_msg>Don't print the config any more<commit_after>use std::io::prelude::*;
use std::fs::File;
use std::path::Path;
use std::io::{Error, ErrorKind};
use toml;

#[derive(Clone)]
pub struct Config {
    config: toml::Value
}

impl Config {
    pub fn from_path<P: AsRef<Path>>(path: P) -> Result<Config, Error>{
        let mut fd = try!(File::open(path));
        let mut toml = String::new();
        try!(fd.read_to_string(&mut toml));
        let config = match toml.parse() {
            Ok(config) => config,
            Err(_) => return Err(Error::new(ErrorKind::InvalidData, "Syntax error"))
        };
        Ok(Config {
            config: config
        })
    }

    pub fn lookup<'a>(&'a self, path: &'a str) -> Option<&'a toml::Value> {
        self.config.lookup(path)
    }
}
<|endoftext|>