Rename: Initial support of naming conventions
This commit is contained in:
@@ -31,40 +31,169 @@ import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.jet.lang.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.jet.lang.psi.JetQualifiedExpression
|
||||
|
||||
public class OperatorToFunctionIntention : JetSelfTargetingIntention<JetExpression>("operator.to.function", javaClass()) {
|
||||
fun isApplicablePrefix(element: JetPrefixExpression): Boolean {
|
||||
return when (element.getOperationReference().getReferencedNameElementType()) {
|
||||
JetTokens.PLUS, JetTokens.MINUS, JetTokens.PLUSPLUS, JetTokens.MINUSMINUS, JetTokens.EXCL -> true
|
||||
else -> false
|
||||
class object {
|
||||
private fun isApplicablePrefix(element: JetPrefixExpression): Boolean {
|
||||
return when (element.getOperationReference().getReferencedNameElementType()) {
|
||||
JetTokens.PLUS, JetTokens.MINUS, JetTokens.PLUSPLUS, JetTokens.MINUSMINUS, JetTokens.EXCL -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isApplicablePostfix(element: JetPostfixExpression): Boolean {
|
||||
return when (element.getOperationReference().getReferencedNameElementType()) {
|
||||
JetTokens.PLUSPLUS, JetTokens.MINUSMINUS -> true
|
||||
else -> false
|
||||
private fun isApplicablePostfix(element: JetPostfixExpression): Boolean {
|
||||
return when (element.getOperationReference().getReferencedNameElementType()) {
|
||||
JetTokens.PLUSPLUS, JetTokens.MINUSMINUS -> true
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isApplicableBinary(element: JetBinaryExpression): Boolean {
|
||||
return when (element.getOperationReference().getReferencedNameElementType()) {
|
||||
JetTokens.PLUS, JetTokens.MINUS, JetTokens.MUL, JetTokens.DIV, JetTokens.PERC, JetTokens.RANGE, JetTokens.IN_KEYWORD, JetTokens.NOT_IN, JetTokens.PLUSEQ, JetTokens.MINUSEQ, JetTokens.MULTEQ, JetTokens.DIVEQ, JetTokens.PERCEQ, JetTokens.EQEQ, JetTokens.EXCLEQ, JetTokens.GT, JetTokens.LT, JetTokens.GTEQ, JetTokens.LTEQ -> true
|
||||
JetTokens.EQ -> element.getLeft() is JetArrayAccessExpression
|
||||
else -> false
|
||||
private fun isApplicableBinary(element: JetBinaryExpression): Boolean {
|
||||
return when (element.getOperationReference().getReferencedNameElementType()) {
|
||||
JetTokens.PLUS, JetTokens.MINUS, JetTokens.MUL, JetTokens.DIV, JetTokens.PERC, JetTokens.RANGE, JetTokens.IN_KEYWORD, JetTokens.NOT_IN, JetTokens.PLUSEQ, JetTokens.MINUSEQ, JetTokens.MULTEQ, JetTokens.DIVEQ, JetTokens.PERCEQ, JetTokens.EQEQ, JetTokens.EXCLEQ, JetTokens.GT, JetTokens.LT, JetTokens.GTEQ, JetTokens.LTEQ -> true
|
||||
JetTokens.EQ -> element.getLeft() is JetArrayAccessExpression
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun isApplicableCall(element: JetCallExpression): Boolean {
|
||||
val bindingContext = AnalyzerFacadeWithCache.getContextForElement(element)
|
||||
val resolvedCall = element.getResolvedCall(bindingContext)
|
||||
val descriptor = resolvedCall?.getResultingDescriptor()
|
||||
if (descriptor is FunctionDescriptor && descriptor.getName().asString() == "invoke") {
|
||||
private fun isApplicableCall(element: JetCallExpression): Boolean {
|
||||
val bindingContext = AnalyzerFacadeWithCache.getContextForElement(element)
|
||||
val resolvedCall = element.getResolvedCall(bindingContext)
|
||||
val descriptor = resolvedCall?.getResultingDescriptor()
|
||||
if (descriptor is FunctionDescriptor && descriptor.getName().asString() == "invoke") {
|
||||
val parent = element.getParent()
|
||||
if (parent is JetDotQualifiedExpression && element.getCalleeExpression()?.getText() == "invoke") return false
|
||||
return !(element.getValueArgumentList() == null && element.getFunctionLiteralArguments().isEmpty())
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private fun convertPrefix(element: JetPrefixExpression): JetExpression {
|
||||
val op = element.getOperationReference().getReferencedNameElementType()
|
||||
val base = element.getBaseExpression()!!.getText()
|
||||
|
||||
val call = when (op) {
|
||||
JetTokens.PLUS -> "plus()"
|
||||
JetTokens.MINUS -> "minus()"
|
||||
JetTokens.PLUSPLUS -> "inc()"
|
||||
JetTokens.MINUSMINUS -> "dec()"
|
||||
JetTokens.EXCL -> "not()"
|
||||
else -> return element
|
||||
}
|
||||
|
||||
val transformation = "$base.$call"
|
||||
val transformed = JetPsiFactory(element).createExpression(transformation)
|
||||
return element.replace(transformed) as JetExpression
|
||||
}
|
||||
|
||||
private fun convertPostFix(element: JetPostfixExpression): JetExpression {
|
||||
val op = element.getOperationReference().getReferencedNameElementType()
|
||||
val base = element.getBaseExpression().getText()
|
||||
|
||||
val call = when (op) {
|
||||
JetTokens.PLUSPLUS -> "inc()"
|
||||
JetTokens.MINUSMINUS -> "dec()"
|
||||
else -> return element
|
||||
}
|
||||
|
||||
val transformation = "$base.$call"
|
||||
val transformed = JetPsiFactory(element).createExpression(transformation)
|
||||
return element.replace(transformed) as JetExpression
|
||||
}
|
||||
|
||||
private fun convertBinary(element: JetBinaryExpression): JetExpression {
|
||||
val op = element.getOperationReference().getReferencedNameElementType()
|
||||
val left = element.getLeft()!!
|
||||
val right = element.getRight()!!
|
||||
val leftText = left.getText()
|
||||
val rightText = right.getText()
|
||||
|
||||
if (op == JetTokens.EQ) {
|
||||
if (left is JetArrayAccessExpression) {
|
||||
convertArrayAccess(left as JetArrayAccessExpression)
|
||||
}
|
||||
return element
|
||||
}
|
||||
|
||||
val context = AnalyzerFacadeWithCache.getContextForElement(element)
|
||||
val functionCandidate = element.getResolvedCall(context)
|
||||
val functionName = functionCandidate?.getCandidateDescriptor()?.getName().toString()
|
||||
val elemType = context[BindingContext.EXPRESSION_TYPE, left]
|
||||
|
||||
val transformation = when (op) {
|
||||
JetTokens.PLUS -> "$leftText.plus($rightText)"
|
||||
JetTokens.MINUS -> "$leftText.minus($rightText)"
|
||||
JetTokens.MUL -> "$leftText.times($rightText)"
|
||||
JetTokens.DIV -> "$leftText.div($rightText)"
|
||||
JetTokens.PERC -> "$leftText.mod($rightText)"
|
||||
JetTokens.RANGE -> "$leftText.rangeTo($rightText)"
|
||||
JetTokens.IN_KEYWORD -> "$rightText.contains($leftText)"
|
||||
JetTokens.NOT_IN -> "!$rightText.contains($leftText)"
|
||||
JetTokens.PLUSEQ -> if (functionName == "plusAssign") "$leftText.plusAssign($rightText)" else "$leftText = $leftText.plus($rightText)"
|
||||
JetTokens.MINUSEQ -> if (functionName == "minusAssign") "$leftText.minusAssign($rightText)" else "$leftText = $leftText.minus($rightText)"
|
||||
JetTokens.MULTEQ -> if (functionName == "multAssign") "$leftText.multAssign($rightText)" else "$leftText = $leftText.mult($rightText)"
|
||||
JetTokens.DIVEQ -> if (functionName == "divAssign") "$leftText.divAssign($rightText)" else "$leftText = $leftText.div($rightText)"
|
||||
JetTokens.PERCEQ -> if (functionName == "modAssign") "$leftText.modAssign($rightText)" else "$leftText = $leftText.mod($rightText)"
|
||||
JetTokens.EQEQ -> if (elemType?.isNullable() ?: true) "$leftText?.equals($rightText) ?: $rightText.identityEquals(null)" else "$leftText.equals($rightText)"
|
||||
JetTokens.EXCLEQ -> if (elemType?.isNullable() ?: true) "!($leftText?.equals($rightText) ?: $rightText.identityEquals(null))" else "!$leftText.equals($rightText)"
|
||||
JetTokens.GT -> "$leftText.compareTo($rightText) > 0"
|
||||
JetTokens.LT -> "$leftText.compareTo($rightText) < 0"
|
||||
JetTokens.GTEQ -> "$leftText.compareTo($rightText) >= 0"
|
||||
JetTokens.LTEQ -> "$leftText.compareTo($rightText) <= 0"
|
||||
else -> return element
|
||||
}
|
||||
|
||||
val transformed = JetPsiFactory(element).createExpression(transformation)
|
||||
|
||||
return element.replace(transformed) as JetExpression
|
||||
}
|
||||
|
||||
private fun convertArrayAccess(element: JetArrayAccessExpression): JetExpression {
|
||||
val parent = element.getParent()
|
||||
if (parent is JetDotQualifiedExpression && element.getCalleeExpression()?.getText() == "invoke") return false
|
||||
return !(element.getValueArgumentList() == null && element.getFunctionLiteralArguments().isEmpty())
|
||||
val array = element.getArrayExpression()!!.getText()
|
||||
val indices = element.getIndicesNode()
|
||||
val indicesText = indices.getText()?.trim("[","]") ?: throw AssertionError("Indices node of ArrayExpression shouldn't be null: JetArrayAccessExpression = ${element.getText()}")
|
||||
|
||||
val transformation : String
|
||||
val replaced : JetElement
|
||||
if (parent is JetBinaryExpression && parent.getOperationReference().getReferencedNameElementType() == JetTokens.EQ) {
|
||||
// part of an assignment
|
||||
val right = parent.getRight()!!.getText()
|
||||
transformation = "$array.set($indicesText, $right)"
|
||||
replaced = parent
|
||||
}
|
||||
else {
|
||||
transformation = "$array.get($indicesText)"
|
||||
replaced = element
|
||||
}
|
||||
|
||||
val transformed = JetPsiFactory(element).createExpression(transformation)
|
||||
return replaced.replace(transformed) as JetExpression
|
||||
}
|
||||
|
||||
private fun convertCall(element: JetCallExpression): JetExpression {
|
||||
val callee = element.getCalleeExpression()!!
|
||||
val arguments = element.getValueArgumentList()
|
||||
val argumentString = arguments?.getText()?.trim("(", ")")
|
||||
val funcLitArgs = element.getFunctionLiteralArguments()
|
||||
val calleeText = callee.getText()
|
||||
val transformation = if (argumentString == null) "$calleeText.invoke" else "$calleeText.invoke($argumentString)"
|
||||
val transformed = JetPsiFactory(element).createExpression(transformation)
|
||||
funcLitArgs.forEach { transformed.add(it) }
|
||||
return callee.getParent()!!.replace(transformed) as JetExpression
|
||||
}
|
||||
|
||||
public fun convert(element: JetExpression): JetExpression {
|
||||
return when (element) {
|
||||
is JetPrefixExpression -> convertPrefix(element)
|
||||
is JetPostfixExpression -> convertPostFix(element)
|
||||
is JetBinaryExpression -> convertBinary(element)
|
||||
is JetArrayAccessExpression -> convertArrayAccess(element)
|
||||
is JetCallExpression -> convertCall(element)
|
||||
else -> element
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
override fun isApplicableTo(element: JetExpression): Boolean {
|
||||
@@ -78,128 +207,7 @@ public class OperatorToFunctionIntention : JetSelfTargetingIntention<JetExpressi
|
||||
}
|
||||
}
|
||||
|
||||
fun convertPrefix(element: JetPrefixExpression) {
|
||||
val op = element.getOperationReference().getReferencedNameElementType()
|
||||
val base = element.getBaseExpression()!!.getText()
|
||||
|
||||
val call = when (op) {
|
||||
JetTokens.PLUS -> "plus()"
|
||||
JetTokens.MINUS -> "minus()"
|
||||
JetTokens.PLUSPLUS -> "inc()"
|
||||
JetTokens.MINUSMINUS -> "dec()"
|
||||
JetTokens.EXCL -> "not()"
|
||||
else -> return
|
||||
}
|
||||
|
||||
val transformation = "$base.$call"
|
||||
val transformed = JetPsiFactory(element).createExpression(transformation)
|
||||
element.replace(transformed)
|
||||
}
|
||||
|
||||
fun convertPostFix(element: JetPostfixExpression) {
|
||||
val op = element.getOperationReference().getReferencedNameElementType()
|
||||
val base = element.getBaseExpression().getText()
|
||||
|
||||
val call = when (op) {
|
||||
JetTokens.PLUSPLUS -> "inc()"
|
||||
JetTokens.MINUSMINUS -> "dec()"
|
||||
else -> return
|
||||
}
|
||||
|
||||
val transformation = "$base.$call"
|
||||
val transformed = JetPsiFactory(element).createExpression(transformation)
|
||||
element.replace(transformed)
|
||||
}
|
||||
|
||||
fun convertBinary(element: JetBinaryExpression) {
|
||||
val op = element.getOperationReference().getReferencedNameElementType()
|
||||
val left = element.getLeft()!!
|
||||
val right = element.getRight()!!
|
||||
val leftText = left.getText()
|
||||
val rightText = right.getText()
|
||||
|
||||
if (op == JetTokens.EQ) {
|
||||
if (left is JetArrayAccessExpression) {
|
||||
convertArrayAccess(left as JetArrayAccessExpression)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
val context = AnalyzerFacadeWithCache.getContextForElement(element)
|
||||
val functionCandidate = element.getResolvedCall(context)
|
||||
val functionName = functionCandidate?.getCandidateDescriptor()?.getName().toString()
|
||||
val elemType = context[BindingContext.EXPRESSION_TYPE, left]
|
||||
|
||||
val transformation = when (op) {
|
||||
JetTokens.PLUS -> "$leftText.plus($rightText)"
|
||||
JetTokens.MINUS -> "$leftText.minus($rightText)"
|
||||
JetTokens.MUL -> "$leftText.times($rightText)"
|
||||
JetTokens.DIV -> "$leftText.div($rightText)"
|
||||
JetTokens.PERC -> "$leftText.mod($rightText)"
|
||||
JetTokens.RANGE -> "$leftText.rangeTo($rightText)"
|
||||
JetTokens.IN_KEYWORD -> "$rightText.contains($leftText)"
|
||||
JetTokens.NOT_IN -> "!$rightText.contains($leftText)"
|
||||
JetTokens.PLUSEQ -> if (functionName == "plusAssign") "$leftText.plusAssign($rightText)" else "$leftText = $leftText.plus($rightText)"
|
||||
JetTokens.MINUSEQ -> if (functionName == "minusAssign") "$leftText.minusAssign($rightText)" else "$leftText = $leftText.minus($rightText)"
|
||||
JetTokens.MULTEQ -> if (functionName == "multAssign") "$leftText.multAssign($rightText)" else "$leftText = $leftText.mult($rightText)"
|
||||
JetTokens.DIVEQ -> if (functionName == "divAssign") "$leftText.divAssign($rightText)" else "$leftText = $leftText.div($rightText)"
|
||||
JetTokens.PERCEQ -> if (functionName == "modAssign") "$leftText.modAssign($rightText)" else "$leftText = $leftText.mod($rightText)"
|
||||
JetTokens.EQEQ -> if (elemType?.isNullable() ?: true) "$leftText?.equals($rightText) ?: $rightText.identityEquals(null)" else "$leftText.equals($rightText)"
|
||||
JetTokens.EXCLEQ -> if (elemType?.isNullable() ?: true) "!($leftText?.equals($rightText) ?: $rightText.identityEquals(null))" else "!$leftText.equals($rightText)"
|
||||
JetTokens.GT -> "$leftText.compareTo($rightText) > 0"
|
||||
JetTokens.LT -> "$leftText.compareTo($rightText) < 0"
|
||||
JetTokens.GTEQ -> "$leftText.compareTo($rightText) >= 0"
|
||||
JetTokens.LTEQ -> "$leftText.compareTo($rightText) <= 0"
|
||||
else -> return
|
||||
}
|
||||
|
||||
val transformed = JetPsiFactory(element).createExpression(transformation)
|
||||
|
||||
element.replace(transformed)
|
||||
}
|
||||
|
||||
fun convertArrayAccess(element: JetArrayAccessExpression) {
|
||||
val parent = element.getParent()
|
||||
val array = element.getArrayExpression()!!.getText()
|
||||
val indices = element.getIndicesNode()
|
||||
val indicesText = indices.getText()?.trim("[","]") ?: throw AssertionError("Indices node of ArrayExpression shouldn't be null: JetArrayAccessExpression = ${element.getText()}")
|
||||
|
||||
val transformation : String
|
||||
val replaced : JetElement
|
||||
if (parent is JetBinaryExpression && parent.getOperationReference().getReferencedNameElementType() == JetTokens.EQ) {
|
||||
// part of an assignment
|
||||
val right = parent.getRight()!!.getText()
|
||||
transformation = "$array.set($indicesText, $right)"
|
||||
replaced = parent
|
||||
}
|
||||
else {
|
||||
transformation = "$array.get($indicesText)"
|
||||
replaced = element
|
||||
}
|
||||
|
||||
val transformed = JetPsiFactory(element).createExpression(transformation)
|
||||
replaced.replace(transformed)
|
||||
}
|
||||
|
||||
fun convertCall(element: JetCallExpression) {
|
||||
val callee = element.getCalleeExpression()!!
|
||||
val arguments = element.getValueArgumentList()
|
||||
val argumentString = arguments?.getText()?.trim("(", ")")
|
||||
val funcLitArgs = element.getFunctionLiteralArguments()
|
||||
val calleeText = callee.getText()
|
||||
val transformation = if (argumentString == null) "$calleeText.invoke" else "$calleeText.invoke($argumentString)"
|
||||
val transformed = JetPsiFactory(element).createExpression(transformation)
|
||||
funcLitArgs.forEach { transformed.add(it) }
|
||||
callee.getParent()!!.replace(transformed)
|
||||
}
|
||||
|
||||
override fun applyTo(element: JetExpression, editor: Editor) {
|
||||
return when (element) {
|
||||
is JetPrefixExpression -> convertPrefix(element)
|
||||
is JetPostfixExpression -> convertPostFix(element)
|
||||
is JetBinaryExpression -> convertBinary(element)
|
||||
is JetArrayAccessExpression -> convertArrayAccess(element)
|
||||
is JetCallExpression -> convertCall(element)
|
||||
}
|
||||
convert(element)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -37,4 +37,6 @@ refactoring.move.non.kotlin.file=Target must be a Kotlin file
|
||||
package.private.0.will.no.longer.be.accessible.from.1=Package-private {0} will no longer be accessible from {1}
|
||||
0.uses.package.private.1={0} uses package-private {1}
|
||||
0.will.no.longer.be.accessible.after.extraction={0} will no longer be accessible after extraction
|
||||
0.will.become.invisible.after.extraction={0} will become invisible after extraction
|
||||
0.will.become.invisible.after.extraction={0} will become invisible after extraction
|
||||
|
||||
naming.convention.will.be.violated.after.rename=Naming conventions will be violated after rename
|
||||
@@ -33,7 +33,7 @@ import org.jetbrains.jet.plugin.JetBundle;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class RenameJetClassProcessor extends RenamePsiElementProcessor {
|
||||
public class RenameJetClassProcessor extends RenameKotlinPsiProcessor {
|
||||
@Override
|
||||
public boolean canProcessElement(@NotNull PsiElement element) {
|
||||
return element instanceof JetClassOrObject || element instanceof KotlinLightClass;
|
||||
|
||||
+2
-3
@@ -19,7 +19,6 @@ package org.jetbrains.jet.plugin.refactoring.rename;
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.refactoring.rename.RenamePsiElementProcessor
|
||||
import com.intellij.psi.search.SearchScope
|
||||
import org.jetbrains.jet.asJava.LightClassUtil
|
||||
import org.jetbrains.jet.lang.psi.JetNamedFunction
|
||||
@@ -28,7 +27,7 @@ import org.jetbrains.jet.lang.resolve.java.jetAsJava.KotlinLightMethod
|
||||
import kotlin.properties.Delegates
|
||||
import org.jetbrains.jet.plugin.refactoring.runReadAction
|
||||
|
||||
public class RenameKotlinFunctionProcessor : RenamePsiElementProcessor() {
|
||||
public class RenameKotlinFunctionProcessor : RenameKotlinPsiProcessor() {
|
||||
private val javaMethodProcessorInstance by Delegates.lazy {
|
||||
// KT-4250
|
||||
// RenamePsiElementProcessor.EP_NAME.findExtension(javaClass<RenameJavaMethodProcessor>())!!
|
||||
@@ -65,4 +64,4 @@ public class RenameKotlinFunctionProcessor : RenamePsiElementProcessor() {
|
||||
is JetNamedFunction -> runReadAction { LightClassUtil.getLightClassMethod(element) }
|
||||
else -> throw IllegalStateException("Can't be for element $element there because of canProcessElement()")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.refactoring.rename
|
||||
|
||||
import com.intellij.refactoring.rename.RenamePsiElementProcessor
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import org.jetbrains.jet.lang.psi.JetNamedFunction
|
||||
import org.jetbrains.jet.lang.resolve.java.jetAsJava.KotlinLightMethod
|
||||
import org.jetbrains.jet.lang.psi.JetNamedDeclaration
|
||||
|
||||
abstract class RenameKotlinPsiProcessor : RenamePsiElementProcessor() {
|
||||
override fun canProcessElement(element: PsiElement): Boolean = element is JetNamedDeclaration
|
||||
|
||||
override fun findCollisions(
|
||||
element: PsiElement?,
|
||||
newName: String?,
|
||||
allRenames: Map<out PsiElement?, String>,
|
||||
result: MutableList<UsageInfo>
|
||||
) {
|
||||
checkConflictsAndReplaceUsageInfos(result)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* 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.refactoring.rename
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.usageView.UsageInfo
|
||||
import java.util.ArrayList
|
||||
import com.intellij.refactoring.util.MoveRenameUsageInfo
|
||||
import org.jetbrains.jet.plugin.references.JetMultiDeclarationReference
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.getParentByTypeAndBranch
|
||||
import org.jetbrains.jet.lang.psi.JetWhenConditionInRange
|
||||
import com.intellij.refactoring.rename.UnresolvableCollisionUsageInfo
|
||||
import org.jetbrains.jet.plugin.refactoring.JetRefactoringBundle
|
||||
import org.jetbrains.jet.plugin.references.JetForLoopInReference
|
||||
import org.jetbrains.jet.plugin.references.JetReference
|
||||
import org.jetbrains.jet.plugin.references.AbstractJetReference
|
||||
|
||||
fun checkConflictsAndReplaceUsageInfos(result: MutableList<UsageInfo>) {
|
||||
val usagesToAdd = ArrayList<UsageInfo>()
|
||||
val usagesToRemove = ArrayList<UsageInfo>()
|
||||
|
||||
for (usageInfo in result) {
|
||||
val ref = usageInfo.getReference()
|
||||
if (usageInfo !is MoveRenameUsageInfo || ref !is AbstractJetReference<*> || ref.canRename()) continue
|
||||
|
||||
val refElement = usageInfo.getElement()
|
||||
val referencedElement = usageInfo.getReferencedElement()
|
||||
if (refElement != null && referencedElement != null) {
|
||||
usagesToAdd.add(UnresolvableConventionViolationUsageInfo(refElement, referencedElement))
|
||||
usagesToRemove.add(usageInfo)
|
||||
}
|
||||
}
|
||||
|
||||
result.removeAll(usagesToRemove)
|
||||
result.addAll(usagesToAdd)
|
||||
}
|
||||
|
||||
class UnresolvableConventionViolationUsageInfo(
|
||||
element: PsiElement,
|
||||
referencedElement: PsiElement
|
||||
) : UnresolvableCollisionUsageInfo(element, referencedElement) {
|
||||
override fun getDescription(): String = JetRefactoringBundle.message("naming.convention.will.be.violated.after.rename")
|
||||
}
|
||||
@@ -20,14 +20,18 @@ import com.google.common.collect.Lists;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.MultiRangeReference;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import jet.runtime.typeinfo.JetValueParameter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.JetArrayAccessExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetContainerNode;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.plugin.intentions.OperatorToFunctionIntention;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -84,4 +88,16 @@ public class JetArrayAccessReference extends JetSimpleReference<JetArrayAccessEx
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRename() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiElement handleElementRename(@Nullable String newElementName) {
|
||||
return ReferencesPackage.renameImplicitConventionalCall(this, newElementName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,11 @@ package org.jetbrains.jet.plugin.references;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.psi.MultiRangeReference;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import jet.runtime.typeinfo.JetValueParameter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
@@ -27,6 +31,7 @@ import org.jetbrains.jet.lang.resolve.calls.callUtil.CallUtilPackage;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.plugin.intentions.OperatorToFunctionIntention;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -98,4 +103,16 @@ public class JetInvokeFunctionReference extends JetSimpleReference<JetCallExpres
|
||||
TextRange textRange = node.getTextRange();
|
||||
return textRange.shiftRight(-getExpression().getTextOffset());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRename() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
@Nullable
|
||||
@Override
|
||||
public PsiElement handleElementRename(@Nullable String newElementName) {
|
||||
return ReferencesPackage.renameImplicitConventionalCall(this, newElementName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,11 @@ import java.util.Collections
|
||||
import org.jetbrains.jet.lang.descriptors.ClassDescriptor
|
||||
import org.jetbrains.jet.lang.resolve.source.PsiSourceElement
|
||||
import org.jetbrains.jet.lang.resolve.source.getPsi
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.jet.lang.psi.JetNamedFunction
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor
|
||||
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor
|
||||
|
||||
class JetMultiDeclarationReference(element: JetMultiDeclaration) : JetMultiReference<JetMultiDeclaration>(element) {
|
||||
override fun getTargetDescriptors(context: BindingContext): Collection<DeclarationDescriptor> {
|
||||
@@ -38,4 +43,13 @@ class JetMultiDeclarationReference(element: JetMultiDeclaration) : JetMultiRefer
|
||||
if (start == null || end == null) return TextRange.EMPTY_RANGE
|
||||
return TextRange(start.getStartOffsetInParent(), end.getStartOffsetInParent())
|
||||
}
|
||||
|
||||
override fun canRename(): Boolean {
|
||||
return resolveToDescriptors().all { it is CallableMemberDescriptor && it.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED}
|
||||
}
|
||||
|
||||
override fun handleElementRename(newElementName: String?): PsiElement? {
|
||||
if (canRename()) return expression
|
||||
throw IncorrectOperationException()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public trait JetReference : PsiPolyVariantReference {
|
||||
public fun resolveMap(): Map<DeclarationDescriptor, Collection<PsiElement>>
|
||||
}
|
||||
|
||||
abstract class AbstractJetReference<T : JetElement>(element: T)
|
||||
public abstract class AbstractJetReference<T : JetElement>(element: T)
|
||||
: PsiPolyVariantReferenceBase<T>(element), JetReference {
|
||||
|
||||
val expression: T
|
||||
@@ -67,6 +67,7 @@ abstract class AbstractJetReference<T : JetElement>(element: T)
|
||||
|
||||
override fun getCanonicalText(): String = "<TBD>"
|
||||
|
||||
open fun canRename(): Boolean = false
|
||||
override fun handleElementRename(newElementName: String?): PsiElement? = throw IncorrectOperationException()
|
||||
|
||||
override fun bindToElement(element: PsiElement): PsiElement = throw IncorrectOperationException()
|
||||
|
||||
@@ -28,6 +28,15 @@ import org.jetbrains.jet.lang.psi.psiUtil.getQualifiedElementSelector
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.getOutermostNonInterleavingQualifiedElement
|
||||
import org.jetbrains.jet.plugin.codeInsight.addToShorteningWaitSet
|
||||
import org.jetbrains.jet.plugin.refactoring.getKotlinFqName
|
||||
import org.jetbrains.jet.lang.types.expressions.OperatorConventions
|
||||
import org.jetbrains.jet.lexer.JetToken
|
||||
import org.jetbrains.jet.plugin.intentions.OperatorToFunctionIntention
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.getParentByType
|
||||
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorResolver
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.jet.lang.psi.psiUtil.getParentByTypeAndBranch
|
||||
|
||||
public class JetSimpleNameReference(
|
||||
jetSimpleNameExpression: JetSimpleNameExpression
|
||||
@@ -35,8 +44,23 @@ public class JetSimpleNameReference(
|
||||
|
||||
override fun getRangeInElement(): TextRange = TextRange(0, getElement().getTextLength())
|
||||
|
||||
override fun canRename(): Boolean {
|
||||
if (expression.getParentByTypeAndBranch(javaClass<JetWhenConditionInRange>()) { getOperationReference() } != null) return false
|
||||
|
||||
val elementType = expression.getReferencedNameElementType()
|
||||
if (elementType == JetTokens.PLUSPLUS || elementType == JetTokens.MINUSMINUS) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
public override fun handleElementRename(newElementName: String?): PsiElement? {
|
||||
if (newElementName == null) return null;
|
||||
if (!canRename()) throw IncorrectOperationException()
|
||||
if (newElementName == null) return expression;
|
||||
|
||||
// Do not rename if the reference corresponds to synthesized component function
|
||||
if ((expression.getText() ?: "").startsWith(DescriptorResolver.COMPONENT_FUNCTION_NAME_PREFIX) && resolve() is JetParameter) {
|
||||
return expression
|
||||
}
|
||||
|
||||
val psiFactory = JetPsiFactory(expression)
|
||||
val element = when (expression.getReferencedNameElementType()) {
|
||||
@@ -45,7 +69,30 @@ public class JetSimpleNameReference(
|
||||
else -> psiFactory.createNameIdentifier(newElementName)
|
||||
}
|
||||
|
||||
return expression.getReferencedNameElement().replace(element)
|
||||
var nameElement = expression.getReferencedNameElement()
|
||||
|
||||
val elementType = nameElement.getNode()?.getElementType()
|
||||
val opExpression =
|
||||
PsiTreeUtil.getParentOfType<JetExpression>(expression, javaClass<JetUnaryExpression>(), javaClass<JetBinaryExpression>())
|
||||
if (elementType is JetToken && OperatorConventions.getNameForOperationSymbol(elementType) != null && opExpression != null) {
|
||||
val oldDescriptor = AnalyzerFacadeWithCache.getContextForElement(expression)[BindingContext.REFERENCE_TARGET, expression]
|
||||
val newExpression = OperatorToFunctionIntention.convert(opExpression)
|
||||
newExpression.accept(
|
||||
object: JetTreeVisitorVoid() {
|
||||
override fun visitCallExpression(expression: JetCallExpression) {
|
||||
val callee = expression.getCalleeExpression() as? JetSimpleNameExpression
|
||||
if (callee != null && AnalyzerFacadeWithCache.getContextForElement(callee)[BindingContext.REFERENCE_TARGET, callee] == oldDescriptor) {
|
||||
nameElement = callee.getReferencedNameElement()
|
||||
}
|
||||
else {
|
||||
super.visitCallExpression(expression)
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return nameElement.replace(element)
|
||||
}
|
||||
|
||||
public enum class ShorteningMode {
|
||||
|
||||
@@ -29,6 +29,12 @@ import org.jetbrains.jet.lang.psi.JetProperty
|
||||
import java.util.HashSet
|
||||
import com.intellij.util.containers.ContainerUtil
|
||||
import org.jetbrains.jet.lang.psi.JetNamedDeclaration
|
||||
import org.jetbrains.jet.lang.psi.JetExpression
|
||||
import org.jetbrains.jet.lang.psi.JetElement
|
||||
import org.jetbrains.jet.plugin.intentions.OperatorToFunctionIntention
|
||||
import org.jetbrains.jet.lang.psi.JetQualifiedExpression
|
||||
import org.jetbrains.jet.lang.psi.JetCallExpression
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
|
||||
// Navigation element of the resolved reference
|
||||
// For property accessor return enclosing property
|
||||
@@ -59,3 +65,11 @@ fun PsiReference.matchesTarget(target: PsiElement): Boolean {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
fun AbstractJetReference<out JetExpression>.renameImplicitConventionalCall(newName: String?): JetExpression {
|
||||
if (newName == null) return expression
|
||||
|
||||
val expr = OperatorToFunctionIntention.convert(expression) as JetQualifiedExpression
|
||||
val newCallee = (expr.getSelectorExpression() as JetCallExpression).getCalleeExpression()!!.getReference()!!.handleElementRename(newName)
|
||||
return PsiTreeUtil.getParentOfType<JetQualifiedExpression>(newCallee, javaClass<JetQualifiedExpression>()) as JetExpression
|
||||
}
|
||||
Reference in New Issue
Block a user