From 10f7d6d7ddb21e821e33796c65cc543be3f4ea60 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Mon, 31 Aug 2015 19:08:01 +0300 Subject: [PATCH] Inspection (and quickfix) for extension propeties conflicting with synthetic ones --- .../idea/test/DirectiveBasedActionUtils.kt | 4 +- .../ConflictingExtensionProperty.html | 5 + idea/src/META-INF/plugin.xml | 7 + .../ConflictingExtensionPropertyInspection.kt | 195 ++++++++++++++++++ .../conflictingExtensionProperty/File.kt | 16 ++ .../inspectionData/expected.xml | 28 +++ .../inspectionData/inspections.test | 1 + .../javaDeprecated.before.Main.kt | 1 - .../deleteRedundantExtension/.inspection | 1 + .../deleteRedundantExtension/explicitThis.kt | 7 + .../explicitThis.kt.after | 2 + .../memberExtension.kt | 7 + .../memberExtension.kt.after | 5 + .../removeImports.after.JustImport.kt | 4 + .../removeImports.after.StarImport.kt | 8 + .../removeImports.after.Usages.kt | 7 + .../removeImports.after.kt | 6 + .../removeImports.before.JustImport.kt | 6 + .../removeImports.before.Main.kt | 9 + .../removeImports.before.StarImport.kt | 8 + .../removeImports.before.Usages.kt | 8 + .../removeImportsOverloads.after.Usages.kt | 9 + .../removeImportsOverloads.after.kt | 9 + .../removeImportsOverloads.before.Main.kt | 12 ++ .../removeImportsOverloads.before.Usages.kt | 9 + .../returnInGetter.kt | 5 + .../returnInGetter.kt.after | 3 + .../deleteRedundantExtension/simple.kt | 5 + .../deleteRedundantExtension/simple.kt.after | 3 + .../valInsteadOfVar.kt | 4 + .../valInsteadOfVar.kt.after | 2 + .../varInsteadOfVal.kt | 6 + .../deleteRedundantExtension/withSetter.kt | 7 + .../withSetter.kt.after | 2 + .../wrongExplicitThis.kt | 7 + .../wrongExplicitThis2.kt | 9 + .../deleteRedundantExtension/wrongGetter.kt | 7 + .../deleteRedundantExtension/wrongGetter2.kt | 6 + .../deleteRedundantExtension/wrongSetter.kt | 8 + .../JetInspectionTestGenerated.java | 6 + .../AbstractQuickFixMultiFileTest.java | 33 +++ .../idea/quickfix/AbstractQuickFixTest.java | 16 +- .../QuickFixMultiFileTestGenerated.java | 21 ++ .../idea/quickfix/QuickFixTestGenerated.java | 81 ++++++++ .../kotlin/idea/quickfix/quickfixTestUtils.kt | 31 +++ 45 files changed, 620 insertions(+), 16 deletions(-) create mode 100644 idea/resources/inspectionDescriptions/ConflictingExtensionProperty.html create mode 100644 idea/src/org/jetbrains/kotlin/idea/inspections/ConflictingExtensionPropertyInspection.kt create mode 100644 idea/testData/inspections/conflictingExtensionProperty/File.kt create mode 100644 idea/testData/inspections/conflictingExtensionProperty/inspectionData/expected.xml create mode 100644 idea/testData/inspections/conflictingExtensionProperty/inspectionData/inspections.test create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/.inspection create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/explicitThis.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/explicitThis.kt.after create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/memberExtension.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/memberExtension.kt.after create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.after.JustImport.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.after.StarImport.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.after.Usages.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.after.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.before.JustImport.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.before.Main.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.before.StarImport.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.before.Usages.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/removeImportsOverloads.after.Usages.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/removeImportsOverloads.after.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/removeImportsOverloads.before.Main.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/removeImportsOverloads.before.Usages.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/returnInGetter.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/returnInGetter.kt.after create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/simple.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/simple.kt.after create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/valInsteadOfVar.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/valInsteadOfVar.kt.after create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/varInsteadOfVal.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/withSetter.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/withSetter.kt.after create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/wrongExplicitThis.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/wrongExplicitThis2.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/wrongGetter.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/wrongGetter2.kt create mode 100644 idea/testData/quickfix/migration/deleteRedundantExtension/wrongSetter.kt create mode 100644 idea/tests/org/jetbrains/kotlin/idea/quickfix/quickfixTestUtils.kt diff --git a/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/DirectiveBasedActionUtils.kt b/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/DirectiveBasedActionUtils.kt index 75d7cbae09a..c6ba21f6025 100644 --- a/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/DirectiveBasedActionUtils.kt +++ b/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/DirectiveBasedActionUtils.kt @@ -68,6 +68,8 @@ public object DirectiveBasedActionUtils { "Edit intention settings", "Edit inspection profile setting", "Inject language or reference", - "Suppress '" + "Suppress '", + "Run inspection on", + "Inspection '" ) } diff --git a/idea/resources/inspectionDescriptions/ConflictingExtensionProperty.html b/idea/resources/inspectionDescriptions/ConflictingExtensionProperty.html new file mode 100644 index 00000000000..1cb77ded0a8 --- /dev/null +++ b/idea/resources/inspectionDescriptions/ConflictingExtensionProperty.html @@ -0,0 +1,5 @@ + + +This inspection reports extension properties that conflict with synthetic ones automatically produced from Java get/set-methods and that should be either removed or renamed to avoid breaking code by future changes in the compiler. + + diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 81963e66ff2..221ac8b7412 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -1138,6 +1138,13 @@ level="WARNING" /> + + diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/ConflictingExtensionPropertyInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/ConflictingExtensionPropertyInspection.kt new file mode 100644 index 00000000000..d73b0fd5663 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/ConflictingExtensionPropertyInspection.kt @@ -0,0 +1,195 @@ +/* + * 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.inspections + +import com.intellij.codeInspection.* +import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.progress.ProgressIndicator +import com.intellij.openapi.progress.ProgressManager +import com.intellij.openapi.progress.Task +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiElementVisitor +import com.intellij.psi.search.GlobalSearchScope +import com.intellij.psi.search.searches.ReferencesSearch +import com.intellij.util.ui.UIUtil +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.analyze +import org.jetbrains.kotlin.idea.caches.resolve.getFileTopLevelScope +import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor +import org.jetbrains.kotlin.idea.core.targetDescriptors +import org.jetbrains.kotlin.idea.imports.importableFqName +import org.jetbrains.kotlin.idea.quickfix.JetIntentionAction +import org.jetbrains.kotlin.idea.references.JetSimpleNameReference +import org.jetbrains.kotlin.idea.stubindex.JetSourceFilterScope +import org.jetbrains.kotlin.idea.util.application.executeWriteCommand +import org.jetbrains.kotlin.idea.util.application.runReadAction +import org.jetbrains.kotlin.incremental.components.NoLookupLocation +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.psi.* +import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType +import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall +import org.jetbrains.kotlin.resolve.scopes.FileScope +import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull + +public class ConflictingExtensionPropertyInspection : AbstractKotlinInspection(), CleanupLocalInspectionTool { + override fun buildVisitor(holder: ProblemsHolder, isOnTheFly: Boolean, session: LocalInspectionToolSession): PsiElementVisitor { + val file = session.file as? JetFile ?: return PsiElementVisitor.EMPTY_VISITOR + val fileScope = file.getResolutionFacade().getFileTopLevelScope(file) + + return object : JetVisitorVoid() { + override fun visitProperty(property: JetProperty) { + super.visitProperty(property) + + if (property.receiverTypeReference != null) { + val nameElement = property.nameIdentifier ?: return + val conflictingExtension = conflictingSyntheticExtension(property.resolveToDescriptor() as PropertyDescriptor, fileScope) + if (conflictingExtension != null) { + val problemDescriptor = holder.manager.createProblemDescriptor( + nameElement, + //TODO: review message + "This property conflicts with synthetic extension and should be removed to avoid breaking code by future changes in the compiler", + createQuickFix(property, conflictingExtension), + ProblemHighlightType.GENERIC_ERROR_OR_WARNING, + true + ) + holder.registerProblem(problemDescriptor) + } + } + } + } + } + + private fun conflictingSyntheticExtension(descriptor: PropertyDescriptor, fileScope: FileScope): SyntheticJavaPropertyDescriptor? { + val extensionReceiverType = descriptor.extensionReceiverParameter?.type ?: return null + return fileScope + .getSyntheticExtensionProperties(listOf(extensionReceiverType), descriptor.name, NoLookupLocation.FROM_IDE) + .firstIsInstanceOrNull() + } + + private fun createQuickFix(declaration: JetProperty, syntheticProperty: SyntheticJavaPropertyDescriptor): LocalQuickFix? { + val getter = declaration.getter ?: return null + val setter = declaration.setter + + if (!checkGetterBodyIsGetMethodCall(getter, syntheticProperty.getMethod)) return null + + if (setter != null) { + val setMethod = syntheticProperty.setMethod ?: return null // synthetic property is val but our property is var + if (!checkSetterBodyIsSetMethodCall(setter, setMethod)) return null + } + + return IntentionWrapper(DeleteRedundantExtensionAction(declaration), declaration.containingFile) + } + + private fun checkGetterBodyIsGetMethodCall(getter: JetPropertyAccessor, getMethod: FunctionDescriptor): Boolean { + if (getter.hasBlockBody()) { + val statement = (getter.bodyExpression as? JetBlockExpression)?.statements?.singleOrNull() ?: return false + return (statement as? JetReturnExpression)?.returnedExpression.isGetMethodCall(getMethod) + } + else { + return getter.bodyExpression.isGetMethodCall(getMethod) + } + } + + private fun checkSetterBodyIsSetMethodCall(setter: JetPropertyAccessor, setMethod: FunctionDescriptor): Boolean { + val valueParameterName = setter.valueParameters.singleOrNull()?.nameAsName ?: return false + if (!setter.hasBlockBody()) return false + val statement = (setter.bodyExpression as? JetBlockExpression)?.statements?.singleOrNull() ?: return false + return statement.isSetMethodCall(setMethod, valueParameterName) + } + + private fun JetExpression?.isGetMethodCall(getMethod: FunctionDescriptor): Boolean { + when (this) { + is JetCallExpression -> { + val resolvedCall = getResolvedCall(analyze()) + return resolvedCall != null && resolvedCall.status.isSuccess && resolvedCall.resultingDescriptor.original == getMethod.original + } + + is JetQualifiedExpression -> { + val receiver = receiverExpression + return receiver is JetThisExpression && receiver.labelQualifier == null && selectorExpression.isGetMethodCall(getMethod) + } + + else -> return false + } + } + + private fun JetExpression?.isSetMethodCall(setMethod: FunctionDescriptor, valueParameterName: Name): Boolean { + when (this) { + is JetCallExpression -> { + if ((valueArguments.singleOrNull()?.getArgumentExpression() as? JetSimpleNameExpression)?.getReferencedNameAsName() != valueParameterName) return false + val resolvedCall = getResolvedCall(analyze()) + return resolvedCall != null && resolvedCall.status.isSuccess && resolvedCall.resultingDescriptor.original == setMethod.original + } + + is JetQualifiedExpression -> { + val receiver = receiverExpression + return receiver is JetThisExpression && receiver.labelQualifier == null && selectorExpression.isSetMethodCall(setMethod, valueParameterName) + } + + else -> return false + } + } + + private class DeleteRedundantExtensionAction(property: JetProperty) : JetIntentionAction(property) { + private val LOG = Logger.getInstance(DeleteRedundantExtensionAction::class.java); + + override fun getFamilyName() = "Delete redundant extension property" + override fun getText() = familyName + + override fun startInWriteAction() = false + + override fun invoke(project: Project, editor: Editor?, file: JetFile) { + val declaration = element + val fqName = declaration.resolveToDescriptor().importableFqName + if (fqName != null) { + ProgressManager.getInstance().run( + object : Task.Modal(project, "Searching for imports to delete", true) { + override fun run(indicator: ProgressIndicator) { + val importsToDelete = runReadAction { + val searchScope = JetSourceFilterScope.kotlinSources(GlobalSearchScope.projectScope(project), project) + ReferencesSearch.search(declaration, searchScope) + .filterIsInstance() + .map { ref -> ref.expression.getStrictParentOfType() } + .filterNotNull() + .filter { import -> !import.isAllUnder && import.targetDescriptors().size() == 1 } + } + UIUtil.invokeLaterIfNeeded { + project.executeWriteCommand(text) { + importsToDelete.forEach { import -> + try { + import.delete() + } + catch(e: Exception) { + LOG.error(e) + } + } + declaration.delete() + } + } + } + }) + } + else { + project.executeWriteCommand(text) { declaration.delete() } + } + } + } +} \ No newline at end of file diff --git a/idea/testData/inspections/conflictingExtensionProperty/File.kt b/idea/testData/inspections/conflictingExtensionProperty/File.kt new file mode 100644 index 00000000000..9c47d84d7ed --- /dev/null +++ b/idea/testData/inspections/conflictingExtensionProperty/File.kt @@ -0,0 +1,16 @@ +import java.io.File +import java.io.Serializable + +val File.name: String + get() = getName() + +val Serializable.name: String + get() = "" + +val File.parent: File + get() = getParentFile() + +class MyFile : File("") + +val MyFile.isFile: Boolean + get() = isFile() \ No newline at end of file diff --git a/idea/testData/inspections/conflictingExtensionProperty/inspectionData/expected.xml b/idea/testData/inspections/conflictingExtensionProperty/inspectionData/expected.xml new file mode 100644 index 00000000000..d26edca2533 --- /dev/null +++ b/idea/testData/inspections/conflictingExtensionProperty/inspectionData/expected.xml @@ -0,0 +1,28 @@ + + + File.kt + 4 + light_idea_test_case + + Extension property conflicts with automatically produced one + This property conflicts with synthetic extension and should be removed to avoid breaking code by future changes in the compiler + + + + File.kt + 10 + light_idea_test_case + + Extension property conflicts with automatically produced one + This property conflicts with synthetic extension and should be removed to avoid breaking code by future changes in the compiler + + + + File.kt + 15 + light_idea_test_case + + Extension property conflicts with automatically produced one + This property conflicts with synthetic extension and should be removed to avoid breaking code by future changes in the compiler + + diff --git a/idea/testData/inspections/conflictingExtensionProperty/inspectionData/inspections.test b/idea/testData/inspections/conflictingExtensionProperty/inspectionData/inspections.test new file mode 100644 index 00000000000..11fa203cb2e --- /dev/null +++ b/idea/testData/inspections/conflictingExtensionProperty/inspectionData/inspections.test @@ -0,0 +1 @@ +// INSPECTION_CLASS: org.jetbrains.kotlin.idea.inspections.ConflictingExtensionPropertyInspection diff --git a/idea/testData/quickfix/deprecatedSymbolUsage/javaDeprecated.before.Main.kt b/idea/testData/quickfix/deprecatedSymbolUsage/javaDeprecated.before.Main.kt index 887988f0aa8..4c5a64968db 100644 --- a/idea/testData/quickfix/deprecatedSymbolUsage/javaDeprecated.before.Main.kt +++ b/idea/testData/quickfix/deprecatedSymbolUsage/javaDeprecated.before.Main.kt @@ -1,5 +1,4 @@ // "class org.jetbrains.kotlin.idea.quickfix.DeprecatedSymbolUsageFix" "false" -// ACTION: Inspection 'DEPRECATED_SYMBOL_WITH_MESSAGE' options fun foo() { val c = JavaClass() diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/.inspection b/idea/testData/quickfix/migration/deleteRedundantExtension/.inspection new file mode 100644 index 00000000000..eed53fe3f39 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/.inspection @@ -0,0 +1 @@ +org.jetbrains.kotlin.idea.inspections.ConflictingExtensionPropertyInspection \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/explicitThis.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/explicitThis.kt new file mode 100644 index 00000000000..18d56b3d5a1 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/explicitThis.kt @@ -0,0 +1,7 @@ +// "Delete redundant extension property" "true" + +var Thread.priority: Int + get() = this.getPriority() + set(value) { + this.setPriority(value) + } \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/explicitThis.kt.after b/idea/testData/quickfix/migration/deleteRedundantExtension/explicitThis.kt.after new file mode 100644 index 00000000000..1aceb5e4c7e --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/explicitThis.kt.after @@ -0,0 +1,2 @@ +// "Delete redundant extension property" "true" + diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/memberExtension.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/memberExtension.kt new file mode 100644 index 00000000000..5e17941aba2 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/memberExtension.kt @@ -0,0 +1,7 @@ +// "Delete redundant extension property" "true" +import java.io.File + +class C { + val File.name: String + get() = getName() +} diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/memberExtension.kt.after b/idea/testData/quickfix/migration/deleteRedundantExtension/memberExtension.kt.after new file mode 100644 index 00000000000..c1444359acd --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/memberExtension.kt.after @@ -0,0 +1,5 @@ +// "Delete redundant extension property" "true" +import java.io.File + +class C { +} diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.after.JustImport.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.after.JustImport.kt new file mode 100644 index 00000000000..8387e08ec93 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.after.JustImport.kt @@ -0,0 +1,4 @@ +package test + +fun foo() { +} \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.after.StarImport.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.after.StarImport.kt new file mode 100644 index 00000000000..5faa41b8874 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.after.StarImport.kt @@ -0,0 +1,8 @@ +package test + +import java.io.File +import utils.* + +fun foo(file: File) { + print(file.name) +} \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.after.Usages.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.after.Usages.kt new file mode 100644 index 00000000000..b897040cdff --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.after.Usages.kt @@ -0,0 +1,7 @@ +package test + +import java.io.File + +fun foo(file: File) { + print(file.name) +} \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.after.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.after.kt new file mode 100644 index 00000000000..3465328a649 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.after.kt @@ -0,0 +1,6 @@ +// "Delete redundant extension property" "true" +package utils + +import java.io.File + +// WITH_RUNTIME \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.before.JustImport.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.before.JustImport.kt new file mode 100644 index 00000000000..f259524280f --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.before.JustImport.kt @@ -0,0 +1,6 @@ +package test + +import utils.name + +fun foo() { +} \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.before.Main.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.before.Main.kt new file mode 100644 index 00000000000..91a5430aba4 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.before.Main.kt @@ -0,0 +1,9 @@ +// "Delete redundant extension property" "true" +package utils + +import java.io.File + +val File.name: String + get() = getName() + +// WITH_RUNTIME \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.before.StarImport.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.before.StarImport.kt new file mode 100644 index 00000000000..5faa41b8874 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.before.StarImport.kt @@ -0,0 +1,8 @@ +package test + +import java.io.File +import utils.* + +fun foo(file: File) { + print(file.name) +} \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.before.Usages.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.before.Usages.kt new file mode 100644 index 00000000000..22aacc11d4b --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.before.Usages.kt @@ -0,0 +1,8 @@ +package test + +import java.io.File +import utils.name + +fun foo(file: File) { + print(file.name) +} \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/removeImportsOverloads.after.Usages.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImportsOverloads.after.Usages.kt new file mode 100644 index 00000000000..8c558377f65 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImportsOverloads.after.Usages.kt @@ -0,0 +1,9 @@ +package test + +import java.io.File +import utils.name + +fun foo(file: File, thread: Thread) { + print(file.name) + print(thread.name) +} \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/removeImportsOverloads.after.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImportsOverloads.after.kt new file mode 100644 index 00000000000..ae4de13e553 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImportsOverloads.after.kt @@ -0,0 +1,9 @@ +// "Delete redundant extension property" "true" +package utils + +import java.io.File + +val Thread.name: String + get() = getName() + +// WITH_RUNTIME \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/removeImportsOverloads.before.Main.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImportsOverloads.before.Main.kt new file mode 100644 index 00000000000..a309f46c08b --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImportsOverloads.before.Main.kt @@ -0,0 +1,12 @@ +// "Delete redundant extension property" "true" +package utils + +import java.io.File + +val File.name: String + get() = getName() + +val Thread.name: String + get() = getName() + +// WITH_RUNTIME \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/removeImportsOverloads.before.Usages.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImportsOverloads.before.Usages.kt new file mode 100644 index 00000000000..8c558377f65 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/removeImportsOverloads.before.Usages.kt @@ -0,0 +1,9 @@ +package test + +import java.io.File +import utils.name + +fun foo(file: File, thread: Thread) { + print(file.name) + print(thread.name) +} \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/returnInGetter.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/returnInGetter.kt new file mode 100644 index 00000000000..4271fe88d04 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/returnInGetter.kt @@ -0,0 +1,5 @@ +// "Delete redundant extension property" "true" +import java.io.File + +val File.name: String + get() { return getName() } \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/returnInGetter.kt.after b/idea/testData/quickfix/migration/deleteRedundantExtension/returnInGetter.kt.after new file mode 100644 index 00000000000..c2fe797d149 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/returnInGetter.kt.after @@ -0,0 +1,3 @@ +// "Delete redundant extension property" "true" +import java.io.File + diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/simple.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/simple.kt new file mode 100644 index 00000000000..4c2f0541488 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/simple.kt @@ -0,0 +1,5 @@ +// "Delete redundant extension property" "true" +import java.io.File + +val File.name: String + get() = getName() \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/simple.kt.after b/idea/testData/quickfix/migration/deleteRedundantExtension/simple.kt.after new file mode 100644 index 00000000000..c2fe797d149 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/simple.kt.after @@ -0,0 +1,3 @@ +// "Delete redundant extension property" "true" +import java.io.File + diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/valInsteadOfVar.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/valInsteadOfVar.kt new file mode 100644 index 00000000000..1cde1940de0 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/valInsteadOfVar.kt @@ -0,0 +1,4 @@ +// "Delete redundant extension property" "true" + +val Thread.priority: Int + get() = getPriority() diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/valInsteadOfVar.kt.after b/idea/testData/quickfix/migration/deleteRedundantExtension/valInsteadOfVar.kt.after new file mode 100644 index 00000000000..1aceb5e4c7e --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/valInsteadOfVar.kt.after @@ -0,0 +1,2 @@ +// "Delete redundant extension property" "true" + diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/varInsteadOfVal.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/varInsteadOfVal.kt new file mode 100644 index 00000000000..a8b1430e0d4 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/varInsteadOfVal.kt @@ -0,0 +1,6 @@ +// "Delete redundant extension property" "false" +import java.io.File + +var File.name: String + get() = getName() + set(value) {} \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/withSetter.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/withSetter.kt new file mode 100644 index 00000000000..83e0f50a7d8 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/withSetter.kt @@ -0,0 +1,7 @@ +// "Delete redundant extension property" "true" + +var Thread.priority: Int + get() = getPriority() + set(value) { + setPriority(value) + } \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/withSetter.kt.after b/idea/testData/quickfix/migration/deleteRedundantExtension/withSetter.kt.after new file mode 100644 index 00000000000..1aceb5e4c7e --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/withSetter.kt.after @@ -0,0 +1,2 @@ +// "Delete redundant extension property" "true" + diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/wrongExplicitThis.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/wrongExplicitThis.kt new file mode 100644 index 00000000000..b46dea7f309 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/wrongExplicitThis.kt @@ -0,0 +1,7 @@ +// "Delete redundant extension property" "false" +// ACTION: Convert property to function + +class C : Thread() { + val Thread.priority: Int + get() = this@C.getPriority() +} diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/wrongExplicitThis2.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/wrongExplicitThis2.kt new file mode 100644 index 00000000000..b492247ef7c --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/wrongExplicitThis2.kt @@ -0,0 +1,9 @@ +// "Delete redundant extension property" "false" + +class C : Thread() { + var Thread.priority: Int + get() = getPriority() + set(value) { + this@C.setPriority(value) + } +} diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/wrongGetter.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/wrongGetter.kt new file mode 100644 index 00000000000..5afe2572e81 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/wrongGetter.kt @@ -0,0 +1,7 @@ +// "Delete redundant extension property" "false" + +var Thread.priority: Int + get() = getPriority() + 1 + set(value) { + setPriority(value) + } \ No newline at end of file diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/wrongGetter2.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/wrongGetter2.kt new file mode 100644 index 00000000000..ee8bb758fa8 --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/wrongGetter2.kt @@ -0,0 +1,6 @@ +// "Delete redundant extension property" "false" +// ACTION: Convert property to function +import java.io.File + +public val File.parent: File? + get() = getParentFile() diff --git a/idea/testData/quickfix/migration/deleteRedundantExtension/wrongSetter.kt b/idea/testData/quickfix/migration/deleteRedundantExtension/wrongSetter.kt new file mode 100644 index 00000000000..5ac5e1e55fc --- /dev/null +++ b/idea/testData/quickfix/migration/deleteRedundantExtension/wrongSetter.kt @@ -0,0 +1,8 @@ +// "Delete redundant extension property" "false" + +var Thread.priority: Int + get() = this.getPriority() + set(value) { + this.setPriority(value) + System.out.print("set") + } diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/JetInspectionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/JetInspectionTestGenerated.java index fdb1874eaf8..6ffca985581 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/JetInspectionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/JetInspectionTestGenerated.java @@ -94,6 +94,12 @@ public class JetInspectionTestGenerated extends AbstractJetInspectionTest { JetTestUtils.assertAllTestsPresentInSingleGeneratedClass(this.getClass(), new File("idea/testData/inspections"), Pattern.compile("^(inspections\\.test)$")); } + @TestMetadata("conflictingExtensionProperty/inspectionData/inspections.test") + public void testConflictingExtensionProperty_inspectionData_Inspections_test() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/inspections/conflictingExtensionProperty/inspectionData/inspections.test"); + doTest(fileName); + } + @TestMetadata("redundantSamConstructor/inspectionData/inspections.test") public void testRedundantSamConstructor_inspectionData_Inspections_test() throws Exception { String fileName = JetTestUtils.navigationMetadata("idea/testData/inspections/redundantSamConstructor/inspectionData/inspections.test"); diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixMultiFileTest.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixMultiFileTest.java index ca35d7439d4..de264b7e0a3 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixMultiFileTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixMultiFileTest.java @@ -21,18 +21,24 @@ import com.intellij.codeInsight.daemon.impl.HighlightInfo; import com.intellij.codeInsight.daemon.quickFix.LightQuickFixTestCase; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.codeInsight.intention.impl.ShowIntentionActionsHandler; +import com.intellij.codeInspection.InspectionEP; +import com.intellij.codeInspection.InspectionProfileEntry; +import com.intellij.codeInspection.LocalInspectionEP; import com.intellij.openapi.command.CommandProcessor; +import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.io.FileUtil; import com.intellij.psi.PsiFile; import com.intellij.util.ArrayUtil; +import com.intellij.util.containers.ContainerUtil; import com.intellij.util.ui.UIUtil; import junit.framework.ComparisonFailure; import kotlin.KotlinPackage; import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.idea.KotlinDaemonAnalyzerTestCase; +import org.jetbrains.kotlin.idea.quickfix.utils.UtilsPackage; import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil; import org.jetbrains.kotlin.idea.test.DirectiveBasedActionUtils; import org.jetbrains.kotlin.idea.test.PluginTestCaseBase; @@ -42,6 +48,7 @@ import org.jetbrains.kotlin.test.JetTestUtils; import java.io.File; import java.io.FilenameFilter; +import java.io.IOException; import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -65,9 +72,35 @@ public abstract class AbstractQuickFixMultiFileTest extends KotlinDaemonAnalyzer } protected void doTestWithExtraFile(String beforeFileName) throws Exception { + enableInspections(beforeFileName); doTest(beforeFileName, true); } + private void enableInspections(String beforeFileName) throws IOException, ClassNotFoundException { + File inspectionFile = UtilsPackage.findInspectionFile(new File(beforeFileName).getParentFile()); + if (inspectionFile != null) { + String className = FileUtil.loadFile(inspectionFile).trim(); + Class inspectionClass = Class.forName(className); + enableInspectionTools(inspectionClass); + } + } + + private void enableInspectionTools(@NotNull Class klass) { + List eps = ContainerUtil.newArrayList(); + ContainerUtil.addAll(eps, Extensions.getExtensions(LocalInspectionEP.LOCAL_INSPECTION)); + ContainerUtil.addAll(eps, Extensions.getExtensions(InspectionEP.GLOBAL_INSPECTION)); + + InspectionProfileEntry tool = null; + for (InspectionEP ep : eps) { + if (klass.getName().equals(ep.implementationClass)) { + tool = ep.instantiateTool(); + } + } + assert tool != null : "Could not find inspection tool for class: " + klass; + + enableInspectionTools(tool); + } + @Override protected void setUp() throws Exception { super.setUp(); diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixTest.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixTest.java index 2ca6ddf98b9..8103b4971c9 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixTest.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/AbstractQuickFixTest.java @@ -41,6 +41,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.idea.KotlinLightQuickFixTestCase; import org.jetbrains.kotlin.idea.js.KotlinJavaScriptLibraryManager; +import org.jetbrains.kotlin.idea.quickfix.utils.UtilsPackage; import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil; import org.jetbrains.kotlin.idea.test.DirectiveBasedActionUtils; import org.jetbrains.kotlin.idea.test.PluginTestCaseBase; @@ -64,19 +65,6 @@ public abstract class AbstractQuickFixTest extends KotlinLightQuickFixTestCase { ((StartupManagerImpl) StartupManager.getInstance(getProject())).runPostStartupActivities(); } - @Nullable - private static File findInspectionFile(@NotNull File startDir) { - File currentDir = startDir; - while (currentDir != null) { - File inspectionFile = new File(currentDir, ".inspection"); - if (inspectionFile.exists()) { - return inspectionFile; - } - currentDir = currentDir.getParentFile(); - } - return null; - } - protected void doTest(@NotNull String beforeFileName) throws Exception { try { configureRuntimeIfNeeded(beforeFileName); @@ -184,7 +172,7 @@ public abstract class AbstractQuickFixTest extends KotlinLightQuickFixTestCase { } private void enableInspections(String beforeFileName) throws IOException, ClassNotFoundException { - File inspectionFile = findInspectionFile(new File(beforeFileName).getParentFile()); + File inspectionFile = UtilsPackage.findInspectionFile(new File(beforeFileName).getParentFile()); if (inspectionFile != null) { String className = FileUtil.loadFile(inspectionFile).trim(); Class inspectionClass = Class.forName(className); diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java index 47d08f13e66..27f34f95418 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixMultiFileTestGenerated.java @@ -990,6 +990,27 @@ public class QuickFixMultiFileTestGenerated extends AbstractQuickFixMultiFileTes JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration"), Pattern.compile("^(\\w+)\\.before\\.Main\\.kt$"), true); } + @TestMetadata("idea/testData/quickfix/migration/deleteRedundantExtension") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class DeleteRedundantExtension extends AbstractQuickFixMultiFileTest { + public void testAllFilesPresentInDeleteRedundantExtension() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration/deleteRedundantExtension"), Pattern.compile("^(\\w+)\\.before\\.Main\\.kt$"), true); + } + + @TestMetadata("removeImports.before.Main.kt") + public void testRemoveImports() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/removeImports.before.Main.kt"); + doTestWithExtraFile(fileName); + } + + @TestMetadata("removeImportsOverloads.before.Main.kt") + public void testRemoveImportsOverloads() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/removeImportsOverloads.before.Main.kt"); + doTestWithExtraFile(fileName); + } + } + @TestMetadata("idea/testData/quickfix/migration/javaAnnotationPositionedArguments") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index 34924b1ae30..af86ddf1757 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -3923,6 +3923,87 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true); } + @TestMetadata("idea/testData/quickfix/migration/deleteRedundantExtension") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class DeleteRedundantExtension extends AbstractQuickFixTest { + public void testAllFilesPresentInDeleteRedundantExtension() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/quickfix/migration/deleteRedundantExtension"), Pattern.compile("^([\\w\\-_]+)\\.kt$"), true); + } + + @TestMetadata("explicitThis.kt") + public void testExplicitThis() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/explicitThis.kt"); + doTest(fileName); + } + + @TestMetadata("memberExtension.kt") + public void testMemberExtension() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/memberExtension.kt"); + doTest(fileName); + } + + @TestMetadata("returnInGetter.kt") + public void testReturnInGetter() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/returnInGetter.kt"); + doTest(fileName); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/simple.kt"); + doTest(fileName); + } + + @TestMetadata("valInsteadOfVar.kt") + public void testValInsteadOfVar() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/valInsteadOfVar.kt"); + doTest(fileName); + } + + @TestMetadata("varInsteadOfVal.kt") + public void testVarInsteadOfVal() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/varInsteadOfVal.kt"); + doTest(fileName); + } + + @TestMetadata("withSetter.kt") + public void testWithSetter() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/withSetter.kt"); + doTest(fileName); + } + + @TestMetadata("wrongExplicitThis.kt") + public void testWrongExplicitThis() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/wrongExplicitThis.kt"); + doTest(fileName); + } + + @TestMetadata("wrongExplicitThis2.kt") + public void testWrongExplicitThis2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/wrongExplicitThis2.kt"); + doTest(fileName); + } + + @TestMetadata("wrongGetter.kt") + public void testWrongGetter() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/wrongGetter.kt"); + doTest(fileName); + } + + @TestMetadata("wrongGetter2.kt") + public void testWrongGetter2() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/wrongGetter2.kt"); + doTest(fileName); + } + + @TestMetadata("wrongSetter.kt") + public void testWrongSetter() throws Exception { + String fileName = JetTestUtils.navigationMetadata("idea/testData/quickfix/migration/deleteRedundantExtension/wrongSetter.kt"); + doTest(fileName); + } + } + @TestMetadata("idea/testData/quickfix/migration/lambdaSyntax") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/quickfixTestUtils.kt b/idea/tests/org/jetbrains/kotlin/idea/quickfix/quickfixTestUtils.kt new file mode 100644 index 00000000000..87121b05021 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/quickfixTestUtils.kt @@ -0,0 +1,31 @@ +/* + * 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.quickfix.utils + +import java.io.File + +fun findInspectionFile(startDir: File): File? { + var currentDir: File? = startDir + while (currentDir != null) { + val inspectionFile = File(currentDir, ".inspection") + if (inspectionFile.exists()) { + return inspectionFile + } + currentDir = currentDir.parentFile + } + return null +}