Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature: Update plugin API. #255

Merged
merged 8 commits into from
Jun 23, 2023
77 changes: 66 additions & 11 deletions src/linter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,33 @@ use std::collections::HashMap;
use std::path::{Path, PathBuf};
use sv_parser::{unwrap_locate, Locate, NodeEvent, RefNode, SyntaxTree};

// Rule enum is for use by plugins.
#[derive(Clone, Copy)]
pub enum Rule {
Text(*mut dyn TextRule),
Syntax(*mut dyn SyntaxRule),
}

// Macro for use within plugins.
// Example usage in a plugin's `get_plugin` function:
// pluginrules!(
// SamplePlugin,
// AnotherPlugin,
// )
#[macro_export]
macro_rules! pluginrules {
( $( $x:ty ),* $(,)? ) => {
{
let mut vec: Vec<Rule> = Vec::new();
$(
let rule = <$x>::default();
vec.push(rule.into_rule());
)*
vec
}
};
}

#[derive(Clone, Copy)]
pub enum TextRuleResult {
Pass,
Expand All @@ -23,6 +50,14 @@ pub trait TextRule: Sync + Send {
fn name(&self) -> String;
fn hint(&self, config: &ConfigOption) -> String;
fn reason(&self) -> String;

fn into_rule(self) -> Rule
where
Self: Sized + 'static,
{
let temp = Box::new(self);
Rule::Text(Box::into_raw(temp))
}
}

#[derive(Clone, Copy)]
Expand All @@ -43,6 +78,14 @@ pub trait SyntaxRule: Sync + Send {
fn name(&self) -> String;
fn hint(&self, config: &ConfigOption) -> String;
fn reason(&self) -> String;

fn into_rule(self) -> Rule
where
Self: Sized + 'static,
{
let temp = Box::new(self);
Rule::Syntax(Box::into_raw(temp))
}
}

pub struct Linter {
Expand Down Expand Up @@ -86,20 +129,32 @@ impl Linter {
}
}

pub fn load(&mut self, path: &Path) {
let lib = unsafe { Library::new(path) };
if let Ok(lib) = lib {
self.plugins.push(lib);
let lib = self.plugins.last().unwrap();
pub fn load(&mut self, path: &Path) -> Result<(), libloading::Error> {
let lib = unsafe { Library::new(path) }?;

let get_plugin: Result<Symbol<extern "C" fn() -> *mut dyn SyntaxRule>, _> =
unsafe { lib.get(b"get_plugin") };
if let Ok(get_plugin) = get_plugin {
let plugin = unsafe { Box::from_raw(get_plugin()) };
self.ctl_enabled.insert(plugin.name(), true);
self.syntaxrules.push(plugin);
self.plugins.push(lib);
let lib = self.plugins.last().unwrap();

let get_plugin: Result<Symbol<extern "C" fn() -> Vec<Rule>>, _> =
unsafe { lib.get(b"get_plugin") };
if let Ok(get_plugin) = get_plugin {
let plugins = get_plugin();
for plugin in plugins {
match plugin {
Rule::Text(p) => {
let plugin = unsafe { Box::from_raw(p) };
self.textrules.push(plugin);
},
Rule::Syntax(p) => {
let plugin = unsafe { Box::from_raw(p) };
self.ctl_enabled.insert(plugin.name(), true);
self.syntaxrules.push(plugin);
},
}
}
}

Ok(())
}

pub fn textrules_check(&mut self, line: &str, path: &Path, beg: &usize) -> Vec<LintFailed> {
Expand Down
31 changes: 17 additions & 14 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,14 +171,18 @@ pub fn run_opt(printer: &mut Printer, opt: &Opt) -> Result<bool, Error> {
_ => true,
};

if !opt.silent && !do_dump_filelist && !opt.preprocess_only {
let msg = format!(
"Config file '{}' is not found. Enable all rules",
opt.config.to_string_lossy()
);
printer.print_warning(&msg)?;
if !opt.plugins.is_empty() {
Config::new()
} else {
if !opt.silent && !do_dump_filelist && !opt.preprocess_only {
let msg = format!(
"Config file '{}' is not found. Enable all rules",
opt.config.to_string_lossy()
);
printer.print_warning(&msg)?;
}
Config::new().enable_all()
}
Config::new().enable_all()
};

run_opt_config(printer, opt, config)
Expand All @@ -198,7 +202,7 @@ pub fn run_opt_config(printer: &mut Printer, opt: &Opt, config: Config) -> Resul

let mut linter = Linter::new(config);
for plugin in &opt.plugins {
linter.load(&plugin);
linter.load(&plugin)?;
}

let mut defines = HashMap::new();
Expand Down Expand Up @@ -267,17 +271,16 @@ pub fn run_opt_config(printer: &mut Printer, opt: &Opt, config: Config) -> Resul
let text: String = read_to_string(&path)?;

let mut beg: usize = 0;
for line in text.lines() {
for failed in linter.textrules_check(&line, &path, &beg) {
for line in text.split_inclusive('\n') {
let line_stripped = line.trim_end_matches(&['\n', '\r']);

for failed in linter.textrules_check(&line_stripped, &path, &beg) {
pass = false;
if !opt.silent {
printer.print_failed(&failed, opt.single, opt.github_actions)?;
}
}

// Newlines are not included in each line and `text` does not
// contain CRLF because `read_to_string` convents CRLF to LF.
beg += line.len() + 1; // Track the beginning byte index.
beg += line.len();
}

match parse_sv_str(text.as_str(), &path, &defines, &includes, opt.ignore_include, false) {
Expand Down