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

//! Main for building the binary of a Grin peer-to-peer node.

extern crate blake2_rfc as blake2;
extern crate clap;
extern crate daemonize;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate slog;

extern crate grin_api as api;
extern crate grin_config as config;
extern crate grin_core as core;
extern crate grin_grin as grin;
extern crate grin_keychain as keychain;
extern crate grin_util as util;
extern crate grin_wallet as wallet;

use std::thread;
use std::io::Read;
use std::fs::File;
use std::time::Duration;

use clap::{App, Arg, ArgMatches, SubCommand};
use daemonize::Daemonize;

use config::GlobalConfig;
use wallet::WalletConfig;
use core::global;
use util::{init_logger, LoggingConfig, LOGGER};

fn start_from_config_file(mut global_config: GlobalConfig) {
	info!(
		LOGGER,
		"Starting the Grin server from configuration file at {}",
		global_config.config_file_path.unwrap().to_str().unwrap()
	);

	global::set_mining_mode(
		global_config
			.members
			.as_mut()
			.unwrap()
			.server
			.clone()
			.mining_parameter_mode
			.unwrap(),
	);

	grin::Server::start(global_config.members.as_mut().unwrap().server.clone()).unwrap();
	loop {
		thread::sleep(Duration::from_secs(60));
	}
}

fn main() {
	// First, load a global config object,
 // then modify that object with any switches
 // found so that the switches override the
 // global config file

	// This will return a global config object,
 // which will either contain defaults for all // of the config structures or a
 // configuration
 // read from a config file

	let mut global_config = GlobalConfig::new(None).unwrap_or_else(|e| {
		panic!("Error parsing config file: {}", e);
	});

	if global_config.using_config_file {
		// initialise the logger
		init_logger(global_config.members.as_mut().unwrap().logging.clone());
		info!(
			LOGGER,
			"Using configuration file at: {}",
			global_config
				.config_file_path
				.clone()
				.unwrap()
				.to_str()
				.unwrap()
		);
		global::set_mining_mode(
			global_config
				.members
				.as_mut()
				.unwrap()
				.server
				.clone()
				.mining_parameter_mode
				.unwrap(),
		);
	} else {
		init_logger(Some(LoggingConfig::default()));
	}

	let args = App::new("Grin")
		.version("0.1")
		.author("The Grin Team")
		.about("Lightweight implementation of the MimbleWimble protocol.")

    // specification of all the server commands and options
    .subcommand(SubCommand::with_name("server")
                .about("Control the Grin server")
                .arg(Arg::with_name("port")
                     .short("p")
                     .long("port")
                     .help("Port to start the P2P server on")
                     .takes_value(true))
                .arg(Arg::with_name("api_port")
                     .short("a")
                     .long("api_port")
                     .help("Port on which to start the api server (e.g. transaction pool api)")
                     .takes_value(true))
                .arg(Arg::with_name("seed")
                     .short("s")
                     .long("seed")
                     .help("Override seed node(s) to connect to")
                     .takes_value(true)
                     .multiple(true))
                .arg(Arg::with_name("mine")
                     .short("m")
                     .long("mine")
                     .help("Starts the debugging mining loop"))
                .arg(Arg::with_name("wallet_url")
                     .short("w")
                     .long("wallet_url")
                     .help("A listening wallet receiver to which mining rewards will be sent")
                .takes_value(true))
                .subcommand(SubCommand::with_name("start")
                            .about("Start the Grin server as a daemon"))
                .subcommand(SubCommand::with_name("stop")
                            .about("Stop the Grin server daemon"))
                .subcommand(SubCommand::with_name("run")
                            .about("Run the Grin server in this console")))

    // specification of all the client commands and options
    .subcommand(SubCommand::with_name("client")
                .about("Communicates with the Grin server")
                .subcommand(SubCommand::with_name("status")
                            .about("current status of the Grin chain")))

	// specification of the wallet commands and options
	.subcommand(SubCommand::with_name("wallet")
		.about("Wallet software for Grin")
		.arg(Arg::with_name("pass")
			.short("p")
			.long("pass")
			.help("Wallet passphrase used to generate the private key seed")
			.takes_value(true)
			.default_value("mimblewimble"))
		.arg(Arg::with_name("data_dir")
			.short("dd")
			.long("data_dir")
			.help("Directory in which to store wallet files (defaults to current \
			directory)")
			.takes_value(true))
		.arg(Arg::with_name("port")
			.short("r")
			.long("port")
			.help("Port on which to run the wallet receiver when in receiver mode")
			.takes_value(true))
		.arg(Arg::with_name("api_server_address")
			.short("a")
			.long("api_server_address")
			.help("Api address of running node on which to check inputs and post transactions")
			.takes_value(true))

		.subcommand(SubCommand::with_name("receive")
			.about("Run the wallet in receiving mode. If an input file is \
				provided, will process it, otherwise runs in server mode waiting \
				for send requests.")
			.arg(Arg::with_name("input")
				.help("Partial transaction to receive, expects as a JSON file.")
				.short("i")
				.long("input")
				.takes_value(true)))

		.subcommand(SubCommand::with_name("send")
			.about("Builds a transaction to send someone some coins. By default, \
				the transaction will just be printed to stdout. If a destination is \
				provided, the command will attempt to contact the receiver at that \
				address and send the transaction directly.")
			.arg(Arg::with_name("amount")
				.help("Amount to send in the smallest denomination")
				.index(1))
			.arg(Arg::with_name("minimum_confirmations")
				.help("Minimum number of confirmations required for an output to be spendable.")
				.short("c")
				.long("min_conf")
				.default_value("1")
				.takes_value(true))
			.arg(Arg::with_name("dest")
				.help("Send the transaction to the provided server")
				.short("d")
				.long("dest")
				.takes_value(true)))

		.subcommand(SubCommand::with_name("burn")
			.about("** TESTING ONLY ** Burns the provided amount to a known \
				key. Similar to send but burns an output to allow single-party \
				transactions.")
			.arg(Arg::with_name("amount")
				.help("Amount to burn in the smallest denomination")
				.index(1))
			.arg(Arg::with_name("minimum_confirmations")
				.help("Minimum number of confirmations required for an output to be spendable.")
				.short("c")
				.long("min_conf")
				.default_value("1")
				.takes_value(true)))

		.subcommand(SubCommand::with_name("info")
			.about("basic wallet info (outputs)"))

		.subcommand(SubCommand::with_name("init")
			.about("Initialize a new wallet seed file.")))

	.get_matches();

	match args.subcommand() {
		// server commands and options
		("server", Some(server_args)) => {
			server_command(server_args, global_config);
		}

		// client commands and options
		("client", Some(client_args)) => match client_args.subcommand() {
			("status", _) => {
				println!("status info...");
			}
			_ => panic!("Unknown client command, use 'grin help client' for details"),
		},

		// client commands and options
		("wallet", Some(wallet_args)) => {
			wallet_command(wallet_args);
		}

		// If nothing is specified, try to just use the config file instead
		// this could possibly become the way to configure most things
		// with most command line options being phased out
		_ => {
			if global_config.using_config_file {
				start_from_config_file(global_config);
			} else {
				// won't attempt to just start with defaults,
	// and will reject
				println!("Unknown command, and no configuration file was found.");
				println!("Use 'grin help' for a list of all commands.");
			}
		}
	}
}

/// Handles the server part of the command line, mostly running, starting and
/// stopping the Grin blockchain server. Processes all the command line
/// arguments
/// to build a proper configuration and runs Grin with that configuration.
fn server_command(server_args: &ArgMatches, global_config: GlobalConfig) {
	info!(LOGGER, "Starting the Grin server...");

	// just get defaults from the global config
	let mut server_config = global_config.members.unwrap().server;

	if let Some(port) = server_args.value_of("port") {
		server_config.p2p_config.as_mut().unwrap().port = port.parse().unwrap();
	}

	if let Some(api_port) = server_args.value_of("api_port") {
		let default_ip = "0.0.0.0";
		server_config.api_http_addr = format!("{}:{}", default_ip, api_port);
	}

	if server_args.is_present("mine") {
		server_config.mining_config.as_mut().unwrap().enable_mining = true;
	}

	if let Some(wallet_url) = server_args.value_of("wallet_url") {
		server_config
			.mining_config
			.as_mut()
			.unwrap()
			.wallet_receiver_url = wallet_url.to_string();
	}

	if let Some(seeds) = server_args.values_of("seed") {
		server_config.seeding_type = grin::Seeding::List;
		server_config.seeds = Some(seeds.map(|s| s.to_string()).collect());
	}

	// start the server in the different run modes (interactive or daemon)
	match server_args.subcommand() {
		("run", _) => {
			grin::Server::start(server_config).unwrap();
			loop {
				thread::sleep(Duration::from_secs(60));
			}
		}
		("start", _) => {
			let daemonize = Daemonize::new()
				.pid_file("/tmp/grin.pid")
				.chown_pid_file(true)
				.privileged_action(move || {
					grin::Server::start(server_config.clone()).unwrap();
					loop {
						thread::sleep(Duration::from_secs(60));
					}
				});
			match daemonize.start() {
				Ok(_) => info!(LOGGER, "Grin server succesfully started."),
				Err(e) => error!(LOGGER, "Error starting: {}", e),
			}
		}
		("stop", _) => println!("TODO, just 'kill $pid' for now."),
		_ => panic!("Unknown server command, use 'grin help server' for details"),
	}
}

fn wallet_command(wallet_args: &ArgMatches) {
	let mut wallet_config = WalletConfig::default();

	if let Some(port) = wallet_args.value_of("port") {
		let default_ip = "0.0.0.0";
		wallet_config.api_http_addr = format!("{}:{}", default_ip, port);
	}

	if let Some(dir) = wallet_args.value_of("dir") {
		wallet_config.data_file_dir = dir.to_string().clone();
	}

	if let Some(sa) = wallet_args.value_of("api_server_address") {
		wallet_config.check_node_api_http_addr = sa.to_string().clone();
	}

	// Derive the keychain based on seed from seed file and specified passphrase.
 // Generate the initial wallet seed if we are running "wallet init".
	if let ("init", Some(_)) = wallet_args.subcommand() {
		wallet::WalletSeed::init_file(&wallet_config).expect("Failed to init wallet seed file.");

		// we are done here with creating the wallet, so just return
		return;
	}

	let wallet_seed =
		wallet::WalletSeed::from_file(&wallet_config).expect("Failed to read wallet seed file.");
	let passphrase = wallet_args
		.value_of("pass")
		.expect("Failed to read passphrase.");
	let keychain = wallet_seed
		.derive_keychain(&passphrase)
		.expect("Failed to derive keychain from seed file and passphrase.");

	match wallet_args.subcommand() {
		("receive", Some(receive_args)) => if let Some(f) = receive_args.value_of("input") {
			let mut file = File::open(f).expect("Unable to open transaction file.");
			let mut contents = String::new();
			file.read_to_string(&mut contents)
				.expect("Unable to read transaction file.");
			wallet::receive_json_tx_str(&wallet_config, &keychain, contents.as_str()).unwrap();
		} else {
			wallet::server::start_rest_apis(wallet_config, keychain);
		},
		("send", Some(send_args)) => {
			let amount = send_args
				.value_of("amount")
				.expect("Amount to send required")
				.parse()
				.expect("Could not parse amount as a whole number.");
			let minimum_confirmations: u64 = send_args
				.value_of("minimum_confirmations")
				.unwrap_or("1")
				.parse()
				.expect("Could not parse minimum_confirmations as a whole number.");
			let mut dest = "stdout";
			if let Some(d) = send_args.value_of("dest") {
				dest = d;
			}
			wallet::issue_send_tx(
				&wallet_config,
				&keychain,
				amount,
				minimum_confirmations,
				dest.to_string(),
			).unwrap();
		}
		("burn", Some(send_args)) => {
			let amount = send_args
				.value_of("amount")
				.expect("Amount to burn required")
				.parse()
				.expect("Could not parse amount as a whole number.");
			let minimum_confirmations: u64 = send_args
				.value_of("minimum_confirmations")
				.unwrap_or("1")
				.parse()
				.expect("Could not parse minimum_confirmations as a whole number.");
			wallet::issue_burn_tx(&wallet_config, &keychain, amount, minimum_confirmations)
				.unwrap();
		}
		("info", Some(_)) => {
			wallet::show_info(&wallet_config, &keychain);
		}
		_ => panic!("Unknown wallet command, use 'grin help wallet' for details"),
	}
}
<commit_msg>Fix server run mode when passing a seed<commit_after>// Copyright 2016 The Grin Developers
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Main for building the binary of a Grin peer-to-peer node.

extern crate blake2_rfc as blake2;
extern crate clap;
extern crate daemonize;
extern crate serde;
extern crate serde_json;
#[macro_use]
extern crate slog;

extern crate grin_api as api;
extern crate grin_config as config;
extern crate grin_core as core;
extern crate grin_grin as grin;
extern crate grin_keychain as keychain;
extern crate grin_util as util;
extern crate grin_wallet as wallet;

use std::thread;
use std::io::Read;
use std::fs::File;
use std::time::Duration;

use clap::{App, Arg, ArgMatches, SubCommand};
use daemonize::Daemonize;

use config::GlobalConfig;
use wallet::WalletConfig;
use core::global;
use util::{init_logger, LoggingConfig, LOGGER};

fn start_from_config_file(mut global_config: GlobalConfig) {
	info!(
		LOGGER,
		"Starting the Grin server from configuration file at {}",
		global_config.config_file_path.unwrap().to_str().unwrap()
	);

	global::set_mining_mode(
		global_config
			.members
			.as_mut()
			.unwrap()
			.server
			.clone()
			.mining_parameter_mode
			.unwrap(),
	);

	grin::Server::start(global_config.members.as_mut().unwrap().server.clone()).unwrap();
	loop {
		thread::sleep(Duration::from_secs(60));
	}
}

fn main() {
	// First, load a global config object,
 // then modify that object with any switches
 // found so that the switches override the
 // global config file

	// This will return a global config object,
 // which will either contain defaults for all // of the config structures or a
 // configuration
 // read from a config file

	let mut global_config = GlobalConfig::new(None).unwrap_or_else(|e| {
		panic!("Error parsing config file: {}", e);
	});

	if global_config.using_config_file {
		// initialise the logger
		init_logger(global_config.members.as_mut().unwrap().logging.clone());
		info!(
			LOGGER,
			"Using configuration file at: {}",
			global_config
				.config_file_path
				.clone()
				.unwrap()
				.to_str()
				.unwrap()
		);
		global::set_mining_mode(
			global_config
				.members
				.as_mut()
				.unwrap()
				.server
				.clone()
				.mining_parameter_mode
				.unwrap(),
		);
	} else {
		init_logger(Some(LoggingConfig::default()));
	}

	let args = App::new("Grin")
		.version("0.1")
		.author("The Grin Team")
		.about("Lightweight implementation of the MimbleWimble protocol.")

    // specification of all the server commands and options
    .subcommand(SubCommand::with_name("server")
                .about("Control the Grin server")
                .arg(Arg::with_name("port")
                     .short("p")
                     .long("port")
                     .help("Port to start the P2P server on")
                     .takes_value(true))
                .arg(Arg::with_name("api_port")
                     .short("a")
                     .long("api_port")
                     .help("Port on which to start the api server (e.g. transaction pool api)")
                     .takes_value(true))
                .arg(Arg::with_name("seed")
                     .short("s")
                     .long("seed")
                     .help("Override seed node(s) to connect to")
                     .takes_value(true))
                .arg(Arg::with_name("mine")
                     .short("m")
                     .long("mine")
                     .help("Starts the debugging mining loop"))
                .arg(Arg::with_name("wallet_url")
                     .short("w")
                     .long("wallet_url")
                     .help("A listening wallet receiver to which mining rewards will be sent")
                .takes_value(true))
                .subcommand(SubCommand::with_name("start")
                            .about("Start the Grin server as a daemon"))
                .subcommand(SubCommand::with_name("stop")
                            .about("Stop the Grin server daemon"))
                .subcommand(SubCommand::with_name("run")
                            .about("Run the Grin server in this console")))

    // specification of all the client commands and options
    .subcommand(SubCommand::with_name("client")
                .about("Communicates with the Grin server")
                .subcommand(SubCommand::with_name("status")
                            .about("current status of the Grin chain")))

	// specification of the wallet commands and options
	.subcommand(SubCommand::with_name("wallet")
		.about("Wallet software for Grin")
		.arg(Arg::with_name("pass")
			.short("p")
			.long("pass")
			.help("Wallet passphrase used to generate the private key seed")
			.takes_value(true)
			.default_value("mimblewimble"))
		.arg(Arg::with_name("data_dir")
			.short("dd")
			.long("data_dir")
			.help("Directory in which to store wallet files (defaults to current \
			directory)")
			.takes_value(true))
		.arg(Arg::with_name("port")
			.short("r")
			.long("port")
			.help("Port on which to run the wallet receiver when in receiver mode")
			.takes_value(true))
		.arg(Arg::with_name("api_server_address")
			.short("a")
			.long("api_server_address")
			.help("Api address of running node on which to check inputs and post transactions")
			.takes_value(true))

		.subcommand(SubCommand::with_name("receive")
			.about("Run the wallet in receiving mode. If an input file is \
				provided, will process it, otherwise runs in server mode waiting \
				for send requests.")
			.arg(Arg::with_name("input")
				.help("Partial transaction to receive, expects as a JSON file.")
				.short("i")
				.long("input")
				.takes_value(true)))

		.subcommand(SubCommand::with_name("send")
			.about("Builds a transaction to send someone some coins. By default, \
				the transaction will just be printed to stdout. If a destination is \
				provided, the command will attempt to contact the receiver at that \
				address and send the transaction directly.")
			.arg(Arg::with_name("amount")
				.help("Amount to send in the smallest denomination")
				.index(1))
			.arg(Arg::with_name("minimum_confirmations")
				.help("Minimum number of confirmations required for an output to be spendable.")
				.short("c")
				.long("min_conf")
				.default_value("1")
				.takes_value(true))
			.arg(Arg::with_name("dest")
				.help("Send the transaction to the provided server")
				.short("d")
				.long("dest")
				.takes_value(true)))

		.subcommand(SubCommand::with_name("burn")
			.about("** TESTING ONLY ** Burns the provided amount to a known \
				key. Similar to send but burns an output to allow single-party \
				transactions.")
			.arg(Arg::with_name("amount")
				.help("Amount to burn in the smallest denomination")
				.index(1))
			.arg(Arg::with_name("minimum_confirmations")
				.help("Minimum number of confirmations required for an output to be spendable.")
				.short("c")
				.long("min_conf")
				.default_value("1")
				.takes_value(true)))

		.subcommand(SubCommand::with_name("info")
			.about("basic wallet info (outputs)"))

		.subcommand(SubCommand::with_name("init")
			.about("Initialize a new wallet seed file.")))

	.get_matches();

	match args.subcommand() {
		// server commands and options
		("server", Some(server_args)) => {
			server_command(server_args, global_config);
		}

		// client commands and options
		("client", Some(client_args)) => match client_args.subcommand() {
			("status", _) => {
				println!("status info...");
			}
			_ => panic!("Unknown client command, use 'grin help client' for details"),
		},

		// client commands and options
		("wallet", Some(wallet_args)) => {
			wallet_command(wallet_args);
		}

		// If nothing is specified, try to just use the config file instead
		// this could possibly become the way to configure most things
		// with most command line options being phased out
		_ => {
			if global_config.using_config_file {
				start_from_config_file(global_config);
			} else {
				// won't attempt to just start with defaults,
	// and will reject
				println!("Unknown command, and no configuration file was found.");
				println!("Use 'grin help' for a list of all commands.");
			}
		}
	}
}

/// Handles the server part of the command line, mostly running, starting and
/// stopping the Grin blockchain server. Processes all the command line
/// arguments
/// to build a proper configuration and runs Grin with that configuration.
fn server_command(server_args: &ArgMatches, global_config: GlobalConfig) {
	info!(LOGGER, "Starting the Grin server...");

	// just get defaults from the global config
	let mut server_config = global_config.members.unwrap().server;

	if let Some(port) = server_args.value_of("port") {
		server_config.p2p_config.as_mut().unwrap().port = port.parse().unwrap();
	}

	if let Some(api_port) = server_args.value_of("api_port") {
		let default_ip = "0.0.0.0";
		server_config.api_http_addr = format!("{}:{}", default_ip, api_port);
	}

	if server_args.is_present("mine") {
		server_config.mining_config.as_mut().unwrap().enable_mining = true;
	}

	if let Some(wallet_url) = server_args.value_of("wallet_url") {
		server_config
			.mining_config
			.as_mut()
			.unwrap()
			.wallet_receiver_url = wallet_url.to_string();
	}

	if let Some(seeds) = server_args.values_of("seed") {
		server_config.seeding_type = grin::Seeding::List;
		server_config.seeds = Some(seeds.map(|s| s.to_string()).collect());
	}

	// start the server in the different run modes (interactive or daemon)
	match server_args.subcommand() {
		("run", _) => {
			grin::Server::start(server_config).unwrap();
			loop {
				thread::sleep(Duration::from_secs(60));
			}
		}
		("start", _) => {
			let daemonize = Daemonize::new()
				.pid_file("/tmp/grin.pid")
				.chown_pid_file(true)
				.privileged_action(move || {
					grin::Server::start(server_config.clone()).unwrap();
					loop {
						thread::sleep(Duration::from_secs(60));
					}
				});
			match daemonize.start() {
				Ok(_) => info!(LOGGER, "Grin server succesfully started."),
				Err(e) => error!(LOGGER, "Error starting: {}", e),
			}
		}
		("stop", _) => println!("TODO, just 'kill $pid' for now."),
		(cmd, _) => {
      println!(":: {:?}", server_args);
      panic!("Unknown server command '{}', use 'grin help server' for details", cmd);
    }
	}
}

fn wallet_command(wallet_args: &ArgMatches) {
	let mut wallet_config = WalletConfig::default();

	if let Some(port) = wallet_args.value_of("port") {
		let default_ip = "0.0.0.0";
		wallet_config.api_http_addr = format!("{}:{}", default_ip, port);
	}

	if let Some(dir) = wallet_args.value_of("dir") {
		wallet_config.data_file_dir = dir.to_string().clone();
	}

	if let Some(sa) = wallet_args.value_of("api_server_address") {
		wallet_config.check_node_api_http_addr = sa.to_string().clone();
	}

	// Derive the keychain based on seed from seed file and specified passphrase.
 // Generate the initial wallet seed if we are running "wallet init".
	if let ("init", Some(_)) = wallet_args.subcommand() {
		wallet::WalletSeed::init_file(&wallet_config).expect("Failed to init wallet seed file.");

		// we are done here with creating the wallet, so just return
		return;
	}

	let wallet_seed =
		wallet::WalletSeed::from_file(&wallet_config).expect("Failed to read wallet seed file.");
	let passphrase = wallet_args
		.value_of("pass")
		.expect("Failed to read passphrase.");
	let keychain = wallet_seed
		.derive_keychain(&passphrase)
		.expect("Failed to derive keychain from seed file and passphrase.");

	match wallet_args.subcommand() {
		("receive", Some(receive_args)) => if let Some(f) = receive_args.value_of("input") {
			let mut file = File::open(f).expect("Unable to open transaction file.");
			let mut contents = String::new();
			file.read_to_string(&mut contents)
				.expect("Unable to read transaction file.");
			wallet::receive_json_tx_str(&wallet_config, &keychain, contents.as_str()).unwrap();
		} else {
			wallet::server::start_rest_apis(wallet_config, keychain);
		},
		("send", Some(send_args)) => {
			let amount = send_args
				.value_of("amount")
				.expect("Amount to send required")
				.parse()
				.expect("Could not parse amount as a whole number.");
			let minimum_confirmations: u64 = send_args
				.value_of("minimum_confirmations")
				.unwrap_or("1")
				.parse()
				.expect("Could not parse minimum_confirmations as a whole number.");
			let mut dest = "stdout";
			if let Some(d) = send_args.value_of("dest") {
				dest = d;
			}
			wallet::issue_send_tx(
				&wallet_config,
				&keychain,
				amount,
				minimum_confirmations,
				dest.to_string(),
			).unwrap();
		}
		("burn", Some(send_args)) => {
			let amount = send_args
				.value_of("amount")
				.expect("Amount to burn required")
				.parse()
				.expect("Could not parse amount as a whole number.");
			let minimum_confirmations: u64 = send_args
				.value_of("minimum_confirmations")
				.unwrap_or("1")
				.parse()
				.expect("Could not parse minimum_confirmations as a whole number.");
			wallet::issue_burn_tx(&wallet_config, &keychain, amount, minimum_confirmations)
				.unwrap();
		}
		("info", Some(_)) => {
			wallet::show_info(&wallet_config, &keychain);
		}
		_ => panic!("Unknown wallet command, use 'grin help wallet' for details"),
	}
}
<|endoftext|>


<commit_before>#![cfg_attr(all(test, feature = "nightly"), feature(test))] // we only need test feature when testing

#[macro_use] extern crate log;

extern crate syntex_syntax;
extern crate toml;
extern crate env_logger;

extern crate racer;

#[cfg(not(test))]
use racer::core;
#[cfg(not(test))]
use racer::util;
#[cfg(not(test))]
use racer::core::Match;
#[cfg(not(test))]
use racer::util::{getline, path_exists};
#[cfg(not(test))]
use racer::nameres::{do_file_search, do_external_search, PATH_SEP};
#[cfg(not(test))]
use racer::scopes;
#[cfg(not(test))]
use std::path::Path;

#[cfg(not(test))]
fn match_with_snippet_fn(m: Match, session: core::SessionRef) {
    let (linenum, charnum) = scopes::point_to_coords_from_file(&m.filepath, m.point, session).unwrap();
    if m.matchstr == "" {
        panic!("MATCHSTR is empty - waddup?");
    }

    let snippet = racer::snippets::snippet_for_match(&m, session);
    println!("MATCH {};{};{};{};{};{:?};{}", m.matchstr,
                                    snippet,
                                    linenum.to_string(),
                                    charnum.to_string(),
                                    m.filepath.to_str().unwrap(),
                                    m.mtype,
                                    m.contextstr
             );
}

#[cfg(not(test))]
fn match_fn(m: Match, session: core::SessionRef) {
    if let Some((linenum, charnum)) = scopes::point_to_coords_from_file(&m.filepath,
                                                                        m.point,
                                                                        session) {
        println!("MATCH {},{},{},{},{:?},{}", m.matchstr,
                                    linenum.to_string(),
                                    charnum.to_string(),
                                    m.filepath.to_str().unwrap(),
                                    m.mtype,
                                    m.contextstr
                 );
    } else {
        error!("Could not resolve file coords for match {:?}", m);
    }
}

#[cfg(not(test))]
fn complete(args: Vec<String>, print_type: CompletePrinter) {
    if args.len() < 1 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    match args[0].parse::<usize>() {
        Ok(linenum) => {
            complete_by_line_coords(args, linenum, print_type);
        }
        Err(_) => {
            external_complete(&args);
        }
    }
}

#[cfg(not(test))]
fn complete_by_line_coords(args: Vec<String>,
                           linenum: usize,
                           print_type: CompletePrinter) {
    // input: linenum, colnum, fname
    let tb = std::thread::Builder::new().name("searcher".to_string());

    // PD: this probably sucks for performance, but lots of plugins
    // end up failing and leaving tmp files around if racer crashes,
    // so catch the crash.
    let res = tb.spawn(move || {
        run_the_complete_fn(args, linenum, print_type);
    }).unwrap();
    match res.join() {
        Ok(_) => {},
        Err(e) => {
            error!("Search thread paniced: {:?}", e);
        }
    }

    println!("END");

}

#[cfg(not(test))]
enum CompletePrinter {
    Normal,
    WithSnippets
}

#[cfg(not(test))]
fn run_the_complete_fn(args: Vec<String>, linenum: usize, print_type: CompletePrinter) {
        if args.len() < 3 {
            println!("Provide more arguments!");
            print_usage();
            std::process::exit(1);
        }
        let charnum = args[1].parse::<usize>().unwrap();
        let fname = &args[2];
        let substitute_file = Path::new(match args.len() > 3 {
            true => &args[3],
            false => fname
        });

    let fpath = Path::new(fname);
    let session = core::Session::from_path(&fpath, &substitute_file);
    let src = session.load_file(&fpath);
    let line = &getline(&substitute_file, linenum, &session);
    let (start, pos) = util::expand_ident(line, charnum);
    println!("PREFIX {},{},{}", start, pos, &line[start..pos]);

    let point = scopes::coords_to_point(&src, linenum, charnum);

    for m in core::complete_from_file(&src, &fpath, point, &session) {
        match print_type {
            CompletePrinter::Normal => match_fn(m, &session),
            CompletePrinter::WithSnippets => match_with_snippet_fn(m, &session),
        };
    }
}

#[cfg(not(test))]
fn external_complete(args: &[String]) {
    // input: a command line string passed in
    let arg = &args[0];
    let it = arg.split("::");
    let p: Vec<&str> = it.collect();
    let session = core::Session::from_path(&Path::new("."), &Path::new("."));

    for m in do_file_search(p[0], &Path::new(".")) {
        if p.len() == 1 {
            match_fn(m, &session);
        } else {
            for m in do_external_search(&p[1..], &m.filepath, m.point,
                                        core::SearchType::StartsWith,
                                        core::Namespace::BothNamespaces, &session) {
                match_fn(m, &session);
            }
        }
    }
}

#[cfg(not(test))]
fn prefix(args: &[String]) {
    if args.len() < 3 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    let linenum = args[0].parse::<usize>().unwrap();
    let charnum = args[1].parse::<usize>().unwrap();
    let fname = &args[2];
    let substitute_file = Path::new(match args.len() > 3 {
        true => &args[3],
        false => fname
    });
    let fpath = Path::new(&fname);
    let session = core::Session::from_path(&fpath, &substitute_file);

    // print the start, end, and the identifier prefix being matched
    let path = Path::new(fname);
    let line = &getline(&path, linenum, &session);
    let (start, pos) = util::expand_ident(line, charnum);
    println!("PREFIX {},{},{}", start, pos, &line[start..pos]);
}

#[cfg(not(test))]
fn find_definition(args: &[String]) {
    if args.len() < 3 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    let linenum = args[0].parse::<usize>().unwrap();
    let charnum = args[1].parse::<usize>().unwrap();
    let fname = &args[2];
    let substitute_file = Path::new(match args.len() > 3 {
        true => &args[3],
        false => fname
    });
    let fpath = Path::new(&fname);
    let session = core::Session::from_path(&fpath, &substitute_file);
    let src = session.load_file(&fpath);
    let pos = scopes::coords_to_point(&src, linenum, charnum);

    core::find_definition(&src, &fpath, pos, &session).map(|m| match_fn(m, &session));
    println!("END");
}

#[cfg(not(test))]
fn print_usage() {
    let program = std::env::args().next().unwrap().clone();
    println!("usage: {} complete linenum charnum fname [substitute_file]", program);
    println!("or:    {} find-definition linenum charnum fname [substitute_file]", program);
    println!("or:    {} complete fullyqualifiedname   (e.g. std::io::)", program);
    println!("or:    {} prefix linenum charnum fname", program);
    println!("or replace complete with complete-with-snippet for more detailed completions.");
    println!("or:    {} daemon     - to start a process that receives the above commands via stdin", program);
}

#[cfg(not(test))]
fn check_rust_src_env_var() {
    if let Ok(srcpaths) = std::env::var("RUST_SRC_PATH") {
        let v = srcpaths.split(PATH_SEP).collect::<Vec<_>>();
        if !v.is_empty() {
            let f = Path::new(v[0]);
            if !path_exists(f) {
                println!("racer can't find the directory pointed to by the RUST_SRC_PATH variable \"{}\". Try using an absolute fully qualified path and make sure it points to the src directory of a rust checkout - e.g. \"/home/foouser/src/rust/src\".", srcpaths);
                std::process::exit(1);
            } else if !path_exists(f.join("libstd")) {
                println!("Unable to find libstd under RUST_SRC_PATH. N.B. RUST_SRC_PATH variable needs to point to the *src* directory inside a rust checkout e.g. \"/home/foouser/src/rust/src\". Current value \"{}\"", srcpaths);
                std::process::exit(1);
            }
        }
    } else {
        println!("RUST_SRC_PATH environment variable must be set to point to the src directory of a rust checkout. E.g. \"/home/foouser/src/rust/src\"");
        std::process::exit(1);
    }
}

#[cfg(not(test))]
fn daemon() {
    use std::io;
    let mut input = String::new();
    while let Ok(n) = io::stdin().read_line(&mut input) {
        if n == 0 {
            break;
        }
        let args: Vec<String> = input.split(" ").map(|s| s.trim().to_string()).collect();
        run(args);

        input.clear();
    }
}

#[cfg(not(test))]
fn main() {
    // make sure we get a stack trace ifwe panic
    ::std::env::set_var("RUST_BACKTRACE","1");

    env_logger::init().unwrap();
    check_rust_src_env_var();

    let mut args: Vec<String> = std::env::args().collect();

    if args.len() == 1 {
        print_usage();
        std::process::exit(1);
    }

    args.remove(0);
    run(args);
}

#[cfg(not(test))]
fn run(mut args: Vec<String>) {
    //let command  = &args[0];
    let command = args.remove(0);
    match &command[..] {
        "daemon" => daemon(),
        "prefix" => prefix(&args),
        "complete" => complete(args, CompletePrinter::Normal),
        "complete-with-snippet" => complete(args, CompletePrinter::WithSnippets),
        "find-definition" => find_definition(&args),
        "help" => print_usage(),
        cmd => {
            println!("Sorry, I didn't understand command {}", cmd);
            print_usage();
            std::process::exit(1);
        }
    }
}
<commit_msg>Add defaults to RUST_SRC_PATH.<commit_after>#![cfg_attr(all(test, feature = "nightly"), feature(test))] // we only need test feature when testing

#[macro_use] extern crate log;

extern crate syntex_syntax;
extern crate toml;
extern crate env_logger;

extern crate racer;

#[cfg(not(test))]
use racer::core;
#[cfg(not(test))]
use racer::util;
#[cfg(not(test))]
use racer::core::Match;
#[cfg(not(test))]
use racer::util::{getline, path_exists};
#[cfg(not(test))]
use racer::nameres::{do_file_search, do_external_search, PATH_SEP};
#[cfg(not(test))]
use racer::scopes;
#[cfg(not(test))]
use std::path::Path;

#[cfg(not(test))]
fn match_with_snippet_fn(m: Match, session: core::SessionRef) {
    let (linenum, charnum) = scopes::point_to_coords_from_file(&m.filepath, m.point, session).unwrap();
    if m.matchstr == "" {
        panic!("MATCHSTR is empty - waddup?");
    }

    let snippet = racer::snippets::snippet_for_match(&m, session);
    println!("MATCH {};{};{};{};{};{:?};{}", m.matchstr,
                                    snippet,
                                    linenum.to_string(),
                                    charnum.to_string(),
                                    m.filepath.to_str().unwrap(),
                                    m.mtype,
                                    m.contextstr
             );
}

#[cfg(not(test))]
fn match_fn(m: Match, session: core::SessionRef) {
    if let Some((linenum, charnum)) = scopes::point_to_coords_from_file(&m.filepath,
                                                                        m.point,
                                                                        session) {
        println!("MATCH {},{},{},{},{:?},{}", m.matchstr,
                                    linenum.to_string(),
                                    charnum.to_string(),
                                    m.filepath.to_str().unwrap(),
                                    m.mtype,
                                    m.contextstr
                 );
    } else {
        error!("Could not resolve file coords for match {:?}", m);
    }
}

#[cfg(not(test))]
fn complete(args: Vec<String>, print_type: CompletePrinter) {
    if args.len() < 1 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    match args[0].parse::<usize>() {
        Ok(linenum) => {
            complete_by_line_coords(args, linenum, print_type);
        }
        Err(_) => {
            external_complete(&args);
        }
    }
}

#[cfg(not(test))]
fn complete_by_line_coords(args: Vec<String>,
                           linenum: usize,
                           print_type: CompletePrinter) {
    // input: linenum, colnum, fname
    let tb = std::thread::Builder::new().name("searcher".to_string());

    // PD: this probably sucks for performance, but lots of plugins
    // end up failing and leaving tmp files around if racer crashes,
    // so catch the crash.
    let res = tb.spawn(move || {
        run_the_complete_fn(args, linenum, print_type);
    }).unwrap();
    match res.join() {
        Ok(_) => {},
        Err(e) => {
            error!("Search thread paniced: {:?}", e);
        }
    }

    println!("END");

}

#[cfg(not(test))]
enum CompletePrinter {
    Normal,
    WithSnippets
}

#[cfg(not(test))]
fn run_the_complete_fn(args: Vec<String>, linenum: usize, print_type: CompletePrinter) {
        if args.len() < 3 {
            println!("Provide more arguments!");
            print_usage();
            std::process::exit(1);
        }
        let charnum = args[1].parse::<usize>().unwrap();
        let fname = &args[2];
        let substitute_file = Path::new(match args.len() > 3 {
            true => &args[3],
            false => fname
        });

    let fpath = Path::new(fname);
    let session = core::Session::from_path(&fpath, &substitute_file);
    let src = session.load_file(&fpath);
    let line = &getline(&substitute_file, linenum, &session);
    let (start, pos) = util::expand_ident(line, charnum);
    println!("PREFIX {},{},{}", start, pos, &line[start..pos]);

    let point = scopes::coords_to_point(&src, linenum, charnum);

    for m in core::complete_from_file(&src, &fpath, point, &session) {
        match print_type {
            CompletePrinter::Normal => match_fn(m, &session),
            CompletePrinter::WithSnippets => match_with_snippet_fn(m, &session),
        };
    }
}

#[cfg(not(test))]
fn external_complete(args: &[String]) {
    // input: a command line string passed in
    let arg = &args[0];
    let it = arg.split("::");
    let p: Vec<&str> = it.collect();
    let session = core::Session::from_path(&Path::new("."), &Path::new("."));

    for m in do_file_search(p[0], &Path::new(".")) {
        if p.len() == 1 {
            match_fn(m, &session);
        } else {
            for m in do_external_search(&p[1..], &m.filepath, m.point,
                                        core::SearchType::StartsWith,
                                        core::Namespace::BothNamespaces, &session) {
                match_fn(m, &session);
            }
        }
    }
}

#[cfg(not(test))]
fn prefix(args: &[String]) {
    if args.len() < 3 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    let linenum = args[0].parse::<usize>().unwrap();
    let charnum = args[1].parse::<usize>().unwrap();
    let fname = &args[2];
    let substitute_file = Path::new(match args.len() > 3 {
        true => &args[3],
        false => fname
    });
    let fpath = Path::new(&fname);
    let session = core::Session::from_path(&fpath, &substitute_file);

    // print the start, end, and the identifier prefix being matched
    let path = Path::new(fname);
    let line = &getline(&path, linenum, &session);
    let (start, pos) = util::expand_ident(line, charnum);
    println!("PREFIX {},{},{}", start, pos, &line[start..pos]);
}

#[cfg(not(test))]
fn find_definition(args: &[String]) {
    if args.len() < 3 {
        println!("Provide more arguments!");
        print_usage();
        std::process::exit(1);
    }
    let linenum = args[0].parse::<usize>().unwrap();
    let charnum = args[1].parse::<usize>().unwrap();
    let fname = &args[2];
    let substitute_file = Path::new(match args.len() > 3 {
        true => &args[3],
        false => fname
    });
    let fpath = Path::new(&fname);
    let session = core::Session::from_path(&fpath, &substitute_file);
    let src = session.load_file(&fpath);
    let pos = scopes::coords_to_point(&src, linenum, charnum);

    core::find_definition(&src, &fpath, pos, &session).map(|m| match_fn(m, &session));
    println!("END");
}

#[cfg(not(test))]
fn print_usage() {
    let program = std::env::args().next().unwrap().clone();
    println!("usage: {} complete linenum charnum fname [substitute_file]", program);
    println!("or:    {} find-definition linenum charnum fname [substitute_file]", program);
    println!("or:    {} complete fullyqualifiedname   (e.g. std::io::)", program);
    println!("or:    {} prefix linenum charnum fname", program);
    println!("or replace complete with complete-with-snippet for more detailed completions.");
    println!("or:    {} daemon     - to start a process that receives the above commands via stdin", program);
}

#[cfg(not(test))]
fn check_rust_src_env_var() {
    if let Ok(srcpaths) = std::env::var("RUST_SRC_PATH") {
        let v = srcpaths.split(PATH_SEP).collect::<Vec<_>>();
        if !v.is_empty() {
            let f = Path::new(v[0]);
            if !path_exists(f) {
                println!("racer can't find the directory pointed to by the RUST_SRC_PATH variable \"{}\". Try using an absolute fully qualified path and make sure it points to the src directory of a rust checkout - e.g. \"/home/foouser/src/rust/src\".", srcpaths);
                std::process::exit(1);
            } else if !path_exists(f.join("libstd")) {
                println!("Unable to find libstd under RUST_SRC_PATH. N.B. RUST_SRC_PATH variable needs to point to the *src* directory inside a rust checkout e.g. \"/home/foouser/src/rust/src\". Current value \"{}\"", srcpaths);
                std::process::exit(1);
            }
        }
    } else {
        let default_paths = [
            "/usr/local/src/rust/src",
            "/usr/src/rust/src",
        ];
        for &path in &default_paths {
            let f = Path::new(path);
            if path_exists(f) {
                std::env::set_var("RUST_SRC_PATH", path);
                return;
            }
        }

        println!("RUST_SRC_PATH environment variable must be set to point to the src directory of a rust checkout. E.g. \"/home/foouser/src/rust/src\"");
        std::process::exit(1);
    }
}

#[cfg(not(test))]
fn daemon() {
    use std::io;
    let mut input = String::new();
    while let Ok(n) = io::stdin().read_line(&mut input) {
        if n == 0 {
            break;
        }
        let args: Vec<String> = input.split(" ").map(|s| s.trim().to_string()).collect();
        run(args);

        input.clear();
    }
}

#[cfg(not(test))]
fn main() {
    // make sure we get a stack trace ifwe panic
    ::std::env::set_var("RUST_BACKTRACE","1");

    env_logger::init().unwrap();
    check_rust_src_env_var();

    let mut args: Vec<String> = std::env::args().collect();

    if args.len() == 1 {
        print_usage();
        std::process::exit(1);
    }

    args.remove(0);
    run(args);
}

#[cfg(not(test))]
fn run(mut args: Vec<String>) {
    //let command  = &args[0];
    let command = args.remove(0);
    match &command[..] {
        "daemon" => daemon(),
        "prefix" => prefix(&args),
        "complete" => complete(args, CompletePrinter::Normal),
        "complete-with-snippet" => complete(args, CompletePrinter::WithSnippets),
        "find-definition" => find_definition(&args),
        "help" => print_usage(),
        cmd => {
            println!("Sorry, I didn't understand command {}", cmd);
            print_usage();
            std::process::exit(1);
        }
    }
}
<|endoftext|>


<commit_before>use std::os::unix::io::AsRawFd;
use std::sync::Arc;

use drm::buffer::Buffer as DrmBuffer;
use drm::control::{Device as ControlDevice, dumbbuffer::DumbBuffer as Handle};

use super::{Allocator, Buffer, Format};
use crate::backend::drm::device::{DrmDevice, DrmDeviceInternal, FdWrapper};

pub struct DumbBuffer<A: AsRawFd + 'static> {
    fd: Arc<FdWrapper<A>>,
    handle: Handle,
    format: Format,
}

impl<A: AsRawFd + 'static> Allocator<DumbBuffer<A>> for DrmDevice<A> {
    type Error = drm::SystemError;

    fn create_buffer(&mut self, width: u32, height: u32, format: Format) -> Result<DumbBuffer<A>, Self::Error> {
        let handle = self.create_dumb_buffer((width, height), format.code, 32/* TODO */)?;

        Ok(DumbBuffer {
            fd: match &*self.internal {
                DrmDeviceInternal::Atomic(dev) => dev.fd.clone(),
                DrmDeviceInternal::Legacy(dev) => dev.fd.clone(),
            },
            handle,
            format,
        })
    }
}

impl<A: AsRawFd + 'static> Buffer for DumbBuffer<A> {
    fn width(&self) -> u32 {
        self.handle.size().0
    }

    fn height(&self) -> u32 {
        self.handle.size().1
    }

    fn format(&self) -> Format {
        self.format
    }
}

impl<A: AsRawFd + 'static> Drop for DumbBuffer<A> {
    fn drop(&mut self) {
        let _ = self.fd.destroy_dumb_buffer(self.handle);
    }
}<commit_msg>allocator: Expose dumb buffer handle<commit_after>use std::os::unix::io::AsRawFd;
use std::sync::Arc;

use drm::buffer::Buffer as DrmBuffer;
use drm::control::{Device as ControlDevice, dumbbuffer::DumbBuffer as Handle};

use super::{Allocator, Buffer, Format};
use crate::backend::drm::device::{DrmDevice, DrmDeviceInternal, FdWrapper};

pub struct DumbBuffer<A: AsRawFd + 'static> {
    fd: Arc<FdWrapper<A>>,
    pub handle: Handle,
    format: Format,
}

impl<A: AsRawFd + 'static> Allocator<DumbBuffer<A>> for DrmDevice<A> {
    type Error = drm::SystemError;

    fn create_buffer(&mut self, width: u32, height: u32, format: Format) -> Result<DumbBuffer<A>, Self::Error> {
        let handle = self.create_dumb_buffer((width, height), format.code, 32/* TODO */)?;

        Ok(DumbBuffer {
            fd: match &*self.internal {
                DrmDeviceInternal::Atomic(dev) => dev.fd.clone(),
                DrmDeviceInternal::Legacy(dev) => dev.fd.clone(),
            },
            handle,
            format,
        })
    }
}

impl<A: AsRawFd + 'static> Buffer for DumbBuffer<A> {
    fn width(&self) -> u32 {
        self.handle.size().0
    }

    fn height(&self) -> u32 {
        self.handle.size().1
    }

    fn format(&self) -> Format {
        self.format
    }
}

impl<A: AsRawFd + 'static> Drop for DumbBuffer<A> {
    fn drop(&mut self) {
        let _ = self.fd.destroy_dumb_buffer(self.handle);
    }
}<|endoftext|>


<commit_before>use std::io;
use std::{thread, time};

fn run_self_test(address: String) -> io::Result<()> {
    let client_address = address.clone();

    let child = thread::spawn(move || {
        if let Err(e) = ::run_server(address, 4) {
            match e.kind() {
                ::varlink::ErrorKind::Timeout => {}
                _ => panic!("error: {}", e),
            }
        }
    });

    // give server time to start
    thread::sleep(time::Duration::from_secs(1));

    let ret = ::run_client(client_address);
    if let Err(e) = ret {
        panic!("error: {:?}", e);
    }
    if let Err(e) = child.join() {
        Err(io::Error::new(
            io::ErrorKind::ConnectionRefused,
            format!("{:#?}", e),
        ))
    } else {
        Ok(())
    }
}

#[test]
fn test_unix() {
    assert!(run_self_test("unix:/tmp/org.varlink.certification".into()).is_ok());
}

#[test]
#[cfg(any(target_os = "linux", target_os = "android"))]
fn test_unix_abstract() {
    assert!(run_self_test("unix:@org.varlink.certification".into()).is_ok());
}

#[test]
fn test_tcp() {
    assert!(run_self_test("tcp:0.0.0.0:23456".into()).is_ok());
}

#[test]
fn test_exec() {
    let address: String;

    if ::std::path::Path::new("../../target/debug/varlink-certification").exists() {
        address = "exec:../../target/debug/varlink-certification".into();
    } else if ::std::path::Path::new("./target/debug/varlink-certification").exists() {
        address = "exec:./target/debug/varlink-certification".into();
    } else {
        eprintln!("test test::test_exec ... skipping, no varlink-certification binary found");
        return;
    }

    assert!(::run_client(address).is_ok());
}

#[test]
fn test_wrong_address_1() {
    assert!(::run_server("tcpd:0.0.0.0:12345".into(), 1).is_err());
}
<commit_msg>varlink-certification: test_exec() with cargo install as fallback<commit_after>use std::io;
use std::process::{Command, Stdio};
use std::{thread, time};
use {ErrorKind, Result};

fn run_self_test(address: String) -> io::Result<()> {
    let client_address = address.clone();

    let child = thread::spawn(move || {
        if let Err(e) = ::run_server(address, 4) {
            match e.kind() {
                ::varlink::ErrorKind::Timeout => {}
                _ => panic!("error: {}", e),
            }
        }
    });

    // give server time to start
    thread::sleep(time::Duration::from_secs(1));

    let ret = ::run_client(client_address);
    if let Err(e) = ret {
        panic!("error: {:?}", e);
    }
    if let Err(e) = child.join() {
        Err(io::Error::new(
            io::ErrorKind::ConnectionRefused,
            format!("{:#?}", e),
        ))
    } else {
        Ok(())
    }
}

#[test]
fn test_unix() {
    assert!(run_self_test("unix:/tmp/org.varlink.certification".into()).is_ok());
}

#[test]
#[cfg(any(target_os = "linux", target_os = "android"))]
fn test_unix_abstract() {
    assert!(run_self_test("unix:@org.varlink.certification".into()).is_ok());
}

#[test]
fn test_tcp() {
    assert!(run_self_test("tcp:0.0.0.0:23456".into()).is_ok());
}

fn get_exec() -> Result<String> {
    if ::std::path::Path::new("../../target/debug/varlink-certification").exists() {
        return Ok("exec:../../target/debug/varlink-certification".into());
    }

    if ::std::path::Path::new("./target/debug/varlink-certification").exists() {
        return Ok("exec:./target/debug/varlink-certification".into());
    }

    let mut child = Command::new("cargo")
        .arg("install")
        .arg("--force")
        .arg("--path=varlink-certification")
        .arg("--bin=varlink-certification")
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .spawn()?;
    match child.wait() {
        Ok(e) if e.success() => return Ok("exec:varlink-certification".into()),
        _ => {}
    }

    let mut child = Command::new("cargo")
        .arg("install")
        .arg("--force")
        .arg("--bin=varlink-certification")
        .stdout(Stdio::null())
        .stderr(Stdio::null())
        .spawn()?;
    match child.wait() {
        Ok(e) if e.success() => return Ok("exec:varlink-certification".into()),
        _ => {}
    }
    Err(ErrorKind::Io_Error(io::ErrorKind::NotFound).into())
}

#[test]
fn test_exec() {
    match get_exec() {
        Err(_) => {
            eprintln!("test test::test_exec ... skipping, no varlink-certification binary found");
            return;
        }
        Ok(address) => assert!(::run_client(address).is_ok()),
    }
}

#[test]
fn test_wrong_address_1() {
    assert!(::run_server("tcpd:0.0.0.0:12345".into(), 1).is_err());
}
<|endoftext|>


<commit_before>use crate::completion::{
    CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions,
};

use ra_syntax::{ast::{self, edit}, AstNode, SyntaxKind, TextRange};
use hir::{self, Docs, HasSource};

use ra_assists::utils::get_missing_impl_items;

/// Analyzes the specified `CompletionContext` and provides magic completions
/// if the context falls within a `impl Trait for` block.
///
/// # Completion Activation
/// The completion will activate when a user begins to type a function
/// definition, an associated type, or an associated constant.
///
/// ### Functions
/// ```ignore
/// trait SomeTrait {
///     fn foo(&self);
/// }
///
/// impl SomeTrait for () {
///     fn <|>
/// }
/// ```
///
/// ### Associated Types
/// ```ignore
/// trait SomeTrait {
///     type SomeType;
/// }
///
/// impl SomeTrait for () {
///     type <|>
/// }
/// ```
///
/// ### Associated Constants
/// ```ignore
/// trait SomeTrait {
///     const SOME_CONST: u16;
/// }
///
/// impl SomeTrait for () {
///     const <|>
/// }
/// ```
pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {

    // it is possible to have a parent `fn` and `impl` block. Ignore completion
    // attempts from within a `fn` block.
    if ctx.function_syntax.is_some() {
        return;
    }

    if let Some(ref impl_block) = ctx.impl_block {
        for item in get_missing_impl_items(ctx.db, &ctx.analyzer, impl_block) {
            match item {
                hir::AssocItem::Function(f) => add_function_impl(acc, ctx, &f),
                hir::AssocItem::TypeAlias(t) => add_type_alias_impl(acc, ctx, &t),
                hir::AssocItem::Const(c) => add_const_impl(acc, ctx, &c),
            }
        }
    }
}

fn add_function_impl(acc: &mut Completions, ctx: &CompletionContext, func: &hir::Function) {
    use crate::display::FunctionSignature;

    let display = FunctionSignature::from_hir(ctx.db, func.clone());

    let func_name = func.name(ctx.db);

    let label = if func.params(ctx.db).len() > 0 {
        format!("fn {}(..)", func_name.to_string())
    } else {
        format!("fn {}()", func_name.to_string())
    };

    let builder = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label.clone())
        .lookup_by(label)
        .set_documentation(func.docs(ctx.db));

    let completion_kind = if func.has_self_param(ctx.db) {
        CompletionItemKind::Method
    } else {
        CompletionItemKind::Function
    };

    let snippet = {
        let mut s = format!("{}", display);
        s.push_str(" {}");
        s
    };

    builder.insert_text(snippet).kind(completion_kind).add_to(acc);
}

fn add_type_alias_impl(
    acc: &mut Completions,
    ctx: &CompletionContext,
    type_alias: &hir::TypeAlias,
) {
    let snippet = format!("type {} = ", type_alias.name(ctx.db).to_string());

    CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
        .insert_text(snippet)
        .kind(CompletionItemKind::TypeAlias)
        .set_documentation(type_alias.docs(ctx.db))
        .add_to(acc);
}

fn add_const_impl(
    acc: &mut Completions,
    ctx: &CompletionContext,
    const_: &hir::Const,
) {
    let snippet = make_const_compl_syntax(&const_.source(ctx.db).value);

    CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
        .insert_text(snippet)
        .kind(CompletionItemKind::Const)
        .set_documentation(const_.docs(ctx.db))
        .add_to(acc);
}

/// Using a `ConstDef` `SyntaxNode` to create a `String` that represents
/// the output of the magic completion.
///
/// There isn't a whole lot of information about a `hir::Const` or
/// `ast::ConstDef` to prove useful when creating the magic completion for the
/// associated constant. This method simply copies the syntax tree of the
/// target trait up until a `;` or `=` is found. From the sliced syntax tree
/// it formulates the magic completion string.
fn make_const_compl_syntax(const_: &ast::ConstDef) -> String {
    let const_ = edit::strip_attrs_and_docs(const_);

    let const_start = const_.syntax().text_range().start();
    let const_end = const_.syntax().text_range().end();

    let start = const_
        .syntax()
        .first_child_or_token()
        .map_or(
            const_start,
            |f| f.text_range().start());

    let end = const_
        .syntax()
        .children_with_tokens()
        .find(|s| s.kind() == SyntaxKind::SEMI || s.kind() == SyntaxKind::EQ)
        .map_or(const_end, |f| f.text_range().start());

    let len = end - start;
    let range = TextRange::from_to(0.into(), len);

    let syntax = const_.syntax().text().slice(range).to_string();

    format!("{} = ", syntax.trim_end())
}

#[cfg(test)]
mod tests {
    use crate::completion::{do_completion, CompletionItem, CompletionKind};
    use insta::assert_debug_snapshot;

    fn complete(code: &str) -> Vec<CompletionItem> {
        do_completion(code, CompletionKind::Magic)
    }

    #[test]
    fn single_function() {
        let completions = complete(
            r"
            trait Test {
                fn foo();
            }

            struct T1;

            impl Test for T1 {
                <|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "fn foo()",
                source_range: [138; 138),
                delete: [138; 138),
                insert: "fn foo() {}",
                kind: Function,
            },
        ]
        "###);
    }

    #[test]
    fn hide_implemented_fn() {
        let completions = complete(
            r"
            trait Test {
                fn foo();
                fn bar();
            }

            struct T1;

            impl Test for T1 {
                fn foo() {}

                <|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "fn bar()",
                source_range: [193; 193),
                delete: [193; 193),
                insert: "fn bar() {}",
                kind: Function,
            },
        ]
        "###);
    }

    #[test]
    fn generic_fn() {
        let completions = complete(
            r"
            trait Test {
                fn foo<T>();
            }

            struct T1;

            impl Test for T1 {
                <|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "fn foo()",
                source_range: [141; 141),
                delete: [141; 141),
                insert: "fn foo<T>() {}",
                kind: Function,
            },
        ]
        "###);
    }

    #[test]
    fn generic_constrait_fn() {
        let completions = complete(
            r"
            trait Test {
                fn foo<T>() where T: Into<String>;
            }

            struct T1;

            impl Test for T1 {
                <|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "fn foo()",
                source_range: [163; 163),
                delete: [163; 163),
                insert: "fn foo<T>()\nwhere T: Into<String> {}",
                kind: Function,
            },
        ]
        "###);
    }
}
<commit_msg>Added tests to test associated types and consts.<commit_after>use crate::completion::{
    CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions,
};

use ra_syntax::{ast::{self, edit}, AstNode, SyntaxKind, TextRange};
use hir::{self, Docs, HasSource};

use ra_assists::utils::get_missing_impl_items;

/// Analyzes the specified `CompletionContext` and provides magic completions
/// if the context falls within a `impl Trait for` block.
///
/// # Completion Activation
/// The completion will activate when a user begins to type a function
/// definition, an associated type, or an associated constant.
///
/// ### Functions
/// ```ignore
/// trait SomeTrait {
///     fn foo(&self);
/// }
///
/// impl SomeTrait for () {
///     fn <|>
/// }
/// ```
///
/// ### Associated Types
/// ```ignore
/// trait SomeTrait {
///     type SomeType;
/// }
///
/// impl SomeTrait for () {
///     type <|>
/// }
/// ```
///
/// ### Associated Constants
/// ```ignore
/// trait SomeTrait {
///     const SOME_CONST: u16;
/// }
///
/// impl SomeTrait for () {
///     const <|>
/// }
/// ```
pub(crate) fn complete_trait_impl(acc: &mut Completions, ctx: &CompletionContext) {

    // it is possible to have a parent `fn` and `impl` block. Ignore completion
    // attempts from within a `fn` block.
    if ctx.function_syntax.is_some() {
        return;
    }

    if let Some(ref impl_block) = ctx.impl_block {
        for item in get_missing_impl_items(ctx.db, &ctx.analyzer, impl_block) {
            match item {
                hir::AssocItem::Function(f) => add_function_impl(acc, ctx, &f),
                hir::AssocItem::TypeAlias(t) => add_type_alias_impl(acc, ctx, &t),
                hir::AssocItem::Const(c) => add_const_impl(acc, ctx, &c),
            }
        }
    }
}

fn add_function_impl(acc: &mut Completions, ctx: &CompletionContext, func: &hir::Function) {
    use crate::display::FunctionSignature;

    let display = FunctionSignature::from_hir(ctx.db, func.clone());

    let func_name = func.name(ctx.db);

    let label = if func.params(ctx.db).len() > 0 {
        format!("fn {}(..)", func_name.to_string())
    } else {
        format!("fn {}()", func_name.to_string())
    };

    let builder = CompletionItem::new(CompletionKind::Magic, ctx.source_range(), label.clone())
        .lookup_by(label)
        .set_documentation(func.docs(ctx.db));

    let completion_kind = if func.has_self_param(ctx.db) {
        CompletionItemKind::Method
    } else {
        CompletionItemKind::Function
    };

    let snippet = {
        let mut s = format!("{}", display);
        s.push_str(" {}");
        s
    };

    builder.insert_text(snippet).kind(completion_kind).add_to(acc);
}

fn add_type_alias_impl(
    acc: &mut Completions,
    ctx: &CompletionContext,
    type_alias: &hir::TypeAlias,
) {
    let snippet = format!("type {} = ", type_alias.name(ctx.db).to_string());

    CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
        .insert_text(snippet)
        .kind(CompletionItemKind::TypeAlias)
        .set_documentation(type_alias.docs(ctx.db))
        .add_to(acc);
}

fn add_const_impl(
    acc: &mut Completions,
    ctx: &CompletionContext,
    const_: &hir::Const,
) {
    let snippet = make_const_compl_syntax(&const_.source(ctx.db).value);

    CompletionItem::new(CompletionKind::Magic, ctx.source_range(), snippet.clone())
        .insert_text(snippet)
        .kind(CompletionItemKind::Const)
        .set_documentation(const_.docs(ctx.db))
        .add_to(acc);
}

/// Using a `ConstDef` `SyntaxNode` to create a `String` that represents
/// the output of the magic completion.
///
/// There isn't a whole lot of information about a `hir::Const` or
/// `ast::ConstDef` to prove useful when creating the magic completion for the
/// associated constant. This method simply copies the syntax tree of the
/// target trait up until a `;` or `=` is found. From the sliced syntax tree
/// it formulates the magic completion string.
fn make_const_compl_syntax(const_: &ast::ConstDef) -> String {
    let const_ = edit::strip_attrs_and_docs(const_);

    let const_start = const_.syntax().text_range().start();
    let const_end = const_.syntax().text_range().end();

    let start = const_
        .syntax()
        .first_child_or_token()
        .map_or(
            const_start,
            |f| f.text_range().start());

    let end = const_
        .syntax()
        .children_with_tokens()
        .find(|s| s.kind() == SyntaxKind::SEMI || s.kind() == SyntaxKind::EQ)
        .map_or(const_end, |f| f.text_range().start());

    let len = end - start;
    let range = TextRange::from_to(0.into(), len);

    let syntax = const_.syntax().text().slice(range).to_string();

    format!("{} = ", syntax.trim_end())
}

#[cfg(test)]
mod tests {
    use crate::completion::{do_completion, CompletionItem, CompletionKind};
    use insta::assert_debug_snapshot;

    fn complete(code: &str) -> Vec<CompletionItem> {
        do_completion(code, CompletionKind::Magic)
    }

    #[test]
    fn single_function() {
        let completions = complete(
            r"
            trait Test {
                fn foo();
            }

            struct T1;

            impl Test for T1 {
                <|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "fn foo()",
                source_range: [138; 138),
                delete: [138; 138),
                insert: "fn foo() {}",
                kind: Function,
            },
        ]
        "###);
    }

    #[test]
    fn hide_implemented_fn() {
        let completions = complete(
            r"
            trait Test {
                fn foo();
                fn bar();
            }

            struct T1;

            impl Test for T1 {
                fn foo() {}

                <|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "fn bar()",
                source_range: [193; 193),
                delete: [193; 193),
                insert: "fn bar() {}",
                kind: Function,
            },
        ]
        "###);
    }

    #[test]
    fn generic_fn() {
        let completions = complete(
            r"
            trait Test {
                fn foo<T>();
            }

            struct T1;

            impl Test for T1 {
                <|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "fn foo()",
                source_range: [141; 141),
                delete: [141; 141),
                insert: "fn foo<T>() {}",
                kind: Function,
            },
        ]
        "###);
    }

    #[test]
    fn generic_constrait_fn() {
        let completions = complete(
            r"
            trait Test {
                fn foo<T>() where T: Into<String>;
            }

            struct T1;

            impl Test for T1 {
                <|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "fn foo()",
                source_range: [163; 163),
                delete: [163; 163),
                insert: "fn foo<T>()\nwhere T: Into<String> {}",
                kind: Function,
            },
        ]
        "###);
    }

    #[test]
    fn associated_type() {
        let completions = complete(
            r"
            trait Test {
                type SomeType;
            }

            impl Test for () {
                <|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "type SomeType = ",
                source_range: [119; 119),
                delete: [119; 119),
                insert: "type SomeType = ",
                kind: TypeAlias,
            },
        ]
        "###);
    }

    #[test]
    fn associated_const() {
        let completions = complete(
            r"
            trait Test {
                const SOME_CONST: u16;
            }

            impl Test for () {
                <|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "const SOME_CONST: u16 = ",
                source_range: [127; 127),
                delete: [127; 127),
                insert: "const SOME_CONST: u16 = ",
                kind: Const,
            },
        ]
        "###);
    }

    #[test]
    fn associated_const_with_default() {
        let completions = complete(
            r"
            trait Test {
                const SOME_CONST: u16 = 42;
            }

            impl Test for () {
                <|>
            }
            ",
        );
        assert_debug_snapshot!(completions, @r###"
        [
            CompletionItem {
                label: "const SOME_CONST: u16 = ",
                source_range: [132; 132),
                delete: [132; 132),
                insert: "const SOME_CONST: u16 = ",
                kind: Const,
            },
        ]
        "###);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use aptos_transaction_builder::aptos_stdlib;
use aptos_types::{on_chain_config::Version, transaction::TransactionStatus};
use aptos_vm::AptosVM;
use language_e2e_tests::{
    common_transactions::peer_to_peer_txn, test_with_different_versions,
    versioning::CURRENT_RELEASE_VERSIONS,
};

#[test]
fn initial_aptos_version() {
    test_with_different_versions! {CURRENT_RELEASE_VERSIONS, |test_env| {
        let mut executor = test_env.executor;

        let vm = AptosVM::new(executor.get_state_view());

        assert_eq!(
            vm.internals().version().unwrap(),
            Version { major: test_env.version_number }
        );

        let account = test_env.dr_account;
        println!("@@@@@@@@@@@@ account {:?}", account);
        let txn = account
            .transaction()
            .payload(aptos_stdlib::version_set_version(test_env.version_number + 1))
            .sequence_number(test_env.dr_sequence_number)
            .sign();
        println!("@@@@@@@@@@@@ txn {:?}", txn);
        executor.new_block();
        executor.execute_and_apply(txn);
        println!("!!!!!!! EXECUTED");

        let new_vm = AptosVM::new(executor.get_state_view());
        assert_eq!(
            new_vm.internals().version().unwrap(),
            Version { major: test_env.version_number + 1 }
        );
    }
    }
}

#[test]
fn drop_txn_after_reconfiguration() {
    test_with_different_versions! {CURRENT_RELEASE_VERSIONS, |test_env| {
        let mut executor = test_env.executor;
        let vm = AptosVM::new(executor.get_state_view());

        assert_eq!(
            vm.internals().version().unwrap(),
            Version { major: test_env.version_number }
        );

        let account = test_env.dr_account;
        let txn = account
            .transaction()
            .payload(aptos_stdlib::version_set_version(test_env.version_number + 1))
            .sequence_number(test_env.dr_sequence_number)
            .sign();
        executor.new_block();

        let sender = executor.create_raw_account_data(1_000_000, 10);
        let receiver = executor.create_raw_account_data(100_000, 10);
        let txn2 = peer_to_peer_txn(sender.account(), receiver.account(), 11, 1000);

        let mut output = executor.execute_block(vec![txn, txn2]).unwrap();
        assert_eq!(output.pop().unwrap().status(), &TransactionStatus::Retry)
    }
    }
}
<commit_msg>[move-e2e-tests] cleanup println<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use aptos_transaction_builder::aptos_stdlib;
use aptos_types::{on_chain_config::Version, transaction::TransactionStatus};
use aptos_vm::AptosVM;
use language_e2e_tests::{
    common_transactions::peer_to_peer_txn, test_with_different_versions,
    versioning::CURRENT_RELEASE_VERSIONS,
};

#[test]
fn initial_aptos_version() {
    test_with_different_versions! {CURRENT_RELEASE_VERSIONS, |test_env| {
        let mut executor = test_env.executor;

        let vm = AptosVM::new(executor.get_state_view());

        assert_eq!(
            vm.internals().version().unwrap(),
            Version { major: test_env.version_number }
        );

        let account = test_env.dr_account;
        let txn = account
            .transaction()
            .payload(aptos_stdlib::version_set_version(test_env.version_number + 1))
            .sequence_number(test_env.dr_sequence_number)
            .sign();
        executor.new_block();
        executor.execute_and_apply(txn);

        let new_vm = AptosVM::new(executor.get_state_view());
        assert_eq!(
            new_vm.internals().version().unwrap(),
            Version { major: test_env.version_number + 1 }
        );
    }
    }
}

#[test]
fn drop_txn_after_reconfiguration() {
    test_with_different_versions! {CURRENT_RELEASE_VERSIONS, |test_env| {
        let mut executor = test_env.executor;
        let vm = AptosVM::new(executor.get_state_view());

        assert_eq!(
            vm.internals().version().unwrap(),
            Version { major: test_env.version_number }
        );

        let account = test_env.dr_account;
        let txn = account
            .transaction()
            .payload(aptos_stdlib::version_set_version(test_env.version_number + 1))
            .sequence_number(test_env.dr_sequence_number)
            .sign();
        executor.new_block();

        let sender = executor.create_raw_account_data(1_000_000, 10);
        let receiver = executor.create_raw_account_data(100_000, 10);
        let txn2 = peer_to_peer_txn(sender.account(), receiver.account(), 11, 1000);

        let mut output = executor.execute_block(vec![txn, txn2]).unwrap();
        assert_eq!(output.pop().unwrap().status(), &TransactionStatus::Retry)
    }
    }
}
<|endoftext|>


<commit_before>//! lint on inherent implementations

use crate::utils::{in_macro, span_lint_and_then};
use rustc::hir::*;
use rustc::impl_lint_pass;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc_data_structures::fx::FxHashMap;
use rustc_session::declare_tool_lint;
use rustc_span::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for multiple inherent implementations of a struct
    ///
    /// **Why is this bad?** Splitting the implementation of a type makes the code harder to navigate.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// struct X;
    /// impl X {
    ///     fn one() {}
    /// }
    /// impl X {
    ///     fn other() {}
    /// }
    /// ```
    ///
    /// Could be written:
    ///
    /// ```rust
    /// struct X;
    /// impl X {
    ///     fn one() {}
    ///     fn other() {}
    /// }
    /// ```
    pub MULTIPLE_INHERENT_IMPL,
    restriction,
    "Multiple inherent impl that could be grouped"
}

#[allow(clippy::module_name_repetitions)]
#[derive(Default)]
pub struct MultipleInherentImpl {
    impls: FxHashMap<def_id::DefId, Span>,
}

impl_lint_pass!(MultipleInherentImpl => [MULTIPLE_INHERENT_IMPL]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MultipleInherentImpl {
    fn check_item(&mut self, _: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) {
        if let ItemKind::Impl(_, _, _, ref generics, None, _, _) = item.kind {
            // Remember for each inherent implementation encoutered its span and generics
            // but filter out implementations that have generic params (type or lifetime)
            // or are derived from a macro
            if !in_macro(item.span) && generics.params.len() == 0 {
                self.impls.insert(item.hir_id.owner_def_id(), item.span);
            }
        }
    }

    fn check_crate_post(&mut self, cx: &LateContext<'a, 'tcx>, krate: &'tcx Crate<'_>) {
        if let Some(item) = krate.items.values().nth(0) {
            // Retrieve all inherent implementations from the crate, grouped by type
            for impls in cx
                .tcx
                .crate_inherent_impls(item.hir_id.owner_def_id().krate)
                .inherent_impls
                .values()
            {
                // Filter out implementations that have generic params (type or lifetime)
                let mut impl_spans = impls.iter().filter_map(|impl_def| self.impls.get(impl_def));
                if let Some(initial_span) = impl_spans.nth(0) {
                    impl_spans.for_each(|additional_span| {
                        span_lint_and_then(
                            cx,
                            MULTIPLE_INHERENT_IMPL,
                            *additional_span,
                            "Multiple implementations of this structure",
                            |db| {
                                db.span_note(*initial_span, "First implementation here");
                            },
                        )
                    })
                }
            }
        }
    }
}
<commit_msg>Use `is_empty()`<commit_after>//! lint on inherent implementations

use crate::utils::{in_macro, span_lint_and_then};
use rustc::hir::*;
use rustc::impl_lint_pass;
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
use rustc_data_structures::fx::FxHashMap;
use rustc_session::declare_tool_lint;
use rustc_span::Span;

declare_clippy_lint! {
    /// **What it does:** Checks for multiple inherent implementations of a struct
    ///
    /// **Why is this bad?** Splitting the implementation of a type makes the code harder to navigate.
    ///
    /// **Known problems:** None.
    ///
    /// **Example:**
    /// ```rust
    /// struct X;
    /// impl X {
    ///     fn one() {}
    /// }
    /// impl X {
    ///     fn other() {}
    /// }
    /// ```
    ///
    /// Could be written:
    ///
    /// ```rust
    /// struct X;
    /// impl X {
    ///     fn one() {}
    ///     fn other() {}
    /// }
    /// ```
    pub MULTIPLE_INHERENT_IMPL,
    restriction,
    "Multiple inherent impl that could be grouped"
}

#[allow(clippy::module_name_repetitions)]
#[derive(Default)]
pub struct MultipleInherentImpl {
    impls: FxHashMap<def_id::DefId, Span>,
}

impl_lint_pass!(MultipleInherentImpl => [MULTIPLE_INHERENT_IMPL]);

impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MultipleInherentImpl {
    fn check_item(&mut self, _: &LateContext<'a, 'tcx>, item: &'tcx Item<'_>) {
        if let ItemKind::Impl(_, _, _, ref generics, None, _, _) = item.kind {
            // Remember for each inherent implementation encoutered its span and generics
            // but filter out implementations that have generic params (type or lifetime)
            // or are derived from a macro
            if !in_macro(item.span) && generics.params.is_empty() {
                self.impls.insert(item.hir_id.owner_def_id(), item.span);
            }
        }
    }

    fn check_crate_post(&mut self, cx: &LateContext<'a, 'tcx>, krate: &'tcx Crate<'_>) {
        if let Some(item) = krate.items.values().nth(0) {
            // Retrieve all inherent implementations from the crate, grouped by type
            for impls in cx
                .tcx
                .crate_inherent_impls(item.hir_id.owner_def_id().krate)
                .inherent_impls
                .values()
            {
                // Filter out implementations that have generic params (type or lifetime)
                let mut impl_spans = impls.iter().filter_map(|impl_def| self.impls.get(impl_def));
                if let Some(initial_span) = impl_spans.nth(0) {
                    impl_spans.for_each(|additional_span| {
                        span_lint_and_then(
                            cx,
                            MULTIPLE_INHERENT_IMPL,
                            *additional_span,
                            "Multiple implementations of this structure",
                            |db| {
                                db.span_note(*initial_span, "First implementation here");
                            },
                        )
                    })
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>extern crate proc_macro;
#[macro_use]
extern crate quote;
extern crate syn;

use proc_macro::TokenStream;
use syn::DeriveInput;

#[proc_macro_derive(FitsRow, attributes(fitsio))]
pub fn read_row(input: TokenStream) -> TokenStream {
    let input: DeriveInput = syn::parse(input).unwrap();
    let expanded = impl_read_row(input);
    expanded.into()
}

fn impl_read_row(input: syn::DeriveInput) -> quote::Tokens {
    let name = &input.ident;

    let mut tokens = Vec::new();

    match &input.data {
        &syn::Data::Struct(ref s) => match &s.fields {
            &syn::Fields::Named(ref fields) => for field in &fields.named {
                let ident = &field.ident.unwrap();
                let ident_str = ident.to_string();
                if field.attrs.is_empty() {
                    tokens.push(quote! {
                        out.#ident = tbl.read_cell_value(fits_file, #ident_str, idx)?;
                    });
                } else {
                    for attr in &field.attrs {
                        match attr.interpret_meta() {
                            Some(syn::Meta::List(l)) => for entry in l.nested {
                                match entry {
                                    syn::NestedMeta::Meta(syn::Meta::NameValue(
                                        syn::MetaNameValue {
                                            ident: attr_ident,
                                            lit,
                                            ..
                                        },
                                    )) => {
                                        if attr_ident.to_string() != "colname" {
                                            continue;
                                        }

                                        match lit {
                                            syn::Lit::Str(ls) => {
                                                tokens.push(quote! {
                                                    out.#ident = tbl.read_cell_value(
                                                        fits_file,
                                                        #ls,
                                                        idx)?;
                                                });
                                            }
                                            _ => panic!(
                                                "Only #[fitsio(colname = \"...\")] is supported"
                                            ),
                                        }
                                    }
                                    _ => panic!("Only #[fitsio(colname = \"...\")] is supported"),
                                }
                            },
                            _ => panic!("Only #[fitsio(colname = \"...\")] is supported"),
                        }
                    }
                }
            },
            _ => panic!("Only #[fitsio(colname = \"...\")] is supported"),
        },
        _ => panic!("derive only possible for structs"),
    }

    quote!{
        impl FitsRow for #name {
            fn from_table(
                tbl: &::fitsio::hdu::FitsHdu,
                fits_file: &mut ::fitsio::FitsFile, idx: usize) ->
                    ::fitsio::errors::Result<Self> where Self: Sized  {
                let mut out = Self::default();

                #(#tokens)*

                Ok(out)
            }
        }
    }
}
<commit_msg>Expand impl function as types were wrong<commit_after>extern crate proc_macro;
#[macro_use]
extern crate quote;
extern crate syn;

use proc_macro::TokenStream;
use syn::DeriveInput;

#[proc_macro_derive(FitsRow, attributes(fitsio))]
pub fn read_row(input: TokenStream) -> TokenStream {
    let input: DeriveInput = syn::parse(input).unwrap();
    let name = &input.ident;

    let mut tokens = Vec::new();

    match &input.data {
        &syn::Data::Struct(ref s) => match &s.fields {
            &syn::Fields::Named(ref fields) => for field in &fields.named {
                let ident = &field.ident.as_ref().unwrap();
                let ident_str = ident.to_string();
                if field.attrs.is_empty() {
                    tokens.push(quote! {
                        out.#ident = tbl.read_cell_value(fits_file, #ident_str, idx)?;
                    });
                } else {
                    for attr in &field.attrs {
                        match attr.interpret_meta() {
                            Some(syn::Meta::List(l)) => for entry in l.nested {
                                match entry {
                                    syn::NestedMeta::Meta(syn::Meta::NameValue(
                                        syn::MetaNameValue {
                                            ident: attr_ident,
                                            lit,
                                            ..
                                        },
                                    )) => {
                                        if attr_ident.to_string() != "colname" {
                                            continue;
                                        }

                                        match lit {
                                            syn::Lit::Str(ls) => {
                                                tokens.push(quote! {
                                                    out.#ident = tbl.read_cell_value(
                                                        fits_file,
                                                        #ls,
                                                        idx)?;
                                                });
                                            }
                                            _ => panic!(
                                                "Only #[fitsio(colname = \"...\")] is supported"
                                            ),
                                        }
                                    }
                                    _ => panic!("Only #[fitsio(colname = \"...\")] is supported"),
                                }
                            },
                            _ => panic!("Only #[fitsio(colname = \"...\")] is supported"),
                        }
                    }
                }
            },
            _ => panic!("Only #[fitsio(colname = \"...\")] is supported"),
        },
        _ => panic!("derive only possible for structs"),
    }

    let expanded = quote!{
        impl FitsRow for #name {
            fn from_table(
                tbl: &::fitsio::hdu::FitsHdu,
                fits_file: &mut ::fitsio::FitsFile, idx: usize) ->
                    ::fitsio::errors::Result<Self> where Self: Sized  {
                let mut out = Self::default();

                #(#tokens)*

                Ok(out)
            }
        }
    };
    expanded.into()
}
<|endoftext|>