WIP: postion indexing

This commit is contained in:
hsjobeki 2023-11-25 17:30:43 +01:00
parent e6e4b81fa1
commit abe7df20dc
No known key found for this signature in database
18 changed files with 668 additions and 111 deletions

View File

@ -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": {

View File

@ -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 @@
];
});
}

View File

@ -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 {

341
pesto/Cargo.lock generated
View File

@ -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"

View File

@ -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]

View File

@ -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";

View File

@ -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<usize>,
}
// 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<FilePosition> = 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<Vec<Option<LambdaDoc>>> = positions_by_file
.iter()
.map(|(file, positions)| {
let index = DocIndex::new(&file);
let docs: Vec<Option<LambdaDoc>> = 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);
// }

52
pesto/src/pasta.rs Normal file
View File

@ -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<bool>,
pub name: Option<String>,
pub position: Option<FilePosition>,
pub args: Option<Vec<String>>,
pub experimental: Option<bool>,
pub arity: Option<usize>,
// I want to potentially overwrite those two
pub content: Option<String>,
#[allow(non_snake_case)]
pub countApplied: Option<usize>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct AttrMeta {
pub position: Option<FilePosition>,
/// I want to add this
pub content: Option<String>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct DocsMeta {
pub lambda: Option<LambdaMeta>,
pub attr: AttrMeta,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct Docs {
pub docs: DocsMeta,
pub path: Vec<String>,
}
pub fn read_pasta(path: &PathBuf) -> Vec<Docs> {
let raw = fs::read_to_string(&path);
match raw {
Ok(content) => {
let data: Vec<Docs> = serde_json::from_str(&content).unwrap();
data
}
Err(e) => {
panic!("error, {}", e)
}
}
}

View File

@ -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<String>,
src: Rc<String>,
ast: SyntaxNode,
pos_idx: HashMap<(usize, usize), TextSize>,
node_idx: HashMap<TextSize, Option<SyntaxNode>>,
}
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<TextSize>;
fn node_at_pos(&self, line: usize, column: usize) -> Option<SyntaxNode>;
fn get_docs(&self, line: usize, column: usize) -> Option<LambdaDoc>;
// fn nodes_at_pos(&self, pos: &Vec<TextSize>) -> HashMap<TextSize, Option<SyntaxNode>>;
// fn init_pos_idx(&self, positions: Vec<(usize, usize)>) -> HashMap<(usize, usize), TextSize>;
fn get_docs_list(&self, idx: Vec<TextSize>) -> HashMap<TextSize, Option<LambdaDoc>>;
}
fn get_src(path: &PathBuf) -> Option<String> {
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<TextSize>) -> HashMap<TextSize, Option<SyntaxNode>> {
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<String> = 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<TextSize> = 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<TextSize> {
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<usize> = 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<SyntaxNode> {
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<TextSize>) -> HashMap<TextSize, Option<LambdaDoc>> {
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<LambdaDoc> {
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<String>,
count_applied: i32,
pub content: Option<String>,
pub count_applied: i32,
}
fn get_parent_lambda(expr: &SyntaxNode) -> (SyntaxNode, i32) {

View File

@ -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))
})
}
}

View File

@ -0,0 +1 @@
Some(LambdaDoc { content: None, count_applied: 0 })

View File

@ -0,0 +1 @@
let inherit (self.asserts) assertMsg assertOneOf; in 1

View File

@ -0,0 +1,4 @@
{
"line": 1,
"column": 27
}

View File

@ -1 +1 @@
Some(LambdaDoc { content: Some("Docs"), count_applied: 1 })
Some(LambdaDoc { content: None, count_applied: 1 })

View File

@ -1 +1 @@
Some(LambdaDoc { content: Some("Docs"), count_applied: 3 })
Some(LambdaDoc { content: None, count_applied: 3 })

View File

@ -1 +1 @@
Some(LambdaDoc { content: Some("Docs"), count_applied: 0 })
Some(LambdaDoc { content: None, count_applied: 0 })

View File

@ -1,4 +1,4 @@
{
"line": 5,
"line": 4,
"column": 9
}

View File

@ -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;
};
};
};
}