Skip to content

internal: Make CompletionItem label and lookup fields SmolStrs #10699

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 13 additions & 16 deletions crates/cfg/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,24 +66,21 @@ impl CfgOptions {
}
}

pub fn get_cfg_keys(&self) -> Vec<&SmolStr> {
self.enabled
.iter()
.map(|x| match x {
CfgAtom::Flag(key) => key,
CfgAtom::KeyValue { key, .. } => key,
})
.collect()
pub fn get_cfg_keys(&self) -> impl Iterator<Item = &SmolStr> {
self.enabled.iter().map(|x| match x {
CfgAtom::Flag(key) => key,
CfgAtom::KeyValue { key, .. } => key,
})
}

pub fn get_cfg_values(&self, cfg_key: &str) -> Vec<&SmolStr> {
self.enabled
.iter()
.filter_map(|x| match x {
CfgAtom::KeyValue { key, value } if cfg_key == key => Some(value),
_ => None,
})
.collect()
pub fn get_cfg_values<'a>(
&'a self,
cfg_key: &'a str,
) -> impl Iterator<Item = &'a SmolStr> + 'a {
self.enabled.iter().filter_map(move |x| match x {
CfgAtom::KeyValue { key, value } if cfg_key == key => Some(value),
_ => None,
})
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/ide_completion/src/completions/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ fn complete_new_attribute(acc: &mut Completions, ctx: &CompletionContext, attrib
let mut item = CompletionItem::new(
CompletionItemKind::Attribute,
ctx.source_range(),
name.to_string(),
name.to_smol_str(),
);
if let Some(docs) = mac.docs(ctx.sema.db) {
item.documentation(docs);
Expand Down
21 changes: 8 additions & 13 deletions crates/ide_completion/src/completions/attribute/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,26 +31,21 @@ pub(crate) fn complete_cfg(acc: &mut Completions, ctx: &CompletionContext) {
Some("target_endian") => ["little", "big"].into_iter().for_each(add_completion),
Some(name) => {
if let Some(krate) = ctx.krate {
krate.potential_cfg(ctx.db).get_cfg_values(&name).iter().for_each(|s| {
let mut item = CompletionItem::new(
CompletionItemKind::Attribute,
ctx.source_range(),
s.as_str(),
);
item.insert_text(format!(r#""{}""#, s));
krate.potential_cfg(ctx.db).get_cfg_values(&name).cloned().for_each(|s| {
let insert_text = format!(r#""{}""#, s);
let mut item =
CompletionItem::new(CompletionItemKind::Attribute, ctx.source_range(), s);
item.insert_text(insert_text);

acc.add(item.build());
})
};
}
None => {
if let Some(krate) = ctx.krate {
krate.potential_cfg(ctx.db).get_cfg_keys().iter().for_each(|s| {
let item = CompletionItem::new(
CompletionItemKind::Attribute,
ctx.source_range(),
s.as_str(),
);
krate.potential_cfg(ctx.db).get_cfg_keys().cloned().for_each(|s| {
let item =
CompletionItem::new(CompletionItemKind::Attribute, ctx.source_range(), s);
acc.add(item.build());
})
}
Expand Down
17 changes: 8 additions & 9 deletions crates/ide_completion/src/completions/attribute/derive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use hir::{HasAttrs, MacroDef, MacroKind};
use ide_db::helpers::{import_assets::ImportAssets, insert_use::ImportScope, FamousDefs};
use itertools::Itertools;
use rustc_hash::FxHashSet;
use syntax::{ast, SyntaxKind};
use syntax::{ast, SmolStr, SyntaxKind};

use crate::{
completions::flyimport::compute_fuzzy_completion_order_key,
Expand All @@ -30,7 +30,6 @@ pub(super) fn complete_derive(
}

let name = name.to_smol_str();
let label;
let (label, lookup) = match core.zip(mac.module(ctx.db).map(|it| it.krate())) {
// show derive dependencies for `core`/`std` derives
Some((core, mac_krate)) if core == mac_krate => {
Expand All @@ -48,13 +47,13 @@ pub(super) fn complete_derive(
},
));
let lookup = components.join(", ");
label = components.iter().rev().join(", ");
(label.as_str(), Some(lookup))
let label = Itertools::intersperse(components.into_iter().rev(), ", ");
(SmolStr::from_iter(label), Some(lookup))
} else {
(&*name, None)
(name, None)
}
}
_ => (&*name, None),
_ => (name, None),
};

let mut item =
Expand All @@ -68,7 +67,7 @@ pub(super) fn complete_derive(
item.add_to(acc);
}

flyimport_attribute(ctx, acc);
flyimport_attribute(acc, ctx);
}

fn get_derives_in_scope(ctx: &CompletionContext) -> Vec<(hir::Name, MacroDef)> {
Expand All @@ -83,7 +82,7 @@ fn get_derives_in_scope(ctx: &CompletionContext) -> Vec<(hir::Name, MacroDef)> {
result
}

fn flyimport_attribute(ctx: &CompletionContext, acc: &mut Completions) -> Option<()> {
fn flyimport_attribute(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> {
if ctx.token.kind() != SyntaxKind::IDENT {
return None;
};
Expand Down Expand Up @@ -115,7 +114,7 @@ fn flyimport_attribute(ctx: &CompletionContext, acc: &mut Completions) -> Option
let mut item = CompletionItem::new(
CompletionItemKind::Attribute,
ctx.source_range(),
mac.name(ctx.db)?.to_string(),
mac.name(ctx.db)?.to_smol_str(),
);
item.add_import(ImportEdit { import, scope: import_scope.clone() });
if let Some(docs) = mac.docs(ctx.db) {
Expand Down
3 changes: 2 additions & 1 deletion crates/ide_completion/src/completions/fn_param.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)
}
func.param_list().into_iter().flat_map(|it| it.params()).for_each(|param| {
if let Some(pat) = param.pat() {
// FIXME: We should be able to turn these into SmolStr without having to allocate a String
let text = param.syntax().text().to_string();
let lookup = pat.syntax().text().to_string();
params.entry(text).or_insert(lookup);
Expand Down Expand Up @@ -59,7 +60,7 @@ pub(crate) fn complete_fn_param(acc: &mut Completions, ctx: &CompletionContext)

let self_completion_items = ["self", "&self", "mut self", "&mut self"];
if ctx.impl_def.is_some() && me?.param_list()?.params().next().is_none() {
self_completion_items.iter().for_each(|self_item| {
self_completion_items.into_iter().for_each(|self_item| {
add_new_item_to_acc(ctx, acc, self_item.to_string(), self_item.to_string())
});
}
Expand Down
4 changes: 2 additions & 2 deletions crates/ide_completion/src/completions/keyword.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
return;
}

let mut add_keyword = |kw, snippet| add_keyword(ctx, acc, kw, snippet);
let mut add_keyword = |kw, snippet| add_keyword(acc, ctx, kw, snippet);

let expects_assoc_item = ctx.expects_assoc_item();
let has_block_expr_parent = ctx.has_block_expr_parent();
Expand Down Expand Up @@ -157,7 +157,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
)
}

fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet: &str) {
fn add_keyword(acc: &mut Completions, ctx: &CompletionContext, kw: &str, snippet: &str) {
let mut item = CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), kw);

match ctx.config.snippet_cap {
Expand Down
2 changes: 1 addition & 1 deletion crates/ide_completion/src/completions/qualified_path.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
if ctx.in_use_tree() {
if let hir::ScopeDef::Unknown = def {
if let Some(ast::NameLike::NameRef(name_ref)) = ctx.name_syntax.as_ref() {
if name_ref.syntax().text() == name.to_string().as_str() {
if name_ref.syntax().text() == name.to_smol_str().as_str() {
// for `use self::foo$0`, don't suggest `foo` as a completion
cov_mark::hit!(dont_complete_current_use);
continue;
Expand Down
11 changes: 5 additions & 6 deletions crates/ide_completion/src/completions/trait_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ fn add_function_impl(
func: hir::Function,
impl_def: hir::Impl,
) {
let fn_name = func.name(ctx.db).to_string();
let fn_name = func.name(ctx.db).to_smol_str();

let label = if func.assoc_fn_params(ctx.db).is_empty() {
format!("fn {}()", fn_name)
Expand Down Expand Up @@ -205,12 +205,12 @@ fn add_type_alias_impl(
ctx: &CompletionContext,
type_alias: hir::TypeAlias,
) {
let alias_name = type_alias.name(ctx.db).to_string();
let alias_name = type_alias.name(ctx.db).to_smol_str();

let snippet = format!("type {} = ", alias_name);

let range = replacement_range(ctx, type_def_node);
let mut item = CompletionItem::new(SymbolKind::TypeAlias, ctx.source_range(), snippet.clone());
let mut item = CompletionItem::new(SymbolKind::TypeAlias, ctx.source_range(), &snippet);
item.text_edit(TextEdit::replace(range, snippet))
.lookup_by(alias_name)
.set_documentation(type_alias.docs(ctx.db));
Expand All @@ -224,7 +224,7 @@ fn add_const_impl(
const_: hir::Const,
impl_def: hir::Impl,
) {
let const_name = const_.name(ctx.db).map(|n| n.to_string());
let const_name = const_.name(ctx.db).map(|n| n.to_smol_str());

if let Some(const_name) = const_name {
if let Some(source) = const_.source(ctx.db) {
Expand All @@ -238,8 +238,7 @@ fn add_const_impl(
let snippet = make_const_compl_syntax(&transformed_const);

let range = replacement_range(ctx, const_def_node);
let mut item =
CompletionItem::new(SymbolKind::Const, ctx.source_range(), snippet.clone());
let mut item = CompletionItem::new(SymbolKind::Const, ctx.source_range(), &snippet);
item.text_edit(TextEdit::replace(range, snippet))
.lookup_by(const_name)
.set_documentation(const_.docs(ctx.db));
Expand Down
36 changes: 16 additions & 20 deletions crates/ide_completion/src/item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use ide_db::{
SymbolKind,
};
use smallvec::SmallVec;
use stdx::{format_to, impl_from, never};
use syntax::{algo, TextRange};
use stdx::{impl_from, never};
use syntax::{algo, SmolStr, TextRange};
use text_edit::TextEdit;

/// `CompletionItem` describes a single completion variant in the editor pop-up.
Expand All @@ -22,7 +22,7 @@ use text_edit::TextEdit;
#[derive(Clone)]
pub struct CompletionItem {
/// Label in the completion pop up which identifies completion.
label: String,
label: SmolStr,
/// Range of identifier that is being completed.
///
/// It should be used primarily for UI, but we also use this to convert
Expand All @@ -46,7 +46,7 @@ pub struct CompletionItem {
///
/// That is, in `foo.bar$0` lookup of `abracadabra` will be accepted (it
/// contains `bar` sub sequence), and `quux` will rejected.
lookup: Option<String>,
lookup: Option<SmolStr>,

/// Additional info to show in the UI pop up.
detail: Option<String>,
Expand Down Expand Up @@ -268,7 +268,7 @@ impl CompletionItem {
pub(crate) fn new(
kind: impl Into<CompletionItemKind>,
source_range: TextRange,
label: impl Into<String>,
label: impl Into<SmolStr>,
) -> Builder {
let label = label.into();
Builder {
Expand Down Expand Up @@ -379,13 +379,13 @@ impl ImportEdit {
pub(crate) struct Builder {
source_range: TextRange,
imports_to_add: SmallVec<[ImportEdit; 1]>,
trait_name: Option<String>,
label: String,
trait_name: Option<SmolStr>,
label: SmolStr,
insert_text: Option<String>,
is_snippet: bool,
detail: Option<String>,
documentation: Option<Documentation>,
lookup: Option<String>,
lookup: Option<SmolStr>,
kind: CompletionItemKind,
text_edit: Option<TextEdit>,
deprecated: bool,
Expand All @@ -400,25 +400,21 @@ impl Builder {

let mut label = self.label;
let mut lookup = self.lookup;
let mut insert_text = self.insert_text;
let insert_text = self.insert_text.unwrap_or_else(|| label.to_string());

if let [import_edit] = &*self.imports_to_add {
// snippets can have multiple imports, but normal completions only have up to one
if let Some(original_path) = import_edit.import.original_path.as_ref() {
lookup = lookup.or_else(|| Some(label.clone()));
insert_text = insert_text.or_else(|| Some(label.clone()));
format_to!(label, " (use {})", original_path)
label = SmolStr::from(format!("{} (use {})", label, original_path));
}
} else if let Some(trait_name) = self.trait_name {
insert_text = insert_text.or_else(|| Some(label.clone()));
format_to!(label, " (as {})", trait_name)
label = SmolStr::from(format!("{} (as {})", label, trait_name));
}

let text_edit = match self.text_edit {
Some(it) => it,
None => {
TextEdit::replace(self.source_range, insert_text.unwrap_or_else(|| label.clone()))
}
None => TextEdit::replace(self.source_range, insert_text),
};

CompletionItem {
Expand All @@ -437,16 +433,16 @@ impl Builder {
import_to_add: self.imports_to_add,
}
}
pub(crate) fn lookup_by(&mut self, lookup: impl Into<String>) -> &mut Builder {
pub(crate) fn lookup_by(&mut self, lookup: impl Into<SmolStr>) -> &mut Builder {
self.lookup = Some(lookup.into());
self
}
pub(crate) fn label(&mut self, label: impl Into<String>) -> &mut Builder {
pub(crate) fn label(&mut self, label: impl Into<SmolStr>) -> &mut Builder {
self.label = label.into();
self
}
pub(crate) fn trait_name(&mut self, trait_name: impl Into<String>) -> &mut Builder {
self.trait_name = Some(trait_name.into());
pub(crate) fn trait_name(&mut self, trait_name: SmolStr) -> &mut Builder {
self.trait_name = Some(trait_name);
self
}
pub(crate) fn insert_text(&mut self, insert_text: impl Into<String>) -> &mut Builder {
Expand Down
10 changes: 5 additions & 5 deletions crates/ide_completion/src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,11 +83,11 @@ pub(crate) fn render_field(
ty: &hir::Type,
) -> CompletionItem {
let is_deprecated = ctx.is_deprecated(field);
let name = field.name(ctx.db()).to_string();
let name = field.name(ctx.db()).to_smol_str();
let mut item = CompletionItem::new(
SymbolKind::Field,
ctx.source_range(),
receiver.map_or_else(|| name.clone(), |receiver| format!("{}.{}", receiver, name)),
receiver.map_or_else(|| name.clone(), |receiver| format!("{}.{}", receiver, name).into()),
);
item.set_relevance(CompletionRelevance {
type_match: compute_type_match(ctx.completion, ty),
Expand All @@ -97,7 +97,7 @@ pub(crate) fn render_field(
item.detail(ty.display(ctx.db()).to_string())
.set_documentation(field.docs(ctx.db()))
.set_deprecated(is_deprecated)
.lookup_by(name.as_str());
.lookup_by(name.clone());
let is_keyword = SyntaxKind::from_keyword(name.as_str()).is_some();
if is_keyword && !matches!(name.as_str(), "self" | "crate" | "super" | "Self") {
item.insert_text(format!("r#{}", name));
Expand Down Expand Up @@ -199,7 +199,7 @@ fn render_resolution_(
let mut item = CompletionItem::new(
CompletionItemKind::UnresolvedReference,
ctx.source_range(),
local_name.to_string(),
local_name.to_smol_str(),
);
if let Some(import_to_add) = import_to_add {
item.add_import(import_to_add);
Expand All @@ -208,7 +208,7 @@ fn render_resolution_(
}
};

let local_name = local_name.to_string();
let local_name = local_name.to_smol_str();
let mut item = CompletionItem::new(kind, ctx.source_range(), local_name.clone());
if let hir::ScopeDef::Local(local) = resolution {
let ty = local.ty(ctx.db());
Expand Down
Loading