diff --git a/flake.lock b/flake.lock index 733a040..72b8c02 100644 --- a/flake.lock +++ b/flake.lock @@ -187,17 +187,18 @@ }, "nixpkgs-master": { "locked": { - "lastModified": 1700733543, - "narHash": "sha256-yQysLoGKq78l2+zkof5NpBb/JTWIsmEfR3g7bcWHbLc=", - "owner": "NixOS", + "lastModified": 1699884649, + "narHash": "sha256-HF1iNm+SqZJtUgoi57Mk21jDsgeybIcopDwaNFLqexc=", + "owner": "hsjobeki", "repo": "nixpkgs", - "rev": "fa094c6dd42f8e62334a146e463e3e4684d405c0", + "rev": "047dce513a20231fde99b1e9b950ab6b562b27b0", "type": "github" }, "original": { - "id": "nixpkgs", - "ref": "master", - "type": "indirect" + "owner": "hsjobeki", + "ref": "migrate-doc-comments", + "repo": "nixpkgs", + "type": "github" } }, "nixpkgs-regression": { diff --git a/flake.nix b/flake.nix index 34ae2d3..58de142 100644 --- a/flake.nix +++ b/flake.nix @@ -2,7 +2,7 @@ description = "Noogle.dev | Discover the nix api surface"; inputs = { nixpkgs.url = "nixpkgs/nixos-unstable"; - nixpkgs-master.url = "nixpkgs/master"; + nixpkgs-master.url = "github:hsjobeki/nixpkgs/?ref=migrate-doc-comments"; # A custom nix verison, to introspect lambda values. nix.url = "github:hsjobeki/nix/?ref=feat/positions"; @@ -36,3 +36,4 @@ ]; }); } + diff --git a/pasta/src/tools.nix b/pasta/src/tools.nix index 781dfe1..bba8aae 100644 --- a/pasta/src/tools.nix +++ b/pasta/src/tools.nix @@ -4,9 +4,27 @@ let dropBack = l: lib.reverseList (lib.drop 1 (lib.reverseList l)); + /* * + # Returns + + We use the rust notation, since a pasta struct is needed for pesto anyways. + + struct { + lambda: { + position: Position + ... + } + attr: { + position: Position + } + } + */ getDocs = parent: name: let - lambda = builtins.lambdaMeta parent.${name}; + lambda = if lib.isFunction parent.${name} then + builtins.lambdaMeta parent.${name} + else + null; attr = { position = builtins.unsafeGetAttrPos name parent; }; in { inherit lambda attr; }; @@ -16,7 +34,10 @@ let collectFns = set: { initialPath ? [ ], limit ? null, }: let - filterFns = builtins.filter (item: item.type == "lambda"); + filterFns = builtins.filter (item: + item.docs != null + # item.type == "lambda" + ); getFnDocs = map (fn: { path = initialPath ++ fn.path; inherit (fn) docs; @@ -52,7 +73,7 @@ let path = lib.unique (item.key ++ [ name ]); in if lib.isDerivation nextVal || name == "__functor" || (limit != null && item.depth >= limit) then - # skipping some values by + # skipping all more nested values by # returning the previous item item else { diff --git a/pesto/Cargo.lock b/pesto/Cargo.lock index 7695f18..15b21fa 100644 --- a/pesto/Cargo.lock +++ b/pesto/Cargo.lock @@ -11,6 +11,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anstream" version = "0.6.4" @@ -65,6 +80,46 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +[[package]] +name = "base64" +version = "0.21.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" + +[[package]] +name = "bumpalo" +version = "3.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" + +[[package]] +name = "cc" +version = "1.0.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "num-traits", + "serde", + "windows-targets", +] + [[package]] name = "clap" version = "4.4.8" @@ -111,18 +166,75 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + [[package]] name = "countme" version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7704b5fdd17b18ae31c4c1da5a2e0305a2bf17b5249300a9ee9ed7b72114c636" +[[package]] +name = "darling" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "deranged" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f32d04922c60427da6f9fef14d042d9edddef64cb9d4ce0d64d0685fbeb1fd3" +dependencies = [ + "powerfmt", + "serde", +] + [[package]] name = "dissimilar" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86e3bdc80eee6e16b2b6b0f87fbc98c04bee3455e35174c0de1a125d0688c632" +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "expect-test" version = "1.4.1" @@ -133,24 +245,114 @@ dependencies = [ "once_cell", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f93e7192158dbcda357bdec5fb5788eebf8bbac027f3f33e719d29135ae84156" + [[package]] name = "heck" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "iana-time-zone" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", + "serde", +] + +[[package]] +name = "indexmap" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +dependencies = [ + "equivalent", + "hashbrown 0.14.2", + "serde", +] + [[package]] name = "itoa" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +[[package]] +name = "js-sys" +version = "0.3.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" + +[[package]] +name = "log" +version = "0.4.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" + [[package]] name = "memchr" version = "2.6.4" @@ -166,6 +368,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num-traits" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.18.0" @@ -183,10 +394,17 @@ dependencies = [ "rowan", "serde", "serde_json", + "serde_with", "textwrap", "walkdir", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "proc-macro2" version = "1.0.69" @@ -250,7 +468,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "906057e449592587bf6724f00155bf82a6752c868d78a8fb3aa41f4e6357cfe8" dependencies = [ "countme", - "hashbrown", + "hashbrown 0.12.3", "memoffset", "rustc-hash", "text-size", @@ -308,6 +526,35 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_with" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23" +dependencies = [ + "base64", + "chrono", + "hex", + "indexmap 1.9.3", + "indexmap 2.1.0", + "serde", + "serde_json", + "serde_with_macros", + "time", +] + +[[package]] +name = "serde_with_macros" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "smawk" version = "0.3.2" @@ -348,6 +595,35 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "time" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a34ab300f2dee6e562c10a046fc05e358b29f9bf92277f30c3c8d82275f6f5" +dependencies = [ + "deranged", + "itoa", + "powerfmt", + "serde", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" + +[[package]] +name = "time-macros" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" +dependencies = [ + "time-core", +] + [[package]] name = "unicode-ident" version = "1.0.12" @@ -382,6 +658,60 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "wasm-bindgen" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" + [[package]] name = "winapi" version = "0.3.9" @@ -413,6 +743,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.48.0" diff --git a/pesto/Cargo.toml b/pesto/Cargo.toml index 53b97a0..ba519a9 100644 --- a/pesto/Cargo.toml +++ b/pesto/Cargo.toml @@ -17,6 +17,7 @@ clap = { version = "4.4.4", features = ["derive"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" expect-test = "1.4.0" +serde_with = "3.4.0" # [dev-dependencies] diff --git a/pesto/flake-module.nix b/pesto/flake-module.nix index 4a8c593..3f048ac 100644 --- a/pesto/flake-module.nix +++ b/pesto/flake-module.nix @@ -13,10 +13,10 @@ pesto = craneLib.buildPackage commonArgs; checks = { inherit pesto; - pestoClippy = craneLib.cargoClippy (commonArgs // { + pesto-clippy = craneLib.cargoClippy (commonArgs // { cargoClippyExtraArgs = "--all-targets -- --deny warnings"; }); - pestoFmt = craneLib.cargoFmt { inherit src; }; + pesto-fmt = craneLib.cargoFmt { inherit src; }; pesto-nextest = craneLib.cargoNextest (commonArgs // { partitions = 1; partitionType = "count"; diff --git a/pesto/src/main.rs b/pesto/src/main.rs index ec30425..a1a2985 100644 --- a/pesto/src/main.rs +++ b/pesto/src/main.rs @@ -1,12 +1,15 @@ mod comment; +mod pasta; mod position; mod tests; use clap::Parser; +use std::{fs::File, io::Write, path::PathBuf, println}; -use std::{collections::HashMap, fs, path::PathBuf, println}; - -use crate::position::{DocComment, DocIndex, FilePosition, LambdaDoc, TextPosition}; +use crate::{ + pasta::read_pasta, + position::{DocComment, DocIndex}, +}; #[derive(Debug, Parser)] #[command(author, version, about)] @@ -28,47 +31,91 @@ struct Options { column: Option, } +// fn populate_map<'a>( +// mut positions_by_file: HashMap<&'a PathBuf, Vec<&'a Docs>>, +// position: &'a FilePosition, +// docs: &'a Docs, +// ) -> HashMap<&'a PathBuf, Vec<&'a Docs>> { +// match positions_by_file.get_mut(&position.file) { +// Some(list) => { +// list.push(docs); +// } +// None => { +// positions_by_file.insert(&position.file, vec![docs]); +// } +// }; +// positions_by_file +// } + pub fn main() { // let mut output = io::stdout(); let opts = Options::parse(); if let Some(nix_file) = opts.file { - let pos = DocIndex::new(&nix_file); + let pos = DocIndex::new(&nix_file, vec![(opts.line.unwrap(), opts.column.unwrap())]); if let Some(docs) = pos.get_docs(opts.line.unwrap(), opts.column.unwrap()) { println!("{:?}", docs); } } if let Some(pos_file) = opts.pos_file { - let raw_pos = fs::read_to_string(&pos_file).unwrap(); - let positions: Vec = serde_json::from_str(&raw_pos).unwrap(); - // TODO: group positions by file, to avoid opening the same file again. - let mut positions_by_file: HashMap<&PathBuf, Vec<&FilePosition>> = HashMap::new(); - for position in positions.iter() { - match positions_by_file.get_mut(&position.file) { - Some(list) => list.push(position), - None => { - // - positions_by_file.insert(&position.file, vec![position]); - } - }; - } - for (f, p) in positions_by_file.iter() { - println!("{:?} {:?}", f, p); - } - let res: Vec>> = positions_by_file - .iter() - .map(|(file, positions)| { - let index = DocIndex::new(&file); - let docs: Vec> = positions - .iter() - .map(move |pos| index.get_docs(pos.line, pos.column)) - .collect(); - docs - }) - .collect(); + let mut data = read_pasta(&pos_file); + println!("data length: {}", data.len()); - println!("{:?}", res); + // Iter mutable, to change the doc "content" field + for (idx, item) in data.iter_mut().enumerate() { + println!("{}", idx); + if let Some(position) = &item.docs.attr.position { + let index = DocIndex::new(&position.file, vec![(position.line, position.column)]); + let doc_comment = index.get_docs(position.line, position.column); + if let Some(meta) = doc_comment { + item.docs.attr.content = meta.content; + } + } + if let Some(lambda) = &mut item.docs.lambda { + if let Some(position) = &lambda.position { + let index = + DocIndex::new(&position.file, vec![(position.line, position.column)]); + let doc_comment = index.get_docs(position.line, position.column); + if let Some(meta) = doc_comment { + lambda.content = meta.content; + lambda.countApplied = Some(usize::try_from(meta.count_applied).unwrap()); + } + } + } + } + + println!("{:?}", data.get(0)); + let mut out_file = File::create("out.json").unwrap(); + out_file.write(serde_json::to_string(&data).unwrap().as_bytes()); + // Group positions by file, to avoid opening the same file again. + + // let mut positions_by_file: HashMap<&PathBuf, Vec<&Docs>> = HashMap::new(); + // for item in &data { + // if let Some(ref position) = item.docs.attr.position { + // positions_by_file = populate_map(positions_by_file, &position, item); + // } + // if let Some(ref position) = item.docs.lambda.position { + // positions_by_file = populate_map(positions_by_file, &position, item); + // } + // } + + // if let Some((f, _p)) = positions_by_file.get_key_value(&PathBuf::from( + // "/nix/store/9g6kcr0ny3k369ydl36c8mz2gf69432x-source/lib/strings-with-deps.nix", + // )) { + // println!("{:?} {:?}", f, _p); + // } + + // positions_by_file.iter().for_each(|(file, positions)| { + // let index = DocIndex::new(&file); + // positions.iter().for_each(|reason: &LookupReason| { + // let docs = index.get_docs(reason.position.line, reason.position.column); + // println!("{:?}", docs); + // data.iter() + // .map(|item| if item.path == reason.id { item } else { item }); + // }) + // }); + // println!("{:?}", res); // if let Some(docs) = pos.get_docs() { // println!("{:?}", docs); // } diff --git a/pesto/src/pasta.rs b/pesto/src/pasta.rs new file mode 100644 index 0000000..092931f --- /dev/null +++ b/pesto/src/pasta.rs @@ -0,0 +1,52 @@ +use std::{fs, path::PathBuf}; + +use serde::{Deserialize, Serialize}; + +use crate::position::FilePosition; + +#[serde_with::skip_serializing_none] +#[derive(Debug, Serialize, Deserialize)] +pub struct LambdaMeta { + #[allow(non_snake_case)] + pub isPrimop: Option, + pub name: Option, + pub position: Option, + pub args: Option>, + pub experimental: Option, + pub arity: Option, + + // I want to potentially overwrite those two + pub content: Option, + #[allow(non_snake_case)] + pub countApplied: Option, +} +#[derive(Debug, Serialize, Deserialize)] +pub struct AttrMeta { + pub position: Option, + /// I want to add this + pub content: Option, +} +#[derive(Debug, Serialize, Deserialize)] +pub struct DocsMeta { + pub lambda: Option, + pub attr: AttrMeta, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct Docs { + pub docs: DocsMeta, + pub path: Vec, +} + +pub fn read_pasta(path: &PathBuf) -> Vec { + let raw = fs::read_to_string(&path); + match raw { + Ok(content) => { + let data: Vec = serde_json::from_str(&content).unwrap(); + data + } + Err(e) => { + panic!("error, {}", e) + } + } +} diff --git a/pesto/src/position.rs b/pesto/src/position.rs index 0cb4d51..260c065 100644 --- a/pesto/src/position.rs +++ b/pesto/src/position.rs @@ -4,6 +4,10 @@ use rnix::{match_ast, SyntaxNode}; use rowan::TextSize; use rowan::{ast::AstNode, WalkEvent}; use serde::{Deserialize, Serialize}; +use std::collections::HashMap; +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::rc::Rc; use std::{fs, path::PathBuf, println}; @@ -25,103 +29,183 @@ pub struct FilePosition { #[derive(Debug)] pub struct DocIndex<'a> { file: &'a PathBuf, - src: Option, + src: Rc, + ast: SyntaxNode, + pos_idx: HashMap<(usize, usize), TextSize>, + node_idx: HashMap>, } pub trait DocComment<'a> { - fn new(file: &'a PathBuf) -> Self; + fn new(file: &'a PathBuf, positions: Vec<(usize, usize)>) -> Self; + // Single item methods fn get_pos_idx(&self, line: usize, column: usize) -> Option; fn node_at_pos(&self, line: usize, column: usize) -> Option; fn get_docs(&self, line: usize, column: usize) -> Option; + + // fn nodes_at_pos(&self, pos: &Vec) -> HashMap>; + // fn init_pos_idx(&self, positions: Vec<(usize, usize)>) -> HashMap<(usize, usize), TextSize>; + fn get_docs_list(&self, idx: Vec) -> HashMap>; } fn get_src(path: &PathBuf) -> Option { - println!("reading {:?}", path); - if let Ok(src) = fs::read_to_string(&path) { + if let Ok(src) = fs::read_to_string(path) { return Some(src); } panic!("could not read file"); } +/// Initializes a HashMap for lookup operation between L:C and absolute position. +fn init_pos_idx( + path: &PathBuf, + positions: Vec<(usize, usize)>, +) -> HashMap<(usize, usize), TextSize> { + let file = File::open(path).unwrap(); + let reader = BufReader::new(file); + + let mut res = HashMap::new(); + + let mut curr_line = 0; + let mut curr_position = 0; + for line in reader.lines() { + positions.iter().for_each(|(line, col)| { + if *line == curr_line + 1 { + res.insert( + (*line, *col), + TextSize::from(u32::try_from(curr_position + col - 1).unwrap()), + ); + } + }); + + curr_line += 1; + curr_position += line.unwrap().chars().count() + 1; + } + res +} + +// Take a list of lookup operations +// Since iterating over the AST can be expensive +fn init_node_idx(ast: &SyntaxNode, pos: &Vec) -> HashMap> { + let mut res = HashMap::new(); + for ev in ast.preorder() { + match ev { + WalkEvent::Enter(node) => { + if let Some(pos_key) = pos + .iter() + .find(|position| node.text_range().start() == **position) + { + if res.get(pos_key).is_none() { + res.insert(*pos_key, Some(node)); + } + } + } + WalkEvent::Leave(node) => { + if let Some(pos_key) = pos + .iter() + .find(|position| node.text_range().end() == **position) + { + if res.get(pos_key).is_none() { + res.insert(*pos_key, Some(node)); + } + } + } + } + } + res +} + impl<'a> DocComment<'a> for DocIndex<'a> { - fn new(file: &'a PathBuf) -> Self { - Self { - file: file, - src: get_src(file), + fn new(file: &'a PathBuf, positions: Vec<(usize, usize)>) -> Self { + if let Some(src) = get_src(file) { + let rc: Rc = Rc::new(src); + let ast = rnix::Root::parse(Rc::clone(&rc).as_str()).syntax(); + let pos_idx = init_pos_idx(&file, positions); + let ast_positions: Vec = pos_idx.values().map(|t| *t).collect(); + let node_idx = init_node_idx(&ast, &ast_positions); + + return Self { + file, + ast, + src: rc, + pos_idx, + node_idx, + }; + } else { + panic!("cannot open file"); } } fn get_pos_idx(&self, l: usize, c: usize) -> Option { - if let Some(src) = &self.src { - let mut result: usize = 0; - let mut pos = None; - for (line, content) in src.lines().enumerate() { - if line + 1 == l { - for (col, _) in content.chars().enumerate() { - if col + 1 == c { - pos = Some(result + col); - break; - } - } - } - if pos.is_some() { - break; - } - result += content.len() + 1; + let src = &self.src; + let mut result: usize = 0; + let mut pos: Option = None; + for (line, content) in src.lines().enumerate() { + if line + 1 == l { + pos = Some(result + c - 1); + break; } - - return pos.map(|pos| TextSize::from(u32::try_from(pos).unwrap())); + result += content.len() + 1; } - // Could not read source - None + return pos.map(|pos| TextSize::from(u32::try_from(pos).unwrap())); } fn node_at_pos(&self, line: usize, column: usize) -> Option { - let src = &self.src; let pos_idx = &self.get_pos_idx(line, column).unwrap(); - if let Some(src) = src { - let ast = rnix::Root::parse(&src).ok().expect("failed to parse input"); - - let mut expr = None; - for ev in ast.syntax().preorder() { - match ev { - WalkEvent::Enter(node) => { - if node.text_range().start() == *pos_idx { - expr = Some(node); - break; - } + let mut expr = None; + for ev in self.ast.preorder() { + match ev { + WalkEvent::Enter(node) => { + if node.text_range().start() == *pos_idx { + expr = Some(node); + break; + } + } + WalkEvent::Leave(node) => { + if node.text_range().end() == *pos_idx { + expr = Some(node); + break; } - _ => {} } } - return expr; } - None + return expr; + } + + fn get_docs_list(&self, positions: Vec) -> HashMap> { + let mut res = HashMap::new(); + let ast_map = init_node_idx(&self.ast, &positions); + positions.iter().for_each(|position| { + if let Some(Some(expr)) = ast_map.get(position) { + let (outer_lambda, count_applied) = get_parent_lambda(&expr); + let doc = LambdaDoc { + content: get_expr_docs(&outer_lambda), + count_applied, + }; + res.insert(*position, Some(doc)); + } + }); + + res } fn get_docs(&self, line: usize, column: usize) -> Option { - let expr = self.node_at_pos(line, column); - println!("L{}:C{}, {:?}", line, column, expr); - expr.map(|e| { + let idx = self.pos_idx.get(&(line, column)).unwrap(); + let expr = self.node_idx.get(idx); + println!("L{}:C{}, expr: {:?}", line, column, expr); + if let Some(Some(e)) = expr { let (outer_lambda, count_applied) = get_parent_lambda(&e); - LambdaDoc { - pos: FilePosition { - file: self.file.clone(), - line, - column, - }, + return Some(LambdaDoc { content: get_expr_docs(&outer_lambda), count_applied, - } - }) + }); + } + return None; } } #[derive(Debug)] pub struct LambdaDoc { - pos: FilePosition, - content: Option, - count_applied: i32, + pub content: Option, + pub count_applied: i32, } fn get_parent_lambda(expr: &SyntaxNode) -> (SyntaxNode, i32) { diff --git a/pesto/src/tests.rs b/pesto/src/tests.rs index 0beb1ca..ceed995 100644 --- a/pesto/src/tests.rs +++ b/pesto/src/tests.rs @@ -1,7 +1,7 @@ #[cfg(test)] mod tests { - use std::{ffi::OsStr, format, fs, path::PathBuf}; + use std::{ffi::OsStr, format, fs, path::PathBuf, println}; use crate::position::{DocComment, DocIndex, TextPosition}; @@ -40,9 +40,11 @@ mod tests { #[test] fn test_main() { dir_tests("atom", |path, (line, column)| { - let pos = DocIndex::new(path); + let pos = DocIndex::new(path, vec![(line, column)]); - format!("{:?}", pos.get_docs(line,column)) + // let idx = pos.get_pos_idxs_buffer(vec![(line, column), (1, 1)]); + // println!("{:?}", idx); + format!("{:?}", pos.get_docs(line, column)) }) } } diff --git a/pesto/test_data/atom/inherit.expect b/pesto/test_data/atom/inherit.expect new file mode 100644 index 0000000..b0eb192 --- /dev/null +++ b/pesto/test_data/atom/inherit.expect @@ -0,0 +1 @@ +Some(LambdaDoc { content: None, count_applied: 0 }) \ No newline at end of file diff --git a/pesto/test_data/atom/inherit.nix b/pesto/test_data/atom/inherit.nix new file mode 100644 index 0000000..e396851 --- /dev/null +++ b/pesto/test_data/atom/inherit.nix @@ -0,0 +1 @@ +let inherit (self.asserts) assertMsg assertOneOf; in 1 diff --git a/pesto/test_data/atom/inherit.pos b/pesto/test_data/atom/inherit.pos new file mode 100644 index 0000000..03606e4 --- /dev/null +++ b/pesto/test_data/atom/inherit.pos @@ -0,0 +1,4 @@ +{ + "line": 1, + "column": 27 +} diff --git a/pesto/test_data/atom/partially_applied_1_lambda.expect b/pesto/test_data/atom/partially_applied_1_lambda.expect index dcbcdd0..3014a72 100644 --- a/pesto/test_data/atom/partially_applied_1_lambda.expect +++ b/pesto/test_data/atom/partially_applied_1_lambda.expect @@ -1 +1 @@ -Some(LambdaDoc { content: Some("Docs"), count_applied: 1 }) \ No newline at end of file +Some(LambdaDoc { content: None, count_applied: 1 }) \ No newline at end of file diff --git a/pesto/test_data/atom/partially_applied_2_lambda.expect b/pesto/test_data/atom/partially_applied_2_lambda.expect index 795dab8..8d60c69 100644 --- a/pesto/test_data/atom/partially_applied_2_lambda.expect +++ b/pesto/test_data/atom/partially_applied_2_lambda.expect @@ -1 +1 @@ -Some(LambdaDoc { content: Some("Docs"), count_applied: 3 }) \ No newline at end of file +Some(LambdaDoc { content: None, count_applied: 3 }) \ No newline at end of file diff --git a/pesto/test_data/atom/trivial_lambda.expect b/pesto/test_data/atom/trivial_lambda.expect index 629eaa6..b0eb192 100644 --- a/pesto/test_data/atom/trivial_lambda.expect +++ b/pesto/test_data/atom/trivial_lambda.expect @@ -1 +1 @@ -Some(LambdaDoc { content: Some("Docs"), count_applied: 0 }) \ No newline at end of file +Some(LambdaDoc { content: None, count_applied: 0 }) \ No newline at end of file diff --git a/pesto/test_data/atom/trivial_lambda.pos b/pesto/test_data/atom/trivial_lambda.pos index 4ddb66a..793f168 100644 --- a/pesto/test_data/atom/trivial_lambda.pos +++ b/pesto/test_data/atom/trivial_lambda.pos @@ -1,4 +1,4 @@ { - "line": 5, + "line": 4, "column": 9 } diff --git a/preCommit.nix b/preCommit.nix index 46c4996..83d8ecd 100644 --- a/preCommit.nix +++ b/preCommit.nix @@ -8,7 +8,10 @@ # markdownlint.enable = true; }; excludes = [ "indexer/test" ".github" "scripts/data" ]; - settings = { statix.ignore = [ "indexer/test" ]; }; + settings = { + statix.ignore = [ "indexer/test" ]; + nixfmt.width = 80; + }; }; }; }