summaryrefslogtreecommitdiff
path: root/cli/lsp/document_source.rs
blob: c2bef884ebcd3cd14096db593ab50bdff3ee132e (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
use deno_ast::Diagnostic;
use deno_ast::MediaType;
use deno_ast::ParsedSource;
use deno_ast::SourceTextInfo;
use deno_core::ModuleSpecifier;
use once_cell::sync::OnceCell;
use std::sync::Arc;

use super::analysis;
use super::text::LineIndex;

#[derive(Debug)]
struct DocumentSourceInner {
  specifier: ModuleSpecifier,
  media_type: MediaType,
  text_info: SourceTextInfo,
  parsed_module: OnceCell<Result<ParsedSource, Diagnostic>>,
  line_index: LineIndex,
}

/// Immutable information about a document.
#[derive(Debug, Clone)]
pub struct DocumentSource {
  inner: Arc<DocumentSourceInner>,
}

impl DocumentSource {
  pub fn new(
    specifier: &ModuleSpecifier,
    media_type: MediaType,
    text: Arc<String>,
    line_index: LineIndex,
  ) -> Self {
    Self {
      inner: Arc::new(DocumentSourceInner {
        specifier: specifier.clone(),
        media_type,
        text_info: SourceTextInfo::new(text),
        parsed_module: OnceCell::new(),
        line_index,
      }),
    }
  }

  pub fn text_info(&self) -> &SourceTextInfo {
    &self.inner.text_info
  }

  pub fn line_index(&self) -> &LineIndex {
    &self.inner.line_index
  }

  pub fn module(&self) -> Option<&Result<ParsedSource, Diagnostic>> {
    let is_parsable = matches!(
      self.inner.media_type,
      MediaType::JavaScript
        | MediaType::Jsx
        | MediaType::TypeScript
        | MediaType::Tsx
        | MediaType::Dts,
    );
    if is_parsable {
      // lazily parse the module
      Some(self.inner.parsed_module.get_or_init(|| {
        analysis::parse_module(
          &self.inner.specifier,
          self.inner.text_info.clone(),
          self.inner.media_type,
        )
      }))
    } else {
      None
    }
  }
}