@@ -73,7 +73,9 @@ impl LspInstaller for GoLspAdapter {
delegate.show_notification(NOTIFICATION_MESSAGE, cx);
})?
}
- anyhow::bail!("cannot install gopls");
+ anyhow::bail!(
+ "Could not install the Go language server `gopls`, because `go` was not found."
+ );
}
let release =
@@ -1663,12 +1663,20 @@ impl ProjectPanel {
let edit_state = self.state.edit_state.as_mut()?;
let worktree_id = edit_state.worktree_id;
let is_new_entry = edit_state.is_new_entry();
- let filename = self.filename_editor.read(cx).text(cx);
+ let mut filename = self.filename_editor.read(cx).text(cx);
+ let path_style = self.project.read(cx).path_style(cx);
+ if path_style.is_windows() {
+ // on windows, trailing dots are ignored in paths
+ // this can cause project panel to create a new entry with a trailing dot
+ // while the actual one without the dot gets populated by the file watcher
+ while let Some(trimmed) = filename.strip_suffix('.') {
+ filename = trimmed.to_string();
+ }
+ }
if filename.trim().is_empty() {
return None;
}
- let path_style = self.project.read(cx).path_style(cx);
let filename_indicates_dir = if path_style.is_windows() {
filename.ends_with('/') || filename.ends_with('\\')
} else {
@@ -6612,6 +6612,74 @@ async fn test_create_entries_without_selection_hide_root(cx: &mut gpui::TestAppC
);
}
+#[cfg(windows)]
+#[gpui::test]
+async fn test_create_entry_with_trailing_dot_windows(cx: &mut gpui::TestAppContext) {
+ init_test(cx);
+
+ let fs = FakeFs::new(cx.executor());
+ fs.insert_tree(
+ path!("/root"),
+ json!({
+ "dir1": {
+ "file1.txt": "",
+ },
+ }),
+ )
+ .await;
+
+ let project = Project::test(fs.clone(), [path!("/root").as_ref()], cx).await;
+ let workspace = cx.add_window(|window, cx| Workspace::test_new(project.clone(), window, cx));
+ let cx = &mut VisualTestContext::from_window(*workspace, cx);
+
+ let panel = workspace
+ .update(cx, |workspace, window, cx| {
+ let panel = ProjectPanel::new(workspace, window, cx);
+ workspace.add_panel(panel.clone(), window, cx);
+ panel
+ })
+ .unwrap();
+ cx.run_until_parked();
+
+ #[rustfmt::skip]
+ assert_eq!(
+ visible_entries_as_strings(&panel, 0..20, cx),
+ &[
+ "v root",
+ " > dir1",
+ ],
+ "Initial state with nothing selected"
+ );
+
+ panel.update_in(cx, |panel, window, cx| {
+ panel.new_file(&NewFile, window, cx);
+ });
+ cx.run_until_parked();
+ panel.update_in(cx, |panel, window, cx| {
+ assert!(panel.filename_editor.read(cx).is_focused(window));
+ });
+ panel
+ .update_in(cx, |panel, window, cx| {
+ panel
+ .filename_editor
+ .update(cx, |editor, cx| editor.set_text("foo.", window, cx));
+ panel.confirm_edit(true, window, cx).unwrap()
+ })
+ .await
+ .unwrap();
+ cx.run_until_parked();
+ #[rustfmt::skip]
+ assert_eq!(
+ visible_entries_as_strings(&panel, 0..20, cx),
+ &[
+ "v root",
+ " > dir1",
+ " foo <== selected <== marked",
+ ],
+ "A new file is created under the root directory without the trailing dot"
+ );
+}
+
#[gpui::test]
async fn test_highlight_entry_for_external_drag(cx: &mut gpui::TestAppContext) {
init_test(cx);