Skip to content
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
122 changes: 115 additions & 7 deletions crates/editor/src/code_completion_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,89 @@ async fn test_fuzzy_over_sort_positions(cx: &mut TestAppContext) {
assert_eq!(matches[2].string, "fetch_code_lens");
}

#[gpui::test]
async fn test_semver_label_sort_by_latest_version(cx: &mut TestAppContext) {
let mut versions = [
"10.4.112",
"10.4.22",
"10.4.2",
"10.4.20",
"10.4.21",
"10.4.12",
// Pre-release versions
"10.4.22-alpha",
"10.4.22-beta.1",
"10.4.22-rc.1",
// Build metadata versions
"10.4.21+build.123",
"10.4.20+20210327",
];
versions.sort_by(|a, b| {
match (
semver::Version::parse(a).ok(),
semver::Version::parse(b).ok(),
) {
(Some(a_ver), Some(b_ver)) => b_ver.cmp(&a_ver),
_ => std::cmp::Ordering::Equal,
}
});
let completions: Vec<_> = versions
.iter()
.enumerate()
.map(|(i, version)| {
// This sort text would come from the LSP
let sort_text = format!("{:08}", i);
CompletionBuilder::new(version, None, &sort_text, None)
})
.collect();

// Case 1: User types just the major and minor version
let matches =
filter_and_sort_matches("10.4.", &completions, SnippetSortOrder::default(), cx).await;
// Versions are ordered by recency (latest first)
let expected_versions = [
"10.4.112",
"10.4.22",
"10.4.22-rc.1",
"10.4.22-beta.1",
"10.4.22-alpha",
"10.4.21+build.123",
"10.4.21",
"10.4.20+20210327",
"10.4.20",
"10.4.12",
"10.4.2",
];
for (match_item, expected) in matches.iter().zip(expected_versions.iter()) {
assert_eq!(match_item.string.as_ref() as &str, *expected);
}

// Case 2: User types the major, minor, and patch version
let matches =
filter_and_sort_matches("10.4.2", &completions, SnippetSortOrder::default(), cx).await;
let expected_versions = [
// Exact match comes first
"10.4.2",
// Ordered by recency with exact major, minor, and patch versions
"10.4.22",
"10.4.22-rc.1",
"10.4.22-beta.1",
"10.4.22-alpha",
"10.4.21+build.123",
"10.4.21",
"10.4.20+20210327",
"10.4.20",
// Versions with non-exact patch versions are ordered by fuzzy score
// Higher fuzzy score than 112 patch version since "2" appears before "1"
// in "12", making it rank higher than "112"
"10.4.12",
"10.4.112",
];
for (match_item, expected) in matches.iter().zip(expected_versions.iter()) {
assert_eq!(match_item.string.as_ref() as &str, *expected);
}
}

async fn test_for_each_prefix<F>(
target: &str,
completions: &Vec<Completion>,
Expand All @@ -259,30 +342,55 @@ struct CompletionBuilder;

impl CompletionBuilder {
fn constant(label: &str, filter_text: Option<&str>, sort_text: &str) -> Completion {
Self::new(label, filter_text, sort_text, CompletionItemKind::CONSTANT)
Self::new(
label,
filter_text,
sort_text,
Some(CompletionItemKind::CONSTANT),
)
}

fn function(label: &str, filter_text: Option<&str>, sort_text: &str) -> Completion {
Self::new(label, filter_text, sort_text, CompletionItemKind::FUNCTION)
Self::new(
label,
filter_text,
sort_text,
Some(CompletionItemKind::FUNCTION),
)
}

fn method(label: &str, filter_text: Option<&str>, sort_text: &str) -> Completion {
Self::new(label, filter_text, sort_text, CompletionItemKind::METHOD)
Self::new(
label,
filter_text,
sort_text,
Some(CompletionItemKind::METHOD),
)
}

fn variable(label: &str, filter_text: Option<&str>, sort_text: &str) -> Completion {
Self::new(label, filter_text, sort_text, CompletionItemKind::VARIABLE)
Self::new(
label,
filter_text,
sort_text,
Some(CompletionItemKind::VARIABLE),
)
}

fn snippet(label: &str, filter_text: Option<&str>, sort_text: &str) -> Completion {
Self::new(label, filter_text, sort_text, CompletionItemKind::SNIPPET)
Self::new(
label,
filter_text,
sort_text,
Some(CompletionItemKind::SNIPPET),
)
}

fn new(
label: &str,
filter_text: Option<&str>,
sort_text: &str,
kind: CompletionItemKind,
kind: Option<CompletionItemKind>,
) -> Completion {
Completion {
replace_range: Anchor::MIN..Anchor::MAX,
Expand All @@ -294,7 +402,7 @@ impl CompletionBuilder {
server_id: LanguageServerId(0),
lsp_completion: Box::new(CompletionItem {
label: label.to_string(),
kind: Some(kind),
kind: kind,
sort_text: Some(sort_text.to_string()),
filter_text: filter_text.map(|text| text.to_string()),
..Default::default()
Expand Down
3 changes: 2 additions & 1 deletion crates/languages/src/json/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ brackets = [
tab_size = 2
prettier_parser_name = "json"
debuggers = ["JavaScript"]

[overrides.string]
completion_query_characters = [":", " "]
completion_query_characters = [":", " ", "."]
Loading