/
githubmirror
/
deno
Обзор
Документация
Войти
/
githubmirror
/
deno
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
libs/resolver/cache/parsed_source.rs
189 строк
5 KB
David Sherret
refactor: force a reason on clippy overrides (#32761)
16 мар 2026, 15:41
Не верифицирован
16 мар 2026, 15:41
39a07b2
Код
Авторство
О чём код?
// Copyright 2018-2026 the Deno authors. MIT license. use deno_ast::ParsedSource; use deno_graph::ast::CapturingEsParser; use deno_graph::ast::DefaultEsParser; use deno_graph::ast::EsParser; use deno_graph::ast::ParsedSourceStore; use deno_media_type::MediaType; use url::Url; /// Lazily parses JS/TS sources from a `deno_graph::ModuleGraph` given /// a `ParsedSourceCache`. Note that deno_graph doesn't necessarily cause /// files to end up in the `ParsedSourceCache` because it might have all /// the information it needs via caching in order to skip parsing. #[derive(Clone, Copy)] pub struct LazyGraphSourceParser<'a> { cache: &'a ParsedSourceCache, graph: &'a deno_graph::ModuleGraph, } impl<'a> LazyGraphSourceParser<'a> { pub fn new( cache: &'a ParsedSourceCache, graph: &'a deno_graph::ModuleGraph, ) -> Self { Self { cache, graph } } #[allow( clippy::result_large_err, reason = "ParseDiagnostic is intentionally large" )] pub fn get_or_parse_source( &self, module_specifier: &Url, ) -> Result<Option<ParsedSource>, deno_ast::ParseDiagnostic> { let Some(deno_graph::Module::Js(module)) = self.graph.get(module_specifier) else { return Ok(None); }; self .cache .get_parsed_source_from_js_module(module) .map(Some) } } #[allow( clippy::disallowed_types, reason = "source text is always stored as Arc<str>" )] type ArcStr = std::sync::Arc<str>; #[allow(clippy::disallowed_types, reason = "definition")] pub type ParsedSourceCacheRc = deno_maybe_sync::MaybeArc<ParsedSourceCache>; #[derive(Debug, Default)] pub struct ParsedSourceCache { sources: deno_maybe_sync::MaybeDashMap<Url, ParsedSource>, } impl ParsedSourceCache { #[allow( clippy::result_large_err, reason = "ParseDiagnostic is intentionally large" )] pub fn get_parsed_source_from_js_module( &self, module: &deno_graph::JsModule, ) -> Result<ParsedSource, deno_ast::ParseDiagnostic> { self.get_matching_parsed_source( &module.specifier, module.media_type, module.source.text.clone(), ) } #[allow( clippy::result_large_err, reason = "ParseDiagnostic is intentionally large" )] pub fn get_matching_parsed_source( &self, specifier: &Url, media_type: MediaType, source: ArcStr, ) -> Result<ParsedSource, deno_ast::ParseDiagnostic> { let parser = self.as_capturing_parser(); // this will conditionally parse because it's using a CapturingEsParser parser.parse_program(deno_graph::ast::ParseOptions { specifier, source, media_type, scope_analysis: false, }) } #[allow( clippy::result_large_err, clippy::disallowed_types, reason = "ParseDiagnostic is intentionally large, ArcStr type alias" )] pub fn remove_or_parse_module( &self, specifier: &Url, media_type: MediaType, source: ArcStr, ) -> Result<ParsedSource, deno_ast::ParseDiagnostic> { if let Some(parsed_source) = self.remove_parsed_source(specifier) && parsed_source.media_type() == media_type && parsed_source.text().as_ref() == source.as_ref() { // note: message used tests log::debug!("Removed parsed source: {}", specifier); return Ok(parsed_source); } let options = deno_graph::ast::ParseOptions { specifier, source, media_type, scope_analysis: false, }; DefaultEsParser.parse_program(options) } /// Frees the parsed source from memory. pub fn free(&self, specifier: &Url) { self.sources.remove(specifier); } /// Fress all parsed sources from memory. pub fn free_all(&self) { self.sources.clear(); } /// Creates a parser that will reuse a ParsedSource from the store /// if it exists, or else parse. pub fn as_capturing_parser(&self) -> CapturingEsParser<'_> { CapturingEsParser::new(None, self) } #[allow( clippy::len_without_is_empty, reason = "is_empty is not needed for this type" )] pub fn len(&self) -> usize { self.sources.len() } } /// 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 ParsedSourceStore for ParsedSourceCache { fn set_parsed_source( &self, specifier: Url, parsed_source: ParsedSource, ) -> Option<ParsedSource> { self.sources.insert(specifier, parsed_source) } fn get_parsed_source(&self, specifier: &Url) -> Option<ParsedSource> { self.sources.get(specifier).map(|p| p.clone()) } fn remove_parsed_source(&self, specifier: &Url) -> Option<ParsedSource> { self.sources.remove(specifier).map(|(_, p)| p) } fn get_scope_analysis_parsed_source( &self, specifier: &Url, ) -> Option<ParsedSource> { { let parsed_source = self.sources.get(specifier)?; if parsed_source.has_scope_analysis() { return Some(parsed_source.clone()); } } // upgrade to have scope analysis let (specifier, parsed_source) = self.sources.remove(specifier)?; let parsed_source = parsed_source.into_with_scope_analysis(); self.sources.insert(specifier, parsed_source.clone()); Some(parsed_source) } }