Simplify CB names (#7534)

1. When opening CB with source node, the type name is skipped and only method names are displayed. Fixes #7471
2. When entered Main module of some library, the module names are no longer displayed with their full qualified name.

![image](https://github.com/enso-org/enso/assets/3919101/2d1fe4ad-6391-41d6-89a1-410492457b57)

# Important Notes
Refactoring: I changed the internal representation of `ImString` to `Rc<str>` instead of `Rc<String>` to reduce the number of allocations and memory jumps. I even tried to remove `ImString` altogether, but it was not easy, and the main problem was lacking Default implementation.
This commit is contained in:
Adam Obuchowicz 2023-08-14 09:22:50 +02:00 committed by GitHub
parent fd972f8b0a
commit 334ed64b99
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 66 additions and 40 deletions

View File

@ -131,16 +131,8 @@ impl Component {
id: entry::Id, id: entry::Id,
entry: Rc<Entry>, entry: Rc<Entry>,
group_id: Option<usize>, group_id: Option<usize>,
label: ImString,
) -> Self { ) -> Self {
let label = match entry.kind {
entry::Kind::Module
if entry.defined_in.is_main_module() || entry.defined_in.is_top_element() =>
format!("{}", entry.defined_in).into(),
_ => match entry.self_type.as_ref() {
Some(self_type) => format!("{}.{}", self_type.alias_name(), entry.name).into(),
None => entry.name.to_im_string(),
},
};
let aliases = let aliases =
entry.aliases().map(|alias| format!("{alias} ({label})").into()).collect_vec().into(); entry.aliases().map(|alias| format!("{alias} ({label})").into()).collect_vec().into();
let data = Suggestion::FromDatabase { id, entry }; let data = Suggestion::FromDatabase { id, entry };

View File

@ -286,7 +286,16 @@ impl<'a> Builder<'a> {
None => WhenDisplayed::in_base_mode(&entry, group_id.is_some()), None => WhenDisplayed::in_base_mode(&entry, group_id.is_some()),
}; };
let when_displayed = when_displayed.consider_tags(&entry); let when_displayed = when_displayed.consider_tags(&entry);
let component = Component::new_from_database_entry(id, entry, group_id); let label = match entry.kind {
suggestion_database::entry::Kind::Module if self.inside_module.is_none() =>
format!("{}", entry.defined_in).into(),
_ => match entry.self_type.as_ref() {
Some(self_type) if self.this_type.is_none() =>
format!("{}.{}", self_type.alias_name(), entry.name).into(),
_ => entry.name.to_im_string(),
},
};
let component = Component::new_from_database_entry(id, entry, group_id, label);
if matches!(when_displayed, WhenDisplayed::Always) { if matches!(when_displayed, WhenDisplayed::Always) {
self.built_list.displayed_by_default.push(component.clone()); self.built_list.displayed_by_default.push(component.clone());
} }
@ -482,6 +491,35 @@ mod tests {
]); ]);
} }
#[test]
fn building_main_module_content_list() {
let database = mock_database();
let groups = mock_groups();
let (module_id, _) = database
.lookup_by_qualified_name(&QualifiedName::from_text("test.Test").unwrap())
.unwrap();
let mut builder = Builder::new_inside_module(&database, &groups, module_id);
builder.add_components_from_db(database.keys());
let list = builder.build();
check_displayed_components(&list, vec!["TopModule1", "TopModule2"]);
check_groups(&list, vec![None, None]);
check_filterable_components(&list, vec![
"TopModule1",
"TopModule1.fun1",
"TopModule1.fun2",
"SubModule1",
"SubModule1.fun4",
"SubModule2",
"SubModule2.fun5",
"SubModule3",
"SubModule3.fun6",
"TopModule2",
"TopModule2.fun0",
]);
}
#[test] #[test]

View File

@ -163,7 +163,7 @@ impl Path {
if let [ref _src, ref dirs @ .., _] = *self.file_path.segments.as_slice() { if let [ref _src, ref dirs @ .., _] = *self.file_path.segments.as_slice() {
// Path must designate a valid module and must be able to designate any valid module. // Path must designate a valid module and must be able to designate any valid module.
// Therefore, unwraps in this method are safe. // Therefore, unwraps in this method are safe.
let parent_modules = dirs.iter().map(ImString::new).collect(); let parent_modules = dirs.iter().map(ImString::from).collect();
let name = ImString::new(self.module_name()); let name = ImString::new(self.module_name());
Id { parent_modules, name } Id { parent_modules, name }
} else { } else {

View File

@ -160,17 +160,16 @@ impl AsRef<str> for CowString {
// ================ // ================
/// Immutable string implementation with a fast clone implementation. /// Immutable string implementation with a fast clone implementation.
#[derive(Clone, CloneRef, Default, Eq, Hash, PartialEq, Ord, PartialOrd)] #[derive(Clone, CloneRef, Eq, Hash, PartialEq, Ord, PartialOrd)]
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
pub struct ImString { pub struct ImString {
content: Rc<String>, content: Rc<str>,
} }
impl ImString { impl ImString {
/// Constructor. /// Constructor.
pub fn new(content: impl Into<String>) -> Self { pub fn new(content: impl Into<Rc<str>>) -> Self {
let content = Rc::new(content.into()); Self { content: content.into() }
Self { content }
} }
/// Extract a string slice containing the entire string. /// Extract a string slice containing the entire string.
@ -179,6 +178,12 @@ impl ImString {
} }
} }
impl Default for ImString {
fn default() -> Self {
"".into()
}
}
impl std::fmt::Display for ImString { impl std::fmt::Display for ImString {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(&self.content, f) std::fmt::Display::fmt(&self.content, f)
@ -204,12 +209,6 @@ impl AsRef<ImString> for ImString {
} }
} }
impl AsRef<String> for ImString {
fn as_ref(&self) -> &String {
self.content.as_ref()
}
}
impl AsRef<str> for ImString { impl AsRef<str> for ImString {
fn as_ref(&self) -> &str { fn as_ref(&self) -> &str {
self.content.as_ref() self.content.as_ref()
@ -222,9 +221,9 @@ impl Borrow<str> for ImString {
} }
} }
impl Borrow<String> for ImString { impl From<Rc<str>> for ImString {
fn borrow(&self) -> &String { fn from(content: Rc<str>) -> Self {
&self.content Self { content }
} }
} }
@ -236,13 +235,13 @@ impl From<String> for ImString {
impl From<&String> for ImString { impl From<&String> for ImString {
fn from(t: &String) -> Self { fn from(t: &String) -> Self {
Self::new(t) Self::new(t.as_str())
} }
} }
impl From<&&String> for ImString { impl From<&&String> for ImString {
fn from(t: &&String) -> Self { fn from(t: &&String) -> Self {
Self::new(*t) Self::new(t.as_str())
} }
} }
@ -264,18 +263,21 @@ impl From<Cow<'_, str>> for ImString {
} }
} }
impl From<ImString> for Rc<str> {
fn from(t: ImString) -> Self {
t.content
}
}
impl From<ImString> for String { impl From<ImString> for String {
fn from(value: ImString) -> Self { fn from(value: ImString) -> Self {
match Rc::try_unwrap(value.content) { value.as_str().into()
Ok(str) => str,
Err(rc) => rc.deref().clone(),
}
} }
} }
impl PartialEq<&str> for ImString { impl PartialEq<&str> for ImString {
fn eq(&self, other: &&str) -> bool { fn eq(&self, other: &&str) -> bool {
self.content.as_ref().eq(other) self.content.as_ref().eq(*other)
} }
} }
@ -287,7 +289,7 @@ impl PartialEq<str> for ImString {
impl PartialEq<ImString> for &str { impl PartialEq<ImString> for &str {
fn eq(&self, other: &ImString) -> bool { fn eq(&self, other: &ImString) -> bool {
self.eq(other.content.as_ref()) self.eq(&other.content.as_ref())
} }
} }
@ -410,12 +412,6 @@ macro_rules! im_string_newtype_without_serde {
} }
} }
impl AsRef<String> for $name {
fn as_ref(&self) -> &String {
self.content.as_ref()
}
}
impl AsRef<str> for $name { impl AsRef<str> for $name {
fn as_ref(&self) -> &str { fn as_ref(&self) -> &str {
self.content.as_ref() self.content.as_ref()

View File

@ -942,7 +942,7 @@ impl From<Rope> for String {
impl From<Rope> for ImString { impl From<Rope> for ImString {
fn from(t: Rope) -> Self { fn from(t: Rope) -> Self {
ImString::new(t) ImString::new(t.to_im_string())
} }
} }