mirror of
https://github.com/denoland/deno.git
synced 2025-01-21 13:00:36 -05:00
update for deno_lint changes
This commit is contained in:
parent
321e37bf2e
commit
2edd30904a
6 changed files with 120 additions and 61 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1875,8 +1875,6 @@ dependencies = [
|
|||
[[package]]
|
||||
name = "deno_lint"
|
||||
version = "0.68.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce713d564f76efd90535061113210bdc6b942ed6327b33eb1d5f76a5daf8e7a5"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"deno_ast",
|
||||
|
|
|
@ -350,3 +350,4 @@ opt-level = 3
|
|||
|
||||
[patch.crates-io]
|
||||
deno_config = { git = "https://github.com/denoland/deno_config.git", branch = "deno_lint_rules" }
|
||||
deno_lint = { path = "../deno_lint" }
|
||||
|
|
|
@ -213,6 +213,11 @@ export function installPlugin(plugin) {
|
|||
}
|
||||
state.plugins.push(plugin);
|
||||
state.installedPlugins.add(plugin.name);
|
||||
|
||||
return {
|
||||
name: plugin.name,
|
||||
ruleNames: Object.keys(plugin.rules),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -15,6 +15,8 @@ use deno_core::futures::FutureExt as _;
|
|||
use deno_core::parking_lot::Mutex;
|
||||
use deno_graph::ModuleGraph;
|
||||
use deno_lint::diagnostic::LintDiagnostic;
|
||||
use deno_lint::linter::ExternalLinterCb;
|
||||
use deno_lint::linter::ExternalLinterResult;
|
||||
use deno_lint::linter::LintConfig as DenoLintConfig;
|
||||
use deno_lint::linter::LintFileOptions;
|
||||
use deno_lint::linter::Linter as DenoLintLinter;
|
||||
|
@ -75,18 +77,6 @@ impl CliLinter {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn run_plugins(
|
||||
&self,
|
||||
parsed_source: ParsedSource,
|
||||
file_path: PathBuf,
|
||||
) -> Result<Vec<LintDiagnostic>, AnyError> {
|
||||
let Some(plugin_runner) = self.maybe_plugin_runner.clone() else {
|
||||
return Ok(vec![]);
|
||||
};
|
||||
|
||||
run_plugins(plugin_runner, parsed_source, file_path)
|
||||
}
|
||||
|
||||
pub fn has_package_rules(&self) -> bool {
|
||||
!self.package_rules.is_empty()
|
||||
}
|
||||
|
@ -107,22 +97,23 @@ impl CliLinter {
|
|||
&self,
|
||||
parsed_source: &ParsedSource,
|
||||
) -> Vec<LintDiagnostic> {
|
||||
let mut diagnostics = self
|
||||
.linter
|
||||
.lint_with_ast(parsed_source, self.deno_lint_config.clone());
|
||||
let file_path = parsed_source.specifier().to_file_path().unwrap();
|
||||
// TODO(bartlomieju): surface error is running plugin fails
|
||||
// TODO(bartlomieju): plugins don't support fixing for now.
|
||||
let run_plugin_result = self.run_plugins(parsed_source.clone(), file_path);
|
||||
if let Err(err) = run_plugin_result.as_ref() {
|
||||
eprintln!("run plugin result {:#?}", err);
|
||||
}
|
||||
let maybe_plugin_diagnostics = run_plugin_result.ok();
|
||||
if let Some(plugin_diagnostics) = maybe_plugin_diagnostics {
|
||||
diagnostics.extend_from_slice(&plugin_diagnostics);
|
||||
}
|
||||
let external_linter: Option<ExternalLinterCb> =
|
||||
if let Some(plugin_runner) = self.maybe_plugin_runner.clone() {
|
||||
Some(Arc::new(move |parsed_source: ParsedSource| {
|
||||
// TODO: clean this up
|
||||
let file_path = parsed_source.specifier().to_file_path().unwrap();
|
||||
run_plugins(plugin_runner.clone(), parsed_source, file_path)
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
diagnostics
|
||||
self.linter.lint_with_ast(
|
||||
parsed_source,
|
||||
self.deno_lint_config.clone(),
|
||||
external_linter,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn lint_file(
|
||||
|
@ -140,22 +131,37 @@ impl CliLinter {
|
|||
MediaType::from_specifier(&specifier)
|
||||
};
|
||||
|
||||
// TODO(bartlomieju): surface error is running plugin fails
|
||||
let external_linter: Option<ExternalLinterCb> =
|
||||
if let Some(plugin_runner) = self.maybe_plugin_runner.clone() {
|
||||
Some(Arc::new(move |parsed_source: ParsedSource| {
|
||||
// TODO: clean this up
|
||||
let file_path = parsed_source.specifier().to_file_path().unwrap();
|
||||
run_plugins(plugin_runner.clone(), parsed_source, file_path)
|
||||
}))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
if self.fix {
|
||||
self.lint_file_and_fix(&specifier, media_type, source_code, file_path)
|
||||
self.lint_file_and_fix(
|
||||
&specifier,
|
||||
media_type,
|
||||
source_code,
|
||||
file_path,
|
||||
external_linter,
|
||||
)
|
||||
} else {
|
||||
let (source, mut diagnostics) = self
|
||||
let (source, diagnostics) = self
|
||||
.linter
|
||||
.lint_file(LintFileOptions {
|
||||
specifier,
|
||||
media_type,
|
||||
source_code,
|
||||
config: self.deno_lint_config.clone(),
|
||||
external_linter,
|
||||
})
|
||||
.map_err(AnyError::from)?;
|
||||
let plugin_diagnostics =
|
||||
self.run_plugins(source.clone(), file_path.to_path_buf())?;
|
||||
|
||||
diagnostics.extend_from_slice(&plugin_diagnostics);
|
||||
|
||||
Ok((source, diagnostics))
|
||||
}
|
||||
|
@ -167,20 +173,17 @@ impl CliLinter {
|
|||
media_type: MediaType,
|
||||
source_code: String,
|
||||
file_path: &Path,
|
||||
external_linter: Option<ExternalLinterCb>,
|
||||
) -> Result<(ParsedSource, Vec<LintDiagnostic>), deno_core::anyhow::Error> {
|
||||
// initial lint
|
||||
let (source, mut diagnostics) = self.linter.lint_file(LintFileOptions {
|
||||
let (source, diagnostics) = self.linter.lint_file(LintFileOptions {
|
||||
specifier: specifier.clone(),
|
||||
media_type,
|
||||
source_code,
|
||||
config: self.deno_lint_config.clone(),
|
||||
external_linter: external_linter.clone(),
|
||||
})?;
|
||||
|
||||
let plugin_diagnostics =
|
||||
self.run_plugins(source.clone(), file_path.to_path_buf())?;
|
||||
|
||||
diagnostics.extend_from_slice(&plugin_diagnostics);
|
||||
|
||||
// Try applying fixes repeatedly until the file has none left or
|
||||
// a maximum number of iterations is reached. This is necessary
|
||||
// because lint fixes may overlap and so we can't always apply
|
||||
|
@ -196,6 +199,7 @@ impl CliLinter {
|
|||
self.deno_lint_config.clone(),
|
||||
source.text_info_lazy(),
|
||||
&diagnostics,
|
||||
external_linter.clone(),
|
||||
)?;
|
||||
match change {
|
||||
Some(change) => {
|
||||
|
@ -241,6 +245,7 @@ fn apply_lint_fixes_and_relint(
|
|||
config: DenoLintConfig,
|
||||
text_info: &SourceTextInfo,
|
||||
diagnostics: &[LintDiagnostic],
|
||||
external_linter: Option<ExternalLinterCb>,
|
||||
) -> Result<Option<(ParsedSource, Vec<LintDiagnostic>)>, AnyError> {
|
||||
let Some(new_text) = apply_lint_fixes(text_info, diagnostics) else {
|
||||
return Ok(None);
|
||||
|
@ -251,6 +256,7 @@ fn apply_lint_fixes_and_relint(
|
|||
source_code: new_text,
|
||||
media_type,
|
||||
config,
|
||||
external_linter,
|
||||
})
|
||||
.map(Some)
|
||||
.context(
|
||||
|
@ -309,8 +315,10 @@ fn run_plugins(
|
|||
plugin_runner: Arc<Mutex<PluginHostProxy>>,
|
||||
parsed_source: ParsedSource,
|
||||
file_path: PathBuf,
|
||||
) -> Result<Vec<LintDiagnostic>, AnyError> {
|
||||
) -> Result<ExternalLinterResult, AnyError> {
|
||||
let source_text_info = parsed_source.text_info_lazy().clone();
|
||||
let plugin_info = plugin_runner.lock().get_plugin_rules();
|
||||
|
||||
#[allow(clippy::await_holding_lock)]
|
||||
let fut = async move {
|
||||
let mut plugin_runner = plugin_runner.lock();
|
||||
|
@ -328,5 +336,8 @@ fn run_plugins(
|
|||
|
||||
let plugin_diagnostics = tokio_util::create_and_run_current_thread(fut)?;
|
||||
|
||||
Ok(plugin_diagnostics)
|
||||
Ok(ExternalLinterResult {
|
||||
diagnostics: plugin_diagnostics,
|
||||
rules: plugin_info,
|
||||
})
|
||||
}
|
||||
|
|
|
@ -1,11 +1,17 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
|
||||
use deno_ast::ModuleSpecifier;
|
||||
use deno_ast::ParsedSource;
|
||||
use deno_ast::SourceTextInfo;
|
||||
use deno_core::error::custom_error;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::futures::FutureExt;
|
||||
use deno_core::parking_lot::Mutex;
|
||||
use deno_core::resolve_url_or_path;
|
||||
use deno_core::v8;
|
||||
use deno_core::PollEventLoopOptions;
|
||||
|
@ -15,10 +21,6 @@ use deno_runtime::deno_permissions::PermissionsContainer;
|
|||
use deno_runtime::tokio_util;
|
||||
use deno_runtime::worker::MainWorker;
|
||||
use deno_runtime::WorkerExecutionMode;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::mpsc::channel;
|
||||
use tokio::sync::mpsc::Receiver;
|
||||
use tokio::sync::mpsc::Sender;
|
||||
|
@ -37,7 +39,7 @@ pub enum PluginHostRequest {
|
|||
}
|
||||
|
||||
pub enum PluginHostResponse {
|
||||
LoadPlugin(Result<(), AnyError>),
|
||||
LoadPlugin(Result<Vec<PluginInfo>, AnyError>),
|
||||
Run(Result<Vec<LintDiagnostic>, AnyError>),
|
||||
}
|
||||
|
||||
|
@ -99,11 +101,26 @@ v8_static_strings! {
|
|||
pub struct PluginHostProxy {
|
||||
tx: Sender<PluginHostRequest>,
|
||||
rx: Arc<tokio::sync::Mutex<Receiver<PluginHostResponse>>>,
|
||||
pub(crate) plugin_info: Arc<Mutex<Vec<PluginInfo>>>,
|
||||
#[allow(unused)]
|
||||
join_handle: std::thread::JoinHandle<Result<(), AnyError>>,
|
||||
logger: PluginLogger,
|
||||
}
|
||||
|
||||
impl PluginHostProxy {
|
||||
pub fn get_plugin_rules(&self) -> Vec<String> {
|
||||
let infos = self.plugin_info.lock();
|
||||
|
||||
let mut all_names = vec![];
|
||||
|
||||
for info in infos.iter() {
|
||||
all_names.extend_from_slice(&info.get_rules());
|
||||
}
|
||||
|
||||
all_names
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PluginHost {
|
||||
worker: MainWorker,
|
||||
install_plugin_fn: Rc<v8::Global<v8::Function>>,
|
||||
|
@ -123,17 +140,16 @@ async fn create_plugin_runner_inner(
|
|||
..Default::default()
|
||||
};
|
||||
let flags = Arc::new(flags);
|
||||
let factory = CliFactory::from_flags(flags);
|
||||
let factory = CliFactory::from_flags(flags.clone());
|
||||
let cli_options = factory.cli_options()?;
|
||||
let main_module =
|
||||
resolve_url_or_path("./$deno$lint.mts", cli_options.initial_cwd()).unwrap();
|
||||
// TODO(bartlomieju): should we run with all permissions?
|
||||
// TODO(bartlomieju): use none permissions, but with it, the JSR plugin doesn't work
|
||||
// anymore
|
||||
let permissions = PermissionsContainer::allow_all(
|
||||
factory.permission_desc_parser()?.clone(),
|
||||
// Permissions::none(false),
|
||||
);
|
||||
let perm_parser = factory.permission_desc_parser()?;
|
||||
let permissions = Permissions::from_options(
|
||||
perm_parser.as_ref(),
|
||||
&flags.permissions.to_options(&[]),
|
||||
)?;
|
||||
let permissions = PermissionsContainer::new(perm_parser.clone(), permissions);
|
||||
// let npm_resolver = factory.npm_resolver().await?.clone();
|
||||
// let resolver = factory.resolver().await?.clone();
|
||||
let worker_factory = factory.create_cli_main_worker_factory().await?;
|
||||
|
@ -193,6 +209,25 @@ async fn create_plugin_runner_inner(
|
|||
})
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct PluginInfo {
|
||||
pub name: String,
|
||||
pub rule_names: Vec<String>,
|
||||
}
|
||||
|
||||
impl PluginInfo {
|
||||
pub fn get_rules(&self) -> Vec<String> {
|
||||
let mut rules = Vec::with_capacity(self.rule_names.len());
|
||||
|
||||
for rule_name in &self.rule_names {
|
||||
rules.push(format!("{}/{}", self.name, rule_name));
|
||||
}
|
||||
|
||||
rules
|
||||
}
|
||||
}
|
||||
|
||||
impl PluginHost {
|
||||
fn create(logger: PluginLogger) -> Result<PluginHostProxy, AnyError> {
|
||||
let (tx_req, rx_req) = channel(10);
|
||||
|
@ -224,6 +259,7 @@ impl PluginHost {
|
|||
let proxy = PluginHostProxy {
|
||||
tx: tx_req,
|
||||
rx: Arc::new(tokio::sync::Mutex::new(rx_res)),
|
||||
plugin_info: Arc::new(Mutex::new(vec![])),
|
||||
join_handle,
|
||||
logger,
|
||||
};
|
||||
|
@ -325,7 +361,7 @@ impl PluginHost {
|
|||
async fn load_plugins(
|
||||
&mut self,
|
||||
plugin_specifiers: Vec<ModuleSpecifier>,
|
||||
) -> Result<(), AnyError> {
|
||||
) -> Result<Vec<PluginInfo>, AnyError> {
|
||||
let mut load_futures = Vec::with_capacity(plugin_specifiers.len());
|
||||
for specifier in plugin_specifiers {
|
||||
let mod_id = self
|
||||
|
@ -344,6 +380,8 @@ impl PluginHost {
|
|||
.run_event_loop(PollEventLoopOptions::default())
|
||||
.await?;
|
||||
|
||||
let mut infos = Vec::with_capacity(load_futures.len());
|
||||
|
||||
for (fut, mod_id) in load_futures {
|
||||
fut.await?;
|
||||
let module = self.worker.js_runtime.get_module_namespace(mod_id).unwrap();
|
||||
|
@ -358,11 +396,15 @@ impl PluginHost {
|
|||
let args = &[default_export];
|
||||
self.logger.log("Installing plugin...");
|
||||
// TODO(bartlomieju): do it in a try/catch scope
|
||||
install_plugins_local.call(scope, undefined.into(), args);
|
||||
self.logger.log("Plugin installed");
|
||||
let plugin_info = install_plugins_local
|
||||
.call(scope, undefined.into(), args)
|
||||
.unwrap();
|
||||
let info: PluginInfo = deno_core::serde_v8::from_v8(scope, plugin_info)?;
|
||||
self.logger.log(&format!("Plugin installed: {}", info.name));
|
||||
infos.push(info);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(infos)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -384,6 +426,8 @@ impl PluginHostProxy {
|
|||
self
|
||||
.logger
|
||||
.error(&format!("load plugins response {:#?}", result));
|
||||
let infos = result?;
|
||||
*self.plugin_info.lock() = infos;
|
||||
return Ok(());
|
||||
}
|
||||
Err(custom_error("AlreadyClosed", "Plugin host has closed"))
|
||||
|
|
|
@ -125,7 +125,7 @@ impl CliLintRule {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct ConfiguredRules {
|
||||
pub all_rule_codes: HashSet<&'static str>,
|
||||
pub all_rule_codes: HashSet<Cow<'static, str>>,
|
||||
pub rules: Vec<CliLintRule>,
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ impl LintRuleProvider {
|
|||
.chain(cli_lint_rules)
|
||||
.chain(cli_graph_rules)
|
||||
.inspect(|rule| {
|
||||
all_rule_names.insert(rule.code());
|
||||
all_rule_names.insert(rule.code().into());
|
||||
});
|
||||
let rules = filtered_rules(
|
||||
all_rules,
|
||||
|
|
Loading…
Add table
Reference in a new issue