Skip to content

Commit 57823d9

Browse files
authored
Merge pull request #6 from kevv87/feat/lint_in4
Support for IN4 Rule
2 parents 9e616a7 + e915c23 commit 57823d9

File tree

13 files changed

+390
-68
lines changed

13 files changed

+390
-68
lines changed

example_files/example_lint_cfg.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"in1": { "indentation_spaces": 4 },
1010
"in2": {},
1111
"in3": {},
12+
"in4": {},
1213
"in9": {},
1314
"in10": {}
1415
}

src/analysis/parsing/statement.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ use crate::analysis::parsing::structure::{parse_vardecl, VarDecl};
2525
use crate::analysis::LocalDMLError;
2626
use crate::lint::{DMLStyleError,
2727
rules::{CurrentRules,
28-
indentation::{IN3Args, IN9Args},
29-
spacing::{NspInparenArgs,
30-
SpBracesArgs,
31-
SpPunctArgs}},
32-
AuxParams};
28+
indentation::{IN3Args, IN4Args, IN9Args},
29+
spacing::{NspInparenArgs,
30+
SpBracesArgs,
31+
SpPunctArgs}},
32+
AuxParams};
3333
use crate::vfs::TextFile;
3434

3535
fn statement_contexts(context: &ParseContext)
@@ -147,6 +147,7 @@ impl TreeElement for CompoundContent {
147147
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
148148
rules.sp_brace.check(acc, SpBracesArgs::from_compound(self));
149149
rules.in3.check(acc, IN3Args::from_compound_content(self, aux.depth));
150+
rules.in4.check(acc, IN4Args::from_compound_content(self, aux.depth));
150151
}
151152
fn should_increment_depth(&self) -> bool {
152153
true
@@ -1103,6 +1104,11 @@ impl TreeElement for SwitchContent {
11031104
&self.cases,
11041105
&self.rbrace)
11051106
}
1107+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>,
1108+
rules: &CurrentRules, aux: AuxParams)
1109+
{
1110+
rules.in4.check(acc, IN4Args::from_switch_content(self, aux.depth));
1111+
}
11061112
}
11071113

11081114
impl Parse<StatementContent> for SwitchContent {

src/analysis/parsing/structure.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use crate::lint::rules::spacing::{SpBracesArgs,
2020
NspInparenArgs,
2121
NspFunparArgs,
2222
SpPunctArgs};
23-
use crate::lint::rules::indentation::{IN3Args};
23+
use crate::lint::rules::indentation::{IN3Args, IN4Args};
2424
use crate::lint::{rules::CurrentRules, AuxParams, DMLStyleError};
2525
use crate::analysis::reference::{Reference, ReferenceKind};
2626
use crate::analysis::FileSpec;
@@ -707,6 +707,7 @@ impl TreeElement for ObjectStatementsContent {
707707
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
708708
rules.sp_brace.check(acc, SpBracesArgs::from_obj_stmts(self));
709709
rules.in3.check(acc, IN3Args::from_obj_stmts_content(self, aux.depth));
710+
rules.in4.check(acc, IN4Args::from_obj_stmts_content(self, aux.depth));
710711
}
711712
}
712713

src/analysis/parsing/types.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// © 2024 Intel Corporation
22
// SPDX-License-Identifier: Apache-2.0 and MIT
3-
use crate::lint::{rules::{indentation::IN3Args,
3+
use crate::lint::{rules::{indentation::{IN3Args, IN4Args},
44
spacing::SpBracesArgs,
55
CurrentRules},
66
AuxParams,
@@ -55,6 +55,7 @@ impl TreeElement for StructTypeContent {
5555
}
5656
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
5757
rules.in3.check(acc, IN3Args::from_struct_type_content(self, aux.depth));
58+
rules.in4.check(acc, IN4Args::from_struct_type_content(self, aux.depth));
5859
rules.sp_brace.check(acc, SpBracesArgs::from_struct_type_content(self));
5960
}
6061
fn should_increment_depth(&self) -> bool {
@@ -137,6 +138,7 @@ impl TreeElement for LayoutContent {
137138
}
138139
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
139140
rules.in3.check(acc, IN3Args::from_layout_content(self, aux.depth));
141+
rules.in4.check(acc, IN4Args::from_layout_content(self, aux.depth));
140142
rules.sp_brace.check(acc, SpBracesArgs::from_layout_content(self));
141143
}
142144
fn should_increment_depth(&self) -> bool {
@@ -314,6 +316,7 @@ impl TreeElement for BitfieldsContent {
314316
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
315317
rules.sp_brace.check(acc, SpBracesArgs::from_bitfields_content(self));
316318
rules.in3.check(acc, IN3Args::from_bitfields_content(self, aux.depth));
319+
rules.in4.check(acc, IN4Args::from_bitfields_content(self, aux.depth));
317320
}
318321
fn should_increment_depth(&self) -> bool {
319322
true

src/lint/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use rules::{instantiate_rules, CurrentRules, RuleType};
77
use rules::{spacing::{SpBraceOptions, SpPunctOptions, NspFunparOptions,
88
NspInparenOptions, NspUnaryOptions, NspTrailingOptions},
99
indentation::{LongLineOptions, IN1Options, IN3Options,
10-
IN2Options, IN9Options, IN10Options},
10+
IN2Options, IN4Options, IN9Options, IN10Options},
1111
};
1212
use crate::analysis::{DMLError, IsolatedAnalysis, LocalDMLError};
1313
use crate::analysis::parsing::tree::TreeElement;
@@ -66,6 +66,8 @@ pub struct LintCfg {
6666
#[serde(default)]
6767
pub in3: Option<IN3Options>,
6868
#[serde(default)]
69+
pub in4: Option<IN4Options>,
70+
#[serde(default)]
6971
pub in9: Option<IN9Options>,
7072
#[serde(default)]
7173
pub in10: Option<IN10Options>,
@@ -84,6 +86,7 @@ impl Default for LintCfg {
8486
in1: Some(IN1Options{indentation_spaces: INDENTATION_LEVEL_DEFAULT}),
8587
in2: Some(IN2Options{}),
8688
in3: Some(IN3Options{indentation_spaces: INDENTATION_LEVEL_DEFAULT}),
89+
in4: Some(IN4Options{indentation_spaces: INDENTATION_LEVEL_DEFAULT}),
8790
in9: Some(IN9Options{indentation_spaces: INDENTATION_LEVEL_DEFAULT}),
8891
in10: Some(IN10Options{indentation_spaces: INDENTATION_LEVEL_DEFAULT}),
8992
}

src/lint/rules/indentation.rs

Lines changed: 132 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::convert::TryInto;
22

33
use crate::analysis::parsing::{statement::{self, CompoundContent, ForContent,
4-
SwitchCase, WhileContent},
4+
SwitchCase, WhileContent, SwitchContent},
55
structure::ObjectStatementsContent,
66
types::{BitfieldsContent, LayoutContent, StructTypeContent}};
77
use crate::span::{Range, ZeroIndexed};
@@ -248,6 +248,137 @@ impl Rule for IN3Rule {
248248
}
249249
}
250250

251+
pub struct IN4Rule {
252+
pub enabled: bool,
253+
pub indentation_spaces: u32,
254+
}
255+
256+
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
257+
pub struct IN4Options {
258+
#[serde(default = "default_indentation_spaces")]
259+
pub indentation_spaces: u32,
260+
}
261+
262+
impl Rule for IN4Rule {
263+
fn name() -> &'static str {
264+
"IN4"
265+
}
266+
fn description() -> &'static str {
267+
"Closing braces at the beginning of a line should be aligned to the corresponding \
268+
indentation level of the statement that started the code block. A closing brace should \
269+
only ever appear on the same line as the opening brace, or first on a line."
270+
}
271+
fn get_rule_type() -> RuleType {
272+
RuleType::IN4
273+
}
274+
}
275+
276+
pub struct IN4Args {
277+
expected_depth: u32,
278+
lbrace: ZeroRange,
279+
last_member: ZeroRange,
280+
rbrace: ZeroRange,
281+
}
282+
283+
impl IN4Args {
284+
pub fn from_compound_content(node: &CompoundContent, depth: u32) -> Option<IN4Args> {
285+
Some(IN4Args {
286+
expected_depth: depth.saturating_sub(1),
287+
lbrace: node.lbrace.range(),
288+
last_member: node.statements.last()?.range(),
289+
rbrace: node.rbrace.range(),
290+
})
291+
}
292+
293+
pub fn from_obj_stmts_content(node: &ObjectStatementsContent, depth: u32) -> Option<IN4Args> {
294+
if let ObjectStatementsContent::List(lbrace, stmnts, rbrace) = node {
295+
Some(IN4Args {
296+
expected_depth: depth.saturating_sub(1),
297+
lbrace: lbrace.range(),
298+
last_member: stmnts.last()?.range(),
299+
rbrace: rbrace.range(),
300+
})
301+
} else {
302+
None
303+
}
304+
}
305+
306+
pub fn from_switch_content(node: &SwitchContent, depth: u32) -> Option<IN4Args> {
307+
Some(IN4Args {
308+
// Switch content does not increase indentation level before this call
309+
// so there is no need to reduce it
310+
expected_depth: depth,
311+
lbrace: node.lbrace.range(),
312+
last_member: node.cases.last()?.range(),
313+
rbrace: node.rbrace.range(),
314+
})
315+
}
316+
317+
pub fn from_struct_type_content(node: &StructTypeContent, depth: u32) -> Option<IN4Args> {
318+
Some(IN4Args {
319+
expected_depth: depth.saturating_sub(1),
320+
lbrace: node.lbrace.range(),
321+
last_member: node.members.last()?.range(),
322+
rbrace: node.rbrace.range(),
323+
})
324+
}
325+
326+
pub fn from_layout_content(node: &LayoutContent, depth: u32) -> Option<IN4Args> {
327+
Some(IN4Args {
328+
expected_depth: depth.saturating_sub(1),
329+
lbrace: node.lbrace.range(),
330+
last_member: node.fields.last()?.range(),
331+
rbrace: node.rbrace.range(),
332+
})
333+
}
334+
335+
pub fn from_bitfields_content(node: &BitfieldsContent, depth: u32) -> Option<IN4Args> {
336+
Some(IN4Args {
337+
expected_depth: depth.saturating_sub(1),
338+
lbrace: node.lbrace.range(),
339+
last_member: node.fields.last()?.range(),
340+
rbrace: node.rbrace.range(),
341+
})
342+
}
343+
344+
}
345+
346+
impl IN4Rule {
347+
pub fn from_options(options: &Option<IN4Options>) -> IN4Rule {
348+
match options {
349+
Some(options) => IN4Rule {
350+
enabled: true,
351+
indentation_spaces: options.indentation_spaces,
352+
},
353+
None => IN4Rule {
354+
enabled: false,
355+
indentation_spaces: 0,
356+
},
357+
}
358+
}
359+
360+
pub fn check(&self, acc: &mut Vec<DMLStyleError>, args: Option<IN4Args>) {
361+
if !self.enabled { return; }
362+
let Some(args) = args else { return; };
363+
364+
let lbrace_on_same_row_than_rbrace:bool = args.lbrace.row_start
365+
== args.rbrace.row_start;
366+
if lbrace_on_same_row_than_rbrace { return; }
367+
368+
let last_member_on_same_row_than_rbrace:bool = args.last_member.row_end
369+
== args.rbrace.row_start;
370+
if last_member_on_same_row_than_rbrace {
371+
return self.push_err(acc, args.rbrace);
372+
}
373+
374+
let rbrace_on_same_ind_level_than_switchtok:bool = args.rbrace.col_start.0
375+
== args.expected_depth * self.indentation_spaces;
376+
if !rbrace_on_same_ind_level_than_switchtok {
377+
return self.push_err(acc, args.rbrace);
378+
}
379+
}
380+
}
381+
251382
pub struct IN9Rule {
252383
pub enabled: bool,
253384
indentation_spaces: u32

src/lint/rules/mod.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ pub mod tests;
77
use spacing::{SpBracesRule,
88
SpPunctRule, NspFunparRule, NspInparenRule,
99
NspUnaryRule, NspTrailingRule};
10-
use indentation::{LongLinesRule, IN2Rule, IN3Rule, IN9Rule, IN10Rule};
11-
use crate::lint::LintCfg;
10+
use indentation::{LongLinesRule, IN2Rule, IN3Rule, IN4Rule, IN9Rule, IN10Rule};
11+
use crate::lint::{LintCfg, DMLStyleError};
12+
use crate::analysis::{LocalDMLError, parsing::tree::ZeroRange};
1213

1314
pub struct CurrentRules {
1415
pub sp_brace: SpBracesRule,
@@ -20,6 +21,7 @@ pub struct CurrentRules {
2021
pub long_lines: LongLinesRule,
2122
pub in2: IN2Rule,
2223
pub in3: IN3Rule,
24+
pub in4: IN4Rule,
2325
pub in9: IN9Rule,
2426
pub in10: IN10Rule
2527
}
@@ -35,6 +37,7 @@ pub fn instantiate_rules(cfg: &LintCfg) -> CurrentRules {
3537
long_lines: LongLinesRule::from_options(&cfg.long_lines),
3638
in2: IN2Rule { enabled: cfg.in2.is_some() },
3739
in3: IN3Rule::from_options(&cfg.in3),
40+
in4: IN4Rule::from_options(&cfg.in4),
3841
in9: IN9Rule::from_options(&cfg.in9),
3942
in10: IN10Rule::from_options(&cfg.in10)
4043
}
@@ -45,6 +48,16 @@ pub trait Rule {
4548
fn name() -> &'static str;
4649
fn description() -> &'static str;
4750
fn get_rule_type() -> RuleType;
51+
fn push_err(&self, acc: &mut Vec<DMLStyleError>, range: ZeroRange) {
52+
let dmlerror = DMLStyleError {
53+
error: LocalDMLError {
54+
range: range,
55+
description: Self::description().to_string(),
56+
},
57+
rule_type: Self::get_rule_type(),
58+
};
59+
acc.push(dmlerror);
60+
}
4861
}
4962

5063
#[derive(PartialEq)]
@@ -58,7 +71,9 @@ pub enum RuleType {
5871
LongLines,
5972
IN2,
6073
IN3,
74+
IN4,
6175
IN6,
6276
IN9,
6377
IN10
6478
}
79+

src/lint/rules/tests/indentation/in2.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::lint::rules::tests::common::set_up;
2-
use crate::lint::rules::tests::indentation::assert_indentation;
2+
use crate::lint::rules::tests::indentation::assert_snippet;
33

44
pub static IN2_USING_TAB_INDENT: &str = "
55
bank BankA {
@@ -28,7 +28,7 @@ bank BankA {
2828
#[test]
2929
fn in2_using_tab_indent() {
3030
let rules = set_up();
31-
assert_indentation(IN2_USING_TAB_INDENT, 6, rules);
31+
assert_snippet(IN2_USING_TAB_INDENT, 6, &rules);
3232
}
3333

3434
pub static IN2_USING_SPACE_INDENT: &str = "
@@ -58,5 +58,5 @@ bank BankA {
5858
#[test]
5959
fn in2_using_space_indent() {
6060
let rules = set_up();
61-
assert_indentation(IN2_USING_SPACE_INDENT, 0, rules);
61+
assert_snippet(IN2_USING_SPACE_INDENT, 0, &rules);
6262
}

0 commit comments

Comments
 (0)