Skip to content

Commit 698813a

Browse files
jvsqzjme-cr
authored andcommitted
Add rule LL6 for funcall broken after left paren
1 parent 3e540d1 commit 698813a

File tree

4 files changed

+97
-1
lines changed

4 files changed

+97
-1
lines changed

src/analysis/parsing/expression.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use crate::lint::{DMLStyleError,
2525
CurrentRules},
2626
AuxParams};
2727
use crate::lint::rules::indentation::IndentParenExprArgs;
28+
use crate::lint::rules::linebreaking::FuncCallBreakOnOpeningParenArgs;
2829

2930
#[derive(Debug, Clone, PartialEq)]
3031
pub struct UnaryExpressionContent {
@@ -214,11 +215,13 @@ impl TreeElement for FunctionCallContent {
214215
noderef, ReferenceKind::Callable));
215216
}
216217
}
217-
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, _aux: AuxParams) {
218+
fn evaluate_rules(&self, acc: &mut Vec<DMLStyleError>, rules: &CurrentRules, aux: AuxParams) {
218219
rules.nsp_funpar.check(acc, NspFunparArgs::from_function_call(self));
219220
rules.nsp_inparen.check(acc, NspInparenArgs::from_function_call(self));
220221
rules.sp_punct.check(acc, SpPunctArgs::from_function_call(self));
221222
rules.indent_paren_expr.check(acc, IndentParenExprArgs::from_function_call(self));
223+
rules.func_call_break_on_opening_paren
224+
.check(acc, FuncCallBreakOnOpeningParenArgs::from_function_call(self, aux.depth));
222225
}
223226
}
224227

src/lint/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use std::fmt;
22
use std::fs;
33
use std::path::{Path, PathBuf};
44
use log::{debug, error, trace};
5+
use rules::linebreaking::FuncCallBreakOnOpeningParenOptions;
56
use serde::{Deserialize, Serialize};
67
use rules::{instantiate_rules, CurrentRules, RuleType};
78
use rules::{spacing::{SpBraceOptions, SpPunctOptions, NspFunparOptions,
@@ -75,6 +76,8 @@ pub struct LintCfg {
7576
pub indent_empty_loop: Option<IndentEmptyLoopOptions>,
7677
#[serde(default)]
7778
pub indent_continuation_line: Option<IndentContinuationLineOptions>,
79+
#[serde(default)]
80+
pub func_call_break_on_opening_paren: Option<FuncCallBreakOnOpeningParenOptions>,
7881
}
7982

8083
impl Default for LintCfg {
@@ -95,10 +98,12 @@ impl Default for LintCfg {
9598
indent_switch_case: Some(IndentSwitchCaseOptions{indentation_spaces: INDENTATION_LEVEL_DEFAULT}),
9699
indent_empty_loop: Some(IndentEmptyLoopOptions{indentation_spaces: INDENTATION_LEVEL_DEFAULT}),
97100
indent_continuation_line: Some(IndentContinuationLineOptions{indentation_spaces: INDENTATION_LEVEL_DEFAULT}),
101+
func_call_break_on_opening_paren: Some(FuncCallBreakOnOpeningParenOptions{}),
98102
}
99103
}
100104
}
101105

106+
102107
#[derive(Debug, Clone)]
103108
pub struct DMLStyleError {
104109
pub error: LocalDMLError,

src/lint/rules/linebreaking.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
use serde::{Deserialize, Serialize};
2+
use crate::analysis::parsing::lexer::TokenKind;
3+
use crate::analysis::parsing::tree::{ZeroRange, TreeElement};
4+
use crate::analysis::parsing::{expression::{CastContent, FunctionCallContent}};
5+
use crate::lint::{DMLStyleError, LintCfg, RuleType};
6+
use crate::lint::rules::indentation::IndentParenExprArgs;
7+
use super::Rule;
8+
9+
pub struct FuncCallBreakOnOpeningParen {
10+
pub enabled: bool,
11+
}
12+
13+
pub struct FuncCallBreakOnOpeningParenArgs {
14+
pub member_ranges: Vec<ZeroRange>,
15+
pub expected_depth: u32,
16+
}
17+
18+
#[derive(Clone, Debug, Serialize, Deserialize, PartialEq)]
19+
pub struct FuncCallBreakOnOpeningParenOptions{}
20+
21+
// pub struct FunctionCallContent {
22+
// pub fun: Expression,
23+
// pub lparen: LeafToken,
24+
// pub arguments: Vec<(SingleInitializer, Option<LeafToken>)>,
25+
// pub rparen: LeafToken,
26+
// }
27+
28+
impl FuncCallBreakOnOpeningParenArgs {
29+
pub fn from_function_call(node: &FunctionCallContent, depth: u32) -> Option<FuncCallBreakOnOpeningParenArgs> {
30+
let mut filtered_member_ranges: Vec<ZeroRange> = vec![];
31+
for (arg, _comma) in node.arguments.iter() {
32+
filtered_member_ranges.extend(
33+
IndentParenExprArgs::filter_out_parenthesized_tokens(arg.tokens())
34+
.iter().filter(|t| t.kind != TokenKind::RParen).map(|t| t.range)
35+
);
36+
}
37+
if filtered_member_ranges.is_empty()
38+
|| ! IndentParenExprArgs::is_broken_after_lparen(
39+
node.lparen.range(),
40+
filtered_member_ranges.first()?.to_owned()) {
41+
return None
42+
}
43+
Some(FuncCallBreakOnOpeningParenArgs {
44+
member_ranges: filtered_member_ranges,
45+
expected_depth: depth,
46+
})
47+
}
48+
}
49+
50+
impl FuncCallBreakOnOpeningParen {
51+
pub fn check(&self, acc: &mut Vec<DMLStyleError>, args: Option<FuncCallBreakOnOpeningParenArgs>) {
52+
if !self.enabled {
53+
return;
54+
}
55+
let Some(args) = args else { return; };
56+
// TODO : enable shared access to indentation_spaces param for all related rules
57+
let expected_line_start = args.expected_depth * 4; // Assuming 4 spaces per indent level
58+
let mut last_row = args.member_ranges.first().unwrap().row_start.0;
59+
60+
for member_range in args.member_ranges {
61+
if member_range.row_start.0 != last_row {
62+
last_row = member_range.row_start.0;
63+
if member_range.col_start.0 != expected_line_start {
64+
acc.push(self.create_err(member_range));
65+
}
66+
}
67+
}
68+
}
69+
}
70+
71+
impl Rule for FuncCallBreakOnOpeningParen {
72+
fn name() -> &'static str {
73+
"FUNC_CALL_BREAK_ON_OPENING_PAREN"
74+
}
75+
fn description() -> &'static str {
76+
"Function or method calls broken right after opening parenthesis should
77+
indent continuation lines one more level."
78+
}
79+
fn get_rule_type() -> RuleType {
80+
RuleType::LL6
81+
}
82+
}
83+

src/lint/rules/mod.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub mod spacing;
22
pub mod indentation;
3+
pub mod linebreaking;
34

45
#[cfg(test)]
56
pub mod tests;
@@ -8,6 +9,7 @@ use spacing::{SpBracesRule,
89
SpPunctRule, NspFunparRule, NspInparenRule,
910
NspUnaryRule, NspTrailingRule};
1011
use indentation::{LongLinesRule, IndentNoTabRule, IndentCodeBlockRule, IndentClosingBraceRule, IndentParenExprRule, IndentSwitchCaseRule, IndentEmptyLoopRule, IndentContinuationLineRule};
12+
use linebreaking::FuncCallBreakOnOpeningParen;
1113
use crate::lint::{LintCfg, DMLStyleError};
1214
use crate::analysis::{LocalDMLError, parsing::tree::ZeroRange};
1315

@@ -26,6 +28,7 @@ pub struct CurrentRules {
2628
pub indent_switch_case: IndentSwitchCaseRule,
2729
pub indent_empty_loop: IndentEmptyLoopRule,
2830
pub indent_continuation_line: IndentContinuationLineRule,
31+
pub func_call_break_on_opening_paren: FuncCallBreakOnOpeningParen,
2932
}
3033

3134
pub fn instantiate_rules(cfg: &LintCfg) -> CurrentRules {
@@ -44,6 +47,7 @@ pub fn instantiate_rules(cfg: &LintCfg) -> CurrentRules {
4447
indent_switch_case: IndentSwitchCaseRule::from_options(&cfg.indent_switch_case),
4548
indent_empty_loop: IndentEmptyLoopRule::from_options(&cfg.indent_empty_loop),
4649
indent_continuation_line: IndentContinuationLineRule::from_options(&cfg.indent_continuation_line),
50+
func_call_break_on_opening_paren: FuncCallBreakOnOpeningParen { enabled: cfg.func_call_break_on_opening_paren.is_some() },
4751
}
4852
}
4953

@@ -72,6 +76,7 @@ pub enum RuleType {
7276
NspUnary,
7377
NspTrailing,
7478
LL1,
79+
LL6,
7580
IN2,
7681
IN3,
7782
IN4,

0 commit comments

Comments
 (0)