<commit_before>pub trait Property<T> {
    fn inherits_automatically() -> bool;
    fn compute(&self, &T) -> Self;
}

/// Generates a property definition that simply parses strings to enum variants
/// or to a tuple struct of the given type.
///
/// For example, the SVG spec defines the `stroke-linejoin` property
/// to have possible values `miter | round | bevel | inherit`, with a default
/// of `miter`.  We can define the property like this:
///
/// ```ignore
/// make_property!(
/// StrokeLinejoin,
/// default: Miter,
///
/// "miter" => Miter,
/// "round" => Round,
/// "bevel" => Bevel,
/// );
/// ```
///
/// The macro will generate a `StrokeLinejoin` enum with the provided
/// variants.  It will generate an `impl Default for StrokeLinejoin`
/// with the provided `default:` value.  Finally, it will generate an
/// `impl Parse for StrokeLinejoin`, from `parsers::Parse`, where
/// `type Data = ()` and `type Err = AttributeError`.
#[macro_export]
macro_rules! make_property {
    ($computed_values_type: ty,
     $name: ident,
     default: $default: ident,
     inherits_automatically: $inherits_automatically: expr,
     identifiers:
     $($str_prop: expr => $variant: ident,)+
    ) => {
        #[derive(Debug, Copy, Clone, PartialEq)]
        pub enum $name {
            $($variant),+
        }

        impl_default!($name, $name::$default);
        impl_property!($computed_values_type, $name, $inherits_automatically);

        impl ::parsers::Parse for $name {
            type Data = ();
            type Err = ::error::AttributeError;

            fn parse(s: &str, _: Self::Data) -> Result<$name, ::error::AttributeError> {
                match s.trim() {
                    $($str_prop => Ok($name::$variant),)+

                    _ => Err(::error::AttributeError::from(::parsers::ParseError::new("invalid value"))),
                }
            }
        }
    };

    ($computed_values_type: ty,
     $name: ident,
     default: $default: expr,
     inherits_automatically: $inherits_automatically: expr,
     newtype_from_str: $type: ty
    ) => {
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name(pub $type);

        impl_default!($name, $name($default));
        impl_property!($computed_values_type, $name, $inherits_automatically);

        impl ::parsers::Parse for $name {
            type Data = ();
            type Err = ::error::AttributeError;

            fn parse(s: &str, _: Self::Data) -> Result<$name, ::error::AttributeError> {
                s.trim()
                    .parse()
                    .map(|val| $name(val))
                    .map_err(|_| ::error::AttributeError::from(
                        ::parsers::ParseError::new("parse error")
                    ))
            }
        }
    };

    ($computed_values_type: ty,
     $name: ident,
     default: $default: expr,
     inherits_automatically: $inherits_automatically: expr,
     newtype_parse: $type: ty,
     parse_data_type: $parse_data_type: ty
    ) => {
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name(pub $type);

        impl_default!($name, $name($default));

        impl ::property_macros::Property<$computed_values_type> for $name {
            fn inherits_automatically() -> bool {
                $inherits_automatically
            }

            fn compute(&self, _v: &$computed_values_type) -> Self {
                self.clone()
            }
        }

        impl ::parsers::Parse for $name {
            type Data = $parse_data_type;
            type Err = ::error::AttributeError;

            fn parse(s: &str, d: Self::Data) -> Result<$name, ::error::AttributeError> {
                Ok($name(<$type as ::parsers::Parse>::parse(s, d)?))
            }
        }
    };

    ($computed_values_type: ty,
     $name: ident,
     default: $default: expr,
     newtype_parse: $type: ty,
     parse_data_type: $parse_data_type: ty,
     property_impl: { $prop: item }
    ) => {
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name(pub $type);

        impl_default!($name, $name($default));

        $prop

        impl ::parsers::Parse for $name {
            type Data = $parse_data_type;
            type Err = ::error::AttributeError;

            fn parse(s: &str, d: Self::Data) -> Result<$name, ::error::AttributeError> {
                Ok($name(<$type as ::parsers::Parse>::parse(s, d)?))
            }
        }
    };

    ($computed_values_type: ty,
     $name: ident,
     default: $default: expr,
     newtype: $type: ty,
     property_impl: { $prop: item },
     parse_impl: { $parse: item }
    ) => {
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name(pub $type);

        impl_default!($name, $name($default));

        $prop

        $parse
    };

    ($computed_values_type: ty,
     $name: ident,
     inherits_automatically: $inherits_automatically: expr,
     fields: {
       $($field_name: ident : $field_type: ty, default: $field_default : expr,)+
     }
     parse_impl: { $parse: item }
    ) => {
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name {
            $(pub $field_name: $field_type),+
        }

        impl_default!($name, $name { $($field_name: $field_default),+ });
        impl_property!($computed_values_type, $name, $inherits_automatically);

        $parse
    };
}

macro_rules! impl_default {
    ($name:ident, $default:expr) => {
        impl Default for $name {
            fn default() -> $name {
                $default
            }
        }
    };
}

macro_rules! impl_property {
    ($computed_values_type:ty, $name:ident, $inherits_automatically:expr) => {
        impl ::property_macros::Property<$computed_values_type> for $name {
            fn inherits_automatically() -> bool {
                $inherits_automatically
            }

            fn compute(&self, _v: &$computed_values_type) -> Self {
                self.clone()
            }
        }
    };
}

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

    use cssparser::RGBA;
    use parsers::Parse;

    #[test]
    fn check_generated_property() {
        make_property! {
            (),
            Foo,
            default: Def,
            inherits_automatically: true,

            identifiers:
            "def" => Def,
            "bar" => Bar,
            "baz" => Baz,
        }

        assert_eq!(<Foo as Default>::default(), Foo::Def);
        assert_eq!(<Foo as Property<()>>::inherits_automatically(), true);
        assert!(<Foo as Parse>::parse("blargh", ()).is_err());
        assert_eq!(<Foo as Parse>::parse("bar", ()), Ok(Foo::Bar));

        make_property! {
            (),
            Bar,
            default: "bar".to_string(),
            inherits_automatically: true,
            newtype_from_str: String
        }

        assert_eq!(<Bar as Default>::default(), Bar("bar".to_string()));
        assert_eq!(<Bar as Property<()>>::inherits_automatically(), true);
        assert_eq!(
            <Bar as Parse>::parse("test", ()),
            Ok(Bar("test".to_string()))
        );

        make_property! {
            (),
            Baz,
            default: 42f64,
            inherits_automatically: true,
            newtype_from_str: f64
        }

        assert_eq!(<Baz as Default>::default(), Baz(42f64));
        assert_eq!(<Baz as Property<()>>::inherits_automatically(), true);
        assert_eq!(<Baz as Parse>::parse("42", ()), Ok(Baz(42f64)));
    }

    #[test]
    fn check_compute() {
        make_property! {
            RGBA,
            AddColor,
            default: RGBA::new(1, 1, 1, 1),
            newtype_parse: RGBA,
            parse_data_type: (),
            property_impl: {
                impl Property<RGBA> for AddColor {
                    fn inherits_automatically() -> bool {
                        true
                    }

                    fn compute(&self, v: &RGBA) -> Self {
                        AddColor(RGBA::new(
                            self.0.red + v.red,
                            self.0.green + v.green,
                            self.0.blue + v.blue,
                            self.0.alpha + v.alpha
                        ))
                    }
                }
            }
        }

        let color = RGBA::new(1, 1, 1, 1);
        let a = <AddColor as Parse>::parse("#02030405", ()).unwrap();
        let b = a.compute(&color);

        assert_eq!(b, AddColor(RGBA::new(3, 4, 5, 6)));
    }
}
<commit_msg>make_property!() - Use a cssparser<commit_after>pub trait Property<T> {
    fn inherits_automatically() -> bool;
    fn compute(&self, &T) -> Self;
}

/// Generates a property definition that simply parses strings to enum variants
/// or to a tuple struct of the given type.
///
/// For example, the SVG spec defines the `stroke-linejoin` property
/// to have possible values `miter | round | bevel | inherit`, with a default
/// of `miter`.  We can define the property like this:
///
/// ```ignore
/// make_property!(
/// StrokeLinejoin,
/// default: Miter,
///
/// "miter" => Miter,
/// "round" => Round,
/// "bevel" => Bevel,
/// );
/// ```
///
/// The macro will generate a `StrokeLinejoin` enum with the provided
/// variants.  It will generate an `impl Default for StrokeLinejoin`
/// with the provided `default:` value.  Finally, it will generate an
/// `impl Parse for StrokeLinejoin`, from `parsers::Parse`, where
/// `type Data = ()` and `type Err = AttributeError`.
#[macro_export]
macro_rules! make_property {
    ($computed_values_type: ty,
     $name: ident,
     default: $default: ident,
     inherits_automatically: $inherits_automatically: expr,
     identifiers:
     $($str_prop: expr => $variant: ident,)+
    ) => {
        #[derive(Debug, Copy, Clone, PartialEq)]
        pub enum $name {
            $($variant),+
        }

        impl_default!($name, $name::$default);
        impl_property!($computed_values_type, $name, $inherits_automatically);

        impl ::parsers::Parse for $name {
            type Data = ();
            type Err = ::error::AttributeError;

            fn parse(s: &str, _: Self::Data) -> Result<$name, ::error::AttributeError> {
                let mut input = ::cssparser::ParserInput::new(s);
                let mut parser = ::cssparser::Parser::new(&mut input);
                let loc = parser.current_source_location();

                parser
                    .expect_ident()
                    .and_then(|cow| match cow.as_ref() {
                        $($str_prop => Ok($name::$variant),)+

                            _ => Err(
                                loc.new_basic_unexpected_token_error(
                                    ::cssparser::Token::Ident(::cssparser::CowRcStr::from(
                                        cow.as_ref().to_string(),
                                    ))),
                            ),
                    })
                    .map_err(|_| {
                        ::error::AttributeError::Parse(::parsers::ParseError::new(
                            "unexpected value",
                        ))
                    })
            }
        }
    };

    ($computed_values_type: ty,
     $name: ident,
     default: $default: expr,
     inherits_automatically: $inherits_automatically: expr,
     newtype_from_str: $type: ty
    ) => {
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name(pub $type);

        impl_default!($name, $name($default));
        impl_property!($computed_values_type, $name, $inherits_automatically);

        impl ::parsers::Parse for $name {
            type Data = ();
            type Err = ::error::AttributeError;

            fn parse(s: &str, _: Self::Data) -> Result<$name, ::error::AttributeError> {
                s.trim()
                    .parse()
                    .map(|val| $name(val))
                    .map_err(|_| ::error::AttributeError::from(
                        ::parsers::ParseError::new("parse error")
                    ))
            }
        }
    };

    ($computed_values_type: ty,
     $name: ident,
     default: $default: expr,
     inherits_automatically: $inherits_automatically: expr,
     newtype_parse: $type: ty,
     parse_data_type: $parse_data_type: ty
    ) => {
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name(pub $type);

        impl_default!($name, $name($default));

        impl ::property_macros::Property<$computed_values_type> for $name {
            fn inherits_automatically() -> bool {
                $inherits_automatically
            }

            fn compute(&self, _v: &$computed_values_type) -> Self {
                self.clone()
            }
        }

        impl ::parsers::Parse for $name {
            type Data = $parse_data_type;
            type Err = ::error::AttributeError;

            fn parse(s: &str, d: Self::Data) -> Result<$name, ::error::AttributeError> {
                Ok($name(<$type as ::parsers::Parse>::parse(s, d)?))
            }
        }
    };

    ($computed_values_type: ty,
     $name: ident,
     default: $default: expr,
     newtype_parse: $type: ty,
     parse_data_type: $parse_data_type: ty,
     property_impl: { $prop: item }
    ) => {
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name(pub $type);

        impl_default!($name, $name($default));

        $prop

        impl ::parsers::Parse for $name {
            type Data = $parse_data_type;
            type Err = ::error::AttributeError;

            fn parse(s: &str, d: Self::Data) -> Result<$name, ::error::AttributeError> {
                Ok($name(<$type as ::parsers::Parse>::parse(s, d)?))
            }
        }
    };

    ($computed_values_type: ty,
     $name: ident,
     default: $default: expr,
     newtype: $type: ty,
     property_impl: { $prop: item },
     parse_impl: { $parse: item }
    ) => {
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name(pub $type);

        impl_default!($name, $name($default));

        $prop

        $parse
    };

    ($computed_values_type: ty,
     $name: ident,
     inherits_automatically: $inherits_automatically: expr,
     fields: {
       $($field_name: ident : $field_type: ty, default: $field_default : expr,)+
     }
     parse_impl: { $parse: item }
    ) => {
        #[derive(Debug, Clone, PartialEq)]
        pub struct $name {
            $(pub $field_name: $field_type),+
        }

        impl_default!($name, $name { $($field_name: $field_default),+ });
        impl_property!($computed_values_type, $name, $inherits_automatically);

        $parse
    };
}

macro_rules! impl_default {
    ($name:ident, $default:expr) => {
        impl Default for $name {
            fn default() -> $name {
                $default
            }
        }
    };
}

macro_rules! impl_property {
    ($computed_values_type:ty, $name:ident, $inherits_automatically:expr) => {
        impl ::property_macros::Property<$computed_values_type> for $name {
            fn inherits_automatically() -> bool {
                $inherits_automatically
            }

            fn compute(&self, _v: &$computed_values_type) -> Self {
                self.clone()
            }
        }
    };
}

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

    use cssparser::RGBA;
    use parsers::Parse;

    #[test]
    fn check_generated_property() {
        make_property! {
            (),
            Foo,
            default: Def,
            inherits_automatically: true,

            identifiers:
            "def" => Def,
            "bar" => Bar,
            "baz" => Baz,
        }

        assert_eq!(<Foo as Default>::default(), Foo::Def);
        assert_eq!(<Foo as Property<()>>::inherits_automatically(), true);
        assert!(<Foo as Parse>::parse("blargh", ()).is_err());
        assert_eq!(<Foo as Parse>::parse("bar", ()), Ok(Foo::Bar));

        make_property! {
            (),
            Bar,
            default: "bar".to_string(),
            inherits_automatically: true,
            newtype_from_str: String
        }

        assert_eq!(<Bar as Default>::default(), Bar("bar".to_string()));
        assert_eq!(<Bar as Property<()>>::inherits_automatically(), true);
        assert_eq!(
            <Bar as Parse>::parse("test", ()),
            Ok(Bar("test".to_string()))
        );

        make_property! {
            (),
            Baz,
            default: 42f64,
            inherits_automatically: true,
            newtype_from_str: f64
        }

        assert_eq!(<Baz as Default>::default(), Baz(42f64));
        assert_eq!(<Baz as Property<()>>::inherits_automatically(), true);
        assert_eq!(<Baz as Parse>::parse("42", ()), Ok(Baz(42f64)));
    }

    #[test]
    fn check_compute() {
        make_property! {
            RGBA,
            AddColor,
            default: RGBA::new(1, 1, 1, 1),
            newtype_parse: RGBA,
            parse_data_type: (),
            property_impl: {
                impl Property<RGBA> for AddColor {
                    fn inherits_automatically() -> bool {
                        true
                    }

                    fn compute(&self, v: &RGBA) -> Self {
                        AddColor(RGBA::new(
                            self.0.red + v.red,
                            self.0.green + v.green,
                            self.0.blue + v.blue,
                            self.0.alpha + v.alpha
                        ))
                    }
                }
            }
        }

        let color = RGBA::new(1, 1, 1, 1);
        let a = <AddColor as Parse>::parse("#02030405", ()).unwrap();
        let b = a.compute(&color);

        assert_eq!(b, AddColor(RGBA::new(3, 4, 5, 6)));
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Structured representation of a plugin's features and capabilities.

use std::path::PathBuf;

use syntax::SyntaxDefinition;

// optional environment variable for debug plugin executables
#[cfg(not(target_os = "fuchsia"))]
static PLUGIN_DIR: &'static str = "XI_PLUGIN_DIR";

// example plugins. Eventually these should be loaded from disk.
#[cfg(not(target_os = "fuchsia"))]
pub fn debug_plugins() -> Vec<PluginDescription> {
    use std::env;
    use self::PluginActivation::*;
    use self::PluginScope::*;
    let plugin_dir = match env::var(PLUGIN_DIR).map(PathBuf::from) {
        Ok(p) => p,
        Err(_) => env::current_exe().unwrap().parent().unwrap().to_owned(),
    };
    print_err!("looking for debug plugins in {:?}", plugin_dir);

    let make_path = |p: &str| -> PathBuf {
        let mut pb = plugin_dir.clone();
        pb.push(p);
        pb
    };

    vec![
        PluginDescription::new("syntect", "0.0", BufferLocal, make_path("xi-syntect-plugin"),
        vec![Autorun]),
        PluginDescription::new("braces", "0.0", BufferLocal, make_path("bracket_example.py"),
        Vec::new()),
        PluginDescription::new("spellcheck", "0.0", BufferLocal, make_path("spellcheck.py"),
        Vec::new()),
        PluginDescription::new("shouty", "0.0", BufferLocal, make_path("shouty.py"),
        Vec::new()),
    ].iter()
        .filter(|desc|{
            if !desc.exec_path.exists() {
                print_err!("missing plugin {} at {:?}", desc.name, desc.exec_path);
                false
            } else {
                true
            }
        })
        .map(|desc| desc.to_owned())
        .collect::<Vec<_>>()
}

#[cfg(target_os = "fuchsia")]
pub fn debug_plugins() -> Vec<PluginDescription> {
    Vec::new()
}

/// Describes attributes and capabilities of a plugin.
///
/// Note: - these will eventually be loaded from manifest files.
#[derive(Debug, Clone)]
pub struct PluginDescription {
    pub name: String,
    pub version: String,
    pub scope: PluginScope,
    // more metadata ...
    /// path to plugin executable
    pub exec_path: PathBuf,
    /// Events that cause this plugin to run
    pub activations: Vec<PluginActivation>,
}

/// `PluginActivation`s represent events that trigger running a plugin.
#[derive(Debug, Clone)]
pub enum PluginActivation {
    /// Always run this plugin, when available.
    Autorun,
    /// Run this plugin if the provided SyntaxDefinition is active.
    #[allow(dead_code)]
    OnSyntax(SyntaxDefinition),
    /// Run this plugin in response to a given command.
    #[allow(dead_code)]
    OnCommand,
}

#[derive(Debug, Clone)]
/// Describes the scope of events a plugin receives.
pub enum PluginScope {
    /// The plugin receives events from multiple buffers.
    Global,
    /// The plugin receives events for a single buffer.
    BufferLocal,
    /// The plugin is launched in response to a command, and receives no
    /// further updates.
    SingleInvocation,
}

impl PluginDescription {
    #[cfg(not(target_os = "fuchsia"))]
    fn new<S, P>(name: S, version: S, scope: PluginScope, exec_path: P,
                 activations: Vec<PluginActivation>) -> Self
        where S: Into<String>, P: Into<PathBuf>
    {
        PluginDescription {
            name: name.into(),
            scope: scope,
            version: version.into(),
            exec_path: exec_path.into(),
            activations: activations,
        }
    }

    /// Returns `true` if this plugin is globally scoped, else `false`.
    pub fn is_global(&self) -> bool {
        match self.scope {
            PluginScope::Global => true,
            _ => false,
        }
    }
}
<commit_msg>First pass of plugin command types<commit_after>// Copyright 2017 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Structured representation of a plugin's features and capabilities.

use std::path::PathBuf;

use serde_json::{self, Value};
use serde::Serialize;

use syntax::SyntaxDefinition;

// optional environment variable for debug plugin executables
#[cfg(not(target_os = "fuchsia"))]
static PLUGIN_DIR: &'static str = "XI_PLUGIN_DIR";

// example plugins. Eventually these should be loaded from disk.
#[cfg(not(target_os = "fuchsia"))]
pub fn debug_plugins() -> Vec<PluginDescription> {
    use std::env;
    use self::PluginActivation::*;
    use self::PluginScope::*;
    let plugin_dir = match env::var(PLUGIN_DIR).map(PathBuf::from) {
        Ok(p) => p,
        Err(_) => env::current_exe().unwrap().parent().unwrap().to_owned(),
    };
    print_err!("looking for debug plugins in {:?}", plugin_dir);

    let make_path = |p: &str| -> PathBuf {
        let mut pb = plugin_dir.clone();
        pb.push(p);
        pb
    };

    vec![
        PluginDescription::new("syntect", "0.0", BufferLocal, make_path("xi-syntect-plugin"),
        vec![Autorun], Vec::new()),
        PluginDescription::new("braces", "0.0", BufferLocal, make_path("bracket_example.py"),
        Vec::new(), Vec::new()),
        PluginDescription::new("spellcheck", "0.0", BufferLocal, make_path("spellcheck.py"),
        Vec::new(), Vec::new()),
        PluginDescription::new("shouty", "0.0", BufferLocal, make_path("shouty.py"),
        Vec::new(), Vec::new()),
        PluginDescription::new("cmd_test", "0.0", BufferLocal, make_path("cmd_test.py"),
        Vec::new(), vec![Command::new(
            "Count Lines", "Print the number of lines in the active buffer",
            PlaceholderRpc::new("cmd_test.count_lines", None), None)]),
    ].iter()
        .filter(|desc|{
            if !desc.exec_path.exists() {
                print_err!("missing plugin {} at {:?}", desc.name, desc.exec_path);
                false
            } else {
                true
            }
        })
        .map(|desc| desc.to_owned())
        .collect::<Vec<_>>()
}

#[cfg(target_os = "fuchsia")]
pub fn debug_plugins() -> Vec<PluginDescription> {
    Vec::new()
}

/// Describes attributes and capabilities of a plugin.
///
/// Note: - these will eventually be loaded from manifest files.
#[derive(Debug, Clone)]
pub struct PluginDescription {
    pub name: String,
    pub version: String,
    pub scope: PluginScope,
    // more metadata ...
    /// path to plugin executable
    pub exec_path: PathBuf,
    /// Events that cause this plugin to run
    pub activations: Vec<PluginActivation>,
    pub commands: Vec<Command>,
}

/// `PluginActivation`s represent events that trigger running a plugin.
#[derive(Debug, Clone)]
pub enum PluginActivation {
    /// Always run this plugin, when available.
    Autorun,
    /// Run this plugin if the provided SyntaxDefinition is active.
    #[allow(dead_code)]
    OnSyntax(SyntaxDefinition),
    /// Run this plugin in response to a given command.
    #[allow(dead_code)]
    OnCommand,
}

#[derive(Debug, Clone)]
/// Describes the scope of events a plugin receives.
pub enum PluginScope {
    /// The plugin receives events from multiple buffers.
    Global,
    /// The plugin receives events for a single buffer.
    BufferLocal,
    /// The plugin is launched in response to a command, and receives no
    /// further updates.
    SingleInvocation,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Command {
    pub title: String,
    pub description: String,
    pub rpc_cmd: PlaceholderRpc,
    pub args: Vec<CommandArgument>,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CommandArgument {
    pub tag: String,
    pub arg_type: ArgumentType,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub options: Option<Vec<ArgumentOption>>,
}

#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ArgumentType {
    Number, Int, PosInt, Bool, String, Choice,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ArgumentOption {
    pub title: String,
    pub value: Value,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PlaceholderRpc {
    pub method: String,
    pub params: Value,
}

impl Command {
    pub fn new<S, V>(title: S, description: S, rpc_cmd: PlaceholderRpc, args: V) -> Self
    where S: AsRef<str>,
          V: Into<Option<Vec<CommandArgument>>> {
        let title = title.as_ref().to_owned();
        let description = description.as_ref().to_owned();
        let args = args.into().unwrap_or(Vec::new());
        Command { title, description, rpc_cmd, args }
    }
}

impl CommandArgument {
    pub fn new<S: AsRef<str>>(tag: S, arg_type: ArgumentType,
                              options: Option<Vec<ArgumentOption>>) -> Self {
        let tag = tag.as_ref().to_owned();
        CommandArgument { tag, arg_type, options }
    }
}

impl ArgumentOption {
    pub fn new<S: AsRef<str>, V: Serialize>(title: S, value: V) -> Self {
        let title = title.as_ref().to_owned();
        let value = serde_json::to_value(value).unwrap();
        ArgumentOption { title, value }
    }
}

impl PlaceholderRpc {
    pub fn new<S, V>(method: S, params: V) -> Self
        where S: AsRef<str>,
              V: Into<Option<Value>> {
        PlaceholderRpc {
            method: method.as_ref().to_owned(),
            params: params.into().unwrap_or(json!({})),
        }
    }
}

impl PluginDescription {
    #[cfg(not(target_os = "fuchsia"))]
    fn new<S, P>(name: S, version: S, scope: PluginScope, exec_path: P,
                 activations: Vec<PluginActivation>, commands: Vec<Command>) -> Self
        where S: Into<String>, P: Into<PathBuf>
    {
        PluginDescription {
            name: name.into(),
            scope: scope,
            version: version.into(),
            exec_path: exec_path.into(),
            activations: activations,
            commands: commands,
        }
    }

    /// Returns `true` if this plugin is globally scoped, else `false`.
    pub fn is_global(&self) -> bool {
        match self.scope {
            PluginScope::Global => true,
            _ => false,
        }
    }
}

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

    #[test]
    fn test_serde_command() {
        let json = r#"
        {
        "title": "Test Command",
        "description": "Passes the current test",
        "rpc_cmd": {
            "method": "test.cmd",
            "params": {
                "this_works": "{this_works}",
                "a_choice": "{choice_tag}"
            }
        },
        "args": [
            {"tag": "this_works", "arg_type": "Bool"},
            {
                "tag": "choice_tag",
                "arg_type": "Choice",
                "options": [
                    {"title": "First Choice", "value": 5},
                    {"title": "Second Choice", "value": 10}
                ]
            }
        ]
        }
        "#;

        let command: Command = serde_json::from_str(&json).unwrap();
        assert_eq!(command.title, "Test Command");
        assert_eq!(command.args[0].arg_type, ArgumentType::Bool);
        assert_eq!(command.rpc_cmd.params["this_works"], "{this_works}");
        assert_eq!(command.args[1].options.clone().unwrap()[1].value, json!(10));
    }
}
<|endoftext|>


<commit_before>//https://rust-lang.github.io/book/ch04-04-slices.html

fn first_word(s: &String) -> usize {

    // Since we need to go through the String element by element, and
    // check if a value is a space, we will convert our String to an
    // array of bytes, using the `.as_bytes()` method.
    let bytes = s.as_bytes();

    // We discussed using the iter() method with for in Chapter 3.7. Here,
    // we’re adding another method: enumerate(). While iter() returns each
    // element, enumerate() modifies the result of iter(), and returns a
    // tuple instead. The first element of the tuple is the index, and the
    // second element is a reference to the element itself. This is a bit
    // nicer than calculating the index ourselves.
    //
    // Since it’s a tuple, we can use patterns, just like elsewhere in Rust.
    // So we match against the tuple with i for the index, and &byte for
    // the byte itself.
    //for (i, &byte) in bytes.iter().enumerate() {
    let heart = '❤';//lol wait, outdated doc? https://doc.rust-lang.org/std/primitive.char.html#representation
    println!("{}", heart);//yup, looks like it - rust nightly can do this.
    //let heart2 = '❤'; //oh, wait - nevermind! I guess this looks the same but it's different!!! - aka this errors!
    for (i, chr) in s.chars().enumerate() {

        //println!("Processing {} {}",i,byte);
        println!("Processing {} {}",i,chr);
        // 32 is the value of a space in UTF-8
        //if chr == 0x20 {
        if chr == '\u{0020}' {

            // We found a space! Return this position.
            return i;
        }
    }

    // If we got here, we didn’t find a space, so this whole thing must be a
    // word. So return the length.
    s.len()
}

fn main() {
    //ok, apparently 0x20 isn't part of any unicode char seen as utf-8 as far as i tested until
    //here(not all):
    //http://www.utf8-chartable.de/unicode-utf8-table.pl?start=121856&number=1024&utf8=0x
    //about to search here next(as soon as internet is back):
    //http://www.fileformat.info/search/search.htm?q=0x20
    //ok this explains it: http://www.joelonsoftware.com/articles/Unicode.html
    //since high bits are always at least 10, there won't be any 0x20 dangling around as part of
    //the utf8 represented unicode - except 0x20 itself :D
    let s=String::from("❤Ԡ123԰4Ġ❤we❤ll❤ok");//ok this last ❤ is one codepoint!!!
    //❤ is two unicode code points which is why you'll see a blank after it!
    //src: https://doc.rust-lang.org/std/primitive.char.html
    let word = first_word(&s);
    // word is now totally invalid! There’s no more word here.
    println!("{}", '\u{2764}');//since this is ... good enough for the heart!
    println!("{}", '\u{fe0f}');//why is this needed? well, ok: https://www.fileformat.info/info/unicode/char/2764/index.htm variation selector
    println!("{}",word);
    println!("heart.len {}",String::from("❤").len());//6
}
<commit_msg>unicode via \u{}<commit_after>//https://rust-lang.github.io/book/ch04-04-slices.html

fn first_word(s: &String) -> usize {

    // Since we need to go through the String element by element, and
    // check if a value is a space, we will convert our String to an
    // array of bytes, using the `.as_bytes()` method.
    let bytes = s.as_bytes();

    // We discussed using the iter() method with for in Chapter 3.7. Here,
    // we’re adding another method: enumerate(). While iter() returns each
    // element, enumerate() modifies the result of iter(), and returns a
    // tuple instead. The first element of the tuple is the index, and the
    // second element is a reference to the element itself. This is a bit
    // nicer than calculating the index ourselves.
    //
    // Since it’s a tuple, we can use patterns, just like elsewhere in Rust.
    // So we match against the tuple with i for the index, and &byte for
    // the byte itself.
    //for (i, &byte) in bytes.iter().enumerate() {
    let heart = '❤';//lol wait, outdated doc? https://doc.rust-lang.org/std/primitive.char.html#representation
    println!("{}", heart);//yup, looks like it - rust nightly can do this.
    //let heart2 = '❤'; //oh, wait - nevermind! I guess this looks the same but it's different!!! - aka this errors!
    for (i, chr) in s.chars().enumerate() {

        //println!("Processing {} {}",i,byte);
        println!("Processing {} {}",i,chr);
        // 32 is the value of a space in UTF-8
        //if chr == 0x20 {
        if chr == '\u{0020}' {

            // We found a space! Return this position.
            return i;
        }
    }

    // If we got here, we didn’t find a space, so this whole thing must be a
    // word. So return the length.
    s.len()
}

fn main() {
    //ok, apparently 0x20 isn't part of any unicode char seen as utf-8 as far as i tested until
    //here(not all):
    //http://www.utf8-chartable.de/unicode-utf8-table.pl?start=121856&number=1024&utf8=0x
    //about to search here next(as soon as internet is back):
    //http://www.fileformat.info/search/search.htm?q=0x20
    //ok this explains it: http://www.joelonsoftware.com/articles/Unicode.html
    //since high bits are always at least 10, there won't be any 0x20 dangling around as part of
    //the utf8 represented unicode - except 0x20 itself :D
    let s=String::from("❤Ԡ12\u{14}3԰4Ġ❤we❤ll❤ok");//ok this last ❤ is one codepoint!!!
    //❤ is two unicode code points which is why you'll see a blank after it!
    //src: https://doc.rust-lang.org/std/primitive.char.html
    let word = first_word(&s);
    // word is now totally invalid! There’s no more word here.
    println!("{}", '\u{2764}');//since this is ... good enough for the heart!
    println!("{}", '\u{fe0f}');//why is this needed? well, ok: https://www.fileformat.info/info/unicode/char/2764/index.htm variation selector
    println!("{}",word);
    println!("heart.len {}",String::from("❤").len());//6
}
<|endoftext|>


<commit_before>//! RA Proc Macro Server
//!
//! This library is able to call compiled Rust custom derive dynamic libraries on arbitrary code.
//! The general idea here is based on <https://github.com/fedochet/rust-proc-macro-expander>.
//!
//! But we adapt it to better fit RA needs:
//!
//! * We use `tt` for proc-macro `TokenStream` server, it is easier to manipulate and interact with
//!   RA than `proc-macro2` token stream.
//! * By **copying** the whole rustc `lib_proc_macro` code, we are able to build this with `stable`
//!   rustc rather than `unstable`. (Although in general ABI compatibility is still an issue)…

#![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)]
#![cfg_attr(
    feature = "sysroot-abi",
    feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span)
)]
#![allow(unreachable_pub)]

mod dylib;
mod abis;

use std::{
    collections::{hash_map::Entry, HashMap},
    env,
    ffi::OsString,
    fs,
    path::{Path, PathBuf},
    time::SystemTime,
};

use proc_macro_api::{
    msg::{ExpandMacro, FlatTree, PanicMessage},
    ProcMacroKind,
};

#[derive(Default)]
pub(crate) struct ProcMacroSrv {
    expanders: HashMap<(PathBuf, SystemTime), dylib::Expander>,
}

impl ProcMacroSrv {
    pub fn expand(&mut self, task: ExpandMacro) -> Result<FlatTree, PanicMessage> {
        let expander = self.expander(task.lib.as_ref()).map_err(|err| {
            debug_assert!(false, "should list macros before asking to expand");
            PanicMessage(format!("failed to load macro: {}", err))
        })?;

        let prev_env = EnvSnapshot::new();
        for (k, v) in &task.env {
            env::set_var(k, v);
        }
        let prev_working_dir = match task.current_dir {
            Some(dir) => {
                let prev_working_dir = std::env::current_dir().ok();
                if let Err(err) = std::env::set_current_dir(&dir) {
                    eprintln!("Failed to set the current working dir to {}. Error: {:?}", dir, err)
                }
                prev_working_dir
            }
            None => None,
        };

        let macro_body = task.macro_body.to_subtree();
        let attributes = task.attributes.map(|it| it.to_subtree());
        // FIXME: replace this with std's scoped threads once they stabilize
        // (then remove dependency on crossbeam)
        let result = crossbeam::scope(|s| {
            let res = s
                .spawn(|_| {
                    expander
                        .expand(&task.macro_name, &macro_body, attributes.as_ref())
                        .map(|it| FlatTree::new(&it))
                })
                .join();

            match res {
                Ok(res) => res,
                Err(e) => std::panic::resume_unwind(e),
            }
        });
        let result = match result {
            Ok(result) => result,
            Err(e) => std::panic::resume_unwind(e),
        };

        prev_env.rollback();

        if let Some(dir) = prev_working_dir {
            if let Err(err) = std::env::set_current_dir(&dir) {
                eprintln!(
                    "Failed to set the current working dir to {}. Error: {:?}",
                    dir.display(),
                    err
                )
            }
        }

        result.map_err(PanicMessage)
    }

    pub(crate) fn list_macros(
        &mut self,
        dylib_path: &Path,
    ) -> Result<Vec<(String, ProcMacroKind)>, String> {
        let expander = self.expander(dylib_path)?;
        Ok(expander.list_macros())
    }

    fn expander(&mut self, path: &Path) -> Result<&dylib::Expander, String> {
        let time = fs::metadata(path).and_then(|it| it.modified()).map_err(|err| {
            format!("Failed to get file metadata for {}: {:?}", path.display(), err)
        })?;

        Ok(match self.expanders.entry((path.to_path_buf(), time)) {
            Entry::Vacant(v) => v.insert(dylib::Expander::new(path).map_err(|err| {
                format!("Cannot create expander for {}: {:?}", path.display(), err)
            })?),
            Entry::Occupied(e) => e.into_mut(),
        })
    }
}

struct EnvSnapshot {
    vars: HashMap<OsString, OsString>,
}

impl EnvSnapshot {
    fn new() -> EnvSnapshot {
        EnvSnapshot { vars: env::vars_os().collect() }
    }

    fn rollback(self) {
        let mut old_vars = self.vars;
        for (name, value) in env::vars_os() {
            let old_value = old_vars.remove(&name);
            if old_value != Some(value) {
                match old_value {
                    None => env::remove_var(name),
                    Some(old_value) => env::set_var(name, old_value),
                }
            }
        }
        for (name, old_value) in old_vars {
            env::set_var(name, old_value)
        }
    }
}

pub mod cli;

#[cfg(test)]
mod tests;
<commit_msg>Use large stack on expander thread<commit_after>//! RA Proc Macro Server
//!
//! This library is able to call compiled Rust custom derive dynamic libraries on arbitrary code.
//! The general idea here is based on <https://github.com/fedochet/rust-proc-macro-expander>.
//!
//! But we adapt it to better fit RA needs:
//!
//! * We use `tt` for proc-macro `TokenStream` server, it is easier to manipulate and interact with
//!   RA than `proc-macro2` token stream.
//! * By **copying** the whole rustc `lib_proc_macro` code, we are able to build this with `stable`
//!   rustc rather than `unstable`. (Although in general ABI compatibility is still an issue)…

#![warn(rust_2018_idioms, unused_lifetimes, semicolon_in_expressions_from_macros)]
#![cfg_attr(
    feature = "sysroot-abi",
    feature(proc_macro_internals, proc_macro_diagnostic, proc_macro_span)
)]
#![allow(unreachable_pub)]

mod dylib;
mod abis;

use std::{
    collections::{hash_map::Entry, HashMap},
    env,
    ffi::OsString,
    fs,
    path::{Path, PathBuf},
    time::SystemTime,
};

use proc_macro_api::{
    msg::{ExpandMacro, FlatTree, PanicMessage},
    ProcMacroKind,
};

#[derive(Default)]
pub(crate) struct ProcMacroSrv {
    expanders: HashMap<(PathBuf, SystemTime), dylib::Expander>,
}

const EXPANDER_STACK_SIZE: usize = 8 * 1024 * 1024;

impl ProcMacroSrv {
    pub fn expand(&mut self, task: ExpandMacro) -> Result<FlatTree, PanicMessage> {
        let expander = self.expander(task.lib.as_ref()).map_err(|err| {
            debug_assert!(false, "should list macros before asking to expand");
            PanicMessage(format!("failed to load macro: {}", err))
        })?;

        let prev_env = EnvSnapshot::new();
        for (k, v) in &task.env {
            env::set_var(k, v);
        }
        let prev_working_dir = match task.current_dir {
            Some(dir) => {
                let prev_working_dir = std::env::current_dir().ok();
                if let Err(err) = std::env::set_current_dir(&dir) {
                    eprintln!("Failed to set the current working dir to {}. Error: {:?}", dir, err)
                }
                prev_working_dir
            }
            None => None,
        };

        let macro_body = task.macro_body.to_subtree();
        let attributes = task.attributes.map(|it| it.to_subtree());
        // FIXME: replace this with std's scoped threads once they stabilize
        // (then remove dependency on crossbeam)
        let result = crossbeam::scope(|s| {
            let res = match s
                .builder()
                .stack_size(EXPANDER_STACK_SIZE)
                .name(task.macro_name.clone())
                .spawn(|_| {
                    expander
                        .expand(&task.macro_name, &macro_body, attributes.as_ref())
                        .map(|it| FlatTree::new(&it))
                }) {
                Ok(handle) => handle.join(),
                Err(e) => std::panic::resume_unwind(Box::new(e)),
            };

            match res {
                Ok(res) => res,
                Err(e) => std::panic::resume_unwind(e),
            }
        });
        let result = match result {
            Ok(result) => result,
            Err(e) => std::panic::resume_unwind(e),
        };

        prev_env.rollback();

        if let Some(dir) = prev_working_dir {
            if let Err(err) = std::env::set_current_dir(&dir) {
                eprintln!(
                    "Failed to set the current working dir to {}. Error: {:?}",
                    dir.display(),
                    err
                )
            }
        }

        result.map_err(PanicMessage)
    }

    pub(crate) fn list_macros(
        &mut self,
        dylib_path: &Path,
    ) -> Result<Vec<(String, ProcMacroKind)>, String> {
        let expander = self.expander(dylib_path)?;
        Ok(expander.list_macros())
    }

    fn expander(&mut self, path: &Path) -> Result<&dylib::Expander, String> {
        let time = fs::metadata(path).and_then(|it| it.modified()).map_err(|err| {
            format!("Failed to get file metadata for {}: {:?}", path.display(), err)
        })?;

        Ok(match self.expanders.entry((path.to_path_buf(), time)) {
            Entry::Vacant(v) => v.insert(dylib::Expander::new(path).map_err(|err| {
                format!("Cannot create expander for {}: {:?}", path.display(), err)
            })?),
            Entry::Occupied(e) => e.into_mut(),
        })
    }
}

struct EnvSnapshot {
    vars: HashMap<OsString, OsString>,
}

impl EnvSnapshot {
    fn new() -> EnvSnapshot {
        EnvSnapshot { vars: env::vars_os().collect() }
    }

    fn rollback(self) {
        let mut old_vars = self.vars;
        for (name, value) in env::vars_os() {
            let old_value = old_vars.remove(&name);
            if old_value != Some(value) {
                match old_value {
                    None => env::remove_var(name),
                    Some(old_value) => env::set_var(name, old_value),
                }
            }
        }
        for (name, old_value) in old_vars {
            env::set_var(name, old_value)
        }
    }
}

pub mod cli;

#[cfg(test)]
mod tests;
<|endoftext|>


<commit_before>#![allow(dead_code, unused_must_use)]

#[cfg(feature = "sqlite")]
type Backend = ::diesel::sqlite::Sqlite;
#[cfg(feature = "mysql")]
type Backend = ::diesel::mysql::Mysql;
#[cfg(feature = "postgres")]
type Backend = ::diesel::pg::Pg;

#[test]
fn simple_belongs_to() {
    use diesel::*;

    table! {
        users {
            id -> Integer,
            name -> Text,
        }
    }

    table! {
        posts {
            id -> Integer,
            user_id -> Integer,
            title -> Text,
        }
    }

    #[derive(Identifiable)]
    pub struct User {
        id: i32,
        name: String
    }

    #[derive(Associations, Identifiable)]
    #[belongs_to(User)]
    pub struct Post {
        id: i32,
        user_id: i32,
        title: String,
    }

    let _can_join_tables = posts::table.inner_join(users::table)
        .select((users::id, users::name))
        .filter(posts::id.eq(1)
                .and(posts::user_id.eq(2))
                .and(posts::title.eq("Bar")));

    let _can_reverse_join_tables = users::table.inner_join(posts::table)
        .select((posts::id, posts::user_id, posts::title))
        .filter(users::id.eq(1)
                .and(users::name.eq("Sean")));

    let t = User { id: 42, name: "Sean".into() };

    let belong_to = Post::belonging_to(&t);
    let filter = posts::table.filter(posts::user_id.eq(42));

    assert_eq!(
        debug_sql::<Backend, _>(&belong_to),
        debug_sql::<Backend, _>(&filter)
    );
}

#[test]
fn custom_foreign_key() {
    use diesel::*;

    table! {
        users {
            id -> Integer,
            name -> Text,
        }
    }

    table! {
        posts {
            id -> Integer,
            belongs_to_user -> Integer,
            title -> Text,
        }
    }

    #[derive(Identifiable)]
    pub struct User {
        id: i32,
        name: String
    }

    #[derive(Associations, Identifiable)]
    #[belongs_to(User, foreign_key = "belongs_to_user")]
    pub struct Post {
        id: i32,
        belongs_to_user: i32,
        title: String,
    }

    let _can_join_tables = posts::table.inner_join(users::table)
        .select((users::id, users::name))
        .filter(posts::id.eq(1)
            .and(posts::belongs_to_user.eq(2))
                .and(posts::title.eq("Bar")));

    let _can_reverse_join_tables = users::table.inner_join(posts::table)
        .select((posts::id, posts::belongs_to_user, posts::title))
        .filter(users::id.eq(1)
                .and(users::name.eq("Sean")));

    let t = User { id: 42, name: "Sean".into() };

    let belong_to = Post::belonging_to(&t);
    let filter = posts::table.filter(posts::belongs_to_user.eq(42));

    assert_eq!(
        debug_sql::<Backend, _>(&belong_to),
        debug_sql::<Backend, _>(&filter)
    );
}

#[test]
fn self_referential() {
    use diesel::*;

    table! {
        trees {
            id -> Integer,
            parent_id -> Nullable<Integer>,
        }
    }

    #[derive(Associations, Identifiable)]
    #[belongs_to(Tree, foreign_key = "parent_id")]
    pub struct Tree {
        id: i32,
        parent_id: Option<i32>,
    }
    let t = Tree { id: 42, parent_id: None };

    let belong_to = Tree::belonging_to(&t);
    let filter = trees::table.filter(trees::parent_id.eq(42));
    assert_eq!(
        debug_sql::<Backend, _>(&belong_to),
        debug_sql::<Backend, _>(&filter)
    );
}
<commit_msg>Try to build<commit_after>#![allow(dead_code, unused_must_use)]

#[cfg(feature = "sqlite")]
type Backend = ::diesel::sqlite::Sqlite;
#[cfg(feature = "mysql")]
type Backend = ::diesel::mysql::Mysql;
#[cfg(feature = "postgres")]
type Backend = ::diesel::pg::Pg;

#[test]
fn simple_belongs_to() {
    use diesel::*;

    table! {
        users {
            id -> Integer,
            name -> Text,
        }
    }

    table! {
        posts {
            id -> Integer,
            user_id -> Integer,
            title -> Text,
        }
    }

    #[derive(Identifiable)]
    pub struct User {
        id: i32,
        name: String
    }

    #[derive(Associations, Identifiable)]
    #[belongs_to(User)]
    pub struct Post {
        id: i32,
        user_id: i32,
        title: String,
    }

    let _can_join_tables = posts::table.inner_join(users::table)
        .select((users::id, users::name, posts::id))
        .filter(posts::id.eq(1)
                .and(posts::user_id.eq(2))
                .and(posts::title.eq("Bar")));

    let _can_reverse_join_tables = users::table.inner_join(posts::table)
        .select((posts::id, posts::user_id, posts::title))
        .filter(users::id.eq(1)
                .and(users::name.eq("Sean")));

    let t = User { id: 42, name: "Sean".into() };

    let belong_to = Post::belonging_to(&t);
    let filter = posts::table.filter(posts::user_id.eq(42));

    assert_eq!(
        debug_sql::<Backend, _>(&belong_to),
        debug_sql::<Backend, _>(&filter)
    );
}

#[test]
fn custom_foreign_key() {
    use diesel::*;

    table! {
        users {
            id -> Integer,
            name -> Text,
        }
    }

    table! {
        posts {
            id -> Integer,
            belongs_to_user -> Integer,
            title -> Text,
        }
    }

    #[derive(Identifiable)]
    pub struct User {
        id: i32,
        name: String
    }

    #[derive(Associations, Identifiable)]
    #[belongs_to(User, foreign_key = "belongs_to_user")]
    pub struct Post {
        id: i32,
        belongs_to_user: i32,
        title: String,
    }

    let _can_join_tables = posts::table.inner_join(users::table)
        .select((users::id, users::name))
        .filter(posts::id.eq(1)
            .and(posts::belongs_to_user.eq(2))
                .and(posts::title.eq("Bar")));

    let _can_reverse_join_tables = users::table.inner_join(posts::table)
        .select((posts::id, posts::belongs_to_user, posts::title))
        .filter(users::id.eq(1)
                .and(users::name.eq("Sean")));

    let t = User { id: 42, name: "Sean".into() };

    let belong_to = Post::belonging_to(&t);
    let filter = posts::table.filter(posts::belongs_to_user.eq(42));

    assert_eq!(
        debug_sql::<Backend, _>(&belong_to),
        debug_sql::<Backend, _>(&filter)
    );
}

#[test]
fn self_referential() {
    use diesel::*;

    table! {
        trees {
            id -> Integer,
            parent_id -> Nullable<Integer>,
        }
    }

    #[derive(Associations, Identifiable)]
    #[belongs_to(Tree, foreign_key = "parent_id")]
    pub struct Tree {
        id: i32,
        parent_id: Option<i32>,
    }
    let t = Tree { id: 42, parent_id: None };

    let belong_to = Tree::belonging_to(&t);
    let filter = trees::table.filter(trees::parent_id.eq(42));
    assert_eq!(
        debug_sql::<Backend, _>(&belong_to),
        debug_sql::<Backend, _>(&filter)
    );
}
<|endoftext|>


<commit_before>use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};

use crate::utils::{any_parent_is_automatically_derived, match_def_path, paths, span_lint_and_sugg};

declare_clippy_lint! {
    /// **What it does:** Checks for literal calls to `Default::default()`.
    ///
    /// **Why is this bad?** It's more clear to the reader to use the name of the type whose default is
    /// being gotten than the generic `Default`.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// // Bad
    /// let s: String = Default::default();
    ///
    /// // Good
    /// let s = String::default();
    /// ```
    pub DEFAULT_TRAIT_ACCESS,
    pedantic,
    "checks for literal calls to `Default::default()`"
}

declare_lint_pass!(DefaultTraitAccess => [DEFAULT_TRAIT_ACCESS]);

impl<'tcx> LateLintPass<'tcx> for DefaultTraitAccess {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        if_chain! {
            if let ExprKind::Call(ref path, ..) = expr.kind;
            if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
            if let ExprKind::Path(ref qpath) = path.kind;
            if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
            if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD);
            then {
                match qpath {
                    QPath::Resolved(..) => {
                        if_chain! {
                            // Detect and ignore <Foo as Default>::default() because these calls do
                            // explicitly name the type.
                            if let ExprKind::Call(ref method, ref _args) = expr.kind;
                            if let ExprKind::Path(ref p) = method.kind;
                            if let QPath::Resolved(Some(_ty), _path) = p;
                            then {
                                return;
                            }
                        }

                        // TODO: Work out a way to put "whatever the imported way of referencing
                        // this type in this file" rather than a fully-qualified type.
                        let expr_ty = cx.typeck_results().expr_ty(expr);
                        if let ty::Adt(def, ..) = expr_ty.kind {
                            let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did));
                            span_lint_and_sugg(
                                cx,
                                DEFAULT_TRAIT_ACCESS,
                                expr.span,
                                &format!("calling `{}` is more clear than this expression", replacement),
                                "try",
                                replacement,
                                Applicability::Unspecified, // First resolve the TODO above
                            );
                         }
                    },
                    QPath::TypeRelative(..) | QPath::LangItem(..) => {},
                }
            }
        }
    }
}
<commit_msg>Auto merge of #6004 - mikerite:default-trait-access-20200904, r=ebroto<commit_after>use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{Expr, ExprKind, QPath};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};

use crate::utils::{any_parent_is_automatically_derived, match_def_path, paths, span_lint_and_sugg};

declare_clippy_lint! {
    /// **What it does:** Checks for literal calls to `Default::default()`.
    ///
    /// **Why is this bad?** It's more clear to the reader to use the name of the type whose default is
    /// being gotten than the generic `Default`.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// // Bad
    /// let s: String = Default::default();
    ///
    /// // Good
    /// let s = String::default();
    /// ```
    pub DEFAULT_TRAIT_ACCESS,
    pedantic,
    "checks for literal calls to `Default::default()`"
}

declare_lint_pass!(DefaultTraitAccess => [DEFAULT_TRAIT_ACCESS]);

impl<'tcx> LateLintPass<'tcx> for DefaultTraitAccess {
    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
        if_chain! {
            if let ExprKind::Call(ref path, ..) = expr.kind;
            if !any_parent_is_automatically_derived(cx.tcx, expr.hir_id);
            if let ExprKind::Path(ref qpath) = path.kind;
            if let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
            if match_def_path(cx, def_id, &paths::DEFAULT_TRAIT_METHOD);
            // Detect and ignore <Foo as Default>::default() because these calls do explicitly name the type.
            if let QPath::Resolved(None, _path) = qpath;
            then {
                let expr_ty = cx.typeck_results().expr_ty(expr);
                if let ty::Adt(def, ..) = expr_ty.kind {
                    // TODO: Work out a way to put "whatever the imported way of referencing
                    // this type in this file" rather than a fully-qualified type.
                    let replacement = format!("{}::default()", cx.tcx.def_path_str(def.did));
                    span_lint_and_sugg(
                        cx,
                        DEFAULT_TRAIT_ACCESS,
                        expr.span,
                        &format!("calling `{}` is more clear than this expression", replacement),
                        "try",
                        replacement,
                        Applicability::Unspecified, // First resolve the TODO above
                    );
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// vim: tw=80
/// # Arguments
///
/// * `expectation`:    Name of the generated Expectation type
/// * `module`:         Name of the private module to create
/// * `o`:              Output type.  Must be static
/// * `methty`:         Comma-delimited sequence of arguments types for the
///                     method being mocked.
/// * `matchcall`:      Comma-delimited sequence of expressions that produce
///                     values of type `matchty` from values of type `methty`.
/// * `args`:           comma-delimited sequence of argument names for each
///                     argument.  Ideally this wouldn't need to be specified,
///                     but it is due to Rust's macro hygiene rules.
/// * `predargs`:       Comma-delimited sequence of identifiers of the same
///                     length as `args`, but distinct.
/// * `matchty`:        comma-delimited sequence of types for each match
///                     argument.  Must all be `'static`.
///
/// # Examples
///
/// ```
/// // Mock a method like foo(&self, x: u32, y: &i16) -> u32
/// omnimock!{(u32, &i16), u32, i, [&i.0, i.1], [i0, i1], [u32, i16]}
#[macro_export]
macro_rules! omnimock {(
        $expectation:ident,
        $module:ident,
        $o:ty,
        [ $( $methty:ty ),* ],
        [ $( $matchcall:expr ),* ],
        [ $( $args:ident ),* ],
        [ $( $predargs:ident ),* ],
        [ $( $matchty:ty ),* ]) =>
    {
        mod $module {

        enum Rfunc {
            Default,
            // Indicates that a `return_once` expectation has already returned
            Expired,
            Mut(Box<dyn FnMut($( $methty, )*) -> $o + Send>),
            // Should be Box<dyn FnOnce> once that feature is stabilized
            // https://github.com/rust-lang/rust/issues/28796
            Once(Box<dyn FnMut($( $methty, )*) -> $o + Send>),
        }

        impl  Rfunc {
            fn call_mut(&mut self, $( $args: $methty, )* ) -> $o {
                match self {
                    Rfunc::Default => {
                        unimplemented!()
                        //Self::return_default()
                    },
                    Rfunc::Expired => {
                        panic!("Called a method twice that was expected only once")
                    },
                    Rfunc::Mut(f) => {
                        f( $( $args, )* )
                    },
                    Rfunc::Once(_) => {
                        let fo = ::std::mem::replace(self, Rfunc::Expired);
                        if let Rfunc::Once(mut f) = fo {
                            f( $( $args, )* )
                        } else {
                            unreachable!()
                        }
                    },
                }
            }
        }

        impl std::default::Default for Rfunc {
            fn default() -> Self {
                Rfunc::Default
            }
        }

        enum Matcher {
            Func(Box<Fn($( &$matchty, )* ) -> bool>),
            Pred( $( Box<::mockall::Predicate<$matchty>>, )* )
        }

        impl Matcher {
            fn eval(&self, $( $args: &$matchty, )*) {
                let passed = match self {
                    Matcher::Func(f) => f($( $args, )*),
                    Matcher::Pred($( $predargs, )*) =>
                        [$( $predargs.eval($args), )*]
                        .into_iter()
                        .all(|x| *x),
                };
                assert!(passed);
            }

            fn verify(&self, $( $args: &$matchty, )* ) {
                self.eval( $( $args, )* );
            }
        }

        impl Default for Matcher {
            #[allow(unused_variables)]
            fn default() -> Self {
                Matcher::Func(Box::new(|$( $args, )*| true))
            }
        }

        #[derive(Default)]
        struct Common {
            matcher: ::std::sync::Mutex<Matcher>,
            seq_handle: Option<::mockall::SeqHandle>,
            times: ::mockall::Times
        }

        impl Common {
            fn call(&self, $( $args: &$matchty, )* ) {
                self.matcher.lock().unwrap().verify($( $args, )*);
                self.times.call();
                self.verify_sequence();
                if self.times.is_satisfied() {
                    self.satisfy_sequence()
                }
            }

            fn satisfy_sequence(&self) {
                if let Some(handle) = &self.seq_handle {
                    handle.satisfy()
                }
            }

            fn verify_sequence(&self) {
                if let Some(handle) = &self.seq_handle {
                    handle.verify()
                }
            }

            #[allow(non_camel_case_types)]  // Repurpose $predargs for generics
            fn with<$( $predargs: ::mockall::Predicate<$matchty> + 'static,)*>
                (&mut self, $( $args: $predargs,)*)
            {
                use ::std::ops::DerefMut;
                let mut guard = self.matcher.lock().unwrap();
                let m = Matcher::Pred($( Box::new($args), )*);
                ::std::mem::replace(guard.deref_mut(), m);
            }

            fn withf<F>(&mut self, f: F)
                where F: Fn($( &$matchty, )* ) -> bool + Send + 'static
            {
                use ::std::ops::DerefMut;
                let mut guard = self.matcher.lock().unwrap();
                let m = Matcher::Func(Box::new(f));
                ::std::mem::replace(guard.deref_mut(), m);
            }
        }

        #[derive(Default)]
        pub struct Expectation {
            common: Common,
            rfunc: ::std::sync::Mutex<Rfunc>,
        }

        impl Expectation {
            pub fn call(&self, $( $args: $methty, )* ) -> $o {
                self.common.call($( $matchcall, )*);
                self.rfunc.lock().unwrap().call_mut($( $args, )*)
            }

            pub fn returning<F>(&mut self, f: F) -> &mut Self
                where F: FnMut($( $methty, )*) -> $o + Send + 'static
            {
                {
                    use ::std::ops::DerefMut;
                    let mut guard = self.rfunc.lock().unwrap();
                    ::std::mem::replace(guard.deref_mut(), Rfunc::Mut(Box::new(f)));
                }
                self
            }

            #[allow(non_camel_case_types)]  // Repurpose $predargs for generics
            pub fn with<$( $predargs: ::mockall::Predicate<$matchty> + 'static,)*>
                (&mut self, $( $args: $predargs,)*) -> &mut Self
            {
                self.common.with($( $args, )*);
                self
            }

            pub fn withf<F>(&mut self, f: F) -> &mut Self
                where F: Fn($( &$matchty, )* ) -> bool + Send + 'static
            {
                self.common.withf(f);
                self
            }
        }

        }
        use $module::Expectation as $expectation;
    }
}
<commit_msg>Omnimock: better error messages for failed match args<commit_after>// vim: tw=80
/// Generate Expectation and Expectations types with specific signatures
///
/// # Arguments
///
/// * `expectation`:    Name of the generated Expectation type
/// * `module`:         Name of the private module to create
/// * `o`:              Output type.  Must be static
/// * `methty`:         Comma-delimited sequence of arguments types for the
///                     method being mocked.
/// * `matchcall`:      Comma-delimited sequence of expressions that produce
///                     values of type `matchty` from values of type `methty`.
/// * `args`:           comma-delimited sequence of argument names for each
///                     argument.  Ideally this wouldn't need to be specified,
///                     but it is due to Rust's macro hygiene rules.
/// * `predargs`:       Comma-delimited sequence of identifiers of the same
///                     length as `args`, but distinct.
/// * `matchty`:        comma-delimited sequence of types for each match
///                     argument.  Must all be `'static`.
///
/// # Examples
///
/// ```
/// // Mock a method like foo(&self, x: u32, y: &i16) -> u32
/// omnimock!{(u32, &i16), u32, i, [&i.0, i.1], [i0, i1], [u32, i16]}
#[macro_export]
macro_rules! omnimock {(
        $expectation:ident,
        $module:ident,
        $o:ty,
        [ $( $methty:ty ),* ],
        [ $( $matchcall:expr ),* ],
        [ $( $args:ident ),* ],
        [ $( $predargs:ident ),* ],
        [ $( $matchty:ty ),* ]) =>
    {
        mod $module {

        enum Rfunc {
            Default,
            // Indicates that a `return_once` expectation has already returned
            Expired,
            Mut(Box<dyn FnMut($( $methty, )*) -> $o + Send>),
            // Should be Box<dyn FnOnce> once that feature is stabilized
            // https://github.com/rust-lang/rust/issues/28796
            Once(Box<dyn FnMut($( $methty, )*) -> $o + Send>),
        }

        impl  Rfunc {
            fn call_mut(&mut self, $( $args: $methty, )* ) -> $o {
                match self {
                    Rfunc::Default => {
                        unimplemented!()
                        //Self::return_default()
                    },
                    Rfunc::Expired => {
                        panic!("Called a method twice that was expected only once")
                    },
                    Rfunc::Mut(f) => {
                        f( $( $args, )* )
                    },
                    Rfunc::Once(_) => {
                        let fo = ::std::mem::replace(self, Rfunc::Expired);
                        if let Rfunc::Once(mut f) = fo {
                            f( $( $args, )* )
                        } else {
                            unreachable!()
                        }
                    },
                }
            }
        }

        impl std::default::Default for Rfunc {
            fn default() -> Self {
                Rfunc::Default
            }
        }

        enum Matcher {
            Func(Box<Fn($( &$matchty, )* ) -> bool>),
            Pred( $( Box<::mockall::Predicate<$matchty>>, )* )
        }

        impl Matcher {
            fn eval(&self, $( $args: &$matchty, )*) -> bool {
                match self {
                    Matcher::Func(f) => f($( $args, )*),
                    Matcher::Pred($( $predargs, )*) =>
                        [$( $predargs.eval($args), )*]
                        .into_iter()
                        .all(|x| *x),
                }
            }

            fn verify(&self, $( $args: &$matchty, )* ) {
                use predicates_tree::CaseTreeExt;
                match self {
                    Matcher::Func(f) => assert!(f($( $args, )*),
                        "Expectation didn't match arguments"),
                    Matcher::Pred($( $predargs, )*) => {
                        $(if let Some(c) = $predargs.find_case(false, $args) {
                            panic!("Expectation didn't match arguments:\n{}",
                                   c.tree());
                        })*
                    }
                }
            }
        }

        impl Default for Matcher {
            #[allow(unused_variables)]
            fn default() -> Self {
                Matcher::Func(Box::new(|$( $args, )*| true))
            }
        }

        #[derive(Default)]
        struct Common {
            matcher: ::std::sync::Mutex<Matcher>,
            seq_handle: Option<::mockall::SeqHandle>,
            times: ::mockall::Times
        }

        impl Common {
            fn call(&self, $( $args: &$matchty, )* ) {
                self.matcher.lock().unwrap().verify($( $args, )*);
                self.times.call();
                self.verify_sequence();
                if self.times.is_satisfied() {
                    self.satisfy_sequence()
                }
            }

            fn satisfy_sequence(&self) {
                if let Some(handle) = &self.seq_handle {
                    handle.satisfy()
                }
            }

            fn verify_sequence(&self) {
                if let Some(handle) = &self.seq_handle {
                    handle.verify()
                }
            }

            #[allow(non_camel_case_types)]  // Repurpose $predargs for generics
            fn with<$( $predargs: ::mockall::Predicate<$matchty> + 'static,)*>
                (&mut self, $( $args: $predargs,)*)
            {
                use ::std::ops::DerefMut;
                let mut guard = self.matcher.lock().unwrap();
                let m = Matcher::Pred($( Box::new($args), )*);
                ::std::mem::replace(guard.deref_mut(), m);
            }

            fn withf<F>(&mut self, f: F)
                where F: Fn($( &$matchty, )* ) -> bool + Send + 'static
            {
                use ::std::ops::DerefMut;
                let mut guard = self.matcher.lock().unwrap();
                let m = Matcher::Func(Box::new(f));
                ::std::mem::replace(guard.deref_mut(), m);
            }
        }

        #[derive(Default)]
        pub struct Expectation {
            common: Common,
            rfunc: ::std::sync::Mutex<Rfunc>,
        }

        impl Expectation {
            pub fn call(&self, $( $args: $methty, )* ) -> $o {
                self.common.call($( $matchcall, )*);
                self.rfunc.lock().unwrap().call_mut($( $args, )*)
            }

            pub fn returning<F>(&mut self, f: F) -> &mut Self
                where F: FnMut($( $methty, )*) -> $o + Send + 'static
            {
                {
                    use ::std::ops::DerefMut;
                    let mut guard = self.rfunc.lock().unwrap();
                    ::std::mem::replace(guard.deref_mut(), Rfunc::Mut(Box::new(f)));
                }
                self
            }

            #[allow(non_camel_case_types)]  // Repurpose $predargs for generics
            pub fn with<$( $predargs: ::mockall::Predicate<$matchty> + 'static,)*>
                (&mut self, $( $args: $predargs,)*) -> &mut Self
            {
                self.common.with($( $args, )*);
                self
            }

            pub fn withf<F>(&mut self, f: F) -> &mut Self
                where F: Fn($( &$matchty, )* ) -> bool + Send + 'static
            {
                self.common.withf(f);
                self
            }
        }

        }
        use $module::Expectation as $expectation;
    }
}
<|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 dom::bindings::callback::ExceptionHandling::Report;
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast};
use dom::bindings::js::JS;
use dom::bindings::trace::RootedVec;
use dom::event::{Event, EventPhase};
use dom::eventtarget::{EventTarget, ListenerPhase};
use dom::node::Node;
use dom::virtualmethods::vtable_for;

// See https://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm
pub fn dispatch_event(target: &EventTarget, pseudo_target: Option<&EventTarget>,
                      event: &Event) -> bool {
    assert!(!event.dispatching());
    assert!(event.initialized());

    event.set_target(match pseudo_target {
        Some(pseudo_target) => pseudo_target,
        None => target.clone(),
    });
    event.set_dispatching(true);

    let type_ = event.Type();

    //TODO: no chain if not participating in a tree
    let mut chain: RootedVec<JS<EventTarget>> = RootedVec::new();
    if let Some(target_node) = NodeCast::to_ref(target) {
        for ancestor in target_node.ancestors() {
            let ancestor_target = EventTargetCast::from_ref(ancestor.r());
            chain.push(JS::from_ref(ancestor_target))
        }
    }

    event.set_phase(EventPhase::Capturing);

    /* capturing */
    for cur_target in chain.r().iter().rev() {
        let stopped = match cur_target.get_listeners_for(&type_, ListenerPhase::Capturing) {
            Some(listeners) => {
                event.set_current_target(cur_target);
                for listener in &listeners {
                    // Explicitly drop any exception on the floor.
                    listener.call_or_handle_event(*cur_target, event, Report);

                    if event.stop_immediate() {
                        break;
                    }
                }

                event.stop_propagation()
            }
            None => false
        };

        if stopped {
            break;
        }
    }

    /* at target */
    if !event.stop_propagation() {
        event.set_phase(EventPhase::AtTarget);
        event.set_current_target(target.clone());

        let opt_listeners = target.get_listeners(&type_);
        for listeners in opt_listeners {
            for listener in listeners {
                // Explicitly drop any exception on the floor.
                listener.call_or_handle_event(target, event, Report);

                if event.stop_immediate() {
                    break;
                }
            }
        }
    }

    /* bubbling */
    if event.bubbles() && !event.stop_propagation() {
        event.set_phase(EventPhase::Bubbling);

        for cur_target in chain.r() {
            let stopped = match cur_target.get_listeners_for(&type_, ListenerPhase::Bubbling) {
                Some(listeners) => {
                    event.set_current_target(cur_target);
                    for listener in &listeners {
                        // Explicitly drop any exception on the floor.
                        listener.call_or_handle_event(*cur_target, event, Report);

                        if event.stop_immediate() {
                            break;
                        }
                    }

                    event.stop_propagation()
                }
                None => false
            };
            if stopped {
                break;
            }
        }
    }

    /* default action */
    let target = event.GetTarget();
    match target {
        Some(ref target) => {
            let node: Option<&Node> = NodeCast::to_ref(target.r());
            match node {
                Some(node) => {
                    let vtable = vtable_for(&node);
                    vtable.handle_event(event);
                }
                None => {}
            }
        }
        None => {}
    }

    event.set_dispatching(false);
    event.set_phase(EventPhase::None);
    event.clear_current_target();

    !event.DefaultPrevented()
}
<commit_msg>Reorder the code in dispatch_event a bit.<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 dom::bindings::callback::ExceptionHandling::Report;
use dom::bindings::codegen::Bindings::EventBinding::EventMethods;
use dom::bindings::codegen::InheritTypes::{EventTargetCast, NodeCast};
use dom::bindings::js::JS;
use dom::bindings::trace::RootedVec;
use dom::event::{Event, EventPhase};
use dom::eventtarget::{EventTarget, ListenerPhase};
use dom::node::Node;
use dom::virtualmethods::vtable_for;

// See https://dom.spec.whatwg.org/#concept-event-dispatch for the full dispatch algorithm
pub fn dispatch_event(target: &EventTarget, pseudo_target: Option<&EventTarget>,
                      event: &Event) -> bool {
    assert!(!event.dispatching());
    assert!(event.initialized());

    event.set_target(match pseudo_target {
        Some(pseudo_target) => pseudo_target,
        None => target.clone(),
    });
    event.set_dispatching(true);

    //TODO: no chain if not participating in a tree
    let mut chain: RootedVec<JS<EventTarget>> = RootedVec::new();
    if let Some(target_node) = NodeCast::to_ref(target) {
        for ancestor in target_node.ancestors() {
            let ancestor_target = EventTargetCast::from_ref(ancestor.r());
            chain.push(JS::from_ref(ancestor_target))
        }
    }

    let type_ = event.Type();

    /* capturing */
    event.set_phase(EventPhase::Capturing);
    for cur_target in chain.r().iter().rev() {
        let stopped = match cur_target.get_listeners_for(&type_, ListenerPhase::Capturing) {
            Some(listeners) => {
                event.set_current_target(cur_target);
                for listener in &listeners {
                    // Explicitly drop any exception on the floor.
                    listener.call_or_handle_event(*cur_target, event, Report);

                    if event.stop_immediate() {
                        break;
                    }
                }

                event.stop_propagation()
            }
            None => false
        };

        if stopped {
            break;
        }
    }

    /* at target */
    if !event.stop_propagation() {
        event.set_phase(EventPhase::AtTarget);
        event.set_current_target(target.clone());

        let opt_listeners = target.get_listeners(&type_);
        for listeners in opt_listeners {
            for listener in listeners {
                // Explicitly drop any exception on the floor.
                listener.call_or_handle_event(target, event, Report);

                if event.stop_immediate() {
                    break;
                }
            }
        }
    }

    /* bubbling */
    if event.bubbles() && !event.stop_propagation() {
        event.set_phase(EventPhase::Bubbling);

        for cur_target in chain.r() {
            let stopped = match cur_target.get_listeners_for(&type_, ListenerPhase::Bubbling) {
                Some(listeners) => {
                    event.set_current_target(cur_target);
                    for listener in &listeners {
                        // Explicitly drop any exception on the floor.
                        listener.call_or_handle_event(*cur_target, event, Report);

                        if event.stop_immediate() {
                            break;
                        }
                    }

                    event.stop_propagation()
                }
                None => false
            };
            if stopped {
                break;
            }
        }
    }

    /* default action */
    let target = event.GetTarget();
    match target {
        Some(ref target) => {
            let node: Option<&Node> = NodeCast::to_ref(target.r());
            match node {
                Some(node) => {
                    let vtable = vtable_for(&node);
                    vtable.handle_event(event);
                }
                None => {}
            }
        }
        None => {}
    }

    event.set_dispatching(false);
    event.set_phase(EventPhase::None);
    event.clear_current_target();

    !event.DefaultPrevented()
}
<|endoftext|>


<commit_before>//! This example of boxcars looks at the header of replays given as command line arguments and
//! counts how often a properties occurs across them.
use boxcars::{HeaderProp, ParserBuilder};
use std::collections::HashMap;
use std::error;
use std::fs::File;
use std::io::Read;
use std::borrow::Cow;

fn count_properties(props: &[(String, HeaderProp)], counter: &mut HashMap<String, usize>, prefix: &str) {
    for (key, prop) in props.iter() {
        let new_prefix = if prefix == "" {
            Cow::Borrowed(key)
        } else {
            Cow::Owned(format!("{}:{}", prefix, key))
        };

        let k = match prop {
            HeaderProp::Array(inner) => {
                for p in inner.iter() {
                    count_properties(p, counter, &new_prefix);
                }
                format!("{}:array", new_prefix)
            },
            HeaderProp::Bool(_) => format!("{}:bool", new_prefix),
            HeaderProp::Byte => format!("{}:byte", new_prefix),
            HeaderProp::Float(_) => format!("{}:float", new_prefix),
            HeaderProp::Int(_) =>format!("{}:int", new_prefix),
            HeaderProp::Name(_) =>format!("{}:name", new_prefix),
            HeaderProp::QWord(_) => format!("{}:qword", new_prefix),
            HeaderProp::Str(_) => format!("{}:str", new_prefix),
        };

        *counter.entry(k).or_default() += 1;
    }
}

fn main() -> Result<(), Box<dyn error::Error>> {
    let mut counter: HashMap<String, usize> = HashMap::new();
    let mut buffer: Vec<u8> = Vec::new();
    let mut files = 0;
    for file in std::env::args().skip(1) {
        let rs = File::open(&file).and_then(|mut f| f.read_to_end(&mut buffer));
        if let Err(e) = rs {
            println!("unable to read file {}: {}", &file, e);
            continue;
        }

        let replay = ParserBuilder::new(&buffer)
            .never_check_crc()
            .never_parse_network_data()
            .parse();

        let replay = if let Err(e) = replay {
            println!("unable to parse file {}: {}", &file, e);
            continue;
        } else {
            replay.unwrap()
        };

        files += 1;
        count_properties(&replay.properties, &mut counter, "");

/*        for (key, prop) in replay.properties.iter() {
            let k = match prop {
                HeaderProp::Array(_) => format!("{}:array", key),
                HeaderProp::Bool(_) => format!("{}:bool", key),
                HeaderProp::Byte => format!("{}:byte", key),
                HeaderProp::Float(_) => format!("{}:float", key),
                HeaderProp::Int(_) =>format!("{}:int", key),
                HeaderProp::Name(_) =>format!("{}:name", key),
                HeaderProp::QWord(_) => format!("{}:qword", key),
                HeaderProp::Str(_) => format!("{}:str", key),
            };

            *counter.entry(k).or_default() += 1;
        }*/

        println!("Parsed: {}", file);
        buffer.clear();
    }

    println!("Parsed {} files", files);
    let mut counts = counter.iter().collect::<Vec<_>>();
    counts.sort();
    for (key, count) in counts.iter() {
        println!("{}: {}", key, count);
    }

    Ok(())
}
<commit_msg>Remove commented out block from example<commit_after>//! This example of boxcars looks at the header of replays given as command line arguments and
//! counts how often a properties occurs across them.
use boxcars::{HeaderProp, ParserBuilder};
use std::collections::HashMap;
use std::error;
use std::fs::File;
use std::io::Read;
use std::borrow::Cow;

fn count_properties(props: &[(String, HeaderProp)], counter: &mut HashMap<String, usize>, prefix: &str) {
    for (key, prop) in props.iter() {
        let new_prefix = if prefix == "" {
            Cow::Borrowed(key)
        } else {
            Cow::Owned(format!("{}:{}", prefix, key))
        };

        let k = match prop {
            HeaderProp::Array(inner) => {
                for p in inner.iter() {
                    count_properties(p, counter, &new_prefix);
                }
                format!("{}:array", new_prefix)
            },
            HeaderProp::Bool(_) => format!("{}:bool", new_prefix),
            HeaderProp::Byte => format!("{}:byte", new_prefix),
            HeaderProp::Float(_) => format!("{}:float", new_prefix),
            HeaderProp::Int(_) =>format!("{}:int", new_prefix),
            HeaderProp::Name(_) =>format!("{}:name", new_prefix),
            HeaderProp::QWord(_) => format!("{}:qword", new_prefix),
            HeaderProp::Str(_) => format!("{}:str", new_prefix),
        };

        *counter.entry(k).or_default() += 1;
    }
}

fn main() -> Result<(), Box<dyn error::Error>> {
    let mut counter: HashMap<String, usize> = HashMap::new();
    let mut buffer: Vec<u8> = Vec::new();
    let mut files = 0;
    for file in std::env::args().skip(1) {
        let rs = File::open(&file).and_then(|mut f| f.read_to_end(&mut buffer));
        if let Err(e) = rs {
            println!("unable to read file {}: {}", &file, e);
            continue;
        }

        let replay = ParserBuilder::new(&buffer)
            .never_check_crc()
            .never_parse_network_data()
            .parse();

        let replay = if let Err(e) = replay {
            println!("unable to parse file {}: {}", &file, e);
            continue;
        } else {
            replay.unwrap()
        };

        files += 1;
        count_properties(&replay.properties, &mut counter, "");

        println!("Parsed: {}", file);
        buffer.clear();
    }

    println!("Parsed {} files", files);
    let mut counts = counter.iter().collect::<Vec<_>>();
    counts.sort();
    for (key, count) in counts.iter() {
        println!("{}: {}", key, count);
    }

    Ok(())
}
<|endoftext|>