summaryrefslogtreecommitdiff
path: root/cli/lsp/utils.rs
blob: 8f4de9c05e8ef5892518bb950120fa90fa42e29f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.

use deno_core::error::AnyError;
use deno_core::url::Position;
use deno_core::url::Url;
use deno_core::ModuleSpecifier;

/// Normalizes a file name returned from the TypeScript compiler into a URI that
/// should be sent by the language server to the client.
pub fn normalize_file_name(file_name: &str) -> Result<Url, AnyError> {
  let specifier_str = if file_name.starts_with("file://") {
    file_name.to_string()
  } else {
    format!("deno:///{}", file_name.replacen("://", "/", 1))
  };
  Url::parse(&specifier_str).map_err(|err| err.into())
}

pub fn normalize_specifier(
  specifier: &ModuleSpecifier,
) -> Result<Url, AnyError> {
  let url = specifier.as_url();
  if url.scheme() == "file" {
    Ok(url.clone())
  } else {
    let specifier_str =
      format!("deno:///{}", url.as_str().replacen("://", "/", 1));
    Url::parse(&specifier_str).map_err(|err| err.into())
  }
}

/// Normalize URLs from the client, where "virtual" `deno:///` URLs are
/// converted into proper module specifiers.
pub fn normalize_url(url: Url) -> ModuleSpecifier {
  if url.scheme() == "deno"
    && (url.path().starts_with("/http") || url.path().starts_with("/asset"))
  {
    let specifier_str = url[Position::BeforePath..]
      .replacen("/", "", 1)
      .replacen("/", "://", 1);
    if let Ok(specifier) =
      percent_encoding::percent_decode_str(&specifier_str).decode_utf8()
    {
      if let Ok(specifier) = ModuleSpecifier::resolve_url(&specifier) {
        return specifier;
      }
    }
  }
  ModuleSpecifier::from(url)
}

#[cfg(test)]
mod tests {
  use super::*;

  #[test]
  fn test_normalize_file_name() {
    let fixture = "https://deno.land/x/mod.ts";
    let actual = normalize_file_name(fixture).unwrap();
    let expected = Url::parse("deno:///https/deno.land/x/mod.ts").unwrap();
    assert_eq!(actual, expected);
  }

  #[test]
  fn test_normalize_specifier() {
    let fixture =
      ModuleSpecifier::resolve_url("https://deno.land/x/mod.ts").unwrap();
    let actual = normalize_specifier(&fixture).unwrap();
    let expected = Url::parse("deno:///https/deno.land/x/mod.ts").unwrap();
    assert_eq!(actual, expected);
  }

  #[test]
  fn test_normalize_url() {
    let fixture = Url::parse("deno:///https/deno.land/x/mod.ts").unwrap();
    let actual = normalize_url(fixture);
    assert_eq!(
      actual,
      ModuleSpecifier::resolve_url("https://deno.land/x/mod.ts").unwrap()
    );
  }
}