Inspection (and quickfix) for extension propeties conflicting with synthetic ones

This commit is contained in:
Valentin Kipyatkov
2015-08-31 19:08:01 +03:00
parent d41e01c0e4
commit 10f7d6d7dd
45 changed files with 620 additions and 16 deletions
@@ -68,6 +68,8 @@ public object DirectiveBasedActionUtils {
"Edit intention settings",
"Edit inspection profile setting",
"Inject language or reference",
"Suppress '"
"Suppress '",
"Run inspection on",
"Inspection '"
)
}
@@ -0,0 +1,5 @@
<html>
<body>
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.
</body>
</html>
+7
View File
@@ -1138,6 +1138,13 @@
level="WARNING"
/>
<localInspection implementationClass="org.jetbrains.kotlin.idea.inspections.ConflictingExtensionPropertyInspection"
displayName="Extension property conflicts with synthetic one"
groupName="Kotlin"
enabledByDefault="true"
level="WARNING"
/>
<project.converterProvider implementation="org.jetbrains.kotlin.idea.converters.JetRunConfigurationSettingsFormatConverterProvider"/>
<fileType.fileViewProviderFactory filetype="KJSM" implementationClass="com.intellij.psi.ClassFileViewProviderFactory"/>
@@ -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<JetProperty>(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<JetSimpleNameReference>()
.map { ref -> ref.expression.getStrictParentOfType<JetImportDirective>() }
.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() }
}
}
}
}
@@ -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()
@@ -0,0 +1,28 @@
<problems>
<problem>
<file>File.kt</file>
<line>4</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="File.kt" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Extension property conflicts with automatically produced one</problem_class>
<description>This property conflicts with synthetic extension and should be removed to avoid breaking code by future changes in the compiler</description>
</problem>
<problem>
<file>File.kt</file>
<line>10</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="File.kt" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Extension property conflicts with automatically produced one</problem_class>
<description>This property conflicts with synthetic extension and should be removed to avoid breaking code by future changes in the compiler</description>
</problem>
<problem>
<file>File.kt</file>
<line>15</line>
<module>light_idea_test_case</module>
<entry_point TYPE="file" FQNAME="File.kt" />
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Extension property conflicts with automatically produced one</problem_class>
<description>This property conflicts with synthetic extension and should be removed to avoid breaking code by future changes in the compiler</description>
</problem>
</problems>
@@ -0,0 +1 @@
// INSPECTION_CLASS: org.jetbrains.kotlin.idea.inspections.ConflictingExtensionPropertyInspection
@@ -1,5 +1,4 @@
// "class org.jetbrains.kotlin.idea.quickfix.DeprecatedSymbolUsageFix" "false"
// ACTION: Inspection 'DEPRECATED_SYMBOL_WITH_MESSAGE' options
fun foo() {
val c = JavaClass()
@@ -0,0 +1 @@
org.jetbrains.kotlin.idea.inspections.ConflictingExtensionPropertyInspection
@@ -0,0 +1,7 @@
// "Delete redundant extension property" "true"
var Thread.<caret>priority: Int
get() = this.getPriority()
set(value) {
this.setPriority(value)
}
@@ -0,0 +1,2 @@
// "Delete redundant extension property" "true"
@@ -0,0 +1,7 @@
// "Delete redundant extension property" "true"
import java.io.File
class C {
val File.<caret>name: String
get() = getName()
}
@@ -0,0 +1,5 @@
// "Delete redundant extension property" "true"
import java.io.File
class C {
}
@@ -0,0 +1,4 @@
package test
fun foo() {
}
@@ -0,0 +1,8 @@
package test
import java.io.File
import utils.*
fun foo(file: File) {
print(file.name)
}
@@ -0,0 +1,7 @@
package test
import java.io.File
fun foo(file: File) {
print(file.name)
}
@@ -0,0 +1,6 @@
// "Delete redundant extension property" "true"
package utils
import java.io.File
// WITH_RUNTIME
@@ -0,0 +1,6 @@
package test
import utils.name
fun foo() {
}
@@ -0,0 +1,9 @@
// "Delete redundant extension property" "true"
package utils
import java.io.File
val File.<caret>name: String
get() = getName()
// WITH_RUNTIME
@@ -0,0 +1,8 @@
package test
import java.io.File
import utils.*
fun foo(file: File) {
print(file.name)
}
@@ -0,0 +1,8 @@
package test
import java.io.File
import utils.name
fun foo(file: File) {
print(file.name)
}
@@ -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)
}
@@ -0,0 +1,9 @@
// "Delete redundant extension property" "true"
package utils
import java.io.File
val Thread.name: String
get() = getName()
// WITH_RUNTIME
@@ -0,0 +1,12 @@
// "Delete redundant extension property" "true"
package utils
import java.io.File
val File.<caret>name: String
get() = getName()
val Thread.name: String
get() = getName()
// WITH_RUNTIME
@@ -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)
}
@@ -0,0 +1,5 @@
// "Delete redundant extension property" "true"
import java.io.File
val File.<caret>name: String
get() { return getName() }
@@ -0,0 +1,3 @@
// "Delete redundant extension property" "true"
import java.io.File
@@ -0,0 +1,5 @@
// "Delete redundant extension property" "true"
import java.io.File
val File.<caret>name: String
get() = getName()
@@ -0,0 +1,3 @@
// "Delete redundant extension property" "true"
import java.io.File
@@ -0,0 +1,4 @@
// "Delete redundant extension property" "true"
val Thread.<caret>priority: Int
get() = getPriority()
@@ -0,0 +1,2 @@
// "Delete redundant extension property" "true"
@@ -0,0 +1,6 @@
// "Delete redundant extension property" "false"
import java.io.File
var File.<caret>name: String
get() = getName()
set(value) {}
@@ -0,0 +1,7 @@
// "Delete redundant extension property" "true"
var Thread.<caret>priority: Int
get() = getPriority()
set(value) {
setPriority(value)
}
@@ -0,0 +1,2 @@
// "Delete redundant extension property" "true"
@@ -0,0 +1,7 @@
// "Delete redundant extension property" "false"
// ACTION: Convert property to function
class C : Thread() {
val Thread.<caret>priority: Int
get() = this@C.getPriority()
}
@@ -0,0 +1,9 @@
// "Delete redundant extension property" "false"
class C : Thread() {
var Thread.<caret>priority: Int
get() = getPriority()
set(value) {
this@C.setPriority(value)
}
}
@@ -0,0 +1,7 @@
// "Delete redundant extension property" "false"
var Thread.<caret>priority: Int
get() = getPriority() + 1
set(value) {
setPriority(value)
}
@@ -0,0 +1,6 @@
// "Delete redundant extension property" "false"
// ACTION: Convert property to function
import java.io.File
public val File.<caret>parent: File?
get() = getParentFile()
@@ -0,0 +1,8 @@
// "Delete redundant extension property" "false"
var Thread.<caret>priority: Int
get() = this.getPriority()
set(value) {
this.setPriority(value)
System.out.print("set")
}
@@ -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");
@@ -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<InspectionEP> 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();
@@ -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);
@@ -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)
@@ -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)
@@ -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
}