Skip to content
This repository was archived by the owner on Nov 9, 2023. It is now read-only.

Commit e92d9a2

Browse files
ByFishhAlexandre jublot
authored and
Alexandre jublot
committed
feat(rules): adding rules ordering file, contract and visibility draft
1 parent a9e3c1f commit e92d9a2

File tree

4 files changed

+276
-65
lines changed

4 files changed

+276
-65
lines changed
+12-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
use std::collections::HashMap;
2+
use crate::rules::order::ordering_contract::OrderingContract;
3+
use crate::rules::order::ordering_file::OrderingFile;
4+
use crate::rules::order::ordering_visibility::OrderingVisibility;
25
use crate::rules::types::{RuleEntry, RuleType};
3-
use crate::rules::order::ordering::Ordering;
46

57
#[macro_use]
6-
pub(crate) mod ordering;
8+
pub(crate) mod ordering_contract;
9+
pub(crate) mod ordering_file;
10+
mod ordering_visibility;
711

812
// List all rules
913

@@ -12,15 +16,19 @@ use crate::rules::RuleBuilder;
1216
pub fn create_default_rules() -> Vec<RuleEntry> {
1317
let mut rules = Vec::new();
1418

15-
rules.push(Ordering::create_default());
19+
rules.push(OrderingContract::create_default());
20+
rules.push(OrderingFile::create_default());
21+
rules.push(OrderingVisibility::create_default());
1622

1723
rules
1824
}
1925

2026
pub fn create_rules() -> HashMap<String, fn(RuleEntry) -> Box<dyn RuleType>> {
2127
let mut rules : HashMap<String, RuleBuilder> = HashMap::new();
2228

23-
rules.insert( "ordering".to_string(), Ordering::create);
29+
rules.insert( "ordering-contract".to_string(), OrderingContract::create);
30+
rules.insert( "ordering-file".to_string(), OrderingFile::create);
31+
rules.insert( "ordering-visibility".to_string(), OrderingFile::create);
2432

2533
rules
2634
}

solidhunter-lib/src/rules/order/ordering.rs renamed to solidhunter-lib/src/rules/order/ordering_contract.rs

+13-61
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::rules::types::*;
44
use crate::types::*;
55
use solc_wrapper::{ContractDefinitionChildNodes, ContractKind, decode_location, NodeType, SourceLocation, SourceUnit, SourceUnitChildNodes};
66

7-
pub struct Ordering {
7+
pub struct OrderingContract {
88
data: RuleEntry
99
}
1010

@@ -14,93 +14,45 @@ pub struct Eval {
1414
src: SourceLocation
1515
}
1616

17-
fn eval_file(source_unit_childs: &Vec<SourceUnitChildNodes>) -> Vec<Eval>{
18-
19-
let mut eval = Vec::new();
20-
21-
for node in source_unit_childs {
22-
match node {
23-
SourceUnitChildNodes::ErrorDefinition(error) => {
24-
if error.node_type == NodeType::EnumDefinition {
25-
eval.push(Eval { weight: 1, src: error.src.clone() });
26-
} else if error.node_type == NodeType::StructDefinition {
27-
eval.push(Eval { weight: 2, src: error.src.clone() });
28-
}
29-
//TODO: Remove this when Error definition fixed
30-
}
31-
SourceUnitChildNodes::EnumDefinition(tmp) => eval.push(Eval { weight: 2, src: tmp.src.clone() }),
32-
SourceUnitChildNodes::StructDefinition(tmp) => eval.push(Eval { weight: 3, src: tmp.src.clone() }),
33-
SourceUnitChildNodes::ContractDefinition(contract) => {
34-
if contract.contract_kind == ContractKind::Interface {
35-
eval.push(Eval { weight: 3, src: contract.src.clone() });
36-
} else if contract.contract_kind == ContractKind::Library {
37-
eval.push(Eval { weight: 4, src: contract.src.clone() });
38-
} else {
39-
eval.push(Eval { weight: 5, src: contract.src.clone() });
40-
}
41-
}
42-
_ => { continue; }
43-
}
44-
}
45-
46-
eval
47-
}
48-
4917
fn eval_contract(contract_child_node: &Vec<ContractDefinitionChildNodes>) -> Vec<Eval>{
5018

5119
let mut eval = Vec::new();
5220

5321
for node in contract_child_node {
5422
match node {
23+
24+
ContractDefinitionChildNodes::UsingForDirective(tmp) => eval.push(Eval { weight: 1, src: tmp.src.clone() }),
25+
5526
ContractDefinitionChildNodes::ErrorDefinition(tmp) => {
5627
//TODO: Remove this when Error definition fixed
5728
if tmp.node_type == NodeType::EnumDefinition {
5829
eval.push(Eval { weight: 3, src: tmp.src.clone() });
5930
} else if tmp.node_type == NodeType::StructDefinition {
6031
eval.push(Eval { weight: 2, src: tmp.src.clone() });
32+
} else if tmp.node_type == NodeType::EventDefinition {
33+
eval.push(Eval { weight: 5, src: tmp.src.clone() });
6134
}
6235
},
63-
ContractDefinitionChildNodes::UsingForDirective(tmp) => eval.push(Eval { weight: 1, src: tmp.src.clone() }),
6436
ContractDefinitionChildNodes::StructDefinition(tmp) => eval.push(Eval { weight: 2, src: tmp.src.clone() }),
6537
ContractDefinitionChildNodes::EnumDefinition(tmp) => eval.push(Eval { weight: 3, src: tmp.src.clone() }),
38+
6639
ContractDefinitionChildNodes::VariableDeclaration(tmp) => eval.push(Eval { weight: 4, src: tmp.src.clone() }),
6740
ContractDefinitionChildNodes::EventDefinition(tmp) => eval.push(Eval { weight: 5, src: tmp.src.clone() }),
6841
ContractDefinitionChildNodes::ModifierDefinition(tmp) => eval.push(Eval { weight: 6, src: tmp.src.clone() }),
6942
ContractDefinitionChildNodes::FunctionDefinition(tmp) => eval.push(Eval { weight: 7, src: tmp.src.clone() }),
43+
7044
_ => { continue; }
7145
}
7246
}
7347

7448
eval
7549
}
7650

77-
impl RuleType for Ordering {
51+
impl RuleType for OrderingContract {
7852

7953
fn diagnose(&self, file: &SolidFile, files: &Vec<SolidFile>) -> Vec<LintDiag> {
8054

8155
let mut res = Vec::new();
82-
let eval = eval_file(&file.data.nodes);
83-
84-
if eval.len() > 1 {
85-
for i in 0..eval.len() - 1 {
86-
if eval[i].weight > eval[i + 1].weight {
87-
let location = decode_location(&eval[i].src, &file.content);
88-
res.push(LintDiag {
89-
range: Range {
90-
start: Position { line: location.0.line as u64, character: location.0.column as u64 },
91-
end: Position { line: location.1.line as u64, character: location.1.column as u64 },
92-
length: location.0.length as u64,
93-
},
94-
message: format!("File need to be ordered: Using for -> Struct -> Enum -> Variable -> Event -> Modifier -> Function"),
95-
severity: Some(self.data.severity),
96-
code: None,
97-
source: None,
98-
uri: file.path.clone(),
99-
source_file_content: file.content.clone(),
100-
});
101-
}
102-
}
103-
}
10456

10557
for node in &file.data.nodes {
10658
match node {
@@ -117,7 +69,7 @@ impl RuleType for Ordering {
11769
end: Position { line: location.1.line as u64, character: location.1.column as u64 },
11870
length: location.0.length as u64,
11971
},
120-
message: format!("Contract need to be ordered: Enum -> Struct -> Interface -> Library -> Contract"),
72+
message: format!("Contract need to be ordered: Using for -> Struct -> Enum -> Variable -> Event -> Modifier -> Function"),
12173
severity: Some(self.data.severity),
12274
code: None,
12375
source: None,
@@ -135,17 +87,17 @@ impl RuleType for Ordering {
13587
}
13688
}
13789

138-
impl Ordering {
90+
impl OrderingContract {
13991
pub(crate) fn create(data: RuleEntry) -> Box<dyn RuleType> {
140-
let mut rule = Ordering {
92+
let mut rule = OrderingContract {
14193
data
14294
};
14395
Box::new(rule)
14496
}
14597

14698
pub(crate) fn create_default() -> RuleEntry {
14799
RuleEntry {
148-
id: "ordering".to_string(),
100+
id: "ordering-contract".to_string(),
149101
severity: Severity::WARNING,
150102
data: vec![]
151103
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
use clap::builder::Str;
2+
use crate::linter::SolidFile;
3+
use crate::rules::types::*;
4+
use crate::types::*;
5+
use solc_wrapper::{ContractDefinitionChildNodes, ContractKind, decode_location, NodeType, SourceLocation, SourceUnit, SourceUnitChildNodes};
6+
7+
pub struct OrderingFile {
8+
data: RuleEntry
9+
}
10+
11+
#[derive(Debug)]
12+
pub struct Eval {
13+
weight: usize,
14+
src: SourceLocation
15+
}
16+
17+
fn eval_file(source_unit_childs: &Vec<SourceUnitChildNodes>, res: &mut Vec<LintDiag>, severity: Severity, file: &SolidFile) -> Vec<Eval>{
18+
19+
let mut eval = Vec::new();
20+
21+
for node in source_unit_childs {
22+
match node {
23+
SourceUnitChildNodes::ContractDefinition(contract) => {
24+
if contract.contract_kind == ContractKind::Interface {
25+
eval.push(Eval { weight: 1, src: contract.src.clone() });
26+
} else if contract.contract_kind == ContractKind::Library {
27+
eval.push(Eval { weight: 2, src: contract.src.clone() });
28+
} else {
29+
eval.push(Eval { weight: 3, src: contract.src.clone() });
30+
}
31+
}
32+
SourceUnitChildNodes::ErrorDefinition(error) => {
33+
let location = decode_location(error.src.as_str(), &file.content);
34+
35+
if error.node_type == NodeType::EnumDefinition {
36+
res.push(LintDiag {
37+
range: Range {
38+
start: Position { line: location.0.line as u64, character: location.0.column as u64 },
39+
end: Position { line: location.1.line as u64, character: location.1.column as u64 },
40+
length: location.0.length as u64,
41+
},
42+
message: format!("Enum can't be outside a contract."),
43+
severity: Some(severity),
44+
code: None,
45+
source: None,
46+
uri: file.path.clone(),
47+
source_file_content: file.content.clone(),
48+
});
49+
} else if error.node_type == NodeType::StructDefinition {
50+
res.push(LintDiag {
51+
range: Range {
52+
start: Position { line: location.0.line as u64, character: location.0.column as u64 },
53+
end: Position { line: location.1.line as u64, character: location.1.column as u64 },
54+
length: location.0.length as u64,
55+
},
56+
message: format!("Struct can't be outside a contract."),
57+
severity: Some(severity),
58+
code: None,
59+
source: None,
60+
uri: file.path.clone(),
61+
source_file_content: file.content.clone(),
62+
});
63+
}
64+
//TODO: Edit this when Error definition fixed
65+
}
66+
//SourceUnitChildNodes::EnumDefinition(tmp) => eval.push(Eval { weight: 2, src: tmp.src.clone() }),
67+
//SourceUnitChildNodes::StructDefinition(tmp) => eval.push(Eval { weight: 3, src: tmp.src.clone() }),
68+
_ => { continue; }
69+
}
70+
}
71+
72+
eval
73+
}
74+
75+
impl RuleType for OrderingFile {
76+
fn diagnose(&self, file: &SolidFile, files: &Vec<SolidFile>) -> Vec<LintDiag> {
77+
78+
let mut res = Vec::new();
79+
let eval = eval_file(&file.data.nodes, &mut res, self.data.severity, file);
80+
81+
if eval.len() > 1 {
82+
for i in 0..eval.len() - 1 {
83+
if eval[i].weight > eval[i + 1].weight {
84+
let location = decode_location(&eval[i].src, &file.content);
85+
res.push(LintDiag {
86+
range: Range {
87+
start: Position { line: location.0.line as u64, character: location.0.column as u64 },
88+
end: Position { line: location.1.line as u64, character: location.1.column as u64 },
89+
length: location.0.length as u64,
90+
},
91+
message: format!("File need to be ordered: Interface -> Library -> Contract"),
92+
severity: Some(self.data.severity),
93+
code: None,
94+
source: None,
95+
uri: file.path.clone(),
96+
source_file_content: file.content.clone(),
97+
});
98+
}
99+
}
100+
}
101+
102+
res
103+
}
104+
}
105+
106+
impl OrderingFile {
107+
pub(crate) fn create(data: RuleEntry) -> Box<dyn RuleType> {
108+
let mut rule = OrderingFile {
109+
data
110+
};
111+
Box::new(rule)
112+
}
113+
114+
pub(crate) fn create_default() -> RuleEntry {
115+
RuleEntry {
116+
id: "ordering-file".to_string(),
117+
severity: Severity::WARNING,
118+
data: vec![]
119+
}
120+
}
121+
}

0 commit comments

Comments
 (0)