mirror of
https://github.com/denoland/deno.git
synced 2025-03-04 09:57:11 -05:00
feat: support excluding rules from lint plugins
This commit is contained in:
parent
9685d713fc
commit
adc25f85a1
9 changed files with 178 additions and 119 deletions
|
@ -63,6 +63,7 @@ const PropFlags = {
|
||||||
const state = {
|
const state = {
|
||||||
plugins: [],
|
plugins: [],
|
||||||
installedPlugins: new Set(),
|
installedPlugins: new Set(),
|
||||||
|
ignoredRules: new Set(),
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -197,8 +198,9 @@ export class Context {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {LintPlugin} plugin
|
* @param {LintPlugin} plugin
|
||||||
|
* @param {string[]} exclude
|
||||||
*/
|
*/
|
||||||
export function installPlugin(plugin) {
|
export function installPlugin(plugin, exclude) {
|
||||||
if (typeof plugin !== "object") {
|
if (typeof plugin !== "object") {
|
||||||
throw new Error("Linter plugin must be an object");
|
throw new Error("Linter plugin must be an object");
|
||||||
}
|
}
|
||||||
|
@ -214,6 +216,12 @@ export function installPlugin(plugin) {
|
||||||
state.plugins.push(plugin);
|
state.plugins.push(plugin);
|
||||||
state.installedPlugins.add(plugin.name);
|
state.installedPlugins.add(plugin.name);
|
||||||
|
|
||||||
|
// TODO(@marvinhagemeister): This should be done once instead of
|
||||||
|
// for every plugin
|
||||||
|
for (let i = 0; i < exclude.length; i++) {
|
||||||
|
state.ignoredRules.add(exclude[i]);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: plugin.name,
|
name: plugin.name,
|
||||||
ruleNames: Object.keys(plugin.rules),
|
ruleNames: Object.keys(plugin.rules),
|
||||||
|
@ -921,6 +929,12 @@ export function runPluginsForFile(fileName, serializedAst) {
|
||||||
for (const name of Object.keys(plugin.rules)) {
|
for (const name of Object.keys(plugin.rules)) {
|
||||||
const rule = plugin.rules[name];
|
const rule = plugin.rules[name];
|
||||||
const id = `${plugin.name}/${name}`;
|
const id = `${plugin.name}/${name}`;
|
||||||
|
|
||||||
|
// Check if this rule is excluded
|
||||||
|
if (state.ignoredRules.has(id)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
const ctx = new Context(id, fileName);
|
const ctx = new Context(id, fileName);
|
||||||
const visitor = rule.create(ctx);
|
const visitor = rule.create(ctx);
|
||||||
|
|
||||||
|
|
2
cli/js/40_lint_types.d.ts
vendored
2
cli/js/40_lint_types.d.ts
vendored
|
@ -70,6 +70,8 @@ export interface LintPlugin {
|
||||||
export interface LintState {
|
export interface LintState {
|
||||||
plugins: LintPlugin[];
|
plugins: LintPlugin[];
|
||||||
installedPlugins: Set<string>;
|
installedPlugins: Set<string>;
|
||||||
|
/** format: `<plugin>/<rule>` */
|
||||||
|
ignoredRules: Set<string>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type VisitorFn = (node: unknown) => void;
|
export type VisitorFn = (node: unknown) => void;
|
||||||
|
|
|
@ -1643,6 +1643,7 @@ impl ConfigData {
|
||||||
crate::tools::lint::create_runner_and_load_plugins(
|
crate::tools::lint::create_runner_and_load_plugins(
|
||||||
plugin_specifiers,
|
plugin_specifiers,
|
||||||
logger,
|
logger,
|
||||||
|
lint_options.rules.exclude.clone(),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
// eprintln!("plugin load result {:#?}", plugin_load_result);
|
// eprintln!("plugin load result {:#?}", plugin_load_result);
|
||||||
|
|
|
@ -1,5 +1,11 @@
|
||||||
{
|
{
|
||||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "string",
|
||||||
|
"pattern": "^[a-z0-9-]+\\/[a-z0-9-]+$"
|
||||||
|
},
|
||||||
|
{
|
||||||
"enum": [
|
"enum": [
|
||||||
"adjacent-overload-signatures",
|
"adjacent-overload-signatures",
|
||||||
"ban-ts-comment",
|
"ban-ts-comment",
|
||||||
|
@ -109,4 +115,6 @@
|
||||||
"valid-typeof",
|
"valid-typeof",
|
||||||
"verbatim-module-syntax"
|
"verbatim-module-syntax"
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -286,6 +286,8 @@ impl WorkspaceLinter {
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
self.file_count += paths.len();
|
self.file_count += paths.len();
|
||||||
|
|
||||||
|
let exclude = lint_options.rules.exclude.clone();
|
||||||
|
|
||||||
let maybe_plugin_specifiers = lint_options.resolve_lint_plugins()?;
|
let maybe_plugin_specifiers = lint_options.resolve_lint_plugins()?;
|
||||||
let lint_rules = self.lint_rule_provider.resolve_lint_rules_err_empty(
|
let lint_rules = self.lint_rule_provider.resolve_lint_rules_err_empty(
|
||||||
lint_options.rules,
|
lint_options.rules,
|
||||||
|
@ -311,8 +313,11 @@ impl WorkspaceLinter {
|
||||||
let mut plugin_runner = None;
|
let mut plugin_runner = None;
|
||||||
if let Some(plugin_specifiers) = maybe_plugin_specifiers {
|
if let Some(plugin_specifiers) = maybe_plugin_specifiers {
|
||||||
let logger = plugins::PluginLogger::new(logger_printer, true);
|
let logger = plugins::PluginLogger::new(logger_printer, true);
|
||||||
let runner =
|
let runner = plugins::create_runner_and_load_plugins(
|
||||||
plugins::create_runner_and_load_plugins(plugin_specifiers, logger)
|
plugin_specifiers,
|
||||||
|
logger,
|
||||||
|
exclude,
|
||||||
|
)
|
||||||
.await?;
|
.await?;
|
||||||
plugin_runner = Some(Arc::new(Mutex::new(runner)));
|
plugin_runner = Some(Arc::new(Mutex::new(runner)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ use crate::tools::lint::serialize_ast_to_buffer;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum PluginHostRequest {
|
pub enum PluginHostRequest {
|
||||||
LoadPlugins(Vec<ModuleSpecifier>),
|
LoadPlugins(Vec<ModuleSpecifier>, Option<Vec<String>>),
|
||||||
Run(Vec<u8>, PathBuf, SourceTextInfo),
|
Run(Vec<u8>, PathBuf, SourceTextInfo),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,8 +272,8 @@ impl PluginHost {
|
||||||
while let Some(req) = self.rx.recv().await {
|
while let Some(req) = self.rx.recv().await {
|
||||||
self.logger.log("received message");
|
self.logger.log("received message");
|
||||||
match req {
|
match req {
|
||||||
PluginHostRequest::LoadPlugins(specifiers) => {
|
PluginHostRequest::LoadPlugins(specifiers, exclude) => {
|
||||||
let r = self.load_plugins(specifiers).await;
|
let r = self.load_plugins(specifiers, exclude).await;
|
||||||
let _ = self.tx.send(PluginHostResponse::LoadPlugin(r)).await;
|
let _ = self.tx.send(PluginHostResponse::LoadPlugin(r)).await;
|
||||||
}
|
}
|
||||||
PluginHostRequest::Run(serialized_ast, specifier, source_text_info) => {
|
PluginHostRequest::Run(serialized_ast, specifier, source_text_info) => {
|
||||||
|
@ -361,6 +361,7 @@ impl PluginHost {
|
||||||
async fn load_plugins(
|
async fn load_plugins(
|
||||||
&mut self,
|
&mut self,
|
||||||
plugin_specifiers: Vec<ModuleSpecifier>,
|
plugin_specifiers: Vec<ModuleSpecifier>,
|
||||||
|
exclude: Option<Vec<String>>,
|
||||||
) -> Result<Vec<PluginInfo>, AnyError> {
|
) -> Result<Vec<PluginInfo>, AnyError> {
|
||||||
let mut load_futures = Vec::with_capacity(plugin_specifiers.len());
|
let mut load_futures = Vec::with_capacity(plugin_specifiers.len());
|
||||||
for specifier in plugin_specifiers {
|
for specifier in plugin_specifiers {
|
||||||
|
@ -393,7 +394,19 @@ impl PluginHost {
|
||||||
let install_plugins_local =
|
let install_plugins_local =
|
||||||
v8::Local::new(scope, &*self.install_plugin_fn.clone());
|
v8::Local::new(scope, &*self.install_plugin_fn.clone());
|
||||||
let undefined = v8::undefined(scope);
|
let undefined = v8::undefined(scope);
|
||||||
let args = &[default_export];
|
|
||||||
|
let exclude_v8: v8::Local<v8::Value> =
|
||||||
|
exclude.clone().map_or(v8::null(scope).into(), |v| {
|
||||||
|
let elems = v
|
||||||
|
.iter()
|
||||||
|
.map(|item| v8::String::new(scope, item).unwrap().into())
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
v8::Array::new_with_elements(scope, elems.as_slice()).into()
|
||||||
|
});
|
||||||
|
|
||||||
|
let args = &[default_export, exclude_v8];
|
||||||
|
|
||||||
self.logger.log("Installing plugin...");
|
self.logger.log("Installing plugin...");
|
||||||
// TODO(bartlomieju): do it in a try/catch scope
|
// TODO(bartlomieju): do it in a try/catch scope
|
||||||
let plugin_info = install_plugins_local
|
let plugin_info = install_plugins_local
|
||||||
|
@ -412,10 +425,11 @@ impl PluginHostProxy {
|
||||||
pub async fn load_plugins(
|
pub async fn load_plugins(
|
||||||
&self,
|
&self,
|
||||||
plugin_specifiers: Vec<ModuleSpecifier>,
|
plugin_specifiers: Vec<ModuleSpecifier>,
|
||||||
|
exclude: Option<Vec<String>>,
|
||||||
) -> Result<(), AnyError> {
|
) -> Result<(), AnyError> {
|
||||||
self
|
self
|
||||||
.tx
|
.tx
|
||||||
.send(PluginHostRequest::LoadPlugins(plugin_specifiers))
|
.send(PluginHostRequest::LoadPlugins(plugin_specifiers, exclude))
|
||||||
.await?;
|
.await?;
|
||||||
let mut rx = self.rx.lock().await;
|
let mut rx = self.rx.lock().await;
|
||||||
self.logger.log("receiving load plugins");
|
self.logger.log("receiving load plugins");
|
||||||
|
@ -472,9 +486,10 @@ impl PluginHostProxy {
|
||||||
pub async fn create_runner_and_load_plugins(
|
pub async fn create_runner_and_load_plugins(
|
||||||
plugin_specifiers: Vec<ModuleSpecifier>,
|
plugin_specifiers: Vec<ModuleSpecifier>,
|
||||||
logger: PluginLogger,
|
logger: PluginLogger,
|
||||||
|
exclude: Option<Vec<String>>,
|
||||||
) -> Result<PluginHostProxy, AnyError> {
|
) -> Result<PluginHostProxy, AnyError> {
|
||||||
let host_proxy = PluginHost::create(logger)?;
|
let host_proxy = PluginHost::create(logger)?;
|
||||||
host_proxy.load_plugins(plugin_specifiers).await?;
|
host_proxy.load_plugins(plugin_specifiers, exclude).await?;
|
||||||
Ok(host_proxy)
|
Ok(host_proxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
{
|
{
|
||||||
"tempDir": true,
|
|
||||||
"steps": [
|
"steps": [
|
||||||
{
|
{
|
||||||
"args": "lint a.ts",
|
"args": "lint a.ts",
|
||||||
"output": "lint.out",
|
"output": "lint.out",
|
||||||
"exitCode": 1
|
"exitCode": 1
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"args": "lint -c deno_exclude.json a.ts",
|
||||||
|
"output": "lint_exclude.out"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"args": "lint --fix a.ts",
|
"args": "lint --fix a.ts",
|
||||||
"output": "lint_fixed.out"
|
"output": "lint_fixed.out"
|
||||||
|
|
10
tests/specs/lint/lint_plugin/deno_exclude.json
Normal file
10
tests/specs/lint/lint_plugin/deno_exclude.json
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"lint": {
|
||||||
|
"plugins": ["./plugin.ts"],
|
||||||
|
"rules": {
|
||||||
|
"exclude": [
|
||||||
|
"test-plugin/my-rule"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
tests/specs/lint/lint_plugin/lint_exclude.out
Normal file
1
tests/specs/lint/lint_plugin/lint_exclude.out
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Checked 1 file
|
Loading…
Add table
Reference in a new issue