11use serde:: { Deserialize , Serialize } ;
22use 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 ;
3+ use crate :: analysis:: parsing:: parser:: Token ;
4+ use crate :: analysis:: parsing:: structure:: MethodContent ;
5+ use crate :: analysis:: parsing:: tree:: { TreeElement , TreeElementTokenIterator , ZeroRange } ;
6+ use crate :: analysis:: parsing:: expression:: { CastContent , FunctionCallContent , ParenExpressionContent } ;
7+ use crate :: lint:: { DMLStyleError , RuleType } ;
8+ use super :: indentation:: IndentParenExprArgs ;
79use super :: Rule ;
810
9- pub struct FuncCallBreakOnOpeningParen {
11+ pub const INDENTATION_LEVEL_DEFAULT : u32 = 4 ;
12+
13+ fn default_indentation_spaces ( ) -> u32 {
14+ INDENTATION_LEVEL_DEFAULT
15+ }
16+
17+ pub struct FuncCallBreakOnOpenParenRule {
1018 pub enabled : bool ,
19+ indentation_spaces : u32
1120}
1221
13- pub struct FuncCallBreakOnOpeningParenArgs {
14- pub member_ranges : Vec < ZeroRange > ,
22+ pub struct FuncCallBreakOnOpenParenArgs {
23+ pub members_ranges : Vec < ZeroRange > ,
1524 pub expected_depth : u32 ,
25+ pub lparen : ZeroRange ,
1626}
1727
1828#[ derive( Clone , Debug , Serialize , Deserialize , PartialEq ) ]
19- pub struct FuncCallBreakOnOpeningParenOptions { }
29+ pub struct FuncCallBreakOnOpenParenOptions {
30+ #[ serde( default = "default_indentation_spaces" ) ]
31+ pub indentation_spaces : u32 ,
32+ }
2033
21- // pub struct FunctionCallContent {
22- // pub fun: Expression,
23- // pub lparen: LeafToken,
24- // pub arguments: Vec<(SingleInitializer, Option<LeafToken>)>,
25- // pub rparen: LeafToken,
26- // }
34+ impl Rule for FuncCallBreakOnOpenParenRule {
35+ fn name ( ) -> & ' static str {
36+ "FUNC_CALL_BREAK_ON_OPEN_PAREN"
37+ }
38+ fn description ( ) -> & ' static str {
39+ "Function or method calls broken right after opening parenthesis should
40+ indent continuation lines one more level."
41+ }
42+ fn get_rule_type ( ) -> RuleType {
43+ RuleType :: LL6
44+ }
45+ }
2746
28- impl FuncCallBreakOnOpeningParenArgs {
29- pub fn from_function_call ( node : & FunctionCallContent , depth : u32 ) -> Option < FuncCallBreakOnOpeningParenArgs > {
47+ impl FuncCallBreakOnOpenParenArgs {
48+ pub fn filter_out_parenthesized_tokens ( expression_tokens : TreeElementTokenIterator ) -> Vec < Token > {
49+ let mut token_list: Vec < Token > = vec ! [ ] ;
50+ let mut paren_depth = 0 ;
51+ // paren_depth is used to identify nested
52+ // parenthesized expressions within other expressions
53+ // and avoid double checking this type, given
54+ // ParenExpressionContent already checks indent_paren_expr on its own
55+ for token in expression_tokens {
56+ match token. kind {
57+ TokenKind :: LParen => {
58+ if paren_depth == 0 { token_list. push ( token) ; }
59+ paren_depth += 1 ;
60+ } ,
61+ TokenKind :: RParen => {
62+ paren_depth-=1 ;
63+ } ,
64+ TokenKind :: LBrace => {
65+ break ;
66+ } ,
67+ _ => {
68+ if paren_depth == 0 { token_list. push ( token) ; }
69+ }
70+ }
71+ }
72+ token_list
73+ }
74+ pub fn from_function_call ( node : & FunctionCallContent , depth : u32 ) -> Option < FuncCallBreakOnOpenParenArgs > {
3075 let mut filtered_member_ranges: Vec < ZeroRange > = vec ! [ ] ;
3176 for ( arg, _comma) in node. arguments . iter ( ) {
3277 filtered_member_ranges. extend (
33- IndentParenExprArgs :: filter_out_parenthesized_tokens ( arg. tokens ( ) )
34- . iter ( ) . filter ( |t| t . kind != TokenKind :: RParen ) . map ( |t| t. range )
78+ Self :: filter_out_parenthesized_tokens ( arg. tokens ( ) )
79+ . iter ( ) . map ( |t| t. range )
3580 ) ;
3681 }
3782 if filtered_member_ranges. is_empty ( )
@@ -40,24 +85,74 @@ impl FuncCallBreakOnOpeningParenArgs {
4085 filtered_member_ranges. first ( ) ?. to_owned ( ) ) {
4186 return None
4287 }
43- Some ( FuncCallBreakOnOpeningParenArgs {
44- member_ranges : filtered_member_ranges,
88+ Some ( FuncCallBreakOnOpenParenArgs {
89+ members_ranges : filtered_member_ranges,
90+ expected_depth : depth,
91+ lparen : node. lparen . range ( ) ,
92+ } )
93+ }
94+
95+ pub fn from_paren_expression ( node : & ParenExpressionContent , depth : u32 ) -> Option < FuncCallBreakOnOpenParenArgs > {
96+ Some ( FuncCallBreakOnOpenParenArgs {
97+ members_ranges : Self :: filter_out_parenthesized_tokens ( node. expr . tokens ( ) )
98+ . iter ( ) . map ( |t| t. range ) . collect ( ) ,
99+ expected_depth : depth,
100+ lparen : node. lparen . range ( ) ,
101+ } )
102+ }
103+
104+ pub fn from_method ( node : & MethodContent , depth : u32 ) -> Option < FuncCallBreakOnOpenParenArgs > {
105+ let mut filtered_member_ranges: Vec < ZeroRange > = vec ! [ ] ;
106+ for ( arg, _comma) in node. arguments . iter ( ) {
107+ filtered_member_ranges. extend (
108+ Self :: filter_out_parenthesized_tokens ( arg. tokens ( ) )
109+ . iter ( ) . map ( |t| t. range ) ) ;
110+ }
111+ Some ( FuncCallBreakOnOpenParenArgs {
112+ members_ranges : filtered_member_ranges,
113+ expected_depth : depth,
114+ lparen : node. lparen . range ( ) ,
115+ } )
116+ }
117+
118+ pub fn from_cast ( node : & CastContent , depth : u32 ) -> Option < FuncCallBreakOnOpenParenArgs > {
119+ let mut cast_member_tokens = node. from . tokens ( ) ;
120+ cast_member_tokens. append ( & mut node. to . tokens ( ) ) ;
121+ Some ( FuncCallBreakOnOpenParenArgs {
122+ members_ranges : Self :: filter_out_parenthesized_tokens ( cast_member_tokens)
123+ . iter ( ) . map ( |t| t. range ) . collect ( ) ,
45124 expected_depth : depth,
125+ lparen : node. lparen . range ( ) ,
46126 } )
47127 }
48128}
49129
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 ;
130+ impl FuncCallBreakOnOpenParenRule {
131+ pub fn from_options ( options : & Option < FuncCallBreakOnOpenParenOptions > ) -> FuncCallBreakOnOpenParenRule {
132+ match options {
133+ Some ( options) => FuncCallBreakOnOpenParenRule {
134+ enabled : true ,
135+ indentation_spaces : options. indentation_spaces
136+ } ,
137+ None => FuncCallBreakOnOpenParenRule {
138+ enabled : false ,
139+ indentation_spaces : 0
140+ }
141+ }
142+ }
59143
60- for member_range in args. member_ranges {
144+ pub fn check ( & self , acc : & mut Vec < DMLStyleError > , args : Option < FuncCallBreakOnOpenParenArgs > ) {
145+ if !self . enabled { return ; }
146+ let Some ( args) = args else { return ; } ;
147+ if args. members_ranges . is_empty ( ) { return ; }
148+ let expected_line_start = self . indentation_spaces * ( args. expected_depth + 1 ) ;
149+ let mut last_row = args. lparen . row_start . 0 ;
150+ if last_row == args. members_ranges . first ( ) . unwrap ( ) . row_start . 0 {
151+ // If the first member is on the same line as the lparen, we don't
152+ // need to check it.
153+ return ;
154+ }
155+ for member_range in args. members_ranges {
61156 if member_range. row_start . 0 != last_row {
62157 last_row = member_range. row_start . 0 ;
63158 if member_range. col_start . 0 != expected_line_start {
@@ -67,17 +162,3 @@ impl FuncCallBreakOnOpeningParen {
67162 }
68163 }
69164}
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-
0 commit comments