1+ package checkstyle .checks ;
2+
3+ import checkstyle .Checker .LinePos ;
4+ import checkstyle .LintMessage .SeverityLevel ;
5+ import haxeparser .Data ;
6+ import haxe .macro .Expr ;
7+
8+ @name (" NeedBraces" )
9+ @desc (" Checks for braces on if, if else, for and while statements" )
10+ class NeedBracesCheck extends Check {
11+
12+ public static inline var FOR : String = " FOR" ;
13+ public static inline var IF : String = " IF" ;
14+ public static inline var ELSE_IF : String = " ELSE_IF" ;
15+ public static inline var WHILE : String = " WHILE" ;
16+
17+ public var tokens : Array <String >;
18+ public var allowSingleLineStatement : Bool ;
19+
20+ public function new () {
21+ super ();
22+ tokens = [];
23+ allowSingleLineStatement = true ;
24+ }
25+
26+ function hasToken (token : String ): Bool {
27+ if (tokens .length == 0 ) return true ;
28+ if (tokens .indexOf (token ) > - 1 ) return true ;
29+ return false ;
30+ }
31+
32+ override function actualRun () {
33+ ExprUtils .walkFile (checker .ast , function (e ) {
34+ if (isPosSuppressed (e .pos )) return ;
35+ switch (e .expr ) {
36+ case EFor (it , expr ):
37+ if (! hasToken (FOR )) return ;
38+ var itLine : LinePos = checker .getLinePos (it .pos .max );
39+ var exprLine : LinePos = checker .getLinePos (expr .pos .min );
40+ checkBraces (expr , ' for loop' , itLine .line == exprLine .line , false );
41+ case EIf (econd , eif , eelse ):
42+ if (! hasToken (IF )) return ;
43+ var condLine : LinePos = checker .getLinePos (econd .pos .max );
44+ var ifLine : LinePos = checker .getLinePos (eif .pos .min );
45+ var elseSameLine : Bool = false ;
46+ if (eelse != null ){
47+ var elseLine : LinePos = checker .getLinePos (eelse .pos .min );
48+ var line : String = checker .lines [elseLine .line ];
49+ if (StringTools .startsWith (StringTools .trim (line ), " else" )) elseSameLine = true ;
50+ }
51+ checkBraces (eif , ' if branch' , condLine .line == ifLine .line , true );
52+ checkBraces (eelse , ' else branch' , elseSameLine , true );
53+ case EWhile (econd , expr , _ ):
54+ if (! hasToken (WHILE )) return ;
55+ var condLine : LinePos = checker .getLinePos (econd .pos .max );
56+ var exprLine : LinePos = checker .getLinePos (expr .pos .min );
57+ checkBraces (expr , ' while loop' , condLine .line == exprLine .line , false );
58+ default :
59+ }
60+ });
61+ }
62+
63+ @SuppressWarnings (" checkstyle:CyclomaticComplexity" )
64+ function checkBraces (e : Expr , name : String , sameLine : Bool , parentIsIf : Bool ) {
65+ if ((e == null ) || (e .expr == null )) return ;
66+
67+ var minLine : LinePos = checker .getLinePos (e .pos .min );
68+ var maxLine : LinePos = checker .getLinePos (e .pos .max );
69+ var multiLine : Bool = (minLine .line < maxLine .line );
70+ switch (e .expr ) {
71+ case EBlock (_ ):
72+ if (! multiLine && ! allowSingleLineStatement ) {
73+ logPos (' Single line Block detected' , e .pos , Reflect .field (SeverityLevel , severity ));
74+ }
75+ return ;
76+ case EIf (_ , _ , _ ):
77+ if (! parentIsIf || ! hasToken (ELSE_IF )) {
78+ if (multiLine ) sameLine = false ;
79+ }
80+ if (sameLine && allowSingleLineStatement ) return ;
81+ if (sameLine && ! allowSingleLineStatement ) {
82+ logPos (' Body of $name on same line' , e .pos , Reflect .field (SeverityLevel , severity ));
83+ return ;
84+ }
85+ logPos (' No braces used for body of $name ' , e .pos , Reflect .field (SeverityLevel , severity ));
86+ default :
87+ if (multiLine ) sameLine = false ;
88+ if (sameLine && allowSingleLineStatement ) return ;
89+ if (sameLine && ! allowSingleLineStatement ) {
90+ logPos (' Body of $name on same line' , e .pos , Reflect .field (SeverityLevel , severity ));
91+ return ;
92+ }
93+ logPos (' No braces used for body of $name ' , e .pos , Reflect .field (SeverityLevel , severity ));
94+ }
95+ }
96+ }
0 commit comments