Переглянути джерело

Bump clap version (#871)

Signed-off-by: Sean Young <sean@mess.org>
Sean Young 3 роки тому
батько
коміт
ce92a2cffe
5 змінених файлів з 100 додано та 85 видалено
  1. 1 1
      Cargo.toml
  2. 4 4
      src/bin/languageserver/mod.rs
  3. 93 79
      src/bin/solang.rs
  4. 1 0
      src/codegen/mod.rs
  5. 1 1
      src/file_resolver.rs

+ 1 - 1
Cargo.toml

@@ -18,7 +18,7 @@ regex = "1"
 num-bigint = "0.4"
 num-traits = "0.2"
 parity-wasm = "0.45"
-clap = "3.1"
+clap = "3.2"
 hex = "0.4"
 tiny-keccak = { version = "2.0", features = ["keccak"] }
 serde_json = "1.0"

+ 4 - 4
src/bin/languageserver/mod.rs

@@ -53,13 +53,13 @@ impl SolangServer {
 
             let dir = path.parent().unwrap();
 
-            let _ = resolver.add_import_path(PathBuf::from(dir));
+            let _ = resolver.add_import_path(dir);
 
             let mut diags = Vec::new();
 
-            if let Some(paths) = self.matches.values_of_os("IMPORTPATH") {
+            if let Some(paths) = self.matches.get_many::<PathBuf>("IMPORTPATH") {
                 for path in paths {
-                    if let Err(e) = resolver.add_import_path(PathBuf::from(path)) {
+                    if let Err(e) = resolver.add_import_path(path) {
                         diags.push(Diagnostic {
                             message: format!("import path '{}': {}", path.to_string_lossy(), e),
                             severity: Some(DiagnosticSeverity::ERROR),
@@ -69,7 +69,7 @@ impl SolangServer {
                 }
             }
 
-            if let Some(maps) = self.matches.values_of("IMPORTMAP") {
+            if let Some(maps) = self.matches.get_many::<String>("IMPORTMAP") {
                 for p in maps {
                     if let Some((map, path)) = p.split_once('=') {
                         if let Err(e) =

+ 93 - 79
src/bin/solang.rs

@@ -1,18 +1,24 @@
-use clap::{Arg, ArgMatches, Command};
+use clap::{
+    builder::{ArgAction, ValueParser},
+    value_parser, Arg, ArgMatches, Command, ValueSource,
+};
 use itertools::Itertools;
 use num_traits::cast::ToPrimitive;
 use serde::Serialize;
-use std::collections::HashMap;
-use std::ffi::{OsStr, OsString};
-use std::fs::{create_dir_all, File};
-use std::io::prelude::*;
-use std::path::{Path, PathBuf};
-
-use solang::abi;
-use solang::codegen::{codegen, OptimizationLevel, Options};
-use solang::emit::Generate;
-use solang::file_resolver::FileResolver;
-use solang::sema::{ast::Namespace, diagnostics};
+use solang::{
+    abi,
+    codegen::{codegen, OptimizationLevel, Options},
+    emit::Generate,
+    file_resolver::FileResolver,
+    sema::{ast::Namespace, diagnostics},
+};
+use std::{
+    collections::HashMap,
+    ffi::{OsStr, OsString},
+    fs::{create_dir_all, File},
+    io::prelude::*,
+    path::{Path, PathBuf},
+};
 
 mod doc;
 mod languageserver;
@@ -50,7 +56,7 @@ fn main() {
                 .help("Solidity input files")
                 .required(true)
                 .conflicts_with("LANGUAGESERVER")
-                .allow_invalid_utf8(true)
+                .value_parser(ValueParser::os_string())
                 .multiple_values(true),
         )
         .arg(
@@ -58,14 +64,14 @@ fn main() {
                 .help("Emit compiler state at early stage")
                 .long("emit")
                 .takes_value(true)
-                .possible_values(&["ast-dot", "cfg", "llvm-ir", "llvm-bc", "object", "asm"]),
+                .value_parser(["ast-dot", "cfg", "llvm-ir", "llvm-bc", "object", "asm"]),
         )
         .arg(
             Arg::new("OPT")
                 .help("Set llvm optimizer level")
                 .short('O')
                 .takes_value(true)
-                .possible_values(&["none", "less", "default", "aggressive"])
+                .value_parser(["none", "less", "default", "aggressive"])
                 .default_value("default"),
         )
         .arg(
@@ -73,7 +79,7 @@ fn main() {
                 .help("Target to build for")
                 .long("target")
                 .takes_value(true)
-                .possible_values(&["solana", "substrate", "ewasm"])
+                .value_parser(["solana", "substrate", "ewasm"])
                 .required(true),
         )
         .arg(
@@ -81,12 +87,14 @@ fn main() {
                 .help("Address length on Substrate")
                 .long("address-length")
                 .takes_value(true)
+                .value_parser(value_parser!(u64).range(4..1024))
                 .default_value("32"),
         )
         .arg(
             Arg::new("VALUE_LENGTH")
                 .help("Value length on Substrate")
                 .long("value-length")
+                .value_parser(value_parser!(u64).range(4..1024))
                 .takes_value(true)
                 .default_value("16"),
         )
@@ -115,8 +123,8 @@ fn main() {
                 .short('I')
                 .long("importpath")
                 .takes_value(true)
-                .allow_invalid_utf8(true)
-                .multiple_occurrences(true),
+                .value_parser(ValueParser::path_buf())
+                .action(ArgAction::Append),
         )
         .arg(
             Arg::new("IMPORTMAP")
@@ -124,36 +132,41 @@ fn main() {
                 .short('m')
                 .long("importmap")
                 .takes_value(true)
-                .multiple_occurrences(true),
+                .action(ArgAction::Append),
         )
         .arg(
             Arg::new("CONSTANTFOLDING")
                 .help("Disable constant folding codegen optimization")
                 .long("no-constant-folding")
+                .action(ArgAction::SetFalse)
                 .display_order(1),
         )
         .arg(
             Arg::new("STRENGTHREDUCE")
                 .help("Disable strength reduce codegen optimization")
                 .long("no-strength-reduce")
+                .action(ArgAction::SetFalse)
                 .display_order(2),
         )
         .arg(
             Arg::new("DEADSTORAGE")
                 .help("Disable dead storage codegen optimization")
                 .long("no-dead-storage")
+                .action(ArgAction::SetFalse)
                 .display_order(3),
         )
         .arg(
             Arg::new("VECTORTOSLICE")
                 .help("Disable vector to slice codegen optimization")
                 .long("no-vector-to-slice")
+                .action(ArgAction::SetFalse)
                 .display_order(4),
         )
         .arg(
             Arg::new("COMMONSUBEXPRESSIONELIMINATION")
                 .help("Disable common subexpression elimination")
                 .long("no-cse")
+                .action(ArgAction::SetFalse)
                 .display_order(5),
         )
         .arg(
@@ -175,37 +188,23 @@ fn main() {
         )
         .get_matches();
 
-    let address_length = matches.value_of("ADDRESS_LENGTH").unwrap();
+    let address_length = matches.get_one::<u64>("ADDRESS_LENGTH").unwrap();
 
-    let address_length = match address_length.parse() {
-        Ok(len) if (4..1024).contains(&len) => len,
-        _ => {
-            eprintln!("error: address length '{}' is not valid", address_length);
-            std::process::exit(1);
-        }
-    };
+    let value_length = matches.get_one::<u64>("VALUE_LENGTH").unwrap();
 
-    let value_length = matches.value_of("VALUE_LENGTH").unwrap();
-
-    let value_length = match value_length.parse() {
-        Ok(len) if (4..1024).contains(&len) => len,
-        _ => {
-            eprintln!("error: value length '{}' is not valid", value_length);
-            std::process::exit(1);
-        }
-    };
-
-    let target = match matches.value_of("TARGET") {
-        Some("solana") => solang::Target::Solana,
-        Some("substrate") => solang::Target::Substrate {
-            address_length,
-            value_length,
+    let target = match matches.get_one::<String>("TARGET").unwrap().as_str() {
+        "solana" => solang::Target::Solana,
+        "substrate" => solang::Target::Substrate {
+            address_length: *address_length as usize,
+            value_length: *value_length as usize,
         },
-        Some("ewasm") => solang::Target::Ewasm,
+        "ewasm" => solang::Target::Ewasm,
         _ => unreachable!(),
     };
 
-    if !target.is_substrate() && matches.occurrences_of("ADDRESS_LENGTH") > 0 {
+    if !target.is_substrate()
+        && matches.value_source("ADDRESS_LENGTH") == Some(ValueSource::CommandLine)
+    {
         eprintln!(
             "error: address length cannot be modified for target '{}'",
             target
@@ -213,7 +212,9 @@ fn main() {
         std::process::exit(1);
     }
 
-    if !target.is_substrate() && matches.occurrences_of("VALUE_LENGTH") > 0 {
+    if !target.is_substrate()
+        && matches.value_source("VALUE_LENGTH") == Some(ValueSource::CommandLine)
+    {
         eprintln!(
             "error: value length cannot be modified for target '{}'",
             target
@@ -221,11 +222,11 @@ fn main() {
         std::process::exit(1);
     }
 
-    if matches.is_present("LANGUAGESERVER") {
+    if matches.contains_id("LANGUAGESERVER") {
         languageserver::start_server(target, matches);
     }
 
-    let verbose = matches.is_present("VERBOSE");
+    let verbose = matches.contains_id("VERBOSE");
     let mut json = JsonResult {
         errors: Vec::new(),
         target: target.to_string(),
@@ -237,31 +238,31 @@ fn main() {
         eprintln!("info: Solang version {}", env!("GIT_HASH"));
     }
 
-    let math_overflow_check = matches.is_present("MATHOVERFLOW");
+    let math_overflow_check = matches.contains_id("MATHOVERFLOW");
 
     let mut resolver = FileResolver::new();
 
-    for filename in matches.values_of_os("INPUT").unwrap() {
+    for filename in matches.get_many::<OsString>("INPUT").unwrap() {
         if let Ok(path) = PathBuf::from(filename).canonicalize() {
-            let _ = resolver.add_import_path(path.parent().unwrap().to_path_buf());
+            let _ = resolver.add_import_path(path.parent().unwrap());
         }
     }
 
-    if let Err(e) = resolver.add_import_path(PathBuf::from(".")) {
+    if let Err(e) = resolver.add_import_path(&PathBuf::from(".")) {
         eprintln!("error: cannot add current directory to import path: {}", e);
         std::process::exit(1);
     }
 
-    if let Some(paths) = matches.values_of_os("IMPORTPATH") {
+    if let Some(paths) = matches.get_many::<PathBuf>("IMPORTPATH") {
         for path in paths {
-            if let Err(e) = resolver.add_import_path(PathBuf::from(path)) {
+            if let Err(e) = resolver.add_import_path(path) {
                 eprintln!("error: import path '{}': {}", path.to_string_lossy(), e);
                 std::process::exit(1);
             }
         }
     }
 
-    if let Some(maps) = matches.values_of("IMPORTMAP") {
+    if let Some(maps) = matches.get_many::<String>("IMPORTMAP") {
         for p in maps {
             if let Some((map, path)) = p.split_once('=') {
                 if let Err(e) = resolver.add_import_map(OsString::from(map), PathBuf::from(path)) {
@@ -275,12 +276,12 @@ fn main() {
         }
     }
 
-    if matches.is_present("DOC") {
-        let verbose = matches.is_present("VERBOSE");
+    if matches.contains_id("DOC") {
+        let verbose = matches.contains_id("VERBOSE");
         let mut success = true;
         let mut files = Vec::new();
 
-        for filename in matches.values_of_os("INPUT").unwrap() {
+        for filename in matches.get_many::<&OsString>("INPUT").unwrap() {
             let ns = solang::parse_and_resolve(filename, &mut resolver, target);
 
             ns.print_diagnostics(&resolver, verbose);
@@ -297,10 +298,16 @@ fn main() {
 
         if success {
             // generate docs
-            doc::generate_docs(matches.value_of("OUTPUT").unwrap_or("."), &files, verbose);
+            doc::generate_docs(
+                matches
+                    .get_one::<String>("OUTPUT")
+                    .unwrap_or(&String::from(".")),
+                &files,
+                verbose,
+            );
         }
     } else {
-        let opt_level = match matches.value_of("OPT").unwrap() {
+        let opt_level = match matches.get_one::<String>("OPT").unwrap().as_str() {
             "none" => OptimizationLevel::None,
             "less" => OptimizationLevel::Less,
             "default" => OptimizationLevel::Default,
@@ -309,12 +316,14 @@ fn main() {
         };
 
         let opt = Options {
-            dead_storage: !matches.is_present("DEADSTORAGE"),
-            constant_folding: !matches.is_present("CONSTANTFOLDING"),
-            strength_reduce: !matches.is_present("STRENGTHREDUCE"),
-            vector_to_slice: !matches.is_present("VECTORTOSLICE"),
+            dead_storage: *matches.get_one::<bool>("DEADSTORAGE").unwrap(),
+            constant_folding: *matches.get_one::<bool>("CONSTANTFOLDING").unwrap(),
+            strength_reduce: *matches.get_one::<bool>("STRENGTHREDUCE").unwrap(),
+            vector_to_slice: *matches.get_one::<bool>("VECTORTOSLICE").unwrap(),
             math_overflow_check,
-            common_subexpression_elimination: !matches.is_present("COMMONSUBEXPRESSIONELIMINATION"),
+            common_subexpression_elimination: *matches
+                .get_one::<bool>("COMMONSUBEXPRESSIONELIMINATION")
+                .unwrap(),
             opt_level,
         };
 
@@ -322,7 +331,7 @@ fn main() {
 
         let mut errors = false;
 
-        for filename in matches.values_of_os("INPUT").unwrap() {
+        for filename in matches.get_many::<OsString>("INPUT").unwrap() {
             match process_file(filename, &mut resolver, target, &matches, &mut json, &opt) {
                 Ok(ns) => namespaces.push(ns),
                 Err(_) => {
@@ -333,12 +342,12 @@ fn main() {
 
         let namespaces = namespaces.iter().collect::<Vec<_>>();
 
-        if let Some("ast-dot") = matches.value_of("EMIT") {
+        if let Some("ast-dot") = matches.get_one::<String>("EMIT").map(|v| v.as_str()) {
             std::process::exit(0);
         }
 
         if errors {
-            if matches.is_present("STD-JSON") {
+            if matches.contains_id("STD-JSON") {
                 println!("{}", serde_json::to_string(&json).unwrap());
                 std::process::exit(0);
             } else {
@@ -361,7 +370,7 @@ fn main() {
             if !save_intermediates(&binary, &matches) {
                 let bin_filename = output_file(&matches, "bundle", target.file_extension());
 
-                if matches.is_present("VERBOSE") {
+                if matches.contains_id("VERBOSE") {
                     eprintln!(
                         "info: Saving binary {} for contracts: {}",
                         bin_filename.display(),
@@ -386,7 +395,7 @@ fn main() {
                     .code(Generate::Linked)
                     .expect("llvm code emit should work");
 
-                if matches.is_present("STD-JSON") {
+                if matches.contains_id("STD-JSON") {
                     json.program = hex::encode_upper(&code);
                 } else {
                     let mut file = create_file(&bin_filename);
@@ -422,14 +431,19 @@ fn main() {
             }
         }
 
-        if matches.is_present("STD-JSON") {
+        if matches.contains_id("STD-JSON") {
             println!("{}", serde_json::to_string(&json).unwrap());
         }
     }
 }
 
 fn output_file(matches: &ArgMatches, stem: &str, ext: &str) -> PathBuf {
-    Path::new(matches.value_of("OUTPUT").unwrap_or(".")).join(format!("{}.{}", stem, ext))
+    Path::new(
+        matches
+            .get_one::<String>("OUTPUT")
+            .unwrap_or(&String::from(".")),
+    )
+    .join(format!("{}.{}", stem, ext))
 }
 
 fn process_file(
@@ -440,7 +454,7 @@ fn process_file(
     json: &mut JsonResult,
     opt: &Options,
 ) -> Result<Namespace, ()> {
-    let verbose = matches.is_present("VERBOSE");
+    let verbose = matches.contains_id("VERBOSE");
 
     let mut json_contracts = HashMap::new();
 
@@ -450,14 +464,14 @@ fn process_file(
     // codegen all the contracts; some additional errors/warnings will be detected here
     codegen(&mut ns, opt);
 
-    if matches.is_present("STD-JSON") {
+    if matches.contains_id("STD-JSON") {
         let mut out = ns.diagnostics_as_json(resolver);
         json.errors.append(&mut out);
     } else {
         ns.print_diagnostics(resolver, verbose);
     }
 
-    if let Some("ast-dot") = matches.value_of("EMIT") {
+    if let Some("ast-dot") = matches.get_one::<String>("EMIT").map(|v| v.as_str()) {
         let filepath = PathBuf::from(filename);
         let stem = filepath.file_stem().unwrap().to_string_lossy();
         let dot_filename = output_file(matches, &stem, "dot");
@@ -490,13 +504,13 @@ fn process_file(
             continue;
         }
 
-        if let Some("cfg") = matches.value_of("EMIT") {
+        if let Some("cfg") = matches.get_one::<String>("EMIT").map(|v| v.as_str()) {
             println!("{}", resolved_contract.print_cfg(&ns));
             continue;
         }
 
         if target == solang::Target::Solana {
-            if matches.is_present("STD-JSON") {
+            if matches.contains_id("STD-JSON") {
                 json_contracts.insert(
                     resolved_contract.name.to_owned(),
                     JsonContract {
@@ -539,7 +553,7 @@ fn process_file(
             continue;
         }
 
-        if matches.is_present("STD-JSON") {
+        if matches.contains_id("STD-JSON") {
             json_contracts.insert(
                 binary.name.to_owned(),
                 JsonContract {
@@ -588,9 +602,9 @@ fn process_file(
 }
 
 fn save_intermediates(binary: &solang::emit::binary::Binary, matches: &ArgMatches) -> bool {
-    let verbose = matches.is_present("VERBOSE");
+    let verbose = matches.contains_id("VERBOSE");
 
-    match matches.value_of("EMIT") {
+    match matches.get_one::<String>("EMIT").map(|v| v.as_str()) {
         Some("llvm-ir") => {
             if let Some(runtime) = &binary.runtime {
                 // In Ethereum, an ewasm contract has two parts, deployer and runtime. The deployer code returns the runtime wasm

+ 1 - 0
src/codegen/mod.rs

@@ -73,6 +73,7 @@ impl From<inkwell::OptimizationLevel> for OptimizationLevel {
     }
 }
 
+#[derive(Debug)]
 pub struct Options {
     pub dead_storage: bool,
     pub constant_folding: bool,

+ 1 - 1
src/file_resolver.rs

@@ -48,7 +48,7 @@ impl FileResolver {
     }
 
     /// Add import path
-    pub fn add_import_path(&mut self, path: PathBuf) -> io::Result<()> {
+    pub fn add_import_path(&mut self, path: &Path) -> io::Result<()> {
         self.import_paths.push((None, path.canonicalize()?));
         Ok(())
     }