Detailed changes
@@ -264,11 +264,7 @@ impl CompletionBuilder {
Completion {
replace_range: Anchor::MIN..Anchor::MAX,
new_text: label.to_string(),
- label: CodeLabel {
- text: label.to_string(),
- runs: Default::default(),
- filter_range: 0..label.len(),
- },
+ label: CodeLabel::plain(label.to_string(), filter_text),
documentation: None,
source: CompletionSource::Lsp {
insert_range: None,
@@ -299,7 +295,7 @@ async fn filter_and_sort_matches(
let candidates: Arc<[StringMatchCandidate]> = completions
.iter()
.enumerate()
- .map(|(id, completion)| StringMatchCandidate::new(id, &completion.filter_text()))
+ .map(|(id, completion)| StringMatchCandidate::new(id, &completion.label.filter_text()))
.collect();
let cancel_flag = Arc::new(AtomicBool::new(false));
let background_executor = cx.executor();
@@ -260,7 +260,7 @@ impl CompletionsMenu {
let match_candidates = completions
.iter()
.enumerate()
- .map(|(id, completion)| StringMatchCandidate::new(id, completion.filter_text()))
+ .map(|(id, completion)| StringMatchCandidate::new(id, completion.label.filter_text()))
.collect();
let completions_menu = Self {
@@ -1115,7 +1115,7 @@ impl CompletionsMenu {
SnippetSortOrder::Inline => Reverse(0),
};
let sort_positions = string_match.positions.clone();
- let sort_exact = Reverse(if Some(completion.filter_text()) == query {
+ let sort_exact = Reverse(if Some(completion.label.filter_text()) == query {
1
} else {
0
@@ -1982,25 +1982,27 @@ impl CodeLabel {
} else {
label.clone()
};
+ let filter_range = item
+ .filter_text
+ .as_deref()
+ .and_then(|filter| text.find(filter).map(|ix| ix..ix + filter.len()))
+ .unwrap_or(0..label_length);
Self {
text,
runs,
- filter_range: 0..label_length,
+ filter_range,
}
}
pub fn plain(text: String, filter_text: Option<&str>) -> Self {
- let mut result = Self {
+ let filter_range = filter_text
+ .and_then(|filter| text.find(filter).map(|ix| ix..ix + filter.len()))
+ .unwrap_or(0..text.len());
+ Self {
runs: Vec::new(),
- filter_range: 0..text.len(),
+ filter_range,
text,
- };
- if let Some(filter_text) = filter_text {
- if let Some(ix) = result.text.find(filter_text) {
- result.filter_range = ix..ix + filter_text.len();
- }
}
- result
}
pub fn push_str(&mut self, text: &str, highlight: Option<HighlightId>) {
@@ -131,8 +131,16 @@ impl super::LspAdapter for CLspAdapter {
let text = format!("{} {}", detail, label);
let source = Rope::from(format!("struct S {{ {} }}", text).as_str());
let runs = language.highlight_text(&source, 11..11 + text.len());
+ let filter_range = completion
+ .filter_text
+ .as_deref()
+ .and_then(|filter_text| {
+ text.find(filter_text)
+ .map(|start| start..start + filter_text.len())
+ })
+ .unwrap_or(detail.len() + 1..text.len());
return Some(CodeLabel {
- filter_range: detail.len() + 1..text.len(),
+ filter_range,
text,
runs,
});
@@ -143,8 +151,16 @@ impl super::LspAdapter for CLspAdapter {
let detail = completion.detail.as_ref().unwrap();
let text = format!("{} {}", detail, label);
let runs = language.highlight_text(&Rope::from(text.as_str()), 0..text.len());
+ let filter_range = completion
+ .filter_text
+ .as_deref()
+ .and_then(|filter_text| {
+ text.find(filter_text)
+ .map(|start| start..start + filter_text.len())
+ })
+ .unwrap_or(detail.len() + 1..text.len());
return Some(CodeLabel {
- filter_range: detail.len() + 1..text.len(),
+ filter_range,
text,
runs,
});
@@ -155,16 +171,24 @@ impl super::LspAdapter for CLspAdapter {
let detail = completion.detail.as_ref().unwrap();
let text = format!("{} {}", detail, label);
let runs = language.highlight_text(&Rope::from(text.as_str()), 0..text.len());
- let filter_start = detail.len() + 1;
- let filter_end =
- if let Some(end) = text.rfind('(').filter(|end| *end > filter_start) {
- end
- } else {
- text.len()
- };
+ let filter_range = completion
+ .filter_text
+ .as_deref()
+ .and_then(|filter_text| {
+ text.find(filter_text)
+ .map(|start| start..start + filter_text.len())
+ })
+ .unwrap_or_else(|| {
+ let filter_start = detail.len() + 1;
+ let filter_end = text
+ .rfind('(')
+ .filter(|end| *end > filter_start)
+ .unwrap_or(text.len());
+ filter_start..filter_end
+ });
return Some(CodeLabel {
- filter_range: filter_start..filter_end,
+ filter_range,
text,
runs,
});
@@ -186,7 +210,8 @@ impl super::LspAdapter for CLspAdapter {
.grammar()
.and_then(|g| g.highlight_id_for_name(highlight_name?))
{
- let mut label = CodeLabel::plain(label.to_string(), None);
+ let mut label =
+ CodeLabel::plain(label.to_string(), completion.filter_text.as_deref());
label.runs.push((
0..label.text.rfind('(').unwrap_or(label.text.len()),
highlight_id,
@@ -196,7 +221,10 @@ impl super::LspAdapter for CLspAdapter {
}
_ => {}
}
- Some(CodeLabel::plain(label.to_string(), None))
+ Some(CodeLabel::plain(
+ label.to_string(),
+ completion.filter_text.as_deref(),
+ ))
}
async fn label_for_symbol(
@@ -233,10 +233,18 @@ impl super::LspAdapter for GoLspAdapter {
let text = format!("{label} {detail}");
let source = Rope::from(format!("import {text}").as_str());
let runs = language.highlight_text(&source, 7..7 + text.len());
+ let filter_range = completion
+ .filter_text
+ .as_deref()
+ .and_then(|filter_text| {
+ text.find(filter_text)
+ .map(|start| start..start + filter_text.len())
+ })
+ .unwrap_or(0..label.len());
return Some(CodeLabel {
text,
runs,
- filter_range: 0..label.len(),
+ filter_range,
});
}
Some((
@@ -250,10 +258,18 @@ impl super::LspAdapter for GoLspAdapter {
name_offset,
language.highlight_text(&source, 4..4 + text.len()),
);
+ let filter_range = completion
+ .filter_text
+ .as_deref()
+ .and_then(|filter_text| {
+ text.find(filter_text)
+ .map(|start| start..start + filter_text.len())
+ })
+ .unwrap_or(0..label.len());
return Some(CodeLabel {
text,
runs,
- filter_range: 0..label.len(),
+ filter_range,
});
}
Some((lsp::CompletionItemKind::STRUCT, _)) => {
@@ -263,10 +279,18 @@ impl super::LspAdapter for GoLspAdapter {
name_offset,
language.highlight_text(&source, 5..5 + text.len()),
);
+ let filter_range = completion
+ .filter_text
+ .as_deref()
+ .and_then(|filter_text| {
+ text.find(filter_text)
+ .map(|start| start..start + filter_text.len())
+ })
+ .unwrap_or(0..label.len());
return Some(CodeLabel {
text,
runs,
- filter_range: 0..label.len(),
+ filter_range,
});
}
Some((lsp::CompletionItemKind::INTERFACE, _)) => {
@@ -276,10 +300,18 @@ impl super::LspAdapter for GoLspAdapter {
name_offset,
language.highlight_text(&source, 5..5 + text.len()),
);
+ let filter_range = completion
+ .filter_text
+ .as_deref()
+ .and_then(|filter_text| {
+ text.find(filter_text)
+ .map(|start| start..start + filter_text.len())
+ })
+ .unwrap_or(0..label.len());
return Some(CodeLabel {
text,
runs,
- filter_range: 0..label.len(),
+ filter_range,
});
}
Some((lsp::CompletionItemKind::FIELD, detail)) => {
@@ -290,10 +322,18 @@ impl super::LspAdapter for GoLspAdapter {
name_offset,
language.highlight_text(&source, 16..16 + text.len()),
);
+ let filter_range = completion
+ .filter_text
+ .as_deref()
+ .and_then(|filter_text| {
+ text.find(filter_text)
+ .map(|start| start..start + filter_text.len())
+ })
+ .unwrap_or(0..label.len());
return Some(CodeLabel {
text,
runs,
- filter_range: 0..label.len(),
+ filter_range,
});
}
Some((lsp::CompletionItemKind::FUNCTION | lsp::CompletionItemKind::METHOD, detail)) => {
@@ -304,8 +344,16 @@ impl super::LspAdapter for GoLspAdapter {
name_offset,
language.highlight_text(&source, 5..5 + text.len()),
);
+ let filter_range = completion
+ .filter_text
+ .as_deref()
+ .and_then(|filter_text| {
+ text.find(filter_text)
+ .map(|start| start..start + filter_text.len())
+ })
+ .unwrap_or(0..label.len());
return Some(CodeLabel {
- filter_range: 0..label.len(),
+ filter_range,
text,
runs,
});
@@ -268,10 +268,15 @@ impl LspAdapter for PythonLspAdapter {
lsp::CompletionItemKind::CONSTANT => grammar.highlight_id_for_name("constant")?,
_ => return None,
};
+ let filter_range = item
+ .filter_text
+ .as_deref()
+ .and_then(|filter| label.find(filter).map(|ix| ix..ix + filter.len()))
+ .unwrap_or(0..label.len());
Some(language::CodeLabel {
text: label.clone(),
runs: vec![(0..label.len(), highlight_id)],
- filter_range: 0..label.len(),
+ filter_range,
})
}
@@ -1152,10 +1157,15 @@ impl LspAdapter for PyLspAdapter {
lsp::CompletionItemKind::CONSTANT => grammar.highlight_id_for_name("constant")?,
_ => return None,
};
+ let filter_range = item
+ .filter_text
+ .as_deref()
+ .and_then(|filter| label.find(filter).map(|ix| ix..ix + filter.len()))
+ .unwrap_or(0..label.len());
Some(language::CodeLabel {
text: label.clone(),
runs: vec![(0..label.len(), highlight_id)],
- filter_range: 0..label.len(),
+ filter_range,
})
}
@@ -310,10 +310,15 @@ impl LspAdapter for RustLspAdapter {
let source = Rope::from(format!("{prefix}{text} }}"));
let runs =
language.highlight_text(&source, prefix.len()..prefix.len() + text.len());
+ let filter_range = completion
+ .filter_text
+ .as_deref()
+ .and_then(|filter| text.find(filter).map(|ix| ix..ix + filter.len()))
+ .unwrap_or(0..name.len());
return Some(CodeLabel {
text,
runs,
- filter_range: 0..name.len(),
+ filter_range,
});
}
(
@@ -330,10 +335,15 @@ impl LspAdapter for RustLspAdapter {
let source = Rope::from(format!("{prefix}{text} = ();"));
let runs =
language.highlight_text(&source, prefix.len()..prefix.len() + text.len());
+ let filter_range = completion
+ .filter_text
+ .as_deref()
+ .and_then(|filter| text.find(filter).map(|ix| ix..ix + filter.len()))
+ .unwrap_or(0..name.len());
return Some(CodeLabel {
text,
runs,
- filter_range: 0..name.len(),
+ filter_range,
});
}
(
@@ -367,9 +377,13 @@ impl LspAdapter for RustLspAdapter {
text.push(' ');
text.push_str(&detail);
}
-
+ let filter_range = completion
+ .filter_text
+ .as_deref()
+ .and_then(|filter| text.find(filter).map(|ix| ix..ix + filter.len()))
+ .unwrap_or(0..completion.label.find('(').unwrap_or(text.len()));
return Some(CodeLabel {
- filter_range: 0..completion.label.find('(').unwrap_or(text.len()),
+ filter_range,
text,
runs,
});
@@ -378,12 +392,18 @@ impl LspAdapter for RustLspAdapter {
.as_ref()
.map_or(false, |detail| detail.starts_with("macro_rules! "))
{
- let source = Rope::from(completion.label.as_str());
- let runs = language.highlight_text(&source, 0..completion.label.len());
-
+ let text = completion.label.clone();
+ let len = text.len();
+ let source = Rope::from(text.as_str());
+ let runs = language.highlight_text(&source, 0..len);
+ let filter_range = completion
+ .filter_text
+ .as_deref()
+ .and_then(|filter| text.find(filter).map(|ix| ix..ix + filter.len()))
+ .unwrap_or(0..len);
return Some(CodeLabel {
- filter_range: 0..completion.label.len(),
- text: completion.label.clone(),
+ filter_range,
+ text,
runs,
});
}
@@ -406,7 +426,7 @@ impl LspAdapter for RustLspAdapter {
label.push(' ');
label.push_str(detail);
}
- let mut label = CodeLabel::plain(label, None);
+ let mut label = CodeLabel::plain(label, completion.filter_text.as_deref());
if let Some(highlight_name) = highlight_name {
let highlight_id = language.grammar()?.highlight_id_for_name(highlight_name)?;
label.runs.push((
@@ -1181,6 +1201,49 @@ mod tests {
],
})
);
+
+ assert_eq!(
+ adapter
+ .label_for_completion(
+ &lsp::CompletionItem {
+ kind: Some(lsp::CompletionItemKind::METHOD),
+ label: "await.as_deref_mut()".to_string(),
+ filter_text: Some("as_deref_mut".to_string()),
+ label_details: Some(CompletionItemLabelDetails {
+ detail: None,
+ description: Some("fn(&mut self) -> IterMut<'_, T>".to_string()),
+ }),
+ ..Default::default()
+ },
+ &language
+ )
+ .await,
+ Some(CodeLabel {
+ text: "await.as_deref_mut()".to_string(),
+ filter_range: 6..18,
+ runs: vec![],
+ })
+ );
+
+ assert_eq!(
+ adapter
+ .label_for_completion(
+ &lsp::CompletionItem {
+ kind: Some(lsp::CompletionItemKind::FIELD),
+ label: "inner_value".to_string(),
+ filter_text: Some("value".to_string()),
+ detail: Some("String".to_string()),
+ ..Default::default()
+ },
+ &language,
+ )
+ .await,
+ Some(CodeLabel {
+ text: "inner_value: String".to_string(),
+ filter_range: 6..11,
+ runs: vec![(0..11, HighlightId(3)), (13..19, HighlightId(0))],
+ })
+ );
}
#[gpui::test]
@@ -668,11 +668,15 @@ impl LspAdapter for TypeScriptLspAdapter {
} else {
item.label.clone()
};
-
+ let filter_range = item
+ .filter_text
+ .as_deref()
+ .and_then(|filter| text.find(filter).map(|ix| ix..ix + filter.len()))
+ .unwrap_or(0..len);
Some(language::CodeLabel {
text,
runs: vec![(0..len, highlight_id)],
- filter_range: 0..len,
+ filter_range,
})
}
@@ -195,11 +195,15 @@ impl LspAdapter for VtslsLspAdapter {
} else {
item.label.clone()
};
-
+ let filter_range = item
+ .filter_text
+ .as_deref()
+ .and_then(|filter| text.find(filter).map(|ix| ix..ix + filter.len()))
+ .unwrap_or(0..len);
Some(language::CodeLabel {
text,
runs: vec![(0..len, highlight_id)],
- filter_range: 0..len,
+ filter_range,
})
}
@@ -5306,16 +5306,6 @@ impl ProjectItem for Buffer {
}
impl Completion {
- pub fn filter_text(&self) -> &str {
- match &self.source {
- CompletionSource::Lsp { lsp_completion, .. } => lsp_completion
- .filter_text
- .as_deref()
- .unwrap_or_else(|| self.label.filter_text()),
- _ => self.label.filter_text(),
- }
- }
-
pub fn kind(&self) -> Option<CompletionItemKind> {
self.source
// `lsp::CompletionListItemDefaults` has no `kind` field