2023-01-13 02:51:32 -05:00
|
|
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
|
|
|
|
2022-08-22 12:14:59 -04:00
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
use deno_ast::MediaType;
|
|
|
|
use deno_ast::ModuleSpecifier;
|
|
|
|
use deno_ast::ParsedSource;
|
|
|
|
use deno_core::parking_lot::Mutex;
|
|
|
|
use deno_graph::CapturingModuleParser;
|
|
|
|
use deno_graph::ModuleParser;
|
|
|
|
|
2023-10-25 18:13:22 -04:00
|
|
|
#[derive(Default)]
|
2022-08-22 12:14:59 -04:00
|
|
|
pub struct ParsedSourceCache {
|
2023-10-25 18:13:22 -04:00
|
|
|
sources: Mutex<HashMap<ModuleSpecifier, ParsedSource>>,
|
2022-08-22 12:14:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ParsedSourceCache {
|
2023-02-22 14:15:25 -05:00
|
|
|
pub fn get_parsed_source_from_esm_module(
|
2022-08-22 12:14:59 -04:00
|
|
|
&self,
|
2023-02-22 14:15:25 -05:00
|
|
|
module: &deno_graph::EsmModule,
|
|
|
|
) -> Result<ParsedSource, deno_ast::Diagnostic> {
|
|
|
|
self.get_or_parse_module(
|
|
|
|
&module.specifier,
|
|
|
|
module.source.clone(),
|
|
|
|
module.media_type,
|
|
|
|
)
|
2022-08-22 12:14:59 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Gets the matching `ParsedSource` from the cache
|
|
|
|
/// or parses a new one and stores that in the cache.
|
|
|
|
pub fn get_or_parse_module(
|
|
|
|
&self,
|
|
|
|
specifier: &deno_graph::ModuleSpecifier,
|
|
|
|
source: Arc<str>,
|
|
|
|
media_type: MediaType,
|
|
|
|
) -> deno_core::anyhow::Result<ParsedSource, deno_ast::Diagnostic> {
|
2022-08-29 14:24:10 -04:00
|
|
|
let parser = self.as_capturing_parser();
|
2022-08-22 12:14:59 -04:00
|
|
|
// this will conditionally parse because it's using a CapturingModuleParser
|
|
|
|
parser.parse_module(specifier, source, media_type)
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Frees the parsed source from memory.
|
|
|
|
pub fn free(&self, specifier: &ModuleSpecifier) {
|
2023-10-25 18:13:22 -04:00
|
|
|
self.sources.lock().remove(specifier);
|
2022-08-22 12:14:59 -04:00
|
|
|
}
|
2022-08-29 14:24:10 -04:00
|
|
|
|
|
|
|
/// Creates a parser that will reuse a ParsedSource from the store
|
|
|
|
/// if it exists, or else parse.
|
|
|
|
pub fn as_capturing_parser(&self) -> CapturingModuleParser {
|
2023-10-25 18:13:22 -04:00
|
|
|
CapturingModuleParser::new(None, self)
|
2022-08-29 14:24:10 -04:00
|
|
|
}
|
2023-09-07 09:09:16 -04:00
|
|
|
|
2023-10-25 18:13:22 -04:00
|
|
|
pub fn as_store(self: &Arc<Self>) -> Arc<dyn deno_graph::ParsedSourceStore> {
|
|
|
|
self.clone()
|
2023-09-07 09:09:16 -04:00
|
|
|
}
|
2022-08-22 12:14:59 -04:00
|
|
|
}
|
|
|
|
|
2023-10-25 18:13:22 -04:00
|
|
|
/// It's ok that this is racy since in non-LSP situations
|
|
|
|
/// this will only ever store one form of a parsed source
|
|
|
|
/// and in LSP settings the concurrency will be enforced
|
|
|
|
/// at a higher level to ensure this will have the latest
|
|
|
|
/// parsed source.
|
|
|
|
impl deno_graph::ParsedSourceStore for ParsedSourceCache {
|
|
|
|
fn set_parsed_source(
|
2022-08-22 12:14:59 -04:00
|
|
|
&self,
|
2023-10-25 18:13:22 -04:00
|
|
|
specifier: deno_graph::ModuleSpecifier,
|
|
|
|
parsed_source: ParsedSource,
|
|
|
|
) -> Option<ParsedSource> {
|
|
|
|
self.sources.lock().insert(specifier, parsed_source)
|
2023-02-09 09:17:48 -05:00
|
|
|
}
|
|
|
|
|
2023-10-25 18:13:22 -04:00
|
|
|
fn get_parsed_source(
|
2022-08-22 12:14:59 -04:00
|
|
|
&self,
|
2023-10-25 18:13:22 -04:00
|
|
|
specifier: &deno_graph::ModuleSpecifier,
|
|
|
|
) -> Option<ParsedSource> {
|
|
|
|
self.sources.lock().get(specifier).cloned()
|
2022-08-22 12:14:59 -04:00
|
|
|
}
|
|
|
|
}
|