11/**
22 * Requires curly braces after statements.
33 *
4- * Types: `Array` or `Boolean`
4+ * Types: `Array` or `Boolean` or `Object`
55 *
6- * Values: Array of quoted keywords or `true` to require curly braces after the following keywords:
6+ * Values:
7+ * - Array of quoted keywords
8+ * - `true` to require curly braces after the following keywords
9+ * - `Object`
10+ * - `'keywords'`
11+ * - Array of quoted keywords
12+ * - `'allExcept'`
13+ * - Array of keywords inside of the block that would allow curly braces
14+ * - Ex: ["return" , "continue", "break"]
715 *
816 * JSHint: [`curly`](http://jshint.com/docs/options/#curly)
917 *
@@ -45,19 +53,47 @@ module.exports = function() {};
4553
4654module . exports . prototype = {
4755
48- configure : function ( statementTypes ) {
56+ configure : function ( options ) {
4957 assert (
50- Array . isArray ( statementTypes ) || statementTypes === true ,
51- this . getOptionName ( ) + ' option requires array or true value'
58+ Array . isArray ( options ) || options === true || typeof options === 'object' ,
59+ this . getOptionName ( ) + ' option requires array, true value, or object '
5260 ) ;
5361
54- if ( statementTypes === true ) {
55- statementTypes = defaultKeywords ;
62+ var keywordMap = {
63+ 'return' : 'ReturnStatement' ,
64+ 'break' : 'BreakStatement' ,
65+ 'continue' : 'ContinueStatement'
66+ } ;
67+
68+ if ( options === true ) {
69+ options = defaultKeywords ;
70+ }
71+
72+ if ( ! Array . isArray ( options ) ) {
73+ assert (
74+ Array . isArray ( options . allExcept ) ,
75+ this . getOptionName ( ) + '.allExcept ' +
76+ 'property requires an array value'
77+ ) ;
78+ assert (
79+ Array . isArray ( options . keywords ) || options . keywords === true ,
80+ this . getOptionName ( ) + '.keywords ' +
81+ 'property requires an array value or a value of true'
82+ ) ;
83+
84+ if ( options . keywords === true ) {
85+ options . keywords = defaultKeywords ;
86+ }
87+
88+ this . _exceptions = options . allExcept . map ( function ( statementType ) {
89+ return keywordMap [ statementType ] ;
90+ } ) ;
91+ options = options . keywords ;
5692 }
5793
5894 this . _typeIndex = { } ;
59- for ( var i = 0 , l = statementTypes . length ; i < l ; i ++ ) {
60- this . _typeIndex [ statementTypes [ i ] ] = true ;
95+ for ( var i = 0 , l = options . length ; i < l ; i ++ ) {
96+ this . _typeIndex [ options [ i ] ] = true ;
6197 }
6298 } ,
6399
@@ -66,6 +102,8 @@ module.exports.prototype = {
66102 } ,
67103
68104 check : function ( file , errors ) {
105+ var typeIndex = this . _typeIndex ;
106+ var exceptions = this . _exceptions ;
69107
70108 function isNotABlockStatement ( node ) {
71109 return node && node . type !== 'BlockStatement' ;
@@ -87,15 +125,17 @@ module.exports.prototype = {
87125 } ) ;
88126 }
89127
90- var typeIndex = this . _typeIndex ;
91-
92128 if ( typeIndex . if || typeIndex . else ) {
93129 file . iterateNodesByType ( 'IfStatement' , function ( node ) {
94- if ( typeIndex . if && isNotABlockStatement ( node . consequent ) ) {
130+ if ( typeIndex . if && isNotABlockStatement ( node . consequent ) &&
131+ // check exceptions for if and else
132+ ! ( exceptions && exceptions . indexOf ( node . consequent . type ) !== - 1 ) ) {
95133 addError ( 'If' , node ) ;
96134 }
97135 if ( typeIndex . else && isNotABlockStatement ( node . alternate ) &&
98- node . alternate . type !== 'IfStatement' ) {
136+ node . alternate . type !== 'IfStatement' &&
137+ // check exceptions for if and else
138+ ! ( exceptions && exceptions . indexOf ( node . consequent . type ) !== - 1 ) ) {
99139 addError ( 'Else' , file . getPrevToken ( file . getFirstNodeToken ( node . alternate ) ) ) ;
100140 }
101141 } ) ;
0 commit comments