<commit_before>#![recursion_limit="256"]

#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;

extern crate syn;
#[macro_use]
extern crate quote;
use syn::*;
extern crate glob;
use glob::glob;

use std::fs::{File, metadata};
use std::io::Read;
use std::io::Write;
use std::process::Command;

extern crate ordermap;
use ordermap::OrderMap;

mod generators;
mod parsers;
use parsers::parse;

pub fn scan_and_generate(src_prefix: &str) {
    for maybe_mod_path in glob(&format!("{}/**/mod.rs", src_prefix)).unwrap() {
        if let Ok(mod_path) = maybe_mod_path {
            //println!("cargo:warning={:?}", mod_path);
            let auto_path = mod_path.clone().to_str().unwrap().replace(
                "mod.rs",
                "kay_auto.rs",
            );
            if let Ok(src_meta) = metadata(&mod_path) {
                let regenerate = match metadata(&auto_path) {
                    Ok(auto_meta) => src_meta.modified().unwrap() > auto_meta.modified().unwrap(),
                    _ => true,
                };

                if regenerate {
                    let auto_file = if let Ok(ref mut file) = File::open(&mod_path) {
                        let mut file_str = String::new();
                        file.read_to_string(&mut file_str).unwrap();
                        match parse(&file_str) {
                            Ok(model) => generate(&model),
                            Err(error) => format!("PARSE ERROR:\n {:?}", error),
                        }
                    } else {
                        panic!("couldn't load");
                    };

                    if let Ok(ref mut file) = File::create(&auto_path) {
                        file.write_all(auto_file.as_bytes()).unwrap();
                    }

                    let _ = Command::new("rustfmt")
                        .arg(&auto_path)
                        .spawn();
                }
            } else {
                panic!("couldn't load");
            };
        }
    }
}

type ActorName = Ty;
type TraitName = syn::Path;

#[derive(Default)]
pub struct Model {
    pub actors: OrderMap<ActorName, ActorDef>,
    pub traits: OrderMap<TraitName, TraitDef>,
}

#[derive(Default)]
pub struct ActorDef {
    pub handlers: Vec<Handler>,
    pub impls: Vec<TraitName>,
    pub defined_here: bool,
}

#[derive(Default)]
pub struct TraitDef {
    pub handlers: Vec<Handler>,
}

#[derive(Clone)]
pub struct Handler {
    name: Ident,
    arguments: Vec<FnArg>,
    scope: HandlerType,
    critical: bool,
    returns_fate: bool,
    from_trait: Option<TraitName>,
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum HandlerType {
    Handler,
    Init,
}

pub fn generate(model: &Model) -> String {
    let traits_msgs = model.generate_traits();
    let actors_msgs = model.generate_actor_ids_messages_and_conversions();
    let setup = model.generate_setups();

    quote!(
        //! This is all auto-generated. Do not touch.
        #[allow(unused_imports)]
        use kay::{ActorSystem, TypedID, RawID, Fate, Actor, TraitIDFrom};
        use super::*;

        #traits_msgs
        #actors_msgs

        #[allow(unused_variables)]
        #[allow(unused_mut)]
        pub fn auto_setup(system: &mut ActorSystem) {
            #setup
        }

    ).into_string()
}

#[test]
fn simple_actor() {
    let input = quote!(
        pub struct SomeActor {
            id: Option<SomeActorID>,
            field: usize
        }

        impl SomeActor {
            pub fn some_method(&mut self, some_param: &usize, world: &mut World) {
                self.id().some_method(42, world);
            }

            pub fn no_params_fate(&mut self, world: &mut World) -> Fate {
                Fate::Die
            }

            pub fn init_ish(id: SomeActorID, some_param: &usize, world: &mut World) -> SomeActor {
                SomeActor {
                    id: Some(id),
                    field: some_param
                }
            }
        }
    );
    let expected = quote!(
        //! This is all auto-generated. Do not touch.
        #[allow(unused_imports)]
        use kay::{ActorSystem, TypedID, RawID, Fate, Actor, TraitIDFrom};
        use super::*;

        impl Actor for SomeActor {
            type ID = SomeActorID;

            fn id(&self) -> Self::ID {
                self.id
            }
            unsafe fn set_id(&mut self, id: RawID) {
                self.id = Self::ID::from_raw(id);
            }
        }

        #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
        pub struct SomeActorID {
            _raw_id: RawID
        }

        impl TypedID for SomeActorID {
            unsafe fn from_raw(id: RawID) -> Self {
                SomeActorID { _raw_id: id }
            }

            fn as_raw(&self) -> RawID {
                self._raw_id
            }
        }

        impl SomeActorID {
            pub fn some_method(&self, some_param: usize, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeActor_some_method(some_param));
            }

            pub fn no_params_fate(&self, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeActor_no_params_fate());
            }

            pub fn init_ish(some_param: usize, world: &mut World) -> Self {
                let id = unsafe{
                    SomeActorID::from_raw(world.allocate_instance_id::<SomeActor>())
                };
                let swarm = world.local_broadcast::<SomeActor>();
                world.send(swarm, MSG_SomeActor_init_ish(id, some_param));
                id
            }
        }

        #[allow(non_camel_case_types)]
        #[derive(Compact, Clone)]
        struct MSG_SomeActor_some_method(pub usize);
        #[allow(non_camel_case_types)]
        #[derive(Copy, Clone)]
        struct MSG_SomeActor_no_params_fate();
        #[allow(non_camel_case_types)]
        #[derive(Compact, Clone)]
        struct MSG_SomeActor_init_ish(pub SomeActorID, pub usize);

        #[allow(unused_variables)]
        #[allow(unused_mut)]
        pub fn auto_setup(system: &mut ActorSystem) {
            system.add_handler::<SomeActor, _, _>(
                |&MSG_SomeActor_some_method(ref some_param), instance, world| {
                instance.some_method(some_param, world);
                Fate::Live
            }, false);

            system.add_handler::<SomeActor, _, _>(
                |&MSG_SomeActor_no_params_fate(), instance, world| {
                instance.no_params_fate(world)
            }, false);

            system.add_spawner::<SomeActor, _, _>(
                |&MSG_SomeActor_init_ish(id, ref some_param), world| {
                SomeActor::init_ish(id, some_param, world)
            }, false);
        }
    );

    assert_eq!(
        expected.into_string(),
        generate(&parse(&input.into_string()).unwrap())
    );
}

#[test]
fn trait_and_impl() {
    let input = quote!(
        pub struct SomeActor {
            _id: Option<SomeActorID>,
            field: usize
        }

        trait SomeTrait {
            fn some_method(&mut self, some_param: &usize, world: &mut World);
            fn no_params_fate(&mut self, world: &mut World) -> Fate;
            fn some_default_impl_method(&mut self, world: &mut World) {
                self.some_method(3, world);
            }
        }

        impl SomeTrait for SomeActor {
            fn some_method(&mut self, some_param: &usize, world: &mut World) {
                self.id().some_method(42, world);
            }

            fn no_params_fate(&mut self, world: &mut World) -> Fate {
                Fate::Die
            }
        }

        impl ForeignTrait for SomeActor {
            fn simple(&mut self, some_param: &usize, world: &mut World) {
                self.id().some_method(some_param, world);
            }
        }

        // This shouldn't generate any RawID
        impl Deref for SomeActor {
            type Target = usize;
            fn deref(&self) -> &usize {
                &self.field
            }
        }
    );
    let expected = quote!(
        //! This is all auto-generated. Do not touch.
        #[allow(unused_imports)]
        use kay::{ActorSystem, TypedID, RawID, Fate, Actor, TraitIDFrom};
        use super::*;

        #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
        pub struct SomeTraitID {
            _raw_id: RawID
        }

        impl TypedID for SomeTraitID {
            unsafe fn from_raw(id: RawID) -> Self {
                SomeTraitID { _raw_id: id }
            }

            fn as_raw(&self) -> RawID {
                self._raw_id
            }
        }

        impl<A: Actor + SomeTrait> TraitIDFrom<A> for SomeTraitID {}

        impl SomeTraitID {
            pub fn some_method(&self, some_param: usize, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeTrait_some_method(some_param));
            }

            pub fn no_params_fate(&self, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeTrait_no_params_fate());
            }

            pub fn some_default_impl_method(&self, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeTrait_some_default_impl_method());
            }

            pub fn register_handlers<A: Actor + SomeTrait>(system: &mut ActorSystem) {
                system.add_handler::<A, _, _>(
                    |&MSG_SomeTrait_some_method(ref some_param), instance, world| {
                    instance.some_method(some_param, world);
                    Fate::Live
                }, false);

                system.add_handler::<A, _, _>(
                    |&MSG_SomeTrait_no_params_fate(), instance, world| {
                    instance.no_params_fate(world)
                }, false);

                system.add_handler::<A, _, _>(
                    |&MSG_SomeTrait_some_default_impl_method(), instance, world| {
                    instance.some_default_impl_method(world);
                    Fate::Live
                }, false);
            }
        }

        #[allow(non_camel_case_types)]
        #[derive(Compact, Clone)]
        struct MSG_SomeTrait_some_method(pub usize);
        #[allow(non_camel_case_types)]
        #[derive(Copy, Clone)]
        struct MSG_SomeTrait_no_params_fate();
        #[allow(non_camel_case_types)]
        #[derive(Copy, Clone)]
        struct MSG_SomeTrait_some_default_impl_method();

        impl Actor for SomeActor {
            type ID = SomeActorID;

            fn id(&self) -> Self::ID {
                self.id
            }
            unsafe fn set_id(&mut self, id: RawID) {
                self.id = Self::ID::from_raw(id);
            }
        }

        #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
        pub struct SomeActorID {
            _raw_id: RawID
        }

        impl TypedID for SomeActorID {
            unsafe fn from_raw(id: RawID) -> Self {
                SomeActorID { _raw_id: id }
            }

            fn as_raw(&self) -> RawID {
                self._raw_id
            }
        }

        impl SomeActorID { }

        impl Into<SomeTraitID> for SomeActorID {
            fn into(self) -> SomeTraitID {
                unsafe {SomeTraitID::from_raw(self.as_raw())}
            }
        }

        impl Into<ForeignTraitID> for SomeActorID {
            fn into(self) -> ForeignTraitID {
                unsafe {ForeignTraitID::from_raw(self.as_raw())}
            }
        }

        #[allow(unused_variables)]
        #[allow(unused_mut)]
        pub fn auto_setup(system: &mut ActorSystem) {
            SomeTraitID::register_handlers::<SomeActor>(system);
            ForeignTraitID::register_handlers::<SomeActor>(system);
        }
    );

    assert_eq!(
        expected.into_string(),
        generate(&parse(&input.into_string()).unwrap())
    );
}
<commit_msg>Fix auto-generated files.<commit_after>#![recursion_limit="256"]

#[cfg(test)]
#[macro_use]
extern crate pretty_assertions;

extern crate syn;
#[macro_use]
extern crate quote;
use syn::*;
extern crate glob;
use glob::glob;

use std::fs::{File, metadata};
use std::io::Read;
use std::io::Write;
use std::process::Command;

extern crate ordermap;
use ordermap::OrderMap;

mod generators;
mod parsers;
use parsers::parse;

pub fn scan_and_generate(src_prefix: &str) {
    for maybe_mod_path in glob(&format!("{}/**/mod.rs", src_prefix)).unwrap() {
        if let Ok(mod_path) = maybe_mod_path {
            //println!("cargo:warning={:?}", mod_path);
            let auto_path = mod_path.clone().to_str().unwrap().replace(
                "mod.rs",
                "kay_auto.rs",
            );
            if let Ok(src_meta) = metadata(&mod_path) {
                let regenerate = match metadata(&auto_path) {
                    Ok(auto_meta) => src_meta.modified().unwrap() > auto_meta.modified().unwrap(),
                    _ => true,
                };

                if regenerate {
                    let auto_file = if let Ok(ref mut file) = File::open(&mod_path) {
                        let mut file_str = String::new();
                        file.read_to_string(&mut file_str).unwrap();
                        match parse(&file_str) {
                            Ok(model) => generate(&model),
                            Err(error) => panic!("PARSE ERROR:\n {:?}", error),
                        }
                    } else {
                        panic!("couldn't load");
                    };

                    if let Ok(ref mut file) = File::create(&auto_path) {
                        file.write_all(auto_file.as_bytes()).unwrap();
                    }

                    let _ = Command::new("rustfmt")
                        .arg(&auto_path)
                        .arg("--backup")
                        .spawn();
                }
            } else {
                panic!("couldn't load");
            };
        }
    }
}

type ActorName = Ty;
type TraitName = syn::Path;

#[derive(Default)]
pub struct Model {
    pub actors: OrderMap<ActorName, ActorDef>,
    pub traits: OrderMap<TraitName, TraitDef>,
}

#[derive(Default)]
pub struct ActorDef {
    pub handlers: Vec<Handler>,
    pub impls: Vec<TraitName>,
    pub defined_here: bool,
}

#[derive(Default)]
pub struct TraitDef {
    pub handlers: Vec<Handler>,
}

#[derive(Clone)]
pub struct Handler {
    name: Ident,
    arguments: Vec<FnArg>,
    scope: HandlerType,
    critical: bool,
    returns_fate: bool,
    from_trait: Option<TraitName>,
}

#[derive(Copy, Clone, PartialEq, Eq)]
pub enum HandlerType {
    Handler,
    Init,
}

pub fn generate(model: &Model) -> String {
    let traits_msgs = model.generate_traits();
    let actors_msgs = model.generate_actor_ids_messages_and_conversions();
    let setup = model.generate_setups();

    quote!(
        //! This is all auto-generated. Do not touch.
        #[allow(unused_imports)]
        use kay::{ActorSystem, TypedID, RawID, Fate, Actor, TraitIDFrom};
        #[allow(unused_imports)]
        use super::*;

        #traits_msgs
        #actors_msgs

        #[allow(unused_variables)]
        #[allow(unused_mut)]
        pub fn auto_setup(system: &mut ActorSystem) {
            #setup
        }

    ).into_string()
}

#[test]
fn simple_actor() {
    let input = quote!(
        pub struct SomeActor {
            id: Option<SomeActorID>,
            field: usize
        }

        impl SomeActor {
            pub fn some_method(&mut self, some_param: &usize, world: &mut World) {
                self.id().some_method(42, world);
            }

            pub fn no_params_fate(&mut self, world: &mut World) -> Fate {
                Fate::Die
            }

            pub fn init_ish(id: SomeActorID, some_param: &usize, world: &mut World) -> SomeActor {
                SomeActor {
                    id: Some(id),
                    field: some_param
                }
            }
        }
    );
    let expected = quote!(
        //! This is all auto-generated. Do not touch.
        #[allow(unused_imports)]
        use kay::{ActorSystem, TypedID, RawID, Fate, Actor, TraitIDFrom};
        use super::*;

        impl Actor for SomeActor {
            type ID = SomeActorID;

            fn id(&self) -> Self::ID {
                self.id
            }
            unsafe fn set_id(&mut self, id: RawID) {
                self.id = Self::ID::from_raw(id);
            }
        }

        #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
        pub struct SomeActorID {
            _raw_id: RawID
        }

        impl TypedID for SomeActorID {
            unsafe fn from_raw(id: RawID) -> Self {
                SomeActorID { _raw_id: id }
            }

            fn as_raw(&self) -> RawID {
                self._raw_id
            }
        }

        impl SomeActorID {
            pub fn some_method(&self, some_param: usize, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeActor_some_method(some_param));
            }

            pub fn no_params_fate(&self, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeActor_no_params_fate());
            }

            pub fn init_ish(some_param: usize, world: &mut World) -> Self {
                let id = unsafe{
                    SomeActorID::from_raw(world.allocate_instance_id::<SomeActor>())
                };
                let swarm = world.local_broadcast::<SomeActor>();
                world.send(swarm, MSG_SomeActor_init_ish(id, some_param));
                id
            }
        }

        #[allow(non_camel_case_types)]
        #[derive(Compact, Clone)]
        struct MSG_SomeActor_some_method(pub usize);
        #[allow(non_camel_case_types)]
        #[derive(Copy, Clone)]
        struct MSG_SomeActor_no_params_fate();
        #[allow(non_camel_case_types)]
        #[derive(Compact, Clone)]
        struct MSG_SomeActor_init_ish(pub SomeActorID, pub usize);

        #[allow(unused_variables)]
        #[allow(unused_mut)]
        pub fn auto_setup(system: &mut ActorSystem) {
            system.add_handler::<SomeActor, _, _>(
                |&MSG_SomeActor_some_method(ref some_param), instance, world| {
                instance.some_method(some_param, world);
                Fate::Live
            }, false);

            system.add_handler::<SomeActor, _, _>(
                |&MSG_SomeActor_no_params_fate(), instance, world| {
                instance.no_params_fate(world)
            }, false);

            system.add_spawner::<SomeActor, _, _>(
                |&MSG_SomeActor_init_ish(id, ref some_param), world| {
                SomeActor::init_ish(id, some_param, world)
            }, false);
        }
    );

    assert_eq!(
        expected.into_string(),
        generate(&parse(&input.into_string()).unwrap())
    );
}

#[test]
fn trait_and_impl() {
    let input = quote!(
        pub struct SomeActor {
            _id: Option<SomeActorID>,
            field: usize
        }

        trait SomeTrait {
            fn some_method(&mut self, some_param: &usize, world: &mut World);
            fn no_params_fate(&mut self, world: &mut World) -> Fate;
            fn some_default_impl_method(&mut self, world: &mut World) {
                self.some_method(3, world);
            }
        }

        impl SomeTrait for SomeActor {
            fn some_method(&mut self, some_param: &usize, world: &mut World) {
                self.id().some_method(42, world);
            }

            fn no_params_fate(&mut self, world: &mut World) -> Fate {
                Fate::Die
            }
        }

        impl ForeignTrait for SomeActor {
            fn simple(&mut self, some_param: &usize, world: &mut World) {
                self.id().some_method(some_param, world);
            }
        }

        // This shouldn't generate any RawID
        impl Deref for SomeActor {
            type Target = usize;
            fn deref(&self) -> &usize {
                &self.field
            }
        }
    );
    let expected = quote!(
        //! This is all auto-generated. Do not touch.
        #[allow(unused_imports)]
        use kay::{ActorSystem, TypedID, RawID, Fate, Actor, TraitIDFrom};
        use super::*;

        #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
        pub struct SomeTraitID {
            _raw_id: RawID
        }

        impl TypedID for SomeTraitID {
            unsafe fn from_raw(id: RawID) -> Self {
                SomeTraitID { _raw_id: id }
            }

            fn as_raw(&self) -> RawID {
                self._raw_id
            }
        }

        impl<A: Actor + SomeTrait> TraitIDFrom<A> for SomeTraitID {}

        impl SomeTraitID {
            pub fn some_method(&self, some_param: usize, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeTrait_some_method(some_param));
            }

            pub fn no_params_fate(&self, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeTrait_no_params_fate());
            }

            pub fn some_default_impl_method(&self, world: &mut World) {
                world.send(self.as_raw(), MSG_SomeTrait_some_default_impl_method());
            }

            pub fn register_handlers<A: Actor + SomeTrait>(system: &mut ActorSystem) {
                system.add_handler::<A, _, _>(
                    |&MSG_SomeTrait_some_method(ref some_param), instance, world| {
                    instance.some_method(some_param, world);
                    Fate::Live
                }, false);

                system.add_handler::<A, _, _>(
                    |&MSG_SomeTrait_no_params_fate(), instance, world| {
                    instance.no_params_fate(world)
                }, false);

                system.add_handler::<A, _, _>(
                    |&MSG_SomeTrait_some_default_impl_method(), instance, world| {
                    instance.some_default_impl_method(world);
                    Fate::Live
                }, false);
            }
        }

        #[allow(non_camel_case_types)]
        #[derive(Compact, Clone)]
        struct MSG_SomeTrait_some_method(pub usize);
        #[allow(non_camel_case_types)]
        #[derive(Copy, Clone)]
        struct MSG_SomeTrait_no_params_fate();
        #[allow(non_camel_case_types)]
        #[derive(Copy, Clone)]
        struct MSG_SomeTrait_some_default_impl_method();

        impl Actor for SomeActor {
            type ID = SomeActorID;

            fn id(&self) -> Self::ID {
                self.id
            }
            unsafe fn set_id(&mut self, id: RawID) {
                self.id = Self::ID::from_raw(id);
            }
        }

        #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
        pub struct SomeActorID {
            _raw_id: RawID
        }

        impl TypedID for SomeActorID {
            unsafe fn from_raw(id: RawID) -> Self {
                SomeActorID { _raw_id: id }
            }

            fn as_raw(&self) -> RawID {
                self._raw_id
            }
        }

        impl SomeActorID { }

        impl Into<SomeTraitID> for SomeActorID {
            fn into(self) -> SomeTraitID {
                unsafe {SomeTraitID::from_raw(self.as_raw())}
            }
        }

        impl Into<ForeignTraitID> for SomeActorID {
            fn into(self) -> ForeignTraitID {
                unsafe {ForeignTraitID::from_raw(self.as_raw())}
            }
        }

        #[allow(unused_variables)]
        #[allow(unused_mut)]
        pub fn auto_setup(system: &mut ActorSystem) {
            SomeTraitID::register_handlers::<SomeActor>(system);
            ForeignTraitID::register_handlers::<SomeActor>(system);
        }
    );

    assert_eq!(
        expected.into_string(),
        generate(&parse(&input.into_string()).unwrap())
    );
}
<|endoftext|>


<commit_before>use turtle::Turtle;

fn main() {
    let mut turtle = Turtle::new();

    turtle.right(90.0);
    turtle.set_pen_size(2.0);
    turtle.set_pen_color("yellow");

    for _ in 0..5 {
        turtle.forward(300.0);
        turtle.right(180.0 - (180.0 / 5.0));
    }
}
<commit_msg>Add variables to the `star` example<commit_after>//! This example draws star shapes.
//!
//! A star is a circle divided into points, and points are connected across the
//! interior of the circle, instead of to their neighbors.
//!
//! Imagine a five-pointed star. It is made by dividing a circle into five
//! points, and then connecting each point to its neighbors *two* steps away
//! instead of *one*. Connecting each point to its immediate neighbors draws a
//! pentagon, but connecting each point to farther neighbors draws a star.
//!
//! This relationship is true for many different numbers of points, and
//! distances between them. If we divide a circle into some number of points,
//! and pick a number of points around the circle to skip before drawing
//! connecting lines, we can draw all kinds of stars, and see the relationship
//! between the skip count, the point count, and the shape of the produced star.

use turtle::Turtle;

/// The winding number denotes how far around the circumference of the circle to
/// wind an imaginary string, before anchoring it to a point and pulling it
/// tight, as a chord across the interior of the circle.
///
/// Experiment with changing this number to see what shapes the turtle draws!
const WINDING: f64 = 3.0;

/// This divides the circle’s circumference into `n` equal sections.
///
/// Experiment with changing this number to see what shapes the turtle draws!
const POINTS: f64 = 5.0;

/// This computes the angle that the turtle rotates at each point in order to
/// “bounce” off the circle edge and draw the next line.
const TURN: f64 = 360.0 * WINDING / POINTS;

fn main() {
    let mut turtle = Turtle::new();

    turtle.right(90.0);
    turtle.set_pen_size(2.0);
    turtle.set_pen_color("yellow");

    for _ in 0.. POINTS as usize {
        turtle.forward(300.0);
        turtle.right(TURN);
    }
}
<|endoftext|>


<commit_before>//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website [https://serde.rs/] for additional documentation and
//! usage examples.
//!
//! [https://serde.rs/]: https://serde.rs/
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//!   used for IPC within the Servo rendering engine.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//!   size without the need for version negotiation.
//! - [YAML], a popular human-friendly configuration language that ain't markup
//!   language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [RON], a Rusty Object Notation.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//!   definition.
//! - [Hjson], a variant of JSON designed to be readable and writable by humans.
//! - [JSON5], A superset of JSON including some productions from ES5.
//! - [URL], the x-www-form-urlencoded format.
//! - [Envy], a way to deserialize environment variables into Rust structs.
//!   *(deserialization only)*
//! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into
//!   Rust structs. *(deserialization only)*
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/TyOverby/bincode
//! [CBOR]: https://github.com/pyfisch/cbor
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [Avro]: https://github.com/flavray/avro-rs
//! [Hjson]: https://github.com/laktak/hjson-rust
//! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [URL]: https://github.com/nox/serde_urlencoded
//! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: http://doc.crates.io/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html

////////////////////////////////////////////////////////////////////////////////

// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.90")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
//    https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(specialization, never_type))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Ignored clippy and clippy_pedantic lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        // not available in our oldest supported compiler
        const_static_lifetime,
        empty_enum,
        redundant_field_names,
        // integer and float ser/de requires these sorts of casts
        cast_possible_truncation,
        cast_possible_wrap,
        cast_precision_loss,
        cast_sign_loss,
        // things are often more readable this way
        cast_lossless,
        module_name_repetitions,
        single_match_else,
        type_complexity,
        use_self,
        zero_prefixed_literal,
        // not practical
        needless_pass_by_value,
        similar_names,
        // preference
        doc_markdown,
    )
)]
// Rustc lints.
#![deny(missing_docs, unused_imports)]

////////////////////////////////////////////////////////////////////////////////

#[cfg(feature = "alloc")]
extern crate alloc;

/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;
        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::{cmp, iter, mem, num, slice, str};
    pub use self::core::{f32, f64};
    pub use self::core::{i16, i32, i64, i8, isize};
    pub use self::core::{u16, u32, u64, u8, usize};

    pub use self::core::cell::{Cell, RefCell};
    pub use self::core::clone::{self, Clone};
    pub use self::core::convert::{self, From, Into};
    pub use self::core::default::{self, Default};
    pub use self::core::fmt::{self, Debug, Display};
    pub use self::core::marker::{self, PhantomData};
    pub use self::core::ops::Range;
    pub use self::core::option::{self, Option};
    pub use self::core::result::{self, Result};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::borrow::{Cow, ToOwned};
    #[cfg(feature = "std")]
    pub use std::borrow::{Cow, ToOwned};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::string::{String, ToString};
    #[cfg(feature = "std")]
    pub use std::string::String;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::vec::Vec;
    #[cfg(feature = "std")]
    pub use std::vec::Vec;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::boxed::Box;
    #[cfg(feature = "std")]
    pub use std::boxed::Box;

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::rc::{Rc, Weak as RcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::rc::{Rc, Weak as RcWeak};

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::sync::{Arc, Weak as ArcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::sync::{Arc, Weak as ArcWeak};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
    #[cfg(feature = "std")]
    pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};

    #[cfg(feature = "std")]
    pub use std::{error, net};

    #[cfg(feature = "std")]
    pub use std::collections::{HashMap, HashSet};
    #[cfg(feature = "std")]
    pub use std::ffi::{CStr, CString, OsStr, OsString};
    #[cfg(feature = "std")]
    pub use std::hash::{BuildHasher, Hash};
    #[cfg(feature = "std")]
    pub use std::io::Write;
    #[cfg(feature = "std")]
    pub use std::num::Wrapping;
    #[cfg(feature = "std")]
    pub use std::path::{Path, PathBuf};
    #[cfg(feature = "std")]
    pub use std::sync::{Mutex, RwLock};
    #[cfg(feature = "std")]
    pub use std::time::{SystemTime, UNIX_EPOCH};

    #[cfg(all(feature = "std", collections_bound))]
    pub use std::collections::Bound;

    #[cfg(core_reverse)]
    pub use self::core::cmp::Reverse;

    #[cfg(ops_bound)]
    pub use self::core::ops::Bound;

    #[cfg(range_inclusive)]
    pub use self::core::ops::RangeInclusive;

    #[cfg(any(core_duration, feature = "std"))]
    pub use self::core::time::Duration;
}

////////////////////////////////////////////////////////////////////////////////

#[macro_use]
mod macros;

#[macro_use]
mod integer128;

pub mod de;
pub mod ser;

#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};

// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
pub mod export;

// Helpers used by generated code and doc tests. Not public API.
#[doc(hidden)]
pub mod private;

// Re-export #[derive(Serialize, Deserialize)].
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;
<commit_msg>Remove link to hjson<commit_after>//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website [https://serde.rs/] for additional documentation and
//! usage examples.
//!
//! [https://serde.rs/]: https://serde.rs/
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//!   used for IPC within the Servo rendering engine.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//!   size without the need for version negotiation.
//! - [YAML], a popular human-friendly configuration language that ain't markup
//!   language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [RON], a Rusty Object Notation.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//!   definition.
//! - [JSON5], A superset of JSON including some productions from ES5.
//! - [URL], the x-www-form-urlencoded format.
//! - [Envy], a way to deserialize environment variables into Rust structs.
//!   *(deserialization only)*
//! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into
//!   Rust structs. *(deserialization only)*
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/TyOverby/bincode
//! [CBOR]: https://github.com/pyfisch/cbor
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [Avro]: https://github.com/flavray/avro-rs
//! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [URL]: https://github.com/nox/serde_urlencoded
//! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: http://doc.crates.io/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html

////////////////////////////////////////////////////////////////////////////////

// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.90")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
//    https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(specialization, never_type))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Ignored clippy and clippy_pedantic lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        // not available in our oldest supported compiler
        const_static_lifetime,
        empty_enum,
        redundant_field_names,
        // integer and float ser/de requires these sorts of casts
        cast_possible_truncation,
        cast_possible_wrap,
        cast_precision_loss,
        cast_sign_loss,
        // things are often more readable this way
        cast_lossless,
        module_name_repetitions,
        single_match_else,
        type_complexity,
        use_self,
        zero_prefixed_literal,
        // not practical
        needless_pass_by_value,
        similar_names,
        // preference
        doc_markdown,
    )
)]
// Rustc lints.
#![deny(missing_docs, unused_imports)]

////////////////////////////////////////////////////////////////////////////////

#[cfg(feature = "alloc")]
extern crate alloc;

/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;
        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::{cmp, iter, mem, num, slice, str};
    pub use self::core::{f32, f64};
    pub use self::core::{i16, i32, i64, i8, isize};
    pub use self::core::{u16, u32, u64, u8, usize};

    pub use self::core::cell::{Cell, RefCell};
    pub use self::core::clone::{self, Clone};
    pub use self::core::convert::{self, From, Into};
    pub use self::core::default::{self, Default};
    pub use self::core::fmt::{self, Debug, Display};
    pub use self::core::marker::{self, PhantomData};
    pub use self::core::ops::Range;
    pub use self::core::option::{self, Option};
    pub use self::core::result::{self, Result};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::borrow::{Cow, ToOwned};
    #[cfg(feature = "std")]
    pub use std::borrow::{Cow, ToOwned};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::string::{String, ToString};
    #[cfg(feature = "std")]
    pub use std::string::String;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::vec::Vec;
    #[cfg(feature = "std")]
    pub use std::vec::Vec;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::boxed::Box;
    #[cfg(feature = "std")]
    pub use std::boxed::Box;

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::rc::{Rc, Weak as RcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::rc::{Rc, Weak as RcWeak};

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::sync::{Arc, Weak as ArcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::sync::{Arc, Weak as ArcWeak};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
    #[cfg(feature = "std")]
    pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};

    #[cfg(feature = "std")]
    pub use std::{error, net};

    #[cfg(feature = "std")]
    pub use std::collections::{HashMap, HashSet};
    #[cfg(feature = "std")]
    pub use std::ffi::{CStr, CString, OsStr, OsString};
    #[cfg(feature = "std")]
    pub use std::hash::{BuildHasher, Hash};
    #[cfg(feature = "std")]
    pub use std::io::Write;
    #[cfg(feature = "std")]
    pub use std::num::Wrapping;
    #[cfg(feature = "std")]
    pub use std::path::{Path, PathBuf};
    #[cfg(feature = "std")]
    pub use std::sync::{Mutex, RwLock};
    #[cfg(feature = "std")]
    pub use std::time::{SystemTime, UNIX_EPOCH};

    #[cfg(all(feature = "std", collections_bound))]
    pub use std::collections::Bound;

    #[cfg(core_reverse)]
    pub use self::core::cmp::Reverse;

    #[cfg(ops_bound)]
    pub use self::core::ops::Bound;

    #[cfg(range_inclusive)]
    pub use self::core::ops::RangeInclusive;

    #[cfg(any(core_duration, feature = "std"))]
    pub use self::core::time::Duration;
}

////////////////////////////////////////////////////////////////////////////////

#[macro_use]
mod macros;

#[macro_use]
mod integer128;

pub mod de;
pub mod ser;

#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};

// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
pub mod export;

// Helpers used by generated code and doc tests. Not public API.
#[doc(hidden)]
pub mod private;

// Re-export #[derive(Serialize, Deserialize)].
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;
<|endoftext|>


<commit_before>//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website [https://serde.rs/] for additional documentation and
//! usage examples.
//!
//! [https://serde.rs/]: https://serde.rs/
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//!   used for IPC within the Servo rendering engine.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//!   size without the need for version negotiation.
//! - [YAML], a self-proclaimed human-friendly configuration language that ain't
//!   markup language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [RON], a Rusty Object Notation.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//!   definition.
//! - [JSON5], A superset of JSON including some productions from ES5.
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
//! - [URL], the x-www-form-urlencoded format.
//! - [Envy], a way to deserialize environment variables into Rust structs.
//!   *(deserialization only)*
//! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into
//!   Rust structs. *(deserialization only)*
//! - [S-expressions], the textual representation of code and data used by the
//!   Lisp language family.
//! - [D-Bus]'s binary wire format.
//! - [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy serialization format.
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/servo/bincode
//! [CBOR]: https://github.com/pyfisch/cbor
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [Avro]: https://github.com/flavray/avro-rs
//! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [Postcard]: https://github.com/jamesmunns/postcard
//! [URL]: https://github.com/nox/serde_urlencoded
//! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: http://doc.crates.io/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html
//! [S-expressions]: https://github.com/rotty/lexpr-rs
//! [D-Bus]: https://docs.rs/zvariant
//! [FlexBuffers]: https://github.com/google/flatbuffers/tree/master/rust/flexbuffers

////////////////////////////////////////////////////////////////////////////////

// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.115")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
//    https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(never_type))]
#![allow(unknown_lints, bare_trait_objects, deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Ignored clippy and clippy_pedantic lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
        unnested_or_patterns,
        // not available in our oldest supported compiler
        checked_conversions,
        empty_enum,
        redundant_field_names,
        redundant_static_lifetimes,
        // integer and float ser/de requires these sorts of casts
        cast_possible_truncation,
        cast_possible_wrap,
        cast_sign_loss,
        // things are often more readable this way
        cast_lossless,
        module_name_repetitions,
        option_if_let_else,
        single_match_else,
        type_complexity,
        use_self,
        zero_prefixed_literal,
        // correctly used
        enum_glob_use,
        wildcard_imports,
        // not practical
        needless_pass_by_value,
        similar_names,
        too_many_lines,
        // preference
        doc_markdown,
        unseparated_literal_suffix,
        // false positive
        needless_doctest_main,
        // noisy
        missing_errors_doc,
        must_use_candidate,
    )
)]
// Rustc lints.
#![forbid(unsafe_code)]
#![deny(missing_docs, unused_imports)]

////////////////////////////////////////////////////////////////////////////////

#[cfg(feature = "alloc")]
extern crate alloc;

/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;
        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::{cmp, iter, mem, num, slice, str};
    pub use self::core::{f32, f64};
    pub use self::core::{i16, i32, i64, i8, isize};
    pub use self::core::{u16, u32, u64, u8, usize};

    pub use self::core::cell::{Cell, RefCell};
    pub use self::core::clone::{self, Clone};
    pub use self::core::convert::{self, From, Into};
    pub use self::core::default::{self, Default};
    pub use self::core::fmt::{self, Debug, Display};
    pub use self::core::marker::{self, PhantomData};
    pub use self::core::ops::Range;
    pub use self::core::option::{self, Option};
    pub use self::core::result::{self, Result};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::borrow::{Cow, ToOwned};
    #[cfg(feature = "std")]
    pub use std::borrow::{Cow, ToOwned};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::string::{String, ToString};
    #[cfg(feature = "std")]
    pub use std::string::{String, ToString};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::vec::Vec;
    #[cfg(feature = "std")]
    pub use std::vec::Vec;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::boxed::Box;
    #[cfg(feature = "std")]
    pub use std::boxed::Box;

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::rc::{Rc, Weak as RcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::rc::{Rc, Weak as RcWeak};

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::sync::{Arc, Weak as ArcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::sync::{Arc, Weak as ArcWeak};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
    #[cfg(feature = "std")]
    pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};

    #[cfg(feature = "std")]
    pub use std::{error, net};

    #[cfg(feature = "std")]
    pub use std::collections::{HashMap, HashSet};
    #[cfg(feature = "std")]
    pub use std::ffi::{CStr, CString, OsStr, OsString};
    #[cfg(feature = "std")]
    pub use std::hash::{BuildHasher, Hash};
    #[cfg(feature = "std")]
    pub use std::io::Write;
    #[cfg(feature = "std")]
    pub use std::num::Wrapping;
    #[cfg(feature = "std")]
    pub use std::path::{Path, PathBuf};
    #[cfg(feature = "std")]
    pub use std::sync::{Mutex, RwLock};
    #[cfg(feature = "std")]
    pub use std::time::{SystemTime, UNIX_EPOCH};

    #[cfg(all(feature = "std", collections_bound))]
    pub use std::collections::Bound;

    #[cfg(core_reverse)]
    pub use self::core::cmp::Reverse;

    #[cfg(ops_bound)]
    pub use self::core::ops::Bound;

    #[cfg(range_inclusive)]
    pub use self::core::ops::RangeInclusive;

    #[cfg(all(feature = "std", std_atomic))]
    pub use std::sync::atomic::{
        AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
        AtomicUsize, Ordering,
    };
    #[cfg(all(feature = "std", std_atomic64))]
    pub use std::sync::atomic::{AtomicI64, AtomicU64};

    #[cfg(any(core_duration, feature = "std"))]
    pub use self::core::time::Duration;
}

////////////////////////////////////////////////////////////////////////////////

#[macro_use]
mod macros;

#[macro_use]
mod integer128;

pub mod de;
pub mod ser;

#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};

// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
pub mod export;

// Helpers used by generated code and doc tests. Not public API.
#[doc(hidden)]
pub mod private;

#[cfg(not(feature = "std"))]
mod std_error;

// Re-export #[derive(Serialize, Deserialize)].
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;
<commit_msg>Replace serde_urlencoded link with serde_qs<commit_after>//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website [https://serde.rs/] for additional documentation and
//! usage examples.
//!
//! [https://serde.rs/]: https://serde.rs/
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//!   used for IPC within the Servo rendering engine.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//!   size without the need for version negotiation.
//! - [YAML], a self-proclaimed human-friendly configuration language that ain't
//!   markup language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [RON], a Rusty Object Notation.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//!   definition.
//! - [JSON5], A superset of JSON including some productions from ES5.
//! - [Postcard], a no\_std and embedded-systems friendly compact binary format.
//! - [URL] query strings, in the x-www-form-urlencoded format.
//! - [Envy], a way to deserialize environment variables into Rust structs.
//!   *(deserialization only)*
//! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into
//!   Rust structs. *(deserialization only)*
//! - [S-expressions], the textual representation of code and data used by the
//!   Lisp language family.
//! - [D-Bus]'s binary wire format.
//! - [FlexBuffers], the schemaless cousin of Google's FlatBuffers zero-copy serialization format.
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/servo/bincode
//! [CBOR]: https://github.com/pyfisch/cbor
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [Avro]: https://github.com/flavray/avro-rs
//! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [Postcard]: https://github.com/jamesmunns/postcard
//! [URL]: https://docs.rs/serde_qs
//! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: http://doc.crates.io/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html
//! [S-expressions]: https://github.com/rotty/lexpr-rs
//! [D-Bus]: https://docs.rs/zvariant
//! [FlexBuffers]: https://github.com/google/flatbuffers/tree/master/rust/flexbuffers

////////////////////////////////////////////////////////////////////////////////

// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.115")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
//    https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(never_type))]
#![allow(unknown_lints, bare_trait_objects, deprecated)]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Ignored clippy and clippy_pedantic lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        // clippy bug: https://github.com/rust-lang/rust-clippy/issues/5704
        unnested_or_patterns,
        // not available in our oldest supported compiler
        checked_conversions,
        empty_enum,
        redundant_field_names,
        redundant_static_lifetimes,
        // integer and float ser/de requires these sorts of casts
        cast_possible_truncation,
        cast_possible_wrap,
        cast_sign_loss,
        // things are often more readable this way
        cast_lossless,
        module_name_repetitions,
        option_if_let_else,
        single_match_else,
        type_complexity,
        use_self,
        zero_prefixed_literal,
        // correctly used
        enum_glob_use,
        wildcard_imports,
        // not practical
        needless_pass_by_value,
        similar_names,
        too_many_lines,
        // preference
        doc_markdown,
        unseparated_literal_suffix,
        // false positive
        needless_doctest_main,
        // noisy
        missing_errors_doc,
        must_use_candidate,
    )
)]
// Rustc lints.
#![forbid(unsafe_code)]
#![deny(missing_docs, unused_imports)]

////////////////////////////////////////////////////////////////////////////////

#[cfg(feature = "alloc")]
extern crate alloc;

/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;
        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::{cmp, iter, mem, num, slice, str};
    pub use self::core::{f32, f64};
    pub use self::core::{i16, i32, i64, i8, isize};
    pub use self::core::{u16, u32, u64, u8, usize};

    pub use self::core::cell::{Cell, RefCell};
    pub use self::core::clone::{self, Clone};
    pub use self::core::convert::{self, From, Into};
    pub use self::core::default::{self, Default};
    pub use self::core::fmt::{self, Debug, Display};
    pub use self::core::marker::{self, PhantomData};
    pub use self::core::ops::Range;
    pub use self::core::option::{self, Option};
    pub use self::core::result::{self, Result};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::borrow::{Cow, ToOwned};
    #[cfg(feature = "std")]
    pub use std::borrow::{Cow, ToOwned};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::string::{String, ToString};
    #[cfg(feature = "std")]
    pub use std::string::{String, ToString};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::vec::Vec;
    #[cfg(feature = "std")]
    pub use std::vec::Vec;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::boxed::Box;
    #[cfg(feature = "std")]
    pub use std::boxed::Box;

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::rc::{Rc, Weak as RcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::rc::{Rc, Weak as RcWeak};

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::sync::{Arc, Weak as ArcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::sync::{Arc, Weak as ArcWeak};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
    #[cfg(feature = "std")]
    pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};

    #[cfg(feature = "std")]
    pub use std::{error, net};

    #[cfg(feature = "std")]
    pub use std::collections::{HashMap, HashSet};
    #[cfg(feature = "std")]
    pub use std::ffi::{CStr, CString, OsStr, OsString};
    #[cfg(feature = "std")]
    pub use std::hash::{BuildHasher, Hash};
    #[cfg(feature = "std")]
    pub use std::io::Write;
    #[cfg(feature = "std")]
    pub use std::num::Wrapping;
    #[cfg(feature = "std")]
    pub use std::path::{Path, PathBuf};
    #[cfg(feature = "std")]
    pub use std::sync::{Mutex, RwLock};
    #[cfg(feature = "std")]
    pub use std::time::{SystemTime, UNIX_EPOCH};

    #[cfg(all(feature = "std", collections_bound))]
    pub use std::collections::Bound;

    #[cfg(core_reverse)]
    pub use self::core::cmp::Reverse;

    #[cfg(ops_bound)]
    pub use self::core::ops::Bound;

    #[cfg(range_inclusive)]
    pub use self::core::ops::RangeInclusive;

    #[cfg(all(feature = "std", std_atomic))]
    pub use std::sync::atomic::{
        AtomicBool, AtomicI16, AtomicI32, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU8,
        AtomicUsize, Ordering,
    };
    #[cfg(all(feature = "std", std_atomic64))]
    pub use std::sync::atomic::{AtomicI64, AtomicU64};

    #[cfg(any(core_duration, feature = "std"))]
    pub use self::core::time::Duration;
}

////////////////////////////////////////////////////////////////////////////////

#[macro_use]
mod macros;

#[macro_use]
mod integer128;

pub mod de;
pub mod ser;

#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};

// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
pub mod export;

// Helpers used by generated code and doc tests. Not public API.
#[doc(hidden)]
pub mod private;

#[cfg(not(feature = "std"))]
mod std_error;

// Re-export #[derive(Serialize, Deserialize)].
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;
<|endoftext|>


<commit_before>//! ra_analyzer crate is the brain of Rust analyzer. It relies on the `salsa`
//! crate, which provides and incremental on-demand database of facts.

macro_rules! ctry {
    ($expr:expr) => {
        match $expr {
            None => return Ok(None),
            Some(it) => it,
        }
    };
}

mod db;
mod imp;
mod completion;
mod symbol_index;
pub mod mock_analysis;
mod runnables;

mod extend_selection;
mod syntax_highlighting;

use std::{fmt, sync::Arc};

use rustc_hash::FxHashMap;
use ra_syntax::{SourceFileNode, TextRange, TextUnit, SmolStr, SyntaxKind};
use ra_text_edit::TextEdit;
use rayon::prelude::*;
use relative_path::RelativePathBuf;
use salsa::ParallelDatabase;

use crate::symbol_index::{SymbolIndex, FileSymbol};

pub use crate::{
    completion::{CompletionItem, CompletionItemKind, InsertText},
    runnables::{Runnable, RunnableKind},
};
pub use ra_editor::{
    Fold, FoldKind, HighlightedRange, LineIndex, StructureNode, Severity
};
pub use hir::FnSignatureInfo;

pub use ra_db::{
    Canceled, Cancelable, FilePosition, FileRange,
    CrateGraph, CrateId, SourceRootId, FileId, SyntaxDatabase, FilesDatabase
};

#[derive(Default)]
pub struct AnalysisChange {
    new_roots: Vec<(SourceRootId, bool)>,
    roots_changed: FxHashMap<SourceRootId, RootChange>,
    files_changed: Vec<(FileId, Arc<String>)>,
    libraries_added: Vec<LibraryData>,
    crate_graph: Option<CrateGraph>,
}

#[derive(Default)]
struct RootChange {
    added: Vec<AddFile>,
    removed: Vec<RemoveFile>,
}

#[derive(Debug)]
struct AddFile {
    file_id: FileId,
    path: RelativePathBuf,
    text: Arc<String>,
}

#[derive(Debug)]
struct RemoveFile {
    file_id: FileId,
    path: RelativePathBuf,
}

impl fmt::Debug for AnalysisChange {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let mut d = fmt.debug_struct("AnalysisChange");
        if !self.new_roots.is_empty() {
            d.field("new_roots", &self.new_roots);
        }
        if !self.roots_changed.is_empty() {
            d.field("roots_changed", &self.roots_changed);
        }
        if !self.files_changed.is_empty() {
            d.field("files_changed", &self.files_changed.len());
        }
        if !self.libraries_added.is_empty() {
            d.field("libraries_added", &self.libraries_added.len());
        }
        if !self.crate_graph.is_some() {
            d.field("crate_graph", &self.crate_graph);
        }
        d.finish()
    }
}

impl fmt::Debug for RootChange {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("AnalysisChange")
            .field("added", &self.added.len())
            .field("removed", &self.removed.len())
            .finish()
    }
}

impl AnalysisChange {
    pub fn new() -> AnalysisChange {
        AnalysisChange::default()
    }
    pub fn add_root(&mut self, root_id: SourceRootId, is_local: bool) {
        self.new_roots.push((root_id, is_local));
    }
    pub fn add_file(
        &mut self,
        root_id: SourceRootId,
        file_id: FileId,
        path: RelativePathBuf,
        text: Arc<String>,
    ) {
        let file = AddFile {
            file_id,
            path,
            text,
        };
        self.roots_changed
            .entry(root_id)
            .or_default()
            .added
            .push(file);
    }
    pub fn change_file(&mut self, file_id: FileId, new_text: Arc<String>) {
        self.files_changed.push((file_id, new_text))
    }
    pub fn remove_file(&mut self, root_id: SourceRootId, file_id: FileId, path: RelativePathBuf) {
        let file = RemoveFile { file_id, path };
        self.roots_changed
            .entry(root_id)
            .or_default()
            .removed
            .push(file);
    }
    pub fn add_library(&mut self, data: LibraryData) {
        self.libraries_added.push(data)
    }
    pub fn set_crate_graph(&mut self, graph: CrateGraph) {
        self.crate_graph = Some(graph);
    }
}

/// `AnalysisHost` stores the current state of the world.
#[derive(Debug, Default)]
pub struct AnalysisHost {
    db: db::RootDatabase,
}

impl AnalysisHost {
    /// Returns a snapshot of the current state, which you can query for
    /// semantic information.
    pub fn analysis(&self) -> Analysis {
        Analysis {
            db: self.db.snapshot(),
        }
    }
    /// Applies changes to the current state of the world. If there are
    /// outstanding snapshots, they will be canceled.
    pub fn apply_change(&mut self, change: AnalysisChange) {
        self.db.apply_change(change)
    }
}

#[derive(Debug)]
pub struct SourceChange {
    pub label: String,
    pub source_file_edits: Vec<SourceFileEdit>,
    pub file_system_edits: Vec<FileSystemEdit>,
    pub cursor_position: Option<FilePosition>,
}

#[derive(Debug)]
pub struct SourceFileEdit {
    pub file_id: FileId,
    pub edit: TextEdit,
}

#[derive(Debug)]
pub enum FileSystemEdit {
    CreateFile {
        source_root: SourceRootId,
        path: RelativePathBuf,
    },
    MoveFile {
        src: FileId,
        dst_source_root: SourceRootId,
        dst_path: RelativePathBuf,
    },
}

#[derive(Debug)]
pub struct Diagnostic {
    pub message: String,
    pub range: TextRange,
    pub fix: Option<SourceChange>,
    pub severity: Severity,
}

#[derive(Debug)]
pub struct Query {
    query: String,
    lowercased: String,
    only_types: bool,
    libs: bool,
    exact: bool,
    limit: usize,
}

impl Query {
    pub fn new(query: String) -> Query {
        let lowercased = query.to_lowercase();
        Query {
            query,
            lowercased,
            only_types: false,
            libs: false,
            exact: false,
            limit: usize::max_value(),
        }
    }
    pub fn only_types(&mut self) {
        self.only_types = true;
    }
    pub fn libs(&mut self) {
        self.libs = true;
    }
    pub fn exact(&mut self) {
        self.exact = true;
    }
    pub fn limit(&mut self, limit: usize) {
        self.limit = limit
    }
}

#[derive(Debug)]
pub struct NavigationTarget {
    file_id: FileId,
    symbol: FileSymbol,
}

impl NavigationTarget {
    pub fn name(&self) -> SmolStr {
        self.symbol.name.clone()
    }
    pub fn kind(&self) -> SyntaxKind {
        self.symbol.kind
    }
    pub fn file_id(&self) -> FileId {
        self.file_id
    }
    pub fn range(&self) -> TextRange {
        self.symbol.node_range
    }
}

/// Result of "goto def" query.
#[derive(Debug)]
pub struct ReferenceResolution {
    /// The range of the reference itself. Client does not know what constitutes
    /// a reference, it handles us only the offset. It's helpful to tell the
    /// client where the reference was.
    pub reference_range: TextRange,
    /// What this reference resolves to.
    pub resolves_to: Vec<NavigationTarget>,
}

impl ReferenceResolution {
    fn new(reference_range: TextRange) -> ReferenceResolution {
        ReferenceResolution {
            reference_range,
            resolves_to: Vec::new(),
        }
    }

    fn add_resolution(&mut self, file_id: FileId, symbol: FileSymbol) {
        self.resolves_to.push(NavigationTarget { file_id, symbol })
    }
}

/// Analysis is a snapshot of a world state at a moment in time. It is the main
/// entry point for asking semantic information about the world. When the world
/// state is advanced using `AnalysisHost::apply_change` method, all existing
/// `Analysis` are canceled (most method return `Err(Canceled)`).
#[derive(Debug)]
pub struct Analysis {
    db: salsa::Snapshot<db::RootDatabase>,
}

impl Analysis {
    pub fn file_text(&self, file_id: FileId) -> Arc<String> {
        self.db.file_text(file_id)
    }
    pub fn file_syntax(&self, file_id: FileId) -> SourceFileNode {
        self.db.source_file(file_id).clone()
    }
    pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> {
        self.db.file_lines(file_id)
    }
    pub fn extend_selection(&self, frange: FileRange) -> TextRange {
        extend_selection::extend_selection(&self.db, frange)
    }
    pub fn matching_brace(&self, file: &SourceFileNode, offset: TextUnit) -> Option<TextUnit> {
        ra_editor::matching_brace(file, offset)
    }
    pub fn syntax_tree(&self, file_id: FileId) -> String {
        let file = self.db.source_file(file_id);
        ra_editor::syntax_tree(&file)
    }
    pub fn join_lines(&self, frange: FileRange) -> SourceChange {
        let file = self.db.source_file(frange.file_id);
        SourceChange::from_local_edit(frange.file_id, ra_editor::join_lines(&file, frange.range))
    }
    pub fn on_enter(&self, position: FilePosition) -> Option<SourceChange> {
        let file = self.db.source_file(position.file_id);
        let edit = ra_editor::on_enter(&file, position.offset)?;
        let res = SourceChange::from_local_edit(position.file_id, edit);
        Some(res)
    }
    pub fn on_eq_typed(&self, position: FilePosition) -> Option<SourceChange> {
        let file = self.db.source_file(position.file_id);
        Some(SourceChange::from_local_edit(
            position.file_id,
            ra_editor::on_eq_typed(&file, position.offset)?,
        ))
    }
    pub fn file_structure(&self, file_id: FileId) -> Vec<StructureNode> {
        let file = self.db.source_file(file_id);
        ra_editor::file_structure(&file)
    }
    pub fn folding_ranges(&self, file_id: FileId) -> Vec<Fold> {
        let file = self.db.source_file(file_id);
        ra_editor::folding_ranges(&file)
    }
    pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<NavigationTarget>> {
        let res = symbol_index::world_symbols(&*self.db, query)?
            .into_iter()
            .map(|(file_id, symbol)| NavigationTarget { file_id, symbol })
            .collect();
        Ok(res)
    }
    pub fn approximately_resolve_symbol(
        &self,
        position: FilePosition,
    ) -> Cancelable<Option<ReferenceResolution>> {
        self.db.approximately_resolve_symbol(position)
    }
    pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
        self.db.find_all_refs(position)
    }
    pub fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable<Option<String>> {
        self.db.doc_text_for(nav)
    }
    pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<NavigationTarget>> {
        self.db.parent_module(position)
    }
    pub fn module_path(&self, position: FilePosition) -> Cancelable<Option<String>> {
        self.db.module_path(position)
    }
    pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
        self.db.crate_for(file_id)
    }
    pub fn crate_root(&self, crate_id: CrateId) -> Cancelable<FileId> {
        Ok(self.db.crate_root(crate_id))
    }
    pub fn runnables(&self, file_id: FileId) -> Cancelable<Vec<Runnable>> {
        let file = self.db.source_file(file_id);
        Ok(runnables::runnables(self, &file, file_id))
    }
    pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> {
        syntax_highlighting::highlight(&*self.db, file_id)
    }
    pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> {
        let completions = completion::completions(&self.db, position)?;
        Ok(completions.map(|it| it.into()))
    }
    pub fn assists(&self, frange: FileRange) -> Cancelable<Vec<SourceChange>> {
        Ok(self.db.assists(frange))
    }
    pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> {
        self.db.diagnostics(file_id)
    }
    pub fn resolve_callable(
        &self,
        position: FilePosition,
    ) -> Cancelable<Option<(FnSignatureInfo, Option<usize>)>> {
        self.db.resolve_callable(position)
    }
    pub fn type_of(&self, frange: FileRange) -> Cancelable<Option<String>> {
        self.db.type_of(frange)
    }
    pub fn rename(
        &self,
        position: FilePosition,
        new_name: &str,
    ) -> Cancelable<Vec<SourceFileEdit>> {
        self.db.rename(position, new_name)
    }
}

pub struct LibraryData {
    root_id: SourceRootId,
    root_change: RootChange,
    symbol_index: SymbolIndex,
}

impl fmt::Debug for LibraryData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("LibraryData")
            .field("root_id", &self.root_id)
            .field("root_change", &self.root_change)
            .field("n_symbols", &self.symbol_index.len())
            .finish()
    }
}

impl LibraryData {
    pub fn prepare(
        root_id: SourceRootId,
        files: Vec<(FileId, RelativePathBuf, Arc<String>)>,
    ) -> LibraryData {
        let symbol_index = SymbolIndex::for_files(files.par_iter().map(|(file_id, _, text)| {
            let file = SourceFileNode::parse(text);
            (*file_id, file)
        }));
        let mut root_change = RootChange::default();
        root_change.added = files
            .into_iter()
            .map(|(file_id, path, text)| AddFile {
                file_id,
                path,
                text,
            })
            .collect();
        LibraryData {
            root_id,
            root_change,
            symbol_index,
        }
    }
}

#[test]
fn analysis_is_send() {
    fn is_send<T: Send>() {}
    is_send::<Analysis>();
}
<commit_msg>doctrings<commit_after>//! ra_analyzer crate is the brain of Rust analyzer. It relies on the `salsa`
//! crate, which provides and incremental on-demand database of facts.

macro_rules! ctry {
    ($expr:expr) => {
        match $expr {
            None => return Ok(None),
            Some(it) => it,
        }
    };
}

mod db;
mod imp;
mod completion;
mod symbol_index;
pub mod mock_analysis;
mod runnables;

mod extend_selection;
mod syntax_highlighting;

use std::{fmt, sync::Arc};

use rustc_hash::FxHashMap;
use ra_syntax::{SourceFileNode, TextRange, TextUnit, SmolStr, SyntaxKind};
use ra_text_edit::TextEdit;
use rayon::prelude::*;
use relative_path::RelativePathBuf;
use salsa::ParallelDatabase;

use crate::symbol_index::{SymbolIndex, FileSymbol};

pub use crate::{
    completion::{CompletionItem, CompletionItemKind, InsertText},
    runnables::{Runnable, RunnableKind},
};
pub use ra_editor::{
    Fold, FoldKind, HighlightedRange, LineIndex, StructureNode, Severity
};
pub use hir::FnSignatureInfo;

pub use ra_db::{
    Canceled, Cancelable, FilePosition, FileRange,
    CrateGraph, CrateId, SourceRootId, FileId, SyntaxDatabase, FilesDatabase
};

#[derive(Default)]
pub struct AnalysisChange {
    new_roots: Vec<(SourceRootId, bool)>,
    roots_changed: FxHashMap<SourceRootId, RootChange>,
    files_changed: Vec<(FileId, Arc<String>)>,
    libraries_added: Vec<LibraryData>,
    crate_graph: Option<CrateGraph>,
}

#[derive(Default)]
struct RootChange {
    added: Vec<AddFile>,
    removed: Vec<RemoveFile>,
}

#[derive(Debug)]
struct AddFile {
    file_id: FileId,
    path: RelativePathBuf,
    text: Arc<String>,
}

#[derive(Debug)]
struct RemoveFile {
    file_id: FileId,
    path: RelativePathBuf,
}

impl fmt::Debug for AnalysisChange {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        let mut d = fmt.debug_struct("AnalysisChange");
        if !self.new_roots.is_empty() {
            d.field("new_roots", &self.new_roots);
        }
        if !self.roots_changed.is_empty() {
            d.field("roots_changed", &self.roots_changed);
        }
        if !self.files_changed.is_empty() {
            d.field("files_changed", &self.files_changed.len());
        }
        if !self.libraries_added.is_empty() {
            d.field("libraries_added", &self.libraries_added.len());
        }
        if !self.crate_graph.is_some() {
            d.field("crate_graph", &self.crate_graph);
        }
        d.finish()
    }
}

impl fmt::Debug for RootChange {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("AnalysisChange")
            .field("added", &self.added.len())
            .field("removed", &self.removed.len())
            .finish()
    }
}

impl AnalysisChange {
    pub fn new() -> AnalysisChange {
        AnalysisChange::default()
    }
    pub fn add_root(&mut self, root_id: SourceRootId, is_local: bool) {
        self.new_roots.push((root_id, is_local));
    }
    pub fn add_file(
        &mut self,
        root_id: SourceRootId,
        file_id: FileId,
        path: RelativePathBuf,
        text: Arc<String>,
    ) {
        let file = AddFile {
            file_id,
            path,
            text,
        };
        self.roots_changed
            .entry(root_id)
            .or_default()
            .added
            .push(file);
    }
    pub fn change_file(&mut self, file_id: FileId, new_text: Arc<String>) {
        self.files_changed.push((file_id, new_text))
    }
    pub fn remove_file(&mut self, root_id: SourceRootId, file_id: FileId, path: RelativePathBuf) {
        let file = RemoveFile { file_id, path };
        self.roots_changed
            .entry(root_id)
            .or_default()
            .removed
            .push(file);
    }
    pub fn add_library(&mut self, data: LibraryData) {
        self.libraries_added.push(data)
    }
    pub fn set_crate_graph(&mut self, graph: CrateGraph) {
        self.crate_graph = Some(graph);
    }
}

#[derive(Debug)]
pub struct SourceChange {
    pub label: String,
    pub source_file_edits: Vec<SourceFileEdit>,
    pub file_system_edits: Vec<FileSystemEdit>,
    pub cursor_position: Option<FilePosition>,
}

#[derive(Debug)]
pub struct SourceFileEdit {
    pub file_id: FileId,
    pub edit: TextEdit,
}

#[derive(Debug)]
pub enum FileSystemEdit {
    CreateFile {
        source_root: SourceRootId,
        path: RelativePathBuf,
    },
    MoveFile {
        src: FileId,
        dst_source_root: SourceRootId,
        dst_path: RelativePathBuf,
    },
}

#[derive(Debug)]
pub struct Diagnostic {
    pub message: String,
    pub range: TextRange,
    pub fix: Option<SourceChange>,
    pub severity: Severity,
}

#[derive(Debug)]
pub struct Query {
    query: String,
    lowercased: String,
    only_types: bool,
    libs: bool,
    exact: bool,
    limit: usize,
}

impl Query {
    pub fn new(query: String) -> Query {
        let lowercased = query.to_lowercase();
        Query {
            query,
            lowercased,
            only_types: false,
            libs: false,
            exact: false,
            limit: usize::max_value(),
        }
    }
    pub fn only_types(&mut self) {
        self.only_types = true;
    }
    pub fn libs(&mut self) {
        self.libs = true;
    }
    pub fn exact(&mut self) {
        self.exact = true;
    }
    pub fn limit(&mut self, limit: usize) {
        self.limit = limit
    }
}

#[derive(Debug)]
pub struct NavigationTarget {
    file_id: FileId,
    symbol: FileSymbol,
}

impl NavigationTarget {
    pub fn name(&self) -> SmolStr {
        self.symbol.name.clone()
    }
    pub fn kind(&self) -> SyntaxKind {
        self.symbol.kind
    }
    pub fn file_id(&self) -> FileId {
        self.file_id
    }
    pub fn range(&self) -> TextRange {
        self.symbol.node_range
    }
}

/// Result of "goto def" query.
#[derive(Debug)]
pub struct ReferenceResolution {
    /// The range of the reference itself. Client does not know what constitutes
    /// a reference, it handles us only the offset. It's helpful to tell the
    /// client where the reference was.
    pub reference_range: TextRange,
    /// What this reference resolves to.
    pub resolves_to: Vec<NavigationTarget>,
}

impl ReferenceResolution {
    fn new(reference_range: TextRange) -> ReferenceResolution {
        ReferenceResolution {
            reference_range,
            resolves_to: Vec::new(),
        }
    }

    fn add_resolution(&mut self, file_id: FileId, symbol: FileSymbol) {
        self.resolves_to.push(NavigationTarget { file_id, symbol })
    }
}

/// `AnalysisHost` stores the current state of the world.
#[derive(Debug, Default)]
pub struct AnalysisHost {
    db: db::RootDatabase,
}

impl AnalysisHost {
    /// Returns a snapshot of the current state, which you can query for
    /// semantic information.
    pub fn analysis(&self) -> Analysis {
        Analysis {
            db: self.db.snapshot(),
        }
    }
    /// Applies changes to the current state of the world. If there are
    /// outstanding snapshots, they will be canceled.
    pub fn apply_change(&mut self, change: AnalysisChange) {
        self.db.apply_change(change)
    }
}

/// Analysis is a snapshot of a world state at a moment in time. It is the main
/// entry point for asking semantic information about the world. When the world
/// state is advanced using `AnalysisHost::apply_change` method, all existing
/// `Analysis` are canceled (most method return `Err(Canceled)`).
#[derive(Debug)]
pub struct Analysis {
    db: salsa::Snapshot<db::RootDatabase>,
}

impl Analysis {
    /// Gets the text of the source file.
    pub fn file_text(&self, file_id: FileId) -> Arc<String> {
        self.db.file_text(file_id)
    }
    /// Gets the syntax tree of the file.
    pub fn file_syntax(&self, file_id: FileId) -> SourceFileNode {
        self.db.source_file(file_id).clone()
    }
    /// Gets the file's `LineIndex`: data structure to convert between absolute
    /// offsets and line/column representation.
    pub fn file_line_index(&self, file_id: FileId) -> Arc<LineIndex> {
        self.db.file_lines(file_id)
    }
    /// Selects the next syntactic nodes encopasing the range.
    pub fn extend_selection(&self, frange: FileRange) -> TextRange {
        extend_selection::extend_selection(&self.db, frange)
    }
    /// Returns position of the mathcing brace (all types of braces are
    /// supported).
    pub fn matching_brace(&self, file: &SourceFileNode, offset: TextUnit) -> Option<TextUnit> {
        ra_editor::matching_brace(file, offset)
    }
    /// Returns a syntax tree represented as `String`, for debug purposes.
    // FIXME: use a better name here.
    pub fn syntax_tree(&self, file_id: FileId) -> String {
        let file = self.db.source_file(file_id);
        ra_editor::syntax_tree(&file)
    }
    /// Returns an edit to remove all newlines in the range, cleaning up minor
    /// stuff like trailing commas.
    pub fn join_lines(&self, frange: FileRange) -> SourceChange {
        let file = self.db.source_file(frange.file_id);
        SourceChange::from_local_edit(frange.file_id, ra_editor::join_lines(&file, frange.range))
    }
    /// Returns an edit which should be applied when opening a new line, fixing
    /// up minor stuff like continuing the comment.
    pub fn on_enter(&self, position: FilePosition) -> Option<SourceChange> {
        let file = self.db.source_file(position.file_id);
        let edit = ra_editor::on_enter(&file, position.offset)?;
        Some(SourceChange::from_local_edit(position.file_id, edit))
    }
    /// Returns an edit which should be applied after `=` was typed. Primaraly,
    /// this works when adding `let =`.
    // FIXME: use a snippet completion instead of this hack here.
    pub fn on_eq_typed(&self, position: FilePosition) -> Option<SourceChange> {
        let file = self.db.source_file(position.file_id);
        let edit = ra_editor::on_eq_typed(&file, position.offset)?;
        Some(SourceChange::from_local_edit(position.file_id, edit))
    }
    /// Returns a tree representation of symbols in the file. Useful to draw a
    /// file outline.
    pub fn file_structure(&self, file_id: FileId) -> Vec<StructureNode> {
        let file = self.db.source_file(file_id);
        ra_editor::file_structure(&file)
    }
    /// Returns the set of folding ranges.
    pub fn folding_ranges(&self, file_id: FileId) -> Vec<Fold> {
        let file = self.db.source_file(file_id);
        ra_editor::folding_ranges(&file)
    }
    /// Fuzzy searches for a symbol.
    pub fn symbol_search(&self, query: Query) -> Cancelable<Vec<NavigationTarget>> {
        let res = symbol_index::world_symbols(self.db, query)?
            .into_iter()
            .map(|(file_id, symbol)| NavigationTarget { file_id, symbol })
            .collect();
        Ok(res)
    }
    /// Resolves reference to definition, but does not gurantee correctness.
    pub fn approximately_resolve_symbol(
        &self,
        position: FilePosition,
    ) -> Cancelable<Option<ReferenceResolution>> {
        self.db.approximately_resolve_symbol(position)
    }
    /// Finds all usages of the reference at point.
    pub fn find_all_refs(&self, position: FilePosition) -> Cancelable<Vec<(FileId, TextRange)>> {
        self.db.find_all_refs(position)
    }
    /// Returns documentation string for a given target.
    pub fn doc_text_for(&self, nav: NavigationTarget) -> Cancelable<Option<String>> {
        self.db.doc_text_for(nav)
    }
    /// Returns a `mod name;` declaration whihc created the current module.
    pub fn parent_module(&self, position: FilePosition) -> Cancelable<Vec<NavigationTarget>> {
        self.db.parent_module(position)
    }
    /// Returns `::` separated path to the current module from the crate root.
    pub fn module_path(&self, position: FilePosition) -> Cancelable<Option<String>> {
        self.db.module_path(position)
    }
    /// Returns crates this file belongs too.
    pub fn crate_for(&self, file_id: FileId) -> Cancelable<Vec<CrateId>> {
        self.db.crate_for(file_id)
    }
    /// Returns the root file of the given crate.
    pub fn crate_root(&self, crate_id: CrateId) -> Cancelable<FileId> {
        Ok(self.db.crate_root(crate_id))
    }
    /// Returns the set of possible targets to run for the current file.
    pub fn runnables(&self, file_id: FileId) -> Cancelable<Vec<Runnable>> {
        let file = self.db.source_file(file_id);
        Ok(runnables::runnables(self, &file, file_id))
    }
    /// Computes syntax highlighting for the given file.
    pub fn highlight(&self, file_id: FileId) -> Cancelable<Vec<HighlightedRange>> {
        syntax_highlighting::highlight(&*self.db, file_id)
    }
    /// Computes completions at the given position.
    pub fn completions(&self, position: FilePosition) -> Cancelable<Option<Vec<CompletionItem>>> {
        let completions = completion::completions(&self.db, position)?;
        Ok(completions.map(|it| it.into()))
    }
    /// Computes assists (aks code actons aka intentions) for the given
    /// position.
    pub fn assists(&self, frange: FileRange) -> Cancelable<Vec<SourceChange>> {
        Ok(self.db.assists(frange))
    }
    /// Computes the set of diagnostics for the given file.
    pub fn diagnostics(&self, file_id: FileId) -> Cancelable<Vec<Diagnostic>> {
        self.db.diagnostics(file_id)
    }
    /// Computes parameter information for the given call expression.
    pub fn resolve_callable(
        &self,
        position: FilePosition,
    ) -> Cancelable<Option<(FnSignatureInfo, Option<usize>)>> {
        self.db.resolve_callable(position)
    }
    /// Computes the type of the expression at the given position.
    pub fn type_of(&self, frange: FileRange) -> Cancelable<Option<String>> {
        self.db.type_of(frange)
    }
    /// Returns the edit required to rename reference at the position to the new
    /// name.
    pub fn rename(
        &self,
        position: FilePosition,
        new_name: &str,
    ) -> Cancelable<Vec<SourceFileEdit>> {
        self.db.rename(position, new_name)
    }
}

pub struct LibraryData {
    root_id: SourceRootId,
    root_change: RootChange,
    symbol_index: SymbolIndex,
}

impl fmt::Debug for LibraryData {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("LibraryData")
            .field("root_id", &self.root_id)
            .field("root_change", &self.root_change)
            .field("n_symbols", &self.symbol_index.len())
            .finish()
    }
}

impl LibraryData {
    pub fn prepare(
        root_id: SourceRootId,
        files: Vec<(FileId, RelativePathBuf, Arc<String>)>,
    ) -> LibraryData {
        let symbol_index = SymbolIndex::for_files(files.par_iter().map(|(file_id, _, text)| {
            let file = SourceFileNode::parse(text);
            (*file_id, file)
        }));
        let mut root_change = RootChange::default();
        root_change.added = files
            .into_iter()
            .map(|(file_id, path, text)| AddFile {
                file_id,
                path,
                text,
            })
            .collect();
        LibraryData {
            root_id,
            root_change,
            symbol_index,
        }
    }
}

#[test]
fn analysis_is_send() {
    fn is_send<T: Send>() {}
    is_send::<Analysis>();
}
<|endoftext|>