Skip to content
This repository has been archived by the owner on Jul 3, 2024. It is now read-only.

Commit

Permalink
merge: PR #148 from feature/50-solidity-linter-rules/101-no-empty-blo…
Browse files Browse the repository at this point in the history
…cks-rule-staging

101 - No Empty Blocks Rule
  • Loading branch information
0xmemorygrinder authored Oct 9, 2023
2 parents 417e9b5 + 521c7d1 commit 9d8cc99
Show file tree
Hide file tree
Showing 8 changed files with 186 additions and 2 deletions.
4 changes: 3 additions & 1 deletion libs/ast-extractor/src/retriever.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,16 @@ pub use r#struct::*;
mod udt;
pub use udt::*;

mod using;
mod finder;
mod using;

pub use using::*;

mod stmts;
pub use stmts::*;

mod block;
pub use block::*;
pub use finder::*;

mod expr_call;
Expand Down
24 changes: 24 additions & 0 deletions libs/ast-extractor/src/retriever/block.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use syn_solidity::{Block, Visit};

struct BlockVisitor {
blocks: Vec<Block>,
}

impl BlockVisitor {
pub fn new() -> Self {
Self { blocks: Vec::new() }
}
}

impl<'ast> Visit<'ast> for BlockVisitor {
fn visit_block(&mut self, i: &Block) {
self.blocks.push(i.clone());
syn_solidity::visit::visit_block(self, i);
}
}

pub fn retrieve_block_nodes(ast: &syn_solidity::File) -> Vec<Block> {
let mut visitor = BlockVisitor::new();
visitor.visit_file(ast);
visitor.blocks
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
use crate::linter::SolidFile;
use crate::rules::types::*;
use crate::types::*;
use ast_extractor::{
retriever::{retrieve_block_nodes, retrieve_contract_nodes},
Spanned,
};

// const DEFAULT_SEVERITY: &str = "warn";
const DEFAULT_MESSAGE: &str = "should not be an empty block";
pub const RULE_ID: &str = "empty-block";

pub struct EmptyBlock {
_data: RuleEntry,
}

impl RuleType for EmptyBlock {
fn diagnose(&self, _file: &SolidFile, _files: &[SolidFile]) -> Vec<LintDiag> {
let mut res = Vec::new();
let _reports = check_empty_block(_file);
for report in _reports.iter().flatten() {
res.push(LintDiag {
id: RULE_ID.to_string(),
severity: Some(Severity::WARNING),
range: report.clone(),
code: None,
source: None,
message: DEFAULT_MESSAGE.to_string(),
uri: _file.path.clone(),
source_file_content: _file.content.clone(),
});
}
res
}
}

fn check_empty_block(file: &SolidFile) -> Vec<Option<Range>> {
let mut res: Vec<Option<Range>> = Vec::new();

let contracts = retrieve_contract_nodes(&file.data);
for contract in contracts.iter() {
if contract.body.is_empty() {
res.push(Some(Range {
start: Position {
line: contract.span().start().line,
character: contract.span().start().column + 1,
},
end: Position {
line: contract.span().end().line,
character: contract.span().end().column,
},
}));
}
}

let blocks = retrieve_block_nodes(&file.data);
for block in blocks.iter() {
if block.stmts.is_empty() {
res.push(Some(Range {
start: Position {
line: block.span().start().line,
character: block.span().start().column + 1,
},
end: Position {
line: block.span().end().line,
character: block.span().end().column,
},
}));
}
}
res
}

impl EmptyBlock {
pub fn create(data: RuleEntry) -> Box<dyn RuleType> {
let rule = EmptyBlock { _data: data };
Box::new(rule)
}

pub fn create_default() -> RuleEntry {
RuleEntry {
id: RULE_ID.to_string(),
severity: Severity::WARNING,
data: vec![],
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ use std::collections::HashMap;
#[macro_use]
pub mod line_maxlen;
pub mod custom_errors;
pub mod empty_block;
pub mod function_max_lines;
pub mod global_import;
pub mod max_states_count;
pub mod reason_string;

pub mod one_contract_per_file;

// List all rules

use crate::rules::best_practises::custom_errors::CustomErrors;
use crate::rules::best_practises::empty_block::EmptyBlock;
use crate::rules::best_practises::function_max_lines::FunctionMaxLines;
use crate::rules::best_practises::global_import::GlobalImport;
use crate::rules::best_practises::line_maxlen::LineMaxLen;
Expand All @@ -31,6 +32,7 @@ pub fn create_default_rules() -> Vec<RuleEntry> {
OneContractPerFile::create_default(),
CustomErrors::create_default(),
GlobalImport::create_default(),
EmptyBlock::create_default(),
]
}

Expand All @@ -54,6 +56,7 @@ pub fn create_rules() -> RulesMap {
OneContractPerFile::create,
);
rules.insert(global_import::RULE_ID.to_string(), GlobalImport::create);
rules.insert(empty_block::RULE_ID.to_string(), EmptyBlock::create);

rules
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
{
"name": "solidhunter",
"includes": [],
"plugins": [],
"rules": [
{
"id": "line-max-len",
"severity": "WARNING",
"data": [
"80"
]
},
{
"id": "max-states-count",
"severity": "WARNING",
"data": [
"15"
]
},
{
"id": "function-max-lines",
"severity": "WARNING",
"data": [
"20"
]
},
{
"id": "reason-string",
"severity": "WARNING",
"data": [
"32"
]
},
{
"id": "func-name-camelcase",
"severity": "WARNING",
"data": []
},
{
"id": "func-param-name-camelcase",
"severity": "WARNING",
"data": []
},
{
"id": "use-forbidden-name",
"severity": "WARNING",
"data": []
},
{
"id": "import-on-top",
"severity": "WARNING",
"data": []
},
{
"id": "empty-block",
"severity": "WARNING",
"data": []
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pragma solidity 0.8.19;

contract Test {}

contract Test_b {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
empty-block:3:10:3:13
empty-block:5:10:5:15
Original file line number Diff line number Diff line change
Expand Up @@ -157,5 +157,6 @@ test_directories! {
EventNameCamelCase,
ConstNameSnakeCase,
StateVisibility,
EmptyBlock,
GlobalImport
}

0 comments on commit 9d8cc99

Please sign in to comment.