11use serde:: { Deserialize , Serialize } ;
22use crate :: analysis:: parsing:: lexer:: TokenKind ;
3+ use crate :: analysis:: parsing:: structure:: MethodContent ;
34use crate :: analysis:: parsing:: tree:: { ZeroRange , TreeElement } ;
4- use crate :: analysis:: parsing:: { expression:: { CastContent , FunctionCallContent } } ;
5- use crate :: lint:: { DMLStyleError , LintCfg , RuleType } ;
5+ use crate :: analysis:: parsing:: expression:: { CastContent , FunctionCallContent , ParenExpressionContent } ;
6+ use crate :: lint:: { DMLStyleError , RuleType } ;
67use crate :: lint:: rules:: indentation:: IndentParenExprArgs ;
78use super :: Rule ;
89
9- pub struct FuncCallBreakOnOpeningParen {
10+ pub const INDENTATION_LEVEL_DEFAULT : u32 = 4 ;
11+
12+ fn default_indentation_spaces ( ) -> u32 {
13+ INDENTATION_LEVEL_DEFAULT
14+ }
15+
16+ pub struct FuncCallBreakOnOpenParenRule {
1017 pub enabled : bool ,
18+ indentation_spaces : u32
1119}
1220
13- pub struct FuncCallBreakOnOpeningParenArgs {
14- pub member_ranges : Vec < ZeroRange > ,
21+ pub struct FuncCallBreakOnOpenParenArgs {
22+ pub members_ranges : Vec < ZeroRange > ,
1523 pub expected_depth : u32 ,
24+ pub lparen : ZeroRange ,
1625}
1726
1827#[ derive( Clone , Debug , Serialize , Deserialize , PartialEq ) ]
19- pub struct FuncCallBreakOnOpeningParenOptions { }
28+ pub struct FuncCallBreakOnOpenParenOptions {
29+ #[ serde( default = "default_indentation_spaces" ) ]
30+ pub indentation_spaces : u32 ,
31+ }
32+
33+ impl Rule for FuncCallBreakOnOpenParenRule {
34+ fn name ( ) -> & ' static str {
35+ "FUNC_CALL_BREAK_ON_OPEN_PAREN"
36+ }
37+ fn description ( ) -> & ' static str {
38+ "Function or method calls broken right after opening parenthesis should
39+ indent continuation lines one more level."
40+ }
41+ fn get_rule_type ( ) -> RuleType {
42+ RuleType :: LL6
43+ }
44+ }
2045
21- // pub struct FunctionCallContent {
22- // pub fun: Expression,
23- // pub lparen: LeafToken,
24- // pub arguments: Vec<(SingleInitializer, Option<LeafToken>)>,
25- // pub rparen: LeafToken,
26- // }
46+ impl FuncCallBreakOnOpenParenRule {
47+ pub fn from_options ( options : & Option < FuncCallBreakOnOpenParenOptions > ) -> FuncCallBreakOnOpenParenRule {
48+ match options {
49+ Some ( options) => FuncCallBreakOnOpenParenRule {
50+ enabled : true ,
51+ indentation_spaces : options. indentation_spaces
52+ } ,
53+ None => FuncCallBreakOnOpenParenRule {
54+ enabled : false ,
55+ indentation_spaces : 0
56+ }
57+ }
58+ }
59+
60+ pub fn check ( & self , acc : & mut Vec < DMLStyleError > , args : Option < FuncCallBreakOnOpenParenArgs > ) {
61+ if !self . enabled { return ; }
62+ let Some ( args) = args else { return ; } ;
63+ if args. members_ranges . is_empty ( ) { return ; }
64+ let expected_line_start = self . indentation_spaces * ( args. expected_depth + 1 ) ;
65+ let mut last_row = args. lparen . row_start . 0 ;
66+ if last_row == args. members_ranges . first ( ) . unwrap ( ) . row_start . 0 {
67+ // If the first member is on the same line as the lparen, we don't
68+ // need to check it.
69+ return ;
70+ }
71+ for member_range in args. members_ranges {
72+ if member_range. row_start . 0 != last_row {
73+ last_row = member_range. row_start . 0 ;
74+ if member_range. col_start . 0 != expected_line_start {
75+ acc. push ( self . create_err ( member_range) ) ;
76+ }
77+ }
78+ }
79+ }
80+ }
2781
28- impl FuncCallBreakOnOpeningParenArgs {
29- pub fn from_function_call ( node : & FunctionCallContent , depth : u32 ) -> Option < FuncCallBreakOnOpeningParenArgs > {
82+ impl FuncCallBreakOnOpenParenArgs {
83+ pub fn from_function_call ( node : & FunctionCallContent , depth : u32 ) -> Option < FuncCallBreakOnOpenParenArgs > {
3084 let mut filtered_member_ranges: Vec < ZeroRange > = vec ! [ ] ;
3185 for ( arg, _comma) in node. arguments . iter ( ) {
3286 filtered_member_ranges. extend (
@@ -40,44 +94,44 @@ impl FuncCallBreakOnOpeningParenArgs {
4094 filtered_member_ranges. first ( ) ?. to_owned ( ) ) {
4195 return None
4296 }
43- Some ( FuncCallBreakOnOpeningParenArgs {
44- member_ranges : filtered_member_ranges,
97+ Some ( FuncCallBreakOnOpenParenArgs {
98+ members_ranges : filtered_member_ranges,
4599 expected_depth : depth,
100+ lparen : node. lparen . range ( ) ,
46101 } )
47102 }
48- }
49103
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 ;
104+ pub fn from_paren_expression ( node : & ParenExpressionContent , depth : u32 ) -> Option < FuncCallBreakOnOpenParenArgs > {
105+ Some ( FuncCallBreakOnOpenParenArgs {
106+ members_ranges : IndentParenExprArgs :: filter_out_parenthesized_tokens ( node. expr . tokens ( ) )
107+ . iter ( ) . filter ( |t| t. kind != TokenKind :: RParen ) . map ( |t| t. range ) . collect ( ) ,
108+ expected_depth : depth,
109+ lparen : node. lparen . range ( ) ,
110+ } )
111+ }
59112
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- }
113+ pub fn from_method ( node : & MethodContent , depth : u32 ) -> Option < FuncCallBreakOnOpenParenArgs > {
114+ let mut filtered_member_ranges: Vec < ZeroRange > = vec ! [ ] ;
115+ for ( arg, _comma) in node. arguments . iter ( ) {
116+ filtered_member_ranges. extend (
117+ IndentParenExprArgs :: filter_out_parenthesized_tokens ( arg. tokens ( ) )
118+ . iter ( ) . filter ( |t| t. kind != TokenKind :: RParen ) . map ( |t| t. range ) ) ;
67119 }
120+ Some ( FuncCallBreakOnOpenParenArgs {
121+ members_ranges : filtered_member_ranges,
122+ expected_depth : depth,
123+ lparen : node. lparen . range ( ) ,
124+ } )
68125 }
69- }
70126
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
127+ pub fn from_cast ( node : & CastContent , depth : u32 ) -> Option < FuncCallBreakOnOpenParenArgs > {
128+ let mut cast_member_tokens = node. from . tokens ( ) ;
129+ cast_member_tokens. append ( & mut node. to . tokens ( ) ) ;
130+ Some ( FuncCallBreakOnOpenParenArgs {
131+ members_ranges : IndentParenExprArgs :: filter_out_parenthesized_tokens ( cast_member_tokens)
132+ . iter ( ) . filter ( |t| t. kind != TokenKind :: RParen ) . map ( |t| t. range ) . collect ( ) ,
133+ expected_depth : depth,
134+ lparen : node. lparen . range ( ) ,
135+ } )
81136 }
82137}
83-
0 commit comments