@@ -9,14 +9,16 @@ import com.saveourtool.diktat.ruleset.utils.isSingleLineIfElse
9
9
import com.saveourtool.diktat.ruleset.utils.loopType
10
10
import com.saveourtool.diktat.ruleset.utils.prevSibling
11
11
12
- import org.jetbrains.kotlin.KtNodeTypes
13
12
import org.jetbrains.kotlin.KtNodeTypes.BLOCK
13
+ import org.jetbrains.kotlin.KtNodeTypes.BLOCK_CODE_FRAGMENT
14
+ import org.jetbrains.kotlin.KtNodeTypes.BODY
14
15
import org.jetbrains.kotlin.KtNodeTypes.CALL_EXPRESSION
15
16
import org.jetbrains.kotlin.KtNodeTypes.ELSE
16
17
import org.jetbrains.kotlin.KtNodeTypes.IF
17
18
import org.jetbrains.kotlin.KtNodeTypes.LAMBDA_EXPRESSION
18
19
import org.jetbrains.kotlin.KtNodeTypes.REFERENCE_EXPRESSION
19
20
import org.jetbrains.kotlin.KtNodeTypes.SAFE_ACCESS_EXPRESSION
21
+ import org.jetbrains.kotlin.KtNodeTypes.THEN
20
22
import org.jetbrains.kotlin.KtNodeTypes.WHEN
21
23
import org.jetbrains.kotlin.com.intellij.lang.ASTNode
22
24
import org.jetbrains.kotlin.com.intellij.psi.impl.source.tree.CompositeElement
@@ -84,8 +86,7 @@ class BracesInConditionalsAndLoopsRule(configRules: List<RulesConfig>) : DiktatR
84
86
}
85
87
}
86
88
? : run {
87
- val nodeAfterCondition = ifPsi.rightParenthesis!! .node.treeNext
88
- node.insertEmptyBlockBetweenChildren(nodeAfterCondition, nodeAfterCondition, indent)
89
+ node.insertEmptyBlockInsideThenNode(indent)
89
90
}
90
91
}
91
92
}
@@ -116,18 +117,53 @@ class BracesInConditionalsAndLoopsRule(configRules: List<RulesConfig>) : DiktatR
116
117
}
117
118
? : run {
118
119
// `else` can have empty body e.g. when there is a semicolon after: `else ;`
119
- node.insertEmptyBlockBetweenChildren(elseKeyword.node.treeNext, null , indent)
120
+ node.insertEmptyBlockInsideElseNode( indent)
120
121
}
121
122
}
122
123
}
123
124
}
124
125
126
+ private fun ASTNode.insertEmptyBlockInsideThenNode (indent : Int ) {
127
+ val ifPsi = psi as KtIfExpression
128
+ val elseKeyword = ifPsi.elseKeyword
129
+ val emptyThenNode = findChildByType(THEN )
130
+
131
+ emptyThenNode?.findChildByType(BLOCK_CODE_FRAGMENT ) ? : run {
132
+ val whiteSpacesAfterCondition = ifPsi.rightParenthesis?.node?.treeNext
133
+
134
+ whiteSpacesAfterCondition?.let {
135
+ replaceChild(it, PsiWhiteSpaceImpl (" " ))
136
+ }
137
+ emptyThenNode?.insertEmptyBlock(indent)
138
+ elseKeyword?.let {
139
+ addChild(PsiWhiteSpaceImpl (" " ), elseKeyword.node)
140
+ }
141
+ }
142
+ }
143
+
144
+ private fun ASTNode.insertEmptyBlockInsideElseNode (indent : Int ) {
145
+ val ifPsi = psi as KtIfExpression
146
+ val elseKeyword = ifPsi.elseKeyword
147
+ val emptyElseNode = findChildByType(ELSE )
148
+
149
+ emptyElseNode?.findChildByType(BLOCK_CODE_FRAGMENT ) ? : run {
150
+ val whiteSpacesAfterElseKeyword = elseKeyword?.node?.treeNext
151
+
152
+ whiteSpacesAfterElseKeyword?.let {
153
+ replaceChild(it, PsiWhiteSpaceImpl (" " ))
154
+ }
155
+ emptyElseNode?.insertEmptyBlock(indent)
156
+ }
157
+ }
158
+
125
159
@Suppress(" UnsafeCallOnNullableType" )
126
160
private fun checkLoop (node : ASTNode ) {
127
161
val loopBody = (node.psi as KtLoopExpression ).body
128
162
val loopBodyNode = loopBody?.node
163
+
129
164
if (loopBodyNode == null || loopBodyNode.elementType != BLOCK ) {
130
- NO_BRACES_IN_CONDITIONALS_AND_LOOPS .warnAndFix(configRules, emitWarn, isFixMode, node.elementType.toString(), node.startOffset, node) {
165
+ NO_BRACES_IN_CONDITIONALS_AND_LOOPS .warnAndFix(configRules, emitWarn, isFixMode,
166
+ node.elementType.toString(), node.startOffset, node) {
131
167
// fixme proper way to calculate indent? or get step size (instead of hardcoded 4)
132
168
val indent = node.findIndentBeforeNode()
133
169
@@ -136,16 +172,29 @@ class BracesInConditionalsAndLoopsRule(configRules: List<RulesConfig>) : DiktatR
136
172
}
137
173
? : run {
138
174
// this corresponds to do-while with empty body
139
- node.insertEmptyBlockBetweenChildren(
140
- node.findChildByType(DO_KEYWORD )!! .treeNext,
141
- node.findChildByType(WHILE_KEYWORD )!! .treePrev,
142
- indent
143
- )
175
+ node.insertEmptyBlockInsideDoWhileNode(indent)
144
176
}
145
177
}
146
178
}
147
179
}
148
180
181
+ private fun ASTNode.insertEmptyBlockInsideDoWhileNode (indent : Int ) {
182
+ findChildByType(BODY ) ? : run {
183
+ val doKeyword = findChildByType(DO_KEYWORD )
184
+ val whileKeyword = findChildByType(WHILE_KEYWORD )
185
+ val whiteSpacesAfterDoKeyword = doKeyword?.treeNext
186
+
187
+ addChild(CompositeElement (BODY ), whileKeyword)
188
+ val emptyWhenNode = findChildByType(BODY )
189
+
190
+ whiteSpacesAfterDoKeyword?.let {
191
+ replaceChild(it, PsiWhiteSpaceImpl (" " ))
192
+ }
193
+ emptyWhenNode?.insertEmptyBlock(indent)
194
+ addChild(PsiWhiteSpaceImpl (" " ), whileKeyword)
195
+ }
196
+ }
197
+
149
198
private fun ASTNode.findIndentBeforeNode (): Int {
150
199
val isElseIfStatement = treeParent.elementType == ELSE
151
200
val primaryIfNode = if (isElseIfStatement) treeParent.treeParent else this
@@ -175,7 +224,8 @@ class BracesInConditionalsAndLoopsRule(configRules: List<RulesConfig>) : DiktatR
175
224
block.findChildrenMatching { it.isPartOfComment() }.isEmpty()
176
225
}
177
226
.forEach {
178
- NO_BRACES_IN_CONDITIONALS_AND_LOOPS .warnAndFix(configRules, emitWarn, isFixMode, " WHEN" , it.node.startOffset, it.node) {
227
+ NO_BRACES_IN_CONDITIONALS_AND_LOOPS .warnAndFix(configRules, emitWarn, isFixMode,
228
+ " WHEN" , it.node.startOffset, it.node) {
179
229
it.astReplace(it.firstStatement!! .node.psi)
180
230
}
181
231
}
@@ -187,21 +237,14 @@ class BracesInConditionalsAndLoopsRule(configRules: List<RulesConfig>) : DiktatR
187
237
))
188
238
}
189
239
190
- private fun ASTNode.insertEmptyBlockBetweenChildren (
191
- firstChild : ASTNode ,
192
- secondChild : ASTNode ? ,
193
- indent : Int
194
- ) {
195
- val emptyBlock = CompositeElement (KtNodeTypes .BLOCK_CODE_FRAGMENT )
196
- addChild(emptyBlock, firstChild)
197
- addChild(PsiWhiteSpaceImpl (" " ), emptyBlock)
240
+ private fun ASTNode.insertEmptyBlock (indent : Int ) {
241
+ val emptyBlock = CompositeElement (BLOCK_CODE_FRAGMENT )
242
+ addChild(emptyBlock, null )
198
243
emptyBlock.addChild(LeafPsiElement (LBRACE , " {" ))
199
244
emptyBlock.addChild(PsiWhiteSpaceImpl (" \n ${" " .repeat(indent)} " ))
200
245
emptyBlock.addChild(LeafPsiElement (RBRACE , " }" ))
201
- secondChild?.let {
202
- replaceChild(it, PsiWhiteSpaceImpl (" " ))
203
- }
204
246
}
247
+
205
248
companion object {
206
249
private const val INDENT_STEP = 4
207
250
const val NAME_ID = " races-rule"
0 commit comments