<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 std::num::Zero;
use std::io;
use std::fmt;
use std::error::Error;

use serde;
use serde_json;
use nix;
use term;

pub type FroyoResult<T> = Result<T, FroyoError>;

//
// Use distinct 'newtype' types for sectors and sector offsets for type safety.
// When needed, these can still be derefed to u64.
// Derive a bunch of stuff so we can do ops on them.
//
custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct Sectors(u64);
}

impl Sectors {
    pub const fn new(val: u64) -> Sectors {
        Sectors(val)
    }
}

impl Zero for Sectors {
    fn zero() -> Self {
        Sectors(0)
    }
}

impl serde::Serialize for Sectors {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.serialize_u64(**self)
    }
}

impl serde::Deserialize for Sectors {
    fn deserialize<D>(deserializer: &mut D) -> Result<Sectors, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(Sectors(val))
    }
}

custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct SectorOffset(u64);
}

impl SectorOffset {
    pub const fn new(val: u64) -> SectorOffset {
        SectorOffset(val)
    }
}

impl Zero for SectorOffset {
    fn zero() -> Self {
        SectorOffset(0)
    }
}

impl serde::Serialize for SectorOffset {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.serialize_u64(**self)
    }
}

impl serde::Deserialize for SectorOffset {
    fn deserialize<D>(deserializer: &mut D) -> Result<SectorOffset, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(SectorOffset(val))
    }
}

// A type for Data Blocks as used by the thin pool.
custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct DataBlocks(u64);
}

impl DataBlocks {
    pub const fn new(val: u64) -> DataBlocks {
        DataBlocks(val)
    }
}

impl Zero for DataBlocks {
    fn zero() -> Self {
        DataBlocks(0)
    }
}

impl serde::Serialize for DataBlocks {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.serialize_u64(**self)
    }
}

impl serde::Deserialize for DataBlocks {
    fn deserialize<D>(deserializer: &mut D) -> Result<DataBlocks, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(DataBlocks(val))
    }
}

//
// An error type for errors generated within Froyo
//
#[derive(Debug, Clone)]
pub struct InternalError(pub String);

impl fmt::Display for InternalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}", self.0)
    }
}

impl Error for InternalError {
    fn description(&self) -> &str {
        &self.0
    }
}

// Define a common error enum.
// See http://blog.burntsushi.net/rust-error-handling/
#[derive(Debug)]
pub enum FroyoError {
    Froyo(InternalError),
    Io(io::Error),
    Serde(serde_json::error::Error),
    Nix(nix::Error),
    Dbus(()),
    Term(term::Error),
}

impl fmt::Display for FroyoError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            FroyoError::Froyo(ref err) => write!(f, "Froyo error: {}", err.0),
            FroyoError::Io(ref err) => write!(f, "IO error: {}", err),
            FroyoError::Serde(ref err) => write!(f, "Serde error: {}", err),
            FroyoError::Nix(ref err) => write!(f, "Nix error: {}", err.errno().desc()),
            FroyoError::Dbus(()) => write!(f, "Dbus error"),
            FroyoError::Term(ref err) => write!(f, "Term error: {}", err),
        }
    }
}

impl Error for FroyoError {
    fn description(&self) -> &str {
        match *self {
            FroyoError::Froyo(ref err) => &err.0,
            FroyoError::Io(ref err) => err.description(),
            FroyoError::Serde(ref err) => Error::description(err),
            FroyoError::Nix(ref err) => err.errno().desc(),
            FroyoError::Dbus(()) => "Dbus error",
            FroyoError::Term(ref err) => Error::description(err),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            FroyoError::Froyo(ref err) => Some(err),
            FroyoError::Io(ref err) => Some(err),
            FroyoError::Serde(ref err) => Some(err),
            FroyoError::Nix(ref err) => Some(err),
            FroyoError::Dbus(()) => None,
            FroyoError::Term(ref err) => Some(err),
        }
    }
}

impl From<InternalError> for FroyoError {
    fn from(err: InternalError) -> FroyoError {
        FroyoError::Froyo(err)
    }
}

impl From<io::Error> for FroyoError {
    fn from(err: io::Error) -> FroyoError {
        FroyoError::Io(err)
    }
}

impl From<serde_json::error::Error> for FroyoError {
    fn from(err: serde_json::error::Error) -> FroyoError {
        FroyoError::Serde(err)
    }
}

impl From<nix::Error> for FroyoError {
    fn from(err: nix::Error) -> FroyoError {
        FroyoError::Nix(err)
    }
}

impl From<()> for FroyoError {
    fn from(err: ()) -> FroyoError {
        FroyoError::Dbus(err)
    }
}

impl From<term::Error> for FroyoError {
    fn from(err: term::Error) -> FroyoError {
        FroyoError::Term(err)
    }
}
<commit_msg>types: Use dbus::Error instead of ()<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 std::num::Zero;
use std::io;
use std::fmt;
use std::error::Error;

use serde;
use serde_json;
use nix;
use term;
use dbus;

pub type FroyoResult<T> = Result<T, FroyoError>;

//
// Use distinct 'newtype' types for sectors and sector offsets for type safety.
// When needed, these can still be derefed to u64.
// Derive a bunch of stuff so we can do ops on them.
//
custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct Sectors(u64);
}

impl Sectors {
    pub const fn new(val: u64) -> Sectors {
        Sectors(val)
    }
}

impl Zero for Sectors {
    fn zero() -> Self {
        Sectors(0)
    }
}

impl serde::Serialize for Sectors {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.serialize_u64(**self)
    }
}

impl serde::Deserialize for Sectors {
    fn deserialize<D>(deserializer: &mut D) -> Result<Sectors, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(Sectors(val))
    }
}

custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct SectorOffset(u64);
}

impl SectorOffset {
    pub const fn new(val: u64) -> SectorOffset {
        SectorOffset(val)
    }
}

impl Zero for SectorOffset {
    fn zero() -> Self {
        SectorOffset(0)
    }
}

impl serde::Serialize for SectorOffset {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.serialize_u64(**self)
    }
}

impl serde::Deserialize for SectorOffset {
    fn deserialize<D>(deserializer: &mut D) -> Result<SectorOffset, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(SectorOffset(val))
    }
}

// A type for Data Blocks as used by the thin pool.
custom_derive! {
    #[derive(NewtypeFrom, NewtypeAdd, NewtypeSub, NewtypeDeref,
             NewtypeBitAnd, NewtypeNot, NewtypeDiv, NewtypeRem,
             NewtypeMul,
             Debug, Clone, Copy, Eq, PartialEq, PartialOrd, Ord)]
    pub struct DataBlocks(u64);
}

impl DataBlocks {
    pub const fn new(val: u64) -> DataBlocks {
        DataBlocks(val)
    }
}

impl Zero for DataBlocks {
    fn zero() -> Self {
        DataBlocks(0)
    }
}

impl serde::Serialize for DataBlocks {
    fn serialize<S>(&self, serializer: &mut S) -> Result<(), S::Error>
        where S: serde::Serializer,
    {
        serializer.serialize_u64(**self)
    }
}

impl serde::Deserialize for DataBlocks {
    fn deserialize<D>(deserializer: &mut D) -> Result<DataBlocks, D::Error>
        where D: serde::de::Deserializer
    {
        let val = try!(serde::Deserialize::deserialize(deserializer));
        Ok(DataBlocks(val))
    }
}

//
// An error type for errors generated within Froyo
//
#[derive(Debug, Clone)]
pub struct InternalError(pub String);

impl fmt::Display for InternalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        write!(f, "{}", self.0)
    }
}

impl Error for InternalError {
    fn description(&self) -> &str {
        &self.0
    }
}

// Define a common error enum.
// See http://blog.burntsushi.net/rust-error-handling/
#[derive(Debug)]
pub enum FroyoError {
    Froyo(InternalError),
    Io(io::Error),
    Serde(serde_json::error::Error),
    Nix(nix::Error),
    Dbus(dbus::Error),
    Term(term::Error),
}

impl fmt::Display for FroyoError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            FroyoError::Froyo(ref err) => write!(f, "Froyo error: {}", err.0),
            FroyoError::Io(ref err) => write!(f, "IO error: {}", err),
            FroyoError::Serde(ref err) => write!(f, "Serde error: {}", err),
            FroyoError::Nix(ref err) => write!(f, "Nix error: {}", err.errno().desc()),
            FroyoError::Dbus(ref err) => write!(f, "Dbus error: {}", err),
            FroyoError::Term(ref err) => write!(f, "Term error: {}", err),
        }
    }
}

impl Error for FroyoError {
    fn description(&self) -> &str {
        match *self {
            FroyoError::Froyo(ref err) => &err.0,
            FroyoError::Io(ref err) => err.description(),
            FroyoError::Serde(ref err) => Error::description(err),
            FroyoError::Nix(ref err) => err.errno().desc(),
            FroyoError::Dbus(ref err) => err.description(),
            FroyoError::Term(ref err) => Error::description(err),
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            FroyoError::Froyo(ref err) => Some(err),
            FroyoError::Io(ref err) => Some(err),
            FroyoError::Serde(ref err) => Some(err),
            FroyoError::Nix(ref err) => Some(err),
            FroyoError::Dbus(ref err) => Some(err),
            FroyoError::Term(ref err) => Some(err),
        }
    }
}

impl From<InternalError> for FroyoError {
    fn from(err: InternalError) -> FroyoError {
        FroyoError::Froyo(err)
    }
}

impl From<io::Error> for FroyoError {
    fn from(err: io::Error) -> FroyoError {
        FroyoError::Io(err)
    }
}

impl From<serde_json::error::Error> for FroyoError {
    fn from(err: serde_json::error::Error) -> FroyoError {
        FroyoError::Serde(err)
    }
}

impl From<nix::Error> for FroyoError {
    fn from(err: nix::Error) -> FroyoError {
        FroyoError::Nix(err)
    }
}

impl From<dbus::Error> for FroyoError {
    fn from(err: dbus::Error) -> FroyoError {
        FroyoError::Dbus(err)
    }
}

impl From<term::Error> for FroyoError {
    fn from(err: term::Error) -> FroyoError {
        FroyoError::Term(err)
    }
}
<|endoftext|>


<commit_before>use super::*;

pub fn escape_single_quote<S: AsRef<str>>(s: S) -> String {
    s.as_ref().replace("'", "''")
}

#[test]
fn test_escape_single_quote() {
    assert_eq!(escape_single_quote("my' precious"), "my'' precious");
}

pub fn get_rootPath<'a>(
    path: &'a Path,
    languageId: &str,
    rootMarkers: &Option<RootMarkers>,
) -> Fallible<&'a Path> {
    if let Some(ref rootMarkers) = *rootMarkers {
        let empty = vec![];
        let rootMarkers = match *rootMarkers {
            RootMarkers::Array(ref arr) => arr,
            RootMarkers::Map(ref map) => map.get(languageId).unwrap_or(&empty),
        };

        for marker in rootMarkers {
            let ret = traverse_up(path, |dir| {
                let p = dir.join(marker);
                let p = p.to_str();
                if p.is_none() {
                    return false;
                }
                let p = p.unwrap_or_default();
                match glob::glob(p) {
                    Ok(paths) => paths.count() > 0,
                    _ => false,
                }
            });

            if ret.is_ok() {
                return ret;
            }
        }
    }

    match languageId {
        "rust" => traverse_up(path, |dir| dir.join("Cargo.toml").exists()),
        "php" => traverse_up(path, |dir| dir.join("composer.json").exists()),
        "javascript" | "typescript" | "javascript.jsx" | "typescript.tsx" => {
            traverse_up(path, |dir| dir.join("package.json").exists())
        }
        "python" => traverse_up(path, |dir| {
            dir.join("setup.py").exists()
                || dir.join("Pipfile").exists()
                || dir.join("requirements.txt").exists()
        }),
        "c" | "cpp" => traverse_up(path, |dir| dir.join("compile_commands.json").exists()),
        "cs" => traverse_up(path, is_dotnet_root),
        "java" => traverse_up(path, |dir| {
            dir.join(".project").exists()
                || dir.join("pom.xml").exists()
                || dir.join("build.gradle").exists()
        }),
        "scala" => traverse_up(path, |dir| dir.join("build.sbt").exists()),
        "haskell" => traverse_up(path, |dir| dir.join("stack.yaml").exists())
            .or_else(|_| traverse_up(path, |dir| dir.join(".cabal").exists())),
        _ => Err(format_err!("Unknown languageId: {}", languageId)),
    }
    .or_else(|_| {
        traverse_up(path, |dir| {
            dir.join(".git").exists() || dir.join(".hg").exists() || dir.join(".svn").exists()
        })
    })
    .or_else(|_| {
        let parent = path
            .parent()
            .ok_or_else(|| format_err!("Failed to get parent dir! path: {:?}", path));
        warn!(
            "Unknown project type. Fallback to use dir as project root: {:?}",
            parent
        );
        parent
    })
}

fn traverse_up<F>(path: &Path, predicate: F) -> Fallible<&Path>
where
    F: Fn(&Path) -> bool,
{
    if predicate(path) {
        return Ok(path);
    }

    let next_path = path.parent().ok_or_else(|| err_msg("Hit root"))?;

    traverse_up(next_path, predicate)
}

fn is_dotnet_root(dir: &Path) -> bool {
    if dir.join("project.json").exists() {
        return true;
    }
    if !dir.is_dir() {
        return false;
    }

    let entries = match dir.read_dir() {
        Ok(entries) => entries,
        Err(_) => return false,
    };
    for entry in entries {
        if let Ok(entry) = entry {
            if entry.path().ends_with(".csproj") {
                return true;
            }
        }
    }

    false
}

pub trait ToUrl {
    fn to_url(&self) -> Fallible<Url>;
}

impl<P: AsRef<Path> + std::fmt::Debug> ToUrl for P {
    fn to_url(&self) -> Fallible<Url> {
        Url::from_file_path(self)
            .or_else(|_| Url::from_str(&self.as_ref().to_string_lossy()))
            .or_else(|_| Err(format_err!("Failed to convert ({:?}) to Url", self)))
    }
}

pub fn apply_TextEdits(lines: &[String], edits: &[TextEdit]) -> Fallible<Vec<String>> {
    // Edits are ordered from bottom to top, from right to left.
    let mut edits_by_index = vec![];
    for edit in edits {
        let start_line = edit.range.start.line.to_usize()?;
        let start_character: usize = edit.range.start.character.to_usize()?;
        let end_line: usize = edit.range.end.line.to_usize()?;
        let end_character: usize = edit.range.end.character.to_usize()?;

        let start = lines[..std::cmp::min(start_line, lines.len())]
            .iter()
            .map(String::len)
            .fold(0, |acc, l| acc + l + 1 /*line ending*/)
            + start_character;
        let end = lines[..std::cmp::min(end_line, lines.len())]
            .iter()
            .map(String::len)
            .fold(0, |acc, l| acc + l + 1 /*line ending*/)
            + end_character;
        edits_by_index.push((start, end, &edit.new_text));
    }

    let mut text = lines.join("\n");
    for (start, end, new_text) in edits_by_index {
        let start = std::cmp::min(start, text.len());
        let end = std::cmp::min(end, text.len());
        text = String::new() + &text[..start] + new_text + &text[end..];
    }

    Ok(text.lines().map(ToOwned::to_owned).collect())
}

#[test]
fn test_apply_TextEdit() {
    let lines: Vec<String> = r#"fn main() {
0;
}
"#
    .lines()
    .map(|l| l.to_owned())
    .collect();

    let expect: Vec<String> = r#"fn main() {
    0;
}
"#
    .lines()
    .map(|l| l.to_owned())
    .collect();

    let edit = TextEdit {
        range: Range {
            start: Position {
                line: 0,
                character: 0,
            },
            end: Position {
                line: 3,
                character: 0,
            },
        },
        new_text: r#"fn main() {
    0;
}
"#
        .to_owned(),
    };

    assert_eq!(apply_TextEdits(&lines, &[edit]).unwrap(), expect);
}

#[test]
fn test_apply_TextEdit_overlong_end() {
    let lines: Vec<String> = r#"abc = 123"#.lines().map(|l| l.to_owned()).collect();

    let expect: Vec<String> = r#"nb = 123"#.lines().map(|l| l.to_owned()).collect();

    let edit = TextEdit {
        range: Range {
            start: Position {
                line: 0,
                character: 0,
            },
            end: Position {
                line: 99999999,
                character: 0,
            },
        },
        new_text: r#"nb = 123"#.to_owned(),
    };

    assert_eq!(apply_TextEdits(&lines, &[edit]).unwrap(), expect);
}

pub trait Combine {
    /// Recursively combine two objects.
    fn combine(&self, other: &Self) -> Self
    where
        Self: Sized + Clone;
}

impl Combine for Value {
    fn combine(&self, other: &Self) -> Self {
        match (self, other) {
            (this, Value::Null) => this.clone(),
            (Value::Object(this), Value::Object(other)) => {
                let mut map = serde_json::Map::new();
                let mut keys: HashSet<String> = HashSet::new();
                for k in this.keys() {
                    keys.insert(k.clone());
                }
                for k in other.keys() {
                    keys.insert(k.clone());
                }
                for k in keys.drain() {
                    let v1 = this.get(&k).unwrap_or(&Value::Null);
                    let v2 = other.get(&k).unwrap_or(&Value::Null);
                    map.insert(k, v1.combine(v2));
                }
                Value::Object(map)
            }
            (_, other) => other.clone(),
        }
    }
}

/// Expand condensed json path as in VSCode.
///
/// e.g.,
/// ```json
/// {
///   "rust.rls": true
/// }
/// ```
/// will be expanded to
/// ```json
/// {
///   "rust": {
///     "rls": true
///   }
/// }
/// ```
pub fn expand_json_path(value: Value) -> Value {
    match value {
        Value::Object(map) => {
            let mut value_expanded = json!({});
            for (k, v) in map {
                let mut v = v;
                for token in k.rsplit('.') {
                    v = json!({ token: v });
                }
                value_expanded = value_expanded.combine(&v);
            }
            value_expanded
        }
        _ => value,
    }
}

#[test]
fn test_expand_json_path() {
    assert_eq!(
        expand_json_path(json!({
            "k": "v"
        })),
        json!({
            "k": "v"
        })
    );
    assert_eq!(
        expand_json_path(json!({
            "rust.rls": true
        })),
        json!({
            "rust": {
                "rls": true
            }
        })
    );
}

pub fn vim_cmd_args_to_value(args: &[String]) -> Fallible<Value> {
    let mut map = serde_json::map::Map::new();
    for arg in args {
        let mut tokens: Vec<_> = arg.splitn(2, '=').collect();
        tokens.reverse();
        let key = tokens.pop().ok_or_else(|| {
            format_err!("Failed to parse command arguments! tokens: {:?}", tokens)
        })?;
        let value = tokens.pop().ok_or_else(|| {
            format_err!("Failed to parse command arguments! tokens: {:?}", tokens)
        })?;
        let value = Value::String(value.to_owned());
        map.insert(key.to_owned(), value);
    }

    Ok(Value::Object(map))
}

#[test]
fn test_vim_cmd_args_to_value() {
    let cmdargs = ["rootPath=/tmp".to_owned()];
    assert_eq!(
        vim_cmd_args_to_value(&cmdargs).unwrap(),
        json!({
            "rootPath": "/tmp"
        })
    );
}

pub fn diff_value<'a>(v1: &'a Value, v2: &'a Value, path: &str) -> HashMap<String, (Value, Value)> {
    let mut diffs = HashMap::new();
    match (v1, v2) {
        (&Value::Null, &Value::Null)
        | (&Value::Bool(_), &Value::Bool(_))
        | (&Value::Number(_), &Value::Number(_))
        | (&Value::String(_), &Value::String(_))
        | (&Value::Array(_), &Value::Array(_)) => {
            if v1 != v2 {
                diffs.insert(path.to_owned(), (v1.clone(), v2.clone()));
            }
        }
        (&Value::Object(ref map1), &Value::Object(ref map2)) => {
            let keys1: HashSet<&String> = map1.keys().collect();
            let keys2: HashSet<&String> = map2.keys().collect();
            for k in keys1.union(&keys2) {
                let mut next_path = String::from(path);
                next_path += ".";
                next_path += k;
                let next_diffs = diff_value(
                    map1.get(*k).unwrap_or(&Value::Null),
                    map2.get(*k).unwrap_or(&Value::Null),
                    &next_path,
                );
                diffs.extend(next_diffs);
            }
        }
        _ => {
            diffs.insert(path.to_owned(), (v1.clone(), v2.clone()));
        }
    }

    diffs
}

#[test]
fn test_diff_value() {
    assert_eq!(diff_value(&json!({}), &json!({}), "state",), hashmap!());
    assert_eq!(
        diff_value(
            &json!({
                "line": 1,
            }),
            &json!({
                "line": 3,
            }),
            "state"
        ),
        hashmap! {
            "state.line".to_owned() => (json!(1), json!(3)),
        }
    );
}

pub trait Canonicalize {
    fn canonicalize(&self) -> String;
}

impl<P> Canonicalize for P
where
    P: AsRef<Path>,
{
    fn canonicalize(&self) -> String {
        let path = match std::fs::canonicalize(self) {
            Ok(path) => path.to_string_lossy().into_owned(),
            _ => self.as_ref().to_string_lossy().into_owned(),
        };

        // Trim UNC prefixes.
        // See https://github.com/rust-lang/rust/issues/42869
        path.trim_start_matches("\\\\?\\").into()
    }
}

pub fn get_default_initializationOptions(languageId: &str) -> Value {
    match languageId {
        "java" => json!({
            "extendedClientCapabilities": {
                "classFileContentsSupport": true
            }
        }),
        _ => json!(Value::Null),
    }
}

/// Given a parameter label and its containing signature, return the part before the label, the
/// label itself, and the part after the label.
pub fn decode_parameterLabel(
    parameter_label: &lsp::ParameterLabel,
    signature: &str,
) -> Fallible<(String, String, String)> {
    match *parameter_label {
        lsp::ParameterLabel::Simple(ref label) => {
            let chunks: Vec<&str> = signature.split(label).collect();
            if chunks.len() != 2 {
                return Err(err_msg("Parameter is not part of signature"));
            }
            let begin = chunks[0].to_string();
            let label = label.to_string();
            let end = chunks[1].to_string();
            Ok((begin, label, end))
        }
        lsp::ParameterLabel::LabelOffsets([start, finish]) => {
            // Offsets are based on a UTF-16 string representation, inclusive start,
            // exclusive finish.
            let start = start.to_usize()?;
            let finish = finish.to_usize()?;
            let utf16: Vec<u16> = signature.encode_utf16().collect();
            let begin = utf16
                .get(..start)
                .ok_or_else(|| err_msg("Offset out of range"))?;
            let begin = String::from_utf16(begin)?;
            let label = utf16
                .get(start..finish)
                .ok_or_else(|| err_msg("Offset out of range"))?;
            let label = String::from_utf16(label)?;
            let end = utf16
                .get(finish..)
                .ok_or_else(|| err_msg("Offset out of range"))?;
            let end = String::from_utf16(end)?;
            Ok((begin, label, end))
        }
    }
}
<commit_msg>add new root marker for python projects: pyproject.toml<commit_after>use super::*;

pub fn escape_single_quote<S: AsRef<str>>(s: S) -> String {
    s.as_ref().replace("'", "''")
}

#[test]
fn test_escape_single_quote() {
    assert_eq!(escape_single_quote("my' precious"), "my'' precious");
}

pub fn get_rootPath<'a>(
    path: &'a Path,
    languageId: &str,
    rootMarkers: &Option<RootMarkers>,
) -> Fallible<&'a Path> {
    if let Some(ref rootMarkers) = *rootMarkers {
        let empty = vec![];
        let rootMarkers = match *rootMarkers {
            RootMarkers::Array(ref arr) => arr,
            RootMarkers::Map(ref map) => map.get(languageId).unwrap_or(&empty),
        };

        for marker in rootMarkers {
            let ret = traverse_up(path, |dir| {
                let p = dir.join(marker);
                let p = p.to_str();
                if p.is_none() {
                    return false;
                }
                let p = p.unwrap_or_default();
                match glob::glob(p) {
                    Ok(paths) => paths.count() > 0,
                    _ => false,
                }
            });

            if ret.is_ok() {
                return ret;
            }
        }
    }

    match languageId {
        "rust" => traverse_up(path, |dir| dir.join("Cargo.toml").exists()),
        "php" => traverse_up(path, |dir| dir.join("composer.json").exists()),
        "javascript" | "typescript" | "javascript.jsx" | "typescript.tsx" => {
            traverse_up(path, |dir| dir.join("package.json").exists())
        }
        "python" => traverse_up(path, |dir| {
            dir.join("setup.py").exists()
                || dir.join("Pipfile").exists()
                || dir.join("requirements.txt").exists()
                || dir.join("pyproject.toml").exists()
        }),
        "c" | "cpp" => traverse_up(path, |dir| dir.join("compile_commands.json").exists()),
        "cs" => traverse_up(path, is_dotnet_root),
        "java" => traverse_up(path, |dir| {
            dir.join(".project").exists()
                || dir.join("pom.xml").exists()
                || dir.join("build.gradle").exists()
        }),
        "scala" => traverse_up(path, |dir| dir.join("build.sbt").exists()),
        "haskell" => traverse_up(path, |dir| dir.join("stack.yaml").exists())
            .or_else(|_| traverse_up(path, |dir| dir.join(".cabal").exists())),
        _ => Err(format_err!("Unknown languageId: {}", languageId)),
    }
    .or_else(|_| {
        traverse_up(path, |dir| {
            dir.join(".git").exists() || dir.join(".hg").exists() || dir.join(".svn").exists()
        })
    })
    .or_else(|_| {
        let parent = path
            .parent()
            .ok_or_else(|| format_err!("Failed to get parent dir! path: {:?}", path));
        warn!(
            "Unknown project type. Fallback to use dir as project root: {:?}",
            parent
        );
        parent
    })
}

fn traverse_up<F>(path: &Path, predicate: F) -> Fallible<&Path>
where
    F: Fn(&Path) -> bool,
{
    if predicate(path) {
        return Ok(path);
    }

    let next_path = path.parent().ok_or_else(|| err_msg("Hit root"))?;

    traverse_up(next_path, predicate)
}

fn is_dotnet_root(dir: &Path) -> bool {
    if dir.join("project.json").exists() {
        return true;
    }
    if !dir.is_dir() {
        return false;
    }

    let entries = match dir.read_dir() {
        Ok(entries) => entries,
        Err(_) => return false,
    };
    for entry in entries {
        if let Ok(entry) = entry {
            if entry.path().ends_with(".csproj") {
                return true;
            }
        }
    }

    false
}

pub trait ToUrl {
    fn to_url(&self) -> Fallible<Url>;
}

impl<P: AsRef<Path> + std::fmt::Debug> ToUrl for P {
    fn to_url(&self) -> Fallible<Url> {
        Url::from_file_path(self)
            .or_else(|_| Url::from_str(&self.as_ref().to_string_lossy()))
            .or_else(|_| Err(format_err!("Failed to convert ({:?}) to Url", self)))
    }
}

pub fn apply_TextEdits(lines: &[String], edits: &[TextEdit]) -> Fallible<Vec<String>> {
    // Edits are ordered from bottom to top, from right to left.
    let mut edits_by_index = vec![];
    for edit in edits {
        let start_line = edit.range.start.line.to_usize()?;
        let start_character: usize = edit.range.start.character.to_usize()?;
        let end_line: usize = edit.range.end.line.to_usize()?;
        let end_character: usize = edit.range.end.character.to_usize()?;

        let start = lines[..std::cmp::min(start_line, lines.len())]
            .iter()
            .map(String::len)
            .fold(0, |acc, l| acc + l + 1 /*line ending*/)
            + start_character;
        let end = lines[..std::cmp::min(end_line, lines.len())]
            .iter()
            .map(String::len)
            .fold(0, |acc, l| acc + l + 1 /*line ending*/)
            + end_character;
        edits_by_index.push((start, end, &edit.new_text));
    }

    let mut text = lines.join("\n");
    for (start, end, new_text) in edits_by_index {
        let start = std::cmp::min(start, text.len());
        let end = std::cmp::min(end, text.len());
        text = String::new() + &text[..start] + new_text + &text[end..];
    }

    Ok(text.lines().map(ToOwned::to_owned).collect())
}

#[test]
fn test_apply_TextEdit() {
    let lines: Vec<String> = r#"fn main() {
0;
}
"#
    .lines()
    .map(|l| l.to_owned())
    .collect();

    let expect: Vec<String> = r#"fn main() {
    0;
}
"#
    .lines()
    .map(|l| l.to_owned())
    .collect();

    let edit = TextEdit {
        range: Range {
            start: Position {
                line: 0,
                character: 0,
            },
            end: Position {
                line: 3,
                character: 0,
            },
        },
        new_text: r#"fn main() {
    0;
}
"#
        .to_owned(),
    };

    assert_eq!(apply_TextEdits(&lines, &[edit]).unwrap(), expect);
}

#[test]
fn test_apply_TextEdit_overlong_end() {
    let lines: Vec<String> = r#"abc = 123"#.lines().map(|l| l.to_owned()).collect();

    let expect: Vec<String> = r#"nb = 123"#.lines().map(|l| l.to_owned()).collect();

    let edit = TextEdit {
        range: Range {
            start: Position {
                line: 0,
                character: 0,
            },
            end: Position {
                line: 99999999,
                character: 0,
            },
        },
        new_text: r#"nb = 123"#.to_owned(),
    };

    assert_eq!(apply_TextEdits(&lines, &[edit]).unwrap(), expect);
}

pub trait Combine {
    /// Recursively combine two objects.
    fn combine(&self, other: &Self) -> Self
    where
        Self: Sized + Clone;
}

impl Combine for Value {
    fn combine(&self, other: &Self) -> Self {
        match (self, other) {
            (this, Value::Null) => this.clone(),
            (Value::Object(this), Value::Object(other)) => {
                let mut map = serde_json::Map::new();
                let mut keys: HashSet<String> = HashSet::new();
                for k in this.keys() {
                    keys.insert(k.clone());
                }
                for k in other.keys() {
                    keys.insert(k.clone());
                }
                for k in keys.drain() {
                    let v1 = this.get(&k).unwrap_or(&Value::Null);
                    let v2 = other.get(&k).unwrap_or(&Value::Null);
                    map.insert(k, v1.combine(v2));
                }
                Value::Object(map)
            }
            (_, other) => other.clone(),
        }
    }
}

/// Expand condensed json path as in VSCode.
///
/// e.g.,
/// ```json
/// {
///   "rust.rls": true
/// }
/// ```
/// will be expanded to
/// ```json
/// {
///   "rust": {
///     "rls": true
///   }
/// }
/// ```
pub fn expand_json_path(value: Value) -> Value {
    match value {
        Value::Object(map) => {
            let mut value_expanded = json!({});
            for (k, v) in map {
                let mut v = v;
                for token in k.rsplit('.') {
                    v = json!({ token: v });
                }
                value_expanded = value_expanded.combine(&v);
            }
            value_expanded
        }
        _ => value,
    }
}

#[test]
fn test_expand_json_path() {
    assert_eq!(
        expand_json_path(json!({
            "k": "v"
        })),
        json!({
            "k": "v"
        })
    );
    assert_eq!(
        expand_json_path(json!({
            "rust.rls": true
        })),
        json!({
            "rust": {
                "rls": true
            }
        })
    );
}

pub fn vim_cmd_args_to_value(args: &[String]) -> Fallible<Value> {
    let mut map = serde_json::map::Map::new();
    for arg in args {
        let mut tokens: Vec<_> = arg.splitn(2, '=').collect();
        tokens.reverse();
        let key = tokens.pop().ok_or_else(|| {
            format_err!("Failed to parse command arguments! tokens: {:?}", tokens)
        })?;
        let value = tokens.pop().ok_or_else(|| {
            format_err!("Failed to parse command arguments! tokens: {:?}", tokens)
        })?;
        let value = Value::String(value.to_owned());
        map.insert(key.to_owned(), value);
    }

    Ok(Value::Object(map))
}

#[test]
fn test_vim_cmd_args_to_value() {
    let cmdargs = ["rootPath=/tmp".to_owned()];
    assert_eq!(
        vim_cmd_args_to_value(&cmdargs).unwrap(),
        json!({
            "rootPath": "/tmp"
        })
    );
}

pub fn diff_value<'a>(v1: &'a Value, v2: &'a Value, path: &str) -> HashMap<String, (Value, Value)> {
    let mut diffs = HashMap::new();
    match (v1, v2) {
        (&Value::Null, &Value::Null)
        | (&Value::Bool(_), &Value::Bool(_))
        | (&Value::Number(_), &Value::Number(_))
        | (&Value::String(_), &Value::String(_))
        | (&Value::Array(_), &Value::Array(_)) => {
            if v1 != v2 {
                diffs.insert(path.to_owned(), (v1.clone(), v2.clone()));
            }
        }
        (&Value::Object(ref map1), &Value::Object(ref map2)) => {
            let keys1: HashSet<&String> = map1.keys().collect();
            let keys2: HashSet<&String> = map2.keys().collect();
            for k in keys1.union(&keys2) {
                let mut next_path = String::from(path);
                next_path += ".";
                next_path += k;
                let next_diffs = diff_value(
                    map1.get(*k).unwrap_or(&Value::Null),
                    map2.get(*k).unwrap_or(&Value::Null),
                    &next_path,
                );
                diffs.extend(next_diffs);
            }
        }
        _ => {
            diffs.insert(path.to_owned(), (v1.clone(), v2.clone()));
        }
    }

    diffs
}

#[test]
fn test_diff_value() {
    assert_eq!(diff_value(&json!({}), &json!({}), "state",), hashmap!());
    assert_eq!(
        diff_value(
            &json!({
                "line": 1,
            }),
            &json!({
                "line": 3,
            }),
            "state"
        ),
        hashmap! {
            "state.line".to_owned() => (json!(1), json!(3)),
        }
    );
}

pub trait Canonicalize {
    fn canonicalize(&self) -> String;
}

impl<P> Canonicalize for P
where
    P: AsRef<Path>,
{
    fn canonicalize(&self) -> String {
        let path = match std::fs::canonicalize(self) {
            Ok(path) => path.to_string_lossy().into_owned(),
            _ => self.as_ref().to_string_lossy().into_owned(),
        };

        // Trim UNC prefixes.
        // See https://github.com/rust-lang/rust/issues/42869
        path.trim_start_matches("\\\\?\\").into()
    }
}

pub fn get_default_initializationOptions(languageId: &str) -> Value {
    match languageId {
        "java" => json!({
            "extendedClientCapabilities": {
                "classFileContentsSupport": true
            }
        }),
        _ => json!(Value::Null),
    }
}

/// Given a parameter label and its containing signature, return the part before the label, the
/// label itself, and the part after the label.
pub fn decode_parameterLabel(
    parameter_label: &lsp::ParameterLabel,
    signature: &str,
) -> Fallible<(String, String, String)> {
    match *parameter_label {
        lsp::ParameterLabel::Simple(ref label) => {
            let chunks: Vec<&str> = signature.split(label).collect();
            if chunks.len() != 2 {
                return Err(err_msg("Parameter is not part of signature"));
            }
            let begin = chunks[0].to_string();
            let label = label.to_string();
            let end = chunks[1].to_string();
            Ok((begin, label, end))
        }
        lsp::ParameterLabel::LabelOffsets([start, finish]) => {
            // Offsets are based on a UTF-16 string representation, inclusive start,
            // exclusive finish.
            let start = start.to_usize()?;
            let finish = finish.to_usize()?;
            let utf16: Vec<u16> = signature.encode_utf16().collect();
            let begin = utf16
                .get(..start)
                .ok_or_else(|| err_msg("Offset out of range"))?;
            let begin = String::from_utf16(begin)?;
            let label = utf16
                .get(start..finish)
                .ok_or_else(|| err_msg("Offset out of range"))?;
            let label = String::from_utf16(label)?;
            let end = utf16
                .get(finish..)
                .ok_or_else(|| err_msg("Offset out of range"))?;
            let end = String::from_utf16(end)?;
            Ok((begin, label, end))
        }
    }
}
<|endoftext|>


<commit_before>extern crate base64;

use self::base64::encode;
use http::retrieve_asset;
use regex::Regex;
use std::collections::HashMap;
use url::{ParseError, Url};

lazy_static! {
    static ref HAS_PROTOCOL: Regex = Regex::new(r"^[a-z0-9]+:").unwrap();
    static ref REGEX_URL: Regex = Regex::new(r"^https?://").unwrap();
}

const MAGIC: [[&[u8]; 2]; 19] = [
    // Image
    [b"GIF87a", b"image/gif"],
    [b"GIF89a", b"image/gif"],
    [b"\xFF\xD8\xFF", b"image/jpeg"],
    [b"\x89PNG\x0D\x0A\x1A\x0A", b"image/png"],
    [b"<?xml ", b"image/svg+xml"],
    [b"<svg ", b"image/svg+xml"],
    [b"RIFF....WEBPVP8 ", b"image/webp"],
    [b"\x00\x00\x01\x00", b"image/x-icon"],
    // Audio
    [b"ID3", b"audio/mpeg"],
    [b"\xFF\x0E", b"audio/mpeg"],
    [b"\xFF\x0F", b"audio/mpeg"],
    [b"OggS", b"audio/ogg"],
    [b"RIFF....WAVEfmt ", b"audio/wav"],
    [b"fLaC", b"audio/x-flac"],
    // Video
    [b"RIFF....AVI LIST", b"video/avi"],
    [b"....ftyp", b"video/mp4"],
    [b"\x00\x00\x01\x0B", b"video/mpeg"],
    [b"....moov", b"video/quicktime"],
    [b"\x1A\x45\xDF\xA3", b"video/webm"],
];

pub fn data_to_dataurl(mime: &str, data: &[u8]) -> String {
    let mimetype = if mime.is_empty() {
        detect_mimetype(data)
    } else {
        mime.to_string()
    };
    format!("data:{};base64,{}", mimetype, encode(data))
}

pub fn detect_mimetype(data: &[u8]) -> String {
    for item in MAGIC.iter() {
        if data.starts_with(item[0]) {
            return String::from_utf8(item[1].to_vec()).unwrap();
        }
    }
    "".to_owned()
}

pub fn url_has_protocol<T: AsRef<str>>(url: T) -> bool {
    HAS_PROTOCOL.is_match(url.as_ref().to_lowercase().as_str())
}

pub fn is_data_url<T: AsRef<str>>(url: T) -> Result<bool, ParseError> {
    Url::parse(url.as_ref()).and_then(|u| Ok(u.scheme() == "data"))
}

pub fn is_valid_url<T: AsRef<str>>(path: T) -> bool {
    REGEX_URL.is_match(path.as_ref())
}

pub fn resolve_url<T: AsRef<str>, U: AsRef<str>>(from: T, to: U) -> Result<String, ParseError> {
    let result = if is_valid_url(to.as_ref()) {
        to.as_ref().to_string()
    } else {
        Url::parse(from.as_ref())?
            .join(to.as_ref())?
            .as_ref()
            .to_string()
    };
    Ok(result)
}

pub fn resolve_css_imports(
    cache: &mut HashMap<String, String>,
    css_string: &str,
    as_dataurl: bool,
    href: &str,
    opt_user_agent: &str,
    opt_silent: bool,
    opt_insecure: bool,
) -> String {
    let mut resolved_css = String::from(css_string);
    let re =
        Regex::new(r###"(?P<import>@import )?url\((?P<to_repl>"?(?P<url>[^"]+)"?)\)"###).unwrap();

    for link in re.captures_iter(&css_string) {
        let target_link = link.name("url").unwrap().as_str();

        // Generate absolute URL for content
        let embedded_url = match resolve_url(href, target_link) {
            Ok(url) => url,
            Err(_) => continue, // Malformed URL
        };

        // Download the asset.  If it's more CSS, resolve that too
        let content = match link.name("import") {
            // The link is an @import link
            Some(_) => retrieve_asset(
                cache,
                &embedded_url,
                false,      // Formating as data URL will be done later
                "text/css", // Expect CSS
                opt_user_agent,
                opt_silent,
                opt_insecure,
            )
            .map(|(content, _)| {
                resolve_css_imports(
                    cache,
                    &content,
                    true, //NOW, convert to data URL
                    &embedded_url,
                    opt_user_agent,
                    opt_silent,
                    opt_insecure,
                )
            }),

            // The link is some other, non-@import link
            None => retrieve_asset(
                cache,
                &embedded_url,
                true, // Format as data URL
                "",   // Unknown MIME type
                opt_user_agent,
                opt_silent,
                opt_insecure,
            )
            .map(|(a, _)| a),
        }
        .unwrap_or_else(|e| {
            eprintln!("Warning: {}", e,);

            //If failed to resolve, replace with absolute URL
            embedded_url
        });

        let replacement = format!("\"{}\"", &content);

        let t = resolved_css
            .replace(link.name("to_repl").unwrap().as_str(), &replacement)
            .to_string();
        resolved_css = t.clone();
    }

    if as_dataurl {
        data_to_dataurl("text/css", resolved_css.as_bytes())
    } else {
        resolved_css
    }
}
<commit_msg>Use a slightly more efficient .replace_range() instead of cloning the string twice<commit_after>extern crate base64;

use self::base64::encode;
use http::retrieve_asset;
use regex::Regex;
use std::collections::HashMap;
use url::{ParseError, Url};

lazy_static! {
    static ref HAS_PROTOCOL: Regex = Regex::new(r"^[a-z0-9]+:").unwrap();
    static ref REGEX_URL: Regex = Regex::new(r"^https?://").unwrap();
}

const MAGIC: [[&[u8]; 2]; 19] = [
    // Image
    [b"GIF87a", b"image/gif"],
    [b"GIF89a", b"image/gif"],
    [b"\xFF\xD8\xFF", b"image/jpeg"],
    [b"\x89PNG\x0D\x0A\x1A\x0A", b"image/png"],
    [b"<?xml ", b"image/svg+xml"],
    [b"<svg ", b"image/svg+xml"],
    [b"RIFF....WEBPVP8 ", b"image/webp"],
    [b"\x00\x00\x01\x00", b"image/x-icon"],
    // Audio
    [b"ID3", b"audio/mpeg"],
    [b"\xFF\x0E", b"audio/mpeg"],
    [b"\xFF\x0F", b"audio/mpeg"],
    [b"OggS", b"audio/ogg"],
    [b"RIFF....WAVEfmt ", b"audio/wav"],
    [b"fLaC", b"audio/x-flac"],
    // Video
    [b"RIFF....AVI LIST", b"video/avi"],
    [b"....ftyp", b"video/mp4"],
    [b"\x00\x00\x01\x0B", b"video/mpeg"],
    [b"....moov", b"video/quicktime"],
    [b"\x1A\x45\xDF\xA3", b"video/webm"],
];

pub fn data_to_dataurl(mime: &str, data: &[u8]) -> String {
    let mimetype = if mime.is_empty() {
        detect_mimetype(data)
    } else {
        mime.to_string()
    };
    format!("data:{};base64,{}", mimetype, encode(data))
}

pub fn detect_mimetype(data: &[u8]) -> String {
    for item in MAGIC.iter() {
        if data.starts_with(item[0]) {
            return String::from_utf8(item[1].to_vec()).unwrap();
        }
    }
    "".to_owned()
}

pub fn url_has_protocol<T: AsRef<str>>(url: T) -> bool {
    HAS_PROTOCOL.is_match(url.as_ref().to_lowercase().as_str())
}

pub fn is_data_url<T: AsRef<str>>(url: T) -> Result<bool, ParseError> {
    Url::parse(url.as_ref()).and_then(|u| Ok(u.scheme() == "data"))
}

pub fn is_valid_url<T: AsRef<str>>(path: T) -> bool {
    REGEX_URL.is_match(path.as_ref())
}

pub fn resolve_url<T: AsRef<str>, U: AsRef<str>>(from: T, to: U) -> Result<String, ParseError> {
    let result = if is_valid_url(to.as_ref()) {
        to.as_ref().to_string()
    } else {
        Url::parse(from.as_ref())?
            .join(to.as_ref())?
            .as_ref()
            .to_string()
    };
    Ok(result)
}

pub fn resolve_css_imports(
    cache: &mut HashMap<String, String>,
    css_string: &str,
    as_dataurl: bool,
    href: &str,
    opt_user_agent: &str,
    opt_silent: bool,
    opt_insecure: bool,
) -> String {
    let mut resolved_css = String::from(css_string);
    let re =
        Regex::new(r###"(?P<import>@import )?url\((?P<to_repl>"?(?P<url>[^"]+)"?)\)"###).unwrap();

    for link in re.captures_iter(&css_string) {
        let target_link = link.name("url").unwrap().as_str();

        // Generate absolute URL for content
        let embedded_url = match resolve_url(href, target_link) {
            Ok(url) => url,
            Err(_) => continue, // Malformed URL
        };

        // Download the asset.  If it's more CSS, resolve that too
        let content = match link.name("import") {
            // The link is an @import link
            Some(_) => retrieve_asset(
                cache,
                &embedded_url,
                false,      // Formating as data URL will be done later
                "text/css", // Expect CSS
                opt_user_agent,
                opt_silent,
                opt_insecure,
            )
            .map(|(content, _)| {
                resolve_css_imports(
                    cache,
                    &content,
                    true, //NOW, convert to data URL
                    &embedded_url,
                    opt_user_agent,
                    opt_silent,
                    opt_insecure,
                )
            }),

            // The link is some other, non-@import link
            None => retrieve_asset(
                cache,
                &embedded_url,
                true, // Format as data URL
                "",   // Unknown MIME type
                opt_user_agent,
                opt_silent,
                opt_insecure,
            )
            .map(|(a, _)| a),
        }
        .unwrap_or_else(|e| {
            eprintln!("Warning: {}", e,);

            //If failed to resolve, replace with absolute URL
            embedded_url
        });

        let replacement = format!("\"{}\"", &content);
        let dest = link.name("to_repl").unwrap();

        resolved_css.replace_range(dest.start()..dest.end(), &replacement);
    }

    if as_dataurl {
        data_to_dataurl("text/css", resolved_css.as_bytes())
    } else {
        resolved_css
    }
}
<|endoftext|>


<commit_before>use super::inline_keyboard_button::InlineKeyboardButton;

/// Represents an inline keyboard that appears right next to the message it belongs to.
#[derive(Serialize, Debug)]
pub struct InlineKeyboardMarkup {
    pub inline_keyboard: Vec<Vec<InlineKeyboardButton>>,
}

impl InlineKeyboardMarkup {
    /// Constructs a new `InlineKeyboardMarkup`.
    pub fn new(inline_keyboard: Vec<Vec<InlineKeyboardButton>>) -> InlineKeyboardMarkup {
        InlineKeyboardMarkup { inline_keyboard: inline_keyboard }
    }
}
<commit_msg>Removing redundant path<commit_after>use super::InlineKeyboardButton;

/// Represents an inline keyboard that appears right next to the message it belongs to.
#[derive(Serialize, Debug)]
pub struct InlineKeyboardMarkup {
    pub inline_keyboard: Vec<Vec<InlineKeyboardButton>>,
}

impl InlineKeyboardMarkup {
    /// Constructs a new `InlineKeyboardMarkup`.
    pub fn new(inline_keyboard: Vec<Vec<InlineKeyboardButton>>) -> InlineKeyboardMarkup {
        InlineKeyboardMarkup { inline_keyboard: inline_keyboard }
    }
}
<|endoftext|>


<commit_before>//! A graph-like structure used to represent the rustc commands to build the project and the
//! interdependencies between them.
//!
//! The BuildPlan structure is used to store the dependency graph of a dry run so that it can be
//! shared with an external build system. Each Invocation in the BuildPlan comprises a single
//! subprocess and defines the build environment, the outputs produced by the subprocess, and the
//! dependencies on other Invocations.

use std::collections::BTreeMap;

use core::TargetKind;
use super::{Context, Kind, Unit};
use super::context::OutputFile;
use util::{internal, CargoResult, ProcessBuilder};
use std::sync::Arc;
use std::path::PathBuf;
use serde_json;
use semver;

#[derive(Debug, Serialize)]
struct Invocation {
    package_name: String,
    package_version: semver::Version,
    target_kind: TargetKind,
    kind: Kind,
    deps: Vec<usize>,
    outputs: Vec<PathBuf>,
    links: BTreeMap<PathBuf, PathBuf>,
    program: String,
    args: Vec<String>,
    env: BTreeMap<String, String>,
    cwd: Option<PathBuf>,
}

#[derive(Debug)]
pub struct BuildPlan {
    invocation_map: BTreeMap<String, usize>,
    plan: SerializedBuildPlan,
}

#[derive(Debug, Serialize)]
struct SerializedBuildPlan {
    invocations: Vec<Invocation>,
    inputs: Vec<PathBuf>,
}

impl Invocation {
    pub fn new(unit: &Unit, deps: Vec<usize>) -> Invocation {
        let id = unit.pkg.package_id();
        Invocation {
            package_name: id.name().to_string(),
            package_version: id.version().clone(),
            kind: unit.kind,
            target_kind: unit.target.kind().clone(),
            deps,
            outputs: Vec::new(),
            links: BTreeMap::new(),
            program: String::new(),
            args: Vec::new(),
            env: BTreeMap::new(),
            cwd: None,
        }
    }

    pub fn add_output(&mut self, path: &PathBuf, link: &Option<PathBuf>) {
        self.outputs.push(path.clone());
        if let Some(ref link) = *link {
            self.links.insert(link.clone(), path.clone());
        }
    }

    pub fn update_cmd(&mut self, cmd: &ProcessBuilder) -> CargoResult<()> {
        self.program = cmd.get_program()
            .to_str()
            .ok_or_else(|| format_err!("unicode program string required"))?
            .to_string();
        self.cwd = Some(cmd.get_cwd().unwrap().to_path_buf());
        for arg in cmd.get_args().iter() {
            self.args.push(
                arg.to_str()
                    .ok_or_else(|| format_err!("unicode argument string required"))?
                    .to_string(),
            );
        }
        for (var, value) in cmd.get_envs() {
            let value = match value {
                Some(s) => s,
                None => continue,
            };
            self.env.insert(
                var.clone(),
                value
                    .to_str()
                    .ok_or_else(|| format_err!("unicode environment value required"))?
                    .to_string(),
            );
        }
        Ok(())
    }
}

impl BuildPlan {
    pub fn new() -> BuildPlan {
        BuildPlan {
            invocation_map: BTreeMap::new(),
            plan: SerializedBuildPlan::new(),
        }
    }

    pub fn add(&mut self, cx: &Context, unit: &Unit) -> CargoResult<()> {
        let id = self.plan.invocations.len();
        self.invocation_map.insert(unit.buildkey(), id);
        let deps = cx.dep_targets(&unit)
            .iter()
            .map(|dep| self.invocation_map[&dep.buildkey()])
            .collect();
        let invocation = Invocation::new(unit, deps);
        self.plan.invocations.push(invocation);
        Ok(())
    }

    pub fn update(
        &mut self,
        invocation_name: &str,
        cmd: &ProcessBuilder,
        outputs: &Arc<Vec<OutputFile>>,
    ) -> CargoResult<()> {
        let id = self.invocation_map[invocation_name];
        let invocation = self.plan
            .invocations
            .get_mut(id)
            .ok_or_else(|| internal(format!("couldn't find invocation for {}", invocation_name)))?;

        invocation.update_cmd(cmd)?;
        for output in outputs.iter() {
            invocation.add_output(&output.path, &output.hardlink);
        }

        Ok(())
    }

    pub fn set_inputs(&mut self, inputs: Vec<PathBuf>) {
        self.plan.inputs = inputs;
    }

    pub fn output_plan(self) {
        let encoded = serde_json::to_string(&self.plan).unwrap();
        println!("{}", encoded);
    }
}

impl SerializedBuildPlan {
    pub fn new() -> SerializedBuildPlan {
        SerializedBuildPlan {
            invocations: Vec::new(),
            inputs: Vec::new(),
        }
    }
}
<commit_msg>more general update<commit_after>//! A graph-like structure used to represent the rustc commands to build the project and the
//! interdependencies between them.
//!
//! The BuildPlan structure is used to store the dependency graph of a dry run so that it can be
//! shared with an external build system. Each Invocation in the BuildPlan comprises a single
//! subprocess and defines the build environment, the outputs produced by the subprocess, and the
//! dependencies on other Invocations.

use std::collections::BTreeMap;

use core::TargetKind;
use super::{Context, Kind, Unit};
use super::context::OutputFile;
use util::{internal, CargoResult, ProcessBuilder};
use std::path::PathBuf;
use serde_json;
use semver;

#[derive(Debug, Serialize)]
struct Invocation {
    package_name: String,
    package_version: semver::Version,
    target_kind: TargetKind,
    kind: Kind,
    deps: Vec<usize>,
    outputs: Vec<PathBuf>,
    links: BTreeMap<PathBuf, PathBuf>,
    program: String,
    args: Vec<String>,
    env: BTreeMap<String, String>,
    cwd: Option<PathBuf>,
}

#[derive(Debug)]
pub struct BuildPlan {
    invocation_map: BTreeMap<String, usize>,
    plan: SerializedBuildPlan,
}

#[derive(Debug, Serialize)]
struct SerializedBuildPlan {
    invocations: Vec<Invocation>,
    inputs: Vec<PathBuf>,
}

impl Invocation {
    pub fn new(unit: &Unit, deps: Vec<usize>) -> Invocation {
        let id = unit.pkg.package_id();
        Invocation {
            package_name: id.name().to_string(),
            package_version: id.version().clone(),
            kind: unit.kind,
            target_kind: unit.target.kind().clone(),
            deps,
            outputs: Vec::new(),
            links: BTreeMap::new(),
            program: String::new(),
            args: Vec::new(),
            env: BTreeMap::new(),
            cwd: None,
        }
    }

    pub fn add_output(&mut self, path: &PathBuf, link: &Option<PathBuf>) {
        self.outputs.push(path.clone());
        if let Some(ref link) = *link {
            self.links.insert(link.clone(), path.clone());
        }
    }

    pub fn update_cmd(&mut self, cmd: &ProcessBuilder) -> CargoResult<()> {
        self.program = cmd.get_program()
            .to_str()
            .ok_or_else(|| format_err!("unicode program string required"))?
            .to_string();
        self.cwd = Some(cmd.get_cwd().unwrap().to_path_buf());
        for arg in cmd.get_args().iter() {
            self.args.push(
                arg.to_str()
                    .ok_or_else(|| format_err!("unicode argument string required"))?
                    .to_string(),
            );
        }
        for (var, value) in cmd.get_envs() {
            let value = match value {
                Some(s) => s,
                None => continue,
            };
            self.env.insert(
                var.clone(),
                value
                    .to_str()
                    .ok_or_else(|| format_err!("unicode environment value required"))?
                    .to_string(),
            );
        }
        Ok(())
    }
}

impl BuildPlan {
    pub fn new() -> BuildPlan {
        BuildPlan {
            invocation_map: BTreeMap::new(),
            plan: SerializedBuildPlan::new(),
        }
    }

    pub fn add(&mut self, cx: &Context, unit: &Unit) -> CargoResult<()> {
        let id = self.plan.invocations.len();
        self.invocation_map.insert(unit.buildkey(), id);
        let deps = cx.dep_targets(&unit)
            .iter()
            .map(|dep| self.invocation_map[&dep.buildkey()])
            .collect();
        let invocation = Invocation::new(unit, deps);
        self.plan.invocations.push(invocation);
        Ok(())
    }

    pub fn update(
        &mut self,
        invocation_name: &str,
        cmd: &ProcessBuilder,
        outputs: &[OutputFile],
    ) -> CargoResult<()> {
        let id = self.invocation_map[invocation_name];
        let invocation = self.plan
            .invocations
            .get_mut(id)
            .ok_or_else(|| internal(format!("couldn't find invocation for {}", invocation_name)))?;

        invocation.update_cmd(cmd)?;
        for output in outputs.iter() {
            invocation.add_output(&output.path, &output.hardlink);
        }

        Ok(())
    }

    pub fn set_inputs(&mut self, inputs: Vec<PathBuf>) {
        self.plan.inputs = inputs;
    }

    pub fn output_plan(self) {
        let encoded = serde_json::to_string(&self.plan).unwrap();
        println!("{}", encoded);
    }
}

impl SerializedBuildPlan {
    pub fn new() -> SerializedBuildPlan {
        SerializedBuildPlan {
            invocations: Vec::new(),
            inputs: Vec::new(),
        }
    }
}
<|endoftext|>


<commit_before>use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::usage::contains_return_break_continue_macro;
use clippy_utils::{eager_or_lazy, get_enclosing_block, in_macro, is_else_clause, is_lang_ctor};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::LangItem::OptionSome;
use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, MatchSource, Mutability, PatKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;

declare_clippy_lint! {
    /// **What it does:**
    /// Lints usage of `if let Some(v) = ... { y } else { x }` which is more
    /// idiomatically done with `Option::map_or` (if the else bit is a pure
    /// expression) or `Option::map_or_else` (if the else bit is an impure
    /// expression).
    ///
    /// **Why is this bad?**
    /// Using the dedicated functions of the Option type is clearer and
    /// more concise than an `if let` expression.
    ///
    /// **Known problems:**
    /// This lint uses a deliberately conservative metric for checking
    /// if the inside of either body contains breaks or continues which will
    /// cause it to not suggest a fix if either block contains a loop with
    /// continues or breaks contained within the loop.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// # let optional: Option<u32> = Some(0);
    /// # fn do_complicated_function() -> u32 { 5 };
    /// let _ = if let Some(foo) = optional {
    ///     foo
    /// } else {
    ///     5
    /// };
    /// let _ = if let Some(foo) = optional {
    ///     foo
    /// } else {
    ///     let y = do_complicated_function();
    ///     y*y
    /// };
    /// ```
    ///
    /// should be
    ///
    /// ```rust
    /// # let optional: Option<u32> = Some(0);
    /// # fn do_complicated_function() -> u32 { 5 };
    /// let _ = optional.map_or(5, |foo| foo);
    /// let _ = optional.map_or_else(||{
    ///     let y = do_complicated_function();
    ///     y*y
    /// }, |foo| foo);
    /// ```
    pub OPTION_IF_LET_ELSE,
    pedantic,
    "reimplementation of Option::map_or"
}

declare_lint_pass!(OptionIfLetElse => [OPTION_IF_LET_ELSE]);

/// Returns true iff the given expression is the result of calling `Result::ok`
fn is_result_ok(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool {
    if let ExprKind::MethodCall(path, _, &[ref receiver], _) = &expr.kind {
        path.ident.name.as_str() == "ok"
            && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(receiver), sym::result_type)
    } else {
        false
    }
}

/// A struct containing information about occurrences of the
/// `if let Some(..) = .. else` construct that this lint detects.
struct OptionIfLetElseOccurence {
    option: String,
    method_sugg: String,
    some_expr: String,
    none_expr: String,
    wrap_braces: bool,
}

/// Extracts the body of a given arm. If the arm contains only an expression,
/// then it returns the expression. Otherwise, it returns the entire block
fn extract_body_from_arm<'a>(arm: &'a Arm<'a>) -> Option<&'a Expr<'a>> {
    if let ExprKind::Block(
        Block {
            stmts: statements,
            expr: Some(expr),
            ..
        },
        _,
    ) = &arm.body.kind
    {
        if let [] = statements {
            Some(expr)
        } else {
            Some(arm.body)
        }
    } else {
        None
    }
}

/// If this is the else body of an if/else expression, then we need to wrap
/// it in curly braces. Otherwise, we don't.
fn should_wrap_in_braces(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
    get_enclosing_block(cx, expr.hir_id).map_or(false, |parent| {
        let mut should_wrap = false;

        if let Some(Expr {
            kind:
                ExprKind::Match(
                    _,
                    arms,
                    MatchSource::IfLetDesugar {
                        contains_else_clause: true,
                    },
                ),
            ..
        }) = parent.expr
        {
            should_wrap = expr.hir_id == arms[1].body.hir_id;
        } else if let Some(Expr {
            kind: ExprKind::If(_, _, Some(else_clause)),
            ..
        }) = parent.expr
        {
            should_wrap = expr.hir_id == else_clause.hir_id;
        }

        should_wrap
    })
}

fn format_option_in_sugg(cx: &LateContext<'_>, cond_expr: &Expr<'_>, as_ref: bool, as_mut: bool) -> String {
    format!(
        "{}{}",
        Sugg::hir(cx, cond_expr, "..").maybe_par(),
        if as_mut {
            ".as_mut()"
        } else if as_ref {
            ".as_ref()"
        } else {
            ""
        }
    )
}

/// If this expression is the option if let/else construct we're detecting, then
/// this function returns an `OptionIfLetElseOccurence` struct with details if
/// this construct is found, or None if this construct is not found.
fn detect_option_if_let_else<'tcx>(
    cx: &'_ LateContext<'tcx>,
    expr: &'_ Expr<'tcx>,
) -> Option<OptionIfLetElseOccurence> {
    if_chain! {
        if !in_macro(expr.span); // Don't lint macros, because it behaves weirdly
        if let ExprKind::Match(cond_expr, arms, MatchSource::IfLetDesugar{contains_else_clause: true}) = &expr.kind;
        if !is_else_clause(cx.tcx, expr);
        if arms.len() == 2;
        if !is_result_ok(cx, cond_expr); // Don't lint on Result::ok because a different lint does it already
        if let PatKind::TupleStruct(struct_qpath, &[inner_pat], _) = &arms[0].pat.kind;
        if is_lang_ctor(cx, struct_qpath, OptionSome);
        if let PatKind::Binding(bind_annotation, _, id, _) = &inner_pat.kind;
        if !contains_return_break_continue_macro(arms[0].body);
        if !contains_return_break_continue_macro(arms[1].body);

        then {
            let capture_mut = if bind_annotation == &BindingAnnotation::Mutable { "mut " } else { "" };
            let some_body = extract_body_from_arm(&arms[0])?;
            let none_body = extract_body_from_arm(&arms[1])?;
            let method_sugg = if eager_or_lazy::is_eagerness_candidate(cx, none_body) { "map_or" } else { "map_or_else" };
            let capture_name = id.name.to_ident_string();
            let wrap_braces = should_wrap_in_braces(cx, expr);
            let (as_ref, as_mut) = match &cond_expr.kind {
                ExprKind::AddrOf(_, Mutability::Not, _) => (true, false),
                ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true),
                _ => (bind_annotation == &BindingAnnotation::Ref, bind_annotation == &BindingAnnotation::RefMut),
            };
            let cond_expr = match &cond_expr.kind {
                // Pointer dereferencing happens automatically, so we can omit it in the suggestion
                ExprKind::Unary(UnOp::Deref, expr) | ExprKind::AddrOf(_, _, expr) => expr,
                _ => cond_expr,
            };
            Some(OptionIfLetElseOccurence {
                option: format_option_in_sugg(cx, cond_expr, as_ref, as_mut),
                method_sugg: method_sugg.to_string(),
                some_expr: format!("|{}{}| {}", capture_mut, capture_name, Sugg::hir(cx, some_body, "..")),
                none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir(cx, none_body, "..")),
                wrap_braces,
            })
        } else {
            None
        }
    }
}

impl<'tcx> LateLintPass<'tcx> for OptionIfLetElse {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
        if let Some(detection) = detect_option_if_let_else(cx, expr) {
            span_lint_and_sugg(
                cx,
                OPTION_IF_LET_ELSE,
                expr.span,
                format!("use Option::{} instead of an if let/else", detection.method_sugg).as_str(),
                "try",
                format!(
                    "{}{}.{}({}, {}){}",
                    if detection.wrap_braces { "{ " } else { "" },
                    detection.option,
                    detection.method_sugg,
                    detection.none_expr,
                    detection.some_expr,
                    if detection.wrap_braces { " }" } else { "" },
                ),
                Applicability::MaybeIncorrect,
            );
        }
    }
}
<commit_msg>Auto merge of #7234 - camsteffen:if-let-else-braces, r=flip1995<commit_after>use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::sugg::Sugg;
use clippy_utils::ty::is_type_diagnostic_item;
use clippy_utils::usage::contains_return_break_continue_macro;
use clippy_utils::{eager_or_lazy, in_macro, is_else_clause, is_lang_ctor};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::LangItem::OptionSome;
use rustc_hir::{Arm, BindingAnnotation, Block, Expr, ExprKind, MatchSource, Mutability, PatKind, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::sym;

declare_clippy_lint! {
    /// **What it does:**
    /// Lints usage of `if let Some(v) = ... { y } else { x }` which is more
    /// idiomatically done with `Option::map_or` (if the else bit is a pure
    /// expression) or `Option::map_or_else` (if the else bit is an impure
    /// expression).
    ///
    /// **Why is this bad?**
    /// Using the dedicated functions of the Option type is clearer and
    /// more concise than an `if let` expression.
    ///
    /// **Known problems:**
    /// This lint uses a deliberately conservative metric for checking
    /// if the inside of either body contains breaks or continues which will
    /// cause it to not suggest a fix if either block contains a loop with
    /// continues or breaks contained within the loop.
    ///
    /// **Example:**
    ///
    /// ```rust
    /// # let optional: Option<u32> = Some(0);
    /// # fn do_complicated_function() -> u32 { 5 };
    /// let _ = if let Some(foo) = optional {
    ///     foo
    /// } else {
    ///     5
    /// };
    /// let _ = if let Some(foo) = optional {
    ///     foo
    /// } else {
    ///     let y = do_complicated_function();
    ///     y*y
    /// };
    /// ```
    ///
    /// should be
    ///
    /// ```rust
    /// # let optional: Option<u32> = Some(0);
    /// # fn do_complicated_function() -> u32 { 5 };
    /// let _ = optional.map_or(5, |foo| foo);
    /// let _ = optional.map_or_else(||{
    ///     let y = do_complicated_function();
    ///     y*y
    /// }, |foo| foo);
    /// ```
    pub OPTION_IF_LET_ELSE,
    pedantic,
    "reimplementation of Option::map_or"
}

declare_lint_pass!(OptionIfLetElse => [OPTION_IF_LET_ELSE]);

/// Returns true iff the given expression is the result of calling `Result::ok`
fn is_result_ok(cx: &LateContext<'_>, expr: &'_ Expr<'_>) -> bool {
    if let ExprKind::MethodCall(path, _, &[ref receiver], _) = &expr.kind {
        path.ident.name.as_str() == "ok"
            && is_type_diagnostic_item(cx, cx.typeck_results().expr_ty(receiver), sym::result_type)
    } else {
        false
    }
}

/// A struct containing information about occurrences of the
/// `if let Some(..) = .. else` construct that this lint detects.
struct OptionIfLetElseOccurence {
    option: String,
    method_sugg: String,
    some_expr: String,
    none_expr: String,
}

/// Extracts the body of a given arm. If the arm contains only an expression,
/// then it returns the expression. Otherwise, it returns the entire block
fn extract_body_from_arm<'a>(arm: &'a Arm<'a>) -> Option<&'a Expr<'a>> {
    if let ExprKind::Block(
        Block {
            stmts: statements,
            expr: Some(expr),
            ..
        },
        _,
    ) = &arm.body.kind
    {
        if let [] = statements {
            Some(expr)
        } else {
            Some(arm.body)
        }
    } else {
        None
    }
}

fn format_option_in_sugg(cx: &LateContext<'_>, cond_expr: &Expr<'_>, as_ref: bool, as_mut: bool) -> String {
    format!(
        "{}{}",
        Sugg::hir(cx, cond_expr, "..").maybe_par(),
        if as_mut {
            ".as_mut()"
        } else if as_ref {
            ".as_ref()"
        } else {
            ""
        }
    )
}

/// If this expression is the option if let/else construct we're detecting, then
/// this function returns an `OptionIfLetElseOccurence` struct with details if
/// this construct is found, or None if this construct is not found.
fn detect_option_if_let_else<'tcx>(
    cx: &'_ LateContext<'tcx>,
    expr: &'_ Expr<'tcx>,
) -> Option<OptionIfLetElseOccurence> {
    if_chain! {
        if !in_macro(expr.span); // Don't lint macros, because it behaves weirdly
        if let ExprKind::Match(cond_expr, arms, MatchSource::IfLetDesugar{contains_else_clause: true}) = &expr.kind;
        if !is_else_clause(cx.tcx, expr);
        if arms.len() == 2;
        if !is_result_ok(cx, cond_expr); // Don't lint on Result::ok because a different lint does it already
        if let PatKind::TupleStruct(struct_qpath, &[inner_pat], _) = &arms[0].pat.kind;
        if is_lang_ctor(cx, struct_qpath, OptionSome);
        if let PatKind::Binding(bind_annotation, _, id, _) = &inner_pat.kind;
        if !contains_return_break_continue_macro(arms[0].body);
        if !contains_return_break_continue_macro(arms[1].body);

        then {
            let capture_mut = if bind_annotation == &BindingAnnotation::Mutable { "mut " } else { "" };
            let some_body = extract_body_from_arm(&arms[0])?;
            let none_body = extract_body_from_arm(&arms[1])?;
            let method_sugg = if eager_or_lazy::is_eagerness_candidate(cx, none_body) { "map_or" } else { "map_or_else" };
            let capture_name = id.name.to_ident_string();
            let (as_ref, as_mut) = match &cond_expr.kind {
                ExprKind::AddrOf(_, Mutability::Not, _) => (true, false),
                ExprKind::AddrOf(_, Mutability::Mut, _) => (false, true),
                _ => (bind_annotation == &BindingAnnotation::Ref, bind_annotation == &BindingAnnotation::RefMut),
            };
            let cond_expr = match &cond_expr.kind {
                // Pointer dereferencing happens automatically, so we can omit it in the suggestion
                ExprKind::Unary(UnOp::Deref, expr) | ExprKind::AddrOf(_, _, expr) => expr,
                _ => cond_expr,
            };
            Some(OptionIfLetElseOccurence {
                option: format_option_in_sugg(cx, cond_expr, as_ref, as_mut),
                method_sugg: method_sugg.to_string(),
                some_expr: format!("|{}{}| {}", capture_mut, capture_name, Sugg::hir(cx, some_body, "..")),
                none_expr: format!("{}{}", if method_sugg == "map_or" { "" } else { "|| " }, Sugg::hir(cx, none_body, "..")),
            })
        } else {
            None
        }
    }
}

impl<'tcx> LateLintPass<'tcx> for OptionIfLetElse {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'tcx>) {
        if let Some(detection) = detect_option_if_let_else(cx, expr) {
            span_lint_and_sugg(
                cx,
                OPTION_IF_LET_ELSE,
                expr.span,
                format!("use Option::{} instead of an if let/else", detection.method_sugg).as_str(),
                "try",
                format!(
                    "{}.{}({}, {})",
                    detection.option, detection.method_sugg, detection.none_expr, detection.some_expr,
                ),
                Applicability::MaybeIncorrect,
            );
        }
    }
}
<|endoftext|>


<commit_before>use std::char;
use std::cell::Cell;

#[derive(Debug)]
pub enum Value {
    Int(String),
    Str(String),
}

#[derive(Debug, PartialEq)]
pub enum TokenType {
    ILLEGAL,
    EOF,
    IDENT,
    INT,
    ASSIGN,
    EQ,
    BANG,
    NOT_EQ,
    PLUS,
    MINUS,
    COMMA,
    SEMICOLON,
    LPAREN,
    RPAREN,
    LBRACE,
    RBRACE,
    FUNCTION,
    LET,
}

impl TokenType {
}

#[derive(Debug)]
pub struct Token {
    pub token_type: TokenType,
    pub value: Option<Value>,
}

pub struct Lexer {
    input: String,
    position: Cell<usize>,
    read_position: Cell<usize>,
}

impl Lexer {
    pub fn new(input: String) -> Lexer {
        return Lexer {
            input: input,
            position: Cell::new(0),
            read_position: Cell::new(0),
        };
    }

    pub fn from_string(&self, s: String) -> TokenType {
        match s.trim().as_ref() {
            "\n" => TokenType::EOF,
            "=" =>  {
                if self.peek_char() == '=' {
                    let ch = self.peek_char(); // chに退避させて次の文字を読む
                    self.read_char();
                    TokenType::EQ
                } else {
                    TokenType::ASSIGN
                }
            },
            "(" => TokenType::LPAREN,
            ")" => TokenType::RPAREN,
            "let" => TokenType::LET,
            "+" => TokenType::PLUS,
            "-" => TokenType::MINUS,
            "," => TokenType::COMMA,
            ";" => TokenType::SEMICOLON,
            "{" => TokenType::LBRACE,
            "}" => TokenType::RBRACE,
            "!" => {
                if self.peek_char() == '=' {
                    let ch = self.peek_char(); // chに退避させて次の文字を読む
                    self.read_char();
                    TokenType::NOT_EQ
                } else {
                    TokenType::BANG
                }

            },
            "func" => TokenType::FUNCTION,
            c => TokenType::ILLEGAL
        }
    }

    pub fn read_char(&self) -> char {
        if self.read_position.get() >= self.input.len() {
            return '0';
        } else {
            let c = self.input.chars().nth(self.read_position.get()).unwrap();
            self.position.set(self.read_position.get());
            self.read_position.set(self.read_position.get() + 1);
            return c;
        }
    }

    pub fn next_token(&self) -> Token {
        let c = self.read_char();
        let token_type = self.from_string(c.to_string());
        return Token {
            token_type: token_type,
            value: Some(Value::Str(c.to_string()))
        };
    }

    pub fn peek_char(&self) -> char {
        if self.read_position.get() >= self.input.len() {
            return '0';
        } else {
            return self.input.chars().nth(self.read_position.get()).unwrap();
        }
    }

    pub unsafe fn read_identifier(&self) -> String {
        let start_position = self.position.get();
        let ch = self.peek_char();
        while is_letter(ch) {
            self.read_char();
        }
        let end_position = self.position.get();
        let s = self.input.slice_unchecked(start_position, end_position);
        return s.to_string();
    }

    pub unsafe fn read_number(&self) -> String {
        let start_position = self.position.get();
        let ch = self.peek_char();
        while is_digit(ch) {
            self.read_char();
        }
        let end_position = self.position.get();
        let s = self.input.slice_unchecked(start_position, end_position);
        return s.to_string();
    }

    pub fn skip_white_space(&self) {
        let ch = self.peek_char();
        while ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' {
            self.read_char();
        }
    }
}

fn is_letter(ch: char) -> bool {
    return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_'
}

fn is_digit(ch: char) -> bool {
    return '0' <= ch && ch <= '9';
}

#[test]
fn read_char() {
    let input = String::from("=!");
    let l = &Lexer::new(input);
    assert_eq!('=', l.read_char());
    assert_eq!('!', l.read_char());
    assert_eq!('0', l.read_char());
}

#[test]
fn peek_char() {
    let input = String::from("!=");
    let l = &Lexer::new(input);
    assert_eq!('!', l.peek_char());
    assert_eq!('!', l.peek_char());
}

#[test]
fn next_token() {
    let input = String::from("=()");
    let l = &Lexer::new(input);
    assert_eq!(l.next_token().token_type, TokenType::ASSIGN);
    assert_eq!(l.next_token().token_type, TokenType::LPAREN);
    assert_eq!(l.next_token().token_type, TokenType::RPAREN);
}

#[test]
fn from_string() {
    let input = String::from("=()");
    let l = &Lexer::new(input);
    assert_eq!(l.from_string(String::from("=")), TokenType::ASSIGN);
    assert_eq!(l.from_string(String::from("(")), TokenType::LPAREN);
}
<commit_msg>edit lang.rs:<commit_after>use std::char;
use std::cell::Cell;

#[derive(Debug)]
pub enum Value {
    Int(String),
    Str(String),
}

#[derive(Debug, PartialEq)]
pub enum TokenType {
    ILLEGAL,
    EOF,
    IDENT,
    INT,
    ASSIGN,
    EQ,
    BANG,
    NOT_EQ,
    PLUS,
    MINUS,
    COMMA,
    SEMICOLON,
    LPAREN,
    RPAREN,
    LBRACE,
    RBRACE,
    SLASH,
    ASTERISK,
    LT,
    GT,
    FUNCTION,
    LET,
}

impl TokenType {
}

#[derive(Debug)]
pub struct Token {
    pub token_type: TokenType,
    pub value: Option<Value>,
}

pub struct Lexer {
    input: String,
    position: Cell<usize>,
    read_position: Cell<usize>,
    ch: Cell<char>
}

impl Lexer {
    pub fn new(input: String) -> Lexer {
        let l = Lexer {
            input: input,
            position: Cell::new(0),
            read_position: Cell::new(0),
            ch: Cell::new('0')
        };
        l.read_char();
        return l;
    }

    pub fn from_string(&self, s: String) -> TokenType {
        match s.trim().as_ref() {
            "\n" => TokenType::EOF,
            "=" =>  {
                if self.peek_char() == '=' {
                    let ch = self.ch.get(); // chに退避させて次の文字を読む
                    self.read_char();
                    TokenType::EQ
                } else {
                    TokenType::ASSIGN
                }
            },
            "(" => TokenType::LPAREN,
            ")" => TokenType::RPAREN,
            "let" => TokenType::LET,
            "+" => TokenType::PLUS,
            "-" => TokenType::MINUS,
            "," => TokenType::COMMA,
            ";" => TokenType::SEMICOLON,
            "{" => TokenType::LBRACE,
            "}" => TokenType::RBRACE,
            "/" => TokenType::SLASH,
            "," => TokenType::COMMA,
            "0" => TokenType::EOF,
            "!" => {
                if self.peek_char() == '=' {
                    let ch = self.ch.get(); // chに退避させて次の文字を読む
                    self.read_char();
                    TokenType::NOT_EQ
                } else {
                    TokenType::BANG
                }

            },
            "func" => TokenType::FUNCTION,
            c => {
                TokenType::ILLEGAL
            }
        }
    }

    pub fn read_char(&self) -> char {
        if self.read_position.get() >= self.input.len() {
            return '0';
        } else {
            let c = self.input.chars().nth(self.read_position.get()).unwrap();
            self.position.set(self.read_position.get());
            self.read_position.set(self.read_position.get() + 1);
            return c;
        }
    }

    pub fn next_token(&self) -> Token {
        let c = self.read_char();
        let token_type = self.from_string(c.to_string());
        return Token {
            token_type: token_type,
            value: Some(Value::Str(c.to_string()))
        };
    }

    pub fn peek_char(&self) -> char {
        if self.read_position.get() >= self.input.len() {
            return '0';
        } else {
            return self.input.chars().nth(self.read_position.get()).unwrap();
        }
    }

    pub unsafe fn read_identifier(&self) -> String {
        let start_position = self.position.get();
        let ch = self.ch.get();
        while is_letter(ch) {
            self.read_char();
        }
        let end_position = self.position.get();
        let s = self.input.slice_unchecked(start_position, end_position);
        return s.to_string();
    }

    pub unsafe fn read_number(&self) -> String {
        let start_position = self.position.get();
        let ch = self.ch.get();
        while is_digit(ch) {
            self.read_char();
        }
        let end_position = self.position.get();
        let s = self.input.slice_unchecked(start_position, end_position);
        return s.to_string();
    }

    pub fn skip_white_space(&self) {
        let ch = self.ch.get();
        while ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' {
            self.read_char();
        }
    }
}

fn is_letter(ch: char) -> bool {
    return 'a' <= ch && ch <= 'z' || 'A' <= ch && ch <= 'Z' || ch == '_'
}

fn is_digit(ch: char) -> bool {
    return '0' <= ch && ch <= '9';
}

#[test]
fn read_char() {
    let input = String::from("=!");
    let l = &Lexer::new(input);
    assert_eq!('=', l.read_char());
    assert_eq!('!', l.read_char());
    assert_eq!('0', l.read_char());
}

#[test]
fn peek_char() {
    let input = String::from("!=");
    let l = &Lexer::new(input);
    assert_eq!('!', l.peek_char());
    assert_eq!('!', l.peek_char());
}

#[test]
fn next_token() {
    let input = String::from("=()");
    let l = &Lexer::new(input);
    assert_eq!(l.next_token().token_type, TokenType::ASSIGN);
    assert_eq!(l.next_token().token_type, TokenType::LPAREN);
    assert_eq!(l.next_token().token_type, TokenType::RPAREN);
}

#[test]
fn from_string() {
    let input = String::from("=()");
    let l = &Lexer::new(input);
    assert_eq!(l.from_string(String::from("=")), TokenType::ASSIGN);
    assert_eq!(l.from_string(String::from("(")), TokenType::LPAREN);
}
<|endoftext|>


<commit_before>extern crate conduit_git_http_backend as git_backend;
extern crate git2_curl;
extern crate civet;
extern crate conduit;
extern crate curl;
extern crate git2;
extern crate tempdir;

use civet::{Server, Config};
use std::fs::File;
use std::path::Path;
use tempdir::TempDir;

const PORT: u16 = 7848;

fn main() {
    unsafe {
        let h = curl::http::handle::Handle::new();
        git2_curl::register(h.timeout(1000));
    }

    // Spin up a server for git-http-backend
    let td = TempDir::new("wut").unwrap();
    let _a = Server::start(Config { port: PORT, threads: 1 },
                           git_backend::Serve(td.path().to_path_buf()));

    // Prep a repo with one file called `foo`
    let sig = git2::Signature::now("foo", "bar").unwrap();
    let r1 = git2::Repository::init(td.path()).unwrap();
    File::create(&td.path().join(".git").join("git-daemon-export-ok")).unwrap();
    {
        let mut index = r1.index().unwrap();
        File::create(&td.path().join("foo")).unwrap();
        index.add_path(Path::new("foo")).unwrap();
        index.write().unwrap();
        let tree_id = index.write_tree().unwrap();
        r1.commit(Some("HEAD"), &sig, &sig, "test",
                  &r1.find_tree(tree_id).unwrap(),
                  &[]).unwrap();
    }

    // Clone through the git-http-backend
    let td2 = TempDir::new("wut2").unwrap();
    let r = git2::Repository::clone(&format!("http://localhost:{}", PORT),
                                    td2.path()).unwrap();
    assert!(File::open(&td2.path().join("foo")).is_ok());
    {
        File::create(&td.path().join("bar")).unwrap();
        let mut index = r1.index().unwrap();
        index.add_path(&Path::new("bar")).unwrap();
        index.write().unwrap();
        let tree_id = index.write_tree().unwrap();
        let parent = r1.head().ok().and_then(|h| h.target()).unwrap();
        let parent = r1.find_commit(parent).unwrap();
        r1.commit(Some("HEAD"), &sig, &sig, "test",
                  &r1.find_tree(tree_id).unwrap(),
                  &[&parent]).unwrap();
    }

    let mut remote = r.find_remote("origin").unwrap();
    remote.fetch(&["refs/heads/*:refs/heads/*"], None).unwrap();
    let b = r.find_branch("master", git2::BranchType::Local).unwrap();
    let id = b.get().target().unwrap();
    let obj = r.find_object(id, None).unwrap();
    r.reset(&obj, git2::ResetType::Hard, None).unwrap();;

    assert!(File::open(&td2.path().join("bar")).is_ok());
}
<commit_msg>Fix git2-curl tests<commit_after>extern crate conduit_git_http_backend as git_backend;
extern crate git2_curl;
extern crate civet;
extern crate conduit;
extern crate curl;
extern crate git2;
extern crate tempdir;

use civet::{Server, Config};
use std::fs::File;
use std::path::Path;
use tempdir::TempDir;

const PORT: u16 = 7848;

fn main() {
    unsafe {
        let h = curl::http::handle::Handle::new();
        git2_curl::register(h.timeout(1000));
    }

    // Spin up a server for git-http-backend
    let td = TempDir::new("wut").unwrap();
    let _a = Server::start(Config { port: PORT, threads: 1 },
                           git_backend::Serve(td.path().to_path_buf()));

    // Prep a repo with one file called `foo`
    let sig = git2::Signature::now("foo", "bar").unwrap();
    let r1 = git2::Repository::init(td.path()).unwrap();
    File::create(&td.path().join(".git").join("git-daemon-export-ok")).unwrap();
    {
        let mut index = r1.index().unwrap();
        File::create(&td.path().join("foo")).unwrap();
        index.add_path(Path::new("foo")).unwrap();
        index.write().unwrap();
        let tree_id = index.write_tree().unwrap();
        r1.commit(Some("HEAD"), &sig, &sig, "test",
                  &r1.find_tree(tree_id).unwrap(),
                  &[]).unwrap();
    }

    // Clone through the git-http-backend
    let td2 = TempDir::new("wut2").unwrap();
    let r = git2::Repository::clone(&format!("http://localhost:{}", PORT),
                                    td2.path()).unwrap();
    assert!(File::open(&td2.path().join("foo")).is_ok());
    {
        File::create(&td.path().join("bar")).unwrap();
        let mut index = r1.index().unwrap();
        index.add_path(&Path::new("bar")).unwrap();
        index.write().unwrap();
        let tree_id = index.write_tree().unwrap();
        let parent = r1.head().ok().and_then(|h| h.target()).unwrap();
        let parent = r1.find_commit(parent).unwrap();
        r1.commit(Some("HEAD"), &sig, &sig, "test",
                  &r1.find_tree(tree_id).unwrap(),
                  &[&parent]).unwrap();
    }

    let mut remote = r.find_remote("origin").unwrap();
    remote.fetch(&["refs/heads/*:refs/heads/*"], None, None).unwrap();
    let b = r.find_branch("master", git2::BranchType::Local).unwrap();
    let id = b.get().target().unwrap();
    let obj = r.find_object(id, None).unwrap();
    r.reset(&obj, git2::ResetType::Hard, None).unwrap();;

    assert!(File::open(&td2.path().join("bar")).is_ok());
}
<|endoftext|>