summaryrefslogtreecommitdiff
path: root/cli/lsp/utils.rs
blob: 3bdd00875acdc1a46f28645f3db3ef87a5fe012d (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
// Copyright 2018-2020 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())
}

/// 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_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()
    );
  }
}