Skip to content

Commit

Permalink
implement basic source code listing for defs
Browse files Browse the repository at this point in the history
  • Loading branch information
wfraser committed Jul 4, 2020
1 parent 395977d commit b31429c
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 14 deletions.
2 changes: 1 addition & 1 deletion src/analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ impl Analysis {
pub_only: false, // this should be controlled by cmdline args or something
reachable_only: false, // this should be controlled by cmdline args or something
distro_crate: false,
signatures: false, // this seems to be busted
signatures: false, // this causes rustc to ICE...
borrow_data: false,
})
.expect("failed to json-serialize rust analysis configuration");
Expand Down
33 changes: 30 additions & 3 deletions src/browser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,33 @@ impl Browser {
items
}

pub fn get_info(&self, crate_id: &CrateId, item: &Item) -> String {
let mut txt = String::new();
match item {
Item::Def(def) => {
if !def.docs.is_empty() {
txt += &def.docs;
txt.push('\n');
}
txt += &format!("defined in {:?}\nstarting on line {}",
def.span.file_name,
def.span.line_start.0);
}
Item::Impl(d) => {
txt += &format!("it's an impl: {:?}\n", d);
let imp = self.analysis.get_impl(crate_id, d.impl_id).unwrap();
txt += &format!("impl: {:?}\n", imp);
txt += &format!("defined in {:?}\nstarting on line {}",
d.span.file_name,
d.span.line_start.0);
}
Item::Root => {
txt += &format!("crate root of {:?}", crate_id);
}
}
txt
}

pub fn get_debug_info(&self, crate_id: &CrateId, item: &Item) -> String {
let mut txt = format!("{:#?}", item);
match item {
Expand Down Expand Up @@ -159,9 +186,9 @@ fn def_label(def: &Def) -> String {
DefKind::Macro => "macro",
DefKind::Type => "type",
DefKind::ExternType => "extern type",
DefKind::Const => "const",
DefKind::Static => "static",
DefKind::ForeignStatic => "extern static",
DefKind::Const => return format!("const {}: {}", def.name, def.value),
DefKind::Static => return format!("static {}: {}", def.name, def.value),
DefKind::ForeignStatic => return format!("extern static {}: {}", def.name, def.value),
DefKind::TupleVariant | DefKind::StructVariant => return def.value.clone(),
DefKind::Field => return format!("{}: {}", def.name, def.value),
DefKind::Local => "local", // or should we return None?
Expand Down
2 changes: 2 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ fn main() {
eprintln!("Reading analysis data...");
let analysis = Analysis::load(&args.workspace_path);

std::env::set_current_dir(&args.workspace_path).unwrap();

let browser = Browser::new(analysis);
ui::run(browser);
}
73 changes: 63 additions & 10 deletions src/ui.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use cursive::Cursive;
use cursive::{Cursive, XY};
use cursive::event::Key;
use cursive::traits::*;
use cursive::views::{Dialog, LinearLayout, ScrollView, SelectView, TextView};
Expand Down Expand Up @@ -29,16 +29,41 @@ fn make_selectview(data: &mut UserData, crate_id: CrateId, parent: &Item, depth:
let crate_id2 = crate_id.clone();
select.set_on_submit(move |ui, item| {
let data = ui.user_data::<UserData>().unwrap();
let txt = data.browser.get_debug_info(&crate_id2, item);
ui.add_layer(
Dialog::around(
ScrollView::new(
TextView::new(txt)
)
.scroll_y(true)

let info_txt = data.browser.get_info(&crate_id2, item);
let (source_txt, span) = get_source(item);

let crate_id_dlg = crate_id2.clone();
let item_dlg = item.clone();
let info_dialog = Dialog::around(
LinearLayout::vertical()
.child(TextView::new(info_txt).scrollable())
.child(TextView::new(source_txt)
.scrollable()
.with_name("source_scroll"))
.scrollable()
)
.dismiss_button("ok")
);
.dismiss_button("ok")
.button("debug", move |ui| {
let data = ui.user_data::<UserData>().unwrap();
let dbg_txt = data.browser.get_debug_info(&crate_id_dlg, &item_dlg);
let dbg_dialog = Dialog::around(
TextView::new(dbg_txt)
.scrollable()
)
.dismiss_button("ok");
ui.add_layer(dbg_dialog);
});

ui.add_layer(info_dialog);

if let Some(span) = span {
ui.refresh(); // Need to force a layout before we can do a scroll.
ui.call_on_name("source_scroll", move |view: &mut ScrollView<TextView>| {
view.set_offset(XY::new(0, (span.line_start.0 - 1) as usize));
});
}

});

select.set_on_select(move |ui, item| {
Expand All @@ -51,6 +76,34 @@ fn make_selectview(data: &mut UserData, crate_id: CrateId, parent: &Item, depth:
Some(select)
}

fn get_source(item: &Item) -> (String, Option<rls_data::SpanData>) {
use std::fs::File;
use std::io::{BufRead, BufReader};
let mut txt = String::new();
match item {
Item::Def(def) => {
match File::open(&def.span.file_name) {
Ok(f) => {
for (i, line) in BufReader::new(f)
.lines()
.enumerate()
{
txt += &format!("{}: ", i + 1);
txt += &line.unwrap_or_else(|e| format!("<Read Error: {}>", e));
txt.push('\n');
}
}
Err(e) => {
txt += &format!("error opening source: {}", e);
}
}
return (txt, Some(def.span.clone()))
}
_ => txt += &format!("source listing unimplemented for {:?}", item),
}
(txt, None)
}

fn add_panel(ui: &mut Cursive, crate_id: CrateId, parent: &Item, depth: usize) {
ui.call_on_name("horiz_layout", |view: &mut LinearLayout| {
while view.len() > depth {
Expand Down

0 comments on commit b31429c

Please sign in to comment.