Skip to content

Commit

Permalink
feat: code action for dependency version
Browse files Browse the repository at this point in the history
  • Loading branch information
washanhanzi committed Oct 9, 2024
1 parent af55779 commit 2994ffa
Show file tree
Hide file tree
Showing 9 changed files with 250 additions and 120 deletions.
48 changes: 0 additions & 48 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ cargo = { package = "my-cargo", git = "https://github.com/washanhanzi/cargo.git"
anyhow = "1.0.88"
clap = { version = "4.5.18", features = ["derive"] }
once_cell = "1.19.0"
ribboncurls = "0.4.1"
semver = "1.0.23"

openssl = { version = '0.10', optional = true }
Expand Down
68 changes: 50 additions & 18 deletions src/controller/appraiser.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{collections::HashMap, path::Path};
use std::collections::HashMap;

use cargo::util::VersionExt;
use semver::Version;
Expand All @@ -13,6 +13,7 @@ use tower_lsp::{
};

use crate::{
controller::code_action::code_action,
decoration::DecorationEvent,
entity::cargo_dependency_to_toml_key,
usecase::{diff_symbol_maps, Walker},
Expand Down Expand Up @@ -121,32 +122,36 @@ impl Appraiser {
let Some(h) = hover(node, dep) else {
continue;
};
tx.send(h).unwrap()
let _ = tx.send(h);
}
CargoDocumentEvent::CodeAction(uri, range, tx) => {
let Some((symbol_map, reverse_map, dependencies)) = state.state(&uri)
else {
continue;
};
eprintln!("code action: {:?}", range);
let Some(node) = reverse_map.precise_match(range.start, symbol_map) else {
continue;
};
let Some(dep) = dependencies.iter().find(|dep| dep.id == node.key.row_id())
else {
continue;
};
if dep.resolved.is_some() {
eprintln!("code action: {:?}", dep.resolved.as_ref().unwrap().name);
tx.send(CodeActionResponse::new()).unwrap();
}
let Some(action) = code_action(uri, node, dep) else {
continue;
};
let _ = tx.send(action);
}
CargoDocumentEvent::Closed(uri) => {
state.close(&uri);
}
CargoDocumentEvent::CargoLockChanged => {
state.clear();
render_tx.send(DecorationEvent::Reset).await.unwrap();
//clear state except the "current" uri
let Some((uri, rev)) = state.clear_except_current() else {
continue;
};
if let Err(e) = cargo_tx.send(Ctx { uri, rev }).await {
eprintln!("cargo lock changed tx error: {}", e);
}
}
CargoDocumentEvent::Changed(text) => {
let p = taplo::parser::parse(&text);
Expand All @@ -169,6 +174,9 @@ impl Appraiser {
let rev = state.inc_rev(&msg.uri);
let (symbol_map, reverse_map, dirty_nodes, dependencies) =
state.state_mut(&msg.uri);
let Ok(path) = msg.uri.to_file_path() else {
continue;
};

let (new_symbol_map, new_deps) = {
//parse cargo.toml text
Expand Down Expand Up @@ -196,12 +204,10 @@ impl Appraiser {
}

//get dependencies
//TODO ?? save the clone
let uri_clone = msg.uri.clone();
let path = Path::new(uri_clone.path());
let gctx = cargo::util::context::GlobalContext::default().unwrap();
//TODO ERROR parse manifest
let workspace = cargo::core::Workspace::new(path, &gctx).unwrap();
let workspace =
cargo::core::Workspace::new(path.as_path(), &gctx).unwrap();
//TODO if it's error, it's a virtual workspace
let current = workspace.current().unwrap();
let mut unresolved = HashMap::new();
Expand All @@ -213,7 +219,7 @@ impl Appraiser {
let (new_symbol_map, mut new_deps) = walker.consume();

//loop new_deps, get unresolved
for dep in &mut new_deps {
for (_, dep) in &mut new_deps {
let key = dep.toml_key();
if unresolved.contains_key(&key) {
//take out value from unresolved
Expand Down Expand Up @@ -243,7 +249,30 @@ impl Appraiser {
reverse_map.init(symbol_map);

// Loop through both created and changed nodes
for v in created.iter().chain(changed.iter()) {
for v in &created {
dependencies.push(new_deps.get(v).unwrap().clone());
// Send to a dedicated render task
if let Some(n) = symbol_map.get(v) {
render_tx
.send(DecorationEvent::DependencyLoading(
msg.uri.clone(),
v.to_string(),
n.range,
))
.await
.unwrap();
}
}

for v in &changed {
//find dep in dependencies with same id and replace it
for dep in dependencies.iter_mut() {
if dep.id == v.as_str() {
if let Some(new_dep) = new_deps.get(v) {
*dep = new_dep.clone();
}
}
}
// Send to a dedicated render task
if let Some(n) = symbol_map.get(v) {
render_tx
Expand All @@ -258,6 +287,8 @@ impl Appraiser {
}

for v in deleted {
//inplace mutate dependencies
dependencies.retain(|dep| dep.id != v);
//send to a dedicate render task
render_tx
.send(DecorationEvent::DependencyRemove(
Expand All @@ -268,14 +299,15 @@ impl Appraiser {
.unwrap();
}

//override old deps
*dependencies = new_deps;

//no change to resolve
if dirty_nodes.is_empty() {
continue;
}

//override old deps
//or better we only override the changed deps
// *dependencies = new_deps;

//resolve cargo dependencies in another task
cargo_tx
.send(Ctx {
Expand Down
19 changes: 12 additions & 7 deletions src/controller/cargo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,16 @@ pub struct CargoResolveOutput {
}

pub async fn parse_cargo_output(ctx: &Ctx) -> CargoResolveOutput {
//TODO can we do better
let uri_clone = ctx.uri.clone();
let path = Path::new(uri_clone.path());
//TODO refactor
let Ok(path) = ctx.uri.to_file_path() else {
return CargoResolveOutput {
ctx: ctx.clone(),
dependencies: HashMap::new(),
summaries: HashMap::new(),
};
};
let gctx = cargo::util::context::GlobalContext::default().unwrap();
let workspace = cargo::core::Workspace::new(path, &gctx).unwrap();
let workspace = cargo::core::Workspace::new(path.as_path(), &gctx).unwrap();
let current = workspace.current().unwrap();
let deps = current.dependencies();

Expand Down Expand Up @@ -100,13 +105,13 @@ pub async fn parse_cargo_output(ctx: &Ctx) -> CargoResolveOutput {
CargoResolveOutput {
ctx: ctx.clone(),
dependencies: res,
summaries: summaries_map(uri_clone.path()),
//TODO maybe reuse gctx
summaries: summaries_map(path.as_path()),
}
}

//TODO the current Vec<Summary> didn't include yanked
fn summaries_map(path: &str) -> HashMap<String, Vec<Summary>> {
let path = Path::new(path);
fn summaries_map(path: &Path) -> HashMap<String, Vec<Summary>> {
let gctx = cargo::util::context::GlobalContext::default().unwrap();
let workspace = cargo::core::Workspace::new(path, &gctx).unwrap();

Expand Down
Loading

0 comments on commit 2994ffa

Please sign in to comment.