Skip to content

Commit 7a11f07

Browse files
alecalvopjvsqzj
andcommitted
Add SP Reserved spacing rule (#21)
* Add SP Reserved spacing rule * Add support for `while` `for` and `else` * Add rule documentation * Add rule to example_lint_cfg.json --------- Co-authored-by: Vasquez Alfaro, Juan J <juan.j.vasquez.alfaro@intel.com>
1 parent 216cfc6 commit 7a11f07

File tree

14 files changed

+362
-87
lines changed

14 files changed

+362
-87
lines changed

example_files/example_lint_cfg.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
{
2+
"sp_reserved": {},
23
"sp_brace": {},
34
"sp_punct": {},
45
"sp_binop": {},

src/analysis/parsing/statement.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use log::error;
44

55
use crate::lint::rules::indentation::IndentEmptyLoopArgs;
6+
use crate::lint::rules::spacing::SpReservedArgs;
67
use crate::span::Range;
78
use crate::analysis::parsing::lexer::TokenKind;
89
use crate::analysis::parsing::statement;
@@ -437,6 +438,7 @@ impl TreeElement for IfContent {
437438
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
438439
rules.nsp_inparen.check(acc, NspInparenArgs::from_if(self));
439440
rules.indent_paren_expr.check(acc, IndentParenExprArgs::from_if(self));
441+
rules.sp_reserved.check(acc, SpReservedArgs::from_if(self));
440442
}
441443
}
442444

@@ -550,6 +552,7 @@ impl TreeElement for WhileContent {
550552
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
551553
rules.indent_paren_expr.check(acc, IndentParenExprArgs::from_while(self));
552554
rules.indent_empty_loop.check(acc, IndentEmptyLoopArgs::from_while_content(self, aux.depth));
555+
rules.sp_reserved.check(acc, SpReservedArgs::from_while(self));
553556
}
554557
}
555558

@@ -865,6 +868,7 @@ impl TreeElement for ForContent {
865868
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
866869
rules.indent_paren_expr.check(acc, IndentParenExprArgs::from_for(self));
867870
rules.indent_empty_loop.check(acc, IndentEmptyLoopArgs::from_for_content(self, aux.depth));
871+
rules.sp_reserved.check(acc, SpReservedArgs::from_for(self));
868872
}
869873
}
870874

@@ -1284,6 +1288,9 @@ impl TreeElement for AfterContent {
12841288
&self.callexpression,
12851289
&self.semi)
12861290
}
1291+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
1292+
rules.sp_reserved.check(acc, SpReservedArgs::from_after_content(self));
1293+
}
12871294
}
12881295

12891296
impl Parse<StatementContent> for AfterContent {

src/lint/features.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
Below are listed the currently supported rules for linting:
44

55
## Spacing
6+
- SpReserved, `sp_reserved`: around reserved words, such as `if`, `else`, `default`, `size`, `const` and `in`, except when a reserved word is used as an identifier (e.g., `local uint8 *data;`). Currently supported reserved words: `if`, `for` and `while`.
67
- SpBinop, `sp_binop`: spaces around binary operators except for derefencing operators (dot `a.b` and arrow `a->b` )
78
- SpTernary, `sp_ternary`: spaces around `?` and `:` in ternary conditional expressions
89
- SpBraces, `sp_brace`: spaces around braces (`{` and `}`)

src/lint/mod.rs

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,20 @@ use std::path::{Path, PathBuf};
44
use log::{debug, error, trace};
55
use serde::{Deserialize, Serialize};
66
use rules::{instantiate_rules, CurrentRules, RuleType};
7-
use rules::{spacing::{SpBraceOptions, SpPunctOptions, SpBinopOptions, NspFunparOptions,
8-
SpTernaryOptions, SpPtrDeclOptions, NspPtrDeclOptions,
9-
NspInparenOptions, NspUnaryOptions, NspTrailingOptions},
10-
indentation::{LongLineOptions, IndentSizeOptions, IndentCodeBlockOptions,
11-
IndentNoTabOptions, IndentClosingBraceOptions, IndentParenExprOptions, IndentSwitchCaseOptions, IndentEmptyLoopOptions},
7+
use rules::{spacing::{SpReservedOptions,
8+
SpBraceOptions,
9+
SpPunctOptions,
10+
SpBinopOptions,
11+
NspFunparOptions,
12+
SpTernaryOptions,
13+
SpPtrDeclOptions,
14+
NspPtrDeclOptions,
15+
NspInparenOptions,
16+
NspUnaryOptions,
17+
NspTrailingOptions},
18+
indentation::{LongLineOptions, IndentSizeOptions, IndentCodeBlockOptions,
19+
IndentNoTabOptions, IndentClosingBraceOptions, IndentParenExprOptions,
20+
IndentSwitchCaseOptions, IndentEmptyLoopOptions},
1221
};
1322
use crate::analysis::{DMLError, IsolatedAnalysis, LocalDMLError};
1423
use crate::analysis::parsing::tree::TreeElement;
@@ -46,6 +55,8 @@ pub fn maybe_parse_lint_cfg(path: PathBuf) -> Option<LintCfg> {
4655
#[serde(default)]
4756
#[serde(deny_unknown_fields)]
4857
pub struct LintCfg {
58+
#[serde(default)]
59+
pub sp_reserved: Option<SpReservedOptions>,
4960
#[serde(default)]
5061
pub sp_brace: Option<SpBraceOptions>,
5162
#[serde(default)]
@@ -93,6 +104,7 @@ fn get_true() -> bool {
93104
impl Default for LintCfg {
94105
fn default() -> LintCfg {
95106
LintCfg {
107+
sp_reserved: Some(SpReservedOptions{}),
96108
sp_brace: Some(SpBraceOptions{}),
97109
sp_punct: Some(SpPunctOptions{}),
98110
sp_binop: Some(SpBinopOptions{}),
@@ -242,6 +254,8 @@ pub mod tests {
242254
env!("CARGO_MANIFEST_DIR"),
243255
EXAMPLE_CFG);
244256
let example_cfg = parse_lint_cfg(example_path.into()).unwrap();
257+
println!("Example LintCfg: {:#?}", example_cfg);
258+
println!("LintCfg::default(): {:#?}", LintCfg::default());
245259
assert_eq!(example_cfg, LintCfg::default());
246260
}
247261
}

src/lint/rules/mod.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,23 @@ pub mod indentation;
44
#[cfg(test)]
55
pub mod tests;
66

7-
use spacing::{NspFunparRule, NspInparenRule, NspTrailingRule, NspUnaryRule, SpBracesRule, SpBinopRule, SpTernaryRule, SpPtrDeclRule, NspPtrDeclRule, SpPunctRule};
7+
use spacing::{NspFunparRule,
8+
NspInparenRule,
9+
NspTrailingRule,
10+
NspUnaryRule,
11+
SpBracesRule,
12+
SpBinopRule,
13+
SpTernaryRule,
14+
SpPtrDeclRule,
15+
NspPtrDeclRule,
16+
SpPunctRule,
17+
SpReservedRule};
818
use indentation::{LongLinesRule, IndentNoTabRule, IndentCodeBlockRule, IndentClosingBraceRule, IndentParenExprRule, IndentSwitchCaseRule, IndentEmptyLoopRule};
919
use crate::lint::{LintCfg, DMLStyleError};
1020
use crate::analysis::{LocalDMLError, parsing::tree::ZeroRange};
1121

1222
pub struct CurrentRules {
23+
pub sp_reserved: SpReservedRule,
1324
pub sp_brace: SpBracesRule,
1425
pub sp_punct: SpPunctRule,
1526
pub sp_binop: SpBinopRule,
@@ -31,6 +42,7 @@ pub struct CurrentRules {
3142

3243
pub fn instantiate_rules(cfg: &LintCfg) -> CurrentRules {
3344
CurrentRules {
45+
sp_reserved: SpReservedRule { enabled: cfg.sp_reserved.is_some() },
3446
sp_brace: SpBracesRule { enabled: cfg.sp_brace.is_some() },
3547
sp_punct: SpPunctRule { enabled: cfg.sp_punct.is_some() },
3648
sp_binop: SpBinopRule { enabled: cfg.sp_binop.is_some() },
@@ -70,6 +82,7 @@ pub trait Rule {
7082

7183
#[derive(PartialEq, Debug, Clone, Eq, Hash)]
7284
pub enum RuleType {
85+
SpReserved,
7386
SpBraces,
7487
SpPunct,
7588
SpBinop,

src/lint/rules/spacing.rs

Lines changed: 106 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,117 @@ use crate::analysis::parsing::expression::{BinaryExpressionContent,
1313
PostUnaryExpressionContent,
1414
TertiaryExpressionContent,
1515
UnaryExpressionContent};
16-
use crate::analysis::parsing::statement::{CompoundContent,
17-
ExpressionStmtContent,
18-
IfContent, VariableDeclContent};
16+
use crate::analysis::parsing::statement::{AfterContent, CompoundContent, ExpressionStmtContent,
17+
ForContent, IfContent, VariableDeclContent,
18+
WhileContent};
1919
use crate::analysis::parsing::structure::{MethodContent,
2020
ObjectStatementsContent};
2121

2222
use crate::span::{ZeroIndexed, Range};
2323

24+
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
25+
pub struct SpReservedOptions {}
26+
27+
pub struct SpReservedRule {
28+
pub enabled: bool,
29+
}
30+
pub struct SpReservedArgs {
31+
before_range: Option<ZeroRange>,
32+
token_range: ZeroRange,
33+
after_range: Option<ZeroRange>,
34+
}
35+
impl SpReservedArgs {
36+
pub fn from_after_content(node: &AfterContent) -> Vec<SpReservedArgs> {
37+
let mut args_list = vec![];
38+
if let Some(timer) = &node.timer {
39+
args_list.push(SpReservedArgs {
40+
before_range: None,
41+
token_range: node.after.range(),
42+
after_range: Some(timer.range()),
43+
});
44+
}
45+
args_list
46+
}
47+
pub fn from_if(node: &IfContent) -> Vec<SpReservedArgs> {
48+
let mut args_list = vec![];
49+
50+
args_list.push(SpReservedArgs {
51+
before_range: None,
52+
token_range: node.iftok.range(),
53+
after_range: Some(node.lparen.range()),
54+
});
55+
56+
if let Some((else_tok, elsebranch)) = &node.elsebranch {
57+
args_list.push(SpReservedArgs {
58+
before_range: Some(node.truebranch.range()),
59+
token_range: else_tok.range(),
60+
after_range: Some(elsebranch.range()),
61+
});
62+
}
63+
64+
args_list
65+
}
66+
pub fn from_for(node: &ForContent) -> Vec<SpReservedArgs> {
67+
let mut args_list = vec![];
68+
args_list.push(SpReservedArgs {
69+
before_range: None,
70+
token_range: node.fortok.range(),
71+
after_range: Some(node.lparen.range()),
72+
});
73+
args_list
74+
}
75+
pub fn from_while(node: &WhileContent) -> Vec<SpReservedArgs> {
76+
let mut args_list = vec![];
77+
args_list.push(SpReservedArgs {
78+
before_range: None,
79+
token_range: node.whiletok.range(),
80+
after_range: Some(node.lparen.range()),
81+
});
82+
args_list
83+
}
84+
}
85+
86+
impl SpReservedRule {
87+
pub fn check(&self, acc: &mut Vec<DMLStyleError>,
88+
args: Vec<SpReservedArgs>) {
89+
if !self.enabled { return; }
90+
for arg in args {
91+
if let Some(before_range) = &arg.before_range {
92+
if (before_range.row_end == arg.token_range.row_start)
93+
&& (before_range.col_end == arg.token_range.col_start) {
94+
acc.push(
95+
self.create_err(Range::combine(
96+
*before_range, arg.token_range
97+
))
98+
);
99+
}
100+
}
101+
if let Some(after_range) = &arg.after_range {
102+
if (arg.token_range.row_end == after_range.row_start)
103+
&& (arg.token_range.col_end == after_range.col_start) {
104+
acc.push(
105+
self.create_err(Range::combine(
106+
arg.token_range, *after_range
107+
))
108+
);
109+
}
110+
}
111+
}
112+
}
113+
}
114+
115+
impl Rule for SpReservedRule {
116+
fn name() -> &'static str {
117+
"SP_RESERVED"
118+
}
119+
fn description() -> &'static str {
120+
"Missing space around reserved words"
121+
}
122+
fn get_rule_type() -> RuleType {
123+
RuleType::SpReserved
124+
}
125+
}
126+
24127
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
25128
pub struct SpBraceOptions {}
26129

src/lint/rules/tests/spacing/mod.rs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,29 +6,18 @@ mod nsp_unary;
66
mod sp_braces;
77
mod sp_ptrdecl;
88
mod sp_punct;
9+
mod sp_reserved;
910
mod sp_binop;
1011
mod sp_ternary;
1112

12-
// Put whitespace (space or newline):
13-
// SP.reserved around reserved words, such as if, else, default,
14-
// size, const and in, except when a reserved word is used as an identifier
15-
// (e.g., local uint8 *data;)
16-
#[allow(dead_code)]
17-
static SP_RESERVED: &str = "
18-
method this_is_some_method() {
19-
local int this_some_integer = 0x666;
20-
if(this_some_integer == 0x666)
21-
return;
22-
}
23-
";
2413

2514
// SP.comment around the comment delimiters //, /* and **/
2615
#[allow(dead_code)]
2716
static SP_COMMENT: &str = "
2817
/*Function
2918
documentation*/
3019
method this_is_some_method(conf_object_t *dummy_obj) {
31-
if(!dummy_obj)//Not null
20+
if (!dummy_obj)//Not null
3221
return;
3322
}
3423
";

src/lint/rules/tests/spacing/nsp_funpar.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use crate::lint::rules::RuleType;
55
// NSP.funpar between a function/method name and its opening parenthesis
66
static NO_SPACE_METHOD_FUNC_INCORRECT: &str = "
77
method this_is_some_method (conf_object_t *dummy_obj) {
8-
if(!dummy_obj)
8+
if (!dummy_obj)
99
other_method_called ();
1010
}
1111
";
@@ -25,7 +25,7 @@ fn no_space_method_func_incorrect() {
2525

2626
static NO_SPACE_METHOD_FUNC_CORRECT: &str = "
2727
method this_is_some_method(conf_object_t *dummy_obj) {
28-
if(!dummy_obj)
28+
if (!dummy_obj)
2929
other_method_called();
3030
}
3131
";

src/lint/rules/tests/spacing/nsp_inparen.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::lint::rules::RuleType;
44
// NSP.inparen immediately inside parentheses or brackets
55
static NO_SPACE_INPAREN_METHOD_FUNC_INDEX_INCORRECT: &str = "
66
method this_is_some_method( conf_object_t *dummy_obj ) {
7-
if( !dummy_obj[ 0 ] )
7+
if ( !dummy_obj[ 0 ] )
88
return;
99
}
1010
";
@@ -15,10 +15,10 @@ fn no_space_inparen_method_func_index_incorrect() {
1515
RuleType::NspInparen,
1616
(1, 1, 27, 28),
1717
(1, 1, 52, 53),
18-
(2, 2, 7, 8),
19-
(2, 2, 23, 24),
20-
(2, 2, 19, 20),
21-
(2, 2, 21, 22),
18+
(2, 2, 8, 9),
19+
(2, 2, 24, 25),
20+
(2, 2, 20, 21),
21+
(2, 2, 22, 23),
2222
);
2323
assert_snippet(NO_SPACE_INPAREN_METHOD_FUNC_INDEX_INCORRECT, expected_errors, &rules);
2424
// Test rule disable
@@ -29,7 +29,7 @@ fn no_space_inparen_method_func_index_incorrect() {
2929
// NSP.inparen immediately inside parentheses or brackets
3030
static NO_SPACE_INPAREN_METHOD_FUNC_INDEX_CORRECT: &str = "
3131
method this_is_some_method(conf_object_t *dummy_obj) {
32-
if(!dummy_obj[0])
32+
if (!dummy_obj[0])
3333
return;
3434
}
3535
";

0 commit comments

Comments
 (0)