From 61342b633122c1dce29f878cf30e8c08c201f65d Mon Sep 17 00:00:00 2001 From: kyu08 <49891479+kyu08@users.noreply.github.com> Date: Tue, 26 Nov 2024 13:11:47 +0900 Subject: [PATCH] parse package.json` --- Cargo.lock | 61 +++++++++++++++++++++++++++++++++ Cargo.toml | 2 ++ Makefile | 4 +++ src/model/js_package_manager.rs | 45 +++++++++++++++++++----- src/model/pnpm.rs | 9 ++--- 5 files changed, 107 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1ea5083c..dce1da8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -80,6 +80,25 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "codespan" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3362992a0d9f1dd7c3d0e89e0ab2bb540b7a95fea8cd798090e758fda2899b5e" +dependencies = [ + "codespan-reporting", +] + +[[package]] +name = "codespan-reporting" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3538270d33cc669650c4b093848450d380def10c331d38c768e34cac80576e6e" +dependencies = [ + "termcolor", + "unicode-width", +] + [[package]] name = "colored" version = "2.1.0" @@ -188,9 +207,11 @@ name = "fzf-make" version = "0.38.0" dependencies = [ "anyhow", + "codespan", "colored", "crossterm", "fuzzy-matcher", + "json-spanned-value", "portable-pty", "pretty_assertions", "ratatui", @@ -290,6 +311,16 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +[[package]] +name = "json-spanned-value" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb343fa4e3b1b22b344937deedac88da995abf139c2232cbeaa436c38380a210" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -578,6 +609,18 @@ dependencies = [ "syn 2.0.48", ] +[[package]] +name = "serde_json" +version = "1.0.133" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + [[package]] name = "serde_spanned" version = "0.6.7" @@ -740,6 +783,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "termios" version = "0.2.2" @@ -939,6 +991,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index d4c8d9f8..6d8d8096 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,3 +24,5 @@ toml = "0.8.19" serde = {version = "1.0.204", features = ["derive"]} simple-home-dir = "0.4.0" pretty_assertions = "1.4.1" +json-spanned-value = "0.2.2" +codespan = "0.11.1" diff --git a/Makefile b/Makefile index 1d0a80d3..d802804c 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,10 @@ export RUST_BACKTRACE=full +.PHONY: run2 +run2: + cd test_data && cargo run + .PHONY: ci ci: # Checks same as CI @make test-ci; \ diff --git a/src/model/js_package_manager.rs b/src/model/js_package_manager.rs index eaa54e2a..4d9d93cd 100644 --- a/src/model/js_package_manager.rs +++ b/src/model/js_package_manager.rs @@ -1,17 +1,21 @@ use super::{command, pnpm, runner}; use crate::file::path_to_content; +use codespan::Files; +use json_spanned_value::{self as jsv, spanned}; use std::path::PathBuf; pub fn get_js_package_manager(current_dir: PathBuf) -> runner::Runner { // TODO: lockfileの種類に応じて各JSパッケージマネージャの初期化コードを呼び出す - get_js_commands(current_dir.clone()); - runner::Runner::PnpmCommand(pnpm::Pnpm::new(current_dir).unwrap()) + let commands = get_js_commands(current_dir.clone()); + runner::Runner::PnpmCommand( + pnpm::Pnpm::new(current_dir.join(JS_PACKAGE_METADATA_FILE_NAME), commands).unwrap(), + ) } const JS_PACKAGE_METADATA_FILE_NAME: &str = "package.json"; +const JS_PACKAGE_METADATA_COMMAND_KEY: &str = "scripts"; fn get_js_commands(_current_dir: PathBuf) -> Vec { - // TODO: lockfileの種類に応じて各JSパッケージマネージャの初期化コードを呼び出す match path_to_content::path_to_content(PathBuf::from(JS_PACKAGE_METADATA_FILE_NAME)) { Ok(c) => parse_package_json(c), Err(_) => vec![], @@ -19,9 +23,34 @@ fn get_js_commands(_current_dir: PathBuf) -> Vec { } fn parse_package_json(content: String) -> Vec { - panic!("{}", content); - // serdeでparseしてもいいが、行番号をとれるのかどうかがわからん。 - // 無理なら自力でparseするしかなさそう。 - // これが使えるかもしれない?https://github.com/MaulingMonkey/json-spanned-value/blob/db682d75b30438866b6e9d02f1187918eb329e1b/examples/demo.rs - vec![] + let mut files = Files::new(); + let file = files.add(JS_PACKAGE_METADATA_FILE_NAME, content.clone()); + let mut result = vec![]; + + // TODO: これだと不正なJSONだったときにコケそうなのでresultをちゃんとハンドリングする + let example: spanned::Object = jsv::from_str(content.as_str()).unwrap(); + for (k, v) in example { + if k.as_str() != JS_PACKAGE_METADATA_COMMAND_KEY { + continue; + } + + // object is the content of "scripts" key + if let Some(object) = v.as_object() { + for (k, _) in object { + let name = k.to_string(); + let line_number = + files.line_index(file, k.start() as u32).number().to_usize() as u32; + + result.push(command::Command { + runner_type: super::runner_type::RunnerType::Pnpm, // TODO: ここは動的に受け取る + name, + file_name: PathBuf::from(JS_PACKAGE_METADATA_FILE_NAME), + line_number, + }); + } + }; + break; + } + + result } diff --git a/src/model/pnpm.rs b/src/model/pnpm.rs index e688292b..230b56a0 100644 --- a/src/model/pnpm.rs +++ b/src/model/pnpm.rs @@ -1,6 +1,5 @@ use super::command; -use anyhow::Result; -use std::{path::PathBuf, process}; +use std::path::PathBuf; #[derive(Clone, Debug, PartialEq)] pub struct Pnpm { @@ -15,10 +14,8 @@ impl Pnpm { format!("pnpm run {}", command.name) } - pub fn new(current_dir: PathBuf) -> Result { - // TODO: ここ実装する - // TODO: package.jsonのパース処理は共通化したほうがよさそう - todo!("implement") + pub fn new(path: PathBuf, commands: Vec) -> Pnpm { + Pnpm { path, commands } } // // I gave up writing tests using temp_dir because it was too difficult (it was necessary to change the implementation to some extent).