@@ -18,7 +18,9 @@ use crate::{
21−use std::{borrow::Cow, cmp::Ordering, collections::BTreeMap, path::PathBuf, sync::Arc};
22+ borrow::Cow, cmp::Ordering, collections::BTreeMap, fmt::Write, path::PathBuf, sync::Arc,
23/// Gets the language server that is attached to a document, and
25/// Gets the language server that is attached to a document, and
24/// if it's not active displays a status message. Using this macro
26/// if it's not active displays a status message. Using this macro
@@ -43,23 +45,32 @@ impl ui::menu::Item for lsp::Location {
43 type Data = PathBuf;
45 type Data = PathBuf;
45 fn label(&self, cwdir: &Self::Data) -> Spans {
47 fn label(&self, cwdir: &Self::Data) -> Spans {
48+ // The preallocation here will overallocate a few characters since it will account for the
49+ // URL's scheme, which is not used most of the time since that scheme will be "file://".
50+ // Those extra chars will be used to avoid allocating when writing the line number (in the
51+ // common case where it has 5 digits or less, which should be enough for a cast majority
53+ let mut res = String::with_capacity(self.uri.as_str().len());
46− let file: Cow<'_, str> = (self.uri.scheme() == "file")
55+ if self.uri.scheme() == "file" {
47− .then(|| {
56+ // With the preallocation above and UTF-8 paths already, this closure will do one (1)
48− self.uri
57+ // allocation, for `to_file_path`, else there will be two (2), with `to_string_lossy`.
58+ let mut write_path_to_res = || -> Option<()> {
49− .to_file_path()
59+ let path = self.uri.to_file_path().ok()?;
52− path.strip_prefix(&cwdir)
60+ res.push_str(&path.strip_prefix(&cwdir).unwrap_or(&path).to_string_lossy());
53− .map(|path| path.to_path_buf())
61+ Some(())
56− .map(|path| Cow::from(path.to_string_lossy().into_owned()))
59− .flatten()
63+ write_path_to_res();
65+ // Never allocates since we declared the string with this capacity already.
60− .unwrap_or_else(|| self.uri.as_str().into());
66+ res.push_str(self.uri.as_str());
69+ // Most commonly, this will not allocate, especially on Unix systems where the root prefix
70+ // is a simple `/` and not `C:\` (with whatever drive letter)
61− let line = self.range.start.line;
71+ write!(&mut res, ":{}", self.range.start.line)
62− format!("{}:{}", file, line).into()
72+ .expect("Will only failed if allocating fail");
@@ -73,10 +84,8 @@ impl ui::menu::Item for lsp::SymbolInformation {
74 match self.location.uri.to_file_path() {
85 match self.location.uri.to_file_path() {
75 Ok(path) => {
86 Ok(path) => {
76− let relative_path = helix_core::path::get_relative_path(path.as_path())
87+ let get_relative_path = path::get_relative_path(path.as_path());
79− format!("{} ({})", &self.name, relative_path).into()
88+ format!("{} ({})", &self.name, get_relative_path.to_string_lossy()).into()
81 Err(_) => format!("{} ({})", &self.name, &self.location.uri).into(),
90 Err(_) => format!("{} ({})", &self.name, &self.location.uri).into(),
@@ -115,24 +124,21 @@ impl ui::menu::Item for PickerDiagnostic {
115 // remove background as it is distracting in the picker list
124 // remove background as it is distracting in the picker list
116 style.bg = None;
125 style.bg = None;
118− let code = self
127+ let code: Cow<'_, str> = self
121 .as_ref()
130 .as_ref()
122 .map(|c| match c {
131 .map(|c| match c {
123− NumberOrString::Number(n) => n.to_string(),
132+ NumberOrString::Number(n) => n.to_string().into(),
124− NumberOrString::String(s) => s.to_string(),
133+ NumberOrString::String(s) => s.as_str().into(),
126− .map(|code| format!(" ({})", code))
127 .unwrap_or_default();
135 .unwrap_or_default();
129 let path = match format {
137 let path = match format {
130 DiagnosticsFormat::HideSourcePath => String::new(),
138 DiagnosticsFormat::HideSourcePath => String::new(),
131 DiagnosticsFormat::ShowSourcePath => {
139 DiagnosticsFormat::ShowSourcePath => {
132− let path = path::get_truncated_path(self.url.path())
140+ let path = path::get_truncated_path(self.url.path());
135− format!("{}: ", path)
141+ format!("{}: ", path.to_string_lossy())