<commit_before>use std::str::FromStr;
use controller::Reader;
use utils;

// Each line in the database file is a 'Record' that contains the following data to be read
// and serialized.
pub struct Record {
    // Unique (?) id given to each record.
    id: u64,
    // The payload of each record that is Base64 encoded and JSON serialized.
    payload: String,
    // Any necessary metedata needed to identify the record.
    // TODO Base64 encoded and JSON encoded?
    metadata: String,
}

pub struct Factory {
    reader: Reader,
}

pub type RecordResult<T, E> = Result<T, E>;

//TODO Add some factory traits here if necessary
pub trait RecordFactory {
    fn create(data: String) -> RecordResult<Record, String>;
}

impl Factory {
    pub fn new(reader: Reader) -> Factory {
        Factory {
            reader: reader,
        }
    }
}

//TODO Remove the below flag when `create` is used
#[allow(dead_code, unused_must_use, unused_variables)]
fn create(data: String) -> RecordResult<Record, String> {
    let vec_of_data = utils::string_slice(data);
    let id_num = FromStr::from_str(vec_of_data[0].as_slice());
    let id_value: u64 = match id_num {
        Some(value)     => value,
        None            => -1 // This is a failure value
    };

    Ok(Record {
        id: id_value,
        payload: vec_of_data[1].clone(),
        metadata: vec_of_data[2].clone(),
    })

}

#[test]
fn test_create_record() {
    let input = String::from_str("1 payload metadata");
    let id_: u64 = 1;
    let expected = Record {
        id: id_,
        payload: String::from_str("payload"),
        metadata: String::from_str("metadata"),
    };
    let output: Record = create(input).ok().expect("Parsing failed.");
    assert_eq!(expected.id, output.id);
    assert_eq!(expected.payload, output.payload);
    assert_eq!(expected.metadata, output.metadata);
}
<commit_msg>Moved `create` and trait of RecordFactory<commit_after>use std::str::FromStr;
use controller::Reader;
use utils;

// Each line in the database file is a 'Record' that contains the following data to be read
// and serialized.
pub struct Record {
    // Unique (?) id given to each record.
    id: u64,
    // The payload of each record that is Base64 encoded and JSON serialized.
    payload: String,
    // Any necessary metedata needed to identify the record.
    // TODO Base64 encoded and JSON encoded?
    metadata: String,
}

pub struct Factory {
    reader: Reader,
}

pub type RecordResult<T, E> = Result<T, E>;

//TODO Add some factory traits here if necessary
pub trait RecordFactory {
    fn new(reader: Reader) -> Self;

    fn create(&self, data: String) -> RecordResult<Record, String>;
}

impl RecordFactory for Factory {
    fn new(reader: Reader) -> Factory {
        Factory {
            reader: reader,
        }
    }

    //TODO Remove the below flag when `create` is used
    #[allow(dead_code, unused_must_use, unused_variables)]
    fn create(&self, data: String) -> RecordResult<Record, String> {
        let vec_of_data = utils::string_slice(data);
        let id_num = FromStr::from_str(vec_of_data[0].as_slice());
        let id_value: u64 = match id_num {
            Some(value)     => value,
            None            => -1 // This is a failure value
        };

        Ok(Record {
            id: id_value,
            payload: vec_of_data[1].clone(),
            metadata: vec_of_data[2].clone(),
        })
    }
}

//TODO Remove the below flag when `create` is used
#[allow(dead_code, unused_must_use, unused_variables)]
fn create(data: String) -> RecordResult<Record, String> {
    let vec_of_data = utils::string_slice(data);
    let id_num = FromStr::from_str(vec_of_data[0].as_slice());
    let id_value: u64 = match id_num {
        Some(value)     => value,
        None            => -1 // This is a failure value
    };

    Ok(Record {
        id: id_value,
        payload: vec_of_data[1].clone(),
        metadata: vec_of_data[2].clone(),
    })

}

#[test]
fn test_create_record() {
    let input = String::from_str("1 payload metadata");
    let id_: u64 = 1;
    let expected = Record {
        id: id_,
        payload: String::from_str("payload"),
        metadata: String::from_str("metadata"),
    };
    let reader = Reader::new(Path::new("tests/base-test.txt"));
    let _factory: Factory = RecordFactory::new(reader);
    let output: Record = _factory.create(input).ok().expect("Parsing failed.");
    assert_eq!(expected.id, output.id);
    assert_eq!(expected.payload, output.payload);
    assert_eq!(expected.metadata, output.metadata);
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;
extern crate rls_analysis;
extern crate rls_data as data;
extern crate serde;
#[macro_use]
extern crate serde_json;

use data::GlobalCrateId;
use data::DefKind;
use rls_analysis::{AnalysisHost, AnalysisLoader};
use std::collections::HashMap;
use std::fs::{self, File};
use std::path::{Path, PathBuf};

/// A global definition id in a crate.
///
/// FIXME(emilio): This key is kind of slow, because GlobalCrateId contains a
/// String. There's a "disambiguator" field which may be more than enough for
/// our purposes.
#[derive(Clone, Hash, Debug, Eq, PartialEq)]
pub struct DefId(GlobalCrateId, u32);

/// A map from global definition ids to the actual definition.
pub struct Defs {
    map: HashMap<DefId, data::Def>,
}

// Given a definition, and the global crate id where that definition is found,
// return a qualified name that identifies the definition unambiguously.
fn crate_independent_qualname(
    def: &data::Def,
    crate_id: &data::GlobalCrateId,
) -> String {
    // For functions with "no_mangle", we just use the name.
    if def.kind == DefKind::Function &&
        def.attributes.iter().any(|attr| attr.value == "no_mangle")
    {
        return def.name.clone();
    }

    format!("{}{}", crate_id.name, def.qualname)
}

impl Defs {
    fn new() -> Self {
        Self { map: HashMap::new() }
    }

    fn insert(&mut self, analysis: &data::Analysis, def: &data::Def) {
        let crate_id = analysis.prelude.as_ref().unwrap().crate_id.clone();
        let mut definition = def.clone();
        definition.qualname = crate_independent_qualname(&def, &crate_id);

        let index = definition.id.index;
        let previous = self.map.insert(DefId(crate_id, index), definition);
        if let Some(previous) = previous {
            // This shouldn't happen, but as of right now it can happen with
            // some builtin definitions when highly generic types are involved.
            // This is probably a rust bug, just ignore it for now.
            eprintln!(
                "Found a definition with the same ID twice? {:?}, {:?}",
                previous,
                def,
            );
        }
    }

    /// Getter for a given local id, which takes care of converting to a global
    /// ID and returning the definition if present.
    fn get(&self, analysis: &data::Analysis, id: data::Id) -> Option<data::Def> {
        let prelude = analysis.prelude.as_ref().unwrap();
        let krate_id = if id.krate == 0 {
            prelude.crate_id.clone()
        } else {
            // TODO(emilio): This escales with the number of crates in this
            // particular crate, but it's probably not too bad, since it should
            // be a pretty fast linear search.
            let krate = prelude.external_crates.iter().find(|krate| {
                krate.num == id.krate
            });

            let krate = match krate {
                Some(k) => k,
                None => {
                    eprintln!("Crate not found: {:?}", id);
                    return None;
                }
            };

            krate.id.clone()
        };

        let id = DefId(krate_id, id.index);
        self.map.get(&id).cloned()
    }
}

#[derive(Clone)]
pub struct Loader {
    deps_dir: PathBuf,
}

impl Loader {
    pub fn new(deps_dir: PathBuf) -> Self {
        Self { deps_dir }
    }
}

impl AnalysisLoader for Loader {
    fn needs_hard_reload(&self, _: &Path) -> bool {
        true
    }

    fn fresh_host(&self) -> AnalysisHost<Self> {
        AnalysisHost::new_with_loader(self.clone())
    }

    fn set_path_prefix(&mut self, _: &Path) {}

    fn abs_path_prefix(&self) -> Option<PathBuf> {
        None
    }
    fn search_directories(&self) -> Vec<PathBuf> {
        vec![self.deps_dir.clone()]
    }
}

// Searchfox uses 1-indexed lines, 0-indexed columns.
fn span_to_string(span: &data::SpanData) -> String {
    // Rust spans are multi-line... So we just set the start column if it spans
    // multiple rows, searchfox has fallback code to handle this.
    if span.line_start != span.line_end {
        return format!("{}:{}", span.line_start.0, span.column_start.0 - 1);
    }
    if span.column_start == span.column_end {
        return format!("{}:{}", span.line_start.0, span.column_start.0 - 1);
    }
    format!("{}:{}-{}", span.line_start.0, span.column_start.zero_indexed().0, span.column_end.zero_indexed().0)
}

fn def_kind_to_human(kind: DefKind) -> &'static str {
    match kind {
        DefKind::Enum => "enum",
        DefKind::Local => "local",
        DefKind::ExternType => "extern type",
        DefKind::Const => "constant",
        DefKind::Field => "field",
        DefKind::Function => "function",
        DefKind::Macro => "macro",
        DefKind::Method => "method",
        DefKind::Mod => "module",
        DefKind::Static => "static",
        DefKind::Struct => "struct",
        DefKind::Tuple => "tuple",
        DefKind::TupleVariant => "tuple variant",
        DefKind::Union => "union",
        DefKind::Type => "type",
        DefKind::Trait => "trait",
        DefKind::StructVariant => "struct variant",
    }
}

fn visit(
    file: &mut File,
    kind: &'static str,
    location: &data::SpanData,
    qualname: &str,
    def: &data::Def,
    context: Option<&str>,
) {
    use serde_json::map::Map;
    use serde_json::value::Value;
    use std::io::Write;

    let mut out = Map::new();
    out.insert("loc".into(), Value::String(span_to_string(location)));
    out.insert("target".into(), json!(1));
    out.insert("kind".into(), Value::String(kind.into()));
    let pretty = {
        let mut pretty = def_kind_to_human(def.kind).to_owned();
        pretty.push_str(" ");
        pretty.push_str(qualname);

        pretty
    };
    out.insert("pretty".into(), Value::String(pretty.clone()));
    out.insert("sym".into(), Value::String(qualname.into()));
    if let Some(context) = context {
        out.insert("context".into(), Value::String(context.into()));
        out.insert("contextsym".into(), Value::String(context.into()));
    }

    let object = serde_json::to_string(&Value::Object(out)).unwrap();
    file.write_all(object.as_bytes()).unwrap();
    write!(file, "\n").unwrap();

    let mut out = Map::new();
    out.insert("loc".into(), Value::String(span_to_string(location)));
    out.insert("source".into(), json!(1));
    out.insert("kind".into(), Value::String(kind.into()));
    out.insert("pretty".into(), Value::String(pretty));
    out.insert("sym".into(), Value::String(qualname.into()));

    let object = serde_json::to_string(&Value::Object(out)).unwrap();
    file.write_all(object.as_bytes()).unwrap();
    write!(file, "\n").unwrap();
}

fn analyze_file(
    file_name: &PathBuf,
    defs: &Defs,
    file_analysis: &data::Analysis,
    src_dir: &Path,
    output_dir: &Path,
) {
    let file = match file_name.strip_prefix(src_dir) {
        Ok(f) => f,
        Err(..) => {
            eprintln!("File not in the source directory: {}", file_name.display());
            return;
        }
    };

    let output_file = output_dir.join(file);
    let mut output_dir = output_file.clone();
    output_dir.pop();
    if let Err(err) = fs::create_dir_all(output_dir) {
        eprintln!(
            "Couldn't create dir for: {}, {:?}",
            output_file.display(),
            err
        );
        return;
    }
    let mut file = match File::create(&output_file) {
        Ok(f) => f,
        Err(err) => {
            eprintln!(
                "Couldn't open output file: {}, {:?}",
                output_file.display(),
                err
            );
            return;
        }
    };

    for import in &file_analysis.imports {
        let id = match import.ref_id {
            Some(id) => id,
            None => {
                eprintln!("Dropping import {} ({:?}): {}, no ref", import.name, import.kind, import.value);
                continue;
            }
        };

        let def = match defs.get(file_analysis, id) {
            Some(def) => def,
            None => {
                eprintln!("Dropping import {} ({:?}): {}, no def for ref {:?}", import.name, import.kind, import.value, id);
                continue;
            }
        };

        visit(&mut file, "use", &import.span, &def.qualname, &def, None)
    }

    for def in &file_analysis.defs {
        let parent =
            def.parent.and_then(|parent_id| defs.get(file_analysis, parent_id));

        if let Some(ref parent) = parent {
            if parent.kind == DefKind::Trait {
                let trait_dependent_name =
                    format!("{}::{}", parent.qualname, def.name);
                visit(
                    &mut file,
                    "def",
                    &def.span,
                    &trait_dependent_name,
                    &def,
                    Some(&parent.qualname),
                )
            }
        }

        let crate_id = &file_analysis.prelude.as_ref().unwrap().crate_id;
        let qualname = crate_independent_qualname(&def, crate_id);
        visit(&mut file, "def", &def.span, &qualname, &def, parent.as_ref().map(|p| &*p.qualname))
    }

    for ref_ in &file_analysis.refs {
        let def = match defs.get(file_analysis, ref_.ref_id) {
            Some(d) => d,
            None => {
                eprintln!("Dropping ref {:?}, kind {:?}, no def", ref_.ref_id, ref_.kind);
                continue;
            }
        };
        visit(
            &mut file,
            "use",
            &ref_.span,
            &def.qualname,
            &def,
            /* context = */ None, // TODO
        )
    }
}

fn analyze_crate(
    analysis: &data::Analysis,
    defs: &Defs,
    src_dir: &Path,
    output_dir: &Path,
) {
    let mut per_file = HashMap::new();

    println!("Analyzing crate: {:?}", analysis.prelude);

    macro_rules! flat_map_per_file {
        ($field:ident) => {
            for item in &analysis.$field {
                let mut file_analysis =
                    per_file.entry(item.span.file_name.clone())
                        .or_insert_with(|| {
                            let prelude = analysis.prelude.clone();
                            let mut analysis = data::Analysis::new(analysis.config.clone());
                            analysis.prelude = prelude;
                            analysis
                        });
                file_analysis.$field.push(item.clone());
            }
        }
    }

    flat_map_per_file!(imports);
    flat_map_per_file!(defs);
    flat_map_per_file!(impls);
    flat_map_per_file!(refs);
    flat_map_per_file!(macro_refs);
    flat_map_per_file!(relations);

    for (mut name, analysis) in per_file.drain() {
        if name.is_relative() {
            name = src_dir.join(name);
        }
        analyze_file(&name, defs, &analysis, src_dir, output_dir);
    }
}

fn main() {
    let matches = app_from_crate!()
        .args_from_usage(
            "<src>    'Points to the source root'
             <input>  'Points to the deps/save-analysis directory'
             <output> 'Points to the directory where searchfox metadata should go'",
        )
        .get_matches();

    let src_dir = Path::new(matches.value_of("src").unwrap());
    let input_dir = Path::new(matches.value_of("input").unwrap());
    let output_dir = Path::new(matches.value_of("output").unwrap());

    let loader = Loader::new(PathBuf::from(input_dir));

    let crates = rls_analysis::read_analysis_from_files(&loader, Default::default(), &[]);

    let mut defs = Defs::new();
    for krate in &crates {
        for def in &krate.analysis.defs {
            //println!("Indexing def: {:?}", def);
            defs.insert(&krate.analysis, def);
        }
    }

    for krate in crates {
        analyze_crate(&krate.analysis, &defs, &src_dir, &output_dir);
    }
}
<commit_msg>rust-indexer: Add env_logger to the rust indexer.<commit_after>#[macro_use]
extern crate clap;
extern crate env_logger;
extern crate rls_analysis;
extern crate rls_data as data;
extern crate serde;
#[macro_use]
extern crate serde_json;

use data::GlobalCrateId;
use data::DefKind;
use rls_analysis::{AnalysisHost, AnalysisLoader};
use std::collections::HashMap;
use std::fs::{self, File};
use std::path::{Path, PathBuf};

/// A global definition id in a crate.
///
/// FIXME(emilio): This key is kind of slow, because GlobalCrateId contains a
/// String. There's a "disambiguator" field which may be more than enough for
/// our purposes.
#[derive(Clone, Hash, Debug, Eq, PartialEq)]
pub struct DefId(GlobalCrateId, u32);

/// A map from global definition ids to the actual definition.
pub struct Defs {
    map: HashMap<DefId, data::Def>,
}

// Given a definition, and the global crate id where that definition is found,
// return a qualified name that identifies the definition unambiguously.
fn crate_independent_qualname(
    def: &data::Def,
    crate_id: &data::GlobalCrateId,
) -> String {
    // For functions with "no_mangle", we just use the name.
    if def.kind == DefKind::Function &&
        def.attributes.iter().any(|attr| attr.value == "no_mangle")
    {
        return def.name.clone();
    }

    format!("{}{}", crate_id.name, def.qualname)
}

impl Defs {
    fn new() -> Self {
        Self { map: HashMap::new() }
    }

    fn insert(&mut self, analysis: &data::Analysis, def: &data::Def) {
        let crate_id = analysis.prelude.as_ref().unwrap().crate_id.clone();
        let mut definition = def.clone();
        definition.qualname = crate_independent_qualname(&def, &crate_id);

        let index = definition.id.index;
        let previous = self.map.insert(DefId(crate_id, index), definition);
        if let Some(previous) = previous {
            // This shouldn't happen, but as of right now it can happen with
            // some builtin definitions when highly generic types are involved.
            // This is probably a rust bug, just ignore it for now.
            eprintln!(
                "Found a definition with the same ID twice? {:?}, {:?}",
                previous,
                def,
            );
        }
    }

    /// Getter for a given local id, which takes care of converting to a global
    /// ID and returning the definition if present.
    fn get(&self, analysis: &data::Analysis, id: data::Id) -> Option<data::Def> {
        let prelude = analysis.prelude.as_ref().unwrap();
        let krate_id = if id.krate == 0 {
            prelude.crate_id.clone()
        } else {
            // TODO(emilio): This escales with the number of crates in this
            // particular crate, but it's probably not too bad, since it should
            // be a pretty fast linear search.
            let krate = prelude.external_crates.iter().find(|krate| {
                krate.num == id.krate
            });

            let krate = match krate {
                Some(k) => k,
                None => {
                    eprintln!("Crate not found: {:?}", id);
                    return None;
                }
            };

            krate.id.clone()
        };

        let id = DefId(krate_id, id.index);
        self.map.get(&id).cloned()
    }
}

#[derive(Clone)]
pub struct Loader {
    deps_dir: PathBuf,
}

impl Loader {
    pub fn new(deps_dir: PathBuf) -> Self {
        Self { deps_dir }
    }
}

impl AnalysisLoader for Loader {
    fn needs_hard_reload(&self, _: &Path) -> bool {
        true
    }

    fn fresh_host(&self) -> AnalysisHost<Self> {
        AnalysisHost::new_with_loader(self.clone())
    }

    fn set_path_prefix(&mut self, _: &Path) {}

    fn abs_path_prefix(&self) -> Option<PathBuf> {
        None
    }
    fn search_directories(&self) -> Vec<PathBuf> {
        vec![self.deps_dir.clone()]
    }
}

// Searchfox uses 1-indexed lines, 0-indexed columns.
fn span_to_string(span: &data::SpanData) -> String {
    // Rust spans are multi-line... So we just set the start column if it spans
    // multiple rows, searchfox has fallback code to handle this.
    if span.line_start != span.line_end {
        return format!("{}:{}", span.line_start.0, span.column_start.0 - 1);
    }
    if span.column_start == span.column_end {
        return format!("{}:{}", span.line_start.0, span.column_start.0 - 1);
    }
    format!("{}:{}-{}", span.line_start.0, span.column_start.zero_indexed().0, span.column_end.zero_indexed().0)
}

fn def_kind_to_human(kind: DefKind) -> &'static str {
    match kind {
        DefKind::Enum => "enum",
        DefKind::Local => "local",
        DefKind::ExternType => "extern type",
        DefKind::Const => "constant",
        DefKind::Field => "field",
        DefKind::Function => "function",
        DefKind::Macro => "macro",
        DefKind::Method => "method",
        DefKind::Mod => "module",
        DefKind::Static => "static",
        DefKind::Struct => "struct",
        DefKind::Tuple => "tuple",
        DefKind::TupleVariant => "tuple variant",
        DefKind::Union => "union",
        DefKind::Type => "type",
        DefKind::Trait => "trait",
        DefKind::StructVariant => "struct variant",
    }
}

fn visit(
    file: &mut File,
    kind: &'static str,
    location: &data::SpanData,
    qualname: &str,
    def: &data::Def,
    context: Option<&str>,
) {
    use serde_json::map::Map;
    use serde_json::value::Value;
    use std::io::Write;

    let mut out = Map::new();
    out.insert("loc".into(), Value::String(span_to_string(location)));
    out.insert("target".into(), json!(1));
    out.insert("kind".into(), Value::String(kind.into()));
    let pretty = {
        let mut pretty = def_kind_to_human(def.kind).to_owned();
        pretty.push_str(" ");
        pretty.push_str(qualname);

        pretty
    };
    out.insert("pretty".into(), Value::String(pretty.clone()));
    out.insert("sym".into(), Value::String(qualname.into()));
    if let Some(context) = context {
        out.insert("context".into(), Value::String(context.into()));
        out.insert("contextsym".into(), Value::String(context.into()));
    }

    let object = serde_json::to_string(&Value::Object(out)).unwrap();
    file.write_all(object.as_bytes()).unwrap();
    write!(file, "\n").unwrap();

    let mut out = Map::new();
    out.insert("loc".into(), Value::String(span_to_string(location)));
    out.insert("source".into(), json!(1));
    out.insert("kind".into(), Value::String(kind.into()));
    out.insert("pretty".into(), Value::String(pretty));
    out.insert("sym".into(), Value::String(qualname.into()));

    let object = serde_json::to_string(&Value::Object(out)).unwrap();
    file.write_all(object.as_bytes()).unwrap();
    write!(file, "\n").unwrap();
}

fn analyze_file(
    file_name: &PathBuf,
    defs: &Defs,
    file_analysis: &data::Analysis,
    src_dir: &Path,
    output_dir: &Path,
) {
    let file = match file_name.strip_prefix(src_dir) {
        Ok(f) => f,
        Err(..) => {
            eprintln!("File not in the source directory: {}", file_name.display());
            return;
        }
    };

    let output_file = output_dir.join(file);
    let mut output_dir = output_file.clone();
    output_dir.pop();
    if let Err(err) = fs::create_dir_all(output_dir) {
        eprintln!(
            "Couldn't create dir for: {}, {:?}",
            output_file.display(),
            err
        );
        return;
    }
    let mut file = match File::create(&output_file) {
        Ok(f) => f,
        Err(err) => {
            eprintln!(
                "Couldn't open output file: {}, {:?}",
                output_file.display(),
                err
            );
            return;
        }
    };

    for import in &file_analysis.imports {
        let id = match import.ref_id {
            Some(id) => id,
            None => {
                eprintln!("Dropping import {} ({:?}): {}, no ref", import.name, import.kind, import.value);
                continue;
            }
        };

        let def = match defs.get(file_analysis, id) {
            Some(def) => def,
            None => {
                eprintln!("Dropping import {} ({:?}): {}, no def for ref {:?}", import.name, import.kind, import.value, id);
                continue;
            }
        };

        visit(&mut file, "use", &import.span, &def.qualname, &def, None)
    }

    for def in &file_analysis.defs {
        let parent =
            def.parent.and_then(|parent_id| defs.get(file_analysis, parent_id));

        if let Some(ref parent) = parent {
            if parent.kind == DefKind::Trait {
                let trait_dependent_name =
                    format!("{}::{}", parent.qualname, def.name);
                visit(
                    &mut file,
                    "def",
                    &def.span,
                    &trait_dependent_name,
                    &def,
                    Some(&parent.qualname),
                )
            }
        }

        let crate_id = &file_analysis.prelude.as_ref().unwrap().crate_id;
        let qualname = crate_independent_qualname(&def, crate_id);
        visit(&mut file, "def", &def.span, &qualname, &def, parent.as_ref().map(|p| &*p.qualname))
    }

    for ref_ in &file_analysis.refs {
        let def = match defs.get(file_analysis, ref_.ref_id) {
            Some(d) => d,
            None => {
                eprintln!("Dropping ref {:?}, kind {:?}, no def", ref_.ref_id, ref_.kind);
                continue;
            }
        };
        visit(
            &mut file,
            "use",
            &ref_.span,
            &def.qualname,
            &def,
            /* context = */ None, // TODO
        )
    }
}

fn analyze_crate(
    analysis: &data::Analysis,
    defs: &Defs,
    src_dir: &Path,
    output_dir: &Path,
) {
    let mut per_file = HashMap::new();

    println!("Analyzing crate: {:?}", analysis.prelude);

    macro_rules! flat_map_per_file {
        ($field:ident) => {
            for item in &analysis.$field {
                let mut file_analysis =
                    per_file.entry(item.span.file_name.clone())
                        .or_insert_with(|| {
                            let prelude = analysis.prelude.clone();
                            let mut analysis = data::Analysis::new(analysis.config.clone());
                            analysis.prelude = prelude;
                            analysis
                        });
                file_analysis.$field.push(item.clone());
            }
        }
    }

    flat_map_per_file!(imports);
    flat_map_per_file!(defs);
    flat_map_per_file!(impls);
    flat_map_per_file!(refs);
    flat_map_per_file!(macro_refs);
    flat_map_per_file!(relations);

    for (mut name, analysis) in per_file.drain() {
        if name.is_relative() {
            name = src_dir.join(name);
        }
        analyze_file(&name, defs, &analysis, src_dir, output_dir);
    }
}

fn main() {
    env_logger::init().unwrap();
    let matches = app_from_crate!()
        .args_from_usage(
            "<src>    'Points to the source root'
             <input>  'Points to the deps/save-analysis directory'
             <output> 'Points to the directory where searchfox metadata should go'",
        )
        .get_matches();

    let src_dir = Path::new(matches.value_of("src").unwrap());
    let input_dir = Path::new(matches.value_of("input").unwrap());
    let output_dir = Path::new(matches.value_of("output").unwrap());

    let loader = Loader::new(PathBuf::from(input_dir));

    let crates = rls_analysis::read_analysis_from_files(&loader, Default::default(), &[]);

    let mut defs = Defs::new();
    for krate in &crates {
        for def in &krate.analysis.defs {
            //println!("Indexing def: {:?}", def);
            defs.insert(&krate.analysis, def);
        }
    }

    for krate in crates {
        analyze_crate(&krate.analysis, &defs, &src_dir, &output_dir);
    }
}
<|endoftext|>


<commit_before>use super::*;

use std::process::{Command, Child, Stdio};
use std::thread;
use std::time::Duration;

pub struct GeckoDriverBuilder {
    port: u16,
    ff_binary: String,
    kill_on_drop: bool,
}

impl GeckoDriverBuilder {
    pub fn new() -> Self {
        GeckoDriverBuilder {
            port: 4444,
            ff_binary: "firefox".to_owned(),
            kill_on_drop: true,
        }
    }
    pub fn port(mut self, port: u16) -> Self {
        self.port = Some(port);
        self
    }
    pub fn firefox_binary(mut self, binary: &str) -> Self {
        self.ff_binary = binary.to_owned();
        self
    }
    pub fn kill_on_drop(mut self, kill: bool) -> Self {
        self.kill_on_drop = kill;
        self
    }
    pub fn spawn(self) -> Result<GeckoDriver, Error> {
        let child = Command::new("geckodriver")
            .arg("-b")
            .arg(self.ff_binary)
            .arg("--webdriver-port")
            .arg(format!("{}", self.port))
            .stdin(Stdio::null())
            .stderr(Stdio::null())
            .stdout(Stdio::null())
            .spawn()?;

        // TODO: parameterize this
        thread::sleep(Duration::new(1, 500));
        Ok(GeckoDriver {
            child: child,
            url: format!("http://localhost:{}", self.port),
            kill_on_drop: self.kill_on_drop,
        })
    }
}

/// A geckodriver process
pub struct GeckoDriver {
    pub child: Child,
    url: String,
    kill_on_drop: bool,
}

impl GeckoDriver {
    pub fn spawn() -> Result<Self, Error> {
        GeckoDriverBuilder::new().spawn()
    }
    pub fn build() -> GeckoDriverBuilder {
        GeckoDriverBuilder::new()
    }
}

impl Drop for GeckoDriver {
    fn drop(&mut self) {
        if self.kill_on_drop {
            let _ = self.child.kill();
        }
    }
}

impl Driver for GeckoDriver {
    fn url(&self) -> &str {
        &self.url
    }
}

<commit_msg>Listen on random TCP port geckdriver<commit_after>use super::*;

use std::process::{Command, Child, Stdio};
use std::thread;
use std::time::Duration;
use std::net::TcpListener;

/// Find a TCP port number to use. This is racy but see
/// https://bugzilla.mozilla.org/show_bug.cgi?id=1240830
///
/// If port is Some, check if we can bind to the given port. Otherwise
/// pick a random port.
fn check_tcp_port(port: Option<u16>) -> io::Result<u16> {
    TcpListener::bind(&("localhost", port.unwrap_or(0)))
        .and_then(|stream| stream.local_addr())
        .map(|x| x.port())
}

pub struct GeckoDriverBuilder {
    port: Option<u16>,
    ff_binary: String,
    kill_on_drop: bool,
}

impl GeckoDriverBuilder {
    pub fn new() -> Self {
        GeckoDriverBuilder {
            port: None,
            ff_binary: "firefox".to_owned(),
            kill_on_drop: true,
        }
    }
    pub fn port(mut self, port: u16) -> Self {
        self.port = Some(port);
        self
    }
    pub fn firefox_binary(mut self, binary: &str) -> Self {
        self.ff_binary = binary.to_owned();
        self
    }
    pub fn kill_on_drop(mut self, kill: bool) -> Self {
        self.kill_on_drop = kill;
        self
    }
    pub fn spawn(self) -> Result<GeckoDriver, Error> {
        let port = check_tcp_port(self.port)?;

        let child = Command::new("geckodriver")
            .arg("-b")
            .arg(self.ff_binary)
            .arg("--webdriver-port")
            .arg(format!("{}", port))
            .stdin(Stdio::null())
            .stderr(Stdio::null())
            .stdout(Stdio::null())
            .spawn()?;

        // TODO: parameterize this
        thread::sleep(Duration::new(1, 500));
        Ok(GeckoDriver {
            child: child,
            url: format!("http://localhost:{}", port),
            kill_on_drop: self.kill_on_drop,
        })
    }
}

/// A geckodriver process
pub struct GeckoDriver {
    pub child: Child,
    url: String,
    kill_on_drop: bool,
}

impl GeckoDriver {
    pub fn spawn() -> Result<Self, Error> {
        GeckoDriverBuilder::new().spawn()
    }
    pub fn build() -> GeckoDriverBuilder {
        GeckoDriverBuilder::new()
    }
}

impl Drop for GeckoDriver {
    fn drop(&mut self) {
        if self.kill_on_drop {
            let _ = self.child.kill();
        }
    }
}

impl Driver for GeckoDriver {
    fn url(&self) -> &str {
        &self.url
    }
}

<|endoftext|>


<commit_before>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// This test case tests the incremental compilation hash (ICH) implementation
// for function interfaces.

// The general pattern followed here is: Change one thing between rev1 and rev2
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.

// must-compile-successfully
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph

#![allow(warnings)]
#![feature(conservative_impl_trait)]
#![feature(intrinsics)]
#![feature(linkage)]
#![feature(rustc_attrs)]
#![crate_type="rlib"]

// Add Parameter ---------------------------------------------------------------

#[cfg(cfail1)]
pub fn add_parameter() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
#[rustc_clean(cfg="cfail3")]
pub fn add_parameter(p: i32) {}

// Add Return Type -------------------------------------------------------------

#[cfg(cfail1)]
pub fn add_return_type() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody")]
#[rustc_clean(cfg="cfail3")]
pub fn add_return_type() -> () {}

// Change Parameter Type -------------------------------------------------------

#[cfg(cfail1)]
pub fn type_of_parameter(p: i32) {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
#[rustc_clean(cfg="cfail3")]
pub fn type_of_parameter(p: i64) {}

// Change Parameter Type Reference ---------------------------------------------

#[cfg(cfail1)]
pub fn type_of_parameter_ref(p: &i32) {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
#[rustc_clean(cfg="cfail3")]
pub fn type_of_parameter_ref(p: &mut i32) {}

// Change Parameter Order ------------------------------------------------------

#[cfg(cfail1)]
pub fn order_of_parameters(p1: i32, p2: i64) {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
#[rustc_clean(cfg="cfail3")]
pub fn order_of_parameters(p2: i64, p1: i32) {}

// Unsafe ----------------------------------------------------------------------

#[cfg(cfail1)]
pub fn make_unsafe() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
#[rustc_clean(cfg="cfail3")]
pub unsafe fn make_unsafe() {}

// Extern ----------------------------------------------------------------------

#[cfg(cfail1)]
pub fn make_extern() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody, TypeckTables, FnSignature")]
#[rustc_clean(cfg="cfail3")]
pub extern fn make_extern() {}

// Extern C Extern Rust-Intrinsic ----------------------------------------------

#[cfg(cfail1)]
pub extern "C" fn make_intrinsic() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody, TypeckTables, FnSignature")]
#[rustc_clean(cfg="cfail3")]
pub extern "rust-intrinsic" fn make_intrinsic() {}

// Type Parameter --------------------------------------------------------------

#[cfg(cfail1)]
pub fn type_parameter() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody, GenericsOfItem, TypeOfItem, PredicatesOfItem")]
#[rustc_clean(cfg="cfail3")]
pub fn type_parameter<T>() {}

// Lifetime Parameter ----------------------------------------------------------

#[cfg(cfail1)]
pub fn lifetime_parameter() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody, GenericsOfItem")]
#[rustc_clean(cfg="cfail3")]
pub fn lifetime_parameter<'a>() {}

// Trait Bound -----------------------------------------------------------------

#[cfg(cfail1)]
pub fn trait_bound<T>() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody, PredicatesOfItem")]
#[rustc_clean(cfg="cfail3")]
pub fn trait_bound<T: Eq>() {}

// Builtin Bound ---------------------------------------------------------------

#[cfg(cfail1)]
pub fn builtin_bound<T>() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody, PredicatesOfItem")]
#[rustc_clean(cfg="cfail3")]
pub fn builtin_bound<T: Send>() {}

// Lifetime Bound --------------------------------------------------------------

#[cfg(cfail1)]
pub fn lifetime_bound<'a, T>() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody, GenericsOfItem, TypeOfItem, PredicatesOfItem")]
#[rustc_clean(cfg="cfail3")]
pub fn lifetime_bound<'a, T: 'a>() {}

// Second Trait Bound ----------------------------------------------------------

#[cfg(cfail1)]
pub fn second_trait_bound<T: Eq>() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody, PredicatesOfItem")]
#[rustc_clean(cfg="cfail3")]
pub fn second_trait_bound<T: Eq + Clone>() {}

// Second Builtin Bound --------------------------------------------------------

#[cfg(cfail1)]
pub fn second_builtin_bound<T: Send>() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody, PredicatesOfItem")]
#[rustc_clean(cfg="cfail3")]
pub fn second_builtin_bound<T: Send + Sized>() {}

// Second Lifetime Bound -------------------------------------------------------

#[cfg(cfail1)]
pub fn second_lifetime_bound<'a, 'b, T: 'a>() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody, GenericsOfItem, TypeOfItem, PredicatesOfItem")]
#[rustc_clean(cfg="cfail3")]
pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {}

// Inline ----------------------------------------------------------------------

#[cfg(cfail1)]
pub fn inline() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody")]
#[rustc_clean(cfg="cfail3")]
#[inline]
pub fn inline() {}

// Inline Never ----------------------------------------------------------------

#[cfg(cfail1)]
#[inline(always)]
pub fn inline_never() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody")]
#[rustc_clean(cfg="cfail3")]
#[inline(never)]
pub fn inline_never() {}

// No Mangle -------------------------------------------------------------------

#[cfg(cfail1)]
pub fn no_mangle() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody")]
#[rustc_clean(cfg="cfail3")]
#[no_mangle]
pub fn no_mangle() {}

// Linkage ---------------------------------------------------------------------

#[cfg(cfail1)]
pub fn linkage() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody")]
#[rustc_clean(cfg="cfail3")]
#[linkage="weak_odr"]
pub fn linkage() {}

// Return Impl Trait -----------------------------------------------------------

#[cfg(cfail1)]
pub fn return_impl_trait() -> i32 {
    0
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody, TypeckTables, FnSignature")]
#[rustc_clean(cfg="cfail3")]
pub fn return_impl_trait() -> impl Clone {
    0
}

// Change Return Impl Trait ----------------------------------------------------

#[cfg(cfail1)]
pub fn change_return_impl_trait() -> impl Clone {
    0u32
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg="cfail2", except="Hir, HirBody")]
#[rustc_clean(cfg="cfail3")]
pub fn change_return_impl_trait() -> impl Copy {
    0u32
}

// Change Return Type Indirectly -----------------------------------------------

pub struct ReferencedType1;
pub struct ReferencedType2;

pub mod change_return_type_indirectly {
    #[cfg(cfail1)]
    use super::ReferencedType1 as ReturnType;
    #[cfg(not(cfail1))]
    use super::ReferencedType2 as ReturnType;

    #[rustc_clean(cfg="cfail2", except="Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
    #[rustc_clean(cfg="cfail3")]
    pub fn indirect_return_type() -> ReturnType {
        ReturnType {}
    }
}

// Change Parameter Type Indirectly --------------------------------------------

pub mod change_parameter_type_indirectly {
    #[cfg(cfail1)]
    use super::ReferencedType1 as ParameterType;
    #[cfg(not(cfail1))]
    use super::ReferencedType2 as ParameterType;

    #[rustc_clean(cfg="cfail2", except="Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
    #[rustc_clean(cfg="cfail3")]
    pub fn indirect_parameter_type(p: ParameterType) {}
}

// Change Trait Bound Indirectly -----------------------------------------------

pub trait ReferencedTrait1 {}
pub trait ReferencedTrait2 {}

pub mod change_trait_bound_indirectly {
    #[cfg(cfail1)]
    use super::ReferencedTrait1 as Trait;
    #[cfg(not(cfail1))]
    use super::ReferencedTrait2 as Trait;

    #[rustc_clean(cfg="cfail2", except="Hir, HirBody, PredicatesOfItem")]
    #[rustc_clean(cfg="cfail3")]
    pub fn indirect_trait_bound<T: Trait>(p: T) {}
}

// Change Trait Bound Indirectly In Where Clause -------------------------------

pub mod change_trait_bound_indirectly_in_where_clause {
    #[cfg(cfail1)]
    use super::ReferencedTrait1 as Trait;
    #[cfg(not(cfail1))]
    use super::ReferencedTrait2 as Trait;

    #[rustc_clean(cfg="cfail2", except="Hir, HirBody, PredicatesOfItem")]
    #[rustc_clean(cfg="cfail3")]
    pub fn indirect_trait_bound_where<T>(p: T) where T: Trait {}
}
<commit_msg>Format function interface fingerprint hash tests<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// This test case tests the incremental compilation hash (ICH) implementation
// for function interfaces.

// The general pattern followed here is: Change one thing between rev1 and rev2
// and make sure that the hash has changed, then change nothing between rev2 and
// rev3 and make sure that the hash has not changed.

// must-compile-successfully
// revisions: cfail1 cfail2 cfail3
// compile-flags: -Z query-dep-graph

#![allow(warnings)]
#![feature(conservative_impl_trait)]
#![feature(intrinsics)]
#![feature(linkage)]
#![feature(rustc_attrs)]
#![crate_type = "rlib"]

// Add Parameter ---------------------------------------------------------------

#[cfg(cfail1)]
pub fn add_parameter() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2",
              except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
#[rustc_clean(cfg = "cfail3")]
pub fn add_parameter(p: i32) {}

// Add Return Type -------------------------------------------------------------

#[cfg(cfail1)]
pub fn add_return_type() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
#[rustc_clean(cfg = "cfail3")]
pub fn add_return_type() -> () {}

// Change Parameter Type -------------------------------------------------------

#[cfg(cfail1)]
pub fn type_of_parameter(p: i32) {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2",
              except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
#[rustc_clean(cfg = "cfail3")]
pub fn type_of_parameter(p: i64) {}

// Change Parameter Type Reference ---------------------------------------------

#[cfg(cfail1)]
pub fn type_of_parameter_ref(p: &i32) {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2",
              except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
#[rustc_clean(cfg = "cfail3")]
pub fn type_of_parameter_ref(p: &mut i32) {}

// Change Parameter Order ------------------------------------------------------

#[cfg(cfail1)]
pub fn order_of_parameters(p1: i32, p2: i64) {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2",
              except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
#[rustc_clean(cfg = "cfail3")]
pub fn order_of_parameters(p2: i64, p1: i32) {}

// Unsafe ----------------------------------------------------------------------

#[cfg(cfail1)]
pub fn make_unsafe() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2",
              except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
#[rustc_clean(cfg = "cfail3")]
pub unsafe fn make_unsafe() {}

// Extern ----------------------------------------------------------------------

#[cfg(cfail1)]
pub fn make_extern() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, TypeckTables, FnSignature")]
#[rustc_clean(cfg = "cfail3")]
pub extern "C" fn make_extern() {}

// Extern C Extern Rust-Intrinsic ----------------------------------------------

#[cfg(cfail1)]
pub extern "C" fn make_intrinsic() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, TypeckTables, FnSignature")]
#[rustc_clean(cfg = "cfail3")]
pub extern "rust-intrinsic" fn make_intrinsic() {}

// Type Parameter --------------------------------------------------------------

#[cfg(cfail1)]
pub fn type_parameter() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2",
              except = "Hir, HirBody, GenericsOfItem, TypeOfItem, PredicatesOfItem")]
#[rustc_clean(cfg = "cfail3")]
pub fn type_parameter<T>() {}

// Lifetime Parameter ----------------------------------------------------------

#[cfg(cfail1)]
pub fn lifetime_parameter() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, GenericsOfItem")]
#[rustc_clean(cfg = "cfail3")]
pub fn lifetime_parameter<'a>() {}

// Trait Bound -----------------------------------------------------------------

#[cfg(cfail1)]
pub fn trait_bound<T>() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")]
#[rustc_clean(cfg = "cfail3")]
pub fn trait_bound<T: Eq>() {}

// Builtin Bound ---------------------------------------------------------------

#[cfg(cfail1)]
pub fn builtin_bound<T>() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")]
#[rustc_clean(cfg = "cfail3")]
pub fn builtin_bound<T: Send>() {}

// Lifetime Bound --------------------------------------------------------------

#[cfg(cfail1)]
pub fn lifetime_bound<'a, T>() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2",
              except = "Hir, HirBody, GenericsOfItem, TypeOfItem, PredicatesOfItem")]
#[rustc_clean(cfg = "cfail3")]
pub fn lifetime_bound<'a, T: 'a>() {}

// Second Trait Bound ----------------------------------------------------------

#[cfg(cfail1)]
pub fn second_trait_bound<T: Eq>() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")]
#[rustc_clean(cfg = "cfail3")]
pub fn second_trait_bound<T: Eq + Clone>() {}

// Second Builtin Bound --------------------------------------------------------

#[cfg(cfail1)]
pub fn second_builtin_bound<T: Send>() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")]
#[rustc_clean(cfg = "cfail3")]
pub fn second_builtin_bound<T: Send + Sized>() {}

// Second Lifetime Bound -------------------------------------------------------

#[cfg(cfail1)]
pub fn second_lifetime_bound<'a, 'b, T: 'a>() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2",
              except = "Hir, HirBody, GenericsOfItem, TypeOfItem, PredicatesOfItem")]
#[rustc_clean(cfg = "cfail3")]
pub fn second_lifetime_bound<'a, 'b, T: 'a + 'b>() {}

// Inline ----------------------------------------------------------------------

#[cfg(cfail1)]
pub fn inline() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
#[rustc_clean(cfg = "cfail3")]
#[inline]
pub fn inline() {}

// Inline Never ----------------------------------------------------------------

#[cfg(cfail1)]
#[inline(always)]
pub fn inline_never() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
#[rustc_clean(cfg = "cfail3")]
#[inline(never)]
pub fn inline_never() {}

// No Mangle -------------------------------------------------------------------

#[cfg(cfail1)]
pub fn no_mangle() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
#[rustc_clean(cfg = "cfail3")]
#[no_mangle]
pub fn no_mangle() {}

// Linkage ---------------------------------------------------------------------

#[cfg(cfail1)]
pub fn linkage() {}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
#[rustc_clean(cfg = "cfail3")]
#[linkage = "weak_odr"]
pub fn linkage() {}

// Return Impl Trait -----------------------------------------------------------

#[cfg(cfail1)]
pub fn return_impl_trait() -> i32 {
    0
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, TypeckTables, FnSignature")]
#[rustc_clean(cfg = "cfail3")]
pub fn return_impl_trait() -> impl Clone {
    0
}

// Change Return Impl Trait ----------------------------------------------------

#[cfg(cfail1)]
pub fn change_return_impl_trait() -> impl Clone {
    0u32
}

#[cfg(not(cfail1))]
#[rustc_clean(cfg = "cfail2", except = "Hir, HirBody")]
#[rustc_clean(cfg = "cfail3")]
pub fn change_return_impl_trait() -> impl Copy {
    0u32
}

// Change Return Type Indirectly -----------------------------------------------

pub struct ReferencedType1;
pub struct ReferencedType2;

pub mod change_return_type_indirectly {
    #[cfg(cfail1)]
    use super::ReferencedType1 as ReturnType;
    #[cfg(not(cfail1))]
    use super::ReferencedType2 as ReturnType;

    #[rustc_clean(cfg = "cfail2",
                  except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
    #[rustc_clean(cfg = "cfail3")]
    pub fn indirect_return_type() -> ReturnType {
        ReturnType {}
    }
}

// Change Parameter Type Indirectly --------------------------------------------

pub mod change_parameter_type_indirectly {
    #[cfg(cfail1)]
    use super::ReferencedType1 as ParameterType;
    #[cfg(not(cfail1))]
    use super::ReferencedType2 as ParameterType;

    #[rustc_clean(cfg = "cfail2",
                  except = "Hir, HirBody, MirValidated, MirOptimized, TypeckTables, FnSignature")]
    #[rustc_clean(cfg = "cfail3")]
    pub fn indirect_parameter_type(p: ParameterType) {}
}

// Change Trait Bound Indirectly -----------------------------------------------

pub trait ReferencedTrait1 {}
pub trait ReferencedTrait2 {}

pub mod change_trait_bound_indirectly {
    #[cfg(cfail1)]
    use super::ReferencedTrait1 as Trait;
    #[cfg(not(cfail1))]
    use super::ReferencedTrait2 as Trait;

    #[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")]
    #[rustc_clean(cfg = "cfail3")]
    pub fn indirect_trait_bound<T: Trait>(p: T) {}
}

// Change Trait Bound Indirectly In Where Clause -------------------------------

pub mod change_trait_bound_indirectly_in_where_clause {
    #[cfg(cfail1)]
    use super::ReferencedTrait1 as Trait;
    #[cfg(not(cfail1))]
    use super::ReferencedTrait2 as Trait;

    #[rustc_clean(cfg = "cfail2", except = "Hir, HirBody, PredicatesOfItem")]
    #[rustc_clean(cfg = "cfail3")]
    pub fn indirect_trait_bound_where<T>(p: T)
    where
        T: Trait,
    {
    }
}
<|endoftext|>


<commit_before>mod render;

use self::render::*;
use super::module::*;

use glutin::{self, Api, ContextBuilder, ControlFlow, EventsLoop, GlContext, GlRequest, Window,
             WindowBuilder, WindowEvent};
use modular_flow as mf;

use std::env;
use std::fs::File;
use std::io::Read;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread;
use std::time::{Duration, Instant};
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};

use gfx;
use gfx::texture;
use gfx::traits::{Factory, FactoryExt};
use gfx::{CommandBuffer, Device, Encoder, IntoIndexBuffer, PipelineState, Resources, Slice};
use gfx::memory::{Bind, Usage};
use gfx::buffer::Role;
use gfx::handle::{Buffer, DepthStencilView, RenderTargetView, Sampler, ShaderResourceView, Texture};
use gfx_window_glutin as gfx_glutin;
use gfx_text;
use gfx_device_gl as gl;

pub fn gui_main() {
    let mut model = Model::new();
    main_loop(&mut model);
}

type OwnedModule = Mutex<Box<GuiModule>>;
type Graph = mf::Graph<OwnedModule>;
type Interface = mf::Interface<OwnedModule>;

/// Model holds info about GUI state
/// and program state
struct Model {
    time: f32,
    graph: Arc<Graph>,
    window_size: [f32; 2],
    mouse_pos: [f32; 2],
    node_z: Vec<mf::NodeId>,
    module_types: Vec<mf::MetaModule<OwnedModule>>,
}

impl Model {
    fn new() -> Model {
        Model {
            graph: Graph::new(),
            time: 0.0,
            window_size: [0.0, 0.0],
            mouse_pos: [0.0, 0.0],
            node_z: Vec::new(),
            module_types: Vec::new(),
        }
    }

    fn update_depth(&mut self) {
        use std::collections::HashSet;
        let graph_nodes = self.graph.node_map();
        let mut seen = HashSet::new();
        self.node_z.drain_filter(|node| {
            seen.insert(*node);
            !graph_nodes.contains_key(node)
        });
        for (id, _) in &graph_nodes {
            if !seen.contains(id) {
                self.node_z.push(*id);
            }
        }
    }
    fn update(&mut self) {
        self.update_depth();
    }

    fn handle_mouse_input(&mut self, state: &glutin::ElementState, button: &glutin::MouseButton) {
        use glutin::*;

        let graph_nodes = self.graph.node_map();
        let mut hit = false;
        let mut idx = self.node_z.len();
        for id in self.node_z.iter().rev() {
            idx -= 1;
            if let Some(node) = graph_nodes.get(id) {
                let mut module = node.module().lock().unwrap();
                let rect = *module.window_rect();
                if point_in_rect(self.mouse_pos, &rect) {
                    module.handle_click(self, state, button);
                    hit = true;
                    break;
                }
            }
        }
        if hit {
            if let ElementState::Pressed = state {
                let removed = self.node_z.remove(idx);
                self.node_z.push(removed);
            }
        }
    }

    fn handle(&mut self, event: &glutin::Event) {
        use glutin::WindowEvent::*;
        use glutin::*;
        //println!("{:?}", event);
        match event {
            glutin::Event::WindowEvent {
                window_id: _,
                event,
            } => match event {
                Resized(w, h) => {
                    self.window_size = [*w as f32, *h as f32];
                }
                CursorMoved {
                    device_id: _,
                    position,
                    modifiers: _,
                } => {
                    self.mouse_pos = [position.0 as f32, position.1 as f32];
                }
                MouseInput {
                    device_id: _,
                    state,
                    button,
                    modifiers: _,
                } => {
                    self.handle_mouse_input(&state, &button);
                }
                _ => (),
            },
            _ => (),
        }
    }
    fn load_metamodules(&mut self, ctx: RenderContext) {
        let mod_ctx = ctx.clone();
        let test_module = mf::MetaModule::new(
            "TestModule",
            Arc::new(move |ifc| {
                Mutex::new(
                    Box::new(GuiModuleWrapper::new(TestModule::new(ifc), mod_ctx.clone())) as Box<GuiModule>,
                )
            }),
        );
        self.module_types.push(test_module);
    }
}

fn main_loop(model: &mut Model) {
    // init window
    let mut events_loop = EventsLoop::new();
    let context = ContextBuilder::new().with_gl_profile(glutin::GlProfile::Core);
    let builder = WindowBuilder::new().with_title(String::from("flow-synth"));
    let (window, mut device, mut factory, mut main_color, mut main_depth) =
        gfx_glutin::init::<ColorFormat, DepthFormat>(builder, context, &events_loop);

    let mut target = Target {
        color: main_color,
        depth: main_depth,
    };

    // init rendering pipeline
    let mut ctx = RenderContext::new(factory.clone());

    model.load_metamodules(ctx.clone());
    model.graph.add_node(&model.module_types[0]);
    model.graph.add_node(&model.module_types[0]);
    model.graph.add_node(&model.module_types[0]);
    model.graph.add_node(&model.module_types[0]);

    // begin main loop
    let mut running = true;
    let timer = Instant::now();
    let mut frames = VecDeque::new();
    while running {
        // update fps
        let now = timer.elapsed();
        model.time = now.as_secs() as f32 + now.subsec_nanos() as f32 / 1_000_000_000.0;
        frames.push_back(model.time);
        while let Some(&old_frame) = frames.front() {
            if old_frame < model.time - 1.0 {
                frames.pop_front();
            } else {
                break;
            }
        }

        // handle events
        events_loop.poll_events(|event| {
            model.handle(&event);
            for node in model.graph.nodes() {
                let mut module = node.module().lock().unwrap();
                module.handle(&model, &event);
            }
            use glutin::WindowEvent::*;
            match event {
                glutin::Event::WindowEvent {
                    window_id: _,
                    event,
                } => match event {
                    Closed => running = false,
                    Resized(_, _) => {
                        gfx_glutin::update_views(&window, &mut target.color, &mut target.depth);
                    }
                    _ => (),
                },
                _ => (),
            }
        });

        // update model
        model.update();
        for node in model.graph.nodes() {
            let mut module = node.module().lock().unwrap();
            module.update(&model);
        }

        ctx.begin_frame(&target);

        // render nodes
        let mut z_idx = 0;
        let graph_nodes = model.graph.node_map();
        for id in &model.node_z {
            match graph_nodes.get(id) {
                Some(node) => {
                    let mut module = node.module().lock().unwrap();
                    module.render(
                        &mut device,
                        &mut ctx,
                        1.0 - z_idx as f32 / graph_nodes.len() as f32,
                    );
                    z_idx += 1;
                }
                None => (), // node was removed between call to model.update() and here. safe to ignore
            }
        }

        // render global widgets

        // debug text
        ctx.draw_text(
            &format!("FPS={} Time={}", frames.len(), model.time),
            [0.0, 0.0],
            [1.0, 1.0, 1.0],
        );

        ctx.end_frame(&mut device, &target);
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}

const TITLE_BAR_HEIGHT: f32 = 24.0;
const BORDER_SIZE: f32 = 1.0;

trait GuiModule: Module {
    fn render(&mut self, &mut gl::Device, &mut RenderContext, f32);
    fn window_rect(&self) -> &Rect;

    fn update(&mut self, model: &Model);
    fn handle(&mut self, model: &Model, event: &glutin::Event);
    fn handle_click(&mut self, model: &Model, state: &glutin::ElementState, button: &glutin::MouseButton);
}
struct GuiModuleWrapper<T: Module> {
    module: T,

    window_rect: Rect,
    size: [f32; 2],
    drag: Option<[f32; 2]>,
    dirty: bool,

    internal_ctx: RenderContext,
    module_target_texture: Texture<gl::Resources, gfx::format::R8_G8_B8_A8>,
    module_depth_texture: Texture<gl::Resources, gfx::format::D24_S8>,
    module_target_resource: ShaderResourceView<gl::Resources, [f32; 4]>,
    module_target: Target,
}

impl<T: Module> GuiModuleWrapper<T> {
    fn new(module: T, ctx: RenderContext) -> GuiModuleWrapper<T> {
        let mut factory = ctx.factory().clone();
        let size = [256.0; 2];
        let module_target_texture = factory
            .create_texture(
                texture::Kind::D2(size[0] as u16, size[1] as u16, texture::AaMode::Single),
                1, //levels
                Bind::RENDER_TARGET | Bind::SHADER_RESOURCE,
                Usage::Data,
                Some(gfx::format::ChannelType::Unorm),
            )
            .unwrap();
        let module_color_target = factory
            .view_texture_as_render_target(
                &module_target_texture,
                0,    //level
                None, //layer
            )
            .unwrap();
        let module_target_resource = factory
            .view_texture_as_shader_resource::<gfx::format::Rgba8>(
                &module_target_texture,
                (0, 0), // levels
                gfx::format::Swizzle::new(),
            )
            .unwrap();

        let module_depth_texture = factory
            .create_texture(
                texture::Kind::D2(size[0] as u16, size[1] as u16, texture::AaMode::Single),
                1, //levels
                Bind::DEPTH_STENCIL,
                Usage::Data,
                Some(gfx::format::ChannelType::Unorm),
            )
            .unwrap();
        let module_depth_target = factory
            .view_texture_as_depth_stencil(
                &module_depth_texture,
                0,    //level
                None, //layer
                texture::DepthStencilFlags::empty(),
            )
            .unwrap();

        let module_target = Target {
            color: module_color_target,
            depth: module_depth_target,
        };

        GuiModuleWrapper {
            module,
            window_rect: Rect {
                translate: [0.0, 0.0, 0.0],
                scale: size,
            },
            size,
            drag: None,
            dirty: true,
            internal_ctx: ctx,
            module_target_resource,
            module_target_texture,
            module_depth_texture,
            module_target,
        }
    }
    fn render_self(&mut self) {
        // borders
        self.internal_ctx.draw_rect(ColoredRect {
            translate: [0.0, 0.0, 0.0],
            scale: self.size,
            color: [1.0, 1.0, 1.0],
        });
        // background
        self.internal_ctx.draw_rect(ColoredRect {
            translate: [BORDER_SIZE, BORDER_SIZE + TITLE_BAR_HEIGHT, 0.0],
            scale: [
                self.size[0] - BORDER_SIZE * 2.0,
                self.size[1] - BORDER_SIZE * 2.0 - TITLE_BAR_HEIGHT,
            ],
            color: [0.1, 0.1, 0.1],
        });
        // title bar
        self.internal_ctx.draw_rect(ColoredRect {
            translate: [BORDER_SIZE, BORDER_SIZE, 0.0],
            scale: [self.size[0] - BORDER_SIZE * 2.0, TITLE_BAR_HEIGHT],
            color: [0.0, 0.0, 0.0],
        });
        let title = &self.title();
        self.internal_ctx
            .draw_text(title, [4.0, 4.0], [1.0, 1.0, 1.0]);
    }
}

impl<T> GuiModule for GuiModuleWrapper<T>
where
    T: Module,
{
    fn render(&mut self, device: &mut gl::Device, ctx: &mut RenderContext, z_idx: f32) {
        if self.dirty {
            self.internal_ctx.begin_frame(&self.module_target);
            self.render_self();
            self.internal_ctx.end_frame(device, &self.module_target);
            self.dirty = false;
        }

        self.window_rect.translate[2] = z_idx;
        ctx.draw_textured_rect(self.window_rect, self.module_target_resource.clone());
    }
    fn update(&mut self, model: &Model) {
        if let Some(drag) = self.drag {
            self.window_rect.translate = [
                (-drag[0] + model.mouse_pos[0]).floor(),
                (-drag[1] + model.mouse_pos[1]).floor(),
                0.0,
            ];
        }
    }
    fn handle(&mut self, model: &Model, event: &glutin::Event) {}
    fn handle_click(&mut self, model: &Model, state: &glutin::ElementState, button: &glutin::MouseButton) {
        use glutin::*;
        match button {
            MouseButton::Left => match state {
                ElementState::Pressed => {
                    let mut title_rect = self.window_rect;
                    title_rect.scale[1] = TITLE_BAR_HEIGHT + BORDER_SIZE;
                    if point_in_rect(model.mouse_pos, &title_rect) {
                        self.drag = Some([
                            model.mouse_pos[0] - self.window_rect.translate[0],
                            model.mouse_pos[1] - self.window_rect.translate[1],
                        ]);
                    }
                }
                ElementState::Released => {
                    self.drag = None;
                }
            },
            _ => {}
        }
    }
    fn window_rect(&self) -> &Rect {
        &self.window_rect
    }
}
impl<T> Module for GuiModuleWrapper<T>
where
    T: Module,
{
    fn start(&mut self) {
        T::start(&mut self.module);
    }
    fn title(&self) -> String {
        T::title(&self.module)
    }
}
<commit_msg>GuiModule -> GuiElement<commit_after>mod render;

use self::render::*;
use super::module::*;

use glutin::{self, Api, ContextBuilder, ControlFlow, EventsLoop, GlContext, GlRequest, Window,
             WindowBuilder, WindowEvent};
use modular_flow as mf;

use std::env;
use std::fs::File;
use std::io::Read;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread;
use std::time::{Duration, Instant};
use std::collections::VecDeque;
use std::sync::{Arc, Mutex};

use gfx;
use gfx::texture;
use gfx::traits::{Factory, FactoryExt};
use gfx::{CommandBuffer, Device, Encoder, IntoIndexBuffer, PipelineState, Resources, Slice};
use gfx::memory::{Bind, Usage};
use gfx::buffer::Role;
use gfx::handle::{Buffer, DepthStencilView, RenderTargetView, Sampler, ShaderResourceView, Texture};
use gfx_window_glutin as gfx_glutin;
use gfx_text;
use gfx_device_gl as gl;

pub fn gui_main() {
    let mut model = Model::new();
    main_loop(&mut model);
}

type OwnedModule = Mutex<Box<GuiElement>>;
type Graph = mf::Graph<OwnedModule>;
type Interface = mf::Interface<OwnedModule>;

/// Model holds info about GUI state
/// and program state
struct Model {
    time: f32,
    graph: Arc<Graph>,
    window_size: [f32; 2],
    mouse_pos: [f32; 2],
    node_z: Vec<mf::NodeId>,
    module_types: Vec<mf::MetaModule<OwnedModule>>,
}

impl Model {
    fn new() -> Model {
        Model {
            graph: Graph::new(),
            time: 0.0,
            window_size: [0.0, 0.0],
            mouse_pos: [0.0, 0.0],
            node_z: Vec::new(),
            module_types: Vec::new(),
        }
    }

    fn update_depth(&mut self) {
        use std::collections::HashSet;
        let graph_nodes = self.graph.node_map();
        let mut seen = HashSet::new();
        self.node_z.drain_filter(|node| {
            seen.insert(*node);
            !graph_nodes.contains_key(node)
        });
        for (id, _) in &graph_nodes {
            if !seen.contains(id) {
                self.node_z.push(*id);
            }
        }
    }
    fn update(&mut self) {
        self.update_depth();
    }

    fn handle_mouse_input(&mut self, state: &glutin::ElementState, button: &glutin::MouseButton) {
        use glutin::*;

        let graph_nodes = self.graph.node_map();
        let mut hit = false;
        let mut idx = self.node_z.len();
        for id in self.node_z.iter().rev() {
            idx -= 1;
            if let Some(node) = graph_nodes.get(id) {
                let mut module = node.module().lock().unwrap();
                let rect = *module.window_rect();
                if point_in_rect(self.mouse_pos, &rect) {
                    module.handle_click(self, state, button);
                    hit = true;
                    break;
                }
            }
        }
        if hit {
            if let ElementState::Pressed = state {
                let removed = self.node_z.remove(idx);
                self.node_z.push(removed);
            }
        }
    }

    fn handle(&mut self, event: &glutin::Event) {
        use glutin::WindowEvent::*;
        use glutin::*;
        //println!("{:?}", event);
        match event {
            glutin::Event::WindowEvent {
                window_id: _,
                event,
            } => match event {
                Resized(w, h) => {
                    self.window_size = [*w as f32, *h as f32];
                }
                CursorMoved {
                    device_id: _,
                    position,
                    modifiers: _,
                } => {
                    self.mouse_pos = [position.0 as f32, position.1 as f32];
                }
                MouseInput {
                    device_id: _,
                    state,
                    button,
                    modifiers: _,
                } => {
                    self.handle_mouse_input(&state, &button);
                }
                _ => (),
            },
            _ => (),
        }
    }
    fn load_metamodules(&mut self, ctx: RenderContext) {
        let mod_ctx = ctx.clone();
        let test_module = mf::MetaModule::new(
            "TestModule",
            Arc::new(move |ifc| {
                Mutex::new(
                    Box::new(GuiModuleWrapper::new(TestModule::new(ifc), mod_ctx.clone())) as Box<GuiElement>,
                )
            }),
        );
        self.module_types.push(test_module);
    }
}

fn main_loop(model: &mut Model) {
    // init window
    let mut events_loop = EventsLoop::new();
    let context = ContextBuilder::new().with_gl_profile(glutin::GlProfile::Core);
    let builder = WindowBuilder::new().with_title(String::from("flow-synth"));
    let (window, mut device, mut factory, mut main_color, mut main_depth) =
        gfx_glutin::init::<ColorFormat, DepthFormat>(builder, context, &events_loop);

    let mut target = Target {
        color: main_color,
        depth: main_depth,
    };

    // init rendering pipeline
    let mut ctx = RenderContext::new(factory.clone());

    model.load_metamodules(ctx.clone());
    model.graph.add_node(&model.module_types[0]);
    model.graph.add_node(&model.module_types[0]);
    model.graph.add_node(&model.module_types[0]);
    model.graph.add_node(&model.module_types[0]);

    // begin main loop
    let mut running = true;
    let timer = Instant::now();
    let mut frames = VecDeque::new();
    while running {
        // update fps
        let now = timer.elapsed();
        model.time = now.as_secs() as f32 + now.subsec_nanos() as f32 / 1_000_000_000.0;
        frames.push_back(model.time);
        while let Some(&old_frame) = frames.front() {
            if old_frame < model.time - 1.0 {
                frames.pop_front();
            } else {
                break;
            }
        }

        // handle events
        events_loop.poll_events(|event| {
            model.handle(&event);
            for node in model.graph.nodes() {
                let mut module = node.module().lock().unwrap();
                module.handle(&model, &event);
            }
            use glutin::WindowEvent::*;
            match event {
                glutin::Event::WindowEvent {
                    window_id: _,
                    event,
                } => match event {
                    Closed => running = false,
                    Resized(_, _) => {
                        gfx_glutin::update_views(&window, &mut target.color, &mut target.depth);
                    }
                    _ => (),
                },
                _ => (),
            }
        });

        // update model
        model.update();
        for node in model.graph.nodes() {
            let mut module = node.module().lock().unwrap();
            module.update(&model);
        }

        ctx.begin_frame(&target);

        // render nodes
        let mut z_idx = 0;
        let graph_nodes = model.graph.node_map();
        for id in &model.node_z {
            match graph_nodes.get(id) {
                Some(node) => {
                    let mut module = node.module().lock().unwrap();
                    module.render(
                        &mut device,
                        &mut ctx,
                        1.0 - z_idx as f32 / graph_nodes.len() as f32,
                    );
                    z_idx += 1;
                }
                None => (), // node was removed between call to model.update() and here. safe to ignore
            }
        }

        // render global widgets

        // debug text
        ctx.draw_text(
            &format!("FPS={} Time={}", frames.len(), model.time),
            [0.0, 0.0],
            [1.0, 1.0, 1.0],
        );

        ctx.end_frame(&mut device, &target);
        window.swap_buffers().unwrap();
        device.cleanup();
    }
}

const TITLE_BAR_HEIGHT: f32 = 24.0;
const BORDER_SIZE: f32 = 1.0;

trait GuiElement {
    fn render(&mut self, &mut gl::Device, &mut RenderContext, f32);
    fn window_rect(&self) -> &Rect;

    fn update(&mut self, model: &Model);
    fn handle(&mut self, model: &Model, event: &glutin::Event);
    fn handle_click(&mut self, model: &Model, state: &glutin::ElementState, button: &glutin::MouseButton);
}
struct GuiModuleWrapper<T: Module> {
    module: T,

    window_rect: Rect,
    size: [f32; 2],
    drag: Option<[f32; 2]>,
    dirty: bool,

    internal_ctx: RenderContext,
    module_target_texture: Texture<gl::Resources, gfx::format::R8_G8_B8_A8>,
    module_depth_texture: Texture<gl::Resources, gfx::format::D24_S8>,
    module_target_resource: ShaderResourceView<gl::Resources, [f32; 4]>,
    module_target: Target,
}

impl<T: Module> GuiModuleWrapper<T> {
    fn new(module: T, ctx: RenderContext) -> GuiModuleWrapper<T> {
        let mut factory = ctx.factory().clone();
        let size = [256.0; 2];
        let module_target_texture = factory
            .create_texture(
                texture::Kind::D2(size[0] as u16, size[1] as u16, texture::AaMode::Single),
                1, //levels
                Bind::RENDER_TARGET | Bind::SHADER_RESOURCE,
                Usage::Data,
                Some(gfx::format::ChannelType::Unorm),
            )
            .unwrap();
        let module_color_target = factory
            .view_texture_as_render_target(
                &module_target_texture,
                0,    //level
                None, //layer
            )
            .unwrap();
        let module_target_resource = factory
            .view_texture_as_shader_resource::<gfx::format::Rgba8>(
                &module_target_texture,
                (0, 0), // levels
                gfx::format::Swizzle::new(),
            )
            .unwrap();

        let module_depth_texture = factory
            .create_texture(
                texture::Kind::D2(size[0] as u16, size[1] as u16, texture::AaMode::Single),
                1, //levels
                Bind::DEPTH_STENCIL,
                Usage::Data,
                Some(gfx::format::ChannelType::Unorm),
            )
            .unwrap();
        let module_depth_target = factory
            .view_texture_as_depth_stencil(
                &module_depth_texture,
                0,    //level
                None, //layer
                texture::DepthStencilFlags::empty(),
            )
            .unwrap();

        let module_target = Target {
            color: module_color_target,
            depth: module_depth_target,
        };

        GuiModuleWrapper {
            module,
            window_rect: Rect {
                translate: [0.0, 0.0, 0.0],
                scale: size,
            },
            size,
            drag: None,
            dirty: true,
            internal_ctx: ctx,
            module_target_resource,
            module_target_texture,
            module_depth_texture,
            module_target,
        }
    }
    fn render_self(&mut self) {
        // borders
        self.internal_ctx.draw_rect(ColoredRect {
            translate: [0.0, 0.0, 0.0],
            scale: self.size,
            color: [1.0, 1.0, 1.0],
        });
        // background
        self.internal_ctx.draw_rect(ColoredRect {
            translate: [BORDER_SIZE, BORDER_SIZE + TITLE_BAR_HEIGHT, 0.0],
            scale: [
                self.size[0] - BORDER_SIZE * 2.0,
                self.size[1] - BORDER_SIZE * 2.0 - TITLE_BAR_HEIGHT,
            ],
            color: [0.1, 0.1, 0.1],
        });
        // title bar
        self.internal_ctx.draw_rect(ColoredRect {
            translate: [BORDER_SIZE, BORDER_SIZE, 0.0],
            scale: [self.size[0] - BORDER_SIZE * 2.0, TITLE_BAR_HEIGHT],
            color: [0.0, 0.0, 0.0],
        });
        let title = &self.title();
        self.internal_ctx
            .draw_text(title, [4.0, 4.0], [1.0, 1.0, 1.0]);
    }
}

impl<T> GuiElement for GuiModuleWrapper<T>
where
    T: Module,
{
    fn render(&mut self, device: &mut gl::Device, ctx: &mut RenderContext, z_idx: f32) {
        if self.dirty {
            self.internal_ctx.begin_frame(&self.module_target);
            self.render_self();
            self.internal_ctx.end_frame(device, &self.module_target);
            self.dirty = false;
        }

        self.window_rect.translate[2] = z_idx;
        ctx.draw_textured_rect(self.window_rect, self.module_target_resource.clone());
    }
    fn update(&mut self, model: &Model) {
        if let Some(drag) = self.drag {
            self.window_rect.translate = [
                (-drag[0] + model.mouse_pos[0]).floor(),
                (-drag[1] + model.mouse_pos[1]).floor(),
                0.0,
            ];
        }
    }
    fn handle(&mut self, model: &Model, event: &glutin::Event) {}
    fn handle_click(&mut self, model: &Model, state: &glutin::ElementState, button: &glutin::MouseButton) {
        use glutin::*;
        match button {
            MouseButton::Left => match state {
                ElementState::Pressed => {
                    let mut title_rect = self.window_rect;
                    title_rect.scale[1] = TITLE_BAR_HEIGHT + BORDER_SIZE;
                    if point_in_rect(model.mouse_pos, &title_rect) {
                        self.drag = Some([
                            model.mouse_pos[0] - self.window_rect.translate[0],
                            model.mouse_pos[1] - self.window_rect.translate[1],
                        ]);
                    }
                }
                ElementState::Released => {
                    self.drag = None;
                }
            },
            _ => {}
        }
    }
    fn window_rect(&self) -> &Rect {
        &self.window_rect
    }
}
impl<T> Module for GuiModuleWrapper<T>
where
    T: Module,
{
    fn start(&mut self) {
        T::start(&mut self.module);
    }
    fn title(&self) -> String {
        T::title(&self.module)
    }
}
<|endoftext|>


<commit_before>use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};

use actix_http::{Error, Response};
use actix_service::{Service, ServiceFactory};
use futures_util::future::{ready, Ready};
use futures_util::ready;
use pin_project::pin_project;

use crate::extract::FromRequest;
use crate::request::HttpRequest;
use crate::responder::Responder;
use crate::service::{ServiceRequest, ServiceResponse};

///  A request handler is an async function that accepts zero or more parameters that can be
///  extracted from a request (ie, [`impl FromRequest`](crate::FromRequest)) and returns a type that can be converted into
///  an [`HttpResponse`](crate::HttpResponse) (ie, [`impl Responder`](crate::Responder)).
///
/// If you got the error `the trait Handler<_, _, _> is not implemented`, then your function is not
/// a valid handler. See [Request Handlers](https://actix.rs/docs/handlers/) for more information.
pub trait Handler<T, R>: Clone + 'static
where
    R: Future,
    R::Output: Responder,
{
    fn call(&self, param: T) -> R;
}

impl<F, R> Handler<(), R> for F
where
    F: Fn() -> R + Clone + 'static,
    R: Future,
    R::Output: Responder,
{
    fn call(&self, _: ()) -> R {
        (self)()
    }
}

#[doc(hidden)]
/// Extract arguments from request, run factory function and make response.
pub struct HandlerService<F, T, R>
where
    F: Handler<T, R>,
    T: FromRequest,
    R: Future,
    R::Output: Responder,
{
    hnd: F,
    _phantom: PhantomData<(T, R)>,
}

impl<F, T, R> HandlerService<F, T, R>
where
    F: Handler<T, R>,
    T: FromRequest,
    R: Future,
    R::Output: Responder,
{
    pub fn new(hnd: F) -> Self {
        Self {
            hnd,
            _phantom: PhantomData,
        }
    }
}

impl<F, T, R> Clone for HandlerService<F, T, R>
where
    F: Handler<T, R>,
    T: FromRequest,
    R: Future,
    R::Output: Responder,
{
    fn clone(&self) -> Self {
        Self {
            hnd: self.hnd.clone(),
            _phantom: PhantomData,
        }
    }
}

impl<F, T, R> ServiceFactory<ServiceRequest> for HandlerService<F, T, R>
where
    F: Handler<T, R>,
    T: FromRequest,
    R: Future,
    R::Output: Responder,
{
    type Response = ServiceResponse;
    type Error = Error;
    type Config = ();
    type Service = Self;
    type InitError = ();
    type Future = Ready<Result<Self::Service, ()>>;

    fn new_service(&self, _: ()) -> Self::Future {
        ready(Ok(self.clone()))
    }
}

/// HandlerService is both it's ServiceFactory and Service Type.
impl<F, T, R> Service<ServiceRequest> for HandlerService<F, T, R>
where
    F: Handler<T, R>,
    T: FromRequest,
    R: Future,
    R::Output: Responder,
{
    type Response = ServiceResponse;
    type Error = Error;
    type Future = HandlerServiceFuture<F, T, R>;

    fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        Poll::Ready(Ok(()))
    }

    fn call(&self, req: ServiceRequest) -> Self::Future {
        let (req, mut payload) = req.into_parts();
        let fut = T::from_request(&req, &mut payload);
        HandlerServiceFuture::Extract(fut, Some(req), self.hnd.clone())
    }
}

#[doc(hidden)]
#[pin_project(project = HandlerProj)]
pub enum HandlerServiceFuture<F, T, R>
where
    F: Handler<T, R>,
    T: FromRequest,
    R: Future,
    R::Output: Responder,
{
    Extract(#[pin] T::Future, Option<HttpRequest>, F),
    Handle(#[pin] R, Option<HttpRequest>),
}

impl<F, T, R> Future for HandlerServiceFuture<F, T, R>
where
    F: Handler<T, R>,
    T: FromRequest,
    R: Future,
    R::Output: Responder,
{
    // Error type in this future is a placeholder type.
    // all instances of error must be converted to ServiceResponse and return in Ok.
    type Output = Result<ServiceResponse, Error>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        loop {
            match self.as_mut().project() {
                HandlerProj::Extract(fut, req, handle) => {
                    match ready!(fut.poll(cx)) {
                        Ok(item) => {
                            let fut = handle.call(item);
                            let state = HandlerServiceFuture::Handle(fut, req.take());
                            self.as_mut().set(state);
                        }
                        Err(e) => {
                            let res: Response = e.into().into();
                            let req = req.take().unwrap();
                            return Poll::Ready(Ok(ServiceResponse::new(req, res)));
                        }
                    };
                }
                HandlerProj::Handle(fut, req) => {
                    let res = ready!(fut.poll(cx));
                    let req = req.take().unwrap();
                    let res = res.respond_to(&req);
                    return Poll::Ready(Ok(ServiceResponse::new(req, res)));
                }
            }
        }
    }
}

/// FromRequest trait impl for tuples
macro_rules! factory_tuple ({ $(($n:tt, $T:ident)),+} => {
    impl<Func, $($T,)+ Res> Handler<($($T,)+), Res> for Func
    where Func: Fn($($T,)+) -> Res + Clone + 'static,
          Res: Future,
          Res::Output: Responder,
    {
        fn call(&self, param: ($($T,)+)) -> Res {
            (self)($(param.$n,)+)
        }
    }
});

#[rustfmt::skip]
mod m {
    use super::*;

    factory_tuple!((0, A));
    factory_tuple!((0, A), (1, B));
    factory_tuple!((0, A), (1, B), (2, C));
    factory_tuple!((0, A), (1, B), (2, C), (3, D));
    factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E));
    factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F));
    factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G));
    factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H));
    factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I));
    factory_tuple!((0, A), (1, B), (2, C), (3, D), (4, E), (5, F), (6, G), (7, H), (8, I), (9, J));
}
<commit_msg>Simplify handler factory macro (#2086)<commit_after>use std::future::Future;
use std::marker::PhantomData;
use std::pin::Pin;
use std::task::{Context, Poll};

use actix_http::{Error, Response};
use actix_service::{Service, ServiceFactory};
use futures_util::future::{ready, Ready};
use futures_util::ready;
use pin_project::pin_project;

use crate::extract::FromRequest;
use crate::request::HttpRequest;
use crate::responder::Responder;
use crate::service::{ServiceRequest, ServiceResponse};

///  A request handler is an async function that accepts zero or more parameters that can be
///  extracted from a request (ie, [`impl FromRequest`](crate::FromRequest)) and returns a type that can be converted into
///  an [`HttpResponse`](crate::HttpResponse) (ie, [`impl Responder`](crate::Responder)).
///
/// If you got the error `the trait Handler<_, _, _> is not implemented`, then your function is not
/// a valid handler. See [Request Handlers](https://actix.rs/docs/handlers/) for more information.
pub trait Handler<T, R>: Clone + 'static
where
    R: Future,
    R::Output: Responder,
{
    fn call(&self, param: T) -> R;
}

#[doc(hidden)]
/// Extract arguments from request, run factory function and make response.
pub struct HandlerService<F, T, R>
where
    F: Handler<T, R>,
    T: FromRequest,
    R: Future,
    R::Output: Responder,
{
    hnd: F,
    _phantom: PhantomData<(T, R)>,
}

impl<F, T, R> HandlerService<F, T, R>
where
    F: Handler<T, R>,
    T: FromRequest,
    R: Future,
    R::Output: Responder,
{
    pub fn new(hnd: F) -> Self {
        Self {
            hnd,
            _phantom: PhantomData,
        }
    }
}

impl<F, T, R> Clone for HandlerService<F, T, R>
where
    F: Handler<T, R>,
    T: FromRequest,
    R: Future,
    R::Output: Responder,
{
    fn clone(&self) -> Self {
        Self {
            hnd: self.hnd.clone(),
            _phantom: PhantomData,
        }
    }
}

impl<F, T, R> ServiceFactory<ServiceRequest> for HandlerService<F, T, R>
where
    F: Handler<T, R>,
    T: FromRequest,
    R: Future,
    R::Output: Responder,
{
    type Response = ServiceResponse;
    type Error = Error;
    type Config = ();
    type Service = Self;
    type InitError = ();
    type Future = Ready<Result<Self::Service, ()>>;

    fn new_service(&self, _: ()) -> Self::Future {
        ready(Ok(self.clone()))
    }
}

/// HandlerService is both it's ServiceFactory and Service Type.
impl<F, T, R> Service<ServiceRequest> for HandlerService<F, T, R>
where
    F: Handler<T, R>,
    T: FromRequest,
    R: Future,
    R::Output: Responder,
{
    type Response = ServiceResponse;
    type Error = Error;
    type Future = HandlerServiceFuture<F, T, R>;

    fn poll_ready(&self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        Poll::Ready(Ok(()))
    }

    fn call(&self, req: ServiceRequest) -> Self::Future {
        let (req, mut payload) = req.into_parts();
        let fut = T::from_request(&req, &mut payload);
        HandlerServiceFuture::Extract(fut, Some(req), self.hnd.clone())
    }
}

#[doc(hidden)]
#[pin_project(project = HandlerProj)]
pub enum HandlerServiceFuture<F, T, R>
where
    F: Handler<T, R>,
    T: FromRequest,
    R: Future,
    R::Output: Responder,
{
    Extract(#[pin] T::Future, Option<HttpRequest>, F),
    Handle(#[pin] R, Option<HttpRequest>),
}

impl<F, T, R> Future for HandlerServiceFuture<F, T, R>
where
    F: Handler<T, R>,
    T: FromRequest,
    R: Future,
    R::Output: Responder,
{
    // Error type in this future is a placeholder type.
    // all instances of error must be converted to ServiceResponse and return in Ok.
    type Output = Result<ServiceResponse, Error>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        loop {
            match self.as_mut().project() {
                HandlerProj::Extract(fut, req, handle) => {
                    match ready!(fut.poll(cx)) {
                        Ok(item) => {
                            let fut = handle.call(item);
                            let state = HandlerServiceFuture::Handle(fut, req.take());
                            self.as_mut().set(state);
                        }
                        Err(e) => {
                            let res: Response = e.into().into();
                            let req = req.take().unwrap();
                            return Poll::Ready(Ok(ServiceResponse::new(req, res)));
                        }
                    };
                }
                HandlerProj::Handle(fut, req) => {
                    let res = ready!(fut.poll(cx));
                    let req = req.take().unwrap();
                    let res = res.respond_to(&req);
                    return Poll::Ready(Ok(ServiceResponse::new(req, res)));
                }
            }
        }
    }
}

/// FromRequest trait impl for tuples
macro_rules! factory_tuple ({ $($param:ident)* } => {
    impl<Func, $($param,)* Res> Handler<($($param,)*), Res> for Func
    where Func: Fn($($param),*) -> Res + Clone + 'static,
          Res: Future,
          Res::Output: Responder,
    {
        #[allow(non_snake_case)]
        fn call(&self, ($($param,)*): ($($param,)*)) -> Res {
            (self)($($param,)*)
        }
    }
});

factory_tuple! {}
factory_tuple! { A }
factory_tuple! { A B }
factory_tuple! { A B C }
factory_tuple! { A B C D }
factory_tuple! { A B C D E }
factory_tuple! { A B C D E F }
factory_tuple! { A B C D E F G }
factory_tuple! { A B C D E F G H }
factory_tuple! { A B C D E F G H I }
factory_tuple! { A B C D E F G H I J }
factory_tuple! { A B C D E F G H I J K }
factory_tuple! { A B C D E F G H I J K L }
<|endoftext|>


<commit_before>use game::{Game, GameStore, Outcome};
use iron::prelude::*;
use iron::status;
use persistent::{Read, Write};
use rand::{Rng, thread_rng};
use request::Data;
use words::WordList;
use serde_json::to_string as serialize;

pub fn check(req: &mut Request) -> IronResult<Response> {
    let token = req.token()?.to_owned();
    let mutex = req.get::<Write<GameStore>>().expect("gamestore not found");

    let mut games = mutex.lock().expect("unable to lock mutex");
    let game = games.entry(token).or_insert_with(|| Game::new(select_word(req)));

    if game.outcome() != Outcome::InProgress {
        *game = Game::new(select_word(req));
    }

    Ok(Response::with((
        status::Ok,
        serialize(&game.check()).unwrap()
    )))
}

pub fn guess(req: &mut Request) -> IronResult<Response> {
    let token = req.token()?.to_owned();
    let guess = req.guess()?.to_owned();
    let mutex = req.get::<Write<GameStore>>().expect("gamestore not found");

    let mut games = mutex.lock().expect("unable to lock mutex");
    let mut game = games.entry(token).or_insert_with(|| Game::new(select_word(req)));

    if game.outcome() != Outcome::InProgress {
        *game = Game::new(select_word(req));
    }

    Ok(Response::with((
        status::Ok,
        serialize(&game.guess(&guess)).unwrap()
    )))
}

fn select_word(req: &mut Request) -> String {
    let word_list = req.get::<Read<WordList>>().expect("wordlist not found");
    thread_rng().choose(&word_list).map_or("apple".to_owned(), |word| word.to_owned())
}<commit_msg>Use application/json header<commit_after>use game::{Game, GameStore, Outcome};
use iron::prelude::*;
use iron::status;
use persistent::{Read, Write};
use rand::{Rng, thread_rng};
use request::Data;
use words::WordList;
use serde::ser::Serialize;
use serde_json::to_string as serialize;

pub fn check(req: &mut Request) -> IronResult<Response> {
    let token = req.token()?.to_owned();
    let mutex = req.get::<Write<GameStore>>().expect("gamestore not found");

    let mut games = mutex.lock().expect("unable to lock mutex");
    let game = games.entry(token).or_insert_with(|| Game::new(select_word(req)));

    if game.outcome() != Outcome::InProgress {
        *game = Game::new(select_word(req));
    }

    Ok(create_response(&game.check()))
}

pub fn guess(req: &mut Request) -> IronResult<Response> {
    let token = req.token()?.to_owned();
    let guess = req.guess()?.to_owned();
    let mutex = req.get::<Write<GameStore>>().expect("gamestore not found");

    let mut games = mutex.lock().expect("unable to lock mutex");
    let mut game = games.entry(token).or_insert_with(|| Game::new(select_word(req)));

    if game.outcome() != Outcome::InProgress {
        *game = Game::new(select_word(req));
    }

    Ok(create_response(&game.guess(&guess)))
}

fn create_response<T: Serialize>(model: &T) -> Response {
    use iron::headers::ContentType;

    let mut response = Response::with((
        status::Ok,
        serialize(model).unwrap(),
    ));
    response.headers.set(ContentType::json());
    response
}

fn select_word(req: &mut Request) -> String {
    let word_list = req.get::<Read<WordList>>().expect("wordlist not found");
    thread_rng().choose(&word_list).map_or("apple".to_owned(), |word| word.to_owned())
}<|endoftext|>


<commit_before>// -*- rust -*-

// error-pattern:1 == 2
// no-valgrind
use std;
import std::task;
import std::comm::port;
import std::comm::recv;

fn child() { assert (1 == 2); }

fn main() {
    let p = port::<int>();
    let f = child;
    task::spawn(f);
    let x = recv(p);
}
<commit_msg>XFAIL run-fail/linked-failure<commit_after>// -*- rust -*-

// error-pattern:1 == 2
// xfail-test
// no-valgrind
use std;
import std::task;
import std::comm::port;
import std::comm::recv;

fn child() { assert (1 == 2); }

fn main() {
    let p = port::<int>();
    let f = child;
    task::spawn(f);
    let x = recv(p);
}
<|endoftext|>