summaryrefslogtreecommitdiff
path: root/cli/lsp/completions.rs
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2022-11-25 09:16:56 -0500
committerGitHub <noreply@github.com>2022-11-25 09:16:56 -0500
commitd80af8324d61ce6fa54f6c9c4a2658c18b9c2428 (patch)
tree029a74086ac82713573a891acbd7bb2155b11752 /cli/lsp/completions.rs
parent3f79c9b6e5cb5ab27bd5b67dfa13ca5c03218fdb (diff)
refactor(lsp): consolidate relative_specifier (#16780)
Closes #14840
Diffstat (limited to 'cli/lsp/completions.rs')
-rw-r--r--cli/lsp/completions.rs176
1 files changed, 3 insertions, 173 deletions
diff --git a/cli/lsp/completions.rs b/cli/lsp/completions.rs
index b223c71a2..67978fbc9 100644
--- a/cli/lsp/completions.rs
+++ b/cli/lsp/completions.rs
@@ -8,6 +8,7 @@ use super::registries::ModuleRegistry;
use super::tsc;
use crate::fs_util::is_supported_ext;
+use crate::fs_util::relative_specifier;
use crate::fs_util::specifier_to_file_path;
use deno_ast::LineAndColumnIndex;
@@ -378,7 +379,7 @@ fn get_local_completions(
if &entry_specifier == base {
return None;
}
- let full_text = relative_specifier(&entry_specifier, base);
+ let full_text = relative_specifier(base, &entry_specifier)?;
// this weeds out situations where we are browsing in the parent, but
// we want to filter out non-matches when the completion is manually
// invoked by the user, but still allows for things like `../src/../`
@@ -443,7 +444,7 @@ fn get_relative_specifiers(
.iter()
.filter_map(|s| {
if s != base {
- Some(relative_specifier(s, base))
+ Some(relative_specifier(base, s).unwrap_or_else(|| s.to_string()))
} else {
None
}
@@ -501,103 +502,6 @@ fn get_workspace_completions(
.collect()
}
-/// Converts a specifier into a relative specifier to the provided base
-/// specifier as a string. If a relative path cannot be found, then the
-/// specifier is simply returned as a string.
-///
-/// ```
-/// use deno_core::resolve_url;
-///
-/// let specifier = resolve_url("file:///a/b.ts").unwrap();
-/// let base = resolve_url("file:///a/c/d.ts").unwrap();
-/// assert_eq!(relative_specifier(&specifier, &base), "../b.ts");
-/// ```
-///
-pub fn relative_specifier(
- specifier: &ModuleSpecifier,
- base: &ModuleSpecifier,
-) -> String {
- if specifier.cannot_be_a_base()
- || base.cannot_be_a_base()
- || specifier.scheme() != base.scheme()
- || specifier.host() != base.host()
- || specifier.port_or_known_default() != base.port_or_known_default()
- {
- if specifier.scheme() == "file" {
- specifier_to_file_path(specifier)
- .unwrap()
- .to_string_lossy()
- .into()
- } else {
- specifier.as_str().into()
- }
- } else if let (Some(iter_a), Some(iter_b)) =
- (specifier.path_segments(), base.path_segments())
- {
- let mut vec_a: Vec<&str> = iter_a.collect();
- let mut vec_b: Vec<&str> = iter_b.collect();
- let last_a = if !specifier.path().ends_with('/') && !vec_a.is_empty() {
- vec_a.pop().unwrap()
- } else {
- ""
- };
- let is_dir_b = base.path().ends_with('/');
- if !is_dir_b && !vec_b.is_empty() {
- vec_b.pop();
- }
- if !vec_a.is_empty() && !vec_b.is_empty() && base.path() != "/" {
- let mut parts: Vec<&str> = Vec::new();
- let mut segments_a = vec_a.into_iter();
- let mut segments_b = vec_b.into_iter();
- loop {
- match (segments_a.next(), segments_b.next()) {
- (None, None) => break,
- (Some(a), None) => {
- if parts.is_empty() {
- parts.push(CURRENT_PATH);
- }
- parts.push(a);
- parts.extend(segments_a.by_ref());
- break;
- }
- (None, _) if is_dir_b => parts.push(CURRENT_PATH),
- (None, _) => parts.push(PARENT_PATH),
- (Some(a), Some(b)) if parts.is_empty() && a == b => (),
- (Some(a), Some(b)) if b == CURRENT_PATH => parts.push(a),
- (Some(_), Some(b)) if b == PARENT_PATH => {
- return specifier[Position::BeforePath..].to_string()
- }
- (Some(a), Some(_)) => {
- if parts.is_empty() && is_dir_b {
- parts.push(CURRENT_PATH);
- } else {
- parts.push(PARENT_PATH);
- }
- // actually the clippy suggestions here are less readable for once
- #[allow(clippy::same_item_push)]
- for _ in segments_b {
- parts.push(PARENT_PATH);
- }
- parts.push(a);
- parts.extend(segments_a.by_ref());
- break;
- }
- }
- }
- if parts.is_empty() {
- format!("./{}{}", last_a, &specifier[Position::AfterPath..])
- } else {
- parts.push(last_a);
- format!("{}{}", parts.join("/"), &specifier[Position::AfterPath..])
- }
- } else {
- specifier[Position::BeforePath..].into()
- }
- } else {
- specifier[Position::BeforePath..].into()
- }
-}
-
#[cfg(test)]
mod tests {
use super::*;
@@ -672,80 +576,6 @@ mod tests {
}
#[test]
- fn test_relative_specifier() {
- let fixtures: Vec<(&str, &str, &str)> = vec![
- (
- "https://deno.land/x/a/b/c.ts",
- "https://deno.land/x/a/b/d.ts",
- "./c.ts",
- ),
- (
- "https://deno.land/x/a/c.ts",
- "https://deno.land/x/a/b/d.ts",
- "../c.ts",
- ),
- (
- "https://deno.land/x/a/b/c/d.ts",
- "https://deno.land/x/a/b/d.ts",
- "./c/d.ts",
- ),
- (
- "https://deno.land/x/a/b/c/d.ts",
- "https://deno.land/x/a/b/c/",
- "./d.ts",
- ),
- (
- "https://deno.land/x/a/b/c/d/e.ts",
- "https://deno.land/x/a/b/c/",
- "./d/e.ts",
- ),
- (
- "https://deno.land/x/a/b/c/d/e.ts",
- "https://deno.land/x/a/b/c/f.ts",
- "./d/e.ts",
- ),
- (
- "https://deno.land/x/a/c.ts?foo=bar",
- "https://deno.land/x/a/b/d.ts",
- "../c.ts?foo=bar",
- ),
- (
- "https://deno.land/x/a/b/c.ts",
- "https://deno.land/x/a/b/d.ts?foo=bar",
- "./c.ts",
- ),
- #[cfg(not(windows))]
- ("file:///a/b/c.ts", "file:///a/b/d.ts", "./c.ts"),
- #[cfg(not(windows))]
- (
- "file:///a/b/c.ts",
- "https://deno.land/x/a/b/c.ts",
- "/a/b/c.ts",
- ),
- (
- "https://deno.land/x/a/b/c.ts",
- "https://deno.land/",
- "/x/a/b/c.ts",
- ),
- (
- "https://deno.land/x/a/b/c.ts",
- "https://deno.land/x/d/e/f.ts",
- "../../a/b/c.ts",
- ),
- ];
- for (specifier_str, base_str, expected) in fixtures {
- let specifier = resolve_url(specifier_str).unwrap();
- let base = resolve_url(base_str).unwrap();
- let actual = relative_specifier(&specifier, &base);
- assert_eq!(
- actual, expected,
- "specifier: \"{}\" base: \"{}\"",
- specifier_str, base_str
- );
- }
- }
-
- #[test]
fn test_get_local_completions() {
let temp_dir = TempDir::new();
let fixtures = temp_dir.path().join("fixtures");