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+ }
33+
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+ }
46+
47+ impl FuncCallBreakOnOpenParenRule {
48+ pub fn from_options ( options : & Option < FuncCallBreakOnOpenParenOptions > ) -> FuncCallBreakOnOpenParenRule {
49+ match options {
50+ Some ( options) => FuncCallBreakOnOpenParenRule {
51+ enabled : true ,
52+ indentation_spaces : options. indentation_spaces
53+ } ,
54+ None => FuncCallBreakOnOpenParenRule {
55+ enabled : false ,
56+ indentation_spaces : 0
57+ }
58+ }
59+ }
2060
21- // pub struct FunctionCallContent {
22- // pub fun: Expression,
23- // pub lparen: LeafToken,
24- // pub arguments: Vec<(SingleInitializer, Option<LeafToken>)>,
25- // pub rparen: LeafToken,
26- // }
61+ pub fn check ( & self , acc : & mut Vec < DMLStyleError > , args : Option < FuncCallBreakOnOpenParenArgs > ) {
62+ if !self . enabled { return ; }
63+ let Some ( args) = args else { return ; } ;
64+ if args. members_ranges . is_empty ( ) { return ; }
65+ let expected_line_start = self . indentation_spaces * ( args. expected_depth + 1 ) ;
66+ let mut last_row = args. lparen . row_start . 0 ;
67+ if last_row == args. members_ranges . first ( ) . unwrap ( ) . row_start . 0 {
68+ // If the first member is on the same line as the lparen, we don't
69+ // need to check it.
70+ return ;
71+ }
72+ for member_range in args. members_ranges {
73+ if member_range. row_start . 0 != last_row {
74+ last_row = member_range. row_start . 0 ;
75+ if member_range. col_start . 0 != expected_line_start {
76+ acc. push ( self . create_err ( member_range) ) ;
77+ }
78+ }
79+ }
80+ }
81+ }
2782
28- impl FuncCallBreakOnOpeningParenArgs {
29- pub fn from_function_call ( node : & FunctionCallContent , depth : u32 ) -> Option < FuncCallBreakOnOpeningParenArgs > {
83+ impl FuncCallBreakOnOpenParenArgs {
84+ pub fn filter_out_parenthesized_tokens ( expression_tokens : TreeElementTokenIterator ) -> Vec < Token > {
85+ let mut token_list: Vec < Token > = vec ! [ ] ;
86+ let mut paren_depth = 0 ;
87+ // paren_depth is used to identify nested
88+ // parenthesized expressions within other expressions
89+ // and avoid double checking this type, given
90+ // ParenExpressionContent already checks indent_paren_expr on its own
91+ for token in expression_tokens {
92+ match token. kind {
93+ TokenKind :: LParen => {
94+ if paren_depth == 0 { token_list. push ( token) ; }
95+ paren_depth += 1 ;
96+ } ,
97+ TokenKind :: RParen => {
98+ paren_depth-=1 ;
99+ } ,
100+ TokenKind :: LBrace => {
101+ break ;
102+ } ,
103+ _ => {
104+ if paren_depth == 0 { token_list. push ( token) ; }
105+ }
106+ }
107+ }
108+ token_list
109+ }
110+ pub fn from_function_call ( node : & FunctionCallContent , depth : u32 ) -> Option < FuncCallBreakOnOpenParenArgs > {
30111 let mut filtered_member_ranges: Vec < ZeroRange > = vec ! [ ] ;
31112 for ( arg, _comma) in node. arguments . iter ( ) {
32113 filtered_member_ranges. extend (
33- IndentParenExprArgs :: filter_out_parenthesized_tokens ( arg. tokens ( ) )
34- . iter ( ) . filter ( |t| t . kind != TokenKind :: RParen ) . map ( |t| t. range )
114+ Self :: filter_out_parenthesized_tokens ( arg. tokens ( ) )
115+ . iter ( ) . map ( |t| t. range )
35116 ) ;
36117 }
37118 if filtered_member_ranges. is_empty ( )
@@ -40,44 +121,44 @@ impl FuncCallBreakOnOpeningParenArgs {
40121 filtered_member_ranges. first ( ) ?. to_owned ( ) ) {
41122 return None
42123 }
43- Some ( FuncCallBreakOnOpeningParenArgs {
44- member_ranges : filtered_member_ranges,
124+ Some ( FuncCallBreakOnOpenParenArgs {
125+ members_ranges : filtered_member_ranges,
45126 expected_depth : depth,
127+ lparen : node. lparen . range ( ) ,
46128 } )
47129 }
48- }
49130
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 ;
131+ pub fn from_paren_expression ( node : & ParenExpressionContent , depth : u32 ) -> Option < FuncCallBreakOnOpenParenArgs > {
132+ Some ( FuncCallBreakOnOpenParenArgs {
133+ members_ranges : Self :: filter_out_parenthesized_tokens ( node. expr . tokens ( ) )
134+ . iter ( ) . map ( |t| t. range ) . collect ( ) ,
135+ expected_depth : depth,
136+ lparen : node. lparen . range ( ) ,
137+ } )
138+ }
59139
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- }
140+ pub fn from_method ( node : & MethodContent , depth : u32 ) -> Option < FuncCallBreakOnOpenParenArgs > {
141+ let mut filtered_member_ranges: Vec < ZeroRange > = vec ! [ ] ;
142+ for ( arg, _comma) in node. arguments . iter ( ) {
143+ filtered_member_ranges. extend (
144+ Self :: filter_out_parenthesized_tokens ( arg. tokens ( ) )
145+ . iter ( ) . map ( |t| t. range ) ) ;
67146 }
147+ Some ( FuncCallBreakOnOpenParenArgs {
148+ members_ranges : filtered_member_ranges,
149+ expected_depth : depth,
150+ lparen : node. lparen . range ( ) ,
151+ } )
68152 }
69- }
70153
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
154+ pub fn from_cast ( node : & CastContent , depth : u32 ) -> Option < FuncCallBreakOnOpenParenArgs > {
155+ let mut cast_member_tokens = node. from . tokens ( ) ;
156+ cast_member_tokens. append ( & mut node. to . tokens ( ) ) ;
157+ Some ( FuncCallBreakOnOpenParenArgs {
158+ members_ranges : Self :: filter_out_parenthesized_tokens ( cast_member_tokens)
159+ . iter ( ) . map ( |t| t. range ) . collect ( ) ,
160+ expected_depth : depth,
161+ lparen : node. lparen . range ( ) ,
162+ } )
81163 }
82164}
83-
0 commit comments