Style new lsp log menu, add a test for it

This commit is contained in:
Max Brunsfeld 2023-06-07 16:55:29 -07:00
parent 66f215cd13
commit 817644eb20
7 changed files with 210 additions and 38 deletions

2
Cargo.lock generated
View File

@ -3763,8 +3763,10 @@ name = "lsp_log"
version = "0.1.0"
dependencies = [
"anyhow",
"client",
"collections",
"editor",
"env_logger 0.9.3",
"futures 0.3.28",
"gpui",
"language",

View File

@ -24,7 +24,9 @@ serde.workspace = true
anyhow.workspace = true
[dev-dependencies]
client = { path = "../client", features = ["test-support"] }
editor = { path = "../editor", features = ["test-support"] }
gpui = { path = "../gpui", features = ["test-support"] }
util = { path = "../util", features = ["test-support"] }
env_logger.workspace = true
unindent.workspace = true

View File

@ -1,3 +1,6 @@
#[cfg(test)]
mod lsp_log_tests;
use collections::HashMap;
use editor::Editor;
use futures::{channel::mpsc, StreamExt};
@ -521,7 +524,7 @@ impl View for LspLogToolbarItemView {
)
}))
.contained()
.with_style(theme.context_menu.container)
.with_style(theme.lsp_log_menu.container)
.constrained()
.with_width(400.)
.with_height(400.)
@ -548,6 +551,9 @@ impl View for LspLogToolbarItemView {
}
}
const RPC_MESSAGES: &str = "RPC Messages";
const SERVER_LOGS: &str = "Server Logs";
impl LspLogToolbarItemView {
pub fn new() -> Self {
Self {
@ -605,18 +611,25 @@ impl LspLogToolbarItemView {
let label: Cow<str> = current_server
.and_then(|row| {
let worktree = row.worktree.read(cx);
Some(format!("{} - ({})", row.server_name.0, worktree.root_name()).into())
Some(
format!(
"{} ({}) - {}",
row.server_name.0,
worktree.root_name(),
if row.rpc_trace_selected {
RPC_MESSAGES
} else {
SERVER_LOGS
},
)
.into(),
)
})
.unwrap_or_else(|| "No server selected".into());
Label::new(
label,
theme
.context_menu
.item
.style_for(state, false)
.label
.clone(),
)
let style = theme.lsp_log_menu.header.style_for(state, false);
Label::new(label, style.text.clone())
.contained()
.with_style(style.container)
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, view, cx| {
@ -628,7 +641,7 @@ impl LspLogToolbarItemView {
id: LanguageServerId,
name: LanguageServerName,
worktree: ModelHandle<Worktree>,
logging_enabled: bool,
rpc_trace_enabled: bool,
logs_selected: bool,
rpc_trace_selected: bool,
theme: &Arc<Theme>,
@ -637,23 +650,25 @@ impl LspLogToolbarItemView {
enum ActivateLog {}
enum ActivateRpcTrace {}
let header = format!("{} - ({})", name.0, worktree.read(cx).root_name());
let item_style = &theme.context_menu.item.default;
Flex::column()
.with_child(
Label::new(header, item_style.label.clone())
.aligned()
.left(),
)
.with_child({
let style = &theme.lsp_log_menu.server;
Label::new(
format!("{} ({})", name.0, worktree.read(cx).root_name()),
style.text.clone(),
)
.contained()
.with_style(style.container)
.aligned()
.left()
})
.with_child(
MouseEventHandler::<ActivateLog, _>::new(id.0, cx, move |state, _| {
let item_style = &theme.context_menu.item.style_for(state, logs_selected);
Label::new("logs", item_style.label.clone())
.aligned()
.left()
let style = theme.lsp_log_menu.item.style_for(state, logs_selected);
Flex::row()
.with_child(Label::new(SERVER_LOGS, style.text.clone()).aligned().left())
.contained()
.with_style(item_style.container)
.with_style(style.container)
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, view, cx| {
@ -662,26 +677,29 @@ impl LspLogToolbarItemView {
)
.with_child(
MouseEventHandler::<ActivateRpcTrace, _>::new(id.0, cx, move |state, cx| {
let item_style = &theme.context_menu.item.style_for(state, rpc_trace_selected);
let style = theme.lsp_log_menu.item.style_for(state, rpc_trace_selected);
Flex::row()
.with_child(ui::checkbox_with_label::<Self, _, Self, _>(
Empty::new(),
&theme.welcome.checkbox,
logging_enabled,
id.0,
cx,
move |this, enabled, cx| {
this.toggle_logging_for_server(id, enabled, cx);
},
))
.with_child(
Label::new("rpc trace", item_style.label.clone())
Label::new(RPC_MESSAGES, style.text.clone())
.aligned()
.left(),
)
.with_child(
ui::checkbox_with_label::<Self, _, Self, _>(
Empty::new(),
&theme.welcome.checkbox,
rpc_trace_enabled,
id.0,
cx,
move |this, enabled, cx| {
this.toggle_logging_for_server(id, enabled, cx);
},
)
.flex_float(),
)
.align_children_center()
.contained()
.with_style(item_style.container)
.with_style(style.container)
})
.with_cursor_style(CursorStyle::PointingHand)
.on_click(MouseButton::Left, move |_, view, cx| {

View File

@ -0,0 +1,97 @@
use super::*;
use gpui::{serde_json::json, TestAppContext};
use language::{tree_sitter_rust, FakeLspAdapter, Language, LanguageConfig};
use project::FakeFs;
use settings::SettingsStore;
#[gpui::test]
async fn test_lsp_logs(cx: &mut TestAppContext) {
if std::env::var("RUST_LOG").is_ok() {
env_logger::init();
}
init_test(cx);
let mut rust_language = Language::new(
LanguageConfig {
name: "Rust".into(),
path_suffixes: vec!["rs".to_string()],
..Default::default()
},
Some(tree_sitter_rust::language()),
);
let mut fake_rust_servers = rust_language
.set_fake_lsp_adapter(Arc::new(FakeLspAdapter {
name: "the-rust-language-server",
..Default::default()
}))
.await;
let fs = FakeFs::new(cx.background());
fs.insert_tree(
"/the-root",
json!({
"test.rs": "",
"package.json": "",
}),
)
.await;
let project = Project::test(fs.clone(), ["/the-root".as_ref()], cx).await;
project.update(cx, |project, _| {
project.languages().add(Arc::new(rust_language));
});
let log_store = cx.add_model(|cx| LogStore::new(cx));
log_store.update(cx, |store, cx| store.add_project(&project, cx));
let _rust_buffer = project
.update(cx, |project, cx| {
project.open_local_buffer("/the-root/test.rs", cx)
})
.await
.unwrap();
let mut language_server = fake_rust_servers.next().await.unwrap();
language_server
.receive_notification::<lsp::notification::DidOpenTextDocument>()
.await;
let (_, log_view) = cx.add_window(|cx| LspLogView::new(project.clone(), log_store.clone(), cx));
language_server.notify::<lsp::notification::LogMessage>(lsp::LogMessageParams {
message: "hello from the server".into(),
typ: lsp::MessageType::INFO,
});
cx.foreground().run_until_parked();
log_view.read_with(cx, |view, cx| {
assert_eq!(
view.menu_items(cx).unwrap(),
&[LogMenuItem {
server_id: language_server.server.server_id(),
server_name: LanguageServerName("the-rust-language-server".into()),
worktree: project.read(cx).worktrees(cx).next().unwrap(),
rpc_trace_enabled: false,
rpc_trace_selected: false,
logs_selected: true,
}]
);
assert_eq!(
view.editor.as_ref().unwrap().read(cx).text(cx),
"hello from the server\n"
);
});
}
fn init_test(cx: &mut gpui::TestAppContext) {
cx.foreground().forbid_parking();
cx.update(|cx| {
cx.set_global(SettingsStore::test(cx));
theme::init((), cx);
language::init(cx);
client::init_settings(cx);
Project::init_settings(cx);
editor::init_settings(cx);
});
}

View File

@ -44,6 +44,7 @@ pub struct Theme {
pub context_menu: ContextMenu,
pub contacts_popover: ContactsPopover,
pub contact_list: ContactList,
pub lsp_log_menu: LspLogMenu,
pub copilot: Copilot,
pub contact_finder: ContactFinder,
pub project_panel: ProjectPanel,
@ -244,6 +245,15 @@ pub struct ContactFinder {
pub disabled_contact_button: IconButton,
}
#[derive(Deserialize, Default)]
pub struct LspLogMenu {
#[serde(flatten)]
pub container: ContainerStyle,
pub header: Interactive<ContainedText>,
pub server: ContainedText,
pub item: Interactive<ContainedText>,
}
#[derive(Clone, Deserialize, Default)]
pub struct TabBar {
#[serde(flatten)]

View File

@ -17,6 +17,7 @@ import projectSharedNotification from "./projectSharedNotification"
import tooltip from "./tooltip"
import terminal from "./terminal"
import contactList from "./contactList"
import lspLogMenu from "./lspLogMenu"
import incomingCallNotification from "./incomingCallNotification"
import { ColorScheme } from "../themes/common/colorScheme"
import feedback from "./feedback"
@ -45,6 +46,7 @@ export default function app(colorScheme: ColorScheme): Object {
contactsPopover: contactsPopover(colorScheme),
contactFinder: contactFinder(colorScheme),
contactList: contactList(colorScheme),
lspLogMenu: lspLogMenu(colorScheme),
search: search(colorScheme),
sharedScreen: sharedScreen(colorScheme),
updateNotification: updateNotification(colorScheme),

View File

@ -0,0 +1,41 @@
import { ColorScheme } from "../themes/common/colorScheme"
import { background, border, text } from "./components"
export default function contactsPanel(colorScheme: ColorScheme) {
let layer = colorScheme.middle
return {
background: background(layer),
border: border(layer),
shadow: colorScheme.popoverShadow,
header: {
...text(layer, "sans", { size: "sm" }),
padding: { left: 8, right: 8, top: 2, bottom: 2 },
cornerRadius: 6,
background: background(layer, "on"),
border: border(layer, "on", { overlay: true }),
hover: {
background: background(layer, "hovered"),
...text(layer, "sans", "hovered", { size: "sm" }),
}
},
server: {
...text(layer, "sans", { size: "sm" }),
padding: { left: 8, right: 8, top: 8, bottom: 8 },
},
item: {
...text(layer, "sans", { size: "sm" }),
padding: { left: 18, right: 18, top: 2, bottom: 2 },
hover: {
background: background(layer, "hovered"),
...text(layer, "sans", "hovered", { size: "sm" }),
},
active: {
background: background(layer, "active"),
},
activeHover: {
background: background(layer, "active"),
},
},
}
}