Skip to content

Commit

Permalink
Implement IN9 rule for switch-case statement indentation
Browse files Browse the repository at this point in the history
  • Loading branch information
jvsqzj authored and kevv87 committed Jan 31, 2025
1 parent 95f213c commit 6812633
Show file tree
Hide file tree
Showing 6 changed files with 141 additions and 6 deletions.
1 change: 1 addition & 0 deletions example_files/example_lint_cfg.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@
"nsp_trailing": {},
"long_lines": { "max_length": 80 },
"in3": { "indentation_spaces": 4 },
"in9": { "indentation_spaces": 4 },
}
5 changes: 3 additions & 2 deletions src/analysis/parsing/statement.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ use crate::analysis::parsing::misc::{Initializer, InitializerContent, CDecl,
use crate::analysis::parsing::structure::{parse_vardecl, VarDecl};
use crate::analysis::LocalDMLError;
use crate::lint::rules::{CurrentRules,
indentation::IN3Args,
indentation::{IN3Args, IN9Args},
spacing::{NspInparenArgs,
SpBracesArgs,
SpPunctArgs},
Expand Down Expand Up @@ -1003,7 +1003,8 @@ impl TreeElement for SwitchCase {
Self::Default(default, colon) => create_subs!(default, colon),
}
}
fn evaluate_rules(&self, acc: &mut Vec<LocalDMLError>, rules: &CurrentRules, _depth: &mut u32) {
fn evaluate_rules(&self, acc: &mut Vec<LocalDMLError>, rules: &CurrentRules, depth: &mut u32) {
rules.in9.check(acc, IN9Args::from_switch_case(self, depth));
}
}

Expand Down
5 changes: 4 additions & 1 deletion src/lint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize};
use rules::{instantiate_rules, CurrentRules};
use rules::{spacing::{SpBraceOptions, SpPunctOptions, NspFunparOptions,
NspInparenOptions, NspUnaryOptions, NspTrailingOptions},
indentation::{LongLineOptions, IN3Options},
indentation::{LongLineOptions, IN3Options, IN9Options},
};
use crate::analysis::{DMLError, IsolatedAnalysis, LocalDMLError};
use crate::analysis::parsing::tree::TreeElement;
Expand Down Expand Up @@ -54,6 +54,8 @@ pub struct LintCfg {
pub long_lines: Option<LongLineOptions>,
#[serde(default)]
pub in3: Option<IN3Options>,
#[serde(default)]
pub in9: Option<IN9Options>,
}

impl Default for LintCfg {
Expand All @@ -69,6 +71,7 @@ impl Default for LintCfg {
max_length: MAX_LENGTH_DEFAULT,
}),
in3: Some(IN3Options{indentation_spaces: 4}),
in9: Some(IN9Options{indentation_spaces: 4}),
}
}
}
Expand Down
88 changes: 86 additions & 2 deletions src/lint/rules/indentation.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use std::convert::TryInto;

use crate::analysis::parsing::{statement::CompoundContent,
use crate::analysis::parsing::{statement::{self, CompoundContent, SwitchCase},
structure::ObjectStatementsContent,
types::{LayoutContent, StructTypeContent}};
use crate::span::{Range, ZeroIndexed, Row, Column};
use crate::analysis::LocalDMLError;
use crate::analysis::parsing::tree::{ZeroRange, TreeElement};
use crate::analysis::parsing::tree::{ZeroRange, Content, TreeElement};
use serde::{Deserialize, Serialize};
use super::Rule;

Expand Down Expand Up @@ -161,6 +161,90 @@ impl Rule for IN3Rule {
}
}

pub struct IN9Rule {
pub enabled: bool,
indentation_spaces: u32
}

#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
pub struct IN9Options {
pub indentation_spaces: u32,
}
pub struct IN9Args<'a> {
case_range: ZeroRange,
expected_depth: &'a mut u32,
}

impl IN9Args<'_> {
pub fn from_switch_case<'a>(node: &SwitchCase, depth: &'a mut u32) -> Option<IN9Args<'a>> {
match node {
SwitchCase::Case(_, _, _) |
SwitchCase::Default(_, _) => {},
SwitchCase::Statement(statement) => {
if let Content::Some(ref content) = *statement.content {
if let statement::StatementContent::Compound(_) = content {
return None;
}
*depth += 1;
}
},
SwitchCase::HashIf(_) => {
return None;
}
}

Some(IN9Args {
case_range: node.range(),
expected_depth: depth
})

}
}

impl IN9Rule {
pub fn from_options(options: &Option<IN9Options>) -> IN9Rule {
match options {
Some(options) => IN9Rule {
enabled: true,
indentation_spaces: options.indentation_spaces
},
None => IN9Rule {
enabled: false,
indentation_spaces: 0
}
}
}
pub fn check<'a>(&self, acc: &mut Vec<LocalDMLError>,
args: Option<IN9Args<'a>>)
{
if !self.enabled { return; }
let Some(args) = args else { return; };
if self.indentation_is_not_aligned(args.case_range, *args.expected_depth) {
let dmlerror = LocalDMLError {
range: args.case_range,
description: Self::description().to_string(),
};
acc.push(dmlerror);
}
}
fn indentation_is_not_aligned(&self, member_range: ZeroRange, depth: u32) -> bool {
// Implicit IN1
let expected_column = self.indentation_spaces * depth;
print!("{:#?}", expected_column);
member_range.col_start.0 != expected_column
}
}

impl Rule for IN9Rule {
fn name() -> &'static str {
"IN9"
}
fn description() -> &'static str {
"Case labels are indented one level less than surrounding lines, \
so that they are on the same level as the switch statement"
}
}

#[cfg(test)]
pub mod tests {

Expand Down
4 changes: 3 additions & 1 deletion src/lint/rules/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ pub mod test;
use spacing::{SpBracesRule,
SpPunctRule, NspFunparRule, NspInparenRule,
NspUnaryRule, NspTrailingRule};
use indentation::{LongLinesRule, IN3Rule};
use indentation::{LongLinesRule, IN3Rule, IN9Rule};
use crate::lint::LintCfg;

pub struct CurrentRules {
Expand All @@ -17,6 +17,7 @@ pub struct CurrentRules {
pub nsp_trailing: NspTrailingRule,
pub long_lines: LongLinesRule,
pub in3: IN3Rule,
pub in9: IN9Rule
}

pub fn instantiate_rules(cfg: &LintCfg) -> CurrentRules {
Expand All @@ -29,6 +30,7 @@ pub fn instantiate_rules(cfg: &LintCfg) -> CurrentRules {
nsp_trailing: NspTrailingRule { enabled: cfg.nsp_trailing.is_some() },
long_lines: LongLinesRule::from_options(&cfg.long_lines),
in3: IN3Rule::from_options(&cfg.in3),
in9: IN9Rule::from_options(&cfg.in9),
}
}

Expand Down
44 changes: 44 additions & 0 deletions src/lint/rules/test/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,5 +168,49 @@ fn in3_cond_structure_bad_indent() {
assert_indentation(IN3_COND_STRUCTURE_BAD_INDENT, 4, rules);
}

pub static IN9_CORRECT_CASE_INDENT: &str = "
method some_switch(int arg) {
switch(arg) {
case ZERO:
#if (asdd == 0) {
some_call();
}
if (a) {
return;
}
some_call();
break;
default: { return; }
}
}
";

pub static IN9_INCORRECT_CASE_INDENT: &str = "
method some_switch(int arg) {
switch(arg) {
case ZERO:
#if (asdd == 0) {
some_call();
}
if (a) {
return;
}
some_call();
break;
case ONE: {
return;
}
default: { return; }
}
}
";

#[test]
// #[ignore]
fn in9_correct_case_indent() {
let rules = set_up();
assert_snippet(IN9_CORRECT_CASE_INDENT, 0, &rules);
assert_snippet(IN9_INCORRECT_CASE_INDENT, 4, &rules);
}

}

0 comments on commit 6812633

Please sign in to comment.