refactor(lsp): remove DocumentInner (#23251)

This commit is contained in:
Nayeem Rahman 2024-04-06 15:36:43 +01:00 committed by GitHub
parent 0e4018a25b
commit f9f37963b7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 96 additions and 106 deletions

View File

@ -178,7 +178,7 @@ impl IndexValid {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub enum AssetOrDocument { pub enum AssetOrDocument {
Document(Document), Document(Arc<Document>),
Asset(AssetDocument), Asset(AssetDocument),
} }
@ -190,7 +190,7 @@ impl AssetOrDocument {
} }
} }
pub fn document(&self) -> Option<&Document> { pub fn document(&self) -> Option<&Arc<Document>> {
match self { match self {
AssetOrDocument::Asset(_) => None, AssetOrDocument::Asset(_) => None,
AssetOrDocument::Document(doc) => Some(doc), AssetOrDocument::Document(doc) => Some(doc),
@ -200,7 +200,7 @@ impl AssetOrDocument {
pub fn text(&self) -> Arc<str> { pub fn text(&self) -> Arc<str> {
match self { match self {
AssetOrDocument::Asset(a) => a.text(), AssetOrDocument::Asset(a) => a.text(),
AssetOrDocument::Document(d) => d.0.text_info.text(), AssetOrDocument::Document(d) => d.text_info.text(),
} }
} }
@ -276,7 +276,7 @@ type ModuleResult = Result<deno_graph::JsModule, deno_graph::ModuleGraphError>;
type ParsedSourceResult = Result<ParsedSource, deno_ast::ParseDiagnostic>; type ParsedSourceResult = Result<ParsedSource, deno_ast::ParseDiagnostic>;
#[derive(Debug)] #[derive(Debug)]
struct DocumentInner { pub struct Document {
/// Contains the last-known-good set of dependencies from parsing the module. /// Contains the last-known-good set of dependencies from parsing the module.
dependencies: Arc<DocumentDependencies>, dependencies: Arc<DocumentDependencies>,
fs_version: String, fs_version: String,
@ -293,9 +293,6 @@ struct DocumentInner {
text_info: SourceTextInfo, text_info: SourceTextInfo,
} }
#[derive(Debug, Clone)]
pub struct Document(Arc<DocumentInner>);
impl Document { impl Document {
fn new( fn new(
specifier: ModuleSpecifier, specifier: ModuleSpecifier,
@ -304,7 +301,7 @@ impl Document {
text_info: SourceTextInfo, text_info: SourceTextInfo,
resolver: &dyn deno_graph::source::Resolver, resolver: &dyn deno_graph::source::Resolver,
npm_resolver: &dyn deno_graph::source::NpmResolver, npm_resolver: &dyn deno_graph::source::NpmResolver,
) -> Self { ) -> Arc<Self> {
// we only ever do `Document::new` on on disk resources that are supposed to // we only ever do `Document::new` on on disk resources that are supposed to
// be diagnosable, unlike `Document::open`, so it is safe to unconditionally // be diagnosable, unlike `Document::open`, so it is safe to unconditionally
// parse the module. // parse the module.
@ -318,7 +315,7 @@ impl Document {
let dependencies = let dependencies =
Arc::new(DocumentDependencies::from_maybe_module(&maybe_module)); Arc::new(DocumentDependencies::from_maybe_module(&maybe_module));
let line_index = Arc::new(LineIndex::new(text_info.text_str())); let line_index = Arc::new(LineIndex::new(text_info.text_str()));
Self(Arc::new(DocumentInner { Arc::new(Document {
dependencies, dependencies,
fs_version, fs_version,
line_index, line_index,
@ -331,42 +328,42 @@ impl Document {
.filter(|_| specifier.scheme() == "file"), .filter(|_| specifier.scheme() == "file"),
text_info, text_info,
specifier, specifier,
})) })
} }
fn maybe_with_new_resolver( fn maybe_with_new_resolver(
&self, &self,
resolver: &dyn deno_graph::source::Resolver, resolver: &dyn deno_graph::source::Resolver,
npm_resolver: &dyn deno_graph::source::NpmResolver, npm_resolver: &dyn deno_graph::source::NpmResolver,
) -> Option<Self> { ) -> Option<Arc<Self>> {
let parsed_source_result = match &self.0.maybe_parsed_source { let parsed_source_result = match &self.maybe_parsed_source {
Some(parsed_source_result) => parsed_source_result.clone(), Some(parsed_source_result) => parsed_source_result.clone(),
None => return None, // nothing to change None => return None, // nothing to change
}; };
let maybe_module = Some(analyze_module( let maybe_module = Some(analyze_module(
&self.0.specifier, &self.specifier,
&parsed_source_result, &parsed_source_result,
self.0.maybe_headers.as_ref(), self.maybe_headers.as_ref(),
resolver, resolver,
npm_resolver, npm_resolver,
)); ));
let dependencies = let dependencies =
Arc::new(DocumentDependencies::from_maybe_module(&maybe_module)); Arc::new(DocumentDependencies::from_maybe_module(&maybe_module));
Some(Self(Arc::new(DocumentInner { Some(Arc::new(Self {
// updated properties // updated properties
dependencies, dependencies,
maybe_module, maybe_module,
maybe_navigation_tree: Mutex::new(None), maybe_navigation_tree: Mutex::new(None),
maybe_parsed_source: Some(parsed_source_result), maybe_parsed_source: Some(parsed_source_result),
// maintain - this should all be copies/clones // maintain - this should all be copies/clones
fs_version: self.0.fs_version.clone(), fs_version: self.fs_version.clone(),
line_index: self.0.line_index.clone(), line_index: self.line_index.clone(),
maybe_headers: self.0.maybe_headers.clone(), maybe_headers: self.maybe_headers.clone(),
maybe_language_id: self.0.maybe_language_id, maybe_language_id: self.maybe_language_id,
maybe_lsp_version: self.0.maybe_lsp_version, maybe_lsp_version: self.maybe_lsp_version,
text_info: self.0.text_info.clone(), text_info: self.text_info.clone(),
specifier: self.0.specifier.clone(), specifier: self.specifier.clone(),
}))) }))
} }
fn open( fn open(
@ -377,7 +374,7 @@ impl Document {
cache: &Arc<dyn HttpCache>, cache: &Arc<dyn HttpCache>,
resolver: &dyn deno_graph::source::Resolver, resolver: &dyn deno_graph::source::Resolver,
npm_resolver: &dyn deno_graph::source::NpmResolver, npm_resolver: &dyn deno_graph::source::NpmResolver,
) -> Self { ) -> Arc<Self> {
let maybe_headers = language_id.as_headers(); let maybe_headers = language_id.as_headers();
let text_info = SourceTextInfo::new(content); let text_info = SourceTextInfo::new(content);
let (maybe_parsed_source, maybe_module) = if language_id.is_diagnosable() { let (maybe_parsed_source, maybe_module) = if language_id.is_diagnosable() {
@ -394,7 +391,7 @@ impl Document {
let dependencies = let dependencies =
Arc::new(DocumentDependencies::from_maybe_module(&maybe_module)); Arc::new(DocumentDependencies::from_maybe_module(&maybe_module));
let line_index = Arc::new(LineIndex::new(text_info.text_str())); let line_index = Arc::new(LineIndex::new(text_info.text_str()));
Self(Arc::new(DocumentInner { Arc::new(Self {
dependencies, dependencies,
fs_version: calculate_fs_version(cache, &specifier) fs_version: calculate_fs_version(cache, &specifier)
.unwrap_or_else(|| "1".to_string()), .unwrap_or_else(|| "1".to_string()),
@ -408,7 +405,7 @@ impl Document {
.filter(|_| specifier.scheme() == "file"), .filter(|_| specifier.scheme() == "file"),
text_info, text_info,
specifier, specifier,
})) })
} }
fn with_change( fn with_change(
@ -417,9 +414,9 @@ impl Document {
changes: Vec<lsp::TextDocumentContentChangeEvent>, changes: Vec<lsp::TextDocumentContentChangeEvent>,
resolver: &dyn deno_graph::source::Resolver, resolver: &dyn deno_graph::source::Resolver,
npm_resolver: &dyn deno_graph::source::NpmResolver, npm_resolver: &dyn deno_graph::source::NpmResolver,
) -> Result<Document, AnyError> { ) -> Result<Arc<Self>, AnyError> {
let mut content = self.0.text_info.text_str().to_string(); let mut content = self.text_info.text_str().to_string();
let mut line_index = self.0.line_index.clone(); let mut line_index = self.line_index.clone();
let mut index_valid = IndexValid::All; let mut index_valid = IndexValid::All;
for change in changes { for change in changes {
if let Some(range) = change.range { if let Some(range) = change.range {
@ -436,19 +433,17 @@ impl Document {
} }
let text_info = SourceTextInfo::from_string(content); let text_info = SourceTextInfo::from_string(content);
let (maybe_parsed_source, maybe_module) = if self let (maybe_parsed_source, maybe_module) = if self
.0
.maybe_language_id .maybe_language_id
.as_ref() .as_ref()
.map(|li| li.is_diagnosable()) .map(|li| li.is_diagnosable())
.unwrap_or(false) .unwrap_or(false)
{ {
let maybe_headers = self let maybe_headers = self
.0
.maybe_language_id .maybe_language_id
.as_ref() .as_ref()
.and_then(|li| li.as_headers()); .and_then(|li| li.as_headers());
parse_and_analyze_module( parse_and_analyze_module(
&self.0.specifier, &self.specifier,
text_info.clone(), text_info.clone(),
maybe_headers, maybe_headers,
resolver, resolver,
@ -460,64 +455,64 @@ impl Document {
let dependencies = if let Some(Ok(module)) = &maybe_module { let dependencies = if let Some(Ok(module)) = &maybe_module {
Arc::new(DocumentDependencies::from_module(module)) Arc::new(DocumentDependencies::from_module(module))
} else { } else {
self.0.dependencies.clone() // use the last known good self.dependencies.clone() // use the last known good
}; };
let line_index = if index_valid == IndexValid::All { let line_index = if index_valid == IndexValid::All {
line_index line_index
} else { } else {
Arc::new(LineIndex::new(text_info.text_str())) Arc::new(LineIndex::new(text_info.text_str()))
}; };
Ok(Document(Arc::new(DocumentInner { Ok(Arc::new(Self {
specifier: self.0.specifier.clone(), specifier: self.specifier.clone(),
fs_version: self.0.fs_version.clone(), fs_version: self.fs_version.clone(),
maybe_language_id: self.0.maybe_language_id, maybe_language_id: self.maybe_language_id,
dependencies, dependencies,
text_info, text_info,
line_index, line_index,
maybe_headers: self.0.maybe_headers.clone(), maybe_headers: self.maybe_headers.clone(),
maybe_module, maybe_module,
maybe_parsed_source: maybe_parsed_source maybe_parsed_source: maybe_parsed_source
.filter(|_| self.0.specifier.scheme() == "file"), .filter(|_| self.specifier.scheme() == "file"),
maybe_lsp_version: Some(version), maybe_lsp_version: Some(version),
maybe_navigation_tree: Mutex::new(None), maybe_navigation_tree: Mutex::new(None),
})))
}
pub fn saved(&self, cache: &Arc<dyn HttpCache>) -> Document {
Document(Arc::new(DocumentInner {
specifier: self.0.specifier.clone(),
fs_version: calculate_fs_version(cache, &self.0.specifier)
.unwrap_or_else(|| "1".to_string()),
maybe_language_id: self.0.maybe_language_id,
dependencies: self.0.dependencies.clone(),
text_info: self.0.text_info.clone(),
line_index: self.0.line_index.clone(),
maybe_headers: self.0.maybe_headers.clone(),
maybe_module: self.0.maybe_module.clone(),
maybe_parsed_source: self.0.maybe_parsed_source.clone(),
maybe_lsp_version: self.0.maybe_lsp_version,
maybe_navigation_tree: Mutex::new(None),
})) }))
} }
pub fn saved(&self, cache: &Arc<dyn HttpCache>) -> Arc<Self> {
Arc::new(Self {
specifier: self.specifier.clone(),
fs_version: calculate_fs_version(cache, &self.specifier)
.unwrap_or_else(|| "1".to_string()),
maybe_language_id: self.maybe_language_id,
dependencies: self.dependencies.clone(),
text_info: self.text_info.clone(),
line_index: self.line_index.clone(),
maybe_headers: self.maybe_headers.clone(),
maybe_module: self.maybe_module.clone(),
maybe_parsed_source: self.maybe_parsed_source.clone(),
maybe_lsp_version: self.maybe_lsp_version,
maybe_navigation_tree: Mutex::new(None),
})
}
pub fn specifier(&self) -> &ModuleSpecifier { pub fn specifier(&self) -> &ModuleSpecifier {
&self.0.specifier &self.specifier
} }
pub fn content(&self) -> Arc<str> { pub fn content(&self) -> Arc<str> {
self.0.text_info.text() self.text_info.text()
} }
pub fn text_info(&self) -> SourceTextInfo { pub fn text_info(&self) -> SourceTextInfo {
self.0.text_info.clone() self.text_info.clone()
} }
pub fn line_index(&self) -> Arc<LineIndex> { pub fn line_index(&self) -> Arc<LineIndex> {
self.0.line_index.clone() self.line_index.clone()
} }
fn fs_version(&self) -> &str { fn fs_version(&self) -> &str {
self.0.fs_version.as_str() self.fs_version.as_str()
} }
pub fn script_version(&self) -> String { pub fn script_version(&self) -> String {
@ -545,12 +540,11 @@ impl Document {
} }
pub fn is_open(&self) -> bool { pub fn is_open(&self) -> bool {
self.0.maybe_lsp_version.is_some() self.maybe_lsp_version.is_some()
} }
pub fn maybe_types_dependency(&self) -> Resolution { pub fn maybe_types_dependency(&self) -> Resolution {
if let Some(types_dep) = self.0.dependencies.maybe_types_dependency.as_ref() if let Some(types_dep) = self.dependencies.maybe_types_dependency.as_ref() {
{
types_dep.dependency.clone() types_dep.dependency.clone()
} else { } else {
Resolution::None Resolution::None
@ -558,42 +552,41 @@ impl Document {
} }
pub fn media_type(&self) -> MediaType { pub fn media_type(&self) -> MediaType {
if let Some(Ok(module)) = &self.0.maybe_module { if let Some(Ok(module)) = &self.maybe_module {
return module.media_type; return module.media_type;
} }
let specifier_media_type = MediaType::from_specifier(&self.0.specifier); let specifier_media_type = MediaType::from_specifier(&self.specifier);
if specifier_media_type != MediaType::Unknown { if specifier_media_type != MediaType::Unknown {
return specifier_media_type; return specifier_media_type;
} }
self self
.0
.maybe_language_id .maybe_language_id
.map(|id| id.as_media_type()) .map(|id| id.as_media_type())
.unwrap_or(MediaType::Unknown) .unwrap_or(MediaType::Unknown)
} }
pub fn maybe_language_id(&self) -> Option<LanguageId> { pub fn maybe_language_id(&self) -> Option<LanguageId> {
self.0.maybe_language_id self.maybe_language_id
} }
/// Returns the current language server client version if any. /// Returns the current language server client version if any.
pub fn maybe_lsp_version(&self) -> Option<i32> { pub fn maybe_lsp_version(&self) -> Option<i32> {
self.0.maybe_lsp_version self.maybe_lsp_version
} }
fn maybe_js_module(&self) -> Option<&ModuleResult> { fn maybe_js_module(&self) -> Option<&ModuleResult> {
self.0.maybe_module.as_ref() self.maybe_module.as_ref()
} }
pub fn maybe_parsed_source( pub fn maybe_parsed_source(
&self, &self,
) -> Option<Result<deno_ast::ParsedSource, deno_ast::ParseDiagnostic>> { ) -> Option<Result<deno_ast::ParsedSource, deno_ast::ParseDiagnostic>> {
self.0.maybe_parsed_source.clone() self.maybe_parsed_source.clone()
} }
pub fn maybe_navigation_tree(&self) -> Option<Arc<tsc::NavigationTree>> { pub fn maybe_navigation_tree(&self) -> Option<Arc<tsc::NavigationTree>> {
self.0.maybe_navigation_tree.lock().clone() self.maybe_navigation_tree.lock().clone()
} }
pub fn update_navigation_tree_if_version( pub fn update_navigation_tree_if_version(
@ -606,12 +599,12 @@ impl Document {
// and setting the navigation tree, because the document is immutable // and setting the navigation tree, because the document is immutable
// and this is enforced by it being wrapped in an Arc. // and this is enforced by it being wrapped in an Arc.
if self.script_version() == script_version { if self.script_version() == script_version {
*self.0.maybe_navigation_tree.lock() = Some(tree); *self.maybe_navigation_tree.lock() = Some(tree);
} }
} }
pub fn dependencies(&self) -> &IndexMap<String, deno_graph::Dependency> { pub fn dependencies(&self) -> &IndexMap<String, deno_graph::Dependency> {
&self.0.dependencies.deps &self.dependencies.deps
} }
/// If the supplied position is within a dependency range, return the resolved /// If the supplied position is within a dependency range, return the resolved
@ -727,7 +720,7 @@ impl RedirectResolver {
#[derive(Debug, Default)] #[derive(Debug, Default)]
struct FileSystemDocuments { struct FileSystemDocuments {
docs: HashMap<ModuleSpecifier, Document>, docs: HashMap<ModuleSpecifier, Arc<Document>>,
dirty: bool, dirty: bool,
} }
@ -738,7 +731,7 @@ impl FileSystemDocuments {
resolver: &dyn deno_graph::source::Resolver, resolver: &dyn deno_graph::source::Resolver,
specifier: &ModuleSpecifier, specifier: &ModuleSpecifier,
npm_resolver: &dyn deno_graph::source::NpmResolver, npm_resolver: &dyn deno_graph::source::NpmResolver,
) -> Option<Document> { ) -> Option<Arc<Document>> {
let fs_version = if specifier.scheme() == "data" { let fs_version = if specifier.scheme() == "data" {
Some("1".to_string()) Some("1".to_string())
} else { } else {
@ -761,7 +754,7 @@ impl FileSystemDocuments {
resolver: &dyn deno_graph::source::Resolver, resolver: &dyn deno_graph::source::Resolver,
specifier: &ModuleSpecifier, specifier: &ModuleSpecifier,
npm_resolver: &dyn deno_graph::source::NpmResolver, npm_resolver: &dyn deno_graph::source::NpmResolver,
) -> Option<Document> { ) -> Option<Arc<Document>> {
let doc = if specifier.scheme() == "file" { let doc = if specifier.scheme() == "file" {
let path = specifier_to_file_path(specifier).ok()?; let path = specifier_to_file_path(specifier).ok()?;
let fs_version = calculate_fs_version_at_path(&path)?; let fs_version = calculate_fs_version_at_path(&path)?;
@ -845,7 +838,7 @@ pub struct Documents {
/// that depend on the key. /// that depend on the key.
dependents_map: Arc<HashMap<ModuleSpecifier, HashSet<ModuleSpecifier>>>, dependents_map: Arc<HashMap<ModuleSpecifier, HashSet<ModuleSpecifier>>>,
/// A map of documents that are "open" in the language server. /// A map of documents that are "open" in the language server.
open_docs: HashMap<ModuleSpecifier, Document>, open_docs: HashMap<ModuleSpecifier, Arc<Document>>,
/// Documents stored on the file system. /// Documents stored on the file system.
file_system_docs: Arc<Mutex<FileSystemDocuments>>, file_system_docs: Arc<Mutex<FileSystemDocuments>>,
/// Any imports to the context supplied by configuration files. This is like /// Any imports to the context supplied by configuration files. This is like
@ -923,7 +916,7 @@ impl Documents {
version: i32, version: i32,
language_id: LanguageId, language_id: LanguageId,
content: Arc<str>, content: Arc<str>,
) -> Document { ) -> Arc<Document> {
let resolver = self.get_resolver(); let resolver = self.get_resolver();
let npm_resolver = self.get_npm_resolver(); let npm_resolver = self.get_npm_resolver();
let document = Document::open( let document = Document::open(
@ -952,7 +945,7 @@ impl Documents {
specifier: &ModuleSpecifier, specifier: &ModuleSpecifier,
version: i32, version: i32,
changes: Vec<lsp::TextDocumentContentChangeEvent>, changes: Vec<lsp::TextDocumentContentChangeEvent>,
) -> Result<Document, AnyError> { ) -> Result<Arc<Document>, AnyError> {
let doc = self let doc = self
.open_docs .open_docs
.get(specifier) .get(specifier)
@ -1135,7 +1128,10 @@ impl Documents {
} }
/// Return a document for the specifier. /// Return a document for the specifier.
pub fn get(&self, original_specifier: &ModuleSpecifier) -> Option<Document> { pub fn get(
&self,
original_specifier: &ModuleSpecifier,
) -> Option<Arc<Document>> {
let specifier = self.resolve_specifier(original_specifier)?; let specifier = self.resolve_specifier(original_specifier)?;
if let Some(document) = self.open_docs.get(&specifier) { if let Some(document) = self.open_docs.get(&specifier) {
Some(document.clone()) Some(document.clone())
@ -1152,7 +1148,7 @@ impl Documents {
/// Return a collection of documents that are contained in the document store /// Return a collection of documents that are contained in the document store
/// based on the provided filter. /// based on the provided filter.
pub fn documents(&self, filter: DocumentsFilter) -> Vec<Document> { pub fn documents(&self, filter: DocumentsFilter) -> Vec<Arc<Document>> {
match filter { match filter {
DocumentsFilter::OpenDiagnosable => self DocumentsFilter::OpenDiagnosable => self
.open_docs .open_docs
@ -1203,7 +1199,7 @@ impl Documents {
let referrer = referrer_doc.specifier(); let referrer = referrer_doc.specifier();
let dependencies = match referrer_doc { let dependencies = match referrer_doc {
AssetOrDocument::Asset(_) => None, AssetOrDocument::Asset(_) => None,
AssetOrDocument::Document(doc) => Some(doc.0.dependencies.clone()), AssetOrDocument::Document(doc) => Some(doc.dependencies.clone()),
}; };
let mut results = Vec::new(); let mut results = Vec::new();
for specifier in specifiers { for specifier in specifiers {
@ -1605,7 +1601,7 @@ fn node_resolve_npm_req_ref(
/// Loader that will look at the open documents. /// Loader that will look at the open documents.
pub struct OpenDocumentsGraphLoader<'a> { pub struct OpenDocumentsGraphLoader<'a> {
pub inner_loader: &'a mut dyn deno_graph::source::Loader, pub inner_loader: &'a mut dyn deno_graph::source::Loader,
pub open_docs: &'a HashMap<ModuleSpecifier, Document>, pub open_docs: &'a HashMap<ModuleSpecifier, Arc<Document>>,
pub unstable_sloppy_imports: bool, pub unstable_sloppy_imports: bool,
} }

View File

@ -286,7 +286,7 @@ impl LanguageServer {
async fn create_graph_for_caching( async fn create_graph_for_caching(
cli_options: CliOptions, cli_options: CliOptions,
roots: Vec<ModuleSpecifier>, roots: Vec<ModuleSpecifier>,
open_docs: Vec<Document>, open_docs: Vec<Arc<Document>>,
) -> Result<(), AnyError> { ) -> Result<(), AnyError> {
let open_docs = open_docs let open_docs = open_docs
.into_iter() .into_iter()
@ -1193,7 +1193,7 @@ impl Inner {
&mut self, &mut self,
specifier: &ModuleSpecifier, specifier: &ModuleSpecifier,
params: DidOpenTextDocumentParams, params: DidOpenTextDocumentParams,
) -> Document { ) -> Arc<Document> {
let mark = self.performance.mark_with_args("lsp.did_open", &params); let mark = self.performance.mark_with_args("lsp.did_open", &params);
let language_id = let language_id =
params params
@ -3452,7 +3452,7 @@ impl tower_lsp::LanguageServer for LanguageServer {
struct PrepareCacheResult { struct PrepareCacheResult {
cli_options: CliOptions, cli_options: CliOptions,
roots: Vec<ModuleSpecifier>, roots: Vec<ModuleSpecifier>,
open_docs: Vec<Document>, open_docs: Vec<Arc<Document>>,
mark: PerformanceMark, mark: PerformanceMark,
} }

View File

@ -1013,54 +1013,48 @@ impl TsServer {
} }
} }
/// An lsp representation of an asset in memory, that has either been retrieved
/// from static assets built into Rust, or static assets built into tsc.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct AssetDocumentInner { pub struct AssetDocument {
specifier: ModuleSpecifier, specifier: ModuleSpecifier,
text: Arc<str>, text: Arc<str>,
line_index: Arc<LineIndex>, line_index: Arc<LineIndex>,
maybe_navigation_tree: Option<Arc<NavigationTree>>, maybe_navigation_tree: Option<Arc<NavigationTree>>,
} }
/// An lsp representation of an asset in memory, that has either been retrieved
/// from static assets built into Rust, or static assets built into tsc.
#[derive(Debug, Clone)]
pub struct AssetDocument(Arc<AssetDocumentInner>);
impl AssetDocument { impl AssetDocument {
pub fn new(specifier: ModuleSpecifier, text: impl AsRef<str>) -> Self { pub fn new(specifier: ModuleSpecifier, text: impl AsRef<str>) -> Self {
let text = text.as_ref(); let text = text.as_ref();
Self(Arc::new(AssetDocumentInner { Self {
specifier, specifier,
text: text.into(), text: text.into(),
line_index: Arc::new(LineIndex::new(text)), line_index: Arc::new(LineIndex::new(text)),
maybe_navigation_tree: None, maybe_navigation_tree: None,
})) }
} }
pub fn specifier(&self) -> &ModuleSpecifier { pub fn specifier(&self) -> &ModuleSpecifier {
&self.0.specifier &self.specifier
} }
pub fn with_navigation_tree( pub fn with_navigation_tree(&self, tree: Arc<NavigationTree>) -> Self {
&self, Self {
tree: Arc<NavigationTree>,
) -> AssetDocument {
AssetDocument(Arc::new(AssetDocumentInner {
maybe_navigation_tree: Some(tree), maybe_navigation_tree: Some(tree),
..(*self.0).clone() ..self.clone()
})) }
} }
pub fn text(&self) -> Arc<str> { pub fn text(&self) -> Arc<str> {
self.0.text.clone() self.text.clone()
} }
pub fn line_index(&self) -> Arc<LineIndex> { pub fn line_index(&self) -> Arc<LineIndex> {
self.0.line_index.clone() self.line_index.clone()
} }
pub fn maybe_navigation_tree(&self) -> Option<Arc<NavigationTree>> { pub fn maybe_navigation_tree(&self) -> Option<Arc<NavigationTree>> {
self.0.maybe_navigation_tree.clone() self.maybe_navigation_tree.clone()
} }
} }