Added IfThenUtils

This commit is contained in:
Zack Grannan
2014-03-02 17:35:31 -08:00
committed by Zalim Bashorov
parent fcbd7b357a
commit 6b5e46da50
@@ -0,0 +1,143 @@
/*
* Copyright 2010-2014 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.plugin.intentions.branchedTransformations
import org.jetbrains.jet.lang.psi.JetExpression
import org.jetbrains.jet.lang.psi.JetBlockExpression
import org.jetbrains.jet.lang.psi.JetBinaryExpression
import org.jetbrains.jet.lang.psi.JetIfExpression
import org.jetbrains.jet.lang.psi.JetPsiUtil
import org.jetbrains.jet.lexer.JetTokens
import org.jetbrains.jet.lang.psi.JetPsiFactory
import com.intellij.openapi.editor.Editor
import org.jetbrains.jet.plugin.refactoring.introduceVariable.JetIntroduceVariableHandler
import org.jetbrains.jet.lang.psi.JetSafeQualifiedExpression
import org.jetbrains.jet.lang.resolve.BindingContext
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
import com.intellij.psi.PsiElement
import org.jetbrains.jet.plugin.refactoring.inline.KotlinInlineValHandler
import org.jetbrains.jet.lang.psi.JetSimpleNameExpression
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowValueFactory
import org.jetbrains.jet.lang.resolve.BindingContextUtils
import org.jetbrains.jet.lang.descriptors.VariableDescriptor
import com.intellij.psi.search.searches.ReferencesSearch
import com.intellij.psi.search.LocalSearchScope
import org.jetbrains.jet.lang.psi.JetDeclaration
fun JetBinaryExpression.comparesNonNullToNull(): Boolean {
val operationToken = this.getOperationToken()
val rhs = this.getRight()
val lhs = this.getLeft()
if (rhs == null || lhs == null) return false
val rightIsNull = rhs.isNullExpression()
val leftIsNull = lhs.isNullExpression()
return leftIsNull != rightIsNull && (operationToken == JetTokens.EQEQ || operationToken == JetTokens.EXCLEQ)
}
fun JetExpression.extractExpressionIfSingle(): JetExpression? {
val innerExpression = JetPsiUtil.deparenthesize(this)
if (innerExpression is JetBlockExpression) {
return if (innerExpression.getStatements().size() == 1)
JetPsiUtil.deparenthesize(innerExpression.getStatements().first as? JetExpression)
else
null
}
return innerExpression
}
fun JetSafeQualifiedExpression.isStatement(): Boolean {
val context = AnalyzerFacadeWithCache.getContextForElement(this)
val expectedType = context.get(BindingContext.EXPECTED_EXPRESSION_TYPE, this);
val isUnit = expectedType != null && KotlinBuiltIns.getInstance().isUnit(expectedType);
// Some "statements" are actually expressions returned from lambdas, their expected types are non-null
val isStatement = context.get(BindingContext.STATEMENT, this) == true && expectedType == null;
return isStatement || isUnit
}
fun JetBinaryExpression.getNonNullExpression(): JetExpression? = when {
this.getLeft()?.isNullExpression() == false ->
this.getLeft()
this.getRight()?.isNullExpression() == false ->
this.getRight()
else ->
null
}
fun JetExpression.isNullExpression(): Boolean = this.extractExpressionIfSingle()?.getText() == "null"
fun JetExpression.isNullExpressionOrEmptyBlock(): Boolean = this.isNullExpression() || this is JetBlockExpression && this.getStatements().empty
fun JetExpression.isNotNullExpression(): Boolean {
val innerExpression = this.extractExpressionIfSingle()
return innerExpression != null && innerExpression.getText() != "null"
}
fun JetExpression.evaluatesTo(other: JetExpression): Boolean {
return this.extractExpressionIfSingle()?.getText() == other.getText()
}
fun JetExpression.convertToIfNotNullExpression(conditionLhs: JetExpression, thenClause: JetExpression, elseClause: JetExpression?): JetIfExpression {
val elseBranch = if (elseClause == null) "" else " else ${elseClause.getText()}"
val conditionalString = "if (${conditionLhs.getText()} != null) ${thenClause.getText()}$elseBranch"
val st = this.replace(conditionalString) as JetExpression
return JetPsiUtil.deparenthesize(st) as JetIfExpression
}
fun JetIfExpression.introduceValueForCondition(occurrenceInThenClause: JetExpression, editor: Editor) {
val project = this.getProject()
val occurrenceInConditional = (this.getCondition() as JetBinaryExpression).getLeft()!!
JetIntroduceVariableHandler.doRefactoring(project, editor, occurrenceInConditional, listOf(occurrenceInConditional, occurrenceInThenClause))
}
fun PsiElement.replace(expressionAsString: String): PsiElement =
this.replace(JetPsiFactory.createExpression(this.getProject(), expressionAsString))
fun JetSimpleNameExpression.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(editor: Editor) {
val declaration = this.getReference()?.resolve() as JetDeclaration
val enclosingElement = JetPsiUtil.getEnclosingElementForLocalDeclaration(declaration)
val isLocal = enclosingElement != null
if (!isLocal) return
val scope = LocalSearchScope(enclosingElement!!)
val references = ReferencesSearch.search(declaration, scope).findAll()
if (references.size() == 1) {
KotlinInlineValHandler().inlineElement(this.getProject(), editor, declaration)
}
}
fun JetSafeQualifiedExpression.inlineReceiverIfApplicableWithPrompt(editor: Editor) {
(this.getReceiverExpression() as? JetSimpleNameExpression)?.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(editor)
}
fun JetBinaryExpression.inlineLeftSideIfApplicableWithPrompt(editor: Editor) {
(this.getLeft() as? JetSimpleNameExpression)?.inlineIfDeclaredLocallyAndOnlyUsedOnceWithPrompt(editor)
}
fun JetExpression.isStableVariable(): Boolean {
val context = AnalyzerFacadeWithCache.getContextForElement(this)
val descriptor = BindingContextUtils.extractVariableDescriptorIfAny(context, this, false)
return descriptor is VariableDescriptor && DataFlowValueFactory.isStableVariable(descriptor)
}