Moved 2 intentions from idea-analysis to idea

This commit is contained in:
Valentin Kipyatkov
2015-05-12 14:26:04 +03:00
parent addcadeddf
commit 54051c40dc
2 changed files with 26 additions and 32 deletions
@@ -1,94 +0,0 @@
/*
* Copyright 2010-2015 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.kotlin.idea.intentions
import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.psi.JetCallExpression
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.util.DelegatingCall
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.psi.JetTypeProjection
import org.jetbrains.kotlin.psi.Call
import org.jetbrains.kotlin.di.InjectorForMacros
import org.jetbrains.kotlin.resolve.BindingTraceContext
import org.jetbrains.kotlin.psi.JetProperty
import org.jetbrains.kotlin.psi.JetTypeArgumentList
import org.jetbrains.kotlin.psi.JetReturnExpression
import org.jetbrains.kotlin.psi.JetDeclarationWithBody
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.psi.psiUtil.getTextWithLocation
import org.jetbrains.kotlin.resolve.bindingContextUtil.getDataFlowInfo
import org.jetbrains.kotlin.idea.util.approximateFlexibleTypes
import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
public class RemoveExplicitTypeArguments : JetSelfTargetingOffsetIndependentIntention<JetTypeArgumentList>(
"remove.explicit.type.arguments", javaClass()) {
override fun isApplicableTo(element: JetTypeArgumentList): Boolean {
val callExpression = element.getParent()
if (callExpression !is JetCallExpression) return false
val context = callExpression.analyze()
if (callExpression.getTypeArguments().isEmpty()) return false
val injector = InjectorForMacros(callExpression.getProject(), callExpression.findModuleDescriptor())
val scope = context[BindingContext.RESOLUTION_SCOPE, callExpression]
val originalCall = callExpression.getResolvedCall(context)
if (originalCall == null || scope !is JetScope) return false
val untypedCall = CallWithoutTypeArgs(originalCall.getCall())
// todo Check with expected type for other expressions
// If always use expected type from trace there is a problem with nested calls:
// the expression type for them can depend on their explicit type arguments (via outer call),
// therefore we should resolve outer call with erased type arguments for inner call
val parent = callExpression.getParent()
val expectedTypeIsExplicitInCode = when (parent) {
is JetProperty -> parent.getInitializer() == callExpression && parent.getTypeReference() != null
is JetDeclarationWithBody -> parent.getBodyExpression() == callExpression
is JetReturnExpression -> true
else -> false
}
val jType = if (expectedTypeIsExplicitInCode) {
context[BindingContext.EXPECTED_EXPRESSION_TYPE, callExpression] ?: TypeUtils.NO_EXPECTED_TYPE
}
else {
TypeUtils.NO_EXPECTED_TYPE
}
val dataFlow = context.getDataFlowInfo(callExpression)
val resolutionResults = injector.getCallResolver().resolveFunctionCall(
BindingTraceContext(), scope, untypedCall, jType, dataFlow, false)
assert (resolutionResults.isSingleResult()) { "Removing type arguments changed resolve for: " +
"${callExpression.getTextWithLocation()} to ${resolutionResults.getResultCode()}" }
val args = originalCall.getTypeArguments()
val newArgs = resolutionResults.getResultingCall().getTypeArguments()
return args == newArgs.mapValues { approximateFlexibleTypes(it.getValue(), false) }
}
private class CallWithoutTypeArgs(call: Call) : DelegatingCall(call) {
override fun getTypeArguments(): List<JetTypeProjection> = listOf()
override fun getTypeArgumentList() = null
}
override fun applyTo(element: JetTypeArgumentList, editor: Editor) {
element.delete()
}
}
@@ -1,92 +0,0 @@
/*
* Copyright 2010-2015 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.kotlin.idea.intentions
import org.jetbrains.kotlin.lexer.JetToken
import org.jetbrains.kotlin.lexer.JetSingleValueToken
import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.lexer.JetTokens
import org.jetbrains.kotlin.idea.JetBundle
import org.jetbrains.kotlin.psi.*
public class SimplifyNegatedBinaryExpressionIntention : JetSelfTargetingOffsetIndependentIntention<JetPrefixExpression>("simplify.negated.binary.expression", javaClass()) {
private fun JetPrefixExpression.unparenthesize(): JetExpression? {
return (this.getBaseExpression() as? JetParenthesizedExpression)?.getExpression()
}
public fun JetToken.negate(): JetSingleValueToken? = when (this) {
JetTokens.IN_KEYWORD -> JetTokens.NOT_IN
JetTokens.NOT_IN -> JetTokens.IN_KEYWORD
JetTokens.IS_KEYWORD -> JetTokens.NOT_IS
JetTokens.NOT_IS -> JetTokens.IS_KEYWORD
JetTokens.EQEQ -> JetTokens.EXCLEQ
JetTokens.EXCLEQ -> JetTokens.EQEQ
JetTokens.LT -> JetTokens.GTEQ
JetTokens.GTEQ -> JetTokens.LT
JetTokens.GT -> JetTokens.LTEQ
JetTokens.LTEQ -> JetTokens.GT
else -> null
}
override fun isApplicableTo(element: JetPrefixExpression): Boolean {
if (element.getOperationReference().getReferencedNameElementType() != JetTokens.EXCL) return false
val expression = element.unparenthesize() as? JetOperationExpression
if (!(expression is JetIsExpression || expression is JetBinaryExpression)) return false
val operation = (JetPsiUtil.getOperationToken(expression) as? JetSingleValueToken) ?: return false
val negOperation = operation.negate() ?: return false
setText(JetBundle.message("simplify.negated.binary.expression", operation.getValue(), negOperation.getValue()))
return true
}
override fun applyTo(element: JetPrefixExpression, editor: Editor) {
applyTo(element)
}
public fun applyTo(element: JetPrefixExpression) {
// Guaranteed to succeed (by isApplicableTo)
val expression = element.unparenthesize()!!
val invertedOperation = JetPsiUtil.getOperationToken(expression as JetOperationExpression)!!.negate()!!
val psiFactory = JetPsiFactory(expression)
element.replace(
when (expression) {
is JetIsExpression -> {
psiFactory.createExpression(
"${expression.getLeftHandSide().getText() ?: ""} ${invertedOperation.getValue()} ${expression.getTypeReference()?.getText() ?: ""}"
)
}
is JetBinaryExpression -> psiFactory.createExpressionByPattern("$0 $1 $2",
expression.getLeft(),
invertedOperation.getValue(),
expression.getRight()
)
else -> throw IllegalStateException(
"Expression is neither a JetIsExpression or JetBinaryExpression (checked by isApplicableTo): ${expression.getText()}"
)
}
)
}
}