-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Commit
- Loading branch information
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
[package] | ||
name = "turbo-static" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] | ||
bincode = "1.3.3" | ||
clap = { workspace = true, features = ["derive"] } | ||
crossbeam-channel = "0.5.12" | ||
fjall = { version = "0.6.3", features = ["bloom"] } | ||
ignore = "0.4.22" | ||
itertools.workspace = true | ||
lsp-server = "0.7.6" | ||
lsp-types = "0.95.1" | ||
proc-macro2 = { workspace = true, features = ["span-locations"] } | ||
serde_json.workspace = true | ||
serde_path_to_error = "0.1.16" | ||
syn = { version = "2", features = ["parsing", "full", "visit", "extra-traits"] } | ||
tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } | ||
tracing.workspace = true | ||
walkdir = "2.5.0" | ||
|
||
[lints] | ||
workspace = true |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
version: "3" | ||
|
||
services: | ||
memgraph: | ||
image: memgraph/memgraph-mage:latest | ||
container_name: memgraph-1 | ||
pull_policy: always | ||
ports: | ||
- "7687:7687" | ||
- "7444:7444" | ||
command: ["--log-level=TRACE"] | ||
|
||
lab: | ||
image: memgraph/lab:latest | ||
container_name: memgraph-2 | ||
pull_policy: always | ||
ports: | ||
- "3000:3000" | ||
depends_on: | ||
- memgraph | ||
environment: | ||
- QUICK_CONNECT_MG_HOST=memgraph | ||
- QUICK_CONNECT_MG_PORT=7687 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
{ | ||
"path": "/Users/arlyon/Programming/nextpack/turbo/crates/turbo-static/file/partitions/links", | ||
"block_size": 4096, | ||
"level_count": 7, | ||
"level_ratio": 8, | ||
"type": "Standard", | ||
"compression": "Lz4" | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
[ | ||
[], | ||
[], | ||
[], | ||
[], | ||
[], | ||
[], | ||
[] | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
# Turbo Static | ||
|
||
Leverages rust-analyzer to build a complete view into the static dependency graph for | ||
your turbo tasks project. | ||
|
||
## How it works | ||
|
||
- find all occurences of #[turbo_tasks::function] across all the packages you want to query | ||
- for each of the tasks we find, query rust analyzer to see which tasks call them | ||
- apply some very basis control flow analysis to determine whether the call is make 1 time, 0/1 times, or 0+ times, | ||
corresponding to direct calls, conditionals, or for loops. nested conditionals collapse | ||
|
||
## Stretch goals | ||
|
||
- evaluate where Vcs end up to track data flow through the app also | ||
- a few different visualization formats | ||
- dot | ||
- neoj4 / graph dbs |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,165 @@ | ||
use std::{path::PathBuf, process}; | ||
|
||
use crossbeam_channel::bounded; | ||
use lsp_server::{IoThreads, Message}; | ||
Check warning on line 4 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing benchmarks on linux / Test
Check warning on line 4 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing benchmarks on linux / Test
Check warning on line 4 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on ubuntu
Check warning on line 4 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on ubuntu
Check warning on line 4 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing benchmarks on macos / Test
Check warning on line 4 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing benchmarks on macos / Test
Check warning on line 4 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on macos
Check warning on line 4 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on macos
Check warning on line 4 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on windows
|
||
|
||
/// An LSP client for Rust Analyzer (RA) that launches it as a subprocess. | ||
pub struct RAClient { | ||
/// Handle to the client | ||
handle: process::Child, | ||
sender: Option<crossbeam_channel::Sender<Message>>, | ||
receiver: Option<crossbeam_channel::Receiver<Message>>, | ||
} | ||
|
||
impl RAClient { | ||
/// Create a new LSP client for Rust Analyzer. | ||
pub fn new() -> Self { | ||
let stdin = process::Stdio::piped(); | ||
let stdout = process::Stdio::piped(); | ||
let stderr = process::Stdio::inherit(); | ||
|
||
let child = process::Command::new("rust-analyzer") | ||
.stdin(stdin) | ||
.stdout(stdout) | ||
.stderr(stderr) | ||
// .env("RA_LOG", "info") | ||
.spawn() | ||
.expect("Failed to start RA LSP server"); | ||
Self { | ||
handle: child, | ||
sender: None, | ||
receiver: None, | ||
} | ||
} | ||
|
||
pub fn start(&mut self, folders: &[PathBuf]) { | ||
let mut stdout = self.handle.stdout.take().unwrap(); | ||
let mut stdin = self.handle.stdin.take().unwrap(); | ||
|
||
let (writer_sender, writer_receiver) = bounded::<Message>(0); | ||
let writer = std::thread::spawn(move || { | ||
Check warning on line 40 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing benchmarks on linux / Test
Check warning on line 40 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing benchmarks on linux / Test
Check warning on line 40 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on ubuntu
Check warning on line 40 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on ubuntu
Check warning on line 40 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing benchmarks on macos / Test
Check warning on line 40 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing benchmarks on macos / Test
Check warning on line 40 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on macos
Check warning on line 40 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on macos
Check warning on line 40 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on windows
|
||
writer_receiver | ||
.into_iter() | ||
.try_for_each(|it| it.write(&mut stdin)) | ||
}); | ||
|
||
let (reader_sender, reader_receiver) = bounded::<Message>(0); | ||
let reader = std::thread::spawn(move || { | ||
Check warning on line 47 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing benchmarks on linux / Test
Check warning on line 47 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing benchmarks on linux / Test
Check warning on line 47 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on ubuntu
Check warning on line 47 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on ubuntu
Check warning on line 47 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on windows
|
||
let mut reader = std::io::BufReader::new(stdout); | ||
while let Ok(Some(msg)) = Message::read(&mut reader) { | ||
reader_sender | ||
.send(msg) | ||
.expect("receiver was dropped, failed to send a message"); | ||
} | ||
}); | ||
|
||
self.sender = Some(writer_sender); | ||
self.receiver = Some(reader_receiver); | ||
|
||
let root_path = std::fs::canonicalize(folders.first().unwrap()) | ||
.unwrap() | ||
.to_string_lossy() | ||
.to_string(); | ||
let workspace_paths = folders | ||
.iter() | ||
.map(|p| std::fs::canonicalize(p).unwrap()) | ||
.map(|p| lsp_types::WorkspaceFolder { | ||
name: p.file_name().unwrap().to_string_lossy().to_string(), | ||
uri: lsp_types::Url::from_file_path(p).unwrap(), | ||
}) | ||
.collect::<Vec<_>>(); | ||
|
||
let resp = self.request(lsp_server::Request { | ||
id: 1.into(), | ||
method: "initialize".to_string(), | ||
params: serde_json::to_value(&lsp_types::InitializeParams { | ||
root_uri: Some(lsp_types::Url::from_file_path(&root_path).unwrap()), | ||
Check warning on line 76 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing benchmarks on linux / Test
Check warning on line 76 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing benchmarks on linux / Test
Check warning on line 76 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on ubuntu
Check warning on line 76 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on ubuntu
Check warning on line 76 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing benchmarks on macos / Test
Check warning on line 76 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing benchmarks on macos / Test
Check warning on line 76 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on macos
Check warning on line 76 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on macos
Check warning on line 76 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on windows
|
||
root_path: Some(root_path), | ||
Check warning on line 77 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing benchmarks on linux / Test
Check warning on line 77 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing benchmarks on linux / Test
Check warning on line 77 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on ubuntu
Check warning on line 77 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on ubuntu
Check warning on line 77 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing benchmarks on macos / Test
Check warning on line 77 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing benchmarks on macos / Test
Check warning on line 77 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on macos
Check warning on line 77 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on macos
Check warning on line 77 in crates/turbo-static/src/lsp_client.rs GitHub Actions / Turbopack Rust testing on windows
|
||
workspace_folders: Some(workspace_paths), | ||
process_id: Some(std::process::id()), | ||
capabilities: lsp_types::ClientCapabilities { | ||
workspace: Some(lsp_types::WorkspaceClientCapabilities { | ||
workspace_folders: Some(true), | ||
..Default::default() | ||
}), | ||
..Default::default() | ||
}, | ||
initialization_options: None, | ||
work_done_progress_params: lsp_types::WorkDoneProgressParams { | ||
work_done_token: Some(lsp_types::ProgressToken::String("prepare".to_string())), | ||
}, | ||
trace: None, | ||
client_info: None, | ||
locale: None, | ||
}) | ||
.unwrap(), | ||
}); | ||
|
||
let resp = self.notify(lsp_server::Notification { | ||
method: "initialized".to_string(), | ||
params: serde_json::to_value(&lsp_types::InitializedParams {}).unwrap(), | ||
}); | ||
} | ||
|
||
pub fn request(&mut self, message: lsp_server::Request) -> lsp_server::Response { | ||
tracing::debug!("sending {:?}", message); | ||
self.sender | ||
.as_mut() | ||
.unwrap() | ||
.send(Message::Request(message)) | ||
.expect("failed to send message"); | ||
|
||
loop { | ||
match self | ||
.receiver | ||
.as_mut() | ||
.unwrap() | ||
.recv() | ||
.expect("failed to receive message") | ||
{ | ||
lsp_server::Message::Response(response) => { | ||
tracing::debug!("received {:?}", response); | ||
return response; | ||
} | ||
m => tracing::trace!("unexpected message: {:?}", m), | ||
} | ||
} | ||
} | ||
|
||
pub fn notify(&mut self, message: lsp_server::Notification) { | ||
self.sender | ||
.as_mut() | ||
.unwrap() | ||
.send(Message::Notification(message)) | ||
.expect("failed to send message"); | ||
} | ||
} | ||
|
||
impl Drop for RAClient { | ||
fn drop(&mut self) { | ||
if self.sender.is_some() { | ||
let resp = self.request(lsp_server::Request { | ||
id: 1.into(), | ||
method: "shutdown".to_string(), | ||
params: serde_json::to_value(&()).unwrap(), | ||
}); | ||
|
||
if resp.error.is_none() { | ||
tracing::info!("shutting down RA LSP server"); | ||
self.notify(lsp_server::Notification { | ||
method: "exit".to_string(), | ||
params: serde_json::to_value(&()).unwrap(), | ||
}); | ||
self.handle | ||
.wait() | ||
.expect("failed to wait for RA LSP server"); | ||
tracing::info!("shut down RA LSP server"); | ||
} else { | ||
tracing::error!("failed to shutdown RA LSP server: {:#?}", resp); | ||
} | ||
} | ||
|
||
self.sender = None; | ||
self.receiver = None; | ||
} | ||
} |