diff --git a/.vscode/settings.json b/.vscode/settings.json index 6dd64cb..25eabfe 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -6,5 +6,8 @@ "[typescript]": { "editor.formatOnSave": true, "editor.defaultFormatter": "biomejs.biome" - } + }, + "cSpell.words": [ + "indexmap" + ] } \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 8d5146f..8db82f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -166,6 +166,12 @@ dependencies = [ "windows", ] +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "erg_common" version = "0.6.53-nightly.2" @@ -260,6 +266,12 @@ dependencies = [ "ahash", ] +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + [[package]] name = "heck" version = "0.5.0" @@ -405,6 +417,16 @@ dependencies = [ "icu_properties", ] +[[package]] +name = "indexmap" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +dependencies = [ + "equivalent", + "hashbrown 0.15.2", +] + [[package]] name = "is-macro" version = "0.3.7" @@ -502,7 +524,7 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ea0ed76adf7defc1a92240b5c36d5368cfe9251640dcce5bd2d0b7c1fd87aeb" dependencies = [ - "hashbrown", + "hashbrown 0.14.5", "itertools", "libm", "ryu", @@ -733,6 +755,7 @@ dependencies = [ "erg_common", "erg_compiler", "glob", + "indexmap", "pylyzer_core", ] diff --git a/Cargo.toml b/Cargo.toml index 4b2079a..ae4d007 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -54,6 +54,7 @@ pylyzer_core = { version = "0.0.81", path = "./crates/pylyzer_core" } erg_common = { workspace = true } els = { workspace = true } glob = "0.3.2" +indexmap = "2.7.1" [dev-dependencies] erg_compiler = { workspace = true } diff --git a/src/config.rs b/src/config.rs index 0f19bc6..e0e85ce 100644 --- a/src/config.rs +++ b/src/config.rs @@ -6,6 +6,7 @@ use erg_common::config::{ErgConfig, ErgMode}; use erg_common::io::Input; use erg_common::pathutil::project_entry_file_of; use erg_common::switch_lang; +use indexmap::IndexSet; use crate::copy::clear_cache; @@ -49,7 +50,7 @@ OPTIONS --clear-cache キャッシュをクリア --code/-c cmd 文字列をプログラムに渡す --dump-decl 型宣言ファイルを出力 - --disable 指定した機能を無効化", + --disable feat 指定した機能を無効化", "simplified_chinese" => "\ @@ -67,7 +68,7 @@ OPTIONS --clear-cache 清除缓存 --code/-c cmd 作为字符串传入程序 --dump-decl 输出类型声明文件 - --disable 禁用指定功能", + --disable feat 禁用指定功能", "traditional_chinese" => "\ @@ -85,7 +86,7 @@ OPTIONS --clear-cache 清除快取 --code/-c cmd 作為字串傳入程式 --dump-decl 輸出類型宣告檔案 - --disable 禁用指定功能", + --disable feat 禁用指定功能", "english" => "\ @@ -103,7 +104,7 @@ OPTIONS --clear-cache clear cache --code/-c cmd program passed in as string --dump-decl output type declaration file - --disable disable specified features", + --disable feat disable specified features", ) } @@ -213,21 +214,53 @@ For more information try `pylyzer --help`" cfg } -pub(crate) fn files_to_be_checked() -> Vec { - let file_or_patterns = env::args() - .skip(1) - .rev() - .take_while(|arg| !arg.starts_with("-")); - let mut files = vec![]; +pub(crate) fn files_to_be_checked() -> IndexSet> { + let mut file_or_patterns = vec![]; + let mut args = env::args().skip(1); + while let Some(arg) = &args.next() { + match arg.as_str() { + "--" => { + // Discard runtime args + break; + } + "--code" | "-c" | "--disable" | "--verbose" => { + // Skip options + let _ = &args.next(); + continue; + } + file_or_pattern if file_or_pattern.starts_with("-") => { + // Skip flags + continue; + } + + file_or_pattern => file_or_patterns.push(file_or_pattern.to_owned()), + } + } + let mut files = IndexSet::new(); for file_or_pattern in file_or_patterns { if PathBuf::from(&file_or_pattern).is_file() { - files.push(PathBuf::from(&file_or_pattern)); + files.insert(Ok(PathBuf::from(&file_or_pattern))); } else { - for entry in glob::glob(&file_or_pattern).expect("Failed to read glob pattern") { - match entry { - Err(e) => eprintln!("err: {e}"), - Ok(path) if path.is_file() => files.push(path), - _ => {} + let entries = glob::glob(&file_or_pattern); + match entries { + Err(_) => { + files.insert(Err(file_or_pattern)); + continue; + } + Ok(entries) => { + let mut entries = entries.into_iter().peekable(); + if entries.peek().is_none() { + files.insert(Err(file_or_pattern)); + } + for entry in entries { + match entry { + Err(e) => eprintln!("err: {e}"), + Ok(path) if path.is_file() => { + files.insert(Ok(path)); + } + _ => {} + } + } } } } diff --git a/src/main.rs b/src/main.rs index 2cc7515..fb7ddd9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,6 +4,8 @@ mod copy; use els::Server; use erg_common::config::ErgMode; use erg_common::spawn::exec_new_thread; +use erg_common::style::colors::RED; +use erg_common::style::RESET; use pylyzer_core::{PythonAnalyzer, SimplePythonParser}; use crate::config::files_to_be_checked; @@ -23,11 +25,21 @@ fn run() { code = analyzer.run(); } else { for path in files { - let cfg = cfg.inherit(path); - let mut analyzer = PythonAnalyzer::new(cfg); - let c = analyzer.run(); - if c != 0 { - code = 1; + match path { + Err(invalid_file_or_pattern) => { + if code == 0 { + code = 1; + } + println!("{RED}Invalid file or pattern{RESET}: {invalid_file_or_pattern}"); + } + Ok(path) => { + let cfg = cfg.inherit(path); + let mut analyzer = PythonAnalyzer::new(cfg); + let c = analyzer.run(); + if c != 0 { + code = 1; + } + } } } }