mirror of
https://github.com/denoland/deno.git
synced 2024-11-28 16:20:57 -05:00
feat(lsp): add cache command (#8911)
This commit is contained in:
parent
e8a81724bb
commit
8011eced14
10 changed files with 165 additions and 111 deletions
|
@ -364,25 +364,25 @@ impl FileFetcher {
|
|||
specifier: &ModuleSpecifier,
|
||||
permissions: &Permissions,
|
||||
redirect_limit: i64,
|
||||
) -> Pin<Box<dyn Future<Output = Result<File, AnyError>>>> {
|
||||
) -> Pin<Box<dyn Future<Output = Result<File, AnyError>> + Send>> {
|
||||
debug!("FileFetcher::fetch_remote() - specifier: {}", specifier);
|
||||
if redirect_limit < 0 {
|
||||
return futures::future::err(custom_error("Http", "Too many redirects."))
|
||||
.boxed_local();
|
||||
.boxed();
|
||||
}
|
||||
|
||||
if let Err(err) = permissions.check_specifier(specifier) {
|
||||
return futures::future::err(err).boxed_local();
|
||||
return futures::future::err(err).boxed();
|
||||
}
|
||||
|
||||
if self.cache_setting.should_use(specifier) {
|
||||
match self.fetch_cached(specifier, redirect_limit) {
|
||||
Ok(Some(file)) => {
|
||||
return futures::future::ok(file).boxed_local();
|
||||
return futures::future::ok(file).boxed();
|
||||
}
|
||||
Ok(None) => {}
|
||||
Err(err) => {
|
||||
return futures::future::err(err).boxed_local();
|
||||
return futures::future::err(err).boxed();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -395,7 +395,7 @@ impl FileFetcher {
|
|||
specifier
|
||||
),
|
||||
))
|
||||
.boxed_local();
|
||||
.boxed();
|
||||
}
|
||||
|
||||
info!("{} {}", colors::green("Download"), specifier);
|
||||
|
@ -436,7 +436,7 @@ impl FileFetcher {
|
|||
}
|
||||
}
|
||||
}
|
||||
.boxed_local()
|
||||
.boxed()
|
||||
}
|
||||
|
||||
/// Fetch a source file and asynchronously return it.
|
||||
|
|
|
@ -60,6 +60,10 @@ impl DiagnosticCollection {
|
|||
self.versions.get(file_id).cloned()
|
||||
}
|
||||
|
||||
pub fn invalidate(&mut self, file_id: &FileId) {
|
||||
self.versions.remove(file_id);
|
||||
}
|
||||
|
||||
pub fn take_changes(&mut self) -> Option<HashSet<FileId>> {
|
||||
if self.changes.is_empty() {
|
||||
return None;
|
||||
|
|
|
@ -9,9 +9,8 @@ use deno_core::serde_json::json;
|
|||
use deno_core::serde_json::Value;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use dprint_plugin_typescript as dprint;
|
||||
use lspower::jsonrpc::Error as LSPError;
|
||||
use lspower::jsonrpc::ErrorCode as LSPErrorCode;
|
||||
use lspower::jsonrpc::Result as LSPResult;
|
||||
use lspower::jsonrpc::Error as LspError;
|
||||
use lspower::jsonrpc::Result as LspResult;
|
||||
use lspower::lsp_types::*;
|
||||
use lspower::Client;
|
||||
use std::collections::HashMap;
|
||||
|
@ -33,6 +32,7 @@ use super::diagnostics;
|
|||
use super::diagnostics::DiagnosticCollection;
|
||||
use super::diagnostics::DiagnosticSource;
|
||||
use super::memory_cache::MemoryCache;
|
||||
use super::sources;
|
||||
use super::sources::Sources;
|
||||
use super::text;
|
||||
use super::text::apply_content_changes;
|
||||
|
@ -361,7 +361,7 @@ impl lspower::LanguageServer for LanguageServer {
|
|||
async fn initialize(
|
||||
&self,
|
||||
params: InitializeParams,
|
||||
) -> LSPResult<InitializeResult> {
|
||||
) -> LspResult<InitializeResult> {
|
||||
info!("Starting Deno language server...");
|
||||
|
||||
let capabilities = capabilities::server_capabilities(¶ms.capabilities);
|
||||
|
@ -439,7 +439,7 @@ impl lspower::LanguageServer for LanguageServer {
|
|||
info!("Server ready.");
|
||||
}
|
||||
|
||||
async fn shutdown(&self) -> LSPResult<()> {
|
||||
async fn shutdown(&self) -> LspResult<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -586,7 +586,7 @@ impl lspower::LanguageServer for LanguageServer {
|
|||
async fn formatting(
|
||||
&self,
|
||||
params: DocumentFormattingParams,
|
||||
) -> LSPResult<Option<Vec<TextEdit>>> {
|
||||
) -> LspResult<Option<Vec<TextEdit>>> {
|
||||
let specifier = utils::normalize_url(params.text_document.uri.clone());
|
||||
let file_text = {
|
||||
let file_cache = self.file_cache.read().unwrap();
|
||||
|
@ -631,7 +631,7 @@ impl lspower::LanguageServer for LanguageServer {
|
|||
}
|
||||
}
|
||||
|
||||
async fn hover(&self, params: HoverParams) -> LSPResult<Option<Hover>> {
|
||||
async fn hover(&self, params: HoverParams) -> LspResult<Option<Hover>> {
|
||||
if !self.enabled() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
@ -662,7 +662,7 @@ impl lspower::LanguageServer for LanguageServer {
|
|||
async fn document_highlight(
|
||||
&self,
|
||||
params: DocumentHighlightParams,
|
||||
) -> LSPResult<Option<Vec<DocumentHighlight>>> {
|
||||
) -> LspResult<Option<Vec<DocumentHighlight>>> {
|
||||
if !self.enabled() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
@ -702,7 +702,7 @@ impl lspower::LanguageServer for LanguageServer {
|
|||
async fn references(
|
||||
&self,
|
||||
params: ReferenceParams,
|
||||
) -> LSPResult<Option<Vec<Location>>> {
|
||||
) -> LspResult<Option<Vec<Location>>> {
|
||||
if !self.enabled() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
@ -743,7 +743,7 @@ impl lspower::LanguageServer for LanguageServer {
|
|||
async fn goto_definition(
|
||||
&self,
|
||||
params: GotoDefinitionParams,
|
||||
) -> LSPResult<Option<GotoDefinitionResponse>> {
|
||||
) -> LspResult<Option<GotoDefinitionResponse>> {
|
||||
if !self.enabled() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
@ -779,7 +779,7 @@ impl lspower::LanguageServer for LanguageServer {
|
|||
async fn completion(
|
||||
&self,
|
||||
params: CompletionParams,
|
||||
) -> LSPResult<Option<CompletionResponse>> {
|
||||
) -> LspResult<Option<CompletionResponse>> {
|
||||
if !self.enabled() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
@ -812,7 +812,7 @@ impl lspower::LanguageServer for LanguageServer {
|
|||
async fn rename(
|
||||
&self,
|
||||
params: RenameParams,
|
||||
) -> LSPResult<Option<WorkspaceEdit>> {
|
||||
) -> LspResult<Option<WorkspaceEdit>> {
|
||||
if !self.enabled() {
|
||||
return Ok(None);
|
||||
}
|
||||
|
@ -827,7 +827,7 @@ impl lspower::LanguageServer for LanguageServer {
|
|||
.await
|
||||
.map_err(|err| {
|
||||
error!("Failed to get line_index {:#?}", err);
|
||||
LSPError::internal_error()
|
||||
LspError::internal_error()
|
||||
})?;
|
||||
|
||||
let req = tsc::RequestMethod::FindRenameLocations((
|
||||
|
@ -844,7 +844,7 @@ impl lspower::LanguageServer for LanguageServer {
|
|||
.await
|
||||
.map_err(|err| {
|
||||
error!("Failed to request to tsserver {:#?}", err);
|
||||
LSPError::invalid_request()
|
||||
LspError::invalid_request()
|
||||
})?;
|
||||
|
||||
let maybe_locations = serde_json::from_value::<
|
||||
|
@ -855,7 +855,7 @@ impl lspower::LanguageServer for LanguageServer {
|
|||
"Failed to deserialize tsserver response to Vec<RenameLocation> {:#?}",
|
||||
err
|
||||
);
|
||||
LSPError::internal_error()
|
||||
LspError::internal_error()
|
||||
})?;
|
||||
|
||||
match maybe_locations {
|
||||
|
@ -873,7 +873,7 @@ impl lspower::LanguageServer for LanguageServer {
|
|||
"Failed to convert tsc::RenameLocations to WorkspaceEdit {:#?}",
|
||||
err
|
||||
);
|
||||
LSPError::internal_error()
|
||||
LspError::internal_error()
|
||||
})?;
|
||||
Ok(Some(workpace_edits))
|
||||
}
|
||||
|
@ -885,8 +885,18 @@ impl lspower::LanguageServer for LanguageServer {
|
|||
&self,
|
||||
method: &str,
|
||||
params: Option<Value>,
|
||||
) -> LSPResult<Option<Value>> {
|
||||
) -> LspResult<Option<Value>> {
|
||||
match method {
|
||||
"deno/cache" => match params.map(serde_json::from_value) {
|
||||
Some(Ok(params)) => Ok(Some(
|
||||
serde_json::to_value(self.cache(params).await?).map_err(|err| {
|
||||
error!("Failed to serialize cache response: {:#?}", err);
|
||||
LspError::internal_error()
|
||||
})?,
|
||||
)),
|
||||
Some(Err(err)) => Err(LspError::invalid_params(err.to_string())),
|
||||
None => Err(LspError::invalid_params("Missing parameters")),
|
||||
},
|
||||
"deno/virtualTextDocument" => match params.map(serde_json::from_value) {
|
||||
Some(Ok(params)) => Ok(Some(
|
||||
serde_json::to_value(self.virtual_text_document(params).await?)
|
||||
|
@ -895,25 +905,60 @@ impl lspower::LanguageServer for LanguageServer {
|
|||
"Failed to serialize virtual_text_document response: {:#?}",
|
||||
err
|
||||
);
|
||||
LSPError::internal_error()
|
||||
LspError::internal_error()
|
||||
})?,
|
||||
)),
|
||||
Some(Err(err)) => Err(LSPError::invalid_params(err.to_string())),
|
||||
None => Err(LSPError::invalid_params("Missing parameters")),
|
||||
Some(Err(err)) => Err(LspError::invalid_params(err.to_string())),
|
||||
None => Err(LspError::invalid_params("Missing parameters")),
|
||||
},
|
||||
_ => {
|
||||
error!("Got a {} request, but no handler is defined", method);
|
||||
Err(LSPError::method_not_found())
|
||||
Err(LspError::method_not_found())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct CacheParams {
|
||||
pub text_document: TextDocumentIdentifier,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct VirtualTextDocumentParams {
|
||||
pub text_document: TextDocumentIdentifier,
|
||||
}
|
||||
|
||||
impl LanguageServer {
|
||||
async fn cache(&self, params: CacheParams) -> LspResult<bool> {
|
||||
let specifier = utils::normalize_url(params.text_document.uri);
|
||||
let maybe_import_map = self.maybe_import_map.read().unwrap().clone();
|
||||
sources::cache(specifier.clone(), maybe_import_map)
|
||||
.await
|
||||
.map_err(|err| {
|
||||
error!("{}", err);
|
||||
LspError::internal_error()
|
||||
})?;
|
||||
{
|
||||
let file_cache = self.file_cache.read().unwrap();
|
||||
if let Some(file_id) = file_cache.lookup(&specifier) {
|
||||
let mut diagnostics_collection = self.diagnostics.write().unwrap();
|
||||
diagnostics_collection.invalidate(&file_id);
|
||||
}
|
||||
}
|
||||
self.prepare_diagnostics().await.map_err(|err| {
|
||||
error!("{}", err);
|
||||
LspError::internal_error()
|
||||
})?;
|
||||
Ok(true)
|
||||
}
|
||||
|
||||
async fn virtual_text_document(
|
||||
&self,
|
||||
params: VirtualTextDocumentParams,
|
||||
) -> LSPResult<Option<String>> {
|
||||
) -> LspResult<Option<String>> {
|
||||
let specifier = utils::normalize_url(params.text_document.uri);
|
||||
let url = specifier.as_url();
|
||||
let contents = if url.as_str() == "deno:/status.md" {
|
||||
|
@ -933,7 +978,7 @@ impl LanguageServer {
|
|||
if let Some(text) =
|
||||
tsc::get_asset(&specifier, &self.ts_server, &state_snapshot)
|
||||
.await
|
||||
.map_err(|_| LSPError::new(LSPErrorCode::InternalError))?
|
||||
.map_err(|_| LspError::internal_error())?
|
||||
{
|
||||
Some(text)
|
||||
} else {
|
||||
|
@ -1009,12 +1054,6 @@ impl DocumentData {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct VirtualTextDocumentParams {
|
||||
pub text_document: TextDocumentIdentifier,
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -10,16 +10,36 @@ use crate::http_cache;
|
|||
use crate::http_cache::HttpCache;
|
||||
use crate::import_map::ImportMap;
|
||||
use crate::media_type::MediaType;
|
||||
use crate::module_graph::GraphBuilder;
|
||||
use crate::program_state::ProgramState;
|
||||
use crate::specifier_handler::FetchHandler;
|
||||
use crate::text_encoding;
|
||||
use crate::Permissions;
|
||||
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::serde_json;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use std::collections::HashMap;
|
||||
use std::fs;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::time::SystemTime;
|
||||
|
||||
pub async fn cache(
|
||||
specifier: ModuleSpecifier,
|
||||
maybe_import_map: Option<ImportMap>,
|
||||
) -> Result<(), AnyError> {
|
||||
let program_state = Arc::new(ProgramState::new(Default::default())?);
|
||||
let handler = Arc::new(Mutex::new(FetchHandler::new(
|
||||
&program_state,
|
||||
Permissions::allow_all(),
|
||||
)?));
|
||||
let mut builder = GraphBuilder::new(handler, maybe_import_map, None);
|
||||
builder.add(&specifier, false).await
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default)]
|
||||
struct Metadata {
|
||||
dependencies: Option<HashMap<String, analysis::Dependency>>,
|
||||
|
|
|
@ -76,7 +76,6 @@ use deno_runtime::worker::MainWorker;
|
|||
use deno_runtime::worker::WorkerOptions;
|
||||
use log::Level;
|
||||
use log::LevelFilter;
|
||||
use std::cell::RefCell;
|
||||
use std::env;
|
||||
use std::io::Read;
|
||||
use std::io::Write;
|
||||
|
@ -85,6 +84,7 @@ use std::path::PathBuf;
|
|||
use std::pin::Pin;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
fn create_web_worker_callback(
|
||||
program_state: Arc<ProgramState>,
|
||||
|
@ -349,7 +349,7 @@ async fn info_command(
|
|||
let program_state = ProgramState::new(flags)?;
|
||||
if let Some(specifier) = maybe_specifier {
|
||||
let specifier = ModuleSpecifier::resolve_url_or_path(&specifier)?;
|
||||
let handler = Rc::new(RefCell::new(specifier_handler::FetchHandler::new(
|
||||
let handler = Arc::new(Mutex::new(specifier_handler::FetchHandler::new(
|
||||
&program_state,
|
||||
// info accesses dynamically imported modules just for their information
|
||||
// so we allow access to all of them.
|
||||
|
@ -497,7 +497,7 @@ async fn create_module_graph_and_maybe_check(
|
|||
program_state: Arc<ProgramState>,
|
||||
debug: bool,
|
||||
) -> Result<module_graph::Graph, AnyError> {
|
||||
let handler = Rc::new(RefCell::new(FetchHandler::new(
|
||||
let handler = Arc::new(Mutex::new(FetchHandler::new(
|
||||
&program_state,
|
||||
// when bundling, dynamic imports are only access for their type safety,
|
||||
// therefore we will allow the graph to access any module.
|
||||
|
@ -850,7 +850,7 @@ async fn run_with_watch(flags: Flags, script: String) -> Result<(), AnyError> {
|
|||
async move {
|
||||
let main_module = ModuleSpecifier::resolve_url_or_path(&script1)?;
|
||||
let program_state = ProgramState::new(flags)?;
|
||||
let handler = Rc::new(RefCell::new(FetchHandler::new(
|
||||
let handler = Arc::new(Mutex::new(FetchHandler::new(
|
||||
&program_state,
|
||||
Permissions::allow_all(),
|
||||
)?));
|
||||
|
|
|
@ -43,7 +43,6 @@ use deno_core::ModuleResolutionError;
|
|||
use deno_core::ModuleSource;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use regex::Regex;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashSet;
|
||||
use std::collections::{BTreeSet, HashMap};
|
||||
use std::error::Error;
|
||||
|
@ -239,8 +238,7 @@ pub struct Module {
|
|||
is_parsed: bool,
|
||||
maybe_emit: Option<Emit>,
|
||||
maybe_emit_path: Option<(PathBuf, Option<PathBuf>)>,
|
||||
maybe_import_map: Option<Rc<RefCell<ImportMap>>>,
|
||||
maybe_parsed_module: Option<ParsedModule>,
|
||||
maybe_import_map: Option<Arc<Mutex<ImportMap>>>,
|
||||
maybe_types: Option<(String, ModuleSpecifier)>,
|
||||
maybe_version: Option<String>,
|
||||
media_type: MediaType,
|
||||
|
@ -258,7 +256,6 @@ impl Default for Module {
|
|||
maybe_emit: None,
|
||||
maybe_emit_path: None,
|
||||
maybe_import_map: None,
|
||||
maybe_parsed_module: None,
|
||||
maybe_types: None,
|
||||
maybe_version: None,
|
||||
media_type: MediaType::Unknown,
|
||||
|
@ -273,7 +270,7 @@ impl Module {
|
|||
pub fn new(
|
||||
cached_module: CachedModule,
|
||||
is_root: bool,
|
||||
maybe_import_map: Option<Rc<RefCell<ImportMap>>>,
|
||||
maybe_import_map: Option<Arc<Mutex<ImportMap>>>,
|
||||
) -> Self {
|
||||
// If this is a local root file, and its media type is unknown, set the
|
||||
// media type to JavaScript. This allows easier ability to create "shell"
|
||||
|
@ -330,7 +327,7 @@ impl Module {
|
|||
|
||||
/// Parse a module, populating the structure with data retrieved from the
|
||||
/// source of the module.
|
||||
pub fn parse(&mut self) -> Result<(), AnyError> {
|
||||
pub fn parse(&mut self) -> Result<ParsedModule, AnyError> {
|
||||
let parsed_module =
|
||||
parse(self.specifier.as_str(), &self.source, &self.media_type)?;
|
||||
|
||||
|
@ -430,9 +427,7 @@ impl Module {
|
|||
dep.maybe_type = maybe_type;
|
||||
}
|
||||
}
|
||||
|
||||
self.maybe_parsed_module = Some(parsed_module);
|
||||
Ok(())
|
||||
Ok(parsed_module)
|
||||
}
|
||||
|
||||
fn resolve_import(
|
||||
|
@ -443,7 +438,8 @@ impl Module {
|
|||
let maybe_resolve = if let Some(import_map) = self.maybe_import_map.clone()
|
||||
{
|
||||
import_map
|
||||
.borrow()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.resolve(specifier, self.specifier.as_str())?
|
||||
} else {
|
||||
None
|
||||
|
@ -650,7 +646,7 @@ pub struct TranspileOptions {
|
|||
#[derive(Debug, Clone)]
|
||||
enum ModuleSlot {
|
||||
/// The module fetch resulted in a non-recoverable error.
|
||||
Err(Rc<AnyError>),
|
||||
Err(Arc<AnyError>),
|
||||
/// The the fetch resulted in a module.
|
||||
Module(Box<Module>),
|
||||
/// Used to denote a module that isn't part of the graph.
|
||||
|
@ -666,7 +662,7 @@ enum ModuleSlot {
|
|||
pub struct Graph {
|
||||
/// A reference to the specifier handler that will retrieve and cache modules
|
||||
/// for the graph.
|
||||
handler: Rc<RefCell<dyn SpecifierHandler>>,
|
||||
handler: Arc<Mutex<dyn SpecifierHandler>>,
|
||||
/// Optional TypeScript build info that will be passed to `tsc` if `tsc` is
|
||||
/// invoked.
|
||||
maybe_tsbuildinfo: Option<String>,
|
||||
|
@ -734,7 +730,7 @@ impl Graph {
|
|||
/// `SpecifierHandler` trait.
|
||||
///
|
||||
pub fn new(
|
||||
handler: Rc<RefCell<dyn SpecifierHandler>>,
|
||||
handler: Arc<Mutex<dyn SpecifierHandler>>,
|
||||
maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
|
||||
) -> Self {
|
||||
Graph {
|
||||
|
@ -844,7 +840,7 @@ impl Graph {
|
|||
let maybe_tsbuildinfo = self.maybe_tsbuildinfo.clone();
|
||||
let hash_data =
|
||||
vec![config.as_bytes(), version::deno().as_bytes().to_owned()];
|
||||
let graph = Rc::new(RefCell::new(self));
|
||||
let graph = Arc::new(Mutex::new(self));
|
||||
|
||||
let response = tsc::exec(
|
||||
js::compiler_isolate_init(),
|
||||
|
@ -858,7 +854,7 @@ impl Graph {
|
|||
},
|
||||
)?;
|
||||
|
||||
let mut graph = graph.borrow_mut();
|
||||
let mut graph = graph.lock().unwrap();
|
||||
graph.maybe_tsbuildinfo = response.maybe_tsbuildinfo;
|
||||
// Only process changes to the graph if there are no diagnostics and there
|
||||
// were files emitted.
|
||||
|
@ -964,7 +960,7 @@ impl Graph {
|
|||
let root_names = self.get_root_names(!config.get_check_js());
|
||||
let hash_data =
|
||||
vec![config.as_bytes(), version::deno().as_bytes().to_owned()];
|
||||
let graph = Rc::new(RefCell::new(self));
|
||||
let graph = Arc::new(Mutex::new(self));
|
||||
|
||||
let response = tsc::exec(
|
||||
js::compiler_isolate_init(),
|
||||
|
@ -979,7 +975,7 @@ impl Graph {
|
|||
)?;
|
||||
|
||||
let mut emitted_files = HashMap::new();
|
||||
let graph = graph.borrow();
|
||||
let graph = graph.lock().unwrap();
|
||||
match options.bundle_type {
|
||||
BundleType::Esm => {
|
||||
assert!(
|
||||
|
@ -1081,7 +1077,7 @@ impl Graph {
|
|||
/// Update the handler with any modules that are marked as _dirty_ and update
|
||||
/// any build info if present.
|
||||
fn flush(&mut self) -> Result<(), AnyError> {
|
||||
let mut handler = self.handler.borrow_mut();
|
||||
let mut handler = self.handler.lock().unwrap();
|
||||
for (_, module_slot) in self.modules.iter_mut() {
|
||||
if let ModuleSlot::Module(module) = module_slot {
|
||||
if module.is_dirty {
|
||||
|
@ -1595,10 +1591,7 @@ impl Graph {
|
|||
if !options.reload && module.is_emit_valid(&config) {
|
||||
continue;
|
||||
}
|
||||
if module.maybe_parsed_module.is_none() {
|
||||
module.parse()?;
|
||||
}
|
||||
let parsed_module = module.maybe_parsed_module.clone().unwrap();
|
||||
let parsed_module = module.parse()?;
|
||||
let emit = parsed_module.transpile(&emit_options)?;
|
||||
emit_count += 1;
|
||||
module.maybe_emit = Some(Emit::Cli(emit));
|
||||
|
@ -1647,18 +1640,18 @@ impl swc_bundler::Resolve for Graph {
|
|||
/// A structure for building a dependency graph of modules.
|
||||
pub struct GraphBuilder {
|
||||
graph: Graph,
|
||||
maybe_import_map: Option<Rc<RefCell<ImportMap>>>,
|
||||
maybe_import_map: Option<Arc<Mutex<ImportMap>>>,
|
||||
pending: FuturesUnordered<FetchFuture>,
|
||||
}
|
||||
|
||||
impl GraphBuilder {
|
||||
pub fn new(
|
||||
handler: Rc<RefCell<dyn SpecifierHandler>>,
|
||||
handler: Arc<Mutex<dyn SpecifierHandler>>,
|
||||
maybe_import_map: Option<ImportMap>,
|
||||
maybe_lockfile: Option<Arc<Mutex<Lockfile>>>,
|
||||
) -> Self {
|
||||
let internal_import_map = if let Some(import_map) = maybe_import_map {
|
||||
Some(Rc::new(RefCell::new(import_map)))
|
||||
Some(Arc::new(Mutex::new(import_map)))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
@ -1685,7 +1678,7 @@ impl GraphBuilder {
|
|||
self
|
||||
.graph
|
||||
.modules
|
||||
.insert(specifier, ModuleSlot::Err(Rc::new(err)));
|
||||
.insert(specifier, ModuleSlot::Err(Arc::new(err)));
|
||||
}
|
||||
Some(Ok(cached_module)) => {
|
||||
let is_root = &cached_module.specifier == specifier;
|
||||
|
@ -1702,7 +1695,7 @@ impl GraphBuilder {
|
|||
self.graph.roots.push(specifier.clone());
|
||||
self.graph.roots_dynamic = self.graph.roots_dynamic && is_dynamic;
|
||||
if self.graph.maybe_tsbuildinfo.is_none() {
|
||||
let handler = self.graph.handler.borrow();
|
||||
let handler = self.graph.handler.lock().unwrap();
|
||||
self.graph.maybe_tsbuildinfo = handler.get_tsbuildinfo(specifier)?;
|
||||
}
|
||||
}
|
||||
|
@ -1723,11 +1716,9 @@ impl GraphBuilder {
|
|||
.graph
|
||||
.modules
|
||||
.insert(specifier.clone(), ModuleSlot::Pending);
|
||||
let future = self.graph.handler.borrow_mut().fetch(
|
||||
specifier.clone(),
|
||||
maybe_referrer.clone(),
|
||||
is_dynamic,
|
||||
);
|
||||
let mut handler = self.graph.handler.lock().unwrap();
|
||||
let future =
|
||||
handler.fetch(specifier.clone(), maybe_referrer.clone(), is_dynamic);
|
||||
self.pending.push(future);
|
||||
}
|
||||
}
|
||||
|
@ -1763,7 +1754,7 @@ impl GraphBuilder {
|
|||
let has_types = module.maybe_types.is_some();
|
||||
module.parse()?;
|
||||
if self.maybe_import_map.is_none() {
|
||||
let mut handler = self.graph.handler.borrow_mut();
|
||||
let mut handler = self.graph.handler.lock().unwrap();
|
||||
handler.set_deps(&specifier, module.dependencies.clone())?;
|
||||
if !has_types {
|
||||
if let Some((types, _)) = module.maybe_types.clone() {
|
||||
|
@ -1934,10 +1925,10 @@ pub mod tests {
|
|||
|
||||
async fn setup(
|
||||
specifier: ModuleSpecifier,
|
||||
) -> (Graph, Rc<RefCell<MockSpecifierHandler>>) {
|
||||
) -> (Graph, Arc<Mutex<MockSpecifierHandler>>) {
|
||||
let c = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
|
||||
let fixtures = c.join("tests/module_graph");
|
||||
let handler = Rc::new(RefCell::new(MockSpecifierHandler {
|
||||
let handler = Arc::new(Mutex::new(MockSpecifierHandler {
|
||||
fixtures,
|
||||
..MockSpecifierHandler::default()
|
||||
}));
|
||||
|
@ -1958,7 +1949,7 @@ pub mod tests {
|
|||
.iter()
|
||||
.map(|(k, v)| (k.to_string(), v.to_string()))
|
||||
.collect();
|
||||
let handler = Rc::new(RefCell::new(MemoryHandler::new(sources)));
|
||||
let handler = Arc::new(Mutex::new(MemoryHandler::new(sources)));
|
||||
let mut builder = GraphBuilder::new(handler.clone(), None, None);
|
||||
builder
|
||||
.add(&specifier, false)
|
||||
|
@ -2064,7 +2055,7 @@ pub mod tests {
|
|||
|
||||
for (specifier, expected_str) in tests {
|
||||
let specifier = ModuleSpecifier::resolve_url_or_path(specifier).unwrap();
|
||||
let handler = Rc::new(RefCell::new(MockSpecifierHandler {
|
||||
let handler = Arc::new(Mutex::new(MockSpecifierHandler {
|
||||
fixtures: fixtures.clone(),
|
||||
..MockSpecifierHandler::default()
|
||||
}));
|
||||
|
@ -2103,7 +2094,7 @@ pub mod tests {
|
|||
assert!(result_info.maybe_ignored_options.is_none());
|
||||
assert_eq!(result_info.stats.0.len(), 12);
|
||||
assert!(result_info.diagnostics.is_empty());
|
||||
let h = handler.borrow();
|
||||
let h = handler.lock().unwrap();
|
||||
assert_eq!(h.cache_calls.len(), 2);
|
||||
assert_eq!(h.tsbuildinfo_calls.len(), 1);
|
||||
}
|
||||
|
@ -2144,7 +2135,7 @@ pub mod tests {
|
|||
assert!(result_info.maybe_ignored_options.is_none());
|
||||
assert_eq!(result_info.stats.0.len(), 12);
|
||||
assert!(!result_info.diagnostics.is_empty());
|
||||
let h = handler.borrow();
|
||||
let h = handler.lock().unwrap();
|
||||
// we shouldn't cache any files or write out tsbuildinfo if there are
|
||||
// diagnostic errors
|
||||
assert_eq!(h.cache_calls.len(), 0);
|
||||
|
@ -2169,7 +2160,7 @@ pub mod tests {
|
|||
assert!(result_info.maybe_ignored_options.is_none());
|
||||
assert_eq!(result_info.stats.0.len(), 12);
|
||||
assert!(result_info.diagnostics.is_empty());
|
||||
let h = handler.borrow();
|
||||
let h = handler.lock().unwrap();
|
||||
assert_eq!(h.cache_calls.len(), 0);
|
||||
assert_eq!(h.tsbuildinfo_calls.len(), 1);
|
||||
}
|
||||
|
@ -2190,7 +2181,7 @@ pub mod tests {
|
|||
.expect("should have checked");
|
||||
assert!(result_info.maybe_ignored_options.is_none());
|
||||
assert!(result_info.diagnostics.is_empty());
|
||||
let h = handler.borrow();
|
||||
let h = handler.lock().unwrap();
|
||||
assert_eq!(h.cache_calls.len(), 1);
|
||||
assert_eq!(h.tsbuildinfo_calls.len(), 1);
|
||||
}
|
||||
|
@ -2231,7 +2222,7 @@ pub mod tests {
|
|||
.expect("should have checked");
|
||||
assert!(result_info.maybe_ignored_options.is_none());
|
||||
assert!(result_info.diagnostics.is_empty());
|
||||
let h = handler.borrow();
|
||||
let h = handler.lock().unwrap();
|
||||
assert_eq!(h.version_calls.len(), 2);
|
||||
let ver0 = h.version_calls[0].1.clone();
|
||||
let ver1 = h.version_calls[1].1.clone();
|
||||
|
@ -2251,7 +2242,7 @@ pub mod tests {
|
|||
.expect("should have checked");
|
||||
assert!(result_info.maybe_ignored_options.is_none());
|
||||
assert!(result_info.diagnostics.is_empty());
|
||||
let h = handler.borrow();
|
||||
let h = handler.lock().unwrap();
|
||||
assert_eq!(h.version_calls.len(), 2);
|
||||
assert!(h.version_calls[0].1 == ver0 || h.version_calls[0].1 == ver1);
|
||||
assert!(h.version_calls[1].1 == ver0 || h.version_calls[1].1 == ver1);
|
||||
|
@ -2403,7 +2394,7 @@ pub mod tests {
|
|||
.expect("could not resolve module");
|
||||
let c = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
|
||||
let fixtures = c.join("tests/module_graph");
|
||||
let handler = Rc::new(RefCell::new(MockSpecifierHandler {
|
||||
let handler = Arc::new(Mutex::new(MockSpecifierHandler {
|
||||
fixtures,
|
||||
..MockSpecifierHandler::default()
|
||||
}));
|
||||
|
@ -2430,7 +2421,7 @@ pub mod tests {
|
|||
let result_info = graph.transpile(TranspileOptions::default()).unwrap();
|
||||
assert_eq!(result_info.stats.0.len(), 3);
|
||||
assert_eq!(result_info.maybe_ignored_options, None);
|
||||
let h = handler.borrow();
|
||||
let h = handler.lock().unwrap();
|
||||
assert_eq!(h.cache_calls.len(), 2);
|
||||
match &h.cache_calls[0].1 {
|
||||
Emit::Cli((code, maybe_map)) => {
|
||||
|
@ -2492,7 +2483,7 @@ pub mod tests {
|
|||
vec!["target".to_string()],
|
||||
"the 'target' options should have been ignored"
|
||||
);
|
||||
let h = handler.borrow();
|
||||
let h = handler.lock().unwrap();
|
||||
assert_eq!(h.cache_calls.len(), 1, "only one file should be emitted");
|
||||
// FIXME(bartlomieju): had to add space in `<div>`, probably a quirk in swc_ecma_codegen
|
||||
match &h.cache_calls[0].1 {
|
||||
|
@ -2521,7 +2512,7 @@ pub mod tests {
|
|||
)
|
||||
.expect("could not parse import map"),
|
||||
);
|
||||
let handler = Rc::new(RefCell::new(MockSpecifierHandler {
|
||||
let handler = Arc::new(Mutex::new(MockSpecifierHandler {
|
||||
fixtures,
|
||||
..Default::default()
|
||||
}));
|
||||
|
@ -2541,7 +2532,7 @@ pub mod tests {
|
|||
let lockfile =
|
||||
Lockfile::new(lockfile_path, false).expect("could not load lockfile");
|
||||
let maybe_lockfile = Some(Arc::new(Mutex::new(lockfile)));
|
||||
let handler = Rc::new(RefCell::new(MockSpecifierHandler {
|
||||
let handler = Arc::new(Mutex::new(MockSpecifierHandler {
|
||||
fixtures,
|
||||
..MockSpecifierHandler::default()
|
||||
}));
|
||||
|
|
|
@ -11,8 +11,6 @@ use crate::specifier_handler::FetchHandler;
|
|||
use crate::specifier_handler::MemoryHandler;
|
||||
use crate::specifier_handler::SpecifierHandler;
|
||||
use crate::tsc_config;
|
||||
use deno_runtime::permissions::Permissions;
|
||||
use std::sync::Arc;
|
||||
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::error::Context;
|
||||
|
@ -23,10 +21,13 @@ use deno_core::serde_json::Value;
|
|||
use deno_core::BufVec;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use deno_core::OpState;
|
||||
use deno_runtime::permissions::Permissions;
|
||||
use serde::Deserialize;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
pub fn init(rt: &mut deno_core::JsRuntime) {
|
||||
super::reg_json_async(rt, "op_compile", op_compile);
|
||||
|
@ -58,11 +59,11 @@ async fn op_compile(
|
|||
let state = state.borrow();
|
||||
state.borrow::<Permissions>().clone()
|
||||
};
|
||||
let handler: Rc<RefCell<dyn SpecifierHandler>> =
|
||||
let handler: Arc<Mutex<dyn SpecifierHandler>> =
|
||||
if let Some(sources) = args.sources {
|
||||
Rc::new(RefCell::new(MemoryHandler::new(sources)))
|
||||
Arc::new(Mutex::new(MemoryHandler::new(sources)))
|
||||
} else {
|
||||
Rc::new(RefCell::new(FetchHandler::new(
|
||||
Arc::new(Mutex::new(FetchHandler::new(
|
||||
&program_state,
|
||||
runtime_permissions,
|
||||
)?))
|
||||
|
|
|
@ -23,10 +23,8 @@ use deno_core::error::AnyError;
|
|||
use deno_core::url::Url;
|
||||
use deno_core::ModuleSource;
|
||||
use deno_core::ModuleSpecifier;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
|
@ -144,7 +142,7 @@ impl ProgramState {
|
|||
runtime_permissions.check_specifier(&specifier)?;
|
||||
}
|
||||
let handler =
|
||||
Rc::new(RefCell::new(FetchHandler::new(self, runtime_permissions)?));
|
||||
Arc::new(Mutex::new(FetchHandler::new(self, runtime_permissions)?));
|
||||
let mut builder =
|
||||
GraphBuilder::new(handler, maybe_import_map, self.lockfile.clone());
|
||||
builder.add(&specifier, is_dynamic).await?;
|
||||
|
|
|
@ -28,7 +28,8 @@ pub type DependencyMap = HashMap<String, Dependency>;
|
|||
pub type FetchFuture = Pin<
|
||||
Box<
|
||||
(dyn Future<Output = Result<CachedModule, (ModuleSpecifier, AnyError)>>
|
||||
+ 'static),
|
||||
+ 'static
|
||||
+ Send),
|
||||
>,
|
||||
>;
|
||||
|
||||
|
@ -129,7 +130,7 @@ impl Dependency {
|
|||
}
|
||||
}
|
||||
|
||||
pub trait SpecifierHandler {
|
||||
pub trait SpecifierHandler: Sync + Send {
|
||||
/// Instructs the handler to fetch a specifier or retrieve its value from the
|
||||
/// cache.
|
||||
fn fetch(
|
||||
|
@ -361,7 +362,7 @@ impl SpecifierHandler for FetchHandler {
|
|||
specifier: source_file.specifier,
|
||||
})
|
||||
}
|
||||
.boxed_local()
|
||||
.boxed()
|
||||
}
|
||||
|
||||
fn get_tsbuildinfo(
|
||||
|
|
24
cli/tsc.rs
24
cli/tsc.rs
|
@ -20,10 +20,10 @@ use deno_core::OpFn;
|
|||
use deno_core::RuntimeOptions;
|
||||
use deno_core::Snapshot;
|
||||
use serde::Deserialize;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::HashMap;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
|
||||
/// Provide static assets that are not preloaded in the compiler snapshot.
|
||||
pub fn get_asset(asset: &str) -> Option<&'static str> {
|
||||
|
@ -115,7 +115,7 @@ pub struct Request {
|
|||
pub config: TsConfig,
|
||||
/// Indicates to the tsc runtime if debug logging should occur.
|
||||
pub debug: bool,
|
||||
pub graph: Rc<RefCell<Graph>>,
|
||||
pub graph: Arc<Mutex<Graph>>,
|
||||
pub hash_data: Vec<Vec<u8>>,
|
||||
pub maybe_tsbuildinfo: Option<String>,
|
||||
/// A vector of strings that represent the root/entry point modules for the
|
||||
|
@ -138,7 +138,7 @@ pub struct Response {
|
|||
struct State {
|
||||
hash_data: Vec<Vec<u8>>,
|
||||
emitted_files: Vec<EmittedFile>,
|
||||
graph: Rc<RefCell<Graph>>,
|
||||
graph: Arc<Mutex<Graph>>,
|
||||
maybe_tsbuildinfo: Option<String>,
|
||||
maybe_response: Option<RespondArgs>,
|
||||
root_map: HashMap<String, ModuleSpecifier>,
|
||||
|
@ -146,7 +146,7 @@ struct State {
|
|||
|
||||
impl State {
|
||||
pub fn new(
|
||||
graph: Rc<RefCell<Graph>>,
|
||||
graph: Arc<Mutex<Graph>>,
|
||||
hash_data: Vec<Vec<u8>>,
|
||||
maybe_tsbuildinfo: Option<String>,
|
||||
root_map: HashMap<String, ModuleSpecifier>,
|
||||
|
@ -260,7 +260,7 @@ fn load(state: &mut State, args: Value) -> Result<Value, AnyError> {
|
|||
media_type = MediaType::from(&v.specifier);
|
||||
maybe_source
|
||||
} else {
|
||||
let graph = state.graph.borrow();
|
||||
let graph = state.graph.lock().unwrap();
|
||||
let specifier =
|
||||
if let Some(remapped_specifier) = state.root_map.get(&v.specifier) {
|
||||
remapped_specifier.clone()
|
||||
|
@ -310,7 +310,7 @@ fn resolve(state: &mut State, args: Value) -> Result<Value, AnyError> {
|
|||
MediaType::from(specifier).as_ts_extension().to_string(),
|
||||
));
|
||||
} else {
|
||||
let graph = state.graph.borrow();
|
||||
let graph = state.graph.lock().unwrap();
|
||||
match graph.resolve(specifier, &referrer, true) {
|
||||
Ok(resolved_specifier) => {
|
||||
let media_type = if let Some(media_type) =
|
||||
|
@ -446,9 +446,9 @@ mod tests {
|
|||
use crate::module_graph::tests::MockSpecifierHandler;
|
||||
use crate::module_graph::GraphBuilder;
|
||||
use crate::tsc_config::TsConfig;
|
||||
use std::cell::RefCell;
|
||||
use std::env;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::Mutex;
|
||||
|
||||
async fn setup(
|
||||
maybe_specifier: Option<ModuleSpecifier>,
|
||||
|
@ -461,7 +461,7 @@ mod tests {
|
|||
let hash_data = maybe_hash_data.unwrap_or_else(|| vec![b"".to_vec()]);
|
||||
let c = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
|
||||
let fixtures = c.join("tests/tsc2");
|
||||
let handler = Rc::new(RefCell::new(MockSpecifierHandler {
|
||||
let handler = Arc::new(Mutex::new(MockSpecifierHandler {
|
||||
fixtures,
|
||||
..MockSpecifierHandler::default()
|
||||
}));
|
||||
|
@ -470,7 +470,7 @@ mod tests {
|
|||
.add(&specifier, false)
|
||||
.await
|
||||
.expect("module not inserted");
|
||||
let graph = Rc::new(RefCell::new(builder.get_graph()));
|
||||
let graph = Arc::new(Mutex::new(builder.get_graph()));
|
||||
State::new(graph, hash_data, maybe_tsbuildinfo, HashMap::new())
|
||||
}
|
||||
|
||||
|
@ -480,13 +480,13 @@ mod tests {
|
|||
let hash_data = vec![b"something".to_vec()];
|
||||
let c = PathBuf::from(env::var_os("CARGO_MANIFEST_DIR").unwrap());
|
||||
let fixtures = c.join("tests/tsc2");
|
||||
let handler = Rc::new(RefCell::new(MockSpecifierHandler {
|
||||
let handler = Arc::new(Mutex::new(MockSpecifierHandler {
|
||||
fixtures,
|
||||
..Default::default()
|
||||
}));
|
||||
let mut builder = GraphBuilder::new(handler.clone(), None, None);
|
||||
builder.add(&specifier, false).await?;
|
||||
let graph = Rc::new(RefCell::new(builder.get_graph()));
|
||||
let graph = Arc::new(Mutex::new(builder.get_graph()));
|
||||
let config = TsConfig::new(json!({
|
||||
"allowJs": true,
|
||||
"checkJs": false,
|
||||
|
|
Loading…
Reference in a new issue