Intentions: function <-> property conversion

This commit is contained in:
Alexey Sedunov
2015-01-28 13:58:40 +03:00
parent 15ebbdb349
commit 03e076aba3
87 changed files with 1488 additions and 54 deletions
@@ -77,6 +77,13 @@ public class JetNamedFunction extends JetTypeParameterListOwnerStub<KotlinFuncti
return getEqualsToken() == null;
}
@NotNull
public PsiElement getFunToken() {
PsiElement element = findChildByType(JetTokens.FUN_KEYWORD);
assert element != null : "'fun' must be present: " + JetPsiUtil.getElementTextWithContext(this);
return element;
}
@Override
@Nullable
public PsiElement getEqualsToken() {
@@ -340,6 +340,10 @@ convert.to.string.template=Convert concatenation to template
convert.to.string.template.family=Convert Concatenation to Template
convert.to.concatenated.string.intention=Convert template to concatenated string
convert.to.concatenated.string.intention.family=Convert Template to Concatenated String
convert.function.to.property.intention=Convert function to property
convert.function.to.property.intention.family=Convert Function to Property
convert.property.to.function.intention=Convert property to function
convert.property.to.function.intention.family=Convert Property to Function
property.is.implemented.too.many=Has implementations
property.is.overridden.too.many=Is overridden in subclasses
@@ -77,7 +77,7 @@ public data class UsagesSearchLocation(
public data class UsagesSearchTarget<out T : PsiElement>(
val element: T,
private val scope: SearchScope,
private val scope: SearchScope = element.getUseScope(),
val location: UsagesSearchLocation = UsagesSearchLocation.DEFAULT,
val restrictByTargetScope: Boolean = true
) {
@@ -0,0 +1,7 @@
class A(val n: Int) {
<spot>val foo: Int get() = n + 1</spot>
}
fun test() {
val k = A(1).foo
}
@@ -0,0 +1,7 @@
class A(val n: Int) {
<spot>fun foo(): Int = n + 1</spot>
}
fun test() {
val k = A(1).foo()
}
@@ -0,0 +1,5 @@
<html>
<body>
This intention converts function to property.
</body>
</html>
@@ -0,0 +1,7 @@
class A(val n: Int) {
<spot>fun foo(): Int = n + 1</spot>
}
fun test() {
val k = A(1).foo()
}
@@ -0,0 +1,7 @@
class A(val n: Int) {
<spot>val foo: Int get() = n + 1</spot>
}
fun test() {
val k = A(1).foo
}
@@ -0,0 +1,5 @@
<html>
<body>
This intention converts property to function
</body>
</html>
+10
View File
@@ -793,6 +793,16 @@
<category>Kotlin</category>
</intentionAction>
<intentionAction>
<className>org.jetbrains.kotlin.idea.intentions.ConvertFunctionToPropertyIntention</className>
<category>Kotlin</category>
</intentionAction>
<intentionAction>
<className>org.jetbrains.kotlin.idea.intentions.ConvertPropertyToFunctionIntention</className>
<category>Kotlin</category>
</intentionAction>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.ExplicitGetInspection"
displayName="Explicit 'get'"
groupName="Kotlin"
@@ -0,0 +1,221 @@
/*
* 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.psi.JetNamedFunction
import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.refactoring.CallableRefactoring
import org.jetbrains.kotlin.idea.refactoring.getAffectedCallables
import com.intellij.util.containers.MultiMap
import org.jetbrains.kotlin.idea.refactoring.checkConflictsInteractively
import org.jetbrains.kotlin.idea.search.usagesSearch.DefaultSearchHelper
import com.intellij.psi.PsiNamedElement
import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchTarget
import org.jetbrains.kotlin.idea.search.usagesSearch.search
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
import org.jetbrains.kotlin.psi.psiUtil.getParentOfTypeAndBranch
import org.jetbrains.kotlin.psi.JetCallElement
import java.util.ArrayList
import com.intellij.openapi.util.text.StringUtil
import com.intellij.refactoring.util.RefactoringUIUtil
import org.jetbrains.kotlin.psi.JetPsiFactory
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
import com.intellij.psi.PsiMethod
import org.jetbrains.kotlin.codegen.PropertyCodegen
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiWhiteSpace
import org.jetbrains.kotlin.psi.psiUtil.siblings
import com.intellij.psi.PsiReference
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
import org.jetbrains.kotlin.psi.JetElement
import org.jetbrains.kotlin.psi.UserDataProperty
import com.intellij.openapi.util.Key
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.idea.util.supertypes
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.codeInsight.ShortenReferences
import org.jetbrains.kotlin.psi.JetProperty
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
import org.jetbrains.kotlin.idea.refactoring.reportDeclarationConflict
import org.jetbrains.kotlin.idea.refactoring.getContainingScope
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToDeclarationUtil
public class ConvertFunctionToPropertyIntention : JetSelfTargetingIntention<JetNamedFunction>(
"convert.function.to.property.intention", javaClass()
) {
class object {
private var JetNamedFunction.typeFqNameToAdd: String? by UserDataProperty(Key.create("TYPE_FQ_NAME_TO_ADD"))
}
private inner class Convertor(
project: Project,
descriptor: CallableDescriptor,
context: BindingContext): CallableRefactoring<CallableDescriptor>(project, descriptor, context, getText()) {
private val elementsToShorten = ArrayList<JetElement>()
private fun convertJetFunction(originalFunction: JetNamedFunction, psiFactory: JetPsiFactory) {
val function = originalFunction.copy() as JetNamedFunction
val propertySample = psiFactory.createProperty("val foo: Int get() = 1")
val needsExplicitType = function.getTypeReference() == null
if (needsExplicitType) {
originalFunction.typeFqNameToAdd?.let { function.setTypeReference(psiFactory.createType(it)) }
}
function.getFunToken().replace(propertySample.getValOrVarNode().getPsi())
function.getValueParameterList()?.delete()
val insertAfter = (function.getEqualsToken() ?: function.getBodyExpression())
?.siblings(forward = false, withItself = false)
?.firstOrNull { it !is PsiWhiteSpace }
if (insertAfter != null) {
function.addAfter(psiFactory.createParameterList("()"), insertAfter)
function.addAfter(propertySample.getGetter().getNamePlaceholder(), insertAfter)
function.addAfter(psiFactory.createNewLine(), insertAfter)
}
val property = originalFunction.replace(psiFactory.createProperty(function.getText())) as JetProperty
if (needsExplicitType) {
elementsToShorten.add(property.getTypeReference())
}
}
override fun performRefactoring(descriptorsForChange: Collection<CallableDescriptor>) {
val conflicts = MultiMap<PsiElement, String>()
val getterName = PropertyCodegen.getterName(callableDescriptor.getName())
val callables = getAffectedCallables(project, descriptorsForChange)
val kotlinCalls = ArrayList<JetCallElement>()
val foreignRefs = ArrayList<PsiReference>()
for (callable in callables) {
if (callable !is PsiNamedElement) continue
if (!checkModifiable(callable)) {
reportDeclarationConflict(conflicts, callable) { "Can't modify $it" }
}
if (callable is JetNamedFunction) {
if (callable.getTypeReference() == null) {
val type = (callable.resolveToDescriptor() as FunctionDescriptor).getReturnType()
val typeToInsert = when {
type == null || type.isError() -> null
type.getConstructor().isDenotable() -> type
else -> type.supertypes().firstOrNull { it.getConstructor().isDenotable() }
} ?: KotlinBuiltIns.getInstance().getNullableAnyType()
callable.typeFqNameToAdd = IdeDescriptorRenderers.SOURCE_CODE.renderType(typeToInsert)
}
callableDescriptor.getContainingScope(bindingContext)
?.getProperties(callableDescriptor.getName())
?.firstOrNull()
?.let { DescriptorToDeclarationUtil.getDeclaration(project, it) }
?.let { reportDeclarationConflict(conflicts, it) { "$it already exists" } }
}
if (callable is PsiMethod) {
callable.getContainingClass()
?.findMethodsByName(getterName, true)
?.firstOrNull { it.getParameterList().getParametersCount() == 0 && it.namedUnwrappedElement !in callables }
?.let { reportDeclarationConflict(conflicts, it) { "$it already exists" } }
}
val usages = DefaultSearchHelper<PsiNamedElement>().newRequest(UsagesSearchTarget(callable)).search()
for (usage in usages) {
if (usage is JetSimpleNameReference) {
val callElement = usage.expression.getParentOfTypeAndBranch<JetCallElement> { getCalleeExpression() }
if (callElement != null) {
if (callElement.getTypeArguments().isNotEmpty()) {
conflicts.putValue(
callElement,
"Type arguments will be lost after conversion: ${StringUtil.htmlEmphasize(callElement.getText())}"
)
}
if (callElement.getValueArguments().isNotEmpty()) {
conflicts.putValue(
callElement,
"Call with arguments will be skipped: ${StringUtil.htmlEmphasize(callElement.getText())}"
)
continue
}
kotlinCalls.add(callElement)
continue
}
}
else {
foreignRefs.add(usage)
}
}
}
project.checkConflictsInteractively(conflicts) {
project.executeWriteCommand(getText()) {
val psiFactory = JetPsiFactory(project)
callables.forEach {
when (it) {
is JetNamedFunction -> convertJetFunction(it, psiFactory)
is PsiMethod -> it.setName(getterName)
}
}
kotlinCalls.forEach { it.replace(it.getCalleeExpression()) }
foreignRefs.forEach { it.handleElementRename(getterName) }
ShortenReferences.process(elementsToShorten)
}
}
}
}
override fun startInWriteAction(): Boolean = false
override fun isApplicableTo(element: JetNamedFunction): Boolean {
throw IllegalStateException("isApplicableTo(JetExpressionImpl, Editor) should be called instead")
}
override fun isApplicableTo(element: JetNamedFunction, editor: Editor): Boolean {
val elementAtCaret = element.getContainingFile().findElementAt(editor.getCaretModel().getOffset())
if (!(element.getNameIdentifier()?.isAncestor(elementAtCaret) ?: false)) return false
if (element.getValueParameters().isNotEmpty() || element.isLocal()) return false
val name = element.getName()
when {
name == "invoke",
name == "iterator",
OperatorConventions.UNARY_OPERATION_NAMES.inverse().containsKey(Name.identifier(name)) -> return false
}
val descriptor = element.analyze()[BindingContext.DECLARATION_TO_DESCRIPTOR, element] as? FunctionDescriptor ?: return false
val returnType = descriptor.getReturnType()
return !(KotlinBuiltIns.isUnit(returnType) || KotlinBuiltIns.isNothing(returnType))
}
override fun applyTo(element: JetNamedFunction, editor: Editor) {
val context = element.analyze()
val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, element] as? CallableDescriptor ?: return
Convertor(element.getProject(), descriptor, context).run()
}
}
@@ -0,0 +1,201 @@
/*
* 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.JetProperty
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.idea.refactoring.CallableRefactoring
import org.jetbrains.kotlin.psi.JetPsiFactory
import com.intellij.psi.PsiWhiteSpace
import org.jetbrains.kotlin.psi.psiUtil.siblings
import com.intellij.util.containers.MultiMap
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.idea.refactoring.getAffectedCallables
import java.util.ArrayList
import com.intellij.psi.PsiReference
import com.intellij.psi.PsiNamedElement
import com.intellij.refactoring.util.RefactoringUIUtil
import org.jetbrains.kotlin.idea.search.usagesSearch.DefaultSearchHelper
import org.jetbrains.kotlin.idea.search.usagesSearch.UsagesSearchTarget
import org.jetbrains.kotlin.idea.search.usagesSearch.search
import org.jetbrains.kotlin.idea.references.JetSimpleNameReference
import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
import org.jetbrains.kotlin.psi.JetSimpleNameExpression
import org.jetbrains.kotlin.idea.references.JetReference
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiField
import com.intellij.psi.PsiReferenceExpression
import com.intellij.psi.PsiElementFactory
import org.jetbrains.kotlin.idea.refactoring.checkConflictsInteractively
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
import org.jetbrains.kotlin.psi.JetCallableReferenceExpression
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import com.intellij.psi.PsiJavaReference
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
import org.jetbrains.kotlin.psi.JetExpressionImpl
import org.jetbrains.kotlin.codegen.PropertyCodegen
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
import org.jetbrains.kotlin.idea.refactoring.reportDeclarationConflict
import org.jetbrains.kotlin.idea.refactoring.getContainingScope
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToDeclarationUtil
public class ConvertPropertyToFunctionIntention : JetSelfTargetingIntention<JetProperty>(
"convert.property.to.function.intention", javaClass()
) {
private inner class Convertor(
project: Project,
descriptor: CallableDescriptor,
context: BindingContext): CallableRefactoring<CallableDescriptor>(project, descriptor, context, getText()) {
private fun convertJetProperty(originalProperty: JetProperty, psiFactory: JetPsiFactory) {
val property = originalProperty.copy() as JetProperty;
val getter = property.getGetter();
val sampleFunction = psiFactory.createFunction("fun foo() {\n\n}");
property.getValOrVarNode().getPsi().replace(sampleFunction.getFunToken());
property.addAfter(psiFactory.createParameterList("()"), property.getNameIdentifier());
if (property.getInitializer() == null) {
if (getter != null) {
val dropGetterTo = (getter.getEqualsToken() ?: getter.getBodyExpression())
?.siblings(forward = false, withItself = false)
?.firstOrNull { it !is PsiWhiteSpace }
getter.deleteChildRange(getter.getFirstChild(), dropGetterTo)
val dropPropertyFrom = getter
.siblings(forward = false, withItself = false)
.first { it !is PsiWhiteSpace }
.getNextSibling()
property.deleteChildRange(dropPropertyFrom, getter.getPrevSibling())
}
}
originalProperty.replace(psiFactory.createFunction(property.getText()))
}
override fun performRefactoring(descriptorsForChange: Collection<CallableDescriptor>) {
val propertyName = callableDescriptor.getName().asString()
val getterName = PropertyCodegen.getterName(callableDescriptor.getName())
val conflicts = MultiMap<PsiElement, String>()
val callables = getAffectedCallables(project, descriptorsForChange)
val kotlinRefs = ArrayList<JetSimpleNameExpression>()
val foreignRefsToRename = ArrayList<PsiReference>()
val javaRefsToReplaceWithCall = ArrayList<PsiReferenceExpression>()
for (callable in callables) {
if (callable !is PsiNamedElement) continue
if (!checkModifiable(callable)) {
val renderedCallable = RefactoringUIUtil.getDescription(callable, true).capitalize()
conflicts.putValue(callable, "Can't modify $renderedCallable")
}
if (callable is JetProperty) {
callableDescriptor.getContainingScope(bindingContext)
?.getFunctions(callableDescriptor.getName())
?.firstOrNull { it.getValueParameters().isEmpty() }
?.let { DescriptorToDeclarationUtil.getDeclaration(project, it) }
?.let { reportDeclarationConflict(conflicts, it) { "$it already exists" } }
}
else if (callable is PsiMethod) {
callable.getContainingClass()
?.findMethodsByName(propertyName, true)
?.firstOrNull { it.getParameterList().getParametersCount() == 0 && it.namedUnwrappedElement !in callables }
?.let { reportDeclarationConflict(conflicts, it) { "$it already exists" } }
}
val usages = DefaultSearchHelper<PsiNamedElement>().newRequest(UsagesSearchTarget(callable)).search()
for (usage in usages) {
if (usage is JetReference) {
if (usage is JetSimpleNameReference) {
val expression = usage.expression
if (expression.getCall(expression.analyze()) != null
&& expression.getStrictParentOfType<JetCallableReferenceExpression>() == null) {
kotlinRefs.add(expression)
}
}
else {
val refElement = usage.getElement()
conflicts.putValue(
refElement,
"Unrecognized reference will be skipped: ${StringUtil.htmlEmphasize(refElement.getText())}"
)
}
continue
}
val refElement = usage.getElement()
if (refElement.getText().endsWith(getterName)) {
foreignRefsToRename.add(usage)
continue
}
if (usage is PsiJavaReference) {
if (usage.resolve() is PsiField && usage is PsiReferenceExpression) {
javaRefsToReplaceWithCall.add(usage)
}
continue
}
conflicts.putValue(
refElement,
"Can't replace foreign reference with call expression: ${StringUtil.htmlEmphasize(refElement.getText())}"
)
}
}
project.checkConflictsInteractively(conflicts) {
project.executeWriteCommand(getText()) {
val kotlinPsiFactory = JetPsiFactory(project)
val javaPsiFactory = PsiElementFactory.SERVICE.getInstance(project)
callables.forEach {
when (it) {
is JetProperty -> convertJetProperty(it, kotlinPsiFactory)
is PsiMethod -> it.setName(propertyName)
}
}
kotlinRefs.forEach { it.replace(kotlinPsiFactory.createExpression("${it.getText()}()")) }
foreignRefsToRename.forEach { it.handleElementRename(propertyName) }
javaRefsToReplaceWithCall.forEach { it.replace(javaPsiFactory.createExpressionFromText("${it.getText()}()", null)) }
}
}
}
}
override fun startInWriteAction(): Boolean = false
override fun isApplicableTo(element: JetProperty): Boolean {
throw IllegalStateException("isApplicableTo(JetExpressionImpl, Editor) should be called instead")
}
override fun isApplicableTo(element: JetProperty, editor: Editor): Boolean {
val elementAtCaret = element.getContainingFile().findElementAt(editor.getCaretModel().getOffset())
if (!(element.getNameIdentifier()?.isAncestor(elementAtCaret) ?: false)) return false
return element.getDelegate() == null && !element.isVar() && !element.isLocal()
}
override fun applyTo(element: JetProperty, editor: Editor) {
val context = element.analyze()
val descriptor = context[BindingContext.DECLARATION_TO_DESCRIPTOR, element] as? CallableDescriptor ?: return
Convertor(element.getProject(), descriptor, context).run()
}
}
@@ -36,20 +36,21 @@ import org.jetbrains.kotlin.idea.JetBundle
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.psi.JetDeclaration
import java.util.HashSet
import com.intellij.usageView.UsageInfo
import org.jetbrains.kotlin.psi.JetNamedFunction
import org.jetbrains.kotlin.asJava.LightClassUtil
import com.intellij.psi.search.searches.OverridingMethodsSearch
import org.jetbrains.kotlin.asJava.KotlinLightMethod
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.JetFunctionDefinitionUsage
import com.intellij.refactoring.changeSignature.OverriderUsageInfo
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToDeclarationUtil
import org.jetbrains.kotlin.asJava.toLightMethods
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
import org.jetbrains.kotlin.psi.JetCallableDeclaration
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
import org.jetbrains.kotlin.psi.JetDeclarationWithBody
import org.jetbrains.kotlin.psi.JetExpression
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.psi.JetDeclaration
public abstract class CallableRefactoring<T: CallableDescriptor>(
val project: Project,
@@ -167,4 +168,31 @@ public abstract class CallableRefactoring<T: CallableDescriptor>(
}
}
}
}
fun getAffectedCallables(project: Project, descriptorsForChange: Collection<CallableDescriptor>): List<PsiElement> {
val baseCallables = descriptorsForChange.map { DescriptorToDeclarationUtil.getDeclaration(project, it) }.filterNotNull()
return baseCallables + baseCallables.flatMap { it.toLightMethods() }.flatMapTo(HashSet<PsiElement>()) { psiMethod ->
val overrides = OverridingMethodsSearch.search(psiMethod).findAll()
overrides.map { method -> method.namedUnwrappedElement ?: method}
}
}
fun DeclarationDescriptor.getContainingScope(bindingContext: BindingContext): JetScope? {
val containingDescriptor = getContainingDeclaration() ?: return null
return when (containingDescriptor) {
is ClassDescriptorWithResolutionScopes -> containingDescriptor.getScopeForInitializerResolution()
is FunctionDescriptor -> {
(DescriptorToSourceUtils.descriptorToDeclaration(containingDescriptor) as? JetDeclarationWithBody)?.let {
it.getBodyScope(bindingContext)
}
}
is PackageFragmentDescriptor -> containingDescriptor.getMemberScope()
else -> null
}
}
fun JetDeclarationWithBody.getBodyScope(bindingContext: BindingContext): JetScope? {
val expression = getBodyExpression()?.getChildren()?.firstOrNull { it is JetExpression } as JetExpression?
return expression?.let { bindingContext[BindingContext.RESOLUTION_SCOPE, it] }
}
@@ -35,7 +35,6 @@ import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl;
import org.jetbrains.kotlin.idea.caches.resolve.ResolvePackage;
import org.jetbrains.kotlin.idea.refactoring.RefactoringPackage;
import org.jetbrains.kotlin.idea.refactoring.changeSignature.usages.*;
@@ -210,9 +209,9 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
if (oldDescriptor instanceof ConstructorDescriptor && containingDeclaration instanceof ClassDescriptorWithResolutionScopes)
parametersScope = ((ClassDescriptorWithResolutionScopes) containingDeclaration).getScopeForInitializerResolution();
else if (function instanceof JetFunction)
parametersScope = getFunctionBodyScope((JetFunction) function, bindingContext);
parametersScope = RefactoringPackage.getBodyScope((JetFunction) function, bindingContext);
JetScope functionScope = getFunctionScope(bindingContext, containingDeclaration);
JetScope functionScope = RefactoringPackage.getContainingScope(oldDescriptor, bindingContext);
if (!ChangeSignaturePackage.getIsConstructor(changeInfo) && functionScope != null && !info.getNewName().isEmpty()) {
for (FunctionDescriptor conflict : functionScope.getFunctions(Name.identifier(info.getNewName()))) {
@@ -260,36 +259,6 @@ public class JetChangeSignatureUsageProcessor implements ChangeSignatureUsagePro
return result;
}
@Nullable
private static JetScope getFunctionScope(BindingContext bindingContext, DeclarationDescriptor containingDeclaration) {
if (containingDeclaration instanceof ClassDescriptorWithResolutionScopes)
return ((ClassDescriptorWithResolutionScopes) containingDeclaration).getScopeForInitializerResolution();
else if (containingDeclaration instanceof FunctionDescriptorImpl) {
PsiElement container = DescriptorToSourceUtils.descriptorToDeclaration(containingDeclaration);
if (container instanceof JetFunction)
return getFunctionBodyScope((JetFunction) container, bindingContext);
}
else if (containingDeclaration instanceof PackageFragmentDescriptor)
return ((PackageFragmentDescriptor) containingDeclaration).getMemberScope();
return null;
}
@Nullable
static JetScope getFunctionBodyScope(JetFunction element, BindingContext bindingContext) {
JetExpression body = element.getBodyExpression();
if (body != null) {
for (PsiElement child : body.getChildren()) {
if (child instanceof JetExpression)
return bindingContext.get(BindingContext.RESOLUTION_SCOPE, (JetExpression)child);
}
}
return null;
}
private static List<JetType> getFunctionParameterTypes(FunctionDescriptor descriptor) {
return ContainerUtil.map(descriptor.getValueParameters(), new Function<ValueParameterDescriptor, JetType>() {
@Override
@@ -74,6 +74,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import com.intellij.psi.PsiPackage
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.psi.psiUtil.parents
import com.intellij.refactoring.util.RefactoringUIUtil
fun <T: Any> PsiElement.getAndRemoveCopyableUserData(key: Key<T>): T? {
val data = getCopyableUserData(key)
@@ -181,6 +182,14 @@ public fun Project.checkConflictsInteractively(conflicts: MultiMap<PsiElement, S
onAccept()
}
public fun reportDeclarationConflict(
conflicts: MultiMap<PsiElement, String>,
declaration: PsiElement,
message: (renderedDeclaration: String) -> String
) {
conflicts.putValue(declaration, message(RefactoringUIUtil.getDescription(declaration, true).capitalize()))
}
public fun <T, E: PsiElement> getPsiElementPopup(
editor: Editor,
elements: List<T>,
@@ -0,0 +1 @@
org.jetbrains.kotlin.idea.intentions.ConvertFunctionToPropertyIntention
@@ -0,0 +1,15 @@
trait T {
fun bar()
}
class A(val n: Int) {
fun <caret>foo() = object : T {
override fun bar() {
}
}
}
fun test() {
val t = A(1).foo()
}
@@ -0,0 +1,16 @@
trait T {
fun bar()
}
class A(val n: Int) {
val foo: T
get() = object : T {
override fun bar() {
}
}
}
fun test() {
val t = A(1).foo
}
@@ -0,0 +1,9 @@
fun test() {
class X
class A(val n: Int) {
fun <caret>foo() = X()
}
val t = A(1).foo()
}
@@ -0,0 +1,10 @@
fun test() {
class X
class A(val n: Int) {
val foo: X
get() = X()
}
val t = A(1).foo
}
@@ -0,0 +1,7 @@
class A(val n: Int) {
fun <caret>foo() = n > 1
}
fun test() {
val t = A(1).foo()
}
@@ -0,0 +1,8 @@
class A(val n: Int) {
val foo: Boolean
get() = n > 1
}
fun test() {
val t = A(1).foo
}
@@ -0,0 +1,9 @@
class A(val n: Int) {
fun <caret>foo(): Boolean {
return n > 1
}
}
fun test() {
val t = A(1).foo()
}
@@ -0,0 +1,10 @@
class A(val n: Int) {
val foo: Boolean
get() {
return n > 1
}
}
fun test() {
val t = A(1).foo
}
@@ -0,0 +1,7 @@
// SHOULD_FAIL_WITH: Property foo already exists
class A(val n: Int) {
fun <caret>foo(): Boolean = n > 1
}
val A.foo: Int
get() = 1
@@ -0,0 +1,12 @@
import test.A;
class J extends A {
boolean getFoo() {
return true;
}
@Override
int foo() {
return 2;
}
}
@@ -0,0 +1,6 @@
// SHOULD_FAIL_WITH: Method J.getFoo() already exists
package test
open class A {
open fun <caret>foo(): Int = 1
}
@@ -0,0 +1,7 @@
class A(val n: Int) {
fun <caret>foo(): Boolean = n > 1
}
fun test() {
val t = A(1).foo()
}
@@ -0,0 +1,8 @@
class A(val n: Int) {
val foo: Boolean
get() = n > 1
}
fun test() {
val t = A(1).foo
}
@@ -0,0 +1,9 @@
// ERROR: Too many arguments for internal final fun foo(): kotlin.Boolean defined in A
// SHOULD_FAIL_WITH: Call with arguments will be skipped: foo(2)
class A(val n: Int) {
fun <caret>foo(): Boolean = n > 1
}
fun test() {
val t = A(1).foo(2)
}
@@ -0,0 +1,8 @@
// IS_APPLICABLE: false
class A(val n: Int) {
fun <caret>foo(k: Int): Boolean = n - k > 1
}
fun test() {
val t = A(1).foo(2)
}
@@ -0,0 +1,9 @@
// WITH_RUNTIME
// IS_APPLICABLE: false
class A(val n: Int) {
fun <caret>invoke(): Int = 1
}
fun test(a: A) {
val n = a()
}
@@ -0,0 +1,11 @@
// WITH_RUNTIME
// IS_APPLICABLE: false
class A(val n: Int) {
fun <caret>iterator(): Iterator<Int> = throw Exception("")
}
fun test() {
for (a in A(10)) {
}
}
@@ -0,0 +1,7 @@
import static test.TestPackage.foo;
class J {
void test() {
boolean b = foo();
}
}
@@ -0,0 +1,7 @@
import static test.TestPackage.getFoo;
class J {
void test() {
boolean b = getFoo();
}
}
@@ -0,0 +1,3 @@
package test
fun <caret>foo(): Boolean = true
@@ -0,0 +1,4 @@
package test
val foo: Boolean
get() = true
@@ -0,0 +1,6 @@
// IS_APPLICABLE: false
fun test(n: Int) {
fun <caret>foo(): Boolean = n > 1
val t = foo()
}
@@ -0,0 +1,9 @@
// WITH_RUNTIME
// IS_APPLICABLE: false
class A(val n: Int) {
fun <caret>foo() = throw Exception("foo")
}
fun test() {
A(1).foo()
}
@@ -0,0 +1,12 @@
// WITH_RUNTIME
package p
import p.foo
class A(val n: Int)
fun A.<caret>foo(): Boolean = n > 1
fun test() {
val t = A::foo
}
@@ -0,0 +1,13 @@
// WITH_RUNTIME
package p
import p.foo
class A(val n: Int)
val A.foo: Boolean
get() = n > 1
fun test() {
val t = A::foo
}
@@ -0,0 +1,19 @@
import test.*;
class JA extends A {
public JA() {
super(1);
}
@Override
boolean foo() {
return true;
}
}
class JTest {
void test() {
boolean x = new A(1).foo();
boolean y = new JA().foo();
}
}
@@ -0,0 +1,19 @@
import test.*;
class JA extends A {
public JA() {
super(1);
}
@Override
boolean getFoo() {
return true;
}
}
class JTest {
void test() {
boolean x = new A(1).getFoo();
boolean y = new JA().getFoo();
}
}
@@ -0,0 +1,18 @@
package test
trait T {
fun foo(): Boolean
}
open class A(val n: Int): T {
override fun foo(): Boolean = n > 1
}
class B: A(1) {
override fun <caret>foo(): Boolean = true
}
fun test() {
val a = A(1).foo()
val b = B().foo()
}
@@ -0,0 +1,20 @@
package test
trait T {
val foo: Boolean
}
open class A(val n: Int): T {
override val foo: Boolean
get() = n > 1
}
class B: A(1) {
override val foo: Boolean
get() = true
}
fun test() {
val a = A(1).foo
val b = B().foo
}
@@ -0,0 +1,8 @@
// SHOULD_FAIL_WITH: Type arguments will be lost after conversion: foo&lt;Double&gt;()
class A(val n: Int) {
fun <caret>foo<T>(): Boolean = n > 1
}
fun test() {
val t = A(1).foo<Double>()
}
@@ -0,0 +1,9 @@
// WITH_RUNTIME
// IS_APPLICABLE: false
class A(val n: Int) {
fun <caret>minus(): A = A(-n)
}
fun test() {
val t = -A(1)
}
@@ -0,0 +1,15 @@
// WITH_RUNTIME
annotation class X(val s: String)
class A(val n: Int) {
val t = 1
internal X("1") fun <T : Number> T.<caret>foo(): Boolean = toInt() - n > 1
val u = 2
}
fun test() {
val t = with(A(1)) {
2.5.foo()
}
}
@@ -0,0 +1,16 @@
// WITH_RUNTIME
annotation class X(val s: String)
class A(val n: Int) {
val t = 1
internal X("1") val <T : Number> T.foo: Boolean
get() = toInt() - n > 1
val u = 2
}
fun test() {
val t = with(A(1)) {
2.5.foo
}
}
@@ -0,0 +1,11 @@
// WITH_RUNTIME
// IS_APPLICABLE: false
class A(val n: Int) {
fun <caret>foo() {
println(n)
}
}
fun test() {
A(1).foo()
}
@@ -0,0 +1 @@
org.jetbrains.kotlin.idea.intentions.ConvertPropertyToFunctionIntention
@@ -0,0 +1,5 @@
class G {
void test() {
test.TestPackage.getBar();
}
}
@@ -0,0 +1,5 @@
class G {
void test() {
test.TestPackage.bar();
}
}
@@ -0,0 +1,4 @@
package test
val <caret>bar: Int
get() = 1
@@ -0,0 +1,3 @@
package test
fun bar(): Int = 1
@@ -0,0 +1,10 @@
class A(val n: Int) {
val <caret>foo: Boolean
get() {
return n > 1
}
}
fun test() {
val t = A(1).foo
}
@@ -0,0 +1,9 @@
class A(val n: Int) {
fun foo(): Boolean {
return n > 1
}
}
fun test() {
val t = A(1).foo()
}
@@ -0,0 +1,11 @@
// WITH_RUNTIME
// IS_APPLICABLE: false
import kotlin.properties.Delegates
class A(val n: Int) {
val <caret>foo: Boolean by Delegates.lazy { n > 1 }
}
fun test() {
val t = A(1).foo
}
@@ -0,0 +1,6 @@
// SHOULD_FAIL_WITH: Function foo already exists
class A(val n: Int) {
val <caret>foo: Boolean = n > 1
}
fun A.foo() = 1
@@ -0,0 +1,12 @@
import test.A;
class J extends A {
boolean foo() {
return true;
}
@Override
int getFoo() {
return 2;
}
}
@@ -0,0 +1,6 @@
// SHOULD_FAIL_WITH: Method J.foo() already exists
package test
open class A {
open val <caret>foo: Int = 1
}
@@ -0,0 +1,8 @@
class A(val n: Int) {
val <caret>foo: Boolean
get() = n > 1
}
fun test() {
val t = A(1).foo
}
@@ -0,0 +1,7 @@
class A(val n: Int) {
fun foo(): Boolean = n > 1
}
fun test() {
val t = A(1).foo()
}
@@ -0,0 +1,7 @@
class A(val n: Int) {
val <caret>foo: Boolean = n > 1
}
fun test() {
val t = A(1).foo
}
@@ -0,0 +1,7 @@
class A(val n: Int) {
fun foo(): Boolean = n > 1
}
fun test() {
val t = A(1).foo()
}
@@ -0,0 +1,9 @@
import test.O;
import static test.O.foo;
class J {
void test() {
int n = O.foo;
int m = foo;
}
}
@@ -0,0 +1,9 @@
import test.O;
import static test.O.foo;
class J {
void test() {
int n = O.foo();
int m = foo();
}
}
@@ -0,0 +1,5 @@
package test
object O {
val <caret>foo: Int = 1
}
@@ -0,0 +1,5 @@
package test
object O {
fun foo(): Int = 1
}
@@ -0,0 +1,7 @@
import static test.TestPackage.getFoo;
class J {
void test() {
boolean b = getFoo();
}
}
@@ -0,0 +1,7 @@
import static test.TestPackage.foo;
class J {
void test() {
boolean b = foo();
}
}
@@ -0,0 +1,4 @@
package test
val <caret>foo: Boolean
get() = true
@@ -0,0 +1,3 @@
package test
fun foo(): Boolean = true
@@ -0,0 +1,13 @@
// WITH_RUNTIME
package p
import p.foo
class A(val n: Int)
val A.<caret>foo: Boolean
get() = n > 1
fun test() {
val t = A::foo
}
@@ -0,0 +1,12 @@
// WITH_RUNTIME
package p
import p.foo
class A(val n: Int)
fun A.foo(): Boolean = n > 1
fun test() {
val t = A::foo
}
@@ -0,0 +1,19 @@
import test.*;
class JA extends A {
public JA() {
super(1);
}
@Override
boolean getFoo() {
return true;
}
}
class JTest {
void test() {
boolean x = new A(1).getFoo();
boolean y = new JA().getFoo();
}
}
@@ -0,0 +1,19 @@
import test.*;
class JA extends A {
public JA() {
super(1);
}
@Override
boolean foo() {
return true;
}
}
class JTest {
void test() {
boolean x = new A(1).foo();
boolean y = new JA().foo();
}
}
@@ -0,0 +1,20 @@
package test
trait T {
val foo: Boolean
}
open class A(val n: Int): T {
override val foo: Boolean
get() = n > 1
}
class B: A(1) {
override val <caret>foo: Boolean
get() = true
}
fun test() {
val a = A(1).foo
val b = B().foo
}
@@ -0,0 +1,18 @@
package test
trait T {
fun foo(): Boolean
}
open class A(val n: Int): T {
override fun foo(): Boolean = n > 1
}
class B: A(1) {
override fun foo(): Boolean = true
}
fun test() {
val a = A(1).foo()
val b = B().foo()
}
@@ -0,0 +1,5 @@
class G {
void test() {
test.TestPackage.bar;
}
}
@@ -0,0 +1,5 @@
// SHOULD_FAIL_WITH: Can't replace foreign reference with call expression: test.TestPackage.bar
package test
val <caret>bar: Int
get() = 1
@@ -0,0 +1,14 @@
// WITH_RUNTIME
annotation class X(val s: String)
class A(val n: Int) {
internal X("1") val <T : Number> T.<caret>foo: Boolean
get() = toInt() - n > 1
}
fun test() {
val t = with(A(1)) {
2.5.foo
}
}
@@ -0,0 +1,13 @@
// WITH_RUNTIME
annotation class X(val s: String)
class A(val n: Int) {
internal X("1") fun <T : Number> T.foo(): Boolean = toInt() - n > 1
}
fun test() {
val t = with(A(1)) {
2.5.foo()
}
}
@@ -0,0 +1,10 @@
// IS_APPLICABLE: false
class A(var n: Int) {
var <caret>foo: Int
get() = n + 1
set(value: Int) { n = value - 1 }
}
fun test() {
val t = A(1).foo
}
@@ -1,4 +1,5 @@
// "Specify type explicitly" "false"
// ACTION: Convert property to function
// ERROR: Public or protected member should have specified type
// ERROR: Unresolved reference: foo
@@ -18,23 +18,34 @@ package org.jetbrains.kotlin.idea.intentions;
import com.google.common.collect.Lists;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.ide.startup.impl.StartupManagerImpl;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.testFramework.LightCodeInsightTestCase;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiFile;
import com.intellij.refactoring.BaseRefactoringProcessor;
import com.intellij.util.PathUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.Convertor;
import kotlin.Function0;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.DirectiveBasedActionUtils;
import org.jetbrains.kotlin.idea.KotlinCodeInsightTestCase;
import org.jetbrains.kotlin.idea.PluginTestCaseBase;
import org.jetbrains.kotlin.idea.util.application.ApplicationPackage;
import org.jetbrains.kotlin.psi.JetFile;
import org.jetbrains.kotlin.test.ConfigLibraryUtil;
import org.jetbrains.kotlin.test.InTextDirectivesUtils;
import org.junit.Assert;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public abstract class AbstractIntentionTest extends LightCodeInsightTestCase {
public abstract class AbstractIntentionTest extends KotlinCodeInsightTestCase {
private static IntentionAction createIntention(File testDataFile) throws Exception {
List<File> candidateFiles = Lists.newArrayList();
@@ -60,12 +71,45 @@ public abstract class AbstractIntentionTest extends LightCodeInsightTestCase {
return (IntentionAction) Class.forName(className).newInstance();
}
private static final String[] EXTENSIONS = { ".kt", ".java", ".groovy" };
protected void doTest(@NotNull String path) throws Exception {
IntentionAction intentionAction = createIntention(new File(path));
File mainFile = new File(path);
String mainFileName = FileUtil.getNameWithoutExtension(mainFile);
IntentionAction intentionAction = createIntention(mainFile);
List<String> sourceFilePaths = new ArrayList<String>();
File parentDir = mainFile.getParentFile();
extraFileLoop:
//noinspection ForLoopThatDoesntUseLoopVariable
for (int i = 1; true; i++) {
for (String extension : EXTENSIONS) {
File extraFile = new File(parentDir, mainFileName + "." + i + extension);
if (extraFile.exists()) {
sourceFilePaths.add(extraFile.getPath());
continue extraFileLoop;
}
}
break;
}
sourceFilePaths.add(path);
configureByFile(path);
Map<String, PsiFile> pathToFile = ContainerUtil.newMapFromKeys(
sourceFilePaths.iterator(),
new Convertor<String, PsiFile>() {
@Override
public PsiFile convert(String path) {
try {
configureByFile(path);
}
catch (Exception e) {
throw new RuntimeException(e);
}
return myFile;
}
}
);
String fileText = FileUtil.loadFile(new File(path), true);
String fileText = FileUtil.loadFile(mainFile, true);
String minJavaVersion = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// MIN_JAVA_VERSION: ");
if (minJavaVersion != null && !SystemInfo.isJavaVersionAtLeast(minJavaVersion)) return;
@@ -79,16 +123,16 @@ public abstract class AbstractIntentionTest extends LightCodeInsightTestCase {
DirectiveBasedActionUtils.checkForUnexpectedErrors((JetFile) getFile());
doTestFor(path, intentionAction, fileText);
doTestFor(pathToFile, intentionAction, fileText);
}
finally {
if (isWithRuntime) {
ConfigLibraryUtil.unConfigureKotlinRuntime(getModule(), getProjectJDK());
ConfigLibraryUtil.unConfigureKotlinRuntime(getModule(), getTestProjectJdk());
}
}
}
private void doTestFor(String path, IntentionAction intentionAction, String fileText) {
private void doTestFor(Map<String, PsiFile> pathToFile, final IntentionAction intentionAction, String fileText) throws Exception {
String isApplicableString = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// IS_APPLICABLE: ");
boolean isApplicableExpected = isApplicableString == null || isApplicableString.equals("true");
@@ -106,11 +150,26 @@ public abstract class AbstractIntentionTest extends LightCodeInsightTestCase {
try {
if (isApplicableExpected) {
intentionAction.invoke(getProject(), getEditor(), getFile());
ApplicationPackage.executeWriteCommand(
getProject(),
intentionAction.getText(),
new Function0<Object>() {
@Override
public Object invoke() {
intentionAction.invoke(getProject(), getEditor(), getFile());
return null;
}
}
);
// Don't bother checking if it should have failed.
if (shouldFailString == null) {
String canonicalPathToExpectedFile = PathUtil.getCanonicalPath(path + ".after");
checkResultByFile(canonicalPathToExpectedFile);
for (Map.Entry<String, PsiFile> entry: pathToFile.entrySet()) {
//noinspection AssignmentToStaticFieldFromInstanceMethod
myFile = entry.getValue();
String canonicalPathToExpectedFile = PathUtil.getCanonicalPath(entry.getKey() + ".after");
checkResultByFile(canonicalPathToExpectedFile);
}
}
}
assertNull("Expected test to fail.", shouldFailString);
@@ -118,6 +177,15 @@ public abstract class AbstractIntentionTest extends LightCodeInsightTestCase {
catch (IntentionTestException e) {
assertEquals("Failure message mismatch.", shouldFailString, e.getMessage());
}
catch (BaseRefactoringProcessor.ConflictsInTestsException e) {
assertEquals("Failure message mismatch.", shouldFailString, StringUtil.join(e.getMessages(), ", "));
}
}
@Override
protected void setUp() throws Exception {
super.setUp();
((StartupManagerImpl) StartupManager.getInstance(getProject())).runPostStartupActivities();
}
@NotNull
@@ -30,7 +30,7 @@ import java.util.regex.Pattern;
@SuppressWarnings("all")
@TestMetadata("idea/testData/intentions")
@TestDataPath("$PROJECT_ROOT")
@InnerTestClasses({IntentionTestGenerated.AddBraces.class, IntentionTestGenerated.AttributeCallReplacements.class, IntentionTestGenerated.Branched.class, IntentionTestGenerated.ConvertAssertToIf.class, IntentionTestGenerated.ConvertIfToAssert.class, IntentionTestGenerated.ConvertNegatedBooleanSequence.class, IntentionTestGenerated.ConvertNegatedExpressionWithDemorgansLaw.class, IntentionTestGenerated.ConvertToBlockBody.class, IntentionTestGenerated.ConvertToConcatenatedStringIntention.class, IntentionTestGenerated.ConvertToExpressionBody.class, IntentionTestGenerated.ConvertToForEachFunctionCall.class, IntentionTestGenerated.ConvertToForEachLoop.class, IntentionTestGenerated.ConvertToStringTemplateIntention.class, IntentionTestGenerated.Declarations.class, IntentionTestGenerated.InsertCurlyBracesToTemplate.class, IntentionTestGenerated.InsertExplicitTypeArguments.class, IntentionTestGenerated.InvertIfCondition.class, IntentionTestGenerated.MakeTypeExplicitInLambda.class, IntentionTestGenerated.MakeTypeImplicitInLambda.class, IntentionTestGenerated.MoveLambdaInsideParentheses.class, IntentionTestGenerated.MoveLambdaOutsideParentheses.class, IntentionTestGenerated.OperatorToFunction.class, IntentionTestGenerated.ReconstructedType.class, IntentionTestGenerated.RemoveBraces.class, IntentionTestGenerated.RemoveCurlyBracesFromTemplate.class, IntentionTestGenerated.RemoveExplicitTypeArguments.class, IntentionTestGenerated.RemoveUnnecessaryParentheses.class, IntentionTestGenerated.ReplaceExplicitFunctionLiteralParamWithIt.class, IntentionTestGenerated.ReplaceItWithExplicitFunctionLiteralParam.class, IntentionTestGenerated.ReplaceWithDotQualifiedMethodCall.class, IntentionTestGenerated.ReplaceWithInfixFunctionCall.class, IntentionTestGenerated.ReplaceWithOperatorAssign.class, IntentionTestGenerated.ReplaceWithTraditionalAssignment.class, IntentionTestGenerated.SimplifyBooleanWithConstants.class, IntentionTestGenerated.SimplifyNegatedBinaryExpressionIntention.class, IntentionTestGenerated.SpecifyType.class, IntentionTestGenerated.SplitIf.class, IntentionTestGenerated.SwapBinaryExpression.class})
@InnerTestClasses({IntentionTestGenerated.AddBraces.class, IntentionTestGenerated.AttributeCallReplacements.class, IntentionTestGenerated.Branched.class, IntentionTestGenerated.ConvertAssertToIf.class, IntentionTestGenerated.ConvertFunctionToProperty.class, IntentionTestGenerated.ConvertIfToAssert.class, IntentionTestGenerated.ConvertNegatedBooleanSequence.class, IntentionTestGenerated.ConvertNegatedExpressionWithDemorgansLaw.class, IntentionTestGenerated.ConvertPropertyToFunction.class, IntentionTestGenerated.ConvertToBlockBody.class, IntentionTestGenerated.ConvertToConcatenatedStringIntention.class, IntentionTestGenerated.ConvertToExpressionBody.class, IntentionTestGenerated.ConvertToForEachFunctionCall.class, IntentionTestGenerated.ConvertToForEachLoop.class, IntentionTestGenerated.ConvertToStringTemplateIntention.class, IntentionTestGenerated.Declarations.class, IntentionTestGenerated.InsertCurlyBracesToTemplate.class, IntentionTestGenerated.InsertExplicitTypeArguments.class, IntentionTestGenerated.InvertIfCondition.class, IntentionTestGenerated.MakeTypeExplicitInLambda.class, IntentionTestGenerated.MakeTypeImplicitInLambda.class, IntentionTestGenerated.MoveLambdaInsideParentheses.class, IntentionTestGenerated.MoveLambdaOutsideParentheses.class, IntentionTestGenerated.OperatorToFunction.class, IntentionTestGenerated.ReconstructedType.class, IntentionTestGenerated.RemoveBraces.class, IntentionTestGenerated.RemoveCurlyBracesFromTemplate.class, IntentionTestGenerated.RemoveExplicitTypeArguments.class, IntentionTestGenerated.RemoveUnnecessaryParentheses.class, IntentionTestGenerated.ReplaceExplicitFunctionLiteralParamWithIt.class, IntentionTestGenerated.ReplaceItWithExplicitFunctionLiteralParam.class, IntentionTestGenerated.ReplaceWithDotQualifiedMethodCall.class, IntentionTestGenerated.ReplaceWithInfixFunctionCall.class, IntentionTestGenerated.ReplaceWithOperatorAssign.class, IntentionTestGenerated.ReplaceWithTraditionalAssignment.class, IntentionTestGenerated.SimplifyBooleanWithConstants.class, IntentionTestGenerated.SimplifyNegatedBinaryExpressionIntention.class, IntentionTestGenerated.SpecifyType.class, IntentionTestGenerated.SplitIf.class, IntentionTestGenerated.SwapBinaryExpression.class})
@RunWith(JUnit3RunnerWithInners.class)
public class IntentionTestGenerated extends AbstractIntentionTest {
public void testAllFilesPresentInIntentions() throws Exception {
@@ -2551,6 +2551,135 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
}
}
@TestMetadata("idea/testData/intentions/convertFunctionToProperty")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ConvertFunctionToProperty extends AbstractIntentionTest {
@TestMetadata("addExplicitAnonymousType.kt")
public void testAddExplicitAnonymousType() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/addExplicitAnonymousType.kt");
doTest(fileName);
}
@TestMetadata("addExplicitLocalType.kt")
public void testAddExplicitLocalType() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/addExplicitLocalType.kt");
doTest(fileName);
}
@TestMetadata("addExplicitType.kt")
public void testAddExplicitType() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/addExplicitType.kt");
doTest(fileName);
}
public void testAllFilesPresentInConvertFunctionToProperty() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/convertFunctionToProperty"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("blockBody.kt")
public void testBlockBody() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/blockBody.kt");
doTest(fileName);
}
@TestMetadata("existingPropertyConflict.kt")
public void testExistingPropertyConflict() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/existingPropertyConflict.kt");
doTest(fileName);
}
@TestMetadata("existingPropertyJavaConflict.kt")
public void testExistingPropertyJavaConflict() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/existingPropertyJavaConflict.kt");
doTest(fileName);
}
@TestMetadata("expressionBody.kt")
public void testExpressionBody() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/expressionBody.kt");
doTest(fileName);
}
@TestMetadata("extraArgumentsConflict.kt")
public void testExtraArgumentsConflict() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/extraArgumentsConflict.kt");
doTest(fileName);
}
@TestMetadata("funWithParameters.kt")
public void testFunWithParameters() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/funWithParameters.kt");
doTest(fileName);
}
@TestMetadata("invoke.kt")
public void testInvoke() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/invoke.kt");
doTest(fileName);
}
@TestMetadata("iterator.kt")
public void testIterator() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/iterator.kt");
doTest(fileName);
}
@TestMetadata("javaUsages.kt")
public void testJavaUsages() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/javaUsages.kt");
doTest(fileName);
}
@TestMetadata("localFun.kt")
public void testLocalFun() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/localFun.kt");
doTest(fileName);
}
@TestMetadata("nothingFun.kt")
public void testNothingFun() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/nothingFun.kt");
doTest(fileName);
}
@TestMetadata("otherRefs.kt")
public void testOtherRefs() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/otherRefs.kt");
doTest(fileName);
}
@TestMetadata("overrides.kt")
public void testOverrides() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/overrides.kt");
doTest(fileName);
}
@TestMetadata("typeArgumentsConflict.kt")
public void testTypeArgumentsConflict() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/typeArgumentsConflict.kt");
doTest(fileName);
}
@TestMetadata("unaryOp.kt")
public void testUnaryOp() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/unaryOp.kt");
doTest(fileName);
}
@TestMetadata("unchangedElements.kt")
public void testUnchangedElements() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/unchangedElements.kt");
doTest(fileName);
}
@TestMetadata("unitFun.kt")
public void testUnitFun() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertFunctionToProperty/unitFun.kt");
doTest(fileName);
}
}
@TestMetadata("idea/testData/intentions/convertIfToAssert")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -2800,6 +2929,99 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
}
}
@TestMetadata("idea/testData/intentions/convertPropertyToFunction")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ConvertPropertyToFunction extends AbstractIntentionTest {
@TestMetadata("accessorCallGroovy.kt")
public void testAccessorCallGroovy() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertPropertyToFunction/accessorCallGroovy.kt");
doTest(fileName);
}
public void testAllFilesPresentInConvertPropertyToFunction() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/convertPropertyToFunction"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("blockBody.kt")
public void testBlockBody() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertPropertyToFunction/blockBody.kt");
doTest(fileName);
}
@TestMetadata("delegatingProperty.kt")
public void testDelegatingProperty() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertPropertyToFunction/delegatingProperty.kt");
doTest(fileName);
}
@TestMetadata("existingFunConflict.kt")
public void testExistingFunConflict() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertPropertyToFunction/existingFunConflict.kt");
doTest(fileName);
}
@TestMetadata("existingFunJavaConflict.kt")
public void testExistingFunJavaConflict() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertPropertyToFunction/existingFunJavaConflict.kt");
doTest(fileName);
}
@TestMetadata("expressionBody.kt")
public void testExpressionBody() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertPropertyToFunction/expressionBody.kt");
doTest(fileName);
}
@TestMetadata("initializer.kt")
public void testInitializer() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertPropertyToFunction/initializer.kt");
doTest(fileName);
}
@TestMetadata("javaUsageAsField.kt")
public void testJavaUsageAsField() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertPropertyToFunction/javaUsageAsField.kt");
doTest(fileName);
}
@TestMetadata("javaUsages.kt")
public void testJavaUsages() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertPropertyToFunction/javaUsages.kt");
doTest(fileName);
}
@TestMetadata("otherRefs.kt")
public void testOtherRefs() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertPropertyToFunction/otherRefs.kt");
doTest(fileName);
}
@TestMetadata("overrides.kt")
public void testOverrides() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertPropertyToFunction/overrides.kt");
doTest(fileName);
}
@TestMetadata("propertyCallGroovy.kt")
public void testPropertyCallGroovy() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertPropertyToFunction/propertyCallGroovy.kt");
doTest(fileName);
}
@TestMetadata("unchangedElements.kt")
public void testUnchangedElements() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertPropertyToFunction/unchangedElements.kt");
doTest(fileName);
}
@TestMetadata("var.kt")
public void testVar() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/convertPropertyToFunction/var.kt");
doTest(fileName);
}
}
@TestMetadata("idea/testData/intentions/convertToBlockBody")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)