<commit_before>#![cfg(not(syn_disable_nightly_tests))]
#![recursion_limit = "1024"]
#![feature(rustc_private)]

extern crate rustc_ast;
extern crate rustc_errors;
extern crate rustc_expand;
extern crate rustc_parse as parse;
extern crate rustc_session;
extern crate rustc_span;

use crate::common::eq::SpanlessEq;
use quote::quote;
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use rustc_ast::ast;
use rustc_errors::PResult;
use rustc_session::parse::ParseSess;
use rustc_span::source_map::FilePathMapping;
use rustc_span::FileName;
use std::fs::File;
use std::io::Read;
use std::panic;
use std::process;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Instant;
use walkdir::{DirEntry, WalkDir};

#[macro_use]
mod macros;

#[allow(dead_code)]
mod common;

mod repo;

#[test]
fn test_round_trip() {
    common::rayon_init();
    repo::clone_rust();
    let abort_after = common::abort_after();
    if abort_after == 0 {
        panic!("Skipping all round_trip tests");
    }

    let failed = AtomicUsize::new(0);

    WalkDir::new("tests/rust")
        .sort_by(|a, b| a.file_name().cmp(b.file_name()))
        .into_iter()
        .filter_entry(repo::base_dir_filter)
        .collect::<Result<Vec<DirEntry>, walkdir::Error>>()
        .unwrap()
        .into_par_iter()
        .for_each(|entry| {
            let path = entry.path();
            if path.is_dir() {
                return;
            }

            let mut file = File::open(path).unwrap();
            let mut content = String::new();
            file.read_to_string(&mut content).unwrap();

            let start = Instant::now();
            let (krate, elapsed) = match syn::parse_file(&content) {
                Ok(krate) => (krate, start.elapsed()),
                Err(msg) => {
                    errorf!("=== {}: syn failed to parse\n{:?}\n", path.display(), msg);
                    let prev_failed = failed.fetch_add(1, Ordering::SeqCst);
                    if prev_failed + 1 >= abort_after {
                        process::exit(1);
                    }
                    return;
                }
            };
            let back = quote!(#krate).to_string();
            let edition = repo::edition(path).parse().unwrap();

            rustc_span::with_session_globals(edition, || {
                let equal = match panic::catch_unwind(|| {
                    let sess = ParseSess::new(FilePathMapping::empty());
                    let before = match librustc_parse(content, &sess) {
                        Ok(before) => before,
                        Err(mut diagnostic) => {
                            diagnostic.cancel();
                            if diagnostic
                                .message()
                                .starts_with("file not found for module")
                            {
                                errorf!("=== {}: ignore\n", path.display());
                            } else {
                                errorf!(
                                    "=== {}: ignore - librustc failed to parse original content: {}\n",
                                    path.display(),
                                    diagnostic.message(),
                                );
                            }
                            return Err(true);
                        }
                    };
                    let after = match librustc_parse(back, &sess) {
                        Ok(after) => after,
                        Err(mut diagnostic) => {
                            errorf!("=== {}: librustc failed to parse", path.display());
                            diagnostic.emit();
                            return Err(false);
                        }
                    };
                    Ok((before, after))
                }) {
                    Err(_) => {
                        errorf!("=== {}: ignoring librustc panic\n", path.display());
                        true
                    }
                    Ok(Err(equal)) => equal,
                    Ok(Ok((before, after))) => if SpanlessEq::eq(&before, &after) {
                        errorf!(
                            "=== {}: pass in {}ms\n",
                            path.display(),
                            elapsed.as_secs() * 1000
                                + u64::from(elapsed.subsec_nanos()) / 1_000_000
                        );
                        true
                    } else {
                        errorf!(
                            "=== {}: FAIL\nbefore: {:#?}\nafter: {:#?}\n",
                            path.display(),
                            before,
                            after,
                        );
                        false
                    },
                };
                if !equal {
                    let prev_failed = failed.fetch_add(1, Ordering::SeqCst);
                    if prev_failed + 1 >= abort_after {
                        process::exit(1);
                    }
                }
            });
        });

    let failed = failed.load(Ordering::SeqCst);
    if failed > 0 {
        panic!("{} failures", failed);
    }
}

fn librustc_parse(content: String, sess: &ParseSess) -> PResult<ast::Crate> {
    let name = FileName::Custom("test_round_trip".to_string());
    parse::parse_crate_from_source_str(name, content, sess)
}
<commit_msg>Factor out round trip helper to process dir entry<commit_after>#![cfg(not(syn_disable_nightly_tests))]
#![recursion_limit = "1024"]
#![feature(rustc_private)]

extern crate rustc_ast;
extern crate rustc_errors;
extern crate rustc_expand;
extern crate rustc_parse as parse;
extern crate rustc_session;
extern crate rustc_span;

use crate::common::eq::SpanlessEq;
use quote::quote;
use rayon::iter::{IntoParallelIterator, ParallelIterator};
use rustc_ast::ast;
use rustc_errors::PResult;
use rustc_session::parse::ParseSess;
use rustc_span::source_map::FilePathMapping;
use rustc_span::FileName;
use std::fs::File;
use std::io::Read;
use std::panic;
use std::path::Path;
use std::process;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Instant;
use walkdir::{DirEntry, WalkDir};

#[macro_use]
mod macros;

#[allow(dead_code)]
mod common;

mod repo;

#[test]
fn test_round_trip() {
    common::rayon_init();
    repo::clone_rust();
    let abort_after = common::abort_after();
    if abort_after == 0 {
        panic!("Skipping all round_trip tests");
    }

    let failed = AtomicUsize::new(0);

    WalkDir::new("tests/rust")
        .sort_by(|a, b| a.file_name().cmp(b.file_name()))
        .into_iter()
        .filter_entry(repo::base_dir_filter)
        .collect::<Result<Vec<DirEntry>, walkdir::Error>>()
        .unwrap()
        .into_par_iter()
        .for_each(|entry| {
            let path = entry.path();
            if !path.is_dir() {
                test(path, &failed, abort_after);
            }
        });

    let failed = failed.load(Ordering::SeqCst);
    if failed > 0 {
        panic!("{} failures", failed);
    }
}

fn test(path: &Path, failed: &AtomicUsize, abort_after: usize) {
    let mut file = File::open(path).unwrap();
    let mut content = String::new();
    file.read_to_string(&mut content).unwrap();

    let start = Instant::now();
    let (krate, elapsed) = match syn::parse_file(&content) {
        Ok(krate) => (krate, start.elapsed()),
        Err(msg) => {
            errorf!("=== {}: syn failed to parse\n{:?}\n", path.display(), msg);
            let prev_failed = failed.fetch_add(1, Ordering::SeqCst);
            if prev_failed + 1 >= abort_after {
                process::exit(1);
            }
            return;
        }
    };
    let back = quote!(#krate).to_string();
    let edition = repo::edition(path).parse().unwrap();

    rustc_span::with_session_globals(edition, || {
        let equal = match panic::catch_unwind(|| {
            let sess = ParseSess::new(FilePathMapping::empty());
            let before = match librustc_parse(content, &sess) {
                Ok(before) => before,
                Err(mut diagnostic) => {
                    diagnostic.cancel();
                    if diagnostic
                        .message()
                        .starts_with("file not found for module")
                    {
                        errorf!("=== {}: ignore\n", path.display());
                    } else {
                        errorf!(
                            "=== {}: ignore - librustc failed to parse original content: {}\n",
                            path.display(),
                            diagnostic.message(),
                        );
                    }
                    return Err(true);
                }
            };
            let after = match librustc_parse(back, &sess) {
                Ok(after) => after,
                Err(mut diagnostic) => {
                    errorf!("=== {}: librustc failed to parse", path.display());
                    diagnostic.emit();
                    return Err(false);
                }
            };
            Ok((before, after))
        }) {
            Err(_) => {
                errorf!("=== {}: ignoring librustc panic\n", path.display());
                true
            }
            Ok(Err(equal)) => equal,
            Ok(Ok((before, after))) => {
                if SpanlessEq::eq(&before, &after) {
                    errorf!(
                        "=== {}: pass in {}ms\n",
                        path.display(),
                        elapsed.as_secs() * 1000 + u64::from(elapsed.subsec_nanos()) / 1_000_000
                    );
                    true
                } else {
                    errorf!(
                        "=== {}: FAIL\nbefore: {:#?}\nafter: {:#?}\n",
                        path.display(),
                        before,
                        after,
                    );
                    false
                }
            }
        };
        if !equal {
            let prev_failed = failed.fetch_add(1, Ordering::SeqCst);
            if prev_failed + 1 >= abort_after {
                process::exit(1);
            }
        }
    });
}

fn librustc_parse(content: String, sess: &ParseSess) -> PResult<ast::Crate> {
    let name = FileName::Custom("test_round_trip".to_string());
    parse::parse_crate_from_source_str(name, content, sess)
}
<|endoftext|>


<commit_before>//! Ensure truncated images are read without panics.

use std::fs;
use std::path::PathBuf;
use std::io::Read;

extern crate image;
extern crate glob;

const BASE_PATH: [&'static str; 2] = [".", "tests"];
const IMAGE_DIR: &'static str = "images";

fn process_images<F>(dir: &str, input_decoder: Option<&str>, func: F)
where F: Fn(PathBuf) {
	let base: PathBuf = BASE_PATH.iter().collect();
	let decoders = &["tga", "tiff", "png", "gif", "bmp", "ico", "jpg"];
	for decoder in decoders {
		let mut path = base.clone();
		path.push(dir);
		path.push(decoder);
		path.push("*");
		path.push("*.".to_string() + match input_decoder {
			Some(val) => val,
			None => decoder
		});
		let pattern = &*format!("{}", path.display());
		for path in glob::glob(pattern).unwrap().filter_map(Result::ok) {
			func(path)
		}
	}
}

fn truncate_images(decoder: &str) {
    process_images(IMAGE_DIR, Some(decoder), |path| {
        println!("{:?}", path);
        let fin = fs::File::open(&path).unwrap();
        let max_length = 1000;
        let mut buf = Vec::with_capacity(max_length);
        fin.take(max_length as u64).read_to_end(&mut buf).unwrap();
        for i in 0..buf.len() {
            image::load_from_memory(&buf[..i+1]).ok();
        }
    })
}

#[test] #[ignore]
fn truncate_tga() {
    truncate_images("tga")
}

#[test] #[ignore]
fn truncate_tiff() {
    truncate_images("tiff")
}

#[test] #[ignore]
fn truncate_png() {
    truncate_images("png")
}

#[test] #[ignore]
fn truncate_gif() {
    truncate_images("gif")
}

#[test] #[ignore]
fn truncate_bmp() {
    truncate_images("bmp")
}

#[test] #[ignore]
fn truncate_ico() {
    truncate_images("ico")
}

#[test] #[ignore]
fn truncate_jpg() {
    truncate_images("jpg")
}
<commit_msg>Truncate test for hdr<commit_after>//! Ensure truncated images are read without panics.

use std::fs;
use std::path::PathBuf;
use std::io::Read;

extern crate image;
extern crate glob;

const BASE_PATH: [&'static str; 2] = [".", "tests"];
const IMAGE_DIR: &'static str = "images";

fn process_images<F>(dir: &str, input_decoder: Option<&str>, func: F)
where F: Fn(PathBuf) {
	let base: PathBuf = BASE_PATH.iter().collect();
	let decoders = &["tga", "tiff", "png", "gif", "bmp", "ico", "jpg", "hdr"];
	for decoder in decoders {
		let mut path = base.clone();
		path.push(dir);
		path.push(decoder);
		path.push("*");
		path.push("*.".to_string() + match input_decoder {
			Some(val) => val,
			None => decoder
		});
		let pattern = &*format!("{}", path.display());
		for path in glob::glob(pattern).unwrap().filter_map(Result::ok) {
			func(path)
		}
	}
}

fn truncate_images(decoder: &str) {
    process_images(IMAGE_DIR, Some(decoder), |path| {
        println!("{:?}", path);
        let fin = fs::File::open(&path).unwrap();
        let max_length = 1000;
        let mut buf = Vec::with_capacity(max_length);
        fin.take(max_length as u64).read_to_end(&mut buf).unwrap();
        for i in 0..buf.len() {
            image::load_from_memory(&buf[..i+1]).ok();
        }
    })
}

#[test] #[ignore]
fn truncate_tga() {
    truncate_images("tga")
}

#[test] #[ignore]
fn truncate_tiff() {
    truncate_images("tiff")
}

#[test] #[ignore]
fn truncate_png() {
    truncate_images("png")
}

#[test] #[ignore]
fn truncate_gif() {
    truncate_images("gif")
}

#[test] #[ignore]
fn truncate_bmp() {
    truncate_images("bmp")
}

#[test] #[ignore]
fn truncate_ico() {
    truncate_images("ico")
}

#[test] #[ignore]
fn truncate_jpg() {
    truncate_images("jpg")
}

#[test]
fn truncate_hdr() {
    truncate_images("hdr");
}
<|endoftext|>


<commit_before>use futures_core::{Async, Poll, task};
use futures_io::{AsyncRead, AsyncWrite};
use std::{fmt, io};
use std::string::String;
use std::vec::Vec;

/// A simple wrapper type which allows types which implement only
/// implement `std::io::Read` or `std::io::Write`
/// to be used in contexts which expect an `AsyncRead` or `AsyncWrite`.
///
/// If these types issue an error with the kind `io::ErrorKind::WouldBlock`,
/// it is expected that they will notify the current task on readiness.
/// Synchronous `std` types should not issue errors of this kind and
/// are safe to use in this context. However, using these types with
/// `AllowStdIo` will cause the event loop to block, so they should be used
/// with care.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct AllowStdIo<T>(T);

impl<T> AllowStdIo<T> {
    /// Creates a new `AllowStdIo` from an existing IO object.
    pub fn new(io: T) -> Self {
        AllowStdIo(io)
    }

    /// Returns a reference to the contained IO object.
    pub fn get_ref(&self) -> &T {
        &self.0
    }

    /// Returns a mutable reference to the contained IO object.
    pub fn get_mut(&mut self) -> &mut T {
        &mut self.0
    }

    /// Consumes self and returns the contained IO object.
    pub fn into_inner(self) -> T {
        self.0
    }
}

impl<T> io::Write for AllowStdIo<T> where T: io::Write {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        self.0.write_all(buf)
    }
    fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
        self.0.write_fmt(fmt)
    }
}

impl<T> AsyncWrite for AllowStdIo<T> where T: io::Write {
    fn poll_write(&mut self, _: &mut task::Context, buf: &[u8])
        -> Poll<usize, io::Error>
    {
        Ok(Async::Ready(io::Write::write(&mut self.0, buf)?))
    }

    fn poll_flush(&mut self, _: &mut task::Context) -> Poll<(), io::Error> {
        Ok(Async::Ready(io::Write::flush(self)?))
    }

    fn poll_close(&mut self, cx: &mut task::Context) -> Poll<(), io::Error> {
        self.poll_flush(cx)
    }
}

impl<T> io::Read for AllowStdIo<T> where T: io::Read {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
    // TODO: implement the `initializer` fn when it stabilizes.
    // See rust-lang/rust #42788
    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        self.0.read_to_end(buf)
    }
    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
        self.0.read_to_string(buf)
    }
    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
        self.0.read_exact(buf)
    }
}

impl<T> AsyncRead for AllowStdIo<T> where T: io::Read {
    fn poll_read(&mut self, _: &mut task::Context, buf: &mut [u8])
        -> Poll<usize, io::Error>
    {
        Ok(Async::Ready(io::Read::read(&mut self.0, buf)?))
    }
}
<commit_msg>Handle ErrorKind::Interrupted in generic std::io adaptor<commit_after>use futures_core::{Async, Poll, task};
use futures_io::{AsyncRead, AsyncWrite};
use std::{fmt, io};
use std::string::String;
use std::vec::Vec;

/// A simple wrapper type which allows types which implement only
/// implement `std::io::Read` or `std::io::Write`
/// to be used in contexts which expect an `AsyncRead` or `AsyncWrite`.
///
/// If these types issue an error with the kind `io::ErrorKind::WouldBlock`,
/// it is expected that they will notify the current task on readiness.
/// Synchronous `std` types should not issue errors of this kind and
/// are safe to use in this context. However, using these types with
/// `AllowStdIo` will cause the event loop to block, so they should be used
/// with care.
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct AllowStdIo<T>(T);

macro_rules! try_with_interrupt {
    ($e:expr) => {
        loop {
            match $e {
                Ok(e) => {
                    break e;
                }
                Err(ref e) if e.kind() == ::std::io::ErrorKind::Interrupted => {
                    continue;
                }
                Err(e) => {
                    return Err(e);
                }
            }
        }
    }
}

impl<T> AllowStdIo<T> {
    /// Creates a new `AllowStdIo` from an existing IO object.
    pub fn new(io: T) -> Self {
        AllowStdIo(io)
    }

    /// Returns a reference to the contained IO object.
    pub fn get_ref(&self) -> &T {
        &self.0
    }

    /// Returns a mutable reference to the contained IO object.
    pub fn get_mut(&mut self) -> &mut T {
        &mut self.0
    }

    /// Consumes self and returns the contained IO object.
    pub fn into_inner(self) -> T {
        self.0
    }
}

impl<T> io::Write for AllowStdIo<T> where T: io::Write {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.0.write(buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.0.flush()
    }
    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        self.0.write_all(buf)
    }
    fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
        self.0.write_fmt(fmt)
    }
}

impl<T> AsyncWrite for AllowStdIo<T> where T: io::Write {
    fn poll_write(&mut self, _: &mut task::Context, buf: &[u8])
        -> Poll<usize, io::Error>
    {
        Ok(Async::Ready(try_with_interrupt!(io::Write::write(&mut self.0, buf))))
    }

    fn poll_flush(&mut self, _: &mut task::Context) -> Poll<(), io::Error> {
        Ok(Async::Ready(try_with_interrupt!(io::Write::flush(self))))
    }

    fn poll_close(&mut self, cx: &mut task::Context) -> Poll<(), io::Error> {
        self.poll_flush(cx)
    }
}

impl<T> io::Read for AllowStdIo<T> where T: io::Read {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.0.read(buf)
    }
    // TODO: implement the `initializer` fn when it stabilizes.
    // See rust-lang/rust #42788
    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
        self.0.read_to_end(buf)
    }
    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
        self.0.read_to_string(buf)
    }
    fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> {
        self.0.read_exact(buf)
    }
}

impl<T> AsyncRead for AllowStdIo<T> where T: io::Read {
    fn poll_read(&mut self, _: &mut task::Context, buf: &mut [u8])
        -> Poll<usize, io::Error>
    {
        Ok(Async::Ready(try_with_interrupt!(io::Read::read(&mut self.0, buf))))
    }
}
<|endoftext|>


<commit_before>use path;

use std::borrow::Cow;
use std::path::PathBuf;

use syn;

pub struct TemplateInput<'a> {
    pub ast: &'a syn::DeriveInput,
    pub meta: TemplateMeta<'a>,
    pub path: PathBuf,
    pub source: Cow<'a, str>,
}

impl<'a> TemplateInput<'a> {
    pub fn new(ast: &'a syn::DeriveInput) -> TemplateInput<'a> {
        let meta = TemplateMeta::new(ast);
        let (path, source) = match meta.source {
            Source::Source(s) => {
                let path = match meta.ext {
                    Some(v) => PathBuf::from(format!("_.{}", v)),
                    None => PathBuf::new(),
                };
                (path, Cow::Borrowed(s))
            },
            Source::Path(s) => {
                let path = path::find_template_from_path(s, None);
                let src = path::get_template_source(&path);
                (path, Cow::Owned(src))
            },
        };
        TemplateInput { ast, meta, path, source }
    }
}

// Holds metadata for the template, based on the `template()` attribute.
pub struct TemplateMeta<'a> {
    source: Source<'a>,
    pub print: Print,
    pub escaping: EscapeMode,
    pub ext: Option<&'a str>,
}

impl<'a> TemplateMeta<'a> {
    fn new(ast: &'a syn::DeriveInput) -> TemplateMeta<'a> {
        let attr = ast.attrs.iter().find(|a| a.name() == "template");
        if attr.is_none() {
            let msg = format!("'template' attribute not found on struct '{}'",
                              ast.ident.as_ref());
            panic!(msg);
        }

        let attr = attr.unwrap();
        let mut source = None;
        let mut print = Print::None;
        let mut escaping = EscapeMode::Html;
        let mut ext = None;
        if let syn::MetaItem::List(_, ref inner) = attr.value {
            for nm_item in inner {
                if let syn::NestedMetaItem::MetaItem(ref item) = *nm_item {
                    if let syn::MetaItem::NameValue(ref key, ref val) = *item {
                        match key.as_ref() {
                            "path" => if let syn::Lit::Str(ref s, _) = *val {
                                if source.is_some() {
                                    panic!("must specify 'source' or 'path', not both");
                                }
                                source = Some(Source::Path(s.as_ref()));
                            } else {
                                panic!("template path must be string literal");
                            },
                            "source" => if let syn::Lit::Str(ref s, _) = *val {
                                if source.is_some() {
                                    panic!("must specify 'source' or 'path', not both");
                                }
                                source = Some(Source::Source(s.as_ref()));
                            } else {
                                panic!("template source must be string literal");
                            },
                            "print" => if let syn::Lit::Str(ref s, _) = *val {
                                print = (s.as_ref() as &str).into();
                            } else {
                                panic!("print value must be string literal");
                            },
                            "escape" => if let syn::Lit::Str(ref s, _) = *val {
                                escaping = (s.as_ref() as &str).into();
                            } else {
                                panic!("escape value must be string literal");
                            },
                            "ext" => if let syn::Lit::Str(ref s, _) = *val {
                                ext = Some((s.as_ref() as &str).into());
                            } else {
                                panic!("ext value must be string literal");
                            },
                            _ => { panic!("unsupported annotation key found") }
                        }
                    }
                }
            }
        }

        match source {
            Some(s) => {
                match (&s, ext.is_some()) {
                    (&Source::Path(_), true) => {
                        panic!("'ext' attribute cannot be used with 'path' attribute")
                    },
                    (&Source::Source(_), false) => {
                        panic!("must include 'ext' attribute when using 'source' attribute")
                    },
                    _ => {},
                }
                TemplateMeta { source: s, print, escaping, ext }
            },
            None => panic!("template path or source not found in struct attributes"),
        }
    }
}

enum Source<'a> {
    Path(&'a str),
    Source(&'a str),
}

#[derive(PartialEq)]
pub enum EscapeMode {
    Html,
    None,
}

impl<'a> From<&'a str> for EscapeMode {
    fn from(s: &'a str) -> EscapeMode {
        use self::EscapeMode::*;
        match s {
            "html" => Html,
            "none" => None,
            v => panic!("invalid value for escape option: {}", v),
        }
    }
}

#[derive(PartialEq)]
pub enum Print {
    All,
    Ast,
    Code,
    None,
}

impl<'a> From<&'a str> for Print {
    fn from(s: &'a str) -> Print {
        use self::Print::*;
        match s {
            "all" => All,
            "ast" => Ast,
            "code" => Code,
            "none" => None,
            v => panic!("invalid value for print option: {}", v),
        }
    }
}
<commit_msg>Refactor creation of TemplateMeta value<commit_after>use path;

use std::borrow::Cow;
use std::path::PathBuf;

use syn;

pub struct TemplateInput<'a> {
    pub ast: &'a syn::DeriveInput,
    pub meta: TemplateMeta<'a>,
    pub path: PathBuf,
    pub source: Cow<'a, str>,
}

impl<'a> TemplateInput<'a> {
    pub fn new(ast: &'a syn::DeriveInput) -> TemplateInput<'a> {
        let meta = TemplateMeta::new(ast);
        let (path, source) = match meta.source {
            Source::Source(s) => {
                let path = match meta.ext {
                    Some(v) => PathBuf::from(format!("_.{}", v)),
                    None => PathBuf::new(),
                };
                (path, Cow::Borrowed(s))
            },
            Source::Path(s) => {
                let path = path::find_template_from_path(s, None);
                let src = path::get_template_source(&path);
                (path, Cow::Owned(src))
            },
        };
        TemplateInput { ast, meta, path, source }
    }
}

// Holds metadata for the template, based on the `template()` attribute.
pub struct TemplateMeta<'a> {
    source: Source<'a>,
    pub print: Print,
    pub escaping: EscapeMode,
    pub ext: Option<&'a str>,
}

impl<'a> TemplateMeta<'a> {
    fn new(ast: &'a syn::DeriveInput) -> TemplateMeta<'a> {
        let attr = ast.attrs.iter().find(|a| a.name() == "template");
        if attr.is_none() {
            let msg = format!("'template' attribute not found on struct '{}'",
                              ast.ident.as_ref());
            panic!(msg);
        }

        let attr = attr.unwrap();
        let mut source = None;
        let mut print = Print::None;
        let mut escaping = EscapeMode::Html;
        let mut ext = None;
        if let syn::MetaItem::List(_, ref inner) = attr.value {
            for nm_item in inner {
                if let syn::NestedMetaItem::MetaItem(ref item) = *nm_item {
                    if let syn::MetaItem::NameValue(ref key, ref val) = *item {
                        match key.as_ref() {
                            "path" => if let syn::Lit::Str(ref s, _) = *val {
                                if source.is_some() {
                                    panic!("must specify 'source' or 'path', not both");
                                }
                                source = Some(Source::Path(s.as_ref()));
                            } else {
                                panic!("template path must be string literal");
                            },
                            "source" => if let syn::Lit::Str(ref s, _) = *val {
                                if source.is_some() {
                                    panic!("must specify 'source' or 'path', not both");
                                }
                                source = Some(Source::Source(s.as_ref()));
                            } else {
                                panic!("template source must be string literal");
                            },
                            "print" => if let syn::Lit::Str(ref s, _) = *val {
                                print = (s.as_ref() as &str).into();
                            } else {
                                panic!("print value must be string literal");
                            },
                            "escape" => if let syn::Lit::Str(ref s, _) = *val {
                                escaping = (s.as_ref() as &str).into();
                            } else {
                                panic!("escape value must be string literal");
                            },
                            "ext" => if let syn::Lit::Str(ref s, _) = *val {
                                ext = Some((s.as_ref() as &str).into());
                            } else {
                                panic!("ext value must be string literal");
                            },
                            _ => { panic!("unsupported annotation key found") }
                        }
                    }
                }
            }
        }

        let source = source.expect("template path or source not found in attributes");
        match (&source, ext.is_some()) {
            (&Source::Path(_), true) => {
                panic!("'ext' attribute cannot be used with 'path' attribute")
            },
            (&Source::Source(_), false) => {
                panic!("must include 'ext' attribute when using 'source' attribute")
            },
            _ => {},
        }
        TemplateMeta { source, print, escaping, ext }
    }
}

enum Source<'a> {
    Path(&'a str),
    Source(&'a str),
}

#[derive(PartialEq)]
pub enum EscapeMode {
    Html,
    None,
}

impl<'a> From<&'a str> for EscapeMode {
    fn from(s: &'a str) -> EscapeMode {
        use self::EscapeMode::*;
        match s {
            "html" => Html,
            "none" => None,
            v => panic!("invalid value for escape option: {}", v),
        }
    }
}

#[derive(PartialEq)]
pub enum Print {
    All,
    Ast,
    Code,
    None,
}

impl<'a> From<&'a str> for Print {
    fn from(s: &'a str) -> Print {
        use self::Print::*;
        match s {
            "all" => All,
            "ast" => Ast,
            "code" => Code,
            "none" => None,
            v => panic!("invalid value for print option: {}", v),
        }
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Different static asserts that ensure the build does what it's expected to.
//!
//! TODO: maybe cfg(test) this?

#![allow(unused_imports)]

use std::mem;

macro_rules! check_enum_value {
    ($a:expr, $b:expr) => {
        unsafe {
            mem::transmute::<[u32; $a as usize],
                             [u32; $b as usize]>([0; $a as usize]);
        }
    }
}

// NB: It's a shame we can't do this statically with bitflags, but no
// const-fn and no other way to access the numerical value :-(
macro_rules! check_enum_value_non_static {
    ($a:expr, $b:expr) => {
        assert_eq!($a as usize, $b as usize);
    }
}

#[test]
fn assert_restyle_hints_match() {
    use style::restyle_hints::*; // For flags
    use gecko_bindings::structs::nsRestyleHint;

    check_enum_value_non_static!(nsRestyleHint::eRestyle_Self, RESTYLE_SELF.bits());
    // XXX This for Servo actually means something like an hypothetical
    // Restyle_AllDescendants (but without running selector matching on the
    // element). ServoRestyleManager interprets it like that, but in practice we
    // should align the behavior with Gecko adding a new restyle hint, maybe?
    //
    // See https://bugzilla.mozilla.org/show_bug.cgi?id=1291786
    check_enum_value_non_static!(nsRestyleHint::eRestyle_SomeDescendants, RESTYLE_DESCENDANTS.bits());
    check_enum_value_non_static!(nsRestyleHint::eRestyle_LaterSiblings, RESTYLE_LATER_SIBLINGS.bits());
}

// Note that we can't call each_pseudo_element, parse_pseudo_element, or
// similar, because we'd need the foreign atom symbols to link.
#[test]
fn assert_basic_pseudo_elements() {
    let mut saw_before = false;
    let mut saw_after = false;

    macro_rules! pseudo_element {
        (":before", $atom:expr, false) => {
            saw_before = true;
        };
        (":after", $atom:expr, false) => {
            saw_after = true;
        };
        ($pseudo_str_with_colon:expr, $atom:expr, $is_anon_box:expr) => {
            // Do nothing
        };
    }

    include!("../../../components/style/generated/gecko_pseudo_element_helper.rs");

    assert!(saw_before);
    assert!(saw_after);
}
<commit_msg>Auto merge of #13564 - Manishearth:fx-stylo, r=jdm<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Different static asserts that ensure the build does what it's expected to.
//!
//! TODO: maybe cfg(test) this?

#![allow(unused_imports)]

use std::mem;

macro_rules! check_enum_value {
    ($a:expr, $b:expr) => {
        unsafe {
            mem::transmute::<[u32; $a as usize],
                             [u32; $b as usize]>([0; $a as usize]);
        }
    }
}

// NB: It's a shame we can't do this statically with bitflags, but no
// const-fn and no other way to access the numerical value :-(
macro_rules! check_enum_value_non_static {
    ($a:expr, $b:expr) => {
        assert_eq!($a as usize, $b as usize);
    }
}

#[test]
fn assert_restyle_hints_match() {
    use style::restyle_hints::*; // For flags
    use style::gecko_bindings::structs::nsRestyleHint;

    check_enum_value_non_static!(nsRestyleHint::eRestyle_Self, RESTYLE_SELF.bits());
    // XXX This for Servo actually means something like an hypothetical
    // Restyle_AllDescendants (but without running selector matching on the
    // element). ServoRestyleManager interprets it like that, but in practice we
    // should align the behavior with Gecko adding a new restyle hint, maybe?
    //
    // See https://bugzilla.mozilla.org/show_bug.cgi?id=1291786
    check_enum_value_non_static!(nsRestyleHint::eRestyle_SomeDescendants, RESTYLE_DESCENDANTS.bits());
    check_enum_value_non_static!(nsRestyleHint::eRestyle_LaterSiblings, RESTYLE_LATER_SIBLINGS.bits());
}

// Note that we can't call each_pseudo_element, parse_pseudo_element, or
// similar, because we'd need the foreign atom symbols to link.
#[test]
fn assert_basic_pseudo_elements() {
    let mut saw_before = false;
    let mut saw_after = false;

    macro_rules! pseudo_element {
        (":before", $atom:expr, false) => {
            saw_before = true;
        };
        (":after", $atom:expr, false) => {
            saw_after = true;
        };
        ($pseudo_str_with_colon:expr, $atom:expr, $is_anon_box:expr) => {
            // Do nothing
        };
    }

    include!("../../../components/style/gecko/generated/gecko_pseudo_element_helper.rs");

    assert!(saw_before);
    assert!(saw_after);
}
<|endoftext|>


<commit_before>use std::sync::atomic::{AtomicBool, Ordering};
use std::cmp::max;

use game::Position;
use types::{NumPlies, Score, ScoreUnit, Data};

// TODO put more parameters here
#[derive(Clone)]
pub struct Param {
    pub draw_val: ScoreUnit,
    pub depth: NumPlies,
}

pub fn negamax(pos: &mut Position,
               alpha: Option<Score>,
               beta: Option<Score>,
               param: Param,
               is_killed: &AtomicBool) -> (Score, Data) {
    if is_killed.load(Ordering::Relaxed) {
        return (Score::Value(ScoreUnit(0)), Data::one_node());
    }
    if param.depth == NumPlies(0) {
        return (pos.eval(param.draw_val), Data::one_node());
    }

    let (has_legal, score_opt, data): (bool, Option<Score>, Data) = {
        let temp = pos.clone();
        let move_iter = temp.legal_iter();

        let mut has_legal = false;
        let mut prev_score_opt: Option<Score> = alpha;
        let mut prev_data = Data::one_node();

        for curr_move in move_iter {

            let new_param = Param {
                draw_val: -param.draw_val,
                depth: NumPlies(param.depth.0 - 1)
            };
            let new_alpha = beta.map(|x| x.decrement());
            let new_beta = prev_score_opt.map(|x| x.decrement());
            let (temp_score, temp_data) = pos.with_move(&curr_move, move |new_pos| {
                negamax(new_pos,
                        new_alpha,
                        new_beta,
                        new_param,
                        is_killed)
            });
            let curr_score = temp_score.increment();
            let curr_data = temp_data.increment();

            let new_score = match prev_score_opt {
                None => curr_score,
                Some(prev_score) => max(prev_score, curr_score),
            };
            let new_data = prev_data.combine(curr_data);

            has_legal = true;
            prev_score_opt = Some(new_score);
            prev_data = new_data;

            if let Some(beta_val) = beta {
                if new_score >= beta_val {
                    prev_score_opt = beta;
                    break;
                }
            }
        }

        (has_legal, prev_score_opt, prev_data)
    };

    let score = if has_legal {
        score_opt.unwrap()
    } else {
        pos.eval(param.draw_val)
    };

    (score, data)
}
<commit_msg>Make negamax more generic<commit_after>use std::sync::atomic::{AtomicBool, Ordering};
use std::cmp::max;

use game::{Position, Move};
use types::{NumPlies, Score, ScoreUnit, Data};

// TODO put more parameters here
#[derive(Clone)]
pub struct Param {
    pub draw_val: ScoreUnit,
    pub depth: NumPlies,
}

pub fn negamax(pos: &mut Position,
               alpha: Option<Score>,
               beta: Option<Score>,
               param: Param,
               is_killed: &AtomicBool) -> (Score, Data) {
    negamax_generic(pos, alpha, beta, param, is_killed,
                    &mut |x| Box::new(x.legal_iter()),
                    &mut |x, draw_val| (x.eval(draw_val), Data::one_node()))
}

// TODO somehow eliminate the Box
fn negamax_generic<F, G>(pos: &mut Position,
                         alpha: Option<Score>,
                         beta: Option<Score>,
                         param: Param,
                         is_killed: &AtomicBool,
                         move_gen_fn: &mut F,
                         eval_fn: &mut G) -> (Score, Data) where
for<'a> F: FnMut(&'a Position) -> Box<Iterator<Item = Move> + 'a>,
for<'b> G: FnMut(&'b mut Position, ScoreUnit) -> (Score, Data) {
    if is_killed.load(Ordering::Relaxed) {
        return (Score::Value(ScoreUnit(0)), Data::one_node());
    }
    if param.depth == NumPlies(0) {
        return eval_fn(pos, param.draw_val);
    }

    let (has_legal, score_opt, data): (bool, Option<Score>, Data) = {
        let temp = pos.clone();
        let move_iter = move_gen_fn(&temp);

        let mut has_legal = false;
        let mut prev_score_opt: Option<Score> = alpha;
        let mut prev_data = Data::one_node();

        for curr_move in move_iter {

            let new_alpha = beta.map(|x| x.decrement());
            let new_beta = prev_score_opt.map(|x| x.decrement());
            let new_param = Param {
                draw_val: -param.draw_val,
                depth: NumPlies(param.depth.0 - 1)
            };
            let (temp_score, temp_data) = pos.with_move(&curr_move, |new_pos|
                negamax_generic(new_pos,
                                new_alpha,
                                new_beta,
                                new_param,
                                is_killed,
                                move_gen_fn,
                                eval_fn));
            let curr_score = temp_score.increment();
            let curr_data = temp_data.increment();

            let new_score = match prev_score_opt {
                None => curr_score,
                Some(prev_score) => max(prev_score, curr_score),
            };
            let new_data = prev_data.combine(curr_data);

            has_legal = true;
            prev_score_opt = Some(new_score);
            prev_data = new_data;

            if let Some(beta_val) = beta {
                if new_score >= beta_val {
                    prev_score_opt = beta;
                    break;
                }
            }
        }

        (has_legal, prev_score_opt, prev_data)
    };

    if has_legal {
        (score_opt.unwrap(), data)
    } else {
        eval_fn(pos, param.draw_val)
    }
}
<|endoftext|>


<commit_before>use crate::helper::{
    get_temp_state, secret_2_address, string_2_bytes, string_2_h256, string_2_u256,
};
use crate::json::state::Test;
use core_executor::engines::NullEngine;
use core_executor::libexecutor::economical_model::EconomicalModel;
use core_executor::libexecutor::sys_config::BlockSysConfig;
use core_executor::state::ApplyResult;
use core_executor::types::transaction::Transaction;
use evm::cita_types::U256;
use evm::env_info::EnvInfo;
use libproto::blockchain::Transaction as ProtoTransaction;
use std::fs;

pub fn test_json_file(p: &str) {
    let f = fs::File::open(p).unwrap();
    let tests = Test::load(f).unwrap();
    for (_name, test) in tests.into_iter() {
        let data_post_byzantium = test.post.unwrap().byzantium;
        if data_post_byzantium.is_none() {
            continue;
        }

        for (_i, postdata) in data_post_byzantium.unwrap().into_iter().enumerate() {
            // Init state
            let mut state = get_temp_state();
            for (address, account) in test.pre.clone().unwrap() {
                let balance = string_2_u256(account.balance);
                let code = string_2_bytes(account.code);
                let nonce = string_2_u256(account.nonce);
                if code.is_empty() {
                    state.new_contract(&address, balance, nonce);
                } else {
                    state.new_contract(&address, balance, nonce);
                    let _ = state.init_code(&address, code);
                }

                for (k, v) in account.storage {
                    let kk = string_2_h256(k);
                    let vv = string_2_h256(v);
                    let _ = state.set_storage(&address, kk, vv);
                }
            }
            state.commit().unwrap();

            // Set envionment
            let mut env_info = EnvInfo::default();
            env_info.difficulty = string_2_u256(test.env.current_difficulty.clone());
            env_info.number = string_2_u256(test.env.current_number.clone()).low_u64();
            env_info.timestamp = string_2_u256(test.env.current_timestamp.clone()).low_u64();
            env_info.gas_limit = string_2_u256(test.env.current_gas_limit.clone());
            env_info.author = test.env.current_coinbase;

            let engine = NullEngine::cita();
            let mut config = BlockSysConfig::default();
            config.quota_price = string_2_u256(test.transaction.gas_price.clone());
            config.economical_model = EconomicalModel::Charge;
            config.quota_price = U256::from(1);

            let idx_gas = &postdata.indexes[&String::from("gas")];
            let idx_value = &postdata.indexes[&String::from("value")];
            let idx_data = &postdata.indexes[&String::from("data")];
            let str_gas = test.transaction.gas_limit.clone()[*idx_gas].clone();
            let str_value = test.transaction.value.clone()[*idx_value].clone();
            let str_data = test.transaction.data.clone()[*idx_data].clone();

            let mut proto_tx = ProtoTransaction::new();
            proto_tx.set_data(string_2_bytes(str_data));
            proto_tx.set_value(string_2_bytes(str_value));
            proto_tx.set_nonce(test.transaction.nonce.clone());
            proto_tx.set_quota(string_2_u256(str_gas).low_u64());
            if !test.transaction.to.is_empty() {
                proto_tx.set_to(test.transaction.to.clone());
            }

            let tx = Transaction::create(&proto_tx).unwrap();
            let sender = secret_2_address(&test.transaction.secret_key);
            let signed_transaction = tx.fake_sign(sender);

            // Execute transactions
            let result: ApplyResult =
                state.apply(&env_info, &engine, &signed_transaction, true, &config);
            match result {
                Ok(outcome) => {
                    debug!("lalalal receipt error: {:?}", outcome.receipt.error);
                }
                _ => panic!("apply_transaction: There must be something wrong!"),
            }

            // check root hash
            state.commit().unwrap();
            let root = state.root();
            debug!("state.root {}", root);
            assert_eq!(*root, string_2_h256(postdata.hash));
        }
    }
}

pub fn test_json_path(p: &str) {
    let info = fs::metadata(p).unwrap();
    if info.is_dir() {
        for entry in fs::read_dir(p).unwrap() {
            let entry = entry.unwrap();
            let p = entry.path();
            test_json_path(p.to_str().unwrap());
        }
    } else {
        test_json_file(p);
    }
}

pub fn skip_json_path(_reason: &str, _name: &str) {}

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

    #[test]
    fn test_json_state() {
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stRefundTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stCodeCopyTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stMemExpandingEIP150Calls",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stCallDelegateCodesCallCodeHomestead",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stRevertTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stArgsZeroOneBalance",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stMemoryStressTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stTransactionTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stReturnDataTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stPreCompiledContracts",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stCodeSizeLimit",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stHomesteadSpecific",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stEIP158Specific",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stZeroKnowledge2",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stCreateTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stSStoreTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stTransitionTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stZeroCallsTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stBadOpcode",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stLogTests",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stNonZeroCallsTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stCallDelegateCodesHomestead",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stBugs",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stShift",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stWalletTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stRandom2",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stEWASMTests",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stStaticCall",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stAttackTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stStackTests",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stPreCompiledContracts2",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stInitCodeTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stZeroKnowledge",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stEIP150singleCodeGasPrices",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stChangedEIP150",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stExample",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stSolidityTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stEIP150Specific",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stQuadraticComplexityTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stSystemOperationsTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stZeroCallsRevert",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stRecursiveCreate",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stRandom",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stDelegatecallTestHomestead",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stMemoryTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stCreate2",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stSpecialTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stCallCodes",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stCallCreateCallCodeTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stExtCodeHash",
        );
    }
}
<commit_msg>change byzantium to homestead[skip travis]<commit_after>use crate::helper::{
    get_temp_state, secret_2_address, string_2_bytes, string_2_h256, string_2_u256,
};
use crate::json::state::Test;
use core_executor::engines::NullEngine;
use core_executor::libexecutor::economical_model::EconomicalModel;
use core_executor::libexecutor::sys_config::BlockSysConfig;
use core_executor::state::ApplyResult;
use core_executor::types::transaction::Transaction;
use evm::cita_types::U256;
use evm::env_info::EnvInfo;
use libproto::blockchain::Transaction as ProtoTransaction;
use std::fs;

pub fn test_json_file(p: &str) {
    let f = fs::File::open(p).unwrap();
    let tests = Test::load(f).unwrap();
    for (_name, test) in tests.into_iter() {
        let data_post_homestead = test.post.unwrap().homestead;
        if data_post_homestead.is_none() {
            continue;
        }

        for (_i, postdata) in data_post_homestead.unwrap().into_iter().enumerate() {
            // Init state
            let mut state = get_temp_state();
            for (address, account) in test.pre.clone().unwrap() {
                let balance = string_2_u256(account.balance);
                let code = string_2_bytes(account.code);
                let nonce = string_2_u256(account.nonce);
                if code.is_empty() {
                    state.new_contract(&address, balance, nonce);
                } else {
                    state.new_contract(&address, balance, nonce);
                    let _ = state.init_code(&address, code);
                }

                for (k, v) in account.storage {
                    let kk = string_2_h256(k);
                    let vv = string_2_h256(v);
                    let _ = state.set_storage(&address, kk, vv);
                }
            }
            state.commit().unwrap();

            // Set envionment
            let mut env_info = EnvInfo::default();
            env_info.difficulty = string_2_u256(test.env.current_difficulty.clone());
            env_info.number = string_2_u256(test.env.current_number.clone()).low_u64();
            env_info.timestamp = string_2_u256(test.env.current_timestamp.clone()).low_u64();
            env_info.gas_limit = string_2_u256(test.env.current_gas_limit.clone());
            env_info.author = test.env.current_coinbase;

            let engine = NullEngine::cita();
            let mut config = BlockSysConfig::default();
            config.quota_price = string_2_u256(test.transaction.gas_price.clone());
            config.economical_model = EconomicalModel::Charge;
            config.quota_price = U256::from(1);

            let idx_gas = &postdata.indexes[&String::from("gas")];
            let idx_value = &postdata.indexes[&String::from("value")];
            let idx_data = &postdata.indexes[&String::from("data")];
            let str_gas = test.transaction.gas_limit.clone()[*idx_gas].clone();
            let str_value = test.transaction.value.clone()[*idx_value].clone();
            let str_data = test.transaction.data.clone()[*idx_data].clone();

            let mut proto_tx = ProtoTransaction::new();
            proto_tx.set_data(string_2_bytes(str_data));
            proto_tx.set_value(string_2_bytes(str_value));
            proto_tx.set_nonce(test.transaction.nonce.clone());
            proto_tx.set_quota(string_2_u256(str_gas).low_u64());
            if !test.transaction.to.is_empty() {
                proto_tx.set_to(test.transaction.to.clone());
            }

            let tx = Transaction::create(&proto_tx).unwrap();
            let sender = secret_2_address(&test.transaction.secret_key);
            let signed_transaction = tx.fake_sign(sender);

            // Execute transactions
            let result: ApplyResult =
                state.apply(&env_info, &engine, &signed_transaction, true, &config);
            match result {
                Ok(outcome) => {
                    debug!("lalalal receipt error: {:?}", outcome.receipt.error);
                }
                _ => panic!("apply_transaction: There must be something wrong!"),
            }

            // check root hash
            state.commit().unwrap();
            let root = state.root();
            debug!("state.root {}", root);
            assert_eq!(*root, string_2_h256(postdata.hash));
        }
    }
}

pub fn test_json_path(p: &str) {
    let info = fs::metadata(p).unwrap();
    if info.is_dir() {
        for entry in fs::read_dir(p).unwrap() {
            let entry = entry.unwrap();
            let p = entry.path();
            test_json_path(p.to_str().unwrap());
        }
    } else {
        test_json_file(p);
    }
}

pub fn skip_json_path(_reason: &str, _name: &str) {}

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

    #[test]
    fn test_json_state() {
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stRefundTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stCodeCopyTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stMemExpandingEIP150Calls",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stCallDelegateCodesCallCodeHomestead",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stRevertTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stArgsZeroOneBalance",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stMemoryStressTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stTransactionTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stReturnDataTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stPreCompiledContracts",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stCodeSizeLimit",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stHomesteadSpecific",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stEIP158Specific",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stZeroKnowledge2",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stCreateTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stSStoreTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stTransitionTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stZeroCallsTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stBadOpcode",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stLogTests",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stNonZeroCallsTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stCallDelegateCodesHomestead",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stBugs",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stShift",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stWalletTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stRandom2",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stEWASMTests",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stStaticCall",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stAttackTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stStackTests",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stPreCompiledContracts2",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stInitCodeTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stZeroKnowledge",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stEIP150singleCodeGasPrices",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stChangedEIP150",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stExample",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stSolidityTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stEIP150Specific",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stQuadraticComplexityTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stSystemOperationsTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stZeroCallsRevert",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stRecursiveCreate",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stRandom",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stDelegatecallTestHomestead",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stMemoryTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stCreate2",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stSpecialTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stCallCodes",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stCallCreateCallCodeTest",
        );
        skip_json_path(
            "run tests integration",
            r"../jsondata/GeneralStateTests/stExtCodeHash",
        );
    }
}
<|endoftext|>


<commit_before>//! Loads "sysroot" crate.
//!
//! One confusing point here is that normally sysroot is a bunch of `.rlib`s,
//! but we can't process `.rlib` and need source code instead. The source code
//! is typically installed with `rustup component add rust-src` command.

use std::{convert::TryFrom, env, ops, path::PathBuf, process::Command};

use anyhow::{format_err, Result};
use la_arena::{Arena, Idx};
use paths::{AbsPath, AbsPathBuf};

use crate::utf8_stdout;

#[derive(Default, Debug, Clone, Eq, PartialEq)]
pub struct Sysroot {
    crates: Arena<SysrootCrateData>,
}

pub(crate) type SysrootCrate = Idx<SysrootCrateData>;

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct SysrootCrateData {
    pub name: String,
    pub root: AbsPathBuf,
    pub deps: Vec<SysrootCrate>,
}

impl ops::Index<SysrootCrate> for Sysroot {
    type Output = SysrootCrateData;
    fn index(&self, index: SysrootCrate) -> &SysrootCrateData {
        &self.crates[index]
    }
}

impl Sysroot {
    pub fn public_deps(&self) -> impl Iterator<Item = (&'static str, SysrootCrate)> + '_ {
        // core is added as a dependency before std in order to
        // mimic rustcs dependency order
        ["core", "alloc", "std"].iter().filter_map(move |&it| Some((it, self.by_name(it)?)))
    }

    pub fn proc_macro(&self) -> Option<SysrootCrate> {
        self.by_name("proc_macro")
    }

    pub fn crates<'a>(&'a self) -> impl Iterator<Item = SysrootCrate> + ExactSizeIterator + 'a {
        self.crates.iter().map(|(id, _data)| id)
    }

    pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> {
        log::debug!("Discovering sysroot for {}", cargo_toml.display());
        let current_dir = cargo_toml.parent().ok_or_else(|| {
            format_err!("Failed to find the parent directory for {}", cargo_toml.display())
        })?;
        let sysroot_dir = discover_sysroot_dir(current_dir)?;
        let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, current_dir)?;
        let res = Sysroot::load(&sysroot_src_dir)?;
        Ok(res)
    }

    pub fn discover_rustc(cargo_toml: &AbsPath) -> Option<AbsPathBuf> {
        log::debug!("Discovering rustc source for {}", cargo_toml.display());
        let current_dir = cargo_toml.parent().unwrap();
        discover_sysroot_dir(current_dir).ok().and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
    }

    pub fn load(sysroot_src_dir: &AbsPath) -> Result<Sysroot> {
        let mut sysroot = Sysroot { crates: Arena::default() };

        for name in SYSROOT_CRATES.trim().lines() {
            let root = [format!("{}/src/lib.rs", name), format!("lib{}/lib.rs", name)]
                .iter()
                .map(|it| sysroot_src_dir.join(it))
                .find(|it| it.exists());

            if let Some(root) = root {
                sysroot.crates.alloc(SysrootCrateData {
                    name: name.into(),
                    root,
                    deps: Vec::new(),
                });
            }
        }

        if let Some(std) = sysroot.by_name("std") {
            for dep in STD_DEPS.trim().lines() {
                if let Some(dep) = sysroot.by_name(dep) {
                    sysroot.crates[std].deps.push(dep)
                }
            }
        }

        if let Some(alloc) = sysroot.by_name("alloc") {
            if let Some(core) = sysroot.by_name("core") {
                sysroot.crates[alloc].deps.push(core);
            }
        }

        if sysroot.by_name("core").is_none() {
            let var_note = if env::var_os("RUST_SRC_PATH").is_some() {
                " (`RUST_SRC_PATH` might be incorrect, try unsetting it)"
            } else {
                ""
            };
            anyhow::bail!(
                "could not find libcore in sysroot path `{}`{}",
                sysroot_src_dir.as_ref().display(),
                var_note,
            );
        }

        Ok(sysroot)
    }

    fn by_name(&self, name: &str) -> Option<SysrootCrate> {
        let (id, _data) = self.crates.iter().find(|(_id, data)| data.name == name)?;
        Some(id)
    }
}

fn discover_sysroot_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
    let mut rustc = Command::new(toolchain::rustc());
    rustc.current_dir(current_dir).args(&["--print", "sysroot"]);
    log::debug!("Discovering sysroot by {:?}", rustc);
    let stdout = utf8_stdout(rustc)?;
    Ok(AbsPathBuf::assert(PathBuf::from(stdout)))
}

fn discover_sysroot_src_dir(
    sysroot_path: &AbsPathBuf,
    current_dir: &AbsPath,
) -> Result<AbsPathBuf> {
    if let Ok(path) = env::var("RUST_SRC_PATH") {
        let path = AbsPathBuf::try_from(path.as_str())
            .map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?;
        let core = path.join("core");
        if core.exists() {
            log::debug!("Discovered sysroot by RUST_SRC_PATH: {}", path.display());
            return Ok(path);
        }
        log::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core);
    }

    get_rust_src(sysroot_path)
        .or_else(|| {
            let mut rustup = Command::new(toolchain::rustup());
            rustup.current_dir(current_dir).args(&["component", "add", "rust-src"]);
            utf8_stdout(rustup).ok()?;
            get_rust_src(sysroot_path)
        })
        .ok_or_else(|| {
            format_err!(
                "\
can't load standard library from sysroot
{}
(discovered via `rustc --print sysroot`)
try installing the Rust source the same way you installed rustc",
                sysroot_path.display(),
            )
        })
}

fn get_rustc_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
    let rustc_src = sysroot_path.join("lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml");
    log::debug!("Checking for rustc source code: {}", rustc_src.display());
    if rustc_src.exists() {
        Some(rustc_src)
    } else {
        None
    }
}

fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
    // Try the new path first since the old one still exists.
    let rust_src = sysroot_path.join("lib/rustlib/src/rust");
    log::debug!("Checking sysroot (looking for `library` and `src` dirs): {}", rust_src.display());
    ["library", "src"].iter().map(|it| rust_src.join(it)).find(|it| it.exists())
}

impl SysrootCrateData {
    pub fn root_dir(&self) -> &AbsPath {
        self.root.parent().unwrap()
    }
}

const SYSROOT_CRATES: &str = "
alloc
core
panic_abort
panic_unwind
proc_macro
profiler_builtins
rtstartup
std
stdarch
term
test
unwind";

const STD_DEPS: &str = "
alloc
core
panic_abort
panic_unwind
profiler_builtins
rtstartup
proc_macro
stdarch
term
test
unwind";
<commit_msg>Update sysroot crates<commit_after>//! Loads "sysroot" crate.
//!
//! One confusing point here is that normally sysroot is a bunch of `.rlib`s,
//! but we can't process `.rlib` and need source code instead. The source code
//! is typically installed with `rustup component add rust-src` command.

use std::{convert::TryFrom, env, ops, path::PathBuf, process::Command};

use anyhow::{format_err, Result};
use la_arena::{Arena, Idx};
use paths::{AbsPath, AbsPathBuf};

use crate::utf8_stdout;

#[derive(Default, Debug, Clone, Eq, PartialEq)]
pub struct Sysroot {
    crates: Arena<SysrootCrateData>,
}

pub(crate) type SysrootCrate = Idx<SysrootCrateData>;

#[derive(Debug, Clone, Eq, PartialEq)]
pub struct SysrootCrateData {
    pub name: String,
    pub root: AbsPathBuf,
    pub deps: Vec<SysrootCrate>,
}

impl ops::Index<SysrootCrate> for Sysroot {
    type Output = SysrootCrateData;
    fn index(&self, index: SysrootCrate) -> &SysrootCrateData {
        &self.crates[index]
    }
}

impl Sysroot {
    pub fn public_deps(&self) -> impl Iterator<Item = (&'static str, SysrootCrate)> + '_ {
        // core is added as a dependency before std in order to
        // mimic rustcs dependency order
        ["core", "alloc", "std"].iter().filter_map(move |&it| Some((it, self.by_name(it)?)))
    }

    pub fn proc_macro(&self) -> Option<SysrootCrate> {
        self.by_name("proc_macro")
    }

    pub fn crates<'a>(&'a self) -> impl Iterator<Item = SysrootCrate> + ExactSizeIterator + 'a {
        self.crates.iter().map(|(id, _data)| id)
    }

    pub fn discover(cargo_toml: &AbsPath) -> Result<Sysroot> {
        log::debug!("Discovering sysroot for {}", cargo_toml.display());
        let current_dir = cargo_toml.parent().ok_or_else(|| {
            format_err!("Failed to find the parent directory for {}", cargo_toml.display())
        })?;
        let sysroot_dir = discover_sysroot_dir(current_dir)?;
        let sysroot_src_dir = discover_sysroot_src_dir(&sysroot_dir, current_dir)?;
        let res = Sysroot::load(&sysroot_src_dir)?;
        Ok(res)
    }

    pub fn discover_rustc(cargo_toml: &AbsPath) -> Option<AbsPathBuf> {
        log::debug!("Discovering rustc source for {}", cargo_toml.display());
        let current_dir = cargo_toml.parent().unwrap();
        discover_sysroot_dir(current_dir).ok().and_then(|sysroot_dir| get_rustc_src(&sysroot_dir))
    }

    pub fn load(sysroot_src_dir: &AbsPath) -> Result<Sysroot> {
        let mut sysroot = Sysroot { crates: Arena::default() };

        for path in SYSROOT_CRATES.trim().lines() {
            let name = path.split('/').last().unwrap();
            let root = [format!("{}/src/lib.rs", path), format!("lib{}/lib.rs", path)]
                .iter()
                .map(|it| sysroot_src_dir.join(it))
                .find(|it| it.exists());

            if let Some(root) = root {
                sysroot.crates.alloc(SysrootCrateData {
                    name: name.into(),
                    root,
                    deps: Vec::new(),
                });
            }
        }

        if let Some(std) = sysroot.by_name("std") {
            for dep in STD_DEPS.trim().lines() {
                if let Some(dep) = sysroot.by_name(dep) {
                    sysroot.crates[std].deps.push(dep)
                }
            }
        }

        if let Some(alloc) = sysroot.by_name("alloc") {
            if let Some(core) = sysroot.by_name("core") {
                sysroot.crates[alloc].deps.push(core);
            }
        }

        if sysroot.by_name("core").is_none() {
            let var_note = if env::var_os("RUST_SRC_PATH").is_some() {
                " (`RUST_SRC_PATH` might be incorrect, try unsetting it)"
            } else {
                ""
            };
            anyhow::bail!(
                "could not find libcore in sysroot path `{}`{}",
                sysroot_src_dir.as_ref().display(),
                var_note,
            );
        }

        Ok(sysroot)
    }

    fn by_name(&self, name: &str) -> Option<SysrootCrate> {
        let (id, _data) = self.crates.iter().find(|(_id, data)| data.name == name)?;
        Some(id)
    }
}

fn discover_sysroot_dir(current_dir: &AbsPath) -> Result<AbsPathBuf> {
    let mut rustc = Command::new(toolchain::rustc());
    rustc.current_dir(current_dir).args(&["--print", "sysroot"]);
    log::debug!("Discovering sysroot by {:?}", rustc);
    let stdout = utf8_stdout(rustc)?;
    Ok(AbsPathBuf::assert(PathBuf::from(stdout)))
}

fn discover_sysroot_src_dir(
    sysroot_path: &AbsPathBuf,
    current_dir: &AbsPath,
) -> Result<AbsPathBuf> {
    if let Ok(path) = env::var("RUST_SRC_PATH") {
        let path = AbsPathBuf::try_from(path.as_str())
            .map_err(|path| format_err!("RUST_SRC_PATH must be absolute: {}", path.display()))?;
        let core = path.join("core");
        if core.exists() {
            log::debug!("Discovered sysroot by RUST_SRC_PATH: {}", path.display());
            return Ok(path);
        }
        log::debug!("RUST_SRC_PATH is set, but is invalid (no core: {:?}), ignoring", core);
    }

    get_rust_src(sysroot_path)
        .or_else(|| {
            let mut rustup = Command::new(toolchain::rustup());
            rustup.current_dir(current_dir).args(&["component", "add", "rust-src"]);
            utf8_stdout(rustup).ok()?;
            get_rust_src(sysroot_path)
        })
        .ok_or_else(|| {
            format_err!(
                "\
can't load standard library from sysroot
{}
(discovered via `rustc --print sysroot`)
try installing the Rust source the same way you installed rustc",
                sysroot_path.display(),
            )
        })
}

fn get_rustc_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
    let rustc_src = sysroot_path.join("lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml");
    log::debug!("Checking for rustc source code: {}", rustc_src.display());
    if rustc_src.exists() {
        Some(rustc_src)
    } else {
        None
    }
}

fn get_rust_src(sysroot_path: &AbsPath) -> Option<AbsPathBuf> {
    // Try the new path first since the old one still exists.
    let rust_src = sysroot_path.join("lib/rustlib/src/rust");
    log::debug!("Checking sysroot (looking for `library` and `src` dirs): {}", rust_src.display());
    ["library", "src"].iter().map(|it| rust_src.join(it)).find(|it| it.exists())
}

impl SysrootCrateData {
    pub fn root_dir(&self) -> &AbsPath {
        self.root.parent().unwrap()
    }
}

const SYSROOT_CRATES: &str = "
alloc
core
panic_abort
panic_unwind
proc_macro
profiler_builtins
std
stdarch/crates/std_detect
term
test
unwind";

const STD_DEPS: &str = "
alloc
core
panic_abort
panic_unwind
profiler_builtins
proc_macro
std_detect
term
test
unwind";
<|endoftext|>


<commit_before>//! This module defines Concrete Syntax Tree (CST), used by rust-analyzer.
//!
//! The CST includes comments and whitespace, provides a single node type,
//! `SyntaxNode`, and a basic traversal API (parent, children, siblings).
//!
//! The *real* implementation is in the (language-agnostic) `rowan` crate, this
//! modules just wraps its API.

use std::{fmt::{self, Write}, borrow::Borrow};

use rowan::{Types, TransparentNewType};

use crate::{
    SmolStr, SyntaxKind, TextRange, SyntaxText, SourceFile, AstNode,
    syntax_error::SyntaxError,
};

pub use rowan::WalkEvent;

#[derive(Debug, Clone, Copy)]
pub enum RaTypes {}
impl Types for RaTypes {
    type Kind = SyntaxKind;
    type RootData = Vec<SyntaxError>;
}

pub type GreenNode = rowan::GreenNode<RaTypes>;

#[derive(PartialEq, Eq, Hash)]
pub struct TreeArc<T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>>(
    pub(crate) rowan::TreeArc<RaTypes, T>,
);

impl<T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>> Borrow<T> for TreeArc<T> {
    fn borrow(&self) -> &T {
        &*self
    }
}

impl<T> TreeArc<T>
where
    T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>,
{
    pub(crate) fn cast<U>(this: TreeArc<T>) -> TreeArc<U>
    where
        U: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>,
    {
        TreeArc(rowan::TreeArc::cast(this.0))
    }
}

impl<T> std::ops::Deref for TreeArc<T>
where
    T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>,
{
    type Target = T;
    fn deref(&self) -> &T {
        self.0.deref()
    }
}

impl<T> PartialEq<T> for TreeArc<T>
where
    T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>,
    T: PartialEq<T>,
{
    fn eq(&self, other: &T) -> bool {
        let t: &T = self;
        t == other
    }
}

impl<T> Clone for TreeArc<T>
where
    T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>,
{
    fn clone(&self) -> TreeArc<T> {
        TreeArc(self.0.clone())
    }
}

impl<T> fmt::Debug for TreeArc<T>
where
    T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>,
    T: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

#[derive(PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct SyntaxNode(pub(crate) rowan::SyntaxNode<RaTypes>);
unsafe impl TransparentNewType for SyntaxNode {
    type Repr = rowan::SyntaxNode<RaTypes>;
}

impl SyntaxNode {
    pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> TreeArc<SyntaxNode> {
        let ptr = TreeArc(rowan::SyntaxNode::new(green, errors));
        TreeArc::cast(ptr)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Direction {
    Next,
    Prev,
}

impl SyntaxNode {
    pub fn leaf_text(&self) -> Option<&SmolStr> {
        self.0.leaf_text()
    }
    pub fn ancestors(&self) -> impl Iterator<Item = &SyntaxNode> {
        crate::algo::generate(Some(self), |&node| node.parent())
    }
    pub fn descendants(&self) -> impl Iterator<Item = &SyntaxNode> {
        self.preorder().filter_map(|event| match event {
            WalkEvent::Enter(node) => Some(node),
            WalkEvent::Leave(_) => None,
        })
    }
    pub fn siblings(&self, direction: Direction) -> impl Iterator<Item = &SyntaxNode> {
        crate::algo::generate(Some(self), move |&node| match direction {
            Direction::Next => node.next_sibling(),
            Direction::Prev => node.prev_sibling(),
        })
    }
    pub fn preorder(&self) -> impl Iterator<Item = WalkEvent<&SyntaxNode>> {
        self.0.preorder().map(|event| match event {
            WalkEvent::Enter(n) => WalkEvent::Enter(SyntaxNode::from_repr(n)),
            WalkEvent::Leave(n) => WalkEvent::Leave(SyntaxNode::from_repr(n)),
        })
    }

    pub fn debug_dump(&self) -> String {
        let mut errors: Vec<_> = match self.ancestors().find_map(SourceFile::cast) {
            Some(file) => file.errors(),
            None => self.root_data().to_vec(),
        };
        errors.sort_by_key(|e| e.offset());
        let mut err_pos = 0;
        let mut level = 0;
        let mut buf = String::new();
        macro_rules! indent {
            () => {
                for _ in 0..level {
                    buf.push_str("  ");
                }
            };
        }

        for event in self.preorder() {
            match event {
                WalkEvent::Enter(node) => {
                    indent!();
                    writeln!(buf, "{:?}", node).unwrap();
                    if node.first_child().is_none() {
                        let off = node.range().end();
                        while err_pos < errors.len() && errors[err_pos].offset() <= off {
                            indent!();
                            writeln!(buf, "err: `{}`", errors[err_pos]).unwrap();
                            err_pos += 1;
                        }
                    }
                    level += 1;
                }
                WalkEvent::Leave(_) => level -= 1,
            }
        }

        assert_eq!(level, 0);
        for err in errors[err_pos..].iter() {
            writeln!(buf, "err: `{}`", err).unwrap();
        }

        buf
    }
}

impl ToOwned for SyntaxNode {
    type Owned = TreeArc<SyntaxNode>;
    fn to_owned(&self) -> TreeArc<SyntaxNode> {
        let ptr = TreeArc(self.0.to_owned());
        TreeArc::cast(ptr)
    }
}

impl SyntaxNode {
    pub(crate) fn root_data(&self) -> &Vec<SyntaxError> {
        self.0.root_data()
    }

    pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode {
        self.0.replace_self(replacement)
    }

    pub fn kind(&self) -> SyntaxKind {
        self.0.kind()
    }

    pub fn range(&self) -> TextRange {
        self.0.range()
    }

    pub fn text(&self) -> SyntaxText {
        SyntaxText::new(self)
    }

    pub fn is_leaf(&self) -> bool {
        self.0.is_leaf()
    }

    pub fn parent(&self) -> Option<&SyntaxNode> {
        self.0.parent().map(SyntaxNode::from_repr)
    }

    pub fn first_child(&self) -> Option<&SyntaxNode> {
        self.0.first_child().map(SyntaxNode::from_repr)
    }

    pub fn last_child(&self) -> Option<&SyntaxNode> {
        self.0.last_child().map(SyntaxNode::from_repr)
    }

    pub fn next_sibling(&self) -> Option<&SyntaxNode> {
        self.0.next_sibling().map(SyntaxNode::from_repr)
    }

    pub fn prev_sibling(&self) -> Option<&SyntaxNode> {
        self.0.prev_sibling().map(SyntaxNode::from_repr)
    }

    pub fn children(&self) -> SyntaxNodeChildren {
        SyntaxNodeChildren(self.0.children())
    }

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

impl fmt::Debug for SyntaxNode {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{:?}@{:?}", self.kind(), self.range())?;
        if has_short_text(self.kind()) {
            write!(fmt, " \"{}\"", self.text())?;
        }
        Ok(())
    }
}

#[derive(Debug)]
pub struct SyntaxNodeChildren<'a>(rowan::SyntaxNodeChildren<'a, RaTypes>);

impl<'a> Iterator for SyntaxNodeChildren<'a> {
    type Item = &'a SyntaxNode;

    fn next(&mut self) -> Option<&'a SyntaxNode> {
        self.0.next().map(SyntaxNode::from_repr)
    }
}

fn has_short_text(kind: SyntaxKind) -> bool {
    use crate::SyntaxKind::*;
    match kind {
        IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true,
        _ => false,
    }
}
<commit_msg>rearrange methods<commit_after>//! This module defines Concrete Syntax Tree (CST), used by rust-analyzer.
//!
//! The CST includes comments and whitespace, provides a single node type,
//! `SyntaxNode`, and a basic traversal API (parent, children, siblings).
//!
//! The *real* implementation is in the (language-agnostic) `rowan` crate, this
//! modules just wraps its API.

use std::{fmt::{self, Write}, borrow::Borrow};

use rowan::{Types, TransparentNewType};

use crate::{
    SmolStr, SyntaxKind, TextRange, SyntaxText, SourceFile, AstNode,
    syntax_error::SyntaxError,
};

pub use rowan::WalkEvent;

#[derive(Debug, Clone, Copy)]
pub enum RaTypes {}
impl Types for RaTypes {
    type Kind = SyntaxKind;
    type RootData = Vec<SyntaxError>;
}

pub type GreenNode = rowan::GreenNode<RaTypes>;

#[derive(PartialEq, Eq, Hash)]
pub struct TreeArc<T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>>(
    pub(crate) rowan::TreeArc<RaTypes, T>,
);

impl<T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>> Borrow<T> for TreeArc<T> {
    fn borrow(&self) -> &T {
        &*self
    }
}

impl<T> TreeArc<T>
where
    T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>,
{
    pub(crate) fn cast<U>(this: TreeArc<T>) -> TreeArc<U>
    where
        U: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>,
    {
        TreeArc(rowan::TreeArc::cast(this.0))
    }
}

impl<T> std::ops::Deref for TreeArc<T>
where
    T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>,
{
    type Target = T;
    fn deref(&self) -> &T {
        self.0.deref()
    }
}

impl<T> PartialEq<T> for TreeArc<T>
where
    T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>,
    T: PartialEq<T>,
{
    fn eq(&self, other: &T) -> bool {
        let t: &T = self;
        t == other
    }
}

impl<T> Clone for TreeArc<T>
where
    T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>,
{
    fn clone(&self) -> TreeArc<T> {
        TreeArc(self.0.clone())
    }
}

impl<T> fmt::Debug for TreeArc<T>
where
    T: TransparentNewType<Repr = rowan::SyntaxNode<RaTypes>>,
    T: fmt::Debug,
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.0, fmt)
    }
}

#[derive(PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct SyntaxNode(pub(crate) rowan::SyntaxNode<RaTypes>);
unsafe impl TransparentNewType for SyntaxNode {
    type Repr = rowan::SyntaxNode<RaTypes>;
}

impl ToOwned for SyntaxNode {
    type Owned = TreeArc<SyntaxNode>;
    fn to_owned(&self) -> TreeArc<SyntaxNode> {
        let ptr = TreeArc(self.0.to_owned());
        TreeArc::cast(ptr)
    }
}

impl fmt::Debug for SyntaxNode {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{:?}@{:?}", self.kind(), self.range())?;
        if has_short_text(self.kind()) {
            write!(fmt, " \"{}\"", self.text())?;
        }
        Ok(())
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Direction {
    Next,
    Prev,
}

impl SyntaxNode {
    pub(crate) fn new(green: GreenNode, errors: Vec<SyntaxError>) -> TreeArc<SyntaxNode> {
        let ptr = TreeArc(rowan::SyntaxNode::new(green, errors));
        TreeArc::cast(ptr)
    }

    pub fn kind(&self) -> SyntaxKind {
        self.0.kind()
    }

    pub fn range(&self) -> TextRange {
        self.0.range()
    }

    pub fn text(&self) -> SyntaxText {
        SyntaxText::new(self)
    }

    pub fn is_leaf(&self) -> bool {
        self.0.is_leaf()
    }

    pub fn leaf_text(&self) -> Option<&SmolStr> {
        self.0.leaf_text()
    }

    pub fn parent(&self) -> Option<&SyntaxNode> {
        self.0.parent().map(SyntaxNode::from_repr)
    }

    pub fn first_child(&self) -> Option<&SyntaxNode> {
        self.0.first_child().map(SyntaxNode::from_repr)
    }

    pub fn last_child(&self) -> Option<&SyntaxNode> {
        self.0.last_child().map(SyntaxNode::from_repr)
    }

    pub fn next_sibling(&self) -> Option<&SyntaxNode> {
        self.0.next_sibling().map(SyntaxNode::from_repr)
    }

    pub fn prev_sibling(&self) -> Option<&SyntaxNode> {
        self.0.prev_sibling().map(SyntaxNode::from_repr)
    }

    pub fn children(&self) -> SyntaxNodeChildren {
        SyntaxNodeChildren(self.0.children())
    }

    pub fn ancestors(&self) -> impl Iterator<Item = &SyntaxNode> {
        crate::algo::generate(Some(self), |&node| node.parent())
    }

    pub fn descendants(&self) -> impl Iterator<Item = &SyntaxNode> {
        self.preorder().filter_map(|event| match event {
            WalkEvent::Enter(node) => Some(node),
            WalkEvent::Leave(_) => None,
        })
    }

    pub fn siblings(&self, direction: Direction) -> impl Iterator<Item = &SyntaxNode> {
        crate::algo::generate(Some(self), move |&node| match direction {
            Direction::Next => node.next_sibling(),
            Direction::Prev => node.prev_sibling(),
        })
    }

    pub fn preorder(&self) -> impl Iterator<Item = WalkEvent<&SyntaxNode>> {
        self.0.preorder().map(|event| match event {
            WalkEvent::Enter(n) => WalkEvent::Enter(SyntaxNode::from_repr(n)),
            WalkEvent::Leave(n) => WalkEvent::Leave(SyntaxNode::from_repr(n)),
        })
    }

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

    pub fn debug_dump(&self) -> String {
        let mut errors: Vec<_> = match self.ancestors().find_map(SourceFile::cast) {
            Some(file) => file.errors(),
            None => self.root_data().to_vec(),
        };
        errors.sort_by_key(|e| e.offset());
        let mut err_pos = 0;
        let mut level = 0;
        let mut buf = String::new();
        macro_rules! indent {
            () => {
                for _ in 0..level {
                    buf.push_str("  ");
                }
            };
        }

        for event in self.preorder() {
            match event {
                WalkEvent::Enter(node) => {
                    indent!();
                    writeln!(buf, "{:?}", node).unwrap();
                    if node.first_child().is_none() {
                        let off = node.range().end();
                        while err_pos < errors.len() && errors[err_pos].offset() <= off {
                            indent!();
                            writeln!(buf, "err: `{}`", errors[err_pos]).unwrap();
                            err_pos += 1;
                        }
                    }
                    level += 1;
                }
                WalkEvent::Leave(_) => level -= 1,
            }
        }

        assert_eq!(level, 0);
        for err in errors[err_pos..].iter() {
            writeln!(buf, "err: `{}`", err).unwrap();
        }

        buf
    }

    pub(crate) fn root_data(&self) -> &Vec<SyntaxError> {
        self.0.root_data()
    }

    pub(crate) fn replace_with(&self, replacement: GreenNode) -> GreenNode {
        self.0.replace_self(replacement)
    }
}

#[derive(Debug)]
pub struct SyntaxNodeChildren<'a>(rowan::SyntaxNodeChildren<'a, RaTypes>);

impl<'a> Iterator for SyntaxNodeChildren<'a> {
    type Item = &'a SyntaxNode;

    fn next(&mut self) -> Option<&'a SyntaxNode> {
        self.0.next().map(SyntaxNode::from_repr)
    }
}

fn has_short_text(kind: SyntaxKind) -> bool {
    use crate::SyntaxKind::*;
    match kind {
        IDENT | LIFETIME | INT_NUMBER | FLOAT_NUMBER => true,
        _ => false,
    }
}
<|endoftext|>